我有一个非常简单的代码来自this example,我使用Lin,Path和Wu-Palmer相似性度量来计算两个单词之间的相似性。我的代码如下:
import edu.cmu.lti.lexical_db.ILexicalDatabase;
import edu.cmu.lti.lexical_db.NictWordNet;
import edu.cmu.lti.ws4j.RelatednessCalculator;
import edu.cmu.lti.ws4j.impl.Lin;
import edu.cmu.lti.ws4j.impl.Path;
import edu.cmu.lti.ws4j.impl.WuPalmer;
public class Test {
private static ILexicalDatabase db = new NictWordNet();
private static RelatednessCalculator lin = new Lin(db);
private static RelatednessCalculator wup = new WuPalmer(db);
private static RelatednessCalculator path = new Path(db);
public static void main(String[] args) {
String w1 = "walk";
String w2 = "trot";
System.out.println(lin.calcRelatednessOfWords(w1, w2));
System.out.println(wup.calcRelatednessOfWords(w1, w2));
System.out.println(path.calcRelatednessOfWords(w1, w2));
}
}
除非两个单词相同,否则分数如预期一样。如果两个单词都相同(例如w1 = "walk"; w2 = "walk";
),那么我所拥有的三个度量应该都返回1.0。但相反,他们正在返回1.7976931348623157E308。
我之前使用过ws4j(实际上是相同的版本),但我从未见过这种行为。在线搜索没有产生任何线索。这可能会出现什么问题?
P.S。 Lin,Wu-Palmer和Path度量应该返回1的事实也可以通过the online demo provided by ws4j验证
答案 0 :(得分:8)
我有类似的问题,这就是这里发生的事情。我希望遇到这个问题的其他人会通过回复找到帮助。
如果您注意到,在线演示允许您通过以下格式指定单词来选择单词意义:单词#pos_tag#word_sense 。例如,带有第一个单词sense的名词 gender 将是 gender#n#1 。
您的代码段默认使用第一个单词sense。当我计算“性别”和“性别”之间的WuPalmer相似性时,它将返回0.26。如果我使用在线演示,它将返回1.0。但如果我们使用“性别#n#1”和“性别#n#1”,在线演示将返回0.26,因此没有差异。在线演示计算所有pos标签/字检测对的最大值。这是一个相应的代码片段,可以解决这个问题:
ILexicalDatabase db = new NictWordNet();
WS4JConfiguration.getInstance().setMFS(true);
RelatednessCalculator rc = new Lin(db);
String word1 = "gender";
String word2 = "sex";
List<POS[]> posPairs = rc.getPOSPairs();
double maxScore = -1D;
for(POS[] posPair: posPairs) {
List<Concept> synsets1 = (List<Concept>)db.getAllConcepts(word1, posPair[0].toString());
List<Concept> synsets2 = (List<Concept>)db.getAllConcepts(word2, posPair[1].toString());
for(Concept synset1: synsets1) {
for (Concept synset2: synsets2) {
Relatedness relatedness = rc.calcRelatednessOfSynset(synset1, synset2);
double score = relatedness.getScore();
if (score > maxScore) {
maxScore = score;
}
}
}
}
if (maxScore == -1D) {
maxScore = 0.0;
}
System.out.println("sim('" + word1 + "', '" + word2 + "') = " + maxScore);
此外,这将为您提供非词干形式的0.0相似性,例如: '性别'和'性'。您可以使用ws4j中包含的porter stemmer来确保在需要时事先干掉单词。
希望这有帮助!
答案 1 :(得分:1)
我在googlecode网站上为ws4j提出了这个问题,事实证明这确实是一个错误。我收到的答复如下:
这看起来是因为尝试覆盖受保护的静态字段(这不能用Java完成)。附加的补丁修复了这个问题,方法是将最小和最大字段的定义移动到RelatednessCalculator中的非静态最终成员并添加getter。然后,实现通过超级构造函数调用提供其最小/最大值。
补丁可以应用补丁-p1&lt; 0001-无法重写的静态成员-替换字段-with.patch
答案 2 :(得分:-1)
这就是为什么 -
在jcn中我们有......
sim(c1,c2)= 1 /距离(c1,c2)
距离(c1,c2)= ic(c1)+ ic(c2) - (2 * ic(lcs(c1,c2)))
其中c1,c2是两个概念, ic是概念的信息内容。 lcs(c1,c2)是c1和c2中最不常见的子语言。
现在,我们不希望距离为0(=>相似性将变为 未定义)。
2例中距离可以为0 ......
(1)ic(c1)= ic(c2)= ic(lcs(c1,c2))= 0
如果lcs结果是根,则ic(lcs(c1,c2))可以为0 节点(根节点的信息内容为零)。但是由于 c1和c2永远不能是根节点,ic(c1)和ic(c2)将为0 仅当2个概念具有0频率计数时,在这种情况下,为 缺少数据,我们返回0的相关性(类似于lin的情况)。
请注意,根节点ACTUALLY的信息内容为 零。从技术上讲,其他概念都不能提供信息 内容值为零。我们分配概念零值,何时 实际上他们的信息内容是不确定的(由于零 频率计数)。要了解为什么要查看公式以获取信息 content:ic(c)= -log(freq(c)/ freq(ROOT)){log(0)?日志(1)?}
(2)距离变为零的第二种情况是......
ic(c1)+ ic(c2)= 2 * ic(lcs(c1,c2))
(可能更有可能是特殊情况ic(c1)= ic(c2)= ic(lcs(c1,c2))如果所有三个都是相同的概念。)
如何处理这个?
直观地说,这是最大相关性的情况(零 距离)。对于jcn来说,这种相关性将是无限的......但是我们 不能回归无穷大。简单地返回0将无法正常工作...... 从这里我们发现了一对最大的概念 相关性,并返回0就像说他们 根本没有关系。
答案 3 :(得分:-1)
1.7976931348623157E308是Double.MAX_VALUE的值,但是某些相似/相关算法(Lin,WuPalmer和Path)的最大值在0和1之间。然后,对于相同的同义词集,可以返回的最大值是1。在我的仓库版本(https://github.com/DonatoMeoli/WS4J)中,我修复了此错误和其他错误。
现在,对于两个相同的单词,返回的值是:
HirstStOnge 16.0
LeacockChodorow 1.7976931348623157E308
Lesk 1.7976931348623157E308
WuPalmer 1.0
Resnik 1.7976931348623157E308
JiangConrath 1.7976931348623157E308
Lin 1.0
Path 1.0
Done in 67 msec.
Process finished with exit code 0