在k-d tree樹中進行資料的k近鄰搜尋是特徵匹配的重要環節,其目的是檢索在k-d tree中與待查詢點距離最近的k個資料點。
最近鄰搜尋是k近鄰的特例,也就是1近鄰。將1近鄰改擴充套件到k近鄰非常容易。下面介紹最簡單的k-d tree最近鄰搜尋演算法。
基本的思路很簡單:首先通過二叉樹搜尋(比較待查詢節點和**節點的**維的值,小於等於就進入左子樹分支,大於就進入右子樹分支直到葉子結點),順著「搜尋路徑」很快能找到最近鄰的近似點,也就是與待查詢點處於同乙個子空間的葉子結點;然後再回溯搜尋路徑,並判斷搜尋路徑上的結點的其他子結點空間中是否可能有距離查詢點更近的資料點,如果有可能,則需要跳到其他子結點空間中去搜尋(將其他子結點加入到搜尋路徑)。重複這個過程直到搜尋路徑為空。
演算法:kdtreefindnearest
輸入:kd
target
輸出 : nearest
dist1. 如果kd是空的,則設dist為無窮大返回2. 向下搜尋直到葉子結點
psearch= &kdwhile(psearch !=null)
psearch加入到search_path中;if(target[psearch->split] <= psearch->dom_elt[psearch->split])
psearch= psearch->left;
}elseelseif(target[s] <= pback->dom_elt[s])
psearch= pback->right;elsepsearch= pback->left;if(psearch !=null)
psearch加入到search_path中
現在舉一些例子來說明上面的最近鄰搜尋演算法,假設我們的k-d tree就是上面通過樣本集建立的。將上面的圖轉化為樹形圖的樣子如下:
我們來查詢點(2.1,3.1),在(7,2)點測試到達(5,4),在(5,4)點測試到達(2,3),然後search_path中的結點為,從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。
再舉乙個稍微複雜的例子,我們來查詢點(2,4.5),在(7,2)處測試到達(5,4),在(5,4)處測試到達(4,7),然後search_path中的結點為,從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中的結點為;另外,(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。
兩次搜尋的返回的最近鄰點雖然是一樣的,但是搜尋(2, 4.5)的過程要複雜一些,因為(2, 4.5)更接近超平面。研究表明,當查詢點的鄰域與分割超平面兩側的空間都產生交集時,回溯的次數大大增加。最壞的情況下搜尋n個結點的k維kd-tree所花費的時間為:
關於k-d tree還有很多擴充套件。由於大量回溯會導致kd-tree最近鄰搜尋的效能大大下降,因此研究人員也提出了改進的k-d tree近鄰搜尋,其中乙個比較著名的就是 best-bin-first,它通過設定優先順序佇列和執行超時限定來獲取近似的最近鄰,有效地減少回溯的次數。
參考資料
2.《影象區域性不變特性特徵與描述》王永明 王貴錦 編著 國防工業出版社
3.kdtree a ****** c library for working with kd-trees
利用kd樹實現最近鄰搜尋
輸入 已經構造的kd樹,目標點x 輸出 x的最近鄰 1在kd樹中找出包含目標點x的葉節點 從根結點出發,遞迴地向下訪問kd樹。若目標點x當前維的座標小於切分點的座標,則移動到左葉子結點,否則移動到右葉子結點。直到子節點為葉節點為止。2以此葉節點為 當前最近點 3遞迴地向上回退,在每個結點進行以下操作...
統計學習方法 KD樹最近鄰搜尋
李航老師書上的的演算法說明沒怎麼看懂,看了網上的部落格,悟出一套迴圈 建立好kd樹以後的最近鄰搜尋 我想應該是這樣的 例子是李航 統計學習演算法 第三章56頁 例3.3 步驟結點查詢標記 棧內元素 本次迴圈結束後 最近點最近距離說明a bcde fg初始化000 0000 0abd m 空mdis ...
K最近鄰演算法
參考 所謂k最近鄰,就是k個最近的鄰居的意思,說的是每個樣本都可以用它最接近的k個鄰居來代表。cover和hart在1968年提出了最初的鄰近演算法。knn是一種分類 classification 演算法,它輸入基於例項的學習 instance based learning 屬於懶惰學習 lazy ...