MindSpore静态LossScale和动态LossScale的区别

背景信息

在混合精度中,使用float16类型来替代float32类型存储数据,从而达到减少内存和提高计算速度的效果。但是由于float16类型要比float32类型表示的范围小很多,所以当某些参数(比如说梯度)在训练过程中变得很小时,就会发生数据下溢的情况,进而影响网络精度。而loss scale正是为了解决float16类型数据下溢问题的,LossScale的主要思想是在计算loss时,将loss扩大一定的倍数,由于链式法则的存在,梯度也会相应扩大,然后在优化器更新权重时再缩小相应的倍数,从而避免了数据下溢的情况又不影响计算结果;而LossScale又可分为静态LossScale与动态LossScale。

MindSpore中提供了两种Loss Scale的方式,分别是FixedLossScaleManager和DynamicLossScaleManager,需要和Model配合使用。在使用Model构建模型时,可配置混合精度策略amp_level和Loss Scale方式loss_scale_manager。

1、静态LossScale

LossScale在训练过程中使用固定scale的值,且在训练过程中不会改变scale的值,scale的值由入参loss_scale控制,可以由用户指定,不指定则取默认值。

静态LossScale算子的另一个参数是drop_overflow_update,用来控制发生溢出时是否更新参数。

一般情况下LossScale功能不需要和优化器配合使用,但如果drop_overflow_update为False,那么优化器需设置loss_scale的值,且loss_scale的值要与静态LossScale算子相同。

FixedLossScaleManager具体用法如下:

1.import必要的库,并声明使用图模式下执行。

import numpy as npimport mindspore as msimport mindspore.nn as nnfrom mindspore.nn import Accuracyfrom mindspore.common.initializer import Normalfrom mindspore import dataset as ds
#ms.set_seed(0)ms.set_context(mode=ms.GRAPH_MODE, device_target="GPU")

2.定义LeNet5网络模型,任何网络模型都可以使用Loss Scale机制。

class LeNet5(nn.Cell):
    """        Lenet network
        Args:            num_class (int): Number of classes. Default: 10.            num_channel (int): Number of channels. Default: 1.
        Returns:            Tensor, output tensor    """
    def __init__(self, num_class=10, num_channel=1):
        super(LeNet5, self).__init__()
        self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')
        self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')
        self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))
        self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02))
        self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02))
        self.relu = nn.ReLU()
        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
        self.flatten = nn.Flatten()

    def construct(self, x):
        x = self.max_pool2d(self.relu(self.conv1(x)))
        x = self.max_pool2d(self.relu(self.conv2(x)))
        x = self.flatten(x)
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x)
        return x

3.定义数据集和训练流程中常用的接口。

# create datasetdef get_data(num, img_size=(1, 32, 32), num_classes=10, is_onehot=True):
    for _ in range(num):
        img = np.random.randn(*img_size)
        target = np.random.randint(0, num_classes)
        target_ret = np.array([target]).astype(np.float32)
        if is_onehot:
            target_onehot = np.zeros(shape=(num_classes,))
            target_onehot[target] = 1
            target_ret = target_onehot.astype(np.float32)
        yield img.astype(np.float32), target_ret
def create_dataset(num_data=1024, batch_size=32, repeat_size=1):
    input_data = ds.GeneratorDataset(list(get_data(num_data)), column_names=['data', 'label'])
    input_data = input_data.batch(batch_size, drop_remainder=True)
    input_data = input_data.repeat(repeat_size)
    return input_data
ds_train = create_dataset()
# Initialize networknetwork = LeNet5(10)
# Define Loss and Optimizernet_loss = nn.SoftmaxCrossEntropyWithLogits(reduction="mean")

   4.真正使用Loss Scale的API接口,作用于优化器和模型中。

# Define Loss Scale, optimizer and model

#1) Drop the parameter update if there is an overflow

loss_scale_manager = ms.FixedLossScaleManager()

net_opt = nn.Momentum(network.trainable_params(), learning_rate=0.01, momentum=0.9)

model = ms.Model(network, net_loss, net_opt, metrics={"Accuracy": Accuracy()}, amp_level="O0", loss_scale_manager=loss_scale_manager)



#2) Execute parameter update even if overflow occurs

loss_scale = 1024.0

loss_scale_manager = ms.FixedLossScaleManager(loss_scale, False)

net_opt = nn.Momentum(network.trainable_params(), learning_rate=0.01, momentum=0.9, loss_scale=loss_scale)

model = ms.Model(network, net_loss, net_opt, metrics={"Accuracy": Accuracy()}, amp_level="O0", loss_scale_manager=loss_scale_manager)



# Run training

model.train(epoch=10, train_dataset=ds_train, callbacks=[ms.LossMonitor()])



TotalTime = 0.639526, [19]
[parse]: 0.00137553
[symbol_resolve]: 0.0630952, [1]
    [Cycle 1]: 0.0626392, [1]
        [resolve]: 0.0626309
[combine_like_graphs]: 0.00123225
[inference_opt_prepare]: 0.000407694
[elininate_unused_parameter]: 0.000182617
[abstract_specialize]: 0.0623443
[auto_monad]: 0.00156646
[inline]: 1.93249e-06
[py_pre_ad]: 9.71369e-07
[pipeline_split]: 2.88989e-06
[optimize]: 0.477379, [14]
    [simplify_data_structures]: 0.00029841
    [opt_a]: 0.473795, [3]
        [Cycle 1]: 0.450451, [25]
            [expand_dump_flag]: 1.45491e-05
            [switch_simplify]: 0.000713205
            [a_1]: 0.00994622
            [recompute_prepare]: 8.40612e-05
            [updatestate_depend_eliminate]: 0.000666355
            [updatestate_assign_eliminate]: 6.59283e-05
            [updatestate_loads_eliminate]: 0.000232871
            [parameter_eliminate]: 2.64868e-06
...
 0.16% :     0.000156s :      1: opt.transforms.opt_after_cconv
 0.04% :     0.000044s :      1: opt.transforms.opt_b
 0.24% :     0.000240s :      1: opt.transforms.opt_trans_graph
 0.02% :     0.000018s :      1: opt.transforms.stop_gradient_special_op
epoch: 1 step: 32, loss is 2.301311731338501
epoch: 2 step: 32, loss is 2.2960867881774902
epoch: 3 step: 32, loss is 2.292977809906006
epoch: 4 step: 32, loss is 2.2935791015625
epoch: 5 step: 32, loss is 2.3079633712768555
epoch: 6 step: 32, loss is 2.3191769123077393
epoch: 7 step: 32, loss is 2.3069581985473633
epoch: 8 step: 32, loss is 2.2944517135620117
epoch: 9 step: 32, loss is 2.3150291442871094
epoch: 10 step: 32, loss is 2.3247132301330566

2、动态LossScale

LossScale在训练过程中可以动态改变scale值的大小,在没有发生溢出(此处为上溢出)的情况下,要尽可能保持较大的scale的值。如果发生了溢出(上溢出),将缩小scale的值。

名词解释:

**上溢出:**数值超出最大表示范围。如表示区间为0~65504,那么当进行50000 + 50000的操作时,则会发生上溢出,输出结果可能是65500。

**下溢出:**数值小于最小表示精度。如最小表示精度为6e-8,那么当进行8e-8 / 10的操作时,则会发生下溢出,输出结果可能是0。

DynamicLossScaleManager会首先将scale设置为一个初始值,该值由入参init_loss_scale控制。

在训练过程中,如果不发生溢出,在更新scale_window次参数后,会尝试扩大scale的值,如果发生了溢出,则跳过参数更新,并缩小scale的值,入参scale_factor是控制扩大或缩小的步数,scale_window控制没有发生溢出时,最大的连续更新步数。

具体用法如下,仅需将FixedLossScaleManager样例中定义LossScale,优化器和模型部分的代码改成如下代码:

# Define Loss Scale, optimizer and model

scale_factor = 4

scale_window = 3000

loss_scale_manager = ms.DynamicLossScaleManager(scale_factor, scale_window)

net_opt = nn.Momentum(network.trainable_params(), learning_rate=0.01, momentum=0.9)

model = ms.Model(network, net_loss, net_opt, metrics={"Accuracy": Accuracy()}, amp_level="O0", loss_scale_manager=loss_scale_manager)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值