机器学习-08-关联规则更新

总结

本系列是机器学习课程的系列课程,主要介绍机器学习中关联规则和协同过滤。

参考

机器学习(三):Apriori算法(算法精讲)

Apriori 算法 理论 重点

【手撕算法】【Apriori】关联规则Apriori原理、代码实现

FPGROWTH算法详解

MovieLens:一个常用的电影推荐系统领域的数据集

23张图,带你入门推荐系统

本门课程的目标

完成一个特定行业的算法应用全过程:

懂业务+会选择合适的算法+数据处理+算法训练+算法调优+算法融合
+算法评估+持续调优+工程化接口实现

机器学习定义

关于机器学习的定义,Tom Michael Mitchell的这段话被广泛引用:
对于某类任务T性能度量P,如果一个计算机程序在T上其性能P随着经验E而自我完善,那么我们称这个计算机程序从经验E中学习
在这里插入图片描述

关联规则

啤酒与尿布

“啤酒与尿布” 的故事相信很多人都听过,年轻爸爸去超市购买尿布时,经常会买点啤酒犒劳自己。因此,沃尔玛将这两种商品进行了捆绑销售,最终获得了更好的销量。

在这里插入图片描述
“啤酒与尿布”的故事
在这里插入图片描述

这个故事背后的理论依据就是 “推荐算法”,因为尿布和啤酒经常出现在同一个购物车中,那么向购买尿布的年轻爸爸推荐啤酒确实有一定道理。

关联规则算法

获得啤酒与尿布的关系的一种算法就是关联规则算法

1.关联规则推荐算法:这种算法基于关联规则挖掘的技术。它通过分析用户行为数据中的项集之间的关联关系,找出频繁项集和关联规则,然后根据这些规则进行推荐。比如,根据用户购买商品的历史记录,可以挖掘出购买商品之间的关联规则,然后根据规则推荐其他相关商品给用户。

关联规则算法最开始是面向购物篮分析问题:

在这里插入图片描述
如何在消费者购买了特定商品,比如PC机和一台数码相机后,作为销售人员的你针对该消费者已购买的商品进行分析(购物篮分析),可以继续给该消费者推荐什么产品,该消费者才能更感兴趣。

关联规则算法可以帮助我们在大量历史销售数字中发现“已有的多数客户在购买PC机和数码相机后,还经常购买哪些产品”这样的一个规律
关联规则就是通过发现顾客放入“购物篮”中的不同商品之间的关联,分析顾客的购物习惯,而物品见的某种联系我们称为关联
这种关联的发现可以帮助零售商了解哪些商品频繁的被顾客同时购买,从而帮助他们开发更好的营销策略。

关联规则 (Association Rules,又称 Basket Analysis) 是形如X→Y的蕴涵式
其中, X和Y分别称为关联规则的先导(antecedent或left-hand-side, LHS)后继(consequent或right-hand-side, RHS)
在这当中,关联规则X→Y,利用其支持度和置信度从大量数据中挖掘出有价值的数据项之间的相关关系。
关联规则解决的常见问题如:“如果一个消费者购买了产品A,那么他有多大机会购买产品B?”以及“如果他购买了产品C和D,那么他还将购买什么产品?”

关联规则定义:

假设
I = {I1,I2,。。。Im}是包含所有商品(item)的集合,
包含k个项的项集称为k项集(k-itemset)
给定一个交易数据库D,其中每个事务(Transaction)T是I的非空子集,即每一个交易都与一个唯一的标识符TID(Transaction ID)对应。
关联规则挖掘的目的即通过已发生的事务数据,找到其中有效关联性较高的项集所构成的规则。
那么,如何度量关联规则的有效性及关联性呢?
首先,该关联规则本身所对应的商品应当具有一定的普遍推荐价值,即支持度较高;关联规则在D中的支持度(support)D中事务同时包含X、Y的百分比,即概率
其次该规则的发生应当具有一定的可能性,即置信度较高置信度(confidence)是D中事务已经包含X的情况下,包含Y的百分比,即条件概率
在这里插入图片描述
如果满足最小支持度阈值min_support最小置信度阈值min_confidence,则认为关联规则是重要的。
当一个项集(XY)的支持度大于等于min_support,这个项集就被称为频繁项集(Frequent Itemset)
当以频繁项集(XY)构成的关联规则(X→Y)的置信度大于等于min_confidence,这个关联规则就被称为强关联规则。强关联规则也是关联规则挖掘的最终产出。

关联规则挖掘过程主要包含两个阶段:

第一阶段必须先从资料集合中找出所有的频繁项集(Frequent Itemsets),
第二阶段再由这些高频项目组中产生强关联规则(Association Rules)。

举个栗子🌰说明下

TID牛奶面包尿布啤酒鸡蛋可乐
1110000
2011110
3101101
4111100
5111001

上表格是顾客购买记录的数据库D,包含5个事务, 即D=5,有5个订单
项集I={牛奶,面包,尿布,啤酒,鸡蛋}
若给定最小支持度in_support=0.5,最小置信度min_confidence=0.6
考虑一个二项集:{牛奶,面包}
事务1,4,5同时包含牛奶和面包,那么说明包含牛奶和面包的有3个事务,即X∩Y=3,支持度(X∩Y)/D=3/5=0.6>min_support,则{牛奶,面包}是一个频繁项集
对于关联规则(牛奶→面包),在数据库D中4个事务是包含牛奶的,即X=4, 因而置信度(X∩Y)/X=3/4=0.75>min_confidence,则认为购买牛奶和购买面包之间存在强关联

关联规则算法Apriori实现

Apriori算法实现原理

R.Agrawal 和 R. Srikant于1994年在文献中提出了Apriori算法,该算法的描述如下图所示:

candidate itemsets候选项集合
frequent itemsets频繁项集合
在这里插入图片描述
1)令k = 1
2)统计每个k项集的支持度,并找出频繁k项集
3)利用频繁k项集生成候选k+1项集
4)令k=k+1,重复第 2)步

//  尺寸为k的候选项目集
C_k:Candidate itemsets of size k  
//大小为k的频繁项目集
L_k:frequent itemsets of size k  
L1={frequent 1-itemsets}; // 大小为1的频繁项目集
// k从1开始,频繁项目集不为0 
for (k=1;L_k≠0;k++)  
    // 从 L_k频繁项目集 中生成 C_k+1候选项目集
	C_k+1=GenerateCandidates(L_k)  
	// 对于每一个数据库D中的事务t 
	for each transaction t in database do 
	    // 包含在t中的C_k+1中的候选者的增量计数
	    increment count of candidates in C_k+1 that are contained in t 
	endfor 
	// 在 C_k+1中的候选集中找到大于最小支持度的作为L_K+1频繁候选项集 
	L_k+1=candidates in C_k+i with support >= min_sup 
endfor    
return U_kL_k;

举例🌰:说明下

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
Apriori算法实例—产生频繁项集在这里插入图片描述
Apriori算法实例—产生关联规则
在这里插入图片描述
Apriori算法思想总结
在这里插入图片描述

FPGROWTH算法

Apriori的挑战及改进方案

挑战
  多次数据库扫描
  巨大数量的候补项集
  繁琐的支持度计算

改善Apriori: 基本想法
  减少扫描数据库的次数
  减少候选项集的数量
  简化候选项集的支持度计算

具体参考这个:
FPGROWTH算法详解

手写完整代码

# 1.构建候选1项集C1
def createC1(dataSet):
    # 获取数据集中所有不重复的项
    c1 = list(set([y for x in dataSet for y in x]))
    c1.sort()  # 排序
    # 将每个项转换为集合形式
    c2 = [[x] for x in c1]
    # 使用frozenset以便作为字典键使用
    return list(map(frozenset, c2))

# 将候选集Ck转换为频繁项集Lk
# D:原始数据集
# Cn: 候选集项Ck
# minSupport:支持度的最小值
def scanD(D, Ck, minSupport):
    # 候选集计数字典
    ssCnt = {}
    # 遍历每条交易记录
    for tid in D:
        # 遍历每个候选项集
        for can in Ck:
            # 如果候选项集是当前交易记录的子集
            if can.issubset(tid):
                # 统计候选项集出现次数
                if can not in ssCnt.keys(): ssCnt[can] = 1
                else: ssCnt[can] += 1

    # 计算总交易数
    numItems = float(len(D))
    Lk = []     # 候选集项Cn生成的频繁项集Lk
    supportData = {}    # 候选集项Cn的支持度字典

    # 计算候选项集的支持度
    for key in ssCnt:
        support = ssCnt[key] / numItems
        # 如果支持度大于等于最小支持度,加入频繁项集
        if support >= minSupport:
            Lk.append(key)
        # 记录所有候选项集的支持度
        supportData[key] = support
    return Lk, supportData

# 连接操作,将频繁Lk-1项集通过拼接转换为候选k项集
def aprioriGen(Lk_1, k):
    Ck = []
    lenLk = len(Lk_1)
    for i in range(lenLk):
        # 获取前k-2个项
        L1_list = list(Lk_1[i])
        L1 = L1_list[:k - 2]
        L1.sort()
        for j in range(i + 1, lenLk):
            # 获取另一个项集的前k-2个项
            L2_list = list(Lk_1[j])
            L2 = list(Lk_1[j])[:k - 2]
            L2.sort()
            # 前k-2个项相同时,将两个集合合并
            if L1 == L2:
                Ck.append(Lk_1[i] | Lk_1[j])
    return Ck

# Apriori算法主函数
def apriori(dataSet, minSupport=0.5):
    # 生成候选1项集
    C1 = createC1(dataSet)
    # 扫描数据集,生成频繁1项集
    L1, supportData = scanD(dataSet, C1, minSupport)
    L = [L1]  # 存储所有频繁项集
    k = 2
    # 循环生成更高阶的频繁项集
    while (len(L[k-2]) > 0):
        Lk_1 = L[k-2]
        # 生成候选k项集
        Ck = aprioriGen(Lk_1, k)
        print("ck:", Ck)
        # 扫描数据集,生成频繁k项集
        Lk, supK = scanD(dataSet, Ck, minSupport)
        supportData.update(supK)
        print("lk:", Lk)
        L.append(Lk)
        k += 1
    return L, supportData

# 生成关联规则
# L: 频繁项集列表
# supportData: 包含频繁项集支持数据的字典
# minConf 最小置信度
def generateRules(L, supportData, minConf=0.7):
    # 包含置信度的规则列表
    bigRuleList = []
    # 从频繁二项集开始遍历
    for i in range(1, len(L)):
        for freqSet in L[i]:
            # 拆分项集为单个项的后件集合
            H1 = [frozenset([item]) for item in freqSet]
            if (i > 1):
                # 处理高阶频繁项集
                rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
            else:
                # 处理频繁二项集
                calcConf(freqSet, H1, supportData, bigRuleList, minConf)
    return bigRuleList

# 计算是否满足最小可信度
def calcConf(freqSet, H, supportData, brl, minConf=0.7):
    prunedH = []  # 满足最小置信度的后件集合
    # 用每个conseq作为后件
    for conseq in H:
        # 计算前件支持度
        P_A = supportData[freqSet.difference(conseq)]
        # 计算置信度
        conf = supportData[freqSet] / P_A
        if conf >= minConf:
            print(freqSet - conseq, '-->', conseq, 'conf:', conf)
            # 将规则加入结果列表(前件, 后件, 置信度)
            brl.append((freqSet - conseq, conseq, conf))
            prunedH.append(conseq)
    return prunedH

# 对规则进行评估
def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
    m = len(H[0])  # 后件长度
    if (len(freqSet) > (m + 1)):
        # 生成更高阶的后件候选集
        Hmp1 = aprioriGen(H, m + 1)
        # 计算置信度
        Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
        if (len(Hmp1) > 0):
            # 递归处理更高阶后件
            rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)

# 测试数据集
dataset = [['土豆', '尿不湿', '啤酒'], ['巧克力', '牛奶', '土豆', '啤酒'], ['牛奶', '尿不湿', '啤酒'],
           ['巧克力', '尿不湿', '啤酒'], ['巧克力', '啤酒']]
# 运行Apriori算法
L, supportData = apriori(dataset, minSupport=0.5)
# 生成关联规则
rules = generateRules(L, supportData, minConf=0.7)
# 打印所有关联规则
for e in rules:
    print(e)

运行输出如下:

ck: [frozenset({‘尿不湿’, ‘啤酒’}), frozenset({‘巧克力’, ‘啤酒’}), frozenset({‘尿不湿’, ‘巧克力’})]
lk: [frozenset({‘尿不湿’, ‘啤酒’}), frozenset({‘巧克力’, ‘啤酒’})]
ck: []
lk: []
frozenset({‘尿不湿’}) --> frozenset({‘啤酒’}) conf: 1.0
frozenset({‘巧克力’}) --> frozenset({‘啤酒’}) conf: 1.0
(frozenset({‘尿不湿’}), frozenset({‘啤酒’}), 1.0)
(frozenset({‘巧克力’}), frozenset({‘啤酒’}), 1.0)

调包完成关联规则

efficient_apriori 包实现
# 安装:pip install efficient-apriori==2.0.5
from efficient_apriori import apriori
# 测试数据集
dataset = [['土豆', '尿不湿', '啤酒'], ['巧克力', '牛奶', '土豆', '啤酒'], ['牛奶', '尿不湿', '啤酒'],
           ['巧克力', '尿不湿', '啤酒'], ['巧克力', '啤酒']]
freqItemSet, rules = apriori(dataset, 0.5, 0.7)
print(freqItemSet)
print(rules)

输出如下:

{1: {(‘尿不湿’,): 3, (‘啤酒’,): 5, (‘巧克力’,): 3}, 2: {(‘啤酒’, ‘尿不湿’): 3, (‘啤酒’, ‘巧克力’): 3}}
[{尿不湿} -> {啤酒}, {巧克力} -> {啤酒}]

fpgrowth_py 包实现

Apriori算法效率比较低,建议在使用的时候直接使用基于Apriori算法开发的FP-growth算法,fpgrowth_py 实现代码如下:

# 安装:pip install fpgrowth_py==1.0.0
from fpgrowth_py import fpgrowth
dataset = [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
freqItemSet, rules = fpgrowth(dataset, 0.5, 0.7)
print(freqItemSet)
print(rules) 

dataset = [['土豆', '尿不湿', '啤酒'], ['巧克力', '牛奶', '土豆', '啤酒'], ['牛奶', '尿不湿', '啤酒'],
           ['巧克力', '尿不湿', '啤酒'], ['巧克力', '啤酒']]

freqItemSet, rules = fpgrowth(dataset, 0.5, 0.7)
print(freqItemSet)
print(rules) 

输出如下:

[{1}, {1, 3}, {3}, {2, 3}, {2}, {5}, {3, 5}, {2, 3, 5}, {2, 5}]
[[{1}, {3}, 1.0], [{2, 3}, {5}, 1.0], [{3, 5}, {2}, 1.0], [{2}, {5}, 1.0], [{5}, {2}, 1.0]]

[{‘尿不湿’}, {‘啤酒’, ‘尿不湿’}, {‘巧克力’}, {‘啤酒’, ‘巧克力’}, {‘啤酒’}]
[[{‘尿不湿’}, {‘啤酒’}, 1.0], [{‘巧克力’}, {‘啤酒’}, 1.0]]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT从业者张某某

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值