FP-growth算法个人总结

FP树

FP-growth算法将数据存储在一种称为FP树的紧凑数据结构中。FP代表频繁模式。一棵FP树看上去和其他的树类似,但是它通过链接来连接相似的元素,被连接的元素可以看作一个链表。下面是FP树的一个例子:
在这里插入图片描述
同搜索树不同,一个元素可以在FP树中出现多次,FP树会存储项集出现的频率,每个项集会以路径形式存在树中。存在相似元素的集合会共享树的一部分。树节点给出集合中单个元素及其在序列中出现的次数,路径会给出该序列出现的次数。相似项之间的链接即为节点连接,用于快速发现相似项的位置。链接在图中用虚曲线表示,它链接了相同的元素。
下面是构成这个FP树所用到的数据:

ID 元素项
1 rzhjp
2 zyxwvuts
3 z
4 rxnos
5 yrxzqtp
6 yzxeqstm

在上面的那棵树中,项集中的元素是某个节点到根节点之间路径上所有元素的集合,该项集出现的频率是第一个节点旁边代表的数字。比如集合{z}一共出现了5次,集合{r,z}一共出现了一次,这和表中的数据结论是相吻合的。至于树中没有出现的元素,是因为我们同样对这棵树设置了最小支持度,小于该值的项集不会出现。这棵树设置的最小支持度为3,所以其他的元素并没有出现在这棵树上。

FP-growth算法的工作流程如下:首先构成FP树,然后利用它来挖掘频繁项集。
为了构建FP树,需要对原始数据扫描两遍。第一遍对所有元素项出现的次数进行统计,把那些不符合支持度的元素去掉。数据库的第一遍扫描用于统计出现的频率,第二次扫描只考虑那些频繁元素。

构建FP树

因为最终结果是要构建一棵FP树,为成功构建该树,需要一个容器来保存。

创建FP树的数据结构

由于树中需要保存大量信息,为了方便之后的计算,我们将树节点存储到一个类中。

class TreeNode:
    def __init__(self,nameVal,numCnt,parentNode):
        self.name=nameVal       #元素名
        self.cnt=numCnt         #出现次数
        self.nodeLink=None      #节点链接
        self.parent=parentNode  #因为路径是从下到上遍历节点,所以需要父节点
        self.children={
   }        #孩子字典

    def inc(self,numCnt):       #自增运算
        self.cnt+=numCnt

    def display(self,ind=1):    #结构展示
        print(' '*ind,self.name,' ',self.cnt)
        for child in self.children.values():
            child.display(ind+1)

现在的FP树数据结构已经构建好了,下面就可以构建FP树了

构建FP树

除了构建FP树所需的数据结构,还需要一个头指针来指向给定类型的第一个实例。利用头指针,可以快速访问树中给定类型的所有元素,下面是一个头指针表的示意图:
在这里插入图片描述
这里的头指针表用字典的形式来存储。除了用于保存指针外,头节点还用来保存FP树种每类元素d总数。
第一次遍历数据集会获得每个元素项出现的频率。接下来去掉不满足最小支持度的元素项。再下一步构建FP树。在构建时,读入每个项集并将其添加到已经存在的路径中,如果路径不存在,则创建一条新路径。
每个事务是一个无序集合,假设有集合{z,y}和{y,z},那么在FP树中,相同项只会表示一次。为了解决这个问题,将集合添加到树之前,需要对每个集合进行排序。排序基于元素项的出现频率来进行。上面的数据经过去除非频繁项集和排序后得到以下结果:

ID 元素项 处理后
1 rzhjp zr
2 zyxwvuts zxyst
3 z z
4 rxnxsros xsr
5 yrxzqtp zxyrt
6 yzxeqstm zxyst

在对集合进行过滤排序之后,就可以构建FP树了。从空集开始,向其不断添加频繁项集。过滤排序后的事务依次添加到树中,如果树中已存在现有的元素,则增加现有元素的值。如果元素不存在,则向树中添加一个分支。对前面数据中前两条进行添加的过程如下:
在这里插入图片描述
构建树的详细代码如下:

def create_tree(dataSet,minSup=1):
    #dataSet较为特殊,它是一个字典形式,存放项集和对应的出现次数,在一开始出现次数都为1
    #minSup为最小支持度
    headerTable={
   }  #存放头指针表
    #第一次遍历数据集
    for tran in dataSet:    #由于dataSet是字典,这个循环是对于字典中的每一个键值
        for item in tran:   #对于键值中的每一个元素
            headerTable[item]=headerTable.get(item,0)+dataSet[tran] #更新该元素在全局中出现的次数
	#第一次遍历结束
    for key in list(headerTable.keys()):    #元素去重,对于每一个候元素来说
        if headerTable[key]<minSup:         #如果当前元素支持度小于最小值
            del(headerTable[key])           #去除

    freItemSet=set(headerTable.keys())      #去重后的元素
    if len(freItemSet)==0:
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值