协同过滤 杰卡德相似度 usercf

import pandas as pd
import numpy as np
from sklearn.metrics import jaccard_score
from sklearn.metrics.pairwise import pairwise_distances

users = ['user1', 'user2', 'user3', 'user4', 'user5']
items = ['Item1', 'Item2', 'Item3', 'Item4', 'Item5']
# datasets = [
#     [1, 0, 1, 1, 0, 0],
#     [1, 0, 0, 1, 1, 0],
#     [1, 0, 1, 0, 0, 1],
#     [0, 1, 0, 1, 1, 0],
#     [1, 1, 1, 0, 1, 1],
#     [1, 0, 1, 0, 0, 0],
# ]
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)
# print(df)
# print(jaccard_score(df['Item1'], df['Item2']))
# 整个矩阵计算杰卡德相似度
user_similar = 1 - pairwise_distances(df.values, metric='jaccard')
# [[1.         0.5        0.66666667 0.2        0.4       ]
#  [0.5        1.         0.25       0.5        0.4       ]
#  [0.66666667 0.25       1.         0.         0.5       ]
#  [0.2        0.5        0.         1.         0.4       ]
#  [0.4        0.4        0.5        0.4        1.        ]]
# 上面算出来的结果是一个二维矩阵,用pd.DataFrame给矩阵加上标题和索引
user_similar = pd.DataFrame(user_similar, columns=users, index=users)
# print(user_similar)
# 加上索引和标题后的效果
#           user1  user2     user3  user4  user5
# user1  1.000000   0.50  0.666667    0.2    0.4
# user2  0.500000   1.00  0.250000    0.5    0.4
# user3  0.666667   0.25  1.000000    0.0    0.5
# user4  0.200000   0.50  0.000000    1.0    0.4
# user5  0.400000   0.40  0.500000    0.4    1.0


# 定义一个字典来存放最相似的用户
topN_users = {}
# 将每一个 用户 都拿来处理
# 返回指定行的数据loc[i] 并且将自己在那一行中删除drop([i])
# 在删除自己后 对 这一行经行排序 sort_values(ascending=False) 由大到小排列
# 排序后对索引进行切片 取出排在最前面的两个 也就是 相似度最高的两个人的 名字!
# 将相似度最高的两个人 存放在topN_users[i]内 【topN_users[i]存放的是每个用户对应的相似度最高的两个用户】比如topN_users['user1']中存放的是['user3', 'user2']
# 也就是说 user1 和【user3和user2像】 但是user3比user2更像user1
for i in user_similar.index:
    _df = user_similar.loc[i].drop([i])
    _df_scorted = _df.sort_values(ascending=False)
    top2 = list(_df_scorted.index[:2])
    topN_users[i] = top2
# print(topN_users)
# 这时候topN_users字典内存放的内容是每个用户对应的最像的两个用户
# {'user1': ['user3', 'user2'], 'user2': ['user1', 'user4'], 'user3': ['user1', 'user5'], 'user4': ['user2', 'user5'], 'user5': ['user3', 'user1']}

# 定义一个推荐字典
# 外层循环topN_users.items()中有两项,一项是 用户的名字 一项是 最相似的两个人
# rs_result = set() 设置推荐项
# 进入二层循环 sim_users中存这 每一个用户 最相似的两个人 所以二层循环在外层循环内 循环二次
# 合并rs_result.union 函数的作用就是合并 取并集
# 拿user1举例 与他最相似的是user3和user2
# user3购买了item1、3 user2购买了item1、4、5 取并集就是 1、3、4、5
# replace()作用是将用户没买过的东西替换为nan dropna()作用是将nan给去除掉 剩下的就是购买过的物品 .index作用是拿到对应的索引
# 这时候rs_result存放的是user2和user3都购买过的物品
# rs_result = rs_result - set(df.loc[user].replace(0, np.nan).dropna().index)
# 将user2和user3都购买过的物品减去user1买过的物品剩下的就是user1没买过的物品 以此循环!
# 经过筛选后得出推荐结果
# 换句话说 协同过滤就是层层筛选
# 先筛选最相似的用户 再筛选相似用户购买过的产品 再在相似用户购买过的产品内去除被推荐用户已经购买过的产品
rs_results = {}
for user, sim_users in topN_users.items():
    rs_result = set()
    for sim_user in sim_users:
        rs_result = rs_result.union(set(df.loc[sim_user].replace(0, np.nan).dropna().index))
        print(rs_result)
    rs_result = rs_result - set(df.loc[user].replace(0, np.nan).dropna().index)
    rs_results[user] = rs_result
print(rs_results)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值