資料分析與挖掘 - R語言:KNN演算法

獵手家園發表於2016-05-25

一個簡單的例子!
環境:CentOS6.5
Hadoop叢集、Hive、R、RHive,具體安裝及除錯方法見部落格內文件。

 

KNN演算法步驟:
需對所有樣本點(已知分類+未知分類)進行歸一化處理。然後,對未知分類的資料集中的每個樣本點依次執行以下操作:
1、計算已知類別資料集中的點與當前點(未知分類)的距離。
2、按照距離遞增排序
3、選取與當前距離最小的k個點
4、確定前k個點所在類別的出現頻率
5、返回前k個點出現頻率最高的類別作為當前點的預測類別

 

編寫R指令碼:

#!/usr/bin/Rscript
#1、對iris進行歸一化處理
iris_s <- data.frame(scale(iris[, 1:4]))
iris_s <- cbind(iris_s, iris[, 5])
names(iris_s)[5] = "Species"

#2、對iris資料集隨機選擇其中的100條記錄作為已知分類的樣本集
sample.list <- sample(1:150, size = 100)
iris.known <- iris_s[sample.list, ]

#3、剩餘50條記錄作為未知分類的樣本集(測試集)
iris.unknown <- iris_s[-sample.list, ]

#4、對測試集中的每一個樣本,計算其與已知樣本的距離,因為已經歸一化,此處直接使用歐氏距離
length.known <- nrow(iris.known)
length.unknown <- nrow(iris.unknown)

#5、計算
for (i in 1:length.unknown) { 
    dis_to_known <- data.frame(dis = rep(0, length.known)) 
    for (j in 1:length.known) { 
        dis_to_known[j, 1] <- dist(rbind(iris.unknown[i, 1:4], iris.known[j,1:4]), method = "euclidean") 
        dis_to_known[j, 2] <- iris.known[j, 5]
        names(dis_to_known)[2] = "Species" 
    }

    dis_to_known <- dis_to_known[order(dis_to_known$dis), ]

    k <- 5 
    type_freq <- as.data.frame(table(dis_to_known[1:k, ]$Species)) 
    type_freq <- type_freq[order(-type_freq$Freq), ]
    iris.unknown[i, 6] <- type_freq[1, 1]
}

names(iris.unknown)[6] = "Species.pre"

#7、輸出分類結果
iris.unknown[, 5:6]

輸出結果:略,結果集中,Species為樣本實際分類,Species.pre為Knn演算法的分類,正確率達90%以上。

 

KNN是有監督的學習演算法,其特點有:
1、精度高,對異常值不敏感
2、只能處理數值型屬性
3、計算複雜度高(如已知分類的樣本數為n,那麼對每個未知分類點要計算n個距離)

 

KNN演算法存在的問題:
1、k值的確定是個難題。
2、如果距離最近的k個已知分類樣本中,頻數最高的型別有多個(頻數相同),如何選擇對未知樣本的分類?目前看是隨機的。
3、如果有n個未知型別樣本,m個已知型別樣本,則需要計算n*m個距離,計算量較大,且需儲存全部資料集合,空間複雜度也較大。
4、能否把預測的樣本分類加入到已知類別集合中,對剩餘的未知型別樣本進行分類?
5、歸一化放在所有處理的最前面,這樣需要知道全部的樣本集合(已知分類+未知分類)來構建分類器,而實際上未知分類的樣本並不一定能事先獲得,這樣如何進行歸一化處理?

 

相關文章