KNN從原理到實現

2021-07-30 07:44:15 字數 4091 閱讀 5453

引文:決策樹和基於規則的分類器都是積極學習方法(eager learner)的例子,因為一旦訓練資料可用,他們就開始學習從輸入屬性到類標號的對映模型。乙個相反的策略是推遲對訓練資料的建模,直到需要分類測試樣例時再進行。採用這種策略的技術被稱為消極學習法(lazy learner)。最近鄰分類器就是這樣的一種方法。

注:knn既可以用於分類,也可以用於回歸。

首先給出一張圖,根據這張圖來理解最近鄰分類器,如下: 

根據上圖所示,有兩類不同的樣本資料,分別用

藍色的小正方形

和紅色的小三角形

表示,而圖正中間的那個

綠色的圓

所標示的資料則是待分類的資料。也就是說,現在, 我們不知道中間那個綠色的資料是從屬於哪一類(藍色小正方形or紅色小三角形),下面,我們就要解決這個問題:給這個綠色的圓分類。

我們常說,物以類聚,人以群分,判別乙個人是乙個什麼樣品質特徵的人,常常可以從他or她身邊的朋友入手,所謂觀其友,而識其人。我們不是要判別上圖中那個綠色的圓是屬於哪一類資料麼,好說,從它的鄰居下手。但一次性看多少個鄰居呢?從上圖中,你還能看到:

於此我們看到,當無法判定當前待分類點是從屬於已知分類中的哪一類時,我們可以依據統計學的理論看它所處的位置特徵,衡量它周圍鄰居的權重,而把它歸為(或分配)到權重更大的那一類。這就是k近鄰演算法的核心思想。其關鍵還在於k值的選取,所以應當謹慎。

knn演算法中,所選擇的鄰居都是已經正確分類的物件。該方法在定類決策上只依據最鄰近的乙個或者幾個樣本的類別來決定待分樣本所屬的類別。

knn 演算法本身簡單有效,它是一種 lazy-learning 演算法,分類器不需要使用訓練集進行訓練,訓練時間複雜度為0。knn 分類的計算複雜度和訓練集中的文件數目成正比,也就是說,如果訓練集中文件總數為 n,那麼 knn 的分類時間複雜度為o(n)。

前面的例子中強調了選擇合適的k值的重要性。如果太小,則最近鄰分類器容易受到訓練資料的雜訊而產生的過分擬合的影響;相反,如果k太大,最近分類器可能會誤會分類測試樣例,因為最近鄰列表中可能包含遠離其近鄰的資料點。(如下圖所示) 

k較大時的最近鄰分類

可見,k值的選取還是非常關鍵。

演算法描述

k近鄰演算法簡單、直觀:給定乙個訓練資料集(包括類別標籤),對新的輸入例項,在訓練資料集中找到與該例項最鄰近的k個例項,這k個例項的多數屬於某個類,就把該輸入例項分為這個類。下面是knn的演算法步驟。

演算法步驟如下所示:

對每個測試樣例z=

(x′,

y′) ,演算法計算它和所有訓練樣例(x

,y)屬

於d之間的距離(如歐氏距離,或相似度),以確定其最近鄰列表dz

。如果訓練樣例的數目很大,那麼這種計算的開銷就會很大。不過,可以使索引技術降低為測試樣例找最近鄰是的計算量。

特徵空間中兩個例項點的距離是兩個例項相似程度的反映。

一旦得到最近鄰列表,測試樣例就可以根據最近鄰的多數類進行分類,使用多數表決方法。

k值選擇

k值對模型的**有著直接的影響,如果k值過小,**結果對鄰近的例項點非常敏感。如果鄰近的例項恰巧是雜訊資料,**就會出錯。也就是說,k值越小就意味著整個模型就變得越複雜,越容易發生過擬合。

相反,如果k值越大,有點是可以減少模型的**誤差,缺點是學習的近似誤差會增大。會使得距離例項點較遠的點也起作用,致使**發生錯誤。同時,k值的增大意味著模型變得越來越簡單。如果k=n,那麼無論輸入例項是什麼,都將簡單的把它**為樣本中最多的一類。這顯然實不可取的。

在實際建模應用中,k值一般取乙個較小的數值,通常採用cross-validation的方法來選擇最優的k值。

knn.py(****《機器學習實戰》一書)

from numpy import *

import operator

class

knn:

defcreatedataset

(self):

group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])

labels = ['a','a','b','b']

return group,labels

defknnclassify

(self,testx,trainx,labels,k):

[n,m]=trainx.shape

#calculate the distance between testx and other training samples

difference = tile(testx,(n,1)) - trainx # tile for array and repeat for matrix in python, == repmat in matlab

difference = difference ** 2

# take pow(difference,2)

distance = difference.sum(1) # take the sum of difference from all dimensions

distance = distance ** 0.5

sortdiffidx = distance.argsort()

# find the k nearest neighbours

vote = {} #create the dictionary

for i in range(k):

ith_label = labels[sortdiffidx[i]];

vote[ith_label] = vote.get(ith_label,0)+1

#get(ith_label,0) : if dictionary 'vote' exist key 'ith_label', return vote[ith_label]; else return 0

sortedvote = sorted(vote.iteritems(),key = lambda x:x[1], reverse = true)

# 'key = lambda x: x[1]' can be substituted by operator.itemgetter(1)

return sortedvote[0][0]

k = knn() #create knn object

group,labels = k.createdataset()

cls = k.knnclassify([0,0],group,labels,3)

print cls

執行: 

1. 在python shell 中可以執行knn.py

>>>import os

>>>os.chdir("/home/liudiwei/code/data_miningknn/")

>>>execfile("knn.py")

輸出:b 

(b表示類別)

2.或者terminal中直接執行

$ python knn.py
3.也可以不在knn.py中寫輸出,而選擇在shell中獲得結果,i.e.,

>>>import knn

>>> knn.k.knnclassify([0,0],knn.group,knn.labels,3)

introduction to data mining 資料探勘導論

rachel zhang-k近鄰分類演算法實現 in python

附件(兩張自己的計算過程圖): 

圖1 knn演算法核心部分

圖2 knn計算過程

AdaBoost 從原理到實現

對於adaboost,可以說是久聞大名,據說在deep learning出來之前,svm和adaboost是效果最好的 兩個演算法,而adaboost是提公升樹 boosting tree 所謂 提公升樹 就是把 弱學習演算法 提公升 boost 為 強學習演算法 語自 統計學習方法 而其中最具代表...

AdaBoost 從原理到實現

對於adaboost,可以說是久聞大名,據說在deep learning出來之前,svm和adaboost是效果最好的 兩個演算法,而adaboost是提公升樹 boosting tree 所謂 提公升樹 就是把 弱學習演算法 提公升 boost 為 強學習演算法 語自 統計學習方法 而其中最具代表...

單點登入(SSO),從原理到實現

cookie sso認證中心發現使用者未登入,將使用者引導至登入頁面 使用者輸入使用者名稱密碼提交登入申請 sso認證中心校驗使用者資訊,建立使用者與sso認證中心之間的會話,稱為全域性會話,同時建立授權令牌 sso認證中心帶著令牌跳轉會最初的請求位址 系統1 系統1拿到令牌,去sso認證中心校驗令...