chapter 16 聚類分析


作者: 于餅喵
閱讀時間:10min


有時我們需要將樣本按照特征分為不同的類,比如,金融機構(gòu)需要根據(jù)客戶的特征將客戶劃分不同的等級,這時聚類算法可以滿足我們的需求

本章主要介紹兩類常用聚類分析方法:

  • 層次聚類(eg. Hierachical Clustering)
  • 劃分聚類 (eg. K-means Clustering)

層次聚類和劃分聚類的區(qū)別在于是否提前指定了類別數(shù)量k,一般層次聚類用于找出最優(yōu)的分類數(shù)目k,而劃分聚類用于將觀測值劃分為給定k個類別

16.1 聚類分析一般步驟

  1. 挑選變量:挑選出用于聚類算法的特征(變量)。比如:通過皮爾斯相關(guān)系數(shù)剔除相關(guān)性高的變量
  2. 標(biāo)準(zhǔn)化數(shù)據(jù):將特征的值標(biāo)準(zhǔn)化為均值為0,方差為1的變量,在R中,可以使用scale()函數(shù)來標(biāo)準(zhǔn)化數(shù)據(jù)
  3. 處理異常值:層次聚類對異常值比較敏感,異常值有可能會改變最終的聚類方案,因此,使用層次聚類算法時去除異常值是必要的。在R中,可以使用outliers包中的函數(shù)moveliers()來去除異常單變量離群點
  4. 計算距離:聚類算法的原理是通過距離來對不同的樣本進行分類,因此距離的計算尤為重要。一般選擇歐式距離或者曼哈頓距離
  5. 選擇聚類算法:若樣本量較小,且不確定分類的數(shù)量k,則可以使用層次聚類;若已經(jīng)根據(jù)業(yè)務(wù)得出了明確的分類數(shù)量k,可使用劃分聚類; 也可使用層次聚類得出最優(yōu)分類數(shù)目k后,再使用劃分聚類進行劃分(two-step clustering)
  6. 驗證最終分類結(jié)果是否顯著
  7. 分類結(jié)果的描述和可視化

16.2 距離(distance)

聚類分析使用距離來反映兩個樣本的相似性

兩個樣本之間的距離公式可以定義為:
D_{i,j} = (\sum_{k=1}^{p} |x_{ik}-x_{jk}|^{s})^{1/s}
當(dāng)s為2時,公式為歐式距離(Euclidean Distance),當(dāng)s為1時,公式為曼哈頓距離。一般常用歐式距離

在R中,可以使用dist(x,method='')來計算數(shù)據(jù)框或矩陣所有行之間的距離(兩兩樣本之間的距離)

# 營養(yǎng)數(shù)據(jù)集
data(nutrient, package="flexclust") 
head(nutrient,5)
distance <- dist(nutrient)
as.matrix(distance)[1:5,1:5] # 使用as.matrix轉(zhuǎn)為矩陣更容易觀察結(jié)果


兩個觀測值之間的距離越大,則其異質(zhì)性越大

16.3 層次聚類(Hierachical Clustering)

層次聚類算法的原理是根據(jù)樣本之間的距離,每次都把距離最近的兩個樣本合成新的一類,直到所有樣本都被合成單個類為止。

Hierachical clustering的算法步驟如下

  1. 定義每個觀測值為一類【即一開始,一個觀測值就是單獨一類】
  2. 計算每一類和其他各類之間的距離
  3. 把距離最短的兩類合成一類
  4. 重復(fù)2,3步,直到所有類都合成一個類為止

16.3.1 實現(xiàn)Hierachical Clustering

在R中,Hierachical Clustering可以使用hclust(data,method='')來實現(xiàn)

nutrient.scaled <- scale(nutrient)
d <- dist(nutrient.scaled)
fit.average <- hclust(d, method="average") 
plot(fit.average, hang=-1, cex=.8, main="Hierachical Clustering")  # 繪制dendrogram,hang命令展示觀測值的標(biāo)簽

dendrogram從下網(wǎng)上看,可以直觀的看出每次迭代后,哪些類被合成了一類

如何看出最優(yōu)的分類個數(shù)呢?NbClust包提供了NbClust()方法來確定層次聚類分析的最佳分類個數(shù),返回26種方法下推薦的聚類分類個數(shù)

install.packages('NbClust')
library('NbClust')
nc <- NbClust(nutrient.scaled, distance="euclidean",min.nc=2, max.nc=15, method="average") 
table(nc$Best.nc[1,])  # 選出不同計算方法下的分類數(shù)目頻數(shù)
barplot(table(nc$Best.nc[1,]),xlab='# of clustering',ylab='# of criteria',main='# of Clusters Chosen by 26 criteria')

使用table(nc$Best.nc[1,])可以查看26種計算標(biāo)準(zhǔn)下所推薦的不同類別數(shù)量的頻數(shù)分布,從barplot可以看出,2、3、5、15都可以作為所分的類別數(shù)量

16.3.2 手肘原則

NbClust包給出的結(jié)果下,2、3、5、15 的頻數(shù)相同,那么此時我們要用哪個數(shù)作為我們的k呢?這時我們可以使用SSE+手肘原則來選擇最優(yōu)的k
\begin{align} \\& SSE = \sum_{i=1}^{k} \sum_{p \in C_{i}} (p - \mu_{i})^2 \\& Ci \quad代表第i個簇 \\& p \ \ \quad代表第i個簇內(nèi)的樣本值 \\& \mu \ \quad 代表第i個簇的質(zhì)心 \end{align}

隨著聚類數(shù)k的增大,樣本劃分會更加精細(xì),每個簇的聚合程度會逐漸提高,那么誤差平方和SSE自然會逐漸變小。并且,當(dāng)k小于真實聚類數(shù)時,由于k的增大會大幅增加每個簇的聚合程度,故SSE的下降幅度會很大,而當(dāng)k到達(dá)真實聚類數(shù)時,再增加k所得到的聚合程度回報會迅速變小,所以SSE的下降幅度會驟減,然后隨著k值的繼續(xù)增大而趨于平緩,也就是說SSE和k的關(guān)系圖是一個手肘的形狀,而這個肘部對應(yīng)的k值就是數(shù)據(jù)的真實聚類數(shù)

library(factoextra)
#設(shè)置隨機種子,保證試驗結(jié)果復(fù)現(xiàn)  
set.seed(123)  
#確定最佳聚類個數(shù),使用within sum of square 
fviz_nbclust(nutrient.scaled,hcut,method="wss") +geom_vline(xintercept = 5, linetype = 2,color='red')+labs(subtitle = "Elbow method")
# wss stands for within sum of square


當(dāng)多分一類并不能給模型帶來更好的效果時(SSE下降幅度很?。?,便停止分類。因此根據(jù)上圖的轉(zhuǎn)折點,可以發(fā)現(xiàn),從2-3和4-5都能帶來模型的提升,但是從5-6模型的提升很少,因此5應(yīng)該為我們最終使用的k

16.3.2 分類結(jié)果的描述

確定了分類次數(shù)k后,我們需要使用確定的k再次進行分類(此處k=5),然后對不同類別的特征進行描述

在R中,可以使用cutree(fit,k='')來對結(jié)果按指定的k進行重新分類

然后使用聚合函數(shù)aggregate(data.frame,by=list(),func)來對結(jié)果進行展示,并按照聚合函數(shù)結(jié)果描述不同類的特征

clusters <- cutree(fit.average,k=5)  # 把dendrogram分成5類
table(clusters)  # 不同類別中的樣本數(shù)
aggregate(nutrient, by=list(cluster=clusters), median)  # 描述不同類
# 重新繪制dendrogram
plot(fit.average, hang=-1, cex=.8, main="5 Cluster Solution") # hang=-1展示標(biāo)簽
rect.hclust(fit.average, k=5) 

Hierachical Clustering的缺點在于,一旦一個樣本值被分配給一個類,那么后續(xù)的迭代中就不能再將它剔除,而劃分聚類分析則可以克服這個缺點

16.4 劃分聚類

劃分聚類算法最常用的算法是k-means算法,

16.4.1 k-means

K-means算法的基本步驟如下:

  1. 指定k個質(zhì)心,一般是算法隨機指定【k為分類數(shù)目】(如圖:cc1和cc2為指定的質(zhì)心)



  1. 計算每個樣本點到質(zhì)心的距離,每個樣本都被分配到距離其最近的質(zhì)心所在的類

根據(jù)所計算的距離,ABC被分配到cc1,DEFG被分配到cc2



  1. 根據(jù)所在類的所有的樣本值,重新計算該類的質(zhì)心的位置【即重新計算cc1和cc2的位置,cc1 >> cc1' ; cc2>> cc2'】



  1. 根據(jù)計算出的新質(zhì)心,重復(fù)第2,3步,直到達(dá)到最大迭代次數(shù),或質(zhì)心位置變化小于指定閾值且各類樣本不在變化

最后ABCE被分配到cc1'所在的類,DGF被分配到cc2'所在的類


K-means在R語言中kmeans(data,centers=)來完成k-means算法,data參數(shù)表示數(shù)據(jù)集,centers參數(shù)表示要分類的數(shù)目k

根據(jù)業(yè)務(wù)或項目要求,如果有明確的分類數(shù)目k,可以直接使用k-means算法;而如果沒有明確的分類數(shù)目k,一般會使用two-steps clustering,即先使用Hierachical-clustering和SSE找出最優(yōu)分類數(shù)目k后,再使用找出的k進行k-means分類

data(wine, package="rattle")  # 葡萄酒數(shù)據(jù)
head(wine)
df <- scale(wine[-1])  # standardize
set.seed(1234)
fviz_nbclust(df,kmeans,method="wss") +geom_vline(xintercept = 3, linetype = 2,color='red')+labs(subtitle = "Elbow method")

根據(jù)手肘原則,k=3為最佳的分類數(shù)目。確定分類數(shù)目后,使用k_means對指定的k進行分類,并使用聚合函數(shù)aggregate對分類結(jié)果進行描述

16.4.2 分類結(jié)果的描述

set.seed(1234) 
fit.kmeans<-kmeans(df,3)
fit.kmeans$size  # 查看各類的樣本數(shù)
fit.kmeans$centers  # 查看質(zhì)心的值
aggregate(wine[-1], by=list(cluster=fit.kmeans$cluster), mean)  # 聚合函數(shù)描述

# 結(jié)果的部分可視化
plot(df[,c('Alcohol','Malic')],col=fit.kmeans$cluster)
points(fit.kmeans$centers[,c('Alcohol','Malic')],col='purple',pch=8)

一般使用聚類算法,都會使用two-step clustering,由于聚類算法屬于無監(jiān)督學(xué)習(xí),所以并沒有唯一的分類答案,需要根據(jù)具體業(yè)務(wù)和項目來靈活應(yīng)用

參考
[1] Kabacoff, Robert. R 語言實戰(zhàn). Ren min you dian chu ban she, 2016.
[2] https://blog.csdn.net/Anna_datahummingbird/article/details/79912348

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容