




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
KNN算法介绍与参数调优K近邻法(k-nearest neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用。比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出了。这里就运用了KNN的思想。KNN方法既可以做分类,也可以做回归,这点和决策树算法相同。KNN做回归和分类的主要区别在于最后做预测时候的决策方式不同。KNN做分类预测时,一般是选择多数表决法,即训练集里和预测的样本特征最近的K个样本,预测为里面有最多类别数的类别。而KNN做回归时,一般是选择平均法,即最近的K个样本的样本输出的平均值作为回归预测值。由于两者区别不大,虽然本文主要是讲解KNN的分类方法,但思想对KNN的回归方法也适用。由于scikit-learn里只使用了蛮力实现(brute-force),KD树实现(KDTree)和球树(BallTree)实现,本文只讨论这几种算法的实现原理。1. KNN算法三要素KNN算法我们主要要考虑三个重要的要素,对于固定的训练集,只要这三点确定了,算法的预测方式也就决定了。这三个最终的要素是k值的选取,距离度量的方式和分类决策规则。对于分类决策规则,一般都是使用前面提到的多数表决法。所以我们重点是关注与k值的选择和距离的度量方式。对于k值的选择,没有一个固定的经验,一般根据样本的分布,选择一个较小的值,可以通过交叉验证选择一个合适的k值。选择较小的k值,就相当于用较小的领域中的训练实例进行预测,训练误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是泛化误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合;选择较大的k值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少泛化误差,但缺点是训练误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。一个极端是k等于样本数m,则完全没有分类,此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的类,模型过于简单。对于距离的度量,我们有很多的距离度量方式,但是最常用的是欧式距离,即对于两个n维向量x和y,两者的欧式距离定义为:Dx,y=i=1n(xi-yi)2大多数情况下,欧式距离可以满足我们的需求,我们不需要再去操心距离的度量。当然我们也可以用他的距离度量方式。比如曼哈顿距离,定义为:Dx,y=i=1n|xi-yi|更加通用点,比如闵可夫斯基距离(Minkowski Distance),定义为:Dx,y=pi=1n|xi-yi|p可以看出,欧式距离是闵可夫斯基距离在p=2时的特例,而曼哈顿距离是p=1时的特例。2. KNN算法蛮力实现从本节起,我们开始讨论KNN算法的实现方式。首先我们看看最想当然的方式。既然我们要找到k个最近的邻居来做预测,那么我们只需要计算预测样本和所有训练集中的样本的距离,然后计算出最小的k个距离即可,接着多数表决,很容易做出预测。这个方法的确简单直接,在样本量少,样本特征少的时候有效。但是在实际运用中很多时候用不上,为什么呢?因为我们经常碰到样本的特征数有上千以上,样本量有几十万以上,如果我们这要去预测少量的测试集样本,算法的时间效率很成问题。因此,这个方法我们一般称之为蛮力实现。比较适合于少量样本的简单模型的时候用。既然蛮力实现在特征多,样本多的时候很有局限性,那么我们有没有其他的好办法呢?有!这里我们讲解两种办法,一个是KD树实现,一个是球树实现。3. KNN算法之KD树实现原理KD树算法没有一开始就尝试对测试样本分类,而是先对训练集建模,建立的模型就是KD树,建好了模型再对测试集做预测。所谓的KD树就是K个特征维度的树,注意这里的K和KNN中的K的意思不同。KNN中的K代表最近的K个样本,KD树中的K代表样本特征的维数。为了防止混淆,后面我们称特征维数为n。KD树算法包括三步,第一步是建树,第二部是搜索最近邻,最后一步是预测。1.1 KD树的建立我们首先来看建树的方法。KD树建树采用的是从m个样本的n维特征中,分别计算n个特征的取值的方差,用方差最大的第k维特征nk来作为根节点。对于这个特征,我们选择特征nk的取值的中位数nkv对应的样本作为划分点,对于所有第k维特征的取值小于nkv的样本,我们划入左子树,对于第k维特征的取值大于等于nkv的样本,我们划入右子树,对于左子树和右子树,我们采用和刚才同样的办法来找方差最大的特征来做更节点,递归的生成KD树。 具体流程如下图:比如我们有二维样本6个,(2,3),(5,4),(9,6),(4,7),(8,1),(7,2),构建kd树的具体步骤为:1)找到划分的特征。6个数据点在x,y维度上的数据方差分别为6.97,5.37,所以在x轴上方差更大,用第1维特征建树。2)确定划分点(7,2)。根据x维上的值将数据排序,6个数据的中值(所谓中值,即中间大小的值)为7,所以划分点的数据是(7,2)。这样,该节点的分割超平面就是通过(7,2)并垂直于:划分点维度的直线x=7;3)确定左子空间和右子空间。 分割超平面x=7将整个空间分为两部分:x=7的部分为左子空间,包含3个节点=(2,3),(5,4),(4,7);另一部分为右子空间,包含2个节点=(9,6),(8,1)。4)用同样的办法划分左子树的节点(2,3),(5,4),(4,7)和右子树的节点(9,6),(8,1)。最终得到KD树。最后得到的KD树如下:1.2 KD树搜索最近邻当我们生成KD树以后,就可以去预测测试集里面的样本目标点了。对于一个目标点,我们首先在KD树里面找到包含目标点的叶子节点。以目标点为圆心,以目标点到叶子节点样本实例的距离为半径,得到一个超球体,最近邻的点一定在这个超球体内部。然后返回叶子节点的父节点,检查另一个子节点包含的超矩形体是否和超球体相交,如果相交就到这个子节点寻找是否有更加近的近邻,有的话就更新最近邻。如果不相交那就简单了,我们直接返回父节点的父节点,在另一个子树继续搜索最近邻。当回溯到根节点时,算法结束,此时保存的最近邻节点就是最终的最近邻。从上面的描述可以看出,KD树划分后可以大大减少无效的最近邻搜索,很多样本点由于所在的超矩形体和超球体不相交,根本不需要计算距离。大大节省了计算时间。我们用3.1建立的KD树,来看对点(2,4.5)找最近邻的过程。先进行二叉查找,先从(7,2)查找到(5,4)节点,在进行查找时是由y = 4为分割超平面的,由于查找点为y值为4.5,因此进入右子空间查找到(4,7),形成搜索路径,但 (4,7)与目标查找点的距离为3.202,而(5,4)与查找点之间的距离为3.041,所以(5,4)为查询点的最近点;以(2,4.5)为圆心,以3.041为半径作圆,如下图所示。可见该圆和y = 4超平面交割,所以需要进入(5,4)左子空间进行查找,也就是将(2,3)节点加入搜索路径中得;于是接着搜索至(2,3)叶子节点,(2,3)距离(2,4.5)比(5,4)要近,所以最近邻点更新为(2,3),最近距离更新为1.5;回溯查找至(5,4),直到最后回溯到根结点(7,2)的时候,以(2,4.5)为圆心1.5为半径作圆,并不和x = 7分割超平面交割,如下图所示。至此,搜索路径回溯完,返回最近邻点(2,3),最近距离1.5。对应的图如下:1.3 KD树预测有了KD树搜索最近邻的办法,KD树的预测就很简单了,在KD树搜索最近邻的基础上,我们选择到了第一个最近邻样本,就把它置为已选。在第二轮中,我们忽略置为已选的样本,重新选择最近邻,这样跑k次,就得到了目标的K个最近邻,然后根据多数表决法,如果是KNN分类,预测为K个最近邻里面有最多类别数的类别。如果是KNN回归,用K个最近邻样本输出的平均值作为回归预测值。4.KNN算法之球树实现原理KD树算法虽然提高了KNN搜索的效率,但是在某些时候效率并不高,比如当处理不均匀分布的数据集时,不管是近似方形,还是矩形,甚至正方形,都不是最好的使用形状,因为他们都有角。一个例子如下图:如果黑色的实例点离目标点星点再远一点,那么虚线圆会如红线所示那样扩大,导致与左上方矩形的右下角相交,既然相 交了,那么就要检查这个左上方矩形,而实际上,最近的点离星点的距离很近,检查左上方矩形区域已是多余。于此我们看见,KD树把二维平面划分成一个一个矩形,但矩形区域的角却是个难以处理的问题。为了优化超矩形体导致的搜索效率的问题,牛人们引入了球树,这种结构可以优化上面的这种问题。我们现在来看看球树建树和搜索最近邻的算法。4.1球树的建立球树,顾名思义,就是每个分割块都是超球体,而不是KD树里面的超矩形体。我们看看具体的建树流程:1) 先构建一个超球体,这个超球体是可以包含所有样本的最小球体。2) 从球中选择一个离球的中心最远的点,然后选择第二个点离第一个点最远,将球中所有的点分配到离这两个聚类中心最近的一个上,然后计算每个聚类的中心,以及聚类能够包含它所有数据点所需的最小半径。这样我们得到了两个子超球体,和KD树里面的左右子树对应。3)对于这两个子超球体,递归执行步骤2). 最终得到了一个球树。可以看出KD树和球树类似,主要区别在于球树得到的是节点样本组成的最小超球体,而KD得到的是节点样本组成的超矩形体,这个超球体要与对应的KD树的超矩形体小,这样在做最近邻搜索的时候,可以避免一些无谓的搜索。4.2球树搜索最近邻使用球树找出给定目标点的最近邻方法是首先自上而下贯穿整棵树找出包含目标点所在的叶子,并在这个球里找出与目标点最邻近的点,这将确定出目标点距离它的最近邻点的一个上限值,然后跟KD树查找一样,检查兄弟结点,如果目标点到兄弟结点中心的距离超过兄弟结点的半径与当前的上限值之和,那么兄弟结点里不可能存在一个更近的点;否则的话,必须进一步检查位于兄弟结点以下的子树。检查完兄弟节点后,我们向父节点回溯,继续搜索最小邻近值。当回溯到根节点时,此时的最小邻近值就是最终的搜索结果。从上面的描述可以看出,KD树在搜索路径优化时使用的是两点之间的距离来判断,而球树使用的是两边之和大于第三边来判断,相对来说球树的判断更加复杂,但是却避免了更多的搜索,这是一个权衡。5.KNN算法的扩展这里我们再讨论下KNN算法的扩展,限定半径最近邻算法。有时候我们会遇到这样的问题,即样本中某系类别的样本非常的少,甚至少于K,这导致稀有类别样本在找K个最近邻的时候,会把距离其实较远的其他样本考虑进来,而导致预测不准确。为了解决这个问题,我们限定最近邻的一个最大距离,也就是说,我们只在一个距离范围内搜索所有的最近邻,这避免了上述问题。这个距离我们一般称为限定半径。接着我们再讨论下另一种扩展,最近质心算法。这个算法比KNN还简单。它首先把样本按输出类别归类。对于第 L类的Cl个样本。它会对这Cl个样本的n维特征中每一维特征求平均值,最终该类别所有维度的n个平均值形成所谓的质心点。对于样本中的所有出现的类别,每个类别会最终得到一个质心点。当我们做预测时,仅仅需要比较预测样本和这些质心的距离,最小的距离对于的质心类别即为预测的类别。这个算法通常用在文本分类处理上。6.KNN算法小结KNN算法是很基本的机器学习算法了,它非常容易学习,在维度很高的时候也有很好的分类效率,因此运用也很广泛,这里总结下KNN的优缺点。KNN的主要优点有:1) 理论成熟,思想简单,既可以用来做分类也可以用来做回归。2) 可用于非线性分类。3) 训练时间复杂度比支持向量机之类的算法低,仅为O(n)。4) 和朴素贝叶斯之类的算法比,对数据没有假设,准确度高,对异常点不敏感。5) 由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。6)该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。KNN的主要缺点有:1)计算量大,尤其是特征数非常多的时候2)样本不平衡的时候,对稀有类别的预测准确率低3)KD树,球树之类的模型建立需要大量的内存4)使用懒散学习方法,基本上不学习,导致预测时速度比起逻辑回归之类的算法慢5)相比决策树模型,KNN模型可解释性不强4.scikit-learn K近邻法类库使用小结4.1scikit-learn 中KNN相关的类库概述在scikit-learn 中,与近邻法这一大类相关的类库都在sklearn.neighbors包之中。KNN分类树的类是KNeighborsClassifier,KNN回归树的类是KNeighborsRegressor。除此之外,还有KNN的扩展,即限定半径最近邻分类树的类RadiusNeighborsClassifier和限定半径最近邻回归树的类RadiusNeighborsRegressor, 以及最近质心分类算法NearestCentroid。在这些算法中,KNN分类和回归的类参数完全一样。限定半径最近邻法分类和回归的类的主要参数也和KNN基本一样。比较特别是的最近质心分类算法,由于它是直接选择最近质心来分类,所以仅有两个参数,距离度量和特征选择距离阈值,比较简单,因此后面就不再专门讲述最近质心分类算法的参数。另外几个在sklearn.neighbors包中但不是做分类回归预测的类也值得关注。kneighbors_graph类返回用KNN时和每个样本最近的K个训练集样本的位置。radius_neighbors_graph返回用限定半径最近邻法时和每个样本在限定半径内的训练集样本的位置。NearestNeighbors是个大杂烩,它即可以返回用KNN时和每个样本最近的K个训练集样本的位置,也可以返回用限定半径最近邻法时和每个样本最近的训练集样本的位置,常常用在聚类模型中。4.2K近邻法和限定半径最近邻法类库参数小结本节对K近邻法和限定半径最近邻法类库参数做一个总结。包括KNN分类树的类KNeighborsClassifier,KNN回归树的类KNeighborsRegressor, 限定半径最近邻分类树的类RadiusNeighborsClassifier和限定半径最近邻回归树的类RadiusNeighborsRegressor。这些类的重要参数基本相同,因此我们放到一起讲。参数KNeighborsClassifierKNeighborsRegressorRadiusNeighborsClassifierRadiusNeighborsRegressorKNN中的K值n_neighborsK值的选择与样本分布有关,一般选择一个较小的K值,可以通过交叉验证来选择一个比较优的K值,默认值是5。如果数据是三维一下的,如果数据是三维或者三维以下的,可以通过可视化观察来调参。不适用于限定半径最近邻法限定半径最近邻法中的半radius不适用于KNN半径的选择与样本分布有关,可以通过交叉验证来选择一个较小的半径,尽量保证每类训练样本其他类别样本的距离较远,默认值是1.0。如果数据是三维或者三维以下的,可以通过可视化观察来调参。近邻权重weights主要用于标识每个样本的近邻样本的权重,如果是KNN,就是K个近邻样本的权重,如果是限定半径最近邻,就是在距离在半径以内的近邻样本的权重。可以选择uniform,distance 或者自定义权重。选择默认的uniform,意味着所有最近邻样本权重都一样,在做预测时一视同仁。如果是distance,则权重和距离成反比例,即距离预测目标更近的近邻具有更高的权重,这样在预测类别或者做回归时,更近的近邻所占的影响因子会更加大。当然,我们也可以自定义权重,即自定义一个函数,输入是距离值,输出是权重值。这样我们可以自己控制不同的距离所对应的权重。一般来说,如果样本的分布是比较成簇的,即各类样本都在相对分开的簇中时,我们用默认的uniform就可以了,如果样本的分布比较乱,规律不好寻找,选择distance是一个比较好的选择。如果用distance发现预测的效果的还是不好,可以考虑自定义距离权重来调优这个参数。KNN和限定半径最近邻法使用的算法algorithm算法一共有三种,第一种是蛮力实现,第二种是KD树实现,第三种是球树实现。这三种方法在K近邻法(KNN)原理小结中都有讲述,如果不熟悉可以去复习下。对于这个参数,一共有4种可选输入,brute对应第一种蛮力实现,kd_tree对应第二种KD树实现,ball_tree对应第三种的球树实现, auto则会在上面三种算法中做权衡,选择一个拟合最好的最优算法。需要注意的是,如果输入样本特征是稀疏的时候,无论我们选择哪种算法,最后scikit-learn都会去用蛮力实现brute。个人的经验,如果样本少特征也少,使用默认的auto就够了。 如果数据量很大或者特征也很多,用auto建树时间会很长,效率不高,建议选择KD树实现kd_tree,此时如果发现kd_tree速度比较慢或者已经知道样本分布不是很均匀时,可以尝试用ball_tree。而如果输入样本是稀疏的,无论你选择哪个算法最后实际运行的都是brute。停止建子树的叶子节点阈值leaf_size这个值控制了使用KD树或者球树时, 停止建子树的叶子节点数量的阈值。这个值越小,则生成的KD树或者球树就越大,层数越深,建树时间越长,反之,则生成的KD树或者球树会小,层数较浅,建树时间较短。默认是30. 这个值一般依赖于样本的数量,随着样本数量的增加,这个值必须要增加,否则不光建树预测的时间长,还容易过拟合。可以通过交叉验证来选择一个适中的值。如果使用的算法是蛮力实现,则这个参数可以忽略。距离度量metricK近邻法和限定半径最近邻法类可以使用的距离度量较多,一般来说默认的欧式距离(即p=2的闵可夫斯基距离)就可以满足我们的需求。可以使用的距离度量参数有:a) 欧式距离“euclidean”: i=1n(xi-yi)2b) 曼哈顿距离 “manhattan”:i=1n|xi-yi|c) 切比雪夫距离“chebyshev”:max|xi-yi|(i=1,2,n)d)闵可夫斯基距离“minkowski”(默认参数):pi=1n|xi-yi|p,,p=1为哈曼顿距离,p=2是欧式距离。e) 带权重闵可夫斯基距离“wminkowski”:pi=1nw*|xi-yi|p f) 标准化欧式距离“seuclidean”: 即对于各特征维度做了归一化以后的欧式距离。此时各样本特征维度的均值为0,方差为1.g) 马氏距离“mahalanobis”: x-yTS-1(x-y),其中,S-1为样本协方差矩阵的逆矩阵。当样本分布独立时,S为单位矩阵,此时马氏距离等同于欧式距离。还有一些其他不是实数的距离度量,一般在KNN之类的算法用不上,这里也就不列了。距离度量附属参数pp是使用距离度量参数 metric 附属参数,只用于闵可夫斯基距离和带权重闵可夫斯基距离中p值的选择,p=1为曼哈顿距离, p=2为欧式距离。默认为2距离度量其他附属参数metric_params一般都用不上,主要是用于带权重闵可夫斯基距离的权重,以及其他一些比较复杂的距离度量的参数。并行处理任务数n_jobs主要用于多核CPU时的并行处理,加快建立KNN树和预测搜索的速度。一般用默认的-1就可以了,即所有的CPU核都参与计算。不适用于限定半径最近邻法异常点类别选择outlier_label不适用于KNN主要用于预测时,如果目标点半径内没有任何训练集的样本点时,应该标记的类别,不建议选择默认值 none,因为这样遇到异常点会报错。一般设置为训练集里最多样本的类别。不适用于限定半径最近邻回归4.3使用KNeighborsRegressor做回归的实例1数据情况:boston数据集2.建模的过程(1)标准化数据(2)初步搜索 n_neighbors,algorithm(3)搜索 leaf_size、wights(4)搜索p值(5)用最佳训练的参数进行预测3.涉及核心内容 自定义scoring的使用1. 自定义评价函数评价函数的输入是实际的label(y_true)和模型的输出label(y_pred)def my_custom_loss_func(y_true, y_pred): :param y_true:实际label :param y_pred: 预测的label :return: r2 =0.5* r2_score(y_true,y_pred) return r22.scoring函数的制作通过 greater_is_better 参数设定scoring的值的优化方向通过 greater_is_better 参数设定scoring的值的优化方向score = make_scorer(my_custom_loss_func, greater_is_better=True)from sklearn.datasets import load_bostonfrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import StandardScalerimport numpy as npfrom sklearn.neighbors import KNeighborsRegressorfrom sklearn.model_selection import GridSearchCVfrom sklearn.metrics import r2_score,mean_absolute_error,mean_squared_error,make_scorerdef search_best_param(clf,X,y,param_base,param_grid,scoring=r2): clf.set_params(*param_base) gs = GridSearchCV( estimator=clf, param_grid=param_grid, scoring=scoring, n_jobs=-1, iid=False, cv=5) gs.fit(X,y) param_base.update(gs.best_params_) print(nbest param:%s%str(gs.best_params_)+ best score:%s%str(gs.best_score_) return param_basedef model_select_step(clf,X,y,param_grids,scoring=r2): param_base=clf.get_params() for param_grid in param_grids: param_base = search_best_param(clf, X, y, param_base=param_base, param_grid=param_grid, scoring=scoring) return param_base自定义scoringdef my_custom_loss_func(y_true, y_pred): :param y_true:实际label :param y_pred: 预测的label :return: r2 =0.5* r2_score(y_true,y_pred) return r2if _name_=_main_: boston = load_boston() X = boston.data y = boston.target X_tra
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026届盘锦市重点中学英语九上期末检测模拟试题含解析
- 2026届浙江省宁波市董玉娣中学九年级化学第一学期期中学业水平测试模拟试题含解析
- 2025版二手房预约买卖合同定金
- 2025借款合同文本正规范本
- 2025样品测试分析技术服务合同
- 2025地勘合同范本
- 文化产业公司担保借款合同范本
- 跨境电商企业员工国际物流与贸易合同
- 酒店水电改造合同6篇
- 常用个人借款合同6篇
- 检验科设备管理制度
- 工程项目借款管理制度
- GB/T 21711.3-2025基础机电继电器第3部分:强制定位(机械联锁)触点继电器
- CJ/T 338-2010生活垃圾转运站压缩机
- 电价合同补充协议书
- 糖尿病前期治未病干预指南(2025版)解读
- 儿童人工智能科普小课堂教学课件
- 羊肚菌种植合作协议合同
- 中山文化课件
- 体育数据治理的流通与规制问题研究
- 社会稳定风险评估协议模板合同8篇
评论
0/150
提交评论