关联规则挖掘(二):Apriori算法

来源:互联网 发布:兰精莫代尔内裤知乎 编辑:程序博客网 时间:2024/05/21 12:46

1 算法简介

在数据挖掘领域,Apriori算法是挖掘关联规则的经典算法。Apriori算法采用的是自底向上的方法,从1-频繁集开始,逐步找出高阶频繁集。

它的基本流程是:第一次扫描交易数据库D时,产生1-频繁集。在此基础上经过连接、修剪产生2-频繁集。以此类推,直到无法产生更高阶的频繁集为止。在第k次循环中,也就是产生k-频繁集的时候,首先产生k-候选集,k-候选集中每一个项集都是对两个只有一个项不同的属于k-1频繁集的项集连接产生的,k-候选集经过筛选后产生k-频繁集。

2 理论基础

首先来看一个频繁集的性质。

定理:如果项目集X是频繁集,那么它的非空子集都是频繁集。

根据定理,已知一个k-频繁集的项集X,X的所有k-1阶子集都肯定是频繁集,也就肯定可以找到两个k-1频繁集的项集,它们只有一项不同,且连接后等于X。这证明了通过连接k-1频繁集产生的k-候选集覆盖了k-频繁集。同时,如果k-候选集中的项集Y,包含有某个k-1阶子集不属于k-1频繁集,那么Y就不可能是频繁集,应该从候选集中裁剪掉。Apriori算法就是利用了频繁集的这个性质。

3 算法伪代码

这是Apriori算法的主函数,它的输入是交易数据库D和最小支持度,最终输出频繁集L。函数第一步是扫描数据库产生1-频繁集,这只要统计每个项目出现的次数就可以了。然后依次产生2阶,3阶,……,k阶频繁集,k频繁集为空则算法停止。apriori_gen函数的功能是根据k-1频繁集产生k-候选集。接着扫描交易数据库里的每一笔交易,调用subset函数产生候选集的子集,这个子集里的每一个项集都是此次交易的子集,并对子集里的每一个项集的计数增一。最后统计候选集里所有项集的计数,将未达到最小支持度标准的项集删去,得到新的频繁集。

可以看到每一次循环,都必须遍历交易数据库;而且对于每一个交易,也要遍历候选集来增加计数,当候选集很大时这也是很大的开销。

输入:交易数据库D,最小支持度SUPmin。输出:频繁集LL1=find_frequent_1_itemset(D);//产生1-频繁集for(k=2;Lk-1!=⌀;k++){       Ck=apriori_gen(Lk-1);//产生k-候选集       for each transaction t in D{             Ct=subset(Ck,t);//Ct是Ck中被t包含的候选集的集合             for each candidate c in Ct                    c.count++;        }        Lk={c∈Ck|c.count>=SUPmin};}L=⋃Lk;

apriori_gen的功能是根据k-1频繁集产生k-候选集。函数是一个二重循环,当遇到两个项集,它们的前k-2项都相同,只有最后一项不同时,就对它们进行连接操作,产生一个k阶的项集(这么做的理论依据如前所述,任何一个k阶的频繁集一定能找到两个满足此条件的k-1阶子频繁集)。新产生的k阶项集可能包含有不是频繁集的子集,遇到这样的情况应该将此项集从候选集中裁剪掉,避免无谓的开销,这就是has_infrequent_subset函数做的工作。

输入:(k-1)-频繁集Lk-1。输出:k-候选集Ck。for each itemset p in Lk-1      for each itemset q in Lk-1           if(p.item1=q.item1&p.item2=q.item2&…&p.itemk-2=q.itemk-2&p.itemk-1 <q.itemk-1)
           {
               c=p.concat(q. itemk-1);//连接p和q               if !has_infequent_subset(c, Lk-1)                       add c to Ck;           }return Ck;  

has_infrequent_subset函数的功能就是判断一个项集是否包含有不是频繁集的子集。函数很简单,遍历候选项集c的k(实际上只需要遍历k-2个)个k-1阶子集,依次判断是否频繁集。

输入:一个k-候选项集c,(k-1)-频繁集Lk-1。输出:c是否从候选集删除for each (k-1)-subsets s of c      if s not in Lk-1 return true;return false;

4 例

继续使用关联规则挖掘(一):基本概念中的引例来看看Apriori算法的执行过程。输入引例中的交易数据库,设置最小支持度为0.3。

                                                         表1 某超市的交易数据库

交易号TID顾客购买的商品交易号TID顾客购买的商品T1bread, cream, milk, teaT6bread, teaT2bread, cream, milkT7beer, milk, teaT3cake, milkT8bread, teaT4milk, teaT9bread, cream, milk, teaT5bread, cake, milkT10bread, milk, tea

4.1 产生1-频繁集

扫描交易数据库,统计得各个项目出现的次数,bread是7次,cream是3次,milk是8次,tea是7次,cake是2次,beer是1次。容易知道1-频繁集包括{bread},{cream},{ milk},{ tea}。

4.2 产生2-频繁集

对1-频繁集进行连接,得到候选集为{bread,cream},{bread,milk},{bread,tea},{cream,milk}, {cream,tea},{milk,tea}。扫描交易数据库,得到它们的支持度分别为0.3,0.5,0.5,0.3,0.2,0.5。于是得到2-频繁集是{bread,cream},{bread,milk},{bread,tea},{cream,milk} ,{milk,tea}。

4.3 产生3-频繁集

对2-频繁集进行连接,并删掉其中包含有子集不是频繁集的项集(比如{bread,cream,tea}有子集{cream,tea}不是频繁集,所以删去),得到的候选集是{bread,cream,milk},{bread,milk,tea}。扫描交易数据库,它们的支持度是0.3,0.3。因此3-频繁集为{bread,cream,milk},{bread,milk,tea}。

4.4 产生4-频繁集

对3-频繁集进行连接,候选集为空,因此4-频繁集为空,算法结束。

最终产生了所有的频繁集{bread},{cream},{ milk},{ tea},{bread,cream},{bread,milk},{bread,tea},{cream,milk} ,{milk,tea},{bread,cream,milk},{bread,milk,tea}。

6 优化

Apriori算法的缺陷是需要多次扫描数据库,而且可能产生非常大的候选集,降低了算法的性能。因此有不少关于Apriori算法的优化方法,其中一个是基于数据分割的优化方法。首先把大容量的数据库从逻辑上分为几个互不相交的块,每块都应用Apriori算法产生局部的频繁集,然后测试它们的支持度来得到最终的全局频繁集。这种方法减少了候选集对内存的负担,而且支持并行挖掘。

参考文献:

[1] 韩慧等。《数据仓库与数据挖掘》。清华大学出版社,2009。

[2] 毛国君等。 《数据挖掘原理与算法》。清华大学出版社,2007。

[3] Apriori algorithm. http://en.wikipedia.org/wiki/Apriori_algorithm, 2011.

原创粉丝点击