【完美解决】RuntimeError: one of the variables needed for gradient computation has been modified by an inp

简介: 将loss.backward()函数内的参数retain_graph值设置为True, loss.backward(retain_graph=True),如果retain_graph设置为False,计算过程中的中间变量使用完即被释放掉。

正文在后面,往下拉即可~~~~~~~~~~~~


欢迎各位深度学习的小伙伴订阅的我的专栏


a42c28e57d5c4e4395f6a1861b0f131b.png


Pytorch深度学习·理论篇+实战篇(2023版)专栏地址:


💛Pytorch深度学习·理论篇(2023版)

https://blog.csdn.net/qq_39237205/category_12077968.html

💚Pytorch深度学习·动手篇(2023版)

https://blog.csdn.net/qq_39237205/category_12077994.html


正文开始


【就看这一篇就行】RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.FloatTensor [256]] is at version 4; expected version 3 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).


针对网上搜到的以下办法均无效的情况:


1)找到网络模型中的 inplace 操作,将inplace=True改成 inplace=False,例如torch.nn.ReLU(inplace=False)


2)将代码中的“a+=b”之类的操作改为“c = a + b”


3)将loss.backward()函数内的参数retain_graph值设置为True, loss.backward(retain_graph=True),如果retain_graph设置为False,计算过程中的中间变量使用完即被释放掉。


↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑以上方案无效↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑


↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓正确解决方案如下↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓


1、问题描述:


320e9e131a5c4794adbcad29a3cde798.png


提示在 loss.backward()报错


RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.FloatTensor [256]] is at version 4; expected version 3 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).


2、问题分析


在用PyTorch进行分布式训练时,遇到以上错误。


日志的大概意思是用于梯度计算的变量通过inplace操作被修改。网上的一些解决方法基本是检查模型定义中是否有inplace=True 设置以及+=操作符。但是这两种方案都不能解决遇到的问题。


经过一些调试发现,只有当某些特定情况下才会触发此报错。下面结合一个对比学习的例子(并不是完整的脚本)来简单描述:


import torch
import torch.nn as nn
from torchvision.models import resnet50
def main():
    model = resnet50(num_classes=256).cuda()
    model = nn.parallel.DistributedDataParallel(model, 
                                                device_ids=[args.local_rank], 
                                                find_unused_parameters=True)
    criterion = nn.MSELoss()
    optimizer = torch.optim.SGD(model.parameters(),
                                lr=0.001,
                                momentum=0.99,
                                weight_decay=1e-4)
    for i in range(10):
        input0 = torch.randn((4, 3, 224, 224), dtype=torch.float32).cuda()
        input2 = torch.randn((4, 3, 224, 224), dtype=torch.float32).cuda()
        out1 = model(input0)
        out2 = model(input1)
        loss = criterion(out1, out2)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
if __name__ == '__main__':
    main()


经过调试发现,当使用nn.DataParallel并行训练或者单卡训练均可正常运行;另外如果将两次模型调用集成到model中,即通过out1, out2 = model(input0, input1) 的方式在分布式训练下也不会报错。


由此可以猜测:在分布式训练中,如果对同一模型进行多次调用则会触发以上报错,即


nn.parallel.DistributedDataParallel方法封装的模型,forword()函数和backward()函数必须交替执行,如果执行多个(次)forward()然后执行一次backward()则会报错。


那么解决此问题的入手点则可以聚焦到nn.parallel.DistributedDataParallel接口上。 通过查询PyTorch官方文档发现此接口下的两个参数:


- find_unused_parameters: 如果模型的输出有不需要进行反向传播的,此参数需要设置为True;
若你的代码运行后卡住不动,基本上就是该参数的问题。
- broadcast_buffers: 该参数默认为True,设置为True时,在模型执行forward之前,gpu0会把
buffer中的参数值全部覆盖到别的gpu上。


问题基本可以定位出来了,即broadcast_buffers=True导致参数被覆盖修改。


3、解决办法


# 在该出错文件上找到被调用的DistributedDataParallel(),将broadcast_buffers设置为False
model = nn.parallel.DistributedDataParallel(model, 
                                             device_ids=[args.local_rank], 
                                             broadcast_buffers=False,
                                             find_unused_parameters=True)


RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.FloatTensor [2048]] is at version 4; expected version 3 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).

目录
相关文章
RuntimeError: a view of a leaf Variable that requires grad is being used in an in-place operation.
RuntimeError: a view of a leaf Variable that requires grad is being used in an in-place operation.
2523 0
|
4月前
|
Ubuntu Linux Python
UserWarning: Glyph 27668 (\N{CJK UNIFIED IDEOGRAPH-6C14}) missing from current font.
UserWarning: Glyph 27668 (\N{CJK UNIFIED IDEOGRAPH-6C14}) missing from current font.
206 2
|
PyTorch 算法框架/工具
Pytorch中Trying to backward through the graph和one of the variables needed for gradient错误解决方案
Pytorch中Trying to backward through the graph和one of the variables needed for gradient错误解决方案
2104 0
Pytorch中Trying to backward through the graph和one of the variables needed for gradient错误解决方案
|
6月前
解决Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com
解决Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com
119 5
UnboundLocalError: local variable ‘loss’ referenced before assignment解决方法
UnboundLocalError: local variable ‘loss’ referenced before assignment解决方法
229 0
|
Java Maven
An attempt was made to call a method that does not exist. The attempt was made from the following
An attempt was made to call a method that does not exist. The attempt was made from the following
462 0
成功解决ValueError: Found input variables with inconsistent numbers of samples: [86, 891]
成功解决ValueError: Found input variables with inconsistent numbers of samples: [86, 891]
UserWarning: Glyph 28857 (\N{CJK UNIFIED IDEOGRAPH-70B9}) missing from current font. FigureCanvasA
UserWarning: Glyph 28857 (\N{CJK UNIFIED IDEOGRAPH-70B9}) missing from current font. FigureCanvasA
UserWarning: Glyph 28857 (\N{CJK UNIFIED IDEOGRAPH-70B9}) missing from current font. FigureCanvasA
|
机器学习/深度学习 数据采集
ValueError: Found input variables with inconsistent numbers of samples: [140, 1120] 怎么解决?
这个错误通常发生在机器学习模型的训练中,它表示输入数据的样本数量不一致。在你的情况下,你的输入数据中有两个变量,一个变量的样本数量为140,另一个变量的样本数量为1120,因此这个错误就出现了。 为了解决这个问题,你需要确保所有输入变量的样本数量是相同的。你可以通过以下几种方式来解决这个问题: 检查数据:检查数据是否正确加载,可能会导致数据样本数量不一致。 数据清洗:检查是否有重复的样本或者缺失的样本,如果有则需要对数据进行清洗。 数据对齐:如果你使用了多个数据源,那么你需要对它们进行对齐以确保它们的样本数量一致。 数据重采样:如果数据中有不均衡的样本数量,你可以考虑使用数据重采样方
918 0
解决办法:RuntimeError: dictionary changed size during iteration
解决办法:RuntimeError: dictionary changed size during iteration
136 0