天天看點

Pytorch Lenet 1:網絡結構介紹

LeNet-5網絡結構解釋

Pytorch Lenet 1:網絡結構介紹

LeNet-5中主要有2個卷積層、2個下抽樣層(池化層)、3個全連接配接層3種連接配接方式

輸入層

資料 input 層,輸入圖像的尺寸統一歸一化為32*32

例如Mnist的資料格式為28x28,需要resize到32x32

c1-卷積層

Pytorch Lenet 1:網絡結構介紹
  • 輸入

    格式為:[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)

Pytorch Lenet 1:網絡結構介紹
  • 輸入

    featuremap資料:[28,28,6]

  • 處理過程

    卷積核f = 2,步長為s = 2

    計算公式同卷積:(in+2xp-f)/s+1 = 28/2 = 14

  • 輸出

    featuremap [14,14,6]

C3-卷積層

Pytorch Lenet 1:網絡結構介紹
  • 輸入

    [14,14,6]的featuremap資料

  • 處理過程

    分别使用16個5x5卷積核,對輸入的6張featuremap進行處理,按照特殊的卷積核輸入組合,輸出一個10x10的featuremap

    卷積層跟輸入的featuremap對應關系表如下圖所示

    Pytorch Lenet 1:網絡結構介紹
    卷積核處理後的資料計算公式為:(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-池化層

Pytorch Lenet 1:網絡結構介紹
  • 輸入

    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]大小的

Pytorch Lenet 1:網絡結構介紹
  • 輸入

    featuremap [5,5,16]

  • 處理過程

    将輸入資料展平成一維的資料[1,400]

    然後,使用全連接配接轉化成[1,120]

    最後對資料進行線性整流

  • 輸出

    featuremap [1,120]

F6-全連接配接

self.fc2 = nn.Linear(120, 84)
x = F.relu(self.fc2(x))
           
Pytorch Lenet 1:網絡結構介紹

同C5,将資料從[1,120]轉換成[1,84],并應用線性整流

輸出層-全連接配接層

self.fc3 = nn.Linear(84, 10)
x = self.fc3(x)
           
Pytorch Lenet 1:網絡結構介紹

将資料從[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>)
           

完整的網絡結構圖

Pytorch Lenet 1:網絡結構介紹