1. 程式人生 > >基於Keras搭建用於MNIST手寫數字識別的CNN

基於Keras搭建用於MNIST手寫數字識別的CNN

說明
以下程式碼引自Keras的Github網站:

為了學習Keras 平臺進行深度學習建模的過程,我加入了一些備註和說明。
程式碼

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from
keras import backend as K batch_size = 128 num_classes = 10 epochs = 12 # input image dimensions img_rows, img_cols = 28, 28 # the data, shuffled and split between train and test sets (x_train, y_train), (x_test, y_test) = mnist.load_data() if K.image_data_format() == 'channels_first': x_train = x_train.reshape(x_train.shape[0
], 1, img_rows, img_cols) x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols) input_shape = (1, img_rows, img_cols) else: x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1) x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) input_shape = (img_rows, img_cols, 1
) x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 x_test /= 255 print('x_train shape:', x_train.shape) print(x_train.shape[0], 'train samples') print(x_test.shape[0], 'test samples') # convert class vectors to binary class matrices y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) 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()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(num_classes, activation='softmax')) model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy']) model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test)) score = model.evaluate(x_test, y_test, verbose=0) print('Test loss:', score[0]) print('Test accuracy:', score[1])

一些說明:

1.Sequential

Sequential是Keras中的序貫模型,可用於構建出多個網路層的線性堆疊。
可以通過向Sequential模型傳遞一個layer的list來構造該模型,

from keras.models import Sequential
from keras.layers import Dense, Activation

model = Sequential([Dense(32, units=784),Activation('relu'),Dense(10),Activation('softmax'),])

或使用.add()方法一個個的將layer加入模型中。

model = Sequential()
model.add(Dense(32, input_shape=(784,)))
model.add(Activation('relu'))

2. backend
在Keras的中文文件中,有以下說明:

Keras是一個模型級的庫,提供了快速構建深度學習網路的模組。Keras並不處理如張量乘法、卷積等底層操作。這些操作依賴於某種特定的、優化良好的張量操作庫。Keras依賴於處理張量的庫就稱為“後端引擎”。Keras提供了三種後端引擎Theano/Tensorflow/CNTK,並將其函式統一封裝,使得使用者可以以同一個介面呼叫不同後端引擎的函式

也就是說Keras對於張量等的操作依賴於backend的不同,當代碼中涉及到相關的操作時,可能需要有針對性的調整。如上面程式碼中 K.image_data_format() 就對backend的圖片資料格式進行了判斷處理。

3.keras.utils.to_categorical

該函式用於將單個數值變為類別形式。
例如,原資料集的y_train前五組資料為:

[5 0 4 1 9]

經過
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes)
變換後,成為

[[ 0.  0.  0.  0.  0.  1.  0.  0.  0.  0.]
 [ 1.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  0.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  1.]]

4.Dense層
Dense就是常用的全連線層,所實現的運算是output = activation(dot(input, kernel)+bias)。其中activation是逐元素計算的啟用函式,kernel是本層的權值矩陣,bias為偏置向量,只有當use_bias=True才會新增。
程式碼:

keras.layers.core.Dense(units, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)

示例:

# as first layer in a sequential model:
model = Sequential()
model.add(Dense(32, input_shape=(16,)))
# now the model will take as input arrays of shape (*, 16),and output arrays of shape (*, 32)

# after the first layer, you don't need to specify
# the size of the input anymore:
model.add(Dense(32))

5.Activation層
Activation層為啟用層,對一個層的輸出施加啟用函式,程式碼:

keras.layers.core.Activation(activation)

其中activation為預定義啟用函式,可選引數如下:
softmax,elu,selu,softplus,softsign,relu,tanh,sigmoid,hard_sigmoid,linear

6.Dropout層
為輸入資料施加Dropout。Dropout將在訓練過程中每次更新引數時按一定概率(rate)隨機斷開輸入神經元,Dropout層用於防止過擬合。

keras.layers.core.Dropout(rate, noise_shape=None, seed=None)

具體原理可參考:

7.Flatten層
Flatten層用來將輸入“壓平”,即把多維的輸入一維化,常用在從卷積層到全連線層的過渡。Flatten不影響batch的大小。

keras.layers.core.Flatten()

8.Conv2D層
二維卷積層,該層對二維輸入進行滑動窗卷積,當使用該層作為第一層時,應提供input_shape引數。例如input_shape = (128,128,3)代表128*128的彩色RGB影象(data_format=’channels_last’)

keras.layers.convolutional.Conv2D(filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
引數 說明
filters 卷積核的數目(即輸出的維度)
kernel_size 單個整數或由兩個整數構成的list/tuple,卷積核的寬度和長度。如為單個整數,則表示在各個空間維度的相同長度。
stride 單個整數或由兩個整數構成的list/tuple,為卷積的步長。如為單個整數,則表示在各個空間維度的相同步長。
padding 補0策略,為“valid”, “same” 。“valid”代表只進行有效的卷積,即對邊界資料不處理。“same”代表保留邊界處的卷積結果,通常會導致輸出shape與輸入shape相同
activation 啟用函式,為預定義的啟用函式名(參考啟用函式),或逐元素(element-wise)的Theano函式。如果不指定該引數,將不會使用任何啟用函式(即使用線性啟用函式:a(x)=x)
dilation_rate 單個整數或由兩個整數構成的list/tuple,指定dilated convolution中的膨脹比例。任何不為1的dilation_rate均與任何不為1的strides均不相容
data_format 字串,“channels_first”或“channels_last”之一,代表影象的通道維的位置。該引數是Keras 1.x中的image_dim_ordering,“channels_last”對應原本的“tf”,“channels_first”對應原本的“th”。以128x128的RGB影象為例,“channels_first”應將資料組織為(3,128,128),而“channels_last”應將資料組織為(128,128,3)。該引數的預設值是~/.keras/keras.json中設定的值,若從未設定過,則為“channels_last”
use_bias 布林值,是否使用偏置項

9.MaxPooling2D層
為空域訊號施加最大值池化

keras.layers.pooling.MaxPooling2D(pool_size=(2, 2), strides=None, padding='valid', data_format=None)
引數 說明
pool_size 整數或長為2的整數tuple,代表在兩個方向(豎直,水平)上的下采樣因子,如取(2,2)將使圖片在兩個維度上均變為原長的一半。為整數意為各個維度值相同且為該數字
strides 整數或長為2的整數tuple,或者None,步長值
border_mode ‘valid’或者‘same’
data_format 與Conv2D層中的引數相同

10. compile
在訓練模型前,需要設定學習流程,主要設定3個變數:optimizer, losses,metrics
程式碼示例:

model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])
引數 說明
optimizer 可以用字串rmspropadagrad等,或者使用建立的Optimizer 例項
loss loss函式,可以採用已經存在字串如categorical_crossentropy表示,也可以是一個目標函式
metrics 度量的標準,對於分類問題可以設定為['accuracy'],或者使用者自己定製

11. fit
按照設定的batch,epoch進行訓練,

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test)

其中verbose引數為0時不更新計算資訊,為1則更新計算資訊。
12.evaluate
對訓練出的模型進行評估,並返回結果。

model.evaluate(x_test, y_test, verbose=0)