码迷,mamicode.com
首页 > 编程语言 > 详细

FP-growth算法

时间:2015-05-21 15:39:35      阅读:447      评论:0      收藏:0      [点我收藏+]

标签:

使用FP-growth算法来高效发现频繁项集

前言

你用过搜索引擎挥发现这样一个功能:输入一个单词或者单词的一部分,搜索引擎酒会自动补全查询词项,用户甚至实现都不知道搜索引擎推荐的东西是否存在,反而会去查找推荐词项,比如在百度输入“为什么”开始查询时,会出现诸如“为什么我有了变身器却不能变身奥特曼”之类滑稽的推荐结果,为了给出这些推荐查询慈祥,搜索引擎公司的研究人员使用了本文要介绍的一个算法,他们通过查看互联网上的用词来找出经常在一块出现的词对,这需要一种高效发现频繁集的方法。该算法称作FP-growth,又称为FP-增长算法,它比Apriori算法要快,它基于Apriori构建,但在完成相同任务时采用了一些不同的技术。不同于Apriori算法的”产生-测试”,这里的任务是将数据集存储在一个特定的称做FP树的结构之后发现频繁项集或者频繁项对,即常在一块出现的元素项的集合FP树,这种做法是的算法的执行速度要快于apriori,通常性能要好两个数量级以上。

FP树表示法

FP树时一种输入数据的压缩表示,它通过逐个读入事务,并把事务映射到FP树中的一条路径来构造,由于不同的事务可能会有若干个相同的项,因此它们的路径可能部分重叠。路径相互重叠越多,使用FP树结构获得的压缩效果越好,如果FP树足够小,能够存放在内存中,就可以直接从这个内存中的结构提取频繁项集,而不必重复地扫描存放在硬盘上的数据。

下图显示了一个数据集,它包含10个事务和5个项。(可以把一条事务都直观理解为超市的顾客购物记录,我们利用算法来发掘那些物品或物品组合频繁的被顾客所购买。)

技术分享

下图绘制了读入三个事务之后的FP树的结构以及最终完成构建的FP树,初始,FP树仅包含一个根节点,用符号null标记,随后,用如下方法扩充FP树:

  1. 扫描一次数据,确定每个项的支持度计数,丢弃非频繁项,而将频繁项按照支持度递减排序,对于上面给出的数据集,a是最频繁的项,接下来依次是b,c,d和e
  2. 算法第二次扫描数据集,构建FP树,读入第一个事务{a,b}后,创建标记为a和b的节点,然后形成null->a->b的路径,对该事务编码,该路径上的所有节点频度为1。
  3. 读入第二个事务{b,c,d}之后,为项b,c,d创建新的节点集,然后连接null->b->c->d形成一条新的节点集,形成一条代表该事务的路径,,该路径的每个节点的频度计数也等于1,尽管前两个事务有一个共同项b,但是他们的路径不相交,因为这两个事务没有共同的前缀
  4. 第三个事务{a,c,d,e}与第一个事务共享一个共同前缀项a,所以第三个事务的路径null->a->c->d->e与第一个事务的路径null->a->b部分重叠,因为他们的路径有重叠,所以节点a的频度计数增加为2,而新创建的节点c,d和e的频度计数等于1
  5. 继续该过程直到每个事务都映射到FP树的一条路径,读入所有的事务后形成FP树

技术分享
技术分享
技术分享
技术分享

通常,FP树的大小比未压缩的数据小,因为购物篮数据的事务常常共享一些共同项,在最好的情况下,所有的事务都具有相同的项集,FP树只包含一条节点路径,当每个事务都具有唯一项集时,导致最坏情况发生,由于事务不包含任何共同项,FP树的大小实际上与原数据的大小一样,然而,由于需要附加的空间为每个项存放节点间的指针和技术,FP树的存储需求增大。

FP树还包含一个连接具有相同项的节点的指针列表,这些指针再上图中用虚线表示,有助于快速访问树中的项。

FP增长算法的频繁项集产生

FP-growth是一种以自底向上方式探索树,由FP树产生频繁项集的算法,给定上面构建的FP树,算法首先查找以e结尾的频繁项集,接下来是b,c,d,最后是a,由于每一个事务都映射到FP树中的一条路径,因为通过仅考察包含特定节点(例如e)的路径,就可以发现以e结尾的频繁项集,使用与节点e相关联的指针,可以快速访问这些路径,下图显示了所提取的路径,后面详细解释如何处理这些路径,以得到频繁项集。

技术分享
技术分享
技术分享
技术分享
技术分享

上面的图演示了讲频繁项集产生的问题分解成多个子问题,其中每个子问题分别涉及发现以e,d,c,b和a结尾的频繁项集

发现以e结尾的频繁项集之后,算法通过处理与节点d相关联的路径,进一步寻找以d为结尾的频繁项集,继续该过程,直到处理了所有与节点c,b和a相关联的路径为止,上面的图分别显示了这些项的路径,而他们对应的频繁项集汇总在下表中

技术分享

FP增长采用分治策略将一个问题分解为较小的子问题,从而发现以某个特定后缀结尾的所有频繁项集。例如,假设对发现所有以e结尾的频繁项集感兴趣,为了实现这个目的,必须首先检查项集{e}本身是否频繁,如果它是平凡的,则考虑发现以de结尾的频繁项集子问题,接下来是ce和ae,依次,每一个子问题可以进一步划分为更小的子问题,通过合并这些子问题的结果,就可以找到所有以e结尾的频繁项集,这种分治策略是FP增长算法采用的关键策略。

为了更具体地说明如何解决这些子问题,考虑发现所有以e结尾的频繁项集的任务。

  1. 第一步收集包含e节点的所有路径,这些初始的路径称为前缀路径,如下图a所示。
  2. 由图a中所显示的前缀路径,通过把与节点e相关联的支持度计数相加得到e的支持度计数。假定最小支持度为2,因为{e}的支持度是3所以它是频繁项集
  3. 由于{e}是频繁的,因此算法必须解决发现以de,ce,be和ae结尾的频繁项集的子问题,在解决这些问题之前,必须先讲前缀路径转化为条件FP树,除了用于发现以某特定后缀结尾的频繁项集之外,条件FP树的结构与FP树类似,条件FP树通过以下步骤得到。

    • 首先,必须更新前缀路径上的支持度计数,因为某些计数包含那些不含项e的事务。例如,下图中的最右边路径null->b:2->c:2->e:1,包含并不含项e的事务{b,c},因此,必须将前缀路径上的计数调整为1,以反映包含{b,c,e}事务的实际个数。
    • 删除e的节点,修剪前缀路径,删除这些节点是因为,沿这些前缀路径的支持度计数已经更新,以反映包含e的那些事务,并且发现以de,ce,be,ae结尾的频繁项集的子问题不再需要节点e的信息。
    • 更新沿前缀路径上的支持度计数之后,某些项可能不再是频繁的,例如,节点b只出现了一次,它的支持度计数等于1,这就意味着只有一个事务同时包含b和e,因为所有以be结尾的项集一定都是非频繁的,所以在以后的分析中可以安全的忽略b。
    • e的条件FP树显示在下图b中,该树看上去与原来的前缀路径不同,因为频度计数已经更新,并且节点b和e已经被删除。
    • FP增长使用e的条件FP树来解决发现以de,ce,be,和ae结尾的频繁项集的子问题,为了发现以de结尾的频繁项集,从项e的条件FP树收集d的所有前缀路径,通过将与节点d相关联的频度计数求和,得到项集{d,e}的支持度计数。因为项集{d,e}支持度计数等于2,所以它是频繁项集,接下来,算法采用上一个步骤中的方法构建de的条件FP树。更新了支持度计数并删除了非频繁项c之后,de的条件FP显示在下图d中,因为该条件FP树只包含一个支持度等于最小支持度的项a,算法提取出{a,d,e}并转到下一个子问题,产生以ce结尾频繁项集,处理c的前缀路径后,只发现项集{c,e}是频繁的,接下来,算法继续解决下一个子问题并发现项集{a,e}是剩下唯一的频繁项集。

技术分享
技术分享
技术分享
技术分享
技术分享
技术分享

这个例子解释了FP增长算法中使用的分治方法,每一次递归,都要通过更新前缀路径中的支持度计数和删除非频繁的项来构建条件FP树,由于子问题时不相交的,因此FP增长不会产生任何重复的项集,此外,与节点相关联的支持度计数允许算法在产生相同的后缀项时进行支持度计数。

FP增长是一个有趣的算法,它展示了如何使用事务数据集的压缩表示来有效的产生频繁项集,此外对于某些事务数据集,FP增长算法比标准的Apriori算法要快几个数量级,FP增长算法的运行性能取决于数据集的“压缩因子”。如果生成的FP树非常茂盛(在最坏的情况下,是一颗完全二叉树)则算法的性能显著下降,因为算法必须产生大量的子问题,并且需要合并每个子问题返回的结果

FP-growth算法

标签:

原文地址:http://blog.csdn.net/xiaolewennofollow/article/details/45891235

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!