KNN(K-Nearest Neighbor)最近鄰規則分類


 

在學習KNN之前中,我們需要帶着幾個問題去學習,當你把這些問題都解決了,KNN你已經掌握的差不多了。

1,問題描述:

  1,KNN的原理是什么?

  2,KNN算法的時間復雜度,和空間復雜度怎么樣?

  3,K值如何選取,取多大合適?

  4,計算兩個樣本之間的距離,采用哪種距離計算方式好?

  5,類別如何判定最合適?

  6,計算量太大怎么辦?

  7,假設樣本中,類型分布非常不均勻,這又該怎么辦?

 

2,K近鄰原理:

  kNN原理很簡單,通過計算待分類樣本與已知類別樣本之間的距離,找到距離待分類最近的K個已知類別的樣本,然后根據少數“服從多數”的判決原則,統計K個樣本中各類樣本出現的次數,出現次數最多的樣本即為待分類樣本的類別。

 

圖1  K近鄰分類

上圖中要確定測試樣本綠色屬於藍色還是紅色。顯然,當K=3時,將以1:2的投票結果分類於紅色;而K=5時,將以3:2的投票結果分類於藍色。

我們不禁會反問,你這樣的分類准確嗎?為什么不同的K值會得到不同的分類結果?你有什么理由說待分類的樣本與K個樣本中出現次數最多樣本是同一類?

 

對於這三個問題,我說下我的理解,

  我們都聽說過這句話“同一類樣本之間差異較小,不同類之間差異較大”,這差異通過什么來體現呢?在KNN算法中,樣本特征之間差異,主要通過特征之間的“距離”來體現,距離體現了他們之間的相似性,在多維空間中,不同類的樣本散布於多維空間之中,同類樣本總是聚集在一起,本質是講就是他們的特征存在相似性,不同類樣本之間是彼此分離的。

 

   圖2 KNN概念圖

因此通過計算待分類樣本與已分類樣本之間的距離來進行分類是可靠的。對於分類決策主要是根據“少數服從多數” 本質上講就是哪類樣本與待分類樣本最相似,就分給哪類。(對於這種判決准則,不一定適用於所有情況,后面會有討論

 

關於為什么K取不同的值,分類結果可能不一致,這主要體現KNN在類邊界上,分類結果會隨K的取值不同,分類結果不穩定,但對於非類邊界分類准確率還是很高的。 

K值選取:

  關於K的取值是K-最近鄰算法中的一大難題,沒有特定的經驗公式來告訴我們K應該取多大?K值如果選取的太小,模型太復雜,K值選取的太大的話,又會導致分類模糊。K的取值與實際背景有關,與你數據分析的目標……那么K值到底怎么選取呢?既然K值這么麻煩有沒有一些常規選取K值的方法,答案是肯定的。

經驗規則:k一般低於訓練樣本數的平方根。

常用方法有Cross Validation,貝葉斯准則, bootstrap……

大家如果想了解更多關於如何用Cross Validation選擇K值可以參照一下兩篇博客:

(1)KNN算法實現及其交叉驗證:http://www.jianshu.com/p/48d391dab189

(2)機器學習-CrossValidation交叉驗證Python實現:http://blog.csdn.net/dream_angel_z/article/details/47110077

 

 

上面提到了類與類之間的相似性通過距離來體現,下面我們看下有哪些距離:

3,距離定義:

1)歐式距離

歐氏距離是最常見的距離度量,衡量的是多維空間中各個點之間的絕對距離。

 

因為計算是基於各維度特征的絕對數值,所以歐氏度量需要保證各維度指標在相同的刻度級別,比如對身高(cm)和體重(kg)兩個單位不同的指標使用歐式距離可能使結果失效。

2馬氏距離:馬氏距離能夠緩解由於屬性的線性組合帶來的距離失真,是數據的協方差矩陣。

 

 

3)曼哈頓距離:

 

曼哈頓距離來源於城市區塊距離,是將多個維度上的距離進行求和后的結果。

4)切比雪夫距離

 

切比雪夫距離起源於國際象棋中國王的走法,我們知道國際象棋國王每次只能往周圍的8格中走一步,那么如果要從棋盤中A格(x1, y1)走到B格(x2, y2)最少需要走幾步?擴展到多維空間,其實切比雪夫距離就是當p趨向於無窮大時的明氏距離。

5)閔氏距離:

 

閔氏距離是歐氏距離的推廣,是對多個距離度量公式的概括性的表述。r取值為2式為曼哈頓距離 ;r取值為1時為歐式距離。

6)平均距離

 

7弦距離:

 

 

 

8)測地距離

 

 

關於距離選擇:

高維度對距離衡量的影響:眾所周知當變量數越多,歐式距離的區分能力就越差。

變量值域對距離的影響:值域越大的變量常常會在距離計算中占據主導作用,因此應先對變量進行標准化。

比較常用的是選用歐式距離。可是這個距離真的具有普適性嗎?《模式分類》中指出歐式距離對平移是敏感的,這點嚴重影響了判定的結果。在此必須選用一個對已知的變換(比如平移、旋轉、尺度變換等)不敏感的距離度量。書中提出了采用切空間距離(tangent distance)來替代傳統的歐氏距離。

(引自:http://blog.csdn.net/liqiming100/article/details/77851226【kNN(K-Nearest Neighbor)最鄰近規則分類中的三大問題(K值選取、距離度量、分類決策規則)】)

 

最近鄰法介紹:

切空間距離定義:

 

(引自:楊劍. 基於局部切距離的近鄰法[A]. 中國自動化學會智能自動化專業委員會、中國科學院自動化研究所.2005年中國智能自動化會議論文集[C].中國自動化學會智能自動化專業委員會、中國科學院自動化研究所:,2005:6.)

 

4,算法實現步驟:

簡單來說,KNN可以看成:有那么一堆你已經知道分類的數據,然后當一個新數據進入的時候,就開始跟訓練數據里的每個點求距離,然后挑離這個訓練數據最近的K個點看看這幾個點屬於什么類型,然后用少數服從多數的原則,給新數據歸類。

具體步驟如下

  step.1---計算未知樣本和每個訓練樣本的距離dist ;

  step.2---對dist從小到大排序;

  step.3---取出距離從小到大的K個訓練樣本,作為K-最近鄰樣本;

  step.4---統計K-最近鄰樣本中每個類標號出現的次數

  step.5---選擇出現頻率最大的類標號作為未知樣本的類標號,

 

5,算法復雜度分析:

   KNN算法簡單有效,但沒有優化的暴力法那樣效率容易達到瓶頸。如樣本個數為N,特征維度為D的時候,該算法時間復雜度呈O(DN)增長。所以通常KNN的實現會把訓練數據構建成K-D Tree(K-dimensional tree),構建過程很快,甚至不用計算D維歐氏距離,而搜索速度高達O(D*log(N))。不過當D維度過高,會產生所謂的”維度災難“,最終效率會降低到與暴力法一樣。因此通常D>20以后,最好使用更高效率的Ball-Tree,其時間復雜度為O(D*log(N))。人們經過長期的實踐發現KNN算法雖然簡單,但能處理大規模的數據分類,尤其適用於樣本分類邊界不規則的情況。最重要的是該算法是很多高級機器學習算法的基礎。

(KNeighbors Classifier可以設置3種算法:‘brute’,‘kd_tree’,‘ball_tree’。如果不知道用哪個好,設置‘auto’讓KNeighborsClassifier自己根據輸入去決定。)

(引用:http://blog.csdn.net/lsldd/article/details/41357931)

 

6,類別如何判定最合理?

  投票法沒有考慮近鄰的距離的遠近,距離更近的近鄰也許更應該決定最終的分類,所以加權投票法更恰當一些。

 

7,KNN實現:

KNN----Python實現:

 

1.    #coding:utf-8  
2.      
3.    from numpy import *  
4.    import operator  
5.      
6.    ##給出訓練數據以及對應的類別  
7.    def createDataSet():  
8.        group = array([[1.0,2.0],[1.2,0.1],[0.1,1.4],[0.3,3.5]])  
9.        labels = ['A','A','B','B']  
10.        return group,labels  
11.      
12.    ###通過KNN進行分類  
13.    def classify(input,dataSe t,label,k):  
14.        dataSize = dataSet.shape[0]  
15.        ####計算歐式距離  
16.        diff = tile(input,(dataSize,1)) - dataSet  
17.        sqdiff = diff ** 2  
18.        squareDist = sum(sqdiff,axis = 1)###行向量分別相加,從而得到新的一個行向量  
19.        dist = squareDist ** 0.5  
20.          
21.        ##對距離進行排序  
22.        sortedDistIndex = argsort(dist)##argsort()根據元素的值從大到小對元素進行排序,返回下標  
23.      
24.        classCount={}  
25.        for i in range(k):  
26.            voteLabel = label[sortedDistIndex[i]]  
27.            ###對選取的K個樣本所屬的類別個數進行統計  
28.            classCount[voteLabel] = classCount.get(voteLabel,0) + 1  
29.        ###選取出現的類別次數最多的類別  
30.        maxCount = 0  
31.        for key,value in classCount.items():  
32.            if value > maxCount:  
33.                maxCount = value  
34.                classes = key  
35.      
36.        return classes  

 

引自:https://www.cnblogs.com/ybjourney/p/4702562.html

 

8,計算量太大怎么辦?

濃縮技術(condensing)
編輯技術(editing)

9,假設樣本中,各類分布不均勻,如何處理:

 (參考:訓練樣本分布不均的KNN分類改進算法_丁應逵)

10,K-最近鄰優缺點分析:

相比於貝葉斯、決策樹、支持向量積、KNN,神經網絡等分類算法,KNN是一種基於實例的學習算法,它不同於貝葉斯、決策樹等算法,KNN不需要訓練,當有新的實例出現時,直接在訓練數據集中找k個最近的實例,把這個新的實例分配給這k個訓練實例中實例數最多類。KNN也成為懶惰學習,它不需要訓練過程,在類標邊界比較整齊的情況下分類的准確率很高。

下面先給大家介紹下KNN的優點:

  • 簡單,易於理解,易於實現,無需估計參數,無需訓練;
  • 適合對稀有事件進行分類;
  • 特別適合於多分類問題(multi-modal,對象具有多個類別標簽), kNN比SVM的表現要好。

 

缺點也很明顯:

  • 懶惰算法,對測試樣本分類時的計算量大,內存開銷大,評分慢;
  • 當樣本不平衡時,如一個類的樣本容量很大,而其他類樣本容量很小時,有可能導致當輸入一個新樣本時,該樣本的K個鄰居中大容量類的樣本占多數;
  • 可解釋性較差,無法給出決策樹那樣的規則。

11,KNN案例分析:

KNN算法實現及其交叉驗證:http://www.jianshu.com/p/48d391dab189

機器學習KNN實戰: https://zhuanlan.zhihu.com/p/23191325

 

參考文獻:

http://blog.csdn.net/zhaoshuaijiang/article/details/40509227

http://blog.csdn.net/lsldd/article/details/41357931

http://blog.csdn.net/xlm289348/article/details/8876353

http://zhaoshuaijiang.com/2014/10/18/knn_kmeans/

https://www.cnblogs.com/fengfenggirl/archive/2013/05/27/knn.html

https://www.cnblogs.com/sumuncle/p/5611705.html

http://blog.csdn.net/haluoluo211/article/details/78177510

https://www.cnblogs.com/ybjourney/p/4702562.html

 

模型中各種距離度量的表示 :http://www.jianshu.com/p/607c64556a08

KNN算法實現及其交叉驗證:http://www.jianshu.com/p/48d391dab189


免責聲明!

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



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