天天看點

Keras實作mnist手寫數字識别

一、編譯環境

tf1.14/1.6.0

python3.6.5

keras2.1.5

二、代碼

#coding=utf-8
[1]
#加載并列印資料結構
import keras
from keras.datasets import mnist
(train_images,train_labels),(test_images,test_labels)=mnist.load_data()
print("訓練集資料結構{};\n訓練集标簽資料結構{};\n測試集資料結構{};\n測試集标簽資料結構{};\n".format(train_images.shape,train_labels.shape,test_images.shape,test_labels.shape))
#注:後面models.fit()函數中設定了shuffle=True,是以此處不再設定

[2]
#列印訓練集的第一張圖檔
import matplotlib.pyplot as plt
digit=train_images[0]
plt.imshow(digit,cmap=plt.cm.binary)   #cmap=plt.cm.binary:二值圖
plt.show()

[3]
#建構網絡結構
'''
1、layers:表示神經網絡中的一個資料處理層(dense:全連接配接層)
2、models.Sequential():表示把每一個資料處理層串聯起來
3、layers.Dense(……):建構一個資料處理層
4、input_shape(28*28):表示目前處理層接收到的資料格式為長和寬都是28的二維數組,後面的“,”表示數組裡面的每個元素到底包含了多少個數字都沒有關系
'''
from keras import layers,models
network=models.Sequential()  #sequential:adj 連續的,有序的
network.add(layers.Dense(512,activation='relu',input_shape=(28*28,)))
network.add(layers.Dense(10,activation='softmax'))
network.compile(optimizer='RMSProp',loss='categorical_crossentropy',metrics=['accuracy'])
'''
model.compile(   #compile:彙編、編制
optimizer=優化器  可以字元串形式給出優化器的名字,也可以是函數形式  #RMSProp 算法通過累計各個變量的梯度的平方和r,然後用每個變量的梯度除以r,即可有效的緩解梯度變量間的梯度差異
loss=損失函數  可以字元串形式給出損失函數的名字,也可以是函數形式  categorical_crossentropy :交叉熵損失函數,因為資料标簽有麼是1要麼是0,是以不用考慮log(0)的情況
metrics=['準确率']  标注網絡評價名額,'accuracy':真實值y和預測值y_都有數值,如y=[1],如y_=[1]
)
'''

[4]
#資料傳入網絡模型前,先做歸一化處理
'''
1.reshape(60000, 28*28):train_images數組原來含有60000個元素,每個元素是一個28行,28列的二維數組,現在把每個二維數組轉變為一個含有28*28個元素的一維數組.
2.由于數字圖案是一個灰階圖,圖檔中每個像素點值的大小範圍在0到255之間.
3.train_images.astype(“float32”)/255 把每個像素點的值從範圍0-255轉變為範圍在0-1之間的浮點值。
'''
train_images=train_images.reshape(len(train_images),784)
train_images=train_images.astype('float32')/255
test_images=test_images.reshape(len(test_images),784)
test_images=test_images.astype('float32')/255

'''
把圖檔對應的标記也做一個更改:
目前所有圖檔的數字圖案對應的是0到9。
例如test_images[0]對應的是數字7的手寫圖案,那麼其對應的标記test_labels[0]的值就是7。
我們需要把數值7變成一個含有10個元素的數組,然後在第7個元素設定為1,其他元素設定為0。
例如test_lables[0] 的值由7轉變為數組[0,0,0,0,0,0,0,1,0,0,]
'''
from keras.utils import to_categorical   #to_categorical就是将類别向量轉換為二進制(隻有0和1)的矩陣類型表示。其表現為将原有的類别向量轉換為獨熱編碼的形式。
print('原測試集第一張圖檔的标簽為:',test_labels[0])
train_labels=to_categorical(train_labels,10)
test_labels=to_categorical(test_labels,10)
print('one_hot處理後測試集一張圖檔标簽為:',test_labels[0])

[5]
'''
把資料輸入網絡進行訓練:
train_images:用于訓練的手寫數字圖檔;
train_labels:對應的是圖檔的标記;
batch_size:每次網絡從輸入的圖檔數組中随機選取128個作為一組進行計算。
epochs:每次計算的循環是五次
'''
network.fit(train_images,train_labels,epochs=2,batch_size=128,shuffle=True)

[6]
'''
model.evaluate()函數:在測試的模式下傳回模型的誤內插補點和評估标準值,計算是分批進行的
evaluate(x=None,y=None,batch=None,verbose=1,sample_weight=None,steps=None)
verbose:0或者1,日志顯示模式。0—安靜模式;1——進度條
參考連結:https://keras.io/zh/models/model/
'''
test_loss,test_acc=network.evaluate(test_images,test_labels,verbose=0)
print('誤差(loss)值:{};\n正确率(acc):{};'.format(test_loss,test_acc))

[7]
#随便輸入一張圖檔,測試網絡的識别效果
import random
(train_images,train_labels),(test_images,test_labels)=mnist.load_data()
#在測試集中随便抽取一張
n=int(random.randint(0,len(test_images)))
digit=test_images[n]
plt.imshow(digit,cmap=plt.cm.binary)
plt.show()
test_image=digit.reshape(1,28*28)
res=network.predict(test_image)
'''
model.predict():為輸入樣本生成輸出預測,計算分批進行
predict(x,batch_size=None,verbose=0,steps=None)
batch_size:整數,如未指定,預設為32
verbose:日志顯示模式,0或1
steps:聲明預測結束之前的總步數(批次樣本),預設值為0
'''
print(res)
print(res.shape)
for i in range(res.shape[1]):  #此處res.shape[1]與one_hot的深度有關,最好不要寫成10
    if(res[0][i]==1):
        print('圖檔上的數字是:{};\n預測成功率為:{}'.format(i,test_acc))
        break

           

三、輸出結果

訓練集資料結構(60000, 28, 28);

訓練集标簽資料結構(60000,);

測試集資料結構(10000, 28, 28);

測試集标簽資料結構(10000,);

原測試集第一張圖檔的标簽為: 7

one_hot處理後測試集一張圖檔标簽為: [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]

誤差(loss)值:0.09232732669711113;

正确率(acc):0.9707;

[[0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]]

(1, 10)

圖檔上的數字是:2;

預測成功率為:0.9707

程序已結束,退出代碼 0

Keras實作mnist手寫數字識别

繼續閱讀