发布时间:2023-09-16 08:30
本程序采用百度paddlepaddle深度学习框架,并在百度 AI Studio 平台上运行
本文参考百度 AI Studio官方API文档,详情参考官方文档
本文参考『跟着雨哥学AI』系列开篇:初识飞桨框架高层API - 飞桨AI Studio - 人工智能学习实训社区 (baidu.com)
目录
1 高层API的主要模块
2 数据加载
2.1 内置数据集
2.2 数据预处理
2.3 数据批加载
3模型组建
3.1 序列组网
3.2 Subclass 组网
3.3 内置模型
4 模型可视化
4.1 模型结构可视化
4.2 使用VisualDL完成训练过程的可视化
5 模型训练
5.1 模型配置
5.2 模型训练
5.3 模型评估
5.4 模型预测
6 高阶用法
6.1 损失函数自定义
6.2 评估方法自定义
6.3 执行过程回调自定义
7 总结
paddle.vision.dataset 包含许多CV相关的数据集,直接调用API即可。
#例如你要调用Cifar10数据集
from paddle.vision.datasets import Cifar10
#例如你要对数据处理
from paddle.vision.transforms import Normalize
normalize = Normalize(mean=[0.5, 0.5, 0.5],
std=[0.5, 0.5, 0.5],
data_format=\'HWC\')
cifar10 = Cifar10(mode=\'train\', transform=normalize)
#这里有两个参数,更多参数阅读百度AI Studio 官方API
#mode=\'train\'或\'test\'
#transform自己指定,这里是normalize,但必须定义normalize
以functional.adjust_brightness为例,这是对图像进行亮度增强,其他很多的图像处理操作也是从paddle.vision.transforms引入,可以与上面的内置数据集的参数transform设置相结合。
import numpy as np
from PIL import Image
from paddle.vision.transforms import functional as F
fake_img = (np.random.rand(256, 300, 3) * 255.).astype(\'uint8\')
fake_img = Image.fromarray(fake_img)
converted_img = F.adjust_brightness(fake_img, 0.4)
print(converted_img.size)
paddle.io.Dataset 和 paddle.io.DataLoader 可以”一键”完成数据的批加载与异步加载。
序列组网即 paddle.nn.Sequential,Sequential是顺序容器的意思,这个容器里封装了一个神经网络结构,逐层描述每层网络。每一层的网络结构可以是拉直层、全连接层、卷积层、LSTM层等,逐层描述的方法相当于一遍前向传播的过程。
#举个例子
# create Sequential with iterable Layers
model1 = paddle.nn.Sequential(
paddle.nn.Linear(10, 5),
paddle.nn.Linear(5, 2)
)
#涉及到的paddle.nn.Linear具体的参数请到百度AI Studio 上查询
(1)Sequential 可以搭建很多顺序结构,但有些如带有跳连的非顺序网络结构,用 Sequential 就无法搭建,可以选择使用类 SubClass 定义的方式来进行网络结构搭建。
(2)在 __init__ 构造函数中进行组网 Layer 的声明,在 forward 中使用声明的 Layer 变量进行前向计算。
(3)子类组网方式也可以实现 sublayer 的复用,针对相同的 layer 可以在构造函数中一次性定义,在 forward 中多次调用。
#举个例子
# SubClass 方式组网,定义所需网络结构快
class Mnist(paddle.nn.Layer): #继承paddle.nn.Layer类
# 定义网络结构块
def __init__(self):
super(Mnist, self).__init__()
self.flatten = nn.Flatten()
self.linear_1 = nn.Linear(784, 512)
self.linear_2 = nn.Linear(512, 10)
self.relu = nn.ReLU()
# 写出前向传播
def forward(self, inputs):
y = self.flatten(inputs)
y = self.linear_1(y)
y = self.relu(y)
y = self.linear_2(y)
return y
lenet = paddle.vision.models.LeNet() 就完成了LeNet模型的搭建,内置模型还有
[\'ResNet\', \'resnet18\', \'resnet34\', \'resnet50\', \'resnet101\', \'resnet152\', \'VGG\', \'vgg11\', \'vgg13\', \'vgg16\', \'vgg19\', \'MobileNetV1\', \'mobilenet_v1\', \'MobileNetV2\', \'mobilenet_v2\', \'LeNet\']
这些经典的模型都能调用,我们通过超参数的调整就能完成大部分项目。
import paddle
mnist = paddle.nn.Sequential(
paddle.nn.Flatten(),
paddle.nn.Linear(784, 512),
paddle.nn.ReLU(),
paddle.nn.Dropout(0.2),
paddle.nn.Linear(512, 10)
)
# 模型封装,用Model类封装
model = paddle.Model(mnist)
model.summary((1, 28, 28))
不仅会给出每一层网络的形状,还会给出每层网络的参数量与模型的总参数量,非常方便直观的就可以看到模型的全部信息。
Layer (type) Input Shape Output Shape Param # =========================================================================== Flatten-88776 [[1, 28, 28]] [1, 784] 0 Linear-20 [[1, 784]] [1, 512] 401,920 ReLU-11 [[1, 512]] [1, 512] 0 Dropout-9 [[1, 512]] [1, 512] 0 Linear-21 [[1, 512]] [1, 10] 5,130 =========================================================================== Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 --------------------------------------------------------------------------- Input size (MB): 0.00 Forward/backward pass size (MB): 0.02 Params size (MB): 1.55 Estimated Total Size (MB): 1.57 ---------------------------------------------------------------------------
{\'total_params\': 407050, \'trainable_params\': 407050}
# 调用飞桨框架的VisualDL模块,保存信息到目录中。
callback = paddle.callbacks.VisualDL(log_dir=\'visualdl_log_dir\')
# 模型配置:为模型训练做准备,设置优化器,损失函数和精度计算方式
model.prepare(optimizer=paddle.optimizer.Adam(parameters=model.parameters()),
loss=nn.CrossEntropyLoss(),
metrics=paddle.metric.Accuracy())
model.fit(train_dataset,
epochs=5,
batch_size=32,
callbacks=callback,
verbose=1)
然后我们调用VisualDL工具,在命令行中输入: visualdl --logdir ./visualdl_log_dir --port 8080
,打开浏览器,输入网址 http://127.0.0.1:8080 就可以在浏览器中看到相关的训练信息,具体如下:
import paddle
from paddle import Model
model= Model(VGGNet())#模型封装
# 为模型训练做准备,设置优化器,损失函数和精度计算方式
model.prepare(optimizer=paddle.optimizer.Adam(parameters=model.parameters()),
loss=paddle.nn.CrossEntropyLoss(),
metrics=paddle.metric.Accuracy())
# 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式
model.fit(train_dataset,
epochs=5,
batch_size=64,
verbose=1)
# 用 evaluate 在测试集上对模型进行验证
eval_result = model.evaluate(test_dataset,batch_size=64,verbose=1)
# 用 predict 在测试集上对模型进行测试
test_result = model.predict(test_dataset)
为了符合自己的实际项目的需求,有时候需要自己设计损失函数。
#伪代码说明
class SelfDefineLoss(paddle.nn.Layer):
\"\"\"
1. 继承paddle.nn.Layer
\"\"\"
def __init__(self):
\"\"\"
2. 构造函数根据自己的实际算法需求和使用需求进行参数定义即可
\"\"\"
super(SelfDefineLoss, self).__init__()
def forward(self, input, label):
\"\"\"
3. 实现forward函数,forward在调用时会传递两个参数:input和label
- input:单个或批次训练数据经过模型前向计算输出结果
- label:单个或批次训练数据对应的标签数据
接口返回值是一个Tensor,根据自定义的逻辑加和或计算均值后的损失
\"\"\"
# 使用Paddle中相关API自定义的计算逻辑
# output = xxxxx
# return output
### 伪代码说明
class SelfDefineMetric(paddle.metric.Metric):
\"\"\"
1. 继承paddle.metric.Metric
\"\"\"
def __init__(self):
\"\"\"
2. 构造函数实现,自定义参数即可
\"\"\"
super(SelfDefineMetric, self).__init__()
def name(self):
\"\"\"
3. 实现name方法,返回定义的评估指标名字
\"\"\"
return \'自定义评价指标的名字\'
def compute(self, ...)
\"\"\"
4. 本步骤可以省略,实现compute方法,这个方法主要用于`update`的加速,可以在这个方法中调用一些paddle实现好的Tensor计算API,编译到模型网络中一起使用低层C++ OP计算。
\"\"\"
return 自己想要返回的数据,会做为update的参数传入。
def update(self, ...):
\"\"\"
5. 实现update方法,用于单个batch训练时进行评估指标计算。
- 当`compute`类函数未实现时,会将模型的计算输出和标签数据的展平作为`update`的参数传入。
- 当`compute`类函数做了实现时,会将compute的返回结果作为`update`的参数传入。
\"\"\"
return acc value
def accumulate(self):
\"\"\"
6. 实现accumulate方法,返回历史batch训练积累后计算得到的评价指标值。
每次`update`调用时进行数据积累,`accumulate`计算时对积累的所有数据进行计算并返回。
结算结果会在`fit`接口的训练日志中呈现。
\"\"\"
# 利用update中积累的成员变量数据进行计算后返回
return accumulated acc value
def reset(self):
\"\"\"
7. 实现reset方法,每个Epoch结束后进行评估指标的重置,这样下个Epoch可以重新进行计算。
\"\"\"
# do reset action
# 自定义Callback 记录训练过程中的loss信息
class LossCallback(paddle.callbacks.Callback):
def on_train_begin(self, logs={}):
# 在fit前 初始化losses,用于保存每个batch的loss结果
self.losses = []
def on_train_batch_end(self, step, logs={}):
# 每个batch训练完成后调用,把当前loss添加到losses中
self.losses.append(logs.get(\'loss\'))
# 初始化一个loss_log 的实例,然后将其作为参数传递给fit
loss_log = LossCallback()
model.fit(train_dataset,
epochs=5,
batch_size=32,
# callbacks=loss_log,
verbose=1)
# loss信息都保存在 loss_log.losses 中
由于飞桨高层 API 是对基础 API 的封装,所以也可以对其进行拆解,将高层 API 用基础 API 实现。对fit,也就是训练过程进行拆解。对高层 API 的了解能够在飞桨框架中实现了 API 的高低融合,使开发者既可以享受到基础 API 的强大,又可以兼顾高层 API 的快捷
SpringBoot整合ElasticSearch(第八更)
kubernetes资源对象介绍及常用命令(五)-(ConfigMap&Secret)
Cannot read properties of undefined (reading ‘push‘) 问题
记一次Gitlab升级, 14.6.0-ee到14.10.0-ee
03_Linux基础-文件类型-主辅提示符-第1提示符-Linux命令-内外部命令-快捷键-改为英文编码-3个时间-stat-其他基础命令
PerformanceObserver自动获取首屏时间实现示例
SpringBoot中使用@scheduled定时执行任务的坑
[ 目标检测 ] 经典网络模型——性能评价指标 AP、mAP
OR Paper Weekly(一) | 用机器学习生成列生成的列,元启发式算法=动物世界?看OR68年发文数据,哪国位居榜首?