本文參考:《DIVE INTO DEEP LEARNING》
LeNet
LeNet是進行手寫數字識別的網絡
LeNet分爲卷積層塊和全連接層塊兩個部分,激活函數都使用sigmoid
。
在卷積層塊中,每個卷積核的stride均爲1,padding均爲0。第一個卷積層輸出通道數爲6,第二個卷積層輸出通道數則增加到16。這是因爲第二個卷積層比第一個卷積層的輸入的高和寬要小,所以增加輸出通道使兩個卷積層的參數尺寸類似。
卷積層塊的兩個最大池化層的窗口形狀均爲 ,且步幅爲2。
全連接層塊含3個全連接層。它們的輸出個數分別是120、84和10,其中10爲輸出的類別個數。
# 以(1, 28, 28)的Mnist手寫數字數據集爲例
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 6, 5),
nn.Sigmoid(),
nn.MaxPool2d(2, 2),
nn.Conv2d(6, 16, 5),
nn.Sigmoid(),
nn.MaxPool2d(2, 2)
)
self.classifier = nn.Sequential(
nn.Linear(16 * 4 * 4, 120),
nn.Sigmoid(),
nn.Linear(120, 84),
nn.Sigmoid(),
nn.Linear(84, 10)
)
def forward(self, x):
x = self.features(x)
x = x.view(x.shape[0], -1)
x = self.classifier(x)
return x
AlexNet
AlexNet與LeNet的設計理念非常相似,但也有顯著的區別
- 激活函數全部使用
ReLU
,相比sigmoid
計算更簡單且緩解了梯度消失問題 - 與相對較小的LeNet相比,AlexNet包含8層變換,其中有5層卷積和2層全連接隱藏層,以及1個全連接輸出層。
- AlexNet第一層中的卷積窗口形狀是 。因爲ImageNet中絕大多數圖像的高和寬均比MNIST圖像的高和寬大10倍以上,ImageNet圖像的物體佔用更多的像素,所以需要更大的卷積窗口來捕獲物體。 同時使用步幅4來較大幅度減小輸出高和寬。而且相比於LeNet,輸出的通道數也要大很多.
- 第二層中的卷積窗口形狀減小到
- 之後的卷積核都採用
- 緊接着最後一個卷積層的是兩個輸出個數爲4096的全連接層。這兩個巨大的全連接層帶來將近1GB的模型參數。同時每個全連接層後還添加了
Dropout
層 - 最後一個全連接輸出層輸出個數爲類別數
- AlexNet引入了大量的圖像增廣,如翻轉、裁剪和顏色變化,從而進一步擴大數據集來緩解過擬合
# 以(1, 28, 28)的Mnist手寫數字數據集爲例
# 這裏在加入網絡訓練之前先要把圖片更改大小爲與ImageNet中圖片相同的224*224 (torchvision.transforms.Resize)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 96, 11, 4),
nn.ReLU(inplace=True),
nn.MaxPool2d(3, 2),
nn.Conv2d(96, 256, 5, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(3, 2),
nn.Conv2d(256, 384, 3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(384, 384, 3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(384, 256, 3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(3, 2),
)
self.classifier = nn.Sequential(
nn.Linear(256 * 5 * 5, 4096),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5, inplace=False),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5, inplace=False),
nn.Linear(4096, 10)
)
def forward(self, x):
x = self.features(x)
x = x.view(x.shape[0], -1)
x = self.classifier(x)
return x