You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch迁移学习:仅训练第一层、冻结其余层的参数异常排查

问题分析与解决

核心错误点

  1. 逻辑完全颠倒:你要训练第一层、冻结其余层,但代码里是先冻结所有参数,再开启最后一层(_fc)的梯度,和需求完全相反。
  2. 变量名混淆:代码中混用了model_b0和model_b7,优化器用了model_b7.parameters(),训练时又传入model_b7,但实际定义的模型是model_b0,这会导致使用未正确配置梯度的模型训练,触发反向传播错误。
  3. 优化器冗余:传入所有参数(包括冻结的)会浪费资源,应该只传入需要训练的参数。

修正后的代码

from efficientnet_pytorch import EfficientNet
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler

# 加载预训练模型
model_b0 = EfficientNet.from_pretrained('efficientnet-b0')
num_ftrs = model_b0._fc.in_features
model_b0._fc = nn.Linear(num_ftrs, 10)

# 1. 冻结所有参数
for param in model_b0.parameters():
    param.requires_grad = False

# 2. 找到第一层并开启梯度(EfficientNet的第一层是features模块下的conv_stem,即features[0])
first_layer = model_b0.features[0]
for param in first_layer.parameters():
    param.requires_grad = True

# 3. 优化器仅传入需要训练的参数(若仅训练第一层,可去掉model_b0._fc.parameters();若全连接层也需训练则保留)
params_to_train = list(first_layer.parameters()) + list(model_b0._fc.parameters())
optimizer_ft = optim.SGD(params_to_train, lr=0.001, momentum=0.9)

exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)

# 训练模型(确保传入正确的model_b0)
model_b0 = train_model(model_b0, criterion, optimizer_ft, exp_lr_scheduler, num_epochs=3)

关键细节说明

  • 第一层定位:EfficientNet的特征提取部分在model_b0.features下,第一个子模块features[0]就是输入卷积层(conv_stem),即模型的第一层。
  • 梯度控制:通过requires_grad=False冻结参数,True开启训练,确保只有目标层参与反向传播更新。
  • 优化器参数筛选:只传入需要训练的参数,避免优化器处理大量冻结参数,提升训练效率,同时避免潜在的梯度计算问题。
  • 变量名统一:全程使用model_b0,避免因变量名混淆导致的模型配置不匹配问题。

报错原因解释

你之前的报错源于两点:

  1. 混用model_b0和model_b7,导致训练时使用的模型未正确设置梯度(model_b7可能未定义或未配置requires_grad)。
  2. 即使变量名正确,原逻辑是训练最后一层,若该层梯度设置有问题,或反向传播时没有任何可训练的参数,就会触发RuntimeError——因为loss的计算路径中没有可求导的参数,无法完成反向传播。

内容的提问来源于stack exchange,提问作者log moment

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 07:25:18