keras與卷積神經網路(CNN)實現識別minist手寫數字
在本篇博文當中,筆者採用了卷積神經網路來對手寫數字進行識別,採用的神經網路的結構是:輸入圖片——卷積層——池化層——卷積層——池化層——卷積層——池化層——Flatten層——全連線層(64個神經元)——全連線層(500個神經元)——softmax函式,最後得到分類的結果。Flatten層用於將池化之後的多個二維陣列展開成一維陣列,再灌入全連線層的神經元當中。
首先導包:
import keras from keras import layers from keras import models
建立神經網路的順序模型:
model = models.Sequential()
新增神經網路的結構(三組卷積層,池化層。一個flatten層,以及兩個全連線層),啟用函式我一般喜歡使用relu,當然你也可以使用sigmoid,tanh這兩個啟用函式,更改我的程式碼即可。由於是手寫數字,最後的softmax一共只能夠有十個數字,因此輸出寫10.啟用函式使用softmax。其他都是relu。
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Flatten()) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(500, activation='relu')) model.add(layers.Dense(10, activation='softmax'))
神經網路搭建完畢,開始導minist手寫數字,對數字進行分類,分為訓練集和驗證集,同時將數字進行reshape,程式碼如下:
from keras.datasets import mnist from keras.utils import to_categorical (train_images, train_labels), (test_images, test_labels) = mnist.load_data() train_images = train_images.reshape((60000, 28, 28, 1)) train_images = train_images.astype('float32') / 255 test_images = test_images.reshape((10000, 28, 28, 1)) test_images = test_images.astype('float32') / 255 train_labels = to_categorical(train_labels) test_labels = to_categorical(test_labels)
緊接著選擇需要進行梯度下降的優化器,常見的有adagrad,adam,rmsprop等等,這裡選擇了rmsprop。損失函式loss function這裡選擇了Cross Entropy,也就是交叉熵(因為最後是一個softmax函式進行分類,我們常常用交叉熵來衡量模型的準確度,這個計算起來比較方便,也比較有道理)。模型fit的過程當中我選擇了mini—batch小批量梯度下降法,用這個方法比較適合電腦,如果使用所有資料進行梯度下降,那麼電腦跑很久才能夠完成,如果使用小批量梯度下降,電腦則可以自動進行平行計算,時間減少。迭代次數我選擇了10次,每一個mini——batch的批量為128,這個無所謂,這個引數適中即可,不可太大也不能太小。程式碼如下:
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) model.fit(train_images, train_labels, epochs=10, batch_size=128)
輸出:
Epoch 1/10 60000/60000 [==============================] - 42s 703us/step - loss: 0.0192 - acc: 0.9940 Epoch 2/10 60000/60000 [==============================] - 42s 706us/step - loss: 0.0166 - acc: 0.9945 Epoch 3/10 60000/60000 [==============================] - 43s 724us/step - loss: 0.0146 - acc: 0.99580s - loss: 0.0145 - acc: 0.9 Epoch 4/10 60000/60000 [==============================] - 43s 720us/step - loss: 0.0129 - acc: 0.9960 Epoch 5/10 60000/60000 [==============================] - 43s 718us/step - loss: 0.0130 - acc: 0.9962 Epoch 6/10 60000/60000 [==============================] - 44s 728us/step - loss: 0.0105 - acc: 0.9966 Epoch 7/10 60000/60000 [==============================] - 44s 737us/step - loss: 0.0095 - acc: 0.9969 Epoch 8/10 60000/60000 [==============================] - 44s 728us/step - loss: 0.0101 - acc: 0.9972 Epoch 9/10 60000/60000 [==============================] - 44s 735us/step - loss: 0.0085 - acc: 0.9974 Epoch 10/10 60000/60000 [==============================] - 45s 743us/step - loss: 0.0081 - acc: 0.99750s - loss: 0.0081 - acc: 0.997
可以看到模型經過十次迭代,訓練集的準確度已經達到了%99.7以上,這樣會不會出現過擬合的情況呢?用不用減少一下模型的迭代次數呢?筆者的心裡怕怕的,於是用驗證集來驗證一下模型的準確度:
test_loss, test_acc = model.evaluate(test_images, test_labels) print(test_acc)
輸出:
0.9868
模型的準確度達到了%98.68,接近百分之九十九的樣子,比筆者僅用全連線神經網路訓練的結果高了零點幾的準確度,從中還是可以看出卷積神經網路的有效性,在沒有進行調參的情況下準確度已經很高