1. 程式人生 > >tensorflow實現AlexNet

tensorflow實現AlexNet

AlexNet是Hinton的學生Alex Krizhevsky在2012年提出的深度卷積神經網路,它是LeNet一種更深更寬的版本。在AlexNet上首次應用了幾個trick,ReLU、Dropout和LRN。AlexNet包含了6億3000萬個連線,6000萬個引數和65萬個神經元,有5個卷積層,3個全連線層。在ILSVRC 2012比賽中,AlexNet以top-5的錯誤率為16.4%的顯著優勢奪得冠軍,第二名的成績是26.2%。AlexNet的trick主要包括:

1、成功使用RELU作為CNN的啟用函式,並驗證其效果在較深的網路中的效果超過了sigmoid,解決了sigmoid在深層的網路中的梯度彌散的問題。

2、使用Dropout來隨機使得一部分神經元失活,來避免模型的過擬合,在AlexNet中,dropout主要應用在全連線層。

3、使用重疊的最大池化,以前在卷積神經網路中大部分都採用平均池化,在AlexNet中都是使用最大池化,最大池化可以避免平均池化的模糊化效果。重疊的最大池化是指卷積核的尺寸要大於步長,這樣池化層的輸出之間會有重疊和覆蓋,提升特徵的豐富性。在AlexNet中使用的卷積核大小為3×3,橫向和縱向的步長都為2。

4、使用LRN層,對區域性神經元的活動建立有競爭機制,讓響應較大的值變得相對更大,並抑制反饋較小的神經元,來增強模型的泛化能力。

5、使用了CUDA來加速深度神經網路的訓練。

6、資料增強,隨機從256×256的原始影象中擷取224×224的影象以及隨機翻轉。如果沒有資料增強,在引數眾多的情況下,卷積神經網路會陷入到過擬閤中,使用資料增強可以減緩過擬合,提升泛化能力。進行預測的時候,提取圖片的四個角加中間位置,並進行左右翻轉,一共10張圖片,對它們進行預測並取10次結果的平均值。在AlexNet論文中也提到了,對影象的RGB資料進行PCA處理,並做一個標準差為0.1的高斯擾動,增加一些噪聲,可以降低1%的錯誤率。

論文原文


1、第一層卷積層

第一層卷積一共有64個11×11×3大小的卷積核,橫向和縱向的步長都為4,初始化權重使用截斷的正態分佈進行初始化,經過ReLU啟用函式之後,再通過LRN層,再使用重疊的最大池化。

    #第一層卷積層
    with tf.name_scope("conv1") as scope:
        #設定卷積核11×11,3通道,64個卷積核
        kernel1 = tf.Variable(tf.truncated_normal([11,11,3,64],mean=0,stddev=0.1,
                                                  dtype=tf.float32),name="weights")
        #卷積,卷積的橫向步長和豎向步長都為4
        conv = tf.nn.conv2d(images,kernel1,[1,4,4,1],padding="SAME")
        #初始化偏置
        biases = tf.Variable(tf.constant(0,shape=[64],dtype=tf.float32),trainable=True,name="biases")
        bias = tf.nn.bias_add(conv,biases)
        #RELU啟用函式
        conv1 = tf.nn.relu(bias,name=scope)
        #輸出該層的資訊
        print_tensor_info(conv1)
        #統計引數
        parameters += [kernel1,biases]
        #lrn處理
        lrn1 = tf.nn.lrn(conv1,4,bias=1,alpha=1e-3/9,beta=0.75,name="lrn1")
        #最大池化
        pool1 = tf.nn.max_pool(lrn1,ksize=[1,3,3,1],strides=[1,2,2,1],padding="VALID",name="pool1")
        #輸出該層資訊
        print_tensor_info(pool1)

2、第二層卷積層

第二層卷積層的結構和第一層大致相似,卷積層的大小由11×11變成了5×5,有192個卷積核。

    #第二層卷積層
    with tf.name_scope("conv2") as scope:
        #初始化權重
        kernel2 = tf.Variable(tf.truncated_normal([5,5,64,192],dtype=tf.float32,stddev=0.1)
                              ,name="weights")
        conv = tf.nn.conv2d(pool1,kernel2,[1,1,1,1],padding="SAME")
        #初始化偏置
        biases = tf.Variable(tf.constant(0,dtype=tf.float32,shape=[192])
                             ,trainable=True,name="biases")
        bias = tf.nn.bias_add(conv,biases)
        #RELU啟用
        conv2 = tf.nn.relu(bias,name=scope)
        print_tensor_info(conv2)
        parameters += [kernel2,biases]
        #LRN
        lrn2 = tf.nn.lrn(conv2,4,1.0,alpha=1e-3/9,beta=0.75,name="lrn2")
        #最大池化
        pool2 = tf.nn.max_pool(lrn2,[1,3,3,1],[1,2,2,1],padding="VALID",name="pool2")
        print_tensor_info(pool2)

3、第三層卷積層

第三層卷積層卷積核的個數是第二層的一倍,第三層卷積層沒有使用LRN層和最大池化。

    #第三層卷積層
    with tf.name_scope("conv3") as scope:
        #初始化權重
        kernel3 = tf.Variable(tf.truncated_normal([3,3,192,384],dtype=tf.float32,stddev=0.1)
                              ,name="weights")
        conv = tf.nn.conv2d(pool2,kernel3,strides=[1,1,1,1],padding="SAME")
        biases = tf.Variable(tf.constant(0.0,shape=[384],dtype=tf.float32),trainable=True,name="biases")
        bias = tf.nn.bias_add(conv,biases)
        #RELU啟用層
        conv3 = tf.nn.relu(bias,name=scope)
        parameters += [kernel3,biases]
        print_tensor_info(conv3)

4、第四層卷積層

    #第四層卷積層
    with tf.name_scope("conv4") as scope:
        #初始化權重
        kernel4 = tf.Variable(tf.truncated_normal([3,3,384,256],stddev=0.1,dtype=tf.float32),
                              name="weights")
        #卷積
        conv = tf.nn.conv2d(conv3,kernel4,strides=[1,1,1,1],padding="SAME")
        biases = tf.Variable(tf.constant(0.0,dtype=tf.float32,shape=[256]),trainable=True,name="biases")
        bias = tf.nn.bias_add(conv,biases)
        #RELU啟用
        conv4 = tf.nn.relu(bias,name=scope)
        parameters += [kernel4,biases]
        print_tensor_info(conv4)

5、第五層卷積層

    #第五層卷積層
    with tf.name_scope("conv5") as scope:
        #初始化權重
        kernel5 = tf.Variable(tf.truncated_normal([3,3,256,256],stddev=0.1,dtype=tf.float32),
                              name="weights")
        conv = tf.nn.conv2d(conv4,kernel5,strides=[1,1,1,1],padding="SAME")
        biases = tf.Variable(tf.constant(0.0,dtype=tf.float32,shape=[256]),name="biases")
        bias = tf.nn.bias_add(conv,biases)
        #REUL啟用層
        conv5 = tf.nn.relu(bias)
        parameters += [kernel5,bias]
        #最大池化
        pool5 = tf.nn.max_pool(conv5,[1,3,3,1],[1,2,2,1],padding="VALID",name="pool5")
        print_tensor_info(pool5)

6、最後三層全連線層和softmax層

    #第六層全連線層
    pool5 = tf.reshape(pool5,(-1,6*6*256))
    weight6 = tf.Variable(tf.truncated_normal([6*6*256,4096],stddev=0.1,dtype=tf.float32),
                           name="weight6")
    ful_bias1 = tf.Variable(tf.constant(0.0,dtype=tf.float32,shape=[4096]),name="ful_bias1")
    ful_con1 = tf.nn.relu(tf.add(tf.matmul(pool5,weight6),ful_bias1))

    #第七層第二層全連線層
    weight7 = tf.Variable(tf.truncated_normal([4096,4096],stddev=0.1,dtype=tf.float32),
                          name="weight7")
    ful_bias2 = tf.Variable(tf.constant(0.0,dtype=tf.float32,shape=[4096]),name="ful_bias2")
    ful_con2 = tf.nn.relu(tf.add(tf.matmul(ful_con1,weight7),ful_bias2))
    #
    #第八層第三層全連線層
    weight8 = tf.Variable(tf.truncated_normal([4096,1000],stddev=0.1,dtype=tf.float32),
                          name="weight8")
    ful_bias3 = tf.Variable(tf.constant(0.0,dtype=tf.float32,shape=[1000]),name="ful_bias3")
    ful_con3 = tf.nn.relu(tf.add(tf.matmul(ful_con2,weight8),ful_bias3))

    #softmax層
    weight9 = tf.Variable(tf.truncated_normal([1000,10],stddev=0.1),dtype=tf.float32,name="weight9")
    bias9 = tf.Variable(tf.constant(0.0,shape=[10]),dtype=tf.float32,name="bias9")
    output_softmax = tf.nn.softmax(tf.matmul(ful_con3,weight9)+bias9)

7、評估模型效能

通過使用模擬出來的圖片來評估模型在訓練過程中的耗時。

#主函式
def run_bechmark():
    with tf.Graph().as_default():
        image_size = 224
        #以高斯分佈產生一些圖片
        images = tf.Variable(tf.random_normal([batch_size,image_size,image_size,3],
                                              dtype=tf.float32,stddev=0.1))
        output,parameters = inference(images)
        init = tf.global_variables_initializer()
        sess = tf.Session()
        sess.run(init)
        time_tensorflow_run(sess,output,"Forward")
        objective = tf.nn.l2_loss(output)
        grad = tf.gradients(objective,parameters)
        time_tensorflow_run(sess,grad,"Forward-backward") 
打印出來的每層相關資訊