第12章:使用FP-growth演算法高效發現頻繁項集
阿新 • • 發佈:2018-12-02
原理:通過構建FP樹,在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(): #self.children.values()是相當於treeNode類 #對不同層級的treeNode輸出不同空格 child.disp(ind+1)
構建FP樹
第一次遍歷資料集先獲得每個元素出現的頻率,去掉不滿足最小支援度的元素;然後構建FP樹,讀入每個項集,並將其新增到一條已存在的路徑中,如果該路徑不存在,則建立一條路徑。在新增每個項集時,要先對項集中的元素按照頻率由大到小排序。下圖展示了將非頻繁項移除並重排序後的事務資料集。
對事務記錄過濾和排序後就可以建立FP樹了,從空集開始,向其中不斷新增頻繁項集。如下圖所示。
程式碼:
def createTree(dataSet,minSup=1): headerTable={} for trans in dataSet: for item in trans: #headerTable.get(item,0)返回指定鍵的值,沒有返回0 headerTable[item]=headerTable.get(item,0)+dataSet[trans] #移除不滿足最小支援度的項 for k in list(headerTable.keys()): if headerTable[k]<minSup: del(headerTable[k]) freqItemSet=set(headerTable.keys()) #如果沒有元素項滿足要求則退出 if(len(freqItemSet)==0): return None,None #重新調整headerTable以使用Node Link 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)] #使用排序後的頻率項對樹填充 #pdb.set_trace() 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函式 updateTree(items[1::], inTree.children[items[0]], headerTable, count) def updateHeader(nodeToTest,targetNode): while(nodeToTest.nodeLink!=None): nodeToTest=nodeToTest.nodeLink nodeToTest.nodeLink=targetNode