Spark ML - 聚类算法
http://ihoge.cn/2018/ML2.html
Spark ML - 聚類算法
1.KMeans快速聚類
首先到UR需要的包:
import org.apache.spark.ml.clustering.{KMeans,KMeansModel} import org.apache.spark.ml.linalg.Vectors開啟RDD的隱式轉(zhuǎn)換:
import spark.implicits._? 為了便于生成相應(yīng)的DataFrame,這里定義一個(gè)名為model_instance的case class作為DataFrame每一行(一個(gè)數(shù)據(jù)樣本)的數(shù)據(jù)類型。
case class model_instance (features: org.apache.spark.ml.linalg.Vector)? 在定義數(shù)據(jù)類型完成后,即可將數(shù)據(jù)讀入RDD[model_instance]的結(jié)構(gòu)中,并通過RDD的隱式轉(zhuǎn)換.toDF()方法完成RDD到DataFrame的轉(zhuǎn)換:
val rawData = sc.textFile("file:///home/hduser/iris.data") val df = rawData.map(line =>{ model_instance( Vectors.dense(line.split(",").filter(p => p.matches("\\d*(\\.?)\\d*")).map(_.toDouble)) )}).toDF()? 與MLlib版的教程類似,我們使用了filter算子,過濾掉類標(biāo)簽,正則表達(dá)式\\d*(\\.?)\\d*可以用于匹配實(shí)數(shù)類型的數(shù)字,\\d*使用了*限定符,表示匹配0次或多次的數(shù)字字符,\\.?使用了?限定符,表示匹配0次或1次的小數(shù)點(diǎn)。
? 在得到數(shù)據(jù)后,我們即可通過ML包的固有流程:創(chuàng)建Estimator并調(diào)用其fit()方法來生成相應(yīng)的Transformer對象,很顯然,在這里KMeans類是Estimator,而用于保存訓(xùn)練后模型的KMeansModel類則屬于Transformer:
val kmeansmodel = new KMeans().setK(3).setFeaturesCol("features").setPredictionCol("prediction").fit(df)? 與MLlib版本類似,ML包下的KMeans方法也有Seed(隨機(jī)數(shù)種子)、Tol(收斂閾值)、K(簇個(gè)數(shù))、MaxIter(最大迭代次數(shù))、initMode(初始化方式)、initStep(KMeans||方法的步數(shù))等參數(shù)可供設(shè)置,和其他的ML框架算法一樣,用戶可以通過相應(yīng)的setXXX()方法來進(jìn)行設(shè)置,或以ParamMap的形式傳入?yún)?shù),這里為了簡介期間,使用setXXX()方法設(shè)置了參數(shù)K,其余參數(shù)均采用默認(rèn)值。
? 與MLlib中的實(shí)現(xiàn)不同,KMeansModel作為一個(gè)Transformer,不再提供predict()樣式的方法,而是提供了一致性的transform()方法,用于將存儲在DataFrame中的給定數(shù)據(jù)集進(jìn)行整體處理,生成帶有預(yù)測簇標(biāo)簽的數(shù)據(jù)集:
val results = kmeansmodel.transform(df)? 為了方便觀察,我們可以使用collect()方法,該方法將DataFrame中所有的數(shù)據(jù)組織成一個(gè)Array對象進(jìn)行返回:
results.collect().foreach(row => {println( row(0) + " is predicted as cluster " + row(1))})也可以通過KMeansModel類自帶的clusterCenters屬性獲取到模型的所有聚類中心情況:
kmeansmodel.clusterCenters.foreach(center => {println("Clustering Center:"+center)})? 與MLlib下的實(shí)現(xiàn)相同,KMeansModel類也提供了計(jì)算 集合內(nèi)誤差平方和(Within Set Sum of Squared Error, WSSSE) 的方法來度量聚類的有效性,在真實(shí)K值未知的情況下,該值的變化可以作為選取合適K值的一個(gè)重要參考:
kmeansmodel.computeCost(df)2.高斯混合模型(GMM)聚類算法
2.1 基本原理
? 高斯混合模型(Gaussian Mixture Model, GMM) 是一種概率式的聚類方法,屬于生成式模型,它假設(shè)所有的數(shù)據(jù)樣本都是由某一個(gè)給定參數(shù)的 多元高斯分布 所生成的。具體地,給定類個(gè)數(shù)K,對于給定樣本空間中的樣本
,一個(gè)高斯混合模型的概率密度函數(shù)可以由K個(gè)多元高斯分布組合成的混合分布表示:
其中,
是以
為均值向量,
為協(xié)方差矩陣的多元高斯分布的概率密度函數(shù),可以看出,高斯混合模型由K個(gè)不同的多元高斯分布共同組成,每一個(gè)分布被稱為高斯混合模型中的一個(gè) 成分(Component), 而
為第i個(gè)多元高斯分布在混合模型中的 權(quán)重 ,且有
。
假設(shè)已有一個(gè)存在的高斯混合模型,那么,樣本空間中的樣本的生成過程即是:以
作為概率(實(shí)際上,權(quán)重可以直觀理解成相應(yīng)成分產(chǎn)生的樣本占總樣本的比例),選擇出一個(gè)混合成分,根據(jù)該混合成分的概率密度函數(shù),采樣產(chǎn)生出相應(yīng)的樣本。
那么,利用GMM進(jìn)行聚類的過程是利用GMM生成數(shù)據(jù)樣本的“逆過程”:給定聚類簇?cái)?shù)K,通過給定的數(shù)據(jù)集,以某一種 參數(shù)估計(jì) 的方法,推導(dǎo)出每一個(gè)混合成分的參數(shù)(即均值向量
、協(xié)方差矩陣
和權(quán)重
),每一個(gè)多元高斯分布成分即對應(yīng)于聚類后的一個(gè)簇。高斯混合模型在訓(xùn)練時(shí)使用了極大似然估計(jì)法,最大化以下對數(shù)似然函數(shù):
顯然,該優(yōu)化式無法直接通過解析方式求得解,故可采用 期望-最大化(Expectation-Maximization, EM) 方法求解,具體過程如下(為了簡潔,這里省去了具體的數(shù)學(xué)表達(dá)式,詳細(xì)可見wikipedia):
1.根據(jù)給定的K值,初始化K個(gè)多元高斯分布以及其權(quán)重; 2.根據(jù)貝葉斯定理,估計(jì)每個(gè)樣本由每個(gè)成分生成的后驗(yàn)概率;(EM方法中的E步) 3.根據(jù)均值,協(xié)方差的定義以及2步求出的后驗(yàn)概率,更新均值向量、協(xié)方差矩陣和權(quán)重;(EM方法的M步) 重復(fù)2~3步,直到似然函數(shù)增加值已小于收斂閾值,或達(dá)到最大迭代次數(shù)? 當(dāng)參數(shù)估計(jì)過程完成后,對于每一個(gè)樣本點(diǎn),根據(jù)貝葉斯定理計(jì)算出其屬于每一個(gè)簇的后驗(yàn)概率,并將樣本劃分到后驗(yàn)概率最大的簇上去。相對于KMeans等直接給出樣本點(diǎn)的簇劃分的聚類方法,GMM這種給出樣本點(diǎn)屬于每個(gè)簇的概率的聚類方法,被稱為 軟聚類(Soft Clustering / Soft Assignment) 。
2.2 模型的訓(xùn)練與分析
? Spark的ML庫提供的高斯混合模型都在org.apache.spark.ml.clustering包下,和其他的聚類方法類似,其具體實(shí)現(xiàn)分為兩個(gè)類:用于抽象GMM的超參數(shù)并進(jìn)行訓(xùn)練的GaussianMixture類(Estimator)和訓(xùn)練后的模型GaussianMixtureModel類(Transformer),在使用前,引入需要的包:
import org.apache.spark.ml.clustering.{GaussianMixture,GaussianMixtureModel} import org.apache.spark.ml.linalg.Vector開啟RDD的隱式轉(zhuǎn)換:
import spark.implicits._? 我們?nèi)圆捎肐ris數(shù)據(jù)集進(jìn)行實(shí)驗(yàn)。為了便于生成相應(yīng)的DataFrame,這里定義一個(gè)名為model_instance的case class作為DataFrame每一行(一個(gè)數(shù)據(jù)樣本)的數(shù)據(jù)類型。
case class model_instance (features: org.apache.spark.ml.linalg.Vector)在定義數(shù)據(jù)類型完成后,即可將數(shù)據(jù)讀入RDD[model_instance]的結(jié)構(gòu)中,并通過RDD的隱式轉(zhuǎn)換.toDF()方法完成RDD到DataFrame的轉(zhuǎn)換:
val rawData = sc.textFile("file:///home/hduser/iris.data") val df = rawData.map(line =>{ model_instance( Vectors.dense(line.split(",").filter(p => p.matches("\\d*(\\.?)\\d*")).map(_.toDouble)) )}).toDF()? 與MLlib的操作類似,我們使用了filter算子,過濾掉類標(biāo)簽,正則表達(dá)式\\d*(\\.?)\\d*可以用于匹配實(shí)數(shù)類型的數(shù)字,\\d*使用了*限定符,表示匹配0次或多次的數(shù)字字符,\\.?使用了?限定符,表示匹配0次或1次的小數(shù)點(diǎn)。
? 可以通過創(chuàng)建一個(gè)GaussianMixture類,設(shè)置相應(yīng)的超參數(shù),并調(diào)用fit(..)方法來訓(xùn)練一個(gè)GMM模型GaussianMixtureModel,在該方法調(diào)用前需要設(shè)置一系列超參數(shù),如下表所示:
- K:聚類數(shù)目,默認(rèn)為2
- maxIter : 最大迭代次數(shù),默認(rèn)為100
- seed : 隨機(jī)數(shù)種子,默認(rèn)為隨機(jī)Long值
- Tol : 對數(shù)似然函數(shù)收斂閾值,默認(rèn)為0.01
其中,每一個(gè)超參數(shù)均可通過名為setXXX(...)(如maxIterations即為setMaxIterations())的方法進(jìn)行設(shè)置。這里,我們建立一個(gè)簡單的GaussianMixture對象,設(shè)定其聚類數(shù)目為3,其他參數(shù)取默認(rèn)值。
val gm = new GaussianMixture().setK(3).setPredictionCol("Prediction").setProbabilityCol("Probability") val gmm = gm.fit(df)和KMeans等硬聚類方法不同的是,除了可以得到對樣本的聚簇歸屬預(yù)測外,還可以得到樣本屬于各個(gè)聚簇的概率(這里我們存在”Probability”列中)。
? 調(diào)用transform()方法處理數(shù)據(jù)集之后,打印數(shù)據(jù)集,可以看到每一個(gè)樣本的預(yù)測簇以及其概率分布向量
val result = gmm.transform(df) result.show(150, false)? 得到模型后,即可查看模型的相關(guān)參數(shù),與KMeans方法不同,GMM不直接給出聚類中心,而是給出各個(gè)混合成分(多元高斯分布)的參數(shù)。在ML的實(shí)現(xiàn)中,GMM的每一個(gè)混合成分都使用一個(gè)MultivariateGaussian類(位于org.apache.spark.ml.stat.distribution包)來存儲,我們可以使用GaussianMixtureModel類的weights成員獲取到各個(gè)混合成分的權(quán)重,使用gaussians成員來獲取到各個(gè)混合成分的參數(shù)(均值向量和協(xié)方差矩陣):
for (i <- 0 until gmm.getK) {println("Component %d : weight is %f \n mu vector is %s \n sigma matrix is %s" format(i, gmm.weights(i), gmm.gaussians(i).mean, gmm.gaussians(i).cov))}更多精彩內(nèi)容請關(guān)注: http://ihoge.cn
總結(jié)
以上是生活随笔為你收集整理的Spark ML - 聚类算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spark ML - 协同过滤
- 下一篇: 逻辑回归算法原理