一种改进的基于N-List的频繁项集挖掘算法
2018-09-26孙建言
翟 悦 王 璨 孙建言
(大连科技学院信息科学系 辽宁 大连 116052)
0 引 言
频繁项集挖掘是数据挖掘研究中最为突出的任务之一,也是数据挖掘中最为耗时的部分,一旦挖掘出所有的频繁项集,关联规则即可通过简单的数学计算得到,可以说频繁项集挖掘算法的效率直接影响着整个数据挖掘的效率,因此十分有必要深入研究频繁项集挖掘算法。传统数据频繁项集挖掘算法主要分为两类: 一类是以Apriori算法为代表的产生候选频繁项集的挖掘算法,Apriori类算法具有需要重复扫描数据库及产生大量候选项集等缺陷;另一类是FP-growth为代表的采用分而治之策略挖掘频繁项集算法,该种采用频繁模式增长类的算法将数据压缩到FP-tree,需要递归构建条件FP-tree,时间性能无法保证。
尽管近年来研究者提出诸多改进的频繁项集挖掘算法,但当事务数据库非常稠密,并且最小支持度设定非常低时, 频繁项集数量会随着其长度呈指数型增长,频繁项集挖掘时间复杂度仍然存在下降空间。因此,Deng等[3-4]提出了基于PPC-tree结构的挖掘算法PrePost,利用一种新的数据结构N-List,通过N-List的交集运算求得项集支持度,它在频繁项集挖掘中有很高的效率。Song等[2]提出的包含因子概念提高了频繁项集的挖掘速度。
本文提出一种借鉴包含因子概念融入PrePost算法,结合两种策略的优势,给出HNSFI算法。该算法利用哈希表存储N-List数据结构所表示的项集,N-List表示的项集与FP-tree相比拥有较高的压缩率,哈希表存储利用空间换时间的方法进一步降低N-List相交运算的时间复杂度,并可根据性质快速计算项集的支持度,同时结合项集的包含因子概念省略某些情况下N-List相交运算过程。包含因子及其相关定理可直接生成频繁项集,当数据集比较稠密时,包含因子的生成时间代价远远小于大量N-List相交运算以及支持度计算时间,因此本文算法特别适合应用在稠密数据库。
1 相关工作
设I={i1,i2,…,in}是n个不同项目的集合,如果对一个集合X,有:X⊆I且k=|X|,则X称为k项集。记D为事务T的集合,T⊆I。对于如表1所示给定事务数据库D共有n条记录, 包含项集X的事务集合记为g(X)={t∈D|∀i∈X,i∈t},集合X的支持数为D中包含X的事务个数,记为X.count;X的支持度为sup(X)=X.count/n,用户可自定义一个最小支持度,记为minsup[5]。
表1 事务数据库D
定义1[11]给定事务数据库D和minsup,对于项集X⊆I,若sup(X)≥minsup,则称X为D中的频繁项集。
定义2[1]PPC树定义如下:
每个结点N由5 个域组成,分别是N.item、N.count、N.preorder、N.postorder和N.child。其中,item表示项集;count域记录了项集的支持数;preorder 域为前序遍历PPC树的序号;postorder 域为后序遍历PPC树的序号;child域指向N的孩子结点。另根结点root.preorder=0,其余各域值均为null。
如表1所示数据,对每个事物项按照出现频度降序排列,如表2所示,根据文献[3]提出的prepost算法生成PPC树如图1所示。
表2 按事物项出现频度降序排列事务数据库D
图1 事务数据库D生成的PPC树
2 构造哈希表存储的N-List
2.1 引用哈希表存储N-List
本文提出利用2级的哈希表存储N-List,这样可以加快N-List相交计算的运算速度,改进文献[3]提出N-List交集算法性能。为了避免1级哈希表在键值上的冲突,本文设置2级的哈希表结构如下:1)第1级,使用项目集的长度定为键值;2)第2级,项目集中包含的各个项的键值累加和作为新键值存储;为了进一步避免不同的项目级对应的键值产生冲突,本文使用素数序列作为1-项集的键值Key。如表3中列出1-项集的键值序列为素数序列,2-项集中项集ab的键值计算为:Key(a)+Key(b)=3+5=8。
表3 使用哈希表存储N-List的键值
定义3[3]N-List结点由PPC树结点中3个域组成,表示为ppi=Ni.preorder,Ni.postorder,Ni.count。
由定义4,按照文献[1]提出的N-List建立方法生成哈希存储的1-项集N-List如图2所示。其中每个1-项集的链表结点按照前序遍历顺序链接。
图2 表2对应的哈希存储的1-项集的N-List
性质1K-项集P对应的N-list为NL(P)={pp1,pp2,…,ppn}
可知P.count=pp1.count+pp2.count+…+ppn.count
例如:键值为3的哈希表存储的{a}存在2个链接结点{(1,1),1},{(4,6),3},按照性质1可知1-项集{a}的支持数a.count=1+3=4。
2.2 哈希存储N-list的链接方法
性质2假设∀ppi,ppj,当且仅当ppi.preorder< ppj.preorder,且ppi.postorder>ppj.postorder时,则称ppi为ppj的前驱结点,记为ppi∝ppj。
例如:ppi={(3,10),5},ppj={(11,7),1},因为ppi.preorder=3
定义5假设XA与XB是两个前缀同为X的k-1项集,由其对应的NL(XA)与NL(XB)合并生成k-项集的N-list的步骤如下:
1) ∀ppXA∈NL(XA), ∀ppXB∈NL(XB),如果ppXA∝ppXB,则生成结点(ppXA.pre,ppXA.post,ppXB.count)∈NL(XAB)。
2) 合并NL(XAB)中前序和后序值相同的结点。
由定义5可知,NL(c)={(3,10),5},NL(d)={<(6,2),1>,<(9,9),2>},NL(cd)生成过程如图3所示。根据性质2可知结点{(3,10),5}为结点{(6,2),1}的前驱结点,因此将结点{(3,10),1}插入NL(cd)中,同理结点{(3,10),5}∝{(9,9),2},故{(3,10),2}也同样插入NL(cd)中。
图3 N-list合并生成cd的过程
3 包含因子与N-List相交运算
3.1 包含因子的引入
定义6[6]假设i为一个项目集,如果存在另一个项目集j,使得满足j∈I,且g(i)⊆g(j),则称j为i的一个包含因子,记为subsume(i)。例如:g(b)={1,2,4},g(a)={1,2,3,4},因为g(b)⊆g(a),故subsume(b)=a。
性质3假设项集x的包含因子subsume(x)={a1,a2,…,am},由x与其包含因子合并生成的2m-1个非空子集的支持数均为x.count。
例如:subsume(b)=a,那么无需进行进一步计算即可得知:b.count=ab.count=3。
定理1[10]假设a,b,c∈I1,如果a∈subsume(b),且b∈subsume(c),则有a∈subsume(c)。
证明:由于a∈subsume(b),b∈subsume(c),根据定义6可知g(b)⊆g(a),g(c)⊆g(b)。必然有g(c)⊆g(a)。因此得出a∈subsume(c)。
包含因子生成算法Gen_subsume()描述如下:
Gen_subsume(I1)
1:for i=1 to |I1|
2: for j=i-1 to 0
3: if j∈i1[i].subsume continue
4: if checkSubsume(I1[i].NL,i1[j].NL)==true
5: 添加I1[j].item和其索引j到I1[i].subsume中
6: 将I1[j].subsume元素添加到I1[i].subsume中
//根据定理2
checkSubsume(NL(a),NL(b))
//根据定理1
1: while j<|a| && i<|b| do