--- title: 対数で確率を扱う話 --- 確率 $p_1$, $p_2$, $p_3$ があり、アンダーフローを防ぐため、対数を取って計算しているとする。つまり $\log p_1$, $\log p_2$, $\log p_3$ が求まっている。 ここで、 $\log \frac{p_1}{p_1 + p_2 + p_3}$, $\log \frac{p_2}{p_1 + p_2 + p_3}$, $\log \frac{p_3}{p_1 + p_2 + p_3}$ を $\exp(\log p_i)$ を計算せずに求めることはできる? --- LogSumExp という方法に落とし込めることがわかったのでメモ - [logsumexp(log sum exponential)とは - EchizenBlog-Zwei](http://d.hatena.ne.jp/echizen_tm/20100628/1277735444) - [混合ガウス分布とlogsumexp - Qiita](https://qiita.com/BigSea/items/1949b3ceefcec4fc32ea) - [Accord.NET Framework の実装](https://github.com/accord-net/framework/blob/5fea1bff19a104990493df71f69b8e892145e4ec/Sources/Accord.Math/Special.cs#L600-L613) $\log \frac{p_1}{p_1 + p_2 + p_3} = \log(p_1) - \log(p_1 + p_2 + p_3)$ なので、問題なのは $\log(p_1 + p_2 + p_3)$ のほう。 $$\log(p_1 + p_2 + p_3) = \log(\exp(\log p_1) + \exp(\log p_2) + \exp(\log p_3))$$ ここで、適当な変数 $a$, $b$ を使って、この形の展開をすると $$ \begin{eqnarray*} \log(\mathrm{e}^a + \mathrm{e}^b) &=& \log(\mathrm{e}^b(\mathrm{e}^{a-b} + 1)) \\ &=& \log(\mathrm{e}^b) + \log(\mathrm{e}^{a-b} + 1) \\ &=& b + \log(\mathrm{e}^{a-b} + 1) \end{eqnarray*} $$ と変形できます。ここで $\exp$ の代わりに $\mathrm{e}$ を使ったのは、こう書かないと僕が指数法則を見つけられないからです。 というわけで、 $|a-b| < a,b$ なら、指数関数を使ってもそんなに極端な値にならないから、精度を維持できるよねって話でした。 Wikipedia 先生や Qiita に当たった感じだと、一般的には $$ \log \left( \sum_{i=1}^n \exp(x_i) \right) = x_{\max} + \log \left( \sum_{i=1}^n \exp(x_i-x_{\max}) \right) $$ で求めるようです。 Accord .NET Framework では $$ LogSum(x, y) = \max\{x,y\} + \log \left( 1 + (\min\{x,y\} - \max\{x,y\}) \right) $$ として $$ \log \left( \sum_{i=1}^n \exp(x_i) \right) = \cdots LogSum(LogSum(-\infty, x_1), x_2) \cdots $$ というループで求めているようです。どっちがいいのかな。