计算 Log-Sum-Exp [原文-Computing Log-Sum-Exp] 本文的计算技巧是有效的,但在机器学习课程上没有明确提到.
假设 $ {N} $ 个 值的数据集 ${{x_n}_{n=1}^N}$,需要计算的值为:
${ z = log \sum_{n=1} ^N exp (x_n ) }$
当采用 softmax 对 multinomial 分布进行参数化时,比如,logistic 回归和有多于 2 个无序类别时,这种计算经常出现.
如果想要计算 log likehood,由于存在归一化常数,也会看到这种表达式.
直接进行计算,则是灾难性的,因为存在下溢(underflow) 和上溢(overflow), 取决于 ${ x_n }$ 的尺度(scale).
假设一种简单的例子, 向量 [0, 1, 0], 看着是很直接明了的,得到的结果 z = 1.55.
${ z = ln(exp(0) + exp(1) + exp(0)) = ln(2+e) = 1.55 }$
当向量为 [1000, 1001, 1000] 时,${ z = ln(exp(1000) + exp(1001) + exp(1000)) = inf }$.
当向量为 [-1000, -999, -1000] 时, ${ z = ln(exp(-1000) + exp(-999) + exp(-1000)) = -inf }$.
中间发生了什么?
在 64-bit 系统中,因为下溢(underflow) 和上溢(overflow) 的存在, ${ exp(1000) = inf }$, ${ exp(-1000) = 0 }$.
即使 log 会以无限精度(infinite precision) 再次合理的缩放(scaled)数值, 但在实际的计算机上,是不可行的.
因此,解决方案是?
采取的技巧是:
${ log \sum_{n=1}^N exp(x_n) = a + log \sum_{n=1}^N exp(x_n- a) }$
${ a }$为任意数.
上式意味着,我们可以任意的平移指数的中心值, 放大或缩小.
一种典型的是使,
${ a = (max)_n x_n }$
这样保证了取指数时的最大值为0.
这种技巧使得绝对不会出现上溢(overflow),即使其余的下溢(underflow),也可以得到一个合理的值.