Alink漫談(二十二) :原始碼分析之聚類評估
阿新 • • 發佈:2020-09-26
# Alink漫談(二十二) :原始碼分析之聚類評估
[ToC]
## 0x00 摘要
Alink 是阿里巴巴基於實時計算引擎 Flink 研發的新一代機器學習演算法平臺,是業界首個同時支援批式演算法、流式演算法的機器學習平臺。本文和上文將帶領大家來分析Alink中 聚類評估 的實現。
## 0x01 背景概念
### 1.1 什麼是聚類
聚類(Clustering),用通俗的話來說,就是物以類聚,人以群分。
聚類是觀察式學習,而不是示例式的學習。聚類能夠作為一個獨立的工具獲得資料的分佈狀況,觀察每一簇資料的特徵,集中對特定的聚簇集合作進一步地分析。
聚類分析還可以作為其他資料探勘任務(如分類、關聯規則)的預處理步驟。
### 1.2 聚類分析的方法
聚類分析可以大致分為如下方法:
劃分方法
> - Construct various partitions and then evaluate them by some criterion,e.g.,minimizing the sum of square errors
> - Typical methods:k-means,k-medoids,CLARANS
層次方法:
> - Create a hierarchical decomposition of the set of data (or objects) using some criterion
> - Typical methods: Diana,Agnes,BIRCH,CAMELEON
基於密度的方法:
> - Based on connectivity and density functions
> - Typical methods: DBSCAN,OPTICS,DenClue
基於網格的方法:
> - Based on multiple-level granularity structure
> - Typical methods: STING,WaveCluster,CLIQUE
基於模型的方法:
> - A model is hypothesized for each of the clusters and tries to find the best fit of that model to each other
> - Typical methods: EM,SOM,COBWEB
基於頻繁模式的方法:
> - Based on the analysis of frequent patterns
> - Typical methods: p-Cluster
基於約束的方法:
> - Clustering by considering user-specified or application-specific constraints
> - Typical methods: COD(obstacles),constrained clustering
基於連結的方法:
> - Objects are often linked together in various ways
> - Massive links can be used to cluster objects: SimRank,LinkClus
### 1.3 聚類評估
聚類評估估計在資料集上進行聚類的可行性和被聚類方法產生的結果的質量。聚類評估主要包括:估計聚類趨勢、確定資料集中的簇數、測定聚類質量。
**估計聚類趨勢**:對於給定的資料集,評估該資料集是否存在非隨機結構。盲目地在資料集上使用聚類方法將返回一些簇,所挖掘的簇可能是誤導。資料集上的聚類分析是有意義的,僅當資料中存在非隨機結構。
聚類趨勢評估確定給定的資料集是否具有可以導致有意義的聚類的非隨機結構。一個沒有任何非隨機結構的資料集,如資料空間中均勻分佈的點,儘管聚類演算法可以為該資料集返回簇,但這些簇是隨機的,沒有任何意義。聚類要求資料的非均勻分佈。
**測定聚類質量**:在資料集上使用聚類方法之後,需要評估結果簇的質量。
具體有兩類方法:外在方法和內在方法
- 外在方法:有監督的方法,需要基準資料。用一定的度量評判聚類結果與基準資料的符合程度。
- 內在方法:無監督的方法,無需基準資料。類內聚集程度和類間離散程度。
## 0x02 Alink支援的評估指標
Alink文件中如下:聚類評估是對聚類演算法的預測結果進行效果評估,支援下列評估指標。但是實際從其測試程式碼中可以發現更多。
**Compactness(CP),** CP越低意味著類內聚類距離越近
$$
\overline{CP_i}=\dfrac{1}{|C_i|}\sum_{x \in C_i}\|x_i-u_i\|
$$
$$
\overline{CP}=\dfrac{1}{k}\sum_{i=1}^{k}\overline{CP_k}
$$
**Seperation(SP)**, SP越高意味類間聚類距離越遠
$$
SP=\dfrac{2}{k^2-k}\sum_{i=1}^{k}\sum_{j=i+1}^{k}\|u_i-u_j\|
$$
**Davies-Bouldin Index(DB)**, DB越小意味著類內距離越小 同時類間距離越大
$$
DB=\dfrac{1}{k}\sum_{i=1}^{k}max(\dfrac{\overline{CP_i}+\overline{CP_j}}{\|u_i-u_j\|}), i \not= j
$$
**Calinski-Harabasz Index(VRC)**, VRC越大意味著聚類質量越好
$$
SSB=\sum_{i=1}^{k}n_i\|u_i-u\|^2
$$
$$
SSW=\sum_{i=1}^{k}\sum_{x \in C_i}\|x_i-u_i\|
$$
$$
VRC=\dfrac{SSB}{SSW}*\dfrac{N-k}{k-1}
$$
從其測試程式碼中,我們可以發現更多指標:
```java
Assert.assertEquals(metrics.getCalinskiHarabaz(), 12150.00, 0.01);
Assert.assertEquals(metrics.getCompactness(), 0.115, 0.01);
Assert.assertEquals(metrics.getCount().intValue(), 6);
Assert.assertEquals(metrics.getDaviesBouldin(), 0.014, 0.01);
Assert.assertEquals(metrics.getSeperation(), 15.58, 0.01);
Assert.assertEquals(metrics.getK().intValue(), 2);
Assert.assertEquals(metrics.getSsb(), 364.5, 0.01);
Assert.assertEquals(metrics.getSsw(), 0.119, 0.01);
Assert.assertEquals(metrics.getPurity(), 1.0, 0.01);
Assert.assertEquals(metrics.getNmi(), 1.0, 0.01);
Assert.assertEquals(metrics.getAri(), 1.0, 0.01);
Assert.assertEquals(metrics.getRi(), 1.0, 0.01);
Assert.assertEquals(metrics.getSilhouetteCoefficient(), 0.99,0.01);
```
我們需要介紹幾個指標
### 2.1 輪廓係數(silhouette coefficient):
對於D中的每個物件o,計算:
- a(o) : o與o所屬的簇內其他物件之間的平均距離a(o) 。
- b(o) : 是o到不包含o的所有簇的最小平均距離。
得到輪廓係數定義為:
$$
s(o)=\dfrac{b(o)-a(o)}{max\{a(o),b(o)\}}
$$
輪廓係數的值在-1和1之間。
a(o)的值反映o所屬的簇的緊湊性。該值越小,簇越緊湊。
b(o)的值捕獲o與其他簇的分離程度。b(o)的值越大,o與其他簇越分離。
當o的輪廓係數值接近1時,包含o的簇是緊湊的,並且o遠離其他簇,這是一種可取的情況。
當輪廓係數的值為負時,這意味在期望情況下,o距離其他簇的物件比距離與自己同在簇的物件更近,許多情況下,這很糟糕,應當避免。
### 2.2 Calinski-Harabaz(CH)
CH指標通過計算類中各點與類中心的距離平方和來度量類內的緊密度,通過計算各類中心點與資料集中心點距離平方和來度量資料集的分離度,CH指標由分離度與緊密度的比值得到。從而,CH越大代表著類自身越緊密,類與類之間越分散,即更優的聚類結果。
CH和輪廓係數適用於實際類別資訊未知的情況。
### 2.3 Davies-Bouldin指數(Dbi)
戴維森堡丁指數(DBI),又稱為分類適確性指標,是由大衛*L·*戴維斯和唐納德*·Bouldin*提出的一種評估聚類演算法優劣的指標。
這個DBI就是計算類內距離之和與類外距離之比,來優化k值的選擇,避免K-means演算法中由於只計算目標函式Wn而導致區域性最優的情況。
### 2.4 Rand index(蘭德指數)(RI) 、Adjusted Rand index(調整蘭德指數)(ARI)
![img](https://img-blog.csdn.net/20160903164214309)
其中C表示實際類別資訊,K表示聚類結果,a表示在C與K中都是同類別的元素對數,b表示在C與K中都是不同類別的元素對數。
RI取值範圍為[0,1],值越大意味著聚類結果與真實情況越吻合。RI越大表示聚類效果準確性越高 同時每個類內的純度越高
為了實現“在聚類結果隨機產生的情況下,指標應該接近零”,調整蘭德係數(Adjusted rand index)被提出,它具有更高的區分度:
![img](https://img-blog.csdn.net/20160903164236481)
ARI取值範圍為[−1,1],值越大意味著聚類結果與真實情況越吻合。從廣義的角度來講,ARI衡量的是兩個資料分佈的吻合程度。
## 0x03 示例程式碼
聚類評估示例程式碼如下:
```java
public class EvalClusterBatchOpExp {
public static void main(String[] args) throws Exception {
Row[] rows = new Row[] {
Row.of(0, "0,0,0"),
Row.of(0, "0.1,0.1,0.1"),
Row.of(0, "0.2,0.2,0.2"),
Row.of(1, "9,9,9"),
Row.of(1, "9.1,9.1,9.1"),
Row.of(1, "9.2,9.2,9.2")
};
MemSourceBatchOp inOp = new MemSourceBatchOp(Arrays.asList(rows), new String[] {"label", "Y"});
KMeans train = new KMeans()
.setVectorCol("Y")
.setPredictionCol("pred")
.setK(2);
ClusterMetrics metrics = new EvalClusterBatchOp()
.setPredictionCol("pred")
.setVectorCol("Y")
.setLabelCol("label")
.linkFrom(train.fit(inOp).transform(inOp))
.collectMetrics();
System.out.println(metrics.getCalinskiHarabaz());
System.out.println(metrics.getCompactness());
System.out.println(metrics.getCount());
System.out.println(metrics.getDaviesBouldin());
System.out.println(metrics.getSeperation());
System.out.println(metrics.getK());
System.out.println(metrics.getSsb());
System.out.println(metrics.getSsw());
System.out.println(metrics.getPurity());
System.out.println(metrics.getNmi());
System.out.println(metrics.getAri());
System.out.println(metrics.getRi());
System.out.println(metrics.getSilhouetteCoefficient());
}
}
```
輸出為:
```java
12150.000000000042
0.11547005383792497
6
0.014814814814814791
15.588457268119896
2
364.5
0.1199999999999996
1.0
1.0
1.0
1.0
0.9997530305375205
```
## 0x04 總體邏輯
程式碼整體邏輯如下:
- label 相關指標計算操作
- 使用 calLocalPredResult 對每個分割槽操作
- flatMap 1 是打散Row,得到 Label y
- flatMap 2 是打散Row,得到 y_hat,所以前兩步是得到 y 和 y_hat 的對映 map。這兩個會廣播給 CalLocalPredResult 使用。
- 呼叫 CalLocalPredResult 建立混淆矩陣
- 使用 reduce 歸併這些分割槽操作結果。
- 使用 extractParamsFromConfusionMatrix 根據混淆矩陣計算 purity, NMI等指標
- Vector相關指標計算操作
- 對資料按照類別進行分組
- 分組歸併,呼叫 CalcClusterMetricsSummary分散式計算向量相關的指標
- 遍歷 rows,累積到 sumVector
- 迴圈,計算出若干統計資訊
- 呼叫 ReduceBaseMetrics,再歸併,形成一個BaseMetricsSummary
- 呼叫 calSilhouetteCoefficient 來計算 SilhouetteCoefficient
- 把資料儲存為Params
- 合併輸出
- 做了一個 union,把 labelMetrics 和 vectorMetrics 聯合起來,再歸併輸出到最後的表中
- 分組歸併
- 輸出到最後表
具體程式碼如下:
```java
public EvalClusterBatchOp linkFrom(BatchOperator... inputs) {
BatchOperator in = checkAndGetFirst(inputs);
String labelColName = this.getLabelCol();
String predResultColName = this.getPredictionCol();
String vectorColName = this.getVectorCol();
DistanceType distanceType = getDistanceType();
ContinuousDistance distance = distanceType.getFastDistance();