首页 Paddle框架 帖子详情
batch_norm_grad输出的Output为0,导致后续出错
收藏
快速回复
Paddle框架 问答深度学习模型训练 1077 2
batch_norm_grad输出的Output为0,导致后续出错
收藏
快速回复
Paddle框架 问答深度学习模型训练 1077 2

现象

跑用户的一个模型,单机单卡、单机单卡关闭L2Decay、多机nccl2接口分布式、多机fleet接口分布式下,均出现batch_norm_grad获取的conv1_bn_offset@GRAD的shape为0,见下图log。
image

该错误在上述不同单机多机下的表现形式又不一样:

  1. fleet多机运行出现allreduce中tensor未初始化现象
    image

  2. nccl2的log中,conv1_bn_offset@GRAD应该初始化了的,不过size仍然为0。且在之后的L2Decay正则化过程中,shape被_generated_var_0给重新扭回去了
    image
    image

  3. 单机单卡中,size也为0,且在L2Decay中shape给Infer回去了
    image

  4. 单机单卡未加正则化,size一样为0,且在MomentumOp中出错。
    image

  5. 分布式开fuse策略,一开始conv1_bn_offset@GRAD的shape正常。原因在fuse的时候直接用的给grad赋param Shape。
    image

// Init the output as input
for (size_t i = 0; i < in_tensors.size(); ++i) {
out_vars[i]->GetMutable<framework::LoDTensor>()->Resize(
in_tensors[i]->dims());
}

原因分析

  1. batch norm中代码问题
    if (ctx->HasOutput(framework::GradVarName("Scale"))) {
    PADDLE_ENFORCE(ctx->HasOutput(framework::GradVarName("Bias")),
    "Output(Scale@GRAD) and Output(Bias@GRAD) should not be "
    "null at same time");
    }

    if (ctx->HasOutput(framework::GradVarName("Scale"))) {
    ctx->SetOutputDim(framework::GradVarName("Scale"), {C});
    ctx->SetOutputDim(framework::GradVarName("Bias"), {C});
    }

    上面代码段中,当没有framework::GradVarName("Scale")时则不会给Bias的梯度赋Shape,恰好符合log中的情况。
  2. 用户代码问题
    后查阅用户代码,其中有一段逻辑写的或许不太符合常理。其中scale设置为冻结参数,bias却是可学习的。
    4404EA4C12E01A443C31FF4854590DBA
    后询问用户,这个写的是有问题的,一般要么两者都可学习,要么两者都冻结。
    在paddle实际计算grad norm梯度的过程也是这么处理的。不过有个有个问题,是否用户有一个冻结一个不冻结的需求?
    if (d_scale && d_bias) {

总结

上面的错误有很多环节都出了问题

  1. batch_norm_grad的Infer Shape出了问题,需要修复。另:是否有Scale和Bias一个可训练,一个不可训练的需求
  2. allreduce对于shape的判断不严谨,需要有>0的判断
  3. WeightDecay中对于shape没有加判断,导致错误的shape也能使用,且给Infer回去了。
  4. fuse策略下直接给grad赋param的Shape值,这个没有问题,不过却绕过了此issue中的错误。
  5. nccl2接口和fleet接口,size为0的tensor,一个初始化了,一个未初始化,和fleet加的策略有关系,需查明。
0
收藏
回复
全部评论(2)
时间顺序
AIStudio791030
#2 回复于2019-12

#21801
这个PR解决了前两个问题。

  1. batch_norm_grad的Infer Shape逻辑加上了要么scale和bias都训练,要么都不训练。
  2. allreduce加上shape需>0的判断。
0
回复
AIStudio791030
#3 回复于2019-12

第5个问题:
用户的代码中在使用nccl2接口时设置build_strategy.memory_optimize为True,fleet接口未设置。 设置为True时,shape={0}的tensor会初始化,未设置时shape={0}的tensor不初始化。

具体原因

因为显存复用策略可能会让它初始化

同时这个策略不推荐使用了,没必要设置这个。

0
回复
需求/bug反馈?一键提issue告诉我们
发现bug?如果您知道修复办法,欢迎提pr直接参与建设飞桨~
在@后输入用户全名并按空格结束,可艾特全站任一用户