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

解决方案:

原代码如下:

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,置零操作时也不会报错。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇