根據 Keras 文件所敘述的神經層,我們使用卷積層、池化層、核心層這三種神經層建構神經網路。這些神經層分別有不同的意義,在此不多做解釋。

說明程式碼的意義, Sequential() 是用來配置訓練的模型,在後續接一系列的神經層。 Conv2D() 是卷積層,視窗的大小由 kernel_size 設定,activation 決定使用的活化函數。 MaxPooling2D() 是池化層,處理卷積層的訊息。 Dropout() 決定屏蔽的比例。 Dense() 是全連接層。 在神經層決定後,使用 compile() 配置學習過程,比如使用的優化器與損失函數等。

第一個模型是 Keras MNIST CNN 的範例,宣稱在測試上有 \(99.25\%\) 的準確度。

## 設定不同的隱藏層
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'))

## 訓練參數設定
batch_size = 128
epochs = 12

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))

## 儲存模型
model.save('cnn_model_example.h5')
## 載入模型
model = load_model('cnn_model_example.h5')

第二到第五個模型是自行設定的神經網路,是以不同想法所構建。 但是在訓練參數的設定上統一使用 batch_size = 128 以及 epochs = 12

第二個模型在卷積的視窗大小稍作改變,另外多加一層隱藏層。

## model_2
## 設定不同的隱藏層
model_2 = Sequential()
### 兩個卷積層
model_2.add(Conv2D(32, kernel_size=(5, 3),
                 activation='relu',
                 input_shape=input_shape))
model_2.add(Conv2D(64, (5, 3), activation='relu'))
model_2.add(MaxPooling2D(pool_size=(2, 2)))
model_2.add(Dropout(0.25))
### 隱藏層(核心層)
model_2.add(Flatten())
model_2.add(Dense(128, activation='relu'))
model_2.add(Dropout(0.5))
model_2.add(Dense(64, activation='relu'))
model_2.add(Dropout(0.3))
### 輸出層
model_2.add(Dense(num_classes, activation='softmax'))

## 訓練參數設定
batch_size = 128
epochs = 12

model_2.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

## 開始訓練
model_2.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))

## 儲存模型
model_2.save('cnn_model_2.h5')
## 載入模型
model_2 = load_model('cnn_model_2.h5')

第三個模型使用較大的卷積視窗,減少核心層的神經元個數。

## model_3
## 設定不同的隱藏層
model_3 = Sequential()
### 兩個卷積層
model_3.add(Conv2D(32, kernel_size=(8, 8),
                 activation='relu',
                 input_shape=input_shape))
model_3.add(Conv2D(64, (8, 8), activation='relu'))
model_3.add(MaxPooling2D(pool_size=(2, 2)))
model_3.add(Dropout(0.3))
### 隱藏層
model_3.add(Flatten())
model_3.add(Dense(32, activation='relu'))
model_3.add(Dropout(0.2))
### 輸出層
model_3.add(Dense(num_classes, activation='softmax'))

## 訓練參數設定
batch_size = 128
epochs = 12

model_3.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

## 開始訓練
model_3.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))

## 儲存模型
model_3.save('cnn_model_3.h5')
## 載入模型
model_3 = load_model('cnn_model_3.h5')

第四個模型利用三層的核心層,搭配不同屏蔽的比例。

## model_4
## 設定不同的隱藏層
model_4 = Sequential()
### 兩個卷積層
model_4.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model_4.add(Conv2D(64, (3, 3), activation='relu'))
model_4.add(MaxPooling2D(pool_size=(2, 2)))
model_4.add(Dropout(0.25))
### 隱藏層
model_4.add(Flatten())
model_4.add(Dense(128, activation='relu'))
model_4.add(Dropout(0.5))
model_4.add(Dense(128, activation='relu'))
model_4.add(Dropout(0.25))
model_4.add(Dense(128, activation='relu'))
model_4.add(Dropout(0.75))
### 輸出層
model_4.add(Dense(num_classes, activation='softmax'))

第五個模型使用四層的核心層,但是神經元的數量遞減,最後一層的神經元個數非常少,可以預期在判識上的準確度不高。

## model_5
## 設定不同的隱藏層
model_5 = Sequential()
### 兩個卷積層
model_5.add(Conv2D(16, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model_5.add(Conv2D(128, (3, 3), activation='relu'))
model_5.add(MaxPooling2D(pool_size=(2, 2)))
model_5.add(Dropout(0.25))
### 隱藏層
model_5.add(Flatten())
model_5.add(Dense(128, activation='relu'))
model_5.add(Dropout(0.8))
model_5.add(Dense(64, activation='relu'))
model_5.add(Dropout(0.7))
model_5.add(Dense(8, activation='relu'))
model_5.add(Dropout(0.6))
model_5.add(Dense(2, activation='relu'))
model_5.add(Dropout(0.5))
### 輸出層
model_5.add(Dense(num_classes, activation='softmax'))

## 訓練參數設定
batch_size = 128
epochs = 12

model_5.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
              
## 開始訓練
model_5.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))

## 儲存模型
model_5.save('cnn_model_5.h5')
## 載入模型
model_5 = load_model('cnn_model_5.h5')