十行代码就能搞定深度学习?飞桨框架高层API,计算机视觉研究院带你一起轻松玩转AI(附源码)

2020 年 12 月 7 日 计算机视觉战队
欢迎关注“
计算机视觉研究院

计算机视觉研究院专栏
作者:Edison_G




前言  向往深度学习技术,可是深度学习框架太难学怎么办?百度倾心打造飞桨框架高层API,零基础也能轻松上手深度学习,一起来看看吧?


另:文末有福利,一定要看完



高层API,What 

深度学习作为人工智能时代的核心技术,近年来无论学术、还是工业领域,均发挥着愈加重要的作用。然而,深度学习理论太难学,开发过程太复杂,又将许多人拒之于深度学习的门外。

为了简化深度学习的学习过程、降低深度学习的开发难度,百度飞桨框架历经近一年的打磨,不断地优化深度学习API,并针对开发者的使用场景进行封装,在飞桨框架的最新版本中,推出了高低融合、科学统一的飞桨全新 API 体系。

飞桨框架将API分为两种,基础API和高层API。用制作披萨举例,一般有两种方法:一种是我们准备好面粉、牛奶、火腿等食材,精心加工后,就能制作出美味的披萨;而第二种则是我们买商家预烤制的披萨饼,以及调好的馅料,直接加热就可以吃到披萨了。


那么这两种方法有什么区别呢?采用方法一,自己准备食材,可以随心所欲的搭配料理,制作酱料,从而满足我们的不同口味,但是,这更适合「老司机」,如果是新人朋友,很有可能翻车;而方法二,用商家预烤制的披萨饼与馅料,直接加热就可以非常快速的完成披萨的制作,而且味道会有保障;但是,相比于方法一,我们会少一些口味的选择。

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

但是,与制作披萨不同的是,飞桨框架可以做到真正的「鱼与熊掌」可以兼得。因为高层API本身不是一个独立的体系,它完全可以和基础API互相配合使用,做到高低融合,使用起来会更加便捷。使我们在开发过程中,既可以享受到基础API的强大,又可以兼顾高层API的快捷。

高层API,All

飞桨框架高层API的全景图如下:



从图中可以看出,飞桨框架高层API由五个模块组成,分别是数据加载、模型组建、模型训练、模型可视化和高阶用法。针对不同的使用场景,飞桨框架提供了不同高层API,从而降低开发难度,让每个人都能轻松上手深度学习。

我们先通过一个深度学习中经典的手写数字分类任务,来简单了解飞桨高层 API。然后再详细的介绍每个模块中所包含的 API。


import paddlefrom paddle.vision.transforms import Compose, Normalizefrom paddle.vision.datasets import MNISTimport paddle.nn as nn 
# 数据预处理,这里用到了归一化transform = Compose([Normalize(mean=[127.5], std=[127.5], data_format='CHW')])
# 数据加载,在训练集上应用数据预处理的操作train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)
# 模型组网mnist = nn.Sequential( nn.Flatten(), nn.Linear(784, 512), nn.ReLU(), nn.Dropout(0.2), nn.Linear(512, 10))
# 模型封装,用 Model 类封装model = paddle.Model(mnist)
# 模型配置:为模型训练做准备,设置优化器,损失函数和精度计算方式model.prepare(optimizer=paddle.optimizer.Adam(parameters=model.parameters()), loss=nn.CrossEntropyLoss(), metrics=paddle.metric.Accuracy())
# 模型训练,model.fit(train_dataset, epochs=10, batch_size=64, verbose=1)
# 模型评估,model.evaluate(test_dataset, verbose=1)
# 模型保存,model.save('model_path')


从示例可以看出,在数据预处理、数据加载、模型组网、模型训练、模型评估、模型保存等场景,高层API均可以通过1~3 行代码实现。相比传统方法动辄几十行的代码量,高层API只需要十来行代码,就能轻松完成一个MNIST分类器的实现。以极少的代码就能达到与基础API同样的效果,大幅降低了深度学习的学习门槛。

如果是初次学习深度学习框架,使用飞桨高层API,可以「凡尔赛」说出「好烦哦,飞桨高层API怎么这么快就完成开发了,我还想多写几行代码呢!」

高层API,How

接下来以CV任务为例,简单介绍飞桨高层API在不同场景下的使用方法。

本示例的完整代码可以在AI Studio上获取,无需准备任何软硬件环境即可直接在线运行代码, https://aistudio.baidu.com/aistudio/projectdetail/1243085

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


对于数据加载,在一些典型的任务中,我们完全可以使用飞桨框架内置的数据集,完成数据的加载。飞桨框架将常用的数据集作为领域API,集成在paddle.vision.datasets 目录中,包含了CV领域中常见的MNIST、Cifar、Flowers等数据集。

而在数据预处理场景中,飞桨框架提供了20多种常见的图像预处理 API,方便我们快速实现数据增强,如实现图像的色调、对比度、饱和度、大小等各种数字图像处理的方法。图像预处理API集成在paddle.vision.transforms目录中,使用起来非常方便。只需要先创建一个数据预处理的transform,在其中存入需要进行的数据预处理方法,然后在数据加载的过程中,将transform作为参数传入即可。

此外,如果我们需要加载自己的数据集,使用飞桨框架标准数据定义与数据加载API paddle.io.Dataset与paddle.io.DataLoader,就可以「一键」完成数据集的定义与数据的加载。这里通过一个案例来展示如何利用Dataset定义数据集,示例如下:
from paddle.io import Dataset
class MyDataset(Dataset): """ 步骤一:继承 paddle.io.Dataset 类 """ def __init__(self): """ 步骤二:实现构造函数,定义数据读取方式,划分训练和测试数据集 """ super(MyDataset, self).__init__()
self.data = [ ['traindata1', 'label1'], ['traindata2', 'label2'], ['traindata3', 'label3'], ['traindata4', '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()
print('=============train dataset=============')for data, label in train_dataset: print(data, label)
只需要按照上述规范的四个步骤,我们就实现了一个自己的数据集。然后,将train_dataset作为参数,传入到DataLoader中,即可获得一个数据加载器,完成训练数据的加载。

Tips:对于数据集的定义,飞桨框架同时支持 map-style 和 iterable-style 两种类型的数据集定义,只需要分别继承 paddle.io.Dataset 和 paddle.io.IterableDataset 即可。

二、网络构建

在网络构建模块,飞桨高层API与基础API保持一致,统一使用paddle.nn下的API进行组网。paddle.nn目录下包含了所有与模型组网相关的API,如卷积相关的Conv1D、Conv2D、Conv3D,循环神经网络相关的RNN、LSTM、GRU等。

对于组网方式,飞桨框架支持Sequential或SubClass进行模型组建。Sequential可以帮助我们快速的组建线性的网络结构,而SubClass支持更丰富灵活的网络结构。我们可以根据实际的使用场景,来选择最合适的组网方式。如针对顺序的线性网络结构可以直接使用Sequential ,而如果是一些比较复杂的网络结构,我们使用SubClass的方式来进行模型的组建,在__init__构造函数中进行Layer的声明,在forward中使用声明的Layer变量进行前向计算。

下面就来分别看一下Sequential与SubClass的实例。

1、Sequential 

对于线性的网络模型,我们只需要按网络模型的结构顺序,一层一层的加到Sequential后面即可,具体实现如下:
# Sequential 形式组网mnist = nn.Sequential(    nn.Flatten(),        nn.Linear(784, 512),        nn.ReLU(),        nn.Dropout(0.2),        nn.Linear(512, 10))

2、SubClass

使用SubClass进行组网的实现如下:
# SubClass 方式组网class Mnist(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更复杂一些。不过,这带来的是网络模型结构的灵活性。我们可以设计不同的网络模型结构来应对不同的场景。

3、飞桨框架内置模型

除了自定义模型结构外,飞桨框架还「贴心」的内置了许多模型,真正的一行代码实现深度学习模型。目前,飞桨框架内置的模型都是CV领域领域的模型,都在paddle.vision.models目录下,包含了常见的vgg系列、resnet系列等模型。使用方式如下:
import paddlefrom paddle.vision.models import resnet18
# 方式一: 一行代码直接使用 resnetresnet = resnet18()
# 方式二: 作为主干网络进行二次开发class FaceNet(paddle.nn.Layer): def __init__(self, num_keypoints=15, pretrained=False): super(FaceNet, self).__init__()
self.backbone = resnet18(pretrained) self.outLayer1 = paddle.nn.Linear(1000, 512) self.outLayer2 = paddle.nn.Linear(512, num_keypoints*2)
def forward(self, inputs): out = self.backbone(inputs) out = self.outLayer1(out) out = self.outLayer2(out) return out

三、模型可视化

在我们完成模型的构建后,有时还需要可视化模型的网络结构与参数,只要我们用Model进行模型的封装后,然后调用model.summary即可实现网络模型的可视化,具体如下:
mnist = nn.Sequential(    nn.Flatten(),        nn.Linear(784, 512),        nn.ReLU(),        nn.Dropout(0.2),        nn.Linear(512, 10))
# 模型封装,用 Model 类封装model = paddle.Model(mnist)model.summary()

其输出如下:

--------------------------------------------------------------------------- Layer (type)       Input Shape          Output Shape         Param #     ===========================================================================   Flatten-795    [[32, 1, 28, 28]]        [32, 784]              0             Linear-5         [[32, 784]]           [32, 512]           401,920            ReLU-3          [[32, 512]]           [32, 512]              0            Dropout-3        [[32, 512]]           [32, 512]              0              Linear-6         [[32, 512]]            [32, 10]            5,130         ===========================================================================    Total params: 407,050    Trainable params: 407,050    Non-trainable params: 0---------------------------------------------------------------------------Input size (MB): 0.10Forward/backward pass size (MB): 0.57Params size (MB): 1.55Estimated Total Size (MB): 2.22---------------------------------------------------------------------------{'total_params': 407050, 'trainable_params': 407050}
Model.summary不仅会给出每一层网络的形状,还会给出每层网络的参数量与模型的总参数量,非常方便直观的就可以看到模型的全部信息。

四、模型训练

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

过去常常困扰深度学习开发者的一个问题是,模型训练的代码过于复杂,常常要写好多步骤,才能使程序运行起来,冗长的代码使许多开发者望而却步。

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

对比传统框架动辄一大块的训练代码。使用飞桨高层API,可以在3-5行内,完成模型的训练,极大的简化了开发的代码量,对初学者开发者非常友好。具体代码如下:
# 将网络结构用 Model 类封装成为模型model = paddle.Model(mnist)
# 为模型训练做准备,设置优化器,损失函数和精度计算方式model.prepare(optimizer=paddle.optimizer.Adam(parameters=model.parameters()), loss=paddle.nn.CrossEntropyLoss(), metrics=paddle.metric.Accuracy())
# 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式model.fit(train_dataset, epochs=10, batch_size=64, verbose=1)
# 启动模型评估,指定数据集,设置日志格式model.evaluate(test_dataset, verbose=1)
# 启动模型测试,指定测试集 Model.predict(test_dataset)

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, places=paddle.CPUPlace(), 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]])

五、高阶用法

除此之外,飞桨高层API还支持一些高阶的玩法,如自定义Loss、自定义Metric、自定义Callback等等。

自定义Loss是指有时我们会遇到特定任务的Loss计算方式在框架既有的Loss接口中不存在,或算法不符合自己的需求,那么期望能够自己来进行Loss的自定义。

自定义Metric和自定义Loss的场景一样,如果遇到一些想要做个性化实现的操作时,我们也可以来通过框架完成自定义的评估计算方法。

自定义Callback则是可以帮助我们收集训练时的一些参数以及数据,由于Model.fit()封装了训练过程,如果我们需要保存训练时的loss、metric等信息,则需要通过callback 参数收集这部分信息。

更多更丰富的玩法,可以扫描关注文末的二维码获取

高层API,Next

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

高层API,Where

看完前面飞桨高层API的使用介绍,是不是有种跃跃欲试的冲动呀?

体验方式一:在线体验
无需准备任何软硬件环境,直接访问以下地址,即可在线跑代码看效果: https://aistudio.baidu.com/aistudio/projectdetail/1243085

体验方式二:本地体验
如果你还想在自己本地电脑上体验,那需要确保本地电脑上已成功安装飞桨开源框架 2.0。

下面介绍飞桨开源框架2.0的安装方法,可以参考下面的命令,直接使用pip安装。安装后,就可以开始使用高层API。
# CPU 版$ pip3 install paddlepaddle==2.0.0rc0 -i https://mirror.baidu.com/pypi/simple# GPU 版$ pip3 install paddlepaddle_gpu==2.0.0rc0 -i https://mirror.baidu.com/pypi/simple

/End.


我们开创“ 计算机视觉协会 ”知识星球一年有余,也得到很多同学的认可,我们定时会推送实践型内容与大家分享,在星球里的同学可以随时提问,随时提需求,我们都会及时给予回复及给出对应的答复。

如果想加入我们“ 计算机视觉研究院 ”,请扫二维码加入我们。我们会按照你的需求将你拉入对应的学习群!
计算机视觉研究院主要涉及深度学习领域,主要致力于人脸检测、人脸识别,多目标检测、目标跟踪、图像分割等研究方向。研究院接下来会不断分享最新的论文算法新框架,我们这次改革不同点就是,我们要着重” 研究 “。之后我们会针对相应领域分享实践过程,让大家真正体会 摆脱理论 的真实场景,培养爱动手编程爱动脑思考的习惯!

后台回复“飞桨代码

获取源码下载地址

计算机视觉研究院
长按扫描二维码关注我们


登录查看更多
0

相关内容

PaddlePaddle(PArallel Distributed Deep LEarning)是由百度推出的一个易用、高效、灵活、可扩展的深度学习框架。 官方网站:https://www.paddlepaddle.org.cn
小米在预训练模型的探索与优化
专知会员服务
18+阅读 · 2020年12月31日
【CVPR2020】图神经网络中的几何原理连接
专知会员服务
56+阅读 · 2020年4月8日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
一网打尽!100+深度学习模型TensorFlow与Pytorch代码实现集合
【书籍】深度学习框架:PyTorch入门与实践(附代码)
专知会员服务
163+阅读 · 2019年10月28日
【开源书】PyTorch深度学习起步,零基础入门(附pdf下载)
专知会员服务
110+阅读 · 2019年10月26日
网易云课堂独家 | 基于PyTorch实现的《深度学习》
深度学习与NLP
11+阅读 · 2019年2月15日
手把手教 | 深度学习库PyTorch(附代码)
数据派THU
27+阅读 · 2018年3月15日
从基础概念到实现,小白如何快速入门PyTorch
机器之心
13+阅读 · 2018年2月26日
测试对比TensorFlow、MXNet、CNTK、Theano四个框架
炼数成金订阅号
3+阅读 · 2017年9月18日
Mesh R-CNN
Arxiv
4+阅读 · 2019年6月6日
Self-Attention Graph Pooling
Arxiv
5+阅读 · 2019年4月17日
Arxiv
4+阅读 · 2018年10月31日
Arxiv
3+阅读 · 2018年5月20日
Arxiv
7+阅读 · 2018年1月24日
Arxiv
4+阅读 · 2017年10月30日
VIP会员
相关VIP内容
小米在预训练模型的探索与优化
专知会员服务
18+阅读 · 2020年12月31日
【CVPR2020】图神经网络中的几何原理连接
专知会员服务
56+阅读 · 2020年4月8日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
一网打尽!100+深度学习模型TensorFlow与Pytorch代码实现集合
【书籍】深度学习框架:PyTorch入门与实践(附代码)
专知会员服务
163+阅读 · 2019年10月28日
【开源书】PyTorch深度学习起步,零基础入门(附pdf下载)
专知会员服务
110+阅读 · 2019年10月26日
相关论文
Mesh R-CNN
Arxiv
4+阅读 · 2019年6月6日
Self-Attention Graph Pooling
Arxiv
5+阅读 · 2019年4月17日
Arxiv
4+阅读 · 2018年10月31日
Arxiv
3+阅读 · 2018年5月20日
Arxiv
7+阅读 · 2018年1月24日
Arxiv
4+阅读 · 2017年10月30日
Top
微信扫码咨询专知VIP会员