Spark下的FP-Growth和Apriori


基本概念

  關聯分析是一種在大規模數據集中尋找有趣關係的非監督學習算法。這些關係能夠有兩種形式:頻繁項集或者關聯規則。頻繁項集(frequent item sets)是常常出如今一塊的物品的集合,關聯規則(association rules)暗示兩種物品之間可能存在很強的關係。html

  下圖是一個乒乓球店的交易記錄,〇表示顧客購買了商品。其中{底板,膠皮,澆水}就是一個頻繁項集;從中能夠找到底板->膠皮這樣的關聯規則:算法

支持度

  怎樣有效定義頻繁和關聯?其中最重要的兩個概念是支持度和置信度。sql

  支持度(support)從字面上理解就是支持的程度,一個項集的支持度(support)被定義爲數據集中包含該項集的記錄所佔的比例。上圖中{底板}的支持度=(5/6) * 100%。數據庫

  這個概念其實常常在現實生活中出現,翻譯成支持率彷佛更好理解,典型的例子就是投票,好比英國脫歐的支持率爲51.89%。apache

  用數學去解釋就是,設W 中有s%的事務同時支持物品集A和B,s%稱爲{A,B}的支持度,即:app

  support({A,B}) = num(A∪B) / W = P(A∩B)ide

  num(A∪B)表示含有物品集{A,B}的事務集的個數,不是數學中的並集。性能

置信度

  置信度(confidence)揭示了A出現時B是否必定出現,若是出現,則出現的機率是多大。若是A->B的置信度是100%,則說明A出現時B必定會出現(返回來不必定)。上圖中底板共出現5次,其中4次同時購買了膠皮,底板->膠皮的置信度是80%。學習

  用公式表示是,物品A->B的置信度=物品{A,B}的支持度 / 物品{A}的支持度:ui

  Confidence(A->B) = support({A,B}) / support({A}) = P(B|A)

Apriori原理

   假設咱們在經營一家商品種類並很少的雜貨店,咱們對那些常常在一塊兒被購買的商品很是感興趣。咱們只有4種商品:商品0,商品1,商品2和商品3。那麼全部可能被一塊兒購買的商品組合都有哪些?這些商品組合可能只有一種商品,好比商品0,也可能包括兩種、三種或者全部四種商品。咱們並不關心某人買了兩件商品0以及四件商品2的狀況,咱們只關心他購買了一種或多種商品。

  下圖顯示了物品之間全部可能的組合。爲了讓該圖更容易懂,圖中使用物品的編號0來取代物品0自己。另外,圖中從上往下的第一個集合是Ф,表示空集或不包含任何物品的集合。物品集合之間的連線代表兩個或者更多集合能夠組合造成一個更大的集合。

  前面說過,咱們的目標是找到常常在一塊兒購買的物品集合。咱們使用集合的支持度來度量其出現的頻率。一個集合的支持度是指有多少比例的交易記錄包含該集合。如何對一個給定的集合,好比{0,3},來計算其支持度?咱們遍歷毎條記錄並檢查該記錄包含0和3,若是記錄確實同時包含這兩項,那麼就增長總計數值。在掃描完全部數據以後,使用統計獲得的總數除以總的交易記錄數,就能夠獲得支持度。上述過程和結果只是針對單個集合{0,3}。要得到每種可能集合的支持度就須要屢次重複上述過程。咱們能夠數一下上圖中的集合數目,會發現即便對於僅有4種物品的集合,也須要遍歷數據15次。而隨着物品數目的增長遍歷次數會急劇增加。對於包含— 物品的數據集共有2N-1種項集組合。事實上,出售10000或更多種物品的商店並很多見。即便只出售100種商品的商店也會有1.26×1030種可能的項集組合。對於現代的計算機而言,須要很長的時間才能完成運算。

  爲了下降所需的計算時間,研究人員發現一種所謂的Apriori原理。Apriori原理能夠幫咱們減小可能感興趣的項集。Apriori原理是說若是某個項集是頻繁的,那麼它的全部子集也是頻繁的。上圖給出的例子,這意味着若是{0,1}是頻繁的,那麼{0}、{1}也必定是頻繁的。這個原理直觀上並無什麼幫助,可是若是反過來看就有用了,也就是說若是一個項集是非頻繁集,那麼它的全部超集也是非頻繁的,以下所示:

  上圖中,已知陰影項集{2,3}是非頻繁的。利用這個知識,咱們就知道項集{0,2,3} ,{1,2,3}以及{0,1,2,3}也是非頻繁的。這也就是說,一旦計算出了{2,3}的支持度,知道它是非頻繁的以後,就不須要再計算{0,2,3}、{1,2,3}和{0,1,2,3}的支持度,由於咱們知道這些集合不會知足咱們的要求。使用該原理就能夠避免項集數目的指數增加,從而在合理時間內計算出頻繁項集。

Apriori算法過程

  關聯分析的目標包括兩項:發現頻繁項集和發現關聯規則。首先須要找到頻繁項集,而後才能得到關聯規則。

Apriori算法過程

  發現頻繁項集的過程如上圖所示:

  1. 由數據集生成候選項集C1(1表示每一個候選項僅有一個數據項);再由C1經過支持度過濾,生成頻繁項集L1(1表示每一個頻繁項僅有一個數據項)。
  2. 將L1的數據項兩兩拼接成C2。
  3. 從候選項集C2開始,經過支持度過濾生成L2。L2根據Apriori原理拼接成候選項集C3;C3經過支持度過濾生成L3……直到Lk中僅有一個或沒有數據項爲止。

  下面是一個超市的交易記錄:

  Apriori算法發現頻繁項集的過程以下:

 

以上轉於:https://www.cnblogs.com/bigmonkey/p/7405555.html

FP-Grwoth 算法過程

Apriori算法雖然思路很簡單,可是該算法有如下缺點:

    (1)在每一步產生侯選項目集時循環產生的組合過多,沒有排除不該該參與組合的元素;

    (2)每次計算項集的支持度時,都對數據集中的所有記錄進行了一遍掃描比較,

在數據集較大時,這樣掃描下來會大大增長計算機的IO開銷。這種代價會讓計算機奔潰。
針對Apriori算法的性能瓶頸——須要產生大量候選集和須要重複掃描數據集,FP-growth算法應用而生。該算法只進行2次數據集掃描並且不使用候選集,直接壓縮數據集成一個頻繁模式樹(FP樹),最後經過這個FP樹生成頻繁項集。對於本題較大的數據集,FP-growth算法是個不錯的選擇。  

(1)按如下步驟構造FP-樹

(a) 掃描事務數據庫D一次。收集頻繁項的集合F和它們的支持度。對F按支持度降序排序,結果爲頻繁項表L。
(b) 建立FP-樹的根結點,以「null」標記它。對於D 中每一個事務Trans,執行:選擇 Trans 中的頻繁項,並按L中的次序排序。設排序後的頻繁項表爲[p | P],其中,p 是第一個元素,而P 是剩餘元素的表。調用insert_tree([p | P], T)。該過程執行狀況以下。若是T有子女N使得N.item-name = p.item-name,則N 的計數增長1;不然建立一個新結點N將其計數設置爲1,連接到它的父結點T,而且經過結點鏈結構將其連接到具備相同item-name的結點。若是P非空,遞歸地調用insert_tree(P, N)。
(2)FP-樹的挖掘
經過調用FP_growth(FP_tree, null)實現。該過程實現以下:
FP_growth(Tree, α)
(1) if Tree 含單個路徑P then
(2) for 路徑 P 中結點的每一個組合(記做β)
(3) 產生模式β ∪ α,其支持度support = β中結點的最小支持度;
(4) else for each ai在Tree的頭部(按照支持度由低到高順序進行掃描) {
(5) 產生一個模式β = ai ∪ α,其支持度support = ai .support;
(6) 構造β的條件模式基,而後構造β的條件FP-樹Treeβ;
(7) if Treeβ ≠ ∅ then
(8) 調用 FP_growth (Treeβ, β);}
end
1.1.3 FP-Growth算法演示—構造FP-樹
(1)事務數據庫創建

原始事務數據庫以下:

Tid

Items

1

I1,I2,I5

2

I2,I4

3

I2,I3

4

I1,I2,I4

5

I1,I3

6

I2,I3

7

I1,I3

8

I1,I2,I3,I5

9

I1,I2,I3

 

 

掃描事務數據庫獲得頻繁1-項目集F。

I1

I2

I3

I4

I5

6

7

6

2

2

 

定義minsup=20%,即最小支持度爲2,從新排列F。

 

I2

I1

I3

I4

I5

7

6

6

2

2

 

從新調整事務數據庫。

 

Tid

Items

1

I2, I1,I5

2

I2,I4

3

I2,I3

4

I2, I1,I4

5

I1,I3

6

I2,I3

7

I1,I3

8

I2, I1,I3,I5

9

I2, I1,I3

 

(2)建立根結點和頻繁項目表

 

 

 

(3)加入第一個事務(I2,I1,I5)

 

 

(4)加入第二個事務(I2,I4)

 

 

(5)加入第三個事務(I2,I3)

 

 

以此類推加入第五、六、七、八、9個事務。

 

(6)加入第九個事務(I2,I1,I3)

 

1.1.4 FP-Growth算法演示—FP-樹挖掘

FP-樹建好後,就能夠進行頻繁項集的挖掘,挖掘算法稱爲FpGrowth(Frequent Pattern Growth)算法,挖掘從表頭header的最後一個項開始,以此類推。本文以I五、I3爲例進行挖掘。

(1)挖掘I5:

對於I5,獲得條件模式基:<(I2,I1:1)>、<I2,I1,I3:1>

構造條件FP-tree:

 

獲得I5頻繁項集:{{I2,I5:2},{I1,I5:2},{I2,I1,I5:2}}

I四、I1的挖掘與I5相似,條件FP-樹都是單路徑。

(1)挖掘I3:

I5的狀況是比較簡單的,由於I5對應的條件FP-樹是單路徑的,I3稍微複雜一點。I3的條件模式基是(I2 I1:2), (I2:2), (I1:2),生成的條件FP-樹以下圖:

 

I3的條件FP-樹仍然是一個多路徑樹,首先把模式後綴I3和條件FP-樹中的項頭表中的每一項取並集,獲得一組模式{I2 I3:4, I1 I3:4},可是這一組模式不是後綴爲I3的全部模式。還須要遞歸調用FP-growth,模式後綴爲{I1,I3},{I1,I3}的條件模式基爲{I2:2},其生成的條件FP-樹以下圖所示。  

 

在FP_growth中把I2和模式後綴{I1,I3}取並獲得模式{I1 I2 I3:2}。

理論上還應該計算一下模式後綴爲{I2,I3}的模式集,可是{I2,I3}的條件模式基爲空,遞歸調用結束。最終模式後綴I3的支持度>2的全部模式爲:{ I2 I3:4, I1 I3:4, I1 I2 I3:2}。

 

轉於: https://blog.csdn.net/sunbow0/article/details/45602415 
 

 


運行Spark fp-growth demo以下:

pom.xml中加載mllib依賴

<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-mllib_2.11</artifactId>
<version>2.3.0</version>
</dependency>


官網提供的代碼以下:

package cn.xdf.userprofile.ML

import org.apache.spark.sql.SparkSession
import org.apache.spark.ml.fpm.FPGrowth

object FPGrowthDemo {

def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder
.appName("FPGrowthDemo").master("local")
.config("spark.sql.warehouse.dir", "C:\\study\\sparktest")
.getOrCreate()
//val spark = getSparkSession("FPGrowthDemo")

import spark.implicits._
val dataset = spark.createDataset(Seq(
"1 2 5",
"1 2 3 5",
"1 2 ")
).map(t => t.split(" ")).toDF("items")

val fpgroth=new FPGrowth().setItemsCol("items").setMinSupport(0.5).setMinConfidence(0.6)
val model=fpgroth.fit(dataset)
// Display frequent itemsets.
model.freqItemsets.show()

// Display generated association rules.
model.associationRules.show()
// transform examines the input items against all the association rules and summarize the
// consequents as prediction
model.transform(dataset).show()
// $example off$

spark.stop()
}
}

運行結果以下:

18/10/23 11:31:27 INFO CodeGenerator: Code generated in 255.413874 ms
+---------+----+
|    items|freq|
+---------+----+
|      [5]|   2|
|   [5, 1]|   2|
|[5, 1, 2]|   2|
|   [5, 2]|   2|
|      [1]|   3|
|   [1, 2]|   3|
|      [2]|   3|
+---------+----+

  

18/10/23 11:45:01 INFO CodeGenerator: Code generated in 566.235467 ms  
+----------+----------+------------------+
|antecedent|consequent|        confidence|
+----------+----------+------------------+
|    [1, 2]|       [5]|0.6666666666666666|
|    [5, 1]|       [2]|               1.0|
|       [2]|       [5]|0.6666666666666666|
|       [2]|       [1]|               1.0|
|       [5]|       [1]|               1.0|
|       [5]|       [2]|               1.0|
|       [1]|       [5]|0.6666666666666666|
|       [1]|       [2]|               1.0|
|    [5, 2]|       [1]|               1.0|
+----------+----------+------------------+
相關文章
相關標籤/搜索