Notes on Delving Deep into Rectifiers

在 ImageNet 数据集上面的准确率首次超越人类. 该论文中主要贡献了两点, 一是 Parameter ReLU, 二是一种新的参数初始化的方法. 这篇论文比 Batch Normalization 稍微早了几天, Batch Normalization 在 ImageNet 上面的准确率也是超越人类.

Parameter ReLU

所谓的 PReLU 其实很简单, 如下图, 左边是 ReLU, 右边是 PReLU, 不同点是, ReLU 在小于 0 的时候全部为0, 而 PReLU 在小于 0 的时候 为 \(ax\)


在实际的实验中发现, PReLU 在数据量不是很大的时候基本上没有什么效果, 对模型准确率基本上没有贡献, 但是, 当数据量很大, 例如百万级的数据量的时候, 对准确率有提升作用.

Kaiming Init Method

我个人认为, 这篇论文中更重要的地方是 kaiming 提出的一种新的初始化模型的方法. 具体过程可以参考原论文, 这里给出结论和代码.
初始化仍然是使用一个正态分布来产生,该正态分布是 \(N\left(0, \sqrt{\frac{2}{n_{l}}}\right)\), 其中, \(n_{l}\) 输入的节点个数. MXNet 源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Xavier(Initializer):
"""Initialize the weight with Xavier or similar initialization scheme.
Parameters
----------
rnd_type: str, optional
Use ```gaussian``` or ```uniform``` to init
factor_type: str, optional
Use ```avg```, ```in```, or ```out``` to init
magnitude: float, optional
scale of random number range
"""
# 若使用上述的 kaiming init method, 设置 rnd_type=gaussian, factor_type='in',
# magnitude=2
def __init__(self, rnd_type="uniform", factor_type="avg", magnitude=3):
self.rnd_type = rnd_type
self.factor_type = factor_type
self.magnitude = float(magnitude)
def _init_weight(self, _, arr):
shape = arr.shape
hw_scale = 1.
if len(shape) > 2:
hw_scale = np.prod(shape[2:])
fan_in, fan_out = shape[1] * hw_scale, shape[0] * hw_scale
factor = 1.
if self.factor_type == "avg":
factor = (fan_in + fan_out) / 2.0
elif self.factor_type == "in":
factor = fan_in
elif self.factor_type == "out":
factor = fan_out
else:
raise ValueError("Incorrect factor type")
scale = np.sqrt(self.magnitude / factor)
if self.rnd_type == "uniform":
random.uniform(-scale, scale, out=arr)
elif self.rnd_type == "gaussian":
random.normal(0, scale, out=arr)
else:
raise ValueError("Unknown random type")