В современном мире объем данных в интернете постоянно растет с огромной скоростью. Возникает логичный вопрос: как ориентироваться в этом информационном потоке?
Чтобы упростить себе задачу поиска и обобщения информации IT-энтузиасты применяют технологии генеративно обученных чат-ботов. Наиболее широкое распространение получил ChatGPT. Яндекс, в свою очередь, добавил в браузер YandexGPT, который позволяет тезисно ознакомиться с содержанием страницы. Всё чаще вакансия Prompt-инженера начинает встречаться на hh и Хабр Карьере. Специалисты и чат-боты помогают конечному пользователю экономить время для поиска необходимой информации.
Но что делать, если возможности обратиться за помощью к подобным технологиям нет? Указанные выше языковые модели нельзя интегрировать в собственные проекты, сценариев их использования много, но они всё равно ограничены.
В статье мы расскажем, как (не без нейронных сетей) можно создать простой алгоритм на Python, который поможет извлекать ключевые слова из любого текста, тем самым избавляться от ненужной информации и автоматизировать процесс анализа материалов. Мы будем работать с русским текстом, а именно — с новостными постами. Поэтому в частном случае используются пакеты для обработки, поддерживающие именно русский язык. В том числе используются модели, обученные на корпусах текстов с новостной семантикой.
Декомпозиция задачи. Описываем этапы простым языком.
Как понять, что именно необходимо “выкидывать” из оригинального текста? Стоит обратиться к одному из разделов языкознания — синтаксическому анализу. Если отвечать на вопрос, что именно в тексте передает основную информацию, то можно выделить:
грамматическую основу предложения, подлежащее + сказуемое;
синтаксические единицы, словосочетания.
В первом случае подлежащим и сказуемым чаще всего выступают существительное и глагол (в некоторых частных случаях подлежащим также может выступать глагол в форме инфинитива, а сказуемым — прилагательное или существительное). Во втором же случае, помимо упомянутых выше частей речи, встречаются еще и причастия.
Возникает вопрос: не напрасно ли обделены вниманием местоимения и наречия? Чтобы понять, почему мы не рассматриваем эти части речи, нужно еще раз оценить, как именно должен работать потенциальный алгоритм. В конечном итоге мы решаем задачу извлечения основной информации из отдельно взятого предложения. В таком случае в паре подлежащего и сказуемого “он сказал” местоимение не несет никакой смысловой нагрузки. Обособленно от всего текста невозможно понять, о ком или о чем идет речь. Если же рассматривать наречия, обозначающие признак действия, предмета или другого признака, то в контексте анализа новостных блоков нам неважно, как именно субъект выполнял те или иные действия.
Таким образом, наш алгоритм можно разбить на 2 этапа:
Определение частей речи в тексте.
Построение комбинаций слов в словосочетания.
В языкознании принято считать, что подлежащее и сказуемое не являются словосочетанием. Однако в данной статье мы будем трактовать их как словосочетание для упрощения восприятия.
Морфологический анализ. Определяем части речи.
С этого момента будет меньше воды и (наконец-то!!!) больше описания технических аспектов реализации.
Хранить информацию о входном тексте, результате его сегментации, выделенных ключевых словах и словосочетаниях мы будем в коллекции элементов doc.
Для определения частей речи в тексте необходимо сначала разбить текст на отдельные слова — токены. Чтобы не “изобретать велосипед”, мы воспользуемся функционалом библиотеки razdel, которая помогает сегментировать русский текст, а именно:
sentenize() для сегментации текста на предложения;
tokenize() для токенизации слов внутри предложения.
В doc по ключу text будет храниться оригинальный текст, а в tokens — перечень со списками всех слов.
Перед тем, как приступить к определению части речи каждого слова, необходимо добавить фильтрацию на стоп-слова (в русском языке это в основном союзы и предлоги). Такие слова встречаются почти в каждом предложении и не несут большой информативной нагрузки, не влияют на построение ключевых словосочетаний, но добавляют много шума. Составлять список таких слов вручную не придется — достаточно воспользоваться готовыми библиотеками. Му обратимся к NLTK, в которой имеется список стоп-слов для русского языка. Его можно скачать следующим образом:
После этого приступаем к созданию функции для морфологического анализа. Непосредственно определение части речи отдельного токена будет производиться с помощью MorphAnalyzer() библиотеки pymorphy2. Для того, чтобы фильтр по частям речи работал оптимальнее, перечень необходимых частей речи (Part Of Speech или POS) мы сохраним не в список, а во множество, так поиск по нему будет производиться быстрее. Учитываются следующие части речи:
NOUN, существительное;
ADJF и ADJS, полная и краткая форма прилагательного;
VERB и INFN, глагол и инфинитив;
PRTF и PRTS, полная и краткая форма причастия.
В итоге по ключу candidates будет храниться коллекция токенов, которые прошли фильтрацию на часть речи.
Синтаксический анализ. Строим ключевые словосочетания.
Для построения словосочетаний можно было бы просто пройтись скользящим окном по каждому предложению и объединить стоящие рядом слова. Однако в русском языке связанные слова могут находиться не рядом друг с другом. Чтобы автоматизировать процесс поиска связанных внутри предложения слов, мы решили провести синтаксический анализ всех предложений и определить семантические связи.
Сначала в директорию вашего проекта необходимо скачать модель navec_news_v1_1B_250K_300d_100q.tar, которая используется в библиотеке navec. С помощью неё мы сможем строить эмбеддинги русских слов. Конкретно эта модель обучена на 1 миллиарде слов, из которых был построен словарь в 250 тысяч уникальных слов. В конечном итоге каждое слово будет описываться вектором размерностью 100. Существует модель, которая обучена на двукратном объеме слов, однако для нашей задачи достаточно и упрощенной версии.
Синтаксический анализ будет проводиться за счет функционала пакета slovnet, а точнее модели slovnet_syntax_news_v1.tar, которую также необходимо предварительно скачать и поместить в директорию проекта.
На примере одного предложения мы хотим продемонстрировать принципы работы синтаксической модели. В том числе, воспользуемся написанной ранее функцией segment_text():
Теперь в doc хранится словарь:
Объявленная модель syntax должна принимать на вход токенизированное предложение, а не оригинальный текст (!!!), поэтому передадим в неё doc[“tokens”][0]:
Получим:
Помимо очевидного ключа text в syntax_markup.tokens хранится:
id - индекс слова во входном предложении (начинается с 1);
head_id - индекс родительского слова (в смысле семантической связи);
rel - тип семантической связи.
Можно увидеть, что у сказуемого “играла” нет родительского слова, так как оно является частью грамматической основы предложения. Соответственно, для построения словосочетаний на основе семантических связей достаточно обратиться к каждому элементу syntax_markup.tokens и определить родительское слово для текущего слова.
Для удобства поиска родительских слов создадим словарь вида {id_слова_в_предложении: само_слово}:
Также добавим проверку, чтобы строить ключевые словосочетания только из ранее отфильтрованных по частям речи слов. В итоге по ключу collocations функция будет сохранять все уникальные составленные словосочетания.
Заключение.
Проверим, как работают наши функции:
Получаем на выходе:
В итоге был получен относительно простой алгоритм, который способен анализировать текст на предмет построения ключевых словосочетаний. Мы хотим еще раз подчеркнуть два момента:
-
Данный алгоритм не претендует на звание SOTA-решения. Это весьма тривиальный пайплайн, который позволяет построить словосочетания длинной в 2 слова. Для улучшения вы можете:
а. добавить древовидную структуру построения словосочетаний, чтобы их длина увеличилась;
b. добавить анализ типа семантических связей, чтобы учитывать правильный порядок слов в словосочетаниях.
Несмотря на то, что использующиеся для построения эмбеддингов и синтаксического анализа модели способны работать с любым текстом, в первую очередь они ориентированы на новостные тексты. Если вы работает, к примеру, с художественной литературой, вам лучше скачать модель navec_hudlit_v1_12B_500K_300d_100q.tar.
Спасибо за внимание!