天天看点

Apriori算法C++实现

最近刚上了数据挖掘这门课,老师讲了两个算法,即Apriori算法和FP-growth算法,然后布置了上机作业,挖掘一个有8万行的记录的retail.dat,需要从中找出强规则,即同时满足最小支持度和最小置信度的规则。

Apriori算法

在这里给出一个实现找出所有频繁模式集的c++代码,其中主要使用的存储结构是二维数组,有点简陋,凑合着看看。

另外,这个版本是刚写出来初始版本,自连接之后没有修剪步骤,而是直接扫描数据库,所以效率偏低。

这个版本测试时用的最小支持度是2000,这个支持度比较大,所以输出结果还是较快的。不过如果最小支持度设为1000以下的话,那么运行速度就差了很多。

Apriori算法C++实现

改进之后增加了修剪步骤的算法运行速度在最小支持度较低时运行速度明显加快,但是还是耗时较长。

Apriori算法C++实现
Apriori算法C++实现

可以看到,在最小支持度在500时,改进后的算法提升了一分多钟,因此修剪对于Apriori算法来说是很重要的一步。

12.02更新

这两天本来打算补完修剪部分,就去研究一下FP-growth算法的。结果发现树的知识还不会,准备先把数据结构的树部分的OJ题刷完再写。于是这两天一直在优化Apriori算法,终于在参考了韩家伟教授的《数据挖掘:概念与技术》一书后,明白了可以用散列函数来处理2项集,效率一下子就提上来了。在这里给出书中的描述。

Apriori算法C++实现

由于散列函数,也就是哈希函数其实我也不会,百度看了大半天,大概懂了一点,在这里用二项集的例子尝试着解释一下。

在优化前的代码中,二项集的处理是每扫描一行数据库,便需要将二项集中的每一项拿出来比较,假设二项集中有n组项,即一行数据库就需要扫描n次,效率十分低下。

而对于一项集,则用了计数排序的思想,即在第一次扫描读取全体数据集时,每读取一个数temp,便在相应的H[temp]++,如此实现了一项集的快速计数。

如果二项集也能采取类似的方法,那么运行效率无疑会比现在高出很多。所以哈希函数就是这么个东西,我们能够用一个关键字key来表示一组数,这里用的应该是叫桶哈希的方法。

首先我们需要创建出一个Hash数组,其大小由你使用的哈希算法决定,然后在扫描生成一项集的同时,对数据集的每一行中的项组成所有的二项集,然后使用散列函数hash(x,y)创建散列表,同时进行相应的桶计数。全部扫描完成后,我们便得到了一个存有全体数据集的一个Hash数组(原谅我只会数组)。

在我们自连接得到了候选二项集C2后,扫描每一个项{i,j},判断Hash[hash(i,j)]是否大于你的最小支持度阈值Min_sup,由此可以通过扫描一次候选二项集C2快速的得到一个频繁二项集L2。

接下来我们看一个简单的例子

Apriori算法C++实现

图6.2中代表一个数据集,我们可以使用函数hash(x,y)=(x10+y)%7创建Hash数组,显然其大小size为7。

先看第一行,I1,I2,I5,可以组成三个二项集{I1,I2},{I1,I5},{I2,I5},我们使用函数将其存入Hash数组中,key=hash(1,2)=(110+2)mod 7=5,H[key]++;hash(1,5)=1,Hash[1]++;hash(2,5)=4,Hash[4]++;即每一个二项集都对应着Hash中的一个key,接下来每一行都可以用该方法存入。

其中{I1,I4},{I3,I5}因为hash(1,4)=hash(3,5)=0,则他们被称为同义词,如果我们不进行任何处理的话,在计数中Hash[0]对应的数包含这两个项。在这里我们可以使用开放地址法(线性探测法),再哈希法,链地址法解决这种“地址冲突”,由于我也是刚刚快速看完哈希函数,所以具体的知识都不太了解,有兴趣的可以自行去查找相关资料,这里就不说如何将他们分别存放了。

经过上面这一步,我们在第一次扫描数据集的时候,就同时得到了一个存着数据集中全部二项集的Hash数组。假设图6.2中项的最小支持度阈值为2,首先可得到候选二项集为{I1,I2},{I1,I3},{I1,I4},…,{I3,I5},{I4,I5},接着就是扫描全体数据集得出每一个二项集的支持度计数,但是我们已经有了一个存着全部二项集的哈希数组,因此我们只需要在Hash找到相应的支持度就可以了。如{I1,I2}的支持度为Hash[hash(1,2)],如果该数值大于2,即存入频繁二项集L2中。

Apriori算法C++实现
Apriori算法C++实现

改进后的算法1%支持度扫描时间由20多秒减少到了7秒,进步了不少。

支持度为千分之五扫描时间也只需要10秒,不过存在的问题还是比较多,各个地方查缺补漏的,越写越乱,可读性极差。

源码发布在我的Github上。