乐趣区

关于python3.x:推荐系统基于用户的协同过滤算法实现

一. 实现步骤

  1. 创立数据集
  2. 计算用户类似度
  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 的 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)
退出移动版