是的,直接修改 final_channels=512
會導致 net_D.pth
在 net.load_state_dict()
時發生錯誤,因為 Discriminator
的輸出層維度改變了,與原先儲存的模型權重 (net_D.pth
) 不匹配。
📌 為什麼會發生錯誤?
你的 net_D.pth
是 基於 final_channels=1
訓練的,它的最後一層是:
nn.Conv2d(ndf * nf_mult, 1, kernel_size=3, stride=1, padding=1, bias=False)
但是當你修改 final_channels=512
,變成:
nn.Conv2d(ndf * nf_mult, 512, kernel_size=3, stride=1, padding=1, bias=False)
這時候,state_dict
內的 final_conv
權重形狀與模型不匹配,導致 load_state_dict()
時出錯。
錯誤訊息類似:
RuntimeError: Error(s) in loading state_dict for Discriminator:
size mismatch for model.final_conv.weight:
copying a param with shape torch.Size([1, 512, 3, 3]) from checkpoint,
but model expects torch.Size([512, 512, 3, 3]).
📌 如何解決?
有兩種方式來解決這個問題:
✅ 方式 1: 手動移除 final_conv
權重,再載入
你可以在載入 state_dict
之前,手動刪除 final_conv
的權重,這樣 final_conv
會用隨機初始化的權重,而不會影響其他層:
import torch
# 載入原本的 state_dict
checkpoint = torch.load("net_D.pth", map_location="cpu")
# **刪除 `final_conv` 權重 (因為形狀不同)**
del checkpoint["model.final_conv.weight"]
# 重新載入模型
net_D = Discriminator(input_nc=3, ndf=64, n_layers=3, final_channels=512)
net_D.load_state_dict(checkpoint, strict=False) # `strict=False` 允許部分權重不匹配
print("✅ 模型載入成功 (final_conv 權重已隨機初始化)")
這樣就可以保留原本 D
的其他權重,只重新初始化 final_conv
,避免錯誤。
✅ 方式 2: 逐步擴展 final_channels
,讓 D
適應
如果你不想直接跳到 final_channels=512
,可以先擴展到 final_channels=8
、final_channels=64
,逐步訓練:
# 先載入舊的模型 (`final_channels=1`)
net_D = Discriminator(input_nc=3, ndf=64, n_layers=3, final_channels=1)
net_D.load_state_dict(torch.load("net_D.pth"))
# 轉換到 `final_channels=64` (只保留前面層的權重)
new_net_D = Discriminator(input_nc=3, ndf=64, n_layers=3, final_channels=64)
# 載入舊權重,但 `final_conv` 用新的隨機初始化
new_checkpoint = net_D.state_dict()
new_checkpoint.pop("model.final_conv.weight") # 刪除不匹配的層
new_net_D.load_state_dict(new_checkpoint, strict=False)
print("✅ 模型遷移到 final_channels=64,開始訓練")
然後訓練幾個 epochs,再增加到 final_channels=512
,讓 D
漸進適應。
📌 結論
- ❌ 直接修改
final_channels=512
會導致load_state_dict()
出錯,因為final_conv
權重形狀不匹配。 - ✅ 解決方法 1:在
load_state_dict()
之前手動刪除final_conv
權重 (strict=False
),讓它用隨機初始化。 - ✅ 解決方法 2:先增加到
final_channels=8
、64
,逐步擴展,讓D
更平穩地學習。
建議使用 方式 1 (刪除 final_conv
權重),這樣你可以 保留 D
主要的判別能力,只重新學習 final_conv
,而不影響之前的訓練成果! 🚀