日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

fpgrowth算法实战 mlib_【spark】41.Spark Mlib:FPGrowth算法

發(fā)布時(shí)間:2024/9/27 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 fpgrowth算法实战 mlib_【spark】41.Spark Mlib:FPGrowth算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡(jiǎn)介

FP-Growth算法是韓嘉煒等人在2000年提出的關(guān)聯(lián)分析算法,它采取如下分治策略:將提供頻繁項(xiàng)集的數(shù)據(jù)庫(kù)壓縮到一棵頻繁模式樹(FP-tree),但仍保留項(xiàng)集關(guān)聯(lián)信息。

在算法中使用了一種稱為頻繁模式樹(Frequent Pattern Tree)的數(shù)據(jù)結(jié)構(gòu)。FP-tree是一種特殊的前綴樹,由頻繁項(xiàng)頭表和項(xiàng)前綴樹構(gòu)成。FP-Growth算法基于以上的結(jié)構(gòu)加快整個(gè)挖掘過(guò)程。

眾所周知,Apriori算法在產(chǎn)生頻繁模式完全集前需要對(duì)數(shù)據(jù)庫(kù)進(jìn)行多次掃描,同時(shí)產(chǎn)生大量的候選頻繁集,這就使Apriori算法時(shí)間和空間復(fù)雜度較大。但是Apriori算法中有一個(gè)很重要的性質(zhì):頻繁項(xiàng)集的所有非空子集都必須也是頻繁的。但是Apriori算法在挖掘額長(zhǎng)頻繁模式的時(shí)候性能往往低下,Jiawei Han提出了FP-Growth算法。

FP-Tree:將事務(wù)數(shù)據(jù)表中的各個(gè)事務(wù)數(shù)據(jù)項(xiàng)按照支持度排序后,把每個(gè)事務(wù)中的數(shù)據(jù)項(xiàng)按降序依次插入到一棵以 NULL為根結(jié)點(diǎn)的樹中,同時(shí)在每個(gè)結(jié)點(diǎn)處記錄該結(jié)點(diǎn)出現(xiàn)的支持度。

1、FPGrowth使用場(chǎng)景

FPGrowth關(guān)聯(lián)規(guī)則算法主要用于發(fā)現(xiàn)頻繁項(xiàng)集。如:沃爾瑪啤酒加尿布。

2、FPGrowth基本概念

FPGrowth算法通過(guò)構(gòu)造一個(gè)FPTree樹結(jié)構(gòu)來(lái)壓縮數(shù)據(jù)記錄,使得挖掘頻繁項(xiàng)集只需要掃描兩次數(shù)據(jù)記錄,而且該算法不需要生成候選集合,所以效率會(huì)比較高。

那么,如何從購(gòu)物籃里面發(fā)現(xiàn)尿布+啤酒這樣的最佳組合呢?

我們以以下數(shù)據(jù)集為例,假設(shè)有如下的一張購(gòu)物清單表,每條記錄代表一次購(gòu)物記錄:

|TID|Items|

|-|-|

| T1 | { 面包 , 牛奶 } |

| T2 | { 面包 , 尿布 , 啤酒 , 雞蛋 }|

| T3 | { 牛奶 , 尿布 , 啤酒 , 可樂(lè) }|

| T4 | { 面包 , 牛奶 , 尿布 , 啤酒 }|

| T5 | { 面包 , 牛奶 , 尿布 , 可樂(lè) }|

其中:

牛奶、面包叫做項(xiàng);

{ 牛奶、面包}叫做項(xiàng)集;

項(xiàng)集出現(xiàn)的次數(shù)叫做支持度。

T* 表示用戶每次的購(gòu)物清單。

3、算法思想

該算法的核心就是生成一棵FPTree。前面提到過(guò),FPTree是一種樹結(jié)構(gòu)。

構(gòu)建的過(guò)程需要將表中的數(shù)據(jù)以及關(guān)系進(jìn)行保存,我們先來(lái)看構(gòu)建過(guò)程:

假設(shè)我們的最小支持度是3,這相當(dāng)于是一個(gè)閾值。接下來(lái)我們開始按如下的步驟處理數(shù)據(jù)。

3.1、step1

掃描數(shù)據(jù)記錄,生成一級(jí)頻繁項(xiàng)集,并按出現(xiàn)次數(shù)由多到少排序,如下所示:

ItemCount

牛奶4

面包4

尿布4

啤酒3

可樂(lè)2(<3,刪除)

雞蛋1(<3,刪除)

可以看到,雞蛋和可樂(lè)在上表中要?jiǎng)h除,因?yàn)榭蓸?lè)只出現(xiàn)2次,雞蛋只出現(xiàn)1次,小于最小支持度,因此不是頻繁項(xiàng)集,非頻繁項(xiàng)集的超集一定不是頻繁項(xiàng)集,所以可樂(lè)和雞蛋不需要再考慮。

3.2、step2

再次掃描數(shù)據(jù)記錄,對(duì)每條記錄中出現(xiàn)在Step 1產(chǎn)生的表中的項(xiàng),按表中的順序排序。初始時(shí),新建一個(gè)根結(jié)點(diǎn),標(biāo)記為null。然后依次掃描每條記錄,構(gòu)建FPTree。

1、第一條記錄:{面包,牛奶}需要根據(jù)Step1中結(jié)果轉(zhuǎn)換成:{牛奶,面包},新建一個(gè)結(jié)點(diǎn),name為{牛奶},將其插入到根節(jié)點(diǎn)下,并設(shè)置count為1,然后新建一個(gè){面包}結(jié)點(diǎn),插入到{牛奶}結(jié)點(diǎn)下面,插入后如下所示:

2、第二條記錄:{面包,尿布,啤酒,雞蛋},過(guò)濾并排序后為:{面包,尿布,啤酒},發(fā)現(xiàn)根結(jié)點(diǎn)沒(méi)有包含{面包}的兒子(有一個(gè){面包}孫子但不是兒子),因此新建一個(gè){面包}結(jié)點(diǎn),插在根結(jié)點(diǎn)下面,這樣根結(jié)點(diǎn)就有了兩個(gè)孩子,隨后新建{尿布}結(jié)點(diǎn)插在{面包}結(jié)點(diǎn)下面,新建{啤酒}結(jié)點(diǎn)插在{尿布}下面,插入后如下所示:

3、第三條記錄:{牛奶,尿布,啤酒,可樂(lè)},過(guò)濾并排序后為:{牛奶,尿布,啤酒},這時(shí)候發(fā)現(xiàn)根結(jié)點(diǎn)有兒子{牛奶},因此不需要新建結(jié)點(diǎn),只需將原來(lái)的{牛奶}結(jié)點(diǎn)的count加1即可,往下發(fā)現(xiàn){牛奶}結(jié)點(diǎn)有一個(gè)兒子{尿布},于是新建{尿布}結(jié)點(diǎn),并插入到{牛奶}結(jié)點(diǎn)下面,隨后新建{啤酒}結(jié)點(diǎn)插入到{尿布}結(jié)點(diǎn)后面。插入后如下圖所示:

4、第四條記錄:{面包,牛奶,尿布,啤酒},過(guò)濾并排序后為:{牛奶,面包,尿布,啤酒},這時(shí)候發(fā)現(xiàn)根結(jié)點(diǎn)有兒子{牛奶},因此不需要新建結(jié)點(diǎn),只需將原來(lái)的{牛奶}結(jié)點(diǎn)的count加1即可,往下發(fā)現(xiàn){牛奶}結(jié)點(diǎn)有一個(gè)兒子{面包},于是也不需要新建{面包}結(jié)點(diǎn),只需將原來(lái){面包}結(jié)點(diǎn)的count加1,由于這個(gè){面包}結(jié)點(diǎn)沒(méi)有兒子,此時(shí)需新建{尿布}結(jié)點(diǎn),插在{面包}結(jié)點(diǎn)下面,隨后新建{啤酒}結(jié)點(diǎn),插在{尿布}結(jié)點(diǎn)下面,插入后如下圖所示:

5、按照1-4這樣的方式迭代所有的記錄,最終會(huì)生成一棵樹,即FPTree。按上表中生成的最終的FPTree如下圖所示:

樹中每個(gè)路徑代表一個(gè)項(xiàng)集,因?yàn)樵S多項(xiàng)集有公共項(xiàng),而且出現(xiàn)次數(shù)越多的項(xiàng)越可能是公共項(xiàng),因此按出現(xiàn)次數(shù)由多到少的順序排序可以節(jié)省空間,實(shí)現(xiàn)壓縮存儲(chǔ)。

另外我們需要一個(gè)表頭和對(duì)每一個(gè)name相同的結(jié)點(diǎn)做一個(gè)線索,方便后面使用,線索的構(gòu)造也是在建樹過(guò)程形成的(下圖虛線)。

至此,整個(gè)FpTree就構(gòu)造好了。

4、利用FPTree挖掘頻繁項(xiàng)集

FPTree建好后,就可以進(jìn)行頻繁項(xiàng)集的挖掘,挖掘算法稱為FPGrowth(Frequent Pattern Growth)算法,挖掘從表頭header的最后一個(gè)項(xiàng)開始。

此處即從{啤酒}開始,根據(jù){啤酒}的線索鏈找到所有{啤酒}結(jié)點(diǎn),然后找出每個(gè){啤酒}結(jié)點(diǎn)的分支:{牛奶,面包,尿布,啤酒:1},{牛奶,尿布,啤酒:1},{面包,尿布,啤酒:1},其中的“1”表示出現(xiàn)1次。

注意,雖然{牛奶}出現(xiàn)4次,但{牛奶,面包,尿布,啤酒}只同時(shí)出現(xiàn)1次,因此分支的count是由后綴結(jié)點(diǎn){啤酒}的count決定的,除去{啤酒},我們得到對(duì)應(yīng)的前綴路徑{牛奶,面包,尿布:1},{牛奶,尿布:1},{面包,尿布:1},根據(jù)前綴路徑我們可以生成一棵條件FPTree,構(gòu)造方式跟之前一樣,此處的數(shù)據(jù)記錄變?yōu)?#xff1a;

T1{牛奶,面包,尿布 : 1}

T2{牛奶,尿布: 1}

T3{面包,尿布: 1}

絕對(duì)支持度依然是3,我們發(fā)現(xiàn)此時(shí),牛奶的支持度為2、面包的支持度為2、尿布的支持度為3,由于我們的支持度為3,所以刪除牛奶和面包。按照相同的算法構(gòu)造得到的FPTree為:

構(gòu)造好條件樹后,對(duì)條件樹進(jìn)行遞歸挖掘,當(dāng)條件樹只有一條路徑時(shí),路徑的所有組合即為條件頻繁集,假設(shè){啤酒}的條件頻繁集為{S1,S2},則{啤酒}的頻繁集為{S1+{啤酒},S2+{啤酒},S1+S2+{啤酒}},即{啤酒}的頻繁集一定有相同的后綴{啤酒},此處的條件頻繁集為:{{},{尿布}},于是{啤酒}的頻繁集為{{啤酒}{尿布,啤酒}}。

接下來(lái)找header表頭的倒數(shù)第二個(gè)項(xiàng){尿布}的頻繁集,同上可以得到{尿布}的前綴路徑為:{面包:1},{牛奶:1},{牛奶,面包:2},條件FPTree的數(shù)據(jù)集為:

T1{面包 :1 }

T2{牛奶 :1}

T3{牛奶,面包 :2}

構(gòu)造的條件FpTree為:

這顆條件樹路徑上的所有組合即為條件頻繁集:

{{},{牛奶},{面包},{牛奶,面包}}

加上{尿布}后,又得到一組頻繁項(xiàng)集

{{尿布},{牛奶,尿布},{面包,尿布},{牛奶,面包,尿布}}

同樣,這組頻繁項(xiàng)集一定包含一個(gè)相同的后綴:{尿布},也就是我們一開始分析的對(duì)象,并且不包含{啤酒},因此這一組頻繁項(xiàng)集與上一組不會(huì)重復(fù)。

重復(fù)以上步驟,對(duì)header表頭的每個(gè)項(xiàng)進(jìn)行挖掘,即可得到整個(gè)頻繁項(xiàng)集,頻繁項(xiàng)集即不重復(fù)也不遺漏。

最終,我們可以得到多個(gè)集合列表,每一個(gè)集合代表一個(gè)頻繁項(xiàng)集。

總結(jié)下來(lái),FPTree的開發(fā)流程為2個(gè):

1、生成樹過(guò)程

2、挖掘樹過(guò)程:挖掘樹的過(guò)程也是一個(gè)生成樹的過(guò)程,每次挖掘一個(gè)節(jié)點(diǎn)的目的,都是為了發(fā)現(xiàn)該節(jié)點(diǎn)的頻繁項(xiàng)集,將最終生成的結(jié)果取所有子集然后將每一項(xiàng)與挖掘的節(jié)點(diǎn)組合,作為我們最后得到的結(jié)果。

Spark Mlib實(shí)現(xiàn)

訓(xùn)練集如下:

面包 牛奶

面包 尿布 啤酒 雞蛋

牛奶 尿布 啤酒 可樂(lè)

面包 牛奶 尿布 啤酒

面包 牛奶 尿布 可樂(lè)

存儲(chǔ)在路徑data/sample_fpgrowth.txt中。

接下來(lái)調(diào)用FPGrouwth算法訓(xùn)練數(shù)據(jù)集。

package com.zhaoyi;// $example on$

import java.util.Arrays;

import java.util.List;

import org.apache.spark.api.java.JavaRDD;

import org.apache.spark.api.java.JavaSparkContext;

import org.apache.spark.mllib.fpm.AssociationRules;

import org.apache.spark.mllib.fpm.FPGrowth;

import org.apache.spark.mllib.fpm.FPGrowthModel;

// $example off$

import org.apache.spark.SparkConf;

public class JavaSimpleFPGrowth {

public static void main(String[] args) {

SparkConf conf = new SparkConf().setMaster("local[*]").set("spark.testing.memory","2140000000")

.setAppName("JavaLinearRegressionWithSGDExample");

JavaSparkContext sc = new JavaSparkContext(conf);

// $example on$

JavaRDD data = sc.textFile("data/sample_fpgrowth.txt");

JavaRDD> transactions = data.map(line -> Arrays.asList(line.split(" ")));

// 最小支持度為0.5

FPGrowth fpg = new FPGrowth()

.setMinSupport(0.5)

.setNumPartitions(10);

FPGrowthModel model = fpg.run(transactions);

for (FPGrowth.FreqItemset itemset: model.freqItemsets().toJavaRDD().collect()) {

System.out.println("[" + itemset.javaItems() + "], " + itemset.freq());

}

double minConfidence = 0.8;

for (AssociationRules.Rule rule

: model.generateAssociationRules(minConfidence).toJavaRDD().collect()) {

System.out.println(

rule.javaAntecedent() + " => " + rule.javaConsequent() + ", " + rule.confidence());

}

// $example off$

sc.stop();

}

}

面包 牛奶

面包 尿布 啤酒 雞蛋

牛奶 尿布 啤酒 可樂(lè)

面包 牛奶 尿布 啤酒

面包 牛奶 尿布 可樂(lè)

可以看到,我們?cè)O(shè)置的最小支持度為0.5,也就是說(shuō),過(guò)濾過(guò)程中,會(huì)將低于出現(xiàn)次數(shù)小于3/5>0.5>2/5次的話,顯然可樂(lè)(出現(xiàn)一次,支持度為2/5=0.4)以及雞蛋(出現(xiàn)1次,支持度為1/5=0.2)都不會(huì)納入頻繁項(xiàng)集之中,在step1中就會(huì)被T除。

最終的輸出結(jié)果

[[尿布]], 4

[[牛奶]], 4

[[牛奶, 尿布]], 3

[[面包]], 4

[[面包, 牛奶]], 3

[[面包, 尿布]], 3

[[啤酒]], 3

[[啤酒, 尿布]], 3

[啤酒] => [尿布], 1.0

可以看到,該輸出結(jié)果完美的實(shí)現(xiàn)了牛奶尿布實(shí)例中的預(yù)測(cè)結(jié)果。即{啤酒,尿布}這樣的組合頻繁項(xiàng)集。

那么,我們可以考慮將這兩種商品擺放到一起,從而起到一定的增加銷售業(yè)績(jī)的作用(事實(shí)上沃爾瑪?shù)拇_這么做了)。

總結(jié)

以上是生活随笔為你收集整理的fpgrowth算法实战 mlib_【spark】41.Spark Mlib:FPGrowth算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。