分组稀疏成对矩阵的结果

时间:2019-06-26 15:49:23

标签: python pandas numpy scikit-learn

我有一个稀疏的成对矩阵(<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检查哪些条目高于阈值的必要性。

1 个答案:

答案 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

从这里开始,您应该可以播放所需的输出。