Тематическое моделирование со скрытым распределением Дирихле

Я Грег Рафферти, специалист по обработке данных из района Залива. Вы можете посмотреть код этого проекта на моем гитхабе. Не стесняйтесь обращаться ко мне с любыми вопросами!

В этом посте я опишу тематическое моделирование с помощью скрытого распределения Дирихле и сравню различные алгоритмы для этого через призму Гарри Поттера. В следующих статьях будут рассмотрены еще две задачи НЛП: обобщение текста и анализ настроений.

Недавно мне поручили новый проект с командой, которая была единодушно шокирована и разочарована тем, что я никогда не читал и не смотрел фильмы об одном вымышленном волшебнике по имени Гарри Поттер. Чтобы влиться в команду и, очевидно, спасти свою карьеру от раннего завершения, быстро стало очевидно, что мне придется пройти ускоренный курс по событиям в Хогвартсе. Вооружившись моей программой для чтения электронных книг и семью новыми блестящими файлами в формате pdf, я решил разобраться, о чем идет речь. Тем временем я начал работать над побочным проектом, состоящим из кучи несвязанных задач НЛП. Мне нужен был набор текстовых документов хорошего размера, и я подумал, что все эти блестящие новые PDF-файлы будут отличным источником.

И где-то в середине третьей книги я внезапно понял, что LDA - это всего лишь алгоритмическая сортировочная шляпа.

LDA или скрытое распределение Дирихле - это генеративная вероятностная модель (в терминах НЛП) корпуса документов, состоящих из слов и / или фраз. Модель состоит из двух таблиц; первая таблица - это вероятность выбора определенного слова в корпусе при выборке из определенной темы, а вторая таблица - это вероятность выбора определенной темы при выборке из определенного документа.

Вот пример. Допустим, у меня есть три (довольно бессмысленных) документа:

document_0 = "Harry Harry wand Harry magic wand"
document_1 = "Hermione robe Hermione robe magic Hermione"
document_2 = "Malfoy spell Malfoy magic spell Malfoy"
document_3 = "Harry Harry Hermione Hermione Malfoy Malfoy"

Вот матрица частотности запросов для этих документов:

Просто взглянув на это, кажется довольно очевидным, что документ 0 в основном о Гарри, немного о магии и отчасти о палочке. Документ 1 также немного о магии, но в основном о Гермионе и мантии. И документ 2 снова частично о магии, но в основном о Малфое и заклинаниях. Документ 3 в равной степени касается Гарри, Гермионы и Малфоя. Обычно это не так просто увидеть, потому что более практичный корпус будет состоять из тысяч или десяти тысяч слов, поэтому давайте посмотрим, что алгоритм LDA выбирает для тем:

И это примерно то, что мы предсказали, просто исходя из частот терминов и нашего чутья. Количество тем - это гиперпараметр, который вам нужно будет тщательно выбрать и настроить, и я расскажу об этом позже, но для этого примера я выбрал 4 темы, чтобы выразить свою точку зрения. Верхняя таблица показывает слова по сравнению с темами, а нижняя таблица показывает документы по сравнению с темами. Сумма в каждом столбце верхней таблицы и каждой строке нижней таблицы должна быть равна 1. Эти таблицы говорят нам, что если бы мы случайно выбрали слово из темы 0, то с вероятностью 70,9% мы взяли бы «Гарри». Если мы выберем слово из темы 3, почти наверняка выберем слово «магия». Если мы выберем Документ 3, то с равной вероятностью выберем тему 0, 1 или 2.

Это зависит от нас, как умных людей, которые могут понять смысл названий этих тем из набора слов. В этих примерах с очень словарным запасом темы совершенно очевидно соответствуют отдельным словам. Если бы мы использовали LDA, скажем, для пары тысяч описаний ресторанов, мы могли бы найти темы, соответствующие типу кухни или атмосфере. Важно отметить, что LDA, в отличие от типичных алгоритмов кластеризации, таких как Kmeans, позволяет документу существовать в нескольких темах. Таким образом, в описании ресторанов мы можем найти один ресторан, помещенный в темы «итальянский», «свидание-вечер» и «кафе».

Так как все это похоже на Сортировочную шляпу? Все новые студенты Хогвартса по прибытии в первый день проходят церемонию, чтобы определить, в каком доме они будут (вероятно, я единственный человек, который не знал об этом всего несколько недель назад). Сортировочная шляпа, однажды надетая кому-то на голову, понимает, о чем они думают, мечтают и переживают. Это немного похоже на то, как LDA строит матрицу частот терминов и понимает, какие слова и N-граммы содержатся в каждом документе.

Затем Сортировочная шляпа сравнивает атрибуты ученика с атрибутами различных домов (храбрость достается Гриффиндору, верность Хаффлпаффу, мудрость Когтеврану, а хитрые, хитрые мерзавцы идут в Слизерин (ладно, в сторону - может ЛЮБОЙ) объясните мне, почему Слизерин упорствовал на протяжении тысячелетней истории этой школы? Это как то одно братство, которое каждый проклятый год попадает в очередной смехотворно непристойный скандал!)). Здесь LDA создает таблицу «слово-тема» и начинает связывать атрибуты тем.

Положение Гарри было заметно разделено между Гриффиндором и Слизерином из-за его сочетания храбрости, интеллекта, таланта и амбиций, но Гриффиндор лишь немного отошел вперед, и Гарри Поттер стал героем целого поколения молодых миллениалов, а не его злодеем. Здесь LDA создает таблицу «документ-тема» и, наконец, определяет, какая тема является доминирующей для каждого документа.

Хорошо, теперь, когда мы примерно знаем, что делает LDA, давайте посмотрим на две разные реализации на Python. Ознакомьтесь с моим репозиторием на Github для получения всех мельчайших подробностей.

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

Обычно вам нужно выбрать наименьшее количество тем, по которым показатель согласованности начнет снижаться. Вот почему это называется диаграммой локтя - вы выбираете локоть между резкими и мелкими достижениями. В этом случае (и это замечательно острый случай; обычно кривые немного плавнее, чем здесь), я бы выбрал где-то около 20 тем.

Первая модель, которую я использовал, - это ldamodel Генсима. По 20 темам Gensim имел оценку согласованности 0,319. Это не здорово; действительно, алгоритм Маллета, который мы рассмотрим далее, почти всегда превосходит алгоритм Генсима. Однако одна действительно крутая вещь в Gensim - это pyLDAvis, интерактивная диаграмма, которую вы можете запустить в записной книжке Jupyter. Он отображает кластеры с двумя основными компонентами и показывает долю слов в каждом кластере:

Следующей реализацией, которую я рассмотрел, был Mallet (MA chine L, зарабатывающий за L anguag E T oolkit), пакет на основе Java, выпущенный UMASS Amherst. Разница между стандартным LDA Маллета и Gensim заключается в том, что Gensim использует метод вариационной байесовской выборки, который быстрее, но менее точен, чем выборка Гиббса Маллета. К счастью для тех, кто предпочитает кодировать на Python, в Gensim есть оболочка для Mallet: Скрытое распределение Дирихле с помощью Mallet. Чтобы использовать его, вам необходимо загрузить пакет Mallet Java отсюда http://mallet.cs.umass.edu/dist/mallet-2.0.8.zip, а также установить Java Development Kit. После того, как все настроено, реализация модели почти такая же, как и стандартная модель Gensim. С помощью Маллета оценка согласованности для модели из 20 тем увеличилась до 0,375 (помните, стандартная модель Gensim выдает 0,319). Это небольшое увеличение, но обычно сохраняется с различными источниками данных, поэтому, хотя Mallet немного медленнее, я предпочитаю его из-за увеличения отдачи.

Наконец, я построил модель Молота на 192 главах всех 7 книг серии о Гарри Поттере. Вот 10 основных ключевых слов, которые выводит модель для каждой скрытой темы. Как бы вы назвали эти кластеры?