主要是讲解一些数据挖掘中频繁模式挖掘的Apriori算法原理应用实践
当我们买东西的时候,我们会发现物品展示方式是不同,购物以后优惠券以及用户忠诚度也是不同的,但是这些来源都是大量数据的分析,为了从顾客身上获得尽可能多的利润,所以需要用各种技术来达到目的。
通过查看哪些商品一起购物可以帮助商店了解客户的购买行为。这种从大规模数据集中寻找物品间的隐含关系被称为关联分析或者关联规则学习。寻找物品的不同组合用蛮力算法的话效率十分底下,所以需要用智能的方法在时间范围内寻找频繁项集。
def createC1(dataset):
C1=[]
for transaction in dataset:
for item in transaction:
if not [item] in C1:#如果不在项集中
C1.append([item])
C1.sort()
#可以作为key值
return map(frozenset,C1)#每个元素是一个frozenset
#满足要求的构成L1,然后L1组合成为C2。进一步过滤成为L2
#frozenset可以作为key值
def scanD(D,Ck,minSupport):
#先在记录中查看所有候选集的次数
ssCnt = {}
for td in D:
for can in Ck:
if can.issubset(td):#如果是那个集合的子集
if not ssCnt.has_key(can):ssCnt[can]=1
else:ssCnt[can]+=1
numCount = len(D)#记录的总数
#记录每个项集的支持度
supportData={}
retList=[]
for key in ssCnt.iterkeys():
support = float(ssCnt[key]*1.0/numCount)
if support>=minSupport:
retList.insert(0,key)#加入满足条件的项集合的序列
supportData[key] = support
return retList,supportData
x = apriori.loadDataSet()
C1 = apriori.createC1(x)#frozenset每个元素
print C1
#构建事物集
D = map(set,x)#每个元素是集合
L1,supportData0 = apriori.scanD(D,C1,0.5)
print L1
得到如下结果:[frozenset([1]), frozenset([2]), frozenset([3]), frozenset([4]), frozenset([5])]
#前面K-1x项目相同的时候可以生成Lk
def aprioriGen(Lk,k):
#前面k-1项目相同就可以合成
retList = []
lenLk = len(Lk)
for i in range(lenLk):
for j in range(i+1,lenLk):
L1 = list(Lk[i])[:k-2]#可以考虑1个元素的时候是0直接合并
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):
C1 = createC1(dataset)
D = map(set,dataset)
L1,supportData = scanD(D,C1,minSupport)
L = [L1]
k = 2#项集为2
#频繁n-1项目总数为
while(len(L[k-2])>0):#因为项集存的位置是0
Ck = aprioriGen(L[k-2],k)
Lk,supK = scanD(D,Ck,minSupport)
supportData.update(supK)#加入字典更新
L.append(Lk)#L+1
k+=1#当空集的时候退出
return L,supportData
dataSet = apriori.loadDataSet() L,supportData = apriori.apriori(dataSet,minSupport=0.7) print L
#规则生成函数
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()
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]#获得条件概率(freq-conseq) -> 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)):#一直到该频繁项集能包含的右边推出等于项的个数-1为止例如{1,2,3,4}当{1}-{2,3,4}以后此时H[0]长度为3
Hmp1 = aprioriGen(H,m+1)#右边推出过程类似生成过程
Hmp1 = calcConf(freqSet,Hmp1,supportData,brl,minConf)#过滤过程返回被推出的右边的项集的集合
if (len(Hmp1)>1):#若有新规则生成继续递归处理
rulesFromConseq(freqSet,Hmp1,supportData,brl,minConf)
测试如下:
#生成所有频繁项集合 dataSet = apriori.loadDataSet() L,supportData = apriori.apriori(dataSet,minSupport=0.5) #生成规则 rules = apriori.generateRules(L,supportData,minConf=0.5)
#只保留包含投票数据的actionId
def getActionIds():
fr = open('recent20bills.txt')
actionIdList=[];billTitleList=[]
for line in fr.readlines():
billNum = int(line.split('\t')[0])
try:
billDetail = votesmart.votes.getBill(billNum)#获取议案对象
for action in billDetail.actions:
if action.level=='House' and \
(action.stage=='Passage' or \
action.stage=='Amendment Vote'):
actionId = int(action.actionId)
actionIdList.append(actionId)
billTitleList.append(line.strip().split('\t')[1])
except:
print "problem gettin bill %d"%billNum
sleep(1)
return actionIdList,billTitleList
我们获得的是类似Bill:12939 has actionId:34089这样的信息。我们需要频繁模式挖掘的话,需要将上面信息转换成项集或者交易数据库的东西。一条交易记录只有一个项出线还是没出现的信息,并不包含出现的次数。
#基于投票数据的事物列表填充函数
def getTransList(actionIdList,billTitleList):
itemMeaning = ['Republican','Democratic']
for billTitle in billTitleList:
itemMeaning.append('%s -- Nay'%billTitle)
itemMeaning.append('%s -- Yea' % billTitle)
#创建事务字典
transDict = {}
voteCount = 2# 0,1是所属党派。2开始是被第几次投票
for actionId in actionIdList:
sleep(3)
print 'getting votes for actionId: %d' %actionId
try:
voteList = votesmart.votes.getBillActionVotes(actionId)
for vote in voteList:
if not transDict.has_key(vote.candidateName):
transDict[vote.candidateName] = []
if vote.officeParties =='Democratic':
transDict[vote.candidateName].append(1)
elif vote.officeParties=='Republican':
transDict[vote.candidateName].append(0)
if vote.action=='Nay':
transDict[vote.candidateName].append(voteCount)
elif vote.action=='Yea':
transDict[vote.candidateName].append(voteCount+1)
except:
print "problem getting actionId:%d" %actionId
voteCount+=2
return transDict,itemMeaning
#其实就是获取的事物集。每一条事物集是[0/1,哪条具体规则] #就是将所有必要信息离散化编号然后统计整个投票过程最后得到类似的结果:
Prohibiting Federal Funding of National Public Radio -- Yea --------> Republican Repealing the Health Care Bill -- Yea confidence: 0.995614
mushDatSet = [line.split() for line in open('mushroom.dat').readlines()]
L,suppData = apriori.apriori(mushDatSet,minSupport=0.3)
#寻找毒的公共特征
for item in L[1]:
if item.intersection('2'):print item
frozenset(['2', '59'])