神經網絡參數計算


卷積神經網絡的參數計算

前言

這篇文章會簡單寫一下卷積神經網絡上參數的計算方法,然后計算各個常見神經網絡的參數。一個是加強對網絡結構的了解,另一方面對網絡參數的量級有一個大概的認識,也可以當作備忘錄,免得想知道的時候還要再算。

此外,還有個比較有爭議的點,評論區里也有人指出,關於全連接中bias(偏置)的計算,我看的一些資料里參數的數量是1,但是在用的深度學習框架中(tensorflow和pytorch)基本都是和輸出層的元素的數量相同,我的看法的話,第二種可能效果更好一些吧,這樣會有更高的自由度,或許有相關的論文,但是我沒發現。不過這一點其實影響不大的,因為bias所占的參數量的比重很小,所以無論用哪種計算方法最終的結果基本沒什么差別。

參數計算方法

全連接的參數計算就不說了,比較簡單。
首先,簡單說一下卷積網絡的參數計算。下圖中是一個32x32x3的輸入,然后用一個5x5x3的卷積對其中某個位置的計算,這里算的是一個點積,所以輸出是一個單獨的標量的值。

因為卷積的操作是通過一個滑動窗口實現的,那么通過卷積操作,我們就得到了一個28x28x1的輸出。

如果我有6個上面說的filter,那么,我就會得到一個28x28x6的輸出。

這就是一個最基礎的卷積操作,那么這里用到的參數是多少呢?我們只需要把每個filter的參數累加起來,當然,不要忘了加上bias:5x5x3x6 + 6 = 456

另外一個需要計算的就是進行卷積以后的輸出的大小,從下面的圖上看就很好理解了,用公式直接算就好了。其中N是輸入圖像的size,F是filter的size,stride是滑動的步長。

然后從上圖中最后一個例子可以看到,stride大於1的時候不一定能整除,這個時候,就需要在原圖像上加上一層padding層,這樣圖像的大小就變化了,然后再用前面的公式算就行了。

然后還有一個maxpooling操作,這個會改變輸入輸出,但是不會有參數。所以使用和計算卷積一樣的公式算就行了。

LeNet

首先計算一下最簡單的LeNet。網絡結構如下:

網絡層(操作) 輸入 filter stride padding 輸出 計算公式 參數量
Input 32x32x1       32x32x1   0
Conv1 32x32x1 5x5x6 1 0 28x28x6 5x5x1x6+6 156
MaxPool1 28x28x6 2x2 2 0 14x14x6   0
Conv2 14x14x6 5x5x16 1 0 10x10x16 5x5x6x16+16 2416
MaxPool2 10x10x16 2x2 2 0 5x5x16   0
FC1 5x5x16       120 5x5x16x120+1 48001
FC2 120       84 120x84+1 10081
FC3 84       10 84x10+1 841

參數總量: 61495
參數內存消耗: 240.214KB

AlexNet

Alexnet的結構圖有些奇怪。但其實是因為要把網絡拆分到兩個GPU上,才畫成了兩層,兩層的結構是一樣的,下面計算的時候的結構相當於合並以后的網絡。

網絡層(操作) 輸入 filter stride padding 輸出 計算公式 參數量
Input 227x227x3       227x227x3   0
Conv1 227x227x3 11x11x96 4 0 55x55x96 11x11x3x96+96 34944
MaxPool1 55x55x96 3x3 2 0 27x27x96   0
Norm1 27x27x96       27x27x96   0
Conv2 27x27x96 5x5x256 1 2 27x27x256 5x5x96x256+256 614656
MaxPool2 27x27x256 3x3 2 0 13x13x256   0
Norml2 13x13x256       13x13x256   0
Conv3 13x13x256 3x3x384 1 1 13x13x384 3x3x256x384+384 885120
Conv4 13x13x384 3x3x384 1 1 13x13x384 3x3x384x384+384 1327488
Conv5 13x13x384 3x3x256 1 1 13x13x256 3x3x384x256+256 884992
MaxPool3 13x13x256 3x3 2 0 6x6x256   0
FC6 6x6x256       4096 6x6x256x4096+1 37748737
FC7 4096       4096 4096x4096+1 16777217
FC8 4096       1000 4096x1000+1 4096001

參數總量: 62369155
參數內存消耗: 237.9195MB

VGG

VGG常見有16層和19層的,這里以16層為例,下面是模型結構圖。

網絡層(操作) 輸入 filter stride padding 輸出 計算公式 參數量
Input 224x224x3       224x224x3   0
Conv3-64 224x224x3 3x3x64 1 1 224x224x64 3x3x3x64 + 64 1792
Conv3-64 224x224x64 3x3x64 1 1 224x224x64 3x3x64x64 + 64 36928
MaxPool2 224x224x64 2x2 2 0 112x112x64   0
Conv3-128 112x112x64 3x3x128 1 1 112x112x128 3x3x64x128 + 128 73856
Conv3-128 112x112x128 3x3x128 1 1 112x112x128 3x3x128x128 + 128 147584
MaxPool2 112x112x128 2x2 2 0 56x56x128   0
Conv3-256 56x56x128 3x3x256 1 1 56x56x256 3x3x128x256 + 256 295168
Conv3-256 56x56x256 3x3x256 1 1 56x56x256 3x3x256x256 + 256 590080
Conv3-256 56x56x256 3x3x256 1 1 56x56x256 3x3x256x256 + 256 590080
MaxPool2 56x56x256 2x2 2 0 28x28x256   0
Conv3-512 28x28x256 3x3x512 1 1 28x28x512 3x3x256x512 + 512 1180160
Conv3-512 28x28x512 3x3x512 1 1 28x28x512 3x3x512x512 + 512 2359808
Conv3-512 28x28x512 3x3x512 1 1 28x28x512 3x3x512x512 + 512 2359808
MaxPool2 28x28x512 2x2 2 0 14x14x512   0
Conv3-512 14x14x512 3x3x512 1 1 14x14x512 3x3x512x512 + 512 2359808
Conv3-512 14x14x512 3x3x512 1 1 14x14x512 3x3x512x512 + 512 2359808
Conv3-512 14x14x512 3x3x512 1 1 14x14x512 3x3x512x512 + 512 2359808
MaxPool2 14x14x512 2x2 2 0 7x7x512   0
FC1 7x7x512       4096 7x7x512x4096 + 1 102760449
FC2 4096       4096 4096*4096 + 1 16777217
FC3 4096       1000 4096*1000 + 1 4096001

參數總量: 138357544 138348355
參數內存消耗: 527.7570MB

GoogleNet

googlenet 提出了inception的概念,用於增加網絡深度和寬度,提高深度神經網絡性能。下面是googlenet的網絡結構:

inception的結構如下:

可以看出,inception的結構是多個卷積堆疊,組合而成的。

還有,從上面的網絡結構中,可以看到一共有三個輸出的分類層:

這個是為了解決深層網絡訓練的時候梯度消失的問題,所以在中間加入了幾個全連接層輔助訓練。
最后,貼一個論文上給出的模型的結構圖:

在這個圖上,已經給出了參數的數量和使用的內存,不過我還是說一下inception模塊的計算方法和一些注意事項。

  1. 首先是輸入,輸入的size應該為224x224x3
  2. 注意第一層的卷積,沒有注明padding,直接算的話,結果是不對的,這里的padding計算方法和tensorflow中卷積方法padding參數設置為’SAME’是一樣的。簡單來說,就是ceil(size/kernel_size),這個對於下面的計算也是一樣的,總之,就是要填適當的0,使得輸出結果和上圖相對應就是了。
    3.在上圖中5~10列對應inception module中的各個卷積操作,對應的值是輸出的feature的數量,對於maxpool操作,他的padding為2,stride為1。
    4.當一個inception模塊計算完后,它的輸出為各個卷積操作輸出的結果連接起來,也就是如果輸出分別為28x28x64、28x28x128、28x28x32、28x28x32,那么最終輸出就是28x28x(63+128+32+32)。

下面的圖給出了inception module內部計算的輸出結果。

可以看出googlenet的參數量要比vgg少很多,但是效果確更優秀。

Resnet

關於resnet,我就不打算計算參數了,因為實在量很大,而且實際上,resnet的基本結構也比較簡單,計算方法和前面的沒什么差別。這里就簡單貼一下結構圖好了。

可以看出來,如果沒有中間一條條連線,其實就是一個很深的普通的卷積網絡,中間的連線可以保證梯度可以傳遞到低層,防止梯度消失的問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM