ws4j возвращает бесконечность для мер подобия, которые должны возвращать 1

У меня есть очень простой код, взятый из этот пример, где я использую меры подобия 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, также можно проверить с помощью демонстрации в Интернете. демо предоставлено ws4j


person Chthonic Project    schedule 19.07.2013    source источник


Ответы (4)


У меня была аналогичная проблема, и вот что здесь происходит. Я надеюсь, что другие люди, столкнувшиеся с этой проблемой, найдут ответ полезным.

Если вы заметили, онлайн-демонстрация позволяет вам выбрать смысл слова, указав слово в следующем формате: word#pos_tag#word_sense. Например, существительное gender с первым значением слова будет иметь вид gender#n#1.

В вашем фрагменте кода по умолчанию используется первый смысл слова. Когда я вычисляю сходство WuPalmer между «полом» и «полом», он возвращает 0,26. Если я использую онлайн-демонстрацию, она вернет 1.0. Но если мы используем «gender#n#1» и «sex#n#1», онлайн-демонстрация вернет 0,26, так что расхождений нет. Онлайн-демонстрация вычисляет максимальное количество всех пар почтовых тегов и смысловых слов. Вот соответствующий фрагмент кода, который должен помочь:

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, чтобы убедиться, что вы заранее подготовили слова, если это необходимо.

Надеюсь это поможет!

person gramonov    schedule 24.10.2013

Я поднял эту проблему на сайте googlecode для ws4j, и оказалось, что это действительно ошибка. Ответ, который я получил, выглядит следующим образом:

Похоже, это связано с попыткой переопределить защищенное статическое поле (это невозможно сделать в Java). Прилагаемый патч устраняет проблему, перемещая определение полей min и max в нестатические конечные члены в RelatednessCalculator и добавляя геттеры. Затем реализации предоставляют свои минимальные/максимальные значения через вызовы суперконструктора.

Патч можно применить с помощью patch -p1 ‹ 0001-Cannot-override-static-members-replaceing-fields-with.patch

И вот проблема (теперь решенная) на их сайте. .

person Chthonic Project    schedule 12.08.2014
comment
Эй, скажите, пожалуйста, как применить патч к текущей банке ws4j, которую я использую. - person Kunjan Shah; 31.01.2018

Вот почему -

В 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 (=> сходство станет неопределенным).

расстояние может быть 0 в 2 случаях...

(1) ic(c1) = ic(c2) = ic(lcs(c1, c2)) = 0

ic(lcs(c1, c2)) может быть 0, если lcs оказывается корневым узлом (информационное содержание корневого узла равно нулю). Но поскольку c1 и c2 никогда не могут быть корневыми узлами, ic(c1) и ic(c2) будут равны 0 только в том случае, если 2 концепта имеют нулевой счетчик частоты, и в этом случае из-за отсутствия данных мы возвращаем связанность 0 (аналогично случаю Лин).

Обратите внимание, что корневой узел НА САМОМ ДЕЛЕ имеет нулевое информационное содержание. Технически ни одно из других понятий не может иметь значение информационного содержания, равное нулю. Мы присваиваем понятиям нулевое значение, тогда как в действительности их информативность не определена (из-за нулевого частотного подсчета). Чтобы понять, зачем смотреть на формулу информационного содержания: 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 был бы равносилен утверждению, что они вообще не связаны.

person user3503711    schedule 19.07.2014
comment
Как это отвечает на мой вопрос? Меня особенно беспокоит странное поведение в трех партитурах: Ву-Палмер, Путь и Лин. - person Chthonic Project; 20.07.2014
comment
О, извините, это причина, по которой jiang-conrath дает значение 1,7976931348623157E308 для тех же слов. Я не видел трех методов. Виноват! - person user3503711; 21.07.2014
comment
Все мое замешательство было связано с этими тремя методами. JCN предполагается стремится к бесконечности по мере увеличения сходства, в то время как три упомянутых мной значения имеют диапазон [0,1]. - person Chthonic Project; 21.07.2014

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
person Donato Meoli    schedule 18.08.2018
comment
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. – Из обзора - person Eugene Primako; 18.08.2018
comment
Похоже, это связано с попыткой переопределить защищенное статическое поле (это невозможно сделать в Java). В своем коде я исправил проблему, переместив определение полей min и max в нестатические конечные члены в RelatednessCalculator и добавив геттеры. Затем реализации предоставляют свои минимальные/максимальные значения через вызовы суперконструктора. - person Donato Meoli; 18.08.2018