原文鏈接:blog.csdn.net/sparta_117/article/details/66965760
使用Tensorflow和MNIST識別自己手寫的數字
最近在學習神經網絡相關的東西,發現有很多資料是Tensorflow教程上的內容,但是教程很多只是一個驗證官方程序的過程。如何將官方程序變成自己可以利用的程序,網上似乎資料比較少,所以我就來介紹一下如何使用Tensorflow和MNIST搭建自己的手寫識別算法,識別自己寫的數字(比如下面我寫的這個蒼勁有力的3~~)。本文也參考了國外大神博客的內容。純新手,之前在博客上收益良多,也希望能幫助和我一樣剛剛起步的童鞋,大家多多指教。
內容如下:
-Tensorflow和MNIST簡介
-CNN算法
-訓練程序
-寫數字,并用Opencv進行預處理
-將圖片輸入網絡進行識別
TensorFlow? 是一個采用數據流圖,用于數值計算的開源軟件庫。它是一個不嚴格的“神經網絡”庫,可以利用它提供的模塊搭建大多數類型的神經網絡。它可以基于CPU或GPU運行,可以自動使用GPU,無需編寫分配程序。主要支持Python編寫,但是官方說也有C++使用界面。
MNIST是一個巨大的手寫數字數據集,被廣泛應用于機器學習識別領域。MNIST有60000張訓練集數據和10000張測試集數據,每一個訓練元素都是28*28像素的手寫數字圖片。作為一個常見的數據集,MNIST經常被用來測試神經網絡,也是比較基本的應用。
識別算法主要使用的是卷積神經網絡算法(CNN)。
主要結構為:輸入-卷積層-池化層-卷積層-池化層-全連接層-輸出
卷積
卷積其實可以看做是提取特征的過程。如果不使用卷積的話,整個網絡的輸入量就是整張圖片,處理就很困難。
(這里使用了參考了別人博客中的內容,來源記不清了TAT)
假設圖中綠色5*5矩陣為原圖片,黃色的3*3矩陣就是我們的過濾器,即卷積核。將黃色矩陣和綠色矩陣被覆蓋的部分進行卷積計算,即每個元素相乘求和,便可得到這一部分的特征值,即圖中的卷積特征。
然后,向右滑動黃色的矩陣,便可繼續求下一部分的卷積特征值。而滑動的距離就是步長。
池化
池化是用來把卷積結果進行壓縮,進一步減少全連接時的連接數。
池化有兩種:
一種是最大池化,在選中區域中找最大的值作為抽樣后的值;
一種是平均值池化,把選中的區域中的平均值作為抽樣后的值。
這里我就先把程序貼出來,主體和tensorflow教程上大致相同。值得注意的是其中的saver部分,將訓練的權重和偏置保存下來,在評價程序中可以再次使用。
訓練好了網絡,下一步就要測試它了。自己寫一個數字,然后用Opencv預處理一下再扔到評價程序里,看看能不能準確識別。
我們先來識別這張我開頭寫的3吧:(可以寫得再奇怪一些,檢測一下識別能力)
下面我們就要對它進行預處理,縮小它的大小為28*28像素,并轉變為灰度圖,進行二值化處理。我使用的是Opencv對圖像進行處理,也可以使用MATLAB等進行預處理。
圖片預處理程序如下:(程序改編自http://blog.csdn.net/skeeee/article/details/16844937,可以使用鼠標拖動選取框,對選取框中的圖像進行處理)
完成預處理程序后,我們得到了這樣的圖片:
這就是28*28的二值化后的圖片,這樣的格式和我們MNIST數據集中的圖片格式相同。只有這樣,我們才能將圖片輸入到網絡中進行識別。
這里我是編寫了一個前向傳播的程序,最后softmax層分類的結果就是最后的識別結果啦。
程序如下:(這里參考了一個外網的博客,地址不記得了。。。)
from PIL import Image, ImageFilter
import tensorflow as tf
import matplotlib.pyplot as plt
import cv2
def imageprepare():
"""
This function returns the pixel values.
The imput is a png file location.
"""
file_name='/home/mzm/MNIST_recognize/p_num2.png'#導入自己的圖片地址
#in terminal 'mogrify -format png *.jpg' convert jpg to png
im = Image.open(file_name).convert('L')
im.save("/home/mzm/MNIST_recognize/sample.png")
plt.imshow(im)
plt.show()
tv = list(im.getdata()) #get pixel values
#normalize pixels to 0 and 1. 0 is pure white, 1 is pure black.
tva = [ (255-x)*1.0/255.0 for x in tv]
#print(tva)
return tva
"""
This function returns the predicted integer.
The imput is the pixel values from the imageprepare() function.
"""
# Define the model (same as when creating the model file)
result=imageprepare()
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
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)
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')
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
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)
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)
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)
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
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)
init_op = tf.initialize_all_variables()
"""
Load the model2.ckpt file
file is stored in the same directory as this python script is started
Use the model to predict the integer. Integer is returend as list.
Based on the documentatoin at
https://www.tensorflow.org/versions/master/how_tos/variables/index.html
"""
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(init_op)
saver.restore(sess, "/home/mzm/MNIST_recognize/form/model2.ckpt")#這里使用了之前保存的模型參數
#print ("Model restored.")
prediction=tf.argmax(y_conv,1)
predint=prediction.eval(feed_dict={x: [result],keep_prob: 1.0}, session=sess)
print(h_conv2)
print('recognize result:')
print(predint[0])
通過這個程序,得到最后的識別結果截圖如下: