在本篇博文當中,筆者采用了卷積神經網絡來對手寫數字進行識別,采用的神經網絡的結構是:輸入圖片——卷積層——池化層——卷積層——池化層——卷積層——池化層——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,接近百分之九十九的樣子,比筆者僅用全連接神經網絡訓練的結果高了零點幾的准確度,從中還是可以看出卷積神經網絡的有效性,在沒有進行調參的情況下准確度已經很高了!