您的位置:首页 > 编程语言 > Python开发

【机器学习实战】11.使用Apriori算法进行关联分析——python3程序

2018-03-06 17:32 573 查看
    之前费心费力写了一篇,结果没有保存。这一篇主要放上书本上的程序分析及运行结果。
    关联分析主要分为:频繁项集生成关联规则生成

1.频繁项集生成——Apriori算法
代码:def createC1(dataSet):
'''
构建大小为1的所有候选项的集合,存储不重复的项值
map(function,data)映射函数,在python3中返回一个迭代器,智能循环一次,故改为list
frozenset() 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素,不可改变
可用做字典键值使用
'''
C1=[]
for transcation in dataSet:
for item in transcation:
if not [item] in C1:
C1.append([item])
C1.sort()
return list(map(frozenset,C1))

def scanD(D,Ck,minSupport):
'''
D:数据集 Ck:候选项集列表 minSupport:最小支持度
'''
ssCnt={} #创建空字典
for tid in D:
for can in Ck:
if can.issubset(tid):
if not ssCnt. __contains__(can): #与课本不同,python3没有has_key()
ssCnt[can]=1
else:
ssCnt[can]+=1

numItems=len(D)
retList=[]
supportData={}
for key in ssCnt:
support=ssCnt[key]/numItems
if support>=minSupport:
retList.insert(0,key) #在列表手部插入关键值
supportData[key]=support

return retList,supportData

def aprioriGen(Lk,k):
'''
创建候选项集 Lk:频繁项集列表 k:项集元素个数,期望得到的是含有k个元素的集合
'''
retList=[]
lenLk=len(Lk)
for i in range(lenLk):
for j in range(i+1,lenLk):
L1=list(Lk[i])[:k-2] #取两个集合前k-2个数
L2=list(Lk[j])[:k-2]
L1.sort()
L2.sort()
if L1==L2:
retList.append(Lk[i]|Lk[j]) #如果两个集合前k-2个元素都相等,那这两个集合合成一个集合,并操作
return retList

def apriori(dataSet,minSupport=0.5):
'''
apriori算法主函数
'''
#前3条语句是对计算查找单个元素中的频繁项集
C1=createC1(dataSet)
D=list(map(set,dataSet))
L1,supportData=scanD(D,C1,minSupport)
L=[L1]
k=2
#L[k-1]中集合有k个元素,循环更新频繁项集
while(len(L[k-2])>0): #是否还有候选集
Ck=aprioriGen(L[k-2],k)
Lk,supK=scanD(D,Ck,minSupport)
supportData.update(supK) #把supk的键值对添加到supportData里
L.append(Lk)
k+=1
return L,supportData
对给定的简单数据集:#创建数据集
def loadDataSet():
return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
if __name__=='__main__':
dataSet=loadDataSet()
L,support=apriori(dataSet,0.5)

for k in support:
print(k,support[k])
print()
print(L)
得到结果:



2.关联规则生成
    我认为书本上的generateRules()函数有错误。当频繁项元素大于2(程序里 i>1)时,应该先计算规则右部元素个数为1时的可信度,而不是直接跳过。代码修改为:
def generateRules(L,supportData,minConf=0.7):
'''
关联规则生成主函数
L:频繁集项列表 supportData:包含频繁项集支持数据的字典 minConf:最小可信度阈值
构建关联规则需有大于等于两个的元素
'''
bigRuleList=[]
for i in range(1,len(L)):
for freqSet in L[i]:
H1=[frozenset([item]) for item in freqSet] #记录freqSet里的单个元素
H1=calcConf(freqSet,H1,supportData,bigRuleList,minConf)
if (i>1):
#考虑进行进一步合并,这里与课本不同
#如果只有两个元素,即只包含关于A->B形式的集合,无需对supportData进行更新
rulesFromConseq(freqSet,H1,supportData,bigRuleList,minConf)

return bigRuleList

def calcConf(freqSet,H,supportData,br1,minConf=0.7):
'''
计算规则可信度以及找到满足最小可信度要求的规则
freqSet是H的超集
具体是计算freqSet-conseq'-->'conseq的可信度
'''
prunedH=[]
for conseq in H:
conf=supportData[freqSet]/support[freqSet-conseq]
if conf>=minConf:
print( freqSet-conseq,'-->',conseq,'conf:',conf)
br1.append((freqSet-conseq,conseq,conf))
prunedH.append(conseq)
return prunedH

def rulesFromConseq(freqSet,H,supportData,br1,minConf=0.7):
'''
这里H相当于freqSet子集
在这个函数里面,循环是从子集元素个数由2一直增大到freqSet的元素个数减1
'''
m=len(H[0])
if(len(freqSet)>(m+1)):
Hmp1=aprioriGen(H,m+1) #将H中各集合(元素个数为m)合并成有m+1个元素的集合
Hmp1=calcConf(freqSet,Hmp1,supportData,br1,minConf)
if(len(Hmp1)>1): #表示至少还有两个子集,可以合并,相当于循环操作
rulesFromConseq(freqSet,Hmp1,supportData,br1,minConf)对给定简单数据集:if __name__=='__main__':

dataSet=loadDataSet()
L,support=apriori(dataSet,0.5)
rules=generateRules(L,support,0.5)得到结果:



图中用红笔标识的部分在书本所写代码中是无法得到的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息