数値計算

1日〜3日までのような日本的正月休みというのはなさそうですが、そろそろ学生も研究室へ顔を出す時期なようなので大学へ行ってみました。大学時代あまり、Numerical Recipeなんかにあるような数値計算らしい数値計算をするプログラムを書いたことがなかったのですが、論文に書いてある式をそのままCで実装すると期待した結果が得られないような問題に最近直面しており、いろいろと小細工して乗り越えようとしていますが、いまいち効果がでないんですよね。面倒なので、任意精度の浮動小数点が扱える言語にのりかえるか、このままCでがんばるか悩ましい。
問題は、

P_g(g|J) = \frac{1}{n}\sum_{j=1}^{n} \frac{ \exp \{ -(g-g_i)^T \Sigma^{-1}(g-g_i)\}}{\sqrt{2^{k}\pi^{k}|\Sigma|}}
\Sigma = \beta \cdot I
\betaは、予備実験により調整されるパラメータで、0.1
テスト画像中のあるリージョンの特徴ベクトルgと、訓練データ(J)中のリージョンiの特徴ベクトルg_iの差の内積は、リージョン間の類似性を表している

 P_g(g|J)を計算するにあたり、expの内部が小さすぎて、そのまま計算するとmath.hのexpがたいてい0を返すようになってしまうということ。で、分母の\sqrt{2^{k}\pi^{k}|\Sigma|}をexpを適用する前に処理してやる(全体にlogを適用し、その後expで戻す)と幾分マシになる。つまり、

 log_n {\frac{ \exp \{ -(g-g_i)^T \Sigma^{-1}(g-g_i)\}}{\sqrt{2^{k}\pi^{k}|\Sigma|}}
 = \frac{-(g-gi)\cdot(g-gi)}{\beta} - \frac{k}{2} \log(2\pi\beta)
を計算した後、expを計算する。

\frac{-(g-gi)\cdot(g-gi)}{\beta}\frac{k}{2} \log(2\pi\beta)が、ともにマイナスになるので、分母を先に適用させることにより多少効果はあるが、まだ足りない模様。