微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我需要对另一个数据帧进行子集化皮尔逊相关的数据帧的矢量化操作

如何解决我需要对另一个数据帧进行子集化皮尔逊相关的数据帧的矢量化操作

一个数据帧上进行操作的最佳方法是什么,对于每一行,我需要在另一个数据帧上进行选择?

例如:

我的第一个数据框在每个项目对之间都有相似之处。首先,我将每个相似度假定为零,然后再计算正确的相似度。

import pandas as pd
import numpy as np
import scipy as sp
from scipy.spatial import distance

 

items = [1,2,3,4]
item_item_idx = pd.MultiIndex.from_product([items,items],names = ['from_item','to_item'])
item_item_df = pd.DataFrame({'similarity': np.zeros(len(item_item_idx))},index = item_item_idx
                            )

我的下一个数据框具有每个用户对每个项目给出的评分。为了简化起见,我们假设每个用户对每一项进行评分,并生成1到5之间的随机评分。

users = [1,4,5]

ratings_idx = pd.MultiIndex.from_product([items,users],names = ['item','user'])
rating_df = pd.DataFrame(
    {'rating': np.random.randint(low = 1,high =  6,size = len(users)*len(items))},columns = ['rating'],index = ratings_idx
    )

现在有了等级,我想更新项目之间的余弦相似度。我需要做的是,对于item_item_df中的每一行,从rating_df中选择每个项目的等级向量,然后计算这两个项目之间的余弦距离。

我想知道最简单的方法。这是我到目前为止尝试过的:

====第一次尝试-遍历行

def similarity(ii,iu):
    
    for index,row in ii.iterrows():
        
        v = iu.loc[index[0]]
        u = iu.loc[index[1]]
        
        row['similarity'] = distance.cosine(v,u)
    
    return(ii)


import time

start_time = time.time()
item_item_df = similarity(item_item_df,rating_df)
print('Time: {:f}s'.format(time.time() - start_time))

带我0.01002秒来运行它。如果遇到1万件商品的问题,我估计需要20个小时才能运行。不好。

问题是,我要遍历行,希望是可以将其向量化以使其更快。我玩过df.apply()和df.map()。这是我到目前为止所做的最好的事情:

====第二尝试-index.map()

def similarity_map(idx):
    
    v = rating_df.loc[idx[0]]
    u = rating_df.loc[idx[1]]
    
    return distance.cosine(v,u)

start_time = time.time()
item_item_df['similarity'] = item_item_df.index.map(similarity_map)
print('Time: {:f}s'.format(time.time() - start_time))

请我执行0.034961秒。比遍历行还要慢。

因此,这是天真的向量化尝试。有可能做吗?我还有什么其他选择可以改善运行时间?

感谢您的关注。

解决方法

对于您给出的示例,我将其旋转到一个数组中并继续我的生活。

from sklearn.metrics.pairwise import cosine_similarity

rating_df = rating_df.reset_index().pivot(index='item',columns='user')
cs_df = pd.DataFrame(cosine_similarity(rating_df),index=rating_df.index,columns=rating_df.index)

>>> cs_df
item         1         2         3         4
item                                        
1     1.000000  0.877346  0.660529  0.837611
2     0.877346  1.000000  0.608781  0.852029
3     0.660529  0.608781  1.000000  0.758098
4     0.837611  0.852029  0.758098  1.000000

使用巨大的,高度稀疏的阵列将更加困难。 Sklearn cosine_similarity采用稀疏数组,但是只要您的项目数量合理(因为输出矩阵将是密集的),这应该可以解决。

,

相同但不同。使用numpy数组。小型数组很好,但是如果有1万行,您将拥有一些大型数组。

import numpy as np
data = rating_df.unstack().values     # shape (4,5)
udotv = np.dot(data,data.T)           # shape (4,4)
mag_data = np.linalg.norm(data,axis=1)
mag = mag_data * mag_data[:,None]
cos_sim = 1 - (udotv / mag)
df['sim2'] = cos_sim.flatten()

4k用户和14k物品几乎毁了我可怜的计算机。我将不得不研究sklearn.metrics.pairwise.cosine_similarity如何处理大数据。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。