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