FP-growth算法:
能够更有效地挖掘数据,这种算法虽然能更为高效地发现频繁项集,但是不能用于发现关联规则。只需要对数据库进行两次扫描,比Apriori算法更快
FP树类定义:
class treeNode:
def __init__(self, nameValue, numOccur, parentNode):
self.name = nameValue #节点名字
self.count = numOccur #计数值
self.nodeLink = None #用于链接相似的元素项
self.parent = parentNode #指向当前节点的父节点
self.chidren = {} #存放节点的子节点
#对count变量增加给定值
def inc(self, numOcuur):
self.count += numOcuur
#用于将树以文本形式显示
def disp(self,ind=1):
print(''*ind,self.name,'', self.count)
for child in self.chidren.values():
child.disp(ind+1)
FP树构建函数:
class treeNode:
def __init__(self, nameValue, numOccur, parentNode):
self.name = nameValue
self.count = numOccur
self.nodeLink = None
self.parent = parentNode
self.chidren = {}
def inc(self, numOcuur):
self.count += numOcuur
def disp(self,ind=1):
print(' '*ind,self.name,' ', self.count)
for child in self.chidren.values():
child.disp(ind+1)
#dataSet数据集,minSup最小支持度
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 list(headerTable.keys()):
if headerTable[k] < minSup:
del(headerTable[k]) #删掉出现次数少于minSup的项
freqItemSet = set(headerTable.keys()) #创建只包含空集合的根节点
#如果所有的项都不频繁就不需要就行下一步处理
if len(freqItemSet) == 0:
return None,None
for k in headerTable:
headerTable[k] = [headerTable[k], None] #扩展头指针表保存计数值及指向每种类型第一个元素项的指针
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.chidren:
inTree.chidren[items[0]].inc(count) #更新该元素项的计数
else:
#如果不存在,则创建一个新的treeNode并将其作为一个子节点添加到树中
inTree.chidren[items[0]] = treeNode(items[0], count, inTree)
#如果头指针表的节点为叶节点
if headerTable[items[0]][1] == None:
headerTable[items[0]][1] = inTree.chidren[items[0]]#叶子节点的子节点为None
else:
updateHeader(headerTable[items[0]][1], inTree.chidren[items[0]])#链接头节点表和子节点
if len(items) > 1:
updateTree(items[1::], inTree.chidren[items[0]], headerTable, count)#迭代调用,[1::]每次调用去掉列表的第一个元素
#确保节点链接指向树中该元素项的每一个实例
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 simpDat
def createInitSet(dataSet):
retDict = {}
for trans in dataSet:
retDict[frozenset(trans)] = 1
return retDict
if __name__ == '__main__':
simpDat = loadSimpDat()
initSet = createInitSet(simpDat)
print(initSet)
myFPtree, myHeaderTab = createTree(initSet, 3)
myFPtree.disp()
结果如下:与书上不同
从一棵FP树中挖掘频繁项集:
发现以给定元素项结尾的所有路径的函数:
#迭代上溯整棵树
def ascendTree(leafNode, prefixPath):
if leafNode.parent != None:
prefixPath.append(leafNode.name)
ascendTree(leafNode.parent, prefixPath)
#每遇到一个元素项都会调用ascendTree()来上溯FP树,并收集所有遇到的元素项的名称
def findPrefixPath(basePat, treeNode):
condPats = {}
while treeNode != None:
prefixPath = []
ascendTree(treeNode, prefixPath)
if len(prefixPath) > 1:
condPats[frozenset(prefixPath[1:])] = treeNode.count #去掉自己
return condPats
递归查找频繁项集的mineTree函数:
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)#将每一个频繁项添加到频繁项集列表freqItemList
condPattBases = findPrefixPath(basePat, headerTable(basePat)[1])#找路径
myCondTree, myHead = createTree(condPattBases, minSup)#创建树
#树中有元素项
if myHead != None:
mineTree(myCondTree, myHead, minSup, newFreqSet, freqItemList)#递归调用mineTree()
运行了很久不出结果!