模型分析
前言:卷积计算公式
在开始之前我先讲一下卷积层的计算公式;
H1,W1: 输入图片的高和宽
F: 卷积核的尺寸
P: 填充的数量
K: 卷积核的个数
H2,W2,D2: 输出后求出来的高、宽、通道数
对于P图像的填充(F卷积核尺寸、S也是一样): 高和宽方向填充的数量可能一样、可能不一样,所以就会产生P为一个二维的坐标,那么相应带入公式则采用相应维度上的数即可
模型图示(原论文)
模型源码
(依照模型图示搭建,与pytorch官方有一点不一致)
#### 首先定义一个类继承自nn.Module模块
class AlexNet(nn.Module):
## 代码中所实现的是将两大部分进行了融合,共同进行了卷积等操作,在通道数上进行了叠加
def __init__(self, num_classes: int = 1000) -> None:
super(AlexNet, self).__init__()
self.features = nn.Sequential(
### 第一大层卷积
nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),
##nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
## 在pytorch中的代码 pytorch中的每卷积层后的每一部分的输出的通道为32
## 作者论文中的为48
## 之后的每一个卷积层都有一些不一样
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
### 第二大层卷积
nn.Conv2d(96, 256, kernel_size=5, padding=2),
#nn.Conv2d(64, 192, kernel_size=5, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
### 第三大层卷积
nn.Conv2d(256, 384, kernel_size=3, padding=1),
#nn.Conv2d(192, 384, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
### 第四大层卷积
nn.Conv2d(384, 384, kernel_size=3, padding=1),
#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=3, stride=2),
)
self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
self.classifier = nn.Sequential(
nn.Dropout(),## 舍弃
nn.Linear(256 * 6 * 6, 4096),##256*6*6 输入的值个数 4096神经元个数
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.features(x)#卷积抽取特征层
x = self.avgpool(x)### 全局平均池化(自适应)
x = torch.flatten(x, 1)## 拉直层
x = self.classifier(x)### 分类层
return x
模型分析
直接从每一层的输入输出进行分析(模型以彩色图为例,图像有三个通道):
首先输入图片的尺寸为(224,224,3),高为224,宽为224,通道数为3.
如图所示:作者将模型分为了两大块,第一块是进行卷积操作,第二块则是进行全连接操作:
下边我将进行每一大层的 每一部分 的分析:
第一大层(卷积、激活、池化)
每一部分:输入(224,224,3)
卷积:
参数 | value |
---|---|
卷积核大小: | (11,11) |
卷积核个数: | 48 |
步长: | 4 |
是否填充: | 填充(2,2) |
(224-11+2*2)/2 +1 =55
输出(55,55,48) 长:55 宽:55 通道数:48
激活:
relu 函数
最大池化:
参数 | value |
---|---|
池化核大小: | (3,3) |
步长: | 2 |
是否填充: | 不填充 |
(55-3+2*0)/2 +1 =27
输出(27,27,48) 长:27 宽:27 通道数:48
第二大层(卷积、激活、池化)
每一部分:输入(27,27,48)
卷积:
参数 | value |
---|---|
卷积核大小: | (5,5) |
卷积核个数: | 128 |
步长: | 1 |
是否填充: | 填充(2,2) |
(27-5+2*2)/1 +1 =27
输出(27,27,128) 长:27 宽:27 通道数:128
激活:
relu 函数
最大池化:
参数 | value |
---|---|
池化核大小: | (3,3) |
步长: | 2 |
是否填充: | 不填充 |
(27-3+2*0)/2 +1 =13
输出(13,13,128) 长:13 宽:13 通道数:128
第三大层(卷积、激活)
每一部分:输入(13,13,128)
卷积:
参数 | value |
---|---|
卷积核大小: | (3,3) |
卷积核个数: | 192 |
步长: | 1 |
是否填充: | 填充(1,1) |
(13-3+2*1)/1 +1 =13
输出(13,13,192) 长:13 宽:13 通道数:192
激活:
relu 函数
如图所示进行了每一部分的输出进行了 交叉。
第四大层(卷积、激活)
每一部分:输入(13,13,192)
卷积:
参数 | value |
---|---|
卷积核大小: | (3,3) |
卷积核个数: | 192 |
步长: | 1 |
是否填充: | 填充(1,1) |
(13-3+2*1)/1 +1 =13
输出(13,13,192) 长:13 宽:13 通道数:192
激活:
relu 函数
第五大层(卷积、激活)
每一部分:输入(13,13,192)
卷积:
参数 | value |
---|---|
卷积核大小: | (3,3) |
卷积核个数: | 128 |
步长: | 1 |
是否填充: | 填充(1,1) |
(13-3+2*1)/1 +1 =13
输出(13,13,128) 长:13 宽:13 通道数:128
激活:
relu 函数
最大池化:
参数 | value |
---|---|
池化核大小: | (3,3) |
步长: | 2 |
是否填充: | 不填充 |
(13-3+2*0)/2 +1 =6
输出(6,6,128) 长:6 宽:6 通道数:128
自适应平均池化
输出(6,6,128)
拉直层
将三维的数据进行拉伸致一维数据,以便于进行全连接层
输出(6×6×128)
第六大层(舍弃层、激活层、全连接层)
舍弃层: 舍弃一部分输入的权重值
全连接层:输入(6×6×128)
神经元个数: 2048
激活层: relu()
第七大层(舍弃层、激活层、全连接层)
舍弃层: 舍弃一部分输入的权重值
全连接层:输入(2048) 上一隐层的神经元个数
神经元个数: 2048
激活层: relu()
第八大层(全连接层)
全连接层:输入(2048) 上一隐层的神经元个数
神经元个数: 自定义分类数
以上就是AlexNet模型的解析全过程啦,如果有一些错误,欢迎指正!!!!