数值稳定的实现

8
我是一名有帮助的助手,以下是您需要翻译的内容:

我需要在Matlab中计算一个向量的归一化指数。

简单地写

res = exp(V)/sum(exp(V))

在V的一个元素中发生溢出,其值大于log(realmax)= 709.7827。(我不确定欠流条件。)

如何实现以避免数值不稳定?

更新:我收到了关于如何避免溢出的优秀反馈。但是,我仍然很乐意听取您对代码可能发生欠流的想法。

2个回答

9
以下方法避免了溢出情况,通过“减去指数并接着取指数”的方式,而非除以指数:
res = 1./sum(exp(bsxfun(@minus, V(:), V(:).')))

作为一个通用规则,尽可能长时间地在对数域中工作,并仅在最后才进行指数运算,可以避免溢出。

谢谢。我对bsxfun不熟悉。如果V是一个矩阵,我们想沿着维度dim应用它怎么办? - user25004
@user25004 那该怎么办? exp(V) 将成为一个矩阵,sum(exp(V),dim) 将成为一个向量。如果这样的话,你如何定义 exp(V)/sum(exp(V,dim)) - Luis Mendo
我是指如果变量名为dim的值为1,则我希望你先前的代码应用于每一列。如果dim的值为2,则该代码是逐行应用的。 - user25004
@user25004 那会更难。而且这会完全改变问题的性质。简单的答案是:循环遍历每一行或每一列。 - Luis Mendo
@user25004 欢迎!如果循环解决方案不够好,请随时将新需求作为新问题提出。 - Luis Mendo
不错的解决方案,应该比我的解决方案精度更高。 - Daniel

4
答案与你之前的问题非常相似。使用数学!
exp(V)=exp(V-max(V))*exp(max(V))
sum(exp(V))=sum(exp(V-max(V))*exp(max(V)))=exp(max(V)*sum(exp(V-max(V))))

将两者结合起来:

res=exp(V-max(V))*exp(max(V))/exp(max(V)*sum(exp(V-max(V)))=exp(V-max(V))/sum(exp(V-max(V)))

一个对输入范围具有鲁棒性的代码:
res=exp(V-max(V))/sum(exp(V-max(V)))

不错的想法!减去最大值 - Luis Mendo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接