前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NLP涉及技术原理和应用简单讲解【一】:paddle(梯度裁剪、ONNX协议、动态图转静态图、推理部署)

NLP涉及技术原理和应用简单讲解【一】:paddle(梯度裁剪、ONNX协议、动态图转静态图、推理部署)

作者头像
汀丶人工智能
发布2022-12-21 17:32:33
9460
发布2022-12-21 17:32:33
举报
文章被收录于专栏:NLP/KGNLP/KG

参考链接:

https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/advanced/gradient_clip_cn.html

1.梯度裁剪

神经网络是通过梯度下降来进行网络学习,随着网络层数的增加,"梯度爆炸"的问题可能会越来越明显。例如:在梯度反向传播中,如果每一层的输出相对输入的偏导 > 1,随着网络层数的增加,梯度会越来越大,则有可能发生 "梯度爆炸"。

如果发生了 "梯度爆炸",在网络学习过程中会直接跳过最优解,所以有必要进行梯度裁剪,防止网络在学习过程中越过最优解。

Paddle提供了三种梯度裁剪方式:

1.1设定范围值裁剪

设定范围值裁剪:将参数的梯度限定在一个范围内,如果超出这个范围,则进行裁剪。

使用方式:需要创建一个 paddle.nn.ClipGradByValue 类的实例,然后传入到优化器中,优化器会在更新参数前,对梯度进行裁剪。

1. 全部参数裁剪(默认)

默认情况下,会裁剪优化器中全部参数的梯度:

代码语言:javascript
复制
import paddle

linear = paddle.nn.Linear(10, 10)
clip = paddle.nn.ClipGradByValue(min=-1, max=1)
sdg = paddle.optimizer.SGD(learning_rate=0.1, parameters=linear.parameters(), grad_clip=clip)

如果仅需裁剪部分参数,用法如下:

2. 部分参数裁剪

部分参数裁剪需要设置参数的 paddle.ParamAttr ,其中的 need_clip 默认为True,表示需要裁剪,如果设置为False,则不会裁剪。

例如:仅裁剪 linear 中 weight 的梯度,则需要在创建 linear 层时设置 bias_attr 如下:

代码语言:javascript
复制
linear = paddle.nn.Linear(10, 10,bias_attr=paddle.ParamAttr(need_clip=False))

1.2 通过L2范数裁剪

通过L2范数裁剪:梯度作为一个多维Tensor,计算其L2范数,如果超过最大值则按比例进行裁剪,否则不裁剪。

使用方式:需要创建一个 paddle.nn.ClipGradByNorm 类的实例,然后传入到优化器中,优化器会在更新参数前,对梯度进行裁剪。

1.3、通过全局L2范数裁剪

将优化器中全部参数的梯度组成向量,对该向量求解L2范数,如果超过最大值则按比例进行裁剪,否则不裁剪。

使用方式:需要创建一个 paddle.nn.ClipGradByGlobalNorm 类的实例,然后传入到优化器中,优化器会在更新参数前,对梯度进行裁剪。

裁剪公式如下

 2. 模型导出ONNX协议

ONNX (Open Neural Network Exchange) 是针对机器学习所设计的开源文件格式,用于存储训练好的模型。它使得不同的人工智能框架可以采用相同格式存储模型并交互。通过ONNX格式,Paddle模型可以使用OpenVINO、ONNX Runtime等框架进行推理。

不进行详细介绍了、参考链接

https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/advanced/model_to_onnx_cn.html

3.动态图转静态图!

3.1 什么是动态图和静态图?

在深度学习模型构建上,飞桨框架支持动态图编程和静态图编程两种方式,其代码编写和执行方式均存在差异。

  • 动态图编程: 采用 Python 的编程风格,解析式地执行每一行网络代码,并同时返回计算结果。在 模型开发 章节中,介绍的都是动态图编程方式。
  • 静态图编程: 采用先编译后执行的方式。需先在代码中预定义完整的神经网络结构,飞桨框架会将神经网络描述为 Program 的数据结构,并对 Program 进行编译优化,再调用执行器获得计算结果。

动态图静态图优缺点:

  • 动态图编程体验更佳、更易调试,但是因为采用 Python 实时执行的方式,开销较大,在性能方面与 C++ 有一定差距;
  • 静态图调试难度大,但是将前端 Python 编写的神经网络预定义为 Program描述,转到 C++ 端重新解析执行,脱离了 Python 依赖,往往执行性能更佳,并且预先拥有完整网络结构也更利于全局优化。

3.2 什么场景下需要动态图转静态图?

飞桨框架在设计时,考虑同时兼顾动态图的高易用性和静态图的高性能优势,采用『动静统一』的方案:

  • 在模型开发时,推荐采用动态图编程。 可获得更好的编程体验、更易用的接口、更友好的调试交互机制。
  • 在模型训练或者推理部署时,只需添加一行装饰器 @to_static,即可将动态图代码转写为静态图代码,并在底层自动使用静态图执行器运行。 可获得更好的模型运行性能。

方案如下图所示:

根据Operator解析执行方式不同,飞桨支持如下两种编程范式:

  • 静态图模式(声明式编程范式)先编译后执行的方式。用户需预先定义完整的网络结构,再对网络结构进行编译优化后,才能执行获得计算结果。
  • 动态图模式(命令式编程范式)解析式的执行方式。用户无需预先定义完整的网络结构,每写一行网络代码,即可同时获得计算结果。

举例来说,假设用户写了一行代码:y=x+1,在静态图模式下,运行此代码只会往计算图中插入一个Tensor加1的Operator,此时Operator并未真正执行,无法获得y的计算结果。但在动态图模式下,所有Operator均是即时执行的,运行完此代码后Operator已经执行完毕,用户可直接获得y的计算结果。

3.3为什么动态图模式越来越流行?

静态图模式作为较早提出的一种编程范式,提供丰富的 API ,能够快速的实现各种模型;并且可以利用全局的信息进行图优化,优化性能和显存占用;在预测部署方面也可以实现无缝衔接。 但具体实践中静态图模式存在如下问题:

  1. 采用先编译后执行的方式,组网阶段和执行阶段割裂,导致调试不方便。
  2. 属于一种符号化的编程方式,要学习新的编程方式,有一定的入门门槛。
  3. 网络结构固定,对于一些树结构的任务支持的不够好。

动态图的出现很好的解决了这些问题,存在以下优势:

  1. 代码运行完成后,可以立马获取结果,支持使用 IDE 断点调试功能,使得调试更方便。
  2. 属于命令式的编程方式,与编写Python的方式类似,更容易上手。
  3. 网络的结构在不同的层次中可以变化,使用更灵活。

https://www.paddlepaddle.org.cn/tutorials/projectdetail/3949104#anchor-8

3.4 静态图

https://www.paddlepaddle.org.cn/tutorials/projectdetail/3949105

  • 动态图的优势在于所有操作在运行时就已经完成,更接近我们平时的编程方式,可随时获取每一个操作的执行结果,使得程序易于调试;静态图在过程中并没有实际执行操作,上述例子中可以看到过程中只能打印声明的类型,最后需要调用执行器来统一执行所有操作,计算结果需要通过执行器统一返回,这使得调试变得困难。
  • 但静态图的优势就在于,在“运行时”所有操作和执行顺序都已经定义完成,能够根据全局信息来做各种优化策略,比如合并相邻操作来进行加速或者减少中间变量,因此对于同样的网络结构,使用静态图模型运行往往能够获取更好的性能和更少的内存占用。
  • 比较典型的如循环神经网络语言模型,由于使用了LSTM结构,动态图在执行过程中,不可避免的会在Python API和底层C++高性能计算库之间频繁切换执行
  • 而静态图由于执行期几乎全部由C++高性能库完成(Python API的调用基本都集中在编译期完成),所以对于此类网络模型,以及类似的使用了LSTM,RNN、GRU等结构的网络来说,静态图一般都能在性能方面体现较大的优势。

总结一下,动态图改写成静态图的时候,主要有以下几点区别:

  1. 使用的API不同:飞桨同时提供了动态图用法和静态图用法,两者可以共用大部分API,但需要注意还有一小部分API需要区分动态图和静态图,比如上例中的模型保存和加载的API等;另外,动态图中可以随意使用Python的控制流语句,但是在静态图中,当控制流中的判断条件与数据相关时(如前文提到while_loop的例子),需要转换为使用while_loop,cond,case,switch_case等几个专用的控制流API。
  2. 数据读取过程不同:虽然使用的接口基本一致,但动态图在程序运行时读入数据,与我们平时编写python等程序的习惯相同,但在静态图组网阶段并没有实际运行网络,因此并不读入数据,所以需要使用“占位符”(paddle.data)指明输入数据的类型、shape等信息,以完成组网,具体用法请参考飞桨官网DataLoader的API文档。
  3. 执行时期不同:动态图是“所见即所得”的执行方式,而静态图分为编译期和执行器,无论是训练还是预测,都需要使用执行器来执行网络,调用执行器时,需要初始化、指定输入数据和要获取的返回值等。

4.推理部署

4.1 服务器部署 — Paddle Inference

服务器部署 — Paddle Inference-使用文档-PaddlePaddle深度学习平台

Paddle Inference 是飞桨的原生推理库, 作用于服务器端和云端,提供高性能的推理能力。

由于能力直接基于飞桨的训练算子,因此Paddle Inference 可以通用支持飞桨训练出的所有模型。

Paddle Inference 功能特性丰富,性能优异,针对不同平台不同的应用场景进行了深度的适配优化,做到高吞吐、低时延,保证了飞桨模型在服务器端即训即用,快速部署。

一些常见的文档链接如下:

与主框架model.predict区别

飞桨推理产品paddle inference和主框架的Model.predict均可实现推理预测,Paddle Inference 是飞桨的原生推理库, 作用于服务器端和云端,提供高性能的推理能力,主框架的Model 对象是一个具备训练、测试、推理的神经网络。相比于Model.predict,inference可使用MKLDNN、CUDNN、TensorRT进行预测加速,同时支持用 X2Paddle 工具从第三方框架(TensorFlow、Pytorh 、 Caffe 等)产出的模型,可联动PaddleSlim,支持加载量化、裁剪和蒸馏后的模型部署。Model.predict适用于训练好的模型直接进行预测,paddle inference适用于对推理性能、通用性有要求的用户,针对不同平台不同的应用场景进行了深度的适配优化,保证模型在服务器端即训即用,快速部署。

高性能实现

内存/显存复用提升服务吞吐量

在推理初始化阶段,对模型中的OP输出Tensor 进行依赖分析,将两两互不依赖的Tensor在内存/显存空间上进行复用,进而增大计算并行量,提升服务吞吐量。

细粒度OP横向纵向融合减少计算量

在推理初始化阶段,按照已有的融合模式将模型中的多个OP融合成一个OP,减少了模型的计算量的同时,也减少了 Kernel Launch的次数,从而能提升推理性能。目前Paddle Inference支持的融合模式多达几十个。

内置高性能的CPU/GPU Kernel

内置同Intel、Nvidia共同打造的高性能kernel,保证了模型推理高性能的执行。

4.2 移动端/嵌入式部署 — Paddle Lite

Paddle-Lite为Paddle-Mobile的升级版,定位支持包括手机移动端在内更多场景的轻量化高效预测,支持更广泛的硬件和平台,是一个高性能、轻量级的深度学习预测引擎。在保持和PaddlePaddle无缝对接外,也兼容支持其他训练框架产出的模型。

完整使用文档位于 Paddle-Lite 文档 。

特性

轻量级

执行阶段和计算优化阶段实现良好解耦拆分,移动端可以直接部署执行阶段,无任何第三方依赖。 包含完整的80个 Op+85个 Kernel 的动态库,对于ARMV7只有800K,ARMV8下为1.3M,并可以裁剪到更低。 在应用部署时,载入模型即可直接预测,无需额外分析优化。

高性能

极致的 ARM CPU 性能优化,针对不同微架构特点实现kernel的定制,最大发挥计算性能,在主流模型上展现出领先的速度优势。 支持量化模型,结合PaddleSlim 模型压缩工具 中量化功能,可以提供高精度高性能的预测能力。 在Huawei NPU, FPGA上也具有有很好的性能表现。

最新性能数据位于 Benchmark 文档

通用性

硬件方面,Paddle-Lite 的架构设计为多硬件兼容支持做了良好设计。除了支持ARM CPU、Mali GPU、Adreno GPU,还特别支持了华为 NPU,以及 FPGA 等边缘设备广泛使用的硬件。即将支持支持包括寒武纪、比特大陆等AI芯片,未来会增加对更多硬件的支持。

模型支持方面,Paddle-Lite和PaddlePaddle训练框架的Op对齐,提供更广泛的模型支持能力。目前已严格验证18个模型85个OP的精度和性能,对视觉类模型做到了较为充分的支持,覆盖分类、检测和定位,包含了特色的OCR模型的支持。未来会持续增加更多模型的支持验证。

框架兼容方面:除了PaddlePaddle外,对其他训练框架也提供兼容支持。当前,支持Caffe 和 TensorFlow 训练出来的模型,通过[X2Paddle] (https://github.com/PaddlePaddle/X2Paddle) 转换工具实现。接下来将会对ONNX等格式模型提供兼容支持。

4.3 模型压缩 — PaddleSlim

PaddleSlim是一个模型压缩工具库,包含模型剪裁、定点量化、知识蒸馏、超参搜索和模型结构搜索等一系列模型压缩策略。

对于业务用户,PaddleSlim提供完整的模型压缩解决方案,可用于图像分类、检测、分割等各种类型的视觉场景。 同时也在持续探索NLP领域模型的压缩方案。另外,PaddleSlim提供且在不断完善各种压缩策略在经典开源任务的benchmark, 以便业务用户参考。

对于模型压缩算法研究者或开发者,PaddleSlim提供各种压缩策略的底层辅助接口,方便用户复现、调研和使用最新论文方法。 PaddleSlim会从底层能力、技术咨询合作和业务场景等角度支持开发者进行模型压缩策略相关的创新工作。

功能

  • 模型剪裁
    • 卷积通道均匀剪裁
    • 基于敏感度的卷积通道剪裁
    • 基于进化算法的自动剪裁
  • 定点量化
    • 在线量化训练(training aware)
    • 离线量化(post training)
  • 知识蒸馏
    • 支持单进程知识蒸馏
    • 支持多进程分布式知识蒸馏
  • 神经网络结构自动搜索(NAS)
    • 支持基于进化算法的轻量神经网络结构自动搜索
    • 支持One-Shot网络结构自动搜索
    • 支持 FLOPS / 硬件延时约束
    • 支持多平台模型延时评估
    • 支持用户自定义搜索算法和搜索空间
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.梯度裁剪
    • 1.1设定范围值裁剪¶
      • 1.2 通过L2范数裁剪¶
        • 1.3、通过全局L2范数裁剪¶
        •  2. 模型导出ONNX协议
        • 3.动态图转静态图!
          • 3.1 什么是动态图和静态图?¶
            • 3.2 什么场景下需要动态图转静态图?¶
              • 3.3为什么动态图模式越来越流行?
                • 3.4 静态图
                • 4.推理部署
                  • 4.1 服务器部署 — Paddle Inference
                    • 4.2 移动端/嵌入式部署 — Paddle Lite
                      • 4.3 模型压缩 — PaddleSlim
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档