"Начиная"

Вычисление сходства документов с использованием моделей BERT, word2vec и других

Введение

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

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

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

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

Функция подобия

Вот некоторые из наиболее распространенных и эффективных способов вычисления сходства:

Косинусное расстояние / сходство - это косинус угла между двумя векторами, который дает нам угловое расстояние между векторами. Формула для вычисления косинусного сходства между двумя векторами A и B:

В двухмерном пространстве это будет выглядеть так:

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

Косинус равен 1 при theta = 0 и -1 при theta = 180, это означает, что для двух перекрывающихся векторов косинус будет самым высоким и самым низким для двух противоположных векторов. По этой причине это называется подобием. Вы можете рассматривать 1 - косинус как расстояние.

Евклидово расстояние - это одна из форм расстояния Минковского, когда p = 2. Он определяется следующим образом:

В двухмерном пространстве евклидово расстояние будет выглядеть так:

Расстояние Жаккара - Индекс Жаккара используется для вычисления сходства между двумя конечными наборами. Расстояние Жаккара можно рассматривать как 1 - Индекс Жаккара.

Мы можем использовать косинус или евклидово расстояние, если можем представлять документы в векторном пространстве. Расстояние Жаккара можно использовать, если мы рассматриваем наши документы как наборы или коллекции слов без какого-либо семантического значения.

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

Вложения

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

Ниже приведены некоторые алгоритмы для расчета вложений документов с примерами.

Tf-idf - Tf-idf - это комбинация частоты термина и обратной частоты документа. Он присваивает вес каждому слову в документе, который вычисляется с использованием частоты использования этого слова в документе и частоты документов с этим словом во всем корпусе документов. Более подробно о tf-idf можно прочитать в этой истории.

Давайте определим следующее как корпус (коллекции) документов, для которых мы хотим вычислить сходства,

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

Попарное косинусное сходство было бы просто скалярным произведением векторов tf-idf, потому что векторы tf-idf из sklearn уже нормализованы, а норма L2 этих векторов равна 1. Значит, знаменатель формулы косинусного сходства в этом случае равен 1.

print (tfidf_vectors[0].toarray())
print (pairwise_similarities.shape)
print (pairwise_similarities[0][:])

# documents similar to the first document in the corpus
most_similar(0,pairwise_similarities,'Cosine Similarity')

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

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

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

# tokenize and pad every document to make them of the same size
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
tokenizer=Tokenizer()
tokenizer.fit_on_texts(documents_df.documents_cleaned)
tokenized_documents=tokenizer.texts_to_sequences(documents_df.documents_cleaned)
tokenized_paded_documents=pad_sequences(tokenized_documents,maxlen=64,padding='post')
vocab_size=len(tokenizer.word_index)+1
print (tokenized_paded_documents[0])

Загрузим предварительно обученные вложения. Каждое слово представлено как 300-мерный вектор.

# loading pre-trained embeddings, each word is represented as a 300 dimensional vector
import gensim
W2V_PATH="GoogleNews-vectors-negative300.bin.gz"
model_w2v = gensim.models.KeyedVectors.load_word2vec_format(W2V_PATH, binary=True)

Используя это вложение, мы можем преобразовать каждое слово нашего корпуса документов в 300-мерный вектор. Поскольку у нас есть 6 документов, и мы дополнили каждый документ максимальным размером 64, векторное представление корпуса будет иметь форму 6X64X300.

# creating embedding matrix, every row is a vector representation from the vocabulary indexed by the tokenizer index. 
embedding_matrix=np.zeros((vocab_size,300))
for word,i in tokenizer.word_index.items():
    if word in model_w2v:
        embedding_matrix[i]=model_w2v[word]
# creating document-word embeddings
document_word_embeddings=np.zeros((len(tokenized_paded_documents),64,300))
for i in range(len(tokenized_paded_documents)):
    for j in range(len(tokenized_paded_documents[0])):
        document_word_embeddings[i][j]=embedding_matrix[tokenized_paded_documents[i][j]]
document_word_embeddings.shape

Теперь нам нужно представить каждый документ как единый вектор. Мы можем либо усреднить, либо суммировать по каждому вектору слов и преобразовать каждое представление 64X300 в 300-мерное представление. Но усреднение или суммирование по всем словам потеряло бы семантическое и контекстное значение документов. Различный объем документов также может отрицательно повлиять на такие операции.

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

# calculating average of word vectors of a document weighted by tf-idf
document_embeddings=np.zeros((len(tokenized_paded_documents),300))
words=tfidfvectoriser.get_feature_names()
for i in range(len(document_word_embeddings)):
    for j in range(len(words)):
        document_embeddings[i]+=embedding_matrix[tokenizer.word_index[words[j]]]*tfidf_vectors[i][j]
print (document_embeddings.shape)
pairwise_similarities=cosine_similarity(document_embeddings)
pairwise_differences=euclidean_distances(document_embeddings)
most_similar(0,pairwise_similarities,'Cosine Similarity')
most_similar(0,pairwise_differences,'Euclidean Distance')

GloVe - Global Vectors for word Embedding (GloVe) - это алгоритм обучения без учителя для создания векторных представлений слова. Обучение выполняется на агрегированной глобальной статистике совместной встречаемости слова и слова из корпуса, и полученные в результате представления демонстрируют интересные линейные подструктуры векторного пространства слов.

Мы будем использовать предварительно обученные вложения перчаток от Stanford. Все шаги останутся такими же, как и при встраивании word2vec, просто в этом случае мы будем использовать предварительно обученную модель Glove. Мы используем 100-размерные вложения Glove из-за большого размера файла вложений. Вы также можете использовать более высокие измерения.

Doc2Vec - Doc2vec - это алгоритм обучения без учителя для создания векторных представлений предложения / абзаца / документов. Это адаптация word2vec. Doc2vec может представлять весь документ в вектор. Таким образом, нам не нужно брать среднее значение векторов слов для создания вектора документа.

Мы будем использовать gensim для обучения модели Doc2vec в нашем корпусе и создания векторных представлений документов.

BERT- Двунаправленное представление кодировщика от преобразователей (BERT) - это современная техника предварительного обучения обработке естественного языка, разработанная Google. BERT обучен работе с немаркированным текстом, включая Википедию и Книжный корпус. BERT использует трансформаторную архитектуру, модель внимания для изучения вложения слов.

BERT состоит из двух предварительных этапов обучения моделированию маскированного языка (MLM) и прогнозирования следующего предложения (NSP). В BERT обучающий текст представлен с помощью трех встраиваний: встраивания токенов + встраивание сегментов + встраивание позиций.

Мы будем использовать предварительно обученную модель BERT от Huggingface для встраивания нашего корпуса. Мы загружаем базовую модель BERT, которая имеет 12 слоев (блоков преобразователей), 12 головок внимания, 110 миллионов параметров и скрытый размер 768.

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

Полный код этой истории доступен здесь - https://github.com/varun21290/medium/blob/master/Document%20Similarities/Document_Similarities.ipynb

Ссылки: