第十二章 使用FP-growth算法高效的發現頻繁項集
一.導語
FP-growth算法是用於發現頻繁項集的算法,它不能夠用於發現關聯規則。FP-growth算法的特殊之處在於它是通過構建一棵Fp樹,然后從FP樹上發現頻繁項集。
FP-growth算法它比Apriori算法的速度更快,一般能夠提高兩個數量級,因為它只需要遍歷兩遍數據庫,它的過程分為兩步:
1.構建FP樹
2.利用FP樹發現頻繁項集
二.FP樹
FP樹它的形狀與普通的樹類似,樹中的節點記錄了一個項和在此路徑上該項出現的頻率。FP樹允許項重復出現,但是它的頻率可能是不同的。重復出現的項就是相似項,相似項之間的連接稱之為節點連接,沿着節點連接我們可以快速的發現相似的項。
FP樹中的項必須是頻繁項,也就是它必須要滿足Apriori算法。FP樹的構建過程需要遍歷兩邊數據庫,第一遍的時候我們統計出所有項的頻率,過濾掉不滿足最小支持度的項;第二遍的時候我們統計出每個項集的頻率。
三.構建FP樹
1.要創建一棵樹,首先我們需要定義樹的數據結構。
這個數據結構有五個數據項,其中的parent表示父節點, children表示孩子節點, similar表示的相似項。
2.創建一棵Fp樹
def createTree(dataSet, minSup=1):
headerTable = {}
# in order to catch the all the item and it's frequent
for transaction in dataSet:
for item in transaction:
headerTable[item] = headerTable.get(item, 0) + dataSet[transaction]
# delete the item which is not frequent item
for key in headerTable.keys():
if headerTable[key] < minSup:
del(headerTable[key])
frequentSet = headerTable.keys()
# if the frequentSet is empty, then we can finish the program early
if len(frequentSet) == 0:
return None, None
# initialize the begin link of headerTable is None
for key in headerTable.keys():
headerTable[key] = [headerTable[key], None]
# initialize the fp-tree
retTree = treeNode("RootNode", 1, None)
# rearrange the transaction and add the transaction into the tree
for transData, times in dataSet.items():
arrangeTrans = {}
for item in transData:
if item in frequentSet:
arrangeTrans[item] = headerTable[item][0]
if len(arrangeTrans)>0:
sortTrans = [v[0] for v in sorted(arrangeTrans.items(), key=lambda p:p[1], reverse=True)]
updateTree(sortTrans, retTree, headerTable, times)
return headerTable, retTree
def updateTree(sortTrans, retTree, headerTable, times):
if sortTrans[0] in retTree.children:
retTree.children[sortTrans[0]].inc(times)
else:
retTree.children[sortTrans[0]] = treeNode(sortTrans[0], times, retTree)
if headerTable[sortTrans[0]][1] == None:
headerTable[sortTrans[0]][1] = retTree.children[sortTrans[0]]
else:
updateHeader(headerTable[sortTrans[0]][1], retTree.children[sortTrans[0]])
if len(sortTrans) > 1:
updateTree(sortTrans[1::], retTree.children[sortTrans[0]], headerTable, times)
def updateHeader(nodeToTest, targetNode):
while nodeToTest.similarNode != None:
nodeToTest = nodeToTest.similarNode
nodeToTest.similarNode = targetNode
四.從一棵FP樹中挖掘頻繁項集
從一棵FP樹中挖掘頻繁項集需要三個步驟,首先我們需要找到所有的條件模式基,其次是根據條件模式基創建一棵條件FP樹,最后我們不斷的重復前兩個步驟直到樹只包含一個元素項為止
首先我們要尋找條件模式基,那么什么是條件模式基呢?所謂的條件模式基就是以查找元素結尾的所有路徑的集合。我們可以根據headertable中的nodelink來找到某一個元素在樹中的所有位置,然后根據這些位置進行前綴路徑的搜索。以下是它的python代碼:
現在我們知道了如何找條件模式基,接下來就是創建一個FP條件樹。在創建樹之前我們首先要知道什么是FP條件樹,所謂的FP條件樹就是將針對某一個條件的條件模式基構建的一棵FP樹。以下是python代碼
五.一個瀏覽新聞共現的例子
korasa.dat中有100萬條數據,我們需要從這一百萬條數據中知道最小支持度為100000的頻繁項集。如果采用Apriori算法時間非常的長,我等了好幾分鍾還沒出結果,就不等了。
然后采用本節的FP-growth算法只用了11秒多就算完了。以下是具體的代碼
六.總結
FP-growth算法作為一種專門發現頻繁項集的算法,比Apriori算法的執行效率更高。它只需要掃描數據庫兩遍,第一遍是為了找到headerTable,也就是找到所有單個的頻繁項。第二遍的時候是為了將每一個事務融入到樹中。
發現頻繁項集是非常有用的操作,經常需要用到,我們可以將其用於搜索,購物交易等多種場景。