天天看點

R語言之K-mean聚類分析

K-mean聚類是很基礎的算法,在大學階段大家都會學,如何通過R語言自己寫K-mean算法,話不多說,上代碼,算法流程和函數解釋代碼後

K_means <- function(data,k,max.iter = 10){
rows <- nrow(data)                 #擷取行數
cols <- ncol(data)                 #擷取列數
within <- numeric(k)               #用于存儲組類平方和
lable_matrix <- matrix(0,rows,2)   #用于存儲類标簽及到類中心的距離
centers <- matrix(0,cols,k)        #用于存儲類中心
centers_matrix <- matrix(0,rows,k) #用于存儲初始确定初始類中心時到類中心的距離
iter <- 0                          #疊代次數
random <- sample(1:rows,1)
centers[,1] <- as.matrix(data[random,])
for(j in 2:k){
 for(i in 1:rows){
  centers_matrix[i,j] <- sum((data[i,] - centers[,j-1])^2)+centers_matrix[i,j-1]
 }
 centers[,j] <- as.matrix(data[which(centers_matrix[,j] == max(centers_matrix[,j])),])
}                                  #計算初始類中心
changed <- TRUE                    #用于判斷資料的類标簽是否發生改變
while(changed){
 if(iter >= max.iter){
  changed <- FALSE
  break
 }
 for(j in 1:rows){
  updata <- 1000000000
  for( i in 1:k){
   updatas <- sum((data[j,]-centers[,i])^2)
   if(updatas < updata){
    updata <- updatas
    lable_matrix[j,1] <- updatas
    lable_matrix[j,2] <- i
   }
  }
 }                                 #更新到類中心的距離以及類标簽
 center <- centers
 for(i in 1:k){
  centers[,i] <- colMeans(data[lable_matrix[,2]==i,])
 }                                 #更新類中心
 changed <- !all(center == centers)#判斷類中心是否變化
 iter <- iter + 1
}
###計算函數傳回值:
totss <- sum((t(data[,])-colMeans(data))^2)
withinss <- numeric()
for(i in 1:k){
 withinss[i] <- sum((t(data[lable_matrix[,2]==i,])-(centers[,i]))^2)
}
tot.withinss <- sum(withinss)
betweenss<-0
for(i in 1:3){
 betweenss <- betweenss + sum(nrow(data[lable_matrix[,2]==i,])*(rowMeans(t(data[lable_matrix[,2]==i,]))-colMeans(data))^2)
}
size <- aggregate(lable_matrix[,2], by=list(lable=lable_matrix[,2]),length)[,2]

centers_matrix <- t(centers)
colnames(centers_matrix) <- colnames(data)
result <- list(cluster = lable_matrix[,2],centers = centers_matrix,totss = totss,withinss = withinss,tot.withinss = tot.withinss
               ,betweenss = betweenss,size = size,iter = iter)
return(result)
}

df <- kmeans(iris[,1:4],3)
df$cluster
df$centers
df$totss
df$withinss
df$tot.withinss
df$betweenss
df$size
df$iter
K_means(iris[,1:4],3)
           

對設定的函數參數以及輸出的結果做一解釋:

參數:data:用于聚類的資料;k:用于聚類的數目;max.iter:最大疊代次數

輸出結果(均與R語言中自帶kmeans函數輸出結果命名一緻):

cluster:聚類結果,即類标簽;

centers:聚類中心;

totss:總平方和;

withinss:各組内的平方和;

tot.withinss:組内平方和;

betweenss:組間平方和;

size:各類的數量;

iter :疊代次數;

我用自己寫的函數與R語言自帶的kmeans函數結果做了對比,資料集使用iris資料集,結果如下:

R語言之K-mean聚類分析
R語言之K-mean聚類分析

 由上面兩圖的結果對比可知:除去疊代次數不一緻外其餘均相同;疊代次數不一緻是因為選取的初始類中心為随機選取造成的。也不排除我的疊代過程不是最優的疊代方式造成,歡迎大家留言談論!

算法流程:

R語言之K-mean聚類分析

對于K-mean聚類算法的詳細流程以及可改進地方和方向,我後期也會發類似的文章。

繼續閱讀