声明:本文为学习笔记,侵权删
一、几个概念
关联分析:参考啤酒与尿不湿的故事,啤酒和尿不湿本身没有关系,但通过调查买啤酒的人有大概率会买尿不湿,所以啤酒+尿不湿就成了一个销售组合。得出这个销售组合的过程就是关联分析。
事务:每条购买信息就是一个事务。
项集:一条事务中物品的随机组合产生的集合。一个集合里有几个项,就叫几项集。
比如在下面这份数据中,有四个事务,{捏脚}是一项集,{捏脚,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["提升度"]])