Apriori算法最核心的思想就是:频繁项集的所有非空子集都必须是频繁的。
所以k+1项频繁集必定是k项频繁集的并集。
因为K项频繁集的并集是可数的,也就是有限的,这样就可以对新形成的k+1项集进行判定,判断其是否是频繁的。
这样做比起穷举频繁集,然后一一验证好得多,每一级的频繁集都依赖于前一级频繁,这一过程过滤了许多非频繁集的计算。
然而每验证k项频繁集均需要扫描一次一数据集,当数据集较大时,要想找到完全频繁项集是比较困难的。
另一个问题:怎么才能提高Apriori算法的性能?
1.使用hash技术,在验证k项集时,对所有候选k+1项集hash到有限个桶内,桶计数小于支持度阈值的就可以从候选集中删除,这样
就减少了k+1项集的候选个数。此技术的效果取决于hash函数的设计,桶的个数,以及数据的分布情况。
2.事务压缩
在验证k项集是否为频繁项集时,可以在事务集里面删除 那些 不包含任何k项集的事务,因为不包含任何k项集的事务不
可能包含任何k+1项集,所以在验证k+1项集时,不再需要他们。
我提出另一种简单的想法: 因为事务集中肯定有许多相同的事务,第一次扫描时,可否添加一个事务计数的字段,并删除重复的事务,这样
也会减少事务集。
3.划分
在每个子集里面找到此子集的每个频繁项集,将所有的子集的频繁项集生成最终的候选集,
每二次扫描时就可对其一一验证,
整个过程只需要对数据集进行两次扫描。(官方说的)
我有一个疑问:要找出每个子集的频繁项集需要访问多少次对应的数据子集?
这个划分的想法非常好,分而治之,可以将每一部分的数据放入到内存,减少IO,也可以用mpa-reduce方案来进行来解决海量数据的问题。
4.选样 选样不失为一个不错的选择。
FP树算法
Apriori每次扫描都只是取每个事务的k项子集进行判断,在验证k+1项集时,又需要取每个事务的k+1项子集,但是k+1项子集
包含了k项子集啊! 对k项子集进行了重复操作,为何不能利用上一次扫描出来的k项子集结果呢?
这样新的算法FP树算法就应运而生了。
FP树简介:
第一次扫描 对所有单项频繁项集进行排序。
每二次扫描开始建树,以null为根结点,每个子节点为单项频繁项集,每个节点记录此节点出现的次数,每一个事务排序后,
从第一代节点开始生长,沿已有树枝生长,如果没有对应的树枝就新建新的树枝,并对走过的节点进行加1计数。
这样这棵树就包含了所有的需要的信息,可以认为树是数据集的另一种表示方式,是无损压缩。
接着就是从这棵树中提取到相应的频繁项集。
首先要依次生成每个item的条件模式基,条件模式基是item的树根,即以以item为起始结点,返溯到根节点,所有这样的树枝的集合。
再由这些条件模式基又可生成条件fp树,从树上就可清楚得到相应的频繁模式。
FP树方法将发现长频繁模式的问题转换成递归地发现一些短模式,然后与后缀连接。他以最不频繁的项作后缀,提供了好的选择性
。此方法大大降低了搜索的开销。可是当数据量很大的,一般情况下,如果数据放不进内存,那么相应的FP树也将放不进内存。
因为fp树可能需要比原始数据更大的内存空间。
当然如果是这种情况,当然使用划分的方法 ,用于生成小数据集的fp树,查找出小数据集的频繁模式。
注:强关联规则不一定是有趣的,只是通过对关联模式的支持度和置信度的计算,对决策提供一定的参考,而仅依靠
支持度和置信度是不能确定得到的规则是有意义的。