1. 程式人生 > 其它 >記錄一次手寫數字識別實戰

記錄一次手寫數字識別實戰

簡單搭建一個神經網路來進行手寫數字識別,準確率可以達到95%以上。

廢話不多說,我們直接開整。首先需要匯入需要的類庫,相關內容我會在後續程式碼中進行詳細介紹。

from keras.datasets import mnist
from keras.utils import to_categorical
from keras import models,layers,regularizers
from keras.optimizers import RMSprop

資料集為MNIST 手寫字元資料集,訓練集為 60,000 張 28x28 畫素灰度影象,測試集為 10,000 同規格影象,總共 10 類數字標籤。

用法:

from keras.datasets import mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
返回2 個元組:

  • x_train, x_test: 分別表示訓練集與測試集的圖片。
  • y_train, y_test: 分別表示訓練集與測試集的數字標籤(範圍在 0-9 之間的整數)。

下載資料集

根據上述用法我們可以直接將這個資料集下載下來。

#載入資料集
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

展平矩陣

通過上述介紹我們知道,每張圖片其實是一個2828的數字矩陣,矩陣中的每個數字(0-255)代表著該畫素點的灰度級。為了可以更方便的對其進行操作,我們將其變為一個一維的向量(784

1),即將這個數字矩陣展平,將這個正方形變為一個寬為1的長方形。astype方法用來轉換資料型別。

#展平
train_images = train_images.reshape((60000, 28*28)).astype('float')
test_images = test_images.reshape((10000, 28*28)).astype('float')

採用one-hot編碼

one-hot編碼是在深度學習中非常常見的一種編碼方式,使用它的目的就是為了能夠讓各種變數轉換為可以被各種演算法利用的形式。將離散型特徵使用one-hot編碼還會讓各個特徵之間的距離更加的合理。舉個例子,若用1來表示狗,2來表示貓,3來表示老鼠。則貓狗之間的距離為1,鼠狗之間的距離為2,但是貓狗之間的差別真的就小於鼠狗之間的差別嗎?這種差別又以什麼來作為標準呢?所以採用one-hot編碼,以[1,0,0]表示狗,[0,1,0]表示貓,[0,0,1]來表示老鼠就不會出現這種情況。
這裡用to_categorical方法來對十種數字進行編碼。例如,數字3的編碼方式為:[0,0,0,1,0,0,0,0,0,0,0]

#將標籤以onehot編碼
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

建立模型

這裡需要用到Sequential 順序模型,該模型是多個網路層的線性堆疊。我們可以簡單地使用 .add() 方法將各層新增到模型中。在這裡需要注意的是順序模型中的第一層(且只有第一層,因為下面的層可以自動地推斷尺寸)需要接收關於其輸入尺寸的資訊。

#建立模型
network = models.Sequential()
#kernel_regularizer正則化降低過擬合
network.add(layers.Dense(units=128, activation='relu', input_shape=(28*28, ), kernel_regularizer=regularizers.l1(0.0001)))
#drout層降低過擬合
network.add(layers.Dropout(0.01))
network.add(layers.Dense(units=32, activation='relu', kernel_regularizer=regularizers.l1(0.0001)))
network.add(layers.Dropout(0.01))
network.add(layers.Dense(units=10, activation='softmax'))

編譯與訓練

通過對模型設定一些超引數來儘可能的使模型達到最優。

#編譯
network.compile(optimizer=RMSprop(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])
#訓練
network.fit(train_images, train_labels, epochs=20, batch_size=128, verbose=2)

在測試集上測試效能

訓練模型最終的目的是為了預測,通過訓練模型已經能夠在訓練集上達到不錯的效果,現在為了檢驗在測試集上它的表現如何,採用evaluate方法返回模型的誤差值和評估標準值。

#在測試集上測試模型效能
test_loss, test_accuracy = network.evaluate(test_images, test_labels)
print("test_loss:", test_loss, "    test_accuracy:", test_accuracy)

最後附上完整程式碼:

from keras.datasets import mnist
import matplotlib.pyplot as plt
from keras.utils import to_categorical
from keras import models,layers,regularizers
from keras.optimizers import RMSprop

#載入資料集
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# print(train_images.shape, test_images.shape)
# print(train_images[0])
# print(train_labels[0])
# plt.imshow(train_images[0])
# plt.show()

#展平
train_images = train_images.reshape((60000, 28*28)).astype('float')
test_images = test_images.reshape((10000, 28*28)).astype('float')
#將標籤以onehot編碼
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
# print(train_labels[0])

#建立模型
network = models.Sequential()
#kernel_regularizer正則化降低過擬合
network.add(layers.Dense(units=128, activation='relu', input_shape=(28*28, ), kernel_regularizer=regularizers.l1(0.0001)))
#drout層降低過擬合
network.add(layers.Dropout(0.01))
network.add(layers.Dense(units=32, activation='relu', kernel_regularizer=regularizers.l1(0.0001)))
network.add(layers.Dropout(0.01))
network.add(layers.Dense(units=10, activation='softmax'))

#編譯
network.compile(optimizer=RMSprop(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])
#訓練
network.fit(train_images, train_labels, epochs=20, batch_size=128, verbose=2)

#在測試集上測試模型效能
# y_pre = network.predict(test_images[:5])
# print(y_pre, test_labels[:5])
test_loss, test_accuracy = network.evaluate(test_images, test_labels)
print("test_loss:", test_loss, "    test_accuracy:", test_accuracy)

本次實戰是參照b站大佬敲出來的,大佬講的很詳細,需要的小夥伴可以來看一下,地址我貼在在這裡了 傳送門
因為搭建的網路較為簡單,所以準確率沒有那麼高。