資料結構和演算法系列 FP Tree演算法的實現

2021-07-03 15:27:46 字數 3258 閱讀 4933

在關聯規則挖掘領域最經典的演算法法是apriori,其致命的缺點是需要多次掃瞄事務資料庫。於是人們提出了各種裁剪(prune)資料集的方法以減少i/o開支,韓嘉煒老師的fp-tree演算法就是其中非常高效的一種。

嚴格地說apriori和fp-tree都是尋找頻繁項集的演算法,頻繁項集就是所謂的「支援度」比較高的項集,下面解釋一下支援度和置信度的概念。

設事務資料庫為:

a  e  f  g

a  f  g

a  b  e  f  g

e  f  g

則的支援度數為3,支援度為3/4。

的支援度數為4,支援度為4/4。

的支援度數為3,支援度為3/4。

=>的置信度為:的支援度數 除以 的支援度數,即3/4

=>的置信度為:的支援度數 除以 的支援度數,即3/3

強關聯規則挖掘是在滿足一定支援度的情況下尋找置信度達到閾值的所有模式。

我們舉個例子來詳細講解fp-tree演算法的完整實現。

事務資料庫如下,一行表示一條購物記錄:

牛奶,雞蛋,麵包,薯片

雞蛋,爆公尺花,薯片,啤酒

雞蛋,麵包,薯片

牛奶,雞蛋,麵包,爆公尺花,薯片,啤酒

牛奶,麵包,啤酒

雞蛋,麵包,啤酒

牛奶,麵包,薯片

牛奶,雞蛋,麵包,黃油,薯片

牛奶,雞蛋,黃油,薯片

我們的目的是要找出哪些商品總是相伴出現的,比如人們買薯片的時候通常也會買雞蛋,則[薯片,雞蛋]就是一條頻繁模式(frequent pattern)。

fp-tree演算法第一步:掃瞄事務資料庫,每項商品按頻數遞減排序,並刪除頻數小於最小支援度minsup的商品。(第一次掃瞄資料庫)

薯片:7雞蛋:7麵包:7牛奶:6啤酒:4                       (這裡我們令minsup=3)

以上結果就是頻繁1項集,記為f1。

第二步:對於每一條購買記錄,按照f1中的順序重新排序。(第二次也是最後一次掃瞄資料庫)

薯片,雞蛋,麵包,牛奶

薯片,雞蛋,啤酒

薯片,雞蛋,麵包

薯片,雞蛋,麵包,牛奶,啤酒

麵包,牛奶,啤酒

雞蛋,麵包,啤酒

薯片,麵包,牛奶

薯片,雞蛋,麵包,牛奶

薯片,雞蛋,牛奶

第三步:把第二步得到的各條記錄插入到fp-tree中。剛開始時字尾模式為空。

插入第一條(薯片,雞蛋,麵包,牛奶)之後

插入第三條記錄(麵包,牛奶,啤酒)

估計你也知道怎麼插了,最終生成的fp-tree是:

上圖中左邊的那一叫做表頭項,樹中相同名稱的節點要鏈結起來,鍊錶的第乙個元素就是表頭項裡的元素。

如果fp-tree為空(只含乙個虛的root節點),則fp-growth函式返回。

此時輸出表頭項的每一項+postmodel,支援度為表頭項中對應項的計數。

第四步:從fp-tree中找出頻繁項。

遍歷表頭項中的每一項(我們拿「牛奶:6」為例),對於各項都執行以下(1)到(5)的操作:

(1)從fp-tree中找到所有的「牛奶」節點,向上遍歷它的祖先節點,得到4條路徑:

薯片:7,雞蛋:6,牛奶:1

薯片:7,雞蛋:6,麵包:4,牛奶:3

薯片:7,麵包:1,牛奶:1

麵包:1,牛奶:1

對於每一條路徑上的節點,其count都設定為牛奶的count

薯片:1,雞蛋:1,牛奶:1

薯片:3,雞蛋:3,麵包:3,牛奶:3

薯片:1,麵包:1,牛奶:1

麵包:1,牛奶:1

因為每一項末尾都是牛奶,可以把牛奶去掉,得到條件模式基(conditional pattern base,cpb),此時的字尾模式是:(牛奶)。

薯片:1,雞蛋:1

薯片:3,雞蛋:3,麵包:3

薯片:1,麵包:1

麵包:1

(2)我們把上面的結果當作原始的事務資料庫,返回到第3步,遞迴迭代執行。

沒講清楚,你可以參考這篇部落格,直接看核心**吧:

public void fpgrowth(list> transrecords,

listpostpattern,context context) throws ioexception, interruptedexception

}// 找到項頭表的每一項的條件模式基,進入遞迴迭代

for (treenode header : headertable)

while (counter-- > 0)

backnode = backnode.getnexthomonym();

}// 遞迴迭代

fpgrowth(newtransrecords, newpostpattern,context);}}

對於fp-tree已經是單枝的情況,就沒有必要再遞迴呼叫fpgrowth了,直接輸出整條路徑上所有節點的各種組合+postmodel就可了。例如當fp-tree為:

我們直接輸出:

3  a+postmodel

3  b+postmodel

3  a+b+postmodel

就可以了。

如何按照上面**裡的做法,是先輸出:

3  a+postmodel

3  b+postmodel

然後把b插入到postmodel的頭部,重新建立乙個fp-tree,這時tree中只含a,於是輸出

3  a+(b+postmodel)

兩種方法結果是一樣的,但畢竟重新建立fp-tree計算量大些。

資料結構 排序演算法系列總結

目錄 1 空間複雜度 2 穩定性 3 執行時間 4 目前預設的sort內建函式排序函式 5 六種常用排序方法 空間複雜度產生的原因有兩個 重新定義了一塊空間用於儲存資料 遞迴產生了棧空間 氣泡排序 選擇排序 堆排序和插入排序屬於原地實現排序,因此空間複雜度為常數級別 快速排序,在演算法中雖然沒有使用...

資料結構與演算法系列1 什麼是資料結構和演算法

資料結構是計算機儲存,組織資料的方式,就是怎麼儲存資料的意思 資料 是描述客觀事物的符號,是計算機中可以操作的物件,是能被計算機識別,並給計算機處理的符號集合 資料元素 是組成資料的,有一定意義的基本單位,在計算機中通常作為整體處理,也被稱為記錄 資料項 乙個資料元素可以由若干資料項的組成 資料物件...

資料結構和演算法系列(3)排序演算法

使用場景 o n n n 1 2 如果n比較小的話它的時間複雜度就會降級 資料量比較小,常見於小遊戲中10個左右資料的排序場景 具體實現 氣泡排序演算法 適用於資料量比較小的場景 param array public static void bubblesort int array if flag ...