K最近鄰算法,簡稱KNN算法,單從名字來猜想,可以簡單粗暴的認為是:K個最近的鄰居,當K=1時,算法便成了最近鄰算法,即尋找最近的那個鄰居。
所謂K最近鄰算法,即是給定一個訓練數據集,對新的輸入實例,在訓練數據集中找到與該實例最鄰近的K個實例,這K個實例的多數屬於某個類,就把該輸入實例分類到這個類中。
K最近鄰算法的核心函數為knn()函數,區別於線性判別和樸素貝葉斯分類,knn()函數集判別規則的“建立”和“預測”這兩個步驟於一體,即不需要在規則建立後再使用predict()函數來進行預測。在使用K最近鄰算法之前,我們先要安裝並加載class軟件包。
首先按照次序向knn()函數中依次放入訓練集中各屬性變量(除去Species變量)、測試集(除去Species變量)、訓練集中的判別變量Species,並首先取K的默認值1進行判別。
> library(class)
> set.seed(1234)
> ind <- sample(2, nrow(iris), replace = TRUE, prob = c(0.7,0.3))
> data_train <- iris[ind==1,]
> data_test <- iris[ind==2,]
>#建立K最近鄰判別規則,並對測試集樣本進行預測
> fit_pre_knn <- knn(data_train[,-5],data_test[,-5],cl=data_train[,5])
>#輸出在K最近鄰判別規則下的判別結果
> fit_pre_knn
[1] setosa setosa setosa setosa setosa setosa setosa setosa
[9] setosa setosa versicolor versicolor versicolor versicolor versicolor versicolor
[17] versicolor versicolor versicolor versicolor versicolor versicolor virginica virginica
[25] virginica virginica versicolor virginica virginica virginica virginica virginica
[33] virginica virginica virginica virginica virginica virginica
Levels: setosa versicolor virginica
>#生成Species真實值與預測值的混淆矩陣
> table(data_test$Species,fit_pre_knn)
fit_pre_knn
setosa versicolor virginica
setosa 10 0 0
versicolor 0 12 0
virginica 0 1 15
由混淆矩陣我們可以看到,Species的三個類別分別有10、12、15個樣本被正確分類,其中setosa、versicolor全部分類正確,而virginica有1個樣本分類錯誤。我們再來計算一下錯誤率:
> error_knn <-sum(as.numeric(as.numeric(fit_pre_knn)!=as.numeric(data_test$Species)))/nrow(data_test)
> error_knn
[1] 0.02631579
我們看到K取1時,K最近鄰的預測錯誤率僅為0.026,判別錯誤率很低 。在實際情況中,K最近鄰算法未必會是最優算法,這時需要針對不同數據集選取使用不同的挖掘算法。
下面我們通過調整K的取值,選擇出最適合於該數據集的K值,將尋找範圍控制在1~20,代碼如下:
>#對將用於存儲K取值1~20時預測錯誤率error_knn變量賦初始值為0
> error_knn <- rep(0,20)
>#構造for循環
> for(i in 1:20) {
+ fit_pre_knn <- knn(data_train[,-5],data_test[,-5],cl=data_train[,5],k=i)
+ error_knn[i] <- sum(as.numeric(as.numeric(fit_pre_knn)!=as.numeric(data_test$Species)))/nrow(data_test)
+ }
> error_knn
[1] 0.02631579 0.05263158 0.02631579 0.02631579 0.00000000 0.00000000 0.00000000 0.02631579 0.00000000 0.02631579 0.00000000 0.02631579
[13] 0.02631579 0.00000000 0.00000000 0.00000000 0.00000000 0.02631579 0.00000000 0.02631579
得到上面的數值結果後,我們來對這20個錯誤率的值作折線圖,這樣可以直觀地看到K取何值時所對應的錯誤率最小。
>plot(error_knn, type="l", xlab="K")
K最近鄰算法也有缺陷,當樣本不平衡,即某些類的樣本容量很大,而其他類樣本容量很小時,有可能導致當輸入一個新樣本時,該樣本的K個最近鄰樣本中大容量類別的樣本佔多數。在這種情況下就可使用有權重的K最近鄰算法來改進。