深度学习(paddle2.0 API)

发布时间: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 总结


1 高层API的主要模块

\"深度学习(paddle2.0

\"深度学习(paddle2.0

2 数据加载

2.1 内置数据集

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

2.2 数据预处理

以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)

2.3 数据批加载

paddle.io.Dataset 和 paddle.io.DataLoader 可以”一键”完成数据的批加载与异步加载。

3模型组建

3.1 序列组网

序列组网即 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 上查询

3.2 Subclass 组网

(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

3.3 内置模型

lenet = paddle.vision.models.LeNet() 就完成了LeNet模型的搭建,内置模型还有

[\'ResNet\', \'resnet18\', \'resnet34\', \'resnet50\', \'resnet101\', \'resnet152\', \'VGG\', \'vgg11\', \'vgg13\', \'vgg16\', \'vgg19\', \'MobileNetV1\', \'mobilenet_v1\', \'MobileNetV2\', \'mobilenet_v2\', \'LeNet\']

这些经典的模型都能调用,我们通过超参数的调整就能完成大部分项目。

4 模型可视化

4.1 模型结构可视化

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}

4.2 使用VisualDL完成训练过程的可视化

# 调用飞桨框架的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 就可以在浏览器中看到相关的训练信息,具体如下:

\"深度学习(paddle2.0

5 模型训练

5.1 模型配置

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())

5.2 模型训练

# 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式
model.fit(train_dataset,
          epochs=5,
          batch_size=64,
          verbose=1)

5.3 模型评估

# 用 evaluate 在测试集上对模型进行验证
eval_result = model.evaluate(test_dataset,batch_size=64,verbose=1)

5.4 模型预测

# 用 predict 在测试集上对模型进行测试
test_result = model.predict(test_dataset)

6 高阶用法

6.1 损失函数自定义

为了符合自己的实际项目的需求,有时候需要自己设计损失函数。

#伪代码说明
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

6.2 评估方法自定义

### 伪代码说明
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

6.3 执行过程回调自定义

# 自定义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 中

7 总结

由于飞桨高层 API 是对基础 API 的封装,所以也可以对其进行拆解,将高层 API 用基础 API 实现。对fit,也就是训练过程进行拆解。对高层 API 的了解能够在飞桨框架中实现了 API 的高低融合,使开发者既可以享受到基础 API 的强大,又可以兼顾高层 API 的快捷

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号