Delphi中的对数似然实现

Mik*_*ott 3 delphi r

我正在尝试计算文本中单词对出现的Log Likelihood得分,并且在我的Delphi实现中得到了相同的异常结果,我从在线发现的Java和Python源代码中得到了这些结果.1993年在这个来源上发表的Ted Dunning给出了一对特定的结果:

  • K11(AB,即关节频率)= 110,
  • K12(附近没有B的字A)= 2442,
  • K21(B附近没有A)= 111
  • K22(文本中除A或B以外的单词数)= 29114

并给出所需的结果为270.72

Dunning还在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是香农熵,计算为和的总和(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;
Run Code Online (Sandbox Code Playgroud)

当它被调用时,上面的返回7.9419而不是所需270.72的:

Log_likelihood_from_Java(2552, 221, 110, 31777);
Run Code Online (Sandbox Code Playgroud)

感谢帮助!

fan*_*cco 6

我在LnOk函数的翻译中发现了这个问题,应该如下:

function LnOK(x: Integer): Extended;
begin
  if x = 0 then
    Result := 0
  else
    Result := x * Ln(x);
end;
Run Code Online (Sandbox Code Playgroud)

无关

就好像我被允许,只是为了提高编码风格一个侧面说明,你可能更愿意超载Entropy功能,而不是使用不同的名字叫他们:

function Entropy(a, b: Integer): Extended; overload;
begin
  Result := LnOK(a + b) - LnOK(a) - LnOK(b);
end;

function Entropy(a, b, c, d: Integer): Extended; overload;
begin
  Result := LnOK(a + b + c + d) - LnOK(a) - LnOK(b) - LnOK(c) - LnOK(d);
end;
Run Code Online (Sandbox Code Playgroud)