R 無監督聚類算法(1)K-means和層次聚類

首先我們要解決幾個問題

聚類算法主要包括哪些算法?

主要包括:K-means、DBSCAN、Density Peaks聚類(局部密度聚類)、層次聚類、譜聚類。

什麼是無監督學習?

• 無監督學習也是相對於有監督學習來說的,因為現實中遇到的大部分數據都是未標記的樣本,要想通過有監督的學習就需要事先人為標註好樣本標籤,這個成本消耗、過程用時都很巨大,所以無監督學習就是使用無標籤的樣本找尋數據規律的一種方法

• 聚類算法就歸屬於機器學習領域下的無監督學習方法。無監督學習的目的是什麼呢?

• 可以從龐大的樣本集合中選出一些具有代表性的樣本子集加以標註,再用於有監督學習

• 可以從無類別信息情況下,尋找表達樣本集具有的特徵

R中有哪些無監督學習的包?

R 無監督聚類算法(1)K-means和層次聚類

<code># 需要用到的數據集和包
library(readr)
library(dplyr)
library(ggplot2)/<code>

我們用的數據集是kaggle中的pokemon dataset

<code># 簡單查看一下數據
pokemon_raw = read_csv('Pokemon.csv')
head(pokemon_raw)
## # A tibble: 6 x 13
## `#` Name `Type 1` `Type 2` Total HP Attack Defense
##
## 1 1 Bulbasaur Grass Poison 318 45 49 49
## 2 2 Ivysaur Grass Poison 405 60 62 63
## 3 3 Venusaur Grass Poison 525 80 82 83
## 4 3 VenusaurMega Venusaur Grass Poison 625 80 100 123
## 5 4 Charmander Fire 309 39 52 43
## 6 5 Charmeleon Fire 405 58 64 58
## # ... with 5 more variables: `Sp. Atk` , `Sp. Def` ,
## # Speed , Generation , Legendary
/<code>
<code># 只選擇連續型變數來做聚類
pokemon = pokemon_raw %>%
select(6:11)
head(pokemon)
## # A tibble: 6 x 6
## HP Attack Defense `Sp. Atk` `Sp. Def` Speed
##
## 1 45 49 49 65 65 45
## 2 60 62 63 80 80 60
## 3 80 82 83 100 100 80
## 4 80 100 123 122 120 80
## 5 39 52 43 60 50 65
## 6 58 64 58 80 65 80
/<code>


k-means

k均值聚類算法(k-means clustering algorithm)是一種迭代求解的聚類分析算法,其步驟是隨機選取K個對象作為初始的聚類中心,然後計算每個對象與各個種子聚類中心之間的距離,把每個對象分配給距離它最近的聚類中心。聚類中心以及分配給它們的對象就代表一個聚類。每分配一個樣本,聚類的聚類中心會根據聚類中現有的對象被重新計算。這個過程將不斷重複直到滿足某個終止條件。終止條件可以是沒有(或最小數目)對象被重新分配給不同的聚類,沒有(或最小數目)聚類中心再發生變化,誤差平方和局部最小。

優點:1.有效率且不容易受到初始值的影響。

缺點:1.不能處理非球形簇;2.不能處理不同尺寸,不懂密度的簇;3.離群值會有較大幹擾(一定要在預處理時剔除掉

R 內置了一個函數kmeans可以用做聚類分析kmeans中第一個參數是dataset。centers是中心點選擇參數,表示聚成幾類。iter.max是迭代次數的參數,即迭代次數,不寫的話默認是10次。 algorithm是算法選擇的參數,算法有”Hartigan-Wong”, “Lloyd”, “Forgy”,”MacQueen”四種。

<code># Initialize total within sum of squares error: wss
wss = 0
# 分成1至15個簇的結果
for (i in 1:15) {
# 先創建一個模型: km.out
km.out = kmeans(pokemon, centers = i, nstart = 20, iter.max = 50)
# 保存每個簇的組內距離平方和
wss[i] = km.out$tot.withinss
}

# 結果可視化,x軸是分群數,y軸是wss,每個簇內部的距離平方和,表示該簇的緊密程度。
plot(1:15, wss, type = "b",
xlab = "Number of Clusters",
ylab = "Within groups sum of squares")/<code>
R 無監督聚類算法(1)K-means和層次聚類

<code># 根據上圖我們選擇分四組
k = 4

# 建立一個4個群的模型
km.pokemon
# 畫出Defense vs. Speed這兩個變數的分群結果
# 因為只能畫出二維的狀態,所以有很多是重疊的部分
plot(pokemon[, c("Defense", "Speed")],
col = km.pokemon$cluster,
main = paste("k-means clustering of Pokemon with", k, "clusters"),
xlab = "Defense", ylab = "Speed")/<code>
R 無監督聚類算法(1)K-means和層次聚類

Hierarchical clustering層次聚類

層次法(Hierarchicalmethods)先計算樣本之間的距離。每次將距離最近的點合併到同一個類。然後,再計算類與類之間的距離,將距離最近的類合併為一個大類。不停的合併,直到合成了一個類。其中類與類的距離的計算方法有:最短距離法,最長距離法,中間距離法,類平均法等。比如最短距離法,將類與類的距離定義為類與類之間樣本的最短距離。

層次聚類算法根據層次分解的順序分為:自下底向上和自上向下,即凝聚的層次聚類算法和分裂的層次聚類算法(agglomerative和divisive),也可以理解為自下而上法(bottom-up)和自上而下法(top-down)。自下而上法就是一開始每個個體(object)都是一個類,然後根據linkage尋找同類,最後形成一個“類”。自上而下法就是反過來,一開始所有個體都屬於一個“類”,然後根據linkage排除異己,最後每個個體都成為一個“類”。這兩種路方法沒有孰優孰劣之分,只是在實際應用的時候要根據數據特點以及你想要的“類”的個數,來考慮是自上而下更快還是自下而上更快。

至於根據Linkage判斷“類”的方法就是最短距離法、最長距離法、中間距離法、類平均法等等(其中類

平均法往往被認為是最常用也最好用的方法,一方面因為其良好的單調性,另一方面因為其空間擴張/濃縮的程度適中)。為彌補分解與合併的不足,層次合併經常要與其它聚類方法相結合,如循環定位。

優點:1.距離和規則的相似度容易定義,限制少;2.不需要預先制定聚類數;3.可以發現類的層次關係;4.可以聚類成其它形狀

缺點:1.計算複雜度太高;2.奇異值也能產生很大影響;3.算法很可能聚類成鏈狀

<code># 查看每列 means
colMeans(pokemon)
## HP Attack Defense Sp. Atk Sp. Def Speed
## 69.25875 79.00125 73.84250 72.82000 71.90250 68.27750

# 查看每列 standard deviations
apply(pokemon, 2, sd)
## HP Attack Defense Sp. Atk Sp. Def Speed
## 25.53467 32.45737 31.18350 32.72229 27.82892 29.06047

# 將數據標準化
pokemon.scaled /<code>

聚類集合間的距離method,也就是linkage(連接方法linkage指的是衡量簇與簇之間的遠近程度的方法)

最長距離法(complete) 默認;最短距離法(single) ;平均距離法(average);重心法(centroid)

<code># 建立 hierarchical clustering 模型: hclust.pokemon
# dist(pokemon.scaled)先需要將數據轉化為兩點間的距離
hclust.pokemon # HitPoints Attack Defense SpecialAttack SpecialDefense Speed
# 69.25875 79.00125 73.84250 72.82000 71.90250 68.27750
# HitPoints Attack Defense SpecialAttack SpecialDefense Speed
# 25.53467 32.45737 31.18350 32.72229 27.82892 29.06047 /<code>
<code># 可視化 hclust.pokemon
plot(hclust.pokemon, main = "complete")/<code>
R 無監督聚類算法(1)K-means和層次聚類

比較 kmeans( ) and hclust( )

<code># Apply cutree() to hclust.pokemon: cut.pokemon
cut.pokemon
# Compare methods

table(km.pokemon$cluster, cut.pokemon)

# cut.pokemon
# 1 2 3
# 1 283 0 0
# 2 114 0 1
# 3 277 11 0
# 4 114 0 0/<code>

這是個令人比較困惑的例子,可以看到kmeans()將觀測結果分成了比較明顯的四簇,但是hclust()幾乎把所有觀測結果都放在了一個簇中。我們雖然期待可以分成較多的分散集群,但是不能單單因為這個就得出哪個比較好的結論。

歡迎關注【數據小鹽罐兒】一個很“鹹”的數據科學公眾號,不定期分享一些有趣好玩的項目以及大量的學習資源


分享到:


相關文章: