我已经实现了apriori算法来挖掘频繁项目集,它可以很好地处理样本数据但是当我试图为http://fimi.ua.ac.be/data/retail.dat提供的零售数据集执行它时,大约3mb数据,88k交易和1600个独特项目大约29个小时。我搜索了性能命中的原因,发现生成候选项集的算法花费了很多时间。任何人都可以帮助我提高性能,或者这是一种正常的算法行为。
答案 0 :(得分:1)
有一个pretty efficient algorithm proposed by Karp Papadimtrioue Shanke,即在数据的单次遍历中找到候选者(它基本上是为流处理而设计的),以便查找频率至少为theta
的项目theta
中的(0,1)
。
高级算法:
该算法产生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.
答案 1 :(得分:1)
您使用的算法是什么,阈值是什么?
如果你有n
1项目集满足你的最低支持,Apriori(和许多其他人)必须考虑n*(n-1)/2
2项目集。这当然变得相当昂贵。在Apriori中,2个项目组通常是最大且最昂贵的步骤(取决于你的设置,3个项目集可能更糟,但通常你没有那么远......)
根据您的数据特征,Eclat可能表现更好 - 或更糟。 FP增长非常聪明,但实施起来似乎非常棘手。
还存在无数种变体,其中一些是概率性的,可能要快得多。
但实质上实施和数据集/参数设置很重要。在同一组数据中,一种方法可能比另一种方法更好;并且实现可以容易地具有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重要 lot 。 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项目集增长,产生了更多的2项目候选人。在3和4项目集中,差异不再那么大。但总体而言,真正低端CPU上的2分钟运行时间还不错。
将最低支持率降至250:
1-frequentItemsets (587)
2-frequentItemsets (640)
3-frequentItemsets (273)
4-frequentItemsets (54)
5-frequentItemsets (4)
APRIORI runtime: 954984 ms
现在运行时开始爆炸。差不多16分钟找到5个项目集:
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
。但鉴于AFAICT数据集的数字含义未知,我们不知道这条规则在实践中是否真的有趣,或者只是玩具练习。
转到minSupport = 100,运行时间进一步增长:
1-frequentItemsets (1857)
2-frequentItemsets (2785)
3-frequentItemsets (1475)
4-frequentItemsets (306)
5-frequentItemsets (28)
6-frequentItemsets (0)
APRIORI runtime: 8256507 ms
即。超过两个小时。大部分时间花在了2个项目集上:有170万名候选人,其中2785人经常参加。对于3项目集,人们可以粗略估计只有几千个候选人,而不是数百万人。我有一些计划通过在两个代码路径之间切换来进一步改进实现,具体取决于候选者的数量。 ('''更新:'''通过更简单的修改,我进一步将运行时间减少了20倍。所以是的,'''实施很重要''',它可以很容易地使得100到1000或更多 - 当APRIORI修剪未完全实施时,例如)
如果我有时间阅读Eclat算法并重新实现它,我可以用结果更新它。我相信这里会更快,FP增长也会更快。
答案 2 :(得分:0)
这取决于您的实施。在实现Apriori时可以进行许多优化。
首先,如果你阅读了Agrawal& amp; Srikant你会注意到他们建议使用一个特殊的哈希树来有效地计算候选人的支持。如果你想看看这个实现是如何工作的,那么在SPMF开源数据挖掘库中有一个用HashTree实现的Apriori版本。它被命名为AprioriHT。
避免多次扫描数据库的另一个优化命名为AprioriTID。每个项目集都使用包含它的事务ID(tid集)进行注释。然后,当通过组合两个项集A和B生成候选项,直接计算AUB的支持而不扫描数据库时,可以执行A和B的tid集的交集。为了进一步优化,您可以实现tid集位向量。这个版本的APriori被称为AprioriTID。
算法Pascal中提出了另一种优化方法。通过使用来自形式概念分析的生成器项集的概念,使用生成器的概念来推断某些项集的支持阈值而不扫描数据库。
另一个优化是按照词典顺序对Apriori中每个级别的项目集进行排序,并按字典顺序对每个项目集中的所有项目进行排序。然后,在生成候选项时,您可以使用此排序来避免将所有项集相互比较以生成更大的候选项。
还有其他优化措施。在FIMI网站上,有各种不同优化的实现。
如果您想查看优化版本,可以查看我在SPMF data mining library in Java中的实现。此外,在同一个网站上,您将获得更快算法的实现,例如FPGrowth。