我有一个问题,为什么用小stddev设置tensorflow的变量。 我想很多人都会测试来自tensorflow初学者指南的mnist测试代码。 如下所示,第一层的权重是通过使用truncated_normal和stddev 0.1来启动的。 我猜想如果将它设置为更大的值,那么它将是相同的结果,这正是准确性。 但是,虽然增加了纪元数,但它并没有起作用。 有人知道这个原因吗?
原文: W_layer = tf.Variable(tf.truncated_normal([inp.get_shape()[1] .value,size],stddev = 0.1),name =' w _' + name) 结果:(990,0.93000001,0.89719999)
修改: W_layer = tf.Variable(tf.truncated_normal([inp.get_shape()[1] .value,size],stddev = 200),name =' w _' + name) 结果:(99990,0.1,0.098000005)
答案 0 :(得分:3)
原因是因为您希望保持所有图层的差异(或标准偏差)大致相同,并且理智。它与学习过程的错误反向传播步骤和使用的激活函数有关。
为了学习网络的权重,反向传播步骤需要了解网络的梯度,这是衡量每个权重影响输入到达最终结果的强度的指标输出;层的权重方差直接影响梯度的传播。
例如,假设激活函数是sigmoidal(例如tf.nn.sigmoid
或tf.nn.tanh
);这意味着所有输入值都被压缩到固定的输出值范围内。对于sigmoid,它是范围0..1
,其中基本上所有大于或小于+/- 4的值z
非常接近于1(对于z > 4
)或零(对于{{ 1}})并且只有该范围内的值往往会有一些有意义的变化"。
现在价值z < -4
和sigmoid(5)
之间的差异几乎无法察觉。因此,所有非常大或非常小的值都会非常缓慢地优化,因为它们对结果sigmoid(1000)
的影响非常小。现在,激活前值y = sigmoid(W*x+b)
(其中z = W*x+b
是输入)取决于实际输入x
和当前权重x
。如果它们中的任何一个很大,例如通过以高方差(即标准偏差)初始化权重,结果必然(相对)大,导致所述问题。这也是为什么使用W
而不是正确的正态分布的原因:后者只保证大多数的值非常接近均值,少于5%的几率虽然情况并非如此,但truncated_normal
只会剪掉每个太大或太小的值,保证所有权重都在同一范围内,同时仍然是正态分布。
更糟糕的是,在典型的神经网络中 - 特别是在深度学习中 - 每个网络层后面跟着一个或多个其他网络层。如果在每一层中输出值范围都很大,那么渐变也会越来越大;这被称为爆炸梯度问题(消失梯度的变化,其中渐变越来越小)。 这是一个问题的原因是因为学习从最后一层开始,每个权重都根据它对错误的贡献程度进行调整。如果渐变确实在最后变得非常大,那么最后一层是第一个为此付出高代价的人:它的权重得到非常强烈的调整 - 可能过度纠正实际问题 - 然后只剩下&#34;剩下的& #34;错误进一步传播回网络或向上传播。在这里,因为最后一层已经被修复了很多&#34;关于测量误差,仅进行较小的调整。这可能导致第一层仅通过一点点或根本不进行校正的问题,从而有效地阻止了那里的所有学习。如果学习率太大,基本上也会发生这种情况。
找到最佳权重初始化本身就是一个主题,并且有一些更复杂的方法,如Xavier initialization或层序单位方差,但小的正态分布值通常只是一个很好的猜测。