Изучайте Семантические Связи в Корпусе с Моделями Векторного Вложения

Разберем семантические связи в корпусе с помощью моделей векторного вложения

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

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

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

Фиксация отношений между понятиями с помощью эмбеддингов слов

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

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

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

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

Обучение модели

Теперь давайте начнем с модели эмбеддингов слов. Вам может быть знакома модель Word2Vec, которая популяризировала использование статических эмбеддингов слов в исследованиях и практике. С другой стороны, GloVe, разработанный командой из Стэнфордского университета, кажется более эффективным методом в большинстве случаев, и мой личный опыт свидетельствует о том, что он даёт эмбеддинги высокого качества, особенно на меньших корпусах. К сожалению, GloVe не реализован в Gensim, но, к счастью, я создал полностью совместимый с Gensim интерфейс для оригинального кода GloVe, и мы собираемся использовать его для обучения модели.

Давайте установим gensim, glovpy, scikit-learn, чтобы мы могли получить 20Newsgroups, а также embedding-explorer:

pip install glovpy gensim scikit-learn

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

from gensim.utils import tokenizefrom sklearn.datasets import fetch_20newsgroupsfrom sklearn.feature_extraction.text import ENGLISH_STOP_WORDSdef clean_tokenize(text: str) -> list[str]:    """This function tokenizes texts and removes stop words from them"""    tokens = tokenize(text, lower=True, deacc=True)    tokens = [token for token in tokens if token not in ENGLISH_STOP_WORDS]    return tokens# Загрузка набора данныхdataset = fetch_20newsgroups(    remove=("headers", "footers", "quotes"), categories=["sci.med"])newsgroups = dataset.data# Токенизация набора данныхtokenized_corpus = [clean_tokenize(text) for text in newsgroups]

После этого мы можем легко обучить модель GloVe на токенизированном корпусе.

from glovpy import GloVe# Обучение эмбеддингов словmodel = GloVe(vector_size=25)model.train(tokenized_corpus)

Уже можно запрашивать данную модель эмбеддинга слов, давайте, например, проверим, какие десять слов наиболее близки к “child”.

model.wv.most_similar("child")==============================+------------+----------+| возраст    | 0.849304 || последовательный | 0.844267 || взрослый  | 0.805101 || диапазон  | 0.800615 || год       | 0.798799 || рука      | 0.792965 || дети      | 0.792113 || использовать | 0.789804 || помеха    | 0.773764 || ремень    | 0.77003  |+------------+----------

Исследуй, Визуализируй!

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

К счастью, здесь нам может помочь пакет «embedding-explorer», который я разработал. Работая в области компьютерных гуманитарных наук, мы часто используем модели вложенных слов и семантические сети, построенные на основе этих моделей, и embedding-explorer помогает нам исследовать их в интерактивном и визуальном режиме. В пакете содержатся несколько интерактивных веб-приложений, сначала мы рассмотрим «network explorer».

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

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

Давайте запустим приложение на нашей модели вложения слов.

from embedding_explorer import show_network_explorervocabulary = model.wv.index_to_keyembeddings = model.wv.vectorsshow_network_explorer(vocabulary, embeddings=embeddings)

Это откроет окно браузера, где вы можете свободно исследовать семантические связи в корпусе. Вот снимок экрана, где я исследую связи вокруг слов «Иисус», «наука» и «религия».

Исследование семантических связей в нашей модели GloVe

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

Сети из N-грамм с использованием Sentence Transformers

А что, если мы хотим рассмотреть не только связи на уровне слов, но и фраз или предложений?

Мое предложение – использовать N-граммы. N-граммы в основном являются последовательными наборами из N терминов в тексте. Например, в предложении «Я люблю свою маленькую милую собаку» у нас есть 4-граммы: «Я люблю свою маленькую», «люблю свою маленькую милую» и «свою маленькую милую собаку». Теперь вопрос: как мы можем научиться создавать хорошие семантические представления N-грамм?

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

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

Решение этой проблемы заключается в использовании sentence transformers, глубоких нейронных языковых моделей, которые производят контекстно чувствительные представления текста. Они превосходят все другие подходы уже несколько лет и стали стандартом промышленности для вложения текста. Обучение такой модели требует большого объема данных, которых у нас нет, но, к счастью, мы можем использовать несколько хороших предобученных моделей.

Извлечение N-грамм

Давайте сначала извлечем N-граммы из нашего корпуса. Я выбрал четыре граммы, но вы можете выбрать любое количество. Мы будем использовать CountVectorizer из scikit-learn для этого.

from sklearn.feature_extraction.text import CountVectorizer# Сначала мы обучаем модель на корпусе, которая изучает все 4-граммы# На данный момент мы учитываем только 4000 самых частых,# Но вы можете свободно экспериментировать с этимfeature_extractor = CountVectorizer(ngram_range=(4,4), max_features=4000)feature_extractor.fit(newsgroups)# Затем мы получаем словарь векторизатораfour_grams = feature_extractor.get_feature_names_out()

Модель эмбеддинга

Нам понадобится модель эмбеддинга для представления текста. Как я уже сказал ранее, мы собираемся использовать предварительно обученную модель. Я выбрал all-MiniLM-L6-v2, так как она очень стабильна, широко используется и достаточно компактна, чтобы работать даже на вашем персональном компьютере.

Мы будем использовать еще один пакет, embetter, чтобы мы могли использовать sentence transformers совместимым образом с scikit-learn.

pip install embetter[text]

Мы можем загрузить модель в Python следующим образом:

from embetter.text import SentenceEncoderencoder = SentenceEncoder("all-MiniLM-L6-v2")

Исследование!

Мы можем загрузить модель и n-граммы в embedding-explorer.

from embedding_explorer import show_network_explorershow_network_explorer(four_grams, vectorizer=encoder)

Обратите внимание, что это позволяет нам указывать любое произвольное значение, а не только те, которые есть в нашем словаре 4-грамм. Вот скриншот, на котором я ввожу два предложения и вижу, какие сети строятся на основе 4-грамм вокруг них.

Исследование фраз и предложений в корпусе

Интересно наблюдать, какие фразы находятся в середине. Похоже, право и история служат своеобразной связью между религией и наукой.

Исследование семантической структуры корпуса на уровне документов с помощью эмбеддингов

Мы уже рассмотрели наш корпус на уровне слов и фраз и увидели семантические структуры, которые возникают в них. Что, если мы хотим получить информацию о том, что происходит на уровне документов? Какие документы находятся близко друг к другу, и какие группы появляются?

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

Представления документов

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

Более традиционная практика машинного обучения обычно использует представления Bag-of-Words или обучает модель Doc2Vec. Все это хорошие варианты (и вы можете и должны с ними экспериментировать), но они, в свою очередь, лишены контекстного понимания текста. Поскольку тексты в нашем корпусе не очень длинные, мы все еще можем использовать sentence transformers для их эмбеддинга. Давайте продолжим с той же моделью эмбеддинга, которую мы использовали для фраз.

Проектирование и кластеризация

Естественным способом исследования семантических представлений документов является их проекция в пространство меньшей размерности (обычно 2D) и использование этих проекций для визуализации документов. Мы также можем посмотреть, как документы кластеризуются при использовании некоторого подхода к кластеризации.

Теперь все это замечательно, но пространство проекции, снижение размерности и подходы к кластеризации настолько обширны, что я постоянно задавал себе вопрос: “Будет ли это выглядеть существенно иначе, если бы я использовал что-то другое?” Чтобы противостоять этой проблеме, я добавил еще одно приложение к embedding-explorer, в котором вы можете свободно и быстро исследовать, какие виды визуализации могут быть получены с использованием различных методов.

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

Кластеризация и проекция рабочего процесса в embedding-explorer

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

Создадим таблицу с колонками, которые содержат:1. Первые 400 символов каждого документа, чтобы мы могли понять, о чем текст.2. Длина текста, чтобы мы могли увидеть, какие тексты длинные, а какие короткие визуализациях.3. Группа, из которой они происходят в нашем наборе данных.

import pandas as pdimport numpy as np# Извлечение длин текстов в количестве символов.lengths = [len(text) for text in corpus]# Извлечение первых 400 символов каждого текста.text_starts = [text[:400] for text in corpus]# Извлечение группы, к которой принадлежит каждый текст# Sklearn возвращает метки как целые числа, нам нужно сопоставить их с# фактическим текстовым обозначением.group_labels = np.array(dataset.target_names)[dataset.target]# Создаем фрейм данных с доступными метаданнымиmetadata = pd.DataFrame(dict(length=lengths, text=text_starts, group=group_labels))

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

from embedding_explorer import show_clusteringshow_clustering(  newsgroups,  vectorizer=encoder,  metadata=metadata,  hover_name="group", # Заголовок всплывающего окна будет группа  hover_data=["text", "length"] # Мы также хотим видеть это при наведении)

Когда приложение запустится, вам будет представлен экран:

Параметры в приложении кластеризации

После выполнения кластеризации вы сможете посмотреть карту всех документов, окрашенных по кластерам. Вы можете навести на точки, чтобы увидеть метаданные о документе…

Снимок экрана приложения кластеризации

и внизу вы даже можете выбрать, как точки должны быть окрашены, помечены и изменены по размеру.

Кластеры с размерами документов

Резюме

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

Мир ✌️

((все изображения в статье были взяты из документации embedding-explorer’a, которую создал автор))