一、KNN演算法概述
kNN分類演算法本身簡單有效,既可以分類又可以進行迴歸。
核心原理:已知樣本資料集的每一個資料的特徵和所屬的分類,將新資料的特徵與樣本資料進行比較,找到最相似(最近鄰)的K(k<=20)個資料,選擇K個資料出現次數最多的分類,作為新資料的分類。
簡而言之: 物以類聚,人以群分 二、舉例:
如下圖所示:
藍色方塊和紅色三角是已知類別,綠色圓圈是我們的待測資料,需要對它進行分類。
如果K=3,綠色圓點的最近3個鄰居是2個紅色三角和1個藍色方塊,所以少數服從多數,綠色圓點屬於三角形這一類。
如果k=5,綠色圓點的最近5個林俊是2個紅色三角和3個藍色,所以綠色圓點屬於藍色這一類。
距離計算:
比較常用的距離計算方法為歐式距離。歐式距離:樣本 與樣本 之間的歐式距離為: 三、演算法流程: 計算已知類別資料集中的點與當前點的距離 按照距離依次排序 選取當前點距離最小的k個點 確定前K個點所在類別的出現機率 返回當前K個點出現頻率最高的類別作為當前點預測分類 四、代碼實現:
# 計算待測點與樣本點的距離def classify0(inX, dataSet, lables, k): dataSetSize = dataSet.shape[0] diffmat = tile(inX, (dataSetSize, 1)) - dataSet # 將待測的點轉換成與樣本資料相等行數的矩陣,然後再與樣本資料的矩陣進行相減 sqDiffMat = diffmat ** 2 # 將樣本點與待測點的差值進行平方和計算 sqDistances = sqDiffMat.sum(axis=1) # 計算兩點之間的距離和 distances = sqDistances ** 0.5 # 對和進行開根運算 sortedDistIndicies = distances.argsort() # 對兩點間的距離進行從小到大排序 # print sortedDistIndicies classCount = {} for i in range(k): # 選擇距離最小的k個點 volteIlabel = lables[sortedDistIndicies[i]] classCount[volteIlabel] = classCount.get(volteIlabel, 0) + 1 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0]
五、總結
優點
KNN 演算法本身簡單有效,它是一種lazy-learning 演算法。不需要使用訓練集進行訓練,訓練時間複雜度為0。
缺陷:
計算複雜度高:需要與每一個樣本資料計算距離,所以KNN的分類時間複雜度為O(n),與樣本總數成正比。
K值的設定:K值的選取對演算法的結果影響很大,如果K設定過小會降低分類精度,如果K值設定過大,且測試樣本屬於訓練集中包含資料較少的類,則會增加雜訊,降低分類效果。通常,K值的設定採用交叉檢驗的方式(以K=1為基準,且K<=20)經驗規則:K一般低於訓練樣本數的平方根。
資料樣本不平衡情況下導致誤差較大:當樣本不平衡時,如一個樣本的容量很大,而其他樣本容量很小時,有可能導致輸入一個新樣本時,該樣本的K個鄰置中大容量的樣本佔多數。解決:不同的樣本給予不同權重項。