fxmeng / RMNet

RM Operation can equivalently convert ResNet to VGG, which is better for pruning; and can help RepVGG perform better when the depth is large.
210 stars 29 forks source link

conv输出进入BN后有精度问题? #17

Open Serissa opened 2 years ago

Serissa commented 2 years ago

您好!我在做RM的时候发现,conv输出进入BN输出有精度问题?

        idconv1 = nn.Conv2d(self.in_planes, self.in_planes+self.mid_planes, kernel_size=3, stride=1, padding=1, bias=False).eval()
        idbn1 = nn.BatchNorm2d(self.in_planes+self.mid_planes).eval()
        # init dirac_ kernel weight, bias, mean var to idconv1
        nn.init.dirac_(idconv1.weight.data[:self.in_planes])
        bn_var_sqrt1 = torch.sqrt(self.running1.running_var + self.running1.eps)
        idbn1.weight.data[:self.in_planes] = bn_var_sqrt1
        idbn1.bias.data[:self.in_planes] = self.running1.running_mean
        idbn1.running_mean.data[:self.in_planes] = self.running1.running_mean
        idbn1.running_var.data[:self.in_planes] = self.running1.running_var
        # init conv1 to idconv1
        idconv1.weight.data[self.in_planes:] = self.conv1.weight.data
        idbn1.weight.data[self.in_planes:] = self.bn1.weight.data
        idbn1.bias.data[self.in_planes:] = self.bn1.bias.data
        idbn1.running_mean.data[self.in_planes:] = self.bn1.running_mean
        idbn1.running_var.data[self.in_planes:] = self.bn1.running_var

图片 左边三conv2d输出结果,右边三batchnorm2d输出结果,其中conv2d输出为0的值在batchnorm2d中输出成一个很小的值(1.6642e-08),请问这是什么原因造成的?如何修改代码消除这种现象。

fxmeng commented 2 years ago

您好!我在做RM的时候发现,conv输出进入BN输出有精度问题? 左边三conv2d输出结果,右边三batchnorm2d输出结果,其中conv2d输出为0的值在batchnorm2d中输出成一个很小的值(1.6642e-08),请问这是什么原因造成的?如何修改代码消除这种现象。

感谢关注RMNet,您所说的精度问题根据我的观察推测是由BN层引起的,按照使用场景:

  1. 带残差的网络训练完,转化为plain model后直接用于推理。此时通常并不需要BN层,因此可以在先去除BN层,再去残差,这种方案可以减小精度误差。代码如下: https://github.com/fxmeng/RMNet/blob/8b848b79a8863c4ea64afffaa0e5dd0de888ac70/models/easy_resnet2vgg.py https://github.com/fxmeng/RMNet/blob/e111ecc48cc8b8159b9e8584e8ba68eb3a9b829a/models/easy_mb2_mb1.py
  2. 带残差的网络训练完,转化为plain model后,还想要继续finetune。此时由于精度问题导致的准确率变化,一般小到可以忽略不计,直接finetune就可以。注意,bn层在训练过程中是很有用的,若需要finetune,就不要去掉bn层。
Serissa commented 2 years ago

理解了,谢谢!