Nltk: Вывод стеммера Портера несовместим с эталонными реализациями

Созданный на 17 янв. 2012  ·  8Комментарии  ·  Источник: nltk/nltk

Недавно я использовал стеммер Porter от NLTK и обнаружил некоторые несоответствия между его выводом и выводом другой версии стеммера Porter, который я использовал. Рассматривая эти несоответствия, я обнаружил, что могут быть некоторые проблемы с реализацией NLTK.

Здесь представлены различные эталонные реализации стеммера Портера, собранные самим Мартином Портером:

http://tartarus.org/~martin/PorterStemmer/

Я попробовал один для Ruby, чтобы проверить работоспособность NLTK (он берет слово из стандарта и сразу же выплевывает его форму, также как и в стандарте):

скрипты $ ruby ​​porter_stemmer.rb
блестящий
сини

Я проверил это по NLTK:

скрипты $ python
Python 2.6.1 (r261: 67515, 24 июня 2010 г., 21:47:49)
[GCC 4.2.1 (Apple Inc., сборка 5646)] на darwin
Для получения дополнительной информации введите «помощь», «авторские права», «кредиты» или «лицензия».

        import nltk
        nltk.stem.porter.PorterStemmer().stem_word('shiny')

"шини"

Все идет нормально. И если я сравниваю эти результаты с ожидаемыми результатами (output.txt), представленными на той же странице для образца файла пользовательского dict (voice.txt), они выглядят правильно:

скрипты $ egrep -n '^ shiny $' voice.txt
18333: блестящий
скрипты $ egrep -n '^ shini $' output.txt
18333: сини

Но если я систематически сравниваю результаты NLTK с результатами в файле ожидаемых результатов, я вижу много несоответствий (формат: слово, правильное ожидаемое основание, неправильное основание NLTK, отмеченное звездочкой):

скрипты $ ./show_bad_stemming_in_nltk.py voice.txt output.txt
аббатство аббатство * аббатство
аббатства аббатство * аббатство
abed ab * abe
absey absei * absey
[...]
кричащий криво * wri
вчера вчера * вчера
вчера, вчера * вчера
Йонгрей Йонгрей * Йонгрей

Выборочная проверка по эталонной реализации Ruby подтверждает, что на самом деле проблема заключается в результатах NLTK:

скрипты $ ruby ​​porter_stemmer.rb
аббатство
аббатство
аббатства
аббатство
кровать
ab
Absey
Absei
кричащий
криво
вчерашний день
вчера
вчера
вчера
Йонгрей
Йонгрей

Я приложил полный список слов, для которых стеммер NLTK Porter дает неожиданные результаты.

(Эта ошибка относится к версии 2.0b9. Я подозреваю, что она существует во всех предыдущих версиях, но я не подтвердил это.)

Перенесли с http://code.google.com/p/nltk/issues/detail?id=625


предыдущие комментарии

gregg.lind сказал в 2011-02-09T20: 22: 57.000Z:

Я был бы счастлив взять это (к пятнице), если никто больше этого не захочет. Я много использовал этот модуль. Грегг Линд

StevenBird1 сказал в 2011-02-14T07: 14: 49.000Z:

Прилагаются исправления Стюарта Робинсона, отправленные в nltk-dev. Похоже, что это дальнейшие правки предыдущей версии, а не новый перенос версии Ruby, как первоначально обсуждалось. Перед включением этой новой версии нам нужно добавить набор тестовых примеров в test / stem.doctest.

goodfirstbug

Самый полезный комментарий

@paulproteus - наконец решено

Все 8 Комментарий

Я только что поставил на это ярлык "goodfirstbug". «Первая хорошая ошибка» - это добавление нескольких тестовых примеров в stem.doctest (https://github.com/nltk/nltk/blob/master/nltk/test/stem.doctest) - если вам хочется слиться в исправлениях Стюарта тоже было бы здорово!

Привет всем, особенно @alexrudnick , следует ли сейчас пометить это как

На бегу, похоже, нет, это еще не решено. Но хотел бы получить известие от сопровождающего.

@paulproteus - наконец решено

Обратите внимание, что поведение стеммера _default_ на момент моего PR, которое только что объединил Стивен, не изменилось; вам нужно явно передать mode=PorterStemmer.MARTIN_EXTENSIONS PorterStemmer чтобы получить поведение, соответствующее эталонным реализациям Мартина (которые сами по себе несовместимы с исходным алгоритмом Мартина).

Возможно, было бы лучше иметь MARTIN_EXTENSIONS в качестве режима по умолчанию (для согласованности с эталонными реализациями), поскольку пользователи будут ожидать, что что-то под названием PorterStemmer будет вести себя из коробки, как эталонные реализации Мартина. Проблема в том, что это было бы нарушением обратной совместимости, причем совершенно неочевидным; кто-то, кто использует предыдущую реализацию NLTK и обновляет NLTK, может долгое время не замечать, что изменились лишь некоторые из их основ, что может вносить небольшие ошибки в зависимости от варианта использования. Другой вариант - вообще не иметь значения по умолчанию и потребовать от каждого пользователя прочитать документацию по различным режимам и явно выбрать, какой из них использовать. Это также нарушит обратную совместимость, но сделает это _очевидным_ способом (просто попытка создать экземпляр стеммера старым способом взорвется), поэтому люди, выполняющие обновления, не читая примечания к выпуску, не будут пойманы. Такой подход позволил бы избежать любого из описанных выше плохих сценариев, но за счет того, что каждый новый пользователь стеммера требовал большей предварительной работы.

Ни один из вариантов не идеален. Я выбрал по умолчанию NLTK_EXTENSIONS , но есть возможность не согласиться. У кого-нибудь есть мнение?

@ExplodingCabbage : я предпочитаю ваш последний вариант, без значения по умолчанию, и сделаю это со следующим основным выпуском (а не второстепенным выпуском, в котором ваша работа появится впервые) с соответствующими предупреждениями в примечаниях к выпуску. Я думаю, было бы хорошо, если бы людей заставляли читать документы и получать пользу от вашей работы. Мне любопытно узнать, что думают другие.

Привет, ребята,

Я писал бэкэнд поисковой системы со стандартным PorterStemmer в nltk, не зная, что он ведет себя не так, как многие другие реализации стеммера Porter. Теперь, когда я работаю над интерфейсом с использованием Javascript, я сталкиваюсь с ошибками, когда интерфейс и мой сервер по-разному определяют слова. Мне было интересно, на что я должен смотреть, если мне нужно воссоздать поведение PorterStemmer по умолчанию nltk в Javascript, чтобы я мог запустить его в браузере. Я надеялся, что, может быть, кто-нибудь (может быть, @ExplodingCabbage ?)

У меня действительно нет времени переиндексировать все в режиме MARTIN_EXTENSIONS, на это уйдут недели ...

@josephcc porter.py в основном не имеет зависимостей и не делает ничего глубокого или волшебного, только длинную серию манипуляций со строками. Вам просто нужно перенести класс PorterStemmer в JavaScript, сохранив только ветки if self.mode == self.NLTK_EXTENSIONS и отбросив логику от остальных.

По общему признанию, не 5-минутная задача и надежная, но выполнимая. Также проверьте PorterTest в https://github.com/nltk/nltk/blob/develop/nltk/test/unit/test_stem.py и рассмотрите возможность запуска тестовых примеров там против вашей реализации JavaScript, чтобы проверить правильность вашей работы.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги