Spark MLlib FPGrowth演算法
1.1 FPGrowth演算法
1.1.1 基本概念
關聯規則挖掘的一個典型例子是購物籃分析。關聯規則研究有助於發現交易資料庫中不同商品(項)之間的聯絡,找出顧客購買行為模式,如購買了某一商品對購買其他商品的影響,分析結果可以應用於商品貨架佈局、貨存安排以及根據購買模式對使用者進行分類。
關聯規則的相關術語如下:
(1)項與項集
這是一個集合的概念,在一籃子商品中的一件消費品即為一項(Item),則若干項的集合為項集,如{啤酒,尿布}構成一個二元項集。
(2)關聯規則
一般記為的形式,X為先決條件,Y為相應的關聯結果,用於表示資料內隱含的關聯性。如:表示購買了尿布的消費者往往也會購買啤酒。
關聯性強度如何,由三個概念——支援度、置信度、提升度來控制和評價。
例:有10000個消費者購買了商品,其中購買尿布1000個,購買啤酒2000個,購買麵包500個,同時購買尿布和麵包800個,同時購買尿布和麵包100個。
(3)支援度(Support)
支援度是指在所有項集中{X, Y}出現的可能性,即項集中同時含有X和Y的概率:
該指標作為建立強關聯規則的第一個門檻,衡量了所考察關聯規則在“量”上的多少。通過設定最小閾值(minsup),剔除“出鏡率”較低的無意義規則,保留出現較為頻繁的項集所隱含的規則。
設定最小閾值為5%,由於{尿布,啤酒}的支援度為800/10000=8%,滿足基本輸了要求,成為頻繁項集,保留規則;而{尿布,麵包}的支援度為100/10000=1%,被剔除。
(4)置信度(Confidence)
置信度表示在先決條件X發生的條件下,關聯結果Y發生的概率:
這是生成強關聯規則的第二個門檻,衡量了所考察的關聯規則在“質”上的可靠性。相似的,我們需要對置信度設定最小閾值(mincon)來實現進一步篩選。
具體的,當設定置信度的最小閾值為70%時,置信度為800/1000=80%,而的置信度為800/2000=40%,被剔除。
(5)提升度(lift)
提升度表示在含有X的條件下同時含有Y的可能性與沒有X這個條件下項集中含有Y的可能性之比:公式為confidence(artichok => cracker)/support(cracker) = 80%/50% = 1.6。該指標與置信度同樣衡量規則的可靠性,可以看作是置信度的一種互補指標。
1.1.2 FP-Growth演算法
FP-Growth(頻繁模式增長)演算法是韓家煒老師在2000年提出的關聯分析演算法,它採取如下分治策略:將提供頻繁項集的資料庫壓縮到一棵頻繁模式樹(FP-Tree),但仍保留項集關聯資訊;該演算法和Apriori演算法最大的不同有兩點:第一,不產生候選集,第二,只需要兩次遍歷資料庫,大大提高了效率。
(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)
以此類推加入第5、6、7、8、9個事務。
(6)加入第九個事務(I2,I1,I3)
1.1.4 FP-Growth演算法演示—FP-樹挖掘
FP-樹建好後,就可以進行頻繁項集的挖掘,挖掘演算法稱為FpGrowth(Frequent Pattern Growth)演算法,挖掘從表頭header的最後一個項開始,以此類推。本文以I5、I3為例進行挖掘。
(1)挖掘I5:
對於I5,得到條件模式基:<(I2,I1:1)>、<I2,I1,I3:1>
構造條件FP-tree:
得到I5頻繁項集:{{I2,I5:2},{I1,I5:2},{I2,I1,I5:2}}
I4、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}。
1.2 Spark Mllib FPGrowth原始碼分析
FPGrowth原始碼包括:FPGrowth、FPTree兩部分。
其中FPGrowth中包括:run方法、genFreqItems方法、genFreqItemsets方法、genCondTransactions方法;
FPTree中包括:add方法、merge方法、project方法、getTransactions方法、extract方法。
// run 計算頻繁項集
/**
* Computes an FP-Growth model that contains frequent itemsets.
* @param data input data set, each element contains a transaction
* @return an [[FPGrowthModel]]
*/
def run[Item: ClassTag](data: RDD[Array[Item]]): FPGrowthModel[Item] = {
if (data.getStorageLevel == StorageLevel.NONE) {
logWarning("Input data is not cached.")
}
val count = data.count()//計算事務總數
val minCount = math.ceil(minSupport * count).toLong//計算最小支援度
val numParts = if (numPartitions > 0) numPartitions else data.partitions.length
val partitioner = new HashPartitioner(numParts)
//freqItems計算滿足最小支援度的Items項
val freqItems = genFreqItems(data, minCount, partitioner)
//freqItemsets計算頻繁項集
val freqItemsets = genFreqItemsets(data, minCount, freqItems, partitioner)
new FPGrowthModel(freqItemsets)
}
// genFreqItems計算滿足最小支援度的Items項
/**
* Generates frequent items by filtering the input data using minimal support level.
* @param minCount minimum count for frequent itemsets
* @param partitioner partitioner used to distribute items
* @return array of frequent pattern ordered by their frequencies
*/
privatedef genFreqItems[Item: ClassTag](
data: RDD[Array[Item]],
minCount: Long,
partitioner: Partitioner): Array[Item] = {
data.flatMap { t =>
val uniq = t.toSet
if (t.size != uniq.size) {
thrownew SparkException(s"Items in a transaction must be unique but got ${t.toSeq}.")
}
t
}.map(v => (v, 1L))
.reduceByKey(partitioner, _ + _)
.filter(_._2 >= minCount)
.collect()
.sortBy(-_._2)
.map(_._1)
}//統計每個Items項的頻次,對小於minCount的Items項過濾,返回Items項。
// genFreqItemsets計算頻繁項集:生成FP-Trees,挖掘FP-Trees
/**
* Generate frequent itemsets by building FP-Trees, the extraction is done on each partition.
* @param data transactions
* @param minCount minimum count for frequent itemsets
* @param freqItems frequent items
* @param partitioner partitioner used to distribute transactions
* @return an RDD of (frequent itemset, count)
*/
privatedef genFreqItemsets[Item: ClassTag](
data: RDD[Array[Item]],
minCount: Long,
freqItems: Array[Item],
partitioner: Partitioner): RDD[FreqItemset[Item]] = {
val itemToRank = freqItems.zipWithIndex.toMap//表頭
data.flatMap { transaction =>
genCondTransactions(transaction, itemToRank, partitioner)
}.aggregateByKey(new FPTree[Int], partitioner.numPartitions)( //生成FP樹
(tree, transaction) => tree.add(transaction, 1L), //FP樹增加一條事務
(tree1, tree2) => tree1.merge(tree2)) //FP樹合併
.flatMap { case (part, tree) =>
tree.extract(minCount, x => partitioner.getPartition(x) == part)//FP樹挖掘頻繁項
}.map { case (ranks, count) =>
new FreqItemset(ranks.map(i => freqItems(i)).toArray, count)
}
}
// add FP-Trees增加一條事務資料
/** Adds a transaction with count. */
def add(t: Iterable[T], count: Long = 1L): this.type = {
require(count > 0)
var curr = root
curr.count += count
t.foreach { item =>
val summary = summaries.getOrElseUpdate(item, new Summary)
summary.count += count
val child = curr.children.getOrElseUpdate(item, {
val newNode = new Node(curr)
newNode.item = item
summary.nodes += newNode
newNode
})
child.count += count
curr = child
}
this
}
// merge FP-Trees合併
/** Merges another FP-Tree. */
def merge(other: FPTree[T]): this.type = {
other.transactions.foreach { case (t, c) =>
add(t, c)
}
this
}
// extract FP-Trees挖掘,返回所有頻繁項集
/** Extracts all patterns with valid suffix and minimum count. */
def extract(
minCount: Long,
validateSuffix: T => Boolean = _ => true): Iterator[(List[T], Long)] = {
summaries.iterator.flatMap { case (item, summary) =>
if (validateSuffix(item) && summary.count >= minCount) {
Iterator.single((item :: Nil, summary.count)) ++
project(item).extract(minCount).map { case (t, c) =>
(item :: t, c)
}
} else {
Iterator.empty
}
}
}
}
1.3 Mllib FPGrowth例項
1、資料
資料格式為:物品1物品2物品3…
r z h k p
z y x w v u t s
s x o n r
x z y m t s q e
z
x z y r q t p
2、程式碼
//讀取樣本資料
valdata_path = "/home/tmp/sample_fpgrowth.txt"
valdata = sc.textFile(data_path)
valexamples = data.map(_.split(" ")).cache()
//建立模型
valminSupport = 2
valnumPartition = 10
valmodel = new FPGrowth()
.setMinSupport(minSupport)
.setNumPartitions(numPartition)
.run(examples)
//列印結果
println(s"Number of frequent itemsets: ${model.freqItemsets.count()}")
model.freqItemsets.collect().foreach { itemset =>
println(itemset.items.mkString("[", ",", "]") + ", " + itemset.freq)
}
http://blog.csdn.net/sunbow0/article/details/45602415
相關文章
- Spark FPGrowth (Frequent Pattern Mining)Spark
- AI開源專案 - Spark MLlibAISpark
- 機器學習庫Spark MLlib簡介與教程機器學習Spark
- Spark MLlib學習(1)--基本統計Spark
- Spark MLlib 核心基礎:向量 And 矩陣Spark矩陣
- Spark MLlib SVM 文字分類器實現Spark文字分類
- Spark MLlib NaiveBayes 貝葉斯分類器SparkAI
- 從Spark MLlib到美圖機器學習框架實踐Spark機器學習框架
- 如何利用Spark MLlib進行個性推薦?Spark
- 模式識別中的Apriori演算法和FPGrowth演算法模式演算法
- 使用Spark MLlib訓練和提供自然語言處理模型Spark自然語言處理模型
- 機器學習講座,如何利用Spark MLlib進行個性推薦?機器學習Spark
- Spark MLlib 入門學習筆記 - 程式設計環境配置Spark筆記程式設計
- 對於相同喜好的使用者,電商高手用Spark MLlib程式碼如何操作?Spark
- 【轉】Spark MLlib協同過濾之交替最小二乘法ALS原理與實踐Spark
- Spark中的聚類演算法Spark聚類演算法
- 用Spark學習FP Tree演算法和PrefixSpan演算法Spark演算法
- 用 LDA 做主題模型:當 MLlib 邂逅 GraphXLDA模型
- 用Spark學習矩陣分解推薦演算法Spark矩陣演算法
- Spark之spark shellSpark
- 【Spark篇】---Spark初始Spark
- 什麼樣的演算法可以用Spark重寫演算法Spark
- Spark on Yarn 和Spark on MesosSparkYarn
- Spark系列 - (3) Spark SQLSparkSQL
- Spark學習進度-Spark環境搭建&Spark shellSpark
- 【Spark】Spark容錯機制Spark
- Spark導論(Spark自學一)Spark
- 你知道嗎?常用的資料探勘分析工具Mahout和MLlib
- sparkSpark
- spark學習筆記--Spark SQLSpark筆記SQL
- Spark記錄(一):Spark全景概述Spark
- Spark開發-Spark核心細說Spark
- Spark開發-spark環境搭建Spark
- [機器學習]協同過濾演算法的原理和基於Spark 例項機器學習演算法Spark
- Spark文件閱讀之一:Spark OverviewSparkView
- Spark 系列(九)—— Spark SQL 之 Structured APISparkSQLStructAPI
- Spark 系列(十四)—— Spark Streaming 基本操作Spark
- Spark 系列(十五)—— Spark Streaming 整合 FlumeSpark