ログサムの壊滅的なキャンセル
相対誤差の少ない倍精度浮動小数点で次の関数を実装しようとしています。 logsum(x,y)=log(exp(x)+exp(y))logsum(x,y)=log(exp(x)+exp(y))\mathrm{logsum}(x,y) = \log(\exp(x) + \exp(y)) これは統計アプリケーションで広く使用され、ログスペースで表される確率または確率密度を追加します。もちろん、またはは簡単にオーバーフローまたはアンダーフローする可能性がありますが、そもそもログスペースがアンダーフローを回避するために使用されるため、これは悪いことです。これが典型的な解決策です。exp(x)exp(x)\exp(x)exp(y)exp(y)\exp(y) logsum(x,y)=x+log1p(exp(y−x))logsum(x,y)=x+log1p(exp(y−x))\mathrm{logsum}(x,y) = x + \mathrm{log1p}(\exp(y - x)) からのキャンセルは発生しますが、によって軽減されます。さらに悪いのは、とが近い場合です。相対誤差プロットは次のとおりです。y−xy−xy-xexpexp\expxxxlog1p(exp(y−x))log1p(exp(y−x))\mathrm{log1p}(\exp(y - x)) プロットはれ、キャンセルが発生する曲線の形状を強調します。最大までのエラーが表示されましたが、さらに悪化すると思われます。(FWIW、「グラウンドトゥルース」関数は、128ビット精度のMPFRの任意精度の浮動小数点を使用して実装されます。) l o g s u m(x 、y )= 0 10 − 1110−1410−1410^{-14}logsum(x,y)=0logsum(x,y)=0\mathrm{logsum}(x,y) = 010−1110−1110^{-11} 私は他の改革を試みましたが、すべて同じ結果になりました。外側の式と、同じエラーがで1近く何かのログを取ることによって発生外側の表現として、キャンセルは、内側の式で行わ。l o g 1 ploglog\loglog1plog1p\mathrm{log1p} 現在、絶対誤差は非常に小さいため、相対誤差は非常に小さくなっています(イプシロン内)。ユーザーは(ログ確率ではなく)確率に本当に関心があるので、このひどい相対誤差は問題ではないと主張するかもしれません。通常はそうではない可能性がありますが、私はライブラリ関数を書いています。そのクライアントは、丸め誤差よりもそれほど悪くない相対誤差を期待できるようにしたいと思います。l o g s u mexp(logsum(x,y))exp(logsum(x,y))\exp(\mathrm{logsum}(x,y))logsumlogsum\mathrm{logsum} 新しいアプローチが必要なようです。何だろう?