1. 程式人生 > >【TensorFlow】卷積神經網路的引數設定與例子

【TensorFlow】卷積神經網路的引數設定與例子

一、卷積操作引數的簡要說明

這裡寫圖片描述
  如上圖所示,假設我們有32*32的RBG圖片,也就是神經網路的 input 是 32*32*3,表示輸入是一個有3個圖層的32*32的圖片。
  假設現在有一個 5*5的 filter處理一個32*32的圖層,那麼處理後的輸出就是一個28*28的圖層。現在總共有3個圖層,filter需要覆蓋這三個圖層,因此對於32*32*3的input,filter需要設定為 5*5*3,表示是一個深度為3,長和寬都為5的卷積核。
  需要注意的是,使用1個5*5*3的filter處理1個32*32*3的input,輸出還是 28*28*1的大小(表示大小為28*28,深度為1的圖層)。
  在實驗中,一個filter對應用來提取 1 種特徵,因此一般需要設定多個卷積核提取多個特徵。比如上圖的第一個CONV層 就是 6 個 5*5*3 的卷積核 ,用於提取 6 種特徵。上文已經說過,使用1個filter,則output是一個深度為1的圖層。那麼這裡使用6個filter,則output是一個深度為6的圖層。
  因此對應上圖的第一個CONV層,Input是32*32*3,使用6個5*5*3的filter,output是 28*28*6。

二、TensorFlow的函式conv2d的引數設定

tf.nn.conv2d(input, w, strides, padding)

1. input

  input是一個4為tensor =[batch, height, width, channels]= [樣本數量,樣本長,樣本寬,樣本深度(對應圖片通道數)],RGB影象通道數為3,黑白影象通道數為1

2. strides

  strides=[ batch 維度上的滑動步長,樣本height方向的滑動步長,樣本width方向的滑動步長, channels 維度上的滑動步長 ]
  一種常用的經典設定是 strides[0]=strides[3]=1。
  strides[0] = 1,也即在 batch 維度上的移動為 1,也就是不跳過任何一個樣本,否則當初也不該把它們作為輸入(input)
  strides[3] = 1,也即在 channels 維度上的移動為 1,也就是不跳過任何一個顏色通道;

3.padding

  padding=’SAME’,卷積操作後樣本的長和寬不發生改變。
  padding=’VALID’,卷積操作後,將樣本中不能進行卷積的部分丟掉:
這裡寫圖片描述

4. w

  w=[filter的長,filter的寬,input的深度,output的深度]。上文已經介紹,output的深度等於filter的個數。

三、Input層 - CONV層 - CONV層的W引數設定例子

  假設我們使用k*k大小的卷積核對1個n*m的影象運算,在tensorflow裡面,我們並不用設定計算圖片卷積後的輸出大小。我們只需要設定上一層的卷積核個數,及對應下一層的卷積核個數。
1. Input層
  例如,我們將一張32*32的RBG影象作為輸入,則input = [ 1,32,32,3 ],第一個1表示圖片的數量。
2. 第一個CONV層
  接受input的第一個卷積層的filter設定為 w=[filter的長,filter的寬,input的深度,output的深度] = [ 3,3,3,32 ],其中input的深度就是圖片的圖層數(RBG圖片有3層)。output的深度為32(等於卷積核的個數)。
3. 第二個CONV層
  上一個的CONV層的output的深度作為第二層的input深度。假設第二層的卷積核的大小是3*3,output的深度為64,則w=[ 3,3,32,64 ]

四、CNN識別Mnist資料集

  (卷積層 - 池化層) - (卷積層 - 池化層) - (卷積層 - 池化層) - 全連線層 - 輸出層

'''
    這裡,我們首先讀取資料MNIST,並分別得到訓練集的圖片和標記的矩陣,以及測試集的圖片和標記的矩陣。程式碼如下:
'''
import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images,mnist.test.labels

'''
    接著,需要處理輸入的資料,把上述 trX 和 teX 的形狀變為[-1,28,28,1],-1 表示不格慮輸入圖片
的數量,28×28 是圖片的長和寬的畫素數,1 是通道(channel)數量,因為 MNIST 的圖片是黑白的,所以
通道是 1,如果是 RGB 彩色影象,通道是 3。
'''
trX = trX.reshape(-1, 28, 28, 1) # 28x28x1 input img
teX = teX.reshape(-1, 28, 28, 1) # 28x28x1 input img
X = tf.placeholder("float", [None, 28, 28, 1])
Y = tf.placeholder("float", [None, 10])

''''
    這裡,我們將要構建一個擁有 3 個卷積層和 3 個池化層,隨後接 1 個全連線層和 1 個輸出層的卷積神經網路。
'''

# 首先定義初始化權重的函式:
def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

'''
    初始化權重方法如下,我們設定卷積核的大小為 3×3:
'''
# w,patch 大小為 3×3,輸入維度為 1,輸出維度為 32
w = init_weights([3, 3, 1, 32]) 
# w2,patch 大小為 3×3,輸入維度為 32,輸出維度為 64
w2 = init_weights([3, 3, 32, 64]) 
# w3,patch 大小為 3×3,輸入維度為 64,輸出維度為 128
w3 = init_weights([3, 3, 64, 128]) 
# w4,全連線層,輸入維度為 128 × 4 × 4(是由上一層的三維輸出資料`4*4*128`轉變成一維),輸出維度為 625
w4 = init_weights([128 * 4 * 4, 625])  
# w_o,輸出層,輸入維度為 625, 輸出維度為 10,代表 10 類(labels)
w_o = init_weights([625, 10]) 

'''
    神經網路模型的構建函式,傳入以下引數
    X:輸入資料
    w:每一層的權重
    p_keep_conv,p_keep_hidden:dropout 要保留的神經元比例
'''
def model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden):
    # 第一組卷積層及池化層,最後 dropout 一些神經元
    l1a = tf.nn.relu(tf.nn.conv2d(X, w, strides=[1, 1, 1, 1], padding='SAME'))
    # l1a shape=(?, 28, 28, 32)
    l1 = tf.nn.max_pool(l1a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    # l1 shape=(?, 14, 14, 32)
    l1 = tf.nn.dropout(l1, p_keep_conv)
    # 第二組卷積層及池化層,最後 dropout 一些神經元
    l2a = tf.nn.relu(tf.nn.conv2d(l1, w2, strides=[1, 1, 1, 1], padding='SAME'))
    # l2a shape=(?, 14, 14, 64)
    l2 = tf.nn.max_pool(l2a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    # l2 shape=(?, 7, 7, 64)
    l2 = tf.nn.dropout(l2, p_keep_conv)
    # 第三組卷積層及池化層,最後 dropout 一些神經元
    l3a = tf.nn.relu(tf.nn.conv2d(l2, w3, strides=[1, 1, 1, 1], padding='SAME'))
    # l3a shape=(?, 7, 7, 128)
    l3 = tf.nn.max_pool(l3a, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    # l3 shape=(?, 4, 4, 128)
    l3 = tf.reshape(l3, [-1, w4.get_shape().as_list()[0]]) # reshape to (?, 2048)
    l3 = tf.nn.dropout(l3, p_keep_conv)
    # 全連線層,最後 dropout 一些神經元
    l4 = tf.nn.relu(tf.matmul(l3, w4))
    l4 = tf.nn.dropout(l4, p_keep_hidden)
    # 輸出層
    pyx = tf.matmul(l4, w_o)
    return pyx #返回預測值

'''
    我們定義 dropout 的佔位符 — keep_conv,它表示在一層中有多少比例的神經元被保留下
來。生成網格模型,得到預測值,如下:
'''
p_keep_conv = tf.placeholder("float")
p_keep_hidden = tf.placeholder("float")
py_x = model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden) #得到預測值


'''
    接下來,定義損失函式,這裡我們仍然採用 tf.nn.softmax_cross_entropy_with_logits 來比較
預測值和真實值的差異,並做均值處理;定義訓練的操作(train_op),採用實現 RMSProp 演算法
的優化器 tf.train.RMSPropOptimizer,學習率為 0.001,衰減值為 0.9,使損失最小;定義預測的
操作(predict_op)。具體如下:
'''
cost = tf.reduce_mean(tf.nn. softmax_cross_entropy_with_logits_v2(logits=py_x, labels=Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)

'''
    最後輸出的`py_x`是一個shape=(?,10)的評分矩陣。每一行對應一個圖片屬於10個的概率值,tf.argmax(py_x, 1)
就是取出每一行概率值最大的下標。
'''
predict_op = tf.argmax(py_x, 1)

'''
    接下來訓練模型和評估模型:
'''
# 先定義訓練時的批次大小和評估時的批次大小
batch_size = 128
test_size = 256

# 在一個會話中啟動圖,開始訓練和評估
with tf.Session() as sess:
    # you need to initialize all variables
    tf. global_variables_initializer().run()
    for i in range(10):
        training_batch = zip(range(0, len(trX), batch_size),
                            range(batch_size, len(trX)+1, batch_size))
        for start, end in training_batch:
            sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end],
                                            p_keep_conv: 0.8, p_keep_hidden: 0.5})
        test_indices = np.arange(len(teX)) # Get A Test Batch
        np.random.shuffle(test_indices)
        test_indices = test_indices[0:test_size]
        print(i, np.mean(np.argmax(teY[test_indices], axis=1) ==
                sess.run(predict_op, feed_dict={X: teX[test_indices],
                                                    p_keep_conv: 1.0,
                                                    p_keep_hidden: 1.0})))

結果:
0 0.953125
1 0.98828125
2 0.9765625
3 0.9921875
4 0.98828125
5 0.99609375
6 0.98828125
7 0.9921875
8 0.9921875
9 0.98828125