接着我們上一個經典的卷積神經網絡LeNet,我們這一篇主要記錄一下深度卷積神經網絡中經典模型 AlexNet,從論文中可以找到其架構:
- input
[ 3, 224 × 224 ]
( channels, weight * height) - Conv2d
[ 1, 96, 11 × 11, 4, 0 ]
(in_channels, out_channels, kernel_size, stride, padding) - Maxpool2d
[96, 3 × 3, 2 ]
(channels, kernel_size, stride) - Conv2d
[ 96, 256, 5 × 5, 1, 2 ]
(in_channels, out_channels, kernel_size, stride, padding) - Maxpool2d
[ 256, 3 × 3, 2 ]
- Conv2d
[ 256, 384, 3 × 3, 1, 1 ]
- Conv2d
[ 384, 384, 3 × 3, 1, 1 ]
- Maxpool2d
[ 384, 3 × 3, 2 ]
- FC
[ 256 × 5 × 5, 4096 ]
- FC
[ 4096, 4096 ]
- FC
[ 4096, 10 ]
AlexNet 特點
首先在論文中,特別描述了一下ReLU激活函數,從下圖(實線表示ReLU
激活函數,虛線表示Tanh
激活函數)對比顯示隨着epochs的增加,ReLU激活函數達到第訓練錯誤率更快。
除此之外,ReLU激活函數的計算更簡單,例如它並沒有sigmoid激活函數中的求冪運算。另一方面,ReLU激活函數在不同的參數初始化方法下使模型更容易訓練。這是由於當sigmoid激活函數輸出極接近0或1時,這些區域的梯度幾乎爲0,從而造成反向傳播無法繼續更新部分模型參數;而ReLU激活函數在正區間的梯度恆爲1。因此,若模型參數初始化不當,sigmoid函數可能在正區間得到幾乎爲0的梯度,從而令模型無法得到有效訓練。
此外,AlexNet在防止過擬閤中採用了Dropout
方法(丟棄法),它用來控制全連接層的模型複雜度。
項目結構圖
模型
按照上面對於網絡結構的分解,在pytorch構建如下網絡:
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.conv = nn.Sequential(
# 第一層卷積層
nn.Conv2d(1, 96, 11, 4, 0),# in_channels, out_channels, kernel_size, stride, padding
nn.ReLU(),
nn.MaxPool2d(3, 2), # kernel_size, stride
# 第二層卷積層。減⼩卷積窗⼝,使⽤填充爲2來使得輸⼊與輸出的⾼和寬⼀致,且增⼤輸出通道數
nn.Conv2d(96, 256, 5, 1, 2),
nn.ReLU(),
nn.MaxPool2d(3, 2),
# 第三層卷積層,使用更小的卷積窗口
nn.Conv2d(256, 384, 3, 1, 1),
nn.ReLU(),
# 第四層卷積層
nn.Conv2d(384, 384, 3, 1, 1),
nn.ReLU(),
# 第五層卷積層
nn.Conv2d(384, 256, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(3, 2)
)
self.fc = nn.Sequential(
nn.Linear(256 * 5 * 5, 4096),
nn.ReLU(),
# Dropout來防止過擬合
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 10)
)
def forward(self, img):
feature = self.conv(img)
#print(feature)
output = self.fc(feature.view(img.shape[0], -1))
return output
訓練數據過程同LeNet,不再放出。