深度學習筆記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實戰》