Pytorch张量到numpy数组

时间:2018-04-11 06:49:22

标签: python numpy pytorch

我的pytorch张量大小为torch.Size([4, 3, 966, 1296])

我想使用以下代码将其转换为numpy数组:

imgs = imgs.numpy()[:, ::-1, :, :]

任何人都可以解释一下这段代码在做什么吗?

6 个答案:

答案 0 :(得分:9)

您要转换的张量有4个维度。

[:, ::-1, :, :] 

:表示第一个维度应按原样复制并转换,第三维和第四维度相同。

::-1表示对于第二轴,它会反转轴

答案 1 :(得分:3)

我相信您还必须使用.detach()。我必须在使用CUDA和GPU的Colab上将Tensor转换为numpy数组。我这样做如下:

# this is just my embedding matrix which is a Torch tensor object
embedding = learn.model.u_weight

embedding_list = list(range(0, 64382))

input = torch.cuda.LongTensor(embedding_list)
tensor_array = embedding(input)
# the output of the line bwlow is a numpy array
tensor_array.cpu().detach().numpy()

答案 2 :(得分:3)

其他答案完全时,我将添加一些将张量转换为numpy数组的现实示例:

示例:共享存储空间

驻留在CPU上的PyTorch张量与numpy数组na共享同一存储空间

import torch
a = torch.ones((1,2))
print(a)
na = a.numpy()
na[0][0]=10
print(na)
print(a)

输出:

tensor([[1., 1.]])
[[10.  1.]]
tensor([[10.,  1.]])

示例:消除共享存储的影响,首先复制numpy数组

为了避免共享存储的影响,我们需要将numpy数组copy() na更改为新的numpy数组nac。 Numpy copy()方法创建新的单独存储。

import torch
a = torch.ones((1,2))
print(a)
na = a.numpy()
nac = na.copy()
nac[0][0]=10
​print(nac)
print(na)
print(a)

输出:

tensor([[1., 1.]])
[[10.  1.]]
[[1. 1.]]
tensor([[1., 1.]])

现在,仅nac numpy数组将与行nac[0][0]=10naa保持不变。

示例:具有requires_grad=True的CPU张量

import torch
a = torch.ones((1,2), requires_grad=True)
print(a)
na = a.detach().numpy()
na[0][0]=10
print(na)
print(a)

输出:

tensor([[1., 1.]], requires_grad=True)
[[10.  1.]]
tensor([[10.,  1.]], requires_grad=True)

在这里我们称为:

na = a.numpy() 

这将导致:RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.,因为PyTorch AD记录了require_grad=True的张量。请注意,tensor.detach()tensor.data的新方法。

这说明了为什么在使用detach()进行转换之前,我们首先需要numpy()它们。

示例:具有requires_grad=False

的CUDA张量
a = torch.ones((1,2), device='cuda')
print(a)
na = a.to('cpu').numpy()
na[0][0]=10
print(na)
print(a)

输出:

tensor([[1., 1.]], device='cuda:0')
[[10.  1.]]
tensor([[1., 1.]], device='cuda:0')

示例:具有requires_grad=True

的CUDA张量
a = torch.ones((1,2), device='cuda', requires_grad=True)
print(a)
na = a.detach().to('cpu').numpy()
na[0][0]=10
​print(na)
print(a)

输出:

tensor([[1., 1.]], device='cuda:0', requires_grad=True)
[[10.  1.]]
tensor([[1., 1.]], device='cuda:0', requires_grad=True)

如果没有detach()方法,则会设置错误RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.

没有设置.to('cpu')方法TypeError: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.的情况。

您可以使用cpu(),而不是to('cpu'),但我更喜欢新的to('cpu')

答案 3 :(得分:1)

这对我有用:

np_arr = torch_tensor.cpu().detach().numpy()

答案 4 :(得分:0)

如果变量附带某些毕业证明,则可以使用此语法。

y = torch.Tensor.cpu(x).detach()。numpy()[:,:,:,-1]

答案 5 :(得分:0)

您的问题措辞很差。您的代码(某种程度上)已经可以满足您的要求。您到底对什么感到困惑? x.numpy()回答问题的原始标题:

Pytorch张量到numpy数组

您需要从标题开始改善问题。

无论如何,以防万一这对其他人有用。您可能需要调用detach才能使代码正常工作。例如

RuntimeError: Can't call numpy() on Variable that requires grad.

因此致电.detach()。示例代码:

# creating data and running through a nn and saving it

import torch
import torch.nn as nn

from pathlib import Path
from collections import OrderedDict

import numpy as np

path = Path('~/data/tmp/').expanduser()
path.mkdir(parents=True, exist_ok=True)

num_samples = 3
Din, Dout = 1, 1
lb, ub = -1, 1

x = torch.torch.distributions.Uniform(low=lb, high=ub).sample((num_samples, Din))

f = nn.Sequential(OrderedDict([
    ('f1', nn.Linear(Din,Dout)),
    ('out', nn.SELU())
]))
y = f(x)

# save data
y.numpy()
x_np, y_np = x.detach().cpu().numpy(), y.detach().cpu().numpy()
np.savez(path / 'db', x=x_np, y=y_np)

print(x_np)

cpu在分离之后进行。参见:https://discuss.pytorch.org/t/should-it-really-be-necessary-to-do-var-detach-cpu-numpy/35489/5


我也不会对这种打滑发表任何评论,因为这不在主题范围之内,也不应该成为您提问的重点。看到这个:

Understanding slice notation