среда, 26 декабря 2012 г.

Умничание вокруг лемматизации

Не то что бы я сильный любитель natural language processing, но так получилось что в исскуственном интеллекте этот раздел занимает очень уважаемую позицию. Да и в Grammarly нахватался кое-чего. Так что теперь это для меня родное, и следовательно, продолжаем разговор.

Итак, лемматизация. Начнем с того, почему это понадобилось. Как я уже писал ранее, я сталкивался с задачей классификации текстов. Есть много подходов, и немало эффективных техник основанно на подсчете частот вхождения слов. В общем речь о частотах и модели bag of words. И вот тут все хорошо в английском. Но неважно в русском или немецком. Потому как в этих языках очень большая вариативность словарных форм. Ответ простой. Привести все слова к  леммам. Однако все опять таки просто для английского, но для русского и немецкого правила намного разнообразнее и сложнее. 


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

Так что я сел и написал хоть и простой, но с неплохими идеями лемматизатор для русского языка. Наивный конечно получился, да интересный в своем роде. Сделал сразу три реализации. На Java, на C++ и конечно на Python. 

Прежде чем продолжать, скажу, что конечно я прочел много статей с http://aot.ru/ и не даром  автора и организатора проекта постоянно цитируют в интернете, отличные материалы. Все в конечном игоге сводится к wordnet, однако в данном случае строить wordnet это и излишне и затруднительно, учитвая скудность моей базы для обучения модели. Так что в эксперементе принимает участие никакой не wordnet, а совсем иной подход.

Состоит конечный лемматизатор из двух частей - обучаемая модель основанная на сохранении путей к леммам в префиксном дереве подобного вида:

Работает алгоритм построения модели на основе обучения с учителем. Даем на вход словоформу и лемму и так миллион раз. Алгоритм упаковывает всё в префиксное дерево, по которому очень быстро [O(1) - константное время означает что скорость поиска леммы не зависит от количества слов в модели]. можно получить базовую форму (лемму). Однако совершенного словаря не существет. Да и его размер, возможно, был бы слишком велик (хотя не уверен). Фактом является то, что достаточно хорошего словаря в свобоном доступе просто нет. 

В случае если база хорошая, практически все словоформы известны. Но если таки попадается словоформа, отсутствующая в исходных данных, лемму получить не удастся.

По этому есть вторая часть. Которая по сути не является лематизатором. Это стеммер. Стеммер Портера, адаптированный под правила русского языка. У него конечно много недостатков, он наивный, примитивный, кусочками правила собраны из сети, потому как я не лингвист, пришлось правила позаимствовать. Но работает в каком то приближении. Если понадобится более качественная реализация можно обратиться к офицальному ресурсу
Текущий же стеммер прост. Многих вещей не умеет. Но кое как работает с суффиксами и окончаниями. Радует, что даже если результирующая лемма ошибочна, она довольно стабильно получается из разных словоформ одного слова, что по сути для задачи классификации подходит хорошо.

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

2 комментария:

  1. А про префиксное дерево Вы сами придумали, или статья какая есть с таким подходом?

    ОтветитьУдалить
    Ответы
    1. Ну, думаю, я не открыл Америку этим, наверняка решение использовать префиксное дерево много кому в голову приходило, но мне в моей не очень большой пока практике в NLP не попадалось еще, так что даже если изобрел велосипед, он мне нравится ))) Кстати, возможно позже узнаю или придумаю более эффективоне решение.

      По крайней мере теперь классификаторы для гораздо большего количества языков писать смогу.

      Удалить