scikit-learn--Nearest Neighbors(最近邻)

sklearn.neighbors提供基于邻居的有监督和无监督的学习方法。无监督最近邻方法是很多学习方法的基础,特别是流形学习和谱聚类。有监督的最近邻方法包括:离散数据的分类、连续数据的回归。
最近邻方法的原理是,找到指定数量的最近样本点,然后根据这些点去预测新的点。样本点的数量可以由用户定义(k-最近邻)或者基于点的局部密度。距离度量标准可以有很多种,欧式距离是最常用的选择。基于邻居的方法被称为non-generalizing machine learning,因为它只是“记住”训练数据(可能转化为一个快速的索引结构,如BallTree或KDTree)。
尽管很简单,但是最近邻方法能解决大量分类和回归问题,包括手写数字或卫星图像识别,作为一种非参数方法,在分类边界不规则的情况下通常是有效的。

无监督的最近邻

NearestNeighbors 执行无监督的最近邻方法,有三种不同的最近邻算法:BallTree、KDTree、a brute-force algorithm based on routines in sklearn.metrics.pairwise,邻居的搜索算法通过关键词 ‘algorithm’ 控制,选项包括['auto', 'ball_tree', 'kd_tree', 'brute'],当设置为‘auto’时,算法将通过训练数据决定最好的方法。
Warning:在最近邻算法中,当有两个点和预测点的距离相同但标签不同时,结果将依赖点在训练数据中的顺序。

KDTree和BallTree

可以使用KDTree或BallTree直接发现最近邻。
KDTree和BallTree的详细解释:
http://blog.csdn.net/skyline0623/article/details/8154911

最近邻分类

基于邻居的分类是一种基于实例的学习或者非泛化学习(a type of instance-based learning or non-generalizing learning),它不试图构建一个通用的内部模型,只是简单的存储训练数据的实例。通过每个点的最近邻的简单多数投票来分类,一个查询点被分配给它的最近邻中最有代表性的那个数据类。
scikit-learn 包括两种最近邻分类器:KNeighborsClassifier 和 RadiusNeighborsClassifier。KNeighborsClassifier是比较常用的一种,一般的,一个比较大的k值能抑制异常值的影响,但是也让分类边界的区分性下降。
如果是不均匀采样数据,RadiusNeighborsClassifier中的基于半径的最近邻分类是一个比较好的选择。用户指定一个固定的半径 r ,那些稀疏区域中的点使用较少的最近邻去分类,在高维参数空间,由于所谓的“维灾难”,这种方法就变得不那么有效。
基本的最近邻分类器使用一致权重,即采用最近邻数据的简单多数表决。在某些情况下,更近的数据点对模型的贡献更大,可以通过参数 weights 来设置。默认情况下,weights=‘uniform’,所有邻居的权重是相同的。weights=‘distance’ ,权重正比于到查询点的距离的倒数。另外,用户也可以自定义函数计算权重。

最近邻回归

当数据标签是离散的而不是连续的,可以使用最近邻回归方法。查询点的标签通过最近邻点的平均标签计算。
scikit-learn有两种最近邻回归方法:KNeighborsRegressor 和 RadiusNeighborsRegressor。

最近邻算法

Brute Force

快速计算最近邻是机器学习中一个活跃的研究领域。最简单的方法是计算数据集中每两个点之间的距离,在小型数据集上,brute-force很有竞争力,然而随着样本数的增长,brute-force变得不可行。

KDTree

为了解决brute-force方法计算效率低下,发明了各种基于树的数据结构。一般情况下,这些结构通过有效编码汇总样本距离信息,来减少所需的距离计算量。基本思想是,如果A离B比较远,B 离C比较近,所以A 离C比较远,而不用明确计算。

构建k-d树(createKDTree)

输入:数据点集Data-set和其所在的空间Range
输出:Kd,类型为k-d tree
1.If Data-set为空,则返回空的k-d tree
2.调用节点生成程序:
(1)确定split域:对于所有描述子数据(特征矢量),统计它们在每个维上的数据方差。
以SURF特征为例,描述子为64维,可计算64个方差。挑选出最大值,对应的维就是split域的值。
数据方差大表明沿该坐标轴方向上的数据分散得比较开,在这个方向上进行数据分割有较好的分辨率;
(2)确定Node-data域:数据点集Data-set按其第split域的值排序。
位于正中间的那个数据点被选为Node-data。此时新的Data-set' = Data-set\Node-data(除去其中Node-data这一点)。
3.dataleft = {d属于Data-set' && d[split] ≤ Node-data[split]}
Left_Range = {Range && dataleft} dataright = {d属于Data-set' && d[split] > Node-data[split]}
Right_Range = {Range && dataright}
4.left = 由(dataleft,Left_Range)建立的k-d tree,即递归调用createKDTree(dataleft,Left_
Range)。并设置left的parent域为Kd;
right = 由(dataright,Right_Range)建立的k-d tree,即调用createKDTree(dataright,Right_
Range)。并设置right的parent域为Kd。

查找算法

从root节点开始,DFS搜索直到叶子节点,同时在stack中顺序存储已经访问的节点。
如果搜索到叶子节点,当前的叶子节点被设为最近邻节点。
然后通过stack回溯:
如果当前点的距离比最近邻点距离近,更新最近邻节点.
然后检查以最近距离为半径的圆是否和父节点的超平面相交.
如果相交,则必须到父节点的另外一侧,用同样的DFS搜索法,开始检查最近邻节点。
如果不相交,则继续往上回溯,而父节点的另一侧子节点都被淘汰,不再考虑的范围中.
当搜索回到root节点时,搜索完成,得到最近邻节点。

选择方差最大的维度作为当前节点的划分维度,方差越大,说明这个维度上的数据波动越大,也就说明了他们就越不可能属于同一空间,需要在这个维度上对数据点进行划分。KDTree在维度小于20的情况下搜索是非常快的。

BallTree

为了解决高维问题,发明了BallTree。KDTree沿着笛卡尔轴划分数据,BallTree使用超球面。虽然建立树的成本大于KDTree,但是在高维数据上非常有效。
BallTree 递归地将数据划分成一个质心C和半径R定义的节点,使得每个点位于由R和C定义的超球体内。通过使用三角不等式减少搜索次数。
有了这个设置,测试点和质心之间的距离计算,已经足够确定测试点和这个节点内所有点的距离的上界和下界。由于BallTree 节点的球形几何形状,它可以执行高维的KD树,但实际的性能是高度依赖于训练数据的结构。

最近邻算法选择

选择最佳算法依赖很多因素:

  • 样本数N和维度D
    1.Brute force 时间复杂度 O(D N),
    2.BallTree 时间复杂度 O(D log(N)),
    3.KDTree,if D<20 ,O(D log(N));else O(D N)。
    在样本数小于30的情况下,Brute force比BallTree和KDTree高效。
  • 数据结构
    数据内在维度和数据稀疏性。数据内在维度(秩)小于数据维度,参数空间是存在线性或非线性关系。稀疏性指数据填充参数空间的程度(这与“稀疏”矩阵中的概念区别开来)。数据矩阵可能没有零项,但结构仍然可以是“稀疏”在这个意义上说。
    1.Brute force 与数据结构无关。
    2 BallTree和KDTree在低内在维度的稀疏数据上将很快。
  • K值
    1.Brute force 不受影响,
    2 BallTree和KDTree 随着K值的增大而变慢,首先,更大的K值导致需要搜索更大的参数空间,Second, using k > 1 requires internal queueing of results as the tree is traversed.
  • 查询数量
    BallTree和KDTree都需要一个创建过程,当有大量查询时,创建的开销可以忽略。如果只是少量的查询,则Brute force 较好。

叶子大小

Brute force 在小样本上比树结构更高效,这解释了BallTree和KDTree 在叶子节点内部转换到Brute force 搜索。这种转换可以通过参数 leaf_size 设置,这个参数有很多影响:
创建时间:比较大的leaf_size ,创建比较快,因为需要创建的节点变少;
查询时间:默认 leaf_size=30
内存:随着leaf_size 增加,存储一棵树所需要的内存是下降的,在BallTree中这非常重要。BallTree 需要的内存空间近似是训练数据规模的1/leaf_size。

Nearest Centroid Classifier

Approximate Nearest Neighbors


来源:http://scikit-learn.org/stable/modules/neighbors.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容