不同于分類和回歸,聚類不需要事先的任何參考分類信息,可以簡單地通過判斷數(shù)據(jù)特征的相似性來完成對數(shù)據(jù)的歸類。
- 層次聚類
不需要事先指定族的個數(shù),以系統(tǒng)樹的形式展現(xiàn)。 - k均值聚類
扁平聚類,不會生成聚類層次,需要事先確定族的個數(shù),性能優(yōu)于層次聚類。 - 基于模型的聚類
以上兩種是啟發(fā)式聚類,不需要任何形式化的模型,而基于模型的則事先假定存在某個數(shù)據(jù)模型,并用EM算法試圖求出最相近的模型參數(shù)和簇的個數(shù)。 - 基于密度的聚類
將分布稠密的樣本劃分到同一個簇,并過濾低密度的區(qū)域。
下面一一看下四種算法,并采用基于簇間距離平方和志平均側(cè)影寬度進行聚類內(nèi)部驗證,通過Ground truth方法完成聚類的外部驗證。
9.2 通過層次聚類處理數(shù)據(jù)
可以分成自底向上的凝聚(agglomerative)和自頂向下的分裂(divise)兩種。首先都要通過距離相似性來判斷對數(shù)據(jù)合并還是分裂處理。整個算法遞歸過程一直到全部歸并到一個簇或不可再分為止,最后系統(tǒng)樹圖展現(xiàn)聚類層次結(jié)構(gòu)。
# data
wget https://github.com/ywchiu/ml_R_cookbook/raw/master/CH9/customer.csv
# 只有60行,復(fù)制在這
ID,Visit.Time,Average.Expense,Sex,Age
1,3,5.7,0,10
2,5,14.5,0,27
3,16,33.5,0,32
4,5,15.9,0,30
5,16,24.9,0,23
6,3,12,0,15
7,12,28.5,0,33
8,14,18.8,0,27
9,6,23.8,0,16
10,3,5.3,0,11
11,4,8.6,0,13
12,14,21,0,25
13,12,28.5,0,33
14,7,16.1,0,16
15,4,17.4,0,9
16,6,4.6,0,21
17,14,23.6,0,22
18,8,15.9,0,19
19,17,25.9,0,18
20,8,20.4,1,39
21,7,10.9,1,17
22,14,33.7,1,17
23,3,5.6,1,12
24,18,21.1,1,26
25,12,30,1,28
26,3,4.8,1,12
27,6,9.1,1,11
28,9,29.4,1,32
29,5,10.2,1,17
30,1,4.5,1,8
31,10,10.9,1,17
32,12,25.4,1,27
33,13,25.5,1,36
34,13,20.1,1,26
35,1,4.5,1,8
36,4,11,1,12
37,10,27.6,1,41
38,4,12,1,23
39,7,10.6,1,15
40,7,10.9,1,17
41,3,8.3,1,8
42,7,16.1,1,16
43,7,11.5,1,19
44,9,15.6,1,21
45,11,24.9,1,25
46,9,29.4,1,32
47,6,23.8,1,16
48,5,14.9,1,17
49,7,15.1,1,21
50,18,21.1,1,26
51,3,5.3,1,11
52,10,17.8,1,29
53,15,27.9,1,23
54,8,12,1,22
55,9,19,1,20
56,3,7.2,1,15
57,13,25.2,1,47
58,8,11.3,1,22
59,6,8.1,1,10
60,11,26.3,1,45
# ###########聚類
customer <- read.csv('customer.csv', header = TRUE)
head(customer)
str(customer)
# 歸一化
customer <- scale(customer[,-1])
# 自底向上
hc <- hclust(dist(customer, method = "euclidean"), method = "ward.D2");hc
Call:
hclust(d = dist(customer, method = "euclidean"), method = "ward.D2")
Cluster method : ward.D2
Distance : euclidean
Number of objects: 60
plot(hc, hang = 0.01, cex=0.7)


距離有最短距離、最長距離(complete linkage)、平均距離和最小方差法。
拓展


9.3 將樹分成簇
# 簇
fit <- cutree(hc,k=4)
fit
[1] 1 1 2 1 2 1 2 2 1 1 1 2 2 1 1 1 2 1 2 3 4 3 4 3 3 4 4 3 4 4 4 3 3 3 4
[36] 4 3 4 4 4 4 4 4 4 3 3 4 4 4 3 4 3 3 4 4 4 3 4 4 3
table(fit)
fit
1 2 3 4
11 8 16 25
plot(hc)
rect.hclust(hc,k=4, border = "red")
plot(fit)


除了指定cutree函數(shù)中的簇個數(shù),還可以通過設(shè)置height值來指定聚類樹的高度,達到切割樹的目的。
拓展
# 單獨標(biāo)記某簇
plot(hc)
rect.hclust(hc,k=4,which =2,border = "red")
# 不同顏色不同簇 dendextend包
dend %>% color_branches(k=4) %>% plot(horiz=TRUE, main="Horizontal Dendrogram")
# 加紅框
dend %>% rect.dendrogram(k=4, horiz = TRUE)



9.4 使用k均值法處理數(shù)據(jù)
扁平聚類,一層劃分得到k簇,需要先確定簇個數(shù),效率優(yōu)于層次聚類。
# knn
set.seed(22)
fit <- kmeans(customer,4)
fit
# 簇中心條形圖
barplot(t(fit$centers),beside = TRUE, xlab = "cluster", ylab = "value")
# 簇散點圖
plot(customer, col=fit$cluster)


分裂聚類,目的是使組內(nèi)平方和最小。還可以規(guī)定具體的聚類方法,如Hatigan-Wong, Lloyd, Forgy以及MacQueen。
9.5 繪制二元聚類圖
二元聚類將變量減少為兩個主要成分,再利用組件(軸線和橢圓)展示數(shù)據(jù)聚類的結(jié)果。
# 二元聚類
library(cluster)
clusplot(customer, fit$cluster, color = TRUE, shade = TRUE)
# 標(biāo)記并放大
par(mfrow=c(1,2))
clusplot(customer, fit$cluster, color = TRUE, shade = TRUE)
rect(0.5,-1.15,3,-0.4,border = "orange", lwd = 2)
clusplot(customer, fit$cluster, color = TRUE, xlim = c(0.5,3),
ylim = c(-1.15,-0.4))


拓展
clusplot使用了princomp和cmdscale兩個函數(shù)降維操作得到主成分
# cmdscale
par(mfrow=c(1,1))
mds <- cmdscale(dist(customer), k=2)
plot(mds,col=fit$cluster)

9.6 聚類算法比較
可以使用簇內(nèi)距離或者簇間距離作為評判標(biāo)準(zhǔn),fpc包的cluster.stat函數(shù)
# 算法比較
install.packages("fpc")
library(fpc)
single_c <- hclust(dist(customer), method = "single") #層次聚類 最短距離法
hc_single <- cutree(single_c, k=4)
# 層次聚類 最長距離法
complete_c <- hclust(dist(customer), method = "complete")
hc_complete <- cutree(complete_c, k=4)
set.seed(22)
# km均值
km <- kmeans(customer,4)
# 基本統(tǒng)計
cs <- cluster.stats(dist(customer), km$cluster)
cs[c('within.cluster.ss', 'avg.silwidth')]
# 列表顯示
sapply(list(kmeans=km$cluster, hc_single =hc_single, hc_complete=hc_complete),
function(c) cluster.stats(dist(customer), c)[c('within.cluster.ss', 'avg.silwidth')])
kmeans hc_single hc_complete
within.cluster.ss 61.3489 136.0092 65.94076 #距離平方和,同一簇之間對象相關(guān)性,越小相關(guān)性越大
avg.silwidth 0.4640587 0.2481926 0.4255961 # 平均輪廓值,既考慮簇內(nèi)聚合又考慮簇間分離度
最長距離層次聚類優(yōu)于最短距離層次聚類和km算法。如下也可以輸出聚類統(tǒng)計信息:
km$withinss
[1] 20.89159 5.90040 22.58236 11.97454
km$betweenss
[1] 174.6511
9.7 從簇中抽取輪廓
輪廓系數(shù)取值0-1,越接近于1,聚類效果越好。
# 輪廓
kms <- silhouette(km$cluster, dist(customer))
summary(kms)
Silhouette of 60 units in 4 clusters from silhouette.default(x = km$cluster, dist = dist(customer)) :
Cluster sizes and average silhouette widths:
25 8 16 11
0.5164434 0.5464597 0.3794910 0.4080823
Individual silhouette widths:
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.1931 0.4030 0.4890 0.4641 0.5422 0.6333
plot(kms)

9.8 獲得優(yōu)化的k均值聚類
k均值算法效率高也易于實現(xiàn),可以使用距離平方和來確定哪個k值能實現(xiàn)最好的效果。
# 優(yōu)化km聚類
nk<- 2:10
set.seed(22)
# 每個簇距離平方和
WSS <- sapply(nk, function(k){
kmeans(customer, centers = k)$tot.withinss
})
WSS
plot(nk,WSS,type = "l", xlab = "no. of k", ylab = "within sum of squares")
# 平均輪廓
SW<- sapply(nk, function(k){
cluster.stats(dist(customer), kmeans(customer,centers = k)$cluster)$avg.silwidth
})
SW
plot(nk,SW, type = "l",xlab = "no. of k", ylab = "average ailhouette width")
nk[which.max(SW)]
[1] 4


9.9 使用密度聚類方法處理數(shù)據(jù)
將分布稠密和稀疏的樣本分開,DBSCAN是最著名的算法。
# 密度聚類
install.packages("mlbench")
library(mlbench)
install.packages("fpc")
library(fpc)
set.seed(2)
p <- mlbench.cassini(500)
plot(p$x)
ds <- dbscan(dist(p$x), 0.2,2,countmode=NULL,method="dist");ds # 可達距離0.2,最小可達點個數(shù)2,計算進度NULL,距離矩陣作為計算依據(jù)
dbscan Pts=500 MinPts=2 eps=0.2
1 2 3
seed 200 200 100
total 200 200 100
plot(ds,p$x)
#預(yù)測
y<- matrix(0,nrow = 3, ncol = 2)
y[1,] <- c(0,0)
y[2,] <- c(0,-1.5)
y[3,] <- c(1,1)
y
[,1] [,2]
[1,] 0 0.0
[2,] 0 -1.5
[3,] 1 1.0
#預(yù)測
y<- matrix(0,nrow = 3, ncol = 2)
y[1,] <- c(0,0)
y[2,] <- c(0,-1.5)
y[3,] <- c(1,1)
y
predict(ds,p$x,y)
[1] 3 1 2


兩個參數(shù)eps和MinPts,分別是最大鄰域半徑和鄰域半徑范圍內(nèi)的最小點數(shù)??梢哉{(diào)用fpc::plotcluster函數(shù)生成一個判別投影圖
9.10 基于模型的聚類方法
# ########模型
install.packages("mclust")
library(mclust)
mb <- Mclust(customer)
par(mfrow=c(1,1))
plot(mb)
summary(mb)
----------------------------------------------------
Gaussian finite mixture model fitted by EM algorithm
----------------------------------------------------
Mclust VII (spherical, varying volume) model with 5 components:
log-likelihood n df BIC ICL
-220.7207 60 29 -560.1775 -561.8828
Clustering table:
1 2 3 4 5
11 8 17 17 7




基于概率的方法,而不啟發(fā)式構(gòu)建簇,假設(shè)服從某未知分布,并試圖找出這個分布,有限混合模型是一類常見的模型,單個模型分配線性權(quán)重再組合得到結(jié)果模型,提供一個靈活模型框架解釋數(shù)據(jù)分布概率。步驟是首先確定模型數(shù)量及概率分布類型,然后構(gòu)建并計算每個模型后驗概率,最后分配到概率最大類別。BIC用于選擇簇的個數(shù)。簇個數(shù)為5.
相異度矩陣的可視化
用來評估聚類的質(zhì)量,熱力圖可以實現(xiàn),相似的顏色深,如對角線。
# 相異度矩陣的可視化
install.packages("seriation")
library(seriation)
dissplot(dist(customer), labels = km$cluster,
options = list(main="Kmeans Clustering With K=4"))
dissplot(dist(customer), labels = hc_complete,
options = list(main="Hierachical Clustering ") )


拓展
dist和image也可以實現(xiàn)
image(as.matrix(dist(customer)))
heapmap當(dāng)然也可以
heatmap(customer,Rowv = as.dendrogram(hclust(t(dist(customer)))), Colv = as.dendrogram(hclust(dist(t(customer)))))

9.12 外部驗證評估
# 外部驗證
install.packages("png")
library(png)
img2 <- readPNG('handwriting.png',TRUE)
img3 <- img2[,nrow(img2):1]
b <- cbind(as.integer(which(img3 < -1) %% 28), which(img3 < -1)/28)
plot(b,xlim = c(1,28), ylim = c(1,28))
# km
set.seed(18)
fit <- kmeans(b,2)
plot(b,col=fit$cluster,xlim = c(1,28), ylim = c(1,28))
# dbscan
ds <- dbscan(b,2)
ds
plot(ds,xlim = c(1,28), ylim = c(1,28))



這里部分理解了計算機處理圖像的方式。