PyTorch
的安装可以到官网 https://pytorch.org/,选择适合自己机器以及安装方式,执行对应的命令即可。
除了安装 PyTorch
之外,建议也安装 torchvision
包。torchvision
包是服务于 PyTorch
深度学习框架的,用来生成图片、视频数据集和一些流行的模型类和预训练模型。
简单来说,torchvision
由 torchvision.datasets
、torchvision.models
、torchvision.transforms
、torchvision.utils
四个模块组成。
PyTorch
中的张量(Tensor
)类似 NumPy
中的 ndarrays
,之所以称之为 Tensor
的另一个原因是它可以运行在 GPU
中,以加速运算。
PyTorch
中的 Tensor
也有自己的数据类型定义方式,常用的如下。
1. Tensor 基本数据类型
1.1 torch.FloatTensor
用于生成数据类型为浮点型的 Tensor
,传递给 torch.FloatTensor
的参数可以是一个列表,也可以是一个维度值。
import torch
a = torch.FloatTensor(2, 3)
b = torch.FloatTensor([1, 2, 3, 4])
输出结果:
tensor([[2.3489e-37, 4.5835e-41, 2.3489e-37],
[4.5835e-41, 4.4842e-44, 0.0000e+00]])
tensor([1., 2., 3., 4.])
可以看到,打印输出的两组变量数据类型都显示为浮点型,不同的是,前面的一组是按照我们指定的维度随机生成的浮点型 Tensor
而另外一组是按我们给定的列表生成的浮点型 Tensor
。
1.2 torch.IntTensor
用于生成数据类型为整型的 Tensor
。传递给 torch.IntTensor
的参数可以是一个列表,也可以是一个维度值。
import torch
a = torch.IntTensor(2, 3)
b = torch.IntTensor([1, 2, 3, 4])
输出结果:
tensor([[1491430264, 32561, 1491430264],
[ 32561, 808464432, 808463205]], dtype=torch.int32)
tensor([1, 2, 3, 4], dtype=torch.int32)
可以看出输出的数据类型都为整形(torch.int32
)
1.3 torch.rand
用于生成数据类型为浮点型且维度指定的随机 Tensor
,和在 NumPy
中使用 numpy.rand
生成随机数的方法类似,随机生成的浮点数据在 0~1 区间均匀分布。
import torch
a = torch.rand(2, 3)
输出结果:
tensor([[0.6882, 0.4118, 0.2646],
[0.0583, 0.2187, 0.8093]])
1.4 torch.randn
用于生成数据类型为浮点型且维度指定的随机 Tensor
,和在 NumPy
中使用 numpy.randn
生成随机数的方法类似,随机生成的浮点数的取值满足均值为 0、方差为 1 的正态分布。
import torch
a = torch.randn(2, 3)
输出结果:
tensor([[ 0.2214, -0.0139, -0.0720],
[ 0.2548, -1.3364, 0.3924]])
1.5 torch.arange
用于生成数据类型为浮点型且自定义起始范围和结束范围的 Tensor
,所以传递给 torch.arange
的参数有三个,分别是范围的起始值、范围的结束值和步长,其中,步长用于指定从起始值到结束值的每步的数据间隔。
import torch
a = torch.arange(1, 10, 2)
输出结果:
tensor([1, 3, 5, 7, 9])
1.6 torch.zeros
用于生成数据类型为浮点型且维度指定的 Tensor
,不过这个浮点型的 Tensor
中的元素值全部为 0
import torch
a = torch.zeros(2, 3, dtype=torch.int8)
print a
输出结果:
tensor([[0, 0, 0],
[0, 0, 0]], dtype=torch.int8)
2. Tensor 基本运算
2.1 torch.abs
将参数传递到 torch.abs
后返回输入参数的绝对值作为输出,输入参数必须是一个 Tensor
数据类型的变量。
import torch
a = torch.randn(2, 3)
print a
b = torch.abs(a)
print b
输出结果:
tensor([[ 0.4873, 0.8172, 0.2003],
[ 0.6815, 1.5656, -0.8303]])
tensor([[0.4873, 0.8172, 0.2003],
[0.6815, 1.5656, 0.8303]])
2.2 torch.add
将参数传递到 torch.add
后返回输入参数的求和结果作为输出,输入参数既可以全部是 Tensor
数据类型的变量,也可以一个是 Tensor
数据类型的变量,另一个是标量。
a = torch.ones([2, 3])
print a
b = torch.add(a, 10)
print b
c = torch.randn([2, 3])
print c
d = torch.add(a, c)
print d
输出结果:
tensor([[1., 1., 1.],
[1., 1., 1.]])
tensor([[11., 11., 11.],
[11., 11., 11.]])
tensor([[ 0.4276, 0.4618, -0.9449],
[-1.4758, -1.3118, -0.2859]])
tensor([[ 1.4276, 1.4618, 0.0551],
[-0.4758, -0.3118, 0.7141]])
2.3 torch.clamp
对输入参数按照自定义的范围进行裁剪,最后将参数裁剪的结果作为输出。所以输入参数一共有三个,分别是需要进行裁剪的 Tensor
数据类型的变量、裁剪的上边界和裁剪的下边界。
具体的裁剪过程是:使用变量中的每个元素分别和裁剪的上边界及裁剪的下边界的值进行比较,如果元素的值小于裁剪的下边界的值,该元素就被重写成裁剪的下边界的值;同理,如果元素的值大于裁剪的上边界的值,该元素就被重写成裁剪的上边界的值。
a = torch.randn(2,3)
print a
b = torch.clamp(a, -0.1, 0.1)
print b
输出结果:
tensor([[-1.0129, -1.3094, 0.4644],
[ 1.0542, -0.5259, -0.3575]])
tensor([[-0.1000, -0.1000, 0.1000],
[ 0.1000, -0.1000, -0.1000]])
2.4 torch.div
将参数传递到 torch.div
后返回输入参数的求商结果作为输出,同样,参与运算的参数可以全部是 Tensor
数据类型的变量,也可以是 Tensor
数据类型的变量和标量的组合。
a = torch.IntTensor([2,4,6,8,10])
print a
b = torch.div(a, 2)
print b
c = torch.IntTensor([2,4,6,8,10])
d = torch.div(a, c)
print d
输出结果:
tensor([ 2, 4, 6, 8, 10], dtype=torch.int32)
tensor([1, 2, 3, 4, 5], dtype=torch.int32)
tensor([1, 1, 1, 1, 1], dtype=torch.int32)
2.5 torch.mul
将参数传递到 torch.mul
后返回输入参数求积的结果作为输出,参与运算的参数可以全部是 Tensor
数据类型的变量,也可以是 Tensor
数据类型的变量和标量的组合。
a = torch.IntTensor([2,4,6,8,10])
print a
b = torch.mul(a, 2)
print b
c = torch.IntTensor([2,4,6,8,10])
d = torch.mul(a, c)
print d
输出结果:
tensor([ 2, 4, 6, 8, 10], dtype=torch.int32)
tensor([ 4, 8, 12, 16, 20], dtype=torch.int32)
tensor([ 4, 16, 36, 64, 100], dtype=torch.int32)
2.6 torch.pow
将参数传递到 torch.pow
后返回输入参数的求幂结果作为输出,参与运算的参数可以全部是 Tensor
数据类型的变量,也可以是 Tensor
数据类型的变量和标量的组合。
a = torch.IntTensor([2,4,6,8,10])
print a
b = torch.pow(a, 2)
print b
c = torch.IntTensor([3,3,3,3,3])
d = torch.pow(a, c)
print d
输出结果:
tensor([ 2, 4, 6, 8, 10], dtype=torch.int32)
tensor([ 4, 16, 36, 64, 100], dtype=torch.int32)
tensor([ 8, 64, 216, 512, 1000], dtype=torch.int32)
2.7 torch.mm
将参数传递到 torch.mm
后返回输入参数的求积结果作为输出,不过这个求积的方式和之前的 torch.mul
运算方式不太一样, torch.mm
运用矩阵之间的乘法规则进行计算,所以被传入的参数会被当作矩阵进行处理,参数的维度自然也要满足矩阵乘法的前提条件,即前一个矩阵的行数必须和后一个矩阵的列数相等,否则不能进行计算。
a = torch.IntTensor([[1,2,3], [4,5,6]])
print a
b = torch.IntTensor([[1,2], [4,5], [7, 8]])
print b
c = torch.mm(a, b)
print c
输出结果:
tensor([[1, 2, 3],
[4, 5, 6]], dtype=torch.int32)
tensor([[1, 2],
[4, 5],
[7, 8]], dtype=torch.int32)
tensor([[30, 36],
[66, 81]], dtype=torch.int32)
2.8 torch.mv
将参数传递到 torch.mv
后返回输入参数的求积结果作为输出,torch.mv
运用矩阵与向量之间的乘法规则进行计算,被传入的参数中的第 1 个参数代表矩阵,第 2 个参数代表向量,顺序不能颠倒。
a = torch.IntTensor([[1,0,0], [0,0,1]])
print a
b = torch.IntTensor([3,3,3])
print b
c = torch.mv(a, b)
print c
输出结果:
tensor([[1, 0, 0],
[0, 0, 1]], dtype=torch.int32)
tensor([3, 3, 3], dtype=torch.int32)
tensor([3, 3], dtype=torch.int32)
3. Tensor 与 NumPy
Tensor
可以与 NumPy
相互转化。
- Tensor 转化为 NumPy
In[2]: import torch
In[3]: a = torch.ones(5)
In[4]: a
Out[4]: tensor([1., 1., 1., 1., 1.])
In[5]: b = a.numpy()
In[6]: b
Out[6]: array([1., 1., 1., 1., 1.], dtype=float32)
- NumPy 转化为 Tensor
In[7]: import numpy as np
In[8]: a = np.ones(5)
In[9]: a
Out[9]: array([1., 1., 1., 1., 1.])
In[10]: b = torch.from_numpy(a)
In[11]: b
Out[11]: tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
值得注意的是,Torch 中的 Tensor
和 NumPy 中的 Array
共享内存位置,一个改变,另一个也同样改变。注意使用的是 b.add_()
。
In[15]: b.add_(1)
Out[15]: tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
In[16]: a
Out[16]: array([2., 2., 2., 2., 2.])
In[17]: b
Out[17]: tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
下面看使用 b.add()
发现 b 并没有改变。
In[18]: b.add(2)
Out[18]: tensor([4., 4., 4., 4., 4.], dtype=torch.float64)
In[19]: a
Out[19]: array([2., 2., 2., 2., 2.])
In[20]: b
Out[20]: tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
b.add_()
和 b.add()
的区别:
任何操作符都固定地在前面加上 _
来表示替换。例如:y.copy_(x)
,y.t_()
,都将改变 y。
4. Tensor 用 GPU 加速
Tensor
可以被移动到任何设备中,例如 GPU
以加速运算,使用 .to
方法即可。
x = torch.randn(1)
if torch.cuda.is_available():
device = torch.device("cuda")
y = torch.ones_like(x, device=device) # directly create a tensor on GPU
x = x.to(device)
z = x + y
print(z)
print(z.to("cpu", torch.double))
输出:
tensor([ 2.0718], device='cuda:0')
tensor([ 2.0718], dtype=torch.float64)