Apriori和fp-growth是频繁项集(frequent itemset mining)挖掘中的两个经典算法,主要的区别在于一个是广度优先的方式,另一个是深度优先的方式,后一种是基于前一种效率较低的背景下提出来的,虽然都是十几年前的,但是理解这两个算法对数据挖掘和学习算法都有很大好处。在理解这两个算法之前,应该先了解频繁项集挖掘是做什么用的。

频繁项集挖掘是关联规则挖掘中的首要的子任务。关联规则挖掘是要找出一个数据集上,满足一定条件的项集。这些项的集合能构成 形如蕴含式"A=>B"这样的“规则”。这个"=>"符号是通过一些条件来定义的,如果没有条件那当然所有的项组合都能形成这样的关系。频繁程度就是一种要求,也就是AB共同次数出现了超过阈值。 A和B能否形成"=>"规则, 就要根据定义来算,那首先就得把A、B需要的条件挖出来,也就是频繁项集挖掘要做的。

关联规则定义比较容易能搜到,频繁项集挖掘简单的说就是:给定一个项列表list = {A,B,C,...},一个数据集D的每条记录都是list 的子集,要找出数据集中频繁共同出现次数超过阈值t,也就是支持度,的所有组合。

这个挖掘其实不好做,因为结果可能是list 中所有项的组合,有2^|list|个可能,搜索空间是个组合爆炸的空间。看下图,先别看红字红线:

要弄好这件事不仅需要有效减小搜索空间,而且对每个可能的搜索都必须快速完成。所以频繁项集挖掘在算法实践和编码实现上就要有非常强的技巧。我们就来深入学习apriori和fp-growth中的搜索方式和技巧。这两个算法很容易找到完整的步骤,这里会更注重里面一些精彩之处,但是可能书写不会那么规范,建议和完整算法对照来读。

先来看看apriori。Apriori采用广度优先的搜索方式,缩小搜索空间用到了一个称为apriori的性质。Apriori性质是这么说的:频繁项集的所有非空子集必然也是频繁的。这是很显然的,比如 同时包含项AB的记录条数肯定比只包含A的记录少。这条性质反过来也可以这么说:如果一个项集是非频繁的,那么它的超集必然也是非频繁的。

算法过程如下:

输入:数据集D,支持度minsup

输出:满足支持度的所有项集的集合L

L1 = 发现1-项集(D);

for (k=2;Lk-1 ≠Φ ;k++) {

Ck = 连接剪枝生成(Lk-1, minsup)

扫描D,为Ck中每个项集c 统计 c.count

保留Lk ={c ∈ Ck|c.count≥min_sup}

L = L ∪ Lk

}

Return L

其中算法精华在于 连接剪枝生成(Lk-1, minsup) 这一步, 包含连接步和剪枝步两个动作:

1. 连接步:长度k-1的项连接成长度k的项;具体就是对两个k-1长的项L1和L2,必须满足前k-2个项都相同才能连接,最后把L1和L2剩下的最后一项加起来,形成k的长度的项。

2. 剪枝步:k项连接完成后,检查其所有k-1子集是否是频繁的,如果是,才保留作为候选项。

可以通过一张截图来演示一下apriori的过程:

对应第一张图,连接步是从第k层的项集,向下扩展一层的候选项集,剪枝步能够通过apriori性质过滤掉那些肯定非频繁的项集。

Apriori的框架其实很小,但是可以想象得到主要的两个步骤: 连接+剪枝(也就是候选集生成),以及,候选集统计是很耗费时间的。

剪枝步也需要对每个k-候选项集的k-1子集都进行一次检测,也很耗费时间;统计频繁次数是必须的,因此需要扫描数据库,经历I/O。那么有必要剪枝,直接统计会不会更好呢,虽然没有试验过,但我估计还是剪枝以后减少候选集的统计更划算。而这两个耗时的步骤在实现上如果能使用到技巧,对算法时间影响最直接。比如剪枝步中k-1候选项集需要逐一向已有的k-1频繁项集查询,这用什么数据结构最好?又如扫描数据库的时候是否能过进行一些压缩,相同的记录进行合并减少遍历次数,以及过滤掉对统计没用的记录?

面对apriori的问题,感觉Fp-growth突然间就冒出来了,它是一个挖掘方式和apriori完全不一样的算法,直接看可能不那么像apriori直观,因为算法一开始就介绍了它采用的数据结构和挖掘方式。所以我们先对比下apriori和fp-growth的差异在哪,再介绍它的算法。

简单的说apriori是先产生一批候选项集,再通过原数据集去过滤非频繁项集:先找A、B、C,检查一下通过了,再找AB、AC、AB,检查又通过了,再到ABC... 这样的广度优先的方式。而fp-growth是先从数据集中找频繁的项,再从包含这个频繁项的子数据集中找其他的频繁项,把它们俩连起来也肯定是频繁的:先找A,再在找包含A的子数据库里,找到B,就得到AB是频繁,再再包含AB的子数据库里,找到C,ABC就是频繁了。

在了解了fp-growth的大致思路以后,我们就能介绍它采用的数据结构和算法了。

首先fp-growth采用了一个叫fp-tree 的数据结构去压缩存储数据集,放到内存里,这样以后过问原数据集的事就不必经过IO了。

Fp-tree主要是一种前缀树,和字典树(trie)接近,并且节点把项的次数也记录下了。字符的顺序有所不同,字典树用的是字母表顺序,fp-tree (frequent pattern tree)用的是字母表的频率降序,这样的好处是出现次数多的项作为共享前缀的概率也大,fp-tree的压缩率就高(后面还会提到),根据apriori性质,非频繁的项没用,因此fp-tree上可以没有它们。

根据前面提到fp-growth步骤,需要找数据库上包含某个项的子数据库,不能从树根开始搜索,因此为了方便,需要把fp-tree中所有枝干、叶子上相同的项全串一起,这样项从一个起点开始,向树根遍历,就能得到包含这个项的子数据库了。这些起点和串起相同节点的链就是fp-tree的另一个部分:头表和兄弟链。头表包含树上所有的单项,并是兄弟链的起点,那么fp-tree不仅完整记录了数据库里所需的信息,还能找到对任一项找到包含了它的子数据库。

有了fp-tree,挖掘频繁项集就变得直观了。首先是压缩数据库,过滤非频繁项,得到一棵fp-tree 1号,对于一个项,比如A,通过兄弟链,遍历树找出 包含A的子树(库),又称A的条件模式树(库),英文原文叫condition pattern tree(base)。然后把这个子库当做一个新的数据库2号,过滤2号库非频繁项,建立一个小点的fp-tree 2号,那么那个A与这个2号树里的所有项,连起来肯定也是频繁的;比如有B,同理把B的条件树找出,也建立个fp-tree 3号,就能得到AB和3号树上的项连起来也肯定是频繁的。这个过程递归完成,建立不出条件子树递归就跳出去。

算法包含两个部分:

1. 是建立fp-tree:扫描一遍数据库,得到每个项的支持度,排序并过滤非频繁项;再扫描一次数据库,每条记录按顺序排序,添加到fp-tree上。

2. 调用算法FP_growth(FP-tree, null)。

Function Fp_growth(FP-tree, a){

if(fp-tree 是单条路径){

对路径上的组合b, 都连接a,输出b∪ a

}else{

For each 项ai in 头表{

输出一个模式b= ai∪ a,其支持度 support =ai.support

构造b的条件模式库,然后构造b的条件模式树 Treeb;

If (Treeb 不为空){

调用算法FP_growth(Treeb,b )

}

}

}

FP_growth是个递归算法,期间需要反复遍历树和构建fp-tree。fp-growth中判断单路径部分可以不要,最后实际结果其实是和下面部分是一样的,但是直接计算单路径产生所有组合会便捷很多。另外一点,fp-tree要按支持度降序的顺序的好处有几点?前面说了可以提高共享前缀的可能,提高压缩率,树小了,遍历的步数还能减小,寻找最优压缩的顺序是个NP难问题,因此选这个办法能有个比较好的压缩率足够了。

fp-growth虽然号称不产生候选集,但是实际上候选集产生已经在寻找条件子库的时候隐隐产生了,剪掉非频繁候选项的时候是通过建树步骤中的第一小步完成的。

fp-growth在实现上也可以有很多技巧,比如寻找条件子树的时候,同一条路径会被遍历很多次,如何有效避免(后来han自己提出,遇到扫把型的fp-tree,即上面是单路径、下面分叉的,可以把单路径所有的组合分别连接到下面的部分挖掘结果上输出,那就不用遍历上面的单路径了) 另外树上节点用什么数据结构保存指向子孙节点的指针,能同时兼顾查询时间和空间?

最后我们总结一下apriori和fp-growth之间的联系和差异。

初读fp-growth算法,估计都感觉不到它和apriori有什么关系,但我个人猜测fp-growth是从apriori的统计候选集太耗时的那里 改良开始的,希望实现候选项集的更快速的计算支持度,最后就彻底的改变的搜索频繁项集的方式。我觉得两个算法的最根本的差异在于apriori是以搜索项集组合的空间作为基础,通过数据库来对照。而fp-growth是以数据库为基础,在里面寻找项集是否频繁,表现为搜索方式一个是广度优先一个是深度优先。。

apriori的那剪枝步和统计支持度在fp-growth上就是不断的建fp-tree和遍历。而前者的统计需要经过的IO,后者已经压缩到内存了;但fp-growth不是在所有数据集上都比apriori强,比如在稀疏的数据集上,fp-tree每个节点可能包含非常多子孙,因此保存子孙节点的指针也是很大开销,fp-tree本来就是通过压缩使得数据集能被内存容纳,结果导致最后fp-tree起不到压缩效果适得其反。优化实现的apriori在稀疏数据集上也往往比fp-growth要快。

这里fp-growth在大部分地方是完胜了apriori,后面很多改进都是基于深度优先的思想,并且更注重实现上的技巧。现在我们也没必要去费太多精力去改进这两个算法了,因为频繁项集挖掘是个组合爆炸的时间复杂度。在2003 2004年ICDM举办过两个workshop就是专门比谁实现的频繁项集挖掘最好(搜"FIMI 03",网站里有很多的源码)。在这里想多提一点,数据挖掘中,没有算法能在所有数据集上PK掉其他算法。因此我们应该了解一种任务的多种算法,看看它们为什么和如何在不同的数据集上体现出自己的优势,这样,通过比较我们不仅能更好的理解和掌握它们的精华,更能在当我们遇到新的数据集的时候,选取合适算法甚至做出针对性的优化措施。

频繁项集挖掘之apriori和fp-growth相关推荐

  1. 频繁项集挖掘算法——Apriori算法

    前言 关联规则就是在给定训练项集上频繁出现的项集与项集之间的一种紧密的联系.其中"频繁"是由人为设定的一个阈值即支持度 (support)来衡量,"紧密"也是由 ...

  2. 关联分析/频繁项集挖掘:Apriori算法

    简介 Apriori是一种流行的算法,用于在关联规则学习中提取频繁项集.Apriori算法被设计用于对包含交易的数据库进行操作,例如商店客户的购买.如果项目集满足用户指定的支持阈值,则该项目集被视为& ...

  3. 数据挖掘---频繁项集挖掘Apriori算法的C++实现

    1 准备   首先实现这个算法是基于中南大学软件学院数据挖掘课的上机作业.作业(全英文)下载地址:http://download.csdn.net/detail/freeape/9188451 2 作 ...

  4. 频繁项集挖掘算法在告警关联中的应用

    # 技术黑板报 # 第十期 推荐阅读时长:15min 在上一篇技术黑板报中,我们介绍了频繁项集挖掘这一问题,并讲解了Apriori算法与FP-Growth算法的技术原理.本期技术黑板报我们将主要围绕频 ...

  5. 数据频繁项集挖掘算法

    ** Apriori算法 ** Apriori 采用广度优先的搜索方式,缩小搜索空间用到了一个称为apriori的性质,其性质为:频繁项集的所有非空子集必然也是频繁的.这是很显然的,比如 同时包含项A ...

  6. 频繁项集挖掘实战和关联规则产生

    在上篇文章<数据挖掘之Apriori频繁项集挖掘>中我们用代码手工实现了Apriori算法, 用<数据挖掘概念与技术>中的数据做检验,和书中结果一致.本篇文章, 我们基于一个更 ...

  7. 数据挖掘(3.1)--频繁项集挖掘方法

    目录 1.Apriori算法 Apriori性质 伪代码 apriori算法 apriori-gen(Lk-1)[候选集产生] has_infrequent_subset(c,Lx-1)[判断候选集元 ...

  8. 基于关联规则(Variational Autoencoders)疾病预测系统实战:(pyspark FPGrowth实现频繁项集挖掘、最后给出预测模型topK准确率和召回率)

    基于关联规则(Variational Autoencoders)疾病预测系统实战:(pyspark FPGrowth实现频繁项集挖掘.最后给出预测模型topK准确率和召回率) 目录

  9. 频繁项集挖掘之Aprior和FPGrowth算法

    频繁项集挖掘的应用多出现于购物篮分析,现介绍两种频繁项集的挖掘算法Aprior和FPGrowth,用以发现购物篮中出现频率较高的购物组合. 基础知识 项:"属性-值"对.比如啤酒2 ...

最新文章

  1. ARM汇编:加载和存储指令集(六大类)---LDR(ADR)、LDRB、LDRH、STR、STRB、STRH
  2. nginx+tomcat实现Windows系统下的负载均衡搭建教程
  3. 项目中除了需求外还需要知道的问题
  4. Apsara Stack 技术百科 | 边缘场景智能云化,让云无处不在
  5. day10-协程遇到IO操作自动切换
  6. cli能记日志web不能php,ThinkPHP6.0日志变化
  7. python内置模块在哪个文件夹_用 Python 内置模块处理 ini 配置文件
  8. Delphi 3D Glscene安装
  9. Linux使用命令 笔记
  10. 工具使用教程(三)【Anaconda虚拟环境下使用Juypter Notebook】
  11. 红帽linux安装ftp服务,红帽Linux安装FTP服务
  12. [含论文+任务书+中期检查表+答辩PPT+源码等]基于javaweb的政府机关公文收发系统
  13. 月入5万!这个头条号变现大招好多人都没注意到
  14. c语言无法定位程序输入点,【求助】无法定位程序输入点PacketGetVersion于动态链接库Packet.dll上...
  15. 四川省乐山市谷歌高清卫星地图下载
  16. 怎样通过其他下载工具下载某盘文件
  17. STM32使用虚拟示波器
  18. 【TcaplusDB知识库】TcaplusDB进程启动介绍
  19. 角点检测的几种基本方法
  20. 错误 LNK2019,无法解析的外部符号__imp____iob_func; 无法解析的外部符号 __imp__fprintf 的解决方法。

热门文章

  1. 计算机应用基础本科常见问题讨论,《计算机应用基础》(本科)2017年6月期末考试指导.pdf...
  2. 华硕计算机用户名默认,华硕路由器后台默认网址是多少
  3. python人脸识别框很小_人脸识别:从传统方法到深度学习
  4. 用commons-fileupload-1.2 实现文件上传
  5. java和net共同点,Java和.NET中的垃圾回收机制比较
  6. php转字,php汉字如何转数字
  7. mysql+表复制+效率_MySQL数据库复制表的几种方式讲解
  8. 使用linux_Linux中VIM使用技巧
  9. 三星s窗口共享android,三星s窗口共享(SideSync pc端)
  10. java 文件拷贝保留原来的属性,Java - 复制JPG,同时保留所有文件属性