重参数技巧的简述
大家好,我是灿视。
今天来聊聊重参数技巧~ 现在说的重参数技巧主要是两方面,一种是用于生成模型中的重参数技巧,一种是目前比较火的
等合并参数的技巧。我这里也主要讨论下这两种技巧,简单的分享一下哈~
水平有限,如有错误,恳请批评指正~
欢迎各位关注我们,关注最硬核的计算机视觉算法面经!!
生成模型中的重参数技巧
生成模型很多,主要包括如
,
为代表及其一系列变形的生成模型。我们今天主要聊聊
~
当然,不是我的老乡,
许嵩哈。
抱歉,不是我
今天说到的
长这个样子:
具体的
推导,后面我们会进行详细描述,其中会涉及到变分的东西。今天我们来看下其重参数技巧。
如右边的操作,就是运用了
的技巧。
左边的
方案,即我们从一个分布中,进行采样,来生成一个图片。而由于
, 我们应该从
采样, 但这个采样操作对
和
是不可导的, 导致常规的通过误差反传的梯度下降法 (GD) 不能使用。
而通过
, 我们首先从
上采样
, 然后,
。这样,
, 而且,
是编码器网络的输出, 只涉及线性操作,
对神经网络而言只是常数
, 因此, 可 以正常使用梯度下降进行优化。
对于
具体推导的细节以及其损失函数,我们后面会详细进行介绍的。这里我们只是简单介绍下
的重参数技巧。
网络结构中的重参数技巧
我这里主要也给大家分享下,在网络结构中的重参数技巧。
- 卷积层 BN层融合 卷积层公式为:
而BN层公式为:
然后我们将卷积层结果带入到BN公式中:
进一步化简为
这其实就是一个卷积层, 只不过权盖考虑了BN的参数。 我们令:
最终的融合结果即为:
- RepVGG
RepVGG结构示意图
中主要的改进点包括:
- 在
网络的
块中加入了
和残差分支,相当于把
网络中的精华应用 到
网络中;
- 模型推理阶段,通过
融合策略将所有的网络层都转换为
*
,便于模型的部署与加速。
- 网络训练和网络推理阶段使用不同的网络架构,训练阶段更关注精度,推理阶段更关注速度。
Reparameter的操作
上图展示了模型推理阶段的重参数化过程,其实就是一个 OP 融合和 OP 替换的过程。图 A 从结构化的角度展示了整个重参数化流程, 图 B 从模型参数的角度展示了整个重参数化流程。整个重参数化步骤如下所示:
- 首先通过式3将残差块中的卷积层和BN层进行融合。途中第一个蓝色箭头上方,完成了几组卷积与
的融合。包括执行
*
层的融合,图中的黑色矩形框中执行
*
层的融合,图中的黄色矩形框中执行
*
(卷积核设置为全1)
层的融合 融合的公式为:
。
其中
表示转换前的卷积层参数,
表示BN层的均值,
表示BN层的方差,
和
分别表示BN层的尺店因子和偏移因 子,
和b'分别表示融合之后的卷积的权重和偏置。
将融合后的卷积层转换为
*
,即将具体不同卷积核的卷积均转换为具有
*
大小的卷积核的卷积。由于整个残差块中可能包含
*
分支和
两种分支。对于
*
分支而言,整个转换过程就是利用
*
的卷积核替换
*
的卷积核,即将
*
卷积核中的数值移动到
*
卷积核的中心点即可;对于
分支 而言,该分支并没有改变输入的特征映射的数值,那么我们可以设置一个
*
的卷积核,将所有的
个位置处的权重值都设置为1,那么它与输入的特征映射相乘之后,保持了原来的数值。
合并残差分支中的
*
。即将所有分支的权重
和偏置
叠加起来,从而获得一个融合之后的
*
网络层。
参考代码:
代码语言:javascript复制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
总结
今天给大家分享了两个重参数技巧。一个是用于生成模型中,一个是用于网络结构中。对于生成模型,重参数技巧可以解决条件概率不可积分的问题。对于网络结构中,重参数技巧,可以加速网络的前向部署速度。
针对对应的细节,我们会单独说到。欢迎各位持续关注我们哦~