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

时间:2019-10-12 15:51:54

标签: deep-learning variance

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

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

根据这本书,由于以下原因,在第二行代码中用np.sqrt(layers [i])进行了除法:

  通过除以当前层中节点数的平方根来缩放w   归一化每个神经元输出的差异

这到底是什么意思?如果我们不这样做,会产生什么影响?

1 个答案:

答案 0 :(得分:0)

权重初始化对于解决消失/爆炸梯度非常重要。为了使输出/渐变(反向)正常流动,每层输出的方差等于其输入方差。反向的梯度也是如此。一层的输入和输出流称为该层的 fan-in fan-out

为了更好地解释我的意思,让我举一个例子。假设我们有一百个连续的层,并且我们应用了具有线性激活的前馈计算(毕竟这只是矩阵乘法),数据是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 个的平方根。可以使用以下代码段验证此属性:

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

中阅读有关内核初始化的更多信息。