MINST手寫數字識別(二)—— 卷積神經網絡(CNN)


      今天我們的主角是keras,其簡潔性和易用性簡直出乎David 9我的預期。大家都知道keras是在TensorFlow上又包裝了一層,向簡潔易用的深度學習又邁出了堅實的一步。

      所以,今天就來帶大家寫keras中的Hello World , 做一個手寫數字識別的cnn。回顧cnn架構:

我們要處理的是這樣的灰度像素圖:

 

我們先來看跑完的結果(在Google Colab上運行

x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/12
60000/60000 [==============================] - 12s 193us/step - loss: 0.2672 - acc: 0.9166 - val_loss: 0.0648 - val_acc: 0.9792
Epoch 2/12
60000/60000 [==============================] - 9s 146us/step - loss: 0.0892 - acc: 0.9731 - val_loss: 0.0433 - val_acc: 0.9866
Epoch 3/12
60000/60000 [==============================] - 9s 146us/step - loss: 0.0666 - acc: 0.9796 - val_loss: 0.0353 - val_acc: 0.9874
Epoch 4/12
60000/60000 [==============================] - 9s 146us/step - loss: 0.0578 - acc: 0.9829 - val_loss: 0.0327 - val_acc: 0.9887
Epoch 5/12
60000/60000 [==============================] - 9s 146us/step - loss: 0.0483 - acc: 0.9856 - val_loss: 0.0295 - val_acc: 0.9901
Epoch 6/12
60000/60000 [==============================] - 9s 146us/step - loss: 0.0433 - acc: 0.9869 - val_loss: 0.0313 - val_acc: 0.9895
Epoch 7/12
60000/60000 [==============================] - 9s 146us/step - loss: 0.0379 - acc: 0.9879 - val_loss: 0.0267 - val_acc: 0.9913
Epoch 8/12
60000/60000 [==============================] - 9s 147us/step - loss: 0.0353 - acc: 0.9891 - val_loss: 0.0263 - val_acc: 0.9913
Epoch 9/12
60000/60000 [==============================] - 9s 146us/step - loss: 0.0327 - acc: 0.9904 - val_loss: 0.0275 - val_acc: 0.9905
Epoch 10/12
60000/60000 [==============================] - 9s 146us/step - loss: 0.0323 - acc: 0.9898 - val_loss: 0.0260 - val_acc: 0.9914
Epoch 11/12
60000/60000 [==============================] - 9s 147us/step - loss: 0.0286 - acc: 0.9913 - val_loss: 0.0283 - val_acc: 0.9909
Epoch 12/12
60000/60000 [==============================] - 9s 147us/step - loss: 0.0267 - acc: 0.9922 - val_loss: 0.0268 - val_acc: 0.9906
Test loss: 0.026836299882206368
Test accuracy: 0.9906

所以我們跑的是keras_mnist_cnn.py最后達到99%的預測准確率。首先來解釋一下輸出:

測試樣本格式是28*28像素的1通道,灰度圖,數量為60000個樣本。

測試集是10000個樣本。

一次epoch是一次完整迭代(所有樣本都訓練過),這里我們用了12次迭代,最后一次迭代就可以收斂到99.06%預測准確率了。

 

接下來我們看代碼:

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

一開始我們導入一些基本庫,包括:

  • minst數據集
  • Sequential類,可以封裝各種神經網絡層,包括Dense全連接層,Dropout層,Cov2D卷積層,等等
  • 我們都直到Keras支持兩個后端TensorFlow和Theano,可以在$HOME/.keras/keras.json中配置

接下來,我們准備訓練集和測試集,以及一些重要參數:

 

# batch_size 太小會導致訓練慢,過擬合等問題,太大會導致欠擬合。所以要適當選擇
batch_size = 128
# 0-9手寫數字一個有10個類別
num_classes = 10
# 12次完整迭代,差不多夠了
epochs = 12
# 輸入的圖片是28*28像素的灰度圖
img_rows, img_cols = 28, 28
# 訓練集,測試集收集非常方便
(x_train, y_train), (x_test, y_test) = mnist.load_data()
 
# keras輸入數據有兩種格式,一種是通道數放在前面,一種是通道數放在后面,
# 其實就是格式差別而已
if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)
# 把數據變成float32更精確
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
# 把類別0-9變成獨熱碼
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes)
y_test = keras.utils.np_utils.to_categorical(y_test, num_classes)

 

然后,是令人興奮而且簡潔得令人吃鯨的訓練構造cnn和訓練過程:

# 牛逼的Sequential類可以讓我們靈活地插入不同的神經網絡層
model = Sequential()
# 加上一個2D卷積層, 32個輸出(也就是卷積通道),激活函數選用relu,
# 卷積核的窗口選用3*3像素窗口
model.add(Conv2D(32,
                 activation='relu',
                 input_shape=input_shape,
                 nb_row=3,
                 nb_col=3))
# 64個通道的卷積層
model.add(Conv2D(64, activation='relu',
                 nb_row=3,
                 nb_col=3))
# 池化層是2*2像素的
model.add(MaxPooling2D(pool_size=(2, 2)))
# 對於池化層的輸出,采用0.35概率的Dropout
model.add(Dropout(0.35))
# 展平所有像素,比如[28*28] -> [784]
model.add(Flatten())
# 對所有像素使用全連接層,輸出為128,激活函數選用relu
model.add(Dense(128, activation='relu'))
# 對輸入采用0.5概率的Dropout
model.add(Dropout(0.5))
# 對剛才Dropout的輸出采用softmax激活函數,得到最后結果0-9
model.add(Dense(num_classes, activation='softmax'))
# 模型我們使用交叉熵損失函數,最優化方法選用Adadelta
model.compile(loss=keras.metrics.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
# 令人興奮的訓練過程
model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs,
          verbose=1, validation_data=(x_test, y_test))

完整地訓練完畢之后,可以計算一下預測准確率:

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

 

 

參考鏈接:
1、nooverfit.com/wp/keras-手把手入門1-手寫數字識別-深度學習實戰/

2、https://blog.csdn.net/yzh201612/article/details/69400002


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM