Логотип Data Secrets
dfghj

Тематическое моделирование c BigARTM

07.11.2024

В соавторстве статьи Константин Воронцов – доктор физико-математических наук, преподаватель ШАД и МГУ, автор метода ARTM и создатель библиотеки BigARTM для тематического моделирования. 

Какую цель мы обычно преследуем, когда анализируем данные? Верно, нам нужно извлечь из них некоторые выводы и инсайты. Если данные структурированы – например, представлены в виде таблиц, – сделать это можно с помощью классических статистических методов и простых алгоритмов. Но что делать, если данные не имеют четкой структуры? Что, если это куча текстовых документов, или изображений, или молекулы белков? Как выявлять в таких структурах паттерны, извлекать из них значимую информацию или осуществлять по ним поиск? 

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

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

В статье мы разберемся с ключевыми концепциями тематического моделирования и основными архитектурами моделей этой области. Будет теория и много практики на интерфейсе библиотеки BigARTM. Кстати, игривое существо на картинке – это придуманный разработчиками тотемный персонаж библиотеки, и мы встретимся с ним еще не раз. Ну что, поехали?

Что такое тематическое моделирование

Тематическое моделирование отвечает на вопросы «о чём этот текст», «какие общие темы есть у этих текстов» и «какими словами представлена эта тема». Задача тематической модели, или, точнее, вероятностной тематической модели состоит в том, чтобы определить вероятность того, что документ или некоторое слово принадлежит к той или иной теме. 

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

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

Чтобы окончательно расставить все точки над i, осталось обсудить математическую постановку задачи. Формально, у нас есть три конечных множества: множество текстовых документов D, словарь всех употребляемых в них термов W и множество тем T. При этом D и W известны нам заранее, а вот T – нет (напоминаем, что задача относится к обучению без учителя). Рассмотрим условные вероятности φ = p(w|t) и θ = p(t|d). Они означают соответственно вероятности того, что «терм w связан с темой t» и того, что «документ d относится к теме t». Эти вероятности нам неизвестны и наша задача сводится к приближению их оценок. Чем точнее такая оценка – тем лучше мы понимаем генеральную совокупность и, следовательно, распределяем тексты и термы по темам. 

Но есть и такие оценки, которые нам уже даны. Это оценки вероятностей p(w|d), и на самом деле это просто частоты терминов в документах. Именно на основе этих оценок мы в дальнейшем будем строить вероятностную модель. Все дело в том, что имеет место равенство: 
Интуиция, стоящая за этой формулой, такова: если представить, что нам, наоборот, даны вероятности  p(w|t) и p(t|d), то с их помощью мы могли бы восстанавливать p(w|d), то есть генерировать текст, взвешенно-случайно выбирая для каждого текста сначала темы, а потом слова из этих тем. В этом смысле тематические модели похожи на известные всем трансформеры, ведь получается, что они предсказывают вероятности появления слов в документах. На трансформеры тематические модели похожи также тем, что превращают слова и документы в эмбеддинги. Правда, в трансформерах эмбеддинги не интерпретируемы, а в тематическом моделировании имеют конкретный смысл – это просто векторы вероятностей тем. Это свойство позволяет анализировать темы и слова в них. 

Классические модели: PLSA и LDA

Внимательный читатель, знакомый с математикой и теорией машинного обучения, посмотрев на предыдущий раздел, скажет: “Тут же сама собой напрашивается оптимизационная задача максимизации правдоподобия!” – и окажется прав. Действительно, то самое равенство, которое мы видели в прошлой главе, на самом деле ведет нас к такой задаче математического программирования: апроНа этом месте у нас есть две новости, хорошая и плохая. Плохая: эта задача поставлена некорректно по Адамару, потому что существует бесконечное множество ее решений. Хорошая: это можно легко обойти, применив регуляризацию. Многие из нас, скорее всего, неоднократно встречались с L1 или L2 регуляризацией. Эти методы применяются для того, чтобы каким-то образом ограничить множество решений дополнительными критериями. В задаче тематического моделирования регуляризации используются с той же целью и помогают найти единственное устойчивое решение задачи выше. На практике регуляризаторы могут помогать учитывать нетекстовые данные, улучшать качество классификации текстов, точность и полноту поиска, различность тем, разреженность решения и т.д. 

И еще одна хорошая новость: в тематическом моделировании, вне зависимости от того, какие именно регуляризаторы мы используем, можно выработать единый общий рецепт решения. Но об этом – немного позже. 

Самой цитируемой и известной моделью в тематическом моделировании можно назвать модель LDA (latent Dirichlet allocation) – латентное размещения Дирихле. Она была изобретена в 2003 году. Ей предшествовала более простая модель вероятностного латентного семантического анализа, PLSA (1999), которая решала задачу без регуляризаторов вообще или, говоря точнее, просто находила какое-то одно решение из бесконечного множества. 

LDA же была первой моделью, в которую исследователи смогли поместить регуляризацию, но, к сожалению, самую простую и только одну. В основе LDA – байесовское обучение: мы задаем априорное распределение на наши параметры модели или, вернее сказать, на матрицы φ и θ , далее добавляем в модель некоторые данные и получаем апостериорные распределения. Этот метод нетривиален — приходится формировать сложные математические выкладки и, если вам захочется добавить какое-то новое ограничение на матрицы φ и θ (то есть новый регуляризатор), это потребует уникального подхода и долгой и непростой теоретической работы, и мы уже не говорим про софт. 

апро15 лет тематическое моделирование продолжало развиваться в рамках такого байесовского подхода: за эти годы были придумано несколько сотен, а может, даже тысяч моделей с разными регуляризаторами, но изящно объединять их так никто и не научился. Пока в 2014 году Константин Воронцов и Анна Потапенко не придумали ARTM

ARTM 

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

Получается, что в данном случае нам вообще неважно, сколько у нас регуляризаторов и насколько они сложные: на нашей задаче это отражается только в виде дополнительного слагаемого с некоторым весом. В машинном обучении такой подход называется мультизадачным обучением (multitask learning). 

Теперь, когда нам не нужно отдельно работать над каждым регуляризатором, можно каждый раз пользоваться одним и тем же методом решения задачи. А именно, оказывается, что ее решение сводится к решению некоторой системы уравнений, называемой также EM-алгоритмом. 
проE-шаг здесь – это вычисление условных распределений скрытых переменных по формуле Байеса. А M-шаг – от слова maximization, вычисление самих параметров модели. Это итерационный алгоритм, то есть сначала здесь выбираются начальные приближения параметров φ и θ, а затем по ним вычисляются вспомогательные переменные p_tdw, которые в свою очередь позволяют найти следующее приближение параметров φ и θ.

Кстати, при таком взгляде на вещи ранее рассмотренные нами модели PLSA и LDA оказываются просто частными случаями обобщенной задачи. 

Как мы уже упоминали, ARTM появилась в 2014 году. Тогда же стартовал проект BigARTM, который воплотил в себе идеи аддитивной регуляризации и расширил спектр приложений тематического моделирования, сняв многие ограничения простых моделей типа PLSA или LDA. Сейчас мы на практике разберемся в этой библиотеке подробнее.  

К практике

BigARTM – это библиотека с открытым исходным кодом, самый быстрый инструмент для тематического моделирования. BigARTM бодрее даже аналогичных реализаций в широко известных Gensim и Vowpal Wabbit. При этом в библиотеке реализован очень широкий спектр полезных механизмов: 

Кстати, Big в названии не значит “много кода”. Просто библиотека позволяет обрабатывать большие объемы данных. Вот некоторые технические подробности того, как это реализовано:

Библиотека является кроссплатформенной: сборку и исполнение можно производить под Windows 7/8/10, Mac OS и различными дистрибутивами Linux. Поддерживаются программные интерфейсы под Python 2.7.*/3.*, C++, а также запуск в виде исполняемого бинарного файла. Детальную информацию о библиотеке можно найти в документации на сайте http://bigartm.org.
Сейчас мы вместе с BigARTM пройдемся по пути построения тематической модели. Первое, что нам понадобится – это подготовить данные. Если ваша коллекция не слишком большая, то сделать это можно очень просто, с помощью sklearn: 

# Import all necessary tools and data
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.datasets import fetch_20newsgroups
from numpy import array
import artm

# Extract data using sklearn and numpy
cv = CountVectorizer(max_features=1000, stop_words=’english’)
n_wd = array(cv.fit_transform(fetch_20newsgroups().data).todense()).T
vocabulary = cv.get_feature_names()

# Create batches and dictionary
bv = artm.BatchVectorizer(data_format=’bow_n_wd’,
n_wd=n_wd,
vocabulary=vocabulary)

В коде наверху вы видите объект класса artm.BatchVectorizer. Это векторизатор – универсальный объект, принимаемый на вход всеми операциями BigARTM. В примере выше он был создан по матрице мешка слов n_wd и словаря, задающего соответствие между строками матрицы и словами коллекции. Если же ваши данные уже предобработаны и хранятся в UCI формате, то векторизатор можно создать так: 

batch_vectorizer = artm.BatchVectorizer(data_path=' ',
data_format='bow_uci',
                                        collection_name='my_collection',
                                        target_folder='my_collection_batches')

Кроме векторизатора стоит также создать словарь. Словари BigARTM предназначены для хранения данных о словах и используются в некоторых регуляризаторах и метриках качества. Словарю соответствует объект artm.Dictionary, который можно либо сформировать автоматически во время разбиения коллекции на пакеты (задав в artm.BatchVectorizer параметр gather_dictionary, по умолчанию равный True), либо создать вручную на основе своих данных. 

bv.dictionary.save(’my_collection_batches/dictionary’)

# Load dictionary back during next BigARTM launch:
dictionary = artm.Dictionary()
dictionary.load(’my_collection_batches/dictionary.dict’)

На этом тему предобработки можно считать закрытой, и мы переходим к модели. Пайплайн создания и обучения модели в BigARTM очень напоминает аналогичный пайплайн в sklearn, так что опытному Data Scientist’у последующий интерфейс покажется очень привычным. Для начала нужно просто определить объект модели и задать желаемое количество тем: 

model = artm.ARTM(num_topics=15, dictionary=bv.dictionary)

По сути, на этом шаге происходит создание матрицы параметров φ размером (количество слов в вашем словаре) x (количество тем). Эта матрица инициализируется случайным образом. Теперь наша цель – обучить созданную модель. Для этого для начала нужно задать ей метрики. Для этого удобно использовать подкласс scores класса ARTM. Например, вот так можно добавить в модель метрику перплексии: 

model.scores.add(artm.PerplexityScore(name='my_first_perplexity_score',
dictionary=my_dictionary))

Кроме перплексии, в библиотеке можно также найти такие метрики, как разреженность матриц, чистота, контранстность, когерентность и доля фоновых слов. 
Итак, вернемся к обучению. Вообще говоря, BigARTM позволяет обучать модель двумя способами: онлайн и оффлайн. В первом случае матрица параметров будет обновляться несколько раз за один (и он может быть единственным) проход по коллекции. Такой онлайн-подход стоит использовать, когда вы имеете дело с большим корпусом. В оффлайн алгоритме, наоборот, матрица обновляется всего раз за один проход по коллекции, но таких проходов будет много. Такой подход подходит для небольших датасетов, и именно его мы рассмотрим. 

model.fit_offline(batch_vectorizer=batch_vectorizer, num_collection_passes=10)

Эта строка кода – первый шаг обучения. После него стоит посмотреть на метрики и убедиться, что все в порядке. Сделать это можно так: 

print model.score_tracker['my_fisrt_perplexity_score'].value

После этого обучение мы можем продолжить: 

model.fit_offline(batch_vectorizer=batch_vectorizer, num_collection_passes=15)

И так далее. Кстати, если в какой-то момент вы поймете, что ваша модель выродилась, то создавать новую не обязательно. Достаточно вызвать model.initialize(dictionary=my_dictionary) и матрица параметров снова вернется к исходному состоянию случайной инициализации. 

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

Подробнее обо всех регуляризаторах BigARTM можно прочитать здесь. Что касается кода, то добавить регуляризатор в модель очень просто. Нужно просто вызвать model.regularizers.add

model.regularizers.add(artm.SmoothSparsePhiRegularizer(
name='sparse_phi_regularizer')
)
model.regularizers.add(artm.SmoothSparseThetaRegularizer(
name='sparse_theta_regularizer')
)
model.regularizers.add(artm.DecorrelatorPhiRegularizer(
name='decorrelator_phi_regularizer')
)

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

reg = artm.DecorrelatorPhiRegularizer(name=’decor’, tau=1e+5)
model.regularizer.add(reg)
model.scores.SparsityPhiScore(name=’sparse’)
model.fit_offline(batch_vectorizer=bv, num_collection_passes=10)
print model.score_tracker(’sparse’).last_value

# Printing result: 0.15 - too small. Let’s increase tau

model.regularizer[’decor’].tau = 3e+5
model.fit_offline(batch_vectorizer=bv, num_collection_passes=15)

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

Но и это не все. В BigARTM можно обрабатывать документы, содержащие не только слова, но и токены других модальностей. Это могут быть какие-то метаданные документов или что-то, содержащееся внутри них: ссылки, картинки, именованные сущности и др. Модальности помогают строить темы с учетом дополнительной информации. С другой стороны, темы помогают выявлять семантику нетекстовых модальностей, предсказывать или рекомендовать значения пропущенных токенов. 

Если ваши документы содержат мультимодальность и вы хотите это учитывать, то сперва придется немного поработать с данными. Ваша задача — создать файл в формате Vowpal Wabbit, где каждая строка — это документ, а каждый документ содержит токены двух модальностей — обычные токены и токены-метки классов, к которым принадлежит документ. Как только файл будет получен, можно загрузить его в BigARTM также, как мы обсуждали ранее. 

Следующий шаг — донести до вашей модели информацию о ваших модальностях и их важности. Для этого используйте примерно такой код: 

model = artm.ARTM(num_topics=20, class_ids={'@default_class': 1.0, '@labels_class': 5.0})

Мы только что создали мультимодальную модель с двумя модальностями, при этом модальность меток классов будет для нее важнее, чем токены модальности @default_class. Веса модальностей, к слову, тоже можно менять между эпохами обучения. 

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

Заключение

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

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