深度学习模型的权重初始化

Initialisation of weights for deeplearning model

我正在阅读一本关于深度学习的书,它将两层神经元之间的权重初始化为:

w = np.random.randn(layers[i] + 1, layers[i + 1] + 1)
self.W.append(w / np.sqrt(layers[i]))

根据本书,在第二行代码中按 np.sqrt(layers[i]) 进行除法,原因如下:

scale w by dividing by the square root of the number of nodes in the current layer, thereby normalizing the variance of each neuron’s output

具体是什么意思?如果我们不这样做,会有什么影响?

权重初始化对于处理 vanishing/Explosion 梯度非常重要。为了使 output/gradients(反向)正确流动,每层输出的 方差 等于其输入的方差。反方向的梯度也是如此。层的输入和输出流称为层的fan-infan-out

为了更好地解释我上面的意思,让我举个例子。假设我们有 100 个连续的层,我们应用线性激活的前馈计算(毕竟它只是矩阵乘法),数据是 100 个特征的 500 个样本:

neurons, features = 100, 100
n_layers = 100

X = np.random.normal(size=(500, features))  # your input
mean, var = 0, 0
for layer in range(n_layers):
    W = np.random.normal(size=(features, neurons))
    X = np.dot(X, W)
    mean = mean + X.mean()
    var = var + X.var()
mean/n_layers, np.sqrt(var/n_layers)

# output:
(-4.055498760574568e+95, 8.424477240271639e+98)

你会发现它会有很大的均值和标准差。让我们分解这个问题;矩阵乘法的 属性,其结果的标准差非常接近 fan in(输入)连接数的平方根。这个 属性 可以用这段代码验证:

fan_in = 1000  # change it to any number

X = np.random.normal(size=(100, fan_in)) 
W = np.random.normal(size=(fan_in, 1))

np.dot(X, W).std()

# result:
32.764359213560454

发生这种情况是因为我们对输入 X 的一个元素乘以 W 的一列的逐元素乘积求和 fan_in(在上述情况下为 1000)。因此,如果我们按比例缩放每个权重1/sqrt(fan_in) 以保持流量分布,如以下代码段所示:

neurons, features = 100, 100
n_layers = 100

X = np.random.normal(size=(500, features))  # your input
mean, var = 0, 0
for layer in range(n_layers):
    W = np.random.normal(size=(features, neurons), scale=np.sqrt(1 / neurons))  # scaled the weights with the fan-in 
    X = np.dot(X, W)
    mean = mean + X.mean()
    var = var + X.var()
mean/n_layers, np.sqrt(var/n_layers)

# output:
(0.0002608301398189543, 1.021452570914829)

您可以在下面阅读有关内核初始化的更多信息blog