機器學習-用keras做cnn手寫數字識別
- 2019 年 10 月 8 日
- 筆記
在用全連接做手寫數字識別的時候,準確率有97%了,但是還是會出現一些測試圖片沒有預測對,出來更好的去優化參數,現在就直接改進神經網路的模型,用cnn去訓練數據。
cnn–Convolutional neural network,簡稱cnn,中文翻譯過來是,卷積神經網路
卷積神經網路(Convolutional Neural Networks, CNN)是一類包含卷積計算且具有深度結構的前饋神經網路(Feedforward Neural Networks),是深度學習(deep learning)的代表演算法之一。卷積神經網路具有表徵學習(representation learning)能力,能夠按其階層結構對輸入資訊進行平移不變分類(shift-invariant classification),因此也被稱為「平移不變人工神經網路(Shift-Invariant Artificial Neural Networks, SIANN)
——-摘自百度百科
cnn的結構有:卷積層,池化層,全連接層
卷積層(Convolution Layer):
卷積層主要進行卷積操作,這裡會有一個叫卷積核的東西匹配數據的矩陣
池化層(Pooling Layer):
這裡就是把卷積層完成卷積操作後得到的特徵圖(feature Map)進行分區域,池化,然後把每個區域取出最大值或者均值或者最小值來表示
數據處理:
from keras.datasets import mnist import numpy as np from keras.utils import to_categorical import matplotlib.pyplot as plt (x_train,y_train),(x_test, y_test) = mnist.load_data() x_train = x_train.reshape(x_train.shape[0],28,28,1) x_test = x_test.reshape(x_test.shape[0],28,28,1) print(x_train.shape) print(x_train[0].shape) input_shape = (28,28,1) x_train = x_train.astype('float32')/255 x_test = x_test.astype('float32')/255 y_train = to_categorical(y_train,10) y_test = to_categorical(y_test, 10)
跟全連接的手寫識別大部分一樣,
有一點不一樣的就是數據是(數據量,圖片尺寸,圖片尺寸,顏色)顏色的意思是黑白的就是1,彩色的就是3
接著就是卷積層跟池化層:
import keras from keras.models import Sequential from keras.layers import Dense,Dropout,Flatten,Conv2D,MaxPooling2D model = Sequential() model.add(Conv2D(32, kernel_size=(3,3),activation='relu', input_shape=input_shape)) model.add(Conv2D(64,(3,3),activation='relu')) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.25)) model.add(Flatten())
首先就是導入相應的模組和庫,然後就是定義一個Sequential模型,接著添加卷積層,這裡用Conv2D,其中第一個參數是訓練這個圖要檢測的過濾器的數量(32,64),第二個參數是卷積核的大小,第三個是激活函數。一般用relu,第四個就是輸入的形狀的資訊。是幾維的,一般在第一層設置好就可以了。接著再添加一層卷積層,接著就是池化層,用來減少卷積層的結果的參數,有助於過度擬合,再接著就是Dropout(抓爆),有助於減低過擬合的現象,一般設置0.5,這裡設置為0.25,
最後就是Flatten,將池化後的數據轉成一列n行的數據。例如池化後的數據是(2,2,128),經過flatten後就是2*2*128 = 512
最後就是全連接層:
model.add(Dense(128,activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10,activation='softmax')) model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy']) model_log = model.fit(x_train,y_train, batch_size=128, epochs= 8, verbose=1, validation_data=(x_test,y_test)) score = model.evaluate(x_test,y_test,verbose=0) print('test accuracy:', score[1]) model.save('cnnshouxie.h5')
這裡跟去全連接的時候一樣,不同就是加了一個抓爆。
就這樣一個簡單的cnn手寫數字識別就做好了,不過手寫數字識別相比於全連接的手寫數字識別,cnn的訓練比較慢,訓練時間長,但是準確性好,我在全連接的圖片沒有測出來,在cnn中就可以測出來。最後在測試中去預測一下圖片的結果。
from keras.models import load_model import cv2 def prepare(path): img = cv2.imread(path,0) img = img.reshape(1,28,28,1) img = img.astype('float32')/255 return img model = load_model('cnnshouxie.h5') model.summary() img = prepare('3.jpg') precetion = model.predict_classes(img) print(precetion)
這裡的預測程式碼跟全連接也是一樣的,不同就是要修改圖片的reshape的參數數目,要與模型的匹配的上

