Возможно, кому-то будет интересно/полезно посмотреть на рабочий(в учебных целях) стеммер русских слов, написанный на Java. Данный стеммер писался для одной лабы по Java в университете(реализовывал примитивный полнотекстовый поиск), но это не значит, что этот стеммер является нерабочим или корявым. Просто его нужно допиливать(как и все созданное в учебных целях и на скорую руку).
Стеммер реализовывался по Snowball'овскому алгоритму http://snowball.tartarus.org/algorithms/russian/stemmer.html. Здесь есть код самого стеммера http://code.google.com/p/khomutetskiy-project/source/browse/#svn/trunk/UNIVER/src/ru/susu/ssearch/stemmer/russian и всяких служебных классов. И если присмотреться к алгоритмическому описанию алгоритма на Lisp-подобном синтаксисе(он у них похоже называется Snowball), то видно, что Lisp'оподобный синтаксис не в пример лаконичнее, но ИМХО не проще в понимании. Пусть каждый сделает выводы сам. Вообще из этого синтаксиса потом генерится Си код, который вообще никак не читаем, но зато быстро работает.
p.s.: http://code.google.com/p/khomutetskiy-project/source/browse/trunk/UNIVER/src/ru/susu/ssearch/test/RussianStemmerTest.java
p.p.s: вообще основное время заняло написание класса-обертки для суффиксов(SuffixContainer) и утилитарного(StemmerUtils). Без них код был бы совсем ужасен.
Будем честными ...
2 месяца назад
Миш, а почему сноуболловский алгоритм а не Портера? просто интересно
ОтветитьУдалитьА это разве не одно и тоже? После гугления сложилось такое ощущение. Например то, что увидел вот здесь http://forum.dklab.ru/php/advises/HeuristicWithoutTheDictionaryExtractionOfARootFromRussianWord.html тоже самое, что я закодил, только на регэкспах.
ОтветитьУдалитьВообще, я от стема большего ожидал. Не думал, что он так грубо и тупо пилит слова.
На регэкспах делать значительно проще. В учебных целях точно на регэкспах надо делать.
ОтветитьУдалитьА тестили?
ОтветитьУдалитьНа большом списке слов прогнать ваш "отсекатель" и другой реализованный по алгоритму Тартаруса. Скажем, питоновский. Если все корректно, то результат должен быть 1 к 1.