在Apriori算法原理總結中,咱們對Apriori算法的原理作了總結。做爲一個挖掘頻繁項集的算法,Apriori算法須要屢次掃描數據,I/O是很大的瓶頸。爲了解決這個問題,FP Tree算法(也稱FP Growth算法)採用了一些技巧,不管多少數據,只須要掃描兩次數據集,所以提升了算法運行的效率。下面咱們就對FP Tree算法作一個總結。html
爲了減小I/O次數,FP Tree算法引入了一些數據結構來臨時存儲數據。這個數據結構包括三部分,以下圖所示:
第一部分是一個項頭表。裏面記錄了全部的1項頻繁集出現的次數,按照次數降序排列。好比上圖中B在全部10組數據中出現了8次,所以排在第一位,這部分好理解。第二部分是FP Tree,它將咱們的原始數據集映射到了內存中的一顆FP樹,這個FP樹比較難理解,它是怎麼創建的呢?這個咱們後面再講。第三部分是節點鏈表。全部項頭表裏的1項頻繁集都是一個節點鏈表的頭,它依次指向FP樹中該1項頻繁集出現的位置。這樣作主要是方便項頭表和FP Tree之間的聯繫查找和更新,也好理解。
下面咱們講項頭表和FP樹的創建過程。算法
FP樹的創建須要首先依賴項頭表的創建。首先咱們看看怎麼創建項頭表。
咱們第一次掃描數據,獲得全部頻繁一項集的的計數。而後刪除支持度低於閾值的項,將1項頻繁集放入項頭表,並按照支持度降序排列。接着第二次也是最後一次掃描數據,將讀到的原始數據剔除非頻繁1項集,並按照支持度降序排列。
上面這段話很抽象,咱們用下面這個例子來具體講解。咱們有10條數據,首先第一次掃描數據並對1項集計數,咱們發現O,I,L,J,P,M, N都只出現一次,支持度低於20%的閾值,所以他們不會出如今下面的項頭表中。剩下的A,C,E,G,B,D,F按照支持度的大小降序排列,組成了咱們的項頭表。
接着咱們第二次掃描數據,對於每條數據剔除非頻繁1項集,並按照支持度降序排列。好比數據項ABCEFO,裏面O是非頻繁1項集,所以被剔除,只剩下了ABCEF。按照支持度的順序排序,它變成了ACEBF。其餘的數據項以此類推。爲何要將原始數據集裏的頻繁1項數據項進行排序呢?這是爲了咱們後面的FP樹的創建時,能夠儘量的共用祖先節點。
經過兩次掃描,項頭表已經創建,排序後的數據集也已經獲得了,下面咱們再看看怎麼創建FP樹。
數據結構
有了項頭表和排序後的數據集,咱們就能夠開始FP樹的創建了。開始時FP樹沒有數據,創建FP樹時咱們一條條的讀入排序後的數據集,插入FP樹,插入時按照排序後的順序,插入FP樹中,排序靠前的節點是祖先節點,而靠後的是子孫節點。若是有共用的祖先,則對應的公用祖先節點計數加1。插入後,若是有新節點出現,則項頭表對應的節點會經過節點鏈表連接上新節點。直到全部的數據都插入到FP樹後,FP樹的創建完成。
彷佛也很抽象,咱們仍是用第二節的例子來描述。
首先,咱們插入第一條數據ACEBF,以下圖所示。此時FP樹沒有節點,所以ACEBF是一個獨立的路徑,全部節點計數爲1, 項頭表經過節點鏈表連接上對應的新增節點。
接着咱們插入數據ACG,以下圖所示。因爲ACG和現有的FP樹能夠有共有的祖先節點序列AC,所以只須要增長一個新節點G,將新節點G的計數記爲1。同時A和C的計數加1成爲2。固然,對應的G節點的節點鏈表要更新
一樣的辦法能夠更新後面8條數據,以下8張圖。因爲原理相似,這裏就很少文字講解了,你們能夠本身去嘗試插入並進行理解對比。相信若是你們本身能夠獨立的插入這10條數據,那麼FP樹創建的過程就沒有什麼難度了。
post
咱們辛辛苦苦,終於把FP樹創建起來了,那麼怎麼去挖掘頻繁項集呢?看着這個FP樹,彷佛仍是不知道怎麼下手。下面咱們講如何從FP樹裏挖掘頻繁項集。獲得了FP樹和項頭表以及節點鏈表,咱們首先要從項頭表的底部項依次向上挖掘。對於項頭表對應於FP樹的每一項,咱們要找到它的條件模式基。所謂條件模式基是以咱們要挖掘的節點做爲葉子節點所對應的FP子樹。獲得這個FP子樹,咱們將子樹中每一個節點的的計數設置爲葉子節點的計數,並刪除計數低於支持度的節點。從這個條件模式基,咱們就能夠遞歸挖掘獲得頻繁項集了。
實在太抽象了,以前我看到這也是一團霧水。仍是以上面的例子來說解。咱們看看先從最底下的F節點開始,咱們先來尋找F節點的條件模式基,因爲F在FP樹中只有一個節點,所以候選就只有下圖左所示的一條路徑,對應{A:8,C:8,E:6,B:2, F:2}。咱們接着將全部的祖先節點計數設置爲葉子節點的計數,即FP子樹變成{A:2,C:2,E:2,B:2, F:2}。通常咱們的條件模式基能夠不寫葉子節點,所以最終的F的條件模式基以下圖右所示。
經過它,咱們很容易獲得F的頻繁2項集爲{A:2,F:2}, {C:2,F:2}, {E:2,F:2}, {B:2,F:2}。遞歸合併二項集,獲得頻繁三項集爲{A:2,C:2,F:2},{A:2,E:2,F:2},...還有一些頻繁三項集,就不寫了。固然一直遞歸下去,最大的頻繁項集爲頻繁5項集,爲{A:2,C:2,E:2,B:2,F:2}
F挖掘完了,咱們開始挖掘D節點。D節點比F節點複雜一些,由於它有兩個葉子節點,所以首先獲得的FP子樹以下圖左。咱們接着將全部的祖先節點計數設置爲葉子節點的計數,即變成{A:2, C:2,E:1 G:1,D:1, D:1}此時E節點和G節點因爲在條件模式基裏面的支持度低於閾值,被咱們刪除,最終在去除低支持度節點並不包括葉子節點後D的條件模式基爲{A:2, C:2}。經過它,咱們很容易獲得D的頻繁2項集爲{A:2,D:2}, {C:2,D:2}。遞歸合併二項集,獲得頻繁三項集爲{A:2,C:2,D:2}。D對應的最大的頻繁項集爲頻繁3項集。
一樣的方法能夠獲得B的條件模式基以下圖右邊,遞歸挖掘到B的最大頻繁項集爲頻繁4項集{A:2, C:2, E:2,B:2}。
繼續挖掘G的頻繁項集,挖掘到的G的條件模式基以下圖右邊,遞歸挖掘到G的最大頻繁項集爲頻繁4項集{A:5, C:5, E:4,G:4}。
E的條件模式基以下圖右邊,遞歸挖掘到E的最大頻繁項集爲頻繁3項集{A:6, C:6, E:6}。
C的條件模式基以下圖右邊,遞歸挖掘到C的最大頻繁項集爲頻繁2項集{A:8, C:8}。
至於A,因爲它的條件模式基爲空,所以能夠不用去挖掘了。
至此咱們獲得了全部的頻繁項集,若是咱們只是要最大的頻繁K項集,從上面的分析能夠看到,最大的頻繁項集爲5項集。包括{A:2, C:2, E:2,B:2,F:2}。
經過上面的流程,相信你們對FP Tree的挖掘頻繁項集的過程也很熟悉了。htm
這裏咱們對FP Tree算法流程作一個概括。FP Tree算法包括三步:
1)掃描數據,獲得全部頻繁一項集的的計數。而後刪除支持度低於閾值的項,將1項頻繁集放入項頭表,並按照支持度降序排列。
2)掃描數據,將讀到的原始數據剔除非頻繁1項集,並按照支持度降序排列。
3)讀入排序後的數據集,插入FP樹,插入時按照排序後的順序,插入FP樹中,排序靠前的節點是祖先節點,而靠後的是子孫節點。若是有共用的祖先,則對應的公用祖先節點計數加1。插入後,若是有新節點出現,則項頭表對應的節點會經過節點鏈表連接上新節點。直到全部的數據都插入到FP樹後,FP樹的創建完成。
4)從項頭表的底部項依次向上找到項頭表項對應的條件模式基。從條件模式基遞歸挖掘獲得項頭表項項的頻繁項集(能夠參見第4節對F的條件模式基的頻繁二項集到頻繁5五項集的挖掘)。
5)若是不限制頻繁項集的項數,則返回步驟4全部的頻繁項集,不然只返回知足項數要求的頻繁項集。blog
FP Tree算法改進了Apriori算法的I/O瓶頸,巧妙的利用了樹結構,這讓咱們想起了BIRCH聚類,BIRCH聚類也是巧妙的利用了樹結構來提升算法運行速度。利用內存數據結構以空間換時間是經常使用的提升算法運行時間瓶頸的辦法。
在實踐中,FP Tree算法是能夠用於生產環境的關聯算法,而Apriori算法則作爲先驅,起着關聯算法指明燈的做用。除了FP Tree,像GSP,CBA之類的算法都是Apriori派系的。
(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com) 排序