TensorFlow 簡單實例


TF 手寫體識別簡單實例:

TensorFlow很適合用來進行大規模的數值計算,其中也包括實現和訓練深度神經網絡模型。下面將介紹TensorFlow中模型的基本組成部分,同時將構建一個CNN模型來對MNIST數據集中的數字手寫體進行識別。

基本設置

在我們構建模型之前,我們首先加載MNIST數據集,然后開啟一個TensorFlow會話(session)。

加載MNIST數據集

TensorFlow中已經有相關腳本,來自動下載和加載MNIST數據集。(腳本會自動創建MNIST_data文件夾來存儲數據集)。下面是腳本程序:

from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets('MNIST_data', one_hot=True) 

這里mnist是一個輕量級的類文件,存儲了NumPy格式的訓練集、驗證集和測試集,它同樣提供了數據中mini-batch迭代的功能。

開啟TensorFlow會話

TensorFlow后台計算依賴於高效的C++,與后台的連接稱為一個會話(session)。TensorFlow中的程序使用,通常都是先創建一個圖(graph),然后在一個會話(session)里運行它。

這里我們使用了一個更為方便的類,InteractiveSession,這能讓你在構建代碼時更加靈活。InteractiveSession允許你做一些交互操作,通過創建一個計算流圖(computation graph)來部分地運行圖計算。當你在一些交互環境(例如IPython)中使用時將更加方便。如果你不是使用InteractiveSession,那么你要在啟動一個會話和運行圖計算前,創建一個整體的計算流圖。

下面是如何創建一個InteractiveSession

import tensorflow as tf
sess = tf.InteractiveSession() 

計算流圖(Computation Graph)

為了在Python中實現高效的數值運算,通常會使用一些Python以外的庫函數,如NumPy。但是,這樣做會造成轉換Python操作的開銷,尤其是在GPUs和分布式計算的環境下。TensorFlow在這一方面(指轉化操作)做了優化,它讓我們能夠在Python之外描述一個包含各種交互計算操作的整體流圖,而不是每次都獨立地在Python之外運行一個單獨的計算,避免了許多的轉換開銷。這樣的優化方法同樣用在了TheanoTorch上。

所以,以上這樣的Python代碼的作用是簡歷一個完整的計算流圖,然后指定圖中的哪些部分需要運行。關於計算流圖的更多具體使用見這里

Softmax Regression模型

上篇博文

CNN模型

Softmax Regression模型在MNIST數據集上91%的准確率,其實還是比較低的。下面我們將使用一個更加精巧的模型,一個簡單的卷積神經網絡模型(CNN)。這個模型能夠達到99.2%的准確率,盡管這不是最高的,但已經足夠接受了。

權值初始化

為了建立模型,我們需要先創建一些權值(w)和偏置(b)等參數,這些參數的初始化過程中需要加入一小部分的噪聲以破壞參數整體的對稱性,同時避免梯度為0.由於我們使用ReLU激活函數(詳細介紹)),所以我們通常將這些參數初始化為很小的正值。為了避免重復的初始化操作,我們可以創建下面兩個函數:

def weight_variable(shape): initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) def bias_variable(shape): initial = tf.constant(0.1, shape=shape) return tf.Variable(initial) 

卷積(Convolution)和池化(Pooling)

TensorFlow同樣提供了方便的卷積和池化計算。怎樣處理邊界元素?怎樣設置卷積窗口大小?在這個例子中,我們始終使用vanilla版本。這里的卷積操作僅使用了滑動步長為1的窗口,使用0進行填充,所以輸出規模和輸入的一致;而池化操作是在2 * 2的窗口內采用最大池化技術(max-pooling)。為了使代碼簡潔,同樣將這些操作抽象為函數形式:

def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') def max_pool_2x2(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') 

其中,padding='SAME'表示通過填充0,使得輸入和輸出的形狀一致。

第一層:卷積層

第一層是卷積層,卷積層將要計算出32個特征映射(feature map),對每個5 * 5的patch。它的權值tensor的大小為[5, 5, 1, 32]. 前兩維是patch的大小,第三維時輸入通道的數目,最后一維是輸出通道的數目。我們對每個輸出通道加上了偏置(bias)。

W_conv1 = weight_variable([5, 5, 1, 32]) b_conv1 = bias_variable([32]) 

為了使得圖片與計算層匹配,我們首先reshape輸入圖像x為4維的tensor,第2、3維對應圖片的寬和高,最后一維對應顏色通道的數目。

?第1維為什么是-1? : 解釋,https://www.zhihu.com/question/52684594  

=== 數組新的shape屬性應該要與原來的配套,如果等於-1的話,那么Numpy會根據剩下的維度計算出數組的另外一個shape屬性值。

x_image = tf.reshape(x, [-1,28,28,1]) 

然后,使用weight tensorx_image進行卷積計算,加上bias,再應用到一個ReLU激活函數,最終采用最大池化。

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) h_pool1 = max_pool_2x2(h_conv1) 

第二層:卷積層

為了使得網絡有足夠深度,我們重復堆積一些相同類型的層。第二層將會有64個特征,對應每個5 * 5的patch。

W_conv2 = weight_variable([5, 5, 32, 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) 

全連接層

到目前為止,圖像的尺寸被縮減為7 * 7,我們最后加入一個神經元數目為1024的全連接層來處理所有的圖像上。接着,將最后的pooling層的輸出reshape為一個一維向量,與權值相乘,加上偏置,再通過一個ReLu函數。

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) 

整個CNN的網絡結構如下圖:

Dropout

為了減少過擬合程度,在輸出層之前應用dropout技術(即丟棄某些神經元的輸出結果)。我們創建一個placeholder來表示一個神經元的輸出在dropout時不被丟棄的概率。Dropout能夠在訓練過程中使用,而在測試過程中不使用。TensorFlow中的tf.nn.dropout操作能夠利用mask技術處理各種規模的神經元輸出。

keep_prob = tf.placeholder(tf.float32) h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) 

輸出層

最終,我們用一個softmax層,得到類別上的概率分布。(與之前的Softmax Regression模型相同)。

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) 

模型訓練和測試

為了測試模型的性能,需要先對模型進行訓練,然后應用在測試集上。和之前Softmax Regression模型中的訓練、測試過程類似。區別在於:

  1. 用更復雜的ADAM最優化方法代替了之前的梯度下降;
  2. 增了額外的參數keep_probfeed_dict中,以控制dropout的幾率;
  3. 在訓練過程中,增加了log輸出功能(每100次迭代輸出一次)。

下面是程序:

cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv)) 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)) sess.run(tf.initialize_all_variables()) for i in range(20000): batch = mnist.train.next_batch(50) if i%100 == 0: train_accuracy = accuracy.eval(feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}) 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})) 

最終,模型在測試集上的准確率大概為99.2%,性能上要優於之前的Softmax Regression模型。

完整代碼及運行結果

利用CNN模型實現手寫體識別的完整代碼如下:

__author__ = 'chapter' import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data def weight_varible(shape): initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) def bias_variable(shape): initial = tf.constant(0.1, shape=shape) return tf.Variable(initial) def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') def max_pool_2x2(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) print("Download Done!") sess = tf.InteractiveSession() # paras W_conv1 = weight_varible([5, 5, 1, 32]) b_conv1 = bias_variable([32]) # conv layer-1 x = tf.placeholder(tf.float32, [None, 784]) x_image = tf.reshape(x, [-1, 28, 28, 1]) h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) h_pool1 = max_pool_2x2(h_conv1) # conv layer-2 W_conv2 = weight_varible([5, 5, 32, 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) # full connection W_fc1 = weight_varible([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 keep_prob = tf.placeholder(tf.float32) h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) # output layer: softmax W_fc2 = weight_varible([1024, 10]) b_fc2 = bias_variable([10]) y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) y_ = tf.placeholder(tf.float32, [None, 10]) # model training cross_entropy = -tf.reduce_sum(y_ * tf.log(y_conv)) train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) correct_prediction = tf.equal(tf.arg_max(y_conv, 1), tf.arg_max(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) sess.run(tf.initialize_all_variables()) for i in range(20000): batch = mnist.train.next_batch(50) if i % 100 == 0: train_accuacy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0}) print("step %d, training accuracy %g"%(i, train_accuacy)) train_step.run(feed_dict = {x: batch[0], y_: batch[1], keep_prob: 0.5}) # accuacy on test print("test accuracy %g"%(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))) 

運行結果如下圖:


 

轉載地址:

http://www.jeyzhang.com/tensorflow-learning-notes-2.html


免責聲明!

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



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