【问题标题】:Using csr_matrix of items similarities to get most similar items to item X without having to transform csr_matrix to dense matrix使用项目相似性的 csr_matrix 来获得与项目 X 最相似的项目,而无需将 csr_matrix 转换为密集矩阵
【发布时间】:2019-02-18 08:55:49
【问题描述】:

我有购买数据 (df_temp)。我设法将使用 Pandas Dataframe 替换为使用稀疏 csr_matrix,因为我有很多产品 (89000),我必须获取他们的用户项目信息(购买或未购买),然后计算产品之间的相似性。

首先,我将 Pandas DataFrame 转换为 Numpy 数组:

 df_user_product = df_temp[['user_id','product_id']].copy()
 ar1 = np.array(df_user_product.to_records(index=False))

其次,创建了一个coo_matrix,因为它以在稀疏矩阵构造中速度快而闻名。

 rows, r_pos = np.unique(ar1['product_id'], return_inverse=True)
 cols, c_pos = np.unique(ar1['user_id'], return_inverse=True)
 s = sparse.coo_matrix((np.ones(r_pos.shape,int), (r_pos, c_pos)))

第三,对于矩阵计算,最好使用 csr_matrix 或 csc_matrix,所以我使用了 csr_matrix,因为我在 rows 中有 product_id(s) => 比 csc_matrix 更有效的行切片。

    sparse_csr_mat = s.tocsr()
    sparse_csr_mat[sparse_csr_mat > 1] = 1

然后,我计算了产品之间的cosine similarity,并将结果放入相似度

import sklearn.preprocessing as pp
col_normed_mat = pp.normalize(sparse_csr_mat, axis=1)
similarities = col_normed_mat * col_normed_mat.T

这是:

<89447x89447 sparse matrix of type '<type 'numpy.float64'>'
    with 1332945 stored elements in Compressed Sparse Row format>

现在,我想在最后有一个字典,其中每个产品都有 5 个最相似的产品。怎么做?由于内存使用限制,我不想将稀疏矩阵转换为密集数组。但我也不知道是否有一种方法可以访问 csr_matrix,就像我们对数组所做的那样,我们检查例如 index=product_id 并获取 index=product_id 的所有行,这样我将获得所有类似的产品product_id 并按余弦相似度值排序,得到最相似的 5 个。

例如相似度矩阵中的一行:

(product_id1, product_id2) 0.45

如何仅过滤与 product_id1 最相似的 X(在我的情况下为 5)产品,而无需将矩阵转换为数组?

查看Stackoverflow,我认为 lil_matrix 可以用于这种情况?怎么样?

感谢您的帮助!

【问题讨论】:

  • 一个小问题,sparse.csr_matrix(...) 采用与coo_matrix 相同的输入。 coo 格式实际上是一种原始数据格式,几乎所有计算都转换为csr 格式。这种转换通常是自动的。但要执行索引等操作,您确实需要csr 格式。
  • 如果你演示了你想用一个小的密集数组做什么,这可能会有所帮助。
  • 您可以使用M = ...tolil() 并查看M.rows。这将是列索引列表的数组。或者获取转置的lil,以获取行索引列表。
  • 关于获取每行稀疏矩阵的前 N ​​个值的问题,例如stackoverflow.com/questions/49207275/…。同样的事情应用于csc 可以获得每列的最高值。
  • @hpaulj 我不明白你在计算时将coo_matrix 自动转换为csr_matrix 是什么意思。在文档中提到 coo_matrix 在计算和更好地使用 csr 时效率不高。

标签: python scipy sparse-matrix cosine-similarity


【解决方案1】:

我终于明白了如何获得与每个产品最相似的 5 个项目,这是通过使用 .tolil() 矩阵,然后将每一行转换为一个 numpy 数组并使用 argsort 获得 5 个最相似的项目。我使用了link 中建议的@hpaulj 解决方案。

def max_n(row_data, row_indices, n):
        i = row_data.argsort()[-n:]
        # i = row_data.argpartition(-n)[-n:]
        top_values = row_data[i]
        top_indices = row_indices[i]  # do the sparse indices matter?

        return top_values, top_indices, i

然后我将它应用到一行进行测试:

top_v, top_ind, ind = max_n(np.array(arr_ll.data[0]),np.array(arr_ll.rows[0]),5)

我需要的是top_indices,这是 5 个最相似产品的索引,但这些索引不是真正的product_id。我在构建coo_matrix 时映射了它们

rows, r_pos = np.unique(ar1['product_id'], return_inverse=True)

但是如何从索引中获取真正的product_id

现在例如我有:

top_ind = [2 1 34 9 123]

如何知道2对应什么product_id1对应什么等?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-12
    • 1970-01-01
    • 2019-02-10
    • 1970-01-01
    相关资源
    最近更新 更多