机器学习实战-使用FP-growth算法来高效发现频繁项集
来源:互联网 发布:gtx1070 gpu数据 编辑:程序博客网 时间:2024/05/21 10:40
上一章介绍了发现频繁项集与关键规则的算法,本章将继续关注发现频繁项集这一任务。我们会深入探索该任务的解决方法,并应用FP-growth算法进行处理。这种算法虽然能更为高效地发现频繁项集,但不能用于发现关联规则。
FP-growth算法
优点:一般要快于Apriori
缺点:实现比较困难,在某些数据集上性能会下降
适用数据类型:标称型数据
FP-growth算法讲数据存储在一种称为FP树的紧凑数据结构中。FP代表频繁模式,Frequent pattern。同搜索树不同的是,一个元素项可以在一棵FP树中出现多次。FP树会存储项集的出现频率,而每个项集会以路径的方式存储在树中。
相似点之间的链接即节点链接(node link),用于快速发现相似的位置。
本章的FP树比书中的其他树更加复杂,因此要创建一个类来保存树的每一个节点:
#FP树class treeNode: def __init__(self, nameValue, numOccur, parentNode): self.name = nameValue self.count = numOccur#计数器 self.nodeLink = None#用于链接相似的元素项 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)
先创建树中的一个单节点:
In [45]: import fpGrowth ...: rootNode = fpGrowth.treeNode('pyramid',9,None)
接下来增加一个子节点:
In [46]: rootNode.children['eye'] = fpGrowth.treeNode('eye',13,None)
显示子节点:
In [47]: rootNode.disp() pyramid 9 eye 13
再增加一个节点看看子节点的展示效果:
In [48]: rootNode.children['phoenix']=fpGrowth.treeNode('phoenix',3,None) ...: rootNode.disp() ...: pyramid 9 eye 13 phoenix 3
除了刚刚给出的FP树以外,还需要一个头指针表来指向给定类型的第一个实例。这里使用一个字典作为数据结构,来保存头指针表。除了存放指针外,头指针表还可以用来存放FP树中每类元素的总数。
接下来,我们通过代码来实现上述过程:
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(): #移除不满足最小支持度的元素项 if headerTable[k] < minSup: del(headerTable[k]) freqItemSet = set(headerTable.keys()) #print 'freqItemSet: ',freqItemSet if len(freqItemSet) == 0: return None, None #都不满足,则退出 for k in headerTable: headerTable[k] = [headerTable[k], None] #修改为下一步准备 #print 'headerTable: ',headerTable retTree = treeNode('Null Set', 1, None) #根节点 for tranSet, count in dataSet.items(): #第二次遍历 localD = {} for item in tranSet: #排序 if item in freqItemSet: localD[item] = headerTable[item][0] if len(localD) > 0: orderedItems = [v[0] for v in sorted(localD.items(), key=lambda p: p[1], reverse=True)] updateTree(orderedItems, retTree, headerTable, count)#用排序后的频率项进行填充 return retTree, headerTable def updateTree(items, inTree, headerTable, count): if items[0] in inTree.children:#检查第一个元素是否作为子节点存在 inTree.children[items[0]].inc(count) #更新计数 else: #新建一个子节点添加到树中 inTree.children[items[0]] = treeNode(items[0], count, inTree) if headerTable[items[0]][1] == None: headerTable[items[0]][1] = inTree.children[items[0]] else: updateHeader(headerTable[items[0]][1], inTree.children[items[0]]) if len(items) > 1:#对剩下的元素项迭代调用,每一次奥调用去掉第一个元素 updateTree(items[1::], inTree.children[items[0]], headerTable, count)def updateHeader(nodeToTest, targetNode): #确保节点链接指向树中该元素项的每一个实例 while (nodeToTest.nodeLink != None): #直达链尾 nodeToTest = nodeToTest.nodeLink nodeToTest.nodeLink = targetNode
下面将数据集和数据包装器加入代码中:
def loadSimpDat(): simpDat = [['r', 'z', 'h', 'j', 'p'], ['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']] return simpDatdef createInitSet(dataSet): retDict = {} for trans in dataSet: retDict[frozenset(trans)] = 1 return retDict
首先,导入数据库实例:
In [2]: import fpGrowth ...: simpDat = fpGrowth.loadSimpDat() ...: In [3]: simpDatOut[3]: [['r', 'z', 'h', 'j', 'p'], ['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']]
接下来为了函数createTree(),需要对上面的数据进行格式化处理:
In [4]: initSet = fpGrowth.createInitSet(simpDat) ...: initSet ...: Out[4]: {frozenset({'e', 'm', 'q', 's', 't', 'x', 'y', 'z'}): 1, frozenset({'n', 'o', 'r', 's', 'x'}): 1, frozenset({'z'}): 1, frozenset({'s', 't', 'u', 'v', 'w', 'x', 'y', 'z'}): 1, frozenset({'p', 'q', 'r', 't', 'x', 'y', 'z'}): 1, frozenset({'h', 'j', 'p', 'r', 'z'}): 1}
于是可以通过如下 命令创建FP树:
In [10]: myFPtree, myHeaderTab = fpGrowth.createTree(initSet, 3) ...: myFPtree.disp() ...: Null Set 1 x 1 s 1 r 1 z 5 x 3 y 3 s 2 t 2 r 1 t 1 r 1
上面给出的是元素项及其对应的频率计数值,其中每个缩进表示所处的树的深度。
现在我们已经构建了FP树,接下来就使用它进行数据挖掘。
从FP树中抽取频繁项集的三个基本步骤如下:
(1)从FP树中获取条件模式基;
(2)利用条件模式基,构建一个条件FP树;
(3)迭代重复步骤(1)和步骤(2),直到树包含一个元素项为止。
首先从上一节发现的已经保存在头指针表中的单个频繁元素项开始。对于每一个元素项,获得其对于的条件模式基(conditional pattern base)。条件模式基是以所查找元素项为结尾的路径集合。每一条路径其实都是一条前缀路径(prefixpath)。简而言之,一条前缀路径是介于所查找元素项与树根节点之间的所有内容。
下面的程序清单给出了前缀路径发现的代码:
def ascendTree(leafNode, prefixPath): #迭代回溯整棵树 if leafNode.parent != None: prefixPath.append(leafNode.name) ascendTree(leafNode.parent, prefixPath)#遍历链表直到到达结尾,每遇到一个元素项都会调用ascendTree()函数来上溯FP树,ing收集所有遇到的元素项的名称 def findPrefixPath(basePat, treeNode): condPats = {} while treeNode != None: prefixPath = [] ascendTree(treeNode, prefixPath) if len(prefixPath) > 1: condPats[frozenset(prefixPath[1:])] = treeNode.count treeNode = treeNode.nodeLink return condPats
使用之前构建的树来看一下实际的运行效果:
In [4]: import fpGrowth ...: fpGrowth.findPrefixPath('x',myHeaderTab['x'][1]) ...: Out[4]: {frozenset({'z'}): 3}In [5]: fpGrowth.findPrefixPath('z',myHeaderTab['z'][1])Out[5]: {}In [6]: fpGrowth.findPrefixPath('r',myHeaderTab['r'][1])Out[6]: {frozenset({'s', 'x'}): 1, frozenset({'z'}): 1, frozenset({'x', 'y', 'z'}): 1}
下面继续补充完整程序:
def mineTree(inTree, headerTable, minSup, preFix, freqItemList): bigL = [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1])]#对头指针表的元素项按照其出现的频率进行排序 for basePat in bigL: #从头指针的底端开始 newFreqSet = preFix.copy() newFreqSet.add(basePat) freqItemList.append(newFreqSet) condPattBases = findPrefixPath(basePat, headerTable[basePat][1]) myCondTree, myHead = createTree(condPattBases, minSup) if myHead != None: #递归调用 print 'conditional tree for: ',newFreqSet myCondTree.disp(1) mineTree(myCondTree, myHead, minSup, newFreqSet, freqItemList)
接下来运行mineTree(),显示出所有的条件树:
In [14]: import fpGrowth ...: freqItems = [] ...: fpGrowth.mineTree(myFPtree, myHeaderTab, 3, set([]),freqItems) ...: conditional tree for: set(['y']) Null Set 1 x 3 z 3conditional tree for: set(['y', 'z']) Null Set 1 x 3conditional tree for: set(['s']) Null Set 1 x 3conditional tree for: set(['t']) Null Set 1 y 3 x 3 z 3conditional tree for: set(['z', 't']) Null Set 1 y 3 x 3conditional tree for: set(['x', 'z', 't']) Null Set 1 y 3conditional tree for: set(['x', 't']) Null Set 1 y 3conditional tree for: set(['x']) Null Set 1 z 3
下面检查一下返回的项集是否与条件树匹配:
In [15]: freqItemsOut[15]: [{'y'}, {'y', 'z'}, {'x', 'y', 'z'}, {'x', 'y'}, {'s'}, {'s', 'x'}, {'t'}, {'t', 'z'}, {'t', 'y', 'z'}, {'t', 'x', 'z'}, {'t', 'x', 'y', 'z'}, {'t', 'x'}, {'t', 'x', 'y'}, {'t', 'y'}, {'r'}, {'x'}, {'x', 'z'}, {'z'}]
未完待续
- [完]机器学习实战 第十二章 使用FP-growth算法来高效发现频繁项集
- 【机器学习实战-python3】使用FP-growth算法来高效 发现频繁项集
- 机器学习实战-使用FP-growth算法来高效发现频繁项集
- 【机器学习实战】第12章 使用FP-growth算法来高效发现频繁项集
- 【机器学习实战】第12章 使用 FP-growth 算法来高效发现频繁项集
- 【机器学习实战】第12章 使用FP-growth算法来高效发现频繁项集
- 机器学习实战笔记-使用FP-growth算法来高效发现频繁项集
- 机器学习实战代码详解(12)使用FP-growth算法来高效发现频繁集
- 《机器学习实战》笔记之十二——使用FP-Growth算法来高效发现频繁项集
- 代码注释:机器学习实战第12章 使用FP-growth算法来高效发现频繁项集
- py2.7《机器学习实战》使用FP-growth算法高效发现频繁项集
- 机器学习之使用FP-growth算法来高效发现频繁项集
- 使用FP-growth算法来高效发现频繁项集
- 使用FP-growth算法来高效发现频繁项集
- 使用FP-growth算法来高效发现频繁项集
- 机器学习之-使用FP-growth算法来高效发现频繁项集-具体怎么实现及应用
- FP-growth算法高效发现频繁项集
- FP-growth算法高效发现频繁项集
- nlp论文阅读:When Are Tree Structures Necessary for Deep Learning of Representations?
- MapReduce----辅助排序(二次排序)
- hashmap的ConcurrentModificationException异常处理方法
- #NOIP模拟赛#多边形Polygon(枚举 + 模拟)
- dotnet core 2.0 安装
- 机器学习实战-使用FP-growth算法来高效发现频繁项集
- Leetcode2D平面DFS
- 单体应用对比微服务
- Cellular Automaton UVA
- jzoj 3456 恭介的法则
- 临时表经典使用范例
- poj 3984 迷宫问题 (BFS)
- 2017"百度之星"程序设计大赛
- 配置tomcat-users.xml