PyTorch上手及其常用API总结

PyTorch介绍

PyTorch

Torch 是一个使用Lua 语言的神经网络库,而PyTorch是Torch在Python的衍生。

PyTorch是一个基于python的科学计算包。本质上是Numpy的代替者,支持GPU、带有高级功能,可以用来搭建和训练深度神经网络;是一个深度学习框架,速度更快,弹性更好。

PyTorch和Tensorflow

Tensorflow 类似一个嵌入Python的编程语言。写的Tensorflow代码会被Python编译成一张计算图,然后由TensorFlow执行引擎运行。Tensorflow有一些额外的概念需要学习,上手时间慢。

对比参考这篇文章PyTorch还是Tensorflow 。下面是结论。后续再补充详细内容。

PyTorch更有利于研究人员、爱好者、小规模项目等快速搞出原型,易于理解。而TensorFlow更适合大规模部署,特别是需要跨平台和嵌入式部署时。

PyTorch和Tensorflow对比如下

PyTORCH Tensorflow
动静态 建立的神经网络是动态的 建立静态计算图
代码难度 易于理解,好看一些。有弹性 底层代码难以看懂
工业化 好上手 高度工业化

数据操作

Tensor

创建Tensor

Tensor实际上是一个数据矩阵,PyTorch处理的单位就是一个一个的Tensor。下面是一些创建方法

1
2
3
4
5
6
7
8
9
10
11
12
13
import torch

# 1. 未初始化,都是0
x = torch.Tensor(5, 3)
# 2. 随机初始化
x = torch.rand(5, 3)
# 3. 传递参数初始化
x = torch.Tensor([1, 2])
# 4. 通过Numpy初始化
a = np.ones(5)
b = torch.from_numpy(a)
# 5. 获取size,返回一个tuple [5, 3]
print x.size()

Tensor也可以通过Numpy来进行创建,或者从Tensor得到一个Numpy。

1
2
3
4
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
c = b.numpy()

Tensor操作

Tensor的运算也很简单,一般的四则运算都是支持的。

1
2
3
4
5
6
7
8
9
10
11
12
x = torch.rand(5, 3)
y = torch.rand(5, 3)

# 1. 直接相加
z = x + y
# 2. torch相加
z = torch.add(x, y)
# 3. 传递参数返回结果
result = torch.rand(5, 3)
torch.add(x, y, out = result)
# 4. 加到自身去,自身y会改变
y.add_(x)

其中所有类似于x.add_(y)的操作都会改变自己x,如x.copy_(y)x.t_()

对于Tensor可以像Numpy那样索引和切片

改变Tensor和Numpy

改变Tensor后,对应的Numpy也会发生改变

1
2
3
4
5
6
7
a = torch.ones(5)
b = a.numpy()
# 改变a
a.add_(1)
# b也会改变
print a # 22222
print b # 22222

CUDA Tensors

使用GPU很简单,只需使用.cuda就可以了

1
2
3
4
if torch.cuda.is_available():
x = x.cuda()
y = y.cuda()
x + y

Variable

在神经网络中,最重要的是torch.autograd这个包,而其中最重要的一个类就是Variable

本质上Variable和Tensor没有区别,不过Variable会放入一个计算图,然后进行前向传播,反向传播和自动求导。这也是PyTorch和Numpy不同的地方。

Variable由data, grad, creator 三部分组成。

  • data: 包装的Tensor,即数据
  • grad: 方向传播的梯度缓冲区
  • creator: 得到这个Variable的操作,如乘法加法等等。

用一个Variable进行计算,返回的也是一个同类型的Variable。

梯度计算例子

线性计算\(z= 2 \cdot x + 3 \cdot y + 4\) ,求\(\frac{ \partial z}{\partial x}\)\(\frac{ \partial z}{\partial y}\)

1
2
3
4
5
6
7
8
9
10
11
12
import torch
from torch.autograd import Variable
# 1. 准备式子
# 默认求导是false
x = Variable(torch.Tensor([2]), requires_grad = True)
y = Variable(torch.Tensor([3]), requires_grad = True)
z = 2 * x + 3 * y + 4
# 2. z对x和y进行求导
z.backward()
# 3. 获得z对x和y的导数
print x.grad.data # 2
print y.grad.data # 3

复杂计算$ y = x + 2$, \(z = y * y * 3\)\(o = avg(z)\) ,求\(\frac{dz}{dx}\)

1
2
3
4
5
6
7
x = Variable(torch.ones(2, 2), requires_grad = True)
y = x + 2
z = y * y * 3
out = z.mean()
out.backward()
# d(out)/dx
print x.grad

传递梯度

1
2
3
4
5
x = Variable(torch.Tensor([2]), requires_grad = True)
y = x + 2
gradients = torch.FloatTensor([0.01, 0.1, 1])
y.backward(gradients)
print x.grad.data

一些常用的API总结

1
2
3
4
5
6
7
8
9
10
11
12
13
x = torch.Tensor([2, 2])
# 随机创建数字
x = torch.randn(3)
x = torch.randn(3, 3)
# 求平均值
x.mean()
# 范数
x.norm()
# torch view。数据相同,改变形状。得到一个Tensor
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(2, 2, 4)
z = x.view(2, 2, -1) # 最后-1,会自己适配

神经网络