前言
本文旨在介绍Pytorch的入门知识。在第一部分,我们简单介绍了当前的主流深度学习框架,并介绍了选择Pytorch的理由及其安装方法。在第二部分,我们给出了Pytorch的一个简单入门,包括张量的使用,如何借助Cuda在Pytorch中使用GPU进行计算,以及Pytorch中的求导运算等。最后在第三部分,我们对文中讲到的关键操作进行了总结。
1. 深度学习框架的简单介绍
1.1 主流深度学习框架
PyTorch是一个基于Python的库,用来提供一个具有灵活性的深度学习开发平台。PyTorch的工作流程非常接近Python的科学计算库numpy。
当前主流的深度学习框架有两种,一种是以Tensorflow为代表的静态图框架,另一种就是以Pytorch为代表的动态图框架。静态图框架要求我们先定义好模型结构再运行模型,而动态图框架意味着程序将按照命令顺序执行,这种机制使得我们调试更加容易。用编程语言做类比,Tensorflow更像C++,而Pytorch更像Python。
Pytorch在近年来发展迅速,下图对比了Pytorch和Tensorflow在论文中的使用情况:
从图中可以看到,2019年1月到6月底,在arXiv.org上发表的论文中,提及TensorFlow和PyTorch的数量相差无几,PyTorch仅稍稍落后。但最关键的在于增长速度:与2018年1月到6月相比,PyTorch增长了194%,相比之下,TensorFlow的增长幅度仅为23%。从当前的数据可以看出,Pytorch因其简单易用而越来越受到大家的青睐。
1.2 为什么选择Pytorch
首先不得不提Tensorflow的反人类设计。Tensorflow的逻辑有两种,一种是建graph时的逻辑,另一种是运行时的逻辑。当要实现的算法比较复杂的时候就会很麻烦,一不小心就会出错。
其次,Pytorch可以和Python无缝衔接,学习成本很低,给人的直观感受就是用着顺手、舒服。
最后,Pytorch代码简洁易懂。因此,作为深度学习的入门工具来说,Pytorch再合适不过了。
1.3 Pytorch 的安装
Pytorch 安装起来十分简单,只要三步即可完成,
(1) 进入 Pytorch 官网
(2) 选择合适的操作系统和版本</br>
在YourOs一栏选择你的操作系统。在CUDA一栏是选择是否安装GPU版本,如果要安装GPU版本,首先要安装上CUDA,然后选择CUDA的版本。
(3) 拷贝 Run this Command 一栏中的命令
将命令拷贝到终端执行,即可自动安装。
2. Pytorch 的简单入门
2.1 张量的概念
简单的说,张量概念是矢量概念和矩阵概念的推广。标量是零阶张量,矢量是一阶张量,矩阵(方阵)是二阶张量,而三阶张量则好比是立体矩阵,更高阶的张量用图形无法表达。机器学习中的数据往往以张量形式表达。
2.2 张量的创建
Pytorch 中张量的创建主要有以下几种形式:
(1) torch.empty 函数
import torch
x = torch.empty(5,3) #创建一个5*3的矩阵
print(x)
y = torch.empty(2,2,2) #创建一个2*2*2的张量
print(y)
输出:
tensor([[1.1210e-44, 0.0000e+00, 0.0000e+00],
[0.0000e+00, 0.0000e+00, 0.0000e+00],
[0.0000e+00, 0.0000e+00, 0.0000e+00],
[0.0000e+00, 0.0000e+00, 0.0000e+00],
[0.0000e+00, 0.0000e+00, 0.0000e+00]])
tensor([[[8.4078e-45, 0.0000e+00],
[1.2708e-31, 1.4013e-45]],
[[0.0000e+00, 0.0000e+00],
[0.0000e+00, 0.0000e+00]]])
empty函数返回填充有未初始化数据的张量,在我们不需要初始化具有特定分布的数据时可以使用。
(2) torch.rand 函数
x = torch.rand(5,3) #创建一个5*3的矩阵
print(x)
y = torch.rand(2,2,2) #创建一个2*2*2的张量
print(y)
输出:
tensor([[0.1413, 0.5294, 0.6538],
[0.4040, 0.0293, 0.7876],
[0.8263, 0.2070, 0.5927],
[0.4749, 0.7163, 0.4874],
[0.2791, 0.3276, 0.1504]])
tensor([[[0.2636, 0.9148],
[0.9117, 0.9742]],
[[0.4946, 0.6069],
[0.5841, 0.6050]]])
torch.rand 建立一个张量,默认将数据初始化为[0,1)的均匀分布。类似的函数有 torch.randn 将数据初始化为均值为0,方差为1的标准正态分布;torch.normal 可以生成指定均值和方差的正态分布。
(3) torch.ones 函数
x = torch.ones(5,3)
print(x)
输出:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
torch.ones 建立一个张量,并将值初始化为1。
(4) torch.zeros 函数
x = torch.zeros(5,3)
print(x)
输出:
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
torch.zeros 建立一个张量,并将矩阵值初始化为0。
(5) 直接从数组建立一个张量
x = torch.tensor([2,3,4,5])
print(x)
输出:
tensor([2, 3, 4, 5])
(6) new_ones,new_zeros,new_empty
x = torch.zeros(2,3,dtype=torch.int32) #新建一个张量
print(x)
y = x.new_ones(1,2) #从x中创建一个新的张量,数据类型不变
print(y)
输出:
tensor([[0, 0, 0],
[0, 0, 0]], dtype=torch.int32)
tensor([[1, 1]], dtype=torch.int32)
这些函数可以从已有张量建立一个新的张量。
(7) ones_like,zeros_like,empty_like
x = torch.ones(4,4)
print(x)
y = torch.rand_like(x)
print(y)
输出:
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
tensor([[0.5023, 0.7911, 0.3639, 0.3315],
[0.8617, 0.0388, 0.1612, 0.2071],
[0.1755, 0.3988, 0.8381, 0.5835],
[0.9588, 0.3950, 0.8371, 0.5337]])
这些函数可以创建一个和目标张量形状相同的张量。
2.3 张量的运算
张量常用的计算操作主要有张量的加法,张量乘法,张量形状改变。
(1) 张量加法
主要有三种方式:
- x+y
- torch.add(x,y,out=result)
- y.add_(x)是将x增加到y上并改变y的值,运算符加“_”是将运算结果赋值给左边的变量。
y = torch.rand(3,5)
x = torch.ones(5)
result = torch.empty(3,5)
print(x+y) #第一种方式
print(torch.add(x,y,out=result)) #第二种方式
y.add_(x) #第三种方式
print(y)
输出:
tensor([[1.8442, 1.9501, 1.8182, 1.0880, 1.7674],
[1.5743, 1.5252, 1.8656, 1.2426, 1.4136],
[1.9056, 1.3625, 1.8482, 1.6156, 1.7287]])
tensor([[1.8442, 1.9501, 1.8182, 1.0880, 1.7674],
[1.5743, 1.5252, 1.8656, 1.2426, 1.4136],
[1.9056, 1.3625, 1.8482, 1.6156, 1.7287]])
tensor([[1.8442, 1.9501, 1.8182, 1.0880, 1.7674],
[1.5743, 1.5252, 1.8656, 1.2426, 1.4136],
[1.9056, 1.3625, 1.8482, 1.6156, 1.7287]])
(2) 张量乘法
- mm 只能是矩阵乘法,也就是输入的两个tensor维度只能是(n,m)和(m,p)
- bmm 是两个三维张量相乘,两个tensor维度是(b,m,p)和(b,p,n),b一般是batch_size
- matmul 可以进行张量乘法,输入可以是高维的
mm 操作示例:
x = torch.ones(3,2)
y = torch.ones(2,3)
x.mm(y)
输出:
tensor([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
bmm 操作示例:
x = torch.ones(2,3,2)
y = torch.ones(2,2,3)
x.bmm(y)
输出:
tensor([[[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]],
[[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]]])
(3) Resize 操作
view函数实现了torch中张量的Resize操作。
x = torch.rand(2,2)
y = x.view(-1) # 从x生成一维向量,长度自动计算
print(y)
z = y.view(2,-1) #从y生成行数为2的矩阵,列的长度自动计算
print(z)
输出:
tensor([[0.2995, 0.2133],
[0.6413, 0.7581]])
tensor([0.2995, 0.2133, 0.6413, 0.7581])
tensor([[0.2995, 0.2133],
[0.6413, 0.7581]])
Resize操作在很多时候都有用,例如我们进行图像识别时,卷积层是n个方阵,要将卷积核输出为类别,通常是先将它们展成一维,再带入softmax函数计算进行分类。
(4) 转置操作 t.()
x = torch.empty(3,4)
print(x)
print(x.t())
输出:
tensor([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
2.4 Pytorch 中张量和 NumPy Array 的相互转化
在Torch Tensor和NumPy array之间相互转化非常容易。Torch Tensor和NumPy array共享内存,所以改变其中一项也会改变另一项。
把Torch Tensor转变成NumPy Array:
a = torch.ones(5)
print(a)
b = a.numpy()
print(b)
输出:
tensor([1., 1., 1., 1., 1.])
[1. 1. 1. 1. 1.]
把上面的a增加1:
a.add_(1)
print(a)
print(b)
输出:
tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]
把NumPy Array转变成Torch Tensor:
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
print(a)
print(b)
np.add(a,1,out=a)
print(a)
print(b)
输出:
[1. 1. 1. 1. 1.]
tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
2.5 Pytorch 中使用GPU计算
在Pytorch 中,使用GPU计算是很方便的,可以在创建张量的时候指定张量计算位置,也可以将张量转移到GPU上计算。
if torch.cuda.is_available():
device = torch.device("cuda")
y = torch.ones(2,3,device=device) #在GPU上创建张量
x = torch.empty(4,5)
x.to(device) #将张量x转移到GPU上
z = x+y
2.6 Pytorch 中的求导运算
我们在进行模型训练的时候,常常需要用梯度下降法,所以求导是很重要的,在Pytorch中,求导非常方便。例如对Y = WX + B,我们计算Y关于W和B的导数。不难发现,Y关于W的导数是X的转置,Y关于B的导数是1。
操作示例:
w = torch.zeros((3,1),requires_grad=True) # 声明W的形状,以及可导性(默认不可导)
x = torch.ones(1,3) # 声明X形状
b = torch.tensor([1.],requires_grad=True)
y = x.mm(w) + b # Y = wx + b
y.backward() # 求导操作
print(w.grad)
print(b.grad)
输出:
tensor([[1.],
[1.],
[1.]])
tensor([1.])
3. 总结
本文我们简单介绍了Pytorch基本知识,包括安装方法,基本的张量操作。张量操作我们主要说明了Pytorch中张量的几种创建方法,张量的运算。然后我们学习了如何在GPU上进行计算,最后我们介绍了Pytorch上的求导操作。
最后,要记住以下重要操作哦:
- 张量创建
- torch.ones(), torch.empty(), torch.zeros()
- x.new_ones(), x.new_rand()..
- torch.empty_like(),torch.zeros_like()
- 张量操作
- 加法 torch.add(x,y,result=z),add_(),"+"
- 乘法 mm(),bmm(),matmul()
- 和numpy的相互转化 a.numpy(), torch.from_numpy()
- GPU计算
- 记住函数 torch.cuda.is_available(),
- torch.device("cuda")
- to(device)
- 求导运算
- 记得在创建张量时加一个requires_grad=True
- loss.backward()函数
- 导数在W.grad中取得
下期我们将以房价预测为例,来搭建一个简单的线性模型!