Algorithm 频繁项集挖掘的性能

Algorithm 频繁项集挖掘的性能,algorithm,data-mining,distributed-system,apriori,Algorithm,Data Mining,Distributed System,Apriori,我已经实现了apriori算法来挖掘频繁项集,它对样本数据的效果很好,但是当我尝试对零售数据集执行它时,它大约需要29小时,零售数据集大约有3mb的数据、88k事务和1600个独特项。我搜索了性能下降的原因,发现生成候选项集的算法花费了很多时间。有谁能帮助我提高性能,或者这是一种正常的算法行为。有一种方法,就是在数据的一次遍历中寻找候选项(它基本上是为流处理而设计的),以便在(0,1)中的任何θ中找到频率至少为θ的项 高级算法: 将元素收集到PF中,计算其外观 每当遇到1/θ不同元素时,将所有

我已经实现了apriori算法来挖掘频繁项集,它对样本数据的效果很好,但是当我尝试对零售数据集执行它时,它大约需要29小时,零售数据集大约有3mb的数据、88k事务和1600个独特项。我搜索了性能下降的原因,发现生成候选项集的算法花费了很多时间。有谁能帮助我提高性能,或者这是一种正常的算法行为。

有一种方法,就是在数据的一次遍历中寻找候选项(它基本上是为流处理而设计的),以便在
(0,1)中的任何
θ
中找到频率至少为
θ
的项

高级算法:

  • 将元素收集到PF中,计算其外观
  • 每当遇到1/θ不同元素时,将所有计数器减少1,并从PF中删除计数器为零的计数器
  • 在PF中输出在此过程中幸存的元素
该算法产生1/Theta(最多)候选,并且没有误报(不会遗漏任何候选)-但它确实有一些误报(一些候选并不频繁)

为简单起见,假设1/Theta是一个整数

伪代码:

PF = {} //empty dictionary
for each element e:
   if PF.contains(e):
       PF[e] = PF[e] + 1
   else:
       PF[e] = 1
       if PF.size() == 1/Theta:
             for each element k in PF:
                PF[k] = PF[k] - 1
                if PF[k] == 0:
                     remove k from PF
When done, all elements in PF are your candidates.

您使用的算法是什么?您的阈值是什么

如果你有满足你的最小支持的<代码> N< /代码> 1项集,Apriori(和许多其他)必须考虑<代码> n*(n-1)/2 2项集。这当然会变得相当昂贵。在Apriori中,2项集通常是最大和最昂贵的步骤(取决于您的设置,3项集可能更糟,但通常您不会走那么远…)

根据您的数据特征,Eclat的性能可能更好,也可能更差。计划生育增长非常聪明,但要正确有效地实施似乎真的很棘手

也存在无数的变体,有些是概率的,可能会更快

但本质上,实现和数据集/参数设置很重要。在同一组数据上,一种方法可能优于另一种方法;而实现可能很容易产生10倍的性能差异。特别是对于APRIORI,许多人不完全理解使用的修剪技巧,结果做了太多的工作

对于您的示例数据集(不幸的是,如果没有解释数字的字典,它完全没有帮助),我的APRIORI在minSupport=1000的低端Atom CPU上大约1分钟完成。找到的4项集为:

32, 38, 39, 48: 1236
32, 39, 41, 48: 1646
36, 38, 39, 48: 1080
38, 39, 41, 48: 1991
38, 39, 48, 110: 1031
38, 39, 48, 170: 1193
但正如前面提到的,参数对APRIORI非常重要。APRIORI可以很好地扩展事务的数量(可能超过主内存的容量),但是它有大量的候选对象,因此需要将minSupport设置得足够高

minSupport=1000时:

1-frequentItemsets (56)
2-frequentItemsets (49)
3-frequentItemsets (24)
4-frequentItemsets (6)
APRIORI runtime: 55401 ms
minSupport=500时:

1-frequentItemsets (185)
2-frequentItemsets (191)
3-frequentItemsets (79)
4-frequentItemsets (13)
5-frequentItemsets (0)
APRIORI runtime: 136594 ms
正如您所看到的,运行时间增加了一倍多。原因是1-itemset不断增长,产生了更多的2-itemset候选项。在3项集和4项集上,差异不再那么大。但总的来说,在真正低端CPU上运行2分钟还不错

将最低支持降低到250:

1-frequentItemsets (587)
2-frequentItemsets (640)
3-frequentItemsets (273)
4-frequentItemsets (54)
5-frequentItemsets (4)
APRIORI runtime: 954984 ms
现在运行时开始爆炸。查找5个项目集需要将近16分钟:

32, 38, 39, 41, 48: 448
36, 38, 39, 41, 48: 334
38, 39, 41, 48, 110: 346
38, 39, 41, 48, 170: 413
如您所见,
38,39,41,48
4项集在该数据集中起着关键作用(但我们在第一次运行中已经发现了这一点)。我们现在还可以给出
38,39,41,48->32的置信度,这将是涉及5个项目的最有置信度规则:涉及前四个项目的交易中约有
22.5%
也涉及到项目
32
。但考虑到这个数据集的数字的含义是未知的,我们不知道这个规则在实践中是否真的有趣,或者仅仅是一个玩具练习

转到minSupport=100,运行时将进一步增长:

1-frequentItemsets (1857)
2-frequentItemsets (2785)
3-frequentItemsets (1475)
4-frequentItemsets (306)
5-frequentItemsets (28)
6-frequentItemsets (0)
APRIORI runtime: 8256507 ms
i、 超过两个小时。大部分时间都花在2个项目集上:有170万名候选人,其中2785人经常参加。对于3个项目集,我们可以粗略估计只有大约1000个候选项目,但不再是数百万个。我有一些计划,通过根据候选数量在两个代码路径之间切换来进一步改进实现。(“更新:”,通过更简单的修改,我将运行时间进一步减少了20倍。因此,是的,“实现很重要”,它可以很容易地将运行时间减少到100到1000倍或更多-例如,当APRIORI修剪未完全实现时)


如果我有时间阅读Eclat算法并重新实现它,我可以用结果更新它。我相信这里会更快,FP增长也会更快。

这取决于您的实施情况。在实现Apriori时,可以进行许多优化

首先,如果你阅读了Agrawal&Srikant的原始Apriori论文,你会注意到他们建议使用一个特殊的哈希树来有效地计算候选人的支持度。如果您想了解这个实现是如何工作的,那么在SPMF开源数据挖掘库中有一个版本的Apriori,它是通过HashTree实现的。它被命名为AprioriHT

另一个避免多次扫描数据库的优化名为AprioriTID。每个项目集都用包含它的事务ID集(tid集)进行注释。然后,当通过组合两个项集a和B生成候选项集时,为了直接统计AUB的支持度而不扫描数据库,可以执行a和B的tid集的交集。为了进一步优化,可以使用位向量实现tid集。这个版本的APriori称为AprioriTID

在Pascal算法中提出了另一个优化。它是使用生成器的概念来推断某些项集的支持阈值,而无需使用生成器项集的概念来扫描数据库