【发布时间】: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