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

Жигaн
не, ну мож я и ламер, но не имбицил. шмоп подключени работает. пхп 5.2.6, апач 1.х. я на соурсфодже отписал поподробнее о баге
 
Автор оригинала: Жигaн

[Farsh]
Там используется com объект(он платный у aot, стоит 250$, работает под виндой ;)) В пхп можно использовать при помощи http://de.php.net/manual/ru/book.com.php
Это понятно , но кроме платных исходников под винду , есть бесплатные под юникс .
У меня задача - соединить хотя бы lemmatizer с php , он запускается из cmd таким образом :
------
devPC:~# export RML=/home/AOT/morph
devPC:~# cd $RML
devPC:/home/AOT/morph# Bin/TestLem Russian
Loading..
Input a word..
>
------
После фразы Loading.. есть двухсекундная задержка .
Из php -
PHP:
$command = 'export RML="/home/AOT/morph"; cd $RML; Bin/TestLem Russian';
$output = shell_exec($command);
По смыслу должно быть тоже самое , но в итоге :"Loading.." , и все .. Насколько я понимаю это изза той самой задержки ( во время нее подгружаются словари ) . И у меня просто нет никаких мыслей , как можно это осуществить ..
Прошу помощи ;) Ошенама нужно ;)

-~{}~ 26.05.08 19:43:

Может ли быть это из-за того , что после запуска программы требуется время на подгрузку словарей , идет не весь ответ ?
 
на aot.ru есть утилита синтактичесчкого анализа lemmatizer.tar.gz можно за основу взять ее код.
 
Wicked
В первую очередь, отличия в подготовке словаря для предсказания, там сделано упрощенно.
berkut
Понял, действительно есть баг. Проблема в том, что stat() перестал возвращать ino ключ.
Обновил на sf, спасибо.
Farsh
Нее, ты дал пример питоновского скрипта, который использует COM компонент. Попробуй через proc_open открыть процесс... Либо переделай $RML\Source\TestLem\TestLem.cpp, это просто. А зачем тебе это?

-~{}~ 27.05.08 03:43:

Farsh
Кстати TestLem можно использовать так:
TestLem Russian words.txt
вывод идет в файл words.lem

> cat words.txt
ТЕСТИРУЕМ

> TestLem Russian words.txt
Loading..
read words.txt
process words.txt
Count of words = 1
Time = 0 seconds; 0 ticks
too few words to measure the speed
writing to words.lem

> cat words.lem
ТЕСТИРУЕМ -> ТЕСТИРОВАТЬ квпж#

квпж - это анкоды кв и пж, расшифровку смотри в $RML/Dicts/Morph/rgramtab.tab
 
Жигaн
посмотрел. Возник вопрос: а для патриции действительно нужно сортировать список слов? Я правильно понимаю, что "// find longest common prefix" - это единственное место, где используется выгода от сортировки?
 
а для патриции действительно нужно сортировать список слов?
нет, обычно как раз строят без сортировки, на упорядоченных данных построение дерева происходит намного быстрее.
// find longest common prefix" - это единственное место, где используется выгода от сортировки
весь алгоритм требует сортировки.

имхо можно ускорить обход дерева...
 
Жигaн
Есть предложение использовать вместо ПРОПИСНЫХ строчные по умолчанию, они чаще используются, а на конвертирование регистра тоже время нужно.

-~{}~ 06.06.08 14:03:

Планируется в будущих версиях функционал для снятия омонимии?

-~{}~ 06.06.08 16:23:

Пытался "подружить" phpMorphy и свой TextParser

При этом возникли затруднения, которые, конечно, обходятся, но хочется более элегантного и быстрого(?) решения.
Класс TextParser возвращает индексированный массив $alnum_all со списком слов, которые встречаются в тексте.
Ключами массива являются порядковые номера слов, значениями -- сами слова в кодировке UTF-8.
Слово -- последовательность букв (допускаются знаки "#" и "+" в конце для C#, C++) или цифр (но не букв и цифр вперемешку).
Для каждого слова из массива необходимо получить его базовую форму.

В настоящее время phpMorphy может работать одновременно только с одним языком.
Для каждого языка приходится создавать отдельный экземпляр класса, что не очень удобно:

Код:
$dict_bundle_ru = new phpMorphy_FilesBundle($dir, 'rus');
$morphy_ru = new phpMorphy($dict_bundle_ru, $opts);

$dict_bundle_en = new phpMorphy_FilesBundle($dir, 'eng');
$morphy_en = new phpMorphy($dict_bundle_en, $opts);

А при обходе массива $alnum_all для каждого слова дополнительно нужно определять язык, чтобы делать вызов getBaseForm() нужного экзепляра класса.
Если одни и те же буквы используются в разных языках, определять язык уже не просто (english / german / turkish).

Словарь в юникоде, содержащий несколько языков одновременно, решил бы эту проблему (язык вообще не важен будет, как я понимаю).
Кол-во веб-страниц в UTF-8 увеличивается (в виду преимуществ самой кодировки и развития программ, поддерживающих юникод), в однобайтовых кодировках -- уменьшается.
Думаю, это перспективно.

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

Почему в 2 раза? Где слабое место?
Если дело в переменной длине кодирования знаков в UTF-8, то можно попробовать UTF-16.
 
Rin
Словарь в юникоде, содержащий несколько языков одновременно, решил бы эту проблему (язык вообще не важен будет, как я понимаю).
Но создал бы очень много новых проблем. Представьте, что в нескольких разных языках есть слово которое в какой-либо форму пишется одинаково, но правила его изменения в разных языках различны. Как в таком случае модуль морфологии должен угадывать правила какого из языков от него хочет увидеть пользователь?

А при обходе массива $alnum_all для каждого слова дополнительно нужно определять язык,
Только вот определение языка для отдельно взятого слова задача практически неразрешимая. А для отдельно взятого текста примерно определить язык можно.

Если дело в переменной длине кодирования знаков в UTF-8, то можно попробовать UTF-16.
Символ в UTF-16 может представляться не только 2-я, но и 4-я байтами.

Жигaн:
>Поддержка различных кодировок будет в следующей версии.
utf-8 для кириллицы снизит производительность ~ в два раза, имхо проще и быстрее через iconv текст прогнать.
А почему скорость должна снизится? Я таких причин не вижу, а вот унификация интерфейса(для разных языков с разными кодировками) и экономия времени на перекодировках может быть существенна. Действительно если волнует переменная длинна символа и utf-8, то можно использовать тот-же utf-16 или utf-32, в первом правда символ тоже может занимать 4 байта, но это довольно редкое явление.
 
phprus
>Представьте, что в нескольких разных языках есть слово которое в какой-либо форму пишется одинаково, но правила его изменения в разных языках различны

Действительно, такое возможно. :)
В таком случае можно явно указать используемые языки и приоритеты, т.к. эта информация в большинстве случаев известна для текста. Например: array('ru', 'ua'), или array('en', 'de', 'it'). В случае коллизии выдавать основную форму слова для более приоритетного языка. Таких случаев не много должно быть и влияние на качество результата будет очень слабым. В существующих для phpMorphy словарях коллизия может возникнуть пока только для en и de. :)

>Только вот определение языка для отдельно взятого слова задача практически неразрешимая. А для отдельно взятого текста примерно определить язык можно.

Это верно. Но сейчас в getBaseForm() массив со словами на разных языках вперемешку не подсунешь. Одно от другого отделять нужно.

>А почему скорость должна снизится?
Как я понимаю, слова в utf-8 разбирать на буквы придется, а буквы переменной длины. Соотв-но дополнительные проверки немного снизят производительность.
Хотя preg_match_all('/./su') должна очень быстро работать для этих целей.
Да и библиотеки iconv и mbstring на Си написаны.
Так что существенных "тормозов" быть не должно.

Для юникода в качестве внутреннего формата можно ограничиться UCS-2, где используется строго 2 байта для кодирования символа, поэтому резать слово на части очень удобно. Для европейских языков этого хватает с избытком. Азиатские языки (арабский, китайский...) вроде не планируются поддерживать в phpMorphy. :)
 
Rin
Как я понимаю, слова в utf-8 разбирать на буквы придется, а буквы переменной длины. Соотв-но дополнительные проверки немного снизят производительность.
То, что немного это понятно, но это немного должны быть очень маленьким, а никак не в 2 раза.

Хотя preg_match_all('/./su') должна очень быстро работать для этих целей.
А я думаю, что нет. Помоему однократный проход по строке с выполнением элементарных битовых операций должен быть быстрее чем построение и исполнение автомата разбирающего регулярное выражение. Но чтобы точно выяснить нужно провести измерения.
 
а можна поинтересоваться, если getPseudoRoot() для англ. языка, на слове Constanza возвращает stanz - это так и должно быть?
 
phprus
>но это немного должны быть очень маленьким, а никак не в 2 раза.

Согласен что оценка завышена, но, возможно, есть еще какие-нибудь "подводные камни", о которых мы пока не знаем. Дерево, кстати, тоже увеличится примерно в 1,5-2 раза + склейка всех языковых словарей в один. В результате чтение дерева будет медленнее.

Вобщем то я и на 2 раза согласен, через год-два производительность компьютеров опять в 2 раза увеличится :)

>Помоему однократный проход по строке с выполнением элементарных битовых операций должен быть быстрее чем построение и исполнение автомата разбирающего регулярное выражение. Но чтобы точно выяснить нужно провести измерения.

В регулярках есть компиляция во внутренний формат, оптимизация и быстрый сишный код. Я в своё время проводил измерения. Рег. выражение оказалось быстрее, cм. is_utf8(), utf8_check(). В большинстве случаев код с использованием грамотно составленных рег. выражений быстрее, чем реализация на чистом PHP.
 
Жигaн:
>Поддержка различных кодировок будет в следующей версии.
utf-8 для кириллицы снизит производительность ~ в два раза, имхо проще и быстрее через iconv текст прогнать.

Почему в 2 раза? Где слабое место?
Если дело в переменной длине кодирования знаков в UTF-8, то можно попробовать UTF-16.
1) чукча не читатель, чукча писатель? ты пробовал сам разобраться в том, где тут цитированное, а где твое?
2) медленнее в 2 раза будет из-за того, что в среднем на одну русскую букву будет не 1, а 2 байта. Из-за, например, этого придется делать в 2 раза больше итераций в работе с деревом.

-~{}~ 07.06.08 17:10:

В таком случае можно явно указать используемые языки и приоритеты, т.к. эта информация в большинстве случаев известна для текста. Например: array('ru', 'ua'), или array('en', 'de', 'it'). В случае коллизии выдавать основную форму слова для более приоритетного языка. Таких случаев не много должно быть и влияние на качество результата будет очень слабым. В существующих для phpMorphy словарях коллизия может возникнуть пока только для en и de.
Насколько я знаю структуры данных, производительности (по сравнению с работой с несколькими объектами phpMorphy) это не прибавит, а скорее наоборот, отнимет. Так что это тупо делается в виде пристройки на 100 строк к phpMorphy.

-~{}~ 07.06.08 17:24:

cм. is_utf8(), utf8_check()
смысл первой функции от меня вообще ускользает. А вторую прощу сделать в виде
function ($data) {return iconv('UTF-8', 'UTF-8//IGNORE', $data) === $data}, которая примерно в 20 раз быстрее, чем регулярка, и в 80 раз - чем побайтовая обработка.
 
Wicked
2) медленнее в 2 раза будет из-за того, что в среднем на одну русскую букву будет не 1, а 2 байта. Из-за, например, этого придется делать в 2 раза больше итераций в работе с деревом.
А зачем в 2 раза больше итераций? От изменения кодировки что-ли количество символом с строке изменится? Нет. Изменится только размер самого символа в байта, так что просто на каждом узле дерева будет не однобайтный символ хранится, а двухбайтный (или 4-х байтный), а замена сравнения однобайтных символов на двухбайтные, я думаю, не может вызвать падение производительности в 2 раза. (в структуре дерева я могу ошибаться, так как точно не знаю как оно строится)
Или там дерево строится только по байтам вводимой строки, а не по символам?
 
Просто сейчас байты и символы совпадают :)

Wicked:
>function ($data) {return iconv('UTF-8', 'UTF-8//IGNORE', $data) === $data}

Ваш код должен обработать всю строку до конца, чтобы потом возвратить результат. is_utf8(), utf8_check() возвращают FALSE сразу при первой неудаче. Часто об этом становится известно уже на первых нескольких символах.
 
Ваш код должен обработать всю строку до конца, чтобы потом возвратить результат. is_utf8(), utf8_check() возвращают FALSE сразу при первой неудаче. Часто об этом становится известно уже на первых нескольких символах.
Ага... Посему я делаю такие выводы:
* Ваша функция ориентируется на быструю работу в 1% проблемных пользователей (юзеры, столкнувшиеся с проблемной формой, хакеры, досеры). Для оставшихся 99% честных пользователей она делает свою работу в 80 раз медленней, чем моя.
* Моя функция ориентируется на быструю работу во всех случаях.

-~{}~ 07.06.08 21:06:

надо бы вынести оффтопик .-)
 
Wicked
как-то так, ага
А почему нельзя в случае перехода к многобайтным кодировкам строить дерево по символам, а не по байтам исходной строки? В языке-же базовый (слово не очень удачное, но другое подобрать не могу) элемент - это символ, а не байт.
 
Сверху