FP-Growth 算法
- 简介:
FP-Growth算法类似Apriori算法原理,通过将数据集压缩变换存储再FP(Frequent-Pattern)树这种数据结构上面,然后寻找频繁项集,这样经过压缩后的寻找,直观上就可以看出能比Apriori算法复杂度小约几个数量级。
- 流程:
该算法的基本流程是:
-
先扫描一遍数据集,筛选出仅含一个元素的频繁项集,并按照频数从大到小排序,以备后用。这里假设数据集含单项元素个数为N个,筛选出的有n个,时间复杂度近似为 O ( N + n l o g n ) O(N+nlogn) O(N+nlogn)。
-
然后扫描数据集,构建FP树。这里有一定算法基础的同学容易看出,本质上是将数据集中的每一个元素集合看作一个字符串,然后就是把这些字符串拿来构建一颗trie树,并在trie树节点上记录每个节点出现次数。
例如:对于数据集(假设频数大于三为频繁)
事务ID 事务中的元素 01 a,b,c 02 a,b 03 b,c 04 a,b,c 05 a,c,d 06 c,d 先统计频数:
元素 频数 c 5 a 4 b 4 d 2 我们开始建立一个null节点表示初始节点,然后依次向下插入数据集中的每项(按照频数排序后插入,例如01的a,b,c就应该按照c,a,b顺序插入,d不是频繁项就去除)。
01插入后:(c,a,b)
02插入后:(a,b)
03插入后:(c,b)
依次类比,插入所有后的FP树为:
接下来再把按频数排序的头指针表指向对应节点(建树的过程中就可以指向,类似链表插入,同一个元素的连接顺序可能不同)
-
接下来有了FP树,就可以从中挖掘频繁项集了,步骤如下:
- 从FP树中获取条件模式基
- 利用条件模式基判断:
- 若为一条链,则组合均为频繁项。
- 若不为一条链(根节点有分支),则难以确定,可以将其看作新的一个数据集,重新构建FP树,然后再来判断。
- 重复上述两步,直到所有节点都被组合过了(所有频繁项集已经找完)。
-
条件模式基的选取:
条件模式基(conditional pattern base)是以所查询元素项为结尾的路径合集(其实也就是一系列前缀路径,以该节点向上走到根节点(null点)所经过的节点集合)。
通过头指针表来获取前缀路径。因为头指针表中,每个头指向了所有该节点在FP树中的位置,所以只需要遍历这条链(上图中红色链),然后每到一个节点再在FP树上往上遍历到null节点即可提取出前缀路径。
例如:对于c:c->null,所以前缀路径为空集;
对于a:a->null,a->c->null,所以前缀路径为{c:3};
对于b:b->a->null,b->a->c->null,b->c->null,所以前缀路径为{a:1},{a,c:2},{c:1};
其中每个项(一组花括号算一个项)出现频数为其中频数最小的元素频数。
这里按照FP树性质子节点频数小于父节点(下方点频数小于上方点),所以直接按照所提取元素频数即可(例如b的对应三个频数都是其下b的频数)。
-
构建条件FP树:
也就是对于每一个条件模式基,将其看作一个数据集,构建其FP树(仍然要重新统计一项元素频数,然后)。
例如:对于c,其为空,所以FP树为空,所以一个频繁项就只有{c}
对于a,其FP树构建出来为一个点c(也算一个链,没有分支),所以其有两个频繁项{a},{a,c}
对于b,排序后为{a:3,c:3},其FP树构建出来为如下图:
此时出现了分支,所以我们重复上述整个流程,将其按照一颗新的FP树来处理。
先找条件模式基,a为空集(a->null),c为c->a->null,c->null也就是{a:2},均为链,但这里{a:2}频数小于3则舍去,然后链直接组合,所以频繁项只有{a},但这里是处理b时的子问题,所以结果要再与b组合,所以真正的频繁项为{a,b}
-
至此,所有频繁项集已经找出:{a:4},{b:4},{c:5},{a,c:3},{a,b:3}
具体代码网上均有,这里不再赘述。
本人粗浅理解,若有问题,欢迎指出!QWQ
参考网址:
https://zhuanlan.zhihu.com/p/117598874
https://www.cnblogs.com/ybjourney/p/4851540.html
--------------------------------------------------------------------------------------------------------------by 橙汁桃菜菜-VictoryCzt