2.kd樹


1:kd簡介

1.1 什么是kd樹

根據KNN每次需要預測一個點時,我們都需要計算訓練數據集里每個點到這個點的距離,然后選出距離最近的k個點進行投票。當數據集很大時,這個計算成本非常高,針對N個樣本,D個特征的數據集,其算法復雜度為O(DN^2)。

kd樹:為了避免每次都重新計算一遍距離,算法會把距離信息保存在一棵樹里,這樣在計算之前從樹里查詢距離信息,盡量避免重新計算。其基本原理是,如果A和B距離很遠,B和C距離很近,那么A和C的距離也很遠。有了這個信息,就可以在合適的時候跳過距離遠的點。

這樣優化后的算法復雜度可降低到O(DNlog(N))。感興趣的讀者可參閱論文:Bentley,J.L.,Communications of the ACM(1975)。

1989年,另外一種稱為Ball Tree的算法,在kd Tree的基礎上對性能進一步進行了優化。感興趣的讀者可以搜索Five balltree construction algorithms來了解詳細的算法信息

kd樹(K-dimension tree)是一種對k維空間中的實例點進行存儲以便對其進行快速檢索的樹形數據結構。kd樹是一種二叉樹,表示對k維空間的一個划分,構造kd樹相當於不斷地用垂直於坐標軸的超平面將K維空間切分,構成一系列的K維超矩形區域。kd樹的每個結點對應於一個k維超矩形區域。利用kd樹可以省去對大部分數據點的搜索,從而減少搜索的計算量

1.2 原理

 

 

黃色的點作為根節點,上面的點歸左子樹,下面的點歸右子樹,接下來再不斷地划分,分割的那條線叫做分割超平面(splitting hyperplane),在一維中是一個點,二維中是線,三維的是面。

 

 

黃色節點就是Root節點,下一層是紅色,再下一層是綠色,再下一層是藍色

 

 

類比“二分查找”:給出一組數據:[9 1 4 7 2 5 0 3 8],要查找8。如果挨個查找(線性掃描),那么將會把數據集都遍歷一遍。而如果排一下序那數據集就變成了:[0 1 2 3 4 5 6 7 8 9],按前一種方式我們進行了很多沒有必要的查找,現在如果我們以5為分界點,那么數據集就被划分為了左右兩個“簇” [0 1 2 3 4]和[6 7 8 9]。

因此,根本就沒有必要進入第一個簇,可以直接進入第二個簇進行查找。把二分查找中的數據點換成k維數據點,這樣的划分就變成了用超平面對k維空間的划分。空間划分就是對數據點進行分類,“挨得近”的數據點就在一個空間里面。

2:kd樹的構造方法

(1)構造根結點,使根結點對應於K維空間中包含所有實例點的超矩形區域;

(2)通過遞歸的方法,不斷地對k維空間進行切分,生成子結點。在超矩形區域上選擇一個坐標軸和在此坐標軸上的一個切分點,確定一個超平面,這個超平面通過選定的切分點並垂直於選定的坐標軸,將當前超矩形區域切分為左右兩個子區域(子結點);這時,實例被分到兩個子區域。

(3)上述過程直到子區域內沒有實例時終止(終止時的結點為葉結點)。在此過程中,將實例保存在相應的結點上。

(4)通常,循環的選擇坐標軸對空間切分,選擇訓練實例點在坐標軸上的中位數為切分點,這樣得到的kd樹是平衡的(平衡二叉樹:它是一棵空樹,或其左子樹和右子樹的深度之差的絕對值不超過1,且它的左子樹和右子樹都是平衡二叉樹)。

KD樹中每個節點是一個向量,和二叉樹按照數的大小划分不同的是,KD樹每層需要選定向量中的某一維,然后根據這一維按左小右大的方式划分數據。在構建KD樹時,關鍵需要解決2個問題:

(1)選擇向量的哪一維進行划分;

(2)如何划分數據;

第一個問題簡單的解決方法可以是隨機選擇某一維或按順序選擇,但是更好的方法應該是在數據比較分散的那一維進行划分(分散的程度可以根據方差來衡量)。好的划分方法可以使構建的樹比較平衡,可以每次選擇中位數來進行划分,這樣問題2也得到了解決。

3:案列分析

3.1 樹的建立

給定一個二維空間數據集:T={(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},構造一個平衡kd樹。

 

 

1:思路引導

根結點對應包含數據集T的矩形,

x軸:(2,5,9,4,8,7),排序:(2,4,5,7,8,9)

y軸:(3,4,6,7,1,2),排序:(1,2,3,4,6,7)

x軸的方差較大,所以先選擇x軸,根據二分法,所以選擇(7,2)點,以平面x(1)=7將空間分為左、右兩個子矩形(子結點);接着左矩形以x(2)=4分為兩個子矩形(左矩形中{(2,3),(5,4),(4,7)}點的x(2)坐標中位數正好為4),右矩形以x(2)=6分為兩個子矩形,如此遞歸,最后得到如下圖所示的特征空間划分和kd樹。

 

 3.2 最近鄰域搜索

假設標記為星星的點是 test point, 綠色的點是找到的近似點,在回溯過程中,需要用到一個隊列,存儲需要回溯的點,在判斷其他子節點空間中是否有可能有距離查詢點更近的數據點時,做法是以查詢點為圓心,以當前的最近距離為半徑畫圓,這個圓稱為候選超球(candidate hypersphere),如果圓與回溯點的軸相交,則需要將軸另一邊的節點都放到回溯隊列里面來。

 

 樣本集{(2,3),(5,4), (9,6), (4,7), (8,1), (7,2)}

3.2.1 查找點(2.1,3.1)

 

 

在(7,2)點測試到達(5,4),在(5,4)點測試到達(2,3),然后search_path中的結點為<(7,2),(5,4), (2,3)>,從search_path中取出(2,3)作為當前最佳結點nearest, dist為0.141;

然后回溯至(5,4),以(2.1,3.1)為圓心,以dist=0.141為半徑畫一個圓,並不和超平面y=4相交,如上圖,所以不必跳到結點(5,4)的右子空間去搜索,因為右子空間中不可能有更近樣本點了。

於是再回溯至(7,2),同理,以(2.1,3.1)為圓心,以dist=0.141為半徑畫一個圓並不和超平面x=7相交,所以也不用跳到結點(7,2)的右子空間去搜索。

至此,search_path為空,結束整個搜索,返回nearest(2,3)作為(2.1,3.1)的最近鄰點,最近距離為0.141。

3.2.2 查找點(2,4.5)

 

 

在(7,2)處測試到達(5,4),在(5,4)處測試到達(4,7)【優先選擇在本域搜索】,然后search_path中的結點為<(7,2),(5,4), (4,7)>,從search_path中取出(4,7)作為當前最佳結點nearest, dist為3.202;

然后回溯至(5,4),以(2,4.5)為圓心,以dist=3.202為半徑畫一個圓與超平面y=4相交,所以需要跳到(5,4)的左子空間去搜索。所以要將(2,3)加入到search_path中,現在search_path中的結點為<(7,2),(2, 3)>;另外,(5,4)與(2,4.5)的距離為3.04 < dist = 3.202,所以將(5,4)賦給nearest,並且dist=3.04。

回溯至(2,3),(2,3)是葉子節點,直接平判斷(2,3)是否離(2,4.5)更近,計算得到距離為1.5,所以nearest更新為(2,3),dist更新為(1.5)

回溯至(7,2),同理,以(2,4.5)為圓心,以dist=1.5為半徑畫一個圓並不和超平面x=7相交, 所以不用跳到結點(7,2)的右子空間去搜索。

至此,search_path為空,結束整個搜索,返回nearest(2,3)作為(2,4.5)的最近鄰點,最近距離為1.5。

 


免責聲明!

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



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