深度学习模型的权重初始化
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-in和fan-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
我正在阅读一本关于深度学习的书,它将两层神经元之间的权重初始化为:
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-in和fan-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