【机器学习】K近邻算法 - 性能分析

Knn算法是一种简单的监督学习算法,虽然性能并不算非常出色,但是可解释性非常强。理论上可以证明,Knn可以以任意精度拟合真实分类高维曲面。

一、Knn算法分析

1、该算法在处理样本分布不均匀的时候效果比较差。比如正类的样本数量为1000,反类的样本数量为100,即正反两类的比例悬殊,当测试一个数据样本的时候,很有可能它虽然在距离上靠近反类,但是由于相邻的样本反类太少,正类太多,导致预测不准确。解决这个问题的方法就是根据K近邻得到的结果,每个类的数量分别再除以各自在训练集中的样本个数,这样将各类样本均衡化,效果更准确。

2、该算法在处理稀疏数据时,效果很差,尽管这是一种懒惰学习算法,但是仍然需要大量的,等密度分布的数据。

3、在预测时,除了将类别均衡化之外,还需要密度均衡化,也就是说,希望所有的样本点在属性空间上的分布非常均匀,这样预测的结果就准确。密度分布可以用K近邻的半径来衡量。即测试样本和第k个样本之间的距离的倒数定义为当前空间的样本密度,如果密度比较大,则预测结果准确,如果密度小,那么数据稀疏,预测的结果就不一定可靠。所以需要以概率来判定。

4、由于是懒惰学习,所以在做增量学习的时候,给每个新增样本都做概率预测,预测更加新的进来的样本的时候,也采用概率预测,会是更精确的做法。这种懒惰学习造成的结果就是只能找到局部最小点,而很难找到全局最小点。

5、KNN的处理一定是有一个分类边界的,这个边界可能不是特别具体,但是也不会大过KNN确定的判定超圆的直径。也就是说,随着数据越来越稠密,假设达到了绝对稠密,在一个样本的极其微小的邻域内找到了K个样本,并判定成功样本的分类,此时,邻域几乎不可见,在属性空间上进行宏观观察,每个分类都以一个超曲面将数据精准分割开来。数据之间没有丝毫杂糅,这就是KNN的不准确性。

二、代码

该算法并不算难,自己写一个也不成问题。但是由于懒,且已经完全明白了该算法的原理,所以就不想写了。直接调用sklearn包。

KNeighborsClassifier()进行参数解释。

(1)n_neighbors : 整数,默认取5。K近邻的K值。

(2)weights : 字符串格式或者自定义,默认是'uniform'。也就是每个属性的权值分配。

       - 'uniform' : 均匀分布,即每个属性具有的权重一致。

       - 'distance' : 也就是说,距离样本越近的样本点对样本的分类影响越大。

       - [callable] : 用户自定义函数,该函数的输入是一列距离值,输出是每个距离对应的权重值。

(3)algorithm : 取值包括'auto', 'ball_tree', 'kd_tree', 'brute'。指选择哪种算法来计算。

       - 'ball_tree' 使用类class:`BallTree`

       - 'kd_tree' 使用类class:`KDTree`

       - 'brute' 使用brute-force search,在稀疏数据时使用该种方法

       - 'auto' 自适应选择一种最合适的。

(4)leaf_size : 整数,默认30。在使用BallTree 或 KDTree方法时,传给算法的叶子节点的数量,默认30个。具体这是什么算法,我也不清楚,没有查找资料。

(5)p : 整数,默认值是2。指选择哪种距离度量,泛化来说,所有的向量距离都是Minkowski距离,p = 1时,称为manhattan距离,p = 2时,称为euclidean_distance。也可以使用其他的距离。

(6)metric : 字符串类型,定义了使用什么距离,默认是'minkowski'。DistanceMetric 类中定义各种可以使用的距离。

(7)metric_params : 如果选择了某个metric,用dict来给对应的距离种类添加参数。一般不用。

(8)n_jobs : 整数,指的是计算机运行的作业数。一个cpu在一个时刻只能运行一个job作业。如果参数选择为-1,那么计算机中所有的CPU都参与了该算法的训练。如果取1,即只有1个CPU在运行,也就是单进程,并且Python解释器是单线程的,也就是说单线程运行。如果参数小于-1,那么(计算机中CPU的个数+1+n_jobs)即是计算机中运行的作业数。比如我的计算机是4核的,参数取值为-2,此时有3个CPU参与了此次训练。

from sklearn.cluster import KMeans
from sklearn import neighbors
from sklearn import datasets
import numpy as np
import pylab as pl


knn = neighbors.KNeighborsClassifier()
iris = datasets.load_iris()

knn.fit(iris.data, iris.target)
predictedLabel = knn.predict([[0.1,0.2,0.3,0.4]])
print predictedLabel

pl.scatter(iris.data[:, 1],  # 样本集的 x 轴数据
           iris.data[:, 3],  # 样本集的 y 轴数据
           c=iris.target,  # 分类结果集
           s=80,
           cmap=pl.cm.Paired)  # cmap 确定颜色
pl.axis('tight')
pl.show()
 
 

除此之外,sklearn还提供了

   RadiusNeighborsClassifier

   KNeighborsRegressor

   RadiusNeighborsRegressor

   NearestNeighbors

猜你喜欢

转载自blog.csdn.net/dongrixinyu/article/details/79039434