knn原理及其python實現
k近鄰
顧名思義,是k個最近鄰居。
比如說上圖,有2類,黑點和白點。那麼怎麼劃分星號?
按照knn來說,會尋找最近的幾個點。比如說,當k=3時,是2個黑點,1個白點,黑點投票多,所以被分爲黑點。當k=7的時候,是5個黑點,2個白點,黑點投票多,更加nearest黑點一些,也是被劃分爲黑點。
k必須是奇數不能爲偶數?
當然並不是絕對的。
比如當k=4時,黑點是2個,白點是2個,這樣怎麼劃分?
假設這四個點到星號點(測試點)的距離爲,前二者屬於黑點,後二者屬於白點。從距離來看,星號點距離黑點要近一點,應該劃分爲爲黑點。
所以我們可以這麼做,以距離做個加權,比如取距離倒數爲權重,越遠則權重越小。由此可見k爲偶數也是可以的。
knn for prediction
比如你要估計一個同學的成績,雖然不知道他的成績,但如果你知道他朋友(neighbors)的成績,我們可以取其k個朋友的成績的均值作爲他的成績
代碼測試
- 生成數據,使用sklearn方便點
#導入的包
import numpy as np
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
from collections import Counter
data = make_blobs(n_samples=200,centers=2)#生成數據,200個點,2類
X,y = data #劃分爲x,y
X_test = np.array([6,4])#測試數據,隨便寫的
#顯示
plt.scatter(X[:,0],X[:,1], c=y, cmap = plt.cm.spring, edgecolor='k')
plt.scatter(x[0],x[1], color = 'b')#測試點,藍色的點
plt.show()
生成的數據如下圖:
從圖中來看似乎離黃色更近。當然,由於沒固定種子,每次運行生成的數據都不一樣,這裏僅做展示。
- 計算測試點與所有樣本的歐氏距離:
distance = [sqrt(np.sum((X_train-x)**2)) for X_train in X]#計算距離,這裏是歐式距離
當然如果不嫌麻煩也可以這麼寫:
distance = []
for x_train in X:
d = sqrt(np.sum(x-x_train)**2)#倆個向量相減仍是向量,向量元素平方後求和
distance.append(d)
- 排序求最近鄰
nearest = np.argsort(distance)#對distance排序,返回的是增序的索引
k=3#定義k,即使用k個近鄰
top_k_y=[y[i] for i in nearest[:k]]#最近的k個測試集的類別
votes = Counter(top_k_y)#Counter是個類,
prediction = votes.most_common(1)[0][0]#帶參數1,意思是計算投票數最高的,設2即計算前2個最高的
的返回是個列表依次存放降序投票數目的列表。比如,帶入參數2(即計算投票數排前2名的結果),其結果如下:
運行:
votes.most_common(2)
結果:
[(1,2),(0,1)]
這表示屬於’1’類的緊鄰有2個,屬於’0’類的有1個,這種情況下,測試集就屬於0類了