CNN網絡結構-AlexNet


背景

2009年,李飛飛和他的團隊發表了ImageNet的論文,還附帶了數據集。

2012年,多倫多大學的Geoffrey Hinton、Ilya Sutskever和Alex Krizhevsky提出了一種深度卷積神經網絡結構:AlexNet,奪得了ImageNet冠軍,成績比當時的第二名高出41%。

結構

經典的Lenet(發布於1999)結構如下:

 

AlexNet的結構模型如下:

 

AlexNet相比LeNet主要的改動在於: 


(1) Data Augmentation數據增長,現在的網絡中已經大量使用了。最主要的是剪裁,光照變換和水平翻轉。
(2) Dropout
Dropout方法和數據增強一樣,都是防止過擬合的。Dropout應該算是AlexNet中一個很大的創新,以至於Hinton在后來很長一段時間里的Talk都拿Dropout說事,后來還出來了一些變種,比如DropConnect等。
(3) ReLU激活函數
用ReLU代替了傳統的Tanh或者Logistic。好處有:
ReLU本質上是分段線性模型,前向計算非常簡單,無需指數之類操作;
ReLU的偏導也很簡單,反向傳播梯度,無需指數或者除法之類操作;
ReLU不容易發生梯度發散問題,Tanh和Logistic激活函數在兩端的時候導數容易趨近於零,多級連乘后梯度更加約等於0;
ReLU關閉了右邊,從而會使得很多的隱層輸出為0,即網絡變得稀疏,起到了類似L1的正則化作用,可以在一定程度上緩解過擬合。
當然,ReLU也是有缺點的,比如左邊全部關了很容易導致某些隱藏節點永無翻身之日,所以后來又出現pReLU、random ReLU等改進,而且ReLU會很容易改變數據的分布,因此ReLU后加Batch Normalization也是常用的改進的方法。
(4) Local Response Normalization
Local Response Normalization要硬翻譯的話是局部響應歸一化,簡稱LRN,實際就是利用臨近的數據做歸一化。這個策略貢獻了1.2%的Top-5錯誤率。
(5) Overlapping Pooling
Overlapping的意思是有重疊,即Pooling的步長比Pooling Kernel的對應邊要小。這個策略貢獻了0.3%的Top-5錯誤率。
(6) 多GPU並行

 

實現

線性的網絡結構

卷積層:5層 
全連接層:3層 
深度:8層 
神經元個數:650k 
分類數目:1000類

參數個數:60M 

C1:96*11*11*3(卷積核個數/寬/高/厚度) 34848個參數
C2:256*5*5*48(卷積核個數/寬/高/厚度) 307200個參數
C3:384*3*3*256(卷積核個數/寬/高/厚度) 884736個參數
C4:384*3*3*192(卷積核個數/寬/高/厚度) 663552個參數
C5:256*3*3*192(卷積核個數/寬/高/厚度) 442368個參數
R1:4096*6*6*256(卷積核個數/寬/高/厚度) 37748736個參數
R2:4096*4096 16777216個參數
R3:4096*1000 4096000個參數

總計:60924656個參數

C1:96*55*55  290400個神經元
C2:256*27*27 186624個神經元 
C3:384*13*13  64896個神經元 
C4:384*13*13  64896個神經元 
C5:256*13*13  43264個神經元 
R1:4096個神經元 
R2:4096個神經元 
R3:1000個神經元

總計:659272個

 

    input_data = mx.symbol.Variable(name="data")
    # stage 1
    conv1 = mx.symbol.Convolution(name='conv1',
        data=input_data, kernel=(11, 11), stride=(4, 4), num_filter=96)
    relu1 = mx.symbol.Activation(data=conv1, act_type="relu")
    lrn1 = mx.symbol.LRN(data=relu1, alpha=0.0001, beta=0.75, knorm=2, nsize=5)
    pool1 = mx.symbol.Pooling(
        data=lrn1, pool_type="max", kernel=(3, 3), stride=(2,2))
    # stage 2
    conv2 = mx.symbol.Convolution(name='conv2',
        data=pool1, kernel=(5, 5), pad=(2, 2), num_filter=256)
    relu2 = mx.symbol.Activation(data=conv2, act_type="relu")
    lrn2 = mx.symbol.LRN(data=relu2, alpha=0.0001, beta=0.75, knorm=2, nsize=5)
    pool2 = mx.symbol.Pooling(data=lrn2, kernel=(3, 3), stride=(2, 2), pool_type="max")
    # stage 3
    conv3 = mx.symbol.Convolution(name='conv3',
        data=pool2, kernel=(3, 3), pad=(1, 1), num_filter=384)
    relu3 = mx.symbol.Activation(data=conv3, act_type="relu")
    conv4 = mx.symbol.Convolution(name='conv4',
        data=relu3, kernel=(3, 3), pad=(1, 1), num_filter=384)
    relu4 = mx.symbol.Activation(data=conv4, act_type="relu")
    conv5 = mx.symbol.Convolution(name='conv5',
        data=relu4, kernel=(3, 3), pad=(1, 1), num_filter=256)
    relu5 = mx.symbol.Activation(data=conv5, act_type="relu")
    pool3 = mx.symbol.Pooling(data=relu5, kernel=(3, 3), stride=(2, 2), pool_type="max")
    # stage 4
    flatten = mx.symbol.Flatten(data=pool3)
    fc1 = mx.symbol.FullyConnected(name='fc1', data=flatten, num_hidden=4096)
    relu6 = mx.symbol.Activation(data=fc1, act_type="relu")
    dropout1 = mx.symbol.Dropout(data=relu6, p=0.5)
    # stage 5
    fc2 = mx.symbol.FullyConnected(name='fc2', data=dropout1, num_hidden=4096)
    relu7 = mx.symbol.Activation(data=fc2, act_type="relu")
    dropout2 = mx.symbol.Dropout(data=relu7, p=0.5)
    # stage 6
    fc3 = mx.symbol.FullyConnected(name='fc3', data=dropout2, num_hidden=num_classes)
    softmax = mx.symbol.SoftmaxOutput(data=fc3, name='softmax')
    return softmax

 


免責聲明!

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



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