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