Frequent Pattern 挖掘之二(FP Growth算法)(转)
FP樹構(gòu)造
FP Growth算法利用了巧妙的數(shù)據(jù)結(jié)構(gòu),大大降低了Aproir挖掘算法的代價,他不需要不斷得生成候選項目隊列和不斷得掃描整個數(shù)據(jù)庫進行比對。為了達到這樣的效果,它采用了一種簡潔的數(shù)據(jù)結(jié)構(gòu),叫做frequent-pattern tree(頻繁模式樹)。下面就詳細談?wù)勅绾螛?gòu)造這個樹,舉例是最好的方法。請看下面這個例子:
這張表描述了一張商品交易清單,abcdefg代表商品,(ordered)frequent items這一列是把商品按照降序重新進行了排列,這個排序很重要,我們操作的所有項目必須按照這個順序來,這個順序的確定非常簡單,只要對數(shù)據(jù)庫進行一次掃描就可以得到這個順序。由于那些非頻繁的項目在整個挖掘中不起任何作用,因此在這一列中排除了這些非頻繁項目。我們在這個例子中設(shè)置最小支持閾值(minimum support threshold)為3。
我們的目標(biāo)是為整個商品交易清單構(gòu)造一顆樹。我們首先定義這顆樹的根節(jié)點為null,然后我們開始掃描整個數(shù)據(jù)庫的每一條記錄開始構(gòu)造FP樹。
第一步:掃描數(shù)據(jù)庫的第一個交易,也就是TID為100的交易。那么就會得到這顆樹的第一個分支<(f:1),(c:1),(a:1),(m:1),(p:1)>。注意這個分支一定是要按照降頻排列的。
第二步:掃描第二條交易記錄(TID=200),我們會有這么一個頻繁項目集合<f,c,a,b,m>。仔細觀察這個隊列,你會發(fā)現(xiàn)這個集合的前3項<f,c,a>與第一步產(chǎn)生的路徑<f,c,a,m,p>的前三項是相同的,也就是說他們可以共享一個前綴。于是我們在第一步產(chǎn)生的路徑的基礎(chǔ)上,把<f,c,a>三個節(jié)點的數(shù)目加1,然后將<(b:1),(m:1)>作為一個分支加在(a:2)節(jié)點的后面,成為它的子節(jié)點。看下圖:
第三步:接著掃描第三條交易記錄(TID=300),你會看到這條記錄的集合是<f, b>,與已存在的路徑相比,只有f是共有的前綴,那么f節(jié)點加1,同時再為f節(jié)點生成一個新的字節(jié)點(b:1).就會有下圖:
第四步:繼續(xù)看第四條交易記錄,它的集合是<c,b,p>,哦,這回不一樣了。你會發(fā)現(xiàn)這個集合的第一個元素是c,與現(xiàn)存的已知路徑的第一個節(jié)點f不一樣,那就不用往下比了,沒有任何公共前綴。直接將該集合作為根節(jié)點的子路徑附加上去。就得到了下圖(圖1):
第五步:最后一條交易記錄來了,你看到了一條集合<f,c,a,m,p>。你驚喜得發(fā)現(xiàn)這條路徑和樹現(xiàn)有最左邊的路徑竟然完全一樣。那么,這整條路徑都是公共前綴,那么這條路徑上的所有點都加1好了。就得到了最終的圖(圖2)。
好了,一顆FP樹就已經(jīng)基本構(gòu)建完成了。等等,還差一點。上述的樹還差一點點就可以稱之為一個完整的FP樹啦。為了便于后邊的樹的遍歷,我們?yōu)檫@棵樹又增加了一個結(jié)構(gòu)-頭表,頭表保存了所有的頻繁項目,并且按照頻率的降序排列,表中的每個項目包含一個節(jié)點鏈表,指向樹中和它同名的節(jié)點。羅嗦了半天,可能還是不清楚,好吧直接上圖,一看你就明白:
以上就是整個FP樹構(gòu)造的完整過程。聰明的讀者一定不難根據(jù)上述例子歸納總結(jié)出FP樹的構(gòu)造算法。這里就不再贅述。
?
?
FP樹的挖掘
?
下面就是最關(guān)鍵的了。我們已經(jīng)有了一個非常簡潔的數(shù)據(jù)結(jié)構(gòu),下一步的任務(wù)就是從這棵樹里挖掘出我們所需要的頻繁項目集合而不需要再訪問數(shù)據(jù)庫了。還是看上面的例子。
?
第一步:我們的挖掘從頭表的最后一項p開始,那么一個明顯的直接頻繁集是(p:3)了。根據(jù)p的節(jié)點鏈表,它的2個節(jié)點存在于2條路徑當(dāng)中:路徑<f:4,c:3,a:3,m:2,p:2>和路徑<c:1,b:1,p:1>.從路徑<f:4,c:3,a:3,m:2,p:2>我們可以看出包含p的路徑<f,c,a,m,p>出現(xiàn)了2次,同時也會有<f,c,a>出現(xiàn)了3次,<f>出現(xiàn)了4次。但是我們只關(guān)注<f,c,a,m,p>,因為我們的目的是找出包含p的所有頻繁集合。同樣的道理我們可以得出<c,b,p>在數(shù)據(jù)庫中出現(xiàn)了1次。于是,p就有2個前綴路徑{(fcam:2),(cb:1)}。這兩條前綴路徑稱之為p的子模式基(subpattern-base),也叫做p的條件模式基(之所以稱之為條件模式基是因為這個子模式基是在p存在的前提條件下)。接下來我們再為這個條件子模式基構(gòu)造一個p的條件FP樹。再回憶一下上面FP樹的構(gòu)造算法,很容易得到下面這棵樹:
但是由于頻繁集的閾值是3。那么實際上這棵樹經(jīng)過剪枝之后只剩下一個分支(c:3),所以從這棵條件FP樹上只能派生出一個頻繁項目集{cp:3}.加上直接頻繁集(p:3)就是最后的結(jié)果.
第二步:我們接下來開始挖掘頭表中的倒數(shù)第二項m,同第一步一樣,顯然有一個直接的頻繁集(m:3).再查看它在FP樹中存在的兩條路徑<f:4,c:3,a:3,m:2>和<f:4,c:3,a:3,b1,m:1>.那么它的頻繁條件子模式基就是{ (fca:2),(fcab:1)}.為這個子模式基構(gòu)造FP樹,同時舍棄不滿足最小頻繁閾值的分支b,那么其實在這棵FP樹中只存在唯一的一個頻繁路徑<f:3,c:3,a:3>.既然這顆子FP樹是存在的,并且不是一顆只有一個節(jié)點的特殊的樹,我們就繼續(xù)遞歸得挖掘這棵樹.這棵子樹是單路徑的子樹,我們可以簡化寫成mine(FP tree|m)=mine(<f:3,c:3,a:3>|m:3).
下面來闡述如何挖掘這顆FP子樹,我們需要遞歸.遞歸子樹也需要這么幾個步驟:
1這顆FP子樹的頭表最后一個節(jié)點是a,結(jié)合遞歸前的節(jié)點m,那么我們就得到am的條件子模式基{(fc:3)},那么此子模式基構(gòu)造的FP樹(我們稱之為m的子子樹)實際上也是一顆單路徑的樹<f:3,c:3>,接下也繼續(xù)繼續(xù)遞歸挖掘子子樹mine(<f:3,c:3>|am:3). (子子樹的遞歸分析暫時打住.因為再分析子子樹的遞歸的話文字就會顯得太混亂)
2同樣,FP子樹頭表的倒數(shù)第二個節(jié)點是c,結(jié)合遞歸前節(jié)點m,就有我們需要遞歸挖掘mine(<f:3>|cm:3).
3 FP子樹的倒數(shù)第三個節(jié)點也是最后一個節(jié)點是f,結(jié)合遞歸前的m節(jié)點,實際上需要遞歸挖掘mine(null|fm:3),實際上呢這種情況下的遞歸就可以終止了,因為子樹已經(jīng)為空了.因此此情況下就可以返回頻繁集合<fm:3>
注意:這三步其實還包含了它們直接的頻繁子模式<am:3>,<cm:3>,<fm:3>,這在每一步遞歸調(diào)用mine<FPtree>都是一樣的,就不再羅嗦得一一重新指明了.
實際上這就是一個很簡單的遞歸過程,就不繼續(xù)往下分析了,聰明的讀者一定會根據(jù)上面的分析繼續(xù)往下推導(dǎo)遞歸,就會得到下面的結(jié)果.
mine(<f:3,c:3>|am:3)=><cam:3>,<fam:3>,<fcam:3>
mine(<f:3>|cm:3)=><fcm:3>
mine(null|fm:3)=><fm:3>
這三步還都包含了各自直接的頻繁子模式<am:3>,<cm:3>,<fm:3>.
最后再加上m的直接頻繁子模式<m:3>,就是整個第二步挖掘m的最后的結(jié)果。請看下圖:
第三步:來看看頭表倒數(shù)第三位<b:3>的挖掘,它有三條路徑<f:4,c:3,a:3,b:1>,<f:4,b:1>,<c:1,b:1>,形成的頻繁條件子模式基為{(fca:1),(f:1),(c:1)},構(gòu)建成的FP樹中的所有節(jié)點的頻率均小于3,那么FP樹為空,結(jié)束遞歸.這一步得到的頻繁集就只有直接頻繁集合<b:3>
第四步:頭表倒數(shù)第四位<a:3>,它有一條路徑<f:4,c:3>,頻繁條件子模式基為{(fc:3)},構(gòu)成一個單路徑的FP樹.實際上可能有人早已經(jīng)發(fā)現(xiàn)了,這種單路徑的FP樹挖掘其實根本不用遞歸這么麻煩,只要進行排列組合就可以直接組成最后的結(jié)果.實際上也確實如此.那么這一步最后的結(jié)果根據(jù)排列組合就有:{(fa:3),(ca:3),(fca:3),(a:3)}
第五步:頭表的倒數(shù)第五位<c:4>,它只有一條路徑<f:4>,頻繁條件子模式基為{(f:3)},那么這一步的頻繁集也就很明顯了:{(fc:3),(c:4)}
第六步:頭表的最后一位<f:4>,沒有條件子模式基,那么只有一個直接頻繁集{(f:4)}
這6步的結(jié)果加在一起,就得到我們所需要的所有頻繁集.下圖給出了每一步頻繁條件模式基.
其實,通過上面的例子,估計早有人看出來了,這種單路徑的FP樹挖掘其實是有規(guī)律的,根本不用遞歸這么復(fù)雜的方法,通過排列組合可以直接生成.的確如此,Han Jiawei針對這種單路徑的情況作了優(yōu)化.如果一顆FP樹有一個很長的單路徑,我們將這棵FP樹分成兩個子樹:一個子樹是由原FP樹的單路徑部分組成,另外一顆子樹由原FP樹的除單路徑之外的其余部分組成.對這兩個子樹分別進行FP Growth算法,然后對最后的結(jié)果進行組合就可可以了.
通過上面博主不厭其煩,孜孜不倦,略顯羅嗦的分析,相信大家已經(jīng)知道FP Growth算法的最終奧義.實際上該算法的背后的思想很簡單,用一個簡潔的數(shù)據(jù)結(jié)構(gòu)把整個數(shù)據(jù)庫進行FP挖掘所需要的信息都包含了進去,通過對數(shù)據(jù)結(jié)構(gòu)的遞歸就可以完成整個頻繁模式的挖掘.由于這個數(shù)據(jù)結(jié)構(gòu)的size遠遠小于數(shù)據(jù)庫,因此可以保存在內(nèi)存中,那么挖掘速度就可以大大提高.
也許有人會問?如果這個數(shù)據(jù)庫足夠大,以至于構(gòu)造的FP樹大到無法完全保存在內(nèi)存中,這該如何是好.這的確是個問題. Han Jiawei在論文中也給出了一種思路,就是通過將原來的大的數(shù)據(jù)庫分區(qū)成幾個小的數(shù)據(jù)庫(這種小的數(shù)據(jù)庫稱之為投射數(shù)據(jù)庫),對這幾個小的數(shù)據(jù)庫分別進行FP Growth算法.
還是拿上面的例子來說事,我們把包含p的所有數(shù)據(jù)庫記錄都單獨存成一個數(shù)據(jù)庫,我們稱之為p-投射數(shù)據(jù)庫,類似的m,b,a,c,f我們都可以生成相應(yīng)的投射數(shù)據(jù)庫,這些投射數(shù)據(jù)庫構(gòu)成的FP樹相對而言大小就小得多,完全可以放在內(nèi)存里.
轉(zhuǎn)載于:https://www.cnblogs.com/xiaohua92/p/5516266.html
總結(jié)
以上是生活随笔為你收集整理的Frequent Pattern 挖掘之二(FP Growth算法)(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php之去掉html标签,PHP删除HT
- 下一篇: 申请美国计算机科学,美国计算机科学(Co