PaddlePaddle2.0基础操作
项目描述
此教程旨在介绍PaddlePaddle(一个易用、高效、灵活、可扩展的深度学习框架),根据PaddlePaddle 2.0 rc官方手册编写,介绍了PaddlePaddle中比较常用的一些API以及其基本用法。
数据集介绍
无
项目要求
- 学会使用自动微分(一个强大的实用工具)
- 使用PaddlePaddle实现深度学习中的常用功能
- 使用paddle.io.Dataset处理数据
- 了解PaddlePaddle中的自动混合精度训练
数据准备
无
环境配置/安装
无
PaddlePaddle 介绍
此教程根据 PaddlePaddle 2.0 rc官方手册编写。
此教程旨在介绍PaddlePaddle(一个易用、高效、灵活、可扩展的深度学习框架)
本教程只介绍了paddle中比较常用的一些API以及其基本用法,并不全面,如有任何问题请参考PaddlePaddle 2.0 rc官方手册,也可以百度一下
你将收获以下知识:
- 自动微分是一个强大的实用工具
- 使用PaddlePaddle实现深度学习中的常用函数
- 使用paddle.io.Dataset处理数据
- PaddlePaddle中的自动混合精度训练
Paddle中张量以及张量和numpy数组之间的转换
到目前为止,我们已经使用了不少和numpy数组相关的操作。 作为PaddlePaddle中数据处理的基本元素,张量tensor
和numpy数组中的ndarray
非常相似。
paddle.reshape()
我们可以使用paddle.reshape()
函数来改变Tensors的维度和排列,该函数的使用方法类似numpy.reshape()
函数。
此函数还能根据指定的其他维度自动计算剩下那一个维度的值(参数中可以使用-1来替代),这在操作batch但是batch维度不明确的时候非常实用。
广播语义
符合下面规则的两个tensor是“可广播的”:
每个tensor至少含有一个维度。
当迭代维度大小时,从最后一维开始,该维度的大小相等或者至少有一个等于1又或者其中一个tensor该维度不存在。
计算图
Paddle中tensor
的特殊之处在于它会在后台隐式的建一个计算图,计算图是一种将数学表达式计算过程用图表达出来的方法,算法会按照算术函数的计算顺序将计算图中所有变量的值有效计算出来。
比如这个表达式 e = ( a + b ) ∗ ( b + 1 ) e=(a+b)*(b+1) e=(a+b)∗(b+1) 当 a = 2 , b = 1 a=2, b=1 a=2,b=1时。 在Paddle中我们能画出评估计算图如下图所示"
CUDA 语义
在Paddle中我们可以很简单的在指定的GPU或者CPU上创建tensor。
在Paddle中我们可以很简单的设置数据操作的全局运行设备。
Paddle 是一个会自动计算梯度的框架
我们知道Paddle无时无刻不在使用图,接下来我们展示一些Paddle自动计算梯度的使用案例。
函数 f ( x ) = ( x − 2 ) 2 f(x) = (x-2)^2 f(x)=(x−2)2.
Q: 如何计算 d d x f ( x ) \frac{d}{dx} f(x) dxdf(x) 以及如何计算 f ′ ( 1 ) f'(1) f′(1).
我们可以先计算叶子变量(y
),然后调用backward()
函数,一次性计算出y
的所有所有梯度。
import paddle
import numpy as np
def f(x):
return (x-2)**2
def df(x):
return 2*(x-2)
x = paddle.to_tensor(1.0, stop_gradient=False)
y = f(x)
y.backward()
print('Paddle\'s f\'(x):', x.grad)
print('Cal\'s f\'(x):', df(1))
Paddle's f'(x): [-2.]
Cal's f'(x): -2
该方法也能计算函数的梯度。
例如 w = [ w 1 , w 2 ] T w = [w_1, w_2]^T w=[w1,w2]T
函数 g ( w ) = 2 w 1 w 2 + w 2 cos ( w 1 ) g(w) = 2w_1w_2 + w_2\cos(w_1) g(w)=2w1w2+w2cos(w1)
Q: 计算 ∇ w g ( w ) \nabla_w g(w) ∇wg(w) 并验证 ∇ w g ( [ π , 1 ] ) = [ 2 , π − 1 ] T \nabla_w g([\pi,1]) = [2, \pi - 1]^T ∇wg([π,1])=[2,π−1]T
def g(w):
return 2*w[0]*w[1] + w[1]*paddle.cos(w[0])
def grad_g(w):
return [(2*w[1] - w[1]*paddle.fluid.layers.sin(w[0])).numpy(), (2*w[0] + paddle.fluid.layers.cos(w[0])).numpy()]
w = paddle.to_tensor([np.pi, 1], stop_gradient=False)
z = g(w)
z.backward()
print('Analytical grad g(w)', grad_g(w))
print('Paddle\'s grad g(w)', w.grad)
Analytical grad g(w) [array([2.], dtype=float32), array([5.2831855], dtype=float32)]
Paddle's grad g(w) [2. 5.2831855]
使用梯度
我们得到梯度之后,就可以使用我们最喜欢的优化算法:梯度下降算法了!
函数 f f f (由上面定义并计算).
Q: 如何计算 x x x 让 f f f最小?"
- 对z调用
backward()
,飞桨即可以自动计算x和y的梯度,并且将他们存进grad
属性中。 - 飞桨默认会释放反向计算图。如果在
backward()
之后继续添加OP,需要将backward()中的retain_graph
参数设置为True,此时之前的反向计算图会保留。 - 因为
backward()
会累积梯度,所以飞桨还提供了clear_grad()函数来清除当前Tensor的梯度。
def f(x):
return (x-2)**2
x = paddle.to_tensor(20.0, stop_gradient=False)
lr = 0.2
for i in range(15):
y = f(x)
y.backward(retain_graph=True)
print(f'x={x.numpy()}, y(x)={f(x).numpy()}, y\'(x)={x.grad}')
x = x - paddle.to_tensor(lr*x.grad)
y.clear_grad()
x=[20.], y(x)=[324.], y'(x)=[36.]
x=[12.799999], y(x)=[116.639984], y'(x)=[21.6]
x=[8.48], y(x)=[41.990395], y'(x)=[12.959999]
x=[5.8879995], y(x)=[15.116541], y'(x)=[7.775999]
x=[4.3328], y(x)=[5.441955], y'(x)=[4.6656]
x=[3.39968], y(x)=[1.9591038], y'(x)=[2.7993598]
x=[2.839808], y(x)=[0.70527744], y'(x)=[1.679616]
x=[2.5038848], y(x)=[0.25389984], y'(x)=[1.0077696]
x=[2.302331], y(x)=[0.09140402], y'(x)=[0.60466194]
x=[2.1813986], y(x)=[0.03290546], y'(x)=[0.36279726]
x=[2.1088393], y(x)=[0.01184599], y'(x)=[0.21767856]
x=[2.0653036], y(x)=[0.00426456], y'(x)=[0.13060714]
x=[2.0391822], y(x)=[0.00153524], y'(x)=[0.07836437]
x=[2.0235093], y(x)=[0.00055269], y'(x)=[0.04701853]
x=[2.0141056], y(x)=[0.00019897], y'(x)=[0.02821112]
线性回归
接下来,我们构造一些数据,并降低损失函数在这些数据上的计算值。
我们实现梯度下降方法来解决线性回归任务。
注意数据维度
Paddle有很多处理batch数据的操作,按照约定俗成的规则,batch数据的维度是 ( N , d ) (N, d) (N,d),其中 N N N是batch的大小。
# make a simple linear dataset with some noise
d = 2
n = 50
X = paddle.randn(shape=[n, d]) # 返回符合标准正态分布(均值为0,标准差为1的正态随机分布)
true_w = paddle.to_tensor([[-1.0], [2.0]])
# 在python 3.5以后,@是一个操作符,表示矩阵-向量乘法
Y = X @ true_w + paddle.randn([n, 1]) * 0.1 # add noise y = w1*x1 + w2*x2
print('X shape', X.shape)
print('Y shape', Y.shape)
print('w shape', true_w.shape)
%matplotlib inline
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib as mpl
from matplotlib import cm
mpl.rcParams['legend.fontsize'] = 20 # mpl模块载入的时候加载配置信息存储在rcParams变量中,rc_params_from_file()函数从文件加载配置信息
font = {
'color': 'b',
'style': 'oblique',
'size': 20,
'weight': 'bold'
}
fig = plt.figure(figsize=(16, 12)) #参数为图片大小
ax = fig.gca(projection='3d') # get current axes,且坐标轴是3d的
ax.set_aspect('equal') # 坐标轴间比例一致
ax.scatter(X.numpy()[:, 0], X.numpy()[:, 1], Y.numpy())
plt.show()
X shape [50, 2]
Y shape [50, 1]
w shape [2, 1]
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/numpy/lib/type_check.py:546: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead
'a.item() instead', DeprecationWarning, stacklevel=1)
正确性检查
为了验证Paddle中梯度计算结果的正确性,我们可以调用梯度计算来计算RSS的梯度:
∇ w L R S S ( w ; X ) = ∇ w 1 n