1. 程式人生 > >K近鄰法(KNN)原理小結

K近鄰法(KNN)原理小結

tel .get ack 索引 觀察 運用 oob import port

  

一、緒論

   K近鄰法(k-nearest neighbors,KNN)是一種很基本的機器學習方法了,在我們平常的生活中也會不自主的應用。比如,我們判斷一個人的人品,只需要觀察他來往最密切的幾個人的人品好壞就可以得出了。這裏就運用了KNN的思想。KNN方法既可以做分類,也可以做回歸,這點和決策樹算法相同。

   KNN做回歸和分類的主要區別在於最後做預測時候的決策方式不同。KNN做分類預測時,一般是選擇多數表決法(少數服從多數),即訓練集裏和預測的樣本特征最近的K個樣本,預測為裏面有最多類別數的類別。而KNN做回歸時,一般是選擇平均法,即最近的K個樣本的樣本輸出的平均值作為回歸預測值。由於兩者區別不大,雖然本文主要是講解KNN的分類方法,但思想對KNN的回歸方法也適用。

二、KNN算法三要素

KNN算法我們主要要考慮三個重要的要素,對於固定的訓練集,只要這三點確定了,算法的預測方式也就決定了。這三個最終的要素是k值的選取,距離度量的方式和分類決策規則。

    對於分類決策規則,一般都是使用前面提到的多數表決法。所以我們重點是關註與k值的選擇和距離的度量方式。

    對於k值的選擇,沒有一個固定的經驗,一般根據樣本的分布,選擇一個較小的值,可以通過交叉驗證選擇一個合適的k值。

    選擇較小的k值,就相當於用較小的領域中的訓練實例進行預測,訓練誤差會減小,只有與輸入實例較近或相似的訓練實例才會對預測結果起作用,與此同時帶來的問題是泛化誤差會增大,換句話說,K值的減小就意味著整體模型變得復雜,容易發生過擬合;


    選擇較大的k值,就相當於用較大領域中的訓練實例進行預測,其優點是可以減少泛化誤差,但缺點是訓練誤差會增大。這時候,與輸入實例較遠(不相似的)訓練實例也會對預測器作用,使預測發生錯誤,且K值的增大就意味著整體的模型變得簡單。
    一個極端是k等於樣本數m,則完全沒有分類,此時無論輸入實例是什麽,都只是簡單的預測它屬於在訓練實例中最多的類,模型過於簡單。

    1.對於距離的度量,我們有很多的距離度量方式,但是最常用的是歐式距離,即對於兩個n維向量x和y,兩者的歐式距離定義為:

          技術分享圖片

      大多數情況下,歐式距離可以滿足我們的需求,我們不需要再去操心距離的度量。

    2.當然我們也可以用他的距離度量方式。比如曼哈頓距離,定義為:

          技術分享圖片

    3.更加通用點,比如閔可夫斯基距離(Minkowski Distance),定義為:

          技術分享圖片

    可以看出,歐式距離是閔可夫斯基距離距離在p=2時的特例,而曼哈頓距離是p=1時的特例。

三、算法的實現(這個機器學習中的,只不過我加了自己的註釋 看起來方便)

  1.對於未知類別屬性的數據集中的每個點依次執行以下操作步驟:

    (1)計算已知類別數據集中的點(或者特征向量),之間的距離。

    (2)按照距離遞增次序排列(用argsort()排序,而不用sort()排序,argsort()是返回的是數值對應得索引,sort()返回得是數值直接排序得結果)。

    (3)選取與當前點距離最小哦啊的K個點。

    (4)確定前K個點所在得類別得出現頻率(一般是建立一個字典,按照 {類別:出現得次數} 組合)

    (5)返回前K個點出現頻率最高得類別作為當前點得預測分類(一般是對保存頻率的字典進行排序,用sorted(),具體用法可查官網:http://www.runoob.com/python/python-func-sorted.html)

    (回歸的話是返回前k個點的平均值,在這之前一般會對特征向量進行預處理,標準化或者歸一化)

import numpy as np

datas=np.array([[1,2],[3,4],[5,6],[6,7]])  #數據,現在的數據是一個坐標
lavels=[A,A,B,C]  #種類

#K近鄰分類  K-表示與當前點距離最小的K個點
def classify(X,Datas,Lavels,K):
    datasize=Datas.shpae[0]  #獲取數據的維度 行數
    #距離計算
    newdatas=np.tile(X,(datasize,1))-Datas
    #tile()用來就是把數組沿各個方向復制 
    #第二個參數是方向上的復制的格式 如果是一個數,橫向復制,元組的話,第一個數是縱向復制,第二個是橫向復制
    
    distance=(newdatas**2).sum(axis=1)**0.05
    #對距離進行排序
    sortdistances=distances.argsort()
    #argsort()不是直接對數值進行排序,是對數值大小對應下的索引進行排序   例如[2,3,1]---[2,0,1]
    #sort()是對數值直接排序的
    
    classCount={}  #是對選取出來K個數據類別進行統計  例如{‘A’:2.‘B’:1}
    for i in range(k):
        votelavel=Lavels[sortdistances[i]]  #根據上面對數值由小到大對應的索引排序從而選擇出來對應的類別
        classCount[votelavel]=classCount.get(votelavel,0)+1
        #字節的理解這樣
        #classCount[‘A‘]=0   classCount.get(‘A‘)+1
    sortclasscount=sorted(classCount.items(),key=lambda k:k[1],reverse=True)  
    #sorted 可以對所有可叠代的對象進行排序操作  reverse=True  降序
    return sortclasscount[0][0]  #選取降序之後第一個頻率出現最大的種類 

K近鄰法(KNN)原理小結