目录
- 数据集读取
- 构建网络
- ==模型输入==
- ==卷积==
- ==反卷积==
- ==上采样==
- ==池化==
- ==BatchNormalization==
- ==激活==
- ==pytorch模型流程==
- ==实现VGG16过程对比==
- 训练
- 参考文章
数据集读取
构建网络
3、keras的Flatten操作可以视作pytorch中的view
模型输入
区别 |
区别 | pytorch | keras |
API | torch.tensor | Input |
形状 | NCHW | NHWC |
需要显示声明input_channels | 不需要input_channels,函数内部会自动获得 |
缩写意义 |
>API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
代码 |
#pytorch
#批次, 通道, 高, 宽
a = torch.randn(1,4,160,160)
#keras
#形状和批次分开
a = Input(shape = (160, 160, 4), batch_size = 1)
卷积
区别 |
区别 | pytorch | keras |
API | nn.Conv2D | Conv2D |
padding | 任意输入一个值 | 'valid’没填充,'same’有填充 |
输入通道 | 参数有输入通道 | 没有输入通道 |
缩写意义 |
padding:在原始图像的边缘用了像素填充
程序 |
#pytorch
self.conv = Conv2d(in_channels, out_channels, kernel_size, stride, padding=padding, bias=bias)
#keras
output = Conv2D(input.shape[-1] // reduction, kernel = (1,1), padding = "valid", use_bias = False)(output)
反卷积
区别 |
区别 | pytorch | keras |
API | nn.ConvTranspose2d | Conv2DTranspose |
输入通道 | 参数有输入通道 | 没有输入通道 |
程序 |
#pytorch
self.dconv = nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride, bias=bias)
#keras
output = Conv2DTranspose(out_channels, kernel_size, stride, use_bias=bias)(input)
上采样
区别 |
区别 | pytorch | keras |
API | nn.UpsamplingBilinear2d | 没有,需要自定义 |
程序 |
#pytorch
#缩放因子
self.up = nn.UpsamplingBilinear2d(scale_factor=2)
#keras
import tensorflow.compat.v1 as tf
#需要tf1版本里的resize
def my_upsampling(x,img_w,img_h,method=0):
"""0:双线性差值。1:最近邻居法。2:双三次插值法。3:面积插值法"""
return tf.image.resize_images(x,(img_w,img_h),0)
#输出宽高
output = Lambda(my_upsampling,arguments={'img_w':input.shape[2] * 2,'img_h':input.shape[1] * 2})(input)
池化
区别 |
区别 | pytorch | keras |
API | nn.AdaptiveAvgPool2d(1) | 没有自适应池化,需要利用自定义池化自定义 |
BatchNormalization
区别 |
区别 | pytorch | keras |
API | nn.BatchNorm2d | BatchNormalization |
输入通道 | 参数有输入通道 | 没有输入通道 |
程序 |
#pytorch
nn.BatchNorm2d(in_size),
#keras
output = BatchNormalization()(output)
激活
区别 |
区别 | pytorch | keras |
API | nn.ReLU | Activation |
程序 |
#pytorch
self.act = nn.Sigmoid()
self.act = nn.ReLU
#keras
output = Activation("sigmoid")(output)
output = Activation("relu")(output)
pytorch模型流程
class D():
def __init__(self, init_age):
print('我年龄是:',init_age)
self.age = init_age
def __call__(self, added_age):
res = self.forward(added_age)
return res
def forward(self, input_):
print('forward 函数被调用了')
return input_ + self.age
print('对象初始化。。。。')
a = D(10)
input_param = a(2)
print("我现在的年龄是:", input_param)
对象初始化。。。。
我年龄是: 10
forward 函数被调用了
我现在的年龄是: 12
1)__init__主要用来做参数初始化用,如 conv、pooling、Linear、BatchNorm 等,这点和tf里面的用法一样
2)forward是表示一个前向传播,构建网络层的先后运算步骤
3)__call__的功能和forward类似,所以很多时候,可以用__call__替代forward函数,两者区别是当网络构建完之后,调__call__的时候,会去先调forward,即__call__其实是包了一层forward,所以会导致两者的功能类似。
实现VGG16过程对比
'''
#pytorch---引入库
import torch
import torch.nn as nn
from .utils import load_state_dict_from_url
'''
#keras---引入库
from keras.models import Sequential
from keras.layers import Dense, Flatten
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
'''
#pytorch---搭建VGG16网络结构
class VGG(nn.Module):
def __init__(self, features, num_classes=1000, init_weights=True):
super(VGG, self).__init__()
self.features = features
self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
self.classifier = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, num_classes),
)
if init_weights:
self._initialize_weights()
def forward(self, x):
x = self.features(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
'''
def generate_vgg16():#搭建VGG16网络结构
input_shape = (224, 224, 3)
model = Sequential([
Conv2D(64, (3, 3), input_shape=input_shape, padding='same', activation='relu'),
Conv2D(64, (3, 3), padding='same', activation='relu'),
MaxPooling2D(pool_size=(2,2), strides=(2,2)),
Conv2D(128, (3, 3), padding='same', activation='relu'),
Conv2D(128, (3, 3), padding='same', activation='relu'),
MaxPooling2D(pool_size=(2,2), strides=(2,2)),
Conv2D(256, (3, 3), padding='same', activation='relu'),
Conv2D(256, (3, 3), padding='same', activation='relu'),
Conv2D(256, (3, 3), padding='same', activation='relu'),
MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
Conv2D(512, (3, 3), padding='same', activation='relu'),
Conv2D(512, (3, 3), padding='same', activation='relu'),
Conv2D(512, (3, 3), padding='same', activation='relu'),
MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
Conv2D(512, (3, 3), padding='same', activation='relu'),
Conv2D(512, (3, 3), padding='same', activation='relu'),
Conv2D(512, (3, 3), padding='same', activation='relu'),
MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
Flatten(),
Dense(4096, activation='relu'),
Dense(4096, activation='relu'),
Dense(1000, activation='softmax')
])
return model
model = generate_vgg16()
model.summary()
训练
用Keras训练模特只需.fit()
history = model.fit_generator(
generator=train_generator,
epochs=10,
validation_data=validation_generator)
在Pytorch中训练模型包括以下几个步骤:
- 在每批训练开始时初始化梯度
- 前向传播
- 反向传播
- 计算损失并更新权重
# 在数据集上循环多次
for epoch in range(2):
for i, data in enumerate(trainloader, 0):
# 获取输入; data是列表[inputs, labels]
inputs, labels = data
# (1) 初始化梯度
optimizer.zero_grad()
# (2) 前向传播
outputs = net(inputs)
loss = criterion(outputs, labels)
# (3) 反向传播
loss.backward()
# (4) 计算损失并更新权重
optimizer.step()
参考文章
pytorch转keraskeras pytorch 构建模型对比
keras 和 pytorch