几天前我开始通过做项目来学习Python。 我有两个数据帧,我用我的数据准备了User和Item Dataframes。用户DF拥有17k个不同的用户,而物品DF拥有1,500个专辑。我正在使用协同过滤来获得两个数据帧之间的余弦相似性 如下
from scipy.spatial.distance import cosine
for i in range(0,len(user_normalized.index)-1):
for j in range(0,len(item_matrix.index)-1):
item_matrix_cpy.at[j, 'cosine'] = 1 -cosine(item_matrix_same_shape.iloc[j], user_normalized.iloc[i])
我观察到我的循环逻辑执行速度非常慢并且无法完成运行。我测试了几个用户的逻辑(< 10),观察到余弦计算需要更长的时间来执行(~12s)。但是当我试图为所有用户运行相同的余弦逻辑(即17K)时,查询将永远完成。 你们能帮助我吗?
答案 0 :(得分:1)
您可以使用以{2}作为输入的sklearn.metrics.pairwise.cosine_similarity
。这种方法比分别对每对进行计算更有效。
from sklearn.metrics.pairwise import cosine_similarity
cosine_similarity(
item_matrix_same_shape.values,
user_normalized.values
)
以下是sklearn's implementation第888行:
normalize
函数为每个样本(用户,专辑)计算一次标准。使用您的代码,每张专辑矢量的标准计算为17K次!答案 1 :(得分:0)
让我们对计算余弦相似度做一些快速基准测试,以便我们对其性能有基线了解
timeit.timeit('cosine_similarity(x,y)',setup='from sklearn.metrics.pairwise import cosine_similarity; import numpy as np; x,y = np.random.random(100),np.random.random(100)',number=20000)
4.5380048290098784
timeit.timeit('cosine(x,y)',setup='from scipy.spatial.distance import cosine; import numpy as np; x,y = np.random.random(100),np.random.random(100)',number=20000)
0.6468068649992347
所以似乎scipy's
余弦优于sklearn
,因此我们可能无法从切换实施中获益......继续前进。
如果你想对17k条目的矩阵执行成对余弦相似性,这相当于已经很多的大约17k^2
个评估== 289,000,000
,如果你的向量很高,尤其如此 - 维度。
让我们看看您的输入的thousandth
有多快的余弦相似性,因此289,000
评估。
timeit.timeit('cosine(x,y)',setup='from scipy.spatial.distance import cosine; import numpy as np; x,y = np.random.random(100),np.random.random(100)',number=int((17000**2)/1000))
9.857225538988132
大约需要10秒钟。由于这种情况与病例数呈线性增长...你可以花费10,000秒或者不到3小时来执行大约3亿次余弦相似性操作(在我的情况下,长度为100的向量)。
所以余弦相似度计算只需要花费一定的时间。您的代码可以改进的一种方法是,您可以将余弦相似性存储在新数据帧或新系列中,然后使用索引将其连接到原始数据帧,而不是在循环的每次迭代中添加到数据帧使用at
方法(可能非常慢)。
如果所有这一切都有意义,那么你的计算负荷就足够了,以至于笔记本电脑开始感到虚弱。你接下来要做什么取决于你的用例 - 这需要做一次吗?跑吧忘了吧。
需要偶尔做但不经常吗?使用python的multiprocessing
模块(重要的是不使用multithreading
并行化您的实现(如果您有四个核心,一次使用所有这些核心),它在这种情况下不会起作用)。
需要经常运行吗?您可能需要更多硬件,或者研究云计算解决方案 - 您会对正确管理的云计算设置的价格感到惊讶。