1. 程式人生 > >深度學習影象分類(一)——AlexNet論文理解

深度學習影象分類(一)——AlexNet論文理解

0. 寫作目的

好記性不如爛筆頭。

1. 論文理解

1.1 ReLU 啟用函式的使用

Rectified Linear Units(ReLU)

使用ReLU比使用tanh(或者sigmoid)啟用函式收斂速度更快。下圖來自AlexNet論文中給出的在CIFAR-10上的測試效果。可以看出ReLU收斂速度更快。

1.2 多GPU訓練

只在特殊層進行GPU資料之間的交流。

例如:第3卷積層的Feature map全部來自於第2卷積層(即來自不同GPU),但第4卷積層的Feature map只來自同一GPU的feature map. 

相比只使用一個GPU進行訓練,多個GPU資訊互動,可以提高精度: 1.7%(top-1)。

1.3 Local Response Normalization (LRN)

文章說: LRN可以增加 泛化能力。

由於後繼的分類網路說,LRN效果並不是很好,所以後繼的網路都未加入該層。因此這裡簡單介紹一下。

LRN即對於一個feature map(N個channel)的其中一個channel,將該層前後各n個channel對應位置的數值,然後進行歸一化。具體可以看下面的公式:

其中, (x, y)是channel中的位置, i是第i個channel,n 是相鄰的“前後”n 個channel數,N是該feature map總的channel數目(即邊界channel的處理),實驗中k = 2, n = 5, aerfa = 1e-4, belta = 0.75。引數是通過交叉驗證得到的。

LRN的使用位置:使用在特徵層的ReLU啟用函式後。

文中給出的效能提升:LRN可以看做是一種“亮度的正則化(brightness normaliztion)”。因為作者並沒有減去均值。

LRN降低1.4%的error rates (TOP-1), 在CIFAR-10驗證的效果是降低2% test error rate。

1.4 Overlapping Pooling

採用重疊池化。

採用的s = 2 (stride), z = 3, 可以降低0.4%(TOP-1)error rates與 s = 2, z = 2(正常的池化,即無重疊池化)。

作者發現:使用Overlapping Pooling 可以輕微地減少過擬合。

2. AlexNet網路

網路為:   5 conv + 3 fully-connect(輸入層不算)

上圖中: 150528 = 224 * 224 * 3

從上圖看出: GPU進行交叉的層是: 第3層、第6層(fc-1)、第7層(fc-2)、第8層(softmax)。

使用LRN層的是: 第1卷積層和第2卷積層, ReLU之後。

MaxPooling層:在第1卷積層、第2卷積層和第5卷積層後。

ReLU應用在每個卷積層和全連線層後(除了最後一層)。

實際的網路為:給出基於tensorflow的AlexNet(未使用多個GPU)

並附上AlexNet的程式碼

import os
import keras
import tensorflow as tf

def print_Layer(layer):
    print(layer.op.name, ' ', layer.get_shape().as_list())
tf.reset_default_graph()
    
def AlexNet():
    input = tf.keras.Input( shape=(224, 224, 3), name='alexNet_input' )
    print_Layer(input)
    
    ## conv1
    conv1 = tf.keras.layers.Conv2D( filters=96, kernel_size=(11,11), strides=(4,4), padding='same', activation=tf.nn.relu, name='conv1')(input)
    print_Layer(conv1)
    x = tf.nn.local_response_normalization( conv1, depth_radius=5, bias=1, alpha=1, beta=0.5, name='LRN-1')
    print_Layer(x)
    
    ## MaxPool
    maxpool1 = tf.keras.layers.MaxPooling2D( pool_size=(3, 3), strides=(2, 2), padding='valid', name='MaxPool1' )(x)
    print_Layer(maxpool1)
    
    ## conv2
    conv2 = tf.keras.layers.Conv2D( filters=256, kernel_size=(5,5), strides=(1,1), padding='same', activation=tf.nn.relu, name='conv2' )(maxpool1)
    print_Layer(conv2)
    x = tf.nn.local_response_normalization( conv2, depth_radius=5, bias=1, alpha=1, beta=0.5, name='LRN-2')
    print_Layer(x)
    
    ## MaxPool
    maxpool2 = tf.keras.layers.MaxPooling2D( pool_size=(3, 3), strides=(2, 2), padding='valid', name='MaxPool2' )(x)
    print_Layer(maxpool2)
    
    ## conv3
    conv3 = tf.keras.layers.Conv2D( filters=384, kernel_size=(3,3), strides=(1,1), padding='same', activation=tf.nn.relu, name='conv3')(maxpool2)
    print_Layer(conv3)
    
    ## conv4
    conv4 = tf.keras.layers.Conv2D( filters=384, kernel_size=(3,3), strides=(1,1), padding='same', activation=tf.nn.relu, name='conv4')(conv3)
    print_Layer(conv4)
    
    ## conv5
    conv5 = tf.keras.layers.Conv2D( filters=256, kernel_size=(3,3), strides=(1,1), padding='same', activation=tf.nn.relu, name='conv5' )(conv4)
    print_Layer(conv5)
    
    ## MaxPool
    maxpool3 = tf.keras.layers.MaxPooling2D( pool_size=(3, 3), strides=(2, 2), padding='valid', name='MaxPool3' )(conv5)
    print_Layer(maxpool3)
    
    ## flatten
    flat = tf.keras.layers.Flatten(name='Flat')(maxpool3)
    print_Layer(flat)
    
    ## fc-1
    fc1 = tf.keras.layers.Dense( units = 4096, activation=tf.nn.relu, name='fc1' )(flat)
    print_Layer(fc1)
    
    ##fc-2
    fc2 = tf.keras.layers.Dense( units = 4096, activation=tf.nn.relu, name='fc2' )(fc1)
    print_Layer(fc2)
    
    ## output
    predict = tf.keras.layers.Dense( units = 1000, activation=tf.nn.softmax, name='predict' )(fc2)
    print_Layer(predict)
    
    return predict

AlexNet()

3. 訓練的細節

3.1 降低過擬合

(1) 資料增強 Data Augmentation

第一種是:影象變換和水平映象。

訓練時: 從256*256的影象中,先進行,crop 224 * 224的影象。

測試時: 從影象中,crop 224*224的影象(10個, (four corner + center) * 2)映象的結果,將10個結果取softmax輸出結果的均值。

第二種是:改變RGBchannel的強度。

對每個訓練影象,先使用PCA(主成分分析)求出特徵值和特徵向量(以RGB為特徵,將影象看成一維的,然後計算),然後在特徵值上乘以一個隨機數,再將修改後的特徵值與特徵向量相乘,得到RGB channel強度變換後的值。隨機數的產生:均值為0,方差為0.1的高斯隨機數。

(2) Dropout

結合多個模型的預測結果是降低test errors的好方法,但是太耗時間,因此使用Dropout來降低過擬合。

Dropout可解釋:每次訓練時都是不同的網路(由於Drop的點不一樣); 降低不同神經元之間的聯絡。

訓練時,在兩個全連線層使用Droptout( 0.5 )。測試時,計算所有神經元,但是結果*0.5.

3.2 訓練引數

SGD + batch_size(128)  +  momentum (0.9) + weight decay (0.0005)

發現weight decay 對模型的學習很重要。不僅僅是正則化,也降低了test errors.

權重更新公式:

權重的初始化: 均值為0的 方差為0.01的高斯分佈。

bias: 第2,4,5卷積層和全連線層初值為1,其他層為0。

當val loss不再下降時,將學習率除以10. 

學習起始值為0.01,訓練過程中修改了3次。

大概訓練了90個epoch。

There may be some mistakes in this blog. So, any suggestions and comments are welcome!

[Reference]