一. 实现步骤
- 创立数据集
- 计算用户类似度
- 获取类似用户
- 获取类似用户相干物品
- 过滤物品
二. 代码实现
1. 筹备数据
import pandas as pd
users = ['User1', 'User2', 'User3', 'User14', 'User5',]
items = ['ItemA', 'ItemB', 'ItemC', 'ItemD', 'ItemE']
datasets = [[1, 0, 1, 1, 0],
[1, 0, 0, 1, 1],
[1, 0, 1, 0, 0],
[0, 1, 0, 1, 1],
[1, 1, 1, 0, 1],
]
df = pd.DataFrame(datasets, columns=items, index=users)
2. 计算用户类似度
应用 sklearn 的 pairwise_distances 计算用户类似度
# sklearn 不能间接计算类似度, 只能计算间隔, 应用 1 - 间隔 就失去类似度
user_similar = 1 - pairwise_distances(df.values, metric='jaccard')
user_similar = pd.DataFrame(user_similar, columns=users, index=users)
3. 获取类似的用户
topN_users = {}
for i in user_similar.index:
# 获取每个用户对应行, 去除本人对本人的类似度
_df = user_similar.loc[i].drop([i])
# 对获取行进行排序
_df_sorted = _df.sort_values(ascending=False)
# 获取类似度最高类似度的两个用户
top2 = list(_df_sorted.index[:2])
# 将获取到的类似用户放入汇合
topN_users[i] = top2
4. 获取类似用户相干物品并过滤物品
rs_results = {}
# 对类似用户汇合循环
for user, sim_users in topN_users.items():
res_result = set()
# 获取每个用户的汇合
for sim_user in sim_users:
# 获取每个类似用户对应的物品的 index
res_result = res_result.union(set(df.loc[sim_user].replace(0, np.nan).dropna().index))
# 过滤掉举荐用户曾经看过的物品
res_result -= set(df.loc[user].replace(0, np.nan).dropna().index)
rs_results[user] = res_result
后果
{'User1': {'ItemE'},
'User2': {'ItemC', 'ItemB'},
'User3': {'ItemE', 'ItemB', 'ItemD'},
'User14': {'ItemA', 'ItemC'},
'User5': {'ItemD'}}
残缺代码
import pandas as pd
from sklearn.metrics import jaccard_score
from sklearn.metrics.pairwise import pairwise_distances
import numpy as np
users = ['User1', 'User2', 'User3', 'User14', 'User5',]
items = ['ItemA', 'ItemB', 'ItemC', 'ItemD', 'ItemE']
datasets = [[1, 0, 1, 1, 0],
[1, 0, 0, 1, 1],
[1, 0, 1, 0, 0],
[0, 1, 0, 1, 1],
[1, 1, 1, 0, 1],
]
df = pd.DataFrame(datasets, columns=items, index=users)
# score = jaccard_score(df['ItemA'], df['ItemB'])
# print(score)
print(df)
user_similar = 1 - pairwise_distances(df.values, metric='jaccard')
user_similar = pd.DataFrame(user_similar, columns=users, index=users)
topN_users = {}
for i in user_similar.index:
_df = user_similar.loc[i].drop([i])
_df_sorted = _df.sort_values(ascending=False)
top2 = list(_df_sorted.index[:2])
topN_users[i] = top2
# print(topN_users)
rs_results = {}
for user, sim_users in topN_users.items():
res_result = set()
for sim_user in sim_users:
res_result = res_result.union(set(df.loc[sim_user].replace(0, np.nan).dropna().index))
res_result -= set(df.loc[user].replace(0, np.nan).dropna().index)
rs_results[user] = res_result
print(rs_results)