背景信息
在混合精度中,使用float16类型来替代float32类型存储数据,从而达到减少内存和提高计算速度的效果。但是由于float16类型要比float32类型表示的范围小很多,所以当某些参数(比如说梯度)在训练过程中变得很小时,就会发生数据下溢的情况。而动态更新网络结构中的loss scale正是为了解决float16类型数据下溢问题的,loss scale的主要思想是在计算loss时,将loss扩大一定的倍数,由于链式法则的存在,梯度也会相应扩大,然后在优化器更新权重时再缩小相应的倍数,从而避免了数据下溢的情况又不影响计算结果。
在MindSpore中,LossScale的使用方法又分动态loss scale和静态loss scale两种,二者具体区别详见静态LossScale和动态LossScale的区别。
1、接口详解
DynamicLossScaleManager
继承了LossScaleManager
类,在训练过程中可以动态改变scale的大小,在没有发生上溢出的情况下,要尽可能保持较大的scale。DynamicLossScaleManager
会首先将scale设置为一个初始值,该值由入参init_loss_scale控制。在训练过程中,如果不发生上溢出,在更新scale_window次参数后,会尝试扩大scale的值;如果发生了上溢出,则跳过参数更新,并缩小scale的值,入参scale_factor是控制扩大或缩小的步数,scale_window控制没有发生溢出时,最大的连续更新步数。
2、示例代码段
from mindspore import Model, nn, DynamicLossScaleManager
#Define network
net = resnet()
#Define loss_scale_manager
loss_scale_manager = DynamicLossScaleManager(init_loss_scale=2**24, scale_factor=4, scale_window=3000)
net = Model(net, loss, opt, metrics=metrics, loss_scale_manager=loss_scale_manager)
2.1、关键代码解析
loss_scale_manager = DynamicLossScaleManager(init_loss_scale=2**24, scale_factor=4, scale_window=3000)
**功能:**定义一个动态LossScale的控制器。指定LossScale的初始值为init_loss_scale。当训练发生上溢出时,将执行init_loss_scale=init_loss_scale/scale_factor。如果连续scale_window个step没有发生上溢出,则执行init_loss_scale=init_loss_scale*scale_factor。
参数注解:
init_loss_scale:
初始化的LossScale,默认值2**24。
scale_factor:
增减系数,默认值为2。
scale_window:
当overflow为False时最大连续正常步数。