写点什么

MindSpore 模型精度调优实战:常用的定位精度调试调优思路

发布于: 3 小时前

​​​​​​​​​​摘要:在模型的开发过程中,精度达不到预期常常让人头疼。为了帮助用户解决模型调试调优的问题,我们为 MindSpore 量身定做了可视化调试调优组件:MindInsight。


本文分享自华为云社区《技术干货 |模型优化精度、速度我全都要!MindSpore模型精度调优实战(二)》,原文作者:HWCloudAI 。

 

引言:在模型的开发过程中,精度达不到预期常常让人头疼。为了帮助用户解决模型调试调优的问题,我们为 MindSpore 量身定做了可视化调试调优组件:MindInsight。我们还梳理了针对常见精度问题的调试调优指南,将以“MindSpore 模型精度调优实战”系列文章的形式分享出来,希望能帮助用户轻松定位精度问题,快速优化模型精度。


回顾 MindSpore 模型精度调优实战系列点击跳转链接→技术干货 | 更快定位精度问题!MindSpore模型精度调优实战(一)


本文是系列分享的第二篇,将给出常用的精度调试调优思路。本系列分享假设您的脚本已经能够运行并算出 loss 值。如果脚本还不能运行,请先参考相关报错提示进行修改。


遇到精度问题时,常用调试调优思路如下:

1. 检查代码和超参

2. 检查模型结构

3. 检查输入数据

4. 检查 loss 曲线

5. 检查精度是否达到预期


代码是精度问题的重要源头,检查代码重在对脚本和代码做检查,力争在源头发现问题(第 2 节);模型结构体现了 MindSpore 对代码的理解,检查模型结构重在检查 MindSpore 的理解和算法工程师的设计是否一致(第 3 节);有的问题要到动态的训练过程中才会发现,检查输入数据(第 4 节)和 loss 曲线(第 5 节)正是将代码和动态训练现象结合进行检查;检查精度是否达到预期则是对整体精度调优过程重新审视,并考虑调整超参、解释模型、优化算法等调优手段(第 6 节)。此外,熟悉模型和工具也是很重要的(第 1 节)。下面将分别介绍这些思路。

1、精度调优准备

1.1 回顾算法设计,全面熟悉模型


精度调优前,要先对算法设计做回顾,确保算法设计明确。如果参考论文实现模型,则应回顾论文中的全部设计细节和超参选择情况;如果参考其它框架脚本实现模型,则应确保有一个唯一的、精度能够达标的标杆脚本;如果是新开发的算法,也应将重要的设计细节和超参选择明确出来。这些信息是后面检查脚本步骤的重要依据。


精度调优前,还要全面熟悉模型。只有熟悉了模型,才能准确理解 MindInsight 提供的信息,判断是否存在问题查找问题源头。因此,花时间理解模型算法和结构、理解模型中算子的作用和参数的含义、理解模型所用优化器的特性等模型要素是很重要的。动手分析精度问题细节前,建议先带着问题加深对这些模型要素的了解。


前,要先对算法设计做回顾,确保算法设计明确。如果参考论文实现模型,则应回顾论文中的全部设计细节和超参选择情况;如果参考其它框架脚本实现模型,则应确保有一个唯一的、精度能够达标的标杆脚本;如果是新开发的算法,也应将重要的设计细节和超参选择明确出来。这些信息是后面检查脚本步骤的重要依据。


精度调优前,还要全面熟悉模型。只有熟悉了模型,才能准确理解 MindInsight 提供的信息,判断是否存在问题查找问题源头。因此,花时间理解模型算法和结构、理解模型中算子的作用和参数的含义、理解模型所用优化器的特性等模型要素是很重要的。动手分析精度问题细节前,建议先带着问题加深对这些模型要素的了解。

1.2 熟悉工具


MindInsight 功能丰富,建议用户简单阅读MindInsight教程,了解主要功能。定位精度问题时,建议使能 summary 训练信息收集功能,在脚本中加入 SummaryCollector,并使用训练看板查看训练过程数据,如下图所示。Summary功能的使用指南训练可视功能的使用指南




当您需要在线调试模型时,请参考使能调试器功能

2、检查代码和超参


代码是精度问题的重要源头,超参问题、模型结构问题、数据问题、算法设计和实现问题会体现在脚本中,对脚本做检查是定位精度问题很有效率的手段。检查代码主要依赖代码走读,建议使用小黄鸭调试法:在代码走读的过程中,耐心地向没有经验的“小黄鸭”解释每一行代码的作用,从而激发灵感,发现代码问题。检查脚本时,要注意检查脚本实现(包括数据处理、模型结构、loss 函数、优化器等实现)同设计是否一致,如果参考了其它脚本,要重点检查脚本实现同其它脚本是否一致,所有不一致的地方都应该有充分合理的理由,否则就应修改。


检查脚本时,也要关注超参的情况,超参问题主要体现为超参取值不合理,例如

1. 学习率设置不合理;

2. loss_scale 参数不合理;

3. 权重初始化参数不合理等。


MindInsight 可以辅助用户对超参做检查,大多数情况下,SummaryCollector 会自动记录常见超参,您可以通过 MindInsight 的训练参数详情功能(如下图)和溯源分析功能查看超参。结合 MindInsight 模型溯源分析模块和脚本中的代码,可以确认超参的取值,识别明显不合理的超参。如果有标杆脚本,建议同标杆脚本一一比对超参取值,如果有默认参数值,则默认值也应一并比对,以避免不同框架的参数默认值不同导致精度下降或者训练错误。



3、检查模型结构


在模型结构方面,常见的问题有:

1. 算子使用错误(使用的算子不适用于目标场景,如应该使用浮点除,错误地使用了整数除);

2. 权重共享错误(共享了不应共享的权重);

3. 权重冻结错误(冻结了不应冻结的权重);

4. 节点连接错误(应该连接到计算图中的 block 未连接);

5. loss 函数错误;

6. 优化器算法错误(如果自行实现了优化器)等。


建议通过检查模型代码的方式对模型结构进行检查。此外,MindInsight 也可以辅助用户对模型结构进行检查。大多数情况下,SummaryCollector 会自动记录计算图,通过 MindInsight,用户可以方便地对计算图进行查看。模型脚本运行后,建议使用 MindInsight 计算图可视模块查看模型结构,加深对计算图的理解,确认模型结构符合预期。若有标杆脚本,还可以同标杆脚本对照查看计算图,检查当前脚本和标杆脚本的计算图是否存在重要的差异。



考虑到模型结构一般都很复杂,期望在这一步就能发现所有的模型结构问题是不现实的。只要通过可视化的模型结构加深对计算图的理解,发现明显的结构问题即可。后面的步骤中,发现了更明确的精度问题现象后,我们还会回到这一步重新检查确认。


注 1:MindInsight 支持查看 SummaryCollector 记录的计算图和 MindSpore context 的 save_graphs 参数导出的 pb 文件计算图。请参考我们教程中的“计算图可视化”部分了解更多信息


注 2:脚本迁移工具可以将 PyTorch、TensorFlow 框架下编写的模型转换为 MindSpore 脚本,请访问教程以了解更多信息

4、检查输入数据


通过检查输入模型的数据,可以结合脚本判断数据处理流水线和数据集是否存在问题。输入数据的常见问题有:

1. 数据缺失值过多;

2. 每个类别中的样本数目不均衡;

3. 数据中存在异常值;

4. 数据标签错误;

5. 训练样本不足;

6. 未对数据进行标准化,输入模型的数据不在正确的范围内;

7. finetune 和 pretrain 的数据处理方式不同;

8. 训练阶段和推理阶段的数据处理方式不同;

9. 数据处理参数不正确等。


MindInsight 可以辅助用户对输入数据、数据处理流水线进行检查。大多数情况下,SummaryCollector 会自动记录输入模型的数据(数据处理后的数据)和数据处理流水线参数。输入模型的数据会展示在“数据抽样”模块,数据处理流水线参数会展示在“数据图”模块和“数据溯源”模块。通过 MindInsight 的数据抽样模块,可以检查输入模型的(数据处理流水线处理后的)数据。若数据明显不符合预期(例如数据被裁剪的范围过大,数据旋转的角度过大等),可以判断输入数据出现了一定的问题。通过 MindInsight 的数据图和数据溯源模块,可以检查数据处理流水线的数据处理过程和具体参数取值,从而发现不合理的数据处理方法




如果有标杆脚本,还可以同标杆脚本对照,检查数据处理流水线输出的数据是否和当前脚本的数据相同。例如,将数据处理流水线输出的数据保存为 npy 文件,然后使用 numpy.allclose()方法对标杆脚本和当前脚本的数据进行对比。如果发现不同,则数据处理阶段可能存在精度问题。


若数据处理流水线未发现问题,可以手动检查数据集是否存在分类不均衡、标签匹配错误、缺失值过多、训练样本不足等问题。

5、检查 loss 曲线


很多精度问题会在网络训练过程中发现,常见的问题或现象有:

1. 权重初始化不合理(例如初始值为 0,初始值范围不合理等);

2. 权重中存在过大、过小值;

3. 权重变化过大;

4. 权重冻结不正确;

5. 权重共享不正确;

6. 激活值饱和或过弱(例如 Sigmoid 的输出接近 1,Relu 的输出全为 0);

7. 梯度爆炸、消失;

8. 训练 epoch 不足;

9. 算子计算结果存在 NAN、INF;

10. 算子计算过程溢出(计算过程中的溢出不一定都是有害的)等。


上述这些问题或现象,有的可以通过 loss 表现出来,有的则难以观察。MindInsight 提供了针对性的功能,可以观察上述现象、自动检查问题,帮助您更快定位问题根因。例如:


  • MindInsight 的参数分布图模块可以展示模型权重随训练过程的变化趋势;

  • MindInsight 的张量可视模块可以展示张量的具体取值,对不同张量进行对比;

  • MindInsight 调试器内置了种类丰富,功能强大的检查能力,可以检查权重问题(例如权重不更新、权重更新过大、权重值过大/过小)、梯度问题(例如梯度消失、梯度爆炸)、激活值问题(例如激活值饱和或过弱)、张量全为 0、NAN/INF、算子计算过程溢出等问题。


调试器使用教程



大多数情况下,SummaryCollector 会自动记录模型的 loss 曲线,可以通过 MindInsight 的标量可视模块查看。loss 曲线能够反映网络训练的动态趋势,通过观察 loss 曲线,可以得到模型是否收敛是否过拟合等信息



大多数情况下,SummaryCollector 会自动记录模型参数变化情况(默认记录 5 个参数),可以通过 MindInsight 的参数分布图模块查看。如果想要记录更多参数的参数分布图,请参考SummaryCollector的histogram_regular参数,或参考HistogramSummary算子



张量不会被自动记录,如果想要通过 MindInsight 查看张量的具体取值,请使用TensorSummary算子


下面结合 loss 曲线的常见现象介绍使用 MindInsight 进行精度问题定位的思路。

5.1 loss 跑飞


loss 跑飞是指 loss 中出现了 NAN、+/-INF 或者特别大的值。loss 跑飞一般意味着算法设计或实现存在问题。定位思路如下:


1. 回顾脚本、模型结构和数据


1)检查超参是否有不合理的特别大/特别小的取值,

2)检查模型结构是否实现正确,特别是检查 loss 函数是否实现正确,

3)检查输入数据中是否有缺失值、是否有特别大/特别小的取值。


2. 观察训练看板中的参数分布图,检查参数更新是否有明显的异常。若发现参数更新异常,可以结合调试器定位参数更新异常的原因。3. 使用调试器模块对训练现场进行检查。


1)若 loss 值出现 NAN、+/-INF,可使用“检查张量溢出”条件添加全局监测点,定位首先出现 NAN、+/-INF 的算子节点,检查算子的输入数据是否会导致计算异常(例如除零)。若是算子输入数据的问题,则可以针对性地加入小数值 epsilon 避免计算异常。


2)若 loss 值出现特别大的值,可使用“检查过大张量”条件添加全局监测点,定位首先出现大值的算子节点,检查算子的输入数据是否会导致计算异常。若输入数据本身存在异常,则可以继续向上追踪产生该输入数据的算子,直到定位出具体原因。


3)若怀疑参数更新、梯度等方面存在异常,可使用“检查权重变化过大”、“检查梯度消失”、“检查梯度过大”等条件设置监测点,定位到异常的权重或梯度,然后结合张量检查视图,逐层向上对可疑的正向算子、反向算子、优化器算子等进行检查。

5.2 loss 收敛慢


loss 收敛慢是指 loss 震荡、收敛速度慢,经过很长时间才能达到预期值,或者最终也无法收敛到预期值。相较于 loss 跑飞,loss 收敛慢的数值特征不明显,更难定位。定位思路如下:


1. 回顾脚本、模型结构和数据


1)检查超参是否有不合理的特别大/特别小的取值,特别是检查学习率是否设置过小或过大,学习率设置过小会导致收敛速度慢,学习率设置过大会导致 loss 震荡、不下降;


2)检查模型结构是否实现正确,特别是检查 loss 函数、优化器是否实现正确;


3)检查输入数据的范围是否正常,特别是输入数据的值是否过小


2. 观察训练看板中的参数分布图,检查参数更新是否有明显的异常。若发现参数更新异常,可以结合调试器定位参数更新异常的原因。3. 使用调试器模块对训练现场进程检查。


1)可使用“检查权重变化过小”、“检查未变化权重”条件对可训练(未固定)的权重进行监测,检查权重是否变化过小。若发现权重变化过小,可进一步检查学习率取值是否过小、优化器算法是否正确实现、梯度是否消失,并做针对性的修复。


2)可使用“检查梯度消失”条件对梯度进行监测,检查是否存在梯度消失的现象。若发现梯度消失,可进一步向上检查导致梯度消失的原因。例如,可以通过“检查激活值范围”条件检查是否出现了激活值饱和、Relu 输出为 0 等问题。

5.3 其它 loss 现象


若训练集上 loss 为 0,一般说明模型出现了过拟合,请尝试增大训练集大小。

6、检查精度是否达到预期


MindInsight 可以为用户记录每次训练的精度结果。在 model.train 和 model.eval 中使用同一个 SummaryCollector 实例时,会自动记录模型评估(metrics)信息。训练结束后,可以通过 MindInsight 的模型溯源模块检查训练结果精度是否达标。



6.1 检查训练集上的精度


若训练集上模型的 loss 值、metric 值未达到预期,可以参考以下思路进行定位和优化:


1. 回顾代码、模型结构、输入数据和 loss 曲线


1)检查脚本,检查超参是否有不合理的值

2)检查模型结构是否实现正确

3)检查输入数据是否正确

4)检查 loss 曲线的收敛结果和收敛趋势是否存在异常


2. 尝试使用 MindInsight 溯源分析功能优化超参。溯源分析页面会对超参的重要性进行分析,用户应优先考虑调整重要性高的超参,从散点图中可以观察出超参和优化目标的关系,从而针对性地调整超参取值。




3. 尝试使用 MindInsight 调参器优化超参。请注意,调参器通过执行多次完整训练的方式进行超参搜索,消耗的时间为网络一次训练用时的若干倍,如果网络一次训练耗时较长,则超参搜索将需要很长的时间。调参器使用教程。尝试使用 MindInsight 模型解释功能优化模型和数据集。模型解释功能可以通过显著图可视化展示对分类结果最重要的区域,还可以通过评分体系提示应该对哪类标签进行优化。


模型解释使用教程


4. 尝试优化模型结构/算法。

6.2 检查验证集上的精度


若训练集精度和验证集精度都未达到预期,则应首先参考上一节检查训练集精度。若训练集精度已达到预期,但是验证集精度未达到预期,大概率是模型出现了过拟合,处理思路如下:


1. 检查验证集评估脚本的评估逻辑有无错误。特别是数据处理方式是否与训练集一致,推理算法有误错误,是否加载了正确的模型 checkpoint。


2. 增加数据量。包括增加样本量,进行数据增强和扰动等。


3. 正则化。常见的技术如参数范数惩罚(例如向目标函数中添加一个正则项  ),参数共享(强迫模型的两个组件共享相同的参数值),提前中止训练等。


4. 适当降低模型的规模。例如减少卷积层数等。

6.3 检查测试集上的精度


若验证集和测试集精度都未达到预期,则应首先参考上一节检查验证集精度。若验证集精度已达到预期,但是测试集精度未达到预期,考虑到测试集的数据是模型从未见过的新数据,原因一般是测试集的数据分布和训练集的数据分布不一致。处理思路如下:


1. 检查测试集评估脚本的评估逻辑有误错误。特别是数据处理方式是否与训练集一致,推理算法有误错误,是否加载了正确的模型 checkpoint。


2. 检查测试集中的数据质量,例如数据的分布范围是否明显同训练集不同,数据是否存在大量的噪声、缺失值或异常值。

7、小结


由于相同的现象存在多个可能原因,精度问题的定位非常依赖专家经验。希望上述定位方法和功能能够起到良好的引导的作用,帮助你不断积累成功经验,成为精度调优大师。


点击关注,第一时间了解华为云新鲜技术~

发布于: 3 小时前阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
MindSpore模型精度调优实战:常用的定位精度调试调优思路