Apriori演算法的介紹

九茶發表於2015-06-27

前言:

資料探勘中的關聯分析可以分成頻繁項集的挖掘和關聯規則的生成兩個步驟,而Apriori演算法是找頻繁項集最常用到的一種演算法。
關於關聯分析和頻繁項集請見:什麼是關聯分析?


中言:

我們還是利用購物籃的例子來講述Apriori演算法的思路。

購物籃資訊如下:

TID Items
001 Cola, Egg, Ham
002 Cola, Diaper, Beer
003 Cola, Diaper, Beer, Ham
004 Diaper, Beer

TID代表交易流水號,Items代表一次交易的商品。

我們Apriori演算法的最終目的就是要找出資料集中的頻繁項集,把最小支援度閾值設為50%,則最終挖掘結果如下(後面的數字表示該項集的支援度計數):

頻繁1-項集:
{Cola} 3
{Diaper} 3
{Beer} 3
{Ham} 2

頻繁2-項集:
{Cola, Diaper} 2
{Cola, Beer} 2
{Cola,Ham} 2
{Diaper, Beer} 3

頻繁3-項集:
{Cola, Diaper, Beer} 2



Apriori演算法的思路是由頻繁(k-1)-項集生成候選k-項集,然後根據最小支援度判斷該候選k-項集是否是頻繁k-項集。
例如先找出所有1-項集,然後篩選出裡面的頻繁1-項集; 根據頻繁1-項集生成候選2-項集,然後篩選出裡面的頻繁2-項集; 再根據頻繁2-項集生成候選3-項集,從裡面篩選出頻繁3-項集;·······

那麼問題來了,如何從頻繁(k-1)-項集生成候選k-項集呢?
答案是利用Apriori性質:一個頻繁項集的任一子集也應該是頻繁子集(用反證法容易證明,略)。所以如果一個項集是非頻繁項集,那麼它的超集也應該是非頻繁項集。
例如{Cola, Diaper}是頻繁項集,所以{Cola}和{Diaper}也應該是頻繁項集。因為{Egg}是非頻繁項集,所以{Cola, Egg}也是非頻繁項集。


從頻繁1-項集生成候選2-項集的步驟是:把頻繁1-項集和頻繁1-項集排列組合成2-項集,把含有非頻繁子項集的2-項集去掉,就是候選2-項集了。

從頻繁2-項集生成候選三項集的步驟是:把頻繁2-項集和頻繁1-項集排列組合成3-項集:{Cola, Diaper, Beer}、{Cola, Diaper, Ham}、{Cola, Beer, Ham}、{Diaper, Beer, Ham}。
因為{Diaper, Ham}不是頻繁2-項集,所以含有{Diaper, Ham}的{Cola, Diaper, Ham}不是候選3-項集,去掉。因為{Beer, Ham}不是頻繁2-項集,所以含有{Beer, Ham}的{Cola, Beer, Ham}、{Diaper, Beer, Ham}不是候選3-項集,去掉。
所以候選3-項集只有{Cola, Diaper, Beer}。

購物籃頻繁項集的挖掘過程如下:
這裡寫圖片描述


Apriori演算法描述如下(程式碼源自《資料探勘原理與實踐》):

演算法:Apriori 演算法的頻繁項集的產生
輸入:資料集D;最小支援度閾值min_sup
輸出:D 中的頻繁項集L
(1) L1
(2) for( k=2; Lk1Φ

L_{k-1} \neq \Phi
; k++)
(3) {
(4)  Ck
C_k
= apriori_gen(Lk1
(5)  for all transactions t
\in
D
(6)  {
(7)    Ct
C_t
= subset(Ck
(8)    for all candidates cCt
c\in C_t

(9)    {
(10)      c.count++;      // 支援度計數增值
(11)    }
(12)  }
(13)  Lk
L_k
= { cCk
c \in C_k
| c.count≥min_sup}      // 提取頻繁k-項集
(14) }
(15) return L=kLk
L = \cup_k L_k
;


procedure apriori_gen(Lk1

L_{k-1}
)
(1) for each itemset l1Lk1
l_1\in L_{k-1}

(2)  for each itemset l2Lk1
l_2 \in L_{k-1}

(3)    if( l1
l_1
[1]=l2
l_2
[1] ∧…∧ ( l1
l_1
[k-2]=l2
l_2
[k-2] ) ∧ ( l1
l_1
[k-1]<l2
l_2
[k-2] ) then
(4)    {
(5)      c = join( l1
l_1
, l2
(6)      if has_infrequent_subset( c, Lk1
L_{k-1 }
) then
(7)        delete c;      // 減枝:移除非頻繁的候選
(8)      else
(9)        add c to Ck
C_k

(10)    }
(11) return Ck
C_k
;


procedure has_infrequent_subset( c, Lk1

L_{k-1}
)
// 使用先驗知識判斷候選項集是否頻繁
(1) for each ( k-1 )-subset s of c
(2)  if s Lk1
\notin L_{k-1}
then
(3)    return TRUE;
(4) return FALSE;


後言:

我們可以看到,Apriori演算法是通過頻繁(k-1)-項集找到頻繁k-項集的,雖然可以通過Apriori性質進行減枝,去掉一部分子集為非頻繁項集的候選項集,但還是需要不斷地掃描資料集,不斷地求候選項集的支援度計數從而判斷它是否是頻繁項集。如果資料集足夠大的時候,這種演算法的效率還是挺讓人捉急的!

然後,FP-Growth演算法就華麗麗的出現了,請見FP-Growth演算法的介紹FP_Growth演算法python實現


轉載請註明出處,謝謝!(原文連結:http://blog.csdn.net/bone_ace/article/details/46660819

相關文章