Problem with arithmetic using logarithms to avoid numerical underflow (take 2)
看过上面的内容并看到了softmax规范化后,我试图规范化矢量,同时避免溢出 -
即如果我有一个数组
x[1], x[2] x[3], x[4], ... , x[n]
我的规范化形式的元素平方和为1.0
并且通过将每个元素除以得到
sqrt(x[1]*x[1]+x[2]*x[2]+...+x[n]*x[n])
现在,即使平方根足够小以适应浮点变量,方块的总和也会溢出,所以我想象一个人可以做类似的事情
s=(2*log(fabs(x[1]))+2*log(fabs(x[2]))+...+2*log(fabs(x[n])))/2
并将元素计算为
exp(log(fabs(x[1]))-s), ..., exp(log(fabs(x[n]))-s
BUT
以上是不正确的,因为log(A + B)不是log(A)+ log(B) - 现在有没有办法进行矢量归一化,以避免溢出更好?
答案 0 :(得分:4)
而不是
norm = sqrt(x[1] * x[1] + ... + x[n] * x[n])
您可能希望在平方之前将矢量的元素除以最大可能值
max_x = max(x[1], ..., x[n])
y[1] = x[1] / max_x / n
...
y[n] = x[n] / max_x / n
norm = n * sqrt(y[1] * y[1] + ... + y[n] * y[n]) * max_x
y
向量的范数应该等于或小于零。 n * max_x
的值仍然可能溢出,因此您还需要注意,操作是以非溢出顺序执行的。
答案 1 :(得分:3)
你似乎在假设:
log(x^2 + y^2)
与:
相同log(x^2) + log(y^2)
然而,这是不正确的,因为你无法简化这样的总和的对数。
答案 2 :(得分:3)
KennyTM是正确的 - 您对对数的想法是错误的。
你不能使用L2规范,因为它要求你计算向量的大小,这正是你遇到溢出问题。
也许L-infinity范数,你将矢量中的每个分量除以最大分量的绝对值首先会更好。一定要保持最大绝对值,这样才能获得正确的幅度。
我完全理解你需要L2规范,但如果溢出确实是一个问题,你需要采取中间步骤才能得到它: