【问题标题】:Match most similar string pairs from two lists of strings?从两个字符串列表中匹配最相似的字符串对?
【发布时间】:2023-01-12 02:43:18
【问题描述】:
我有两个字符串列表(大小相等):
l1 = [
"您使用过以下哪些产品",
“为产品提供评级”,
“你会再次购买该产品吗”
]
l2 = [
“请给产品评分”
“你会再次购买该产品吗”
“请选择您使用过的产品”
]
我必须编写一个程序,该程序应该能够匹配类似的句子,如下所示:
这里基本上有两个子问题:
-
如何准确地量化/评分两个句子之间的相似性。我考虑过使用简单的字符匹配算法 (fuzzywuzzy) 来减少程序占用的时间,但是愿意接受任何关于更好算法的建议。
-
如何应用上述算法找到字符串之间的实际匹配
现在,一旦我们在上述步骤中选择了一种算法,我们如何将其应用于两个列表?我认为一种可能的方法是生成所有可能的字符串对组合并选择得分最高的组合,但是如果列表有 10 个或更多项目,这种方法就会失败,因为在我的机器上每次运行所花费的时间超过 10 分钟。
【问题讨论】:
标签:
python
string
list
algorithm
nlp
【解决方案1】:
为什么不使用模糊匹配,而是使用句子相似性作为语义匹配句子(上下文匹配)的标准?
您可以使用已经在维基百科上训练过的手套模型(类似于 word2vec),其中每个单词都表示为 50 维向量。您可以从这里选择除我使用的模型之外的其他模型 - https://github.com/RaRe-Technologies/gensim-data
一旦将每个句子嵌入为向量(在本例中为 50 dim),您可以使用余弦相似度来确定哪个句子嵌入彼此相似,例如使用 scipy.spatial.distance.cosine。
与模糊匹配不同,模糊匹配基本上是编辑距离或编辑距离来匹配字母表级别的字符串,word2vec(以及 fasttext 和 GloVe 等其他模型)表示 n 维欧氏空间中的每个单词。表示每个词的向量称为词向量或词嵌入。
这是一个例子 -
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
然后,您可以选择list 2中最匹配的句子与list 1中的每个句子进行相应的排序。