【學習筆記】卷積神經網絡


人工神經網絡VS卷積神經網絡

  • 參數太多,在cifar-10的數據集中,只有32*32*3,就會有這么多權重,如果說更大的圖片,比如200*200*3就需要120000多個,這完全是浪費。
  • 沒有利用像素之間位置信息,對於圖像識別任務來說,每個像素與周圍的像素都是聯系比較緊密的。
  • 網絡層數限制 我們知道網絡層數越多其表達能力越強,但是通過梯度下降方法訓練深度人工神經網絡很困難,因為全連接神經網絡的梯度很難傳遞超過3層。因此,我們不可能得到一個很深的全連接神經網絡,也就限制了它的能力。

那么,卷積神經網絡又是怎樣解決這個問題的呢?主要有三個思路:

  • 局部連接:這個是最容易想到的,每個神經元不再和上一層的所有神經元相連,而只和一小部分神經元相連。這樣就減少了很多參數。
  • 權值共享:一組連接可以共享同一個權重,而不是每個連接有一個不同的權重,這樣又減少了很多參數。
  • 下采樣:可以使用Pooling來減少每層的樣本數,進一步減少參數數量,同時還可以提升模型的魯棒性。對於圖像識別任務來說,卷積神經網絡通過盡可能保留重要的參數,去掉大量不重要的參數,來達到更好的學習效果

卷積神經網絡CNN

卷積神經網絡與上一篇文章中的普通神經網絡非常相似:它們由具有學習權重和偏差的神經元組成。每個神經元接收一些輸入,執行點積,並且可選地以非線性跟隨它。整個網絡仍然表現出單一的可微分評分功能:從一端的原始圖像像素到另一個類的分數。並且在最后(完全連接)層上它們仍然具有損失函數(例如SVM / Softmax),並且我們為學習正常神經網絡開發的所有技巧/技巧仍然適用。

CNN每一層都通過可微分的函數將一個激活的值轉換為另一個,一般來說CNN具有卷積層,池化層和完全連接層FC(正如在常規神經網絡中所見),在池化層之前一般會有個激活函數,我們將堆疊這些層,形成一個完整的架構。我們先看下大概的一個圖:

CNN它將一個輸入3D體積變換為輸出3D體積,正常的神經網絡不同,CNN具有三維排列的神經元:寬度,高度,深度。

卷積層

參數及結構

四個超參數控制輸出體積的大小:過濾器大小,深度,步幅和零填充。得到的每一個深度也叫一個Feature Map。

卷積層的處理:在卷積層有一個重要的就是過濾器大小(需要自己指定),若輸入值是一個[32x32x3]的大小(例如RGB CIFAR-10彩色圖像)。如果每個過濾器(Filter)的大小為5×5,則CNN層中的每個Filter將具有對輸入體積中的[5x5x3]區域的權重,總共5 *5* 3 = 75個權重(和+1偏置參數),輸入圖像的3個深度分別與Filter的3個深度進行運算。請注意,沿着深度軸的連接程度必須為3,因為這是輸入值的深度,並且也要記住這只是一個Filter。

  • 假設輸入卷的大小為[16x16x20]。然后使用3x3的示例接收字段大小,CNN中的每個神經元現在將具有總共3 *3* 20 = 180個連接到輸入層的連接。

卷積層的輸出深度:那么一個卷積層的輸出深度是可以指定的,輸出深度是由你本次卷積中Filter的個數決定。加入上面我們使用了64個Filter,也就是[5,5,3,64],這樣就得到了64個Feature Map,這樣這64個Feature Map可以作為下一次操作的輸入值。

卷積層的輸出寬度:輸出寬度可以通過特定算數公式進行得出,后面會列出公式。

卷積輸出值的計算

我們用一個簡單的例子來講述如何計算卷積,然后,我們抽象出卷積層的一些重要概念和計算方法。

假設有一個5*5的圖像,使用一個3*3的filter進行卷積,得到了到一個3*3的Feature Map,至於得到3*3大小,可以自己去計算一下。如下所示:

我們看下它的計算過程,首先計算公式如下:

根據計算的例子,第一次:

第二次:

通過這樣我們可以依次計算出Feature Map中所有元素的值。下面的動畫顯示了整個Feature Map的計算過程:

步長

那么在卷積神經網絡中有一個概念叫步長,也就是Filter移動的間隔大小。上面的計算過程中,步幅(stride)為1。步幅可以設為大於1的數。例如,當步幅為2時,我們可以看到得出2*2大小的Feature Map,發現這也跟步長有關。Feature Map計算如下:

外圍補充與多Filter

我們前面還曾提到,每個卷積層可以有多個filter。每個filter和原始圖像進行卷積后,都可以得到一個Feature Map。因此,卷積后Feature Map的深度(個數)和卷積層的filter個數是相同的。

如果我們的步長移動與filter的大小不適合,導致不能正好移動到邊緣怎么辦?

以上就是卷積層的計算方法。這里面體現了局部連接和權值共享:每層神經元只和上一層部分神經元相連(卷積計算規則),且filter的權值對於上一層所有神經元都是一樣的。

總結輸出大小

卷積網絡API

tf.nn.conv2d(input, filter, strides=, padding=, name=None):

  • 計算給定4-D input和filter張量的2維卷積
  • input:給定的輸入張量,具有[batch,heigth,width,channel],類型為float32,64
  • filter:指定過濾器的大小,[filter_height, filter_width, in_channels, out_channels]
  • strides:strides = [1, stride, stride, 1],步長
  • padding:“SAME”, “VALID”,使用的填充算法的類型,使用“SAME”。其中”VALID”表示滑動超出部分舍棄,“SAME”表示填充,使得變化后height,width一樣大

新的激活函數-Relu

一般在進行卷積之后就會提供給激活函數得到一個輸出值。我們不使用sigmoid,softmax,而使用Relu。該激活函數的定義是:

Relu函數如下:

特點

  • 速度快,和sigmoid函數需要計算指數和倒數相比,relu函數其實就是一個max(0,x),計算代價小很多
  • 稀疏性,通過對大腦的研究發現,大腦在工作的時候只有大約5%的神經元是激活的,而采用sigmoid激活函數的人工神經網絡,其激活率大約是50%。有論文聲稱人工神經網絡在15%-30%的激活率時是比較理想的。因為relu函數在輸入小於0時是完全不激活的,因此可以獲得一個更低的激活率。

rule激活函數API

tf.nn.relu(features, name=None)

  • features:卷積后加上偏置的結果
  • return:結果

Pooling計算

Pooling層主要的作用是特征提取,通過去掉Feature Map中不重要的樣本,進一步減少參數數量。Pooling的方法很多,最常用的是Max Pooling。

除了Max Pooing之外,常用的還有Mean Pooling——取各樣本的平均值。對於深度為D的Feature Map,各層獨立做Pooling,因此Pooling后的深度仍然為D。

Pooling API

tf.nn.max_pool(value, ksize=, strides=, padding=,name=None)

  • 輸入上執行最大池數
  • value:4-D Tensor形狀[batch, height, width, channels]
  • ksize:池化窗口大小,[1, ksize, ksize, 1]
  • strides:步長大小,[1,strides,strides,1]
  • padding:“SAME”, “VALID”,使用的填充算法的類型

Mnist數據集卷積網絡實現

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data


def weight_variables(shape):
    """權重初始化函數"""
    w = tf.Variable(tf.random_normal(shape=shape, mean=0.0, stddev=1.0))
    return w


def bias_variables(shape):
    """偏置初始化函數"""
    b = tf.Variable(tf.constant(0.0, shape=shape))
    return b


def model():
    """自定義的卷積模型"""

    # 建立數據的占位符
    with tf.variable_scope("data"):
        x = tf.placeholder(tf.float32, [None, 28 * 28])
        y_true = tf.placeholder(tf.float32, [None, 10])

    # 第一層卷積 5*5*1,32個 strides=1
    with tf.variable_scope("conv1"):
        w_conv1 = weight_variables([5, 5, 1, 32])
        b_conv1 = bias_variables([32])

        x_reshape = tf.reshape(x, [-1, 28, 28, 1])
        x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape, w_conv1, strides=[1, 1, 1, 1], padding="SAME") + b_conv1)
        # 池化
        x_pool1 = tf.nn.max_pool(x_relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 第二層卷積層,5*5*32,64個filter,strides=1
    with tf.variable_scope("conv2"):
        w_conv2 = weight_variables([5, 5, 32, 64])
        b_conv2 = bias_variables([64])

        x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1, w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2)
        # 池化
        x_pool2 = tf.nn.max_pool(x_relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 全連接
    with tf.variable_scope("fc"):
        w_fc = weight_variables([7 * 7 * 64, 10])
        b_fc = weight_variables([10])

        x_fc_reshape = tf.reshape(x_pool2, [-1, 7 * 7 * 64])

        y_predict = tf.matmul(x_fc_reshape, w_fc) + b_fc

    return x, y_true, y_predict


def conv_fc():
    # 准備數據
    mnist = input_data.read_data_sets("./data/mnist/", one_hot=True)

    x, y_true, y_predict = model()

    # 所有樣本損失值的平均值
    with tf.variable_scope("soft_loss"):
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))

    # 梯度下降
    with tf.variable_scope("optimizer"):
        train_op = tf.train.GradientDescentOptimizer(0.0001).minimize(loss)

    # 計算准確率
    with tf.variable_scope("acc"):
        equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
        accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))

    init_op = tf.global_variables_initializer()

    with tf.Session() as sess:

        sess.run(init_op)

        for i in range(4000):

            mnist_x, mnist_y = mnist.train.next_batch(50)

            sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})

            print("訓練第%d步, 准確率為%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))


if __name__ == '__main__':
    conv_fc()

經過3000次訓練后,准確率達到百分之八九十。。。


免責聲明!

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



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