我正在研究产品推荐。
我的数据集如下(一个示例,完整的数据集包含 110000 个行和 80000个唯一product_id ) :
user_id product_id
0 0E3D17EA-BEEF-493 12909837
1 0FD6955D-484C-4FC8-8C3F 12732936
2 CC2877D0-A15C-4C0A Gklb38
3 b5ad805c-f295-4852 12909841
4 0E3D17EA-BEEF-493 12645715
我想根据每个用户购买的产品计算产品之间的 cosine similarity 。
为什么?我需要得到最终结果:
每个product_id的5种最相似产品的列表。
所以,我认为我要做的第一件事是将数据帧转换为这种格式:
其中每个user_id有一行,而列是product_id。如果用户购买了product_id X,则对应行的列将包含值1,否则为0。
我使用pandas数据框的交叉表功能做到了这一点。
crosstab_df = pd.crosstab(df.user_id, df.product_id).astype('bool').astype('int')
之后,我计算了产品之间的相似度。
def calculate_similarity(data_items):
"""Calculate the column-wise cosine similarity for a sparse
matrix. Return a new dataframe matrix with similarities.
"""
# create a scipy sparse matrix
data_sparse = sparse.csr_matrix(data_items)
#pairwise similarities between all samples in data_sparse.transpose()
similarities = cosine_similarity(data_sparse.transpose())
#put the similarities between products in a dataframe
sim = pd.DataFrame(data=similarities, index= data_items.columns, columns= data_items.columns)
return sim
similarity_matrix = calculate_similarity(crosstab_df)
我知道这样做效率不高,因为在有许多行和许多列的情况下,交叉表的性能不佳,这是我必须处理的情况。因此,我考虑过要使用 scipy稀疏矩阵,而不是使用Crosstab DataFrame,因为它使计算速度更快(相似度计算,向量归一化),因为输入将是一个numpy数组,而不是数据帧
但是,我不知道该怎么做。我还需要跟踪每一列与它对应的product_id,以便随后获得与每个product_id最相似的product_id。
我在其他问题中找到答案:
scipy.sparse.csr_matrix(df.values)
可以使用,但就我而言,我认为,只有在应用交叉表之后才能使用它。而我想摆脱交叉表步骤。
另外,人们建议使用scipy coo_matrix,但对于我想要的结果,我不知道如何在我的情况下应用它。.
我正在寻找一种内存有效的解决方案,因为初始数据集可以增长成千上万行和十万个product_id。