K-mean

這是我對k-means的一些想法

若有錯誤請指正謝謝,這裡拿R內建資料集iris做舉例

在所有分群演算法中,最基本的方法就是k-means分割式分群法

k-mean需要先設定集群的數量,根據該設定找出最佳的集群結構,在大量的資料中,目的為找出群中心

使得同一集群內的物件相似性最大且集群間的差異性最大,即「群內同質,群間異質」的效果

使用scale正規化是為了避免單位對數值的影響

首先取出數值資料,觀察花萼與花瓣的關係

library(ggplot2)
## Warning: package 'ggplot2' was built under R version 3.3.2
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(useful)
iris2 <- iris[,sapply(iris, is.numeric)]
iris2 <- scale(iris2)

設定集群數量

因為資料集的種類是3種,所以先試著取3群,看kmeans的結果與資料集本身的差異

相關細節

顯示群數、每一行的群組平均數、每一列的群別和相似度

1.between_SS / total_SS:群之間的距離平方占總體距離平方差的比率,愈大分群效果愈好,但並不表示愈容易看出資料趨勢,筆者取過10群的比率為95.2%,但是分成10群呈現在資料上反而看不出趨勢,所以如何取群數還需要研究

2.cluster:表示每個點所在的群

3.centers:每個群的群中心

4.totss:各個點的離差平方和

5.withinss:每個單一群內部的離差平方和

6.tot.withinss:所有單一群內的離差平方和的總和

7.betweenss:各個群之間的離差平方和

8.size:每個群的點個數

分成3群,重複輸出kmeans函數,會發現每次的between_SS / total_SS都不同

這是因為每次取3群kmean都需要重新分群,不同的群當然有不同的距離,多重複輸出幾次,會發現between_SS / total_SS愈來愈高,到一定比率就上不去了,就顯示出分3群的極限

kiris2 <- kmeans(iris2, 3)
kiris2
## K-means clustering with 3 clusters of sizes 96, 33, 21
## 
## Cluster means:
##   Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1    0.5690971  -0.3705265    0.6888118   0.6609378
## 2   -0.8135055   1.3145538   -1.2825372  -1.2156393
## 3   -1.3232208  -0.3718921   -1.1334386  -1.1111395
## 
## Clustering vector:
##   [1] 2 3 3 3 2 2 2 2 3 3 2 2 3 3 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 3 3 2 2 2 3
##  [36] 3 2 2 3 2 2 3 3 2 2 3 2 3 2 2 1 1 1 1 1 1 1 3 1 1 3 1 1 1 1 1 1 1 1 1
##  [71] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1 1 3 1 1 1 1 1 1
## [106] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [141] 1 1 1 1 1 1 1 1 1 1
## 
## Within cluster sum of squares by cluster:
## [1] 149.25899  17.33362  23.15862
##  (between_SS / total_SS =  68.2 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"    
## [5] "tot.withinss" "betweenss"    "size"         "iter"        
## [9] "ifault"
plot(kiris2, data = iris2)

畫出資料本身的圖

根據資料本身種類用不同的標記,與上圖作比較,若顏色與形狀容易同時區別出來,表示分群效果不錯

plot(kiris2, data = iris, class = "Species")

群數

上述群數的選擇是以資料本身種類為主,三種分成三群也是合乎常理的,但是有沒有可能有更有效的分群呢?這其實很主觀,因為群數的不同會導致群間距離差平方和的不同,群數與距離間沒有正反比或是規律性,只能找出一個平穩狀態,這裡介紹2種方法來評估群數

1.計算每個群的SSE找出平穩狀態

看出如果依照iris種類分3群的分群效果,效果挺差的,還能分成更多群,差不多到8就開始穩定了,此種方法是計算群內點之間的距離差平方和,然後觀察曲線的跌幅狀態。

x <- (nrow(iris2)-1) * sum(apply(iris2, 2, var))
for (i in 2:15) x[i] <- kmeans(iris2,centers = i)$tot.withinss
plot(x, type = "b",xlab = "Number of clusters")

2.Hartigan Theorem

此種方法是計算k個分群群內平方和與k+1個分群群內平方和的比率,把列數和群數考慮在內,比率大於10表示使用k+1個群比較好,每次執行結果都略有不同,群數大概落在7~9之間。

Hart <- FitKMeans(iris2, max.clusters = 15)
Hart
##    Clusters  Hartigan AddCluster
## 1         2 251.34934       TRUE
## 2         3  86.77954       TRUE
## 3         4  32.42265       TRUE
## 4         5  15.16734       TRUE
## 5         6  12.35587       TRUE
## 6         7  29.72566       TRUE
## 7         8  21.80205       TRUE
## 8         9  15.04763       TRUE
## 9        10  17.33698       TRUE
## 10       11  30.79675       TRUE
## 11       12 -50.14120      FALSE
## 12       13  74.97302       TRUE
## 13       14  31.52879       TRUE
## 14       15 -10.65285      FALSE
PlotHartigan(Hart)

3個分群

畫出混淆矩陣判斷分群效果,好的分群應使圖中的對角線應該都佔有最大一比例

x <- table(iris$Species, kiris2$cluster)
plot(x,main = "Confusion Matrix",xlab = "Species",ylab = "Clusters")