PyTorch 旨在与 NumPy 非常兼容。因此,PyTorch 的 Tensor 与 Numpy 的 array 能够非常方便的进行互相转换。本篇以 Jupyterlab 为平台进行介绍。
numpy to pytorch
常规转换
1 2
| import numpy as np import torch
|
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=torch.float64)
转换时改变数据类型
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
1
| torch.from_numpy(x).type(torch.float32)
|
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
转换时发送到不同的设备上,如 GPU
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
1 2 3
| if torch.cuda.is_available(): y = torch.from_numpy(x).to("cuda") y
|
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], device='cuda:0', dtype=torch.float64)
注意,当使用锁页内存(pytorch 中数据加载器的锁页内存 pinned memory)的方式加载数据时,数据放入 GPU 的时候,应该把 non_blocking=True,这样能够缩减访问时间,加快训练。
1 2 3 4
| if torch.cuda.is_available(): y = torch.from_numpy(x).to("cuda", non_blocking=True) y
|
pytorch to numpy
转向另一个方向会稍微复杂一些,因为有时您必须处理 PyTorch 张量和 NumPy 数组之间的两个差异:
- PyTorch 可以针对不同的设备(如 GPU);
- PyTorch 支持自动微分。
在最简单的情况下,当你在 CPU 上有一个没有梯度的 PyTorch 张量时,你可以简单地调用 .numpy() 方法:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=float32)
如果张量是需要梯度的计算图的一部分(也就是说,如果 x.requires_grad=True),则需要调用 .detach() 方法:
1 2
| x = torch.eye(3, requires_grad=True) x
|
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], requires_grad=True)
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
1 2
| x.requires_grad = True x
|
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], requires_grad=True)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=float32)
如果 Tensor 位于 “cpu” 以外的设备上,则需要先将其带回 CPU,然后才能调用 .numpy() 方法。我们在上面使用 .to(“cuda”) 向 GPU 发送张量时看到了这一点。现在,我们只是反过来:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], device='cuda:0')
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=float32)
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], device='cuda:0')
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=float32)
最完全最常用的将 Tensor 转成 numpy array 的方法如下:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
1
| x.detach().cpu().numpy()
|
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=float32)
1
| x.detach().to('cpu').numpy()
|
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=float32)
转换后共享内存
注意,转换后的 pytorch tensor 与 numpy array 指向同一地址,所以,对一方的值改变另一方也随之改变
除 chartensor 外所有 tensor 都可以转换为 numpy
1 2
| import torch import numpy as np
|
tensor([1., 1., 1., 1., 1.])
array([1., 1., 1., 1., 1.], dtype=float32)
tensor([2., 2., 2., 2., 2.])
array([2., 2., 2., 2., 2.], dtype=float32)
array([3., 3., 3., 3., 3.], dtype=float32)
tensor([3., 3., 3., 3., 3.])
array([1., 1., 1., 1., 1.])
1 2
| d = torch.from_numpy(c) d
|
tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
array([2., 2., 2., 2., 2.])
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
tensor([3., 3., 3., 3., 3.], dtype=torch.float64)
array([3., 3., 3., 3., 3.])
参考文献
- PyTorch Tensor to NumPy Array and Back
- pytorch tensor与numpy转换