『原創』機器學習算法的R語言實現(一):KNN


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

1、精度高,對異常值不敏感
2、只能處理數值型屬性
3、計算復雜度高(如已知分類的樣本數為n,那么對每個未知分類點要計算n個距離)
 
KNN算法步驟:
需對所有樣本點(已知分類+未知分類)進行歸一化處理。
然后,對未知分類的數據集中的每個樣本點依次執行以下操作:
1、計算已知類別數據集中的點與當前點(未知分類)的距離。
2、按照距離遞增排序
3、選取與當前距離最小的k個點
4、確定前k個點所在類別的出現頻率
5、返回前k個點出現頻率最高的類別作為當前點的預測類別
 

機器學習算法R實現-KNN

# 選擇iris數據集為例,iris共有150條數據,內容如下head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
## Sepal.Length\Sepal.Width\Petal.Length\Petal.Width為分類的四個維度,Species為分類結果 # 1、對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" # 1、對iris數據集隨機選擇其中的100條記錄作為已知分類的樣本集 sample.list <- sample(1:150, size = 100) iris.known <- iris_s[sample.list, ] # 2、剩余50條記錄作為未知分類的樣本集(測試集) iris.unknown <- iris_s[-sample.list, ] ## 3、對測試集中的每一個樣本,計算其與已知樣本的距離,因為已經歸一化,此處直接使用歐氏距離 length.known <- nrow(iris.known)length.unknown <- nrow(iris.unknown)
 
 
for (i in 1:length.unknown) {    # dis 記錄與每個已知分類樣本的距離及改樣本的分類    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), ]
 
 
  # Knn中的K,定義了具體最近的K個已知分類的樣本    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"
# 輸出分類結果
 iris.unknown [, 5 : 6 ]
 
##        Species Species.pre
## 3       setosa      setosa
## 4       setosa      setosa
## 5       setosa      setosa
## 7       setosa      setosa
## 15      setosa      setosa
## 20      setosa      setosa
## 21      setosa      setosa
## 30      setosa      setosa
## 33      setosa      setosa
## 35      setosa      setosa
## 36      setosa      setosa
## 38      setosa      setosa
## 40      setosa      setosa
## 41      setosa      setosa
## 49      setosa      setosa
## 51  versicolor  versicolor
## 54  versicolor  versicolor
## 56  versicolor  versicolor
## 57  versicolor  versicolor
## 59  versicolor  versicolor
## 63  versicolor  versicolor
## 70  versicolor  versicolor
## 74  versicolor  versicolor
## 75  versicolor  versicolor
## 78  versicolor  versicolor
## 80  versicolor  versicolor
## 87  versicolor  versicolor
## 89  versicolor  versicolor
## 95  versicolor  versicolor
## 96  versicolor  versicolor
## 98  versicolor  versicolor
## 100 versicolor  versicolor
## 103  virginica   virginica
## 108  virginica   virginica
## 112  virginica   virginica
## 115  virginica   virginica
## 117  virginica   virginica
## 119  virginica   virginica
## 122  virginica   virginica
## 124  virginica  versicolor
## 127  virginica   virginica
## 129  virginica   virginica
## 130  virginica   virginica
## 131  virginica   virginica
## 132  virginica   virginica
## 134  virginica  versicolor
## 142  virginica   virginica
## 144  virginica   virginica
## 148  virginica   virginica
## 149  virginica   virginica

上面結果中,Species為樣本實際分類,Species.pre為Knn算法的分類。經過多次實驗,50個樣本中,有5個左右樣本的分類判斷錯誤,正確率在90%。可見Knn算法效果較好,原理容易理解。

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






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM