0%

什么是PyTorch?

什么是PyTorch?

这是一个基于Python的科学计算软件包,针对两组受众:

  • Numpy的替代品,可以使用GPU的强大功能
  • 深入学习研究平台,提供最大的灵活性和速度

入门

张量

张量与Numpy的ndarray类似,另外还有Tensor也可用于GPU以加速计算

1
2
from __future__ import print_function
import torch

构造一个未初始化的5 * 3矩阵:

1
2
3
4
5
6
7
8
9
10
x = torch.empty(5, 3)
print(x)
"""
output:
tensor([[1.0561e-38, 1.0653e-38, 4.1327e-39],
[8.9082e-39, 9.8265e-39, 9.4592e-39],
[1.0561e-38, 1.0653e-38, 1.0469e-38],
[9.5510e-39, 1.0378e-38, 8.9082e-39],
[9.6429e-39, 8.9082e-39, 9.1837e-39]])
"""

构造一个随机初始化的矩阵:

1
2
3
4
5
6
7
8
9
10
x = torch.rand(5, 3)
print(x)
"""
output:
tensor([[0.4904, 0.0543, 0.2698],
[0.4626, 0.9494, 0.6573],
[0.2933, 0.7157, 0.5195],
[0.3329, 0.3446, 0.3271],
[0.3962, 0.9864, 0.2137]])
"""

构造一个0填充的矩阵 of dtype long:

1
2
3
4
5
6
7
8
9
10
x = torch.zeros(5, 3, dtype=torch.long)
print(x)
"""
output:
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
"""

直接从数据构造Tensor:

1
2
3
4
5
6
x = torch.tensor([5.5, 3])
print(x)
"""
output:
tensor([5.5000, 3.0000])
"""

或者根据现有的张量创建张量。除非用户提供新值,否则这些方法将重用与输入张量的属性,例如dtype

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
x = torch.tensor([5.5, 3])

x = x.new_ones(5, 3, dtype=torch.double) # new method take in size
print(x)

x = torch.randn_like(x, dtype=torch.float) # override dtype!
print(x) # result has the same size
"""
output:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([[-1.5400, 0.6350, 1.6990],
[ 0.0767, 0.3982, -0.0827],
[ 0.1511, 0.8096, 0.0600],
[ 0.2931, 0.8122, -0.3534],
[ 0.7164, -0.0334, 0.2272]])
"""

得到它的大小

1
2
3
4
5
print(x, size())
"""
output:
torch.Size([5, 3])
"""

注意:torch.Size()实际上是一个元组,因此它支持所有元组操作

操作

操作有多种语法。下面的示例中,我们将查看添加操作:

增加:语法1

1
2
3
4
5
6
7
8
9
10
y = torch.rand(5, 3)
print(x + y)
"""
output:
tensor([[ 0.9977, 0.2656, 2.2842],
[ 0.5430, -0.5758, 1.1323],
[ 0.5859, 2.5553, -0.9625],
[-0.2265, 1.2381, 0.8061],
[-0.2200, -0.0597, 0.8266]])
"""

增加:语法2

1
2
3
4
5
6
7
8
9
print(torch.add(x, y))
"""
output:
tensor([[ 0.9977, 0.2656, 2.2842],
[ 0.5430, -0.5758, 1.1323],
[ 0.5859, 2.5553, -0.9625],
[-0.2265, 1.2381, 0.8061],
[-0.2200, -0.0597, 0.8266]])
"""

增加:提供输出张量作为参数

1
2
3
4
5
6
7
8
9
10
11
result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(result)
"""
output:
tensor([[ 0.9977, 0.2656, 2.2842],
[ 0.5430, -0.5758, 1.1323],
[ 0.5859, 2.5553, -0.9625],
[-0.2265, 1.2381, 0.8061],
[-0.2200, -0.0597, 0.8266]])
"""

增加:就地

1
2
3
4
5
6
7
8
9
10
11
# add x to y
y.add_(x)
print(y)
"""
output:
tensor([[ 0.9977, 0.2656, 2.2842],
[ 0.5430, -0.5758, 1.1323],
[ 0.5859, 2.5553, -0.9625],
[-0.2265, 1.2381, 0.8061],
[-0.2200, -0.0597, 0.8266]])
"""

注意:

任何使原张量变形的操作都是用 _ 后固定的。例如:x.copy_(y), x.t_(), 将改变x。

可以使用标准的NumPy索引与所有bells和whistles

1
2
3
4
5
6
7
8
9
10
11
12
x = torch.rand(5, 3)
print(x)
print(x[:, 1])
"""
output:
tensor([[0.3356, 0.3659, 0.7898],
[0.3474, 0.4648, 0.2795],
[0.0268, 0.8986, 0.5615],
[0.8278, 0.4778, 0.0131],
[0.2451, 0.6178, 0.0125]])
tensor([0.3659, 0.4648, 0.8986, 0.4778, 0.6178])
"""

调整大小:如果要调整tensor/重塑tensor,可以使用torch.view

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
x = torch.rand(4, 4)
y = x.view(16)
z = x.view(-1, 8) # the size of -1 is inferred from other dimensions
print(x.size(), y.size(), z.size())
print(x)
print(y)
print(z)
"""
output:
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
tensor([[0.3415, 0.9245, 0.5641, 0.9463],
[0.5833, 0.5632, 0.3456, 0.6338],
[0.2562, 0.6854, 0.1495, 0.0351],
[0.6777, 0.8511, 0.9998, 0.7963]])
tensor([0.3415, 0.9245, 0.5641, 0.9463, 0.5833, 0.5632, 0.3456, 0.6338, 0.2562,
0.6854, 0.1495, 0.0351, 0.6777, 0.8511, 0.9998, 0.7963])
tensor([[0.3415, 0.9245, 0.5641, 0.9463, 0.5833, 0.5632, 0.3456, 0.6338],
[0.2562, 0.6854, 0.1495, 0.0351, 0.6777, 0.8511, 0.9998, 0.7963]])
"""

假如你有一个元素张量,可以用item()获取值作为python数字

1
2
3
4
5
6
7
8
x = torch.randn(1)
print(x)
print(x.item())
"""
output:
tensor([-0.2729])
-0.2729296088218689
"""

torch包含用于多维张量的数据结构,并且定义了浙西额数学运算。此外还提供了徐国使用程序,用于搞笑序列化Tensor和任意类型,以及其他有用的实用程序。

它有一个CUDA对应物,能够在计算能力 >= 3.0的NVIDIA GPU上运行张量计算

关于张量的操作:

NumPy Bridge:

将Torch Tensor转换为NumPy阵列(反之亦然)是一件轻而易举的事

Torch Tensor和NumPy阵列将共享其底层内存位置(如果Torch Tensor在CPU上),更改一个将改变另一个。

将Torch Tensor转换为NumPy数组

1
2
3
4
5
6
7
8
9
a = torch.ones(5)
print(a)
b = a.numpy()
print(b)
"""
output:
tensor([1., 1., 1., 1., 1.])
[1. 1. 1. 1. 1.]
"""

了解numpy数组的值如何变化

1
2
3
4
5
6
7
8
a.add_(1)
print(a)
print(b)
"""
output:
tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]
"""

将NumPy数组转换为Torch Tensor

了解更改np阵列如何自动更改Torch Tensor

1
2
3
4
5
6
7
8
9
10
11
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
torch.add(a, 1, out=a)
print(a)
print(b)
"""
output:
[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
"""

**注意:**除了CharTensor之外,CPU上的所有Tensor都支持转换为NumPy并返回

CUDA Tensors

可以使用.to方法将张量移动到任何设备上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
x = torch.randn(5, 3)
print(x)
if torch.cuda.is_available():
device = torch.device("cuda") # a CUDA device object
y = torch.ones_like(x, device=device) # directly create a tensor on GPU
x = x.to(device) # or just use strings ``.to("cuda")``
z = x + y
print(z)
print(z.to("cpu", torch.double)) # ``.to`` can also change dtype together!
"""
output:
tensor([[-0.6816, 0.2219, -0.4269],
[-1.1169, -1.7020, 0.6161],
[-0.2312, -0.8429, 0.9232],
[ 0.8789, -0.4840, 0.8420],
[-1.4957, -0.8483, 0.0130]])
tensor([[ 0.3184, 1.2219, 0.5731],
[-0.1169, -0.7020, 1.6161],
[ 0.7688, 0.1571, 1.9232],
[ 1.8789, 0.5160, 1.8420],
[-0.4957, 0.1517, 1.0130]], device='cuda:0')
tensor([[ 0.3184, 1.2219, 0.5731],
[-0.1169, -0.7020, 1.6161],
[ 0.7688, 0.1571, 1.9232],
[ 1.8789, 0.5160, 1.8420],
[-0.4957, 0.1517, 1.0130]], dtype=torch.float64)
"""