【问题标题】:ws4j returns infinity for similarity measures that should return 1对于应该返回 1 的相似性度量,ws4j 返回无穷大
【发布时间】:2013-07-18 23:36:41
【问题描述】:

我有一个取自 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(实际上是相同的版本),但我从未见过这种行为。在网上搜索并没有找到任何线索。这里可能出了什么问题?

附: Lin、Wu-Palmer 和 Path 度量值应该返回 1 的事实也可以通过 the online demo provided by ws4j 进行验证

【问题讨论】:

    标签: java nlp wordnet ws4j


    【解决方案1】:

    我遇到了类似的问题,这就是这里发生的事情。我希望其他遇到此问题的人会通过回复找到帮助。

    如果您注意到,在线演示允许您通过指定以下格式的单词来选择词义:word#pos_tag#word_sense。例如,具有第一个词义的名词 gender 将是 gender#n#1

    您的代码 sn-p 默认使用第一个词义。当我计算“性别”和“性别”之间的 WuPalmer 相似度时,它将返回 0.26。如果我使用在线演示,它将返回 1.0。但如果我们使用“gender#n#1”和“sex#n#1”,在线演示将返回 0.26,因此没有差异。在线演示计算所有 pos 标签/词义对的最大值。这是一个对应的 sn-p 代码,应该可以解决问题:

    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 中包含的搬运工词干分析器来确保您事先词干词干。

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      我在 ws4j 的 googlecode 网站上提出了这个问题,结果证明这确实是一个错误。我收到的回复如下:

      这看起来是因为试图覆盖受保护的静态字段(这不能在 Java 中完成)。附加的补丁通过将 min 和 max 字段的定义移动到 RelatednessCalculator 中的非静态最终成员并添加 getter 来解决此问题。然后实现通过超级构造函数调用提供它们的最小值/最大值。

      可以通过 patch -p1

      还有here is the (now resolved) issue 在他们的网站上。

      【讨论】:

      • 嘿,请告诉我如何将补丁应用到我正在使用的当前 ws4j jar 中。
      【解决方案3】:

      这就是为什么 -

      在 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

      ic(lcs(c1, c2)) 如果 lcs 原来是根,则可以为 0 节点(根节点的信息内容为零)。但由于 c1 和 c2 永远不能是根节点,ic(c1) 和 ic(c2) 将为 0 仅当 2 个概念的频率计数为 0 时,在这种情况下,对于 缺少数据,我们返回 0 的相关性(类似于 lin 的情况)。

      请注意,根节点实际上有一个信息内容 零。从技术上讲,其他任何概念都没有信息 内容值为零。我们给概念分配零值,当 实际上,它们的信息内容是未定义的(由于零 频率计数)。要了解为什么请查看公式以获取信息 内容: 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 就像说他们 一点关系都没有。

      【讨论】:

      • 这如何回答我的问题?我特别关注三个分数中的奇怪行为:Wu-Palmer、Path 和 Lin。
      • 哦,对不起,这就是 jiang-conrath 为相同的词给出 1.7976931348623157E308 值的原因。我没有看到这三种方法。我的错!
      • 我对这三种方法感到困惑。 JCN 应该随着相似度的增加而趋于无穷大,而我提到的三个范围为 [0,1]。
      【解决方案4】:

      1.7976931348623157E308 是 Double.MAX_VALUE 的值,但某些相似性/相关性算法(Lin、WuPalmer 和 Path)的最大值介于 0 和 1 之间。那么,对于相同的同义词集,可以返回的最大值为 1。在我的 repo (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
      

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
      • 这看起来是由于试图覆盖受保护的静态字段(这不能在 Java 中完成)。在我的代码中,我通过将 min 和 max 字段的定义移动到 RelatednessCalculator 中的非静态最终成员并添加 getter 来解决此问题。然后实现通过超级构造函数调用提供它们的最小值/最大值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 2022-01-23
      相关资源
      最近更新 更多