knn算法詳解


 

       鄰近算法,或者說K最近鄰(kNN,k-NearestNeighbor)分類算法是數據挖掘分類技術中最簡單的方法之一。所謂K最近鄰,就是k個最近的鄰居的意思,說的是每個樣本都可以用它最接近的k個鄰居來代表。判斷鄰居就是用向量距離大小來刻畫。

 
       kNN算法的核心思想是如果一個樣本在特征空間中的k個最相鄰的樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別,並具有這個類別上樣本的特性。該方法在確定分類決策上只依據最鄰近的一個或者幾個樣本的類別來決定待分樣本所屬的類別。 kNN方法在類別決策時,只與極少量的相鄰樣本有關。由於kNN方法主要靠周圍有限的鄰近的樣本,而不是靠判別類域的方法來確定所屬類別的,因此對於類域的交叉或重疊較多的待分樣本集來說,kNN方法較其他方法更為適合。
                                                                                               
下圖中,綠色圓要被決定賦予哪個類,是紅色三角形還是藍色四方形?如果K=3,由於紅色三角形所占比例為2/3,綠色圓將被賦予紅色三角形那個類,如果K=5,由於藍色四方形比例為3/5,因此綠色圓被賦予藍色四方形類。
                                                                                                                                                    KNN算法的決策過程 一張必不可少的圖
        K最近鄰(k-Nearest Neighbor,KNN)分類算法,是一個理論上比較成熟的方法,也是最簡單的機器學習算法之一。該方法的思路是:如果一個樣本在特征空間中的k個最相似(即特征空間中最鄰近)的樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別。KNN算法中,所選擇的鄰居都是已經正確分類的對象。該方法在定類決策上只依據最鄰近的一個或者幾個樣本的類別來決定待分樣本所屬的類別。 KNN方法雖然從原理上也依賴於極限定理,但在類別決策時,只與極少量的相鄰樣本有關。由於KNN方法主要靠周圍有限的鄰近的樣本,而不是靠判別類域的方法來確定所屬類別的,因此對於類域的交叉或重疊較多的待分樣本集來說,KNN方法較其他方法更為適合。
       KNN算法不僅可以用於分類,還可以用於回歸。通過找出一個樣本的k個最近鄰居,將這些鄰居的屬性的平均值賦給該樣本,就可以得到該樣本的屬性。更有用的方法是將不同距離的鄰居對該樣本產生的影響給予不同的 權值(weight),如權值與距離成反比。
 

算法流程

1. 准備數據,對數據進行 預處理
2. 選用合適的數據結構存儲訓練數據和測試元組
3. 設定參數,如k
4.維護一個大小為k的的按距離由大到小的 優先級隊列,用於存儲最近鄰訓練元組。隨機從訓練元組中選取k個元組作為初始的最近鄰元組,分別計算測試元組到這k個元組的距離,將訓練元組標號和距離存入優先級隊列
5. 遍歷訓練元組集,計算當前訓練元組與測試元組的距離,將所得距離L 與優先級隊列中的最大距離Lmax
6. 進行比較。若L>=Lmax,則舍棄該元組,遍歷下一個元組。若L < Lmax,刪除優先級隊列中最大距離的元組,將當前訓練元組存入優先級隊列。
7. 遍歷完畢,計算優先級隊列中k 個元組的多數類,並將其作為測試元組的類別。
8. 測試元組集測試完畢后計算誤差率,繼續設定不同的k值重新進行訓練,最后取誤差率最小的k 值。
 
 
 
優點
 
1.簡單,易於理解,易於實現,無需估計參數,無需訓練;
2. 適合對稀有事件進行分類;
3.特別適合於多分類問題(multi-modal,對象具有多個類別標簽), kNN比SVM的表現要好
 

缺點

該算法在分類時有個主要的不足是,當樣本不平衡時,如一個類的樣本容量很大,而其他類樣本容量很小時,有可能導致當輸入一個新樣本時,該樣本的K個鄰居中大容量類的樣本占多數。 該算法只計算“最近的”鄰居樣本,某一類的樣本數量很大,那么或者這類樣本並不接近目標樣本,或者這類樣本很靠近目標樣本。無論怎樣,數量並不能影響運行結果。
該方法的另一個不足之處是計算量較大,因為對每一個待分類的文本都要計算它到全體已知樣本的距離,才能求得它的K個最近鄰點。
可理解性差,無法給出像決策樹那樣的規則。
 
 
 
好了前面的分析講解千篇一律下面開始上代碼
本文以 Iris數據集不知道可以百度)為例,用python實現knn算法(實際上就是調用幾個庫,底層的實現看一看算法流程想明白干啥就可以,一個庫函數就搞定了 手動滑稽
下面給出相關代碼:
1.Import dataset 導入數據集
       先導入必要的庫
import numpy as np  
import matplotlib.pyplot as plt  #繪圖
import pandas as pd  

       再導入數據集

以excel格式為例,我的iris目標文件存儲在

"D://test_knn"中
url = "D://test_knn./iris.csv"   #url path

# Assign column names to the dataset
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'Class']

# Read dataset to pandas dataframe
dataset = pd.read_csv(url, names=names) 

可以用下面函數檢驗導入是否成功

dataset.head()  #默認讀取前五行
輸出結果如下:
sepal-length sepal-width petal-length petal-width Class 0 5.1 3.5 1.4 0.2 Iris-setosa 1 4.9 3.0 1.4 0.2 Iris-setosa 2 4.7 3.2 1.3 0.2 Iris-setosa 3 4.6 3.1 1.5 0.2 Iris-setosa 4 5.0 3.6 1.4 0.2 Iris-setosa

 

2.Preprocessing  the dataset   數據預處理

 x= dataset.iloc[:, :-1].values   #x 屬性
 #第一個冒號是所有列,第二個是所有行,除了最后一個(Purchased)
 
 y = dataset.iloc[:, 4].values      #y 標簽
 # 只取最后一個作為依賴變量。

3.Train Test Split 

把數據划分成訓練集和測試集

from sklearn.model_selection import train_test_split  
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20) 

80%的數據划分到訓練集,20%的數據划分到測試集

4.Feature scaling

normalization規范化處理(簡單講就是一組數據按照一定比例縮小或擴大至范數為1)
距離——采用簡單直觀的歐式距離( 反正又不用你算
 
from sklearn.preprocessing import StandardScaler  #導入庫 這個不知道可以去查查用法
scaler = StandardScaler()  
scaler.fit(X_train)

X_train = scaler.transform(X_train)  
X_test = scaler.transform(X_test) 

5.Training and Predictions  訓練預測

from sklearn.neighbors import KNeighborsClassifier  
classifier = KNeighborsClassifier(n_neighbors=5)    # k=5
classifier.fit(X_train, y_train)
y_pred=classifier.predict(X_test)

6.Evaluating the algorithm

from sklearn.metrics import classification_report, confusion_matrix  
print(confusion_matrix(y_test, y_pred))  
print(classification_report(y_test, y_pred))  

預期輸出結果如下:

The output of the above script looks like this:
[[11  0  0]
   0 13  0]
   0  1  6]]
                 precision   recall   f1-score   support

    Iris-setosa       1.00     1.00       1.00        11
Iris-versicolor       1.00     1.00       1.00        13  
 Iris-virginica       1.00     1.00       1.00         6
avg/total 1.00 1.00 1.00 30

7.Comparing Error Rate with the K Value

把各種可能的k的取值,及其對應的分類誤差率(error rate)繪制在一張圖上。

 

error = []

# Calculating error for K values between 1 and 40
for i in range(1, 40):  
    knn = KNeighborsClassifier(n_neighbors=i)
    knn.fit(X_train, y_train)
    pred_i = knn.predict(X_test)
    error.append(np.mean(pred_i != y_test))
plt.figure(figsize=(12, 6))  
plt.plot(range(1, 40), error, color='red', linestyle='dashed', marker='o',  
         markerfacecolor='blue', markersize=10)
plt.title('Error Rate K Value')  
plt.xlabel('K Value')  
plt.ylabel('Mean Error') 

輸出結果預期如下:

   

                                     

 

       至此, 這套knn算法就實現了,現在體會到python工具包的強大了,好多底層的算法都不需要自己寫函數實現。

       搜了一下用C實現knn,代碼很繁瑣,但是很直觀,每一步干什么很清楚。python寫的話呢,如果對這些庫不熟悉,那就很頭禿了,需要一個一個函數查它的用法,不過,如果真的掌握了可以更快更輕松地實現。就是這樣子了!

       剛開始做的時候看到一堆代碼,一臉懵逼,感覺在看文言文一樣。其實只要耐心看,真的只是了解一點庫函數用法,算法本身思想很簡單!

       第一個機器學習算法筆記,開心!

 
 
 


免責聲明!

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



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