1.Apripri算法
问题:
在探究关联规则时,会得到如图所示的一颗树,每棵树都是一种可能,n个物品的关联一共有2^n-1种可能。这无疑是巨大的运算量
但是我们可以从中发现一些规律,如果说一个项是非频繁集,那么它的超集也是非频繁集,根据支持度的计算方法,我们可以知道超集的支持度是要小于它本身的项的。因此,项为非频繁集,超级也必定为非频繁集。
因此,我们可以从上往下进行遍历,并只遍历频繁集的超集
具体过程为:
首先我们遍历一项集,并去掉非频繁集,然后再遍历二巷集,最后,我们再进行一次合并,如图所示,L2的结果有2,3/2,5/3,5,我们就可以合并为(2,3,5)
2.代码实现
创建数据,首先,我们创建如上图所示的数据
def loadDataSet():
return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
然后我们创建一个冻住的集合,里面包含所有的一元项。
ef createC1(dataSet):
C1 = []
for transaction in dataSet:
for item in transaction:
if not [item] in C1:
C1.append([item])
C1.sort()
return list(map(frozenset,C1))
对于扫描模块,首先需要计算得到每一个项出现的次数,以求出支持度,并筛选出超过阈值的项集,进行后续的操作。
def scanD(D,CK,minSupport):
ssCnt = {}
for tid in D:
for can in CK:
if can.issubset(tid):
if not can in ssCnt: # 项为上面数据的子集
ssCnt[can] = 1 # 项不在字典中
else:
ssCnt[can] += 1 # 项在字典中
numItems = float(len(list(D)))
retlist = []
supportData = {}
for key in ssCnt:
support = ssCnt[key]/numItems
if support >= minSupport: # 对项的支持度进行筛选
retlist.insert(0,key)
supportData[key] = support
return retlist,supportData
拼接操作,如代码所示,对于1项集,L1和L2为空,直接进行拼接。对于二项集,如果第一个项相同,则可以进行拼接操作。
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]
if L1 == L2:
retlist.append(LK[i]|LK[j])
return retlist
挖掘频繁项集,如上图所示,首先扫描一项集,然后进行拼接,一项集直接拼接,2项集第一项相同也进行拼接。最后更新项集和对应的支持度。
def apriori(dataSet,minSupport=0.5):
C1 = createC1(dataSet)
L1,supportData = scanD(dataSet,C1,minSupport)
L = [L1]
k = 2
while(len(L[k-2]) > 0):
CK = aprioriGen(L[k-2],k)
LK,supk = scanD(dataSet,CK,minSupport)
supportData.update(supk)
L.append(LK)
k += 1
return L,supportData
规则生成模块,首先,我们需要取出多元项集中的每一项,比如【2,3,5】,取出每一个项,[2],[3],[5]。然后计算置信度。如果是二元项集,如[2,3],就分别计算[2],[3]和[3],[2]之间的置信度。如果是三元项集,如[2,3,5],就计算[2],[3,5]以及[3],[2,5],[5],[2,3]的置信度。
代码如下:
def generateRules(L,supportData,minConf=0.6):
rulelist = []
for i in range(1,len(L)):
for freqSet in L[i]:
H1 = [frozenset([item])for item in freqSet]
rulessFromConseq(freqSet,H1,supportData,rulelist,minConf)
def rulessFromConseq(freqSet,H,supportData,rulelist,minConf=0.6):
m=len(H[0])
while (len(freqSet) > m):
H = calConf(freqSet,H,supportData,rulelist,minConf)
if (len(H)>1):
aprioriGen(H,m+1)
m += 1
else:
break
def calConf(freqSet,H,supportData,rulelist,minConf=0.6):
prunedh = []
for conseq in H:# 置信度的计算
conf = supportData[freqSet]/supportData[freqSet-conseq]
if conf >= minConf:
print (freqSet-conseq,'-->',conseq,'conf:',conf)
rulelist.append((freqSet-conseq,conseq,conf))
prunedh.append(conseq)
return prunedh
执行代码,结果如下:
if __name__ == '__main__':
dataSet = loadDataSet()
L,support = apriori(dataSet)
i = 0
for freq in L:
print ('项数',i+1,':',freq)
i+=1
rules = generateRules(L,support,minConf=0.5)