代码
【MindSpore易点通】精度问题定位经验总结

【MindSpore易点通】精度问题定位经验总结

【MindSpore易点通】精度问题定位经验总结

训练准备阶段CheckList

首先需要

1、了解MindSpore的基本信息

2、准备用MindSpore进行脚本开发或者脚本已经开发完成

为了保证网络训练过程正确,进行下一步训练之前,请做以下几点检查:

网络定义

1、注意MindSpore中SGD优化器和Momentum优化器中的momentum参数与PyTorch中实现一致。但是BN中的momentum参数与PyTorch不一致。具体关系描述如下: MindSpore中BatchNorm1d/BatchNorm2d的momentum参数(定义该参数的变量名称为momentum_ms),该参数与PyTorch里BN的momentum参数(定义该参数的变量名称为momentum_py)的关系为:

momentum_ms = 1 - momentum_py

2、注意MindSpore中Dropout的keep_prob参数,与PyTorch里dropout的p参数不一致,其对应关系为:

keep\_prob = 1 - p

混合精度配置

若您使用的是MindSpore+Ascend的组合进行训练,请注意Ascend为了加速训练,卷积只能使用FP16类型进行计算,因此您的训练过程默认就是混合精度。 为了保证训练过程正确,请在网络定义的时候配置混合精度级别,可参看混合精度中的使用方法。为了保证混合精度训练过程不溢出,需要配合使用Loss Scale功能。

训练中精度CheckList

训练中应该已经完成:

1、训前必做的检查事项

2、开始进行MindSpore的训练,可以输出第一个Step的Loss值

为了保证网络训练过程正确,进行多Epoch迭代之前,请按照顺序做以下几点检查。

检查1:首个Step的前向Loss值是否正确

1、先做变量对齐

结果:若变量对齐之后Loss值一致,说明是初始化问题或者脚本迁移有错误,修改初始化或者对齐脚本后解决。若Loss值仍不同,则转到2。

2、使用Print算子在网络结构中二分法打印算子的正向输出,找到正向精度出现问题的算子。MindSpore的Print算子使用说明,原始迁移脚本可以根据框架特点加入打印,例如PyTorch框架可以直接print节点的正向输出。

结果:找到第一个精度不对的算子,转到3;若所有正向算子精度都一致,那么转到检查2。

3、思考是否能够用别的算子做替换精度有问题的算子,可以查看 API 映射表

结果:替换算子进行训练,观察第一个Loss值能否对应上,若不能则转到4。

4、该算子不可替换,向华为反馈该算子正向精度问题

结果:反馈完成后等待回复。

检查2:首个Step的反向梯度值是否正确

1、先做检查1,保证第一个Step的Loss值能够一致,转到2。

2、使用Print算子在网络结构中二分法打印算子的反向输出,找到反向精度出现问题的算子。MindSpore的Print算子使用说明,原始迁移脚本可以根据框架特点加入反向打印,例如PyTorch框架可以通过register_hook打印节点的反向梯度。

结果:找到第一个反向梯度精度不对的算子,转到3;若所有算子反向梯度都能对应一致,那么转到检查3。

3、思考是否能够用别的算子做替换精度有问题的算子,可以查看API 映射表

结果:替换算子进行训练,看反向梯度能否对应,若不能转到4。

4、该算子不可替换,向华为反馈该算子反向精度问题

检查3:经过第一个Step后权重更新是否正确

1、先做检查1和检查2,保证第一个Step的前向输出和反向梯度能够和原始迁移脚本一致,转到2。

2、保存MindSpore的初始化权值文件,假设名字为ms_checkpoint1。跑一个训练Step后再保存一次更新过后的权值文件,假设名字为ms_checkpoint2。

3、分别对ms_checkpoint1和ms_checkpoint2的相同层进行参数打印,并比较参数是否更新,若不更新转到5,正常更新转到4。

4、保存原始迁移脚本在跑一个训练Step后的权值文件,例如PyTorch保存权值为pt_checkpoint,分别对pt_checkpoint和ms_checkpoint2的相同层进行参数打印,并比较参数更新后是否一致,若不一致则转到5,一致则可以进行多Epoch的收敛实验。

5、若参数不能更新或者参数更新错误,思考是否能够用别的优化器。若不能,则向华为反馈该优化器更新问题。

精度问题定位思路

首先确定已经完成:

1、训前必做的检查事项;

2、开始进行MindSpore的多轮训练,可以画出迭代的Loss变化曲线或者可以在验证集/测试集上测试精度

精度问题可能分为以下几种场景:

场景1:Loss不能收敛

1、定位是否是算子前向或者反向的精度问题,或者是优化器更新问题,可以参考训中指导

场景2:脚本迁移场景下Loss可以收敛,收敛曲线和基线相比差异大或者不能收敛到相同位置,精度不达标

1、检查超参数的设置是否正确(例如优化器的weight decay、优化器的momentum、初始学习率、Dropout的prop和bn的momentum),框架迁移的场景检查初超参数设置是否和原始脚本一致,重头在MindSpore上开发的场景检查超参数设置是否符合预期。

2、检查初始化方式是否正确,框架迁移的场景检查初始化方式和结果是否和原始脚本一致,重头在MindSpore上开发的场景检查初始化结果是否符合预期。

3、检查混合精度是否正确。

4、检查学习率调整的策略是否正确(例如lr schedule以及warmup策略)。

5、多卡(多机)训练场景检查是否真正跑的是数据并行或者模型并行,参考并行检查。

6、定位是否是算子前向或者反向的精度问题,或者是优化器更新问题,可以参考训中指导

场景3:loss可以收敛,收敛曲线一致(脚本迁移场景下),但精度不达标

1、检查测试脚本是否使用Dropout算子,需要在测试阶段手动把Dropout算子去掉

2、检查测试脚本是否把网络Cell对象的set_train属性设置为False(目前只影响BN的mean和variance计算方式,训练模式下mean和variance是在训练期间被计算的,若推理模式下mean和variance是从checkpoint里面load出来的),使用Model接口的eval或者predict方法可以不用做这个检查(这些方法里会自动把Cell对象的set_train属性设置为False)。