1. 程式人生 > >k近鄰法:R實現(一)

k近鄰法:R實現(一)

KNN是有監督的學習演算法,其特點有:

1、精度高,對異常值不敏感

2、只能處理數值型屬性

3、計算複雜度高(如已知分類的樣本數為n,那麼對每個未知分類點要計算n個距離)

KNN演算法步驟:

需對所有樣本點(已知分類+未知分類)進行歸一化處理。

然後,對未知分類的資料集中的每個樣本點依次執行以下操作:

1、計算已知類別資料集中的點與當前點(未知分類)的距離。

2、按照距離遞增排序

3、選取與當前距離最小的k個點

4、確定前k個點所在類別的出現頻率

5、返回前k個點出現頻率最高的類別作為當前點的預測類別

<span style="font-family:Times New Roman;font-size:14px;"># 選擇iris資料集為例,iris共有150條資料
#先大致看一下資料
head(iris)
#對iris進行歸一化處理,scale歸一化的公式為(x-mean(x))/sqrt(var(x))
iris_s <- data.frame(scale(iris[, 1:4]))
iris_s <- cbind(iris_s, iris[, 5])
names(iris_s)[5] = "Species"
#隨機選出100條記錄作為已知分類的樣本集
sample_list <- sample(1:150, size = 100)
iris_know <- iris_s[sample_list, ]
#剩餘的50條記錄作為未知分類的樣本
iris_unknow <- iris_s[-sample_list, ]
#對測試集中的每一個樣本,計算其與已知樣本的距離,因為已經歸一化,此處直接使用歐氏距離
length_know <- nrow(iris_know)
length_unknow <- nrow(iris_unknow)
for (i in 1:length_unknow){
    dis_know <- data.frame(dis = rep(0, length_know))
    for (j in 1:length_know){
        #計算已知點和未知點的距離
        dis_know[j, 1] <- dist(rbind(iris_unknow[i, 1:4], iris_know[j, 1:4]), method = "euclidean")
        names(dis_know)[1] = "dis"
        # 儲存已知樣本分類
        dis_know[j, 2] <- iris_know[j, 5]
        names(dis_know)[2] = "Species"
    }
    #按距離從小到大排序
    dis_know <- dis_know[order(dis_know$dis), ]
    #定義K的大小
    k <-5
    #按因子(也就是分類)進行排序
    type_freq <- as.data.frame(table(dis_know[1:k, ]$Species))
    #按計數值進行排序
    type_freq <- type_freq[order(-type_freq$Freq), ]
    # 記錄頻數最大的型別
    iris_unknow[i, 6] <- type_freq[1,1]
    names(iris_unknow)[6] = "Species.pre"
}

#輸出分類結果
iris_unknow[, 5:6]
</span>