协同过滤算法之通过Jaccard相似度计算推荐结果原理及代码实现

Jaccard相似度介绍

  • 两个集合的交集元素个数在并集中所占的比例, 非常适用于布尔向量表示
  • 分子是两个布尔向量做点积计算, 得到的就是交集元素的个数
  • 分母是两个布尔向量做或运算, 再求元素和
  • 杰卡德相似度适用于隐式反馈数据(0,1布尔值),主要应用于是否收藏,是否点击,是否加购物车。

简单地来说就是交集/并集
J(A,B)=|A∩B|/|A∪B|

Jaccard相似度计算推荐结果代码及实现

基本介绍

  • 我们通过简单的一个DataFrame例子来实现其算法,最终输出结果。通常有两种协同过滤:基于用户的协同过滤推荐(User-based CF)、基于物品的协同过滤推荐(Item-based CF)。这里我们会构建一个用户+物品的DataFrame。

  • 这里为了方便,可以使用jupyternotebook进行书写

import numpy as np
import pandas as pd

users = ["Thomas", "Cauchy", "Alice", "Bob", "Alex"]
items = ["iPad", "MacBook", "iPhone", "iWatch", "AirPods"]
#用户购买记录数据集
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(df.index)
print(df.columns)

在这里插入图片描述

Jaccard相似度计算代码

#导入杰卡德相似度
from sklearn.metrics import jaccard_score
#计算iPad和MacBook的相似度
jaccard_score(df['iPad'],df['MacBook'])
#结果
0.2
#计算所有的数据两两的杰卡德相似系数
from sklearn.metrics.pairwise import pairwise_distances
#计算所有的数据两两的杰卡德相似系数(1-jaccard距离就是相似度)
user_similar = 1-pairwise_distances(df.values,metric='jaccard')
user_similar = pd.DataFrame(user_similar,columns=users,index = users)
#用户相似度
user_similar

在这里插入图片描述

#以相同的思路我们来试着做一下物品的相似度(记住物品需要先进行转置才可以计算)
item_similar = 1-pairwise_distances(df.T.values,metric='jaccard')
item_similar = pd.DataFrame(item_similar,columns=items,index = items)
item_similar

在这里插入图片描述

协同过滤推荐代码实现

  • 通过计算杰卡德相似度,已经得出了用户相似度,接下来我们就需要进行协同过滤推荐了。
  • 实现协同过滤推荐有2个步骤:
  1. 找出最相似的人或物品:TOP-N相似的人或物品
#为每一个用户找到最相似的2个用户

#创建空的dict保存最终结果
topN_users = {}
#遍历每一行数据
for i in user_similar.index:
    #取出每一列数据, 删除自己,按照相似度排序(降序)
    _df = user_similar.loc[i].drop([i])
    _df_sorted = _df.sort_values(ascending = False)
    #排序之后切片取出前两个值,传入空dict
    top2 = list(_df_sorted.index[:2])
    topN_users[i] = top2

在这里插入图片描述

  1. 根据相似的人或物品产生推荐结果
#根据topn的相似用户构建推荐结果
rs_results={}
for user,sim_users in topN_users.items():
    rs_result = set() #为每一用户保存推荐结果
    for sim_user in sim_users:
        #将0替换为控制,去掉空值,做union联合
        rs_result = rs_result.union(set(df.loc[sim_user].replace(0,np.nan).dropna().index))
        
    #过滤掉已经购买的商品(得到的结果需要减去user已经购买过的)
    rs_result -= set(df.loc[user].replace(0,np.nan).dropna().index)
    #将结果传入到dict中
    rs_results[user] = rs_result

在这里插入图片描述

  • 6
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值