educoder第六章 关联挖掘 实验二:FP-growth

第1关:构建FP-tree(不能粘贴复制,我只能放图了)

任务描述

本关任务:创建FP树,并且更新FP树,向其中插入新节点。

相关知识

事务ID 事务中的元素项:


  1. 001 r,z,h,j,p
  2. 002 z,y,x,w,v,u,t,s
  3. 003 z
  4. 004 r,x,n,o,s
  5. 005 y,r,x,z,q,t,p
  6. 006 y,z,x,e,q,s,t,m

这份数据一共有6条记录,每条记录中的元素就是项,第1条记录中有5个项,分别为:rzhjp。项的集合就是项集,比如,[r]是一个项集,[r,z]是一个项集,[r,z,h,j,p]也是一个项集,项集是指项的任意组合。而频繁项集是指,那些在记录中经常一起出现的项组合成的集合。那么,“经常”是怎么衡量的呢?这里就涉及到支持度的概念。支持度是说出现的次数,它可以针对单个项,也可以针对项的组合,在这6条数据记录中,r一共出现了3次,所以r的支持度是3,项集(r,x)出现了2次,所以(r,x)的支持度是2

构建FP树的准备工作

FP代表频繁模式(Frequent Pattern)。我们先看看FP树长什么样子。以下这棵FP树是根据上面那份数据记录建立的。

educoder第六章 关联挖掘 实验二:FP-growth_第1张图片

可以看出,一棵FP树看上去与计算机科学中的其他树结构类似,但是它包含着连接相似节点的链接(图中的红色虚线部分)。 相似节点是指前缀路径不同的项,如在上面的FP树中r的前缀路径有3个,分别为(z)(z,x,y)(x,s),于是,这些不同的r就叫做相似节点。用Python构建FP树时会创建一个字典结构存储这些相似元素。

构造树节点

在构建FP树之前,我们要先定义一个类,用来保存树的每一个节点。


  1. class treeNode:#构造树节点
  2. def __init__(self, nameValue, numOccur, parentNode):
  3. self.name = nameValue#节点名称
  4. self.count = numOccur #节点出现的次数
  5. self.nodeLink = None #链接指向的下一个节点
  6. self.parent = parentNode#父节点
  7. self.children = {}#子节点
  8. def inc(self, numOccur):#该函数用来增加节点出现的次数
  9. self.count += numOccur
  10. def disp(self, ind=1):#展示节点名称和出现的次数
  11. print(' ' * ind, self.name, ' ', self.count)
  12. for child in self.children.values():
  13. child.disp(ind + 1)
  14. 运行下面这段代码:
  15. rootNode=treeNode('pyramid',9,None) #创建节点
  16. rootNode.children['eye']=treeNode('eye',13,None) #增加子节点
  17. rootNode.children['phoenix']=treeNode('phoenix',3,None) #增加另一个子节点
  18. rootNode.disp() #展示树

运行结果:

由于“eye”“phoenix”都是”pyramid“的子节点,所以在展示树的结构时,“eye”“phoenix”的缩进深度相同,都比”pyramid“的缩进深度更深一级。

把原始事务数据集处理成字典的形式

除此之外,我们还需要把原始事务数据集处理成字典的形式,方面后面的函数调用。 定义两个函数,如下:


  1. from collections import OrderedDict
  2. def loadSimpDat():
  3. simpDat=[['r','z','h','j','p'],
  4. ['z','y','x','w','v','u','t','s'],['z'], ['r','x','n','o','s'],['y','r','x','z','q','t','p'],['y','z','x','e','q','s','t','m']]
  5. return simpDat
  6. def createInitSet(dataSet):
  7. retDict=OrderedDict()
  8. for trans in dataSet:
  9. retDict[frozenset(trans)]=1
  10. return retDict

函数loadSimpDat()把多条数据记录存储成列表的形式,函数createInitSet(dataSet)把每条数据记录冻结(frozenset函数)后作为字典的键,而每个键对应的值都是1

我们运行一下看看结果。


  1. simpDat=loadSimpDat()
  2. simpDat

educoder第六章 关联挖掘 实验二:FP-growth_第2张图片


  1. initSet=createInitSet(simpDat)
  2. initSet

educoder第六章 关联挖掘 实验二:FP-growth_第3张图片

第一次遍历数据集

FP树第一次扫描数据库是为了获得每个元素项的出现频率。实现这一步的代码如下(注:代码中的dataSet是经过上面所说的createInitSet(dataSet)函数处理后的数据结果,即一个字典结构):


  1. headerTable={}#用来存储每项元素及其出现次数
  2. for trans in dataSet:#遍历每条记录
  3. for item in trans:#遍历每条记录的每项元素
  4. headerTable[item]=headerTable.get(item,0)+dataSet[trans]#计算每项元素的出现次数
  5. print headerTable
  6. print ("headerTable's length: %s" % len(headerTable))

这时headerTable包含17个元素:

接下来,去掉不满足最小支持度的元素项。


  1. for k in headerTable.keys():
  2. if headerTable[k]<3:#这里的3是指最小支持度的取值,可根据实际情况改变
  3. del(headerTable[k])#如果某项元素的支持度小于最小支持度,从headerTable中删掉该元素
  4. freqItemSet=set(headerTable.keys())#freqItemSet中的每一项元素的支持度均大于或等于最小支持度
  5. print headerTable
  6. print ("headerTable's length: %s" % len(headerTable))

存储符合条件的元素

freqItemSet存储的都是符合条件的元素。如果freqItemSet非空,证明确实有符合条件的元素。从前面的运行结果可以知道,headerTable里面每一个键对应的值是该元素在所有的事务数据记录中出现的次数。现在,我们在每个键对应的值中增加一个“None”,为后面的存储相似元素做准备。 if len(freqItemSet)!=0:
for k in headerTable:
headerTable[k]=[headerTable[k],None] headerTable

构建FP树

构建FP树的思路是这样的:读入每个项集也就是每条记录,并将其添加到一条已经存在的路径中。如果该路径不存在,则创建一条新路径。假设有集合{z,x,y}{y,z,r},为了保证相同项只出现一次,需要对每条记录里的元素项进行排序。在每条记录中,这种排序是根据每个元素出现的次数进行的,也就是说出现次数越多,排位越前。

在对事务数据过滤和排序之后,就可以构建FP树了。从空集(符号为Φ)开始,依次遍历过滤,排序后的每一条记录,如果树中已经存在记录中的某个元素,那么已存在的元素增加值即可,如果树中不存在记录中的元素,那么增加一个分支。我们通过添加前两条事务为例,加深对建树的过程理解。

educoder第六章 关联挖掘 实验二:FP-growth_第4张图片

构建FP树的思路是这样的:读入每个项集也就是每条记录,并将其添加到一条已经存在的路径中。如果该路径不存在,则创建一条新路径。假设有集合{z,x,y}{y,z,r},为了保证相同项只出现一次,需要对每条记录里的元素项进行排序。在每条记录中,这种排序是根据每个元素出现的次数进行的,也就是说出现次数越多,排位越前。

编程要求

请仔细阅读右侧代码,结合相关知识,在Begin-End区域内进行代码补充,构建FP树。

测试要求

测试程序会使用测试集对你编写的代码进行测试

开始你的任务吧,祝你成功!

educoder第六章 关联挖掘 实验二:FP-growth_第5张图片

 educoder第六章 关联挖掘 实验二:FP-growth_第6张图片

 

educoder第六章 关联挖掘 实验二:FP-growth_第7张图片

 

你可能感兴趣的:(educoder,数据挖掘,数据分析,python)