本篇的数据和代码参见:https://github.com/stonycat/ML-in-Action
本章会在上一章讨论话题的基础上进行扩展,将给出一个非常好的频繁项集发现算法。该算法称作FP-growth,它比上一章讨论的Apriori算法要快。它基于Apriori构建,但在完成相同任务时采用了一些不同的技术。这里的任务是将数据集存储在一个特定的称作FP树的结构之后发现频繁项集或者频繁项对,即常在一块出现的元素项的集合FP树。
FP-growth算法只需要对数据库进行两次扫描,而Apriori算法对于每个潜在的频繁项集都会扫描数据集判定给定模式是否频繁,因此FP-growth算法的速度要比Apriori算法快。
它发现频繁项集的基本过程如下:
(1) 构建FP树
(2) 从FP树中挖掘频繁项集
一、创建FP树
#FP树中节点的类定义
class treeNode:
def __init__(self, nameValue, numOccur, parentNode):
self.name = nameValue
self.count = numOccur
self.nodeLink = None #nodeLink 变量用于链接相似的元素项
self.parent = parentNode #指向当前节点的父节点
self.children = {} #空字典,存放节点的子节点
def inc(self, numOccur):
self.count += numOccur
#将树以文本形式显示
def disp(self, ind=1):
print (' ' * ind, self.name, ' ', self.count)
for child in self.children.values():
child.disp(ind + 1)
测试创建树,添加子节点:
二、构建FP树
FP-growth算法将数据存储在一种称为FP树的紧凑数据结构中。FP代表频繁模式(Frequent Pattern)。一棵FP树看上去与计算机科学中的其他树结构类似,但是它通过链接(link)来连接相似元素,被连起来的元素项可以看成一个链表。
在创建真正的频繁集FP树之前,需要对数据进行过滤(不符合频繁要求)和排序(按照频繁度排序)。利用头指针表,可以快速访问FP树中一个给定类型的所有元素。
同搜索树不同的是,一个元素项可以在一棵FP树中出现多次。FP树会存储项集的出现频率,而每个项集会以路径的方式存储在树中。存在相似元素的集合会共享树的一部分。只有当集合之间完全不同时,树才会分叉。 树节点上给出集合中的单个元素及其在序列中的出现次数,路径
会给出该序列的出现次数。
#构建FP-tree
def createTree(dataSet, minSup=1):
headerTable = {}
for trans in dataSet: #第一次遍历:统计各个数据的频繁度
for item in trans:
headerTable[item] = headerTable.get(item, 0) + dataSet[trans]
#用头指针表统计各个类别的出现的次数,计算频繁量:头指针表[类别]=出现次数
for k in headerTable.keys(): #删除未达到最小频繁度的数据