初识飞桨框架API

Posted 一杯冰美式!!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识飞桨框架API相关的知识,希望对你有一定的参考价值。

前言:飞桨框架2.0版本中推出了高层API,对飞桨API进行封装和升级,提高了飞桨的易学性。下面我来带大家了解一下飞桨的高层API。

什么是高层API

        飞桨高层API是飞桨框架推出的快速实现深度学习模型的API,旨在帮助开发者更快更好的完成深度学习模型的学习和开发。

         用框架来类比,飞桨框架基础API对应方法一,飞桨框架高层API对应方法二。使用基础API,我们可以随心所欲的搭建自己的深度学习模型,不会受到任何限制;而使用方法二,我们可以很快的实现模型,达到自己想要的效果,缺点是少了一些自主性。

        这次升级并不是简单的优化,而是将所有的API变得更加体系化。高层API可以和基础API搭配使用,更加便捷。

目前的飞桨高层API由五个模块组成,分别是数据加载、模型组建、模型训练、模型可视化和高阶用法。我们将详细介绍每个模块所包含的API。

高层API详解

1、数据预处理与数据加载

对于数据预处理与数据加载,飞桨框架提供了很多API,如下:

1、飞桨框架内置数据集:paddle.vision.datasets置包含了许多CV领域相关的数据集,直接调用API即可使用;

2、飞桨框架数据预处理:paddle.vision.transforms飞桨框架对于图像预处理的方式,可以快速完成常见的图像预处理的方式,如调整色调、对比度,图像大小等;

3、 飞桨框架数据加载:paddle.io.Dataset与paddle.io.DataLoader飞桨框架标准数据加载方式,可以”一键”完成数据的批加载与异步加载;

1.1 飞桨框架内置数据集

        飞桨将常见的数据集作为领域API对用户开放,我们可以输入代码看一看有哪些数据集:

print("飞桨框架CV领域内置数据集:" + str(paddle.vision.datasets.__all__))

        飞桨提供的数据集包括计算机视觉中常见的数据集,完全满足我们在数据集方面的需求。

        下面我给出一个数据集的加载实例方便理解:

​
train_dataset = paddle.vision.datasets.MNIST(mode='train')
test_dataset = paddle.vision.datasets.MNIST(mode='test')
#取其中一条数据观察
import numpy as np
import matplotlib.pyplot as plt

train_data0,train_label_0 = train_dataset[0][0],train_dataset[0][1]
train_data0 = np.array(train_data0).reshape([28,28])

plt.figure(figsize=(2,2))
plt.imshow(train_data0,cmap = plt.cm.binary)
print('train_data0 label is: ' + str(train_label_0))

​

1.2 飞桨框架预处理方法

        飞桨框架提供了20多种数据集预处理的接口,方便开发者快速实现数据增强,目前都集中在 paddle.vision.transforms 目录下,具体包含的API可以借助这一行代码来查看一下:

print('视觉数据预处理方法:' + str(paddle.vision.transforms.__all__))

        飞桨框架的预处理方法实现了图像的色调、对比度、饱和度、大小等各种数字图像处理的方法。而这些数据预处理方法非常方便,只需要先创建一个数据预处理的transform,在其中存入需要进行的数据预处理方法,然后在数据加载的过程中,将transform作为参数传入即可,具体如下:

​
#首先创建transform
from paddle.vision.transforms import Compose,ColorJitter
from paddle.vision.datasets import Cifar10
transfrom = Compose([ColorJitter()])# transform用于存储数据预处理的接口组合 ColorJitter()实现随机调整亮度、对比度和饱和度
#数据加载,在训练集上应用数据预处理的操作
train_dataset = Cifar10(mode='train',transform=transform)
test_dataset = Cifar10(mode='test')

​

        随机处理和未处理的对比图可以借助如下代码看看:

index = 326
def show_img(img_array):
    img_array = img_array.astype('float32')/255
    plt.figure(figsize=(2,2))
    plt.imshow(img_array,cmap=plt.cm.binary)

dataset_without_transform = Cifar10(mode='train')
show_img(np.array(dataset_without_transform[index][0]))

dataset_with_transform = Cifar10(mode='train',transform=ColorJitter(0.4,0.4,0.4,0.4))
show_img(np.array(dataset_with_transform[index][0]))

​

​

1.3 自定义数据集加载

        有时候我们需要自己使用已有的相关数据定义数据集,这里我们通过一个案例来了解如何进行数据集的定义,飞桨为用户提供了paddle.io.Dataset基类,让用户通过类的集成来快速实现数据集定义。

from paddle.io import Dataset

class MyDataset(Dataset):
    """
    步骤一:继承paddle.io.Dataset类
    """
    def __init__(self, mode='train'):
        """
        步骤二:实现构造函数,定义数据读取方式,划分训练和测试数据集
        """
        super(MyDataset, self).__init__()

        # 下面的traindata1,label1之类的只是一个示例,不能直接用于DataLoader加载,大家可以改成自己的实际数据
        if mode == 'train':
            self.data = [
                ['traindata1', 'label1'], 
                ['traindata2', 'label2'],
                ['traindata3', 'label3'],
                ['traindata4', 'label4'],
            ]
        else:
            self.data = [
                ['testdata1', 'label1'],
                ['testdata2', 'label2'],
                ['testdata3', 'label3'],
                ['testdata4', 'label4'],
            ]

    def __getitem__(self, index):
        """
        步骤三:实现__getitem__方法,定义指定index时如何获取数据,并返回单条数据(训练数据,对应的标签)
        """
        data = self.data[index][0]
        label = self.data[index][1]

        return data, label

    def __len__(self):
        """
        步骤四:实现__len__方法,返回数据集总数目
        """
        return len(self.data)

# 测试定义的数据集
train_dataset = MyDataset(mode='train')
val_dataset = MyDataset(mode='test')

print('=============train dataset=============')
for data, label in train_dataset:
    print(data, label)

print('=============evaluation dataset=============')
for data, label in val_dataset:
    print(data, label)

        之后我们将train_dataset 与 val_dataset 作为参数,传入到DataLoader中,即可获得一个数据加载器,完成训练数据的加载。

2. 网络构建

        飞桨高层API与基础API保持完全的一致,都使用paddle.nn下的API进行组网。这也是尽可能的减少需要暴露的概念,从而提升框架的易学性。飞桨框架 paddle.nn 目录下包含了所有与模型组网相关的API,如卷积相关的 Conv1D、Conv2D、Conv3D,循环神经网络相关的 RNN、LSTM、GRU 等。

        对于组网方式,飞桨框架统一支持 Sequential SubClass 的方式进行模型的组建。我们根据实际的使用场景,来选择最合适的组网方式。如针对顺序的线性网络结构我们可以直接使用 Sequential ,相比于 SubClass Sequential 可以快速的完成组网。 如果是一些比较复杂的网络结构,我们可以使用 SubClass 定义的方式来进行模型代码编写,在 init 构造函数中进行

Layer 的声明,在 forward 中使用声明的 Layer 变量进行前向计算。通过这种方式,我们可以组建更灵活的网络结构。

2.1 Sequential 组网方式

#Sequential组网
mnist = nn.Sequential(
    nn.Flatten(),
    nn.Linear(784,512),
    nn.ReLU(),
    nn.Dropout(0,2),
    nn.Linear(512,10),
)

        对于线性的网络模型,我们可以按网络模型的结构顺序,一层一层加到Sequential后面。

2.2 SubClass 组网方式

#SubClass组网
class Mnist(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()
        self.dropout = nn.Dropout(0.2)

    def forward(self,inputs):
        y = self.flatten(inputs)
        y = self.linear_1(y)
        y = self.relu(y)
        y = self.dropout(y)
        y = self.linear_2(y)

        return y

        上述的SubClass 组网的结果与Sequential 组网的结果完全一致,可以明显看出,使用SubClass 组网会比使用Sequential 更复杂一些。不过,这带来的是网络模型结构的灵活性。

2.3 飞桨内置网络模型

        除了自定义模型结构外,飞桨框架还”贴心”的内置了许多模型,真正的一行代码实现深度学习模型。在paddle.vision.models目录下,具体包含如下的模型:

​
print("视觉相关模型: " + str(paddle.vision.models.__all__))
#['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', 'resnet152', 'VGG', 'vgg11', 'vgg13', 'vgg16', 'vgg19', 'MobileNetV1', 'mobilenet_v1', 'MobileNetV2', 'mobilenet_v2', 'LeNet']
​

        使用起来也十分简单,只需要一行代码就能搭建好模型,如下:

​
#Lenet模型构建
lenet = paddle.vision.models.LeNet()

​

        写完这行代码就完成了Lenet模型的构建,然后就可以开始下一步的模型训练了!

3. 模型训练

3.1 使用高层API在全部数据集上进行训练

        过去模型训练的代码过于复杂,常常要写好多步骤,才能正确的使程序运行起来,冗长的代码使许多开发者望而却步。

        现在,飞桨高层API将训练、评估与预测API都进行了封装,Model.prepare()、Model.fit()、Model.evaluate()、Model.predict()完成模型的训练、评估与预测!

        对初学者用户非常友好!!!

#定义 数据集与模型
import paddle
import paddle.nn as nn
import paddle.vision.transforms as T
from paddle.vision.datasets import MNIST

#数据预处理,(随机调整亮度,对比度,饱和度)

transform = T.Normalize(mean=[127.5],std=[127.5])

#数据加载,在训练集中应用数据预处理

train_dataset = MNIST(mode='train', transform=transform)
test_dataset = MNIST(mode='test', transform=transform)


mnist = nn.Sequential(
    nn.Flatten(),
    nn.Linear(784, 512),
    nn.ReLU(),
    nn.Dropout(0.2),
    nn.Linear(512, 10)
)

#使用高层API进行训练

#将网络结构用Model类进行封装
model = paddle.Model(mnist)

#为模型训练做准备,设置优化器、损失函数、精度计算方式
model.prepare(optimizer = paddle.optimizer.Adam(parameters=model.parameters()),
                loss = paddle.nn.CrossEntropyLoss(),
                metrics = paddle.metric.Accuracy())

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

evaluate_result = model.evaluate(test_dataset, verbose=1)

# 启动模型测试,指定测试集 

predict_result = model.predict(test_dataset)

3.2 使用高层API在一个批次的数据集上训练、验证与测试

        有时我们需要对数据按batch进行取样,然后完成模型的训练与验证,这时,可以使用 train_batch、eval_batch、predict_batch 完成一个批次上的训练、验证与测试,具体如下:

# 模型封装,用Model类封装
model = paddle.Model(mnist)

# 模型配置:为模型训练做准备,设置优化器,损失函数和精度计算方式
model.prepare(optimizer=paddle.optimizer.Adam(parameters=model.parameters()),
              loss=nn.CrossEntropyLoss(),
              metrics=paddle.metric.Accuracy())

# 构建训练集数据加载器
train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True)

# 使用train_batch 完成训练
for batch_id, data in enumerate(train_loader()):
    model.train_batch([data[0]],[data[1]])

# 构建测试集数据加载器
test_loader = paddle.io.DataLoader(test_dataset, batch_size=64, shuffle=True)

# 使用 eval_batch 完成验证
for batch_id, data in enumerate(test_loader()):
    model.eval_batch([data[0]],[data[1]])

# 使用 predict_batch 完成预测
for batch_id, data in enumerate(test_loader()):
    model.predict_batch([data[0]])

3.3 对高层API(model.fit)进行拆解

        由于飞桨高层API是对基础API的封装,所以我们也可以对其进行拆解,将高层API用基础API实现。拆解的步骤如下面的代码,这里我们只对fit,也就是训练过程进行拆解。

import paddle.nn.functional as F

# 加载数据
train_loader = paddle.io.DataLoader(train_dataset, places=paddle.CPUPlace(), batch_size=64, shuffle=True)
# 加载训练集 batch_size 设为 64
def train(model):
    model.train()
    epochs = 5
    optim = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()) # 用Adam作为优化函数
    for epoch in range(epochs):
        for batch_id, data in enumerate(train_loader()):
            x_data = data[0]
            y_data = data[1]
            predicts = model(x_data)
            loss = F.cross_entropy(predicts, y_data) # 计算损失
            acc = paddle.metric.accuracy(predicts, y_data) # 计算精度
            loss.backward() # 反向传播
            if batch_id % 500 == 0:
                print("epoch: , batch_id: , loss is: , acc is: ".format(epoch, batch_id, loss.numpy(), acc.numpy()))
            optim.step()  # 更新参数
            optim.clear_grad()  # 清除梯度
model = Mnist()
train(model)

4. 模型可视化

        在我们完成模型的构建后,有时还需要可视化模型的网络结构与训练过程,来直观的了解深度学习模型与训练过程,方便我们更好地优化模型。飞桨框架高层API提供了一系列相关的API,来帮助我们可视化模型与训练过程,就让我们来看一下吧。

4.1 模型结构可视化

        对于我们组网的模型,只要我们用Model进行模型的封装后,只需要调用 model.summary 即可实现网络模型的可视化。

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

5.2 使用VisualDL完成训练过程可视化(重要)

        VisualDL是飞桨可视化分析工具,以丰富的图表呈现训练参数变化趋势、模型结构、数据样本、直方图以及PR曲线等。可帮助用户更清晰直观地理解深度学习模型训练过程及模型结构,进而实现高效的模型优化。是飞桨模型可视化的大杀器。仅需一行代码就可以轻松使用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 service upload --logdir ./visualdl_log

        复制链接到浏览器中查看可视化结果

总结

        上文以CV任务为例,介绍了飞桨框架高层API的使用指南。后续,飞桨框架还计划推出NLP领域专用的数据预处理模块,如对数据进行padding、获取数据集词表等;在组网方面,也会实现NLP领域中组网专用的API,如组网相关的sequence_mask,评估指标相关的BLEU等;最后,针对NLP领域中的神器transformer,我们也会对其进行特定的优化;

以上是关于初识飞桨框架API的主要内容,如果未能解决你的问题,请参考以下文章

飞桨开源框架2.0,带你走进全新高层API,十行代码搞定深度学习模型开发

01:一文入门谷歌深度学习框架Tensorflow

以贡献飞桨框架API为例,手把手教你从User进阶到Contributor

以贡献飞桨框架API为例,手把手教你从User进阶到Contributor

初识vue

初识vue