我正在尝试计算文本中单词对的对数似然得分,并且在我的Delphi实现中得到了与我从在线Java和Python源代码派生的同样异常的结果。Ted Dunning于1993年发表了这个源代码,为一个特定的单词对给出了以下结果:
- K11(AB,即联合频率)= 110,
- K12(没有B附近的A单词)= 2442,
- K21(没有A附近的B单词)= 111
- K22(除A或B以外的单词数)= 29114
并且给出了所需的结果为270.72。
Dunning还在R中提供了一种实现方法,网址为 http://tdunning.blogspot.co.uk/2008/03/surprise-and-coincidence.html
计算对数似然比得分(也称为G2)非常简单,
LLR = 2 sum(k) (H(k) - H(rowSums(k)) - H(colSums(k)))
其中H是Shannon熵,计算为(k_ij / sum(k)) log (k_ij / sum(k))
的总和。 在R中,此函数定义为H = function(k) {N = sum(k) ; return (sum(k/N * log(k/N + (k==0)))}
但我不知道R,也不确定如何将其翻译为Pascal。
我的翻译尝试包括以下函数:
function LnOK(x : integer): extended;
begin
if x<=0 then Result :=0
else Result := Ln(x);
end;
function Entropy2(a, b: Integer): extended;
begin
Result := LnOK(a + b) - LnOK(a) - LnOK(b);
end;
function Entropy4(a, b, c, d: Integer): extended;
begin
Result := LnOK(a + b + c + d) - LnOK(a) - LnOK(b) - LnOK(c) - LnOK(d);
end;
function Log_likelihood_from_Java(f1, f2, joint, total_tokens: Integer):
single;
var
k11, k12, k21, k22: Integer;
matrixEntropy, rowEntropy, colEntropy: extended;
begin
k11 := joint;
k12 := f2 - joint;
k21 := f1 - joint;
k22 := total_tokens - f1 - f2 + joint;
rowEntropy := Entropy2(k11 + k12, k21 + k22);
colEntropy := Entropy2(k11 + k21, k12 + k22);
matrixEntropy := Entropy4(k11, k12, k21, k22);
if (rowEntropy + colEntropy < matrixEntropy) then
Result := 0.0 // round off error
else
Result := 2.0 * (rowEntropy + colEntropy - matrixEntropy);
end;
以上代码返回的是
7.9419
,而非调用时期望的270.72
。Log_likelihood_from_Java(2552, 221, 110, 31777);
感谢您的帮助!