k近鄰算法的實現:kd樹

當特徵空間維度大,訓練數據容量大時,如何對訓練數據進行快速k近鄰搜索。

k近鄰法最簡單的實現方式是線性掃描,這時要計算輸入實例與每一個訓練實例的距離,當訓練集容量大時計算太耗時,這種方法不可行。

爲了提高k近鄰搜索的效率,可以利用特殊的結構來存儲訓練數據,以便減少距離的計算次數。kd樹就是其中的一種存儲結構。


kd樹:

kd樹定義:kd樹是一種對k維空間中的實例進行存儲,以便進行快速檢索的樹形結構。kd樹是二叉樹,表示對k維空間的一個劃分。

1開始:構造根節點,根節點對應包含T的k維空間的超矩形區域。

x(1)選擇爲座標軸,選擇T中所有實例的x(1)座標的中位數爲切分點,將根節點對應的超矩形區域切分爲兩個子區域。切分由通過切分點並和軸垂直的超平面實現。由根節點生成左右兩個深度爲1的子節點,左子節點對應的子區域中所有點的x(1)座標都小於切分點,右子節點對應的子區域中所有的點的x(1)座標都大於切分點。

將落在切分超平面上的實例點保存在根節點。

2重複,對於深度爲j的節點,選擇x(l)爲切分的座標軸,l=j mod k + 1;以該節點的區域的所有實例的x(l)座標的中位數作爲切分點,將該節點對應的超矩形區域切分爲兩個子區域。切分由通過切分點,且與座標軸x(l)垂直的超平面實現。

該節點生成深度爲j+1的左右兩個子節點,左子節點對應於座標x(l)小於切分點的子區域,右子節點對應於座標x(l)大於切分點的子區域。

將落在切分超平面上的點保存在該節點。

3直到兩個區域沒有實例存在爲止,從而形成kd樹的劃分。


如何使用kd樹進行k近鄰搜索。

利用kd樹可以省去對大部分數據點的搜索,從而減小搜索的計算量。

包含目標點的葉節點對應包含目標點的最小超矩形區域。以此葉節點的實例點作爲當前最近點。

用kd樹搜索最近鄰點:

輸入:構造好的kd樹,目標點:x;

輸出:x的最近鄰點

1在kd樹中找出包含目標點x的葉節點,從根節點出發遞歸的訪問kd樹。若目標點x當前緯度的座標小於切分點的座標,移動到切分點的左節點,否則移動到右節點。直到子節點爲葉節點爲止。

2以此葉節點爲當前最近點。

3遞歸的向上回退,遇到每個節點進行以下操作:

a如果該節點保存的實例點比當前最近點距離目標點更近,則將當前最近點更新爲該實例點。

b當前最近點一定存在於該節點的一個子節點對應的區域。檢查該子節點的父節點的另一個子節點對應的區域是否存在離目標點更近的點。具體的 ,檢查該子節點對應的區域是否和以目標點爲秋心,以目標點與當前最近點距離爲超球體相交。

如果不相交,向上回退。

如果相交,可能在另一個子節點對應的區域內存在距離目標點更近的點,最近鄰搜索另一個子節點。

4當回退到根節點時,搜索結束,最後當前最近點作爲目標點x的最近鄰點。


複雜度:如果實例點是隨機分佈的,那麼kd樹搜索的複雜度是O(logN),N是訓練實例數。

適用於:訓練實例數遠遠大於空間維度數的k近鄰搜索。當空間維數接近於訓練實例數時,搜索效率下降,接近於線性掃描。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章