关联规则挖掘的目标是发现数据项集之间的关联关系或相关关系,是数据挖掘中的一个重要的课题。
关联规则挖掘的一个典型例子是购物篮分析,关联规则挖掘有助于发现交易数据库中不同商品项之间的关系,找出顾客购买行为模式,如购买了某一商品对购物对其他商品的影响。分析结果可以应用于商品货架布局、货存安排以及根据购买模式对用户进行分类。
先简单介绍一下关联规则挖掘中涉及的几个基本概念:
定义1:项与项集
数据库中不可分割的最小单位信息,称为项目,用符号i表示。项的集合称为项集。设集合I={i1, i2, ..., ik}是项集,I中项目的个数为k,则集合I称为k-项集。
定义2:事务
设I={i1, i2, ..., ik}是由数据库中所有项目构成的集合,一次处理所含项目的集合用T表示,T={t1, t2, ..., tn}。每一个包含ti子项的项集都是I子集。
定义3:项集的频数(支持度计数)
包括项集的事务数称为项集的频数(支持度计数)。
定义4:关联规则
关联规则是形如X=>Y的蕴含式,其中X、Y分别是I的真子集,并且X∩Y=Ø。X称为规则的前提,Y称为规则的结果。关联规则反映X中的项目出现时,Y中的项目也跟着出现的规律。
定义5:关联规则的支持度(Support)
关联规则的支持度是交易集中同时包含的X和Y的交易数与所有交易数之比,记为support(X=>Y),即support(X=>Y)=supportX∪Y=P(XY)。支持度反映了X和Y中所含的项在事务集中同时出现的概率。
定义6:关联规则的置信度(Confidence)
关联规则的置信度是交易集中包含X和Y的交易数与所有包含X的交易数之比,记为confidence(X=>Y),即:confidence(X=>Y)==P(Y|X)。置信度反映了包含X的事务中,出现Y的条件概率。
定义7:最小支持度与最小置信度
通常用户为了达到一定的要求,需要指定规则必须满足的支持度和置信度阈限,当support(X=>Y)、confidence(X=>Y)分别大于等于各自的阈限值时,认为X=>Y是有趣的,此两个值称为最小支持阈值(min_sup)和最小置信阈值(min_conf)。其中,min_sup描述了关联规则的最低重要程度,min_conf规定了关联规则必须满足的最低可靠性。
定义8:频繁项集
设U={u1, u2, ..., un}为项目的集合,且UI,U≠Ø,对于给定的最小支持度min_sup,如果项集U的支持度support(U)≧min_sup,则称U为频繁项集,否则,U为非频繁项集。
定义9:强关联规则
support(X=>Y)≧min_sup且confidence(X=>Y)≧min_conf,称关联规则X=>Y为强关联规则,否则为若关联规则。
关联规则挖掘算法是关联规则挖掘研究的主要内容,迄今为止已提出了许多高效的关联规则挖掘算法。最著名的关联规则发现方法是R.Agrawal提出的Apriori算法。Apriori算法主要包含两个步骤:第一步是找出事务数据库中所有大于等于用户指定的最小支持度的数据项集;第二步是利用频繁项集生成所需要的关联规则,根据用户设定的最小置信度进行取舍,最后得到强关联规则。识别或发现所有频繁项目集是关联规则发现算法的核心。
另一个比较著名的算法是J.Han等提出的FP-tree。该方法采用分治的策略,在经过第一遍扫描之后,把数据库中的频集压缩进一棵频繁模式树(FP-tree),同时依然保留其中的关联信息,随后再将FP-tree分化成一些条件库,每个库和一个长度为1 的频集相关然后再对这些条件库分别进行挖掘。当原始数据量很大时,也可以结合划分的方法,使得一个FP-tree可以放入主存中。实验表明FP-Growth对不同长度的规则都有很好的适应性,同时在效率上较之Apriori算法有巨大的提高。
下面对这两个算法进行介绍:
Apriori算法
Apriori算法核心思想中有两个关键步骤——连接步和剪枝步。连接步:为找出Lk(频繁k项集),通过Lk-1与自身连接,产生候选k项集,该候选项集记作Ck;其中Lk-1的元素是可连接的。剪枝步:Ck是Lk的超集,即它的成员可以是也可以不是频繁的,但所有的频繁项集都包含在Ck中。扫描数据库确定Ck中每一个候选的计数,从而确定Lk(计数值不小于最小支持度计数的所有候选是频繁的,从而属于Lk)。然而,Ck可能很大,这样所设计的计算量就很大。为压缩Ck,使用Apriori性质:任何非频繁的(k-1)项集都不可能是频繁k项集的子集。因此,如果一个候选k项集的(k-1)项集不在Lk中,则该候选项也不可能是频繁的,从而可以由Ck中删除。这种子集测试可以使用所有频繁项集的散列树快速完成。
Apriori算法的主要步骤如下:
- 扫描全部数据,产生候选集1-项集的集合C1;
- 根据最小支持度,由候选1-项集的集合C1产生频繁项集1-项集的集合L1;
- 对k>1,重复执行步骤4、5、6;
- 由Lk执行连接和剪枝操作,产生候选(k+1)-项集的集合Ck+1;
- 根据最小支持度,由候选(k+1)-项集的集合Ck+1,产生频繁项集(k+1)-项集的集合Lk+1;
- 若L≠Ø,则k=k+1,跳往步骤4;否则跳往步骤7;
- 根据最小置信度,由频繁项集产生强关联规则,结束。
给个简单的例子作说明吧。
下面这个表格是代表一个事务数据库D,其中最小支持度为50%,最小置信度为70%,求事务数据库中的频繁关联规则。
Tid | 项目集 |
1 | 面包,牛奶,啤酒,尿布 |
2 | 面包,牛奶,啤酒 |
3 | 啤酒,尿布 |
4 | 面包,牛奶,花生 |
Apriori算法的步骤如下所示:
(1)生成候选频繁1-项目集C1={{面包},{牛奶},{啤酒},{花生},{尿布}}。
(2)扫描事务数据库D,计算C1中每个项目集在D中的支持度。从事务数据库D中可以得出每个项目集的支持数分别为3,3,3,1,2,事务数据库D的项目集总数为4,因此可得出C1中每个项目集的支持度分别为75%,75%,75%,25%,50%。根据最小支持度为50%,可以得出频繁1-项目集L1={{面包},{牛奶},{啤酒},{尿布}}。
(3)根据L1生成候选频繁2-项目集C2={{面包,牛奶},{面包,啤酒},{面包,尿布},{牛奶,啤酒},{牛奶,尿布},{啤酒,尿布}}。
(4)扫描事务数据库D,计算C2中每个项目集在D中的支持度。从事务数据库D中可以得出每个项目集的支持数分别为3,2,1,2,1,2,事务数据库D的项目集总数为4,因此可得出C2中每个项目集的支持度分别为75%,50%,25%,50%,25%,50%。根据最小支持度为50%,可以得出频繁2-项目集L2={{面包,牛奶},{面包,啤酒},{牛奶,啤酒},{啤酒,尿布}}。
(5)根据L2生成候选频繁3-项目集C3={{面包,牛奶,啤酒},{面包,牛奶,尿布},{面包,啤酒,尿布},{牛奶,啤酒,尿布}},由于C3中项目集{面包,牛奶,尿布}中的一个子集{牛奶,尿布}是L2中不存在的,因此可以去除。同理项目集{面包,啤酒,尿布}、{牛奶,啤酒,尿布}也可去除。因此C3={面包,牛奶,啤酒}。
(6)扫描事务数据库D,计算C3中每个项目集在D中的支持度。从事务数据库D中可以得出每个项目集的支持数分别为2,事务数据库D的项目集总数为4,因此可得出C2中每个项目集的支持度分别为50%。根据最小支持度为50%,可以得出频繁3-项目集L3={{面包,牛奶,啤酒}}。
(7)L=L1UL2UL3={{面包},{牛奶},{啤酒},{尿布},{面包,牛奶},{面包,啤酒},{牛奶,啤酒},{啤酒,尿布},{面包,牛奶,啤酒}}。
(8)我们只考虑项目集长度大于1的项目集,例如{面包,牛奶,啤酒},它的所有非真子集{面包},{牛奶},{啤酒},{面包,牛奶},{面包,啤酒},{牛奶,啤酒},分别计算关联规则{面包}—>{牛奶,啤酒},{牛奶}—>{面包,啤酒},{啤酒}—>{面包,牛奶},{面包,牛奶}—>{啤酒},{面包,啤酒}—>{牛奶},{牛奶,啤酒}—>{面包}的置信度,其值分别为67%,67%,67%,67%,100%,100%。由于最小置信度为70%,可得},{面包,啤酒}—>{牛奶},{牛奶,啤酒}—>{面包}为频繁关联规则。也就是说买面包和啤酒的同时肯定会买牛奶,买牛奶和啤酒的同时也是会买面包。
Apriori算法最大的优点是算法思路比较简单,它以递归统计为基础,生成频繁项集,易于实现。Apriori算法作为经典的频繁项目集生成算法,在数据挖掘技术中占有很重要的地位。但通过上面的分析发现,为了生成Ck,在连接步骤需要大量的比较,而且由连接生成的项集即使后来由Apriori性质确定了它不是候选项集,但在确定之前仍需对它生成子项集,并对子项集进行确定是否都在Lk-1中。这些步骤都浪费了大量的时间,如果可以保证由连接步生成的项集都是候选项集,那么可以省掉不必要的连接比较和剪枝步骤。
FP-Growth算法
FP-Growth(频繁模式增长)算法是韩家炜老师在2000年提出的关联分析算法,它采取将提供频繁项集的数据库压缩到一棵频繁模式树但仍保留项集关联信息的分治策略。这个算法与Apriori算法有两个最大的不同:第一,不产生候选集;第二只需要两次遍历数据库,大大提高了效率。
算法的具体描述如下:
输入:事务数据库D;最小支持阈值min_sup。
输出:频繁模式的完全集。
第一步:按下述步骤构造FP-Tree:
- 扫描事务数据库D一次。收集频繁项的集合F和它们的支持度。对F按支持度降序排序,结果为频繁项表L。
- 创建FP-Tree的根节点,以”null”标记它。对于D中的每一个事务Trans,执行:选择Trans中的频繁项,并按L中的次序排序。设排序后的频繁项表为[p|P],其中,p是第一个元素,而P是剩余元素的表。调用insert_tree([p|P], T)。该过程执行情况如下:如果T有子女N使得N.item-name = p.item-name,则N的计数加1;否则创建一个新结点N,将其计数设置为1,链接到它的父节点T,并且通过节点链将其链接到具有相同item-name的节点。如果P非空,递归调用insert_tree(P, N)。
第二步:根据FP-Tree挖掘频繁项集,过程实现伪代码如下:
- if Tree含单个路径P then
- for 路径P中节点的每个组合(记作β)
- 产生模式β∪α,其支持度support=β中节点的最小支持度
- else for each ai在Tree头部 {
- 产生一个模式β=ai∪α,其支持度support=ai.support
- 构造β的条件模式基,然后构造β的条件FP-Tree Treeβ
- If Treeβ≠Ø then
- 调用FP-growth(Treeβ, β)}
FP-Growth算法的优点:
- 一个大数据库能够被有效的压缩成比原数据库小很多的高密度结构,避免了重复扫描的开销;
- 算法基于FP-tree的挖掘采取模式增长的递归策略,创造性的提出了无候选项集的挖掘方法,在进行长频繁项集的挖掘时效率较好;
- 挖掘过程中采取了分治策略,将这种压缩后的数据库DB分成一组条件数据库Dn,每个条件数据库关联一个频繁项,并分别挖掘每一个条件数据库。而这些条件数据库Dn要远远小于数据库DB。
FP-Growth算法的缺点:
- 算法采取增长模式的递归策略,虽避免了候选项集的产生,但在挖掘过程中,如果大项集的数量很多,并且由于原数据库得到的FP-Tree的分支很多,而且分支又很长时,该算法需要构造出数量巨大的conditional FP-Tree,不仅费时而且需要大量空间,挖掘效率不高,而且采用递归算法本身的效率也较低;
- 由于海量的事务集合存放在大型数据库中,经典的FP-Growth算法在生成新的FP-tree时每次都要遍历调减模式基两次,导致系统需要反复申请本地及数据库资源查询相同的海量资源,一方面降低了算法效率,另一方面使得数据库产生高负荷,不利于数据库服务器正常运作。
本文参阅了周英的《大数据挖掘系统方法与实例分析》,在此表示感谢!