版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Shingle_/article/details/81988628
数值计算
上溢和下溢
计算机通过有限数量的位模式来表示无限多的实数,总会引入一些近似误差。如果涉及时没有考虑最小化舍入误差的累积,在实践时可能会导致算法实效。
下溢:当接近零的数被四舍五入为零时发生下溢。
许多函数在其参数为零而不是一个很小的正数时会表现出质的不同:
- 避免零除
- 避免取0的对数
上溢:大量级的数被近似为无穷时发生上溢。
必须对上溢和下溢进行数值稳定的一个例子是softmax函数
问题:假设所有的x_i都等于某个常数c,理论上对所有x_i上式结果为1/n。
- 如果 c 是很小的负数,exp(c)就会下溢,softmax分母会变成0,最后的结果将为NaN
- 如果 c 量级很大,exp(c)上溢,导致最后的结果将为NaN
方法:
- 减去最大值导致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/