x i = ( x i ( 1 ) , x i ( 2 ) , . . . . , x i ( n ) ) x_{i} = (x_{i}^{(1)},x_{i}^{(2)}, ....,x_{i}^{(n)}) xi=(xi(1),xi(2),....,xi(n)) , x j = ( x j ( 1 ) , x j ( 2 ) , . . . . , x j ( n ) ) x_{j} = (x_{j}^{(1)},x_{j}^{(2)}, ....,x_{j}^{(n)}) xj=(xj(1),xj(2),....,xj(n)) L p ( x i , x j ) = ( ∑ l = 1 n ∣ x i l − x j l ∣ p ) 1 p L_{p}(x_{i},x_{j}) = (\sum_{l = 1}^{n}|x_{i}^{l} - x_{j}^{l}|^{p})^{\frac{1}{p}} Lp(xi,xj)=(l=1∑n∣xil−xjl∣p)p1
p = 2时为欧式距离,为我们常用的公式,其他公式不再展开
细节注意:
kd的k指的是数据的维度,不是KNN的k直观上看,kdd加速的原因是因为其数据结构(二叉树),如果确定object到某一个节点距离已经很大了,那么这个节点往下的枝叶就不需要遍历.构造kd树时,注意树层数和数据维度无关,他会递归一直划分下去,直到数据集为空,不能再划分(有点像减枝).其kd树的遍历代码实现类似与树的中序遍历(不过遍历同时有减枝),可以自行对比,方便理解里面的递归写法.看到另一种角度的解释(寻找速度更快原因):参考 ~~~~~~ 类比“二分查找”: 给出一组数据: [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维空间的划分。空间划分就是对数据点进行分类, “挨得近”的数据点就在一个空间里面。复现经典:《统计学习方法》第 3 章 k 近邻法