Softmax数值不稳定问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Shingle_/article/details/81988628

数值计算

上溢和下溢

计算机通过有限数量的位模式来表示无限多的实数,总会引入一些近似误差。如果涉及时没有考虑最小化舍入误差的累积,在实践时可能会导致算法实效

下溢:当接近零的数被四舍五入为零时发生下溢。

许多函数在其参数为零而不是一个很小的正数时会表现出质的不同:

  • 避免零除
  • 避免取0的对数

上溢:大量级的数被近似为无穷时发生上溢。


必须对上溢和下溢进行数值稳定的一个例子是softmax函数

s o f t m a x ( x ) i = e x p ( x i ) j = 1 n e x p ( x j )

问题:假设所有的x_i都等于某个常数c,理论上对所有x_i上式结果为1/n。

  • 如果 c 是很小的负数,exp(c)就会下溢,softmax分母会变成0,最后的结果将为NaN
  • 如果 c 量级很大,exp(c)上溢,导致最后的结果将为NaN

方法:

s o f t m a x ( z ) = s o f t m a x ( z m a x i z i )

  • 减去最大值导致exp最大为0,排除了上溢的可能性
  • 同样,分母中至少有一个值为1的项(exp(0)=1),从而也排除了因分母=下溢导致被零除的可能性

还需注意分子可能发生下溢,会导致计算 log softmax(x)时得到负无穷。

实现深度学习算法时,开发者应牢记数值问题


示例(TensorFlow):

把向量化后的x和权重矩阵W相乘,加上偏置b,然后计算每个分类的softmax概率值。

y = tf.nn.softmax(tf.matmul(x,W) + b)

可以很容易的为训练过程指定最小化误差用的损失函数,我们的损失函数是目标类别和预测类别之间的交叉熵。

cross_entropy = -tf.reduce_sum(y_*tf.log(y))

注意,tf.reduce_sum把minibatch里的每个输入的交叉熵值都加起来了。我们计算的交叉熵是指整个minibatch的。

分成2步计算softmax的交叉熵会出现数值不稳定问题,使用中应该使用:

  y = tf.matmul(x, W) + b

  # Define loss and optimizer
  y_ = tf.placeholder(tf.int64, [None])

  # The raw formulation of cross-entropy,
  #
  #   tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.nn.softmax(y)),
  #                                 reduction_indices=[1]))
  #
  # can be numerically unstable.
  #
  # So here we use tf.losses.sparse_softmax_cross_entropy on the raw
  # outputs of 'y', and then average across the batch.

  cross_entropy = tf.losses.sparse_softmax_cross_entropy(labels=y_, logits=y)
  train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

《深度学习》 4.1 & 6.2

http://freemind.pluskid.org/machine-learning/softmax-vs-softmax-loss-numerical-stability/

猜你喜欢

转载自blog.csdn.net/Shingle_/article/details/81988628

相关文章