一、卷积神经网络基本的层结构
(一)卷积层
1.可参考此文章:https://blog.csdn.net/tjlakewalker/article/details/83275322
2.实现代码:
import torch.nn as nn
conv = nn.Conv2d(in_channels=3, #输入通道out_channels=64, #输出通道kernel_size=3, #卷积核stride=1) #步长
print(conv)
# 结果:Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1))
3.输出矩阵的大小计算公式
W:输入矩阵边长 F:过滤器边长 P:填充数 S:步长
输出的正方形矩阵边长:(W-F+2P)/S+1
(二)反卷积层
简单地说就是卷积的反向操作
pytorch中有两种反卷积方法
1.双线性插值上采样:
import torch.nn as nn
bilinear_layer = nn.UpsamplingBilinear2d(size = None, #期望的输出尺寸scale_factor = None) #缩放因子:决定缩放的大小
2.转置卷积
import torch.nn as nn
transpose_conv = nn.ConvTranspose2d(in_channels = None, #输入通道out_channels = None, #输出通道kernel_size = None, #卷积核stride = None, #步长padding = None) #填充数
转置卷积是通过学习的方式,即在训练中更新卷积核的参数,完成上采样,其计算结果更具鲁棒性,缺点是会增加模型的训练时间和训练参数;其代码比卷积层代码仅多了一个填充参数,其余参数不变
(三)池化层
1.最大池化
import torch.nn as nn
maxpool_layer = nn.MaxPool2d(kernel_size = None, #卷积核stride = None, #步长padding = None, #填充数dilation = None, #膨胀数return_indices = None, #是否返回元素的位置信息ceil_mode=None) #是否向上取整
2.平均池化
import torch.nn as nn
average_layer = nn.AvgPool2d(kernel_size = None, #卷积核stride = None, #步长padding = None, #填充数ceil_mode=None) #是否向上取整
3.Mixed pooling
4.Stochastic Pooling
特点:
1.池化层是对输入的特征图进行压缩
2.池化层可以使特征图变小简化计算
3.池化不断抽取局部区域的特征,但不关心区域的位置,目标位置在较小的移动之后扔保持相同的结果,在一定程度上可以增加了平移不变性
(四)正则化层
全称Batch Normalization(BN),就是归一化处理
好处:减轻对初始数据的依赖;加速训练,学习率可以设置更高
坏处:一来batch的大小,batch不同,方差和均值的计算不稳定。------>BN层不适合batch较小的场景,也不适合RNN(RNN是动态网络结构,batch有长有短),只适合batch较大的场景
import torch.nn as nn
conv = nn.Conv2d(in_channels=3, #输入通道out_channels=64, #输出通道kernel_size=3, #卷积核stride=1) #步长
BN = nn.BatchNorm2d(64) #BN层参数紧跟卷积层的输出参数
(五)全连接层
import torch.nn as nn
linear = nn.Linear(in_features=None, #输入通道数out_features=None) #输出通道数:一般是输出类别数
当特征图纬度过大时,可以通过几个全连接层完成降纬,最后一个全连接层的输出通道为最终的分类类别:
import torch.nn as nn
linear_1 = nn.Linear(2048,512) #通过两个全连接层由2048降至5
linear_2 = nn.Linear(512,5)
二、搭建一个简单的完整的神经网络结构
(一)一般步骤
(1)class类的命名:要继承nn.Module
(2)init部分:完成层的构建(可以按照不同的方法来完成各个层结构的构建)
1.层层堆叠法:利用torch.nn逐一构建层结构
2.Sequential时序容器法:但是输出层结构时无名字,只有0、1、2等代号
3.Sequential+add_module法:可以给容器中各层赋予对应的名字
4.Sequential+OrderedDict法:时序容器+有序字典的方式,对层结构和各自对应的名字,同一完成构建
(3)forward部分:完成输入在神经网络中的前向传播过程
(二)构建方法示例
(1)层层堆叠法
#通过层层堆叠方式构建网络
import torch.nn as nn
class Net1(nn.Module):def __init__(self):super(Net1, self).__init__()self.conv1 = nn.Conv2d(3, 32, 3, 1, 1) #定义卷积层conv1self.relu = nn.ReLU() #定义激活函数self.pool = nn.MaxPool2d(2) #定义池化层self.dense1 = nn.Linear(32 * 3 * 3, 128) #构建两个全连接层dense1,dense2self.dense2 = nn.Linear(128, 10)def forward(self,x): #前向传播过程x = self.conv1(x)x = self.relu(x)x = self.pool(x)x = x.view(x.size(0), -1) #拉伸为1维x = self.dense1(x)x = self.relu(x)x = self.dense2(x)return x
net = Net1()
print(net)
# 结果
# Net1(
# (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
# (relu): ReLU()
# (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
# (dense1): Linear(in_features=288, out_features=128, bias=True)
# (dense2): Linear(in_features=128, out_features=10, bias=True)
# )
层层堆叠的方式构建,输出网络层结构时显示的层结构顺序是命名的先后顺序,不代表实际前向传播的层结构顺序
(2)Sequential时序容器法
#通过sequential时序容器构建网络
import torch.nn as nn
class Net2(nn.Module):def __init__(self):super(Net2, self).__init__()self.conv = nn.Sequential( #在第一个时序容器conv中依次构建卷积、激活、池化层nn.Conv2d(3, 32, 3, 1, 1),nn.ReLU(),nn.MaxPool2d(2))self.dense = nn.Sequential( #在第二个时序容器dense中依次构建全连接、激活、全连接层nn.Linear(32 * 3 * 3, 128),nn.ReLU(),nn.Linear(128, 10))def forward(self,x): #前向传播conv_out = self.conv(x)res = conv_out.view(conv_out.size(0), -1)out = self.dense(res)return out
net = Net2()
print(net)
# 结果
# Net2(
# (conv): Sequential(
# (0): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
# (1): ReLU()
# (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
# )
# (dense): Sequential(
# (0): Linear(in_features=288, out_features=128, bias=True)
# (1): ReLU()
# (2): Linear(in_features=128, out_features=10, bias=True)
# )
# )
利用Sequential构建,基本上代表了前向传播的顺序(纬度操作是不会显示在输出的网络结构中,如代码中的拉伸view操作);输出层结构时无名字,只有0、1、2等代号
(3)Sequential+add_module法
#通过Sequential+add_module构建网络
import torch.nn as nn
class Net3(nn.Module):def __init__(self):super(Net3, self).__init__()self.conv = nn.Sequential() #先构建空的Sequential容器,再往里添加self.conv.add_module("conv1", nn.Conv2d(3, 32, 3, 1, 1))self.conv.add_module("relu1", nn.ReLU())self.conv.add_module("pool1", nn.MaxPool2d(2))self.dense = nn.Sequential()self.dense.add_module("dense1", nn.Linear(32 * 3 * 3, 128))self.dense.add_module("relu2", nn.ReLU())self.dense.add_module("dense2", nn.Linear(128, 10))def forward(self,x):conv_out = self.conv(x)res = conv_out.view(conv_out.size(0), -1)out = self.dense(res)return out
net = Net3()
print(net)
# 结果
# Net3(
# (conv): Sequential(
# (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
# (relu1): ReLU()
# (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
# )
# (dense): Sequential(
# (dense1): Linear(in_features=288, out_features=128, bias=True)
# (relu2): ReLU()
# (dense2): Linear(in_features=128, out_features=10, bias=True)
# )
# )
可以给容器中各层赋予对应的名字,但网络深的话代码繁琐
(4)Sequential+OrderedDict法
#通过Sequential+OrderedDict法构建网络
import torch.nn as nn
from collections import OrderedDict
class Net4(nn.Module):def __init__(self):super(Net4, self).__init__()self.conv = nn.Sequential(OrderedDict([('conv1', nn.Conv2d(3, 32, 3, 1, 1)),('relu1', nn.ReLU()),('pool1', nn.MaxPool2d(2))]))self.dense = nn.Sequential(OrderedDict([('dense1', nn.Linear(32 * 3 * 3, 128)),('relu2', nn.ReLU()),('dense2', nn.Linear(128, 10))]))def forward(self,x):conv_out = self.conv(x)res = conv_out.view(conv_out.size(0), -1)out = self.dense(res)return out
net = Net4()
print(net)
# 结果
# Net4(
# (conv): Sequential(
# (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
# (relu1): ReLU()
# (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
# )
# (dense): Sequential(
# (dense1): Linear(in_features=288, out_features=128, bias=True)
# (relu2): ReLU()
# (dense2): Linear(in_features=128, out_features=10, bias=True)
# )
# )
序容器+有序字典的方式,对层结构和各自对应的名字,同一完成构建;也比方法3代码简单一些
三、代码函数中的参数含义参考Pytorch中文社区查找
https://pytorch-cn.readthedocs.io/zh/latest/