從Keras開始掌握深度學(xué)習(xí)-5 優(yōu)化你的模型

前言

在第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è)全連接層是最佳的選擇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容