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

使用PyTorch微调VGG16做图像分类时反向传播报错的解决方法

解决PyTorch预训练VGG16训练时的RuntimeError问题

问题场景

使用PyTorch做图像分类,训练简单线性模型的函数可正常运行,但加载预训练VGG16并修改最后一层、冻结其余参数后,训练抛出错误:

RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn

用户的VGG16修改代码:

model_vgg = models.vgg16(weights='DEFAULT')
model_vgg.classifier[6] = nn.Linear(4096, 2)

for param in model_vgg.parameters():
    param.requires_grad = False
model_vgg.classifier[-1].requires_grad = True

train(model_vgg, train_loader, 2)

原训练函数核心逻辑:

criterion = nn.CrossEntropyLoss()
def train(model, dataloader, epoch):
    model.to(device)
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
    running_loss, running_acc = 0., 0.
    
    for i in range(1, epoch + 1):
        model.train()
        for inputs, targets in dataloader:
            inputs, targets = inputs.to(device), targets.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, targets)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            preds = torch.argmax(outputs, 1)
            running_loss += loss.item()
            running_acc += torch.sum(preds == targets).item()
        
        # 原print语句存在语法错误,需修正
        print(f"[TRAIN epoch {i}] Loss: {running_loss/len(data_train):.2f} Acc: {100 * running_acc/len(data_train):.2f}%")

问题原因

训练函数里初始化优化器时,传入了model.parameters(),但此时模型绝大多数参数的requires_grad被设为False,导致优化器中没有可训练的参数。反向传播时,损失无法找到需要更新的梯度节点,从而触发错误。

解决方案

1. 仅传入可训练参数给优化器

修改训练函数中的优化器初始化代码,只传入最后一层(model.classifier[-1])的参数:

# 替换原optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
optimizer = torch.optim.Adam(model.classifier[-1].parameters(), lr=1e-3)

这样优化器只会跟踪需要训练的最后一层参数,反向传播时就能正常计算梯度。

2. 验证参数可训练状态(可选)

用以下代码确认参数的requires_grad状态,确保只有最后一层参数可训练:

for name, param in model_vgg.named_parameters():
    print(f"{name}: {param.requires_grad}")

输出中应仅classifier.6.weight和classifier.6.bias的requires_grad为True。

3. 修正训练函数语法错误

原训练函数存在两处语法问题:

  • accuracy_history = [](data_train):.2f}%") 是无效代码,需删除或正确初始化
  • print语句未闭合,需补充完整格式化字符串

修正后的训练函数片段:

def train(model, dataloader, epoch, data_train):
    model.to(device)
    optimizer = torch.optim.Adam(model.classifier[-1].parameters(), lr=1e-3)
    running_loss, running_acc = 0., 0.
    loss_history = []
    accuracy_history = []
    
    for i in range(1, epoch + 1):
        model.train()
        running_loss = 0.  # 每个epoch重置损失和准确率
        running_acc = 0.
        for inputs, targets in dataloader:
            inputs, targets = inputs.to(device), targets.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, targets)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            preds = torch.argmax(outputs, 1)
            running_loss += loss.item() * inputs.size(0)  # 按样本数加权
            running_acc += torch.sum(preds == targets).item()
        
        epoch_loss = running_loss / len(data_train)
        epoch_acc = 100 * running_acc / len(data_train)
        loss_history.append(epoch_loss)
        accuracy_history.append(epoch_acc)
        print(f"[TRAIN epoch {i}] Loss: {epoch_loss:.2f} Acc: {epoch_acc:.2f}%")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:58:02