深度學習-Tensorflow2.2-預訓練網路{7}-遷移學習基礎針對小資料集-19
使用預訓練網路(遷移學習)
預訓練網路是一個儲存好的之前已在大型資料集(大規模影像分類任務)上訓練好的卷積神經網路
如果這個原始資料集足夠大且足夠通用,那麼預訓練網路學到的特徵的空間層次結構可以作為有效的提取視覺世界特徵的模型。
即使新問題和新任務與原始任務完全不同學習到的特徵在不同問題之間是可移植的,這也是深度學習與淺層學習方法的一個重要優勢。它使得深度學習對於小資料問題非常的有效。
Keras內建預訓練網路Keras庫中包含VGG16、VGG19\ResNet50、Inception v3、Xception等經典的模型架構。
-
ImageNet
-
ImageNet是一個手動標註好類別的圖片資料庫(為了機器視
覺研究),目前已有22,000個類別。 -
當我們在深度學習和卷積神經網路的背景下聽到“ImageNet”一詞時,我們可能會提到ImageNet視覺識別比賽,稱為ILSVRC。
-
這個圖片分類比賽是訓練一個模型,能夠將輸入圖片正確分
類到1000個類別中的某個類別。訓練集120萬,驗證集5萬,測試集10萬。 -
這1,000個圖片類別是我們在日常生活中遇到的,例如狗,貓,各種家居物品,車輛型別等等。
-
在影像分類方面,ImageNet比賽準確率已經作為計算機視覺分類演算法的基準。自2012年以來,卷積神經網路和深度學習技術主導了這一比賽的排行榜。
-
-
VGG16與VGG19
-
在2014年,VGG模型架構由Simonyan和Zisserman提出,在“極深的大規模影像識別卷積網路”(Very Deep Convolutional Networks for Large Scale Image Recognition)這篇論文中有介紹
-
VGG模型結構簡單有效,前幾層僅使用3×3卷積核來增加網路深度,通過max pooling(最大池化)依次減少每層的神經元數量,最後三層分別是2個有4096個神經元的全連線層和一個輸出softmax層。
-
-
VGG有兩個很大的缺點
-
- 網路架構weight數量相當大,很消耗磁碟空間。
-
- 訓練非常慢
由於其全連線節點的數量較多,再加上網路比較深,VGG16有533MB+,VGG19有574MB。這使得部署VGG比較耗時。
- 訓練非常慢
-
-
微調
-
所謂微調:凍結模型庫的底部的卷積層,共同訓練新新增的分類器層和頂部部分卷積層。這允許我們“微調”基礎模型中的高階特徵表示,以使它們與特定任務更相關。。
-
只有分類器已經訓練好了,才能微調卷積基的頂部卷積層。如果有沒有這樣的話,剛開始的訓練誤差很大,微調之前這些卷積層學到的表示會被破壞掉
-
-
微調步驟
- 一、在預訓練卷積基上新增自定義層
- 二、凍結卷積基所有層
- 三、訓練新增的分類層
- 四、解凍卷積基的一部分層
- 五、聯合訓練解凍的卷積層和新增的自定義層
案例
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import glob
import os
gpu_ok = tf.test.is_gpu_available()
print("tf version:", tf.__version__)
print("use GPU", gpu_ok) # 判斷是否使用gpu進行訓練
# 定義好keras,layers方便後面呼叫
keras = tf.keras
layers = tf.keras.layers
train_image_path = glob.glob("./dc/maogou/*.jpg")
test_image_path = glob.glob("./dc/maogou_test/*.jpg") # 獲取圖片資料集
len(train_image_path),len(test_image_path)
train_image_path[995:1005],test_image_path[593:600]
# 定義目標值 如果是貓 = 1 是狗 = 0
train_image_label = [int(p.split("\\")[1].split(".")[0]=="cat") for p in train_image_path]
test_image_label = [int(p.split("\\")[1].split(".")[0]=="cat") for p in test_image_path]
train_image_label[995:1005],test_image_label[593:600]
# 圖片載入與預處理
def load_preprosess_image(path,lable):
image = tf.io.read_file(path) # 讀取圖片路徑
image = tf.image.decode_jpeg(image,channels=3) # 對圖片進行解碼(jpeg格式圖片,channels=3 將讀入圖片統一為三通道)
image = tf.image.resize(image,[256,256])# 對圖片進行變形360*360畫素(非裁剪)
image = tf.cast(image,tf.float32) # 改變圖片格式
image = image/255 # 對圖片進行歸一化
#lable = tf.reshape(lable,[1]) # 把目標值轉換成2維形狀 如:[1,2,3] =>[[1],[2],[3]]
return image,lable
# 建立資料集 (包含了 路徑 以及目標值)
train_image_ds = tf.data.Dataset.from_tensor_slices((train_image_path,train_image_label))
test_image_ds = tf.data.Dataset.from_tensor_slices((test_image_path,test_image_label))
AUTOTUNE = tf.data.experimental.AUTOTUNE # AUTOTUNE 根據計算機cpu個數自動進行計算
train_image_ds = train_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE) # 對所有圖片以及目標值進行計算 使用AUTOTUNE 根據計算機cpu個數自動進行計算
test_image_ds = test_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE)
train_image_ds ,test_image_ds# 檢視處理後圖片的格式
for img,label in train_image_ds.take(2):
plt.imshow(img)
for img,label in test_image_ds.take(600):
plt.imshow(img)
BATCH_SIZE = 64 # 中文為批,一個batch由若干條資料構成。batch是進行網路優化的基本單位,網路引數的每一輪優化需要使用一個batch。
# batch中的樣本是被並行處理的。與單個樣本相比,一個batch的資料能更好的模擬資料集的分佈,
#batch越大則對輸入資料分佈模擬的越好,反應在網路訓練上,則體現為能讓網路訓練的方向“更加正確”。
#但另一方面,一個batch也只能讓網路的引數更新一次,因此網路引數的迭代會較慢。
#在測試網路的時候,應該在條件的允許的範圍內儘量使用更大的batch,這樣計算效率會更高。
train_count = len(train_image_path) # 檢視資料的個數
test_count = len(test_image_path)
train_count,test_count
train_image_ds = train_image_ds.shuffle(train_count).repeat().batch(BATCH_SIZE) # 亂序
#train_image_ds = train_image_ds.prefetch(AUTOTUNE) # prefetch 該函式有一個後臺執行緒和一個內部快取區,在資料被請求前,
# 就從 dataset 中預載入一些資料(進一步提高效能) prefetch(AUTOTUNE) 根據計算機效能自動分配資料條數
test_image_ds = test_image_ds.repeat().batch(BATCH_SIZE)
#test_image_ds = test_image_ds.prefetch(AUTOTUNE)
使用keras內建經典網路實現
# weights="imagenet"使用預訓練權重,include_top= False不包含全連結層
covn_base = keras.applications.VGG16(weights="imagenet",include_top= False)
covn_base.summary()
# 新增全連線層
model = keras.Sequential() # 建立一個順序模型
model.add(covn_base) # 新增vgg16卷積機
model.add(layers.GlobalAveragePooling2D()) # 全域性平均池化,深度神經網路中經常使用的一個層,使用前後的
#尺寸分別為[B,H,W,C]->[B,C].特別要注意,這個層使用之後特徵圖尺寸的維度變成了2維而非4維。
model.add(layers.Dense(512,activation="relu")) # 輸出512個單元
model.add(layers.Dense(1,activation="sigmoid")) # 輸出1個單元,sigmoid概率值
model.summary() # Trainable params: 14,977,857
covn_base.trainable = False # 因covn_base已經訓練好了所以我們設定false不可訓練(凍結)
model.summary() # 設定了covn_base.trainable = False後再次檢視模型建構Trainable params: 263,169
# 編譯模型
model.compile(optimizer=keras.optimizers.Adam(lr=0.001),
loss="binary_crossentropy",
metrics=["acc"])
# 訓練模型
history = model.fit(
train_image_ds,
steps_per_epoch=train_count//BATCH_SIZE,
epochs=12,
validation_data=test_image_ds,
validation_steps=test_count//BATCH_SIZE)
微調
covn_base.trainable = True # 解凍所有卷積層
len(covn_base.layers) # 一共19個層
fine_tune_at = -3 # 定義倒數3層
for layers in covn_base.layers[:fine_tune_at]:
layers.trainable = False # 除了倒數3層其他層全部凍結
# 編譯模型
model.compile(optimizer=keras.optimizers.Adam(lr=0.0005/10), # 使用更低學習速率
loss="binary_crossentropy",
metrics=["acc"])
# 訓練模型
initial_epochs = 12 # 前面訓練了12次
fine_tune_epochs = 10 # 對新的資料訓練10次
total_epochs = initial_epochs+fine_tune_epochs # 總共次數
history = model.fit(
train_image_ds,
steps_per_epoch=train_count//BATCH_SIZE,
epochs=total_epochs, # 總共需要訓練的次數
initial_epoch=initial_epochs, # 初始化時已經訓練過多少次
validation_data=test_image_ds,
validation_steps=test_count//BATCH_SIZE)
常見預訓練網路
-
可用的模型
在 ImageNet 上預訓練過的用於影像分類的模型:
VGG16 VGG19 ResNet50
InceptionV3 InceptionResNetV2 Xception
MobileNet MobileNetV2
DenseNet NASNet -
模型概覽
-
Xception
使用例項:
tf.keras.applications.xception.Xception(
include_top=True, weights='imagenet', input_tensor=None,
input_shape=None, pooling=None, classes=1000
)
在 ImageNet 上預訓練的 Xception V1 模型,在 ImageNet 上,該模型取得了驗證集 top1 0.790 和 top5 0.945 的準確率。
注意該模型只支援 channels_last 的維度順序(高度、寬度、通道)。
模型預設輸入尺寸是 299x299。
- Xception重要引數
pooling: 可選,
當 include_top 為 False 時,該引數指定了特徵提取時的池化方式。
None 代表不池化,直接輸出最後一層卷積層的輸出,該輸出是一個 4D 張量。
‘avg’ 代表全域性平均池化(GlobalAveragePooling2D),相當於在最後一層卷積層後面再加一層全域性平均池化層,輸出是一個 2D 張量。
‘max’ 代表全域性最大池化。
其他訓練網路引數引數新增連結描述
案例
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import glob
import os
os.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true'
gpu_ok = tf.test.is_gpu_available()
print("tf version:", tf.__version__)
print("use GPU", gpu_ok) # 判斷是否使用gpu進行訓練
keras = tf.keras
layers = tf.keras.layers
train_image_path = glob.glob("./dc/maogou/*.jpg")
test_image_path = glob.glob("./dc/maogou_test/*.jpg") # 獲取圖片資料集
len(train_image_path),len(test_image_path)
train_image_path[995:1005],test_image_path[593:600]
# 定義目標值 如果是貓 = 1 是狗 = 0
train_image_label = [int(p.split("\\")[1].split(".")[0]=="cat") for p in train_image_path]
test_image_label = [int(p.split("\\")[1].split(".")[0]=="cat") for p in test_image_path]
train_image_label[995:1005],test_image_label[593:600]
# 圖片載入與預處理
def load_preprosess_image(path,lable):
image = tf.io.read_file(path) # 讀取圖片路徑
image = tf.image.decode_jpeg(image,channels=3) # 對圖片進行解碼(jpeg格式圖片,channels=3 將讀入圖片統一為三通道)
image = tf.image.resize(image,[256,256])# 對圖片進行變形360*360畫素(非裁剪)
image = tf.cast(image,tf.float32) # 改變圖片格式
image = image/255 # 對圖片進行歸一化
#lable = tf.reshape(lable,[1]) # 把目標值轉換成2維形狀 如:[1,2,3] =>[[1],[2],[3]]
return image,lable
# 建立資料集 (包含了 路徑 以及目標值)
train_image_ds = tf.data.Dataset.from_tensor_slices((train_image_path,train_image_label))
test_image_ds = tf.data.Dataset.from_tensor_slices((test_image_path,test_image_label))
AUTOTUNE = tf.data.experimental.AUTOTUNE # AUTOTUNE 根據計算機cpu個數自動進行計算
train_image_ds = train_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE) # 對所有圖片以及目標值進行計算 使用AUTOTUNE 根據計算機cpu個數自動進行計算
test_image_ds = test_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE)
train_image_ds ,test_image_ds# 檢視處理後圖片的格式
BATCH_SIZE = 64 # 中文為批,一個batch由若干條資料構成。batch是進行網路優化的基本單位,網路引數的每一輪優化需要使用一個batch。
# batch中的樣本是被並行處理的。與單個樣本相比,一個batch的資料能更好的模擬資料集的分佈,
#batch越大則對輸入資料分佈模擬的越好,反應在網路訓練上,則體現為能讓網路訓練的方向“更加正確”。
#但另一方面,一個batch也只能讓網路的引數更新一次,因此網路引數的迭代會較慢。
#在測試網路的時候,應該在條件的允許的範圍內儘量使用更大的batch,這樣計算效率會更高。
train_count = len(train_image_path) # 檢視資料的個數
test_count = len(test_image_path)
train_image_ds = train_image_ds.shuffle(train_count).repeat().batch(BATCH_SIZE) # 亂序
#train_image_ds = train_image_ds.prefetch(AUTOTUNE) # prefetch 該函式有一個後臺執行緒和一個內部快取區,在資料被請求前,
# 就從 dataset 中預載入一些資料(進一步提高效能) prefetch(AUTOTUNE) 根據計算機效能自動分配資料條數
test_image_ds = test_image_ds.repeat().batch(BATCH_SIZE)
#test_image_ds = test_image_ds.prefetch(AUTOTUNE)
# 建立卷積機 weights="imagenet"使用預訓練權重,include_top= False不包含全連結層
covn_base = keras.applications.xception.Xception(weights="imagenet",
include_top= False,
input_shape=(256,256,3),
pooling="avg")
covn_base.trainable = False # 因covn_base已經訓練好了所以我們設定false不可訓練(凍結)
covn_base.summary()
# 新增全連線層
model = keras.Sequential() # 建立一個順序模型
model.add(covn_base) # 新增vgg16卷積機
model.add(layers.Dense(512,activation="relu")) # 輸出512個單元
model.add(layers.Dense(1,activation="sigmoid")) # 輸出1個單元,sigmoid概率值
model.summary() #
# 編譯模型
model.compile(optimizer=keras.optimizers.Adam(lr=0.001),
loss="binary_crossentropy",
metrics=["acc"])
initial_epochs = 5
# 訓練模型
history = model.fit(
train_image_ds,
steps_per_epoch=train_count//BATCH_SIZE,
epochs=initial_epochs,
validation_data=test_image_ds,
validation_steps=test_count//BATCH_SIZE)
微調
covn_base.trainable = True # 解凍所有卷積層
len(covn_base.layers) # 總層數
fine_tune_at = -33 # 定義倒數33層
for layers in covn_base.layers[:fine_tune_at]:
layers.trainable = False # 除了倒數33層其他層全部凍結
# 編譯模型
model.compile(optimizer=keras.optimizers.Adam(lr=0.0005/10), # 使用更低學習速率
loss="binary_crossentropy",
metrics=["acc"])
# 訓練模型
fine_tune_epochs = 5 # 微調後再次訓練5次
total_epochs = initial_epochs+fine_tune_epochs # 總共次數
history = model.fit(
train_image_ds,
steps_per_epoch=train_count//BATCH_SIZE,
epochs=total_epochs, # 總共需要訓練的次數
initial_epoch=initial_epochs, # 初始化時已經訓練過多少次
validation_data=test_image_ds,
validation_steps=test_count//BATCH_SIZE)
相關文章
- 一文看懂遷移學習:怎樣用預訓練模型搞定深度學習?遷移學習模型深度學習
- 深度學習 | 訓練網路trick——mixup深度學習
- 再無需從頭訓練遷移學習模型!亞馬遜開源遷移學習資料庫 Xfer遷移學習模型亞馬遜資料庫
- 深度學習+深度強化學習+遷移學習【研修】深度學習強化學習遷移學習
- 《深度學習案例精粹:基於TensorFlow與Keras》案例集用於深度學習訓練深度學習Keras
- 如何讓訓練神經網路不無聊?試試遷移學習和多工學習神經網路遷移學習
- 【機器學習基礎】神經網路/深度學習基礎機器學習神經網路深度學習
- NLP與深度學習(五)BERT預訓練模型深度學習模型
- ICLR 2019 | 用淺度學習訓練深度網路:避開端到端深度學習難題ICLR深度學習
- 深度學習資料集深度學習
- 零基礎入門深度學習(一):用numpy實現神經網路訓練深度學習神經網路
- 【深度學習系列】遷移學習Transfer Learning深度學習遷移學習
- 深度學習煉丹-超引數設定和網路訓練深度學習
- 深度學習基礎深度學習
- Python深度學習(在小型資料集上從頭開始訓練一個卷積神經網路)--學習筆記(十)Python深度學習卷積神經網路筆記
- 深度學習之遷移學習介紹與使用深度學習遷移學習
- 遷移學習系列---基於例項方法的遷移學習遷移學習
- 深度學習(一)深度學習學習資料深度學習
- 深度學習訓練時網路不收斂的原因分析總結深度學習
- 深度學習與CV教程(6) | 神經網路訓練技巧 (上)深度學習神經網路
- Python 基礎學習 網路小爬蟲Python爬蟲
- 深度學習之PyTorch實戰(4)——遷移學習深度學習PyTorch遷移學習
- 深度學習--RNN基礎深度學習RNN
- 再談遷移學習:微調網路遷移學習
- 深度學習--資料預處理深度學習
- 簡述遷移學習在深度學習中的應用遷移學習深度學習
- Laravel 學習之資料庫遷移Laravel資料庫
- 基於深度學習的網路表示深度學習
- [原始碼解析] 深度學習分散式訓練框架 horovod (4) --- 網路基礎 & Driver原始碼深度學習分散式框架
- 雲端計算時代的深度學習訓練深度學習
- 零基礎如何學習網路安全?網路安全學習方法
- 學習網路安全需要基礎嗎?網路安全內容學習
- 深度學習實驗資料集網站推薦深度學習網站
- 【遷移學習】大資料時代下的遷移學習--- 機器學習的下一個前沿遷移學習大資料機器學習
- 大資料基礎學習-7.Hive-1.1.0大資料Hive
- 機器學習,深度學習必備資料集機器學習深度學習
- 零基礎學習Python的學習路線及教程!附19最新python學習資料分享Python
- 原始碼分析——遷移學習Inception V3網路重訓練實現圖片分類原始碼遷移學習