【发布时间】:2011-01-27 10:53:25
【问题描述】:
我已经做了一个在java中实现Kullback-leibler散度的方法。我使用了以 2 为底的日志,但我不确定我是否正确使用了它,或者我应该使用以 10 为底的日志。我正在使用这种方法来测量两个文本单元(每个不同长度)之间的差异。
我的问题是我没有得到想要的发散度量。
例如对于两个文本单元,即 =>“免费铃声”和第二个“来自 PremieRingtones.com 的手机免费铃声”
我应该得到 0.25 的分歧(根据我的项目参考),但如果我使用 log base2 和 1.38 作为 log base10,我会得到 2.0 的分歧。
我也不知道用什么值代替分母的值而不是零值。如果可能的话,请帮助用一些例子给出清楚的解释,甚至一些链接到我可以得到细节的地方。
这是我的代码 sn-p:
public Double calculateKLD(List<String> values,List<String> value2)
{
Map<String, Integer> map = new HashMap<String, Integer>();
Map<String, Integer> map2 = new HashMap<String, Integer>();
for (String sequence : values)
{
if (!map.containsKey(sequence))
{
map.put(sequence, 0);
}
map.put(sequence, map.get(sequence) + 1);
}
for (String sequence : value2)
{
if (!map2.containsKey(sequence)) {
map2.put(sequence, 0);
}
map2.put(sequence, map2.get(sequence) + 1);
}
Double result = 0.0;
Double frequency2=0.0;
for (String sequence : map.keySet())
{
Double frequency1 = (double) map.get(sequence) / values.size();
System.out.println("Freuency1 "+frequency1.toString());
if(map2.containsKey(sequence))
{
frequency2 = (double) map2.get(sequence) / value2.size();
}
result += frequency1 * (Math.log(frequency1/frequency2) / Math.log(2));
}
return result/2.4;
}
我的输入是这样的
第一个文本单元
list.add("Free");list.add("Ringtones");
第二个文本单元
list2.add("Free");list2.add("Ringtones");list2.add("for");list2.add("your");list2.add("Mobiile");list2.add("Phone");list2.add("from");list2.add("PremieRingtones.com");
调用函数
calculateKLD(list, list2)
【问题讨论】:
-
使用不同的对数会产生比例值。对于 log2,我们说分歧用 bits 表示,自然对数用 nats 和 log10 表示,好吧,我不知道任何术语,但你通常以乘以 10 后的 分贝。它们是真正的单位,它们之间具有恒定的换算系数,例如米和英里、磅和公吨等。
-
如果你使用 log256,你会得到 0.25。看起来你的计算是正确的。当我手动计算它时,我得到 2.0。如果你切换它并执行 D_KL(Q||P),我得到 -0.5。
-
为什么写“
map.put(sequence, 0);”而不是“map.put(sequence, 1);”?