原理
kNN(k近鄰算法)的基本思想就是選擇距離待分類點最近的K個點,統計這K個點中出現的分類的概率, 出現概率最高的分類即爲待分類點的分類
源碼
from numpy import *
import operator
def createDataSet(): # create data set
group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
labels = ['A', 'A', 'B', 'B']
return group,labels
def classify0(inX, dataSet, labels, k): #k-NN classify
"""
:param inX: 用於分類的輸入向量
:param dataSet: 輸入的訓練樣本集
:param labels: 標籤向量
:param k: 用於選擇最近鄰居的數目
:return:
"""
# 用歐氏距離計算當前點與樣本集中所有點的距離
dataSetSize = dataSet.shape[0] #獲取數組維度的長度 (列或行數)
diffMat = tile(inX, (dataSetSize, 1)) - dataSet # tile是重複次數,如tile([0,0],(2,3)),是在重複行2次,列3次,結果是[[0 0 0 0 0 0] [0 0 0 0 0 0]]
sqDiffMat = diffMat ** 2 # 所有元素平方
sqDistances = sqDiffMat.sum(axis = 1) # axis = none 表示所有元素相加, axis = 0表示每一列所有元素相加, axis = 1表示每一行所有元素相加
distances = sqDistances**0.5 # 開方得到待求點到數據集中所有點的距離
sortedDistIndicies = distances.argsort() # 返回的是從小到大排序後的原數據的索引, 如原數據爲[1, 5, 3, 0], 調用argsort()方法返回的是[3, 0, 2, 1]
classCount = {}
# 選擇距離最小的k個點
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]] # 得到前k個標籤
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 統計label出現的次數,默認值爲0
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) # 根據標籤出現次數從高到低排序
return sortedClassCount[0][0]
if __name__ == "__main__":
group, labels = createDataSet()
result = classify0([0, 0], group, labels, 3)
print(result)
加權kNN
有一個問題就是該算法給所有的近鄰分配相等的權重,這個還可以這樣改進,就是給更近的鄰居分配更大的權重(你離我更近,那我就認爲你跟我更相似,就給你分配更大的權重),而較遠的鄰居的權重相應地減少,取其加權平均。需要一個能把距離轉換爲權重的函數,gaussian函數是一個比較普遍的選擇,下圖可以看到gaussian函數的衰減趨勢。
高斯函數
高斯函數的圖形在形狀上像一個倒懸着的鐘。參數a指高斯曲線的峯值,b爲其對應的橫座標,c即標準差(有時也叫高斯RMS寬值),它控制着“鍾”的寬度。
交叉驗證
使用交叉驗證進行算法模型評估以及k值的選取