1 什麼是kd樹
2 如何建立kd樹
用乙個簡單的例子,資料維度只有2維,所以可以簡單地給x,y兩個方向軸編號為0,1,也即split=。
(1)確定split域的首先該取的值。分別計算x,y方向上資料的方差得知x方向上的方差最大,所以split域值首先取0,也就是x軸方向;
(2)確定node-data的域值。根據x軸方向的值2,5,9,4,8,7排序選出中值為7,所以node-data = (7,2)。這樣,該節點的分割超平面就是通過(7,2)並垂直於split = 0(x軸)的直線x = 7;
(3)確定左子空間和右子空間。分割超平面x = 7將整個空間分為兩部分,如圖2所示。x < = 7的部分為左子空間,包含3個節點;另一部分為右子空間,包含2個節點。
如演算法所述,k-d樹的構建是乙個遞迴的過程。然後對左子空間和右子空間內的資料重複根節點的過程就可以得到下一級子節點(5,4)和(9,6)(也就是左右子空間的』根』節點),同時將空間和資料集進一步細分。如此反覆直到空間中只包含乙個資料點,如下圖所示
轉化為相應的平衡二叉樹:
這樣就建立好了,三維的也大體類似
看下圖空間中不同顏色的線條
首先用紅色線條將空間一分為二,然後用綠色線條將兩塊空間繼續切分,最後將分成四塊的空間用藍線切分即可
多維的空間切分大抵如此
3 查詢最鄰近點
方法:python的實現:
class
kdnode
(object):
def__init__
(self, value, split, left, right)
:# value=[x,y]
self.value = value
self.split = split
self.right = right
self.left = left
class
kdtree
(object):
def__init__
(self, data)
:# data=[[x1,y1],[x2,y2]...,]
# 維度
k =len(data[0]
)def
createnode
(split, data_set):if
not data_set:
return
none
data_set.sort(key=
lambda x: x[split]
)# 整除2
split_pos =
len(data_set)//2
median = data_set[split_pos]
split_next =
(split +1)
% k
return kdnode(median, split, createnode(split_next, data_set[
: split_pos]),
createnode(split_next, data_set[split_pos +1:
]))
self.root = createnode(
0, data)
defsearch
(self, root, x, count=1)
: nearest =
for i in
range
(count):[
-1,none])
self.nearest = np.array(nearest)
defrecurve
(node)
:if node is
notnone
: axis = node.split
daxis = x[axis]
- node.value[axis]
if daxis <0:
recurve(node.left)
else
: recurve(node.right)
dist = sqrt(
sum(
(p1 - p2)**2
for p1, p2 in
zip(x, node.value)))
for i, d in
enumerate
(self.nearest)
:if d[0]
<
0or dist < d[0]
:# 如果當前nearest內i處未標記(-1),或者新點與x距離更近
self.nearest = np.insert(self.nearest, i,
[dist, node.value]
, axis=0)
# 插入比i處距離更小的
self.nearest = self.nearest[:-
1]break
# 找到nearest集合裡距離最大值的位置,為-1值的個數
n =list
(self.nearest[:,
0]).count(-1
)# 切分軸的距離比nearest中最大的小(存在相交)
if self.nearest[
-n -1,
0]>
abs(daxis)
:if daxis <0:
# 相交,x[axis]< node.data[axis]時,去右邊(左邊已經遍歷了)
recurve(node.right)
else
:# x[axis]> node.data[axis]時,去左邊,(右邊已經遍歷了)
recurve(node.left)
recurve(root)
return self.nearest
# 最近座標點、最近距離和訪問過的節點數
result = namedtuple(
"result_tuple"
,"nearest_point nearest_dist nodes_visited")
data =[[
2,3]
,[5,
4],[
9,6]
,[4,
7],[
8,1]
,[7,
2]]kd = kdtree(data)
#[3, 4.5]最近的3個點
n = kd.search(kd.root,[3
,4.5],
3)print
(n)#[[1.8027756377319946 list([2, 3])]
[2.0615528128088303
list([
5,4]
)][2.692582403567252
list([
4,7])]]
大概是這些 KNN演算法和KD樹
knn k nearestneighbor 鄰近演算法,或者說k最近鄰分類演算法 是資料探勘分類技術中最簡單的方法之一。所謂k最近鄰,就是k個最近的鄰居的意思,說的是每個樣本都可以用它最接近的k個鄰居來代表。knn演算法的核心思想是如果乙個樣本在特徵空間中的k個最相鄰的樣本中的大多數屬於某乙個類別,...
R語言中的空間最鄰近點問題
在空間分析中,nearest point problem是乙個十分基本而重要的問題。對於小樣本量的點集而言,通過計算距離矩陣並進行排序即可暴力解決。而對於上萬甚至幾十萬以上的點集而言,通過計算距離矩陣顯然需要耗費太多的資源,一般採用kd樹等方法進行搜尋。背後的演算法我也不太懂,這裡僅把r語言中面向s...
使用k d樹進行無序點雲去噪
離散點雲的點之間是沒有拓撲結構的,因此為了找到它的幾何屬性,可以找到各點的鄰域結構。對於取樣點pi p定義其鄰域nk pi為取樣點pi 的最近的 k 個取樣點組成的集合,即k nearest neighbors。那麼尋找k nearest neighbours的方法主要由以下三種 八叉樹法 空間網格...