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

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。
输出:频繁集L
L1=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 顾客购买的商品
T1 bread, cream, milk, tea T6 bread, tea
T2 bread, cream, milk T7 beer, milk, tea
T3 cake, milk T8 bread, tea
T4 milk, tea T9 bread, cream, milk, tea
T5 bread, cake, milk T10 bread, 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.

posted on 2011-12-08 21:11  OpenNaive  阅读(701)  评论(0编辑  收藏  举报

导航