0%

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
45
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")