Python数据处理数据挖掘(三):关联分析(Apriori算法)

声明:本文为学习笔记,侵权删

一、几个概念

关联分析:参考啤酒与尿不湿的故事,啤酒和尿不湿本身没有关系,但通过调查买啤酒的人有大概率会买尿不湿,所以啤酒+尿不湿就成了一个销售组合。得出这个销售组合的过程就是关联分析。

事务:每条购买信息就是一个事务。

项集:一条事务中物品的随机组合产生的集合。一个集合里有几个项,就叫几项集。

比如在下面这份数据中,有四个事务,{捏脚}是一项集,{捏脚,SPA}是二项集。

支持度:support=一个项集出现的频率=项集出现的次数/事务总数。Support({捏脚})=4/4=1,Support({捏脚,汗蒸})=3/4。Support最大为1,最小为0。Support越小,该项集越不受欢迎,繁殖越受欢迎。

最小支持度m:m是主观设定的一个阈值,Support(项集A)≥m,保留A,A称为频繁项集。反之,Support(A)<m,舍弃A。

关联规则:由频繁项集产生,格式:X→Y,X,Y为项集,X为前件,Y为后件。代表的意义是:用户购买了项集X,那么就会购买项集Y。如,二项集{捏脚 汗蒸}可以产生两个关联规则{捏脚}→{汗蒸}、{汗蒸}→{捏脚}。关联规则{捏脚}→{汗蒸}表示顾客去捏脚了,那么他大概率也会去汗蒸。

置信度:Confidence(X→Y)=Support({X,Y})/Support({X})。置信度用来评估一个关联规则的可信度,置信度越高,关联规往往越可信,即发生的概率更大。如,Confidence{(捏脚}→{SPA}) = 捏脚SPA同时发生/捏脚发生 = 0.5/1 = 0.5。注意:置信度高并不代表关联规则一定重要/有意义。X→Y的置信度的可靠性会受Y的支持度影响。比如:Confidence({SPA}→{捏脚}) = 0.5/0.5=1,难道做SPA一定会捏脚吗?虽然在数据集里是如此,但会不会可能是捏脚太受欢迎而SPA本身并不受欢迎?这样的话,SPA+捏脚的大宝剑套餐不一定受欢迎。

最小置信度n:n是主观设定的一个阈值,Confidence(X→Y)≥n,保留关联规则X→Y,且将X→Y称为强关联规则。反之,Confidence(X→Y)<n,舍弃该关联规则。

提升度Lift:为了解决上面高亮部分提出的置信度不可信的问题。提升度表示出关联规X→Y中,X的出现对Y的出现的影响程度。Lift(X→Y)=Confidence(X→Y)/Support(Y) = Support({X,Y})/Support(X)*Support(Y)。可以发现Lift(X→Y)=Lift(Y→X)

Lift<1 前件对后件(X对Y)为抑制作用

Lift>1 前件对后件(X对Y)为促进作用

Lift=1 X和Y互不影响,相互独立

很显然,通过计算,Lift({SPA}→{捏脚})=1,这俩相互独立,互不影响。

如果数据集变成这样:

 这时,Lift({SPA}→{捏脚})=1/6,则SPA对捏脚是抑制作用,做完SPA就不想捏脚了。

Lift({捏脚}→{泰式按摩})=4/3>1,则泰式按摩可以促进捏脚,也可以说捏脚促进泰式按摩,所以泰式按摩+捏脚的套餐可能不错。

二、Apriori算法的实现

所用数据集:

代码: 

import pandas
from apyori import apriori
data = pandas.read_csv(r"D:\Python Code\dataMining\大保健套餐.csv",encoding="GBK")
Services = []
#将每个客户喜欢的服务写成二维数组的形式.(Apriori()函数的输入要求是二维数组类型)
for i in data["服务"]:
    service = i.split(" ")
    Services.append(service)
#Apriori的作用是生成关联规则并给出对应的评价
ass_rules = apriori(Services,min_support=0.2,min_confidence=0.6)
for rule in ass_rules:
    print(rule)

运行结果:

 结果解析:

RelationRecord:一条记录的开始

items:频繁项集

support:频繁项集的支持度

ordered_statistics:该频繁项集产生的强关联规则

item_base:前件

item_add:后件

confidence:该关联规则的置信度

lift:该关联规则的提升度

但这种输出形式依旧不够直观,那么如何把它转化成更为直观的结构,可以更方便地获取其中的内容呢?

注意到,一条记录的结构是这样的:RelationRecord[items,support,ordered_statistics[item_base,item_add,confidence,lift]]

那么就可以一层一层得拨开,获取里层的信息,就像多维数组差不多。话不多说,看示例:

#Apriori
ass_rules = apriori(Services,min_support=0.2,min_confidence=0.6)
all_strong_relation = []
#提取相应的数据
for rule in ass_rules:
    support = round(rule.support,3) #获取一个项集的支持度,小数部分保留三位
    #由这个项集产生的所有强关联.
    for i in rule.ordered_statistics:
        head_set = list(i.items_base)
        #前件为空的时候关联规则没有啥意义,因此删去
        if head_set == []:
            continue
        tail_set = list(i.items_add)
        confidence = round(i.confidence,3)#小数部分保留三位
        lift = round(i.lift,3)#小数部分保留三位
        print(f"head_set:{head_set}  tail_set:{tail_set}  confidence:{confidence}  lift:{lift}")
        
        #把这些数据转换为dataframe的格式
        relation = str(head_set)+"→"+str(tail_set)
        all_strong_relation.append([relation,support,confidence,lift])
strong_Relation = pandas.DataFrame(all_strong_relation,columns=["关联规则","支持度","置信度","提升度"])
print(strong_Relation)
/*
              关联规则   支持度    置信度    提升度
0          ['SPA']→['汗蒸']  0.50  1.000  1.333
1          ['汗蒸']→['SPA']  0.50  0.667  1.333
2           ['捏脚']→['汗蒸']  0.50  0.667  0.889
3           ['汗蒸']→['捏脚']  0.50  0.667  0.889
4    ['捏脚', 'SPA']→['汗蒸']  0.25  1.000  1.333
5  ['泰式按摩', 'SPA']→['汗蒸']  0.25  1.000  1.333
6  ['汗蒸', '泰式按摩']→['SPA']  0.25  1.000  2.000
*/

print("--------------促进关系------------")
print(strong_Relation[strong_Relation["提升度"]>1])

 由此可知,有SPA+汗蒸的套餐都挺受欢迎。那上面提到的{捏脚}→{泰式按摩}这个组合,为什么没有在最终的输出里出现呢?原因:{捏脚}→{泰式按摩}的置信度是0.333…,在创建强关联规则的时候就被排除了。apriori()函数中,我设定的最小置信度是0.6,大于0.333。当然最小置信度和最小支持率都是可以根据实际要求调整的。

完整代码如下:
 

import pandas
from apyori import apriori
data = pandas.read_csv(r"D:\Python Code\dataMining\大保健套餐.csv",encoding="GBK")
Services = []
#将每个客户喜欢的服务写成二维数组的形式.(Apriori()函数的输入要求是二维数组类型)
for i in data["服务"]:
    service = i.split(" ")
    Services.append(service)
#Apriori
ass_rules = apriori(Services,min_support=0.2,min_confidence=0.6)
all_strong_relation = []
#提取相应的数据
for rule in ass_rules:
    support = round(rule.support,3) #获取一个项集的支持度,小数部分保留三位
    #由这个项集产生的所有强关联.
    for i in rule.ordered_statistics:
        head_set = list(i.items_base)
        #前件为空的时候关联规则没有啥意义,因此删去
        if head_set == []:
            continue
        tail_set = list(i.items_add)
        confidence = round(i.confidence,3)#小数部分保留三位
        lift = round(i.lift,3)#小数部分保留三位
        print(f"head_set:{head_set}  tail_set:{tail_set}  confidence:{confidence}  lift:{lift}")
        
        #把这些数据转换为dataframe的格式
        relation = str(head_set)+"→"+str(tail_set)
        all_strong_relation.append([relation,support,confidence,lift])
strong_Relation = pandas.DataFrame(all_strong_relation,columns=["关联规则","支持度","置信度","提升度"])
print(strong_Relation)
print("--------------促进关系------------")
print(strong_Relation[strong_Relation["提升度"]])

物联沃分享整理
物联沃-IOTWORD物联网 » Python数据处理数据挖掘(三):关联分析(Apriori算法)

发表评论