3 min read

Лемматизация (Lemmatization)

Лемматизация (Lemmatization)
Фото: Francesca Hotchin / Unsplash

Лемматизация – объединение слов с одним и тем же корнем или леммой, но с разными склонениями или производными значения для дальнейшего анализа как элемента. Цель состоит в том, чтобы выявить присутствие слова в любой из его форм в Текстовом блоке (Corpus) и, например, определить частоту его появления.

Например, лемматизировать слова «кошки», «кошек» и «кошка» означает привести к именительному падежу все эти слова и получить «кошка». Лемматизация активно используется в области Обработки естественного языка (NLP).

Лемматизация и стемминг

В отличие от лемматизации, Стемминг (Stemming) выделяет грамматическую основу текста. В случае с "кошкой" он отбрасывает окончание "ой" и генерирует стем "кошк".

Практическое применение

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

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

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

Лемматизация: natasha

Понимаю, заголовок звучит весьма странно, однако natasha – это прекрасная библиотека, пригодная для широкого спектра задач NLP, в том числе для лемматизации. Посмотрим, как элегантно этот модуль позволяет приводить слова в тексте к исходному состоянию. Для начала импортируем необходимые библиотеки:

!pip install natasha

Импортируем некоторые составляющие:

import natasha
from natasha import (
    Segmenter,
    MorphVocab,
    
    NewsEmbedding,
    NewsMorphTagger,
    NewsSyntaxParser,
   
    PER,
    Doc
)

Инициируем экземпляры Segmentor, который разделяет текст на слова, MorphVocab, содержащий в себе слова-токены наподобие словаря, NewsMorphTagger, описывающий грамматические свойства слова, и NewsSyntaxParser, описывающий роли слов в предложениях:

segmenter = Segmenter()
morph_vocab = MorphVocab()

emb = NewsEmbedding()
morph_tagger = NewsMorphTagger(emb)
syntax_parser = NewsSyntaxParser(emb)

Создадим текстовый блок. Как видите, библиотека в некой мере ориентирована на анализ новостей:

text = 'Посол Израиля на Украине Йоэль Лион признался, что пришел в шок, узнав о решении властей Львовской области объявить 2019 год годом лидера запрещенной в России Организации украинских националистов (ОУН) Степана Бандеры. Свое заявление он разместил в Twitter. «Я не могу понять, как прославление тех, кто непосредственно принимал участие в ужасных антисемитских преступлениях, помогает бороться с антисемитизмом и ксенофобией. Украина не должна забывать о преступлениях, совершенных против украинских евреев, и никоим образом не отмечать их через почитание их исполнителей», — написал дипломат. 11 декабря Львовский областной совет принял решение провозгласить 2019 год в регионе годом Степана Бандеры в связи с празднованием 110-летия со дня рождения лидера ОУН (Бандера родился 1 января 1909 года). В июле аналогичное решение принял Житомирский областной совет. В начале месяца с предложением к президенту страны Петру Порошенко вернуть Бандере звание Героя Украины обратились депутаты Верховной Рады. Парламентарии уверены, что признание Бандеры национальным героем поможет в борьбе с подрывной деятельностью против Украины в информационном поле, а также остановит «распространение мифов, созданных российской пропагандой». Степан Бандера (1909-1959) был одним из лидеров Организации украинских националистов, выступающей за создание независимого государства на территориях с украиноязычным населением. В 2010 году в период президентства Виктора Ющенко Бандера был посмертно признан Героем Украины, однако впоследствии это решение было отменено судом. '
doc = Doc(text)

Сегментируем абзац на предложения и посмотрим на первые два с помощью display(doc.sents[:2]):

doc.segment(segmenter)
display(doc)
display(doc.sents[:2])
display(doc.tokens[:5])

Функция display(doc.tokens[:5]) позволит посмотреть первые пять слов:

Doc(text='Посол Израиля на Украине Йоэль Лион признался, чт..., tokens=[...], sents=[...])
[DocSent(stop=218, text='Посол Израиля на Украине Йоэль Лион признался, чт..., tokens=[...]),
 DocSent(start=219, stop=257, text='Свое заявление он разместил в Twitter.', tokens=[...])]
[DocToken(stop=5, text='Посол'),
 DocToken(start=6, stop=13, text='Израиля'),
 DocToken(start=14, stop=16, text='на'),
 DocToken(start=17, stop=24, text='Украине'),
 DocToken(start=25, stop=30, text='Йоэль')]

С помощью морфологии – науке о формах слов, изучим каждое отдельное слово:

doc.tag_morph(morph_tagger)
doc.parse_syntax(syntax_parser)
display(doc.tokens[:5])

Отобразим первые пять слов и их свойства – идентификатор (id), роль в предложении (nsubj – подлежащее), часть речи (noun – существительное), прочие интересные свойства (anim – одушевленное, nom – нарицательный, masc – мужского рода, sing – в единственном числе):

[DocToken(stop=5, text='Посол', id='1_1', head_id='1_7', rel='nsubj', pos='NOUN', feats=<Anim,Nom,Masc,Sing>),
 DocToken(start=6, stop=13, text='Израиля', id='1_2', head_id='1_1', rel='nmod', pos='PROPN', feats=<Inan,Gen,Masc,Sing>),
 DocToken(start=14, stop=16, text='на', id='1_3', head_id='1_4', rel='case', pos='ADP'),
 DocToken(start=17, stop=24, text='Украине', id='1_4', head_id='1_1', rel='nmod', pos='PROPN', feats=<Inan,Loc,Fem,Sing>),
 DocToken(start=25, stop=30, text='Йоэль', id='1_5', head_id='1_1', rel='appos', pos='PROPN', feats=<Anim,Nom,Masc,Sing>)]

И наконец, лемматизируем текст:

for token in doc.tokens:
    token.lemmatize(morph_vocab)
    
{_.text: _.lemma for _ in doc.tokens[:10]}

Список получился внушительный, потому выведем только слайс из первых десяти элементов:

{',': ',',
 'Израиля': 'израиль',
 'Йоэль': 'йоэль',
 'Лион': 'лион',
 'Посол': 'посол',
 'Украине': 'украина',
 'на': 'на',
 'признался': 'признаться',
 'пришел': 'прийти',
 'что': 'что'}

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

Автор оригинальной статьи: techslang.com