Python

Категоризация документов с помощью LDA в библиотеке genism

Время прочтения: 3 мин.

Среди множества различных текстов (документов, сообщений, писем) часто сложно найти нужный. Для этого приходится просмотреть и прочитать все тексты, что занимает очень много времени, а в некоторых случаях и вовсе невозможно. Поэтому классификация и категоризация очень важные процессы и пренебрегать ими не стоит. Ведь гораздо проще найти что-либо среди сгруппированных элементов. Однако, бывает и так, что и с помощью технических средств трудно классифицировать тот или иной текст, когда он должен относиться к нескольким группам одновременно. Сложность заключается в том, что к одной теме могут принадлежать тексты, не содержащие мало одинаковых слов, а смысловые связки увидеть может только человек. Например, если в тексте идёт речь о добровольном страховании жизни, то обращение будет отнесено либо к теме «Страхование», либо «Добровольное страхование», хотя по смыслу оно может находиться как в одной теме, так и в другой. Как раз для таких случаев существует направление машинного обучения, именуемое тематическим моделированием.

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

Рассмотрим реализацию LDA на языке Python с применением библиотеки gensim. Сначала в память в переменную all_dosc записываются тексты обращений:

from gensim.models import LdaModel, LdaMulticore
from  gensim.utils import simple_preprocess, lemmatize
from gensim import corpora, models
import re
compline = [line for line in open(r'compline.txt', encoding = 'utf-8')]

Затем создаём список «стоп-слов», которые не влияют на смысл текстов (предлоги, союзы и т.д.):

stop_words = ['а', 'и', 'но', 'ну', 'что', 'что-то','что-нибудь','чего','чей','кого',
'как', 'так', 'как-то', 'на', 'кто','кто-то','как-нибудь','чего','чей','того',
'в', 'от', 'до', 'как-либо', 'что-либо','кто-либо','кем','чем','тем','то', 'с', ',', '.', '(', ')',
'у', 'при' ,'перед', 'если', 'когда', 'где', 'куда' ,'туда','там','тут', 'или', 
'для', 'из-за','из', '-то', 'за','по','\n']

После этого подготавливаем данные для использования в модели, переводя предложения к списку слов. Из исходных предложений исключаются «стоп-слова» и проводится лемматизация текста:

filtered_data = []
for i, doc in enumerate(compline):
    doc_out = []
    for word in doc.split(' '):
        if word.lower() not in stop_words:
            lemmatized_word = lemmatize(word.lower(), allowed_tags = re.compile(‘(NN|JJ|RB)’))
            if lemmatized_word:
                doc_out = doc_out + [lemmatized_word[0].split(b’/’][0].decode(‘utf-8’)]
            else:
                continue
    filtered_data.append(doc_out)
print(filtered_data)

В результате получаем список слов, из которого можно составить словарь и корпус (см. код ниже). Словарь будет содержать в себе список слов из предложений, а корпус все слова с их порядковыми номерами и частотой их использования в тексте (предложениях).

dctn = corpora.Dictionary(filtered_data)
corp = [dct.doc2bow(line) for line in filtered_data]

Как только данные подготовлены, можно приступить непосредственно к построению модели, которая на выходе выдаёт список тем. Количество тем задаётся параметром num_topics.

model = models.ldamodel.LdaModel(corp, num_topics = 10, id2word=dctn, alpha = 1)
model.print_topics()

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

Out[87]:
[(9,  '0.017*"клиент" + 0.005*"страхование" + 0.005*"вернуть" + 0.004*"заявление" + 0.004*"просит"')]

Далее можно по слову и его идентификатору восстановить идентификаторы предложений (в нашем случае текстов обращений с жалобами) и сопоставить их с темами. Таким образом получится список обращений и тем, с которыми их можно ассоциировать. Представленный пример – лишь малая часть возможностей тематического моделирования и библиотеки gensim в частности. Основной недостаток используемого алгоритма LDA заключается в том, что количество тем задаётся параметром, т. е. распределение слов будет только по заданному количеству тем. Если нужно узнать все возможные темы среди множества обращений, то скорее всего подойдёт иерархический процесс Дирихле (HDP), но в рамках данной статьи он не рассматривается.

Советуем почитать