# MNIST手寫辨識(TensorFlow version)
此文章是介紹MNIST手寫辨識的作法及知識,分為兩個版本,,一個為Tensorflow版本,另一個為Pytorch版本,觀念的部分大致相同,比較不一樣的地會是在實作的部分,那廢話不多說,開始吧!
## Contents
我會一步一步的講解每一個步驟,有些步驟是幫助我們做理解的,但對最後實作結果沒有明顯幫助,在文章最後面會有完整程式碼,而某些步驟只是讓我們更了解實作過程的那些程式碼不會被包含在內。
## 1. 引用第三方套件
```python=
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from tensorflow.keras.utils import to_categorical # one-hot encoding
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.datasets import mnist
# from tensorflow.keras.datasets import fashion_mnist
# (x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
```
在Keras和TensorFlow合併之後,Keras就在TensorFlow底下,所以我們import tensorflow底下keras一些小套件,首先是to_categorical,to_categorical的功用是將資料變成one-hot encoding,接著是Sequential,幫助我們建立神經網路,再來是Dense,由於想要打造fully connected的神經網路,我們會用到keras寫好的神經層,然後我們的optimization是使用SGD(Stochastic Gradient Descent),最後我們要引入MNIST的資料集,然後可以看到我有加兩個註解,其實MNIST的資料集非常大,除了數字集外還有一種是fashion版本,裡面有衣服、褲子等圖片,撰寫程式的方法和數字集一致。
## 2. 資料處理
```python=
(x_train, y_train), (x_test, y_test) = mnist.load_data()
n = 9487
plt.imshow(x_train[n], cmap='Greys')
plt.show()
x_train = x_train.reshape(60000, 784)/255
x_test = x_test.reshape(10000, 784)/255
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
```
我們將MNIST的資料讀取,分別把training data和testing data取出並存取,這裡的imshow()只是單純想要觀看MNIST的圖片,再來將我們x data做處理,由於我們的training data有60000份,testing data有10000份,且每張圖片都是28\*28,所以這邊reshape,將資料變成784維的向量,然後我們784筆資料的值是0\~255,我們偏向將資料值能在0\~1之間,所以這邊我們除以255,再來是y data,我們將y data轉成one-hot encoding ,為10維的向量。
## 3. 建造神經網路
```python=
model = Sequential()
model.add(Dense(100, input_dim=784, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(10, activation='softmax')) # output
model.compile(loss='mse', optimizer=SGD(lr=0.09),
metrics=['accuracy'])
model.summary()
```
我們使用Sequential建造神經網路,使用add()函式增加神經層,其中我們使用Dense來代表我們要建造densely-connected神經層,第一個參數是神經層的神經元數,input_dim代表輸入的維度,activation代表激勵函數的類型,再來使用compile來配置訓練model,我們的model使用MSE來計算loss function,優化器使用SGD,learning rate調整為0.09,而metrics這個參數是判斷訓練和測試時的成效。而model.summary()只是單純看神經網路的架構。
## 4. 訓練
```python=
model.fit(x_train, y_train, batch_size=100, epochs=20)
```
此處的fit()函數是我們訓練的模型,第一和二個參數是我們的數據,第三個是我們每次做批量訓練的數量,因為我們不可能直接將所有training data一次全部訓練,這樣數據量太大,所以要做batch training,epochs是我們要訓練幾次。
## 5. 預測
```python=
predict = model.predict_classes(x_test)
n = 9999
score = model.evaluate(x_test, y_test)
print('test loss:', score[0])
print('test accuracy:', score[1])
print('神經網路預測是:', predict[n])
plt.imshow(x_test[n].reshape(28,28), cmap='Greys');
model.save("my_nn.h5")
plt.show()
```
用Keras做預測的時候有兩種方法,一種是使用predict(),這種回傳的是機率,另一種是predict_classes(),這種則會回傳向量中數值最大的index,如果使用predict()想要達到相同效果的話,需再加上argmax(),這邊就選擇使用predict_classes(),我們會這樣做是因為我們使用的是one-hot encoding ,所以得到index時即可找到預測的數值,再來使用model.evaluate()計算model的loss 和 accuracy,然後自訂一個數值來做預測,再將此位置的圖輸出,記得這邊要將784維的資料再轉成28\*28的矩陣,最後再將此訓練過model儲存,即完成此次的MNIST手寫版辨識。
## 總程式碼
```python=
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from tensorflow.keras.utils import to_categorical # one-hot encoding
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.datasets import mnist
# from tensorflow.keras.datasets import fashion_mnist
# (x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
(x_train, y_train), (x_test, y_test) = mnist.load_data()
n = 9487
plt.imshow(x_train[n], cmap='Greys')
plt.show()
x_train = x_train.reshape(60000, 784)/255
x_test = x_test.reshape(10000, 784)/255
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
model = Sequential()
model.add(Dense(100, input_dim=784, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(10, activation='softmax')) # output
model.compile(loss='mse', optimizer=SGD(lr=0.09), metrics=['accuracy'])
model.summary()
model.fit(x_train, y_train, batch_size=100, epochs=20)
predict = model.predict_classes(x_test)
n = 9999
score = model.evaluate(x_test, y_test)
print('test loss:', score[0])
print('test accuracy:', score[1])
print('神經網路預測是:', predict[n])
plt.imshow(x_test[n].reshape(28,28), cmap='Greys');
model.save("my_nn.h5")
plt.show()
```