system: [SYSTEM]

user: 3. Eclat算法及改进算法 3.1. Eclat算法 3.1.1. 算法主要思想 Zaki在2000年提出的Eclat算法是基于深度优先搜索的策略，采用垂直数据格式、等价类技术、交集运算等等。Eclat算法的主要步骤如下：扫描数据库以获得所有频繁1-项集；从频繁1-项集开始生成候选2-项集，然后通过筛选掉非频繁的候选项集来获得所有频繁2-项集；从频繁2-项集生成候选3-项集，然后通过筛选掉非频繁的候选项集来获得所有频繁3-项集；重复上述步骤，直到无法生成候选项集为止。上述步骤概括起来包括两个阶段：一是通过自连接产生候选项集；二是通过求交运算获得支持度。 1) 产生候选集 与Apriori算法一样，Eclat算法也采用连接操作来产生候选项目集，即通过连接两个k-项目集生成(k + 1)-项目集。两个k-项集连接的条件是它们各自的前k-1个项必须相同。例如，有两个3-项集： l 31 = { I 1 ， I 2 ， I 3 } 和 l 32 = { I 1 ， I 2 ， I 4 } ，它们各自的前两项都为{I 1 ， I 2 }，因此l 31 与l 32 能连接生成一个4-项集： l 4 = { I 1 ， I 2 ， I 3 ， I 4 } 。Eclat算法通过使用等价类 [ 7 ] 的概念将搜索空间划分为多个不重叠的子空间，有相同前缀的项目集被划分为同一个类，而候选项目集的生成只在同一个类里操作。这种等价类的技术显然可以提高候选项目集生成的效率，并减少项目的占用内存。 2) 求交运算 Eclat算法求交运算是通过逐项比较事务tid的方式进行的。设l 21 和l 22 是两个项目集， TID _ set ( l 21 ) = { 1 ， 3 ， 5 ， 6 } ， TID _ set ( l 22 ) = { 3 ， 4 ， 5 ， 6 } 。假设l 3 为l 21 与l 22 连接后生成的， Support ( l 3 ) = S ， T I D _ s e t ( l 3 ) = T I D _ s e t ( l 2 1 ) ∩ T I D _ s e t ( l 2 2 ) 。设P 1 和P 2 是两个分别指向TID_set(l 21 )和TID_set(l 22 )各自第一个TID的指针。获取l 21 和l 22 交集的过程如图1所示。由于生成(k + 1)-项集过程和两个k-项集求交的过程是同时进行的，因此可以立即得到(k + 1)-项集的支持度。 3.1.2. 算法实现过程 下面以具体示例阐述算法的实现过程。给定表1所示垂直数据格式的事务库，假设支持度阈值为0.5，对表中数据进行频繁项集的挖掘，具体演示过程如图2所示。在图2中，每个椭圆内部包含了项集、项集支持度计数以及项集对应的事务集，其中粗体标注的椭圆为频繁项集，其余椭圆为候选非频繁项集。图2显示，对于表1中的数据，共生成了20个候选项目集(除去1-项集)，执行了20次连接操作和求交运算，产生了9个频繁项集(除去频繁1-项集)。 3.1.3. 算法主要缺陷 尽管Eclat算法的效率很高，它仍然有以下一些缺陷：1) 由于候选集的产生是在等价类中完成的，没有像Apriori算法一样利用向下封闭性质 [ 8 ] 对候选集进行剪枝优化操作，因此候选项目集的数量超过了Apriori算法。2) 项集的支持度是通过交运算获得的，相比Apriori算法通过扫描事务库获取支持度的方式在效率上有很大提高，但是当项目集包含的事务集规模很大时，逐项的求交运算导致效率依然不尽人意。为此，近年来许多人开始关注Eclat算法并提出了一些改进算法。 3.1.4. 现有改进算法 Eclat_Diffsets算法 [ 9 ] 采用布尔矩阵与差集技术来提高交集计算效率并减少内存占用，该算法采用布尔矩阵存储itemset和TID_set，并通过二进制运算来计算交集，这种方式能明显改善支持度获取效率；熊忠阳等人提出的HEclat算法 [ 10 ] 采用散列布尔矩阵来改善交集计算，该算法使用散列布尔矩阵来存储 图1. Eclat算法求交运算过程示例 Table 1 Vertical data format of a databas Item TID_set I 0 1， 2， 6 I 1 2， 3， 4， 6 I 2 4， 5 I 3 2， 3， 4， 6 I 4 1， 2， 3， 5 I 5 3， 4， 5， 6 I 6 2， 3， 4， 5 表1. 数据库的垂直数据格式 图2. Eclat算法挖掘频繁项集过程演示 项目集的TID_set，当计算两个项目集的交集时，只需要在两个布尔矩阵上使用位“与”操作，散列布尔矩阵只有在数据库的事务数规模不是很大的时候才能提高效率；Eclat_opt算法 [ 11 ] 则采用双层哈希表技术加快候选子集的搜索速度，通过项集集合划分链表技术减少项集连接的比较判断，并利用事务标识(tid)失去阈值技术加快交集计算的速度，这些技术能够对候选3-项集进行充分剪枝，减小搜索空间的同时缩短了生成候选集的时间，此外提高了交集计算的速度。通常情况下，Eclat_opt算法比其他Eclat改进算法更有效。现有的改进算法虽然能够在不同程度上改善原始Eclat算法的效率，但是这些算法仍然有一些缺陷，比如大量无用的候选集产生，耗时的求交运算等。 3.2. 改进的Eclat算法 针对Eclat算法存在的缺陷，本节从候选集的生成和支持度的计算两个方面分别对原始算法进行优化和改进，其具体策略如下： 3.2.1. 候选集生成的优化 为防止大量候选集的产生而导致过多的求交运算，需要在候选集的数量上进行进一步的优化压缩。为此，本文借助Apriori算法中候选集剪枝优化的思想，采用两种剪枝策略相结合的方式对Eclat算法中的候选集进行优化处理。一是在连接生成候选集C k 之前，对L k−1 进行预先剪枝，筛选掉那些在连接后一定是非频繁的项集，以便省去重复的连接操作，即预剪枝优化；二是在连接生成候选集C k 之后，利用频繁项集的先验性质，对候选集再剪枝处理，即后剪枝优化。通过两种剪枝策略相结合的方式，充分压缩最终参与求交运算的候选集规模。 1) 预剪枝优化 预剪枝优化的思想利用了以下性质：若L k−1 项集中存在项目i，使得i在所有频繁项集L k−1 中出现的次数少于k − 1次，则与项集L k−1 (i)连接后生成的C k 一定是非频繁的(L k-1 (i)指的是包含项目i的L k−1 项集)。 对上述性质采用反证法：假设现在有个C k 是频繁项集，根据频繁项集先验性质，它的所有子集也都是频繁项集，因此它的所有k − 1项子集都属于L k−1 ，任意项目i在该C k 的k − 1项子集中出现的次数都为k − 1次，则项目i在所有频繁集C k 的k − 1项子集中总共出现的次数至少为k − 1次，与性质中的条件相矛盾，故C k 是非频繁项集。 2) 后剪枝优化 为进一步压缩候选集的规模，对C k 进行后剪枝优化处理，其剪枝思想利用频繁项集先验性质 [ 12 ] ：频繁项集的所有子集都是频繁的，也就是说，若某个项集是非频繁的，则它的超集也一定是非频繁的。 上述性质在Apriori算法中采用的较多，本文将其引用到Eclat算法中，其证明过程不再赘述。后剪枝具体步骤如下：对每个C k 进行k − 1项子集的分解，判断所有k − 1项子集是否在L k−1 的集合中，若存在k − 1项子集不在L k−1 的集合中，则删除该C k 。 下面以 L 2 = { { I 1 I 2 } ， { I 1 I 4 } ， { I 1 I 5 } ， { I 1 I 6 } ， { I 2 I 6 } ， { I 5 I 6 } } 为例，用上述两种剪枝策略相结合的方法阐述C 3 产生的具体过程。在L 2 中，只有I 4 出现的次数小于两次，因此筛选掉{I 1 I 4 }， L 2 ′ = { { I 1 I 2 } ， { I 1 I 5 } ， { I 1 I 6 } ， { I 2 I 6 } ， { I 5 I 6 } } ；对L 2 ’自连接，根据等价类理论，只有{I 1 I 2 }、{I 1 I 5 }和{I 1 I 6 }相互间可以连接，连接后的 C 3 ′ = { { I 1 I 2 I 5 } ， { I 1 I 2 I 6 } ， { I 1 I 5 I 6 } } ；对于{I 1 I 2 I 5 }，由于子集{I 2 I 5 }不在L 2 中，因此筛选掉{I 1 I 2 I 5 }，则最终的 C 3 = { { I 1 I 2 I 6 } ， { I 1 I 5 I 6 } } 。 3.2.2. 支持度计算的改进 在Eclat算法中交集的计算是最耗时的环节，它需要一个接一个地比较两个项集的tid，当项集的TID_set规模很大时这种方式依然很低效。尽管已有的算法做了相应改进，但是这些算法求交集的基本思想与原始Eclat算法是类似的。为此，本文提出一种基于事务索引的布尔数组取值计数法来计算交集以获得项集的支持度。其步骤如下： 首先，创建一个布尔型的数组，数组的长度由事务的数量确定，数组所有元素初始化为0； 其次，将其中一个项集的tids作为索引，索引对应的数组元素设置为1； 最后，将另一个项集的tids作为索引，取出索引对应的数组元素，如果取出的元素为1，则把该元素的索引加入交集中，并增加一次支持度计数，如果取出的元素为0，则跳过。 下面仍以l 21 和l 22 两个项目集为例，用本文给出的求交方法阐述具体过程如图3所示。在图3中， TID _ set ( l 21 ) = { 1 ， 3 ， 5 ， 6 } ， TID _ set ( l 22 ) = { 3 ， 4 ， 5 ， 6 } 。因为数据库的事务数为6，则初始化布尔数组 Array = ( 0 ， 0 ， 0 ， 0 ， 0 ， 0 ) 。将l 21 中的tids作为索引，把指向Array中的对应元素设为1，即Array [ 1 ] = 1，Array [ 3 ] = 1，Array [ 5 ] = 1，Array [ 6 ] = 1，则 Array = ( 1 ， 0 ， 1 ， 0 ， 1 ， 1 ) 。以l 22 中的tids为索引，检索Array中相应的元素Array [ 3 ] ，Array [ 4 ] ，Array [ 5 ] ，Array [ 6 ] ，其中值为1的分别是Array [ 3 ] ，Array [ 5 ] 和Array [ 6 ] ，因此 TID _ set ( l 3 ) = { 3 ， 5 ， 6 } ， Support ( l 3 ) = 3 。 图3. 改进Eclat算法支持度计算过程示例 上述示例表明，通过使用新的求交方法，只需要设置和检索布尔数组的元素即可求得交集和支持度，避免了传统方法中逐项比较的过程。 3.2.3. 改进算法的具体实现 综合上述两方面的优化策略，改进后的Eclat算法实现步骤如下： 1、扫描事务数据库一次，为每个项目获取事务标识符(tid)，将数据库转成垂直格式； 2、在候选集C k ’产生之前，先对L k−1 剪枝，筛选得到L k−1 ’：计算所有项目在L k−1 集合中出现的次数，删除项目频度小于k − 1次的项目集； 3、利用等价类技术对L k-1 ’自连接，生成候选集C k ’； 4、对C k ’进一步剪枝，筛选得到C k ：列出C k ’项集的所有k − 1项子集，删除子集不在L k−1 集合内的项目集； 5、利用改进的求交运算方法得到C k 的TID_set和Support，并根据预先设定的阈值确定最终的频繁项集L k ； 6、循环2至5步过程，直到L k 的项集数量小于(或等于)k，终止算法。 改进Eclat算法的主程序伪代码如下： 其中，预剪枝函数Prune伪代码如下： 改进的支持度计算函数New_quick_support_count伪代码如下：