机器学习笔记3-k近邻法

机器学习笔记3-k近邻法

k近邻法输入为实例的特征向量,对应于特征空间中的点;输出为实例的类别。分类时,会根据其k个最近邻的训练实例的类别,通过多数表决等方式进行预测。因此,k近邻法不具有显示的学习过程。它包括三个基本要素:k值的选择、距离度量以及分类决策规则。

  • k值的选择会对算法结果产生重要影响。当选择较小的k值时,只有与实例点较近的训练实例会对预测结果起作用,近似误差会减小。但预测结果会对近邻的训练实例非常敏感,估计误差会增大。如果邻近训练实例恰好是噪声,预测就会出错。换句话说,k值的减小就意味着整体模型变得复杂,容易发生过拟合;如果选择较大的k值,可以减少学习的估计误差,但近似误差会增大。这时与实例较远的训练实例也会对预测起作用。k值的增大意味着模型变得简单。在应用中,k值一般取一个比较小的数值,可以用grid_search来找一个最佳k值。
  • 距离度量,能反映出特征空间中两个实例点的相似程度。这里距离一般用欧式距离,也可以用更一般的 L p L_p 距离。
    L p ( x i , x j ) = ( l = 1 n x i ( l ) x j ( l ) p ) 1 p {L_p}({x_i},{x_j}) = {\left( {\sum\limits_{l = {\rm{1}}}^n {{{\left| {x_i^{{\rm{(}}l{\rm{)}}} - x_j^{{\rm{(}}l{\rm{)}}}} \right|}^p}} } \right)^{\frac{{\rm{1}}}{p}}}
    这里 p 1 p \ge 1 。当 p = 2 p=2 时,为欧氏距离;当 p = 1 p=1 时,为曼哈顿距离;当 p = p=\infty 时,为各个坐标距离的最大值。
  • 分类决策规则一般会采用多数表决

k近邻法的实现:kd树
k近邻法最简单的实现方法是线性扫描,这时要计算实例与每个训练实例的距离。这种方法非常耗时。为了提高算法效率,可以用特殊的结构存储训练数据,进而基于这个数据结构进行搜索。比如构建kd树的方法。kd树有点类似于二叉搜索树,两者都满足对于一个根节点,其值不小于左子树的任何节点,且不大于右子树的任何节点。所不同的是构造过程,kd树是基于 R n R^n 空间,会直接对特征空间每一维进行划分;二叉搜索树是将元素一个一个添加的过程,与堆的构建一样。

  1. 如何构造kd树
    输入:k维空间数据集T={ x 1 , x 2 . . . x n x_1,x_2...x_n },其中 x i = ( x i ( 1 ) , x i ( 2 ) ,   , x i ( k ) ) T {x_i} = {(x_i^{(1)},x_i^{(2)}, \cdots ,x_i^{(k)})^T}
    (1)选择 x ( 1 ) x^{(1)} 为坐标轴,以T中所有实例的 x ( 1 ) x^{(1)} 坐标的中位数为切分点(根结点),将 x ( 1 ) x^{(1)} 这一维分成两个子树,左子树对应坐标 x ( 1 ) x^{(1)} 小于根节点的坐标,右子树对应坐标 x ( 1 ) x^{(1)} 大于根节点的坐标。
    (2)重复:对深度为 j j 的结点,选择 x ( l ) x^{(l)} 这一维进行切分, l = j / / k + 1 l=j//k+1 ,以 x ( l ) x^{(l)} 这一维的中位数作为切分点(根结点),将该结点所包含的数据集划分到左右两个子树中。
    (3)直到所有叶结点只包括一个样本,则停止划分。
  2. 如何搜索kd树
    从根结点出发,向下访问kd树。若目标点当前维的坐标小于切分点的坐标,则移动到左子结点,否则移到右子结点,直到子结点为叶结点。以此叶结点为当前最近点,递归地向上回退,在每个结点进行以下操作:
    (1)若该结点保存的实例点距离目标点更近,则以该实例点为当前最近点
    (2)检查该结点的另一子结点所包含的数据集是否有更近的点。如果有,则移到该子结点区域递归地进行最近邻搜索,否则向上回退
    (3)当回退到根结点,搜索结束。(此处写的比较粗糙,具体可参考李航《统计学习方法》,从划分区域和球体相交的角度更好理解)

在python的机器学习库scikit-learn中,有能直接拿来用的knn函数KNeighborsClassifier,其参数n_neighbors即为k值。以下是利用KNeighborsClassifier实现的一小段代码,数据集是sklearn中的内置数据集:

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.neighbors import KNeighborsClassifier 

iris = load_iris()
x, y = iris.data, iris.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25,random_state=33)
scaler=preprocessing.StandardScaler()
x_train=scaler.fit_transform(x_train)
x_test=scaler.transform(x_test)
knn=KNeighborsClassifier(n_neighbors=3) 
knn.fit(x_train,y_train)
y_train_predict=knn.predict(x_train)
from sklearn import metrics
print(metrics.accuracy_score(y_train,y_train_predict))
y_predict=knn.predict(x_test)
print(metrics.accuracy_score(y_test,y_predict))

参考
李航《统计学习方法》
https://mlnote.wordpress.com/2015/12/16/python机器学习实践与kaggle实战-machine-learning-for-kaggle-competition-in-python/

猜你喜欢

转载自blog.csdn.net/zhennang1427/article/details/85101491