TensorFlow 實踐之手寫體數字識別!
本文的主要目的是教會大家運用google開源的深度學習框架tensorflow來實現手寫體數字識別,給出兩種模型,一種是利用機器學習中的softmax regression作分類器,另一種將是搭建一個深度神經網路以達到99%正確率的手寫體數字識別模型。 其次,理解tensorflow工作流程和運行機制。最後,也會讓大家了解一下深度神經網路的搭建過程。
第一種模型
我們知道,做機器學習的項目離不開數據,行業里有句話叫做「得數據者,得天下」,雖有點言過其實,但事實上,足夠的樣本數據是你獲得較好模型的前提之一。這裡,用到的是大名鼎鼎的mnist,其官網是http://yann.lecun.com/exdb/mnist/,大家可以自由下載。google給出的下載源碼是input_data.py,可以從https://github.com/xupeng082008/tensorflow_mnist下載。下載後的數據集分為訓練集、驗證集、測試集(也就是train_data,validation_data,test_dasta,記住,這樣的劃分很重要,它可以檢驗我們得到的模型在真實場景下的識別能力)。無論是訓練、驗證還是測試集,單個樣本都是一幀包含手寫數字的28x28圖像以及其對應的標籤。有了數據,我們開始建立模型。這裡的模型是機器學習經常用到的softmax regression。
簡單地用圖片來表示一下:
用乘積形式表示如下:
在tensorflow中,它是這樣實現的:
import tensorflow as tf
y=tf.nn.softmax(tf.matmul(x,w) + b)
x是輸入(這裡可以理解為28x28的圖像拉伸為一個1x784向量),w是網路權重係數,b是偏置。
代碼相當簡單,好理解。
下面貼出該模型所有的代碼並作出解釋
import tensorflow as tf
import input_data
#載入數據,注意一下one_hot 在tensorflow中,
#表示一個列向量,其中一個不為0,剩下的為0
mnist=input_data.read_data_sets("Mnist_data/",one_hot=True)
#在tensorflow中,tf.placeholder表示一個佔位符,x不是一個特定的值,
#在運行時,才有值
x = tf.placeholder("float",[None,784])
#在tensorflow中,tf.Variable表示變數,且可以用不同的方式初始化
w = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
#softmax模型
y = tf.nn.softmax(tf.matmul(x,w) + b)
y_ = tf.placeholder("float",[None,10])
#模型的損失是交叉熵,詳情可以見原創 乾貨|深度學習——損失函數不同,
收斂效率不同
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
#隨機梯度下降優化演算法
#主要:TensorFlow 在這裡實際上所做的是,它會在後台給述你的計算的那張圖
#裡面增加一系列新的計算操作單元用於實現反向傳播演算法和梯度下降演算法.然後,
#它返回給你的只是一個單一的操作,當運行這個操作時,它用梯度下降演算法訓練
#你的模型,微調你的變數,不斷減少成本
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
#這裡的代碼跟tensorflow運行機制相關
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
for i in range(1000):#1000 or more
batch_xs,batch_ys = mnist.train.next_batch(100)
sess.run(train_step,feed_dict=)
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))
print sess.run(accuracy,feed_dict=)
這裡簡單說說tensorflow運行機制相關,讓讀者有一個感性的認識:
tensorflow使用圖(graphs)來表示模型的整個計算過程
tensorflow在會話(Session)中執行圖所表示的運行過程
tensorflow使用張量(tensors)來代表數據,可以表示為輸入向量,權重係數等等
tensorflow通過變數(Variables)維護變數的運行狀態
tensorflow使用供給(feeds)和取回(fetches)將數據傳入或傳出等操作
總之,tensorflow是以圖來表示整個程序運行系統,圖中以節點為組織,在會話中執行運行,然後產生張量,這個張量是一個四維向量,在圖中流動起來。可以理解前面部分代碼是在構建,後面是在執行。
上面的代碼執行情況如下:
迭代次數正確率100091.19%500092.21%2000092.27%
可以,softmax regression在這裡達到的最好成績92%左右,跟理想的還差很遠。
第二種模型
這裡,我們的模型是一個有著兩個卷積層,2個全聯接層,一個輸出層組成,繼續使用交叉熵損失函數,激活函數是relu,並且使用dropout技術,結構圖如下:
Inputconv1pool1conv2pool2fc1dropoutfc2softmax
下面,我們來看看在tensorflow如何實現上面表格實現的深度神經網路
import tensorflow as tf
import input_data
mnist=input_data.read_data_sets("Mnist_data/",one_hot=True)
sess = tf.InteractiveSession()
x = tf.placeholder("float",shape=[None,784])
y_ = tf.placeholder("float",shape=[None,10])
w = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
#init weights and biases
#初始化權重係數、偏置,注意這裡初始化不是用0來填充,以打破對稱性
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)
#define convolution and pool function
#定義卷積、池化,tensorflow中有實現,具體實踐,我們自行修改參數
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")
#conv and pool
#the first conv_pool
#patchsize(5x5) input_channels(1) output_channels(32 feature_maps)
w_conv1 = weight_variable([5,5,1,32])
b_conv1 = bias_variable([32])
x_image = tf.reshape(x,[-1,28,28,1])
#1st hidden outputs
h_conv1 = tf.nn.relu(conv2d(x_image,w_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
#the second conv_pool
w_conv2 = weight_variable([5,5,32,64])
b_conv2 = bias_variable([64])
#2nd hidden outputs
h_conv2 = tf.nn.relu(conv2d(h_pool1,w_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
#fc全聯接層
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使用dropout技術可以防止過擬合
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)
#readout layer
w_fc2 = weight_variable([1024,10])
b_fc2 = bias_variable([10])
#softmax output
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop,w_fc2) + b_fc2)
#define loss function
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
#optimizer method choice
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,"float"))
sess.run(tf.initialize_all_variables())
for i in range(10000):
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=)
print "test accuracy %g"%accuracy.eval(feed_dict={
x:mnist.test.images,y_:mnist.test.labels,keep_prob:1.0})
下面給出一些訓練過程中間圖:
可以看出,訓練識別率還是很不錯的,我們看下最終迭代10000次的訓練和測試結果:
測試集上的正確率是99%左右。
可見深度神經網路,在手寫體識別項目上表現地相比於softmax regression,效果會好的多的多。
總結
我們學習了在tensorflow中實現softmax regression、一種深度神經網路的過程;簡單了解了tensorflow的運行機制和內部參數、函數機構,相信看完大家可以手動設計一個神經網路將識別率繼續提高。
代碼:https://github.com/xupeng082008/tensorflow_mnist
-加入人工智慧學院系統學習-
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
※未來 3 5 年內,什麼樣的機器學習人才最緊缺?
※神經網路結構在命名實體識別中的應用
TAG:AI講堂 |