前言
在第3篇教程里面,我們所編寫的CNN進(jìn)行分類的模型準(zhǔn)確度達(dá)到了80%。對(duì)于一個(gè)分類模型來(lái)說,80%的準(zhǔn)確率不算很低了。但是,在現(xiàn)有的情況下,我們應(yīng)該如何優(yōu)化這個(gè)模型呢?
在從零開始機(jī)器學(xué)習(xí)的系列里面,理論上的優(yōu)化模型可以修改超參數(shù)。同樣,在Keras的這個(gè)CNN程序中,我們可以指定其他的優(yōu)化器(這里用的是ADAM)。修改卷積核大小、步長(zhǎng)、修改激活函數(shù)的類型、加入/取消全連接層、修改每個(gè)層有多少神經(jīng)元也是可行的方法。
面對(duì)這么多可以修改的地方,修改現(xiàn)有的程序是必定需要做的。
修改現(xiàn)有的程序
首先確定要修改的內(nèi)容。全連接的層數(shù)、層的大小和卷積層的層數(shù)。
全連接層可以有0、1、2層;卷積層可以有1、2、3或更多層;然后就是每層的大小可以是32、64或128...
通過以下的代碼來(lái)確定這些排列組合可以得到多少模型:
dense_layers = [0, 1, 2]
layer_sizes = [32, 64, 128]
conv_layers = [1, 2, 3]
for dense_layer in dense_layers:
for layer_size in layer_sizes:
for conv_layer in conv_layers:
NAME = "{}-conv-{}-nodes-{}-dense-{}".format(conv_layer, layer_size, dense_layer, int(time.time()))
print(NAME)
運(yùn)行上述Python代碼,在控制臺(tái)的輸出如下:
1-conv-32-nodes-0-dense-1540975261
2-conv-32-nodes-0-dense-1540975261
3-conv-32-nodes-0-dense-1540975261
1-conv-64-nodes-0-dense-1540975261
2-conv-64-nodes-0-dense-1540975261
3-conv-64-nodes-0-dense-1540975261
1-conv-128-nodes-0-dense-1540975261
2-conv-128-nodes-0-dense-1540975261
3-conv-128-nodes-0-dense-1540975261
1-conv-32-nodes-1-dense-1540975261
2-conv-32-nodes-1-dense-1540975261
3-conv-32-nodes-1-dense-1540975261
1-conv-64-nodes-1-dense-1540975261
2-conv-64-nodes-1-dense-1540975261
3-conv-64-nodes-1-dense-1540975261
1-conv-128-nodes-1-dense-1540975261
2-conv-128-nodes-1-dense-1540975261
3-conv-128-nodes-1-dense-1540975261
1-conv-32-nodes-2-dense-1540975261
2-conv-32-nodes-2-dense-1540975261
3-conv-32-nodes-2-dense-1540975261
1-conv-64-nodes-2-dense-1540975261
2-conv-64-nodes-2-dense-1540975261
3-conv-64-nodes-2-dense-1540975261
1-conv-128-nodes-2-dense-1540975261
2-conv-128-nodes-2-dense-1540975261
3-conv-128-nodes-2-dense-1540975261
也就是說,通過排列組合可以得到27種模型。
修改第四講的代碼,將上述代碼加入程序,得到如下:
import time
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D
import pickle
from tensorflow.keras.callbacks import TensorBoard
import time
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.33)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
X = pickle.load(open("X.pickle","rb"))
y = pickle.load(open("y.pickle","rb"))
# normalize data image in grayscale is from 0-255
X = X/255.0
# train multiple models
dense_layers = [0, 1, 2]
layer_sizes = [32, 64, 128]
conv_layers = [1, 2, 3]
for dense_layer in dense_layers:
for layer_size in layer_sizes:
for conv_layer in conv_layers:
model_name = "{}-conv-{}-nodes-{}-dense-{}".format(conv_layer, layer_size, dense_layer, int(time.time()))
tensorboard = TensorBoard(log_dir='logs/{}'.format(model_name))
print(model_name)
model = Sequential()
model.add(Conv2D(layer_size, (3, 3), input_shape = X.shape[1:]))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
for l in range(conv_layer-1):
model.add(Conv2D(layer_size, (3, 3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten()) #Conv Layer是2D, DenseLayer是1D的 所以需要將ConvLayer壓平
for l in range(dense_layer):
model.add(Dense(layer_size))
model.add(Activation("relu"))
model.add(Dense(1))
model.add(Activation("sigmoid"))
model.compile(loss="binary_crossentropy",
optimizer="adam",
metrics=["accuracy"]) # 可以使用categorical_crossentropy作為損失函數(shù)
model.fit(X, y, batch_size =32, epochs=20, validation_split=0.1, callbacks=[tensorboard])
在控制臺(tái)運(yùn)行,一共需要訓(xùn)練27個(gè)模型,因此在訓(xùn)練之前,最好將logs的目錄下已經(jīng)存在的日志清空。這樣會(huì)方便我們觀察這一講中的不同參數(shù)對(duì)于模型的影響。
使用TensorBoard觀察模型
和上一講一樣,使用tensorboard --logdir=logs/打開TensorBoard。

TensorBoard觀察所有模型
同樣,我們的關(guān)注點(diǎn)應(yīng)該放在驗(yàn)證集的準(zhǔn)確率和損失上面。
在關(guān)注的區(qū)域拖動(dòng)鼠標(biāo),畫出一個(gè)矩形,則圖標(biāo)會(huì)放大到這個(gè)矩形關(guān)注的范圍內(nèi)。

放大折線圖
通過觀察,驗(yàn)證集損失表現(xiàn)最好的是3個(gè)卷積層-32個(gè)節(jié)點(diǎn)-0個(gè)全連接層的模型(3-32-0紅色);其次是2個(gè)卷積層-32個(gè)節(jié)點(diǎn)-0個(gè)卷積層的模型(2-32-0藍(lán)色);然后是2個(gè)卷積層-64個(gè)節(jié)點(diǎn)和-0個(gè)全連接層的模型(2-64-0粉色)。
同樣再來(lái)到驗(yàn)證集準(zhǔn)確率的折線圖,找到這幾個(gè)折線圖中最高的幾個(gè)模型。
通過分析,幾個(gè)模型中3個(gè)卷積層的準(zhǔn)確率最高,且沒有全連接層的準(zhǔn)確率最高且損失最低。
讓我們?cè)偌尤胍粋€(gè)3卷積-1個(gè)全連接層的模型,并且只將全連接層的大小設(shè)為512。
此處增加全連接層的大小是為了與現(xiàn)有的模型進(jìn)行對(duì)比。增加了全連接層之后,模型的大小會(huì)成倍增加,訓(xùn)練速度增加了一倍。
再次回到TensorBoard,取消選擇所有的除了3個(gè)卷積層和沒有全連接層以外的所有模型。通過對(duì)比,可以看到512大小的全連接層在訓(xùn)練集上面的準(zhǔn)確度比較高,但是到了驗(yàn)證集卻比較低。這也就說明了模型存在了過擬合。
綜上,對(duì)于目前的數(shù)據(jù)集和模型來(lái)說。3個(gè)卷積層、0個(gè)全連接層是最佳的選擇。