Cách tính độ tương tự câu bằng mô hình word2vec của gensim với python


125

Theo Gensim Word2Vec , tôi có thể sử dụng mô hình word2vec trong gói gensim để tính toán độ tương tự giữa 2 từ.

ví dụ

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

Tuy nhiên, mô hình word2vec không dự đoán được sự giống nhau của câu. Tôi tìm ra mô hình LSI có độ tương tự câu trong gensim, nhưng, dường như không thể kết hợp với mô hình word2vec. Độ dài của mỗi câu tôi có không dài lắm (ngắn hơn 10 từ). Vì vậy, có cách nào đơn giản để đạt được mục tiêu?


4
Có một hướng dẫn ACL thảo luận về vấn đề này (trong số những thứ khác): youtube.com/watch?v=_ASOqXiWBVo&feature=youtu.be
Emiel

7
Bây giờ bạn có thể sử dụng doc2vec của gensim và nhận được sự tương tự câu từ cùng một mô-đun
kampta

@kampta. Hi bạn sẽ đề nghị bất kỳ bài viết cho thấy việc thực hiện?
Ian_De_Oliveira

1
Thanh toán hiếm
kampta

Câu trả lời:


86

Đây thực sự là một vấn đề khá thách thức mà bạn đang hỏi. Tính toán tương tự câu đòi hỏi phải xây dựng một mô hình ngữ pháp của câu, hiểu các cấu trúc tương đương (ví dụ: "anh ấy đi bộ đến cửa hàng ngày hôm qua" và "ngày hôm qua, anh ấy đi đến cửa hàng"), tìm thấy sự tương đồng không chỉ trong đại từ và động từ mà còn trong danh từ riêng, tìm các mối quan hệ / mối quan hệ thống kê trong rất nhiều ví dụ văn bản thực sự, v.v.

Điều đơn giản nhất bạn có thể thử - mặc dù tôi không biết điều này sẽ hoạt động tốt như thế nào và chắc chắn nó sẽ không mang lại cho bạn kết quả tối ưu - trước tiên là xóa tất cả các từ "dừng" (các từ như "the", "an ", v.v. không thêm nhiều ý nghĩa cho câu) và sau đó chạy word2vec trên các từ trong cả hai câu, tổng hợp các vectơ trong một câu, tổng hợp các vectơ trong câu khác và sau đó tìm sự khác biệt giữa các khoản tiền. Bằng cách tóm tắt chúng thay vì thực hiện một sự khác biệt về từ ngữ, ít nhất bạn sẽ không phải tuân theo trật tự từ. Điều đó đang được nói, điều này sẽ thất bại theo nhiều cách và không phải là một giải pháp tốt bằng mọi cách (mặc dù các giải pháp tốt cho vấn đề này hầu như luôn liên quan đến một số lượng NLP, học máy và sự thông minh khác).

Vì vậy, câu trả lời ngắn gọn là, không, không có cách nào dễ dàng để làm điều này (ít nhất là không làm tốt nó).


4
Tôi nghĩ bạn đúng. Phương pháp đơn giản nhất là tích lũy tất cả các vectơ của các từ trong một câu và tìm sự khác biệt giữa các khoản tiền. Theo cách này, phương pháp đơn giản này có được thực hiện bằng cách đếm từ không? Bởi vì càng nhiều từ trong một câu, biểu đồ sẽ được tóm tắt nhiều hơn.
zhfkt ngày

2
@zhfkt, rất có thể, vâng. Vì vậy, bạn có thể cần phải chia cho số lượng từ hoặc một số từ như vậy để cố gắng đưa ra yếu tố đó. Dù bằng cách nào, bất kỳ heuristic như thế này sẽ bị thiếu sót nghiêm trọng.
Michael Aaron Safyan


75

Vì bạn đang sử dụng gensim, có lẽ bạn nên sử dụng triển khai doc2vec. doc2vec là phần mở rộng của word2vec cho cụm từ-, câu- và cấp độ tài liệu. Đây là một phần mở rộng khá đơn giản, được mô tả ở đây

http://cs.stanford.edu/~quocle/par Đoạn_vector.pdf

Gensim rất hay vì nó trực quan, nhanh và linh hoạt. Điều tuyệt vời là bạn có thể lấy các từ nhúng đã được lọc trước từ trang word2vec chính thức và lớp syn0 của mô hình Doc2Vec của gensim được hiển thị để bạn có thể ghép các từ nhúng với các vectơ chất lượng cao này!

GoogleNews-vectors-neg300.bin.gz (như được liên kết trong Google Code )

Tôi nghĩ rằng gensim chắc chắn là công cụ dễ nhất (và cho đến nay đối với tôi, tốt nhất) để nhúng một câu trong không gian vectơ.

Có tồn tại các kỹ thuật câu-vectơ khác so với kỹ thuật được đề xuất trong bài báo của Le & Mikolov ở trên. Socher và Manning từ Stanford chắc chắn là hai trong số những nhà nghiên cứu nổi tiếng nhất làm việc trong lĩnh vực này. Công việc của họ được dựa trên nguyên tắc cấu tạo - ngữ nghĩa của câu đến từ:

1. semantics of the words

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

Họ đã đề xuất một vài mô hình như vậy (ngày càng phức tạp hơn) về cách sử dụng thành phần để xây dựng các biểu diễn mức câu.

2011 - mở ra bộ mã hóa tự động đệ quy (rất đơn giản. Bắt đầu từ đây nếu quan tâm)

2012 - mạng nơ ron ma trận-vector

2013 - mạng kéo căng thần kinh

2015 - Cây LSTM

giấy tờ của anh ấy đều có sẵn tại socher.org. Một số mô hình này có sẵn, nhưng tôi vẫn khuyên dùng doc2vec của gensim. Đối với một, URAE 2011 không đặc biệt mạnh mẽ. Ngoài ra, nó đi kèm với trọng lượng phù hợp cho dữ liệu tin tức-y diễn giải. Mã anh ấy cung cấp không cho phép bạn đào tạo lại mạng. Bạn cũng không thể trao đổi trong các vectơ từ khác nhau, vì vậy bạn bị mắc kẹt với các phần nhúng pre-word2vec của năm 2011 từ Turian. Các vectơ này chắc chắn không ở cấp độ của word2vec hoặc GloVe.

Chưa làm việc với Tree LSTM, nhưng có vẻ rất hứa hẹn!

tl; dr Vâng, sử dụng doc2vec của gensim. Nhưng các phương pháp khác không tồn tại!


Bạn có thêm thông tin về cách khởi tạo mô hình doc2vec với các giá trị word2vec được đào tạo trước không?
Simon H

42

Nếu bạn đang sử dụng word2vec, bạn cần tính toán vectơ trung bình cho tất cả các từ trong mỗi câu / tài liệu và sử dụng độ tương tự cosine giữa các vectơ:

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

Tính tương tự:

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

4
Bạn có thể vui lòng giải thích thêm về index2word_set và model.index2word không? Cảm ơn bạn.
thavedyboy

3
Lưu ý rằng việc tính toán "vectơ trung bình" là một sự lựa chọn tùy ý cũng như không tính toán nó.
bịt miệng

2
Tôi ngạc nhiên tại sao đây không phải là câu trả lời hàng đầu, nó hoạt động khá tốt và không có vấn đề trình tự mà phương pháp tính trung bình có.
Asim

Đây là câu trả lời tôi đang tìm kiếm. Đã giải quyết vấn đề của tôi. Cảm ơn giải pháp
iRunner

25

bạn có thể sử dụng thuật toán Khoảng cách của Word Mover. đây là một mô tả dễ dàng về WMD .

#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)

Ps: nếu bạn gặp lỗi về nhập thư viện pyemd , bạn có thể cài đặt nó bằng lệnh sau:

pip install pyemd

2
Tôi đã sử dụng WMD trước đó và nó hoạt động khá tốt, tuy nhiên nó sẽ bị nghẹt trên khối lượng lớn. Hãy dùng thử SoftCosineSimilarity. Cũng được tìm thấy trong gensim ( twitter.com/gensim_py/status/963382840934195200 )
krinker

1
WMD không nhanh lắm khi bạn muốn truy vấn một kho văn bản.
Amartya

18

Khi bạn tính tổng của hai bộ vectơ từ, bạn nên lấy cosin giữa các vectơ, không phải là diff. Cosin có thể được tính bằng cách lấy tích của hai vectơ chuẩn hóa. Vì vậy, số lượng từ không phải là một yếu tố.


1
bạn có thể cung cấp một chút mã giả về cách thực hiện việc này không (tôi không sử dụng gensim / python)
dcsan

13

Có một chức năng từ tài liệu lấy một danh sách các từ và so sánh sự giống nhau của chúng.

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

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

12

Tôi muốn cập nhật giải pháp hiện có để giúp những người sẽ tính toán sự giống nhau về ngữ nghĩa của câu.

Bước 1:

Tải mô hình phù hợp bằng gensim và tính toán vectơ từ cho các từ trong câu và lưu trữ chúng dưới dạng danh sách từ

Bước 2: Tính toán vectơ câu

Việc tính toán sự giống nhau về ngữ nghĩa giữa các câu trước đây rất khó khăn nhưng gần đây, một bài báo có tên " MỘT ĐƠN GIẢN NHƯNG TUYỆT VỜI TUYỆT VỜI ĐỂ KIẾM TIỀN " đã được đề xuất cho thấy một cách tiếp cận đơn giản bằng cách tính trung bình các vectơ từ trong câu các hình chiếu của các vectơ trung bình trên thành phần chính đầu tiên của chúng. Trọng số của một từ w là a / (a ​​+ p (w)) với một tham số và p (w) tần số từ (ước tính) được gọi là tần số nghịch đảo trơn tru phương pháp này thực hiện tốt hơn đáng kể.

Một mã đơn giản để tính toán vectơ câu sử dụng SIF (tần số nghịch đảo trơn tru) phương pháp được đề xuất trong bài báo đã được đưa ra ở đây

Bước 3: sử dụng sklearn cosine_similarity tải hai vectơ cho các câu và tính toán độ tương tự.

Đây là phương pháp đơn giản và hiệu quả nhất để tính độ tương tự của câu.


2
giấy rất đẹp. lưu ý: liên kết đến triển khai SIF yêu cầu viết phương thức get_word_frequency () có thể dễ dàng thực hiện bằng cách sử dụng Counter của Python () và trả về một lệnh với các khóa: từ duy nhất w, giá trị: # w / # tổng doc len
Quetzalcoatl

8

Tôi đang sử dụng phương pháp sau đây và nó hoạt động tốt. Trước tiên, bạn cần chạy POSTagger và sau đó lọc câu của bạn để loại bỏ các từ dừng (định thức, liên từ, ...). Tôi khuyên dùng TextBlob APTagger . Sau đó, bạn xây dựng một word2vec bằng cách lấy giá trị trung bình của mỗi vectơ từ trong câu. Các phương pháp n_similarity trong Gemsim word2vec làm chính xác điều đó bằng cách cho phép để vượt qua hai bộ từ để so sánh.


Sự khác biệt giữa lấy trung bình của vectơ so với việc thêm chúng để tạo ra một vectơ câu là gì?
Καrτhικ

1
Sự khác biệt là kích thước vectơ được cố định cho tất cả các câu
lechatpito

Không có sự khác biệt miễn là bạn sử dụng sự tương tự cosine. @lechatpito Không có gì để làm với kích thước vector. Các vectơ được tóm tắt, không được nối.
Chảo

6

Có các phần mở rộng của Word2Vec nhằm giải quyết vấn đề so sánh các đoạn văn bản dài hơn như cụm từ hoặc câu. Một trong số đó là đoạn2vec hoặc doc2vec.

"Các đại diện phân tán của câu và tài liệu" http://cs.stanford.edu/~quocle/par Đoạn_vector.pdf

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


2
Điều đáng nói là ngay sau đó thuật toán được trình bày hoạt động như thế nào. Về cơ bản, bạn thêm một "mã thông báo" duy nhất cho mọi phát ngôn và tính toán các vectơ word2vec. Cuối cùng, bạn sẽ nhận được các vectơ từ cho mỗi từ của bạn trong kho văn bản (với điều kiện bạn yêu cầu tất cả các từ, cũng là những từ duy nhất). Mỗi "mã thông báo" duy nhất trong cách nói sẽ đại diện cho cách nói đó. Có một số tranh cãi về kết quả được trình bày trong bài báo nhưng đó là một câu chuyện khác.
Vladislavs Dovgalecs

5

Gensim thực hiện một mô hình có tên là Doc2Vec để nhúng đoạn văn .

Có các hướng dẫn khác nhau được trình bày dưới dạng sổ ghi chép IPython:

Một phương pháp khác sẽ dựa vào Word2VecWord Mover's distance (WMD) , như trong hướng dẫn này:

Một giải pháp thay thế sẽ là dựa vào các vectơ trung bình:

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)

Cuối cùng, nếu bạn có thể chạy Tensorflow, bạn có thể thử: https://tfhub.dev/google/universal-sentence-encoder/2


4

Tôi đã thử các phương pháp được cung cấp bởi các câu trả lời trước. Nó hoạt động, nhưng nhược điểm chính của nó là các câu càng dài thì độ tương tự sẽ càng lớn (để tính độ tương tự tôi sử dụng điểm cosine của hai từ nhúng trung bình của hai câu bất kỳ) vì càng nhiều từ thì hiệu ứng ngữ nghĩa càng tích cực sẽ được thêm vào câu.

Tôi nghĩ rằng tôi nên thay đổi suy nghĩ của mình và sử dụng câu nhúng thay vì được nghiên cứu trong bài viết nàyđiều này .


3

Nhóm nghiên cứu của Facebook đã phát hành một giải pháp mới có tên InferSent results và mã được công bố trên Github, kiểm tra repo của họ. Nó là khá tuyệt vời. Tôi đang lên kế hoạch sử dụng nó. https://github.com/facebookresearch/InferSent

giấy của họ https://arxiv.org/abs/1705.02364 Tóm tắt: Nhiều hệ thống NLP hiện đại dựa trên các từ nhúng, trước đây được đào tạo một cách không giám sát trên các khối lớn, như các tính năng cơ bản. Tuy nhiên, những nỗ lực để có được các phần nhúng cho các đoạn văn bản lớn hơn, chẳng hạn như câu, đã không thành công như vậy. Một số nỗ lực trong việc học cách trình bày các câu không được giám sát đã không đạt được hiệu suất đủ thỏa đáng để được áp dụng rộng rãi. Trong bài báo này, chúng tôi chỉ ra cách biểu diễn câu phổ quát được đào tạo bằng cách sử dụng dữ liệu được giám sát của bộ dữ liệu Suy luận ngôn ngữ tự nhiên Stanford có thể luôn vượt trội so với các phương pháp không giám sát như vectơ SkipTh think trên một loạt các nhiệm vụ chuyển giao. Giống như cách thị giác máy tính sử dụng ImageNet để có được các tính năng, sau đó có thể được chuyển sang các tác vụ khác, công việc của chúng tôi có xu hướng chỉ ra sự phù hợp của suy luận ngôn ngữ tự nhiên để chuyển việc học sang các nhiệm vụ NLP khác. Bộ mã hóa của chúng tôi là có sẵn công khai.


3

Nếu không sử dụng Word2Vec, chúng tôi có mô hình khác để tìm nó bằng BERT để nhúng. Dưới đây là liên kết tham khảo 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))

Liên kết khác để theo dõi https://github.com/hanxiao/bert-as-service

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.