使用 Word2Vec 的文本相似度 1.模糊 vs 词嵌入2.词向量/句子向量之间的相似度3.预训练的 word2vec 模型和其他模型4.示例代码实现

问题描述

我想用 Word2Vec 检查文本的相似性。

我目前正在使用另一种逻辑:

from fuzzywuzzy import fuzz

def sim(name,dataset):
    matches = dataset.apply(lambda row: ((fuzz.ratio(row['Text'],name) ) = 0.5),axis=1)
   return 

名称是我的专栏)。

为了应用此功能,我执行以下操作:

df['Sim']=df.apply(lambda row: sim(row['Text'],df),axis=1)

你能告诉我如何用 Word2Vec 替换 Fuzzy.ratio 以比较数据集中的文本吗?

数据集示例:

Text
Hello,this is Peter,what would you need me to help you with today? 
I need you
Good Morning,John here,are you calling regarding your cell phone bill? 
Hi,this this is John. What can I do for you?
...

一个文本和最后一个文本非常相似,尽管它们用不同的词来表达相似的概念。 我想创建一个新列,用于为每一行放置相似的文本。 我希望你能帮助我。

解决方法

TLDR;跳到代码实现的最后一部分(第 4 部分)

1.模糊 vs 词嵌入

与模糊匹配(基本上是 edit distancelevenshtein distance 在字母表级别匹配字符串)不同,word2vec(以及其他模型,例如 fasttext 和 GloVe)表示 n 维欧几里得空间中的每个单词.表示每个词的向量称为词向量或词嵌入。

这些词嵌入是大量词的 n-dimensional vector 表示。可以将这些向量相加以创建句子嵌入的表示。具有相似语义的词的句子将具有相似的向量,因此它们的句子嵌入也会相似。详细了解 word2vec 如何在内部工作 here

enter image description here

假设我有一个包含 2 个词的句子。 Word2Vec 将这里的每个单词表示为某个欧几里得空间中的向量。总结起来,就像标准向量加法会导致同一空间中的另一个向量。这可能是使用单个词嵌入表示句子的不错选择。

注意: 还有其他组合词嵌入的方法,例如加权总和与 tf-idf 权重,或者直接使用句子嵌入和称为 Doc2Vec 的算法。阅读有关此 here 的更多信息。

2.词向量/句子向量之间的相似度

“你应该知道它所拥有的公司一个词”

与词(上下文)一起出现的词通常在语义/含义上相似。 word2vec 的伟大之处在于,具有相似上下文的单词的单词向量在欧几里得空间中彼此更接近。这让您可以进行聚类或简单的距离计算等操作。

enter image description here

找出 2 个词向量的相似程度的好方法是 cosine-similarity。阅读更多here

3.预训练的 word2vec 模型(和其他模型)

word2vec 和此类模型的绝妙之处在于,在大多数情况下,您无需在数据上训练它们。 您可以使用经过大量数据训练的预训练词嵌入,并根据词与句子中其他词的共现对词之间的上下文/语义相似性进行编码。

您可以使用 cosine_similarity

检查这些句子嵌入之间的相似性

4.示例代码实现

我使用已经在维基百科上训练过的手套模型(类似于 word2vec),其中每个单词都表示为 50 维向量。您可以选择我从这里使用的模型以外的其他模型 - https://github.com/RaRe-Technologies/gensim-data

from scipy import spatial
import gensim.downloader as api

model = api.load("glove-wiki-gigaword-50") #choose from multiple models https://github.com/RaRe-Technologies/gensim-data

s0 = 'Mark zuckerberg owns the facebook company'
s1 = 'Facebook company ceo is mark zuckerberg'
s2 = 'Microsoft is owned by Bill gates'
s3 = 'How to learn japanese'

def preprocess(s):
    return [i.lower() for i in s.split()]

def get_vector(s):
    return np.sum(np.array([model[i] for i in preprocess(s)]),axis=0)


print('s0 vs s1 ->',1 - spatial.distance.cosine(get_vector(s0),get_vector(s1)))
print('s0 vs s2 ->',get_vector(s2)))
print('s0 vs s3 ->',get_vector(s3)))
#Semantic similarity between sentence pairs
s0 vs s1 -> 0.965923011302948
s0 vs s2 -> 0.8659112453460693
s0 vs s3 -> 0.5877998471260071
,

如果要比较句子,则不应使用 Word2Vec 或 GloVe 嵌入。他们将句子中的每个单词翻译成一个向量。从两组这样的向量中得出这些句子的相似程度是相当麻烦的。您应该使用专门将整个句子转换为单个向量的东西。然后你只需要比较两个向量的相似程度。 Universal Sentence Encoder 是考虑到计算成本和准确性权衡的最佳编码器之一(DAN 变体)。请参阅此 post 中的用法示例。我相信它描述了一个与您非常接近的用例。