频繁项集挖掘算法——Apriori算法实现初步

基本概念

这周数据挖掘课上老师介绍了一种基础的数据挖掘算法——频繁项集挖掘算法。这种算法用一句话来总结就是要在数据库中扫描出所有的频繁项集。所谓频繁项集是指一个n项集合,该集合在数据库事务列表中出现的次数超过了我们所给定的一个阈值,这个阈值记为min_sup,被称为最小支持度计数,可以用整数来表达也可用分数来表达。

频繁项集挖掘算法最著名的一个实现即是Agrawal和R.Srikant于1994年提出的Apriori算法。该算法与其他挖掘频繁项集算法相比的一个重大优化就是提出了“先验性质”。先验性质通俗地说即是若一个集合是非频繁的,则它的任何超集都是非频繁的,反过来,若一个集合是频繁的则它的所有真子集都是频繁的。之所以说先验性质是Apriori算法相对于其他频繁项集挖掘算法的重大优化是因为先验性质能够有效地减少算法的搜索空间,这一点我们将会在具体实现中体现出来。

算法阐述

该算法的实现原理其实非常简单,即是使用一种逐层搜索的迭代算法,使用k项集来迭代产生出k+1项候选集(candidate set),然后再通过先验性质对k+1项候选集进行剪枝操作,缩小算法搜索空间,进而由此产生k+1项集。由k项集产生出k+1项候选集的过程可分为两步,第一步为连接步,笔者不想用过多的数学表达,仅在这里简单地描述连接步过程。假设我们已经获得了k项频繁项集合,则从该项集的第一项(记为第i项)开始向下寻找前k-1项与其相同的项(记为第j项),则第i项的全部元素和第j项的第k个元素组成了k+1项“候选集”的一项,以此类推直到遍历k项频繁项集。之所以候选集要打引号是因为这里的集合还没有经过剪枝操作,还不能被真正成为候选集。

集合的剪枝操作即在k+1项集中针对每个k+1项集检验它的每个k项真子集是否都为事务集合的频繁项集即可,若然,则保留这个k+1项集作为候选集,否则从集合中删除这个k+1项集。这样我们就获得了k+1项候选集,在这之后针对数据库进行扫描,计算出每个k+1项集的频繁计数(出现了多少次),大于最小频繁计数(min_sup)的保留,小于的从集合中去除,则我们就得到了k+1项频繁项集合。然后再重复以上的工作,迭代搜索,直到找出一个n项频繁集合无法再找出n+1项频繁项集,则算法结束,释放资源,停机。


频繁项集挖掘算法——Apriori算法实现初步_第1张图片
图1【1】

算法实现

笔者使用纯C语言实现该算法,手动管理内存。但在这里不推荐使用C语言。因为C太基础,许多要用到的数据结构均需要手动实现,效率太低且复杂度较高。笔者在实现算法之前对算法的复杂度缺乏了解,以为该算法很简单因此就想用C试试,结果等体会到复杂的时候代码已经写出了数十行,只好硬着头皮写。

笔者使用文件来模拟数据库,程序扫描文件就等效为扫描数据库。为了降低程序的I/O次数并提高运行速度,在程序启动时即读取数据进入内存,使用树形结构来存储数据。该数据结构中使用到两类节点,一类节点用于存储事务元素,一类节点用于存储事务id,并为元素节点提供索引,整个数据结构使用简单的单链表实现。数据结构直观上很像一个散列表:


频繁项集挖掘算法——Apriori算法实现初步_第2张图片

算法首先在读入数据之后产生频繁一项集,该集合的产生算法较为简单:在整个事务列表中搜索所有的事务元素并统计这些元素的出现次数,小于min_sup的一项集丢弃。


频繁项集挖掘算法——Apriori算法实现初步_第3张图片

上图算法返回一个映射,该映射中存储着所有的频繁一项集及其频繁计数,该映射作为下一级函数的数入,用于产生频繁二项集,频繁三项集......。

从频繁二项集开始算法即开始使用递归函数生成,具体算法过程如述:首先接受k项频繁项集,然后使用两个指针一前一后产生出所有符合“连接步条件”的k+1项集合。这个k+1项集合通过先验条件剪枝后得到k+1项候选集,然后计算集合中每一个k+1项集在事务集合中的计数,不符合min_sup的去掉,然后再递归调用该函数,直到找不出更多的集合,则递归返回。


频繁项集挖掘算法——Apriori算法实现初步_第4张图片



这就是该算法的核心步骤了。

算法测试

算法测试时选取的是《数据挖掘》这本书上161页的例子,在本例中笔者使用文本文档来模拟数据库,文本文档中的数据格式如下图所示:


频繁项集挖掘算法——Apriori算法实现初步_第5张图片


程序中设定最小支持度计数为2,则程序的运行结果如下图所示:


频繁项集挖掘算法——Apriori算法实现初步_第6张图片

可见,程序给出的结果和书上的结果是一样的。

该算法的实现笔者已经开源在git上,请有兴趣的朋友们能一起批评指正。

github.com/yhswjtuILMARE/MaxItemSet

参考

[1]http://www.jianshu.com/p/00103435ef89

你可能感兴趣的:(频繁项集挖掘算法——Apriori算法实现初步)