数组的 Pytorch 张量

我有一个形状为 [4, 3, 966, 1296]的 PytorchTensor。我想用以下代码将其转换为 numpy阵列:

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

那个代码是怎么工作的?

410666 次浏览

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

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

:意味着第一维应该被复制和转换,第三和第四维也是如此。

::-1意味着对于第二个轴,它反转轴

我相信你也必须使用 .detach()。我不得不把我的张量转换成一个数字数组的 Colab 使用 CUDA 和 GPU。我是这样做的:

# 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 below is a numpy array
tensor_array.cpu().detach().numpy()

如果你的变量附加了一些梯度,你可以使用这种语法。

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

你的问题措辞很差。您的代码(在某种程度上)已经做了您想做的事情。你到底在困惑什么?x.numpy()回答你问题的原题:

数组的 Pytorch 张量

你需要从你的题目开始改进你的问题。

不管怎样,以防这个对其他人有用。您可能需要调用 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


另外,我不会对滑动做任何评论,因为这是偏离主题,这不应该是你的问题的重点。看这个:

理解切片符号

虽然其他答案 完美解释了这个问题,我将添加一些现实生活中的例子转换张量到麻木数组:

例子: 共享存储

位于 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.]])

例子: 消除共享存储的影响,先拷贝数组

为了避免共享存储的影响,我们需要将数字数组 na转换为新的数字数组 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数组将改变与行 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.,因为 require_grad=True的张量是由 PyTorchAD 记录的。请注意,tensor.detach()tensor.data的新方法。

这就解释了为什么在使用 numpy()进行转换之前,我们需要先对它们进行 detach()

例子: 具有 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')

这对我很有效:

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