K-NN(k-nearset neighbor)算法原理及其還沒有實現(python原始代碼實現和sk_learn實現)

機器學習有三寶:
一、模型
二、策略
三、算法

模型:
先來一波簡介:
K-NN是一種基本分類和迴歸方法,這篇博客我們只討論分類問題中的k近鄰法,kNN的輸入爲實例的特徵向量,對應於特徵空間的點;輸出爲實例的分類類別。
假設給定一個訓練數據集,其中類別已定。分類時,給定測試點,選定k個離測試點最近的點,得到k個結果,對結果進行投票,選擇票數最高的結果作爲分類結果。
因此,k近鄰法不像感知機一般,具有顯式的學習過程,它只是利用訓練數據集對特徵空間進行劃分
空間劃分
其實,KNN的原理很簡單,可以理解爲近朱者赤近墨者黑。
KNN的三個基本要素:k值的選定,距離度量,分類決策規則
準備:訓練集T={(x1,y1),(x2,y2),(x3,y3),…,(xn,yn)}
其中,xi∈X∈Rn,爲實例的特徵向量,yi∈Y={c1,c2,c3,…,cn}爲分類類別
輸出爲實例x所屬的類y
接下里便是上文所提到的投票機制了

k近鄰的特殊情況是k=1時,成爲最近鄰算法,對於輸入實例x的最近鄰的點作爲輸入實例的類別

距離度量:
常見的距離度量有歐式距離,但也可以是更常見的Lp距離,Minkowski 距離
這次,我們聊聊Lp距離:
設特徵空間X是n維實數的向量空間Rn,xi,xj∈X,xi =(xi1,xi2,xi3,…xin)T,
xj =(xj1,xj2,xj3,…xjn)T,則xi,xj的Lp距離定義爲
Lp距離定義(p>=1)

當p=2時,就是我們常說的歐式距離
當p=1時,就是曼哈頓距離
當p=無窮大時,就是各個座標距離的最大值,即
在這裏插入圖片描述
爲什麼P取無窮時,會是這個結果?
這個我用python代碼證明:
通過繪製散點圖可以看到, 當p=無窮時,是一個直線,當p = 2時,會是一個圓
p=10w
p=2
python代碼證明走起:

import matplotlib.pyplot as plt
import numpy as np
def Sum(p,xi,xj):#xj始終爲0,0,0....
    sum = 0
    if(len(xi)!=len(xj)):
        print("their len has to be same!")
    else:
        temp_sum = 0
        for i in range(len(xi)):
            temp_sum += (xi[i]-xj[i])**p
        sum = pow(temp_sum,1/p)
        return sum
if __name__=="__main__":
    yi = [0,0]
    i = 0.01
    zi = []
    xi = [i,0]
    while i < 1.01:
        temp = 0
        while abs(Sum(2,xi,yi)-1)>0.08: #設定閾值,這個浮點數0.08的設置關係到散點圖能不能很好的模擬圖像
            temp = temp + 0.01
            xi = [i,temp]
        print(Sum(2,xi,yi))
        print(xi)
        zi.append(xi[1])
        i += 0.01
        xi=[i,temp]
        print(i)
    Xj = np.arange(0,1,0.01)
    Xi = zi
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    ax1.set_title('Lp')
    # 設置X軸標籤
    plt.xlabel('Xj')
    # 設置Y軸標籤
    plt.ylabel('Xi')
    # 畫散點圖
    ax1.scatter(Xj, Xi, c='r', marker='o')
    plt.show()

假定|xi|=2,xj=[0,0],距離爲1
則繪圖如下:
在這裏插入圖片描述
上面的代碼只有第一象限的結果,關於p=無窮時,代碼裏實現的也是基於xi1的圖像,同理,當我們基於xi2進行繪圖時,將產生一條垂直於x軸的直線。
關於k值的選擇,這裏再提一下:這篇博客只考慮k=1時的情況。但是我們實際應用的時候,可能還要考慮取其他k值,k值一般取一個比較小的數值,通常採用交叉驗證來選取最優的k值

分類決策規則:
kNN往往是是多數表決,即由輸入實例的k個鄰近的訓練例子中的多數類決定輸入實例的類,多數表決等價於經驗風險最小化
證明如下:P(Y ≠ f(x))= 1 - P(Y = f(x)),則誤分類率:(I是指示函數,當yi=cj時,取值爲1,否則爲0)
誤分類率
要使誤分類率最小,等價於要在這裏插入圖片描述
最大,所以多數表決等價於經驗風險最小化
實現:
構建kd樹,搜索kd樹
開始種樹 忄忄忄忄忄:
kd 樹是二叉樹,表示對k維空間的劃分,構建kd樹相當於不斷地用垂直座標軸的超平面將k維空間進行劃分,構成一系列的k維超矩形區域,kd樹的每一個結點對應於一個k維超矩形區域。
算法:
在這裏插入圖片描述
在這裏插入圖片描述
撿個栗子來看看:
T ={(2,3)T,(5,4)T,(9,6)T,(4,7)T,(8,1)T,(7,2)T} (後面的T表示轉置矩陣)
構建第一步: 以xi1作爲判斷標準:
排序後,取(5,4)T, (7,2)T, 按照上面算法來說,應該取5和7的中位數,但是我們還是取偏大的(7,2)作爲根節點,小於xi1小於7的做左節點,反之,則作右節點
後面根據 L= J(mod k)+1決定比較的順序。
以此類推,便很快構建出kd樹
在這裏插入圖片描述
知道你們懶得推,我把圖放出來了

接下來,我們開始kd樹的最近鄰搜索

  1. 測試點首先從根節點出發,按照不同深度不同的xi比較標準,決定往左還是往右,最後到達葉節點
  2. 以當前葉節點作爲最近鄰點,遞歸的往上推,對每一個節點做以下操作
    (a)查看父節點,分別比較父節點、當前最近鄰節點 與 測試點的距離,如果前者較小,則最近鄰節點更新爲該父節點。
    (b)當前最近鄰節點一定存在於該父節點的一個子節點的區域,檢查該父節點的另一個子節點,看是否有更近的節點,如果有,就更新當前最近鄰點,如果沒有,則接着向上遞歸
    如何判斷是否可能有最近鄰節點呢?
    原理很簡單:
    以測試點作爲超球體的球心,以“當前最近鄰節點”到球心的距離作爲半徑,若這個若另一個子節點的區域與超球體相交,則可能有“最近鄰節點”,否則覺悟可能
  3. 當迴歸到根節點時,停止搜索,最後的當前“最近鄰節點”爲最近節點。
    還是撿個栗子:
    在這裏插入圖片描述
    搜索路徑:S->D->B->F->A->C->E
    代碼後續補上:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章