機器學習-用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的參數數目,要與模型的匹配的上