介紹
一、實驗說明
1. 環境登錄
無需密碼自動登錄,系統用戶名shiyanlou,密碼shiyanlou
2. 環境介紹
本實驗環境采用帶桌面的Ubuntu Linux環境,實驗中會用到程序:
1. LX終端(LXTerminal): Linux命令行終端,打開后會進入Bash環境,可以使用Linux命令
2. GVim:非常好用的編輯器,最簡單的用法可以參考課程[Vim編輯器](http://www.shiyanlou.com/courses/2)
3. R:在命令行輸入‘R’進入交互式環境,下面的代碼都是在交互式環境運行。
3. 環境使用
使用R語言交互式環境輸入實驗所需的代碼及文件,使用LX終端(LXTerminal)運行所需命令進行操作。
完成實驗后可以點擊桌面上方的“實驗截圖”保存並分享實驗結果到微博,向好友展示自己的學習進度。實驗樓提供后台系統截圖,可以真實有效證明您已經完成了實驗。
實驗記錄頁面可以在“我的主頁”中查看,其中含有每次實驗的截圖及筆記,以及每次實驗的有效學習時間(指的是在實驗桌面內操作的時間,如果沒有操作,系統會記錄為發呆時間)。這些都是您學習的真實性證明。
二、課程介紹
這一節課主要介紹一些聚類的方法,包括k-均值聚類、k-中心點聚類、層次聚類和密度聚類。前面兩節是介紹采用k-均值算法和k-中心點算法給鳶尾花數據聚類;第三節是關於使用相同的數據采取層次聚類算法的例子;最后一節介紹密度聚類和DBSCAN聚類算法思想,並演示如何使用DBSCAN算法聚類,並使用這個聚類模型給新的數據分類。
三、課程內容
1、K-Means聚類
這一節介紹使用鳶尾花數據進行k-均值聚類。
首先進行數據預處理:
> library(cluster) # 建立一個新的鳶尾花數據集 > iris2 <- iris # 移除數據集中關於種類的划分 > iris2$Species <- NULL # 將數據進行k-均值聚類分為3類 > (kmeans.result <- kmeans(iris2, 3)) # 將k-Means聚類的結果與實際數值進行對比 > table(iris$Species, kmeans.result$cluster)
對比結果顯示:
上圖顯示了setosa(山鳶尾)可以很容易從其他花種中區分開,但是versicolor(變色鳶尾)和virginica(維吉尼亞鳶尾)就比較難以區分。
接下來,繪制數據分布和它們各自的中心點。注意鳶尾花一共有四個屬性,下面的代碼是根據前面兩個屬性:萼片長度和萼片寬度畫出的聚類圖。我們還需要注意的是由於初始中心點的選擇是隨機的,因此聚類的結果隨着初始值的不同而不同。
> 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)
聚類圖如下:
###2、k中心點聚類
本節介紹使用函數pam()和pamk()實現k中心點聚類算法。k中心點聚類和k均值聚類算法很接近,它們之間主要的區別是:在k均值算法中,它的中心代表一個類,而在k中心點算法中將與類中心對象最接近的點作為一個類。
PAM(Partitioning Around Medoids)是k中心點聚類中一個經典算法,它的思想是基於距離聚類,具有良好的抗噪聲、抗偏離點的能力。它的弱點是不能處理大量的數據,但是經過改良的算法CLARA算法選取數據的多個樣本,在每個樣本上都使用PAM算法,然后選取最好的聚類結果。PAM和CLARA這兩個算法在R中可以通過包‘cluster’中的函數pam()和clara()實現,這兩個函數都需要指定聚類的數量k。但是在包'fpc'中的函數pamk()可以通過調用pam()或者clara()選擇效果最優的聚類數。
使用下面的代碼觀察聚類情況:
> library(fpc) > pamk.result <- pamk(iris2) # 聚類數量 > pamk.result$nc # 檢驗聚類情況 > table(pamk.result$pamobject$clustering, iris$Species) > layout(matrix(c(1,2),1,2)) # 一張圖被分割為兩個部分 > plot(pamk.result$pamobject) # 將繪制的兩個圖表合並在一張圖上顯示 > layout(matrix(1))
輸出結果如下:
上面的例子中,pamk()將數據集分為兩類:一類是‘setosa’,另外一類是‘versicolor’和‘virginica’的混合數據。上圖中,左半部分的圖是一個二維的聚類圖,里面的紫線顯示了兩個類別之間的距離。右半部分的圖是這兩個類的投影圖,輪廓線si越接近1就說明該觀測值聚類情況非常好;si越接近0就說明該觀測值不容易被區分,處於兩個類別之間。si為負值就說明該數據被錯誤分類。Si(i=1,2)分別代表第一類和第二類的平均投影情況,它們分別是0.81和0.62說明聚類情況良好。
接下來令聚類數量k=3使用pam()聚類。
> pam.result <- pam(iris2, 3) > table(pam.result$clustering, iris$Species) > layout(matrix(c(1,2),1,2)) > plot(pam.result) > layout(matrix(1))
顯示結果如下:
上圖左半部分顯示:第一類花‘setosa’能很好的與另外兩類花區分,第二類和第三類花就有一些相似的地方,也就是說這兩類鳶尾花的一些數據不能被正確的判別。
根據上面使用pamk()和pam()的兩個聚類例子很難判斷哪一種聚類方法更好,這取決於目標問題和各自的經驗與知識領域。在這個例子中,pam()函數似乎更好一點,能夠將鳶尾花聚為3類。所以pamk()不一定能給出最好的聚類數量。我們需要知道的是pam()函數使用的時候,是通過人為的方式設置了k=3,如果在不知道鳶尾花數據分類的情況下,聚類效果又是不一樣的。
###3、層次聚類
這一節學習使用函數hclust()對鳶尾花數據集進行層次聚類。
首先,從鳶尾花數據集中抽取40個樣本,這樣就會避免聚類圖上的點擁擠甚至重疊在一起,像之前一樣也要把數據集中花的種類去掉,然后對數據進行分層聚類:
> idx <- sample(1:dim(iris)[1], 40) > irisSample <- iris[idx,] > irisSample$Species <- NULL # method="ave"指的是取對象之間的平均距離為組間距離 > 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)
繪制的聚類樹狀圖如下:
同k均值聚類結果一樣,"setosa"這類花能被輕易的識別,第二類和第三類花仍然不能夠很好的被區分。
###4、基於密度的聚類
使用包‘fpc’可以實現DBSCAN算法從而對數值型數據進行聚類。基於密度的聚類算法的目標是將一個高密度分布的數據區域划分為一類,依次類推,從而達到將數據分為幾類的效果。在DBSCAN算法中有以下兩個重要參數:
1. eps:可達距離,定義鄰域的大小
2. MinPts:領域eps內所有滿足為一類點的數量最小值要求。
如果給定點a鄰域內的樣本點數不超過MinPts,那么a就是一個核心對象。所有在a點附近的點如果是密度可達的,也就是說到點a的距離小於或者等於可達距離eps,那么這些點就被划分到a這一類。
密度聚類的優勢在於它可以發現各種形狀和大小的類並且對噪聲不敏感。而k均值算法傾向於發現相同大小的球形類分布的數據群。
下面是關於鳶尾花數據集的基於密度的聚類算法實現:
> library(fpc) > iris2 <- iris[-5] # 移除分類標簽 > ds <- dbscan(iris2, eps=0.42, MinPts=5) # 將聚類結果與原始類標簽進行對比 > table(ds$cluster, iris$Species)
對比結果如下:
上表中,第一列中的1-3分別是已經分好的3類,而0代表噪聲和異常值,也就是沒有被分到任何類的對象。
> plot(ds, iris2)
上圖中黑色的圓圈就是噪聲(異常值)。
另外一種顯示聚類結果的方式是使用包fpc內的函數plotcluster(),我們可以觀察到不同類的數據已經被標簽識別。
> plotcluster(iris2, ds$cluster)
在分析新數據與類之間的相似性的基礎上,聚類模型可以給新數據進行分類。下面的例子就是從鳶尾花數據集中抽取10個樣本,並結合加一些噪聲組成一個新的數據集用來分類。其中,函數runif()可以生成均勻分布的噪聲數據。
# 設置隨機種子,隨機產生10個鳶尾花樣本 > set.seed(435) > idx <- sample(1:nrow(iris), 10) # 移除分類屬性列 > newData <- iris[idx,-5] > newData <- newData + matrix(runif(10*4, min=0, max=0.2), nrow=10, ncol=4) # 給新數據分類 > myPred <- predict(ds, iris2, newData) # 將聚類結果畫圖顯示 > plot(iris2[c(1,4)], col=1+ds$cluster) > points(newData[c(1,4)], pch="*", col=1+myPred, cex=3) # 檢驗聚類效果 > table(myPred, iris$Species[idx])
圖4.1
圖4.1