FP_growth算法zz


  FP_growth算法是韓家煒老師在2000年提出的關聯分析算法,該算法和Apriori算法最大的不同有兩點:第一,不產生候選集,第二,只需要兩次遍歷數據庫,大大提高了效率,用 31646 條測試記錄, 最小支持度是2%,用 Apriori 算法要半個小時但是用FP_growth算法只要6分鍾就可以了,效率非常明顯。它的核心是FP_tree,一種樹型數據結構,特點是盡量把相同元素用一個節點表示,這樣就大大減少了空間,和birch算法有類似的思想。還是以如下數據為例。FP_growth算法
每一行表示一條交易,共有9行,既9筆交易,左邊表示交易ID,右邊表示商品名稱。最小支持度是22%,那么每件商品至少要出現9*22%=2次才算頻繁。第一次掃描數據庫,統計每件商品出現的次數,按次數對各個商品遞減排序,有:FP_growth算法。然后第二次掃描數據庫,在每條交易中按此種順序給商品排序,如果有某個商品出現的次數小於閾值2,則刪除該商品,有:

FP_growth算法
剩下的就是構造FP_tree了,這是核心,樹的每個節點的結構體如下:

//FP-tree的存儲結構
typedef struct CSNode{
 //商品編號
 int item;
 //次數
 int count;
 //父節點,孩子節點,兄弟節點
 CSNode *parent,*firstchild,*nextsibling;
 //相同商品的前驅,后繼節點,方便將相同商品的節點連接起來,根節點的直接孩子節點的這兩個指針都是空
 CSNode *pre,*next;
}*CSTree;
其中item,*firstchild,*nextsibling是樹這個結構體常用的屬性。count記錄商品item出現的次數,*parent是為 了方便從葉子節點逆向訪問根節點而設置的。*pre,*next的注釋已經很清楚了。構造樹的原則是:將每條記錄看做一個從根節點到葉子節點的路徑,如果 某個商品在節點中已經存在了,則對應count計數器加1,相當於所有的前綴都要加1,如果不存在則在該條記錄的后面商品開辟一條新的路徑。下面一條一條 記錄演示怎么構造FP_tree。

    第三次訪問數據庫,構造FP_tree。第一條記錄:I2,I1,I5,有:

FP_growth算法
父節點沒有表示出來,根節點是空節點。2:1表示商品2出現了1次,其他表示類推。左邊的 數組按照商品順序遞減排列,保存了各個商品的當前指針,目的是為了在后面找到相同的后綴,將相同的商品用單項箭頭虛線連起來,實際是雙向鏈表鏈接的,並且 將此時的節點商品1和節點商品5保存為商品1和商品5的當前指針,而對於商品2,商品3,商品4的當前指針還在左邊的數組中保存。注意根節點的直接孩子不 用連起來,后面會講理由。第二條記錄:I2,I4,有:

FP_growth算法
該記錄和第一條記錄共用前綴I2,所以商品2的次數要加1,而商品4則作為商品2的一個新孩子節點,這里沒有把兄弟節點畫出來。並且左邊商品4要指向該節點,此時商品4的當前指針指向節點商品4。第三條記錄:I2,I3,類似,結果是:

FP_growth算法
第四條記錄:I2,I1,I4有:

FP_growth算法
當添加完商品4后,商品4的當前指針要指向新的節點商品4,此時兩條紅色的虛線就把以商品4為后綴的節點連起來了。第5條記錄:I1,I3,有:

FP_growth算法
商品1由於和根節點的所有直接子孩子(這里只有商品2這個子孩子)不同,因此要另外開辟一條路徑。商品3的當前指針要指向新的節點商品3,如圖中的黃色虛線所指,到這里體現了構造FP_tree的一般性了。再把剩下的記錄都加進來,最終的FP_tree是:

FP_growth算法
這顆FP_tree最大程度的把相同的商品放在用同一個節點保存,最大限度的節省了空間。剩下的工作就是挖掘這顆FP_tree了。

    挖掘的目的是找出FP_tree的各個路徑中相同的集合,有兩中方式,方式一,從根節點朝葉子節點順着遍歷樹,方式二,從葉子節點朝根節點逆着遍歷樹。想 想方式一挺麻煩的,幸虧我們設置了*parent指針,通過它就可以很方便的用方式二。我們從商品出現次數由少到多的順序開始遍歷樹,先從商品5開始,由 於有*pre,*next指針分方便將所有以商品5做為葉子節點的路徑全找出來,然后再根據*parent指針找到父節點,根節點是空不用找。以I5做元 素的條件模式基是:{(I2 I1:1),(I2 I1 I3:1)}。后面的1表示出現商品I2,I1,I5同時出現的次數。現在解釋為什么:根節點的直接孩子不用*pre,*next指針連起來,因為假如連 起來的話,那么以它為后綴時,將沒有前綴,也就是說它的頻繁項集是1,這在大多數情況下沒意義。由它構造出條件FP_tree,注意由於開始按照商品名稱 排序了,那么條件模式基中的每一項也會按照這種方式排序。如果條件模式基中某項A是另外一項B的子集那么在算B時,要將A出現的次數加上,實現這個功能最 簡單明了的方法就是一一匹配,假如條件模式基共有N項,則時間復雜度是N的平方,若先按照條件模式基的長度遞增排序得到:{(I2 I1:1),(I2 I1 I3:1)},排序的時間復雜度是N*log(N),那么只有可能是長度短的項是長度長的項的子集,此時總匹配次數是:N-1 + N-2 + ,,, + 1 = N*(N-1)/2,和前面的排序時間加起來是:N*log(N) + N*(N-1)/2當N大於時4時,該值小於N的平方。在實際中N一般會大於4。最終我們得到以I5作為后綴的頻繁項集是:{I2 I5:2},{I1 I5:2},{I2 I1 I5:2}他們出現的次數都大於等於最小支持度。類似可以得到其它后綴的頻繁項集。

    FP_growth算法不產生候選序列,並且只需要3次遍歷數據庫,對比Apriori算法而言有了很大的改進。其實想想這也符合歷史發展的規 律,Apriori在1993年才提出來的,那是數據挖掘才剛起步,而到2000年時,已經有了一定的發展,FP_growth是站在Apriori的肩 膀上發明的,這種現象具有普遍性。


免責聲明!

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



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