参与拿奖:本文已参与「新人创作礼」活动,一起开启掘金创作之路
1.相关概念
关联分析(关联规则学习):从大规模数据中寻找物品间的联系
频繁项集:经常出现在一块的物品的集合
关联规则:暗示两种物品之间存在很强的关系
Apriori算法
优点:易于编码实现
缺点:在大数据集上运行较慢
适用数据类型:数值型或者标称型
2.分析案例
2.1 数据分析
from numpy import *
import pandas as pd
dataId=[i for i in range(5)]
dataValue=['豆奶、莴苣','莴苣、尿布、葡萄酒、甜菜','豆奶、尿布、葡萄酒、橙汁','莴苣、豆奶、尿布、葡萄酒','莴苣、豆奶、尿布、橙汁']
data=pd.DataFrame()
data['交易号码']=dataId
data['商品']=dataValue
上述数据中,葡萄酒、豆奶、尿布就是一组频繁项集,可以观察出买了尿布的人很可能会买葡萄酒。进一步分析可知:
频繁项集中频繁的度量单位:支持度和可信度
一个频繁项集的支持度被定义为:数据集中包含该项集记录所占比例,是针对项集的
例如上述数据中豆奶的支持度为4/5
可信度(置信度):针对一条关联规则来的,这条关联规则的可信度被定义为两个支持度的比值(类似于条件概率)
例如关联规则尿布->葡萄酒的置信度为:支持度(尿布、葡萄酒)/支持度(尿布)
例如关联规则尿布->葡萄酒=3/4,故得出结论所有包含“尿布”的记录中75%都适用
2.2 简单案例
求解项集伪代码如下:
对于数据集中的每条交易记录train:
对于每个候选集项can:
检查can是否属于train的子集
如果是子集:
增加can的计数器
对于每个候选集项:
如果其支持度不小于最小度量,则保留该项集
返回所有项集列表
def loadDataSet():
return [[1,2,3],[1,2,3,4],[2,3],[2,3,4],[2,5]]
# 创建一个不变集合(存放所有商品类别)
def createC1(dataSet):
c1=[]
for trainsaction in dataSet:
for item in trainsaction:
if not [item] in c1:
c1.append([item])
c1.sort()
# 返回一个不变集合
# print(c1)
return list(map(frozenset,c1))
# 输入参数分别为原始数据集、商品种类集合、最小支持度
def scanD(D,ck,minSupport):
ssCnt={}
for tid in D:
for can in ck:
if can.issubset(tid):
if can not in ssCnt:
ssCnt[can]=1
else:
ssCnt[can]+=1
# 上述if-else等价于:
# ssCnt[can]=ssCnt.get(cant,0)+1
numItem=float(len(D))
retList=[]
supportData={}
for key in ssCnt:
# 计算所有项集的支持度
support=ssCnt[key]/numItem
# 根据支持度划分项集子集
if support>= minSupport:
retList.insert(0,key)
supportData[key]=support
return retList,supportData
def test():
data=loadDataSet()
ck=createC1(data)
print('商品种类为:',ck)
retList,supportData=scanD(data,ck,0.5)
print('单商品频繁项集为',retList)
print('单商品支持度为:',supportData)
print('从上述数据可以根据设置最小支持度过滤掉部分数据,减少后续计算程度!')
test()
2.3 Apriori算法
Apriori算法伪代码如下:
当集合项中的个数大于0时:
构建一个k个项组成的候选项集的列表
检查数据以确认每个项集都是频繁的
保留频繁集项并构建k+1项组成的候选集的列表
def loadDataSet():
return [[1,2,3],[1,2,3,4],[1,2,3,4],[2,5],[1,2,3,4]]
# 该函数负责将Lk中的元素分解为不重复的子集所组成的列表
def aprioriGen(Lk,k):
retList=[]
lenLk=len(Lk)
for i in range(lenLk):
for j in range(i+1,lenLk):
L1=list(Lk[i])[:k-2]
L2=list(Lk[j])[:k-2]
L1.sort()
L2.sort()
# print(L1,L2)
# 如果两个列表相等就合并
if L1==L2:
retList.append(Lk[i]|Lk[j])
return retList
def apriori(dataSet,minSupport=0.5):
C1=createC1(dataSet)
D=list(map(set,dataSet))
# print("将列表元素转换为集合:",D)
L1,supportData=scanD(D,C1,minSupport)
L=[L1]
k=2
while(len(L[k-2])>0):
ck=aprioriGen(L[k-2],k)
Lk,supK=scanD(D,ck,minSupport)
supportData.update(supK)
if Lk!=None:
L.append(Lk)
k+=1
return L,supportData
def test():
dataSet=loadDataSet()
L,supportData=apriori(dataSet,minSupport=0.5)
print('频繁项集为:',L)
print('频繁项集机:支持度为 ',supportData)
test()
2.3.1 一点发现
在计算可信度时可以注意到:如果一个项集不满足最低可信度,其子集也一定不满足
从频繁项集中挖掘关联规则:可以先从一个频繁项集开始,接着创建一个关联规则列表,右边只包含一个元素
然后对这些元素进行测试,接下来合并所有剩余规则创建一个新的规则列表,列表右边包含两个元素(该方法为分级法)
2.3.2 生成新的关联规则
def generateRules(L, supportData, minConf=0.7): #supportData is a dict coming from scanD
bigRuleList = []
for i in range(1, len(L)):#only get the sets with two or more items
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 = [] #create new list to return
for conseq in H:
conf = supportData[freqSet]/supportData[freqSet-conseq] #calc confidence
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)): #try further merging
Hmp1 = aprioriGen(H, m+1)#create Hm+1 new candidates
Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
if (len(Hmp1) > 1): #need at least two sets to merge
rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
def test():
data=loadDataSet()
print('在当前数据集上生成一个置信度大于0.7,且其项集支持度大于0.5的关联规则:')
L,supportData=apriori(data,minSupport=0.5)
rules=generateRules(L,supportData,minConf=0.7)
print('关联规则为:',rules)
test()
3.小结
关联分析是用于发现大数据集中元素间有趣关系的一个工具集。
可以适用频繁项集来对这种关系进行量化,但直接计算组合会耗费大量时间,可以采用apriori方法。
可以适用支持度和可信度来生成一条关联规则。
参考资料
[1] 机器学习实战
[2] 书籍源码
[3] jupyter版本
[4] 本节代码