Python PyTorch内存模型:“;torch.from“u numpy()”;vs";torch.Tensor();
我试图深入了解PyTorch张量记忆模型的工作原理Python PyTorch内存模型:“;torch.from“u numpy()”;vs";torch.Tensor();,python,numpy,multidimensional-array,deep-learning,pytorch,Python,Numpy,Multidimensional Array,Deep Learning,Pytorch,我试图深入了解PyTorch张量记忆模型的工作原理 # input numpy array In [91]: arr = np.arange(10, dtype=float32).reshape(5, 2) # input tensors in two different ways In [92]: t1, t2 = torch.Tensor(arr), torch.from_numpy(arr) # their types In [93]: type(arr), type(t1), typ
# input numpy array
In [91]: arr = np.arange(10, dtype=float32).reshape(5, 2)
# input tensors in two different ways
In [92]: t1, t2 = torch.Tensor(arr), torch.from_numpy(arr)
# their types
In [93]: type(arr), type(t1), type(t2)
Out[93]: (numpy.ndarray, torch.FloatTensor, torch.FloatTensor)
# ndarray
In [94]: arr
Out[94]:
array([[ 0., 1.],
[ 2., 3.],
[ 4., 5.],
[ 6., 7.],
[ 8., 9.]], dtype=float32)
我知道PyTorch张量共享NumPy Ndarray的内存缓冲区。因此,改变一个将反映在另一个。所以,这里我正在切片和更新张量中的一些值
t2
In [98]: t2[:, 1] = 23.0
正如所料,它在t2
和arr
中更新,因为它们共享相同的内存缓冲区
In [99]: t2
Out[99]:
0 23
2 23
4 23
6 23
8 23
[torch.FloatTensor of size 5x2]
In [101]: arr
Out[101]:
array([[ 0., 23.],
[ 2., 23.],
[ 4., 23.],
[ 6., 23.],
[ 8., 23.]], dtype=float32)
但是,t1
也会更新。请记住,t1
是使用torch.Tensor()
构建的,而t2
是使用torch.from\u numpy()构建的
因此,无论我们是使用还是从数据数组构造张量,所有这些张量和数据数组共享相同的内存缓冲区
In [99]: t2
Out[99]:
0 23
2 23
4 23
6 23
8 23
[torch.FloatTensor of size 5x2]
In [101]: arr
Out[101]:
array([[ 0., 23.],
[ 2., 23.],
[ 4., 23.],
[ 6., 23.],
[ 8., 23.]], dtype=float32)
基于这一理解,我的问题是,为什么只有一个专门的功能才能完成这项工作
我看了PyTorch文档,但它没有提到这方面的任何内容?有什么想法/建议吗?这来自\u torch\u docs.py
;还有可能讨论“为什么”
摘自numpy
文档:
不同的ndarray
可以共享相同的数据,因此在一个ndarray中所做的更改可能在另一个ndarray中可见。也就是说,一个ndarray
可以是另一个ndarray
的“视图”,它所引用的数据由“基本”ndarray
处理
Pytorch文档
:
如果给定了numpy.ndarray
、torch.Tensor
、或torch.Storage
,则返回共享相同数据的新张量。如果给定一个Python序列,将从该序列的副本创建一个新的张量
from_numpy()
自动继承输入数组dtype
。另一方面,torch.Tensor
是torch.FloatTensor
的别名
因此,如果将int64
数组传递给torch.Tensor
,则输出张量为float张量,它们不会共享存储torch.from_numpy
按预期为您提供torch.LongTensor
a = np.arange(10)
ft = torch.Tensor(a) # same as torch.FloatTensor
it = torch.from_numpy(a)
a.dtype # == dtype('int64')
ft.dtype # == torch.float32
it.dtype # == torch.int64
建议在Pytorch中构建张量的方法是使用以下两个工厂函数:torch.tensor
和torch.as\tensor
torch.tensor
始终复制数据。例如,torch.tensor(x)
相当于x.clone().detach()
torch.as_tensor
总是试图避免数据的拷贝。as_tensor
避免复制数据的一种情况是,原始数据是一个numpy数组 我试着按照你说的去做,结果一切正常:
Torch 1.8.1、Numpy 1.20.1、python 3.8.5
x = np.arange(8, dtype=np.float64).reshape(2,4)
y_4mNp = torch.from_numpy(x)
y_t = torch.tensor(x)
print(f"x={x}\ny_4mNp={y_4mNp}\ny_t={y_t}")
所有变量现在的值与预期值相同:
x=[[0. 1. 2. 3.]
[4. 5. 6. 7.]]
y_4mNp=tensor([[0., 1., 2., 3.],
[4., 5., 6., 7.]], dtype=torch.float64)
y_t=tensor([[0., 1., 2., 3.],
[4., 5., 6., 7.]], dtype=torch.float64)
From_numpy使用的底层内存与np变量使用的内存相同。
因此,改变np或.from_numpy变量会相互影响,但不会影响张量变量。
但是对y\u t的更改只影响它本身,而不影响numpy或from\u numpy变量
x[0,1] = 111 ## changed the numpy variable itself directly
y_4mNp[1,:] = 500 ## changed the .from_numpy variable
y_t[0,:] = 999 ## changed the tensor variable
print(f"x={x}\ny_4mNp={y_4mNp}\ny_t={y_t}")
现在输出:
x=[[ 0. 111. 2. 3.]
[500. 500. 500. 500.]]
y_4mNp=tensor([[ 0., 111., 2., 3.],
[500., 500., 500., 500.]], dtype=torch.float64)
y_t=tensor([[999., 999., 999., 999.],
[ 4., 5., 6., 7.]], dtype=torch.float64)
不知道这是否是早期版本的问题?非常有趣的问题。我不知道答案,但我怀疑torch.Tensor()
可能接受其他形式的输入(例如,列表),但torch.from_numpy()
仅在numpy数组上运行。此评论是关于torch.Tensor
和torch.as_Tensor
,这是很好的了解。但它并没有解决OP关于火炬的问题。
x=[[ 0. 111. 2. 3.]
[500. 500. 500. 500.]]
y_4mNp=tensor([[ 0., 111., 2., 3.],
[500., 500., 500., 500.]], dtype=torch.float64)
y_t=tensor([[999., 999., 999., 999.],
[ 4., 5., 6., 7.]], dtype=torch.float64)