我有一个稀疏的成对矩阵(<class 'scipy.sparse.csr.csr_matrix'>
),它使用TF-IDF和余弦相似度表示字符串pandas.Series
之间的接近度。如果是密集的,则看起来像是一个更大的版本:
[[0,0,0.3,0,0.8],
[0.1,0,0,0,0.4],
[0,0.9,0.6,0,0],
[1,0.9,0,0,0.8],
[0,0.4,0.3,0,0]]
两个轴都用Series
表示,如下所示:
['Smith, David', 'Davis, Jenny', 'David Smith', 'Jennings, Brian']
我的目标是现在尽可能高效地对相似的字符串(超过阈值的任何字符串,例如0.8)进行分组。结果可能看起来像这样(在任何数据结构中,不一定是哈希,这只是一个示例):
{
'Smith, David': ['Smith, David', 'David Smith'],
'Davis, Jenny': ['Davis, Jenny'],
'Jennings, Brian': ['Jennings, Brian']
}
我目前的方法是使用坐标矩阵<class 'class scipy.sparse.coo_matrix'>
和zip
遍历非零条目:
from sklearn.metrics.pairwise import cosine_similarity
cx = cosine_similarity(tf_idf_matrix, dense_output=False).tocoo()
vals = df['Names']
for row, col, data in zip(cx.row, cx.col, cx.data):
do_something(vals[row], vals[col], data)
这很好用,但是一旦系列赛的参赛人数超过100,000个时,它就相当慢了,我感觉自己丢失了一些东西。有没有更有效的方法?也许可以将轴绑定到数组并按我的阈值(0.8)进行过滤?
我觉得这肯定是一项相当普通的任务,但是谷歌搜索使我无处可做。
更新:
通过从使用sklearn.metrics.pairwise.cosine_similarity
切换到sparse_dot_topn.awesome_cossim_topn
,我能够大大减少开销。
这使我可以在构建矩阵时按阈值对其进行过滤,从而显着减少了要循环的项目数,并限制了使用cx.data检查哪些条目高于阈值的必要性。
答案 0 :(得分:1)
IIUC您正在寻找类似的东西
import pandas as pd
data = [[0,0,0.3,0,0.8],
[0.1,0,0,0,0.4],
[0,0.9,0.6,0,0],
[1,0.9,0,0,0.8],
[0,0.4,0.3,0,0]]
names = ['Smith, David', 'Davis, Jenny', 'David Smith',
'Jennings, Brian', 'Black, John']
df = pd.DataFrame(data, columns=names, index=names)
df = df[df>0.8].unstack()
print(df[df.notnull()].reset_index())
level_0 level_1 0
0 Smith, David Jennings, Brian 1.0
1 Davis, Jenny David Smith 0.9
2 Davis, Jenny Jennings, Brian 0.9
从这里开始,您应该可以播放所需的输出。