卷积神经网络中的LeNet-5和ALexNet
1、卷积神经网络的发展
1986年 Rumelhart和Hinton等人提出了反向传播(Back Propagation,BP)算法。
1998年 Yuan LeCun利用BP算法训练LeNet-5网络,标志着CNN的真正面世,但是由于硬件跟不上,卷积神经网络并没有发展起来。
2006年 Hinton在他们的Science Paper中首次提出了Deep Learning的概念。
2012年 Hinton的学生Alex Krizhevsky在寝室用GPU死磕一个Deep Learning模型,一举摘下了视觉领域竞赛 ILSVRC 2012的桂冠,从百万量级的ImageNet数据集合上,效果大幅度超过传统的方法,从传统的70%提升到80%多。
2、LeNet-5
LeNet-5是CNN的一个经典结构,卷积神经网络的开山之作,主要用于手写字体的识别,具有卷积层、池化层、全连接层。
Pytorch Tensor的通道排列顺序
Pytorch Tensor的通道排列顺序为[ batch, channel, height, width]。
batch指同一批次输入的图像的个数;
channel指输入的图像的深度;
height和width分别指输入的图像的高度和宽度。
原始的LeNet-5使用灰度图像,所以输入层的channel为1。这里使用彩色图像,所以输入层有RGB 3个通道,channel=3。
卷积后的矩阵尺寸大小计算公式
N=(W-F+2P)/S+1
① 输入图片大小W×W
② Filter大小F×F
③ 步幅S
④ padding的像素数P
LeNet-5的模型架构
LeNet-5包含一个卷积层、一个池化下采样层、一个卷积层、一个池化下采样层、3个全连接层。
卷积层conv1: Kernel: 16 kernel_size: 5 padding: 0 stride: 1 input_size:[3,32,32] out_size: [16,28,28]
池化层pool1: kernel_size: 2 padding: 0 stride: 2 input_size: [16,28,28] out_size: [16,14,14]
卷积层conv2: Kernel: 32 kernel_size: 5 padding: 0 stride: 1 input_size: [16,14,14] out_size: [32,10,10]
池化层pool2: kernel_size: 2 padding: 0 stride: 2 input_size: [32,10,10] out_size: [32,5,5]
全连接层FC1: 32*5*5 输出结点数:120
全连接层FC2: 输入结点数:120 输出 结点数:84
全连接层FC3:输入结点数:84 输出节点数(分类数目):10
搭建LeNet-5模型
nn.Conv2d函数使用2D卷积的方法对输入进行处理。
nn.Conv2d(in_channels,out_channels,kernel_size),in_channels代表输入特征矩阵的深度,第一个卷积层输入的是RGB图像,那么channels=3,out_channels代表使用卷积核的个数,使用多少个卷积核就会生成一个深度为多少维的特征矩阵,kernel_size代表卷积核的大小。stride和padding默认等于0,bias代表偏置,默认为true(使用)。
N=(W-F+2P)/S+1:W=32,F=5,P=0,S=1,N=28,16个卷积核,所以输出16×28×28,16个卷积核,channel变为16。未列出batch参数,将图像传入第一个卷积层得到的输出大小为batch×16×28×28。第二层卷积核新的特征矩阵的高和宽为14,故W=14,N=10,32个卷积核,所以输出为32×10×10。
nn.MaxPool2d没有使用初 始化函数,继承父类_MaxPool1Nd。父类_MaxPool1Nd(kernel_size,stride=None,padding=0)。kernel_size代表池化核的大小,stride=stride or kernel_size:如果不定义步幅大小,那么步幅=池化核的大小。填充为0。
查看LeNet-5模型
训练LeNet-5模型
transform函数是对图像进行预处理的函数。transforms.Compose()将预处理方法打包成一个整体。
transforms.ToTensor()处理:一般数据排列为height×width×channel,每个维度的像素值为0-255。
经过transforms.ToTensor()处理后变化为channel×height×width,像素值为0-1。
transforms.Normalize()是标准化处理的过程,使用均值和标准差来标准化。输出=(原始数据-均值)/标准差,输出=(输入-0.5)/0.5。反标准化处理:输入=输出×0.5+0.5
查看CIFAR 10中的数据
使用LeNet-5模型进行分类
3、AlexNet
AlexNet模型的出现打破了众多学者的认知,首次证明了学习到的特征可以超越手工设计的特征,越来越多的人加入到深度学习算法的研究浪潮中。
AlexNet的模型架构
AlexNet网络是8层卷积神经网络,前5层为卷积层,后3层为全连接层。
卷积层conv1: kernels:96 kernel_size=11 padding:[1,2] stride=4 input_size: [3,224,224] out_size: [96,55,55]
池化层maxpool1: kernel_size=3 padding=0 stride=2 input_size: [96,55,55] out_size: [96,27,27]
卷积层conv2: kernels:256 kernel_size=5 padding:[2,2] stride=1 input_size: [96,27,27] out_size: [256,27,27]
池化层maxpool2: kernel_size=3 padding=0 stride=2 input_size: [256,27,27] out_size: [256,13,13]
卷积层conv3: kernels:384 kernel_size=3 padding:[1,1] stride=1 input_size: [256,13,13] out_size: [384,13,13]
卷积层conv4: kernels:384 kernel_size=3 padding:[1,1] stride=1 input_size: [384,13,13] out_size: [384,13,13]
卷积层conv5: kernels:256 kernel_size=3 padding:[1,1] stride=1 input_size: [384,13,13] out_size: [256,13,13]
池化层maxpool3: kernel_size=3 padding=0 stride=2 input_size: [256,13,13] out_size: [256,6,6]
全连接层FC1: 256*6*6 输出结点数:2048
全连接层FC2: 输入结点数:2048 输出结点数:2048
全连接层FC3:输入结点数:2048 输出节点数(分类数目):1000
搭建AlexNet模型
Dropout()一般放在全连接层与全连接层之间,在全连接层之前进行展平。
使用nn.Sequential()的原因:如果每个模块都需要单独定义,工作量较大,操作麻烦。对于一个网络层次较多的神经网络,使用nn.Sequential()函数帮助精简代码。
nn.Conv2d()函数使用2D卷积的方法对输入的数据进行处理。
nn.Conv2d(in_channels,out_channels,kernel_size);in_channels代表输入特征矩阵的深度,第一个卷积层输入的是RGB图像,那么in_channels=3;out_channels代表使用卷积核的个数,使用多少个卷积核就会生成一个深度为多少维的特征矩阵;kernel_size代表卷积核的大小。stride和padding默认等于0,bias代表偏置,默认为true(使用)。
ALexNet网络中原来第一层卷积层的padding=[1,2]。在这里padding只能传入两种形式的变量:Int和tuple。如果是Int整型,比如传入1,那么特征矩阵的上方和下方各填充1行0,左边和右边各填充1列0。如果是tuple类型,比如turple(1,2),那么特征矩阵的上方和下方各填充1行0,左边和右边各填充1列0。如果要在特征矩阵的上方填充1行0,下方填充2行0,左边 填充1列0,右边填充2列0,需要使用nn.ZeroPad2d((1,2,1,2))实现更精细化的padding操作。为了便捷,这里我们直接设第一层卷积层的padding=2,即上方、下方、左边、右边都填充2列/2行0。按照N=(W-F+2P)/S+1进行计算,N为小数55.25,pytorc会自动将多余的数据舍弃,即最右边和最下方的0被舍弃,计算结果依然为55。(卷积层和池化层向下取整)
self.modules():返回迭代器,迭代器会遍历神经网络中的每一个模块,即通过self.modules()遍历定义的网络中的每一个层机构。