AlexNet簡介
AlexNet原文地址:https://proceedings.neurips.cc/paper/2012/file/c399862d3b9d6b76c8436e924a68c45b-Paper.pdf
AlexNet誕生于2012年,由2012年ImageNet競賽冠軍獲得者Hinton和他的學(xué)生Alex Krizhevsky設(shè)計的。
AlexNet的貢獻點:
-
首次使用GPU加速網(wǎng)絡(luò)訓(xùn)練
-
使用ReLU激活函數(shù),代替不是傳統(tǒng)的Sigmoid和Tanh,解決了Sigmoid的梯度消失問題,使收斂更快。
-
訓(xùn)練時使用Dropout隨機忽略一部分神經(jīng)元,以減少模型過擬合。
-
使用了LRN局部響應(yīng)歸一化提高準(zhǔn)確率。
-
在CNN中使用重疊的最大池化,提升了特征的豐富性。
AlexNet網(wǎng)絡(luò)的原始輸入圖像大小為【3,224,224】,由5個卷積層、3個池化層和3個全連接層構(gòu)成,并且在每一個卷積層和全連接層之后都進行一次ReLU激活。其中的3個池化層分別跟在第1、第2和第5個卷積層的激活之后。網(wǎng)絡(luò)結(jié)構(gòu)圖如下:
AlexNet網(wǎng)絡(luò)結(jié)構(gòu)解析
卷積層1(Conv + ReLU + MaxPool)
Conv1使用卷積核大小為11,步距為4,padding為2。
輸入大小:【3,224,224】
輸出大小:【48,55,55】
N = (W-F+2P)/ S + 1 = (224-11+2*2)/4+1=55。
卷積之后跟著一個ReLU激活,激活之后接著一個最大池化上采樣,池化核大小為3,步距為2,池化后輸出大小為【48,27,27】。
PyTorch表述本層為:
# input[3, 224, 224]
nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2), # output[48, 55, 55]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[48, 27, 27]
卷積層2(Conv + ReLU + MaxPool)
Conv2使用卷積核大小為5,步距為1,padding為2。
輸入大小:【48,27,27】
輸出大小:【128,27,27】
N = (W-F+2P)/ S + 1 = (27-5+2*2)/1+1=27。
卷積之后跟著一個ReLU激活,激活之后接著一個最大池化上采樣,池化核大小為3,步距為2,池化后輸出大小為【128,13,13】。
PyTorch表述本層為:
# input[48,27,27]
nn.Conv2d(48, 128, kernel_size=5, padding=2), # output[128, 27, 27]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 13, 13]
卷積層3(Conv + ReLU )
Conv3使用卷積核大小為3,步距為1,padding為1。
輸入大小:【128, 13, 13】
輸出大小:【192,13,13】
N = (W-F+2P)/ S + 1 = (13-3+1*2)/1+1=13。
卷積之后跟著一個ReLU激活,沒有池化。
PyTorch表述本層為:
# input[128, 13, 13]
nn.Conv2d(128, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
卷積層4(Conv + ReLU )
Conv4使用卷積核大小為3,步距為1,padding為1。
輸入大小:【192, 13, 13】
輸出大小:【192,13,13】
N = (W-F+2P)/ S + 1 = (13-3+1*2)/1+1=13。
卷積之后跟著一個ReLU激活,沒有池化。
PyTorch表述本層為:
# input[192, 13, 13]
nn.Conv2d(192, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
卷積層5(Conv + ReLU + MaxPool)
Conv5使用卷積核大小為3,步距為1,padding為1。
輸入大小:【192, 13, 13】
輸出大小:【128,13,13】
N = (W-F+2P)/ S + 1 = (13-3+1*2)/1+1=13。
卷積之后跟著一個ReLU激活,激活之后接著一個最大池化上采樣,池化核大小為3,步距為2,池化后輸出大小為【128,6,6】。
PyTorch表述本層為:
# input[192, 13, 13]
nn.Conv2d(192, 128, kernel_size=3, padding=1), # output[128, 13, 13]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 6, 6]
第5個卷積層之后,就是三個全連接層。
FC1
全連接FC1之前先進行一次Dropout。
FC1使用4096個神經(jīng)元,對128個大小為66的特征圖,進行一個全連接。
輸入大小:【12866】
輸出大小:【2048】
FC1之后進行一次ReLU激活。
PyTorch表述本層為:
nn.Dropout(p=0.5),
nn.Linear(128 * 6 * 6, 2048),
nn.ReLU(inplace=True),
FC2
全連接FC2之前先進行一次Dropout。
FC1使用2048個神經(jīng)元,對2048特征圖,進行一個全連接。
輸入大小:【2048】
輸出大小:【2048】
FC1之后進行一次ReLU激活。
PyTorch表述本層為:
nn.Dropout(p=0.5),
nn.Linear(2048, 2048),
nn.ReLU(inplace=True),
FC3
FC3是AlexNet的輸出層,輸出大小為1000,對應(yīng)1000個類別。
PyTorch表述本層為:
nn.Linear(2048, 1000),
使用PyTorch搭建AlexNet網(wǎng)絡(luò)結(jié)構(gòu)
前面在網(wǎng)絡(luò)結(jié)構(gòu)解析的時候,都已經(jīng)給出了每一層的代碼表述。
init
這里我們使用nn.Sequential將5個卷積層放在一起,定義為features(義為提取特征);將3個全連接層放在一起,定義為classifier(義為分類)。
def __init__(self):
super(AlexNet, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2), # output[48, 55, 55]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[48, 27, 27]
nn.Conv2d(48, 128, kernel_size=5, padding=2), # output[128, 27, 27]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 13, 13]
nn.Conv2d(128, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
nn.Conv2d(192, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
nn.Conv2d(192, 128, kernel_size=3, padding=1), # output[128, 13, 13]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 6, 6]
)
self.classifier = nn.Sequential(
nn.Dropout(p=0.5),
nn.Linear(128 * 6 * 6, 2048),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5),
nn.Linear(2048, 2048),
nn.ReLU(inplace=True),
nn.Linear(2048, num_classes),
)
forward
然后定義正向傳播過程文章來源:http://www.zghlxwxcb.cn/news/detail-476423.html
def forward(self, x):
x = self.features(x) # 5個卷積層
x = torch.flatten(x, start_dim=1) # 將3維展平成一維,進行全連接
x = self.classifier(x) # 3個全連接層
return x
完整代碼
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2), # output[48, 55, 55]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[48, 27, 27]
nn.Conv2d(48, 128, kernel_size=5, padding=2), # output[128, 27, 27]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 13, 13]
nn.Conv2d(128, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
nn.Conv2d(192, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
nn.Conv2d(192, 128, kernel_size=3, padding=1), # output[128, 13, 13]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 6, 6]
)
self.classifier = nn.Sequential(
nn.Dropout(p=0.5),
nn.Linear(128 * 6 * 6, 2048),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5),
nn.Linear(2048, 2048),
nn.ReLU(inplace=True),
nn.Linear(2048, 1000),
)
def forward(self, x):
x = self.features(x)
x = torch.flatten(x, start_dim=1)
x = self.classifier(x)
return x
model = AlexNet();
print(model)
打印結(jié)構(gòu):文章來源地址http://www.zghlxwxcb.cn/news/detail-476423.html
到了這里,關(guān)于卷積神經(jīng)網(wǎng)絡(luò)模型之——AlexNet網(wǎng)絡(luò)結(jié)構(gòu)與代碼實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!