確率のかけ算が繰り返されるとアンダーフローが起きる。 これを防ぐために確率の対数の足し算を行う。
フォワードアルゴリズムなどを実装すると、 例えば 0.1+0.5=0.6 のような確率の足し算を log の領域で行う必要が出てくる。
このときに exp() で戻すと、せっかく log にした意味がなくなるので、 logadd() と呼ばれる計算を行うのが一般的。
logAdd に関する情報源
Julius では addlog.c にてテーブルルックアップで実装。
HTK では HTKLib/HMath.c に LAdd() として実装されている。
動作確認は octave で行っている。
%% logadd.m %% logadd(logX, logY) %% based on http://nlp.cs.byu.edu/mediawiki/index.php/Log_Domain_Computations %% Author: nishimotz atmark gmail.com %% Created: 2010-04-24 function [ ret ] = logadd (logX, logY) if logY > logX temp = logX; logX = logY; logY = temp; end if isinf(logX) ret = logX; return end negDiff = logY - logX; if negDiff < -20 ret = logX; return end ret = logX + log(1.0 + exp(negDiff)); endfunction
計算例 1
## A = 0.1 ; logA = -2.3026 ## B = 0.5 ; logB = -0.69315 ## A+B = 0.6 ; log(A+B) = -0.51083 > logadd(-2.3026,-0.69315) ans = -0.51083
計算例 2
## A = 0.0 ; logA = -Inf ## B = 0.9 ; logB = -0.10536 ## A+B = 0.9 ; log(A+B) = -0.10536 > logadd(-Inf,-0.10536) ans = -0.10536