python 使用隐式反馈方法将字典转换为矩阵

python dict to matrix using implict feedback approach

根据我的唯一用户嵌套字典和每位艺术家收听的播放次数,我正在寻求配置最佳模型来测量隐式反馈。我尝试了一些值,但它们看起来只是装饰性的,无法衡量。

示例数据:

    users                                       artist   plays
0   00001411dc427966b17297bf4d69e7e193135d89    korn     12763
1   00001411dc427966b17297bf4d69e7e193135d89    sting    8192
2   00001411dc427966b17297bf4d69e7e193135d89    nirvana  6413

源代码:

user_artist_dict = user_artist_plays.groupby('users').apply(lambda user_artist_plays: dict(zip(user_artist_plays.artist, user_artist_plays.plays))).to_dict()

我想要一个矩阵因式分解 0 在用户没有听艺术家的时候播放,如果他们有的话插入 plays.

我最初的意图是将 DictVectorizer 与 sklearn 一起使用,但它给我带来了 artist 字符串的麻烦。

更新 3 通常的方法是通过 pivot_table 函数。

df.pivot_table(values='plays',index='users',columns='artist',aggfunc='sum',fill_value=0)

或者unstack在那种情况下会更有效

df.set_index(['users','artist']).unstack(fill_value=0)

或者我的疯狂方式

res = pd.get_dummies(df.artist) 
res.loc[:,:]=res.values*df.plays.values.reshape(-1,1)
#make 'users' index 
res.join(df.users).groupby('users').sum()    

输出:

users                                       korn    nirvana sting
00001411dc427966b17297bf4d69e7e193135d89    12763   8192    6413

-

稀疏版。 当前版本的 pandas 对稀疏数据的支持有限,您可以调用 pd.get_dummies(sparse=True) 并且它会 return 一些 SparseDataFrame 但由于大多数操作,它会被转换回DataFrameunstackpivot_table 的稀疏版本仍在 roadmap 中。 所以我们应该使用其他库来解决它,例如 sklearn 有 LabelBinarizerpd.get_dummies 具有相同的功能,但它可以 return scipy.sparse 矩阵。然后在小代数技巧的帮助下我们可以实现目标。


测试数据样本将有助于检查计算的正确性:

df = pd.DataFrame([
             ['a1', 11, 'u1'], ['a3', 23, 'u2'], ['a2', 22, 'u2'],
             ['a3', 33, 'u3'], ['a1', 31, 'u3'], ['a2', 32, 'u3'],
             ['a5', 45, 'u4'], ['a4', 44, 'u4'], ['a3', 43, 'u4'],
             ['a2', 42, 'u4']], columns =['artist', 'plays', 'users'])
print(df.pivot_table(values='plays',index='users',
                     columns='artist',aggfunc='sum',fill_value=0))    

输出

artist  a1  a2  a3  a4  a5
users                     
u1      11   0   0   0   0
u2       0  22  23   0   0
u3      31  32  33   0   0
u4       0  42  43  44  45

结果相同但稀疏

from sklearn.preprocessing import LabelBinarizer
from scipy.sparse import diags
lb_artist = LabelBinarizer(sparse_output=True)
lb_user = LabelBinarizer(sparse_output=True)
X = lb_user.fit_transform(df.users).T*(diags(df.plays)*lb_artist.fit_transform(df.artist))
print(type(X),'shape:',X.shape,'values:',X.nnz,'data:')
print(X)

输出。对于测试样本,它应该是 (user,artist) 10*(user+1)+artist+1

<class 'scipy.sparse.csc.csc_matrix'> shape: (4, 5) values: 10 data:
  (2, 0)    31.0
  (0, 0)    11.0
  (3, 1)    42.0
  (2, 1)    32.0
  (1, 1)    22.0
  (3, 2)    43.0
  (2, 2)    33.0
  (1, 2)    23.0
  (3, 3)    44.0
  (3, 4)    45.0   

lb_userlb_artist 存储键的字符串值,可用于恢复原始帧。

print(
    pd.DataFrame(X.todense(),index=lb_user.classes_,columns=lb_artist.classes_)
    )

输出:

         a1    a2    a3    a4    a5
    u1  11.0   0.0   0.0   0.0   0.0
    u2   0.0  22.0  23.0   0.0   0.0
    u3  31.0  32.0  33.0   0.0   0.0
    u4   0.0  42.0  43.0  44.0  45.0