为什么用小stddev设置tensorflow变量的原因

sem*_*ari 2 variables tensorflow

我有一个关于为什么将 TensorFlow 变量设置为small 的问题stddev。我想很多人都会从 TensorFlow 初学者指南中测试 MNIST 测试代码。接下来,第一层的权重使用0.1truncated_normal来初始化stddev。我猜想如果将其设置为更大的值,那么结果将是相同的,这是完全准确的。但是虽然增加了纪元数,但它不起作用。有谁知道这个原因吗?

原来的 :

W_layer = tf.Variable(tf.truncated_normal([inp.get_shape()[1].value, size],stddev=0.1), name='w_'+name)
#result : (990, 0.93000001, 0.89719999)
Run Code Online (Sandbox Code Playgroud)

修改的 :

W_layer = tf.Variable(tf.truncated_normal([inp.get_shape()[1].value, size],stddev=200), name='w_'+name)
#result : (99990, 0.1, 0.098000005)
Run Code Online (Sandbox Code Playgroud)

sun*_*ide 5

原因是因为您希望保持所有图层的方差(或标准差)大致相同且合理。它与学习过程的误差反向传播步骤和使用的激活函数有关。

为了学习网络的权重,反向传播步骤需要了解网络的梯度,即每个权重对输入影响程度的度量以达到最终输出;层的权重方差直接影响梯度的传播。

例如,假设激活函数是 sigmoidal(例如tf.nn.sigmoidtf.nn.tanh);这意味着所有输入值都被压缩到固定的输出值范围内。对于 sigmoid 来说,它是范围0..1,其中基本上所有z大于或小于 +/- 4 的值都非常接近 1(对于z > 4)或零(对于z < -4),并且只有该范围内的值往往会出现一些有意义的“变化”。

乙状结肠

sigmoid(5)现在,值和之间的差异sigmoid(1000)几乎无法察觉。因此,所有非常大或非常小的值都会优化得很慢,因为它们对结果的影响y = sigmoid(W*x+b)非常小。现在预激活值z = W*x+b(其中x是输入)取决于实际输入x和当前权重W。如果它们中的任何一个很大,例如通过用高方差(即标准偏差)初始化权重,则结果必然(相对)较大,从而导致所述问题。truncated_normal这也是为什么使用 正态分布而不是正确的正态分布的原因:后者只能保证大多数值非常接近平均值,而情况并非如此的可能性不到 5%,而只是简单地truncated_normal剪掉每个值太大或太小的值,保证所有权重都在同一范围内,同时仍然呈正态分布。

更糟糕的是,在典型的神经网络中——尤其是在深度学习中——每个网络层后面都跟着一个或多个其他网络层。如果每一层的输出值范围很大,那么梯度也会越来越大;这被称为梯度爆炸问题(梯度消失的变体,梯度变得越来越小)。这是一个问题的原因是因为学习从最后一层开始,并且每个权重根据它对误差的贡献程度进行调整。如果梯度确实在最后变得非常大,那么最后一层是第一个为此付出高昂代价的层:它的权重调整得非常强烈 - 可能过度校正实际问题 - 然后只有“剩余”误差进一步向后或向上传播网络。在这里,由于最后一层对于测量误差已经“修复了很多”,因此只会进行较小的调整。这可能会导致第一层仅修正一点点或根本不修正的问题,从而有效地阻止了那里的所有学习。如果学习率太大,基本上也会发生同样的情况。

寻找最佳权重初始化本身就是一个主题,并且有一些更复杂的方法,例如Xavier 初始化或层序单位方差,但是小的正态分布值通常只是一个很好的猜测。