pytorch报错AttributeError: ‘NoneType‘ object has no attribute ‘zero_‘

本文探讨了在PyTorch中进行神经网络训练时,使用"-="运算符与"="运算符更新参数的区别。通过实例展示了"-="避免了因赋值操作导致的梯度丢失问题,从而防止在调用`grad.zero_()`时出现错误。理解这一细节对于优化模型训练和避免调试中的常见错误至关重要。
摘要由CSDN通过智能技术生成

解决方案:

原代码如下:

with torch.no_grad():

    w1 = w1 - learning_rate * w1.grad
    w2 = w2 - learning_rate * w2.grad
      
    # 反向传播后手动将梯度设置为零
    w1.grad.zero_()
    w2.grad.zero_()

  使用pytorch构建神经网络,在参数更新后,将梯度清0时报错:
在这里插入图片描述
  使用"-="运算符,将代码修改为:

with torch.no_grad():
    w1 -= learning_rate * w1.grad
    w2 -= learning_rate * w2.grad

    # 反向传播后手动将梯度设置为零
    w1.grad.zero_()
    w2.grad.zero_()

错误分析:

  每个人的编程习惯可能不同,有的人可能在参数更新时使用的运算符是“-=”:

# 第一种方式更新参数
w1 = w1 - learning_rate * w1.grad
w2 = w2 - learning_rate * w2.grad

# 第二种方式更新参数
w1 -= learning_rate * w1.grad
w2 -= learning_rate * w2.grad

  我们知道pytorch重载了运算符,因此可以直接使用基本运算符合来操作两个tensor变量。但是用第一种方式进行参数更新后(我最开始也使用的是第一种方法),接下来执行梯度清0语句时会报错:
在这里插入图片描述
  debug的时候发现,对w1进行更新后,它的一些属性也发生了变化:

在这里插入图片描述
在这里插入图片描述
  w1的grad属性变成了None,而zero_()方法是针对tensor类型的变量。除此之外,requires_grad的值也变为False。
  至于为什么会发现这样的变化,我在查阅相关资料后发现,pytorch对"-“进行了重载,没有对”="进行重载。

a = 1
b = 2
print(id(a))
a = a + b
print(id(a))

运行结果如下:

1546236096
1546236160

  从变量的id号可以看出,在进行赋值操作时,python其实是将计算结果保存到一个新建的内存空间,从根本上来说,就是新建了一个变量a。

print(id(w1))
w1 = w1 - learning_rate * w1.grad
w2 = w2 - learning_rate * w2.grad
print(id(w1))

输出结果为:

2181909743080
2182128952008

  因此在进行参数更新时,python新建了一个tensor类型的变量,并将计算结果保存到新建的w1中,至于为什么grad的值为None,我个人猜测是因为默认的tensor变量的requires_grad的值默认为False,不对梯度进行跟踪(希望由大佬能解释一下)。
  当我们用第二种方式对参数进行更新时:

print(id(w1))
w1 -= learning_rate * w1.grad
w2 -= learning_rate * w2.grad
print(id(w1))

输出结果为:

1636333876872
1636333876872

  可以看出在使用"-="操作符时,pytorch会将计算结果继续保存到原来的w1空间中,所以grad的值并不为None,置零操作时也不会报错。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值