手寫字符的識別(MINST+CNN+TensorFlow+建模+單個數字識別)

手寫數字的識別應該是算是機器學習的入門實驗

手寫字符的開源數據集:http://yann.lecun.com/exdb/mnist/
如果找不到,可以在我的資源中免費下載,free

數據集是不是到手了,想要達到準確識別的效果,俺給分成了兩大塊

訓練and測試
訓練是啥啊,訓練的是模型
測試是啥啊,測試的是模型
所以要建立兩個程序,“train.py”和“text.py”。

數據集不多說,直接建模,直接摟程序,Python代碼走一波

建模需要啥呢?

導入所需庫+數據集讀取+初始化參數+卷積神經網絡搭建+模型性能指標+模型迭代調優+保存深度學習模型

就這幾部分,整明白就完事。別墨跡,長篇大論的,誰也不愛看。

(1)導入所需庫
手寫數字所需要的導入的應該是比較少比較簡單的

import tensorflow as tf
# import input_data
from tensorflow.examples.tutorials.mnist import input_data

(2)數據集讀取
由於是公開數據集,也就是內置數據集,直接讀取即可

mnist = input_data.read_data_sets('E:/MNIST_data(自己的數據集位置)', one_hot=True)               # one_hot 編碼 [1 0 0 0]

(3)初始化參數

# 佔位符
x = tf.placeholder("float", shape=[None, 784], name='x')   # 輸入
y_ = tf.placeholder("float", shape=[None, 10], name='y_')  # 實際值

# 初始化權重
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)   # 產生正態分佈 標準差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')  # 最大池化

卷積神經網絡的參數,基本知識,不過分吧。

(4)卷積神經網絡搭建

# 第一層卷積  卷積在每個5*5中算出32個特徵
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)

# 密集連接層  圖片尺寸縮減到了7*7, 本層用1024個神經元處理
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 防止過擬合
keep_prob = tf.placeholder("float", name='keep_prob')
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, name='y_conv')

w是權重,b是偏置,conv代表卷積,relu是激活函數,pool是池化,fc是全連接層,dropout用於防止過擬合,softmax分類器
tf.matmul爲矩陣相乘
tf.multiply爲矩陣中對應元素各自相乘

接下來引出TensorFlow的核心數據單位——張量(不是張亮,更不是麻辣燙,而是Tensor)
張量是由陣列(任意維數)的原始值組成。張量的階是它的維數,而它的形狀是一個整數元組,指定了陣列每個維度的長度。

介紹幾個特殊張量:
tf.placeholder:
創建佔位符,相當於形參,說白了就是你杵在車位上幫你父親搶車位

tf.Variable:創建變量

tf.get_variable:獲取變量

tf.constant:創建常量

dtype: 數據類型

shape:
數據形狀,默認是 None。[None, 3] 表示列是 3,行不確定。

(5)模型性能指標

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, "float"))
sess.run(tf.global_variables_initializer())

“cross_entropy”:交叉熵損失函數

“tf.reduce_sum”:降維求和,返回與輸入數據類型相同的降維後的結果

“tf.train.AdamOptimizer”:Adam優化算法

“ tf.equal(A,B)”:對比這兩個矩陣或者向量的相等的元素,如果不相等,返回數值是A的矩陣維度。

“tf.argmax()”:返回最大的那個數值所在的下標。

“tf.reduce_mean”:張量在某一維度的平均值。

“tf.cast”:就是框架裏的類型轉換函數

“tf.global_variables_initializer()”:英語直譯ok不,爲啥用呢,因爲tf中建立的變量是沒有初始化的,可能不是一個tensor,要是不用,就是loser。

(6)模型迭代調優

for i in range(2000):
    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(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

就是跑多少,怎麼跑,跑的咋樣。

(7)保存深度學習模型

saver.save(sess, "E:/手寫字符/ckpt_dir/model.ckpt") 

保存下模型,能做到不?

訓練階段這樣就完事了,那保存是啥樣的呢,如下圖所示
在這裏插入圖片描述
接下來改調用模型了

開始測試

當然,在測試之前,你要自己準備好手寫數字的圖片,可以網上找,可以直接手寫,反正有就可以
在這裏插入圖片描述
開始測試代碼
一樣分成幾塊:
庫+讀取+導入模型+結果

(1):庫

from PIL import Image
import tensorflow as tf

(2)讀取單張圖片

def imageprepare():
    file_name = 'E:/手寫字符/9.png'
    myimage = Image.open(file_name)
    myimage = myimage.resize((28, 28), Image.ANTIALIAS).convert('L')   
                                     #變換成28*28像素,並轉換成灰度圖
    tv = list(myimage.getdata())     # 獲取像素值
    tva = [(255-x)*1.0/255.0 for x in tv]      # 轉換像素範圍到[0 1], 0是純白 1是純黑
    return tva

(3)導入模型

with tf.Session() as sess:
    sess.run(init)
    saver = tf.train.import_meta_graph('手寫字符/ckpt_dir/model.ckpt.meta')  
                                    # 載入模型結構
    saver.restore(sess,  '手寫字符/ckpt_dir/model.ckpt')     
                                    # 載入模型參數
    graph = tf.get_default_graph()  # 加載計算圖
    x = graph.get_tensor_by_name("x:0")      # 從模型中讀取佔位符張量
    keep_prob = graph.get_tensor_by_name("keep_prob:0")
    y_conv = graph.get_tensor_by_name("y_conv:0")     # 關鍵的一句  從模型中讀取佔位符變量

(4)結果

prediction = tf.argmax(y_conv, 1)
 predint = prediction.eval(feed_dict={x: [result], keep_prob: 1.0}, session=sess)
                       # feed_dict輸入數據給placeholder佔位符
print(predint[0])      # 打印預測結果

這樣就完成了單張數字的識別了,一次可以識別一張

想看一次識別多張圖片嗎

不要走開,我有一次可多張識別的花朵識別程序,感興趣的可以給我批評指正一下。

看到這用了不少時間吧,快休息休息吧!

發佈了8 篇原創文章 · 獲贊 19 · 訪問量 2179
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章