關聯規則(Association Rules)是海量數據挖掘(Mining Massive Datasets,MMDs)非常經典的任務,其主要目標是試圖從一系列事務集中挖掘出頻繁項以及對應的關聯規則。關聯規則來自於一個家喻戶曉的“啤酒與尿布”的故事,本文通過故事來引出關聯規則的方法。
啤酒與尿布的故事
在一家超市裏,有一個有趣的現象:尿布和啤酒赫然擺在一起出售。但是這個奇怪的舉措卻使尿布和啤酒的銷量雙雙增加了。這不是一個笑話,而是發生在美國沃爾瑪連鎖店超市的真實案例,並一直爲商家所津津樂道。沃爾瑪擁有世界上最大的數據倉庫系統,爲了能夠準確瞭解顧客在其門店的購買習慣,沃爾瑪對其顧客的購物行爲進行購物籃分析,想知道顧客經常一起購買的商品有哪些。沃爾瑪數據倉庫裏集中了其各門店的詳細原始交易數據。在這些原始交易數據的基礎上,沃爾瑪利用數據挖掘方法對這些數據進行分析和挖掘。一個意外的發現是:"跟尿布一起購買最多的商品竟是啤酒!經過大量實際調查和分析,揭示了一個隱藏在"尿布與啤酒"背後的美國人的一種行爲模式:在美國,一些年輕的父親下班後經常要到超市去買嬰兒尿布,而他們中有30%~40%的人同時也爲自己買一些啤酒。產生這一現象的原因是:美國的太太們常叮囑她們的丈夫下班後爲小孩買尿布,而丈夫們在買尿布後又隨手帶回了他們喜歡的啤酒。
關聯規則是一種大數據挖掘的任務,最初的動機是針對購物籃分析(Market Basket Analysis)問題提出的,例如上述的“啤酒與尿布”的故事,如果超市能夠發現一些具有相關聯的商品購物行爲,通過對商品的適當調整可以提高顧客的購物體驗,提升超市的銷售額,因此如何發現這些潛在的規律呢?
本文首先介紹關聯規則的任務,以及相關概念,其次介紹相關算法,目錄索引如下:
1、關聯規則形式化描述
設是一個項集(Item Set),爲項的個數,其中表示第個項,對應於一個個商品。事務(Transaction)表示的一個子集,對應於一個個訂單。事務組成的集合記做,通常也稱作事務數據庫。通常描述中,每一個事務都有唯一的編號,記做TID,每個事務中都包含若干個項Items。
關聯規則是形如的蘊涵式,其中, 和分別稱爲關聯規則的先導(antecedent或left-hand-side, LHS)和後繼(consequent或right-hand-side, RHS) 。其中,關聯規則,存在支持度和置信度,定義如下:
- 支持度(),理解爲某一個項出現的概率。通常設置一個閾值minsupport,當支持度不小於該值時認爲是頻繁項;
- 置信度(),理解爲在X事務的基礎上,X和Y均出現的條件概率。
例題1:分別計算3-項集“麪包,牛奶,尿布”和“麪包→牛奶,尿布”對應支持度和置信度。
1.可統計“麪包,牛奶,尿布”同時出現的TID有4和5,所以支持度是2/5;
2.麪包出現的TID有1,2,4,5,因此支持度爲2/4。
因此關聯規則實際上包含兩個子任務:
- 頻繁模式發現:也稱頻繁模式挖掘、頻繁項挖掘等,是指從一系列候選的項中選擇頻繁的部分,通常衡量頻繁的程度可以是對每一項出現的頻率,當超過某一閾值是則任務這個項是頻繁的。
- 生成關聯規則:在已經發現的最大頻繁項目集中,尋找置信度不小於用戶給定的minconfidence的關聯規則。
2、Apriori算法
Apriori算法是經典的關聯規則算法,其主要思路如下圖所示:
算法流程:
- 首先對數據庫中進行一次掃描,統計每一個項出現的次數,形成候選1-項集;
- 根據minsupport閾值篩選出頻繁1-項集;
- 將頻繁1-項集進行組合,形成候選2-項集;
- 對數據庫進行第二次掃描,爲每個候選2-項集進行計數,並篩選出頻繁2-項集;
- 重複上述流程,直到候選項集爲空;
- 根據生成的頻繁項集,通過計算相應的置信度來生成管理規則。
其中如果項集中包含k個不同的項,稱之爲k-項集。候選k-項集記做,頻繁k-項集記做。
頻繁模式挖掘的基本前提是:
- 如果一個集合是頻繁項集,則它的所有子集都是頻繁項集。
- 如果一個集合不是頻繁項集,則它的所有超集都不是頻繁項集。
例題2:使用Apriori算法對事務集進行頻繁項挖掘,其中minsupport.count=2.
首先對事務數據庫進行掃描,統計各個1-項的計數。由於最小計數閾值minsupport.count=2,因此可以篩選出頻繁1-項集“”。其次兩兩組合,形成個候選2-項集,並進行第二次掃描數據庫進行計數,發現低於閾值,所以剔除掉。對剩餘的頻繁2-項集進行兩兩組合,去除重複的組合後形成候選3-項集,以此類推,最終得到頻繁3-項集爲。
Apriori算法的特點:
- 簡單且易於實現,是最具代表性的關聯規則挖掘算法
- 隨着數據集規模的不斷增長,逐漸顯現出一定的侷限性:
(1)需多次掃描數據庫,很大的I/O負載,算法的執行效率較低;
(2)產生大量的候選項目集,尤其是候選2-項集佔用內存非常大,會消耗大量的內存;
(3)對於每一趟掃描,只有當內存大小足夠容納需要進行計數的候選集時才能正確執行。如果內存不夠大,要麼使用一種空間複雜度更小的算法,要麼只能對一個候選集進行多次掃描,否則將會出現“內存抖動”的情況,即在一趟掃描中頁面頻繁地移進移出內存(頁面置換算法也無法避免內存抖動問題),造成運行時間的劇增。
3、PCY算法
爲了改進Apriori算法,PCY由Park,Chen和Yu等提出,其目標是爲了降低Apriori算法頻繁的掃描數據庫,其次降低候選項集所佔用的內存。其主要創新點有:
- 將哈希函數應用到頻繁項挖掘中;
- 第一次掃描事務數據庫時,將剩餘的空間存放哈希表,從而降低第二次掃描時佔用的大量空間。
如上圖,左邊兩個圖表示Apriori算法的前兩次掃描過程,可知第一次掃描內存空閒很大,而第二次掃描佔用空間很多;右側兩個圖則表示PCY算法的兩次掃描,第一次掃描除了對1-項集進行計數外,額外利用一個2-項哈希表存儲每個2-項的計數,再第二次掃描時則利用該哈希表對應的位圖來判斷是否保留該2-項,從而減少候選2-項集大小。
PCY主要思想可總結如下:
- 首先第一次掃描事務數據庫,並對候選1-項集進行計數,根據閾值篩選出頻繁1-項集;
- 在第一次掃描的同時,對事務集中每個事務中各個項進行兩兩組合,並通過哈希函數映射到相應的桶中,並將相應的桶計數+1;
- 第二次掃描之前,首先根據每個桶中的計數來判斷是否爲頻繁桶,頻繁桶是指計數不低於某個閾值的桶。頻繁的桶對應的位圖記做1,否則記做0;
- 第二次掃描事務數據庫,此時根據頻繁1-項集生成一系列的2-項組合,分別通過哈希函數獲得其桶的編號,並根據位圖來判斷。如果對應的位圖值爲1,則將其保留,否則剔除。因此最後保留的就是候選2-項集,對其進行計數並篩選頻繁2-項集
例題3:使用PCY算法生成頻繁2-項集,其中minsupport.count=2,哈希函數爲:
事務及集合:
1.首先對1-項集進行計數,篩選出頻繁1-項集爲{A},{B},{C},{E};
2.其次根據事務集中每個事務的項兩兩組合,並通過哈希函數映射到7個桶中。例如哈希值爲,所以其映射到下標爲6的桶中;最終形成的桶如下圖所示,如果桶的計數超過不小於2,則爲頻繁桶,位圖對應爲1。所有桶的計數分別爲3,1,2,0,3,1,3,位圖對應爲1,0,1,0,1,0,1。
3.頻繁1-項集,中兩兩組合,並將每一個組合通過哈希函數得到對應的桶編號,如果對於的位圖爲1,則保留爲候選2-項。最終從6個項中篩選出共4個作爲候選項集;
4.最後第二次掃描計數,得到對應的頻繁2-項集爲
因此總的來說,PCY算法的關鍵在於在第一次和第二次掃描之間通過哈希計數提前過濾掉一部分2-項集,使得候選2-項集規模變小,而這種篩選的規則則是根據頻繁桶來確定。
PCY算法特點:
- 優點
高效地產生頻繁項集,提升了性能
減少了數據庫的掃描次數
減少計數所需的內存空間的大小 - 分析
最差的情況:所有桶都是頻繁桶,則第二遍掃描中PCY算法需要計算的相對數目與Apriori算法相比沒有任何減少
在尋找頻繁3-項集以及更多項集時,PCY算法與Apriori算法相同
如果桶的個數越多,每個桶內分的項數量變少
如果不頻繁的項映射到頻繁的桶中,則可能不易過濾(改進:多階段算法)
4、多階段算法
事實上,PCY算法面臨一個問題,即由於哈希函數的原因,有些非頻繁項被映射到了頻繁桶中,導致這部分非頻繁項很難被過濾掉,因此多階段算法旨在解決這個問題。其主要思路是:
- 在PCY的第一遍和第二遍之間插入額外的掃描過程,將2-項集哈希到另外的獨立的哈希表中(使用不同的哈希函數)
- 在每個中間過程中,只需哈希那些在以往掃描中哈希到頻繁桶的頻繁項。
如圖所示:
- 首先進行第一次掃描。該掃描與PCY第一次掃描一樣,首先對1-項集計數,並將每個事務中各個項兩兩組合,通過第一個哈希函數映射到哈希表1中;
- 在第二次掃描時,使用第二個哈希表。當2-項集同時滿足
(1)均爲頻繁項、(2)在第一個哈希表中映射到頻繁桶中;
時,該2-項集可以映射到第二個哈希表中; - 在第三次掃描時,根據頻繁1-項集中各項兩兩組合,對於每個2-項集,當前僅當同時滿足:
(1)均爲頻繁項、(2)在第一個哈希表中映射到頻繁桶中、(3)在第二個哈希表中映射到頻繁桶中;
時,才保留其作爲候選2-項集。 - 對所有候選2-項集篩選出頻繁2-項集
多階段算法特點:
- 因爲在第二趟掃描時,不是所有的2-項集都被散列到桶中,因此桶的計數值變得比第一趟掃描時更小,最終結果是更多的桶變成非頻繁桶;
- 由於兩次掃描採用的哈希函數不同,那些在第一趟掃描時被散列到頻繁桶中的非頻繁2-項集很可能在第二趟掃描時被哈希到一個非頻繁桶中
- 多階段算法尋找頻繁2-項集不只侷限於使用3次掃描
5、多哈希算法
多哈希算法與PCY算法基本一致,不同在於PCY算法只使用一個哈希表,而多哈希算法則是使用了多個哈希表,其算法思想與PCY一致,只是在判斷是否是候選2-項集時,需要同時判斷多個對應位圖是否均爲1,如下圖所示:
多哈希算法特點:
- 只要桶的平均計數不小於閾值,頻繁桶的數目仍然比較多,這樣一個非頻繁2-項集同時哈希到兩個哈希表的頻繁桶內的概率就更低,可以減少第二遍掃描的運算量
- 風險:
使用兩個哈希表時,每個哈希表僅有PCY算法的一半的桶,這樣每個桶上的平均計數會翻倍,必須保證大多數桶的計數不會達到閾值
桶的平均計數可能會超過閾值 - 多哈希算法也不只侷限於使用兩個哈希表:
6、FP-Tree算法
先前的方法均存在一個問題,即頻繁的對數據庫進行掃描,而每次掃描的目的則是爲了計數,因此如何只對數據庫進行兩次掃描便可以對所有可能的頻繁項進行計數呢?FP-Tree算法巧妙的解決了這個問題。
FP-Tree算法主要分爲兩個步驟:構建FP樹和頻繁模式挖掘。
一、構建FP樹算法:
- 對事務數據庫進行一次掃描,統計所有項的計數,並根據最小支持度閾值保留頻繁1-項集;
- 對頻繁1-項集中所有的項遞減順序排列,形成對應的Head Table,其中Head Table每個元素表示頻繁1-項集及其計數,指針默認爲空;
- 創建一個根結點,掃描第二遍事務數據庫,每一個事務對應的所有排序的項依次插入樹中,計數默認爲1,如果已存在該節點,則計數+1(同一個項在每個事務記錄內排號相同時,此時兩個結點是同一個,則直接+1)。若相同的項不在同一個分支時,通過指針相連。
二、頻繁模式挖掘
- 根據Head Table自底向上順序依次進行頻繁項挖掘,此時對於的元素作爲條件模式基;
- 在FP樹中尋找相應的路徑,且計數取最小值,去除掉小於閾值的項,保留不小於閾值的項;
- 根據條件模式基獲得相同基的頻繁項。
例題4:已知最小支持度閾值爲3,使用FP-Tree算法進行頻繁項挖掘,事務數據庫如圖所示:
如圖可知,事務數據庫中共有9個事務,6個項。此時可知a,b,c,d,e,f的計數分別爲7,6,5,5,3,1。首先第一次掃描後可過濾掉“f”,其次根據各自計數在每個事務記錄內降序排列。
根據計數生成Head Table;
其次構建FP樹,例如事務記錄TID=1開始,向根結點依次插入結點(a:1),(b:1),(c:1),此時Head Table中的a,b,c指針分別指向新增的結點。當TID=2時,從根結點插入(b:1),(c:1),(d:1),需要注意的是,雖然當前也插入了b和c,但由於其層數與TID1不同,所以是在新的分支上。而對於TID=3時,第一個項是a,所以直接在(a:1)上計數,變爲(a:2)。
以此類推,即可生成如下圖所示的FP-樹:
其次進行頻繁項挖掘,先以e開始,可知所有路徑以e結尾的有(a:7,b:5,c:3,e:1)、(a:7,c:1,d:1,e:1),(a:7,d:1,e:1)。根據條件模式基,需要將每個結點的計數變爲最小的值,即變爲(a:1,b:1,c:1,e:1)、(a:1,c:1,d:1,e:1),(a:1,d:1,e:1)。此時可以發現每個項的計數有(a:3),(b:1),(c:2),(d:2),(e:3),由於閾值爲3,則只保留(a:3)和(e:3)。因此可以得到頻繁項有(ae:3)和(e:3)。需要注意的是,當前的基底是e,因此必須包含e,例如(a:3)不是e的條件模式基,則不能包含該項。
FP-Tree算法特點:
- FP-Tree算法只需要進行兩次掃描即可完成頻繁模式挖掘,大大減少了I/O開銷;
- 通過Head Table可對相同的項進行計數,省去了重複計數的時間開銷,計數完全可以在內存內外存。
7、XFP-Tree算法
FP-Tree算法有許多可改進之處,例如如果當事務的數量非常龐大時,構建FP樹會佔用大量的時間,XFP-Tree算法旨在並行的構建FP樹來提升效率。
XFP-Tree算法需要創建兩個數據結構,分別是XFP-Tree和位圖矢量:
- XFP樹:與FP樹構建方式相同,不同點在於使用多核機制。首先對Head Table進行劃分,劃分的數量與內核數成整數倍,劃分時儘量保證相對平均;其次在不同的分區上用不同的CPU核創建FP樹,該過程是並行執行的,如下圖所示(例4的示例),3個CPU核並行構建,每個顏色代表不同的CPU核,不同核構建的FP樹通過指針連接。
- 位圖矢量:按照項對每個事務進行記錄,例如TID1的事務只有abd三個項,所以位圖爲1,其他爲0,即11010。位圖矢量的功能是用於對項進行計數,而計數也可以通過多核機制進行並行。例如項ab,cd和e分別分配給P1,P2和P3執行計數。
8、GPApriori算法
有相關工作對Apriori進行了改進,除了先前介紹的PCY,多階段、多哈希外,使用GPU進行頻繁模式挖掘也是一種改進之處。 GPApriori算法則使用GPU進行頻繁項挖掘。
GPApriori算法主要創新點爲:(1)使用字典樹來保存候選項,(2)使用縱向事務列表,(3)可並行實現支持度計算;
一、字典樹
由於許多的候選項可能有相同的前綴,例如候選3-項“1,2,4”和“1,2,5”都有相同的前綴“1,2”,因此可以使用字典樹保存。
二、事務的縱向表示
存儲一個對應於每個候選集的事務id列表(tidset),每個列表也可以被表示爲一個位掩碼(bitset)。例如下圖,左側爲傳統的事務表示,右側爲縱向表示,Candidate表示候選的項集,tidset則表示對應項集包含的事務記錄,其可以使用bit碼錶示。例如1-項集只有第1和第4個事務存在,所以bit碼可以寫成1001。
之所以可以使用縱向表示,是因爲:
(1)當判斷兩個項的組合是否是頻繁項時,直接將二者對應的bit碼按位求與計算,結果中1的個數即爲支持度計數值。例如判斷2-項集(1,3)的計數,則直接求1001和1111的按位與,結果爲1001,則說明有兩個事務滿足這個20項集,再例如3-項集(1,3,5),則可以表示爲(1,3)的1001和(5) 的1101按位與,結果爲1001,說明也有兩個事務同時包含項1、3、5。
(2)使用縱向表示法,可以並行的對支持度進行計數,這也是第三個貢獻。
三、並行支持度計算
當使用縱向表示時,可以將縱向事務表劃分爲多個分塊,每個分塊置於GPU計算節點上,最後使用並行歸約法獲得總計數。
參考文獻
【4】Zhang F, Zhang Y, Bakos J. Gpapriori: Gpu-accelerated frequent itemset mining[C]//Cluster Computing (CLUSTER), 2011 IEEE International Conference on. IEEE, 2011: 590-594.
博客記錄着學習的腳步,分享着最新的技術,非常感謝您的閱讀,本博客將不斷進行更新,希望能夠給您在技術上帶來幫助。