PyTorch张量

时间:2020-02-23 14:43:42  来源:igfitidea点击:

在本PyTorch教程中,我们将讨论PyTorch Tensor,这是此深度学习框架的组成部分。

PyTorch张量

您以前使用过Python numpy吗?如果是,那么本节对您来说将非常简单!即使您没有使用numpy的经验,也可以在PyTorch和NumPy之间无缝切换!

PyTorch中的Tensor类似于numpy数组,具有使用GPU进行计算的另外灵活性。

1. 2D Pytorch张量

想象一个张量为一个数字数组,其维数可能是任意的。
在C/C++/Java中,张量和多维数组之间的唯一区别是,维中所有列的大小都相同。

例如,以下内容可以是二维张量的有效表示。

[[1 2 3 4],
 [5 6 7 8]]

但是请注意,以下示例不是有效示例,因为张量不是锯齿状数组。

[[1 2 3 4],
 [5 6 7]]

PyTorch张量对于程序员来说真的很方便,因为它们几乎与numpy数组相同。

但是,与numpy方法有一些区别,因此建议您也参考官方文档以获取更多信息。

2.初始化一个空的PyTorch张量

让我们考虑以下示例,该示例初始化一个空的Tensor。

import torch 
# Creates a 3 x 2 matrix which is empty
a = torch.empty(3, 2)

张量为空并不意味着它不包含任何东西。
只是分配了内存而已。

import torch 
# Creates a 3 x 2 matrix which is empty
a = torch.empty(3, 2)
print(a)

# Create a zero initialized float tensor
b = torch.zeros(3, 2, dtype=torch.float32)
print(b)

输出

tensor([[3.4655e-37, 0.0000e+00],
      [4.4842e-44, 0.0000e+00],
      [       nan, 6.1657e-44]])
tensor([[0., 0.],
      [0., 0.],
      [0., 0.]])

第一个张量是PyTorch只需为张量分配内存的结果。
存储器中的所有先前内容均不会被擦除。

由于PyTorch会分配内存并将张量元素零初始化,因此第二张量将填充零。

注意与numpy.empty()和numpy.zeros()的相似性。
这是因为PyTorch旨在替代" numpy",因为GPU可用。

3.查找PyTorch张量大小

让我们创建一个基本张量并确定其大小。

import torch 
# Create a tensor from data
c = torch.tensor([[3.2 , 1.6, 2], [1.3, 2.5 , 6.9]])
print(c)

输出

tensor([[3.2000, 1.6000, 2.0000],
      [1.3000, 2.5000, 6.9000]])

要获取张量的大小,我们可以使用tensor.size()

print(c.size())

输出

torch.Size([2, 3])

PyTorch张量操作

像numpy一样,PyTorch支持类似的张量操作。

摘要在下面的代码块中给出。

1.关于张量的基本数学运算

import torch 
# Tensor Operations
x = torch.tensor([[2, 3, 4], [5, 6, 7]])
y = torch.tensor([[2, 3, 4], [1.3, 2.6, 3.9]])

# Addition
print(x + y)
# We can also use torch.add()
print(x + y == torch.add(x, y))

# Subtraction
print(x - y)
# We can also use torch.sub()
print(x-y == torch.sub(x, y))

输出

tensor([[ 4.0000,  6.0000,  8.0000],
      [ 6.3000,  8.6000, 10.9000]])
tensor([[True, True, True],
      [True, True, True]])
tensor([[0.0000, 0.0000, 0.0000],
      [3.7000, 3.4000, 3.1000]])
tensor([[True, True, True],
      [True, True, True]])

我们还可以将结果分配给张量。
将以下代码片段添加到上面的代码中。

# We can assign the output to a tensor
z = torch.zeros(x.shape)
torch.add(x, y, out=z)
print(z)

输出

tensor([[ 4.0000,  6.0000,  8.0000],
      [ 6.3000,  8.6000, 10.9000]])

2.使用PyTorch张量进行内联加减法

当带有下划线(_)后缀时,PyTorch还支持就地操作,例如加法和减法。
让我们继续上面操作摘要代码中的相同变量。

# In-place addition
print('Before In-Place Addition:', y)
y.add_(x)
print('After addition:', y)

输出

Before In-Place Addition: tensor([[2.0000, 3.0000, 4.0000],
      [1.3000, 2.6000, 3.9000]])
After addition: tensor([[ 4.0000,  6.0000,  8.0000],
      [ 6.3000,  8.6000, 10.9000]])

3.访问张量索引

我们也可以在PyTorch中使用基于numpy的索引

# Use numpy slices for indexing
print(y[:, 1]

输出

tensor([6.0000, 8.6000])

重塑PyTorch张量

类似于numpy,我们可以使用torch.reshape()来重塑张量。
我们也可以使用tensor.view()实现相同的功能。

import torch 
x = torch.randn(5, 3)
# Return a view of the x, but only having 
# one dimension
y = x.view(5 * 3)

print('Size of x:', x.size())
print('Size of y:', y.size())

print(x)
print(y)

# Get back the original tensor with reshape()
z = y.reshape(5, 3)
print(z)

输出

Size of x: torch.Size([5, 3])
Size of y: torch.Size([15])

tensor([[ 0.3224,  0.1021, -1.4290],
      [-0.3559,  0.2912, -0.1044],
      [ 0.3652,  2.3112,  1.4784],
      [-0.9630, -0.2499, -1.3288],
      [-0.0667, -0.2910, -0.6420]])

tensor([ 0.3224,  0.1021, -1.4290, -0.3559,  0.2912, -0.1044,  0.3652,  2.3112,
       1.4784, -0.9630, -0.2499, -1.3288, -0.0667, -0.2910, -0.6420])

tensor([[ 0.3224,  0.1021, -1.4290],
      [-0.3559,  0.2912, -0.1044],
      [ 0.3652,  2.3112,  1.4784],
      [-0.9630, -0.2499, -1.3288],
      [-0.0667, -0.2910, -0.6420]])

所有Tensor操作的列表均可在PyTorch的文档中找到。

PyTorch – NumPy桥

我们可以很容易地将PyTorch张量转换为numpy数组,反之亦然。

PyTorch的设计方式是,CPU上的Torch张量和相应的" numpy"数组将具有相同的内存位置。
因此,如果您更改其中一个,则另一个将自动更改。

为了证明这一点,让我们使用" torch.numpy()"和" torch.from_numpy()"方法进行测试。

torch.numpy()用于将Tensor转换为numpy数组,而torch.from_numpy()将执行相反的操作。

import torch 
# We also need to import numpy to declare numpy arrays
import numpy as np

a = torch.tensor([[1, 2, 3], [4, 5, 6]])
print('Original Tensor:', a)

b = a.numpy()
print('Tensor to a numpy array:', b)

# In-Place addition (add 2 to every element)
a.add_(2)

print('Tensor after addition:', a)

print('Numpy Array after addition:', b)

输出

Original Tensor: tensor([[1, 2, 3],
      [4, 5, 6]])
Tensor to a numpy array: [[1 2 3]
 [4 5 6]]
Tensor after addition: tensor([[3, 4, 5],
      [6, 7, 8]])
Numpy Array after addition: [[3 4 5]
 [6 7 8]]

实际上,numpy数组也改变了它的价值!

让我们做相反的事情

import torch
import numpy as np

c = np.array([[4, 5, 6], [7, 8, 9]])
print('Numpy array:', c)

# Convert to a tensor
d = torch.from_numpy(c)
print('Tensor from the array:', d)

# Add 3 to each element in the numpy array
np.add(c, 3, out=c)

print('Numpy array after addition:', c)

print('Tensor after addition:', d)

输出

Numpy array: [[4 5 6]
 [7 8 9]]
Tensor from the array: tensor([[4, 5, 6],
      [7, 8, 9]])
Numpy array after addition: [[ 7  8  9]
 [10 11 12]]
Tensor after addition: tensor([[ 7,  8,  9],
      [10, 11, 12]])

注意:如果您不通过a + = 3或者np.add(out = a)使用numpy`就地加法,那么Tensor将不会反映numpy数组中的更改。

例如,如果您尝试这样做:

c = np.add(c, 3)

由于您使用的是=,这意味着Python将创建一个新对象并将该新对象分配给名为c的名称。
因此,原始内存位置仍保持不变。

将CUDA GPU与PyTorch张量配合使用

通过将张量移动到GPU,我们可以使NVIDIA CUDA GPU执行计算并提高速度。

注意:仅当您启用了CUDA的NVIDIA GPU时才适用。
如果您不确定这些术语是什么,我建议您在线搜索。

我们可以使用" torch.cuda.is_available()"检查是否有可用于PyTorch的GPU。

import torch 
if torch.cuda.is_available():
  print('Your device is supported. We can use the GPU for PyTorch!')
else:
  print('Your GPU is either 不支持 by PyTorch or you haven't installed the GPU version')

对我来说,它是可用的,因此只要您的笔记本电脑支持,请确保先安装CUDA,然后再继续进行。

我们可以使用" tensor.to(device)"将张量从CPU移至GPU,其中" device"是设备对象。

可以是" torch.device(" cuda")",也可以只是" cpu"。

import torch 
x = torch.tensor([1, 2, 3], dtype=torch.long)

if torch.cuda.is_available():
  print('CUDA is available')
  # Create a CUDA Device object
  device = torch.device("cuda")

  # Create a tensor from x and store on the GPU
  y = torch.ones_like(x, device=device)
  
  # Move the tensor from CPU to GPU
  x = x.to(device)

  # This is done on the GPU
  z = x + y
  print(z)

  # Move back to CPU and also change dtype
  print(z.to("cpu", torch.double))
  print(z)
else:
  print('CUDA is not available')

输出

CUDA is available
tensor([2, 3, 4], device='cuda:0')
tensor([2., 3., 4.], dtype=torch.float64)
tensor([2, 3, 4], device='cuda:0')