使用detach()后VGG模型权重不更新,移除则触发原地操作错误如何解决?
绘画风格识别VGG模型训练问题解决
核心问题
训练绘画风格识别VGG模型时陷入两难:
- 给相关张量加
detach()后,模型权重完全无法更新 - 不加
detach()则触发RuntimeError,提示梯度计算依赖的变量被原地操作修改
错误根源解析
- 梯度链路断裂:将
similarity.item()转成数值再重构张量,直接切断了模型输出到损失函数的梯度传播链路,反向传播时权重收不到梯度更新信号 - 原地操作破坏计算图:循环末尾直接赋值
vector2_tensor = vector1_tensor,会覆盖旧的计算图节点,导致下一轮迭代计算梯度时找不到依赖的历史张量,触发报错 - 冗余梯度设置:
cost.requires_grad_(True)完全多余,BCELoss的输出本身就带有梯度,手动设置反而会干扰计算图逻辑
修正方案
关键修改点
- 保留模型输出张量的梯度链路,避免用
.item()破坏计算图 - 用
.detach()隔离上一轮的张量,防止计算图被原地覆盖 - 移除冗余的梯度手动设置
修正后的训练代码
for i, (_image1, _label1) in enumerate(train_loader): optimizer.zero_grad() image1 = _image1.to(DEVICE) label1 = _label1[0] vector1_tensor = model(image1) if i == 0: # 初始化第一轮对比张量 # 用detach()隔离初始张量,避免后续迭代的计算图关联 image2 = image1.detach() label2 = label1 vector2_tensor = vector1_tensor.detach() # 直接用张量计算相似度,保留梯度链路 similarity = Similarity(vector1_tensor, vector2_tensor) # 直接在设备上创建目标张量,避免跨设备问题 target_tensor = torch.tensor([1.0 if label1 == label2 else 0.0], dtype=torch.float, device=DEVICE) cost = loss(similarity, target_tensor) cost.backward() optimizer.step() # 准备下一轮对比张量,用detach()切断当前轮梯度链路 image2 = image1.detach() label2 = label1 vector2_tensor = vector1_tensor.detach()
额外优化建议
- 学习率
5.5过高,建议先调整为0.01再逐步优化,避免模型训练震荡 - 权重初始化用均值1可能导致初始激活值过大,建议改用均值0的正态初始化:
init.normal_(m.weight, mean=0, std=0.01) - 训练日志中损失值固定不变,说明梯度未正确传播,修正后可观察损失是否正常波动下降
内容的提问来源于stack exchange,提问作者young
相关产品推荐
相关产品推荐

