聚類分析 百度百科:傳送門
聚類分析指將物理或抽象對象的集合分組為由類似的對象組成的多個類的分析過程
聚類與分類的不同在於,聚類所要求划分的類是未知的
聚類分析是一種探索性的分析,在分類的過程中,人們不必事先給出一個分類的標准,聚類分析能夠從樣本數據出發,自動進行分類。聚類分析所使用方法的不同,常常會得到不同的結論。不同研究者對於同一組數據進行聚類分析,所得到的聚類數未必一致。
IRIS (IRIS數據集) 百度百科:傳送門
Iris數據集是常用的分類實驗數據集,由Fisher, 1936收集整理。Iris也稱鳶尾花卉數據集,是一類多重變量分析的數據集。數據集包含150個數據集,分為3類,每類50個數據,每個數據包含4個屬性。
可通過花萼長度,花萼寬度,花瓣長度,花瓣寬度4個屬性預測鳶尾花卉屬於(Setosa,Versicolour,Virginica)三個種類中的哪一類。
一、k-means聚類

K-means聚類也稱為快速聚類,k-means聚類涉及兩個主要方面的問題。:第一,如何測試樣本的“親疏程度”;第二,如何進行聚類。通常,“親疏程度”的測度有兩個角度:第一,數據間的相似程度;第二,數據間的差異程度。衡量相似程度一般可采用簡單相關系數或等級相關系數,差異程度一般通過某種距離來測度。k-means聚類方法采用第二個測度角度。k-means聚類的基本思想是先將樣本空間分割成隨意的若干類,然后計算所有樣本點到各類中的距離,由於初始聚類結果是在空間隨意分割的基礎上產生的,因此無法確保所給出的聚類解滿足上述要求,所以要經過多次反復。聚類數目確定本身並不簡單,太大或太小都會失去聚類的意義。由於距離是k-means聚類的基礎,因此也要注意:1、當聚類變量值有數量級上的差異時,一般通過標准化處理消除變量的數量級差異。2、聚類變量之間不應該有較強的線性相關關系。

iris2 <- iris iris2$Species <- NULL kmeans.result <- kmeans(iris2, 3) #將聚類結果與species進行比較 table(iris$Species,kmeans.result$cluster) plot(iris2[c("Sepal.Length", "Sepal.Width")], col = kmeans.result$cluster) points(kmeans.result$centers[,c("Sepal.Length", "Sepal.Width")], col = 1:3, pch = 8, cex=2)
數據預處理:從iris數據集中移除species屬性
> iris2 <- iris > iris2$Species <- NULL > kmeans.result <- kmeans(iris2, 3) > #將聚類結果與species進行比較 > table(iris$Species,kmeans.result$cluster) 1 2 3 setosa 0 0 50 versicolor 2 48 0 virginica 36 14 0
繪制所有簇以及簇中心,值得注意的是多次運行得到的k-means聚類結果可能不同,因為初始的簇中心是隨機選擇的
plot(iris2[c("Sepal.Length", "Sepal.Width")], col = kmeans.result$cluster)
points(kmeans.result$centers[,c("Sepal.Length", "Sepal.Width")], col = 1:3, pch = 8, cex=2)
二、k-medoids聚類

k-medoids聚類 又被稱為K-中心點聚類。函數pam()和pamk()都可以進行k-medoids聚類,k-medoids聚類與k-means聚類類似,主要區別是k-means聚類選擇簇中心表示聚類簇,而k-medoids聚類選擇靠近簇中心的對象表示聚類簇,在含有離群點的情況下,k-medoids聚類的魯棒性更好,不像k-means聚類容易受極值影響。

library(fpc) iris2 <- iris iris2$Species <- NULL pamk.result <- pamk(iris2) pamk.result$nc #簇個數 table(pamk.result$pamobject$clustering, iris$Species) plot(iris2[c("Sepal.Length", "Sepal.Width")], col = pamk.result$pamobject$clustering) points(pamk.result$pamobject$medoids[,c("Sepal.Length", "Sepal.Width")], col = 1:3, pch = 8, cex=2) layout(matrix(c(1,2),1,2)) # 每頁兩張圖 plot(pamk.result$pamobject) layout(matrix(1)) #改回每頁一張圖 library(cluster) pam.result <- pam(iris2, 3) table(pam.result$clustering, iris$Species) layout(matrix(c(1,2),1,2)) # 每頁兩張圖 plot(pam.result) layout(matrix(1)) #改回每頁一張圖
數據預處理:從iris數據集中移除species屬性
> library(fpc) > iris2 <- iris > iris2$Species <- NULL > pamk.result <- pamk(iris2) > pamk.result$nc #簇個數 [1] 2 > table(pamk.result$pamobject$clustering, iris$Species) setosa versicolor virginica 1 50 1 0 2 0 49 50
繪制所有簇以及簇中心
plot(iris2[c("Sepal.Length", "Sepal.Width")], col = pamk.result$pamobject$clustering)
points(pamk.result$pamobject$medoids[,c("Sepal.Length", "Sepal.Width")], col = 1:3, pch = 8, cex=2)
圖中可以看到聚類分為兩簇,這是因為pamk()函數會調用pam()函數或clara()函數根據最優平均陰影官渡估計的聚類簇個數來划分數據
layout(matrix(c(1,2),1,2)) # 每頁兩張圖 plot(pamk.result$pamobject) layout(matrix(1)) #改回每頁一張圖
上圖右邊的圖像顯示了兩個簇的陰影,當si的值較大時(接近1)表明相應的觀測點能夠正確的划分到相似性較大的簇中,從上面的例子我們可以看出兩個簇的si均值分別為0.81和0.62.划分結果很好。
接下來使用函數pam(),並設置k=3.
> library(cluster) > pam.result <- pam(iris2, 3) > table(pam.result$clustering, iris$Species) setosa versicolor virginica 1 50 0 0 2 0 48 14 3 0 2 36
layout(matrix(c(1,2),1,2)) # 每頁兩張圖 plot(pam.result) layout(matrix(1)) #改回每頁一張圖
從上面看似乎函數pam()得到的聚類結果更好,因為pam()人工設置識別出三個不同的簇,而pamk()則是利用啟發方法識別簇個數。所以很難說誰好誰壞
三、層次聚類

層次聚類是另一種主要的聚類方法,也被稱為系統聚類,它具有一些十分必要的特性使得它成為廣泛應用的聚類方法。層次聚類的主要思想是:首先每個觀測點自成一類;然后,度量所有的觀測點彼此間的緊密程度,將其中最親密的觀測點聚成一個小類,形成n-1類,接下來再次度量剩余的觀測點和小類間的親密程度,並用當前最親密的觀測點或小類聚成一類;重復上述過程,不斷將觀測點與小類聚成大類。層次聚類也可以理解為生成一系列嵌套的聚類樹來完成聚類。單點聚類處在樹的最底層,在樹的頂層有一個根節點聚類。根節點聚類覆蓋了全部的所有數據點。首先,我們隨機抽取一個40條記錄的樣本,與之前相同,從數據樣本中剔除species屬性。

idx <- sample(1:dim(iris)[1], 40) irisSample <- iris[idx,] irisSample$Species <- NULL hc <- hclust(dist(irisSample), method="ave") plot(hc, hang = -1, labels=iris$Species[idx]) rect.hclust(hc, k=3) groups <- cutree(hc, k=3)
數據預處理:隨機抽取一個40條記錄的樣本,與之前相同,從數據樣本中剔除species屬性
idx <- sample(1:dim(iris)[1], 40) irisSample <- iris[idx,] irisSample$Species <- NULL hc <- hclust(dist(irisSample), method="ave") plot(hc, hang = -1, labels=iris$Species[idx])
使修剪樹使之分為3類
rect.hclust(hc, k=3)
groups <- cutree(hc, k=3)
修剪樹使之分為3類