Paddle 文档阅读笔记
一、说明
深度学习入门中,最近在看paddle的官方文档,为了防止看了就忘,就把自己认为重要的记录下来,方便日后查阅,边学边修改。
二、基本概念
1、Tensor概念介绍
tensor 即张量,Paddle 也使用tensor来表示数据,可以理解为多维数组。
维度 | 名称 |
---|---|
0 | 标量scalar |
1 | 向量vector |
2 | 矩阵matrix |
3 | 3阶张量 3D array |
4 | 4阶张量 4D array |
(1)tensor 的创建
首先导入paddle库
import paddle
使用paddle.to_tensor()生成tensor
ndim_2_tensor = paddle.to_tensor([[3,5,6],[1,8,5]])
使用Numpy array 创建
import numpy
ndim_2_tensor = paddle.to_tensor(numpy.array([[3,5,6],[1,8,5]]))
(2)将Tensor转化为Numpy array
使用Tensor.numpy()
ndim_2_tensor.numpy()
(3)创建指定shape的paddle API
paddle.zeros([m, n]) # 创建数据全为0,shape为[m, n]的Tensor
paddle.ones([m, n]) # 创建数据全为1,shape为[m, n]的Tensor
paddle.full([m, n], 10) # 创建数据全为10,shape为[m, n]的Tensor
paddle.arange(start, end, step) # 创建从start到end,步长为step的Tensor
paddle.linspace(start, end, num) # 创建从start到end,元素个数固定为num的Tensor
(4)Tensor 的 shape
1.shape : 每个维度的元素数量
2.ndim : tensor 的维度数量
3.axis或者dimension:指tensor某个特定的维度(这里还不太理解)
4.size:指tensor中全部元素的个数
print("Data Type of every element:", ndim_4_tensor.dtype)
print("Number of dimensions:", ndim_4_tensor.ndim)
print("Shape of tensor:", ndim_4_tensor.shape)
print("Elements number along axis 0 of tensor:", ndim_4_tensor.shape[0])
print("Elements number along the last axis of tensor:", ndim_4_tensor.shape[-1])
运行结果
Data Type of every element: VarType.FP32
Number of dimensions: 4
Shape of tensor: [2, 3, 4, 5]
Elements number along axis 0 of tensor: 2
Elements number along the last axis of tensor: 5
(5)使用paddle.reshape方法重新定义tensor的shape
ndim_2_tensor = paddle.to_tensor([[[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, 28, 29, 30]]])
print("the shape of ndim_3_tensor:", ndim_3_tensor.shape)
运行结果
the shape of ndim_3_tensor: [3, 2, 5]
paddle.reshape()
ndim_3_tensor = paddle.reshape(ndim_2_tensor,[0,5,-1])#0表示不变,-1表示这个维度的值是从Tensor的元素总数和剩余维度推断出来的。
得到的新tensor的形状如为[3,5,2]
(6)使用paddle.cast()改变dype
Tensor的数据类型,可以通过 Tensor.dtype 来查看,dtype支持:‘bool’,‘float16’,‘float32’,‘float64’,‘uint8’,‘int8’,‘int16’,‘int32’,‘int64’。
float32_tensor = paddle.to_tensor(1.0)
float64_tensor = paddle.cast(float32_tensor, dtype='float64')
(7)通过place来指定其分配的设备位置,可支持的设备位置有三种:CPU/GPU/固定内存
cpu_tensor = paddle.to_tensor(1, place=paddle.CPUPlace())
gpu_tensor = paddle.to_tensor(1, place=paddle.CUDAPlace(0))
pin_memory_tensor = paddle.to_tensor(1, place=paddle.CUDAPinnedPlace())
(8)查看一个Tensor的name可以通过Tensor.name属性
默认地,在每个Tensor创建时,Paddle会自定义一个独一无二的name。
print("Tensor name:", paddle.to_tensor(1).name)
Tensor name: generated_tensor_0
2、Tensor 的操纵
(1)索引和切片
import paddle
import numpy
#二维tensor的切片和索引
ndim_2_tensor = paddle.to_tensor([[0,1,2,3],[4,5,6,7],[8,9,10,11]])
print('first row:',ndim_2_tensor[0,:].numpy())
print('last row:',ndim_2_tensor[-1,:].numpy())
print('first column:',ndim_2_tensor[:,0].numpy())
print('last column:',ndim_2_tensor[:,-1].numpy())
print('first row and second column:',ndim_2_tensor[0,1].numpy())
结果:
first row: [0 1 2 3]
last row: [ 8 9 10 11]
first column: [0 4 8]
last column: [ 3 7 11]
first row and second column: [1]
(2)数学运算符
下图中的x,y均为tensor
x.abs() #逐元素取绝对值
x.ceil() #逐元素向上取整
x.floor() #逐元素向下取整
x.round() #逐元素四舍五入
x.exp() #逐元素计算自然常数为底的指数
x.log() #逐元素计算x的自然对数
x.reciprocal() #逐元素求倒数
x.square() #逐元素计算平方
x.sqrt() #逐元素计算平方根
x.sin() #逐元素计算正弦
x.cos() #逐元素计算余弦
x.add(y) #逐元素相加
x.subtract(y) #逐元素相减
x.multiply(y) #逐元素相乘
x.divide(y) #逐元素相除
x.mod(y) #逐元素相除并取余
x.pow(y) #逐元素幂运算
x.max() #指定维度上元素最大值,默认为全部维度
x.min() #指定维度上元素最小值,默认为全部维度
x.prod() #指定维度上元素累乘,默认为全部维度
x.sum() #指定维度上元素的和,默认为全部维度
在paddle中下列等价
x + y -> x.add(y) #逐元素相加
x - y -> x.subtract(y) #逐元素相减
x * y -> x.multiply(y) #逐元素相乘
x / y -> x.divide(y) #逐元素相除
x % y -> x.mod(y) #逐元素相除并取余
x ** y -> x.pow(y) #逐元素幂运算
(3)逻辑运算符
x.isfinite() #判断tensor中元素是否是有限的数字,即不包括inf与nan
x.equal_all(y) #判断两个tensor的全部元素是否相等,并返回shape为[1]的bool Tensor
x.equal(y) #判断两个tensor的每个元素是否相等,并返回shape相同的bool Tensor
x.not_equal(y) #判断两个tensor的每个元素是否不相等
x.less_than(y) #判断tensor x的元素是否小于tensor y的对应元素
x.less_equal(y) #判断tensor x的元素是否小于或等于tensor y的对应元素
x.greater_than(y) #判断tensor x的元素是否大于tensor y的对应元素
x.greater_equal(y) #判断tensor x的元素是否大于或等于tensor y的对应元素
x.allclose(y) #判断tensor x的全部元素是否与tensor y的全部元素接近,并返回shape为[1]的bool Tensor
下列等价:
x == y -> x.equal(y) #判断两个tensor的每个元素是否相等
x != y -> x.not_equal(y) #判断两个tensor的每个元素是否不相等
x < y -> x.less_than(y) #判断tensor x的元素是否小于tensor y的对应元素
x <= y -> x.less_equal(y) #判断tensor x的元素是否小于或等于tensor y的对应元素
x > y -> x.greater_than(y) #判断tensor x的元素是否大于tensor y的对应元素
x >= y -> x.greater_equal(y) #判断tensor x的元素是否大于或等于tensor y的对应元素
以下操作仅针对bool型Tensor:
x.logical_and(y) #对两个bool型tensor逐元素进行逻辑与操作
x.logical_or(y) #对两个bool型tensor逐元素进行逻辑或操作
x.logical_xor(y) #对两个bool型tensor逐元素进行逻辑亦或操作
x.logical_not(y) #对两个bool型tensor逐元素进行逻辑非操作
(4)线性代数相关
x.cholesky() #矩阵的cholesky分解
x.t() #矩阵转置
x.transpose([1, 0]) #交换axis 0 与axis 1的顺序
x.norm('fro') #矩阵的Frobenius 范数
x.dist(y, p=2) #矩阵(x-y)的2范数
x.matmul(y) #矩阵乘法
2、广播
(1)判断能否广播
(1)每个张量至少为一维张量.
(2)从后往前比较张量的形状,当前维度的大小要么相等,要么其中一个等于一,要么其中一个不存在.
例如:
import paddle
x = paddle.ones((2, 3, 4))
y = paddle.ones((2, 3, 4))
# 两个张量 形状一致,可以广播
z = x + y
print(z.shape)
# [2, 3, 4]
x = paddle.ones((2, 3, 1, 5))
y = paddle.ones((3, 4, 1))
# 从后向前依次比较:
# 第一次:y的维度大小是1
# 第二次:x的维度大小是1
# 第三次:x和y的维度大小相等
# 第四次:y的维度不存在
# 所以 x和y是可以广播的
z = x + y
print(z.shape)
# [2, 3, 4, 5]
# 相反
x = paddle.ones((2, 3, 4))
y = paddle.ones((2, 3, 6))
# 此时x和y是不可广播的,因为第一次比较 4不等于6
# z = x + y
# InvalidArgumentError: Broadcast dimension mismatch.
3、自动微分机制
(1)背景
前向传播是输入通过每一层节点计算后得到每层输出,上层输出又作为下一层的输入,最终达到输出层。然后通过损失函数计算得到loss值。
反向传播是通过loss值来指导前向节点中的函数参数如何改变,并更新每层中每个节点的参数,来让整个神经网络达到更小的loss值。
自动微分机制就是让你只关注组网中的前向传播过程,然后飞桨框架来自动完成反向传播过程,从而来让你从繁琐的求导、求梯度的过程中解放出来。
(2)使用方法
先导入相关库
#加载飞桨和相关类库
import paddle
from paddle.vision.models import vgg11
import paddle.nn.functional as F
import numpy as np
print(paddle.__version__)
本案例首先定义网络。因为本示例着重展示如何使用飞桨进行自动微分,故组网部分不过多展开,直接使用高层API中封装好的模型vgg11。
然后随机初始化一个输入x,和对应标签label。
model = vgg11()
x = paddle.rand([1,3,224,224])
label = paddle.randint(0,1000)
然后将输入传入到模型中,进行前向传播过程。
# 前向传播
predicts = model(x)
前向传播结束后,你就得到模型的预测结果predicts,这时可以使用飞桨中的对应损失函数API进行损失函数的计算。该例子中使用cross_entropy来计算损失函数,来衡量模型的预测情况。
# 计算损失
loss = F.cross_entropy(predicts, label)
随后进行反向传播,在飞桨中你只需要调用backward()即可自动化展开反向传播过程。各梯度保存在grad属性中。
# 开始进行反向传播
loss.backward()
然后来定义优化器,本例子中使用Adam优化器,设置learning_rate为0.001,并把该模型的所有参数传入优化器中。
# 设置优化器
optim = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
最后通过step来开始执行优化器,并进行模型参数的更新
# 更新参数
optim.step()