運作環境
- 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。
将如圖所示的load()改為本地mnist資料集所在的路徑,根據自己的情況作修改,我是将mnist資料集放在Anaconda目錄下的。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
- 轉換圖檔資料類型并限制資料範圍
黑白圖檔每個像素點都代表了0–255之間的一個數字,此時圖檔在計算機裡是一個二維矩陣,将矩陣中的每個元素轉換為浮點型,為了便于分析計算,将矩陣中每個元素限制到0–1之間X_train=X_train.astype('float32') X_test=X_test.astype('float32') X_train /=255 X_test /=255
- 轉換标簽的資料形态
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())
- 添加全連接配接層
128代表神經元的個數,此處可以随意設定model.add(Dense(128,activation='relu'))
- 添加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')
運作截圖
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)