programing

python으로 gensim의 word2vec 모델을 이용한 문장 유사성 계산 방법

iphone6s 2023. 8. 30. 21:28
반응형

python으로 gensim의 word2vec 모델을 이용한 문장 유사성 계산 방법

Gensim Word2Vec에 따르면, 저는 단어 2vec modeling gensim package를 사용하여 두 단어의 유사성을 계산할 수 있습니다.

예.

trained_model.similarity('woman', 'man') 
0.73723527

그러나 단어2vec 모델은 문장 유사성을 예측하지 못합니다.gensim에서 문장 유사성이 있는 LSI 모델을 찾았지만, word2vec 모델과 결합할 수 없는 것 같습니다.제가 가지고 있는 각 문장의 코퍼스 길이는 그리 길지 않습니다(10단어보다 짧습니다).그렇다면, 목표를 달성할 수 있는 간단한 방법이 있을까요?

이것은 사실 당신이 묻고 있는 꽤 어려운 문제입니다.문장 유사성을 계산하려면 문장의 문법적 모델을 구축하고, 동등한 구조를 이해해야 합니다(예: "그는 어제 가게에 걸어갔다"와 "어제 가게에 걸어갔다"). 대명사와 동사뿐만 아니라 고유 명사에서도 유사성을 찾으며, 많은 통계적 공동 발생/관계를 찾아야 합니다.실제 텍스트 예제 등

여러분이 시도할 수 있는 가장 간단한 방법은 -- 비록 이것이 얼마나 잘 수행될지는 모르겠지만 -- 그리고 이것이 여러분에게 최적의 결과를 제공하지는 않을 것이지만 -- 먼저 모든 "중지" 단어(문장에 큰 의미를 추가하지 않는 "the", "an" 등과 같은 단어)를 제거한 다음, 두 문장의 단어에 대해 2vec를 실행하고, 한 문장의 벡터를 합산하는 것입니다.ce, 다른 문장의 벡터를 합한 다음 합 사이의 차이를 찾습니다.단어별로 차이를 두는 대신 그것들을 합산함으로써, 적어도 단어 순서의 영향을 받지 않을 것입니다.그렇긴 하지만, 이것은 많은 면에서 실패할 것이고 어떤 면에서도 좋은 해결책은 아닙니다(이 문제에 대한 좋은 해결책은 거의 항상 어느 정도의 NLP, 기계 학습 및 기타 영리함을 포함합니다).

그래서, 짧은 대답은, 아니, 이것을 하는 쉬운 방법은 없다는 것입니다(적어도 잘 하지 않는 것).

gensim을 사용하고 있기 때문에 doc2vec 구현을 사용해야 할 것입니다. doc2vec은 단어2vec를 구, 문장, 문서 수준으로 확장한 것입니다.여기에 설명된 꽤 간단한 확장입니다.

http://cs.stanford.edu/ ~quocle/문단_delay.pdf

겐심은 직관적이고 빠르고 유연하기 때문에 좋습니다.좋은 점은 공식 워드2vec 페이지에서 사전 훈련된 단어 임베딩을 가져올 수 있고 gensim의 Doc2Vec 모델의 syn0 레이어가 노출되어 이러한 고품질 벡터로 단어 임베딩을 시드할 수 있다는 것입니다!

Google News-vectors-negative300.bin.gz(Google 코드에서 링크됨)

저는 gensim이 확실히 벡터 공간에 문장을 내장하는 가장 쉬운 (그리고 지금까지 저에게 가장 좋은) 도구라고 생각합니다.

위의 Le & Mikolov의 논문에서 제안된 것 외에 다른 문장 대 벡터 기술이 있습니다.스탠포드의 소허와 매닝은 확실히 이 분야에서 일하는 가장 유명한 연구원들 중 두 명입니다.그들의 작업은 구성의 원칙에 기초했습니다 - 문장의 의미론은 다음과 같습니다.

1. semantics of the words

2. rules for how these words interact and combine into phrases

그들은 문장 수준 표현을 구축하기 위해 구성성을 사용하는 방법에 대해 몇 가지 모델을 제안했습니다(점점 더 복잡해지고 있습니다).

2011년 - 재귀 자동 인코더 전개(매우 비교적 간단합니다. 관심이 있으면 여기서 시작하십시오)

2012년 - 매트릭스 신경망

2013 - 신경 텐서 네트워크

2015 - 트리 LSTM

그의 논문은 모두 socher.org 에서 이용할 수 있습니다.이 모델들 중 일부는 사용할 수 있지만, 저는 여전히 gensim의 doc2vec를 추천합니다.우선 2011년 URAE는 특별히 강력하지 않습니다.또한 news-y 데이터의 패러프레이징에 적합한 가중치를 사전에 학습합니다.그가 제공하는 코드로는 네트워크를 재교육할 수 없습니다.또한 다른 단어 벡터를 바꿀 수 없기 때문에 투리안의 2011년 이전 단어 2vec 임베딩에 얽매입니다.이러한 벡터는 확실히 단어 2vec 또는 GloVe 수준이 아닙니다.

아직 Tree LSTM과 함께 작업하지는 않았지만, 매우 유망해 보입니다!

tl;dr 네, gensim의 doc2vec를 사용하세요.하지만 다른 방법들이 존재합니다!

word2vec를 사용하는 경우 모든 문장/문서의 모든 단어에 대한 평균 벡터를 계산하고 벡터 간 코사인 유사성을 사용해야 합니다.

import numpy as np
from scipy import spatial

index2word_set = set(model.wv.index2word)

def avg_feature_vector(sentence, model, num_features, index2word_set):
    words = sentence.split()
    feature_vec = np.zeros((num_features, ), dtype='float32')
    n_words = 0
    for word in words:
        if word in index2word_set:
            n_words += 1
            feature_vec = np.add(feature_vec, model[word])
    if (n_words > 0):
        feature_vec = np.divide(feature_vec, n_words)
    return feature_vec

유사성 계산:

s1_afv = avg_feature_vector('this is a sentence', model=model, num_features=300, index2word_set=index2word_set)
s2_afv = avg_feature_vector('this is also sentence', model=model, num_features=300, index2word_set=index2word_set)
sim = 1 - spatial.distance.cosine(s1_afv, s2_afv)
print(sim)

> 0.915479828613

워드 무버의 거리 알고리즘을 사용할 수 있습니다.여기 대량살상무기에 대한 쉬운 설명이 있습니다.

#load word2vec model, here GoogleNews is used
model = gensim.models.KeyedVectors.load_word2vec_format('../GoogleNews-vectors-negative300.bin', binary=True)
#two sample sentences 
s1 = 'the first sentence'
s2 = 'the second text'

#calculate distance between two sentences using WMD algorithm
distance = model.wmdistance(s1, s2)

print ('distance = %.3f' % distance)

P.s.: pyemd 라이브러리 가져오기에 대한 오류가 발생할 경우 다음 명령을 사용하여 설치할 수 있습니다.

pip install pyemd

두 단어 벡터 집합의 합을 계산한 후에는 벡터 사이의 코사인을 사용해야 합니다.코사인은 정규화된 두 벡터의 도트 곱을 취하여 계산할 수 있습니다.따라서 단어 카운트는 요인이 아닙니다.

문장의 의미적 유사성을 계산할 사람들을 돕기 위해 기존 솔루션을 업데이트하고 싶습니다.

1단계:

gensim을 사용하여 적합한 모델을 로드하고 문장 내 단어에 대한 단어 벡터를 계산하여 단어 목록으로 저장

2단계: 문장 벡터 계산

이전에는 문장 간 의미론적 유사성 계산이 어려웠지만 최근에는 문장 내 단어 벡터의 가중 평균을 계산한 다음 첫 번째 p에서 평균 벡터의 투영을 제거하여 간단한 접근 방식을 제안하는 "문장 임베딩을 위한 간단하지만 어려운 기준"이라는 논문이 제안되었습니다.주성분여기서 w 단어의 가중치는 a가 매개변수이고 p(w)는 평활 역주파수라고 하는 (추정) 단어 주파수를 갖는 a/(a + p(w))입니다.이 방법이 훨씬 더 잘 수행됩니다.

논문에서 제안된 방법을 SIF(smooth inverse frequency)를 사용하여 문장 벡터를 계산하는 간단한 코드가 여기에 주어졌습니다.

3단계: sklearn cosine_유사성을 사용하여 문장에 대한 두 벡터를 로드하고 유사성을 계산합니다.

이것은 문장 유사성을 계산하는 가장 간단하고 효율적인 방법입니다.

설명서에서 단어 목록을 가져와서 유사성을 비교하는 기능이 있습니다.

s1 = 'This room is dirty'
s2 = 'dirty and disgusting room' #corrected variable name

distance = model.wv.n_similarity(s1.lower().split(), s2.lower().split())

저는 다음과 같은 방법을 사용하고 있으며 잘 작동합니다.먼저 POSTagger를 실행한 다음 문장을 필터링하여 중지 단어(결정자, 접속사 등)를 제거해야 합니다.TextBlob APTagger를 추천합니다.그런 다음 문장에서 각 단어 벡터의 평균을 취하여 단어 2vec를 만듭니다.Gemsim word2vec의 n_유사성 방법은 두 집합의 단어를 비교할 수 있게 함으로써 정확하게 이를 수행합니다.

Word2Vec에는 문구나 문장과 같은 긴 텍스트 조각을 비교하는 문제를 해결하기 위한 확장 기능이 있습니다.그 중 하나가 parter2vec 또는 doc2vec입니다.

"문장 및 문서의 분산 표현" http://cs.stanford.edu/ ~quocle/문단_http.pdf

http://rare-technologies.com/doc2vec-tutorial/

Gensim문단 임베딩을 위해 Doc2Vec라는 모델을 구현합니다.

IPython 노트북으로 제공되는 다양한 튜토리얼이 있습니다.

다른 방법은 이 튜토리얼에 나와 있는 것처럼 Word2VecWMD(Word Mover's Distance)에 의존합니다.

대안 솔루션은 평균 벡터에 의존하는 것입니다.

from gensim.models import KeyedVectors
from gensim.utils import simple_preprocess    

def tidy_sentence(sentence, vocabulary):
    return [word for word in simple_preprocess(sentence) if word in vocabulary]    

def compute_sentence_similarity(sentence_1, sentence_2, model_wv):
    vocabulary = set(model_wv.index2word)    
    tokens_1 = tidy_sentence(sentence_1, vocabulary)    
    tokens_2 = tidy_sentence(sentence_2, vocabulary)    
    return model_wv.n_similarity(tokens_1, tokens_2)

wv = KeyedVectors.load('model.wv', mmap='r')
sim = compute_sentence_similarity('this is a sentence', 'this is also a sentence', wv)
print(sim)

마지막으로, 만약 당신이 Tensorflow를 실행할 수 있다면, 당신은 시도할 수 있습니다: https://tfhub.dev/google/universal-sentence-encoder/2

이전 답변에서 제공한 방법을 사용해 보았습니다.그것은 효과가 있지만, 그것의 주요 단점은 문장이 길수록 더 큰 유사성이 될 것이라는 것입니다(두 문장의 평균 임베딩의 코사인 점수를 사용하는 유사성을 계산하기 위해). 단어가 많을수록 더 긍정적인 의미 효과가 문장에 추가되기 때문입니다.

는 이 논문과 이 에서 공부한 것처럼 생각을 바꾸고 문장 임베딩을 대신 사용해야겠다고 생각했습니다.

Word2Vec를 사용하지 않는 경우 임베드에 BERT를 사용하여 찾을 수 있는 다른 모델이 있습니다.아래는 참조 링크 https://github.com/UKPLab/sentence-transformers 입니다.

pip install -U sentence-transformers

from sentence_transformers import SentenceTransformer
import scipy.spatial

embedder = SentenceTransformer('bert-base-nli-mean-tokens')

# Corpus with example sentences
corpus = ['A man is eating a food.',
          'A man is eating a piece of bread.',
          'The girl is carrying a baby.',
          'A man is riding a horse.',
          'A woman is playing violin.',
          'Two men pushed carts through the woods.',
          'A man is riding a white horse on an enclosed ground.',
          'A monkey is playing drums.',
          'A cheetah is running behind its prey.'
          ]
corpus_embeddings = embedder.encode(corpus)

# Query sentences:
queries = ['A man is eating pasta.', 'Someone in a gorilla costume is playing a set of drums.', 'A cheetah chases prey on across a field.']
query_embeddings = embedder.encode(queries)

# Find the closest 5 sentences of the corpus for each query sentence based on cosine similarity
closest_n = 5
for query, query_embedding in zip(queries, query_embeddings):
    distances = scipy.spatial.distance.cdist([query_embedding], corpus_embeddings, "cosine")[0]

    results = zip(range(len(distances)), distances)
    results = sorted(results, key=lambda x: x[1])

    print("\n\n======================\n\n")
    print("Query:", query)
    print("\nTop 5 most similar sentences in corpus:")

    for idx, distance in results[0:closest_n]:
        print(corpus[idx].strip(), "(Score: %.4f)" % (1-distance))

https://github.com/hanxiao/bert-as-service 에 연결된 기타 링크

Facebook Research 그룹은 InferSent Results라는 새로운 솔루션을 출시했고 코드는 Github에 게시됩니다. 그들의 보고서를 확인하세요.그것은 꽤 멋집니다.저는 그것을 사용할 계획입니다.https://github.com/facebookresearch/InferSent

그들의 논문 https://arxiv.org/abs/1705.02364 추상화:많은 현대 NLP 시스템은 이전에 대규모 말뭉치에서 감독되지 않은 방식으로 훈련된 단어 임베딩에 기본 기능으로 의존합니다.그러나 문장과 같은 텍스트의 더 큰 덩어리에 대한 임베딩을 얻기 위한 노력은 그다지 성공적이지 않았습니다.문장의 감독되지 않은 표현을 학습하려는 여러 시도는 널리 채택되기에 충분히 만족스러운 성능에 도달하지 못했습니다.본 논문에서는 스탠포드 자연어 추론 데이터 세트의 감독 데이터를 사용하여 훈련된 보편적인 문장 표현이 광범위한 전송 작업에서 SkipThought 벡터와 같은 감독되지 않은 방법을 지속적으로 능가할 수 있는 방법을 보여줍니다.컴퓨터 비전이 ImageNet을 사용하여 기능을 획득한 다음 다른 작업으로 전송할 수 있는 방법과 마찬가지로, 우리의 연구는 학습을 다른 NLP 작업으로 전송하기 위한 자연어 추론의 적합성을 나타내는 경향이 있습니다.우리 인코더는 공개적으로 사용할 수 있습니다.

한 문장의 단어 벡터를 함께 추가하면 됩니다.그런 다음 두 문장 벡터의 코사인 유사도를 두 문장의 유사도로 계산합니다.그게 가장 쉬운 방법인 것 같아요.

언급URL : https://stackoverflow.com/questions/22129943/how-to-calculate-the-sentence-similarity-using-word2vec-model-of-gensim-with-pyt

반응형