Python numpy pytorch copy deepcopy clone detach
Python中的直接赋值,原理是对象的引用,虽然赋值后变量有不同的名字,但是变量仍然共享相同的地址。
如果直接赋值并修改列表b中的值,则a对应的值也会被修改。
Python中的浅copy(copy),原理是copy父对象,但不会copy父对象内部的子对象。
如果使用浅copy并修改列表b中的值,则a对应的值就不会被修改。
如果使用浅copy并修改列表b中的值,则a对应的值就不会被修改,但是a中子对象的值被修改了。
Python中的深copy(deepcopy)可以完全copy父对象及其子对象。
如果import copy库并使用copy.deepcopy(),则修改列表b中字列表的值后,a中字列表的值就不会被修改。
Numpy:
在numpy中,如果直接将一个array赋值给另一个array,同样会出现关联的问题。
在numpy中,赋值时使用copy即可解除两个矩阵之间的关联。
Pytorch:
在pytorch中,关联问题同样发生在直接将一个tensor赋值给另外一个tensor时。
Pytorch提供了clone,detach,copy_和new_tensor等多种Tensor复制操作,其中clone和detach在深度学习的模型中最常见到。
clone操作返回一个和源Tensor拥有相同shape,dtype和device的Tensor,与源Tensor不共享内存且可以进行梯度回传。
b作为一个clone的Tensor,会将梯度传递给源Tensor。
如果源Tensor的requires_grad=False并设置clone后的Tensor requires_grad=True,则clone后的Tensor不会发生梯度传递,可以求导。
并且在clone后,Tensor数据不共享。
detach的机制与clone不同,detach返回一个和源Tensor拥有相同shape,dtype和device的Tensor,与源Tensor共享数据内存,但不提供梯度计算,即requires_grad=False,因此通过detach得到的Tensor脱离计算图。
可以看出detach得到的Tensor已经完全脱离计算图,不再进行梯度回传。
可知,detach操作共享数据内存并且脱离计算图,所以经常在仅仅利用Tensor的数值,而不需要梯度回传时使用。
clone:数据不共享,支持梯度回传
detach:数据共享,不支持梯度回传
如果需要clone和detach联合使用,一般采用tensor.clone().detach()这种写法。
new_tensor可以将源Tensor中的数据复制到目标Tensor(数据不共享),同时提供了device,dtype和requires_grad属性控制;
new_tensor(data, dtype=None, device=None, requires_grad=False)
在默认参数下,new_tensor操作等同于tensor.clone().detach(),如果设置requires_grad=True,则相当于tensor.clone().detach().requires_grad=True
copy_
copy_操作可以将源Tensor中的数据复制到目标Tensor(数据不共享),但是device,dtype和requires_grad都保留目标张量的设定,只进行数据复制,同时支持broadcast操作