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

Apriori算法与关联分析

2016-09-04 00:14 260 查看

概述

关联分析是一种在大规模数据集中寻找有趣关系的任务。这些关系可以有两种形式:频繁项集(frequent item sets)或者关联规则。频繁项集是经常出现在一起的物品的集合,关联规则(association rules)暗示两种物品之间可能存在很强的关系。

一个项集的支持度(support)度被定义为在数据集中包含该项集的记录所占的比例。支持度是针对项集来说的,因此可以定义一个最小支持度,只保留满足最小支持度的项集。

置信度(confidence)是针对一条关联规则来说的,假设由Apriori算法得到一个高支持度项集k,这个项集产生一组关联规则,k被分为两个不相交的子集,A,B,并记为

A−>B

第一个子项集成为“前件”,第二个子项集成为“后件”。规则的置信度是规则的支持度除以其前件的支持度,即

C(A−>B)=T(k)/T(A)

寻找频繁项集

Apriori算法用一种比起暴力搜索更快速的方法寻找频繁项集,具体来说,如果一个项集是频繁的,那么它的所有子集也是频繁的。第一遍扫描数据,计算所有1项集的支持度,删除那些支持度小于阈值的项,第二次扫描对可以通过第一次扫描而保留下来的项生成的所有2项集计算支持度。也就是说,要生成所有m项集,我们只需考虑这样的m项集候选,他们的m个规模为m-1的项集都是频繁的。删除那些支持度小于阈值的2项集。每一遍后继数据扫描只考虑能由前一边扫描保留项集和第一遍扫描留下的项组合所生成的项集。继续扫描数据,直到由上一步得到的所有候选项集的支持度都小于指定的阈值。这是至关重要的,因为我们假定所有数据不能全部装入计算机内存。

从频繁项集挖掘关联规则

对于每一个频繁项集,我们可以生成许多关联规则。如果能够减少规则数目来确保问题的可解性,那么计算起来就会好很多。可以观察到,如果某条规则并不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度要求。举例来说,对于频繁项集{0,1,2,3},如果{0,1,2}->{3}不满足最小可信度要求,那么任何左部为{0,1,2}的子集的规则也不会满足最小可信度要求。这和频繁项集的特性类似,对于一个频繁项集,我们可以从后件只有一个元素开始寻找规则,后件有两个元素的规则其中的每一个元素作为后件对应的规则置信度都大于阈值。

Python实现

吐槽…《机器学习实战》上的代码全是错误,而且例子也是错的。。。

自己修改的代码,在测试数据上输出正确

这里简要说几个重要的函数,首先是生成候选项集aprioriGen,比如要生成大小为k的候选项集Ck,如果将所有的长度为k-1的频繁项集和长度为1的频繁项集结合,那么会生成大量重复的集合,需要判重,为了降低计算复杂度,考虑将所有长度为k-1的频繁项集排序,然后对于两层循环,对于前k-2项相同的频繁项集合并,这样可以保证没有重复元素。

然后是递归生成规则的函数generateRules,每次从当前候选后件中寻找置信度大于阈值的规则然后递归下去。

from numpy import *

# Apriori算法

def loadData():
return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]

def createC1(dataSet):
C1 = []
for transaction in dataSet:
for term in transaction:
if [term] not in C1:
C1.append([term])
C1.sort()
return list(map(frozenset, C1))

# 由候选项集生成频繁项集,并计算支持度
def scanD(D, Ck, minSupport):
ssCnt = {}
for transaction in D:
for can in Ck:
if can.issubset(transaction):
if can not in ssCnt: ssCnt[can] = 1
else: ssCnt[can] += 1
numItems = float(len(D))
retList = []
supportData = {}
for key in ssCnt:
# print(key, ssCnt[key])
support = ssCnt[key]/numItems
if support >= minSupport:
retList.append(key)
supportData[key] = support
return retList, supportData

# 生成候选项集
def aprioriGen(Lk, k):
retList = []
sortL = []
for i in range(len(Lk)):
tmpL = sorted(list(Lk[i]))
sortL.append(tmpL[:k-2])
for i in range(len(Lk)):
for j in range(i+1, len(Lk)):
if sortL[i] == sortL[j]:
retList.append(Lk[i]|Lk[j])
return retList

def apriori(dataSet, minSupport=0.5):
C1 = createC1(dataSet)
D = list(map(set, dataSet))
L1, supportData = scanD(D, C1, minSupport)
L = [L1]
k = 2
while(len(L[k-2]) > 0):
Ck = aprioriGen(L[k-2], k)
print(Ck)
Lk, supK = scanD(D, Ck, minSupport)
L.append(Lk)
# update方法将一个字典添加到另一个字典中
supportData.update(supK)
k += 1
return L, supportData

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]
rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
return bigRuleList

def calConf(freqSet, H, supportData, brl, minConf):
prunedH = []
for conseq in H:
conf = supportData[freqSet]/supportData[freqSet-conseq]
if conf >= minConf:
prunedH.append(conseq)
brl.append((freqSet-conseq, conseq, conf))
print(freqSet-conseq, '-->', conseq, 'conf', conf)
return prunedH

def rulesFromConseq(freqSet, H, supportData, brl, minConf):
prunedH = calConf(freqSet, H, supportData, brl, minConf)
m = len(H[0])
if (len(freqSet) > m+1):
newH = aprioriGen(H, m+1)
if (len(newH) > 0):
rulesFromConseq(freqSet, newH, supportData, brl, minConf)

dataSet = loadData()
L, supportData = apriori(dataSet)
print(supportData)
rules = generateRules(L, supportData)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息