TensorFlow2.0 学习笔记(四):迁移学习(MobileNetV2)
歡迎關注WX公眾號:【程序員管小亮】
專欄——TensorFlow學習筆記
文章目錄
- 歡迎關注WX公眾號:【程序員管小亮】
- 專欄——TensorFlow學習筆記
- 一、數據處理
- 1.1_下載數據集
- 1.2_數據預處理
- 1.3_數據增強
- 1.4_數據可視化
- 二、構建模型
- 2.1_可視化模型
- 2.2_設置訓練參數
- 2.3_編譯和訓練模型
- 2.4_可視化訓練指標
- 三、使用預訓練的模型
- 3.1_下載預訓練模型
- 3.2_添加分類層
- 3.3_訓練Mobile模型
- 3.4_微調預訓練網絡
- 推薦閱讀
- 參考文章
下面我們準備使用 Keras 中預定義的經典卷積神經網絡結構進行遷移學習。
一、數據處理
1.1_下載數據集
import matplotlib.pyplot as plt import numpy as np import tensorflow as tf import tensorflow_datasets as tfds print(tf.__version__)
tensorflow_datasets 中包含了許多數據集,我們可以按照需求添加自己的數據集,下面列出所有可用的數據集:
這里即將使用的 tf_flowers 數據集,其大小為 218MB,返回值為 FeaturesDict 對象,尚未進行分割。
- 由于該數據集尚未定義標準分割形式,首先將利用 subsplit 函數將數據集分割為三部分,80% 用于訓練,10% 用于驗證,10% 用于測試;
- 其次如果想加載整個數據集到內存中,可以設置 batch_size=-1;
- 然后使用 tfds.load() 函數來下載數據,需要特別注意設置參數 as_supervised=True,這樣函數就會返回 tf.data.Dataset,一個二元組 (input, label) ,而不是返回 FeaturesDict ,因為二元組的形式更方便理解和使用;
- 最后再指定 with_info=True,這樣就可以得到函數處理的信息,以便加深對數據的理解。
代碼如下:
import tensorflow_datasets as tfdsSPLIT_WEIGHTS = (8, 1, 1) splits = tfds.Split.TRAIN.subsplit(weighted=SPLIT_WEIGHTS) (raw_train, raw_validation, raw_test), metadata = tfds.load(name="tf_flowers",with_info=True,split=list(splits),# batch_size=-1,as_supervised=True)print(raw_train) print(raw_validation) print(raw_test)1.2_數據預處理
從 tensorflow_datasets 中下載的數據集包含很多不同尺寸的圖片,因此需要將這些圖像的尺寸調整為固定的大小,并且將所有像素值都進行標準化,使得像素值的變化范圍都在 0~1 之間。盡管這些操作顯得繁瑣無用,但是必須進行這些預處理操作,因為在訓練一個卷積神經網絡之前,必須指定它的輸入維度。不僅如此,網絡中最后全連接層的 shape 取決于 CNN 的輸入維度,因此這些預處理的操作是很有必要的。最明顯的例子就是上面復現的 LeNet 的 flatten 層,如果你不知道確切的維度,那么就會各種報錯。。。
如下所示,構建一個函數 format_exmaple(),并將它傳遞給 raw_train, raw_validation 和 raw_test 的映射函數,從而完成對數據的預處理。需要指明的是,format_exmaple() 的參數和傳遞給 tfds.load() 的參數有關:
- 如果 as_supervised=True,那么 tfds.load() 將下載一個二元組 (image, labels) ,該二元組將作為參數傳遞給 format_exmaple();
- 如果 as_supervised=False,那么 tfds.load() 將下載一個字典 <image,lable> ,該字典將作為參數傳遞給 format_exmaple() 。
除此之外
-
還對 train 對象調用 .shuffle(BUFFER_SIZE) ,用于打亂訓練集的順序,該操作能夠消除樣本的 次序偏差。
-
再用 .batch(BATCH_SIZE) 來定義這三類數據集的 batch 大小,這里 batch 的大小設置為 32 。
-
最后用 .prefetch() 在后臺預加載數據,該操作能夠在模型訓練的時候進行,從而減少訓練時間。
下圖直觀地描述了 .prefetch() 的作用。
不采取 prefetch 操作,CPU 和 GPU/TPU 的大部分時間都處在空閑狀態。
采取 prefetch 操作后,CPU 和 GPU/TPU 的空閑時間顯著較少。
在該步驟中,有幾點值得注意:
- 操作順序很重要。
- 如果先執行 .shuffle() 操作,再執行 .repeat() 操作,那么將進行跨 batch 的數據打亂操作,每個 epoch 中的 batch 數據都是被提前打亂的,而不用每次加載一個 batch 就打亂依一次它的數據順序;
- 如果先執行 .repeat() 操作,再執行 .shuffle() 操作,那么每次只有單個 batch 內的數據次序被打亂,而不會進行跨 batch 的數據打亂操作。
- 將 buffer_size 設置為和數據集大小一樣,這樣數據能夠被充分的打亂,但是 buffer_size 過大會導致消耗更多的內存。
- 在開始進行打亂操作之前,系統會分配一個緩沖區,用于存放即將進行打亂的數據,因此在數據集開始工作之前,過大的 buffer_size 會導致一定的延時。
- 在緩沖區沒有完全釋放之前,正在執行打亂操作的數據集不會報告數據集的結尾,而數據集會被 .repeat() 重啟,這將會又一次導致延時。
其中 tf.data.experimental.AUTOTUNE 可以讓程序自動的選擇最優的線程并行個數。
1.3_數據增強
在訓練階段,對數據進行實時增廣操作,而不是手動的將這些增廣圖像添加到數據上。
代碼如下:
def augment_data(image, label):print("擴展數據調用!")# 將圖片隨機進行水平翻轉image = tf.image.random_flip_left_right(image)# 隨機設置圖片的對比度image = tf.image.random_contrast(image, lower=0.0, upper=1.0)# 將圖片隨機進行垂直翻轉# image = tf.image.random_flip_up_down(img)# 隨機設置圖片的亮度# image = tf.image.random_brightness(img, max_delta=0.5)# 隨機設置圖片的色度# image = tf.image.random_hue(img, max_delta=0.3)# 隨機設置圖片的飽和度# image = tf.image.random_saturation(img, lower=0.3, upper=0.5)# 增加更多選擇return image, labeltrain = train.map(augment_data) SHUFFLE_BUFFER_SIZE = 1024 BATCH_SIZE = 32train = train.shuffle(SHUFFLE_BUFFER_SIZE).batch(BATCH_SIZE) validation = validation.batch(BATCH_SIZE) test = test.batch(BATCH_SIZE)train = train.prefetch(tf.data.experimental.AUTOTUNE) print(train) print(validation) print(test)print(metadata)
其中 metadata 是 tfds.load 的返回值之一 ds_info : tfds.core.DatasetInfo。請注意 ds_info,無論 split 請求如何,對象都會記錄整個數據集。Split-specific 的信息可在 ds_info.splits 中找到。
1.4_數據可視化
通過可視化數據集中的一些隨機樣本,不僅可以發現其中存在的異?;蛘咂?#xff0c;還可以發現特定類別的圖像的變化或相似程度。使用 train.take() 可以批量獲取數據集,并將其轉化為 numpy 數組, tfds.as_numpy(train) 也具有相同的作用,如下代碼所示:
# 獲取將標簽索引轉換為字符串的函數 get_label_name = metadata.features['label'].int2str在這里,我們逐批獲取數據集,并在將其傳遞給 plotting 函數之前,將其轉換為 numpy 數組。
plt.figure(figsize=(12,12)) for batch in train.take(1):for i in range(9):image, label = batch[0][i], batch[1][i]plt.subplot(3,3,i+1)plt.imshow(image.numpy())plt.title(get_label_name(label.numpy()))plt.grid(False)plt.show()print(image.shape) print(np.min(image)) print(np.max(image))
我們還可以使用 tfds.as_numpy(train) 而不是 train.take() 直接獲取 numpy 數組。
二、構建模型
tf.keras 是一個符合 Keras API 標準的 TensorFlow 實現,它是一個用于構建和訓練模型的高級 API,而且對 TensorFlow 特定功能的支持相當好(例如 eager execution 和 tf.data 管道)。tf.keras 不僅讓 TensorFlow 變得更加易于使用,而且還保留了它的靈活和高效。
from tensorflow import keras print(keras.__version__)張量 (image_height, image_width, color_channels) 作為模型的輸入,在這里不用考慮 batch 的大小。黑白圖像只有一個顏色通道,而彩色圖像具有三個顏色通道 (R,G,B) 。
- 在這里,采用彩色圖像作為輸入,輸入圖像尺寸為 (128,128,3) ,將該參數傳遞給 shape,從而完成輸入層的構建。
- 接下來,將用一種很常見的模式構建 CNN 的卷積部分:一系列堆疊的 Conv2D 層和 MaxPooling2D 層。
- 最后,將卷積部分的輸出((28,28,64) 的張量)饋送到一個或多個全連接層中,從而實現分類。
注意,全連接層的輸入必須是一維的向量,而卷積部分的輸出卻是三維的張量。因此需要先將三維的張量展平成一維的向量,然后再將該向量輸入到全連接層中。數據集中有 5 個類別,這些信息可以從數據集的元數據中獲取。因此,模型最后一個全連接層的輸出是一個長度為 5 的向量,再用 softmax 函數對它進行激活,至此就構建好了 CNN 模型。
2.1_可視化模型
.summary() 為我們提供了完整的模型架構。
simple_model = create_model() simple_model.summary() keras.utils.plot_model(simple_model, 'flower_model_with_shape_info.png', show_shapes=True)2.2_設置訓練參數
我們指定了 tensorboard 保存日志的目錄。
import datetime, oslog_dir="logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") os.makedirs(log_dir)我們還得到了在訓練集、驗證集和測試集中的示例數的值。
- steps_per_epoch:在一個 epoch 中訓練模型的批數。其計算方法是將訓練實例的數量除以每批的大小。
- validation_steps:與 steps_per_epoch 相同,但適用于驗證數據集。
2.3_編譯和訓練模型
import osdef train_model(model):model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])# Creating Keras callbackstensorboard_callback = keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)model_checkpoint_callback = keras.callbacks.ModelCheckpoint('training_checkpoints/weights.{epoch:02d}-{val_loss:.2f}.hdf5', period=5)os.makedirs('training_checkpoints/', exist_ok=True)early_stopping_checkpoint = keras.callbacks.EarlyStopping(patience=5)history = model.fit(train.repeat(),epochs=5,steps_per_epoch=steps_per_epoch,validation_data=validation.repeat(),validation_steps=validation_steps,callbacks=[tensorboard_callback,model_checkpoint_callback,early_stopping_checkpoint])return history history = train_model(simple_model)2.4_可視化訓練指標
TF2.0 中的另一個新特性是能夠在 jupyter 筆記本內部使用成熟的 tensorboard。在開始模型訓練之前,先啟動tensorboard,這樣就可以在模型訓練時查看指標。
%load_ext tensorboard.notebook %tensorboard --logdir logs # 使用以下命令停止TensorBoard # 需要傳遞進程的ID !kill 100276我們將訓練集和驗證集上的評估指標進行了可視化,該指標為 train_model() 的返回值,使用 Matplotlib 繪制曲線圖:
acc = history.history['accuracy'] val_acc = history.history['val_accuracy']loss = history.history['loss'] val_loss = history.history['val_loss']plt.figure(figsize=(8, 8)) plt.subplot(2, 1, 1) plt.plot(acc, label='Training Accuracy') plt.plot(val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.ylabel('Accuracy') plt.title('Training and Validation Accuracy')plt.subplot(2, 1, 2) plt.plot(loss, label='Training Loss') plt.plot(val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.ylabel('Cross Entropy') plt.title('Training and Validation Loss') plt.xlabel('epoch') plt.show()
這些可視化圖能讓我們更加深入了解模型的訓練程度。在模型訓練過程中,確保訓練集和驗證集的精度在逐漸增加,而損失逐漸減少,這是非常重要的。
-
如果訓練精度高但驗證精度低,那么模型很可能出現了 過擬合。這時需要對進行 數據增廣,或者直接從網上下載更多的圖像,從而增加訓練集。此外,還可以采用一些防止過擬合的技術,例如 Dropout 或者 BatchNormalisation 等等,詳細的可以看這個博客——深度學習100問之神經網絡中解決過擬合的幾種方法。
-
如果訓練精度和驗證精度都較高,但是驗證精度比訓練精度略高,那么驗證集很可能包含較多易于分類的圖像。有時我們使用 Dropout 和 BatchNorm 等技術來防止過擬合,但是這些操作會為訓練過程添加一些 隨機性,使得訓練更加困難,因此模型在驗證集上表現會更好些。
稍微拓展一點講,由于訓練集的評估指標是對一個 epoch 的平均估計,而驗證集的評估指標卻是在這個 epoch 結束后,再對驗證集進行評估的,因此驗證集所用的模型可以說要比訓練集的模型訓練的更久一些。
Jupyer notebook 中的 TensorBoard 視圖:
三、使用預訓練的模型
在上面,我們訓練了一個簡單的 CNN 模型,它給出了大約 60% 的準確率。通過使用更大、更復雜的模型,獲得更高的準確率,預訓練模型 是一個很好的選擇,可以直接使用 預訓練模型 來完成分類任務,因為 預訓練模型 通常已經在大型的數據集上進行過訓練,通常用于完成大型的圖像分類任務。
當然也可以運用 遷移學習 的方法,只使用預訓練模型的一部分,重新構建屬于自己的模型。簡單來講,遷移學習 可以理解為:一個在足夠大的數據集上經過訓練的模型,能夠有效地作為視覺感知的通用模型,通過使用該模型的特征映射,我們就可以構建一個魯棒性很強的模型,而不需要很多的數據去訓練。
3.1_下載預訓練模型
tf.keras.applications 中有一些預定義好的經典卷積神經網絡結構(Application應用),如下:
可以直接調用這些經典的卷積神經網絡結構(甚至載入預訓練的參數),而無需手動定義網絡結構。
例如,本次將要用到的模型是由谷歌開發的 MobileNetV2 網絡結構,該模型已經在 ImageNet 數據集上進行過預訓練,共含有 1.4M 張圖像,而且學習了常見的 1000 種物體的基本特征,因此,該模型具有強大的特征提取能力。
model = tf.keras.applications.MobileNetV2()當執行以上代碼時,TensorFlow 會自動從網絡上下載 MobileNetV2 網絡結構,因此在第一次執行代碼時需要具備網絡連接。但是每個網絡結構具有自己特定的詳細參數設置,比如我們這里的 tf.keras.applications.MobileNetV2,詳細的可以看這個 Keras 文檔;一些共通的常用參數如下:
-
input_shape :輸入張量的形狀(不含第一維的 Batch),大多默認為 224 × 224 × 3 。一般而言,模型對輸入張量的大小有下限,長和寬至少為 32 × 32 或 75 × 75;
-
include_top :在網絡的最后是否包含全連接層,默認為 True;
-
weights :預訓練權值,默認為 imagenet,即為當前模型載入在 ImageNet 數據集上預訓練的權值。如需隨機初始化變量可設為 None;
-
classes :分類數,默認為 1000。修改該參數需要 include_top 參數為 True 且 weights 參數為 None。
模型下載時,需要指定參數 include_top=False,這樣網絡的最后就不包含全連接層了,因為我們只想使用該模型進行特征提取,而不是直接使用該模型進行分類。此外,它還將我們的輸入維度限制為該模型所訓練的維度,默認值:299x299。預訓練模型 的分類模塊通常受原始的分類任務限制,如果想將 預訓練模型 用在新的分類任務上,需要自己構建模型的分類模塊,而且需要將該模塊在新的數據集上進行訓練,這樣才能使模型適應新的分類任務。
現在使用 MobileNetV2 網絡在 tf_flowers 分類數據集上進行訓練(為了代碼簡短高效,直接使用了 TensorFlow Datasets 和 tf.data 載入和預處理數據)。通過將 weights 設置為 imagenet,隨機初始化變量且使用在 imagenet 上的預訓練權值,同時不設置 classes,默認對應于 1000 分類的數據集。
from tensorflow import keras # 從預先訓練的模型MobileNetV2導入為基礎模型 base_model = keras.applications.MobileNetV2(input_shape=IMG_SHAPE, include_top=False, weights='imagenet')
我們將 預訓練模型 當做一個特征提取器,輸入 (128,128,3) 的圖像,得到 (4,4,1280) 的輸出特征。特征提取器可以理解為一個特征映射過程,最終的輸出特征是輸入的多維表示,在新的特征空間中,更加利于圖像的分類。
注:在編譯和訓練模型之前,凍結卷積模塊是很重要的。通過凍結(或設置 layer.trainable=false),我們可以防止在訓練期間更新這些層中的權重。
3.2_添加分類層
由于指定了參數 include_top=False,下載的 MobileNetV2 模型不包含最頂層的分類層,因此我們需要添加一個新的分類層,而且它是為 tf_flowers 所專門定制的。
要從特征塊生成預測,請使用 keras.layers.GlobalAveragePooling2D() 層在 2x2 空間位置上平均,以將特征轉換為每個圖像的單個 1280 元素向量。在頂部,應用 keras.layers.Dense 層將這些特征轉換為每個圖像的單個預測。然后使用 tf.keras.sequential api來堆疊特征提取程序和這兩個層,在訓練之前不要忘記編譯模型。
代碼如下:
def build_model():model = keras.Sequential([base_model,keras.layers.GlobalAveragePooling2D(),keras.layers.Dense(metadata.features['label'].num_classes, activation='softmax')])model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])return modelMobile_model = build_model() Mobile_model.summary()3.3_訓練Mobile模型
# 訓練前評估模型(可選) loss0, accuracy0 = Mobile_model.evaluate(validation.repeat(), steps = validation_steps) log_dir = os.path.join("logs","fit",datetime.datetime.now().strftime("%Y%m%d-%H%M%S"), ) os.makedirs(log_dir)# Creating Keras callbacks tensorboard_callback = keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1) model_checkpoint_callback = keras.callbacks.ModelCheckpoint('training_checkpoints/weights.{epoch:02d}-{val_loss:.2f}.hdf5', period=5) os.makedirs('training_checkpoints/', exist_ok=True) early_stopping_checkpoint = keras.callbacks.EarlyStopping(patience=5)history = Mobile_model.fit(train.repeat(),epochs=5,steps_per_epoch = steps_per_epoch,validation_data=validation.repeat(), validation_steps=validation_steps,callbacks=[tensorboard_callback,model_checkpoint_callback,early_stopping_checkpoint]) Train for 91 steps, validate for 11 stepsEpoch 1/5 91/91 [===========] - 134s 1s/step - loss: 1.0087 - accuracy: 0.6075 - val_loss: 1.2909 - val_accuracy: 0.5511 Epoch 2/5 91/91 [===========] - 139s 2s/step - loss: 0.6338 - accuracy: 0.7720 - val_loss: 0.7929 - val_accuracy: 0.7131 Epoch 3/5 91/91 [===========] - 130s 1s/step - loss: 0.5578 - accuracy: 0.7959 - val_loss: 0.8869 - val_accuracy: 0.7131 Epoch 4/5 91/91 [===========] - 140s 2s/step - loss: 0.5147 - accuracy: 0.8108 - val_loss: 0.8605 - val_accuracy: 0.7330 Epoch 5/5 91/91 [===========] - 137s 2s/step - loss: 0.4757 - accuracy: 0.8264 - val_loss: 0.9297 - val_accuracy: 0.6903經過5個階段的訓練,我們得到了約 70% 的準確率,繪制了訓練和驗證精度/損失的學習曲線。
acc = history.history['accuracy'] val_acc = history.history['val_accuracy']loss = history.history['loss'] val_loss = history.history['val_loss']plt.figure(figsize=(8, 8)) plt.subplot(2, 1, 1) plt.plot(acc, label='Training Accuracy') plt.plot(val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.ylabel('Accuracy') plt.title('Training and Validation Accuracy')plt.subplot(2, 1, 2) plt.plot(loss, label='Training Loss') plt.plot(val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.ylabel('Cross Entropy') plt.title('Training and Validation Loss') plt.xlabel('epoch') plt.show()
開始訓練預訓練模型后,訓練集和驗證集的評估指標隨著訓練 epoch 的變化。
從圖中可以看到,驗證集的精度高略低于訓練集的精度。使用測試集來評估模型可以進一步驗證模型的泛化能力。如果想讓模型取得更好的效果,對模型進行微調。
# 保存Keras模型 Mobile_model.save('Mobile_v2_128_tf_flowes.h5') loaded_model = keras.models.load_model('Mobile_v2_128_tf_flowes.h5') loaded_model.evaluate(test)3.4_微調預訓練網絡
在特征提取實驗中,我們只在 Mobile_v2 的基礎模型上訓練了幾層。訓練過程中,訓練前網絡的權值不更新。進一步提高性能的一種方法是在訓練頂級分類器的同時 微調 預訓練模型 頂層的權重。訓練過程將強制將權重從通用特征映射調整到與我們的數據集特定關聯的特征。
注意:只有在預先訓練的模型設置為 non-trainable 的 top-level 分類器之后,才能嘗試此操作。如果在預先訓練的模型上添加一個隨機初始化的分類器并嘗試聯合訓練所有層,則梯度更新的幅度將過大(由于來自分類器的隨機權重),并且預先訓練的模型將忘記它所學到的一切。
此外,微調 預訓練模型 的頂層而不是 預訓練模型 的所有層背后的原因如下:在 convnet 中,一個層越高,它就越專業。convnet 的前幾層學習了非常簡單和通用的特性,這些特性幾乎可以推廣到所有類型的圖像,但是當你往上走的時候,這些特性對模型所訓練的數據集越來越具體。微調 的目標是使這些專門的特性適應新的數據集。
# 取消凍結模型的頂層 base_model.trainable = True # 讓我們看看基本模型中有多少層 print("Number of layers in the base model: ", len(base_model.layers)) # Fine tune from this layer onwards fine_tune_at = 129# Freeze all the layers before the `fine_tune_at` layer for layer in base_model.layers[:fine_tune_at]:layer.trainable = False# Compile the model using a much-lower training rate. Mobile_model_model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=0.0001),loss='sparse_categorical_crossentropy',metrics=['accuracy']) Mobile_model_model.summary() history_fine = Mobile_model.fit(train.repeat(), steps_per_epoch = steps_per_epoch,epochs=10, initial_epoch = 5,validation_data=validation.repeat(), validation_steps=validation_steps,callbacks=[tensorboard_callback,model_checkpoint_callback,early_stopping_checkpoint]) Train for 91 steps, validate for 11 steps Epoch 6/10 91/91 [=========] - 148s 2s/step - loss: 0.4520 - accuracy: 0.8359 - val_loss: 0.9207 - val_accuracy: 0.7273 Epoch 7/10 91/91 [=========] - 139s 2s/step - loss: 0.3368 - accuracy: 0.8773 - val_loss: 0.8071 - val_accuracy: 0.7614 Epoch 8/10 91/91 [=========] - 141s 2s/step - loss: 0.2874 - accuracy: 0.8954 - val_loss: 0.7512 - val_accuracy: 0.7784 Epoch 9/10 91/91 [=========] - 127s 1s/step - loss: 0.2340 - accuracy: 0.9175 - val_loss: 0.7784 - val_accuracy: 0.7812 Epoch 10/10 91/91 [=========] - 136s 1s/step - loss: 0.2130 - accuracy: 0.9200 - val_loss: 0.8010 - val_accuracy: 0.7812注意:如果訓練數據集相當小,并且與 MobileNet V2 所使用的原始數據集相似,那么微調可能會導致過度擬合。
acc += history_fine.history['accuracy'] val_acc += history_fine.history['val_accuracy']loss += history_fine.history['loss'] val_loss += history_fine.history['val_loss']initial_epochs=5plt.figure(figsize=(8, 8)) plt.subplot(2, 1, 1) plt.plot(acc, label='Training Accuracy') plt.plot(val_acc, label='Validation Accuracy') plt.plot([initial_epochs-1,initial_epochs-1], plt.ylim(), label='Start Fine Tuning') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy')plt.subplot(2, 1, 2) plt.plot(loss, label='Training Loss') plt.plot(val_loss, label='Validation Loss') plt.plot([initial_epochs-1,initial_epochs-1], plt.ylim(), label='Start Fine Tuning') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.xlabel('epoch') plt.show()
總之,我們介紹了如何使用預先訓練的模型進行轉移學習以提高準確性:
- 使用 預訓練模型 特征提取:在處理小數據集時,通常會利用在同一域中的較大數據集上訓練的模型所學習的特征,這是通過實例化 預訓練模型 并在上面添加一個全連接分類器來完成的。訓練前的模型被凍結,訓練過程中只更新分類器的權值,在這種情況下,卷積部分提取與每個圖像相關聯的所有特征,并且訓練一個在給定特征集上確定類別的分類器。
- 微調 預訓練模型:為了進一步提高性能,可能需要通過 微調 將 預訓練模型 的頂層重新利用到新的數據集。在這種情況下,調整權重以便學習特定于我們數據集的高度指定和高維特征。只有當訓練數據集很大并且非常類似于預先訓練模型所使用的原始數據集時,這才有意義。
推薦閱讀
- TensorFlow2.0 學習筆記(一):TensorFlow 2.0 的安裝和環境配置以及上手初體驗
- TensorFlow2.0 學習筆記(二):多層感知機(MLP)
- TensorFlow2.0 學習筆記(三):卷積神經網絡(CNN)
- TensorFlow2.0 學習筆記(四):遷移學習(MobileNetV2)
- TensorFlow2.0 學習筆記(五):循環神經網絡(RNN)
參考文章
- TensorFlow 官方文檔
- 簡單粗暴 TensorFlow 2.0
- tfds.load
- https://github.com/himanshurawlani/practical_intro_to_tf2
總結
以上是生活随笔為你收集整理的TensorFlow2.0 学习笔记(四):迁移学习(MobileNetV2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: docker启动nginx后挂了_Doc
- 下一篇: java c3p0获取主键_Tomcat