определить наиболее похожие фразы, используя word2vec - PullRequest
0 голосов
/ 01 мая 2019

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

Идея состоит в том, чтобы определить наиболее похожее предложение для предложения. Я создал средний вектор для слов, составляющих это предложение.

Затем я должен предсказать наиболее похожее предложение, используя встраивание слов.У меня такой вопрос: как я могу определить наилучшее подобное целевое предложение после того, как создал средний вектор исходного предложения?

Вот код:

import gensim
from gensim import utils
import numpy as np
import sys
from sklearn.datasets import fetch_20newsgroups
from nltk import word_tokenize
from nltk import download
from nltk.corpus import stopwords
import matplotlib.pyplot as plt

model = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin.gz', binary=True)


download('punkt') #tokenizer, run once
download('stopwords') #stopwords dictionary, run once
stop_words = stopwords.words('english')

def preprocess(text):
    text = text.lower()
    doc = word_tokenize(text)
    doc = [word for word in doc if word not in stop_words]
    doc = [word for word in doc if word.isalpha()] #restricts string to alphabetic characters only
    return doc
############  doc content  -> num label     -> string label
#note to self: texts[XXXX] -> y[XXXX] = ZZZ -> ng20.target_names[ZZZ]

# Fetch ng20 dataset
ng20 = fetch_20newsgroups(subset='all',
                          remove=('headers', 'footers', 'quotes'))
# text and ground truth labels
texts, y = ng20.data, ng20.target

corpus = [preprocess(text) for text in texts]

def filter_docs(corpus, texts, labels, condition_on_doc):
    """
    Filter corpus, texts and labels given the function condition_on_doc which takes
    a doc.
    The document doc is kept if condition_on_doc(doc) is true.
    """
    number_of_docs = len(corpus)
    print(number_of_docs)

    if texts is not None:
        texts = [text for (text, doc) in zip(texts, corpus)
                 if condition_on_doc(doc)]

    labels = [i for (i, doc) in zip(labels, corpus) if condition_on_doc(doc)]
    corpus = [doc for doc in corpus if condition_on_doc(doc)]

    print("{} docs removed".format(number_of_docs - len(corpus)))

    return (corpus, texts, labels)

corpus, texts, y = filter_docs(corpus, texts, y, lambda doc: (len(doc) != 0))

def document_vector(word2vec_model, doc):
    # remove out-of-vocabulary words
    #print("doc:")
    #print(doc)
    doc = [word for word in doc if word in word2vec_model.vocab]
    return np.mean(word2vec_model[doc], axis=0)

def has_vector_representation(word2vec_model, doc):
    """check if at least one word of the document is in the
    word2vec dictionary"""
    return not all(word not in word2vec_model.vocab for word in doc)

corpus, texts, y = filter_docs(corpus, texts, y, lambda doc: has_vector_representation(model, doc))

x =[]
for doc in corpus: #look up each doc in model

    x.append(document_vector(model, doc))


X = np.array(x) #list to array

model.most_similar(positive=X, topn=1)

1 Ответ

0 голосов
/ 01 мая 2019

Просто используйте косинусное расстояние. Это реализовано в scipy .

Для повышения эффективности вы можете реализовать его самостоятельно и предварительно вычислить нормы векторов в X:

X_norm = np.linalg.norm(X, axis=1).expand_dims(0)

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

def get_most_similar_in_X(Y):
    Y_norm = np.linalg.norm(Y, axis=1).expand_dims(1)
    similarities = np.dot(Y, X.T) / Y_norm / X_norm
    return np.argmax(distances, axis=2)

И вы получаете индексы векторов в X, которые наиболее похожи на векторы в Y.

...