对于应返回1的相似性度量,ws4j返回无穷大

时间:2013-07-19 15:44:48

标签: java nlp wordnet ws4j

我有一个非常简单的代码来自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验证

4 个答案:

答案 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

并在其网站上here is the (now resolved) issue

答案 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