數學-kd樹

轉自:https://zhuanlan.zhihu.com/p/23966698

導語:在上一篇《kd 樹算法之思路篇》中,我們介紹瞭如何用二叉樹格式記錄空間內的距離,並以其爲依據進行高效的索引。在本篇文章中,我們將詳細介紹 kd 樹的構造以及 kd 樹上的 kNN 算法。

作者:肖睿
編輯:宏觀經濟算命師

本文由JoinQuant量化課堂推出,本文的難度屬於進階(下),深度爲 level-1

 

kd 樹的結構

kd樹是一個二叉樹結構,它的每一個節點記載了【特徵座標,切分軸,指向左枝的指針,指向右枝的指針】。

其中,特徵座標是線性空間R^n中的一個點(x_1,x_2,...,x_n)

切分軸由一個整數r表示,這裏1 \le r \le n,是我們在 n 維空間中沿第 r 維進行一次分割。

節點的左枝和右枝分別都是 kd 樹,並且滿足:如果 y 是左枝的一個特徵座標,那麼y_r \le x_r並且如果 z 是右枝的一個特徵座標,那麼z_r \ge x_r

給定一個數據樣本集 S \subseteq R^n和切分軸 r , 以下遞歸算法將構建一個基於該數據集的 kd 樹,每一次循環制作一個節點:

−− 如果 |S|=1,記錄 S 中唯一的一個點爲當前節點的特徵數據,並且不設左枝和右枝。(|S| 指集合 S 中元素的數量)
−− 如果 |S|>1
∙∙ 將 S 內所有點按照第 r 個座標的大小進行排序;
∙∙ 選出該排列後的中位元素(如果一共有偶數個元素,則選擇中位左邊或右邊的元素,左或右並無影響),作爲當前節點的特徵座標,並且記錄切分軸 r;
∙∙ 將 S_L 設爲在 S 中所有排列在中位元素之前的元素; S_R 設爲在 S 中所有排列在中位元素後的元素;
∙∙ 當前節點的左枝設爲以 S_L 爲數據集並且 r 爲切分軸製作出的 kd 樹;當前節點的右枝設爲以 S_R 爲數據集並且 r 爲切分軸製作出的 kd 樹。再設 r\leftarrow(r+1)\ mod\ n。(這裏,我們想輪流沿着每一個維度進行分割;mod\ n 是因爲一共有 n 個維度,在沿着最後一個維度進行分割之後再重新回到第一個維度。)

構造 kd 樹的例子

上面抽象的定義和算法確實是很不好理解,舉一個例子會清楚很多。首先隨機在 \mathbb{R}^2 中隨機生成 13 個點作爲我們的數據集。起始的切分軸r=0;這裏 r=0 對應 xx 軸,而r=1 對應 y 軸。

首先先沿 x 座標進行切分,我們選出 x 座標的中位點,獲取最根部節點的座標

 

並且按照該點的x座標將空間進行切分,所有 x 座標小於 6.27 的數據用於構建左枝,x座標大於 6.27 的點用於構建右枝。

 

在下一步中 r=0+1=1\ mod\ 2 對應 y 軸,左右兩邊再按照 y 軸的排序進行切分,中位點記載於左右枝的節點。得到下面的樹,左邊的 x 是指這該層的節點都是沿 x 軸進行分割的。

 

空間的切分如下

 

下一步中 r≡1+1≡0 mod 2,對應 x 軸,所以下面再按照 x 座標進行排序和切分,有

最後每一部分都只剩一個點,將他們記在最底部的節點中。因爲不再有未被記錄的點,所以不再進行切分。

就此完成了 kd 樹的構造。

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