1.问题描述

我们使用Numpy也是可以手动去编写神经网络进行反向传播深度学习的,就是有两个问题,

1.Numpy手动去编写神经网络很繁琐,代码量较大,不利于大规模开发;2.Numpy无法直接使用GPU加速计算

看到网上有很多人说PyTorch很好用,比TensorFlow优雅便捷。个人认为其中一个很主要的原因PyTorch很类似与Numpy,对数据操作处理很简单。并且PyTorch是支持使用GPU加速的,所以有人比喻PyTorch是GPU版本的Numpy。

PyTorch为了实现GPU加速功能,引入了Tensor,为了实现自动求导功能引入了Variable。但是由于引入了这些新的概念,会让一些不理解初学者在使用的时候遇到一些问题。

2.问题剖析

我们现在已经知道了PyTorch为了实现GPU加速功能,引入了Tensor,为了实现自动求导功能引入了Variable。我们一般读取的数据都是以Numpy Array方式的。在TensorFlow,Numpy的数据会在输入网络后自动转换为Tensor,一般不需要我们进行显性操作,当然偶尔也会有例外,可以参考 [开发技巧]·TensorFlow中numpy与tensor数据相互转化。但是在PyTorch,需要我们自己进行显性操作才可以的。

下面我以一个网络训练的过程来讲解它们之间如何进行相互的转换。

  • 首先我们会读取Numpy的数据,我们为了能够送入网络,使用GPU计算加速,所以要进行Numpy2Tensor操作,由于网络输入输出都是Variable,我们还需要Tensor2Variable。在训练的过程中,我们需要取出loss的值,由于loss参与了backward(),所以此时的loss已经变成了Variable,我们取出loss时需要取出的是Tensor。同样的,如果我想取出网络输出的结果时,由于网络输入输出都是Variable,也需要执行Variable2Tensor,如果进一步我们想把loss显示出来,就需要Tensor2Numpy

总结一下,真正和我们开发人员直接接触的是Numpy数据,需要送入网络时进行Numpy2Tensor,如果一些Tensor作为参数需要求解梯度信息时进行Tensor2Variable。需要从Variable取数据时,使用Variable2Tensor。对Tensor进行读取操作时需要Tensor2Numpy

3.转换方法

  • Numpy2Tensor:1. torch.from_numpy(Numpy_data) 2. torch.tensor(Numpy_data)
  • Tensor2Variable: 1. Variable(Tensor_data)
  • Variable2Tensor: 1. Variable_data.data()
  • Tensor2Numpy : 1.Tensor_data.numpy()

注意一点,Numpy与Variable无法直接转换,需要经过Tensor作为中介。

4 实际测试

import numpy as np
import torch
from torch.autograd import Variable

a=np.random.randint(0,4,(2,2))
print(a)
b=torch.from_numpy(a)
print(b)
c=Variable(torch.from_numpy(a))
print(c)
d=c.data.numpy()
print(d)

输出:

[[2 0]
 [2 3]]
tensor([[2, 0],
        [2, 3]], dtype=torch.int32)
tensor([[2, 0],
        [2, 3]], dtype=torch.int32)
[[2 0]
 [2 3]]
 

关于网络输入为tensor还是Variable,传入参数可以为tensor也可以为variable,但尽量传variable吧,反正input在测试的时候都要包装成variable,做参数更新,如下;

import torch
from torch.autograd import Variable

tensor = torch.FloatTensor([[1,2],[3,4]])
variable = Variable(tensor,requires_grad=True)

print(tensor)
print(variable)

t_out = torch.mean(tensor * tensor)
v_out = torch.mean(variable * variable)

v_out.backward()
print('反向传播之后',variable) #反向传播的时候variable 是受影响的,因为反向传播了

print('变量的data是tensor类型--',variable.data)
print('variable转为numpy--',variable.data.numpy())# 必须借助于tensor转换为numpy

参考一幅图

python与numpy版本 pytorch和numpy版本_python与numpy版本

numpy_tensor=np.random.randint(0,4,(2,2))
# numpy转为tensor
pytorch_tensor1=torch.from_numpy(numpy_tensor)
pytorch_tensor2=torch.tensor(numpy_tensor)
gpu_tensor=pytorch_tensor1.cuda()
print(pytorch_tensor1)
print(pytorch_tensor2)
print(gpu_tensor)


# pytorch_tensor转为numpy
numpy_array=pytorch_tensor1.numpy()
# 如果tensor在gp上
numpy_array=pytorch_tensor1.cpu().numpy()

 

 输出:

tensor([[0, 3],
        [0, 0]], dtype=torch.int32)
tensor([[0, 3],
        [0, 0]], dtype=torch.int32)
tensor([[0, 3],
        [0, 0]], device='cuda:0', dtype=torch.int32)