基于协同过滤的推荐算法

1. 基本思想

协同过滤推荐算法是最经典的推荐算法,它的算法思想为物以类聚,人以群分,基本的协同过滤算法基于以下的假设:

  • User-based CF 基于用户的协同过滤推荐:“跟你爱好相似的人喜欢的东西你也可能会喜欢”
  • Item-based CF 基于物品的协同过滤推荐:“跟你喜欢的东西相似的东西你也可能会喜欢”

实现协同过滤的步骤:
1). 找到相似的Top-N个人或者物品:计算两两的相似度并进行排序
2). 根据相似的人或物品产生推荐结果:利用Top-N生成初始推荐结果,然后过滤掉用户已经有过记录或者明确表示不喜欢的物品

那么,如何计算相似度呢?

2. 相似度计算

根据数据类型的不同,相似度的计算方式也不同,数据类型有:

  • 实数型(物品评分情况)
  • 布尔型(用户的行为:是否点击、是否收藏、是否点赞等)

一般的,相似度计算有杰卡德相似度、余弦相似度、皮尔逊相关系数

  • 余弦相似度

    • 度量的是两个向量之间的夹角,用夹角的余弦值来度量相似的情况

    • 余弦相似度与向量长度无关,一般计算时都要对向量长度进行归一化,两个向量只要方向一致,无论程度强弱,都视为“相似”

      n维空间点a()与b()间的余弦相似度(两个n维向量):

  • 皮尔逊相关系数

    • 实际上也是一种余弦相似度,不过先对向量做了中心化,向量a,b各自减去向量的均值后,再计算余弦相似度
    • 度量的是两个变量的变化趋势是否一致,不适合计算布尔值向量之间的相关度
    • 计算结果在[-1,1]之间,-1表示负相关,1表示正相关
      n维空间点a()与b()间的皮尔逊相关系数(两个n维向量):
  • 杰卡德相似度

    • 两个集合的交集元素个数在并集中所占的比例,非常适用于布尔向量表示

余弦相似度和皮尔逊相关系数适合用户评分数据(实数值)
杰卡德相似度适用于隐式反馈数据(0,1 布尔值)

3. 关于用户-物品评分矩阵

在协同过滤推荐算法中,我们更多的是利用用户对物品的评分数据集,预测用户对没有评分过的物品的评分结果。

用户-物品的评分矩阵,根据评分矩阵的稀疏程度会有不同的解决方案。

  • 稠密评分矩阵

    用户/物品 物品A 物品B 物品C 物品D 物品E
    用户1 5 3 4 4 ?
    用户2 3 1 2 3 3
    用户3 4 3 4 3 5
    用户4 3 3 1 5 4
    用户5 1 5 5 2 1
  • 稀疏评分矩阵

    用户/物品 物品A 物品B 物品C 物品D 物品E
    用户1 5 3 4 ? ?
    用户2 ? ? ? 3 3
    用户3 4 3 4 ? 5
    用户4 ? 3 ? 5 ?
    用户5 1 ? 5 ? 1
使用协同过滤推荐算法预测评分-稠密评分矩阵

目的:预测用户1对于物品E的评分

步骤分析:

  • 构架数据集
  • 计算用户两两之间及物品两两之间相似度,对于评分数据这里我们采用皮尔逊相关系数
  • 评分预测:
    • User-based CF:取出与用户1正相关的用户,使用用户间相似度。公式如下,该方案考虑了用户本身的评分及近邻用户的加权评分相似度打分:
    • Item-based CF:取出与物品E正相关的物品,使用物品间相似度。公式如下,该方案结合了预测物品与相似物品的加权评分相似度打分:

实现过程

  1. 构建数据集:注意构建评分矩阵时,对于缺失的部分需要保留为None,如果设置为0那么会被当做评分0
import pandas as pd

users = ["User1", "User2", "User3", "User4", "User5"]
items = ["Item A", "Item B", "Item C", "Item D", "Item E"]
# 用户购买记录数据集
datasets = [
    [5,3,4,4,None],
    [3,1,2,3,3],
    [4,3,4,3,5],
    [3,3,1,5,4],
    [1,5,5,2,1],
]
  1. 计算用户两两之间及物品两两之间相似度,对于评分数据这里我们采用皮尔逊相关系数

pandas中corr方法可直接用于计算皮尔逊相关系数

df = pd.DataFrame(datasets,index=users,columns=items)

print("用户之间的两两相似度:")
# 直接计算皮尔逊相关系数
# 默认是按列进行计算,因此如果计算用户间的相似度,当前需要进行转置
user_similar = df.T.corr()
user_similar.round(4)

print("物品之间的两两相似度:")
item_similar = df.corr()
item_similar.round(4)

用户之间的两两相似度:

- User1 User2 User3 User4 User5
User1 1.0000 0.8528 0.7071 0.0000 -0.7921
User2 0.8528 1.0000 0.4677 0.4900 -0.9001
User3 0.7071 0.4677 1.0000 -0.1612 -0.4666
User4 0.0000 0.4900 -0.1612 1.0000 -0.6415
User5 -0.7921 -0.9001 -0.4666 -0.6415 1.0000

物品之间的两两相似度:

- Item A Item B Item C Item D Item E
Item A 1.0000 -0.4767 -0.1231 0.5322 0.9695
Item B -0.4767 1.0000 0.6455 -0.3101 -0.4781
Item C -0.1231 0.6455 1.0000 -0.7206 -0.4276
Item D 0.5322 -0.3101 -0.7206 1.0000 0.5817
Item E 0.9695 -0.4781 -0.4276 0.5817 1.0000
  1. 评分预测
    基于用户相似度计算 用户1对于商品E的评分
    1).根据user_similar获取用户1相似的两个用户为:User2,User3
    2).User2,User3对商品E的评分分别为3.0和5.0
    3).计算用户1对于商品E的评分:(0.85283.0+0.70715.0)/(0.8528+0.7071)=3.91

    基于物品相似度计算 用户1对于商品E的评分
    1).根据item_similar获取商品E相似的两个商品为商品A和商品D
    2).用户1对于商品A和商品D的评分分别为5和4
    3).计算用户1对于商品E的评分:(0.96955+0.58174)/(0.9695+0.5817)=4.625

对比可见,User-based CF 和 Item-based CF 的结果是有差异的,因为严格意义上他们应该是属于两种不同的推荐算法,各自在不同的领域,会比另一种更佳,但是具体场景下哪种更合适,需要进行合理的评估,因此在实现推荐系统时,这两种算法往往都是需要实现的,然后根据推荐的效果分析选出更优方案。

对于稀疏矩阵,使用基于模型的协同过滤是更高级的算法,如基于图的模型、基于矩阵分解的方法,这个下篇文章再介绍。

你可能感兴趣的:(基于协同过滤的推荐算法)