使用Word2Vec的文本相似度
我想使用 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 distance或者levenshtein distance在字母级别,word2vec(和其他模型,例如fasttext和手套)表示在n维欧几里得空间的每个单词相匹配的字符串。表示每个词的向量称为词向量或词嵌入。
这些词嵌入是n-dimensional vector大量词表的表示。可以将这些向量相加以创建句子嵌入的表示。具有相似语义的词的句子将具有相似的向量,因此它们的句子嵌入也会相似。在此处阅读有关 word2vec 内部如何工作的更多信息。
假设我有一个包含 2 个词的句子。Word2Vec 将这里的每个单词表示为某个欧几里得空间中的向量。总结起来,就像标准向量加法会导致同一空间中的另一个向量。这可能是使用单个词嵌入表示句子的不错选择。
注意:还有其他组合词嵌入的方法,例如加权总和与 tf-idf 权重,或者直接使用带有称为 Doc2Vec 的算法的句子嵌入。在此处阅读更多相关信息。
2.词向量/句子向量之间的相似性
“你会知道它所拥有的公司一个词”
与词(上下文)一起出现的词通常在语义/含义上相似。word2vec 的伟大之处在于,具有相似上下文的单词的单词向量在欧几里得空间中彼此更接近。这使您可以执行聚类或简单的距离计算等操作。
找出 2 个词向量的相似程度的好方法cosine-similarity。在这里阅读更多。
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 ->', 1 - spatial.distance.cosine(get_vector(s0), get_vector(s2)))
print('s0 vs s3 ->', 1 - spatial.distance.cosine(get_vector(s0), get_vector(s3)))
#Semantic similarity between sentence pairs
s0 vs s1 -> 0.965923011302948
s0 vs s2 -> 0.8659112453460693
s0 vs s3 -> 0.5877998471260071