关联分析是一种在大规模数据集中寻找有趣关系的任务。这些关系主要有两种形式:
量化关联分析是否成功的评价准则也有两个:
对于包含N种物品的数据集共有 2N−1 2 N − 1 种项集组合。
例如4个物品的项集组合如下:
如果暴力寻找频繁项集会及其的耗时,为了加快寻找的速度,需要用到Apriori原理。
Apriori原理:如果某个项集是频繁的,那么它的所有子集也是频繁的。虽然直观上看并没有什么帮助,但是如果反过来看就有用了。也就是说也就是说如果一个项集是非频繁集,那么它的所有超集也是非频繁的。如下图所示:
使用该规则就可以避免项集数目的指数增长,从而在合理时间内计算出频繁项集。
关联分析的目标包括两个:发现频繁项集和发现关联目标。首先需要找到频繁项集,然后才能获得关联规则。
Apriori算法只需要两个参数:数据集和最小支持度。
其中主要的一个辅助函数就是扫描数据集过滤掉那些支持度过低的项集。scanD()伪代码如下:
对数据集中的每一条记录trans
对每个候选集can:
检查can是否是tran的子集:
如果是,则增加can的计数。
对每个候选项集:
如果其支持度不低于最小值,则保留该项集。
返回所有频繁项集列表
Python代码如下:
def loadDataSet():
return [[1,3,4,],[2,3,5],[1,2,3,5],[2,5]]
def createC1(dataSet):
C1 = []
for trans in dataSet:
for item in trans:
if [item] not in C1:
C1.append([item])
C1.sort()
return [frozenset(t) for t in 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
numItems = float(len(D))
retList = []
supportData = {}
for key in ssCnt:
support = ssCnt[key]/numItems
if support >= minSupport:
retList.append(key)
supportData[key] = support
return retList,supportData
整个Apriori算法的伪代码如下:
当集合中项的个数大于0时
构建一个k个项组成的候选项集的列表
检查数据以确定每个项集都是频繁的
保留频繁项集并构建k+1项组成的候选项集的列表
Python代码如下:
def aprioriGen(Lk,k): #create Ck
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()
if L1==L2:
retList.append(Lk[i]|Lk[j])
return retList
def apriori(dataSet,minSupport=0.5):
D = list(map(set,dataSet))
C1 = createC1(dataSet)
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)
L.append(Lk)
k += 1
return L,supportData
我们先生成一个可能的关联规则列表,然后测试每条规则的可信度,如果可信度不低于最小要求,就去掉该规则。
例如项集{0,1,2,3}产生的所有关联规则如下:
怎样来减少需要测试的规则数目的?
利用这一性质:如果某条规则不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度的要求。如上图阴影部分所示:012->3不满足,则右件包含3的规则都不满足要求。
从频繁项集中挖掘关联规则主要思想如下:
这种方法也被成为分级法。
def generateRules(L, supportData, minConf=0.7):
bigRuleList = []
for i in range(1, len(L)):
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 = []
for conseq in H:
conf = supportData[freqSet]/supportData[freqSet-conseq]
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)):
Hmp1 = aprioriGen(H, m + 1)
Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
if (len(Hmp1) > 1):
rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
主要难度在rulesFromConseq()。