天天看點

利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型

利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型

文章目錄

  • 利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型
    • 1.預訓練神經網絡是什麼
    • 2.資料集以及神經網絡的選擇
    • 3.VGG網絡架構
    • 4.确定我們訓練的步驟
    • 5.微調
    • 結語

1.預訓練神經網絡是什麼

​ 預訓練神經網絡是提前在大型資料庫上訓練過的網絡,他蘊含了在大型資料集上訓練過的權重,我們可以将他遷移到小型資料集上進而得到較高的準确率,舉個例子來說,原本的神經網絡是對幾百種分類的大型資料上進行學習的,我們得到的訓練模型含有獲得的權重,我們将他遷移到隻有幾種分類的小型資料上進而來完成分類識别任務,這種又稱遷移學習(**所謂遷移學習,**或者領域适應Domain Adaptation,一般就是要将從源領域(Source Domain)學習到的東西應用到目标領域(Target Domain)上去。源領域和目标領域之間往往有gap/domain discrepancy(源領域的資料和目标領域的資料遵循不同的分布)。

遷移學習能夠将适用于大資料的模型遷移到小資料上,實作個性化遷移。)。

​ 那麼,這裡我們有一個明顯的問題,熟悉神經網絡的同學肯定知道,我們訓練模型其實就是訓練神經網絡的各項參數,讓每個權重結合,最終能夠完成得到正确的輸出,那麼舉個例子,在識别椅子與桌子之上的資料集,上的網絡,得到的權重為什麼能夠應用到其他地方上呢。其實我們換個地方想想,在分類問題上,到底幾個分類是由我們最後的輸出層(全連接配接層,分類器)決定的,而底層的卷積層隻是負責提取特征,是以我們可以使用預訓練神經網絡的卷積來提取特征(這裡是出自網絡上搜尋,以及詢問他人得到的了解,有不對的可以評論區指正)。

2.資料集以及神經網絡的選擇

​ 遷移學習一般用于小型資料上的識别上,我們再把著名的貓狗大戰資料集拿出來,該資料集由一堆貓和狗的圖檔來識别

利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型

然後在預訓練神經網絡上的選擇,keras其中有提供一堆預訓練神經網絡,比如有VGG16,VGG19,ResNet,Xception等許多預訓練神經網絡,我們在這裡選擇VGG16(其實我也有拿Xception來測試,但可能由于代碼編寫問題,拿到的正确率并不高,是以我并沒有拿出來。。。)

3.VGG網絡架構

​ VGG是一個十分經典的神經網絡,網上資料很多,我找到了該網絡的各項模型的具體層結構:

利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型

我們其實可以自己來構造目前的層次,但是我們使用預訓練神經網絡主要是想拿他訓練過的權重,

4.确定我們訓練的步驟

​ 預訓練神經網絡步驟可以由下面這張圖來确定

利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型

我們獲得預訓練網絡的卷積基,抛棄直接連接配接輸出的分類器,當機卷積基(就是不讓卷積基礎的權重随着後面我們新加入的分類器傳播的權重來改變),然後根據具體的任務我們添加新的分類器進而來進行新的訓練

是以我們直接編寫代碼如下:

import tensorflow as tf
from tensorflow import keras
from keras import layers
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import glob
import os
#提取新的與訓練神經網絡我們不要輸出層,隻要中間提取特征的卷積層
conv_base=keras.applications.VGG16(weights='imagenet',include_top=False)#使用在imageNet上使用的權重
#include_top表示是否需要哪些全連接配接層
#檢視一下擷取的網絡結構
conv_base.summary()
           
利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型利用tensorflow使用預訓練神經網絡(VGG16)來訓練模型

然後我們根據具體的分類器來調整我們最後的輸出層,最後是二分類問題,是以我們構造後面的分類器如下:

model=keras.Sequential()
#因為我們使用了已經提前訓練好的參數,我們并不希望該權重改變,是以我們要将該權重設定為不可訓練
conv_base.trainable=False
model.add(conv_base)
model.add(layers.GlobalAveragePooling2D())
model.add(layers.Dense(512,activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))
model.summary()
           

之後我們開始訓練(一些其他資料讀取與訓練代碼與部落客上期部落格一樣),我們檢視每次訓練的結果:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->

Epoch 1: loss: 0.329, accuracy: 0.855

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->

Epoch 2: loss: 0.250, accuracy: 0.893

可以看到僅僅隻是,兩次訓練

準确率便能接近達到0.893,但是在接下來的訓練上準确率是在90左右,無法上升,達到過拟合了,我們為了進一步提高準确率,可以使用微調方法。

5.微調

剛才我們說過底層的卷積基是負責提取特征的部分,含有的權重是可以遷移過來直接使用的,那麼接近輸出層的卷積層的權重,是不是意味着可以調整。使得我們增加我們的準确率,但是有一個前提是我們的分類器必須提前訓練好的,不然随機初始化後的分類器可能會破壞我們調整的卷積基。是以我們接下來的微調都是在第一輪訓練過的分類器

#使得一些高層的卷積基可以訓練
conv_base.trainable=True
for layers in conv_base.layers[:-3]:
    layers.trainable=False
optimizer=keras.optimizers.Adam(0.00005)#同時需要調整更低的學習速率
           

然後我們開始我們第二波的訓練

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->

Epoch 1: loss: 0.196, accuracy: 0.915

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->

Epoch 2: loss: 0.136, accuracy: 0.944

可以看到,我們的正确率開始迅速上升達到95左右,說明我們的微調還是十分有用的。

結語

對于本次使用預訓練神經網絡中,我省略了一些代碼,重點介紹了如何使用預訓練神經網絡以及微調上,有什麼問題和獨到的見解可以評論區指正,謝謝。

繼續閱讀