儘管我我的很是不喜歡人們被劃分圈子,由於這樣就有了歧視、偏見、排擠和矛盾,但「物以類聚,人以羣分」確實是一種客觀的現實——這其中就蘊含着聚類分析的思想。算法
前面所提到的機器學習算法主要都是分類和迴歸,這兩類的應用場景都很清晰,就是對分類型變量或者數值型變量的預測。聚類分析是一種根據樣本之間的距離或者說是類似性(親疏性),把越類似、差別越小的樣本聚成一類(簇),最後造成多個簇,使同一個簇內部的樣本類似度高,不一樣簇之間差別性高。機器學習
有人不理解分類和聚類的差異,其實這個很簡單:分類是一個已知具體有幾種狀況的變量,預測它究竟是哪一種狀況;聚類則是儘可能把相似的樣本聚在一塊兒,不一樣的樣本分開。舉個例子,一我的你判斷他是男是女這是分類,讓男人站一排女人站一排這是聚類。學習
聚類分析算法不少,比較經典的有k-means和層次聚類法。spa
k-means的k就是最終彙集的簇數,這個要你事先本身指定。k-means在常見的機器學習算法中算是至關簡單的,基本過程以下:code
首先任取(你沒看錯,就是任取)k個樣本點做爲k個簇的初始中心;
對每個樣本點,計算它們與k箇中心的距離,把它納入距離最小的中心所在的簇;
等到全部的樣本點歸類完畢,從新計算k個簇的中心;
重複以上過程直至樣本點納入的簇再也不變更。
k-means的聚類過程演示以下:排序
k-means聚類分析的原理雖然簡單,但缺點也比較明顯:ip
首先聚成幾類這個k值你要本身定,但在對數據一無所知的狀況下你本身也不知道k應該定多少;
初始質心也要本身選,而這個初始質心直接決定最終的聚類效果;
每一次迭代都要從新計算各個點與質心的距離,而後排序,時間成本較高。
值得一提的是,計算距離的方式有不少種,不必定非得是笛卡爾距離;計算距離前要歸一化。ci
儘管k-means的原理很簡單,然而層次聚類法的原理更簡單。它的基本過程以下:it
每個樣本點視爲一個簇;
計算各個簇之間的距離,最近的兩個簇聚合成一個新簇;
重複以上過程直至最後只有一簇。
層次聚類不指定具體的簇數,而只關注簇之間的遠近,最終會造成一個樹形圖。table
經過這張樹形圖,不管想劃分紅幾個簇均可以很快地劃出。
如下以癌細胞細據爲例,演示K-means和層次聚類法的過程。
> library(ISLR) > nci.labels = NCI60$labs > nci.data = NCI60$data > > sd.data = scale(nci.data) > data.dist = dist(sd.data) > plot(hclust(data.dist),labels = nci.labels, main = "Complete Linkage", xlab = "", sub = "", ylab = "") # 默認按最長距離聚類> plot(hclust(data.dist,method = "average"),labels = nci.labels, main = "Average Linkage", xlab = "", sub = "", ylab = "") # 類平均法> plot(hclust(data.dist),labels = nci.labels, main = "Single Linkage", xlab = "", sub = "", ylab = "") #最短距離法
Complete Linkage
Average Linkage
Single Linkage
可見選擇不一樣的距離指標,最終的聚類效果也不一樣。其中最長距離和類平均距離用得比較多,由於產生的譜系圖較爲均衡。
> # 指定聚類數> hc.out = hclust(dist(sd.data)) > hc.clusters = cutree(hc.out,4) > table(hc.clusters,nci.labels) nci.labels hc.clusters BREAST CNS COLON K562A-repro K562B-repro LEUKEMIA MCF7A-repro 12320000232000003000116042050001 nci.labels hc.clusters MCF7D-repro MELANOMA NSCLC OVARIAN PROSTATE RENAL UNKNOWN 10886281200100103000000041000000> > plot(hc.out,labels = nci.labels) > abline(h=139,col="red") # 切割成4類
層次聚類劃分紅4類
圖中一條紅線將簇劃分紅4類,很容易看出哪些樣本各屬於哪一簇。
以上是層次聚類法的結果,但若是用k-means聚類的話,結果極可能就不同了。
> # k-means聚類> set.seed(2) > km.out = kmeans(sd.data,4,nstart = 20) > km.clusters = km.out$cluster > table(km.clusters,hc.clusters) # 兩種聚類結果的確有差別,k-means的第2簇與層次聚類的第3簇一致 hc.clusters km.clusters 12341110092008039000420700