# 机器学习数据挖掘关联规则挖掘Apriori算法python代码实现
来源:互联网 发布:centos libssl dev 编辑:程序博客网 时间:2024/05/22 06:55
对于一个算法的讲解,我的习惯是从一个比较小的例子或者从背景开始讲起,所以前面是引入,对机器学习有一点了解的可以跳过前奏,直接看算法部分,希望我的讲解对大家有所帮助:
- 案例
-“啤酒与尿布”的故事产生于20世纪90年代的美国沃尔玛超市中,沃尔玛的超市管理人员分析销售数据时发现了一个令人难于理解的现象:在某些特定的情况下,“啤酒”与“尿布”两件看上去毫无关系的商品会经常出现在同一个购物篮中,这种独特的销售现象引起了管理人员的注意,经过后续调查发现,这种现象出现在年轻的父亲身上。
那么,这个结论是如何得出的呢?下面我们先简单介绍几个相关概念
关联分析:从大规模数据集中寻找物品间的隐含关系被称作关联分析或者关 联规则学习。这些关系可以有两种形式:频繁项集或者关联规则。
频繁项集:经常出现在一块的物品的集合,也就是所有支持度大于最小支持度的项集称为频繁项集。
关联规则:暗示两种物品之间可能存在很强的关系,形如A->B的表达式,A、B均为某子集,且A与B的交集为空。
通过一个简单的例子认识一下概念:
{葡萄酒,尿布,豆奶}这个集合就是频繁项集。尿布—>葡萄酒就是一个关联规则。
寻找频繁项集时,频繁定义是什么???
再引入两个概念
支持度:定义为数据集中包含该项集的记录所占比例。
{豆奶}的支持度为4/5。
{豆奶,尿布}的支持度为3/5。、
置信度(可信度):针对一条诸如{尿布}—>{葡萄酒}的关联规则来定义的。
这条规则定义为支持度({尿布,葡萄酒})/支持度({尿布})=(3/5)/(4/5)=75%
支持度和可信度是用来量化关联分析是否成功的方法,那么,假设想要找到支持度大于某个值的所有项集,如何做???
(最简单的办法就是生成物品所有可能清单,对每一种组合计算其频繁程度。但当物品种类众多时呢???)
下面我们正式进入Apriori算法:
原理: 如果某个项集是频繁的,那么它的所有子集也是频繁的,换句话说,如果一个项集是非频繁集,那么它的所有超集也是非频繁的。
图中,若已知阴影项集{2,3}是非频繁的。利用Apriori原理,项集{0,2,3},{1,2,3},{0,1,2,3}也是非频繁的。也就是说,一旦计算出了{2,3}的支持度,知道它是非频繁集厚,就不需要再计算{0,2,3},{1,2,3},{0,1,2,3}的支持度了,避免了项集数目的指数增长。
算法流程图:
输入: 数据集[[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
最小支持度0.5
步骤1:候选集C1为{[1],[2],[3],[4],[5]}
支持度分别为0.5,0.75,0.75,0.25,0.75
步骤2:频繁集L1为{[1],[2],[3],[5]}
步骤3:候选集C2为{[1,2],[1,3],[1,5],[2,3],[2,5],[3,5]}
支持度分别为0.25,0.5,0.25,0.25,0.5,0.75,0.5
步骤4:频繁集L2为{[1,3],[2,3],[2,5],[3,5]}
步骤5:候选集C3为{[1,3,5],[2,3,5]}
支持度分别为0.25,0.5
步骤6:频繁集L3为{[2,3,5]}
步骤7:候选集C4为{[]}
结束。
从频繁项集中挖取关联规则
一条规则P→H的可信度定义为support(P∪H)/support(P)
类似于频繁项集的生成,可以为每个频繁项集产生许多关联规则。根据Apriori原理,如果某条规则并不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度要求。 对于右图,如果0,1,2→3不满足最小可信度要求,那么左部{0,1,2}的所有子集的规则也不会满足。
关联规则生成函数简介
类似于Apriori算法,可以首先从一个频繁项集开始,接着创建一个规则列表,其中规则右部只包含一个元素,对这些规则进行测试。
接下来合并所有剩余规则来创建一个新的列表规则,其中规则右部包含两个元素。
- 代码
- `#!/usr/bin/python
# coding=utf-8
import numpy as np
import time
import csv
import os
fp = []
def loadDataSet():
with open(‘fp.csv’, ‘rb’) as f:
reader = csv.reader(f)
for row in reader:
fp.append(row)
return fp
def createDataset(fileName):
fr = open(fileName)
read_line = fr.readlines()
support =[]
for line in read_line:
line = line.strip().replace(‘,’,’ ‘).strip()
splitLine = line.split(’ ‘)
m =len(splitLine)
data_Mat = np.zeros((1,m))
data_Mat[:]=splitLine[:]
support.append(data_Mat[0,: ])
return support
def createC1(dataSet):
# 构建所有候选项集的集合
C1 = []
for transaction in dataSet:
for item in transaction:
if not [item] in C1:
C1.append([item])
# C1添加的是列表,对于每一项进行添加,{1},{3},{4},{2},{5}
C1.sort()
return map(frozenset, C1)
# 使用frozenset,被“冰冻”的集合,为后续建立字典key-value使用。
def scanD(D, Ck, minSupport):
# 由候选项集生成符合最小支持度的项集L。参数分别为数据集、候选项集列表,最小支持度
ssCnt = {}
for tid in D: # 对于数据集里的每一条记录
for can in Ck: # 每个候选项集can
if can.issubset(tid):
# 若是候选集can是作为记录的子集,那么其值+1,对其计数
if not ssCnt.has_key(can):
#ssCnt[can] = ssCnt.get(can,0)+1一句可破,没有的时候为0,加上1,有的时候用get取出,加1
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.insert(0, key) # 超过最小支持度的项集,将其记录下来。
supportData[key] = support
return retList, supportData
def aprioriGen(Lk, k): # 创建符合置信度的项集Ck,
retList = []
lenLk = len(Lk)
for i in range(lenLk):
for j in range(i + 1,lenLk):
# k=3时,[:k-2]即取[0],对{0,1},{0,2},{1,2}这三个项集来说,L1=0,L2=0,
# 将其合并得{0,1,2},当L1=0,L2=1不添加,
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):
C1 = createC1(dataSet)
D = map(set, dataSet)
L1, supportData = scanD(D, C1, minSupport)
L = [L1] # L将包含满足最小支持度,即经过筛选的所有频繁n项集,这里添加频繁1项集
k = 2
while (len(L[k - 2]) > 0): # k=2开始,由频繁1项集生成频繁2项集,
# 直到下一个打的项集为空
Ck = aprioriGen(L[k - 2], k)
Lk, supK = scanD(D, Ck, minSupport)
supportData.update(supK) # supportData为字典,存放每个项集的支持度,
# 并以更新的方式加入新的supK
L.append(Lk)
k += 1
return L, supportData
#< span style = “font-size:18px;” > # ===============关联规则生成函数==================
def generateRules(L, supportData, minConf):
bigRuleList = [] # 规则存放在bigRuleList列表中
for i in range(1, len(L)):
for freqSet in L[i]: # L0是频繁1项集,没关联规则
H1 = [frozenset([item]) for item in freqSet]
# H1存放频繁i项集的某个频繁项集的单个元素集合,
# 频繁3项集的{0,1,2}的{{0},{1},{2}
if i > 1:
rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
# 从频繁3项集开始,从置信度算出关联规则
else:
calcConf(freqSet, H1, supportData, bigRuleList, minConf)
# 对频繁2项集,计算置信度
return bigRuleList
def calcConf(freqSet, H, supportData, br1, minConf):
# 计算置信度函数,conf为最小可信度
prunedH = []
for conseq in H:
conf = supportData[freqSet] / supportData[freqSet - conseq] # conf({2}) = s({{0},{1},{2}})/s({{0},{1},{2}}-{2})
if conf >= minConf:
try:
tra = open(“result.txt”,’a’)
except:
print “Error”
tra.write(str(freqSet - conseq))
tra.write(“–>”)
tra.write(str(conseq))
tra.write(“conf:”)
tra.write(str(conf))
tra.write(“\n”)
print(str(conf))
print freqSet - conseq, “——>”, conseq, “conf:”, conf
# 那么有{{0},{1}}——>{{2}}
br1.append((freqSet - conseq, conseq, conf))
prunedH.append(conseq)
return prunedH
def rulesFromConseq(freqSet, H, supportData, br1, minConf):
m = len(H[0]) # m,频繁m项集
if (len(freqSet)) > (m + 1):
Hmp1 = aprioriGen(H, m + 1) # 由H,创建m+1项集
Hmp1 = calcConf(freqSet, Hmp1, supportData, br1, minConf)
# 保留符合置信度的m+1项集,Hmp1 = prunedH
if (len(Hmp1) > 1):
rulesFromConseq(freqSet, Hmp1, supportData, br1, minConf)
if name ==”main“:
#os.remove(‘result.txt’)
start = time.clock()dataSet = createDataset('fp.csv')#print "数据集D:\n", D#print "所有候选1项集C1:\n", C1#L1, supportData0 = scanD(D, C1, 0.0025)#print '符合最小支持度的频繁1项集L1:\n', L1#L, suppData = apriori(dataSet)#print "所有符合最小支持度0.029的项集L:\n", L#print "频繁2项集:\n", aprioriGen(L[0], 2)#L, suppData = apriori(dataSet, minSupport=0.7)#print "所有符合最小支持度为0.7的项集L:\n", LL, suppData = apriori(dataSet, minSupport=0.015)#print "最小可信度阈值为0.8"print(L)try: da = open('result.txt',"a")except: print "Error"da.write(str(L))rules = generateRules(L, suppData, minConf=0.7)print rulesend =time.clock()print "程序运行时间为:",end,"s"#print("最小可信度阈值为0.5")#rules = generateRules(L, suppData, minConf=0.5)#print rules #< / span >
实验数据:
IT类招聘能力需求信息
[10,13,44,45]
[5]
[3]
[13,44,45]
[3,11,16,17,43,44,45,68,74]
[3,9,17,63,64]
[3,12,16,43,45,63,69,74]
[3,8,9,10,12,15,16,17,19,26,32,43,44,45,46,47,48,49,51,57,63,65,66,67,72]
[47]
[2,3,5,8,9,10,11,13,14,15,16,17,19,32,33,37,43,44,45,46,49,51,56,58,59,62,67,68,71,74,76]
[3,5,8,9,10,12,15,16,17,18,19,27,43,44,45,46,47,49,51,65,66,67,73]
[3,43]
[66]
[62]
… …
实验结果
支持度是:2.9%(一项集支持度的平均值)
频繁一项集:
[[(PHP), (Ajax), (JavaScript), (CSS), (Photoshop), (Oracle), (AI), (Tomcat), (Linux), (python), (数据挖掘), (C++), (机器学习), (单片机), (Spring), (JAVA), (HTML5), (Android), (HTML), (MySQL), (iOS), (图像处理), (hibernate), (socket)]
频繁二项集:
[([Linux, JAVA]), ([JavaScript, CSS]), ([JavaScript, HTML]), ([JAVA, CSS]), ([JAVA, JavaScript]), ([JAVA, PHP]), ([HTML5, HTML]), ([JAVA, HTML]), ([Spring, hibernate]), ([Linux, MySQL]), ([Oracle, JAVA]), ([MySQL, Oracle]), ([python, JAVA]), ([JAVA, Spring]), ([HTML, CSS]), ([MySQL, JAVA])]
频繁三项集:
[([JavaScript, HTML, CSS]), ([JAVA, HTML, CSS]), ([JavaScript, JAVA, CSS]), ([JavaScript, JAVA, HTML])]
频繁四项集:
[([JAVA, JavaScript, HTML, CSS])], []]
可信度是:0.5
(JavaScript) ————> (HTML) 可信度:0.563352826511
(JavaScript) ————> (JAVA) 可信度:1.0
(HTML5) ————> (HTML) 可信度:1.0
(hibernate) ————> (Spring) 可信度:0.735380116959
(Spring) ————> (JAVA) 可信度:0.558576371725
(CSS) ————> (HTML) 可信度:0.666278731452
(HTML) ————> (CSS) 可信度:0.564178369056
(JavaScript) ————> ([JAVA, HTML]) 可信度:0.563352826511
([JavaScript, CSS]) ————> ([JAVA, HTML]) 可信度:0.856103476152
([JavaScript, HTML]) ————> ([JAVA, CSS]) 可信度:0.732871972318
([JAVA, CSS]) ————> ([JavaScript, HTML]) 可信度:0.657355679702
([JAVA, HTML]) ————> ([JavaScript, CSS]) 可信度:0.523738872404
可信度是:0.7
(JavaScript) ————> (JAVA) 可信度:1.0
(HTML5) ————> (HTML) 可信度:1.0
(hibernate) ————> (Spring) 可信度:0.735380116959
([JavaScript, CSS]) ————> ([JAVA, HTML]) 可信度:0.856103476152
([JavaScript, HTML]) ————> ([JAVA, CSS]) 可信度:0.732871972318
希望对大家有所帮助,如有错误,还需大家指正。