k(均值)聚類屬於扁平聚類演算法,即進行一層劃分得到k個簇,與層次聚類演算法開始不需要決定簇數不同,k均值聚類需要使用者事先確定好簇個數,因為構建一顆聚類樹是非常耗時的事情,所以k均值聚類演算法的效率要優於層次聚類。

一、資料準備

> data(nutrient,package = “flexclust”)

> str(nutrient)

‘data。frame’: 27 obs。 of 5 variables:

$ energy : int 340 245 420 375 180 115 170 160 265 300 。。。

$ protein: int 20 21 15 19 22 20 25 26 20 18 。。。

$ fat : int 28 17 39 32 10 3 7 5 20 25 。。。

$ calcium: int 9 9 7 9 17 8 12 14 9 9 。。。

$ iron : num 2。6 2。7 2 2。6 3。7 1。4 1。5 5。9 2。6 2。3 。。。

> nutrient1<-scale(nutrient[,-1])

二、(1)使用kmeans方法聚類nutrient1資料集;

> fit<-kmeans(nutrient1,5)

> fit

K-means clustering with 5 clusters of sizes 10, 2, 3, 6, 6

Cluster means:

protein fat calcium iron

1 -0。02352002 1。1298286 -0。4531723 0。06057497

2 -2。35200232 -1。1087718 0。4361807 2。27092763

3 -0。15680015 -0。5165495 2。3541419 -0。48916187

4 1。17600116 -0。6201884 -0。2280575 0。37764310

5 -0。27440027 -0。6349940 -0。3391198 -0。99099632

Clustering vector:

BEEF BRAISED HAMBURGER BEEF ROAST BEEF STEAK

1 1 1 1

BEEF CANNED CHICKEN BROILED CHICKEN CANNED BEEF HEART

4 5 4 4

LAMB LEG ROAST LAMB SHOULDER ROAST SMOKED HAM PORK ROAST

1 1 1 1

PORK SIMMERED BEEF TONGUE VEAL CUTLET BLUEFISH BAKED

1 1 4 5

CLAMS RAW CLAMS CANNED CRABMEAT CANNED HADDOCK FRIED

2 2 5 5

MACKEREL BROILED MACKEREL CANNED PERCH FRIED SALMON CANNED

5 3 5 3

SARDINES CANNED TUNA CANNED SHRIMP CANNED

3 4 4

Within cluster sum of squares by cluster:

[1] 5。4900775 0。5321011 6。7811219 8。9407403 3。7326705

(between_SS / total_SS = 75。5 %)

Available components:

[1] “cluster” “centers” “totss” “withinss” “tot。withinss”

[6] “betweenss” “size” “iter” “ifault”

(2)呼叫barplot函式繪製每個簇中心的條形圖:

> barplot(t(fit$centers),beside = T,xlab = “cluster”,ylab=“value”)

R語言聚類之—kmeans聚類

R語言聚類之—kmeans聚類

(3)還可以繪製簇的散點圖,對於屬於不同的觀測點使用不同的顏色

> plot(nutrient1,col=fit$cluster)

R語言聚類之—kmeans聚類

R語言聚類之—kmeans聚類

(4)使用ggfortify包進行聚類結果的視覺化展示

> library(ggfortify)

> library(ggplot2)

> autoplot(kmeans(nutrient1, 5),data=nutrient1,label=TRUE, label。size=3, frame=TRUE)

R語言聚類之—kmeans聚類

R語言聚類之—kmeans聚類

三、原理

k均值聚類屬於分裂聚類,演算法目標透過將n個物件劃分到k個簇中,使得同一個簇中的物件之間的距離最近,演算法的目的是使組內平方和(Within—Cluster Sum of Squares,WCSS)最小。假設x是一組給定觀測點,s={s1,s2,‘’‘,sk}代表k個劃分,ui是si的中心,wcss公式定義

R語言聚類之—kmeans聚類

R語言聚類之—kmeans聚類

k均值聚類過程分如下五步

(1)指定聚類個數

(2)隨機產生k個劃分

(3)計算每個劃分的中心

(4)將觀測點分配到距離簇中心最近的一個簇中

(5)重複(2)(3)(4)知道wcss基本不發生變化(或最小化)

讀者還可以在k均值聚類演算法中規定具體的聚類方法,如Hartigan—Wong,Lloyd,Forgy,MacQueen

四、擴充套件—獲得最佳化的k

1、準備

為了找到最優的簇個數,讀者需要準備好前述提及的nutrient1資料集

2、操作

執行以下操作為k均值演算法找到最合適的聚類個數。

(1)首先,計算每個簇的距離平方和(withinss)

> nk=2:10

> set。seed(22)

> Wss<-sapply(nk,function(k){

+ kmeans(nutrient1,centers = k)$tot。withinss

+ })

> Wss

[1] 80。107407 56。593182 40。543422 24。155897 22。989831 14。480686 9。669921 10。105902

[9] 7。498038

(2)呼叫plot繪製不同k值下距離平方和的線圖

> plot(nk,Wss,type = “l”,xlab=“number of k”,ylab=“within sum of squares”)

R語言聚類之—kmeans聚類

R語言聚類之—kmeans聚類

(3)計算不同聚類結果的平均輪廓值(avg。silwidth)

> library(fpc)

> sw=sapply(nk,function(k){

+ cluster。stats(dist(nutrient1),kmeans(nutrient1,centers = k)$cluster)$avg。silwidth

+ })

> sw

[1] 0。4755391 0。3022866 0。3736633 0。4061053 0。3962927 0。3534240 0。3284742 0。4001432

[9] 0。4039906

(4)使用線圖繪製不同k值的平均輪廓值

> plot(nk,sw,type = “l”,xlab=“number of clusters”,ylab = “average silhouette width”)

R語言聚類之—kmeans聚類

R語言聚類之—kmeans聚類

(5)得到最大的簇個數

> nk[which。max(sw)]

[1] 2

所以聚類簇個數為2時最好。