1. 程式人生 > >深度學習筆記5-tensorflow實現卷積神經網路

深度學習筆記5-tensorflow實現卷積神經網路

深度學習筆記5-tensorflow實現卷積神經網路

在股票等預測模型中,可以從原始資料提取金融因子等特徵。而影象則無有效特徵,只能藉助SIFT、HOG等提取有效特徵,再集合SVM等機器學習演算法進行影象識別。卷積神經網路(CNN)提取的特徵則可以達到更好的效果,同時它不需要將特徵提取和分類訓練兩個過程分開,它在訓練時就自動提取了最有效的特徵。CNN可以直接使用影象的原始畫素作為輸入,而不必先使用SIFT等演算法提取特徵,減輕了使用傳統演算法如SVM時必需要做的大量重複、煩瑣的資料預處理工作。和SIFT等演算法類似,CNN訓練的模型同樣對縮放、平移、旋轉等畸變具有不變性,有著很強的泛化性。CNN的最大特點在於卷積的權值共享結構,可以大幅減少神經網路的引數量,防止過擬合的同時又降低了神經網路模型的複雜度。

一般的卷積神經網路由多個卷積層構成,每個卷積層中通常會進行如下幾個操作:
(1)影象通過多個不同的卷積核的濾波,並加偏置(bias),提取出區域性特徵,每一個卷積核會映射出一個新的2D影象。
(2)將前面卷積核的濾波輸出結果,進行非線性的啟用函式處理。目前最常見的是使用ReLU函式(ReLU函式可參見深度學習筆記2-啟用函式
(3)對啟用函式的結果再進行池化操作(即降取樣,比如將2×2的圖片降為1×1的圖片),目前一般是使用最大池化,保留最顯著的特徵,並提升模型的畸變容忍能力。
(4)為了提升訓練速度、加快收斂過程、降低引數初始化的要求,可在每一個卷積層後加上BatchNomalization層

TensorFlow實現簡單的卷積網路

import tensorflow as tf
import input_data
#載入MNIST資料集
mnist=input_data.read_data_sets("MNIST_data/",one_hot=True)

#對於權重製造一些隨機的噪聲來打破完全對稱,比如截斷的正態分佈噪聲,標準差設為0.1。
def weight_variable(shape):
    initial=tf.truncated_normal(shape,stddev=0.1)
    return tf.Variable(initial)
    
#因為我們使用ReLU,也給偏置增加一些小的正值(0.1)用來避免死亡節點。
def bias_variable(shape):
    initial=tf.constant(0.1,shape=shape)
    return tf.Variable(initial)

#x是輸入,W是卷積的引數,比如[5,5,1,32]:前面兩個數字代表卷積核的尺寸;
#W的第三個數字代表有多少個channel,對於灰度圖應設定為1,對於彩色圖應設定為3
#W的第四個數字代表卷積核的數量,也就是這個卷積層會提取多少類的特徵。
#Strides代表卷積模板移動的步長,都是1代表會不遺漏地劃過圖片的每一個點。
#Padding代表邊界的處理方式,這裡的SAME代表給邊界加上Padding讓卷積的輸出和輸入保持同樣(SAME)的尺寸。
def conv2d(x,W):
    return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')

#這裡使用2×2的最大池化,即將一個2×2的畫素塊降為1×1的畫素。最大池化會保留原始畫素塊中灰度值最高的那一個畫素,即保留最顯著的特徵。
#因為希望整體上縮小圖片尺寸,因此池化層的strides也設為橫豎兩個方向以2為步長。如果步長還是1,那麼我們會得到一個尺寸不變的圖片。
def max_pool_2x2(x):
    return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

#開始構建圖
x=tf.placeholder("float",shape=[None,784])
#將1D的輸入向量轉為2D的圖片結構,即從1×784的形式轉為原始的28×28的結構。
#同時因為只有一個顏色通道,故最終尺寸為[-1,28,28,1],前面的-1代表樣本數量不固定,最後的1代表顏色通道數量。
#注意圖片格式和卷積格式的各個維度的定義是不一樣的
x_image=tf.reshape(x,[-1,28,28,1])
y_=tf.placeholder("float",shape=[None,10])

#構建第一個卷積層
W_conv1=weight_variable([5,5,1,32])
b_conv1=bias_variable([32])
h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)
h_pool1=max_pool_2x2(h_conv1)

#構建第二個卷積層
W_conv2=weight_variable([5,5,32,64])     #卷積核變成64個了
b_conv2=bias_variable([64])
h_conv2=tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)
h_pool2=max_pool_2x2(h_conv2)

#構建全連線層
W_fc1=weight_variable([7*7*64,1024])
b_fc1=bias_variable([1024])
h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64])
h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1)

#為了減輕過擬合,下面使用一個Dropout層
#通過一個placeholder傳入keep_prob比率來控制遺棄率
#注意,在訓練時,會隨機丟棄一部分節點的資料來減輕過擬合,預測時則保留全部資料來追求最好的預測效能。
keep_prob=tf.placeholder("float")
h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob)

#構建第二個全連線層,將輸出連線一個Softmax層,得到最後的概率輸出。
W_fc2=weight_variable([1024,10])
b_fc2=bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)

#定義損失函式
cross_entropy=-tf.reduce_sum(y_*tf.log(y_conv))

#優化函式選為Adam函式
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

#定義準確率用以評測
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

#下面開始訓練過程,採用預設的Interactive Session
sess=tf.InteractiveSession()
sess.run(tf.global_variables_initializer())   #初始化所有引數
#使用大小為50的mini-batch,共進行1000次訓練迭代。每100次訓練後,會對準確率進行一次評測
for i in range(1000):
    batch=mnist.train.next_batch(50)
    if i%100==0:
        train_accuracy=accuracy.eval(feed_dict={x: batch[0], y_: batch[1],keep_prob:0.5})
        print('step %d, training accuracy %g'%(i,train_accuracy))
    train_step.run(feed_dict={x:batch[0],y_:batch[1],keep_prob:0.5})
#全部訓練完成後,在最終的測試集上進行測試,得到整體的分類準確率。
print('test accuracy %g'%accuracy.eval(feed_dict={x:mnist.test.images,y_:mnist.test.labels,keep_prob:1.0}))
    
sess.close()

基本上,以上程式已經包括了構建神經網路的流程:
(1)定義圖,也就是神經網路forward時的計算
(2)定義loss,選定優化器,並指定優化器優化loss
(3)迭代地對資料進行訓練
(4)在測試集上對準確率進行評測

參考:
黃文堅《Tensorflow實戰》