Pull to refresh

Comments 44

Огромное спасибо за pymorphy, подобные вещи не то что платны, а порой секретны.
Используем его в научном проекте,

Сделано (планируется ли) в pymorphy2, разбор предложений без двусмысленности?
Например:
Моя машина дорогая.
Мой — Мыть
Машина — Маша
дорогой

а должно быть:
Мой
Машина
дорогой
UFO just landed and posted this here
Ну так, pymorphy это делает ))
pymorphy делает только морфологический анализ, и показывает все результаты, в т.ч. и двучмысленные.
Умеет, но это уже задача синтаксического анализатора.
Или классическое «души прекрасные порывы», где без контекста вообще не понять что имеется ввиду.
Это планируется, но не совсем в рамках pymorphy2. Pymorphy2 просто смотрит на то, как слово написано, и выдает все разумные варианты разбора. Ну т.е. как — если просто брать первый разбор, который выдает pymorphy2, то где-то 70% слов (чуть больше) будут разобраны правильно (это если не учитывать пунктуацию, с ней 80%).

Если нужно лучше — то нужно знать, как предложения разбираются на самом деле. А для этого нужно имеющуюся неоднозначность разбора поснимать вручную сначала. И вот этим как раз занимается opencorpora.org/ — когда там все будет готово, мы будем знать:

а) какие разборы встречаются чаще (=> pymorphy2 даже без учета контекста сможет выдавать их в более точном порядке);
б) как разборов друг с другом согласуются (=> можно будет написать штуку, снимающую неоднозначность с учетом контекста).

Размеченные тексты есть также в НКРЯ ( www.ruscorpora.ru/ ), и почти все системы, о которых я знаю, натренированы именно на НКРЯ — но там все мутно с лицензией, и проект «только для своих».
Если быть совсем строгим и скучным, то можно сказать, что снятие неоднозначности не входит в задачу морфологического анализа. Разумеется, такой ответ никого не интересует.

Вообще, для этого стоит использовать таггеры, которые учитывают совместное расположение слов. Например, на основе деревьев решений (TreeTagger) или скрытых марковских моделей (TnT). Обратите внимание, что их лицензии совсем не являются свободными. Принципы работы и данные для обучения этих анализаторов сильно отличаются от pymorphy2.

Возможно, в вашей задаче можно обойтись простым согласованием именных групп. Эвристика проста: если у вас имеются пары прилагательных и существительных, согласующихся по числу, роду, падежу, то отбросьте остальные варианты их разбора.
Это очень, очень круто! Спасибо, Михаил.
Очень увлекательная статья, я словно детектив читал.
Меня всегда удивляли комментарии в духе "- спасибо, как раз ищу морфологический анализатор!", а теперь сам оставляю такой. Мне действительно скоро потребуется разбирать слова и я уже несколько дней держу в уме статью о pymorphy1. Это рок, не иначе.
Спасибо!
Вау. Роскошная библиотека (активно использовал pymorphy1 – просто незаменимая вещь)

И еще более роскошная статья. В ней есть все:
1. Активный поиск решения
2. Промежуточный вариант, который «недожал»
3. Возврат к истокам
4. Хэпи энд ;)
Спасибо) Статья с трудом писалась, я ее все выходные редактировал, так что комплимент статье особенно приятен)
Очень интересно! А литературу не посоветуете по этой теме?
По структурам данных — Ахо, Ульман — «Структуры данных и алгоритмы». Про обработку текста — nlp.stanford.edu/fsnlp/, например. Если попроще, без особых деталей — то nltk.org/book/ — но там гораздо меньше все объясняется. Курсы на coursera по NLP хорошие (и от Стенфорда, и идущий сейчас от Колумбийского университета). Про детали того, как все для русского языка делается — статьи читать можно. Чтоб все понимать, хорошо бы знания тории вероятности и статистики освежить (или получить): «машинное обучение» — это большей частью то же самое, что и статистика.

Морфологический анализ — это только один небольшой шаг к тому, чтоб с текстом что-то делать, не всегда даже обязательный :)
Огромнейшее спасибо!
Спасибо за статью и библиотеку, глянул на нее, когда реализовывал собственный морфологический анализатор на c#. У меня в качестве хранилища лексем использовался trie, не помню какое было потребление памяти и скорость, но для меня это было не критично.
Нет, ссылочки нету, но могу попробовать поискать и выложить
Михаил, хорошая работа, поздравляю :).

Один момент — не увидел по тексту, позволяет ли та реализация DAWG, что вы используете, минимизировать автомат. Если нет — этим стоит занятся, т.к. можно сохранить большое количество памяти без деградации по скорости. Кстати, в aot было хитро — они использовали алгоритм, где при добавлении слова автомат поддерживался минимально возможным.

ps я делаю pure-с клон openfst, более бедный по функционалу, но более оптимальный по скорости и памяти. пока это только сырой драфт. Как доделаю, было бы интересно потестировать на морфологии.
Спасибо! Да, в dawgdic точно такая же хитрость — алгоритм построения устроен так, что автомат, который описывает граф, внутри сразу оказывается минимизированным. Там еще что хорошо — граф внутри не на указателях построен (вроде в aot на указателях, если правильно помню), а в «double array» закодирован и лежит в памяти единым куском. Это позволяет память экономить + для кэша процессора это лучше, чем по указателям прыгать.

Ага, сравнить было бы интересно :)
Ага, массивом граф представлять — правильная идея. Могут возникнуть проблемы добавления-удаления, но здесь не тот случай. Тут статичного представления достаточно.

Успехов :).
Кстати, то, что граф представлен массивом, очень помогло в написании pure-python читалки для него: все данные загружаются в питоний array.array и занимают ровно столько же памяти, сколько и в C++ реализации.
Михаил, не подскажете, какие есть альтернативы добавлению в словарь неизвестных слов через OpenCorpora? Я понимаю, что это приоритетный способ, но есть желание это делать более оперативно.
Алексей, вы можете создать здесь тикет со списком слов, мы добавим в течение максимум пары дней.
Это было бы круто. Я тогда постараюсь прогнать список слов на текущем pymorphy2 и выявить недостающие. А вы добавляете неизвестные слова, но которые успешно предсказываются?
Да, мы всё добавляем. В одной системе успешно предсказываются, в другой нет — мы не хотим за этим следить :-)
А вы не парсите wiktionary.org? Они тоже по CC-BY-SA данные предоставляют.
В pymorphy2 можно неизвестные слова добавить и без участия OpenCorpora, если очень нужно. Я, правда, не пробовал, но суть такая: в pymorphy2 за разбор и предсказание отвечают отдельные «юниты», в том числе за разбор по словарю (см. github.com/kmike/pymorphy2/blob/master/pymorphy2/units/by_lookup.py ). Можно подготовить XML-ку со своими дополнениями к словарю, скомпилировать ее через «pymorphy dict compile» и добавить еще один «юнит» для разбора по этому новому словарю в MorphAnalyzer (там в конструкторе параметр есть). Чтоб создать такой юнит, понадобится, видимо, просто отнаследоваться от DictionaryAnalyzer и в методе __init__ записать в атрибут .dict новый словарь (вместо того, что будет передаваться в параметрах). «Словарь» в этом случае — экземпляр pymorphy2.opencorpora_dict.wrapper.Dictionary.

Добавить этот юнит, наверное, лучше сразу за юнитом для разбора по стандартному словарю. В этом случае при разборе (склонении и т.д.) pymorphy2 попробует сначала разобрать по стандартному словарю, если не выйдет — по дополнительному, если опять не выйдет — включатся предсказатели.

Понятное дело, лучше в OpenCorpora все добавлять — но хочется думать, что этот use-case архитектурно предусмотрен :)
… или еще примитивней — сделать наследника BaseAnalyzerUnit и реализовать нужные методы (tag, parse, lexeme, normalized). Хоть даже вот так (чтоб суть видна была; код организовать по-другому лучше, конечно):

class AlyoshenkaAnalyzer(BaseAnalyzerUnit):  
    # слова "Алёшенька" в словаре нет и оно из-за этого разбирается как имя женского рода
    # пусть хотя бы метод tag работает
    def tag(word, word_lower, seen_tags):
        if word_lower in {"алешенька", "алёшенька"}:
            return [self.morph.TagClass('NOUN,masc,anim,Name sing,nomn')]
        return [] 

Для других методов там посложнее; у наследника DictionaryAnalyzer плюс тот, что никакого кода писать не нужно, и работать все будет быстро.
Похоже, самым разумным тогда будет поднять свой инстанс OpenCorpora, чтобы вносить слова через удобный интерфейс. В любом случае спасибо за информацию.
Огромное спасибо. Если вы не против — перепишу на PHP.
На PHP уже давно есть PHPMorphy. Правда, если не ошибаюсь, его автор, Владимир Камаев, в последнее время не очень поддерживает проект. Насколько я знаю, последняя версия живёт тут: github.com/heromantor/phpmorphy
phpMorphy вроде неплох (это, насколько помню, был почти 1-в-1 клон lemmatizer с aot.ru) — но против переписывания pymorphy2, конечно же, ничего не имею против :)
Большое человеческое спасибо за труд автору! Немного не в ту ветку но все же.

Михаил, подскажите как при помощи pymorphy2 (или pymorphy3) перевести в родительный падеж всё предложение целиком, а не только отдельные слова?

1) Видимо, всё же фразу, а не предложение. Потому что какой родительный падеж у предложения "Я вчера мыл кота"?
2) Никак, потому что вам нужно знать, как слова во фразе друг от друга зависят и какие у них модели подчинения. А для этого нужно понимать предложение. Есть синтаксические парсеры, которые строят такую модель, хотя и не очень точно. Берёте такой парсер, понимаете, падеж каких слов нужно поменять, а pymorphy уже этим занимается.
3) Или ещё есть современный вариант: натравливаете GPT-3 / ChatGPT, и (часто) получаете правильный ответ.

Sign up to leave a comment.

Articles