我想对人名进行编码以进行他们之间的相似性比较,这样当用向量表示时,像“Sarah”这样的名字更接近像“Sarah connor”这样的名字,这与 word2vec 所做的非常相似,但它使用句子来训练,但我只有单词列表。使用 Levenshtein 距离和 Jaccard 索引等字符串匹配算法,我可以找到它们之间的相似性,但这不能用于导出满足上述条件的这些单词的向量嵌入,或者它们可以吗?如果没有,有没有办法对这些名称列表进行编码,使得相似名称的条件(基于字符和其他条件)在 n 维空间中更接近,n 是这些嵌入的向量长度。
如何对“名称”进行编码,以便相似的名称由靠近 n 维平面的向量表示?
数据挖掘
Python
nlp
聚类
word2vec
2022-02-27 09:29:30
2个回答
你可以这样做。我提出了最简单的一个,条件是数据数量不是很大。如果您需要更多想法,请发表评论。
在这种情况下,可以使用基于模糊字符串匹配的相似度编码的思想,得到谱嵌入。数据量在这里至关重要,因为您需要对比较以获得谱嵌入的亲和矩阵。按照下面的代码(并从本文中获得一个绝妙的想法)
data = ['sarah connor', 'sara jones', 'jack blabla', 'jackie jones', ' jakob blabla', 'sara conor']
n = len(data)
aff_mat = np.zeros((n,n)) # This is the S matrix in the paper
D = np.zeros((n,n))
for ii in range(n):
for jj in range(n):
name1 = data[ii]
name2 = data[jj]
surname1 = name1.split()[0]
lastname1 = name1.split()[1]
surname2 = name2.split()[0]
lastname2 = name2.split()[1]
aff_name1_name2 = fuzz.ratio(surname1,surname2) + fuzz.ratio(lastname1,lastname2)
# Fuzz ratios are betweein 0 and 100 and we add 2 of them
# so we normalize the whole score to 0 and 1 by dividing by 200
aff_mat[ii,jj] = aff_name1_name2/200
for ii in range(n):
D[ii,ii] = np.sum(aff_mat[:,ii])
L = D - aff_mat # This is Laplacian matrix
有了拉普拉斯矩阵,您只需直接从论文中的代码计算特征向量。这里我选择第二个和第三个特征向量,因为 forst 特征向量是微不足道的。请不要说计算拉普拉斯矩阵的方法有很多种,我们在这里所做的与论文中的不同。因此,尽管首先选择的论文特征向量,我们去掉第一个。有关这方面的更多详细信息,您可以参考文献。
# compute eigenvectors / eigenvalues of L
evals, evcts = eig(L)
# extract "smallest" 2 eigenvectors (ignoring first one)
sortedevals = argsort(evals)
U = evcts[:,sortedevals[1:3]]
现在 U 是您在二维中的嵌入。只需绘制并查看结果:
for (x,y), label in zip(U, data):
plt.text(x, y, label, ha='center', size=10)
plt.xlim((-1,1))
plt.ylim((-1,1))
plt.show()
这是结果:
现在由您决定如何查询相似的名称。主要工作已经完成。
PS:如上所述,我假设您对名字和姓氏的相似性感兴趣。如果您只想为名字使用相同的代码,只需简单地使用变出。
希望它有所帮助。祝你好运!
我没有尝试过,但听起来 sklearnIsomap可能会完成这项工作,并作为使用 Levenshtein/Jaccard/whatever 计算的距离矩阵metric='precomputed'传递。X查看用户指南以了解其他多种学习方法,但Isomap对我来说很适用。
