Русская морфология

Жигaн

Новичок
Автор оригинала: Kudja
кульная вещь, а вот интересуют кое какие вопросы - можно ли при помощи этого класса взять слово и указать что хочу его же в родительном падеже ед. чесле например???
На данный момент этой функциональности нет. Можно сделать так:
1) устанавливаем в опциях 'with_gramtab' => true
2) Получаем все словоформы для искомого слова с помощью getAllFormsWithGramInfo(). Результат будет таким:
PHP:
$result = array(
	0 => результат_1,
	1 => результат_2,
	…
)
где результат_1 = array(
	'forms' => array(список всех словоформ),
	'all' => список грамматических характеристик для каждой словоформы из ‘forms’
	'common' => общие граммемы для всех словоформ
);

каждый элемент из ‘all’ форматируется след. образом:
ЧАСТЬ_РЕЧИ граммемы_через_запятую; ЧАСТЬ_РЕЧИ граммемы_через_запятую; …
пример:
PHP:
if(false !== ($result = getAllFormsWithGramInfo('РЕБЕНКА'))) { var_dump($result); }
и результат
PHP:
array(1) {
  [0]=>
  array(3) {
    ["all"]=>
    array(10) {
      [0]=>
      string(10) "С мр,ед,им"
      [1]=>
      string(21) "С мр,ед,рд;С мр,ед,вн"
      [2]=>
      string(10) "С мр,ед,дт"
      [3]=>
      string(10) "С мр,ед,тв"
      [4]=>
      string(10) "С мр,ед,пр"
      [5]=>
      string(10) "С мр,мн,им"
      [6]=>
      string(21) "С мр,мн,рд;С мр,мн,вн"
      [7]=>
      string(10) "С мр,мн,дт"
      [8]=>
      string(10) "С мр,мн,тв"
      [9]=>
      string(10) "С мр,мн,пр"
    }
    ["common"]=>
    string(2) "од"
    ["forms"]=>
    array(10) {
      [0]=>
      string(7) "РЕБЕНОК"
      [1]=>
      string(7) "РЕБЕНКА"
      [2]=>
      string(7) "РЕБЕНКУ"
      [3]=>
      string(8) "РЕБЕНКОМ"
      [4]=>
      string(7) "РЕБЕНКЕ"
      [5]=>
      string(4) "ДЕТИ"
      [6]=>
      string(5) "ДЕТЕЙ"
      [7]=>
      string(5) "ДЕТЯМ"
      [8]=>
      string(6) "ДЕТЬМИ"
      [9]=>
      string(5) "ДЕТЯХ"
    }
  }
}
3) пробегаемся по результату и вытаскиваем слова с нужными граммемами
Список граммем можно посмотреть тут: http://www.aot.ru/docs/rusmorph.html
 

shark_255

Новичок
а можно сделать для переводов текста - к примеру
для мультиязычности ? То есть "на лету" переводить текст сайта?
 

alekciy

Новичок
Если честьно, мне не очень понятно, почему же данным тема находится в оффтопике... ведь проект явно интересный и полезный.
 

Farsh

~ on ~ high ~ wave ~
Воооо , то что надо мне сейчас , девхэду Жигану респект :)
Возникли вопросы :
1) Вы реализовали скрипт по алгоритму , расписанному в aot ?
2) Какие должны быть словари для этой штучки ?
Они должны содержать слова в исходной форме ?
Необходимы маскимально большие +))
Буду рад , если подкините ссылочек .
Заранее спасибо
 

Жигaн

Новичок
1) Да. Алгоритм предсказания я взял от aot
2) Словарь использовал от aot (не скомпиленный, в mrd формате)

Описание в общих словах: http://www.aot.ru/docs/sokirko/Dialog2004.htm
Более конкретно: в исходных текстах lemmatizer http://www.aot.ru/download.php в директории Docs/Morph_UNIX.txt.

В настоящий момент в словаре содержаться около 173 тысяч основ, что позволяет получить около пяти миллионов словоформ ;)

по предсказанию есть интересная инфа тут http://company.yandex.ru/grant/report2007.xml в Автоматизация построения словаря на материале массива несловарных словоформ
 

Wicked

Новичок
Жигaн
А не мог бы ты более подробно рассказать, что именно тебе пришлось придумать/разработать, чтобы из AOT получить phpmorphy со словарями?

Также интересно твое мнение насчет того, насколько трудоемко будет сделать аналогичный phpmorphy модуль, но в виде эксеншена для php.
 

FractalizeR

Новичок
А можно на другой хостинг дистрибуты выложить? А то h18 явный отстой....
 

Жигaн

Новичок
Принцип компиляции словаря я взял от aot. Реализация несколько иная т.к. бинарное представление словаря в aot имеет следующие недостатки при использовании в php:
  • необходимо загружать словарь полностью в память + надо делать некоторый препроцессинг для того
  • невозможно работать с разными кодировками по след. причинам:
  • невозможно хранить в словаре бинарные данные (к примеру ucs-2)
  • в коде прибито 3 языка – кодировки ascii, cp1251, cp1252 для English, Russian, German соответственно, добавить новый язык – гемор еще тот…
  • поиск в словаре строки S, длины N выполняется за время O(N), однако коэффициенты слишком велики для реализации на пхп
  • извлекать аннотации (данные ассоциированные со строкой добавленной в автомат) _очень_ дорого - вообще нереально реализовать в php

при проектировании словаря я пытался избавиться от этих недостатков + сделать доступ к словарю наиболее последовательным. В основе используется конечный автомат, представленный в mealy machine подобном виде. КА строится из сортированного списка строк, каждая строка – это словоформа + аннотация. Аннотации хранятся в отдельном блоке, в автомате присутствует только ссылка на нужный участок в блоке. В автомате могут присутствовать любые строки, нет зарезервированных символов. Для бинарного словаря строится два автомата:
1. автомат, построенный на основе списка всех словоформ
2. автомат, построенный на основе списка инвертированных окончаний, для предсказания по окончанию

для 1 используется представление trie как разреженной матрицы для ускорения поиска. Все данные в бинарном виде выровнены

У меня есть libMealy для доступа к fsa, правда из нее надо порезать лишнее. Сделать extension несложно, по сути, это должен быть wrapper не больше. Правда, я не знаю насколько это востребовано.
Я сейчас доделываю конвертер из hunspell для поддержки некоторых полезных языков ;). После этого смогу заняться экстеншеном.
 

Сергей Тарасов

Профессор
Отличная библиотека! Автору большой респект!

На скорость не тестил, но функционал превосходный!

Спасибо!
 

baev

‹°°¬•
Команда форума
Я понимаю, что не всем довелось читать Кэрролла, но поиском-то можно было воспользоваться?

- Вы так хорошо объясняете слова, сэр, - сказала Алиса. - Объясните
мне, пожалуйста, что значит стихотворение под названием "Бармаглот".
- Прочитай-ка его, - ответил Шалтай. - Я могу тебе объяснить все стихи,
какие только были придуманы, и кое-что из тех, которых еще не было!
Это обнадежило Алису, и она начала:

Варкалось. Хливкие шорьки
Пырялись по наве.
И хрюкотали зелюки
Как мюмзики в мове.

- Что же, хватит для начала! - остановил ее Шалтай. - Здесь трудных
слов достаточно! Значит, так: "_варкалось_" - это четыре часа пополудни,
когда пора уже варить обед.
- Понятно, - сказала Алиса, - а "_хливкие_"?
- "_Хливкие_" - это хлипкие и ловкие. "Хлипкие" значит то же, что и
"хилые". Понимаешь, это слово как бумажник. Раскроешь, а там два
отделения! Так и тут - это слово раскладывается на два! (*50)
- Да, теперь мне ясно, - заметила задумчиво Алиса. - А "_шорьки_" кто
такие?
- Это помесь хорька, ящерицы и штопора!
- Забавный, должно быть, у них вид!
- Да, с ними не соскучишься! - согласился Шалтай. - А гнезда они вьют в
тени солнечных часов. А едят они сыр.
- А что такое "_пырялись_"?
- Прыгали, ныряли, вертелись!
- А "_нава_", - сказала Алиса, удивляясь собственной сообразительности,
- это трава под солнечными часами, верно?
- Ну да, конечно! Она называется "нава", потому что простирается
немножко направо... немножко налево...
- И немножко назад! - радостно закончила Алиса (*51).
- Совершенно верно! Ну, а "_хрюкотали_" это хрюкали и хохотали... или,
может, летали, не знаю. А "_зелюки_" это зеленые индюки! Вот тебе еще один
бумажник!
- А "_мюмзики_" - это тоже такие зверьки? - спросила Алиса. - Боюсь, я
вас очень затрудняю.
- Нет, это птицы! Бедные! Перья у них растрепаны и торчат во все
стороны, будто веник... Ну а насчет "_мовы_" я и сам сомневаюсь. По-моему,
это значит "далеко от дома". Смысл тот, что они потерялись. Надеюсь, ты
теперь _довольна_? Где ты слышала такие мудреные вещи?
 

Жигaн

Новичок
Сергей Тарасов
Отличная, либа. Единственное, что мне не хватат до полного счастья, это

1) UTF-8
2) Возможность получить часть речи для входного слова в "один вызов"

На скорость не тестировал.
1) Поддержка различных кодировок будет в следующей версии. utf-8 для кириллицы снизит производительность ~ в два раза, имхо проще и быстрее через iconv текст прогнать.
2) Будет сделано в след. версии

По п2:
Я проектировал библиотеку в основном для лемматизации, все остальное не более чем side effect, отсюда такие проблемы.

В принципе оба пункта уже реализованы, осталось подточить немного.

Роберт
Предсказание я сделал по подобию AOT(осечки есть конечно), про качество от авторов:
http://www.aot.ru/docs/sokirko/Dialog2004.htm
Качество предсказания было подсчитано только для русского языка. Это было сделано следующим образом. Взяты новостные тексты, наугад выбраны 150 неповторяющихся предсказанных слов. Эти слова не должны быть аббревиатурами (все буквы в верхнем регистре). Все слова оказались либо существительными, либо прилагательными. Для 131 слова в результатах предсказания был хотя бы один правильный результат (одновременно лемма, часть речи, род, число и падеж). Т.е. точность предсказания - 87%. Этот результат вполне сравним с результатами других исследователей, например, для английского языка - 85 % (см. [5]) , или для французского - 88% (см [6]).
Теперь о шорьках мр\жр ;)
Вне контекста слово шорьки можно интерпретировать как:
1) существительное мужской род, лемма - шорёк
2) существительное женский род, лемма - шорька
3) прилагательное(краткое), лемма - шорький

в контексте понятно что 3) отпадает, остается существительное мр\жр.
Можно выдавать максимальное количество интерпретаций, а потом снимать омонимию. Не знаю насколько это хорошо - появляется лишнее звено, омонимию снять со стопроцентной точностью невозможно и тормозааа... В среднем (зависит от тематики естественно) количество предсказанных слов ~4%, так что может и нормально все.
 

Rin

*
UTF-8 в качестве внутреннего формата библиотеки абсолютно не нужен. Это не тот случай.
Использование iconv на входе и выходе будет лучшим решением.
 

Wicked

Новичок
Жигaн
В рамках стоящей передо мной задачи сбора статистики вхождения терминов в тексты для автоматической классификации научных текстов, нужно нормализовать эти самые тексты.

Поскольку слова, которые не содержатся в терминах тезауруса, нас не интересуют, то мне пришла мысль сделать неплохую оптимизацию скорости работы, составив hashmap "словоформа" -> array("базовые формы", ...) только для тех словоформ, которые могут иметь отношение к тем словам, которые содержатся в тезаурусе. Таким массивом впоследствии можно будет заменить функционал $morphy->getBaseForm(...) (назовем это вариантом 0).

[cut]

Я тупанул :)
Надо было этот способ раньше опробовать:
3) Составляем hashmap на базе списка словоформ, полученных из getAllForms() от списка словоформ на входе
1.1) Берем уникальные словоформы из тезауруса.
1.2) Получаем все родственные словоформы: $wf_to_wf = $morphy->getAllForms(...).
1.3) Составляем массив уникальных словоформ, сливая все полученные массивы второго уровня в один - $wf_unique.
1.4) Получаем базовые формы для этих словоформ: $wf_to_bf = $morphy->getBaseForm($wf_unique); Это и есть наш hashmap.

Каждый из вариантов, будучи натравленным на массив наших же словоформ (по идее, надо тестировать на чем-нибудь другом, типа научных текстов, но и это подойдет), показывает следующую статистику, собранную таким способом:
PHP:
$statistics["count_distribution"] = array();
foreach($bf as $wf_arr) {
  $cnt = is_array($wf_arr) ? count($wf_arr) : 0;
  $statistics["count_distribution"][$cnt]++;
}
ksort($statistics["count_distribution"]);
Код:
вариант|    0|    3
-------------------
$cnt   |     |
0      |   34|   43
1      | 7776| 7767
2      |  949|  949
3      |   71|   71
4      |    4|    4
5      |    2|    2
ПС:
'with_gramtab' => false,
'predict_by_suffix' => true,
'predict_by_db' => true

-~{}~ 07.04.08 14:57:

predict_by_suffix отключить не могу:
Catchable fatal error: Argument 3 passed to phpMorphy_Morphier_DictBulk::phpMorphy_Morphier_DictBulk() must implement interface phpMorphy_Morphier_Interface, null given, called in C:\WWWROOT\PhpMorphy\phpmorphy-0.2.3.1\src\common.php on line 318 and defined in C:\WWWROOT\PhpMorphy\phpmorphy-0.2.3.1\src\morphiers.php on line 231

-~{}~ 08.04.08 12:44:

И еще... можешь объяснить, зачем строится префиксное дерево в phpMorphy_Morphier_DictBulk::findWord() ?

У меня есть подозрения, что оно строится каким-то субоптимальным :)
Рассмотрим для префикса "АБСОЛЮТ":
Код:
[АБСОЛЮТ]
  [0] => НАЯ
[АБСОЛЮТН]
  [0] => О
  [1] => ЫЕ
[АБСОЛЮТНО]
  [0] => ГО
  [1] => Е
  [2] => Й
  [3] => М
[АБСОЛЮТНЫ]
  [0] => Й
А мне кажется, должно быть как-то так:
Код:
[АБСОЛЮТ]
  [0] => Н
[АБСОЛЮТН]
  [0] => АЯ
  [1] => О
  [2] => Ы
[АБСОЛЮТНО]
  [0] => ГО
  [1] => Е
  [2] => Й
  [3] => М
[АБСОЛЮТНЫ]
  [0] => E
  [1] => Й
Или это ни на что не влияет?

-~{}~ 08.04.08 16:34:

Нашел самый лучший, третий метод :) Обновил верхную часть этого коммента.
Осталось разобраться с этими словоформами (и еще похожими ненайденным) - http://phpclub.ru/paste/index.php?show=2037 - которые отличают этот метод от оригинального, и будет совсем красота.

ЗЫ: слова типа "МАРЦИНКЕВИЧА" вполне себе находятся в MorphWizard'е, скачанном с aot.ru. Попозже попытаюсь сбилдить последние словари, посмотрим что получится.
 
Сверху