RuMor
RuMor - морфологический модуль для русского языка, включающий в себя
две основные функции: нахождение базовой формы слова или всех его словоформ.
Данный модуль может использоваться в поисковых системах для улучшения
поиска по документам с русским текстом.
В качестве исходных данных для генерации словоформ используется словарь Зализняка,
дополненный 30 тысячами основ. Всего в словаре содержится около 125 тысяч основ,
что позволяет генерировать более 3500000 словоформ.
Модуль полностью написан
на языке Перл (также есть версия на ПХП) и не требует каких-либо дополнительных библиотек.
Он легко может быть интегрирован в любую web-систему, где требуется
поиск с учетом морфологии русского языка. Модуль является абсолютно кроссплатформенным
продуктом и может работать как на локальной машине под управлением Windows
для написания и отладки приложений, так и на вебсервере.
Размер сгенерированного словаря для русского языка составляет примерно
5 Мб. Модуль имеет два режима работы: с загруженным в память словарем и
режим работы со словарем, хранящимся на жестком диске. Первый режим
обеспечивает наиболее быструю скорость работы и предпочтителен
во время индексации, когда необходимо обрабатывать большие объемы информации.
Второй режим удобен во время поиска, когда нужно обработать всего несколько слов,
и нет необходимости считывать в память весь словарь.
Скорость работы модуля в режиме нормализации около 7000 слов в секунду
(в режиме работы с жестким диском примерно в два раза меньше),
что вполне достаточно для локального поискового механизма
(ПХП версия на данный момент работает со скоростью около
1000 слов в секунду).
Тест
Практическое использование модуля можно посмотреть на примере
поиска по сайту TarraNova,
где он был использован для индексации 40 Мб русских текстов.
Download demo
Вы можете скачать демонстрационную версию модуля бесплатно.
Данная версия поставляется со словарем, состоящим из слов
на буквы "АБВГД". Кроме того, отсутствует скрипт для конвертации
словарей от ispell.
rumor-2.0-demo (последние изменения 10.08.2020)
Купить
Стоимость модуля - 50 USD (цена включает бесплатные обновления
и поддержку в течение одного года).
Оплатить покупку можно в системе WebMoney, переведя деньги на
кошелек Z599188235387 (или R210677682613 для рублевых переводов по текущему курсу)
или в системе Яндекс.Деньги на кошелек 4100116754259 по текущему курсу.
Юридическим лицам наиболее удобно будет совершить покупку через систему
SWRUB. В этом случае Вам будут высланы
необходимые финансовые документы.
Стоимость обновления модуля с предыдущей версии - 25 USD.
- Webmoney - Z599188235387 (или R210677682613)
- Яндекс.Деньги - 4100116754259
- SWRUB
Использование
Модуль состоит из трех основных файлов:
rumor.pm (rumor.php) - программный код модуля.
tree.fin - основной файл словаря.
prof.fin - дополнительная информация о словоформах, необходимая для построения полной парадигмы.
Также есть два дополнительных скрипта:
Модуль поставляется в двух вариантах: Perl и PHP. Обе версии имеют практически одинаковый
набор функций, поэтому дальнейшее описание будет базироваться на Perl с указанием различий,
присущих PHP.
В начале Вашего скрипта необходимо подключить модуль:
use rumor;
или
include "rumor.php";
Затем необходимо вызвать функцию prep_dict и передать ей в качестве
параметра имя директории, где находятся словари.
prep_dict(".");
Существует альтернативный вариант данной функции - prep_dict_MEM.
В этом случае словарь будет полностью загружен в память и в дальнейшем
модуль будет работать примерно в 1.5-2 раза быстрее. Это может быть удобно,
когда нужно обработать большой объем информации, например при индексировании.
Для получения базовой формы слова используется функция get_base_form, которой
в качестве параметра передается слово (в нижнем регистре). Функция возвращает
массив основ данного слова (в тех случаях, когда данное слово может быть получено
путем изменения разных основ). В большинстве случаев функция вернет одну основу.
@base = get_base_form($word);
или для PHP
$base = get_base_form($word);
Для генерации словоформ заданного слова используется функция get_paradigm.
@forms = get_paradigm($word);
Функция возвращает массив возможных словоформ. Слово должно быть в своей нормальной (словарной) форме.
Для генерации всех словоформ заданного слова используется функция get_all_forms.
@forms = get_all_forms($word);
Функция возвращает массив возможных словоформ. Слово может быть в произвольной форме.
Если данная форма может быть получена путем изменения разных слов, функция вернет
объединенный список словоформ всех возможных основ для данного слова.
Для генерации полной парадигмы слова используется функция get_full_paradigm.
@ref_array = get_full_paradigm($word);
Функция возвращает массив ссылок на структуры, в которых содержится информация о слове.
Формат возвращаемой информации следующий: каждая возвращенная ссылка ссылается на массив,
в первом элементе которого содержится общая информация о слове, например
"существительное мужского рода неодушевленное", второй и третий элементы массива
являются массивами, в одном из которых перечислены словоформы, а в другом морфологическая
информация о каждой словоформе. Например:
Array
(
[0] => существительное мужского рода одушевленное
[1] => Array
(
[0] => человек
[1] => человека
[2] => человеку
[3] => человека
[4] => человеком
[5] => человеке
[6] => люди
[7] => людей
[8] => людям
[9] => людей
[10] => людьми
[11] => людях
)
[2] => Array
(
[0] => ед,им
[1] => ед,рд
[2] => ед,дт
[3] => ед,вн
[4] => ед,тв
[5] => ед,пр
[6] => мн,им
[7] => мн,рд
[8] => мн,дт
[9] => мн,вн
[10] => мн,тв
[11] => мн,пр
)
)
Пример кода для работы с подобной структурой:
@res = get_full_paradigm($word);
foreach $res (@res) {
print "$$res[1][0] - $$res[0]\n";
for ($i=0;$i<=$#{$$res[1]};$i++) {
print "$$res[1][$i] - $$res[2][$i]\n";
}
}
Версия функции на PHP имеет схожую реализацию - возвращается многомерный
массив, с которым можно работать примерно таким образом:
$res = get_full_paradigm($word);
foreach ($res as $data) {
print "<BR>".$data[1][0]." - $data[0]<BR>";
for ($i=0;$i<=count($data[1])-1;$i++) {
print $data[1][$i]." - ".$data[2][$i]."<BR>";
}
}
Для получения детальной информации о конкретной словоформе используется функция
rumor_get_word_info. Функция возвращает массив хешей (массив ассоциативных массивов)
для каждого возможного варианта со следующими ключами:
- "word" - словоформа
- "baseword" - базовая (словарная) форма слова
- "rule" - номер правила, по которому изменяется данное слово
- "wordcode" - код слова
- "wordinfo" - текстовая информация о слове
- "formcode" - код словоформы
- "forminfo" - текстовая информация о словоформе
Например слово "душу" можно получить из трех основ - "душа", "душ" и "душить". Поэтому функция
вернет массив из трех хешей:
word => душу
baseword => душить
rule => 306
wordcode => 12
wordinfo => глагол несовершенного вида
formcode => НЕД1
forminfo => дст,нст,1л,ед
word => душу
baseword => душ
rule => 48
wordcode => 1
wordinfo => существительное мужского рода неодушевленное
formcode => Д
forminfo => ед,дт
word => душу
baseword => душа
rule => 37
wordcode => 3
wordinfo => существительное женского рода неодушевленное
formcode => В
forminfo => ед,вн
Пример использования функции - Perl:
@res = rumor_get_word_info("душу");
foreach my $res (@res) {
print "word => ",$$res{word},"\n";
print "baseword => ",$$res{baseword},"\n";
print "rule => ",$$res{rule},"\n";
print "wordcode => ",$$res{wordcode},"\n";
print "wordinfo => ",$$res{wordinfo},"\n";
print "formcode => ",$$res{formcode},"\n";
print "forminfo => ",$$res{forminfo},"\n\n";
}
PHP:
$res = rumor_get_word_info("душу");
foreach ($res as $data) {
print "Result:\n";
print "word => ".$data['word']."\n";
print "baseword => ".$data['baseword']."\n";
print "rule => ".$data['rule']."\n";
print "wordcode => ".$data['wordcode']."\n";
print "wordinfo => ".$data['wordinfo']."\n";
print "formcode => ".$data['formcode']."\n";
print "forminfo => ".$data['forminfo']."\n";
}
- Номер правила словоформирования ("rule") является внутренним номером,
который может меняться от версии к версии.
- Список кодов слов и словоформ, а также соответсвующую текстовую расшифровку
кодов можно посмотреть в исходниках модуля.
- Поскольку изначально модуль проектировался для использования
в поисковых системах, было принято решение выделить фамилии в особый класс -
"существительное общего рода одушевленное", в котором объединены мужской род,
женский род и множественное число.
Для приведения слова в конкретную форму используется функция rumor_set_wordform.
На вход функции подается словарная форма слова, номер правила и код требуемой словоформы.
Функция возвращает строку со словоформой или "-1" в случае ошибки (например когда
в правиле словообразования отсутствует требуемая словоформа). В отличие от предыдущей функции,
которая возвращала массив возможных вариантов, данная функция всегда возвращает только один
вариант, поэтому на вход ей нужно подавать правильный номер правила, по которому изменяется
слово. Номер правила нужно предварительно получить используя функцию rumor_get_word_info.
Например нужно получить винительный падеж множественного числа слова "кошка". Применив функцию
rumor_get_word_info мы узнаем, что данное слово может означать как одущевленный предмет
(животное), так и неодушевленный (инструмент). И в каждом случае используется свое правило.
И в результате мы получим либо "кошек" для одушевленного существительного, либо "кошки"
для неодушевленного. Пример использования функции:
$wordform = rumor_set_wordform("кошка",62,"ВМ"); # "кошек"
$wordform = rumor_set_wordform("кошка",71,"ВМ"); # "кошки"
Номера правил словообразования (62 и 71) могут измениться в следующих версиях.
Примечание: модуль рассчитан на работу с данными
в кодировке win-1251.
Кодировки
Поскольку потенциально морфологический анализатор может работать
с несколькими языками одновременно (используя словари от программы ispell или
самостоятельно созданные словари), то сам
модуль не имеет никакой информации о кодировках. Скрипт работает
с байтами и обязанность программиста подавать на вход данные
в необходимом формате. Практически любой символ может являться
буквой при создании новых словарей, за исключением двух служебных символов: "|" и "#".
Оригинальный словарь для русского языка использует кодировку Windows-1251,
слова содержатся в словаре в нижнем регистре. Соответственно на вход модуля
нужно подавать данные в этой же кодировке и в нижнем регистре.
Сам модуль не производит никаких преобразований над входными данными.
Также нужно учесть, что в словаре не используется буква "ё", поэтому
ее нужно заменять на "е".
При использовании словарей от ispell разработчик должен решить
в какой кодировке добавить слова в словарь и при необходимости
самостоятельно перекодировать исходные словари. Некоторые словари
используют буквы как в верхнем так и в нижнем регистре. В этом случае
скрипт генерации бинарного словаря автоматически преобразует все слова
к нижнему регистру, для чего ему необходимо указать, какие символы
относятся к верхнему, а какие к нижнему регистру. Для этого в скрипте
"add_ispell_dic.pl" есть две переменные "$CAP_LETTERS" и "$LOW_LETTERS".
В первой переменной нужно перечислить все символы верхнего регистра,
а во второй соответствующие им символы нижнего регистра. Например:
# Win 1251 encoding
my $CAP_LETTERS = '\xC0-\xDF\xA8\xB8';
my $LOW_LETTERS = '\xE0-\xFF\xE5\xE5';
Генерация пользовательского словаря
Пользователи имеют возможность самостоятельно пополнять словарь
новыми словами, используя скрипт "add_word.pl". Поместите этот скрипт в одной
директории с модулем RuMor (rumor.pm) и бинарным словарем (tree.fin).
Создайте поддиректорию "my_dic", в которой будут размещаться ваши словари.
Файлы словарей должны иметь расширение "dic" (например "new_dictionary.dic").
Файлы пользовательских словарей являются обычными текстовыми файлами,
в которых для каждого нового слова нужно в скобках указать по какому правилу
оно изменяется. Для этого нужно подобрать другое слово из тех, которые
уже есть в словаре, и которое имеет такой же набор словоформ, что и новое слово.
Например:
индиец (австралиец)
ноченька (авоська)
поддельный (абажурный)
согласие (абонирование)
вернуть (блеснуть)
фотография (аббревиация)
То есть слово "индиец" изменяется аналогично слову "австралиец" и так далее.
Если не удается подобрать слово с аналогичным набором словоформ, можно создать новое правило
словобразования, для чего нужно в скобках перечислить
все словоформы нового слова, причем первой в списке должна идти словарная форма слова,
а затем все остальные. В дальнейшем можно ссылаться на вновь созданное правило
для других слов. Например:
город (город, города, городом, городе, городами, городам, городах)
дом (город)
Затем нужно запустить скрипт "add_word.pl" и новые слова будут добавлены в словарь.
Желательно по возможности использовать уже существующие правила,
а не создавать свои собственные, так как в первом случае даже
для новых слов будет доступна полная морфологическая информация
по словоформам.
- Файлы словарей должны быть в кодировке Windows-1251.
- При подготовке пользовательских словарей можно воспользоватся
этим адресом http://risearch.com/cgi-bin/demo/rumor/rumor_full.pl
для проверки какие слова уже есть в словаре.
- Результаты работы скрипта пишутся в файл "log.txt", где можно посмотреть,
какие слова не были добавлены (это может произойти, если в скобках написано слово,
которое отсутствует в словаре).
- Перед изменением словаря создается резервная копия файла - "tree.fin.bak"
(этот файл будет перезаписан при следующем запуске "add_word.pl", поэтому желательно
сохранить резервную копию оригинального словаря в другом месте).
- В словаре предусмотрено место для 2000 правил, на данный момент уже существует 1088 правил.
Следовательно для пользовательских словарей остается около 900 правил.
Использование словарей ispell
ispell это одна из наиболее популярных бесплатных программ проверки орфографии
на Unix-системах. В рамках проекта ispell создано множество словарей для разных языков,
распространяемых под лицензией GPL, которые в определенных пределах можно использовать
и для задачи морфоанализа. Но нужно учесть, что изначально эти словари создавались
для проверки орфографии, поэтому качество морфоанализатора основанного на этих
словарях заметно ниже специализированных словарей. Также нужно учесть, что скрипт
конвертации словарей ispell в формат RuMor поддерживает только часть возможностей
ispell и абсолютно корректная конвертация словарей для всех языков не гарантируется.
Скрипт конвертации проверялся на словарях для английского, немецкого и украинского
языков.
Словари ispell обычно состоят из двух файлов: файл с правилами генерации словоформ
(так называемый affix файл) и собственно словарь, где для каждого слова указаны
номера правил, которые нужно применить к этому слову. Если аффикс файл или словарь
разбиты на части, их нужно слить вместе. Скрипт конвертации поддерживает preffix правила
(правила приставок), но для каждой возможной приставки в словарь будет добавлено
отдельное слово, потому что как правило приставки изменяют смысл слова и логично
считать это отдельным словом. Соответственно для тех языков, где приставки участвуют
в формировании словоформ, использование RuMor невозможно.
Для конвертации словаря нужно задать несколько параметров в скрипте "add_ispell_dic.pl":
# ispell dictionary file
my $dic_file = "ispell/base.dic";
# ispell affix file
my $affix_file = "ispell/affix.aff";
# RuMor dictionary file
my $rumor_dic = "tree.fin";
Также прочтите раздел документации, посвященный кодировкам. При необходимости
перекодируйте словари и установите параметры для символов верхнего и нижнего
регистра. После чего можно запустить скрипт и новые слова будут добавлены
в словарь. Старая версия словаря будет сохранена под именем "tree.fin.bak",
но при следующем запуске конвертирующего скрипта она будет перезаписана,
поэтому рекомендуется сохранить оригинальный словарь в надежном месте.
В случае какой-либо ошибки отменить изменения нельзя.
History
- Ver. 2.0 - 14.01.2021
- Добавлена функция для получения полной информации по словоформе:
часть речи, род, число, падеж.
- Добавлена возможность конвертации словарей от ispell в формат RuMor.
- Функции для работы со словарем загруженным в память для версии на ПХП
теперь работают с нормальной скоростью (в 1.5-2 раза быстрее, чем со
словарем на диске).
- Ver. 1.4 - 01.04.2020
- Добавлена возможность самостоятельно пополнять словарь .
- Ver. 1.2 - 05.02.2020
- Добавлено более 6000 фамилий российских политиков, предпринимателей
и других известных личностей.
- Ver. 1.2 - 01.07.2020
- Изменен формат словаря.
- Исправлено несколько ошибок.
- Ver. 1.1 - 02.02.2020
- Словарь дополнен 15-ю тысячами фамилий.
- Ver. 1.0 - 16.10.2020
- Полностью обновлен словарь, который теперь базируется на словаре Зализняка.
- Оптимизирован алгоритм, скорость работы увеличена примерно на 30%.
- Ver. 0.3 - 07.04.2020
- Очередная оптимизация кода.
- Ver. 0.2.b - 24.03.2020
- Модуль был практически переписан заново,
в результате скорость работы увеличилась на порядок.
- Ver. 0.1.b - 14.03.2020
|