《推荐系统笔记(十三)》购物篮分析 —— 基于关联规则的topN推荐

购物篮分析最初出现于大型零售商,他们通过分析大量的发票数据,分析出购买特定商品的消费者更可能还购买哪种商品。

Transactions数据集

每一个这样的数据,其实就是一个消费者一次购买的商品清单,我们将这样的一个数据称为transaction。这样,训练的数据大概是这样的,

IDtransaction
0牛奶、面包、尿布
1可乐、面包、尿布、啤酒
2牛奶、尿布、啤酒、鸡蛋
3面包、牛奶、尿布、啤酒
4面包、牛奶、尿布、可乐

Apriori算法

下面,我们将以上面的这个数据为例,用apriori算法做关联分析,说明apriori算法的过程。

算法过程是这样的:基于支持度求频繁项集 → \rightarrow 基于可信度求关联规则

1. 频繁项集
  • 我们假设支持度和可信度均为0.5,则5条transaction下,个数必须达到 transaction个数支持度=50.5=2.5 个以上,才能进入频繁项集
  • 首先求频繁1项集,观察到,牛奶出现4次>2.5次,入选;面包出现4次>2.5次,入选;尿布出现5次>2.5次,入选;啤酒出现3次>2.5次,入选;可乐出现2次<2.5次,不入选;鸡蛋出现1次<2.5次,不入选。综上,我们有频繁1项集如下
1项集出现次数
牛奶4
面包4
尿布5
啤酒3
  • 其次求频繁2项集,对频繁1项集的商品进行组合,比如{牛奶、面包},检查这种组合在原来数据中出现次数是否大于2.5次。详细的,我们有,{牛奶、面包}出现3次>2.5次,入选;{牛奶、尿布}出现4次>2.5次,入选;{牛奶、啤酒}出现2次<2.5次,不入选;{面包、尿布}出现4次>2.5次,入选;{面包、啤酒}出现2次<2.5次,不入选;{尿布、啤酒}出现3次>2.5次,入选。综上,频繁2项集为
2项集出现次数
{牛奶、面包}3
{牛奶、尿布}4
{面包、尿布}4
{尿布、啤酒}3
  • 然后求频繁3项集,对频繁2项集的元素进行组合,有,{牛奶、面包、尿布}在transaction数据中出现3次>2.5次,入选;{牛奶、尿布、啤酒}出现2次<2.5次,不入选;{面包、尿布、啤酒}出现2次<2.5次,不入选。综上,频繁3项集为
3项集出现次数
{牛奶、面包、尿布}3

我们不用考虑频繁4项集了,因为频繁3项集中只有一个元素,没法做组合产生4项集元素。

2. 关联规则

然后,我们根据频繁项集,求出关联规则。

  • 首先看频繁3项集,里面只有{牛奶、面包、尿布},这样我们就分别看 牛奶 → \rightarrow {面包、尿布},计算 { 牛 奶 、 面 包 、 尿 布 } { 牛 奶 } = 3 4 > 0.5 = 可 信 度 \frac{\{牛奶、面包、尿布\}}{\{牛奶\}}=\frac{3}{4}>0.5=可信度 {}{尿}=43>0.5=,则将 牛奶 → \rightarrow {面包、尿布} 这条规则纳入关联规则中,意思就是,当有人买牛奶时,可以推荐给这人面包和尿布;再看其他的组合,如 面包 → \rightarrow {牛奶、尿布}、{尿布、牛奶} → \rightarrow 面包 等等。
  • 然后再看频繁2项集,举个例子,从2频繁集{牛奶、面包}中,能提取出规则 牛奶 → \rightarrow 面包 和 面包 → \rightarrow 牛奶,接下来需要验证这两条规则是否能满足可信度要求。对于牛奶 → \rightarrow 面包 而言,计算 { 牛 奶 、 面 包 } { 牛 奶 } = 3 4 > 0.5 = 可 信 度 \frac{\{牛奶、面包\}}{\{牛奶\}}=\frac{3}{4}>0.5=可信度 {}{}=43>0.5=,因此可以纳入关联规则。

简单实战

这里,我们用movielens的ratings数据集,采用Apriori算法,做出topN推荐。

movielens数据集已经上传,各位可以免费下载。

我们的想法是这样的,

  • 对于每一个用户,把他看过的电影作为一个transaction
  • 对这样的transaction数据集进行关联分析
  • 根据生成的关联规则,通过对用户看过的电影进行关联,得到推荐的电影
# 第三方库
import pandas as pd
import numpy as np
from efficient_apriori import apriori
# 载入数据
data = pd.read_csv(r'D:\myfile\开课吧\推荐系统\第三节\movielens\ratings.csv')
data.head()
# 创建user_items字典,记录用户u看过的电影i的集合
user_items = {}

# 创建 transaction 数据集
transactions = []


for user, group in data.groupby('userId')['movieId']:
    user_items[user] = set(group.values.tolist())
    transactions.append(tuple(group.values.tolist()))
# 用apriori算法训练,得到频繁项集itemsets 和 关联规则rules
itemsets, rules = apriori(transactions, min_support=0.05, min_confidence=0.6)
# 选出关联规则中形式如 单个物品->物品 的规则
# 将这样的规则重写为字典形式,{单个物品:物品}
# 这样的字典为 rule_recommend
rule_recommend = {}
for rule in rules:
    # 选出 单个物品->物品 的规则
    if len(rule.lhs) == 1:
        rule_recommend[rule.lhs[0]] = set(rule.rhs)
# 我们仅用 物品->物品 的方式进行推荐
# 而不用 {物品1,物品2}->物品 的方式进行推荐
def topN(u):
    # 推荐列表
    recommend = set()
    # 用过的物品
    used_items = user_items[u]
    
    for item in used_items:
        if item in rule_recommend.keys():
            recommend.union(rule_recommend[item])
    
    # 去掉用过的物品
    res = recommend.difference(set(used_items))
    return res

这里存在两个问题,

  • 运行时间很长
  • 预测效果不佳

由于apriori算法组合数次地遍历整个数据集,导致运行时间很长,这是可以理解的,我们可以用fpgrowth算法作为替代。

但是,对于预测效果不佳这个事情,可能的原因有两点,第一,关联规则运用不彻底,实际上,我们仅考虑单个物品对于其他物品的关联,并没有将物品组合对其他物品的关联也纳入推荐机制中;第二,可能是参数不合适,通过调参,或许能有所改善。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值