数据挖掘学习:Apriori算法原理及其实现
基本概念
支持度与置信度
关联规则中的支持度和置信度是规则兴趣度的两种度量。它们分别反映所发现的规则的有用性和确定性
支持度:表示项集X在总数据集中出现的概率
置信度:包含X和Y的项集数与包含X的项集数之比:
- 关联规则的置信度反映了,如果项集中出现X,那么同时出现Y的概率是多少。
- 例如:关联规则R1:{brea}→{milk}的可信度为 confidence(R1)=support({bread, milk})/ support({bread})= 0.5/0.7 =5/7。
项集的最小支持度与频繁集
用于发现关联规则的项集必须满足最小支持度的阈值,称为项集的最小支持度,记为supmin 。
- 从统计的意义上讲,它表示用户关心的关联规则必须满足的最低要求,最低重要性。
- 只有满足最小支持度的项集才能产生关联规则。
支持度大于或者等于supmin的项集称为频繁项集,简称频繁集,反之称为非频繁集。
- 通常,k-项集如果满足supmin,可称为k-频繁集,记作Lk 。
强关联规则
关联规则的最小支持度记为supmin,最小置信度记为confmin。
如果关联规则同时满足如下2个条件:
- support(X → Y)≥ supmin
- confidence(X→Y)≥ confmin
则称关联规则为强关联规则,否则为弱关联规则。
筛选出来的强关联规则可用于指导决策。
Apriori算法简介
Apriori算法是一个关联规则挖掘算法,也是最经典的算法。它利用逐层搜索的迭代方法找出数据库中项集的关系,以形成规则,其过程由连接与剪枝组成。
Apriori算法通过多次扫描数据集,找出所有频繁集,然后用这些频繁集产生强关联规则。
Apriori算法通过迭代来穷举出数据集中的所有频繁集。
Apriori算法的性质:频繁集的所有非空子集也一定是频繁的。
算法示例及其过程
算法过程:
- 输入数据集D,最小支持度阈值supmin ;
- 首先,产生1-频繁集 L1 ;
- 随后,在 L1 上通过连接和修剪产生2-频繁集 L2 ;
- 依次类推,可在 Lk 上通过连接和修剪产生(k+1) - 频繁集 Lk+1 ;
- 最后,直到无法产生新的频繁集为止。
连接: 只相差一个项的两个项集才能进行连接(集合的“合并“操作)
例如:由L2生成C3的过程中,L2中的{A,C}和{B,C}只相差一个项,因此它们可以连接生成{A,B,C}。 但是L2中的{A,C}和{B,E}无法进行连接。
修剪: 去除子集不是频繁集的项集(算法性质)
例如:虽然L2中的{A,C}和{B,C}可以连接生成{A,B,C},但是由于{A,B,C}的子集{A,B}不是频繁集(不在L2中),因此,在生成L3时,需要从C3中删除{A,B,C} 。
Apriori算法的实现
这次代码所用的数据集是博主的一次作业要求,因此这次代码也针对的是一次实验,泛用性有待验证,如有错误敬请指出。
作业要求:
- 编写Apriori算法程序。
- 用Apriori 算法找出频繁项集,支持度和置信度根据情况自行设定。
- 找出强关联规则以及相应的支持度和置信度。
资源已经上传到了博主的资源库中,有需要的朋友们可以去下载体验。代码有所参考书籍《机器学习实战》,《数据挖掘:概念与技术》内容。
代码如下:
import xdrlib,xlrd #读 excel
File='Apriori_1000_Items_DataSet.xls' # 获取数据文件
##Apriori 算法
##1.获取数据集 Datasets
try:
workbook = xlrd.open_workbook(File)#打开 excel 文件
table = workbook.sheet_by_index(0)#打开第一个工作表
nrows = table.nrows#获取当前行
ncols = table.ncols#获取当前列
datasets = [] #数据集
for row in range(2, nrows):
cell_value = table.row_values(row, 1) # 获取第二列中单元格的数据
item = cell_value[0] # 将获取的数据化为字符串
excle_soloCell = [] # 空列表,装单个数据的分离,并每次循环置空
for i in range(0, len(item)):
excle_soloCell.append(item[i])
datasets.append(excle_soloCell) # 把数据追加到 excel_list 中
print('数据集 Datasets:',end='')
print(datasets)
except Exception as e:
print(str(e))
# 2.从 datasets 中获取候选集 C1
# 因数据集中无空集等多余数据所以候选集C1即为datasets
def creatC1(dataSet):
C1 = []
for transaction in dataSet:
for item in transaction:
if not item in C1:
if item == 0: # 0->'false' 1->'true'!
item = 'false'
if item == 1:
item = 'true'
if {item} not in C1:
C1.append({item})
return list(map(frozenset,C1))#frozenset 是冻结的集合,不可以增添或删除或改变
#3.扫描候选集,生成 k-频繁项集 Lk
##分为两步:3.1 扫描 3.2 组合
##3.1 扫描,返回频繁集 Lk
def scanDatasets(Datasets,Ck,minSupport):
item_count = {} #计算候选频繁集中每个项在 Datasets 中的数量。这是一个字典,key 是频繁项集中的项,value 是这些项的个数
for transaction in Datasets:
for item in Ck:
if item.issubset(transaction):
if item not in item_count.keys():
item_count[item] = 1
else:
item_count[item] +=1
transaction_number = float(len(Datasets))
frequentSet = [] #频繁项集
supportData = {} #key:候选项 item in Ck value:支持度
for key in item_count:
support = item_count[key]/transaction_number
supportData[key] = support
if support>=minSupport:
frequentSet.append(key)
return frequentSet,supportData
##3.2 组合,通过 Lk 频繁项集构造 Ck+1 候选项集
def apriori_Gen(Lk,k):#k 是要组合成的 k 候选集 Lk 的类型是集合 set
Ck = []#ck+1 候选项集
for i in range(len(Lk)):
for j in range(i+1,len(Lk)):
L1 = list(Lk[i])[0:k-2]
L2 = list(Lk[j])[0:k-2]
if L1==L2:
Ck.append(Lk[i]|Lk[j])#Lk 元素的类型是集合(frozenset)这里‘|’是并集的操作
return Ck
##4 apriori 算法主函数
def apriori(Datasets,minsupport):
C1 = creatC1(Datasets)
L1,supportData = scanDatasets(Datasets,C1,minsupport)
L = [L1]
k = 2
while(len(L[k-2])>0): #L[k-2]就是 L(k-1) 当上一个频繁项集不等于 0 是循环才能进行下去
Ck = apriori_Gen(L[k-2],k)
Lk,supK = scanDatasets(Datasets,Ck,minsupport)
supportData.update(supK)
L.append(Lk)
k +=1
return L,supportData
L,supportData = apriori(datasets,0.2)#此处输入关联规则的最小支持度
print('频繁项集:')
frequentsest_number = 1
for frequentset in L:
print(frequentset)
print('%d-频繁项集的个数为 %d'%(frequentsest_number,len(frequentset)))
frequentsest_number += 1
def calcConf(freqSet, H, supportData, brl, minConf):
# calcConf(对两个元素的频繁项,计算可信度,例如: {1,2}/{1} 或者 {1,2}/{2} 看是否满足条件)
# freqSet 频繁项集中的元素,例如: frozenset([1, 3])
# H 频繁项集中的元素的集合,例如: [frozenset([1]), frozenset([3])]
# prunedH 记录 可信度大于阈值的集合
prunedH = []
for conseq in H:
conf = supportData[freqSet]/supportData[freqSet-conseq]
if conf >= minConf: # 只要买了 freqSet-conseq 集合,一定会买 conseq 集合(freqSet-conseq 集合和 conseq 集合是全集)
print (freqSet-conseq, '-->', conseq, 'conf:', conf)
brl.append((freqSet-conseq, conseq, conf))
prunedH.append(conseq)
return prunedH
def rulesFromConseq(freqSet, H, supportData, brl, minConf):
m = len(H[0])
if (len(freqSet) > (m + 1)):
# 生 成 m+1 个 长 度 的 所 有 可 能 的 H 中 的 组 合
Hmp1 = apriori_Gen(H, m+1)
# 返回可信度大于最小可信度的集合
Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
# 计算可信度后,还有数据大于最小可信度的话,那么继续递归调用,否则跳出递归
if (len(Hmp1) > 1):
rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
# 生成关联规则
def generateRules(L, supportData, minConf):
# L 频繁项集列表
# bigRuleList 可信度规则列表(组合)
bigRuleList = []
for i in range(1, len(L)):
# 获取频繁项集中每个组合的所有元素
for freqSet in L[i]:
# 组合总的元素并遍历子元素,并转化为 frozenset 集合,再存放到 list 列表中
H1 = [frozenset([item]) for item in freqSet]
# 2 个的组合,走 else, 2 个以上的组合,走 if
if (i > 1):
rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
else:
calcConf(freqSet, H1, supportData, bigRuleList, minConf)
return bigRuleList
print('关联规则')
associationRule = generateRules(L,supportData,0.4) #此处修改关联规则的最小置信度
print('关联规则个数:',len(associationRule))
以上便是Apriori算法个人学习与理解的主要内容。Apriori算法主要针对的还是各类购物篮的关联分析问题,可以给商家一个促销的契机
.
博主第一篇博文,不定期更新,新人上路,敬请指教。