两层全连接神经网络实现手写数字识别
一,思路:
分為兩步,第一步是訓練模型然后把模型保存到磁盤,第二步是復現模型結構然后讀取模型權重系數,輸入手寫數字圖片驗證模型識別能力。
二,模型訓練
在這部分使用mnist數據集,該數據集含有七萬張28*28的灰度化的手寫數字圖片,其中六萬張用于訓練,一萬張用于訓練階段的測試。
過程分為六步:(1.)import 相關模塊 (2.)讀入訓練集與測試集 (3.)用Sequential模型(或者有的人叫它神經網絡容器)搭建神經網絡 (4.)定義神經網絡訓練時的優化器(或者叫參數更新的方法,例如隨機梯度下降法SGD),損失函數(MSE或者交叉熵),測評指標(用來計算損失函數)(5.)訓練模型 ,把最優模型保存到磁盤(6.)打印訓練總覽
代碼如下:
對于該程序的分析,還是要抓住數據結構的變化:
剛剛讀入數據集后train_dat是三維數組,shape:(60000,28,28)。第一個維度的每個元素是一個二維數組即一張圖片的數據。train_label是一個shape為(60000)的一維數組,每個元素是一個數值即標簽。test_data的shape(10000,28,28),test_label的shape為:(10000)。然后數據輸入神經網絡。神經網絡拉直層無運算能力,不算層數,僅僅是把多維數組拉伸為一維數組。拉伸層之后為隱藏層,具有128個神經元,使用relu激活函數。最后是輸出層,具有十個神經元,使用sotmax激活函數使得神經網絡輸出為概率形式。
神經網絡結構示意圖如下:
現在分析數據結構的變換:
輸入數據按32個分成一個batch,即shape:(32,28,28)。經過拉伸層變為shape:(32,784)
拉直層到隱藏層的全連接權重系數矩陣shape:(784,128)。shape:(32,784)Xshape:(784,128)
得到的矩陣shape為(32,128),這就是隱藏層輸出的數據結構。隱藏層到輸出層的全連接結系數矩陣shape:(128,10)。shape(32,128)Xshape:(128,10)=shape:(32,10),這就是輸出層數據數據的結構,一共有32行,每行是一個特征數據(輸入的待識別圖片)對于十分類的概率值,取其中概率值最大的分類對應的標簽作為手寫數字圖片的識別結果。
然后再來看看神經網絡的權重系數參數示意(如下圖):
拉直層沒有運算能力,沒有可訓練參數;全連接層1一共有784X128(隱藏層的系數矩陣元素數目)+128(偏置項元素數目)=100480個可訓練參數;輸出層有128X10(隱藏層與輸出層之間的系數矩陣元素數目)+10(偏置項元素數目)=1290個參數。僅僅一個兩層全連接神經網絡就有超過十萬個參數需要訓練,因此在拉直層之前加入卷積層搭建卷積神經網絡減少待訓練參數數目是必要的。
三,復現模型結構,讀取訓練后得到的最優模型,然后進行實際測試
from PIL import Image import numpy as np import tensorflow as tfmodel_save_path = './mnist.ckpt' # 指定模型的路徑# 復現模型結構 model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),tf.keras.layers.Dense(128, activation='relu'),tf.keras.layers.Dense(10, activation='softmax')])# 讀入已經經過訓練的權重系數 model.load_weights(model_save_path)while True:image_path = input("輸入圖片名")img = Image.open(image_path)# 縮放輸入圖片,使其大小固定img = img.resize((28, 28), Image.ANTIALIAS) # Image.ANTIALIAS抗鋸齒,抗圖像折疊失真img_arr = np.array(img.convert('L')) # 轉為8位寬的np.array數據類型# 遍歷每一個像素,進行閾值二值化處理,把輸入圖片轉換為黑底白字圖片,因為訓練時的圖片 全是黑的白字的for i in range(28):for j in range(28):if img_arr[i][j] < 200:img_arr[i][j] = 255else:img_arr[i][j] = 0img_arr = img_arr / 255.0 # 不歸一化可能無法收斂x_predict = img_arr[tf.newaxis, ...] # 添加一個維度,變為shape:(1,28,28),為輸入predict函數做準備;# predict函數默認參數batch=32,要求輸入數據是三維的。result = model.predict(x_predict) # model.predict執行神經網絡前向傳播過程,得到神經網絡預測結果print(result) # 打印十分類概率值pred = tf.argmax(result, axis=1) # 取概率最大的分類的標簽值,標簽值與0~9數字一一對應print('\n')tf.print("識別結果為:", pred)四,實際測試
手寫了幾張數字圖片(就比如下面那幾張),大小可以任意,因為輸入驗證的時候會調整大小。圖片名例如為2.png,3.png等
注:數據增強(隨機旋轉,隨機偏移等增大數據量)之后的識別結果會更好一點。
如果不想使用keras而只用原生的tensorflow的話可以參考我的一篇博客:
最簡單的單層神經網絡實現鳶尾花分類
參考:北京大學《人工智能實踐-Tensorflow筆記》課程
總結
以上是生活随笔為你收集整理的两层全连接神经网络实现手写数字识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 协同OA产品要完全符合企业的办公模式吗?
- 下一篇: 深度:企业为什么需要一个平台级的OA产品