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
但由于大多数操作,它会被转换回DataFrame
。
unstack
和 pivot_table
的稀疏版本仍在 roadmap 中。
所以我们应该使用其他库来解决它,例如 sklearn 有 LabelBinarizer 与 pd.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_user
和 lb_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
根据我的唯一用户嵌套字典和每位艺术家收听的播放次数,我正在寻求配置最佳模型来测量隐式反馈。我尝试了一些值,但它们看起来只是装饰性的,无法衡量。
示例数据:
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
但由于大多数操作,它会被转换回DataFrame
。
unstack
和 pivot_table
的稀疏版本仍在 roadmap 中。
所以我们应该使用其他库来解决它,例如 sklearn 有 LabelBinarizer 与 pd.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_user
和 lb_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