干货|深度学习中的重参数技巧
极市导读
本文介绍的重参数技巧主要包含两方面,一种是用于生成模型中的重参数技巧,一种是目前比较火的RepVGG等合并参数的技巧。
重参数技巧的简述
网络结构中的重参数技巧
卷积层+BN层融合
卷积层公式为:
而BN层公式为:
然后我们将卷积层结果带入到BN公式中:
进一步化简为
这其实就是一个卷积层, 只不过权盖考虑了BN的参数。我们令:
最终的融合结果即为:
RepVGG
在 网络的 块中加入了 和残差分支,相当于把 网络中的精华应用 到 网络中; 模型推理阶段,通过 融合策略将所有的网络层都转换为 * ,便于模型的部署与加速。 网络训练和网络推理阶段使用不同的网络架构,训练阶段更关注精度,推理阶段更关注速度。
首先通过式3将残差块中的卷积层和BN层进行融合。途中第一个蓝色箭头上方,完成了几组卷积与的融合。包括执行 * +层的融合,图中的黑色矩形框中执行 * +层的融合,图中的黄色矩形框中执行 * (卷积核设置为全1)+层的融合
融合的公式为:
将融合后的卷积层转换为 * ,即将具体不同卷积核的卷积均转换为具有 * 大小的卷积核的卷积。由于整个残差块中可能包含 * 分支和两种分支。对于 * 分支而言,整个转换过程就是利用 * 的卷积核替换 * 的卷积核,即将 * 卷积核中的数值移动到 * 卷积核的中心点即可;对于分支 而言,该分支并没有改变输入的特征映射的数值,那么我们可以设置一个 * 的卷积核,将所有的个位置处的权重值都设置为1,那么它与输入的特征映射相乘之后,保持了原来的数值。
合并残差分支中的 * 。即将所有分支的权重和偏置叠加起来,从而获得一个融合之后的 * 网络层。
参考代码:
def _fuse_bn_tensor(self, branch):
if branch is None:
return 0, 0
if isinstance(branch, nn.Sequential):
kernel = branch.conv.weight
running_mean = branch.bn.running_mean
running_var = branch.bn.running_var
gamma = branch.bn.weight
beta = branch.bn.bias
eps = branch.bn.eps
else:
...
std = (running_var + eps).sqrt()
t = (gamma / std).reshape(-1, 1, 1, 1)
return kernel * t, beta - running_mean * gamma / std
总结
赞 (0)