1. 程式人生 > >卷積神經網路 -- PyTorch 實現系列之 LeNet(datasets: CIFAR-10)

卷積神經網路 -- PyTorch 實現系列之 LeNet(datasets: CIFAR-10)

參考文獻:Gradient-Based Learning Applied to Document Recognition

摘要:

        本文利用PyTorch實現了經典神經網路LeNet。

引入:

        目前有很多部落格都系統介紹了LeNet的結構以及在各個框架下的程式碼實現,然而本人發現其中很大一部分博文是存在比較多的問題的,經過仔細閱讀LeCun的文章,我把原始LeNet的整個思路在此分享給各位,在下也是剛入門,如有疏漏或錯誤,請各位讀者指正!

        PS:由於用的是torch.nn.Modules實現,有些部分被我簡化了,帶我深入學習Pytorch後,再研究一下怎麼把這些忽略掉的引數再加進去吧……

資料集:

        原文使用的是MNIST,這裡我是用了CIFAR-10,最大的不同點只是圖片深度從1變成3(黑白和彩色的區別)。

網路結構:

        LeNet是一個由2個卷積層,2個池化層和3個全連線層組成的深度神經網路結構。

     關於池化層:文中描述為取樣層,可以理解為一個帶引數的AvgPooling,但是肯定不是MaxPooling。這裡我用torch.nn.AvgPool2d代替,忽略掉了6+6個引數。

      關於C3:實際上是不是所有的單元都和S2的所有輸出相連,這裡也是簡化了……

      最後一層:後面接的是一個帶引數的tanh,這裡也把引數忽略了。

主要程式碼如下:

print_every = 100
learning_rate = 1e-2
input_depth = 3
'''
layer_0 : [64, 3, 32, 32]   (Input)
layer_1 : [64, 6, 28, 28]   (Conv)
layer_2 : [64, 6, 14, 14]   (AvgPool)
layer_3 : [64, 16, 10, 10]  (Conv)
layer_4 : [64, 16, 5, 5]    (AvgPool)
layer_5 : [16*5*5, 120]     (Linear)
layer_5 : [120, 84]         (Linear)
layer_7 : [84, 10]          (Linear)
'''
layer_1_depth, layer_1_pad, layer_1_kernel = 6, 0,(5, 5) 
layer_2_kernel = (2,2)
layer_3_depth, layer_3_pad, layer_3_kernel= 16, 0,(5, 5) 
layer_4_kernel = (2,2)
layer_5_input, layer_5_output = 400, 120
layer_6_input, layer_6_output = 120, 84
layer_7_input, layer_7_output = 84, 10
model = nn.Sequential(
    nn.Conv2d(input_depth, layer_1_depth, layer_1_kernel, padding=layer_1_pad),
    nn.AvgPool2d(layer_2_kernel),
    nn.Sigmoid(),
    nn.Conv2d(layer_1_depth, layer_3_depth, layer_3_kernel, padding=layer_3_pad),
    nn.AvgPool2d(layer_4_kernel),
    Flatten(),
    nn.Linear(layer_5_input,layer_5_output),
    nn.Linear(layer_6_input,layer_6_output),
    nn.Linear(layer_7_input,layer_7_output),
    )

# you can use Nesterov momentum in optim.SGD
optimizer = optim.SGD(model.parameters(), lr=learning_rate,
                     momentum=0.9, nesterov=True)

iterations,losss,val_accs = train(model, optimizer, epochs = 10)