《R語言實戰》第四部分第十六章-聚類分析學習筆記
5月初帶病出了一趟差,舟車勞頓,回來以後咳嗽不止,修整了一段時間,這才緩過勁來,這方面的學習也因此耽誤了幾天,接下去要抓緊補回來了。
聚類分析是一種無約束的資料分析方法,其目的在於揭露一個數據集當中觀測值的子集,透過合適的演算法,它可以把大量的觀測值歸為若干個類。類為若干個觀測值組成的群組,組內的觀測值比起組外的觀測值相似度更高,由於定義不精確,因此各種聚類方法也很多。
目前比較常用的兩種聚類方法是層次聚類(hierarchical agglomerative clustering)和劃分聚類(partitioning clustering)。對於層次聚類,比較常用的演算法是:
單聯動(single linkage)
全聯動(complete linkage )
平均聯動(average linkage)
質心(centroid)
Ward方法
對於劃分聚類,最常用的演算法是K均值(K-means)和圍繞中心點的劃分(PAM)。
本章主要對flexclust包中的營養資料集nutrient作層次聚類,在此之前,對聚類分析的一般步驟進行描述。
1 聚類分析的一般步驟
選擇合適的變數,這是第一步,也可能是最重要的一步,再高階的聚類方法也不能彌補聚類變數選擇不好的問題。因此,首先選擇你感覺可能對於識別和理解資料中不同觀測值分組有重要影響的變數。
縮放資料,由於不同變數可能有不同的變化範圍,以免那些變化範圍大的變數對結果有不成比例的影響,常常需要在分析之前縮放資料。通常,將每個變數標準化為均值為0和標準差為1的變數。還有另外兩種替代方法,比如每個變數被其最大值相除,或該變數減去它的平均值併除以變數的平均絕對偏差。實現程式碼如下:
df1
<-
apply
(
mydata
,
2
,
function
(
x
){(
x
-
mean
(
x
))
/
sd
(
x
)})
df2
<-
apply
(
mydata
,
2
,
function
(
x
){
x
/
max
(
x
)})
df3
<-
apply
(
mydata
,
2
,
function
(
x
){(
x
–
mean
(
x
))
/
mad
(
x
)})
在R中可以透過使用scale()函式實現df1程式碼片段的功能。
尋找異常點,通常聚類方法對於異常值比較敏感,對此有幾種解決方法,透過outliers包中的函式來篩選異常單變數離群點,mvoutlier包中 有識別多元變數的離群點的函式。
計算距離,雖然不同的聚類演算法差異很大,但是通常需要計算被聚類的實體之間的距離。兩個觀測之間最常用的距離度量是歐幾里得距離,其它常用的還有曼哈頓距離、蘭氏距離、非對稱二元距離、最大距離和閔可夫斯基距離。在下文的論述當中預設採用歐幾里得距離。
選擇聚類演算法,對於不同型別和不同樣本量的資料,針對性地選擇不同的聚類演算法,從大的方面講有層次聚類和劃分聚類,通常前者對於小樣本來說很實用(如150個觀測值或更少),而且這種情況下巢狀聚類更實用;後者能夠處理更大的資料量,但是需要事先確定聚類的個數。然後,不管是層次聚類還是劃分聚類,都需要一個特定的聚類演算法,不同演算法有著各自的優缺點,需要根據工程實踐進行綜合比選確定。
獲得一種或多種聚類方法,這是步驟5的延續。
確定類的數目,在確定最終聚類方案時必須確定類的數目。通常嘗試不同的型別(比如2~K)並比較解的質量。NbClust包中的NbClust()函式30個不同的指標來幫助你進行選擇,指標如此之多,可見這在聚類分析當中是個難題。
獲得最終的聚類解決方案,類的個數確定以後,就可以提取出子群,形成最終的聚類方案。
結果視覺化,視覺化可以幫助判定聚類方案的意義和用處,層次聚類的結果通常表示為一個樹狀圖。劃分的結果通常利用視覺化雙變數聚類圖來表示。
解讀類,聚類方案確定以後,結果也出來了,必須對其進行解讀。比如,一個類中的觀測值有何相似之處,不同類之間有何不同,這一步通常透過獲得類中每個變數的彙總統計來完成。對於連續資料,每一類中變數的均值和中位數會被計算出來。對於混合資料(資料中包含分類變數),結果中將返回各類的眾數或類別分佈。
驗證結果,對於聚類方案的驗證相當於確認下,如果採用不同的聚類方法或者不同樣本,是否會產生相同的類。fpc、clv和clValid包包含了評估聚類解的穩定性的函式。
2 計算距離
兩個觀測值之間的歐幾里得距離定義如下:
以flexclust包中的營養資料集為例,它包含對27中肉、魚和禽的營養物質的測量。以下程式碼給出了最初的幾個觀測值:
>
install。packages
(
‘flexclust’
)
>
library
(
flexclust
)
載入需要的程輯包:
grid
載入需要的程輯包:
lattice
載入需要的程輯包:
modeltools
載入需要的程輯包:
stats4
>
data
(
nutrient
,
package
=
“flexclust”
)
>
head
(
nutrient
,
4
)
energy
protein
fat
calcium
iron
BEEF
BRAISED
340
20
28
9
2。6
HAMBURGER
245
21
17
9
2。7
BEEF
ROAST
420
15
39
7
2。0
BEEF
STEAK
375
19
32
9
2。6
>
則前兩個觀測值(BEEF BRAISED和HAMBURGER)之間的歐幾里得距離為:
用R中自帶的dist()函式可以計算矩陣或資料框中所有行(觀測值)之間的距離,程式碼如下:
>
d
<-
dist
(
nutrient
)
>
as。matrix
(
d
)
[1
:
4
,
1
:
4
]
BEEF
BRAISED
HAMBURGER
BEEF
ROAST
BEEF
STEAK
BEEF
BRAISED
0。00000
95。6400
80。93429
35。24202
HAMBURGER
95。64000
0。0000
176。49218
130。87784
BEEF
ROAST
80。93429
176。4922
0。00000
45。76418
BEEF
STEAK
35。24202
130。8778
45。76418
0。00000
>
dist()函式的格式為dist(x, method =),預設為歐幾里得距離。
觀測值之間的距離越大,則異質性越大,距離也越遠。
通常,歐幾里得距離作為連續型資料的距離度量,對於其它型別的資料,可以使用cluster包中的daisy()函式獲得包含任意二元、名義、有序或者連續屬性組合的相異矩陣,並且cluster包中的其它函式可以用這種異質性進行聚類分析。
另外,當一個觀測中的某一個變數變換範圍太大,縮放資料有利於均衡各變數的影響。
3 層次聚類分析
層次聚類的演算法如下:
定義每一個觀測值(行或單元)為一類;
計算每類和其他各類的距離;
把距離最短的兩類合併成一類,減少一個類的個數;
重複步驟2和3,直到包含所有觀測值的類合併成單個類為止。
不同的層次聚類演算法主要區別在於它們對類的定義不同,常見的五種聚類方法及其距離定義如下:
層次聚類方法的實現格式如下:
hclust
(
d
,
method
=
)
其中d是透過dist() 函式產生的距離矩陣, 並且方法包括 “single” 、“complete” 、“average” 、“centroid”和“ward”。
以nutrient營養資料集為例,平均聯動聚類程式碼如下:
#載入資料
>
data
(
nutrient
,
package
=
“flexclust”
)
#將行名改為小寫
>
row。names
(
nutrient
)
<-
tolower
(
row。names
(
nutrient
))
#將變數標準化
>
nutrient。scaled
<-
scale
(
nutrient
)
#計算距離
>
d
<-
dist
(
nutrient。scaled
)
#採用平均聯動
>
fit。average
<-
hclust
(
d
,
method
=
“average”
)
#結果視覺化
>
plot
(
fit。average
,
hang
=
-1
,
cex
=
。8
,
main
=
“Average Linkage Clustering”
)
>
上圖提供了27種食物之間的相似性/相異性的層次分析試圖,我們可以達到理解基於食物營養成分的相似性和相異性的目的。不過,如果最終目標是將這些食品分類,我們需要進一步地分析。
NbClust包提供了眾多的指數來確定在一個聚類分析裡面類的最佳數目,結果各有不同,可以用來作為選擇聚類個數K值得一個參考。
程式碼如下:
> library(NbClust)
> devAskNewPage(ask = TRUE)
> nc <- NbClust(nutrient。scaled, distance = “euclidean”,
+ min。nc = 2, max。nc = 15, method = “average”)
> table(nc$Best。nc[1,])
0 1 2 3 4 5 9 10 13 14 15
2 1 4 4 2 4 1 1 2 1 4
> barplot(table(nc$Best。nc[1,]),
+ xlab = “Number of Clusters”, ylab = “Number of Criteria”,
+ main = “Number of Clusters Chosen by 26 Criteria”)
從上圖可知,對於投票個數最多的聚類個數為2、3、5和15,下面的程式碼展示了五類聚類的方案。
#將樹狀圖分成五類
>
clusters
<-
cutree
(
fit。average
,
k
=
5
)
#顯示各類的觀測值
>
table
(
clusters
)
clusters
1
2
3
4
5
7
16
1
2
1
#獲取每類的中位數
>
aggregate
(
nutrient
,
by
=
list
(
cluster
=
clusters
),
median
)
cluster
energy
protein
fat
calcium
iron
1
1
340。0
19
29
9
2。50
2
2
170。0
20
8
13
1。45
3
3
160。0
26
5
14
5。90
4
4
57。5
9
1
78
5。70
5
5
180。0
22
9
367
2。50
>
aggregate
(
as。data。frame
(
nutrient。scaled
),
by
=
list
(
cluster
=
clusters
),
median
)
cluster
energy
protein
fat
calcium
iron
1
1
1。3101024
0。0000000
1。3785620
-0。4480464
0。08110456
2
2
-0。3696099
0。2352002
-0。4869384
-0。3967868
-0。63743114
3
3
-0。4684165
1。6464016
-0。7534384
-0。3839719
2。40779157
4
4
-1。4811842
-2。3520023
-1。1087718
0。4361807
2。27092763
5
5
-0。2708033
0。7056007
-0。3981050
4。1396825
0。08110456
>
plot
(
fit。average
,
hang
=
-1
,
cex
=
。8
,
+
main
=
“Average Linkage Clustering\n5 Cluster Solution”
)
#疊加五類的解決方案
>
rect。hclust
(
fit。average
,
k
=
5
)
從上圖可知,sardines canned單獨成類,beef heart也單獨成類,最大的類(從mackerel canned到bluefish baked)都含有相對較低的鐵。
層次聚類在小樣本當中,特別是需要巢狀聚類和有意義的層次結構時,特別有用。而面對大樣本時,則劃分聚類做得更好。
4 劃分聚類分析
劃分聚類當中,觀測值被分為K組並根據給定的規則改組成最有粘性的類。本節主要討論兩種方法:K均值和基於中心點的劃分(PAM)。
4。1 K均值聚類
比較常見的劃分聚類是K均值聚類,K-mean演算法比較經典,具體可以參考以下相關連結:
K-Means 演算法 | | 酷 殼 - CoolShell
k-means | 資料探勘十大演算法詳解
K-平均演算法
演算法的簡單描述如下:
選擇K箇中心點(隨機選擇K行);
把每個資料點分配到離它最近的中心點;
重新計算每類中的點到該類中心點距離的平均值;
分配每個資料到它最近的中心點;
重複步驟3和步驟4,直到所有的觀測值不再被分配或是達到最大的迭代次數。
上述演算法的實施細節會有所不同,R中所才有的有效演算法是把觀測值分成k組並使得觀測值到其指定的聚類中心的平方的總和為最小。即每個觀測值被分配到使下式得到最小值的那一類當中:
其中:
表示第i個觀測值中第j個變數的值;
表示第k個類中第j個變數的均值,其中p是變數的個數。
K均值聚類可以處理更大的資料集,並且觀測值不會永遠地被分到一類當中。不過它的使用要求所有的變數必須是連續的,並且需要提前確定類的數目,通常也很容易受異常值的影響。
R中K均值聚類分析呼叫格式如下:
kmeans
(
x
,
centers
)
其中:
x表示數值資料集,可以是矩陣或者資料框;
centers是要提取的聚類數目。
該函式返回的資料較多,主要有類的成員、類中心、平方和(類內平方和、類間平方和、總平方和)和類大小。
考慮到K均值聚類在開始時就是隨機選擇k箇中心點,因此在每次呼叫函式時可能獲得不同的方案。當然,使用set。seed()函式可以保證結果的可複製的。
另外,從演算法上可以看出,初始中心值的選擇對於結果也非常敏感,kmeans()函式有一個nstart選項可以嘗試多種初始配置並輸出最好的一個結果。舉個例子,加上nstart=25會生成25個初始配置,一般來說,我們推薦使用這種方法。
前面已經提到過,不同於層次聚類,K均值聚類要求你事先確定要提取的聚類個數,並在初始化的時候就給出來。R中的NbClust包同樣可以用來作為確定聚類個數的參考。基於K均值聚類的特殊性,類中總的平方值對聚類數量的曲線可能是有參考意義的。可根據圖中的彎曲選擇適當的類的數量,正如14。2。1節中描述的卵石試驗彎曲。以下程式碼可以產生相關圖形:
wssplot
<-
function
(
data
,
nc
=
15
,
seed
=
1234
){
wss
<-
(
nrow
(
data
)
-1
)
*
sum
(
apply
(
data
,
2
,
var
))
for
(
i
in
2
:
nc
){
set。seed
(
seed
)
wss[i]
<-
sum
(
kmeans
(
data
,
centers
=
i
)
$
withinss
)}
plot
(
1
:
nc
,
wss
,
type
=
“b”
,
xlab
=
“Number of Clusters”
,
ylab
=
“Within groups sum of squares”
)}
wssplot()函式的三個引數說明如下:data是用來分析的數值資料,nc是要考慮的最大聚類個數,seed是一個隨機數種子。
下面就用K均值聚類來處理一個來自UCI機器學習庫的資料集,也可以透過rattle包來獲得。該資料集包含178種義大利葡萄酒中13中化學成分,考慮到K均值聚類不適合處理型別資料,放棄該資料集當中的品種變數。
#載入資料
>
data
(
wine
,
package
=
“rattle”
)
#顯示資料
>
head
(
wine
)
Type
Alcohol
Malic
Ash
Alcalinity
Magnesium
Phenols
Flavanoids
Nonflavanoids
1
1
14。23
1。71
2。43
15。6
127
2。80
3。06
0。28
2
1
13。20
1。78
2。14
11。2
100
2。65
2。76
0。26
3
1
13。16
2。36
2。67
18。6
101
2。80
3。24
0。30
4
1
14。37
1。95
2。50
16。8
113
3。85
3。49
0。24
5
1
13。24
2。59
2。87
21。0
118
2。80
2。69
0。39
6
1
14。20
1。76
2。45
15。2
112
3。27
3。39
0。34
Proanthocyanins
Color
Hue
Dilution
Proline
1
2。29
5。64
1。04
3。92
1065
2
1。28
4。38
1。05
3。40
1050
3
2。81
5。68
1。03
3。17
1185
4
2。18
7。80
0。86
3。45
1480
5
1。82
4。32
1。04
2。93
735
6
1。97
6。75
1。05
2。85
1450
#資料標準化,並捨棄第一列資料
>
df
<-
scale
(
wine[
-1
]
)
#顯示標準化後的資料
>
head
(
df
)
Alcohol
Malic
Ash
Alcalinity
Magnesium
Phenols
[1
,
]
1。5143408
-0。56066822
0。2313998
-1。1663032
1。90852151
0。8067217
[2
,
]
0。2455968
-0。49800856
-0。8256672
-2。4838405
0。01809398
0。5670481
[3
,
]
0。1963252
0。02117152
1。1062139
-0。2679823
0。08810981
0。8067217
[4
,
]
1。6867914
-0。34583508
0。4865539
-0。8069748
0。92829983
2。4844372
[5
,
]
0。2948684
0。22705328
1。8352256
0。4506745
1。27837900
0。8067217
[6
,
]
1。4773871
-0。51591132
0。3043010
-1。2860793
0。85828399
1。5576991
Flavanoids
Nonflavanoids
Proanthocyanins
Color
Hue
Dilution
[1
,
]
1。0319081
-0。6577078
1。2214385
0。2510088
0。3611585
1。8427215
[2
,
]
0。7315653
-0。8184106
-0。5431887
-0。2924962
0。4049085
1。1103172
[3
,
]
1。2121137
-0。4970050
2。1299594
0。2682629
0。3174085
0。7863692
[4
,
]
1。4623994
-0。9791134
1。0292513
1。1827317
-0。4263410
1。1807407
[5
,
]
0。6614853
0。2261576
0。4002753
-0。3183774
0。3611585
0。4483365
[6
,
]
1。3622851
-0。1755994
0。6623487
0。7298108
0。4049085
0。3356589
Proline
[1
,
]
1。01015939
[2
,
]
0。96252635
[3
,
]
1。39122370
[4
,
]
2。32800680
[5
,
]
-0。03776747
[6
,
]
2。23274072
#繪製組內的平方和和提取的聚類個數的對比
>
wssplot
(
df
)
>
library
(
NbClust
)
>
set。seed
(
1234
)
>
devAskNewPage
(
ask
=
FALSE
)
#NbClust()函式推薦採用三個分類
>
nc
<-
NbClust
(
df
,
min。nc
=
2
,
max。nc
=
15
,
method
=
“kmeans”
)
***
:
The
Hubert
index
is
a
graphical
method
of
determining
the
number
of
clusters。
In
the
plot
of
Hubert
index
,
we
seek
a
significant
knee
that
corresponds
to
a
significant
increase
of
the
value
of
the
measure
i。e
the
significant
peak
in
Hubert
index
second
differences
plot。
***
:
The
D
index
is
a
graphical
method
of
determining
the
number
of
clusters。
In
the
plot
of
D
index
,
we
seek
a
significant
knee
(
the
significant
peak
in
Dindex
second
differences
plot
)
that
corresponds
to
a
significant
increase
of
the
value
of
the
measure。
*******************************************************************
*
Among
all
indices
:
*
4
proposed
2
as
the
best
number
of
clusters
*
15
proposed
3
as
the
best
number
of
clusters
*
1
proposed
10
as
the
best
number
of
clusters
*
1
proposed
12
as
the
best
number
of
clusters
*
1
proposed
14
as
the
best
number
of
clusters
*
1
proposed
15
as
the
best
number
of
clusters
*****
Conclusion
*****
*
According
to
the
majority
rule
,
the
best
number
of
clusters
is
3
*******************************************************************
>
table
(
nc
$
Best。nc[1
,
]
)
0
1
2
3
10
12
14
15
2
1
4
15
1
1
1
1
>
barplot
(
table
(
nc
$
Best。nc[1
,
]
),
+
xlab
=
“Number of Clusters”
,
ylab
=
“Number of Criteria”
,
+
main
=
“Number of Clusters Chosen by 26 Criteria”
)
>
set。seed
(
1234
)
#採用K均值平均聚類,並設定為3個聚類
>
fit。km
<-
kmeans
(
df
,
3
,
nstart
=
25
)
>
fit。km
$
size
[1]
62
65
51
>
fit。km
$
centers
Alcohol
Malic
Ash
Alcalinity
Magnesium
Phenols
1
0。8328826
-0。3029551
0。3636801
-0。6084749
0。57596208
0。88274724
2
-0。9234669
-0。3929331
-0。4931257
0。1701220
-0。49032869
-0。07576891
3
0。1644436
0。8690954
0。1863726
0。5228924
-0。07526047
-0。97657548
Flavanoids
Nonflavanoids
Proanthocyanins
Color
Hue
Dilution
1
0。97506900
-0。56050853
0。57865427
0。1705823
0。4726504
0。7770551
2
0。02075402
-0。03343924
0。05810161
-0。8993770
0。4605046
0。2700025
3
-1。21182921
0。72402116
-0。77751312
0。9388902
-1。1615122
-1。2887761
Proline
1
1。1220202
2
-0。7517257
3
-0。4059428
>
aggregate
(
wine[
-1
]
,
by
=
list
(
cluster
=
fit。km
$
cluster
),
mean
)
cluster
Alcohol
Malic
Ash
Alcalinity
Magnesium
Phenols
Flavanoids
1
1
13。67677
1。997903
2。466290
17。46290
107。96774
2。847581
3。0032258
2
2
12。25092
1。897385
2。231231
20。06308
92。73846
2。247692
2。0500000
3
3
13。13412
3。307255
2。417647
21。24118
98。66667
1。683922
0。8188235
Nonflavanoids
Proanthocyanins
Color
Hue
Dilution
Proline
1
0。2920968
1。922097
5。453548
1。0654839
3。163387
1100。2258
2
0。3576923
1。624154
2。973077
1。0627077
2。803385
510。1692
3
0。4519608
1。145882
7。234706
0。6919608
1。696667
619。0588
>
上圖為組內的平方和與提取的聚類個數的對比圖,從一類到三類下降得很快(之後下降得很慢),建議選用聚類個數為三的解決方案。
上圖為NbCluster包中的26個指標推薦的聚類個數,推薦的結果與組內的平方和與提取的聚類個數的對比圖所展示的吻合。
kmeans()函式同時也輸出了聚類中心,由於聚類中心是基於標準化資料,可以使用aggregate()函式和類的成員來得到原始矩陣中每一類的變數均值。
下面用放棄的葡萄酒品種型別來驗證K均值聚類分析的結果。以下程式碼可以表示交叉列表型別(葡萄酒品種)和類成員:
>
ct。km
<-
table
(
wine
$
Type
,
fit。km
$
cluster
)
>
ct。km
1
2
3
1
59
0
0
2
3
65
3
3
0
0
48
>
並用flexclust包中的蘭德指數(Rand index)來量化型別變數和類之間的關係:
>
library
(
flexclust
)
載入需要的程輯包:
grid
載入需要的程輯包:
lattice
載入需要的程輯包:
modeltools
載入需要的程輯包:
stats4
>
randIndex
(
ct。km
)
ARI
0。897495
>
調整的蘭德指數的變化範圍從-1(不同意)到1(完全同意),本次的葡萄酒品種型別和類的解決方案之間的蘭德指數接近0。9,結果還不錯。
4。2 圍繞中心點的劃分
K均值聚類是基於均值的,所以它對異常值是敏感的。更加穩健的方法是圍繞中心點的劃分(RAM)。RAM用最有代表性的觀測值來表示類,可以使用任意的距離來計算。因此,PAM可以容納混合資料型別,並不僅限於連續變數。PAM演算法如下:
隨機選擇K個觀測值(每個都稱為中心點);
計算觀測值到各個中心的距離/相異性;
把每個觀測值分配到最近的中心點;
計算每個中心點到每個觀測值的距離的總和(總成本);
選擇一個該類中不是中心的點,並和中心點互換;
重新把每個點分配到距它最近的中心點;
再次計算總成本;
如果總成本比步驟(4)計算的總成本少,把新的點作為中心點;
重複步驟(5)~(8)直到中心點不再改變。
在R中可以使用cluster包中的pam()函式來進行劃分聚類分析,格式如下:
pam(x,k,metric = “euclidean”, stand=FALSE)
其中:
x表示資料矩陣或資料框;
k表示聚類的個數;
metric表示使用的相似性/相異性的度量;
stand是一個邏輯值,表示是否有變數應該在計算該指標之前被標準化。
以下用PAM來分析葡萄酒資料。
#載入cluster包
>
library
(
cluster
)
#設定隨機數種子
>
set。seed
(
1234
)
#聚類資料的標準化
>
fit。pam
<-
pam
(
wine[
-1
]
,
k
=
3
,
stand
=
TRUE
)
#輸出中心點
>
fit。pam
$
medoids
Alcohol
Malic
Ash
Alcalinity
Magnesium
Phenols
Flavanoids
Nonflavanoids
[1
,
]
13。48
1。81
2。41
20。5
100
2。70
2。98
0。26
[2
,
]
12。25
1。73
2。12
19。0
80
1。65
2。03
0。37
[3
,
]
13。40
3。91
2。48
23。0
102
1。80
0。75
0。43
Proanthocyanins
Color
Hue
Dilution
Proline
[1
,
]
1。86
5。1
1。04
3。47
920
[2
,
]
1。63
3。4
1。00
3。17
510
[3
,
]
1。41
7。3
0。70
1。56
750
#畫出聚類的方案
>
clusplot
(
fit。pam
,
main
=
“Bivariate Cluster Plot”
)
>
這裡得到的中心點是葡萄酒資料集中實際的觀測值,分別選擇36、107和175個觀測值來代表三類。每個類用包含其所有點的最小面積的橢圓表示。
PAM在蘭德指數中的表現不如K均值,從0。9下降到了0。7。
>
ct。pam
<-
table
(
wine
$
Type
,
fit。pam
$
clustering
)
>
ct。pam
1
2
3
1
59
0
0
2
16
53
2
3
0
1
47
>
randIndex
(
ct。pam
)
ARI
0。6994957
>
5 避免不存在的類
聚類分析是一種旨在識別資料集子組的方法,並且在此方面十分擅長,而且很有可能發現不存在的類。請看下面的程式碼:
>
set。seed
(
1234
)
>
df
<-
rnorm2d
(
1000
,
rho
=
。5
)
>
df
<-
as。data。frame
(
df
)
>
plot
(
df
,
main
=
“Bivariate Normal Distribution with rho=0。5”
)
>
fMultivar包中的rnorm2d()函式用來從相關係數為0。5的二元正態分佈中抽取1000個觀測值,顯然,資料中並沒有什麼類。
隨後,使用wssplot()和Nbclust()函式來確定當前聚類的個數:
> wssplot(df)
> library(NbClust)
> nc <- NbClust(df, min。nc=2, max。nc=15, method=“kmeans”)
> dev。new()
NULL
> barplot(table(nc$Best。n[1,]),
+ xlab=“Number of Clusters”, ylab=“Number of Criteria”,
+ main=“Number of Clusters Chosen by 26 Criteria”)
>
從上圖可以看出,wssplot()函式建議聚類的個數是3,然而NbClust函式返回的準則多數支援2類或3類。如果進一步利用PAM法進行雙聚類分析:
>
library
(
ggplot2
)
>
library
(
cluster
)
>
fit
<-
pam
(
df
,
k
=
2
)
>
df
$
clustering
<-
factor
(
fit
$
clustering
)
>
ggplot
(
data
=
df
,
aes
(
x
=
V1
,
y
=
V2
,
color
=
clustering
,
shape
=
clustering
))
+
+
geom_point
()
+
ggtitle
(
“Clustering of Bivariate Normal Data”
)
對於二元資料,PAM聚類分析還是提取出了兩類,很明顯,這種劃分是刻意的,實際上並沒有真實的類。為了避免類似錯誤,NbClust包中的立方聚類規則(Cubic Cluster Criteria,CCC)可以幫助我們揭示不存在的結構。
> plot(nc$All。index[,4], type=“o”, ylab=“CCC”,
+ xlab=“Number of clusters”, col=“blue”)
二元正態資料的CCC圖,它正確地表明沒有類存在。
聚類分析(或你對它的解讀)找到錯誤聚類的能力使得聚類分析的驗證步驟很重要,你要確保結果是穩健並且可重複的,有時候需要嘗試不同的聚類方法。
6 小結
本章我們首先回顧了常見的聚類方法及聚類分析的一般步驟,然後對層次聚類和劃分聚類的常見方法進行了描述,最後,考慮到可能出現的不存在的類,我們強調了對於類進行驗證的重要性。
聚類分析非常寬泛,若要進一步瞭解可以參考CRAN上面的資料以及
http://
www-users。cs。umn。edu/~k
umar/dmbook/ch8。pdf
,閱讀Tan、Steinbach & Kumar(2006)寫的一本關於資料探勘技術的好書。
下一章,我們將考慮如何用一個準確的方法將觀測值放入已經定義好的分組當中。