iPAS 備考專區 登入

iPAS AI 應用規劃師 中級 科目三 機器學習技術與應用・114 年第二次・L23・第 45 題

VGG16 遷移學習怎麼凍結卷積層只訓練全連接層?

原題

VGG16 連題組第四題:在實務應用中,我們常使用遷移學習(transfer learning)技巧,即載入預訓練模型(如 VGG16),凍結部分層的參數,只針對特定任務重新訓練最後幾層,這種做法可節省訓練時間並提升模型效能。假設你要對 VGG16 進行遷移學習(transfer learning),希望凍結卷積層的參數,只訓練最後全連接層(classifier)。下列哪段程式碼寫法正確?

白話

動物園影像辨識專案的工程師想用 VGG16 預訓練模型做遷移學習,計畫凍結卷積層(model.features)讓它不更新,只重新訓練後面的全連接層(model.classifier)來適應動物分類任務。題目給了四段程式碼,每段都用不同方式嘗試實現「凍結 features,只訓練 classifier」,但只有一段是正確的。

問你:哪一段程式碼正確地「凍結卷積層、只讓全連接層更新」?

一句話總結

遷移學習凍結卷積層的正確方法是選項 B:對 model.features.parameters() 設定 requires_grad = False,只凍結 features 部分,然後換掉 classifier[6],這樣 features 不更新,新的 classifier[6] 預設 requires_grad = True,會正常訓練。

情境

先感受問題:只讓「特定員工」去上新課

動物園工程師有一個 VGG16 預訓練模型,已經在 ImageNet 上學過 1,000 種物件的特徵。現在他只需要分類 10 種動物,不需要從頭訓練 1.38 億個參數。

策略:把卷積層(features)的「學習模式」關掉,它已經學得很好了,凍結保留;換掉最後一個全連接層,改成輸出 10 類;然後只訓練全連接層(classifier)。

在 PyTorch 裡,「學習模式」的開關是 requires_grad:True 表示要更新這個參數,False 表示凍結不動。關鍵是要精準地「只把 features 的 requires_grad 設為 False」,而不是整個模型、也不是 classifier。

舊方法

凍結錯對象,遷移學習會有什麼後果?

  1. 凍結全部(選項 A 的問題):把所有參數都設為 requires_grad = False,然後換掉 classifier[6]。換後的新層預設 requires_grad = True,但原本的 classifier[0-5] 已被凍結。這樣只有新換的最後一層在訓練,其他全連接層的權重都不更新,效果比選項 B 差。
  2. 凍結 classifier(選項 C):把正確應該訓練的那些層(classifier)全部凍結,反而讓 features 繼續更新,這完全相反:破壞了預訓練的特徵提取器,新任務也沒學到。
  3. 對 model 設屬性(選項 D):model.requires_grad = False 設的是 Python 物件屬性,不是 PyTorch 的 requires_grad 機制。PyTorch 的梯度控制是針對各個 Parameter 的,這行程式碼實際上不會凍結任何參數,是無效操作。
  4. requires_grad 是參數層級的設定:凍結必須針對每個 nn.Parameter,要用 .parameters() 迭代每個參數,不能直接對模型物件設定。
  5. 新換的層預設 requires_grad = True:`model.classifier[6] = nn.Linear(4096, 10)` 建立的新層,其參數預設是可訓練的,只要不對它設 False 就會自動更新。

新方法

精準凍結 features,讓 classifier 繼續學習

動物園工程師的正確做法(選項 B):

import torch
import torchvision.models as models

model = models.vgg16(pretrained=True)

# Step 1:只凍結 features(卷積部分)
for param in model.features.parameters():
    param.requires_grad = False

# Step 2:換掉最後一層,輸出改為 10 類(動物)
model.classifier[6] = torch.nn.Linear(4096, 10)
# 新建的 Linear 層預設 requires_grad = True,會自動訓練

執行後的結果:features 裡的 13 層 Conv2d 全部凍結(約 14.7M 參數不更新);classifier 裡的 Linear-33、Linear-36 以及新的 classifier[6] 都是可訓練的(約 123.6M 參數會更新,其中主要是前兩個全連接層)。

這就是選項 B 講的:for param in model.features.parameters(): param.requires_grad = False。

錯選項

為什麼其他選項是錯的

Afor param in model.parameters(): param.requires_grad = False

字面在說什麼

凍結模型全部參數,再換最後一層。

為什麼不對

model.parameters() 包含 features 和 classifier 的所有參數。全部凍結後,只有新換的 classifier[6](建立時預設 requires_grad=True)是可訓練的,classifier[0] 到 classifier[5](前兩個全連接層)都被凍結了。題目要求「只訓練 classifier」,但 A 選項實際上只訓練了最後一層,效果遠不如同時訓練整個 classifier 的選項 B。

誰會選錯

認為「凍結全部再換最後一層」等同於「只訓練最後一層」,沒注意到「只訓練全連接層」應該是指整個 classifier 模組,不只是最後一層。

Cfor param in model.classifier.parameters(): param.requires_grad = False

字面在說什麼

凍結全連接層(classifier)的參數,再換最後一層。

為什麼不對

這完全把需求搞反了。凍結 classifier 讓全連接層無法更新,反而讓 features(卷積層)繼續接受梯度更新。題目說「凍結卷積層」,結果凍結的是全連接層。訓練出來的模型會破壞預訓練的特徵提取能力,分類效果很差。

誰會選錯

讀題時漏掉「凍結卷積層」這個關鍵,看到 classifier 就覺得「最後幾層才需要訓練」,倒過來操作了。

Dmodel.requires_grad = False

字面在說什麼

直接對 model 物件設定 requires_grad 屬性來凍結參數。

為什麼不對

model 是 nn.Module 的子類,model.requires_grad = False 只是在這個 Python 物件上新增一個名為 requires_grad 的屬性,對 PyTorch 的梯度計算完全沒有影響。PyTorch 的凍結機制必須針對每個 nn.Parameter 物件設定其 requires_grad 屬性,只有對 parameter.requires_grad = False 才有效。這是典型的「語法看起來合理但語意完全錯誤」。

誰會選錯

不熟悉 PyTorch 的 Parameter 機制,以為對 Module 物件設定 requires_grad 就能控制所有參數的梯度,混淆了 Module 和 Parameter 的區別。

變形題

同個考點下次怎麼變形

延伸

想再往下看,這 5 個

答案、題目或解析有問題?回報這題

出處:iPAS 經濟部產業人才能力鑑定 ・ 114 年第二梯次 iPAS AI 應用規劃師 中級 科目三 機器學習技術與應用 第 45 題

看官方原文 PDF

原題 © 經濟部產業發展署,AITerms.tw 僅作教學解析使用,本站解析以 CC BY-NC-SA 4.0 授權。