Более глубокий смысл: тематическое моделирование в Python
Опубликовано: 2022-03-11Компьютеры и процессоры, на которых они работают, созданы для работы с числами. Напротив, повседневный язык электронных писем и сообщений в социальных сетях имеет свободную структуру, которая не поддается вычислениям.
Вот тут-то и появляется обработка естественного языка (NLP). NLP — это отрасль информатики, которая пересекается с лингвистикой, применяя вычислительные методы (а именно, искусственный интеллект) для анализа естественного языка и речи. Тематическое моделирование направлено на понимание того, о каких темах идет речь в данном тексте. Тематическое моделирование позволяет разработчикам реализовать полезные функции, такие как обнаружение последних новостей в социальных сетях, рекомендации персонализированных сообщений, обнаружение поддельных пользователей и характеристика потока информации.
Как разработчики могут заставить компьютеры, ориентированные на вычисления, понимать человеческое общение на таком уровне сложности?
Мешок слов
Чтобы ответить на этот вопрос, нам нужно уметь математически описать текст. Мы начнем наш учебник Python по тематическому моделированию с самого простого метода: набора слов.
Этот метод представляет текст как набор слов. Например, предложение This is an example может быть описано как набор слов с использованием частоты, с которой эти слова появляются:
{"an": 1, "example": 1, "is": 1, "this": 1}Обратите внимание, что этот метод игнорирует порядок слов. Возьмите эти примеры:
- «Мне нравятся «Звездные войны», но не нравится «Гарри Поттер».
- «Мне нравится «Гарри Поттер», но не «Звездные войны».
Эти чувства представлены одними и теми же словами, но имеют противоположное значение. Однако для целей анализа тематики текстов эти различия не имеют значения. В обоих случаях речь идет о вкусах к Гарри Поттеру и «Звездным войнам», независимо от того, что это за вкусы. Таким образом, порядок слов не имеет значения.
Когда у нас есть несколько текстов и мы пытаемся понять различия между ними, нам нужно математическое представление для всего нашего корпуса, которое рассматривает каждый текст отдельно. Для этого мы можем использовать матрицу, в которой каждый столбец представляет слово или термин, а каждая строка представляет собой текст. Возможное представление корпуса состоит в том, чтобы отметить в каждой ячейке частоту, с которой данное слово (столбец) используется в определенном тексте (строке).
В нашем примере корпус состоит из двух предложений (строк нашей матрицы):
["I like Harry Potter", "I like Star Wars"]Мы перечисляем слова в этом корпусе в том порядке, в котором мы с ними встречаемся: я , как , Гарри , Поттер , Звезда , Войны . Они соответствуют столбцам нашей матрицы.
Значения в матрице представляют собой количество раз, когда данное слово используется в каждой фразе:
[[1,1,1,1,0,0], [1,1,0,0,1,1]] Обратите внимание, что размер матрицы определяется путем умножения количества текстов на количество разных слов, встречающихся хотя бы в одном тексте. Последняя обычно излишне велика и может быть уменьшена. Например, матрица может содержать два столбца для спряженных глаголов, таких как «играть» и «играть», независимо от того, что их значения схожи.
Но столбцы, описывающие новые концепции, могут отсутствовать. Например, «классическая» и «музыка» имеют отдельные значения, но в сочетании — «классическая музыка» — имеют другое значение.
Из-за этих проблем необходимо предварительно обработать текст, чтобы получить хорошие результаты.
Модели предварительной обработки и тематической кластеризации
Для достижения наилучших результатов необходимо использовать несколько методов предварительной обработки. Вот некоторые из наиболее часто используемых:
- Строчные буквы. Сделайте все слова строчными. Сделайте все слова строчными. Значение слова не меняется независимо от его положения в предложении.
- n -грамм. Считайте все группы из n слов подряд новыми терминами, называемыми n-граммами . Таким образом, такие падежи, как «белый дом», будут учтены и добавлены в список лексики.
- Стемминг. Определите префиксы и суффиксы слов, чтобы изолировать их от корня. Таким образом, такие слова, как «играть», «играть» или «игрок», представлены словом «играть». Стемминг может быть полезен для уменьшения количества слов в словарном списке при сохранении их значения, но он значительно замедляет предварительную обработку, поскольку должен применяться к каждому слову в корпусе.
- Стоп-слова. Не принимайте во внимание группы слов, лишенных смысла или полезности. К ним относятся артикли и предлоги, но также могут быть слова, которые не подходят для нашего конкретного примера, например, некоторые общеупотребительные глаголы.
- Частота термина – обратная частота документа (tf–idf). Используйте коэффициент tf–idf вместо того, чтобы отмечать частоту каждого слова в каждой ячейке матрицы. Он состоит из двух чисел, умноженных:
- tf — частота встречаемости данного термина или слова в тексте;
- idf — логарифм общего количества документов, деленный на количество документов, содержащих данный термин.
tf-idf — это мера того, насколько часто слово используется в корпусе. Чтобы иметь возможность подразделять слова на группы, важно понимать не только, какие слова встречаются в каждом тексте, но и какие слова часто встречаются в одном тексте, но не встречаются в других.
На следующем рисунке показаны некоторые простые примеры этих методов предварительной обработки, когда исходный текст корпуса изменяется для создания релевантного и управляемого списка слов.
Теперь мы продемонстрируем, как применять некоторые из этих методов в Python. Как только мы представим наш корпус математически, нам нужно определить обсуждаемые темы, применяя неконтролируемые алгоритмы машинного обучения. В этом случае «неконтролируемый» означает, что у алгоритма нет предопределенных тематических меток, таких как «научная фантастика», которые можно применить к его выходным данным.

Чтобы сгруппировать наш корпус, мы можем выбрать один из нескольких алгоритмов, включая неотрицательную матричную факторизацию (NMF), разреженный анализ основных компонентов (разреженный PCA) и скрытое распределение дирихле (LDA). Мы сосредоточимся на LDA, потому что он широко используется научным сообществом благодаря хорошим результатам в социальных сетях, медицине, политологии и разработке программного обеспечения.
LDA — это модель неконтролируемой декомпозиции темы: она группирует тексты на основе содержащихся в них слов и вероятности принадлежности слова к определенной теме. Алгоритм LDA выводит распределение слов темы. С помощью этой информации мы можем определить основные темы на основе слов, которые, скорее всего, с ними связаны. Как только мы определили основные темы и связанные с ними слова, мы можем узнать, какая тема или темы относятся к каждому тексту.
Рассмотрим следующий корпус, состоящий из пяти коротких предложений (все взяты из заголовков New York Times ):
corpus = [ "Rafael Nadal Joins Roger Federer in Missing US Open", "Rafael Nadal Is Out of the Australian Open", "Biden Announces Virus Measures", "Biden's Virus Plans Meet Reality", "Where Biden's Virus Plan Stands"]Алгоритм должен четко выделять одну тему, связанную с политикой и коронавирусом, и вторую, связанную с Надалем и теннисом.
Применение стратегии в Python
Чтобы обнаружить темы, мы должны импортировать необходимые библиотеки. В Python есть несколько полезных библиотек для НЛП и машинного обучения, включая NLTK и Scikit-learn (sklearn).
from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer from sklearn.decomposition import LatentDirichletAllocation as LDA from nltk.corpus import stopwords Используя CountVectorizer() , мы генерируем матрицу, которая обозначает частоту слов каждого текста, используя CountVectorizer() . Обратите внимание, что CountVectorizer допускает предварительную обработку, если вы включите такие параметры, как stop_words , чтобы включить стоп-слова, ngram_range , чтобы включить n -граммы, или lowercase lowercase=True , чтобы преобразовать все символы в нижний регистр.
count_vect = CountVectorizer(stop_words=stopwords.words('english'), lowercase=True) x_counts = count_vect.fit_transform(corpus) x_counts.todense() matrix([[0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1]], dtype=int64) Чтобы определить словарь нашего корпуса, мы можем просто использовать атрибут .get_feature_names() :
count_vect.get_feature_names() ['announces', 'australian', 'biden', 'federer', 'joins', 'measures', 'meet', 'missing', 'nadal', 'open', 'plan', 'plans', 'rafael', 'reality', 'roger', 'stands', 'virus']Затем мы выполняем вычисления tf-idf с помощью функции sklearn:
tfidf_transformer = TfidfTransformer() x_tfidf = tfidf_transformer.fit_transform(x_counts)Чтобы выполнить декомпозицию LDA, мы должны определить количество тем. В этом простом случае мы знаем, что есть две темы или «измерения». Но в общих случаях это гиперпараметр, требующий некоторой настройки, которую можно выполнить с помощью таких алгоритмов, как случайный поиск или поиск по сетке:
dimension = 2 lda = LDA(n_components = dimension) lda_array = lda.fit_transform(x_tfidf) lda_array array([[0.8516198 , 0.1483802 ], [0.82359501, 0.17640499], [0.18072751, 0.81927249], [0.1695452 , 0.8304548 ], [0.18072805, 0.81927195]])LDA является вероятностным методом. Здесь мы можем увидеть вероятность того, что каждый из пяти заголовков принадлежит каждой из двух тем. Мы видим, что первые два текста имеют более высокую вероятность принадлежности к первой теме, а следующие три — ко второй теме, как и ожидалось.
Наконец, если мы хотим понять, о чем эти две темы, мы можем увидеть самые важные слова в каждой теме:
components = [lda.components_[i] for i in range(len(lda.components_))] features = count_vect.get_feature_names() important_words = [sorted(features, key = lambda x: components[j][features.index(x)], reverse = True)[:3] for j in range(len(components))] important_words [['open', 'nadal', 'rafael'], ['virus', 'biden', 'measures']]Как и ожидалось, LDA правильно отнесла слова, связанные с теннисными турнирами и Надалем, к первой теме, а слова, связанные с Байденом и вирусом, ко второй теме.
Крупномасштабный анализ и реальные варианты использования
В этой статье можно увидеть крупномасштабный анализ тематического моделирования; Я изучал основные темы новостей во время президентских выборов в США в 2016 году и наблюдал за темами, которые некоторые средства массовой информации, такие как New York Times и Fox News, включали в свое освещение, например, коррупция и иммиграция. В этой статье я также проанализировал корреляции и причинно-следственные связи между содержанием СМИ и результатами выборов.
Тематическое моделирование также широко используется за пределами академических кругов для обнаружения скрытых тематических паттернов, присутствующих в больших коллекциях текстов. Например, его можно использовать в рекомендательных системах или для определения того, о чем говорят клиенты/пользователи в опросах, в формах обратной связи или в социальных сетях.
Блог Toptal Engineering выражает благодарность Хуану Мануэлю Ортису де Сарате за рассмотрение примеров кода, представленных в этой статье.
Рекомендуемая литература по тематическому моделированию
Улучшенное моделирование темы в Twitter
Альбанезе, Федерико и Эстебан Фейерштейн. «Улучшенное моделирование тем в Twitter за счет объединения сообществ». (20 декабря 2021 г.): arXiv: 2201.00690 [cs.IR]
Анализ Twitter для общественного здравоохранения
Пол, Майкл и Марк Дредзе. «Вы то, что вы чирикаете: анализ Twitter для общественного здравоохранения». 3 августа 2021 г.
Классификация политической ориентации в Твиттере
Коэн, Равив и Дерек Рут. «Классификация политической ориентации в Твиттере: это непросто!» 3 августа 2021 г.
Использование реляционных тематических моделей для определения связи
Гетерс, Малкольм и Денис Пошиваник. «Использование реляционных тематических моделей для выявления связи между классами в объектно-ориентированных программных системах». 25 октября 2010 г.
