天天看點

從零開始,搭建CNN(卷積)神經網絡識别Mnist手寫體

運作環境

  • Windows 10 專業版 x64
  • Python 3.7.2
  • tensorflow 1.9
  • keras 2.2.4

導入工具包

  • 神經網絡線性堆疊架構
    from keras.models import Sequential
               
    卷積神經網絡擁有卷積層,池化層,展開層,全連接配接層等,該架構則是容納各個網絡層的東西,可以看做一個容器。
  • 卷積層,池化層,激活層,展開層,全連接配接層,Dropout層
    from keras.layers import Convolution2D,MaxPooling2D
    from keras.layers import Activation,Flatten,Dense,Dropout
               
  • 資料形态轉換工具
    from keras.utils import np_utils
               

搭模組化型

  • 加載資料集
    #mnist資料集,含有60000個訓練資料以及10000個測試資料,樣本圖檔均為1~9的數字手寫體
    from keras.datasets import mnist
    (X_train,y_train),(X_test,y_test)=mnist.load_data()
               
    此處采用網絡加載的方法,如果網絡加載不可用或網絡環境不太好,則可采用本地加載的方法。
    • 本地加載

      如圖所示,按住Ctrl點選load_data。

      從零開始,搭建CNN(卷積)神經網絡識别Mnist手寫體
      将如圖所示的load()改為本地mnist資料集所在的路徑,根據自己的情況作修改,我是将mnist資料集放在Anaconda目錄下的。
      從零開始,搭建CNN(卷積)神經網絡識别Mnist手寫體

      mnist資料集下載下傳位址:https://s3.amazonaws.com/img-datasets/mnist.npz

      也可以采用其他方式下載下傳,不過注意的是下載下傳檔案的擴充名要為npz,已經解過壓的資料集的導入方式是不同的。

  • 轉換圖檔資料狀态
    X_train=X_train.reshape(X_train.shape[0],1,28,28)
    X_test=X_test.reshape(X_test.shape[0],1,28,28)
               

    原本的圖檔資料狀态為:圖檔數量,圖檔寬度,圖檔高度

    轉換後為:圖檔數量,圖檔深度,圖檔寬度,圖檔高度

    mnist資料集圖檔均為黑白圖檔,是以圖檔深度統一為1

  • 轉換圖檔資料類型并限制資料範圍
    X_train=X_train.astype('float32')
    X_test=X_test.astype('float32')
    X_train /=255
    X_test /=255
               
    黑白圖檔每個像素點都代表了0–255之間的一個數字,此時圖檔在計算機裡是一個二維矩陣,将矩陣中的每個元素轉換為浮點型,為了便于分析計算,将矩陣中每個元素限制到0–1之間
  • 轉換标簽的資料形态
    Y_train=np_utils.to_categorical(y_train,10)
    Y_test=np_utils.to_categorical(y_test,10)
               

    每個圖檔對應一個标簽,标簽即是圖檔識别的結果。

    一張标簽對應一張圖檔,那麼每個标簽不外乎是0–9之間的數字,但這不是我們想要的。

    我們要将标簽轉換為一個清單,比如:

    0就是[1,0,0,0,0,0,0,0,0,0]

    1就是[0,1,0,0,0,0,0,0,0,0]

    2就是[0,0,1,0,0,0,0,0,0,0]

    以此類推

  • 創造模型架構
    model=Sequential()
               
    相當于把容器放好,要往裡面添加神經網絡了。
  • 添加第一個卷積層和激活層
    model.add(Convolution2D(32,3,3,input_shape=(1,28,28)))
    model.add(Activation('relu'))
               

    32表示過濾器(卷積核)的個數,3 3 表示過濾器的寬和高

    input_shape表示輸入圖檔深度為1,寬為28,高為28

    經過一次卷積後圖檔大小為 26,26 (原始圖檔未經處理,卷積後圖檔縮小)

    激活層其實就是激活函數,最大的作用就是限制通過卷積核的結果(負數變為0,正數不變)

  • 添加第二個卷積層和激活層
    model.add(Convolution2D(32,3,3))
    model.add(Activation('relu'))
               

    經過兩次卷積後圖檔大小為 24,24

    input_shape可以省略,如果要寫,注意寬和高是26

  • 添加池化層,池化大小為2,2
    model.add(MaxPooling2D(pool_size=(2,2)))
               
    池化層的作用簡單了解就是将上面卷積得到的圖檔變小變模糊,但保留了主要特征,至少從肉眼觀看不影響識别。
  • 添加展開層
    model.add(Flatten())
               
    展開圖像像素點,即把圖像從二維變為一維
  • 添加全連接配接層
    model.add(Dense(128,activation='relu'))
               
    128代表神經元的個數,此處可以随意設定
  • 添加Dropout層,防止過拟合
    model.add(Dropout(0.5))
               
  • 再次添加全連接配接層
    model.add(Dense(10,activation='softmax'))
               

    此處神經元的個數隻能為10,因為該全連接配接層也是輸出層,對應10個标簽。

    softmax代表非線性函數,輸出的結果為“最初輸入的圖檔,屬于每個标簽的機率”

  • 編譯模型
    model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
               

    目标:categorical_crossentropy(誤差損失)盡可能小

    為了完成目标,使用方法:adam

    accuracy(準确率)來評估模型的預測效果

  • 訓練模型
    model.fit(X_train,Y_train,batch_size=32,nb_epoch=10,validation_split=0.3)
               

    batch_size=32 一批處理32個樣本

    nb_epoch=10 有10個周期(訓練時比較吃CPU,如果對電腦沒把握可以減小訓練周期)

    validation_split=0.3 從訓練樣本中拿出30%作為交叉驗證集,是以訓練樣本為42000個,在訓練時有18000個樣本參與測試

  • 評估模型(用測試資料集測試準确度)
    score=model.evaluate(X_test,Y_test)
    print(score)
               

到此,一個基本的CNN神經網絡搭建完成,可以運作了

運作

ValueError: Negative dimension size caused by subtracting 3 from 1 for 'conv2d_1/convolution' (op: 'Conv2D') with input shapes: [?,1,28,28], [3,3,28,32].
           

如果出現該錯誤,則在程式最前面加上:

from keras import backend as K
K.set_image_dim_ordering('th')
           

運作截圖

從零開始,搭建CNN(卷積)神經網絡識别Mnist手寫體

loss:誤差損失(盡可能小)

acc:準确率

整個運作時間大概需要10分鐘,即每個訓練周期差不多1分鐘,對電腦不自信的可以更改周期次數。

附:

from keras import backend as K
K.set_image_dim_ordering('th')

#導入網絡的線性堆疊架構
from keras.models import Sequential

#導入卷積層,池化層
from keras.layers import Convolution2D,MaxPooling2D

#導入激活層,展開層,全連接配接層,Dropout層
from keras.layers import Activation,Flatten,Dense,Dropout

#導入資料形态轉換工具
from keras.utils import np_utils

#加載資料集
#若網絡加載異常,可采用本地檔案加載,此處為網絡加載
#mnist資料集,含有60000個訓練資料以及10000個測試資料,樣本圖檔均 為1~9的數字手寫體
from keras.datasets import mnist
(X_train,y_train),(X_test,y_test)=mnist.load_data()

#轉換圖檔資料形态  轉換為 樣本數量,圖檔深度,圖檔寬度,圖檔高度
X_train=X_train.reshape(X_train.shape[0],1,28,28)
X_test=X_test.reshape(X_test.shape[0],1,28,28)

#轉換圖檔資料類型及限制資料範圍  将數值範圍從[0,255]标準化到[0,1]
X_train=X_train.astype('float32')
X_test=X_test.astype('float32')
X_train /=255
X_test /=255

#轉換标簽的資料形态
#0=[1,0,0,0,0,0,0,0,0,0]
#1=[0,1,0,0,0,0,0,0,0,0]
#...
Y_train=np_utils.to_categorical(y_train,10)
Y_test=np_utils.to_categorical(y_test,10)

#創造模型架構
model=Sequential()

#添加第一個卷積層和激活層
#32表示過濾器(卷積核)的個數,3 3 表示過濾器的寬和高
#input_shape表示輸入圖檔深度為1,寬為28,高為28
#經過一次卷積後圖檔大小為 26,26  (原始圖檔未經處理,卷積後圖檔縮小)
model.add(Convolution2D(32,3,3,input_shape=(1,28,28)))
model.add(Activation('relu'))

#添加第二個卷積層和激活層
#經過兩次卷積後圖檔大小為 24,24
model.add(Convolution2D(32,3,3))
model.add(Activation('relu'))

#添加池化層,池化大小為2,2
#經過池化處理後圖檔大小變為12,12
model.add(MaxPooling2D(pool_size=(2,2)))

#添加展開層,展開圖像像素點
model.add(Flatten())

#添加全連接配接層
#128表示神經元個數,可随意設定
model.add(Dense(128,activation='relu'))

#防止過拟合
model.add(Dropout(0.5))

#再次添加全連接配接層
#此處也是輸出層,神經元個數隻能為10,對應10個标簽
#softmax是非線性函數,輸出的結果為“最初輸入的圖檔,屬于每個标簽的機率”
model.add(Dense(10,activation='softmax'))

#編譯模型
#目标:categorical_crossentropy(誤差損失)盡可能小
#為了完成目标,使用方法:adam
#accuracy(準确率)來評估模型的預測效果
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])

#訓練模型  batch_size=32 一批處理32個樣本
#nb_epoch=10 有10個周期
#validation_split=0.3 從訓練樣本中拿出30%作為交叉驗證集
#是以訓練樣本為42000個,在訓練時有18000個樣本參與測試
model.fit(X_train,Y_train,batch_size=32,nb_epoch=10,validation_split=0.3)


#評估模型(用測試資料集測試準确度)
score=model.evaluate(X_test,Y_test)
print(score)

           

繼續閱讀