FP-growth算法思想和其python實現


第十二章 使用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,也就是找到所有單個的頻繁項。第二遍的時候是為了將每一個事務融入到樹中。

  發現頻繁項集是非常有用的操作,經常需要用到,我們可以將其用於搜索,購物交易等多種場景。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM