LeNet-5網絡結構解釋
LeNet-5中主要有2個卷積層、2個下抽樣層(池化層)、3個全連接配接層3種連接配接方式
輸入層
資料 input 層,輸入圖像的尺寸統一歸一化為32*32
例如Mnist的資料格式為28x28,需要resize到32x32
c1-卷積層
-
輸入
格式為:[1,32,32]
-
處理過程
卷積數量6,卷積核資料f = 5,pading預設為0,stride預設為1
卷積核處理後的資料計算公式為:(in+2xp-f)/s+1 = (32+2x0-5)/1+1 = 28
-
輸出
featuremap大小和數量:[28,28,6]
由y = wx+b,可知,參數和w和b組成,其中w = fxf, 每個卷積和,一個偏置參數,是以b = 1,是以:參數個數為(5x5+1)x6=156(其中5x5對應kernel size,+1為bias,6為feature map 數目)
S2-池化層(subsampling)
-
輸入
featuremap資料:[28,28,6]
-
處理過程
卷積核f = 2,步長為s = 2
計算公式同卷積:(in+2xp-f)/s+1 = 28/2 = 14
-
輸出
featuremap [14,14,6]
C3-卷積層
-
輸入
[14,14,6]的featuremap資料
-
處理過程
分别使用16個5x5卷積核,對輸入的6張featuremap進行處理,按照特殊的卷積核輸入組合,輸出一個10x10的featuremap
卷積層跟輸入的featuremap對應關系表如下圖所示
卷積核處理後的資料計算公式為:(in+2xp-f)/s+1 = (14+2x0-5)/1+1 = 10 -
輸出
featuremap [10,10,16]
# 如果是方陣,則可以隻使用一個數字進行定義 x = F.max_pool2d(F.relu(self.conv2(x)), 2)
S4-池化層
-
輸入
featuremap [10,10,16]
-
處理過程
卷積核f = 2,步長預設為卷積的大小stride = 2
同S2,直接是将featuremap的資料量減半
-
輸出
featuremap [5,5,16]
C5-全連接配接層
對C5沒太立即,看網上資料大部分說是全集程,但實際代碼實作用的又是全連接配接方法?
x = input.view(-1, 5x5x16)#[1,400]
self.fc1 = nn.Linear(16 * 5 * 5, 120)
x = F.relu(self.fc1(x))
全連接配接神經網絡結構一旦固定,需要學習的參數w是固定的,是以針對nn.Linear(16 * 5 * 5)要求輸入必須是[32, 32]大小的
-
輸入
featuremap [5,5,16]
-
處理過程
将輸入資料展平成一維的資料[1,400]
然後,使用全連接配接轉化成[1,120]
最後對資料進行線性整流
-
輸出
featuremap [1,120]
F6-全連接配接
self.fc2 = nn.Linear(120, 84)
x = F.relu(self.fc2(x))
同C5,将資料從[1,120]轉換成[1,84],并應用線性整流
輸出層-全連接配接層
self.fc3 = nn.Linear(84, 10)
x = self.fc3(x)
将資料從[1,84]轉化成[1,10],10代表屬于每一個分類的門檻值
當然如果,你的分類數目不是10,改成你對應的數字即可
實作代碼(前饋過程)
class Net(nn.Module):
def __init__(self,imgChannel):
super(Net, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(imgChannel, 6, 5),#self.C1
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),# self.S2
nn.Conv2d(6, 16, 5),#self.C3
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),#self.S4
)
self.classifier = nn.Sequential(
nn.Linear(16 * 5 * 5, 120),#self.fc1
nn.ReLU(inplace=True),
nn.Linear(120, 84),#self.fc2
nn.ReLU(inplace=True),
nn.Linear(84, 10),#self.fc3
)
def forward(self, x):
x = self.features(x)
x = x.view(-1, self.num_flat_features(x))#[1,400]
x =self.classifier(x)
return x
def num_flat_features(self, x):
# 除去批處理次元的其他所有次元
#torch.Size([1, 16, 5, 5])--->torch.Size([16, 5, 5])
size = x.size()[1:]
num_features = 1
for s in size:
num_features *= s
return num_features#400
測試結果
net = Net()
print(net)
input = torch.randn(1, 1, 32, 32)
net.forward(input)
使用一個随機資料,經網絡處理後的輸出為
tensor([[
-0.0648, -0.1591, 0.0945, 0.0710, 0.0155,
-0.0186, 0.0386, 0.0749,-0.0204, -0.0839]],
grad_fn=<AddmmBackward>)