推荐系统入门笔记三: 基于用户的协同过滤算法实现

一.实现步骤

1. 创建数据集
2. 计算用户相似度,使用jaccard 计算相似度
3. 获取相似用户
4. 获取相似用户相关物品
5. 过滤物品

二.代码实现

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 不能直接计算相似度,只能计算距离,使用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)

26 声望
4 粉丝
0 条评论