所有内容仅供参考,只是为了复习方便,代码都是用于分类的代码,可能与论文中的模型有所差异。也放了一些阅读论文时候的连接
目录
八、ShuffleNet V1 与ShuffleNet V2
一、LeNet-5
0、资料
LeNet-5模型是Yann LeCun教授于1998年在论文《Gradient-based learning applied to document recognition》中提出。它是第一个成功应用于手写数字识别问题并产生实际商业(邮政行业)价值的卷积神经网络。论文下载
CNN只要有三大特色,分别是局部感知、权重共享和多卷积核。如何理解这三个特征呢?
(1)局部感知:局部感知就是我们上面说的感受野,实际上就是卷积核和图像卷积的时候,每次卷积核所覆盖的像素只是一小部分,是局部特征,所以说是局部感知。CNN是一个从局部到整体的过程(局部到整体的实现是在全连通层),而传统的神经网络是整体的过程。
(2)权重共享:不同的图像或者同一张图像共用一个卷积核,减少重复的卷积核。同一张图像当中可能会出现相同的特征,共享卷积核能够进一步减少权值参数。
(3)多卷积核:一种卷积核代表的是一种特征,为获得更多不同的特征集合,卷积层会有多个卷积核,生成不同的特征,这也是为什么卷积后的图片的高,每一个图片代表不同的特征。
1、模型图
其实简单来说,就是2个卷积层,每个卷积通过池化进行下采样,之后3个全连接层。
模型和下面代码是对应的,为了下面表述方便,把ReLU激活函数和池化层都画出出来了,虽然画了七层,但是其中的两个池化层是没有参数的,有参数的是卷积层(两个)和全连接层(三个),所以是LeNet-5网络结构图。使用池化层达到下采样的目的。
2、模型代码
# -*-coding:utf-8-*-
import torch.nn as nn
import torch.nn.functional as F
class LeNet(nn.Module):
def __init__(self,num_classes=0):
super(LeNet,self).__init__()
self.conv1 = nn.Conv2d(3,6,5)
self.conv2 = nn.Conv2d(6,16,5)
self.fc_1 = nn.Linear(16*5*5,120)
self.fc_2 = nn.Linear(120,84)
self.fc_3 = nn.Linear(84,num_classes)
def forward(self,x):
out = F.relu(self.conv1(x))
out = F.max_pool2d(out,2)
out = F.relu(self.conv2(out))
out = F.max_pool2d(out,2)
out = out.view(out.size(0),-1)
out = F.relu(self.fc_1(out))
out = F.relu(self.fc_2(out))
out = self.fc_3(out)
return out
from torchsummary import summary
# #d打印网络结构及参数和输出形状
net = LeNet(10)
summary(net, input_size=(3, 32, 32)) #summary(net,(3,250,250))
3、分析LeNet-5的参数
输入层:图片大小为3×32×32,其中 3表示为彩色图像,3个 channel。
卷积层:filter 大小 5×5,filter 深度(个数)为 6,padding 为 0, 卷积步长 s=1,输出矩阵大小为6× 28×28,其中 6 表示 filter 的个数。参数个数:输入通道x输出通道x卷积核大小+偏置 = 3x6x5x5+6 = 456
池化层:average pooling,filter 大小 2×2(即 f=2),步长 s=2,no padding,输出矩阵大小为 16×14×14。
卷积层:filter 大小 5×5,filter 个数为 16,padding 为 0, 卷积步长 s=1s=1,输出矩阵大小为 16×10×10,其中 16 表示 filter 的个数。
池化层:average pooling,filter 大小 2×2(即 f=2),步长 s=2,no padding,输出矩阵大小为 16×5×5。注意,在该层结束,需要将 16×5×5 的矩阵flatten 成一个 400 维的向量。
全连接层(Fully Connected layer,FC):神经元的个数为 120。
全连接层(Fully Connected layer,FC):神经元的个数为 84。
全连接层(Fully Connected layer,FC):神经元的个数为10,也就是类别数。
二、AlexNet
0、资料
论文:《ImageNet Classification with Deep Convolutional Neural Networks》
参考资料:深入理解AlexNet网络
论文中提到:
(1)ReLU Nonlinearity(Rectified Linear Unit):ReLU激活函数要比tanh激活函数收敛要快。
(2)Local Response Normalization((局部响应归一化)):ReLU激活函数得到的值域没有一个区间,所以要对ReLU得到的结果进行归一化
(3)Overlapping Pooling(覆盖的池化操作):如果 stride < pool_size, 那么就会产生覆盖的池化操作,这种有点类似于convolutional化的操作,这样可以得到更准确的结果。论文中说,在训练模型过程中,覆盖的池化层更不容易过拟合。
(4)f防止过拟合的方法:数据增强和Dropout
1、模型结构
其实简单来说,就是5层Conv,三层的全连接层。
这个图对应下面的代码,之所有只有一个全连接层,是因为分类类别较少。
2、模型代码
# -*-coding:utf-8-*-
import torch.nn as nn
class AlexNet(nn.Module):
def __init__(self, num_classes):
super(AlexNet, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=5),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(64, 192, kernel_size=5, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(192, 384, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(384, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
)
self.fc = nn.Linear(256, num_classes)
def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1)
x = self.fc(x)
return x
from torchsummary import summary
# #d打印网络结构及参数和输出形状
net = AlexNet(10)
summary(net, input_size=(3, 32, 32)) #summary(net,(3,250,250))
3、模型参数
三、VGG
0、资料
论文:《VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION》
参考资料:深度学习VGG模型核心拆解
(1)与AlexNet的不同:增加网络的深度,然后VGG全部采用卷积核的尺寸打下为3*3,2个3*3的卷积层连接,就达到了5*5的效果,相当于可以减少参数。这样做的主要目的是在保证具有相同感知野的条件下,提升了网络的深度,在一定程度上提升了神经网络的效果。
1、模型结构
2、模型代码
import torch
import torch.nn as nn
import torchvision
def Conv3x3BNReLU(in_channels,out_channels):
return nn.Sequential(
nn.Conv2d(in_channels=in_channels,out_channels=out_channels,kernel_size=3,stride=1,padding=1),
nn.BatchNorm2d(out_channels),
nn.ReLU6(inplace=True)
)
class VGGNet(nn.Module):
def __init__(self, block_nums,num_classes=1000):
super(VGGNet, self).__init__()
self.stage1 = self._make_layers(in_channels=3, out_channels=64, block_num=block_nums[0])
self.stage2 = self._make_layers(in_channels=64, out_channels=128, block_num=block_nums[1])
self.stage3 = self._make_layers(in_channels=128, out_channels=256, block_num=block_nums[2])
self.stage4 = self._make_layers(in_channels=256, out_channels=512, block_num=block_nums[3])
self.stage5 = self._make_layers(in_channels=512, out_channels=512, block_num=block_nums[4])
self.classifier = nn.Sequential(
nn.Linear(in_features=512*7*7,out_features=4096),
nn.ReLU6(inplace=True),
nn.Dropout(p=0.2),
nn.Linear(in_features=4096, out_features=4096),
nn.ReLU6(inplace=True),
nn.Dropout(p=0.2),
nn.Linear(in_features=4096, out_features=num_classes)
)
def _ma