在阅读了著名论文Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification之后,我明白了两件事:-
他的初始化借鉴了 Xavier 初始化的好处,只是后者期望线性激活,而先验考虑了 ReLU 非线性激活。事实上,它们仅相差一个因素
sqrt(2)。所有的大惊小怪都是关于通过 Xavier 初始化实现的具有 0 均值和 1 标准的层,但是当使用 ReLU 时,负数被剪裁,因此均值上升,因此 He 初始化引入了 sqrt(2) 校正项,这有助于更好地训练。
所以我的问题是关于基本的 ResBlock 几乎一致地实现如下,
class ResBlock(nn.Module):
def __init__(self,in_c):
super(ResBlock, self).__init__()
self.conv1 = nn.Conv2d(in_c,in_c, kernel_size=3, stride=1, padding=1, bias=True)
self.conv2 = nn.Conv2d(in_c,in_c, kernel_size=3, stride=1, padding=1, bias=True)
self.relu = nn.LeakyReLU(negative_slope=0.2, inplace=True)
def forward(self, x):
identity = x
out = self.relu(self.conv1(x))
#out = F.leaky_relu_(out, negative_slope=0.2)
out = self.conv2(out)
out = out + identity
return out
注意,conv2后面不跟ReLU,只有Conv1后面跟ReLU。因此conv2应该有 Xavier init 和Conv1He init。但主要的做法是对两者都使用 He init。这不是错的吗?
- -编辑 - -
或者,我们可以conv2使用“泄漏参数,a=1”Conv1进行 He 初始化,并使用“泄漏参数 a=0”进行 He 初始化。泄漏参数用于计算适当的增益。但是主要的做法是对两者都使用 He init,并将泄漏参数设置为 0。这不是错的吗?
“泄漏参数 a”是在卷积层之后使用的 ReLU 激活的负斜率。检查此以获取更多信息。
谢谢