1. 程式人生 > >【火爐煉AI】深度學習010-Keras微調提升效能(多分類問題)

【火爐煉AI】深度學習010-Keras微調提升效能(多分類問題)

【火爐煉AI】深度學習010-Keras微調提升效能(多分類問題)

(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2, Keras 2.1.6, Tensorflow 1.9.0)

前面的文章(【火爐煉AI】深度學習007-Keras微調進一步提升效能)我們對二分類問題用Keras進行了Fine-tune,使得模型的準確率進一步提升,此處我們看看對於多分類問題,怎麼使用Fine-tune來提升效能。


1. 準備資料集

和文章【火爐煉AI】深度學習008-Keras解決多分類問題一模一樣,在使用flow_from_directory時需要將class_mode修改為'categorical'。


2. 對VGG16的後半部分進行Fine-tune

此處我們建立的模型是使用VGG16的身子(inclue_top=False)作為特徵提取器,和我們自己定義的頭(前面文章【火爐煉AI】深度學習009-用Keras遷移學習提升效能(多分類問題)中訓練的模型和weights),這篇文章中已經達到了0.96的準確率。但是在前面這篇文章的遷移學習中,我們並沒有修改VGG16這個網路的weights引數,而是直接拿來提取特徵,此處的Fine-tune就是要調整VGG16網路的較高層的卷積層的weights,使其更加適用於我們自己的專案。

如下是模型構建的函式:

# 4,構建模型
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
from keras import applications
from keras import optimizers
from keras.models import Model
def build_model():
    base_model = applications.VGG16(weights='imagenet', include_top=False,input_shape=(IMG_W, IMG_H,IMG_CH))
    # 此處我們只需要卷積層不需要全連線層,故而inclue_top=False,一定要設定input_shape,否則後面會報錯
    # 這一步使用applications模組自帶的VGG16函式直接載入了模型和引數,作為我們自己模型的“身子”
    
    # 下面定義我們自己的分類器,作為我們自己模型的“頭”
    top_model = Sequential()
    top_model.add(Flatten(input_shape=base_model.output_shape[1:])) 
    top_model.add(Dense(256, activation='relu'))
    top_model.add(Dropout(0.5))
    top_model.add(Dense(class_num, activation='softmax')) # 多分類問題
    
    top_model.load_weights(os.path.join(save_folder,'top_FC_model')) 
    # 上面定義了模型結構,此處要把訓練好的引數載入進來,
    
    my_model = Model(inputs=base_model.input, outputs=top_model(base_model.output)) # 將“身子”和“頭”組裝到一起
    # my_model就是我們組裝好的完整的模型,也已經載入了各自的weights
    
    # 普通的模型需要對所有層的weights進行訓練調整,但是此處我們只調整VGG16的後面幾個卷積層,所以前面的卷積層要凍結起來
    for layer in my_model.layers[:15]: # 15層之前都是不需訓練的
        layer.trainable = False
        
    # 模型的配置
    my_model.compile(loss='categorical_crossentropy',
                  optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), # 使用一個非常小的lr來微調
                  metrics=['accuracy'])
    return my_model

-------------------------------------輸---------出--------------------------------

start to fine-tune my model
Epoch 1/50
8/8 [==============================] - 124s 16s/step - loss: 0.0170 - acc: 0.9950 - val_loss: 0.2767 - val_acc: 0.9700
Epoch 2/50
8/8 [==============================] - 131s 16s/step - loss: 3.2684e-04 - acc: 1.0000 - val_loss: 0.2694 - val_acc: 0.9700
Epoch 3/50
8/8 [==============================] - 131s 16s/step - loss: 0.0175 - acc: 0.9950 - val_loss: 0.2593 - val_acc: 0.9700

。。。

Epoch 48/50
8/8 [==============================] - 132s 16s/step - loss: 0.0025 - acc: 1.0000 - val_loss: 0.2758 - val_acc: 0.9700
Epoch 49/50
8/8 [==============================] - 130s 16s/step - loss: 0.0080 - acc: 0.9950 - val_loss: 0.2922 - val_acc: 0.9700
Epoch 50/50
8/8 [==============================] - 131s 16s/step - loss: 4.7076e-04 - acc: 1.0000 - val_loss: 0.2875 - val_acc: 0.9700

--------------------------------------------完-------------------------------------

acc 和loss圖為:

可以看出,test acc的準確率一直在0.97附近,在訓練開始和結束時的acc和loss變化不大,說明對於這個專案,微調的效能提升並不明顯,這是因為本專案所用的資料集太小,容易發生過擬合,通過增大資料集可以解決這些問題。

########################小**********結###############################

1,使用Fine-Tune來解決多分類問題時,需要將loss改成categorical_crossentropy,並且使用SGD優化器,使用非常小的learning rate,防止lr太大使得前面的卷積層網路結構發生較大改變。

#################################################################


注:本部分程式碼已經全部上傳到(我的github)上,歡迎下載。