KNN算法原理以及代碼實現


 

一、KNN簡述

KNN是比較經典的算法,也是是數據挖掘分類技術中最簡單的方法之一。

KNN的核心思想很簡單:離誰近就是誰。具體解釋為如果一個實例在特征空間中的K個最相似(即特征空間中最近鄰)的實例中的大多數屬於某一個類別,則該實例也屬於這個類別。

換個說法可能更好理解,比如一個一定范圍的平面隨機分布着兩種顏色的樣本點,在這個平面內有個實例點不知道它是什么顏色,因此通過它周邊的不同顏色的點分布情況進行推測,假設取K=3,意思是在離這個實例點最近的樣本點中去前三個最近的, 然后看這三個當中那種類別占比大,就判斷該實例點屬於那個類別的,當k=5的時候也一樣這樣判斷,因此k的取值很關鍵,通常不會超過20。當然,因為每個樣本有多個特征,因此實際工作中,這個‘平面’就是三維甚至是多維的,道理是一樣的。如圖:

二、KNN算法原理

在KNN中,通過計算對象間距離來作為各個對象之間的非相似性指標,避免了對象之間的匹配問題,在這里距離一般使用歐氏距離或曼哈頓距離:

對KNN算法的思想總結一下:就是在訓練集中數據和標簽已知的情況下,輸入測試數據,將測試數據的特征與訓練集中對應的特征進行相互比較,找到訓練集中與之最為相似的前K個數據,則該測試數據對應的類別就是K個數據中出現次數最多的那個分類,其算法的描述為:

1)計算測試數據與各個訓練數據之間的距離;

2)按照距離的遞增關系進行排序;

3)選取距離最小的K個點;

4)確定前K個點所在類別的出現頻率;

5)返回前K個點中出現頻率最高的類別作為測試數據的預測分類。

 

三、KNN算法優缺點以及算法改進

優缺點:

1、簡單,易於理解,是一個天然的多分類器;

2、不需要龐大的樣本數據也可以完成一個簡單的分類;

3、不需要訓練和求解參數(既是優點也是缺點);

4、數據量大的時候,計算量也非常大(樣本多,特征多);

5、不平衡樣本處理能力差;

6、並沒有學習和優化的過程,嚴格來說不算是機器學習。

改進:

進行加權平均,離得近的樣本給予更大的權重,離得遠的樣本使其權重變小。

 

四、KNN代碼實現

import numpy as np
import pandas as pd
import matplotlib.pylab as plt
data_=pd.read_csv('vehicle.csv')
print(data_)
feature=np.array(data_.iloc[:,0:2])  # 將參數與特征進行分離,返回數據類型為數組,這里只拿去前兩列
#print(feature)
labels = data_['label'].tolist()   # 將'label'標簽提取出來轉換為列表類型,方便后續使用
#print(labels)

# 數據可視化
plt.scatter(data_['length'][data_['label']=='car'],data_['width'][data_['label']=='car'],c='y')  #先取length的數值,里面有car和truck的長度,再單獨取label那一行為car的值
plt.scatter(data_['length'][data_['label']=='truck'],data_['width'][data_['label']=='truck'],c='r')  #先取width的數值,里面有car和truck的長度,再單獨取label那一行為truck的值
#print(data_['length'])
#print(plt.show())

test = [4.7,2.1] # 待測樣本

numSamples = data_.shape[0]  # 讀取矩陣的長度,這里是讀取第一維的長度# 運行結果:150
diff_= np.tile(test,(numSamples,1)) #這里表示test列表豎向重復150次,橫向重復1一次,組成一個素組
# numpy.tile(A,B)函數:A=[4.7,2.1],B=(3,4),意思是列表A在行方向(從上到下)重復3次,在列放心(從左到右)重復4次
diff = diff_-feature  # 利用這里的實驗值和樣本空間里的每一組數據進行相減
squreDiff = diff**2   # 將差值進行平方
squreDist = np.sum(squreDiff,axis=1)  # 每一列橫向求和,最后返回一維數組
distance = squreDist ** 0.5 
sorteDisIndices = np.argsort(distance)  # 排序
k=9  # k個最近鄰
classCount = {}  # 字典或者列表的數據類型需要聲明
label_count=[]   # 字典或者列表的數據類型需要聲明
for i in range(k):
    voteLabel = labels[sorteDisIndices[i]]
    classCount[voteLabel] = classCount.get(voteLabel,0) + 1
    label_count.append(voteLabel)

from collections import Counter
word_counts = Counter(label_count)
top = word_counts.most_common(1)   # 返回數量最多的值以及對應的標簽
#print(word_counts)
#print(top)


# 利用sklearn進行實現
import numpy as np
import pandas as pd
import matplotlib.pylab as plt
data_
=pd.read_csv('vehicle.csv') feature=np.array(data_.iloc[:,0:2]) # 將參數與特征進行分離,返回數據類型為數組,這里只拿去前兩列 labels = data_['label'].tolist() # 將'label'標簽提取出來轉換為列表類型,方便后續使用 from sklearn.model_selection import train_test_split feautre_train,feautre_test,label_train,label_test=train_test_split(feature,labels,test_size=0.2) # 指出訓練集的標簽和特征以及測試集的標簽和特征,0.2為參數,對測試集以及訓練集按照2:8進行划分 from sklearn.neighbors import KNeighborsClassifier model=KNeighborsClassifier(n_neighbors= 9) model.fit(feautre_train,label_train) # 現在只需要傳入訓練集的數據 prediction=model.predict(feautre_test) #print(prediction) labels=['car','truck'] classes=['car', 'truck'] from sklearn.metrics import classification_report result_=classification_report(label_test,prediction,target_names = classes,labels=labels,digits=4) # target_names:類別;digits:int,輸出浮點值的位數 print(result_)

 


免責聲明!

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



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