机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析

关键字:Apriori、关联规则挖掘、频繁项集
作者:米仓山下
时间:2018-11-2
机器学习实战(Machine Learning in Action,@author: Peter Harrington)
源码下载地址:https://www.manning.com/books/machine-learning-in-action
git@github.com:pbharrin/machinelearninginaction.git

*************************************************************
一、Apriori算法——生成频繁项集

Apriori算法原理:
原理:如果某个项集是频繁的,那么它所有的子集也是频繁的。反过来,如果一个项集是非频繁集,那么他所有的超集也是非频繁的
--------------------------------------------------------------
#创建测试数据集,包含四个列表的列表:[[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
loadDataSet()
#根据测试数据集生成第一个频繁项集,频繁项为单个
createC1(dataSet)
#根据给定的频繁项集Ck,支持度minSupport,计算在数据集D中Ck各频繁项的支持度,并返回支持度大于minSupport的频繁项(数组),及所有频繁项的支持度(频繁项为key,支持度为value的字典)
scanD(D, Ck, minSupport)
--------------------------------------------------------------
#根据给定频繁项集生成下Lk,通过集合并集运算,得到频繁项集Lk+1。

def aprioriGen(Lk, k): #creates 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: #if first k-2 elements are equal
retList.append(Lk[i] | Lk[j]) #set union
return retList

#注:这里强调一下为什么只比较前k-2元素,书中强调的原因是可以减少循环次数,但并没有进一步解释这样做的逻辑。示例数据中,两项的频繁项集为[{2,3}, {3,5}, {2,5}, {1,3}],所有两两并集为[{2,3,5},{1,3,5}]。但是如果仅比较前k-2个元素相同的进行合并为[{2,3,5}],之所以没有{1,3,5}是因为{1,5}不存在,即它不是频繁项集,按照Apriori的原理“某个子项集不是频繁的,那么它的超集也不是频繁的”。因此比较前k-2个元素既可以减少循环次数又不会漏掉频繁项。

--------------------------------------------------------------
#不断扫描数据集,由单元素频繁项不断合并,并求解它们的支持度,记录下符合条件的频繁项,以及频繁项的支持度

def apriori(dataSet, minSupport = 0.5):
C1 = createC1(dataSet) #生成单元素频繁项集
D = 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) #合并频繁项集形成新的候选集
Lk, supK = scanD(D, Ck, minSupport) #计算候选集的支持度,并筛选
supportData.update(supK) #更新存储频繁项支持度的词典
L.append(Lk) #将最新得到的频繁项加入列表中
k += 1
return L, supportData

--------------------------------------------------------------
测试:

>>> import apriori
>>> data=apriori.loadDataSet()
>>> data
[[, , ], [, , ], [, , , ], [, ]]
>>> L,supportData=apriori.apriori(data)
>>> L
[[frozenset([]), frozenset([]), frozenset([]), frozenset([])], [frozenset([, ]), frozenset([, ]), frozenset([, ]), frozenset([, ])], [frozenset([, , ])], []]
>>> supportData
{frozenset([]): 0.75, frozenset([]): 0.75, frozenset([, , ]): 0.5, frozenset([, ]): 0.25, frozenset([, ]): 0.25, frozenset([, ]): 0.5, frozenset([]): 0.25, frozenset([, ]): 0.5, frozenset([, ]): 0.75, frozenset([]): 0.5, frozenset([, ]): 0.5, frozenset([]): 0.75}
>>>

*************************************************************
二、Apriori算法——从频繁项集中挖掘关联规则

置信度:
  置信度(confidence)揭示了A出现时B是否一定出现,如果出现,则出现的概率是多大。如果A->B的置信度是100%,则说明A出现时B一定会出现(返回来不一定)。用公式表示是,物品A->B的置信度=物品{A,B}的支持度 / 物品{A}的支持度:(A称为前件,B称为后件)
Confidence(A->B) = support({A,B}) / support({A}) = P(B|A)

如果某条规则不满足最小可信度要求,那么该规则的所有子集也不会满足最小置信度要求。假设{0,1,2}->{3}不满足最小可信度的要求。那么任何{0,1,2}的子集也不会满足最小可信度的要求。可以利用该性质来减少需要测试的规则数目。

--------------------------------------------------------------
#规则生成函数

def generateRules(L, supportData, minConf=0.7):  #supportData is a dict coming from scanD
bigRuleList = [] #存储关联规则的列表
for i in range(1, len(L)): #取出两个或更多元素的频繁项集,L[0]为单元素频繁项集,遍历
for freqSet in L[i]: #遍历频繁项集L[i]中的频繁项
H1 = [frozenset([item]) for item in freqSet] #某个频繁项中的元素列表
if (i > 1): #元素大于两个的频繁项,将频繁项中的元素进行组合成后件(规则)
rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
else: #i=1,两个元素的频繁项
calcConf(freqSet, H1, supportData, bigRuleList, minConf)
return bigRuleList

--------------------------------------------------------------
#计算可信度
#输入:freqSet——频繁项, H——频繁项元素列表, supportData——频繁项支持度列表, brl——存储关联规则的列表, minConf——最小可信度
#输出:brl——频繁项freqSet中存在的关联规则,prunedH——返回关联规则中的后件列表

def calcConf(freqSet, H, supportData, brl, minConf=0.7):
prunedH = [] #关联规则中的后件列表
for conseq in H: #遍历频繁项中的元素,conseq为元素
conf = supportData[freqSet]/supportData[freqSet-conseq] #可信度(freq-conseq)->conseq
if conf >= minConf: #可信度>minConf
print freqSet-conseq,'-->',conseq,'conf:',conf #打印关联规则及可信度
brl.append((freqSet-conseq, conseq, conf)) #保存关联规则及可信度
prunedH.append(conseq) #保存后件(规则),为后面准备。注:不满足规则的后件,在该元素基础下添加也不会满足
return prunedH

--------------------------------------------------------------
#最初的规则生成更多的规则
#输入:freqSet——频繁项, H——频繁项元素列表;输出:brl——频繁项freqSet中存在的关联规则

def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
m = len(H[0])
if (len(freqSet) > (m + 1)): #频繁项元素数目>后件(候选规则)的元素数,一直执行。例如{1,2,3,4}当{1}-{2,3,4}以后此时H[0]长度为3
Hmp1 = aprioriGen(H, m+1) #合并候选后件(规则),由Hm生成Hm+1。注:不满足规则的后件,在该元素基础下添加也不会满足
Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf) #返回规则后件(规则)列表
if (len(Hmp1) > 1): #返回后件(规则)列表包含1个以上后件(规则),递归进一步组合这些规则
rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)

--------------------------------------------------------------
测试:

>>> reload(apriori)
<module 'apriori' from 'apriori.py'>
>>> L, supportData=apriori.apriori(data)
>>> L
[[frozenset([1]), frozenset([3]), frozenset([2]), frozenset([5])], [frozenset([1, 3]), frozenset([2, 5]), frozenset([2, 3]), frozenset([3, 5])], [frozenset([2, 3, 5])], []]
>>> supportData
{frozenset([5]): 0.75, frozenset([3]): 0.75, frozenset([2, 3, 5]): 0.5, frozenset([1, 2]): 0.25, frozenset([1, 5]): 0.25, frozenset([3, 5]): 0.5, frozenset([4]): 0.25, frozenset([2, 3]): 0.5, frozenset([2, 5]): 0.75, frozenset([1]): 0.5, frozenset([1, 3]): 0.5, frozenset([2]): 0.75}
>>> rules=generateRules(L, supportData, minConf=0.6)
frozenset([3]) --> frozenset([1]) conf: 0.666666666667
frozenset([1]) --> frozenset([3]) conf: 1.0
frozenset([5]) --> frozenset([2]) conf: 1.0
frozenset([2]) --> frozenset([5]) conf: 1.0
frozenset([3]) --> frozenset([2]) conf: 0.666666666667
frozenset([2]) --> frozenset([3]) conf: 0.666666666667
frozenset([5]) --> frozenset([3]) conf: 0.666666666667
frozenset([3]) --> frozenset([5]) conf: 0.666666666667
frozenset([5]) --> frozenset([2, 3]) conf: 0.666666666667
frozenset([3]) --> frozenset([2, 5]) conf: 0.666666666667
frozenset([2]) --> frozenset([3, 5]) conf: 0.666666666667
>>>
>>> rules=generateRules(L, supportData, minConf=0.7)
frozenset([1]) --> frozenset([3]) conf: 1.0 #出现1集合中一定出现了3
frozenset([5]) --> frozenset([2]) conf: 1.0 #出现5集合中一定出现了2
frozenset([2]) --> frozenset([5]) conf: 1.0 #出现2集合中一定出现了5
>>>
>>> rules
[(frozenset([1]), frozenset([3]), 1.0), (frozenset([5]), frozenset([2]), 1.0), (frozenset([2]), frozenset([5]), 1.0)]
>>>

*************************************************************
三、示例:发现毒蘑菇的相似特征
数据集:mushroom.dat
说明:mushroom数据集是关于肋形蘑菇的23种特征的数据集,每个特征都包含一个标称数据值。
mushroom.dat前几列数据为:
1 3 9 13 23 25 34 36 38 40 52 54 59 63 67 76 85 86 90 93 98 107 113
2 3 9 14 23 26 34 36 39 40 52 55 59 63 67 76 85 86 90 93 99 108 114
2 4 9 15 23 27 34 36 39 41 52 55 59 63 67 76 85 86 90 93 99 108 115
第一个特征表示有毒(2)或则可食用(1),下一特征为蘑菇伞的形状,六种可能的值3-8表示。

#将数据读取转换为集合
>>> mushDataSet=[line.split() for line in open('mushroom.dat').readlines()]
>>> mushDataSet[0]
['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
>>> len(mushDataSet)
8124 #生成频繁项集
>>> L, supportData=apriori.apriori(mushDataSet,minSupport = 0.3)
>>> len(L)
10
>>> L[9]
[]
>>> L[8]
[frozenset(['', '', '', '', '', '', '', '', '']), frozenset(['', '', '', '', '', '', '', '', '']), frozenset(['', '', '', '', '', '', '', '', '']), frozenset(['', '', '', '', '', '', '', '', ''])]
>>> #所有特征的标称性数值并不重复,打印长度为8的所有有毒(2)的频繁项
>>> for item in L[7]:
... if item.intersection(''):print item
...
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
frozenset(['', '', '', '', '', '', '', ''])
>>>

#这样就可以看到有哪些特征的蘑菇大概率是毒蘑菇。但:并不表示没有这些特诊的蘑菇就没有毒

*************************************************************
四、总结
关联分析用于发现大规模数据集中元素间有趣关系。通过两种两种方式量化这些有趣关系:第一种是使用频繁项集,给出经常一起出现的元素项;第二种是关联规则,每条关联规则意味着元素之间“如果……那么”的关系。

减少扫描频繁项统计扫描次数的方法就是Apriori。Apriori原理是说如果一个元素项是不频繁的那么包含该元素的超集也是不频繁的。Apriori算法从单元素项集合开始,通过组合满足最小支持度要求的项集来形成更大的集合。支持度用来度量一个集合在原始数据中出现的频率。

原始数据中每条数据是集合,但并不要求每条数据具有相同的长度

缺点:每次增加频繁项集的大小,Apriori算法都会扫描整个数据集。数据集很大时会降低频繁项集发现的速度。相比,12章中FPgrowth算法只需要对数据库进行两次扫描,能够显著加快频繁项集发现速度

参考文献:
https://blog.csdn.net/wanghao109/article/details/39452303
https://www.cnblogs.com/bigmonkey/p/7405555.html
https://blog.csdn.net/zllnau66/article/details/81534368

机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析的更多相关文章

  1. 机器学习实战 - 读书笔记(11) - 使用Apriori算法进行关联分析

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第11章 - 使用Apriori算法进行关联分析. 基本概念 关联分析(associat ...

  2. 机器学习实战 [Machine learning in action]

    内容简介 机器学习是人工智能研究领域中一个极其重要的研究方向,在现今的大数据时代背景下,捕获数据并从中萃取有价值的信息或模式,成为各行业求生存.谋发展的决定性手段,这使得这一过去为分析师和数学家所专属 ...

  3. 学习笔记之机器学习实战 (Machine Learning in Action)

    机器学习实战 (豆瓣) https://book.douban.com/subject/24703171/ 机器学习是人工智能研究领域中一个极其重要的研究方向,在现今的大数据时代背景下,捕获数据并从中 ...

  4. K近邻 Python实现 机器学习实战(Machine Learning in Action)

    算法原理 K近邻是机器学习中常见的分类方法之间,也是相对最简单的一种分类方法,属于监督学习范畴.其实K近邻并没有显式的学习过程,它的学习过程就是测试过程.K近邻思想很简单:先给你一个训练数据集D,包括 ...

  5. 【机器学习实战】第11章 使用 Apriori 算法进行关联分析

    第 11 章 使用 Apriori 算法进行关联分析 关联分析 关联分析是一种在大规模数据集中寻找有趣关系的任务. 这些关系可以有两种形式: 频繁项集(frequent item sets): 经常出 ...

  6. Coursera 机器学习 第6章(下) Machine Learning System Design 学习笔记

    Machine Learning System Design下面会讨论机器学习系统的设计.分析在设计复杂机器学习系统时将会遇到的主要问题,给出如何巧妙构造一个复杂的机器学习系统的建议.6.4 Buil ...

  7. 【python与机器学习实战】感知机和支持向量机学习笔记(一)

    对<Python与机器学习实战>一书阅读的记录,对于一些难以理解的地方查阅了资料辅以理解并补充和记录,重新梳理一下感知机和SVM的算法原理,加深记忆. 1.感知机 感知机的基本概念 感知机 ...

  8. 机器学习——使用Apriori算法进行关联分析

    从大规模的数据集中寻找隐含关系被称作为关联分析(association analysis)或者关联规则学习(association rule learning). Apriori算法 优点:易编码实现 ...

  9. Machine Learning(Andrew Ng)学习笔记

    1.监督学习(supervised learning)&非监督学习(unsupervised learning) 监督学习:处理具有若干属性且返回值不同的对象.分为回归型和分类型:回归型的返回 ...

随机推荐

  1. Nginx 配置 Location 规则优先级问题

    nginx 的 location与配置中 location 顺序没有关系,与 location 表达式的类型有关.相同类型的表达式,字符串长的会优先匹配. 以下是按优先级排列说明: 等号类型(=)的优 ...

  2. java学习-http中get请求的非ascii参数如何编码解码探讨

    # 背景: 看着别人项目代码看到一个PathUtils工具类, 里面只有一个方法,String  rebuild(String Path),将路径进行URLDecoder.decode解码,避免路径中 ...

  3. 记一次解决CSS定位bug思路

    事因 网站中的遮罩层大都有一个问题,就是在这个遮罩层中滑动,里面的内容也会跟着滑动,我是这样想的,既然都有这个问题,干脆写一个通用的插件出来,省的每个还得单独处理.如果是单独处理这个问题是比较好解决的 ...

  4. SSO - 开篇引例

    进公司以来, 所做的产品中, 下面的子系统就没有少于10个的, 其中有的是.net做的, 有的是java做的, 还有安卓端, ios端. 那么这么多子系统, 我可能需要访问其中的多个(同一平台), 我 ...

  5. javaweb的web.xml配置说明,初始化过程

    [重点]初始化过程可知容器对于web.xml的加载过程是context-param >> listener  >> fileter  >> servlet 首先了解 ...

  6. SpringDataJPA快速入门

    访问我的博客 前言 之前在学习 SpringBoot 框架的时候,使用到了 SpringData JPA,但是当时只是简单的查询,没有用到稍微复杂的查询. JPA 的 JPQL 语法规则对于简单的查询 ...

  7. Tomcat学习总结(11)——Linux下的Tomcat安全优化

    1.web.xml配置及修改: 站点默认主页: <welcome-file-list> <welcome-file>index.html</welcome-file> ...

  8. SQL-结构化查询语言(2)

    使用explain查询select查询语句的执行计划 mysql> explain select * from student where Sname='金克斯'\G ************* ...

  9. Java Web 项目简单配置 Spring MVC进行访问

    所需要的 jar 包下载地址: https://download.csdn.net/download/qq_35318576/10275163 配置一: 新建 springmvc.xml 并编辑如下内 ...

  10. python的Web框架,Django模板变量,过滤器和静态文件引入

    HTML模板的路径查找 在setting中设置查找路径: #默认的查找在此处填写,优先级最高,为在manage.py的同级路径中,添加(常规是template)文件夹,在(template)文件夹中配 ...