基於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 | 可以用字串rmsprop 或adagrad 等,或者使用建立的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)