前言
上一篇文章介绍了用来挖掘发现强关联规则的Apriori算法。同时也知道了Apriori算法在实现过程中由于需要频繁的扫描数据集导致效率较低。
FP-growth算法基于Apriori构建,但采用了高级的数据结构减少扫描次数,大大加快了算法速度。FP-growth算法只需要对数据库进行两次扫描,而Apriori算法对于每个潜在的频繁项集都会扫描数据集判定给定模式是否频繁,因此FP-growth算法的速度要比Apriori算法快。
FP-growth算法优缺点
- 优点:
- 因为 FP-growth 算法只需要对数据集遍历两次,所以速度更快。
- FP树将集合按照支持度降序排序,不同路径如果有相同前缀路径共用存储空间,使得数据得到了压缩。
- 不需要生成候选集。
- 比Apriori更快。
- 缺点:
- FP-Tree第二次遍历会存储很多中间过程的值,会占用很多内存。
- 构建FP-Tree是比较昂贵的。
适用数据类型:标称型数据(离散型数据)。
FP-growth算法发现频繁项集的基本过程如下:
- 构建FP树
- 从FP树中挖掘频繁项集
为构建FP树,需要对原始数据集扫描两遍。第一遍对所有元素项的出现次数进行计数。数据库的第一遍扫描用来统计出现的频率,而第二遍扫描中只考虑那些频繁元素。
FP树 介绍
- FP树的节点结构如下:
class treeNode:
def __init__(self, nameValue, numOccur, parentNode):
self.name = nameValue # 节点名称
self.count = numOccur # 节点出现次数
self.nodeLink = None # 不同项集的相同项通过nodeLink连接在一起
# needs to be updated
self.parent = parentNode # 指向父节点
self.children = {} # 存储叶子节点
FP-growth 原理
基于数据构建FP树
步骤1:
1. 遍历所有的数据集合,计算所有项的支持度。
2. 丢弃非频繁的项。
3. 基于 支持度 降序排序所有的项。

4. 所有数据集合按照得到的顺序重新整理。
5. 重新整理完成后,丢弃每个集合末尾非频繁的项。

步骤2:
1. 读取每个项集插入FP树中,同时用一个头部链表数据结构维护不同集合的相同项。

最终得到下面这样一棵FP树

步骤3:
从FP树中挖掘出频繁项集
1. 对头部链表进行降序排序
2. 对头部链表节点从小到大遍历,得到条件模式基,同时获得一个频繁项集。

如上图,从头部链表 t 节点开始遍历,t 节点加入到频繁项集。找到以 t 节点为结尾的路径如下:

去掉FP树中的t节点,得到条件模式基([路径]:值),[z,x,y,s,t]:2,[z,x,y,r,t]:1 。条件模式基的值取决于末尾节点 t ,因为 t 的出现次数最小,一个频繁项集的支持度由支持度最小的项决定。所以 t 节点的条件模式基的值可以理解为对于以 t 节点为末尾的前缀路径出现次数。
3. 条件模式基继续构造条件 FP树, 得到频繁项集,和之前的频繁项组合起来,这是一个递归遍历头部链表生成FP树的过程,递归截止条件是生成的FP树的头部链表为空。
根据步骤 2 得到的条件模式基 [z,x,y,s,t]:2,[z,x,y,r,t]:1 作为数据集继续构造出一棵FP树,计算支持度,去除非频繁项,集合按照支持度降序排序,重复上面构造FP树的步骤。最后得到下面 t-条件FP树 :

据 t-条件FP树 的头部链表进行遍历,从 y 开始。得到频繁项集 [t,y] 。然后又得到 y 的条件模式基,构造出 [t,y] 的条件FP树,即 ty-条件FP树。继续遍历ty-条件FP树的头部链表,得到频繁项集 [t,y,x] ,然后又得到频繁项集 [t,y,x,z] 。 然后得到构造 tyxz-条件FP树 的头部链表是空的,终止遍历。我们得到的频繁项集有 ,这只是一小部分。
- 条件模式基:头部链表中的某一点的前缀路径组合就是条件模式基,条件模式基的值取决于末尾节点的值。
- 条件FP树:以条件模式基为数据集构造的FP树叫做条件FP树。
FP-growth 代码讲解
完整代码地址: https://github.com/apachecn/AiLearning/blob/master/src/py2.x/ml/12.FrequentPattemTree/fpGrowth.py
main 方法大致步骤:
if __name__ == "__main__":
simpDat = loadSimpDat() #加载数据集。
initSet = createInitSet(simpDat) #对数据集进行整理,相同集合进行合并。
myFPtree, myHeaderTab = createTree(initSet, 3)#创建FP树。
freqItemList = []
mineTree(myFPtree, myHeaderTab, 3, set([]), freqItemList) #递归的从FP树中挖掘出频繁项集。
print freqItemList
大家看懂原理,再仔细跟踪一下代码。基本就没有问题了。
参考文章:https://github.com/apachecn/AiLearning/blob/dev/blog/ml/12.使用FP-growth算法来高效发现频繁项集.md