Pytorch中.detach()与.data的用法小结

 更新时间:2023年07月26日 08:22:17   作者:新生代农民工  
这篇文章主要介绍了Pytorch中.detach()与.data的用法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

Pytorch中.detach()与.data的用法

这里是官方文档对detach的定义

实际上,detach()就是返回一个新的tensor,并且这个tensor是从当前的计算图中分离出来的。但是返回的tensor和原来的tensor是共享内存空间的。

import torch
a = torch.tensor([1.0, 2.0, 3.0], requires_grad = True)
a = a.detach() # 会将requires_grad 属性设置为False
print(a.requires_grad)

举个例子来说明一下detach有什么用。 如果A网络的输出被喂给B网络作为输入, 如果我们希望在梯度反传的时候只更新B中参数的值,而不更新A中的参数值,这时候就可以使用detach()

a = A(input)
a = a.deatch() # 或者a.detach_()进行in_place操作
out = B(a)
loss = criterion(out, labels)
loss.backward()

如果希望修改A的参数, 而不希望修改B的参数, 那么就需要手动将B中参数的requires_grad属性设置为False

for param in B.parameters():
    param.requires_grad = False

还有一点需要注意的是Tensor.detach()和Tensor.data的区别

Tensor.data和Tensor.detach()一样, 都会返回一个新的Tensor, 这个Tensor和原来的Tensor共享内存空间,一个改变,另一个也会随着改变,且都会设置新的Tensor的requires_grad属性为False。这两个方法只取出原来Tensor的tensor数据, 丢弃了grad、grad_fn等额外的信息。区别在于Tensor.data不能被autograd追踪到,如果你修改了Tensor.data返回的新Tensor,原来的Tensor也会改变, 但是这时候的微分并没有被追踪到,那么当你执行loss.backward()的时候并不会报错,但是求的梯度就是错误的!因此, 如果你使用了Tensor.data,那么切记一定不要随便修改返回的新Tensor的值。如果你使用的是Tensor.detach()方法,当你修改他的返回值并进行求导操作,会报错。 因此,Tensor.detach()是安全的。

pytorch中的.detach和.data深入详解

前言:这两个方法都可以用来从原有的计算图中分离出某一个tensor,有相似的地方,也有不同的地方,下面来比较性的看一看。PyTorch0.4以及之后的版本中,.data 仍保留,但建议使用 .detach()

一、tensor.data的使用

先直接看一段代码:

import torch
a = torch.tensor([1,2,3.], requires_grad = True)
out = a.sigmoid()
c = out.data  # 需要走注意的是,通过.data “分离”得到的的变量会和原来的变量共用同样的数据,而且新分离得到的张量是不可求导的,c发生了变化,原来的张量也会发生变化
c.zero_()     # 改变c的值,原来的out也会改变
print(c.requires_grad)
print(c)
print(out.requires_grad)
print(out)
print("----------------------------------------------")
out.sum().backward() # 对原来的out求导,
print(a.grad)  # 不会报错,但是结果却并不正确
'''运行结果为:
False
tensor([0., 0., 0.])
True
tensor([0., 0., 0.], grad_fn=<SigmoidBackward>)
----------------------------------------------
tensor([0., 0., 0.])
'''

tensor.data的两点总结:

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

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

二、tensor.detach()的使用

同样是使用上面的案例代码,将.data 更改成 .detach,如下:

import torch
a = torch.tensor([1,2,3.], requires_grad = True)
out = a.sigmoid()
c = out.detach()  # 需要走注意的是,通过.detach() “分离”得到的的变量会和原来的变量共用同样的数据,而且新分离得到的张量是不可求导的,c发生了变化,原来的张量也会发生变化
c.zero_()     # 改变c的值,原来的out也会改变
print(c.requires_grad)
print(c)
print(out.requires_grad)
print(out)
print("----------------------------------------------")
out.sum().backward() # 对原来的out求导,
print(a.grad)  # 此时会报错,错误结果参考下面,显示梯度计算所需要的张量已经被“原位操作inplace”所更改了。
'''
False
tensor([0., 0., 0.])
True
tensor([0., 0., 0.], grad_fn=<SigmoidBackward>)
----------------------------------------------
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation
'''

tensor.detach()的两点总结:

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

(2)使用tensor.detach()的优点。从上面的例子可以看出,由于我更改分离之后的变量值c,导致原来的张量out的值也跟着改变了,这个时候如果依然按照求导规则来求导,由于out已经更改了,所以不会再继续求导了,而是报错,这样就避免了得出完全牛头不对马嘴的求导结果。

三、总结

相同点:tensor.data和tensor.detach() 都是变量从图中分离,但而这都是“原位操作 inplace operation”。

不同点:

(1).data 是一个属性,二.detach()是一个方法;

(2).data 是不安全的,.detach()是安全的。

到此这篇关于Pytorch中.detach()与.data的用法的文章就介绍到这了,更多相关Pytorch中.detach()与.data内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python获取Windows桌面路径的三种方法

    Python获取Windows桌面路径的三种方法

    在日常编程工作中,有时我们需要将文件或数据自动保存到用户的桌面上以便于快速访问,在 Windows 操作系统中,可以通过多种方式来获取桌面路径,本文将详细介绍三种常用的方法,需要的朋友可以参考下
    2024-12-12
  • Flask框架使用异常捕获问题

    Flask框架使用异常捕获问题

    这篇文章主要介绍了Flask框架使用异常捕获问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • caffe的python接口绘制loss和accuracy曲线

    caffe的python接口绘制loss和accuracy曲线

    这篇文章主要为大家介绍了caffe的python接口绘制loss和accuracy曲线示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 基于MSELoss()与CrossEntropyLoss()的区别详解

    基于MSELoss()与CrossEntropyLoss()的区别详解

    今天小编就为大家分享一篇基于MSELoss()与CrossEntropyLoss()的区别详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • PyCharm安装Python时的常见pip报错原因与解决方案全解析

    PyCharm安装Python时的常见pip报错原因与解决方案全解析

    在使用 PyCharm 进行 Python 开发时,许多开发者常遇到 pip install 失败的问题,本文将系统梳理常见错误场景,并提供高效、可靠的解决方法,有需要的小伙伴可以了解下
    2026-02-02
  • Python使用Pydantic进行数据验证与序列化详解

    Python使用Pydantic进行数据验证与序列化详解

    Pydantic库通过使用Python类型注解来提供数据验证和设置管理,使得数据处理变得更加可靠和高效,本文将深入探讨Pydantic的使用,通过理论讲解和实际代码示例,展示如何在项目中高效利用Pydantic进行数据验证与序列化,需要的可以了解下
    2025-12-12
  • 使用Python测试Ping主机IP和某端口是否开放的实例

    使用Python测试Ping主机IP和某端口是否开放的实例

    今天小编就为大家分享一篇使用Python测试Ping主机IP和某端口是否开放的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • Django框架反向解析操作详解

    Django框架反向解析操作详解

    这篇文章主要介绍了Django框架反向解析操作,结合实例形式详细分析了Django框架相关定义、原理、使用方法及操作注意事项,需要的朋友可以参考下
    2019-11-11
  • Python编程-封装,继承与多态

    Python编程-封装,继承与多态

    这篇文章主要介绍了Python编程-封装,继承与多态,文章主要目的解如何利用封装保护属性、掌握单继承和多继承、会重写和调用父类方法
    理解多态的使用等相关介绍,需要的朋友可以参考一下
    2022-01-01
  • django rest framework 实现用户登录认证详解

    django rest framework 实现用户登录认证详解

    这篇文章主要介绍了django rest framework 实现用户登录认证详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07

最新评论