Как стать автором
Обновить

Комментарии 89

А где это вообще можно применить?
ключевые словосочетания на основе частей речи, формирование БД сущностей (существ.) и связей (глаголы) (с доработкой соотв.) для анализа ядра текстов и их дальнейшей автоматической сортировки по заданным критериям, чат-триггеры и т.п.
очень примитивная реализация.
Вам стоит взглянуть сюда и сюда
Для анализа текста эта функция подойдет в 100% случаев. Т.к. при этом не происходит четкого сравнения, а лишь подсчет количества (частей речи, слов, букв и т.д.) и получение отношения одного количественного параметра к другому (веса).
Функция не рассчитана на 100% разбор предложения по частям речи, т.к. это решается только со словарями.
Предсказание порядка следований частей речи в предложении скоро выложу.
Незнаю насколько это правдивая история, но тем не менее:
В какойто программе делали определение пола по имени и фамилии
Но программа время от времени выдавала неправильный результат, после долгих мучений добавили еще допонительное поле «отчество»
Если отчество заканчивалось на «ич» то мужского пола если на «на» то женского.

Я к чему — ваш код всеравно будет выдавать ошибки и от этого никак не избавится. Работать будет только если есть однозначный критерий правильности.
Однозначного — пока нет. Нужно стремиться к этому. Планирую по словосочетаниям в дальнейшем снижать вероятность ошибок (отталкиваясь от фразопостроения в рус. яз.).
Видимо, поле «пол» им религия не позволила добавить.
История умалчивает.
Для пишущих на перле есть модуль Lingua::RU::Inflect — он позволяет, помимо основной своей функции — склонения, ещё и определять пол по имени.

Пол определяется следующим образом:

1. Если есть отчество, пол однозначно определяется по нему.

2. Проверяем имя:

     2.1. Некоторые мужские имена оканчиваются на -а, а женские  — нет (Никита, Илья, Любовь) — проверяем имя на попадание в такой список исключений. Если имя есть среди исключений — пол определён.

     2.2. Есть имена (Женя, Саша, Валя), по которым пол нельзя определить — смотрим, не является ли имя именно таким. Если не является — проверяем окончание: женские имена заканчиваются на -а, -я, мужские — на согласную.

3. Переходим к проверке по фамилии: фамилии, кончающиеся на -ева, -ина, -ына, -ёва, -ова, -ая, -яя — женские, на -ев, -ин, -ын, -ёв, -ов, -ий, -ый — мужские.

4. Если попали сюда, значит, пол нельзя определить — подобный алгоритм не может справиться с такими именами как Саша Петренко или Женя Кац.
4. С этими именами никто не справится, не то что алгоритм
Ваш текст содержит слишком много ошибок, а вы беретесь судить попытку человека сделать полезную функцию для обработки русского языка.
Никто никого не судит.
Одна из моих школьных олимпиадных задачек. :) эх
Слово «Маршировать» — это разве не глагол?
Не пробовали делать массовое тестирование на большой базе слов с известными частями речи?
А, да, еще со знаками препинания в коде проблема. Если помним, то в русском языке запятые, и т.п. ставятся сразу после слова, что выведет из строя логику сравнения.
Зато вы подкинули мне любопытную идею: сервис типа гитхаба, но с редактированием в реалтайме — может получиться забавно.
Апдейт выложу позже. Доработать надо код.
Массово — не пробовал. Прорабатываю алгоритм.
Скорее всего будет дерево весов частей слова, далее — соседних словосочетаний (по частям речи на пред. уровне) и т.д.
Я переживаю, что вам могут слить топик и энтузиазм за компанию за то время, что вы будете дорабатывать код из этого состояния в что-то более-менее соответствующее.
Я постараюсь побыстрее. А «слить энтузиазм за компанию» — это вряд ли.
Ну, это не только в русском, да и не все знаки препинания (например, тире отбиваются пробелами с обеих сторон). И, кстати, если уж говорить о знаках препинания, то пришла в голову мысль: такая система должна уметь обрабатывать не только правильно написанные тексты, но и тексты людей, которые зачем-то ставят знаки препинания нетрадиционным способом, например, вот так, или даже так.
Хм, а парсер молодец — мои примеры ужасной расстановки пробелов вокруг запятых пофиксил. :D
Да что там говорить. Всем известное слово из трех букв, оказывается, глагол. Наверное, повелительное наклонение от «ховать» (прятать). :)
<irony>А каким образом здесь замешано панковское приветствие?</irony>
Я бы еще знаки препинания вырезал бы. С ними начинается неадекват.
print_r(chastrechiRUS('Существительное'));

Array
(
[0] => 1
)
Существительное-пресуществительное существительное
Подразумевается, что текст — нормальный: обработанный на предмет повторов (similarity) и содержащий не менее двух слов для дальнейшего анализа соседних частей речи.
Здесь: либо 2 и более слова, либо словарь исключений. По-другому — не знаю пока как…
«Косил косой косой косой» — удачи в распознавании ;)
самый убойный комментарий для приведенного кода
Спасибо! Допишу на след. этапе (когда деревья будут):
/*
Группы окончаний:
1. прилагательное
2. причастие
3. глагол
4. существительное
*/

Замены порядков частей речи:
3111=>3414 (3441) — «Косил косой косой косой»
1311=>4314 (4341) — «косой Косил косой косой»
1131=>1434 (4134) — «косой косой Косил косой»
1113=>1443 (4143) — «косой косой косой Косил»

В скобках — вероятность такого порядка следования частей речи меньше.
А кто вам сказал, что «косой» — это существительное (в именительном падеже)?
Косой — это сущ. в творительном падеже (или именительном) или прилагательное ед. числа муж.рода. Функция падеж не определяет.
Я что-то упустил?
Косой — это не существительное в именительном падеже, а прилагательное. В том числе и в данном предложении. Поэтому все ваши варианты трактовки с двумя существительными ошибочны.
Если брать предложение, то НЕТ. Если просто набор слов — ДА.
Вы, простите, роль слова в предложении (подлежащее) с его, собственно, частью речи (прилагательное) не путаете?
Нет.
«данные на носителе» — «данные» — сущ.
«данные строки» — «данные» — прил.
Слово «данные» и слово «косой» — это два разных слова. То, что верно для одного, не обязательно верно для другого.
Ок. Какие будут предложения по правильной идентификации частей речи?
Я же говорю: в этом предложении два прилагательных, глагол и одно существительное. А вот как вы их будете распознавать (учитывая, что даже человек этого не может) — я не знаю.
Т.к. это редкий случай, когда два одинаковых прилагательных в одном предложении, и прилагательное имеет меньший вес (чем сущ. или глагол), можно опираться на замены, указанные выше.
Как иначе — я пока тоже не знаю.
Прилагательное имеет меньший вес -> получили три существительных.
запер замок на замок
чтобы замок не замок
Это пять!
Думаю как детектить…
На данном примере, лучше использовать другую структуру массива окончаний. Если я не ошибаюсь, оптимальней будет вот-так:
(… заранее, простите за выравнивание текста, хабра не дает проставить отступы =) вот с отступами: pastebin.ubuntu.com/1229060/ )

function chastrechiRUS($string) {
$endings = ['ыми' => 1, 'ей'=> 1, 'ий' => 1,… ,'ивш' => 2, 'ывш' => 2, 'ующ'=>2,… ];
$endings_length = [2,3];
$ret_data = array();
$words = explode(' ',$string);
foreach ($words as $wk => $w) {
$ret_data[$wk] = 0;
foreach ($endings_length as $length) {
$tmp_ending = substr($w,-$length);
if (isset($endings[$tmp_ending])) {
$ret_data[$wk] = $endings[$tmp_ending];
break;
}
}


}
return array_reverse($ret_data);
}
source не удаляет отступы
function chastrechiRUS($string) {
    	    $endings = ['ыми' => 1, 'ей'=> 1, 'ий' => 1, ... ,'ивш' => 2, 'ывш' => 2, 'ующ'=>2, ... ];
	$endings_length = [2,3];
	$ret_data = array();
	$words = explode(' ',$string);
	foreach ($words as $wk => $w) {
		$ret_data[$wk] = 0;
		foreach ($endings_length as $length) {
			$tmp_ending = substr($w,-$length);
			if (isset($endings[$tmp_ending])) {
				$ret_data[$wk] = $endings[$tmp_ending];
				break;
			}
		}
	

	}
	return array_reverse($ret_data);
}
Сейчас мне source не поможет… Все дело из-за отрицательной кармы =(
Фраза «Определение, конечно не 100%, но можно легко дорабатывать» вряд ли может вызвать что то кроме улыбки, для тех кому действительно интересна эта тема.
Хочу предложить Вам сравнить роботу своего скрипта с phpMorphy
Как я понял: у Вас идет работа со словарями. Это совсем другой путь реализации этой задачи.
Т.е. если слова в словаре нет, то оно уже не будет распознано? Или я ошибаюсь?
Ну это не мой проект
Но насколько я понял, там смесь дерева выбора и алгоритмов предсказания
Вы не думали что самый лучший вариант решения задачи будет использовать какой то алгоритм с обучением (например нейронную сеть), это позволит например снимать морфологическую омонимии на основе близлежащих слов
Если интересна тема, можете причитать дисертацию «Морфологическая и синтаксическая обработка текста (модели и программы)»
95% точности… это не 100% (стр.80)
А Вы решили сделать 100%?
Ну как сделаете, следующим логическим шагом будет сделать поисковик/переводчик с 100% правильной работой
Не забивайте себе голову глупостями, ложитесь спать, завтра рано в школу
Для начала — хотя бы выше 95%
а нет ощущения, что это — принципиально не правильный подход к проблеме? Пытаться найти универсальные закономерности в системе, в которой изменения происходят бесконтрольно, хаотично. Бесконечное множество исключений из правил. А пытаться учесть исключения, значит получить тот же словарь, только в виде костылей
По-логике — исключений должно быть меньше. (ИМХО)
Множество исключений вполне конечно, и закономерности там есть.

Но подход в статье и правда принципиально неправильный: выдумывать эти закономерности от балды — вместо того, чтобы выявить их из словаря + возможно, какой-то частотной статистики. Тут, в принципе, код анализатора даже имел бы право на жизнь, если б данные не от балды были, а какие-то осмысленные.
Это — да. Код писался для 90-95% случаев. Остальные — это уже «допиливание» до идеала.
(Функцию обновил только что)
… цифры 90-95% — это ведь тоже от балды)

Тут пока нечего допиливать. Вот добавили новое правило, как проверить, лучше стало разбирать или хуже (precision, recall)? А никак сейчас. Что-то, возможно, лучше стало разбирать, а что-то хуже. Добавили «тью» для числительных, солист Muse стал числительным.

Допиливание в текущем виде не приближает к идеалу (и imho является напрасной тратой времени), т.к. критериев для добавления/изменения/удаления правил нет.

Чтоб были критерии какие-то, нужна какая-то оценка качества разбора. Код нужно поэтому писать для оценки качества разбора (анализатор написали уже), а на основе этих оценок уже выбирать правила (если уж собрались их вручную собирать).

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

… и мы опять пришли к словарю — не проще-продуктивнее ли тогда написать программу, которая сама правила подберет, чтоб оценка разбора была максимальной, вместо того, чтоб пробовать правила самим?
Да. Вы правы. Я протестирую параллельно двумя методами:
1. Метод bugfix'a (или видимые ошибки)
2. Анализ по словарю, построение правил и т.д.
А потом — сравню, какой лучше будет работать и сделаю выводы для улучшения.
Вы сейчас строите предсказатель на основе набора окончаний, а правила подбираете вручную на основании своих предположений и наблюдений.

Со словарем этот же набор правил (окончание => часть речи) можно построить автоматически, более полно и правильно (что и делается в phpmorphy и большинстве других морф. анализаторов для русского языка). Благо словари для русского языка доступные и хорошие: см., например, opencorpora.org/dict.php.

Кроме того, раз уж есть словарь, то необязательно полагаться только на предсказатель — если слово есть в словаре, то можно и точный разбор вернуть (ну с учетом неустранимой на уровне отдельных слов неоднозначности разбора).
Т.е. если заканчивается на «уй», то это глагол?
Пока да…
Можно исправлять заменой (буду делать в след. версии функции), если нет запятых между словами:
3-3 => 3-4
Интересная функция. Самое главное очень простая.

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

Поправьте пожалуйста код-функции: неудобно читать содержимое массива глаголов: хотел посмотреть наличие -ать, ять (вообще рекомендую использовать правила оформления кода PEAR, pear.php.net/package/PHP_CodeSniffer в помощь)

Далее придется использовать словари. Рекомендую DICT
«реализующую как-бы ответ на вопрос» — пока планирую фильтр:
1. Веса по частям слов.
2. Порядок следования частей речи
3. Словари.
4. Тоновые соединения: цепочки частей речи и корни.
отформатированный вариант Вашей функции:

function chastrechiRUS($string)
{
    /*
      Группы окончаний:
      1. прилагательное
      2. причастие
      3. глагол
      4. существительное
    */

    $groups 
        = array(
            1 => array('ее', 'ие', 'ые', 'ое', 'ими', 'ыми', 'ей', 
                  'ий', 'ый', 'ой', 'ем', 'им','ым','ом','его',
                  'ого','ему','ому','их','ых','ую','юю','ая',
                  'яя','ою','ею'),
            2 => array('ивш','ывш','ующ','ем','нн','вш','ющ',
                       'щ','ущи','ющи', 'ящий','щих','щие'),
            3 => array('ила','ыла','ена','ейте','уйте','ите',
                       'или','ыли','ей', 'уй','ил','ыл',
                       'им','ым','ен','ило','ыло','ено',
                       'ят','ует','уют','ит','ыт','ены','ить',
                       'ыть','ишь','ую','ю','ла','на','ете',
                       'йте','ли','й','л','ем','н','ло','но',
                       'ет','ют','ны','ть','ешь','нно'),
            4 => array ('а','ев','ов','ие','ье','е','иями',
                        'ями','ами','еи','ии','и','ией',
                        'ей','ой','ий','й','иям','ям','ием',
                        'ем','ам','ом','о','у','ах','иях',
                        'ях','ы','ь','ию','ью','ю','ия',
                        'ья','я','ок', 'мва', 'яна', 'ровать'),
        );

    $res=array();

    $words = explode(' ', $string);
    //print_r($words);
    foreach ($words as $wk=>$w) {
        foreach ($groups as $gk=>$g) {
            foreach ($g as $part) {
                if (substr($w, -strlen($part)) == $part 
                    && $res[$wk][$gk] < strlen($part) // любая часть речи, окончания
                    || stripos($w, $part)!==false 
                    && $gk == 2 //причастие, в любом месте слова
                ) {
                    $res[$wk][$gk] = strlen($part);
                }

            }
        }
        if (!isset($res[$wk][$gk])) {
            $res[$wk][$gk] = 0;
        }
    }


    $result = array();
    foreach ($res as $r) {
        arsort($r);
        array_push($result, key($r));
    }
    return $result;
}
Да… Многое поменялось…
Вы успели уже накодить много или код стал по другому восприниматься?
Разница не особо велика и (ИМХО) мне удобнее, когда все && на одной строке, а || сначала строк в условиях.
Когда используются переносы, легче воспринимается логика кода, проще восприятие, легко отлаживается, можно отключать блоки, переносить и копировать в другие части. Не забывайте, что другие будут изучать Ваш код. Идеальным считается код, когда другой человек может разобраться и внести правки без автора и автору будет понятно и остальным тоже.

Считается правилом хорошего тона правая граница 60-75-80 символов (у меня 75)
Если код не умещается, значит что-то не-так. Хорошая функция умещается на одной странице экрана редактора.
Ок. Учту на будущее. Буду переносить и комментировать.
Вот так правильно. Самому будет легче. Первые 10 лет тяжело потом привыкаешь :)

Если код не отформатирован валидно, то это может говорить о следующем: спешка, нет нормального редактора, новичок, недостатки самовоспитания, поверхностное отношение, отсутствие стандартов, одиночка.

На настоящий момент наиболее популярны следующие редакторы, которые пробовал для php: emacs, eclipse (pdt), netbeans, editplus, dev-util/kdevelop-php

Но я пишу код в Far 2.0 с плагином FarColorer (см.тут) и мне вполне удобно.
Да, неплохой редактор. К нему тоже можно прикрутить много чего. Так сказать облагородить.
Добавлю еще PhpStorm. Отлично форматирует прямо «из коробки». Можно, конечно, и свои стандарты кодирования настроить — все достаточно гибко.
наслышан про него
Ничего так. Жаль, что закрытый и java. У меня как java стартует, сразу образуется неубираемый своп, который еще и растет со временем, независимо от того использую еще джава-приложение или давно уже вышел. Это одна из причин моего перехода на emacs с долгого использование eclipse. Стоит до сих пор, жалко сносить, иногда пользую.
Рекомендую почитать комментарии к этому топику.
Emacs — текстовый редактор.
PhpStorm — IDE.
Каждый решает сам, где работать, но IDE дает больше возможностей. Вот хотя бы несколько из них:
  • Рефакторинг
  • Быстрые переходы
  • Удобная интеграция с VCS
«в емаксе есть всё… кроме текстовго редактора»
Когда я прорабатывал эту тему для английского языка, то на основе достаточно большого размеченного корпуса составил статистическую базу триграмм последовательностей частей речи. Вышла она (давно было, не помню) килобайт 10. Эта база повышала вероятность определения частей речи омонимов в спорных ситуациях определения части речи. Это по сути цепи Маркова.
Я про то, что этот подход тут очень даже применим. В гугле это — «trigram tagger».
Да. Спасибо!
Уже прочитал по совету KAndy (пост)
Это однозначно буду делать.
Вы ведь знаете про github и pull-requests? Очень странно видеть на хабре топик «а давайте покодим вместе в комментариях», когда для этого есть специализированные инструменты.
То, что вы делаете называется POS tagger.

Вы предлагаете фактически правиловый подход к идентификации части речи. Логичным следующим шагом будет тот же правиловый подход для разрешения неоднозначности вроде «Мама мыла раму», где «мыла» — что глагол? существительное?

Лучше посмотреть на современные исследования в этой области.
А нет ли скриптика для склонения словосочетаний на PHP? Яндекс-склонятор нормально склоняет только отдельные слова, да и плохо подходит из-за онлайновости.
Пример из одной книжки:

Эти типы стали есть на складе
Определение, конечно не 100%, но можно легко дорабатывать.

Тяжело дорабатывать. Вплоть до того, что у вас будет протегированый весь словарь. Это ж сколько правил.
И даже это не даст хороших результатов.
Часть речи обычно очень сильно зависит от контекста, который у вас, как я понимаю, никак не учитывается. Как по мне, лучше сочетать rule-based подход со статистическим.
«Часть речи обычно очень сильно зависит от контекста, который у вас, как я понимаю, никак не учитывается»
Да. Сделаю в обновлении.

«лучше сочетать rule-based подход со статистическим»
и взвешивать результат между тем и тем.
ДА. Все верно.
Не принимайте близко к сердцу, но… У вас совершенно неадекватные представления о сложности морфологии русского языка… То, что вы делаете сейчас абсолютно так же, но насколько это возможно лучше делает PHPMorphy. Насколько я знаю, у него тоже много правил окончаний + списки исключений. Поверьте, сделать существенно лучше чем у них морфологию не получится. Это мы говорим про чистую морфологию — узнать часть речи и форму по одному слову.
Далее: «Косил косой косой косой», тут уже функцией с правилами на PHP не обойдешься. Тут, как правильно вы заметили, нужно строить деревья синтаксического разбора, выбирать более подходящие из них, на основании этого уточнять морфологические приметы слов, потом выбирать то дерево, которое нам больше нравится и т.д. Работы много. Очень много. Посмотрите на aot.ru — ребята этим занимаются на C++ в свободное время: кода много, словарей много, правил много — а результат не то чтобы сильно крутой был. Ну т.е. простые предложения оно распознает, а вот со сложными начинаются проблемы.
Повторюсь еще раз: у вас абсолютно неадекватное представление о сложности подобных библиотек и завышенные представления о своих возможностях. Не принимайте близко к сердцу. Покрутите PHPMorphy, если вам его возможностей будет мало — идите на aot.ru, покрутите их либы. Более крутого из опенсорсного, насколько я знаю (уже несколько лет не интересовался этой темой) вы не найдете. И конечно же не напишете, если только у вас нету штата лингвистов, программистов и денег им на хлеб с маслом на несколько лет.
Весы: скорость и точность…
Пока Вы будете строить себе лифт, я поднимусь уже по лестнице.
А вообще — все по-делу написано.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории