Pytorch之clone(),detach(),new_tensor(),copy_()

1、clone()

clone()函数返回一个和源张量同shape、dtype和device的张量,与源张量不共享数据内存,但提供梯度的回溯。

import torch

a = torch.tensor(1.0, requires_grad=True)
y = a ** 2
a_ = a.clone()
z = a_ * 3
y.backward()
print(a.grad)  # 2
z.backward()
print(a_.grad)  # None, 无grad
print(a.grad)  # 5. a_的梯度会传递回给a,因此2+3=5


a = a + 1
print(a_) # 1

梯度回溯:对a_进行的运算梯度会加在a(叶子节点)的梯度上。

import torch

a = torch.tensor(1.0, requires_grad=True)
a_ = a.clone()
a_.add_(torch.tensor(1.0))
print(a)    # tensor(1., requires_grad=True)
print(a_)   # tensor(2., grad_fn=<AddBackward0>)
a_.backward()
print(a_.grad)  # None
print(a.grad)   # tensor(1.)

可以发现不共享内存空间。

2、detach()

detach()函数返回一个和源张量同shape、dtype和device的张量,并且与源张量共享数据内存,但不提供梯度的回溯。
import torch

a = torch.tensor(1.0, requires_grad=True)
y = a ** 2
a_ = a.detach()
print(a_.grad)  # None,requires_grad=False
a_.requires_grad_()  # set a_.requires_grad = True
z = a_ * 3
y.backward()
z.backward()
print(a_.grad)  # tensor(3.)
print(a.grad)  # tensor(2.)

可见,a_即使重新定义requires_grad=True,也与a的梯度没有关系。

import torch

a = torch.tensor(1.0, requires_grad=True)
a_ = a.detach()
a_.add_(torch.tensor(1.0))
print(a)    # tensor(2., requires_grad=True)
print(a_)   # tensor(2.)
# a_.backward()
# print(a.grad) # RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn

容易验证a与a_共享内存空间

3、torch.clone.detach() (建议赋值方法)

clone()提供了非数据内存共享的梯度追溯功能,而detach又“舍弃”了梯度回溯功能,因此clone.detach()只做简单的数据复制,既不数据共享,也不梯度共享,从此两个张量无关联。
置于是先clone还是先detach,其返回值一样,一般采用sourcetensor.clone().detach()。

4、new_tensor()

new_tensor()可以将源张量中的数据复制到目标张量(数据不共享),同时提供了更细致的属性控制:

import torch

a = torch.tensor(1.0, device="cuda", dtype=torch.float32, requires_grad=True)
b = a.clone()
c = a.detach()
d = a.clone().detach()
e = a.new_tensor(a)  # more attributions could be setted
f = a.new_tensor(a, device="cpu", dtype=torch.float64, requires_grad=False)
print(a)  # tensor(1., device='cuda:0', requires_grad=True)
print(b)  # tensor(1., device='cuda:0', grad_fn=<CloneBackward>)
print(c)  # tensor(1., device='cuda:0')
print(d)  # tensor(1., device='cuda:0')
print(e)  # tensor(1., device='cuda:0')
print(f)  # tensor(1., dtype=torch.float64)

无参数默认情况下d = e。

5、

import torch

a = torch.tensor(1.0, device="cpu", requires_grad=False)
b = torch.tensor(2.0, device="cuda", requires_grad=True)
print(a)  # tensor(1.)
print(b)  # tensor(2., device='cuda:0', requires_grad=True)
a.copy_(b)
print(a)  # tensor(2., grad_fn=<CopyBackwards>)
print(a.device)  # cpu
print(a.requires_grad)  # True

copy_()会将b复制给a,同时改变a的requires_grad属性,但不改变device属性。(当a.requires_grad=False是copy_()方法会报错)

### 解决 PyTorch 初始化时因缺少 Numpy 模块导致的 UserWarning 错误 当 `import torch` 报错并显示警告信息:“Failed to initialize NumPy: module compiled against API version 0xf but this version”,这通常表明当前环境中安装的 NumPy 和 PyTorch 的版本存在兼容性问题[^1]。 #### 原因分析 此错误的核心在于 Python 程序尝试加载一个与现有环境不匹配的 NumPy 库。具体来说,可能是以下原因之一引起的: - 安装的 NumPy 版本过旧或损坏。 - 当前使用的虚拟环境中有多个不同版本的 NumPy 或者路径冲突。 - PyTorch 需要更高版本的 NumPy 才能正常运行。 --- #### 解决方案 以下是几种常见的解决方案: ##### 方法一:更新 NumPy 到最新稳定版 通过升级 NumPy 来确保它能够满足 PyTorch 对其依赖的要求。可以执行如下命令来完成操作: ```bash pip install --upgrade numpy ``` 或者如果你正在使用 conda,则可以通过以下方式更新 NumPy: ```bash conda update numpy ``` 这种方法适用于大多数情况下由于版本落后而导致的问题。 ##### 方法二:重新创建干净的虚拟环境 如果确认当前工作目录下的依赖项复杂且难以清理,考虑删除现有的虚拟环境并重建一个新的环境。步骤如下: 1. 删除旧有环境(假设名为 myenv): ```bash rm -rf ./myenv/ ``` 2. 创建新的虚拟环境并激活: ```bash python3 -m venv myenv source myenv/bin/activate ``` 3. 在新环境下按照官方推荐的方式安装 PyTorch 及其他必要组件。例如对于 CPU-only 版本: ```bash pip install torch torchvision torchaudio ``` 这样做的好处是可以完全隔离之前可能存在的污染源。 ##### 方法三:调整导入顺序 有时即使已经正确配置好了所有软件包,但由于某些特殊原因仍会出现上述警告消息。此时可以试着改变程序开头部分 import 语句的位置——先引入 NumPy 后再调用 PyTorch 功能函数可能会有所帮助: ```python import numpy as np import torch ``` 注意这里并没有从根本上解决问题而是作为一种临时措施缓解症状而已。 --- #### 关于张量初始化的最佳实践 另外值得注意的是,在实际开发过程中遇到类似 “To copy construct from a tensor...” 这样的提示时,应该遵循最佳做法改写代码逻辑以便更高效地复制 Tensor 数据结构而不破坏原有状态管理机制[^3]: ```python source_tensor = torch.randn((5,)) new_tensor = source_tensor.clone().detach() if new_tensor.requires_grad: new_tensor.requires_grad_(False) ``` 以上片段展示了如何安全有效地克隆分离原始张量实例的同时还能控制梯度计算选项的状态转移过程。 最后提醒一点关于自定义 Dataset 类型设计方面的小技巧:尽量避免直接操纵共享变量比如计数器之类的成员字段除非绝对必要;否则容易引发潜在竞态条件从而影响最终结果准确性[^2]。 --- ### 总结 综上所述,针对题目描述的情况主要可以从三个方面入手排查修复该类异常现象即检查基础库是否齐全有效、优化项目构建流程以及改进编码习惯等方面综合施策加以应对即可达到理想效果。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值