PyTorch神经网络训练调用loss.backward()报张量无grad及grad_fn错误
错误原因
这个报错的直接原因是反向传播所需的计算图被提前中断,问题出在这行代码:y_ = (y_>0.5).float()
大于阈值判断和强制转float的操作属于不可导的离散操作,执行后生成的新y_张量会自动丢失梯度属性:requires_grad变为False,也没有记录计算路径的grad_fn,后续基于这个张量计算得到的loss自然也没有梯度信息,执行反向传播时就会触发该错误。
补充说明:你代码里使用的Variable是PyTorch 0.4版本之前的旧API,现在版本的PyTorch已经将Tensor和Variable合并,不需要额外用Variable包裹张量,这个不是本次报错的直接原因,但属于可优化的冗余写法。另外你原代码漏了每次迭代前清零梯度的optimizer.zero_grad()操作,会导致梯度累加,也会影响训练效果。
解决方法
- 损失计算必须使用模型输出的原始张量,不能使用二值化后的结果。
(y_>0.5).float()属于后处理逻辑,仅用于计算准确率、输出预测结果等不需要梯度的场景,要放到损失计算、梯度更新之后执行。 - 移除冗余的Variable包裹逻辑,补充梯度清零的步骤。
修改后的核心代码示例
for epoch in range(N_EPOCHS): model.train() for i,(im1, im2, labels) in enumerate(train_dl): # 每次迭代前清零梯度 optimizer.zero_grad() i1 = torch.flatten(im1,1) i2 = torch.flatten(im2,1) inp = torch.cat([i1,i2],1) b_y = labels y_ = model(inp).squeeze() # 损失计算使用原始输出,不做二值化 loss = criterion(y_, b_y) loss.backward() optimizer.step() # 二值化后处理放到梯度更新之后,仅用于统计指标 pred = (y_>0.5).float() print(loss.item())
内容的提问来源于stack exchange,提问作者Muhammad Muneeb Ur Rahman
相关产品推荐
相关产品推荐

