Тематическое моделирование с помощью BERT
Использование BERT и TF-IDF для создания легко интерпретируемых тем.
Часто, когда владелец продукта обращается ко мне с просьбой провести анализ на основе НЛП, мне обычно задают следующий вопрос:
«Какая тема часто встречается в этих документах?»
Отсутствие каких-либо категорий или ярлыков. Я вынужден изучить неконтролируемые методы извлечения этих тем, а именно Тематическое моделирование.
Хотя тематические модели, такие как LDA и NMF, оказались хорошей отправной точкой, я всегда чувствовал, что для создания значимых тем требовалось немало усилий с помощью настройки гиперпараметров.
Более того, я хотел использовать модели на основе трансформаторов, такие как BERT, поскольку они показали потрясающие результаты в различных задачах НЛП за последние несколько лет. Предварительно обученные модели особенно полезны, поскольку они должны содержать более точное представление слов и предложений.
Несколько недель назад я увидел этот замечательный проект под названием Top2Vec *, в котором использовались вложения документов и слов для создания тем, которые можно было легко интерпретировать. Я начал искать код для обобщения Top2Vec, чтобы его можно было использовать с предварительно обученными моделями трансформаторов.
Большим преимуществом Doc2Vec является то, что результирующие вложения документа и слова совместно встраиваются в одно и то же пространство, что позволяет встраиванию документа быть представленным вложениями соседних слов. К сожалению, это оказалось трудным, поскольку вложения BERT основаны на токенах и не обязательно занимают одно и то же пространство **.
Вместо этого я решил придумать другой алгоритм, который мог бы использовать вложения преобразователей BERT и 🤗. Результатом стал BERTopic, алгоритм для создания тем с использованием самых современных встраиваний.
Основной темой этой статьи будет не использование BERTopic, а руководство о том, как использовать BERT для создания вашей собственной тематической модели.
ДОКУМЕНТ *: Ангелов, Д. (2020). Top2Vec: распределенное представление тем. Препринт arXiv arXiv: 2008.09470.
ПРИМЕЧАНИЕ * *. Хотя они могут занимать одно и то же пространство, результирующий размер встраиваемых слов будет довольно большим из-за контекстной природы BERT. Более того, существует вероятность того, что в результате вложения предложений или документов ухудшится качество.
1. Данные и пакеты
В этом примере мы используем знаменитый набор данных 20 Newsgroups
, который содержит примерно 18000 сообщений групп новостей по 20 темам. Используя Scikit-Learn, мы можем быстро загрузить и подготовить данные:
Если вы хотите ускорить обучение, вы можете выбрать подмножество train
, так как оно уменьшит количество извлекаемых сообщений.
ПРИМЕЧАНИЕ. Если вы хотите применить тематическое моделирование не ко всему документу, а на уровне абзаца, я бы посоветовал разделить ваши данные перед созданием вложений.
2. Вложения
Самый первый шаг, который нам нужно сделать, - это преобразовать документы в числовые данные. Для этой цели мы используем BERT, поскольку он извлекает различные вложения в зависимости от контекста слова. Мало того, есть много предварительно обученных моделей, готовых к использованию.
Как вы создаете вложения BERT для документа, зависит от вас. Однако я предпочитаю использовать пакет sentence-transformers
, поскольку полученные вложения показали высокое качество и обычно достаточно хорошо работают для встраиваний на уровне документа.
Установите пакет с pip install sentence-transformers
перед созданием вложений документов. Если у вас возникнут проблемы с установкой этого пакета, то сначала стоит установить Pytorch.
Затем запустите следующий код, чтобы преобразовать ваши документы в 512-мерные векторы:
Мы используем Distilbert, поскольку он обеспечивает хороший баланс между скоростью и производительностью. В пакете есть несколько многоязычных моделей, доступных для использования.
ПРИМЕЧАНИЕ. Поскольку у моделей трансформеров есть ограничение по токенам, вы можете столкнуться с некоторыми ошибками при вводе больших документов. В этом случае вы можете рассмотреть возможность разделения документа на параграфы.
3. Кластеризация
Мы хотим убедиться, что документы с похожими темами сгруппированы вместе, чтобы мы могли найти темы в этих кластерах. Перед этим нам сначала нужно снизить размерность вложений, поскольку многие алгоритмы кластеризации плохо справляются с высокой размерностью.
UMAP
Из немногих алгоритмов уменьшения размерности UMAP, возможно, является наиболее эффективным, поскольку он сохраняет значительную часть многомерной локальной структуры в более низкой размерности.
Установите пакет с pip install umap-learn
, прежде чем мы снизим размерность вложений документа. Мы уменьшаем размерность до 5, сохраняя при этом размер локального окружения равным 15. Вы можете поэкспериментировать с этими значениями, чтобы оптимизировать создание вашей темы. Обратите внимание, что слишком низкая размерность приводит к потере информации, а слишком высокая размерность приводит к худшим результатам кластеризации.
HDBSAN
После уменьшения размерности встраиваемых документов до 5 мы можем кластеризовать документы с помощью HDBSCAN. HDBSCAN - это алгоритм, основанный на плотности, который довольно хорошо работает с UMAP, поскольку UMAP поддерживает большую локальную структуру даже в пространстве меньшей размерности. Более того, HDBSCAN не переносит точки данных в кластеры, поскольку считает их выбросами.
Установите пакет с pip install hdbscan
, затем создайте кластеры:
Большой! Теперь мы сгруппировали похожие документы вместе, которые должны представлять темы, из которых они состоят. Чтобы визуализировать полученные кластеры, мы можем дополнительно уменьшить размерность до 2 и визуализировать выбросы в виде серых точек:
Визуализировать отдельные кластеры сложно из-за количества сгенерированных тем (~ 55). Однако мы видим, что даже в двумерном пространстве сохраняется некоторая локальная структура.
ПРИМЕЧАНИЕ. Вы можете пропустить этап уменьшения размерности, если используете алгоритм кластеризации, который может обрабатывать высокую размерность, например k-среднее на основе косинуса.
4. Создание темы
Что мы хотим узнать из кластеров, которые мы создали, - вот что отличает один кластер по своему содержанию от другого?
Как мы можем извлечь темы из сгруппированных документов?
Чтобы решить эту проблему, я придумал вариант TF-IDF на основе классов (c-TF-IDF), который позволил бы мне извлечь то, что делает каждый набор документов уникальным по сравнению с другим.
Интуиция, лежащая в основе метода, заключается в следующем. Когда вы применяете TF-IDF как обычно к набору документов, вы в основном сравниваете важность слов между документами.
Что, если вместо этого мы будем рассматривать все документы в одной категории (например, кластере) как один документ, а затем применять TF-IDF? В результате получится очень длинный документ по каждой категории, а итоговая оценка TF-IDF продемонстрирует важные слова в теме.
c-TF-IDF
Чтобы создать эту оценку TF-IDF на основе классов, нам нужно сначала создать один документ для каждого кластера документов:
Затем мы применяем TF-IDF на основе классов:
Где частота каждого слова t
извлекается для каждого класса i
и делится на общее количество слов w
. Это действие можно рассматривать как форму регуляризации частых слов в классе. Затем общее количество несвязанных документов m
делится на общую частоту слова t
по всем классам n
.
Теперь у нас есть одно значение важности для каждого слова в кластере, которое можно использовать для создания темы. Если мы возьмем 10 самых важных слов в каждом кластере, то получим хорошее представление о кластере и, следовательно, теме.
Представление темы
Чтобы создать представление темы, мы берем 20 лучших слов по каждой теме на основе их оценок c-TF-IDF. Чем выше оценка, тем более репрезентативной должна быть его тема, поскольку оценка является показателем плотности информации.
Мы можем использовать topic_sizes
, чтобы узнать, насколько часто встречаются определенные темы:
Название темы-1
относится ко всем документам, которым не назначены темы. Самое замечательное в HDBSCAN заключается в том, что не все документы направляются в определенный кластер. Если кластер найти не удалось, то это просто выброс.
Мы видим, что темы 7, 43, 12 и 41 - это самые большие кластеры, которые мы могли бы создать. Чтобы просмотреть слова, относящиеся к этим темам, мы можем просто использовать dictionarytop_n_words
для доступа к этим темам:
Глядя на четыре самые большие темы, я бы сказал, что они прекрасно представляют собой легко интерпретируемые темы!
Я вижу спорт, компьютеры, космос и религию как четкие темы, извлеченные из данных.
5. Уменьшение количества тем
Есть шанс, что в зависимости от набора данных вы получите сотни созданных тем! Вы можете настроить параметры HDBSCAN таким образом, чтобы вы получали меньше разделов с помощью его параметра min_cluster_size
, но он не позволяет вам указать точное количество кластеров.
Изящный трюк, который использовал Top2Vec, - это возможность уменьшить количество тем путем слияния векторов тем, которые были наиболее похожи друг на друга.
Мы можем использовать похожую технику, сравнивая векторы c-TF-IDF по темам, объединяя наиболее похожие и, наконец, пересчитывая векторы c-TF-IDF для обновления представления наших тем:
Выше мы взяли наименее распространенную тему и объединили ее с наиболее похожей темой. Повторив это еще 19 раз, мы сократили количество тем с 56 до 36!
ПРИМЕЧАНИЕ. Мы можем пропустить часть пересчета в этом конвейере, чтобы ускорить этап сокращения тем. Однако более точно пересчитать векторы c-TF-IDF, так как это лучше представит вновь созданное содержание тем. Вы можете поиграть с этим, например, обновляя каждые n шагов, чтобы ускорить процесс и сохранить хорошее представление темы.
СОВЕТ: вы можете использовать метод, описанный в этой статье (или просто использовать BERTopic), чтобы также создавать вложения на уровне предложений. Основным преимуществом этого является возможность просмотра распределения тем в одном документе.
Спасибо за чтение!
Если вы, как и я, увлечены искусственным интеллектом, наукой о данных или психологией, пожалуйста, не стесняйтесь добавить меня в LinkedIn или подписаться на меня в Twitter.
Все примеры и код из этой статьи можно найти здесь: