Pytorch中requires_grad_(), tensor.data,detach(), torch.no_grad()的区别

一、tensor.data的使用 (属性)

import torch
 
a = torch.tensor([1,2,3.], requires_grad = True)
out = a.sigmoid()
c = out.data  # 通过.data “分离”得到的的变量会和原来的变量共用数据(指向同一地址),而且新分离得到的张量是不可求导的
c.zero_()     # 改变c的值,原来的out也会改变
print(c.requires_grad)   #false
print(c)      #tensor([0., 0., 0.])
print(out.requires_grad)     #True
print(out)    #tensor([0., 0., 0.], grad_fn=)
print("----------------------------------------------")
 
out.sum().backward() # 对原来的out求导,
print(a.grad)  # 不会报错,但是结果却并不正确

.data的两点总结:

(1)tensor .data 将返回相同数据的 tensor,而且两个tensor共用数据,一者改变,另一者也会跟着改变。新分离得到的tensor的require s_grad = False, 即不可求导的。(这一点其实detach是一样的)

(2)使用tensor.data的局限性。文档中说使用tensor.data是不安全的, 因为 x.data 不能被 autograd 追踪求微分 。什么意思呢?从上面的例子可以看出,由于我更改分离之后的变量值c,导致原来的张量out的值也跟着改变了,但是这种改变对于autograd是没有察觉的,它依然按照求导规则来求导,导致得出完全错误的导数值却浑然不知。它的风险性就是如果我再任意一个地方更改了某一个张量,求导的时候也没有通知我已经在某处更改了,导致得出的导数值完全不正确,故而风险大。这种方式已经基本被淘汰了。

二、detach() (方法)

import torch
 
a = torch.tensor([1,2,3.], requires_grad = True)
out = a.sigmoid()
c = out.detach()  # 通过.detach() “分离”得到的的变量也会与原张量使用同一数据,而且新分离得到的张量是不可求导的
c.zero_()         # 改变c的值,原来的out也会改变
print(c.requires_grad)    #false
print(c)          #tensor([0., 0., 0.])
print(out.requires_grad)  #true
print(out)        #tensor([0., 0., 0.], grad_fn=)
print("----------------------------------------------")
 
out.sum().backward()      # 对原来的out求导,
print(a.grad)     # 此时会报错,监测到梯度计算所需要的张量已经被“原位操作inplace”所更改了

detach()的两点总结:

(1)tensor.detach() 将返回相同数据的 tensor,而且两个tensor共用数据,一者改变,另一者也会跟着改变。新分离得到的tensor的require s_grad = False, 即不可求导的。(这一点和.data是一样的)

(2)使用tensor.detach()的优点。从上面的例子可以看出,detach存在监测机制。由于我更改分离之后的变量值c,导致原来的张量out的值也跟着改变了,这个时候如果依然按照求导规则来求导肯定会错误,所以不会再继续求导了。

三、requires_grad_()
需要注意的是,这个是函数,与requires_grad属性不同。
这个函数的作用是改变requires_grad属性并返回tensor,修改requires_grad属性是inplace操作,默认参数为requires_grad=True。
Pytorch中requires_grad_(), tensor.data,detach(), torch.no_grad()的区别_第1张图片
注意:只开不关

四、torch.no_grad()
用来禁止梯度的计算,常用在网络推断。
被with torch.no_grad包起来的操作,仍会运行或计算,但是他们的requires_grad属性会被赋为False。从而在计算图中关闭这些操作的梯度计算。
Pytorch中requires_grad_(), tensor.data,detach(), torch.no_grad()的区别_第2张图片
当不需要进行反向传播或梯度计算时,requires_grad=True的变量会占用很多计算资源及存储资源。with torch.no_grad作用范围中的操作不会构建计算图。

参考:https://blog.csdn.net/qq_27825451/article/details/96837905

你可能感兴趣的:(python,pytorch)