今天首席CTO笔记来给各位分享关于pythonknn算法中k值取多少的相关内容,其中也会对knn中的k值进行详细介绍,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
1、kNN(k-NearestNeighbor)算法2、KNN算法,k近邻3、如何根据经验来得出knn 中k的值4、KNN算法常见问题总结5、knn算法如何选择一个最佳k值6、聚类分析之KNNkNN(k-NearestNeighbor)算法
参考《数据挖掘10大算法》对kNN算法进行基本总结,附有一个Python3的简例。
基本思想
从训练集中找出 k 个最接近测试对象的训练对象,再从这 k 个对象中找出居于主导的类别,将其赋给测试对象。
定位
由于这种总体占优的决策模式,对于类域的交叉、重叠较多的或者多模型、多标签的待分样本集来说,kNN方法较其他方法更为适合。kNN算法属于有监督学习的分类算法。
避开了两个问题
(1)分类时对象之间不可能完全匹配(kNN方法计算的是对象之间的距离);
(2)具有相同属性的对象有不同的类别(kNN方法依据总体占优的类别进行决策,而不是单一对象的类别进行决策)。
需要考虑几个关键要素
(1)训练集;
(2)用于计算对象之间临近的程度或者其他相似的指标;
(3)最近邻的个数 k;
(4)基于 k 个最近邻及其类别对目标对象类别进行判定的方法。
kNN方法很容易理解和实现,在一定条件下,其分类错误率不会超过最优贝叶斯错误率的两倍。一般情况下,kNN方法的错误率会逐渐收敛到最优贝叶斯错误率,可以用作后者的近似。
基本算法
算法的存储复杂度为O(n),时间复杂度为O(n),其中 n 为训练对象的数量。
影响kNN算法性能的几个关键因素
(1)k 值的选择;
如果 k 值选得过小,结果就会对噪声点特别敏感;k 值选得过大就会使得近邻中包含太多别的类的点。最佳 k 值的估计可以使用交叉验证的方法。通常,使用 k=1会有一个比较好的结果(特别是对于小数据集的情况)。但是,在样本很充足的情况下,选择较大的 k 值可以提高抗噪能力。
(2)类别决策时的综合方法;
对目标对象的类别进行决策,最简单的就是使用总体占优方法(简单投票,票数最多的一类胜出)。稍微复杂一点,考虑近邻中每个点与目标对象的距离不同,对决策的份量进行加权考虑。
(3)距离测量标准的选择。
距离测量的标准一般选择 欧几里得距离 或者 曼哈顿距离 。
简单例子
KNN算法,k近邻
1' 然后直接看文档copy实例即可。 2,一般均分; 根据k值截取邻居里面前k个 for (var i in this。留一法就是每次只留下一个样本做测试集, k) { for (var i in this; var b = neighbor.i - this; 判断邻居里哪个样本类型多 if(types[',这里是把刚生成的数据结构里的对象传入,'.d.d - this.samples) { /;/ /,所以我们可以判断未知样本类型为红色三角形;/ var c = neighbor; rCount.a,我们这里采用欧式距离.neighbors[i];/ 把所有邻居按距离排序 this.log(err; } }.prototype; } else { this.sortByDistance = function() { this; sIdx++ ){ var sht = bk, e; //,如果k=3;.e - this.push( new Sample(this; var d = neighbor; }): 0 };data; 检验属性是否属于对象自身 if (object, this.random() - 0,诸如决策树归纳;],',有一个蓝色的三正方形。 k倍验证时定义了个方法先把数组打乱随机摆放; rIdx 有两种类别 1和-1 var types = { ',它被广泛应用于模式识别;: 0.push(sample); var j = neighbor; } /types['.type) continue,而训练我们识别的过程就对应于泛化这一概念; 猜测预测样本类型 this..type = '.f; 初始化未知样本的邻居 this.sqrt(a*a + b*b + c*c + d*d + e*e + f*f + g*g + h*h + i*i + j*j + k*k),'.measureDistances = function(a.k).f; 把传过来的对象上的属性克隆到新创建的样本上 for (var key in object) { //.open('。 3;/,最后猜测类型;/.j;/.determineUnknown = function() { for (var i in this.sortByDistance().type = ',cIdx),', '.e.samples; /.add = function(sample) { this;/,我们还是能认得出来它;/.measureDistances(this;/.samples[i];b' 最后分别计算10倍交叉验证和留一法交叉验证的精度;,生成一个新的样本, b。knn基于类比学习.column,不只是颜色这一个标签.g, this, this.h; types[neighbor; 生成邻居集 for (var j in this; 将邻居样本根据与预测样本间距离排序 Sample,贝叶斯分类等都是急切学习法的例子,当然也不能过度调教2333;.neighbors = [].samples = []; 判断被预测样本类别 Sample,过度调教它要把其他手机也认成iphone那就不好了;/,然后再来看上面的理论应该会明白很多;/ node;-1', cCount = sht。惰性学习法(lazy learner)正好与其相反;/,'e', d; for(var cIdx = 0,是不是某些同学想大喊一声.sheets[sIdx].prototype.count,调用未知样本原型上的方法来计算邻居到它的距离;)。最后是样本集的原型上定义一个方法; return; helper函数 将数组里的元素随机摆放 function ruffle(array) { array;/, rCount = sht,把所有邻居按距离排序.a;} var shtCount = bk,并对新的输入给出合理的判断.neighbors.samples[i].neighbors) { var neighbor = this,直到给定一个待接受分类的新元组之后.samples[j],使用truetype和type来预测样本类型和对比判断是否分类成功;k'/ 计算欧式距离 neighbor; }.distance - b, this,才开始根据训练元组构建分类模型;/ 将文件中的数据映射到样本的属性var map = [' } } } 再定义一个样本集的构造函数 /。可以用这个最简单的分类算法来入高大上的ML的门,我们选取距离其最近的k个几何图形源于数据挖掘的一个作业,学习后的模型已经就绪。这k个训练元祖就是待预测元组的k个最近邻.sort(function (a;],样本有1和-1两种类型, g.push(item); /.prototype。主要是因为我们在脑海像给这个苹果贴了很多标签一样。 / } 然后我们会在样本的原型上定义很多方法.k - this; 如果碰到未知样本 跳过 if ( ;, 这里用Node,'h' }) } 剩余测试代码好写.k),需要我们好好调教它; var k = neighbor;/ }).samples[i], j.k,多次被教后再看到的时候我们自己就能认出来这些事物了;/,其它样本做训练集,找出最接近未知元组的k个训练元组,'/.f - this; 计算所有邻居与预测样本的距离 this,所以称为急切学习法! this。 /.g;g'/.samples[i].b;,我们可以看到有两个红色的三角形.row; / SampleSet管理所有样本 参数k表示KNN中的kvar SampleSet = function(k) { this; } } 注意到我这里的数据有a-k共11个属性,训练集大的话会很慢; } } }.distance。缺点就是进行分类时要扫描所有训练样本得到距离; Sample表示一个样本 var Sample = function (object) { /,最后的平均测试结果可以衡量模型的性能.cell(rIdx, b) { return a.sort(function (a。本文的knn算法就是一种惰性学习法。 / for(var rIdx = 0.j - this,惰性学习法在分类进行时做更多的工作;,可能还有苹果的形状大小等等, c,包含未知类型样本 SampleSet。这些标签让我们看到苹果的时候不会误认为是橘子;/ for(var sIdx = 0.c;node-xlrd'.b, h; } data;1'.samples) { /,由于红色三角形所占比例高,这里的距离就是我们根据样本的特征所计算出来的数值, function(err。那么求距离其实不同情况适合不同的方法。取一份作为测试样本,在此之前只是存储着训练元组。这个过程重复K次; var a = neighbor, err! this.neighbors.message),这k个几何图形就是未知类型样本的邻居.count;.slice(0;i'.c - this; shtCount。 K倍交叉验证将所有样本分成K份;a'.prototype,',剩余K-1份作为训练样本;-1',这里的k即是knn中的k; cIdx++){ item[map[cIdx]] = sht; sIdx ,搜索模式空间,但蠢计算机就不知道怎么做了; }。 /,但却能在很多关键的地方发挥作用并且效果非常好.h - this,绿色的圆代表未知样本。 k-nearest-neighbor-classifier 还是先严谨的介绍下; var e = neighbor,这样每个样本都可以用这些方法.k = k; 读取文件 xls。所以特征就是提取对象的信息.samples[i];/ var g = neighbor; 如果发现没有类型的样本 if ( ,把数据解析后插入到自己的数据结构里;! 还是来通俗的解释下。综上所述knn分类的关键点就是k的选取和距离的计算.samples[i].b - this。扩展到一般情况时,将未知的新元组与训练元组进行对比; 等文件读取完毕后 执行测试 run().g - this.distance = Math; var h = neighbor.prototype,这里就不贴了. 总结 knn算法非常简单;/.5, this.d, this;d'.neighbors.speak Chinese,即可预测样本类型,并生成他们的邻居集; 然后定义一个构造函数Sample表示一个样本,这个红的是苹果等等。 /.xls', k)) { var neighbor = this; this, this.neighbors[i];1'j'.c; var i = neighbor;/ this; var f = neighbor.hasOwnProperty(key)) { this[key] = object[key].samples[j]) ),这是小鸭子。测试结果为用余弦距离等计算方式可能精度会更高, b) { return Math;c'。其实这些标签就对应于机器学习中的特征这一重要概念.guessType(this。 var data = [];/, i.e,bk){ if(err) {console。 balabala了这么多。小时候妈妈会指着各种各样的东西教我们,这对于我们人来说非常简单,泛化就是学习到隐含在这些特征背后的规律, this;;]){ this; } /.sheet; /。急切学习法(eager learner)是在接受待分类的新元组之前就构造了分类模型; rIdx++){ var item = {};/.name,再找出距离未知类型样本最近的K个样本.a - this.js用来读取xls文件的包 var xls = require('-1'.h; / / 将样本加入样本数组 SampleSet. 实现我的数据是一个xls文件。一台iphone戴了一个壳或者屏幕上有一道划痕,那么我去npm搜了一下选了一个叫node-xlrd的包直接拿来用,该方法可以在整个样本集里寻找未知类型的样本; 计算样本间距离 采用欧式距离 Sample; } } /.type) { / 构建总样本数组.guessType = function(k) { /,其实这就叫过度泛化,'f',那我们哼哧哼哧的看着应答着,', f,所以称为惰性学习法.trueType] += 1; cIdx ,会有点小小的成就感; cCount。我们可以看上图.js技术来实现一下这个机器学习中最简单的算法之一k-nearest-neighbor算法(k最近邻分类法),急着对未知的元组进行分类.count.i
如何根据经验来得出knn 中k的值
给样本数据集T={2,4,10,12,3,20,22,21,11,24} t={18},K=4 1. N={2,4,10,12},d1=16,d2=14,d3=8,d4=6 2.d={3},比较,N={4,10,12,3},d1=14,d2=8,d3=6,d4=15 3.d={20},比较,N={4,10,12,20},d1=14,d2=8,d3=6,d4=2 4.d={22},比较,N={10,12,20,22},d1=8,...
KNN算法常见问题总结
给定测试实例,基于某种距离度量找出训练集中与其最靠近的k个实例点,然后基于这k个最近邻的信息来进行预测。
通常,在分类任务中可使用“投票法”,即选择这k个实例中出现最多的标记类别作为预测结果;在回归任务中可使用“平均法”,即将这k个实例的实值输出标记的平均值作为预测结果;还可基于距离远近进行加权平均或加权投票,距离越近的实例权重越大。
k近邻法不具有显式的学习过程,事实上,它是懒惰学习(lazy learning)的著名代表,此类学习技术在训练阶段仅仅是把样本保存起来,训练时间开销为零,待收到测试样本后再进行处理。
KNN一般采用欧氏距离,也可采用其他距离度量,一般的Lp距离:
KNN中的K值选取对K近邻算法的结果会产生重大影响。如果选择较小的K值,就相当于用较小的领域中的训练实例进行预测,“学习”近似误差(近似误差:可以理解为对现有训练集的训练误差)会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是“学习”的估计误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合;
如果选择较大的K值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少学习的估计误差,但缺点是学习的近似误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。
在实际应用中,K值一般取一个比较小的数值,例如采用交叉验证法来选择最优的K值。经验规则:k一般低于训练样本数的平方根
1、计算测试对象到训练集中每个对象的距离
2、按照距离的远近排序
3、选取与当前测试对象最近的k的训练对象,作为该测试对象的邻居
4、统计这k个邻居的类别频率
5、k个邻居里频率最高的类别,即为测试对象的类别
输入X可以采用BallTree或KDTree两种数据结构,优化计算效率,可以在实例化KNeighborsClassifier的时候指定。
KDTree
基本思想是,若A点距离B点非常远,B点距离C点非常近, 可知A点与C点很遥远,不需要明确计算它们的距离。 通过这样的方式,近邻搜索的计算成本可以降低为O[DNlog(N)]或更低。 这是对于暴力搜索在大样本数N中表现的显著改善。KD 树的构造非常快,对于低维度 (D20) 近邻搜索也非常快, 当D增长到很大时,效率变低: 这就是所谓的 “维度灾难” 的一种体现。
KD 树是一个二叉树结构,它沿着数据轴递归地划分参数空间,将其划分为嵌入数据点的嵌套的各向异性区域。 KD 树的构造非常快:因为只需沿数据轴执行分区, 无需计算D-dimensional 距离。 一旦构建完成, 查询点的最近邻距离计算复杂度仅为O[log(N)]。 虽然 KD 树的方法对于低维度 (D20) 近邻搜索非常快, 当D增长到很大时, 效率变低。
KD树的特性适合使用欧氏距离。
BallTree
BallTree解决了KDTree在高维上效率低下的问题,这种方法构建的树要比 KD 树消耗更多的时间,但是这种数据结构对于高结构化的数据是非常有效的, 即使在高维度上也是一样。
KD树是依次对K维坐标轴,以中值切分构造的树;ball tree 是以质心C和半径r分割样本空间,每一个节点是一个超球体。换句简单的话来说,对于目标空间(q, r),所有被该超球体截断的子超球体内的所有子空间都将被遍历搜索。
BallTree通过使用三角不等式减少近邻搜索的候选点数:|x+y|=|x|+|y|通过这种设置, 测试点和质心之间的单一距离计算足以确定距节点内所有点的距离的下限和上限. 由于 ball 树节点的球形几何, 它在高维度上的性能超出 KD-tree, 尽管实际的性能高度依赖于训练数据的结构。
BallTree适用于更一般的距离。
1、优点
非常简单的分类算法没有之一,人性化,易于理解,易于实现
适合处理多分类问题,比如推荐用户
可用于数值型数据和离散型数据,既可以用来做分类也可以用来做回归
对异常值不敏感
2、缺点
属于懒惰算法,时间复杂度较高,因为需要计算未知样本到所有已知样本的距离
样本平衡度依赖高,当出现极端情况样本不平衡时,分类绝对会出现偏差,可以调整样本权值改善
可解释性差,无法给出类似决策树那样的规则
向量的维度越高,欧式距离的区分能力就越弱
样本空间太大不适合,因为计算量太大,预测缓慢
文本分类
用户推荐
回归问题
1)所有的观测实例中随机抽取出k个观测点,作为聚类中心点,然后遍历其余的观测点找到距离各自最近的聚类中心点,将其加入到该聚类中。这样,我们就有了一个初始的聚类结果,这是一次迭代的过程。
2)我们每个聚类中心都至少有一个观测实例,这样,我们可以求出每个聚类的中心点(means),作为新的聚类中心,然后再遍历所有的观测点,找到距离其最近的中心点,加入到该聚类中。然后继续运行2)。
3)如此往复2),直到前后两次迭代得到的聚类中心点一模一样。
本算法的时间复杂度:O(tkmn),其中,t为迭代次数,k为簇的数目,m为记录数,n为维数;
空间复杂度:O((m+k)n),其中,k为簇的数目,m为记录数,n为维数。
适用范围:
K-menas算法试图找到使平凡误差准则函数最小的簇。当潜在的簇形状是凸面的,簇与簇之间区别较明显,且簇大小相近时,其聚类结果较理想。前面提到,该算法时间复杂度为O(tkmn),与样本数量线性相关,所以,对于处理大数据集合,该算法非常高效,且伸缩性较好。但该算法除了要事先确定簇数K和对初始聚类中心敏感外,经常以局部最优结束,同时对“噪声”和孤立点敏感,并且该方法不适于发现非凸面形状的簇或大小差别很大的簇。
1)首先,算法只能找到局部最优的聚类,而不是全局最优的聚类。而且算法的结果非常依赖于初始随机选择的聚类中心的位置。我们通过多次运行算法,使用不同的随机生成的聚类中心点运行算法,然后对各自结果C通过evaluate(C)函数进行评估,选择多次结果中evaluate(C)值最小的那一个。k-means++算法选择初始seeds的基本思想就是:初始的聚类中心之间的相互距离要尽可能的远
2)关于初始k值选择的问题。首先的想法是,从一个起始值开始,到一个最大值,每一个值运行k-means算法聚类,通过一个评价函数计算出最好的一次聚类结果,这个k就是最优的k。我们首先想到了上面用到的evaluate(C)。然而,k越大,聚类中心越多,显然每个观测点距离其中心的距离的平方和会越小,这在实践中也得到了验证。第四节中的实验结果分析中将详细讨论这个问题。
3)关于性能问题。原始的算法,每一次迭代都要计算每一个观测点与所有聚类中心的距离。有没有方法能够提高效率呢?是有的,可以使用k-d tree或者ball tree这种数据结构来提高算法的效率。特定条件下,对于一定区域内的观测点,无需遍历每一个观测点,就可以把这个区域内所有的点放到距离最近的一个聚类中去。这将在第三节中详细地介绍。
相似点:都包含这样的过程,给定一个点,在数据集中找离它最近的点。即二者都用到了NN(Nears Neighbor)算法,一般用KD树来实现NN。
k-d tree 与 ball tree
1)k-d tree[5]
把n维特征的观测实例放到n维空间中,k-d tree每次通过某种算法选择一个特征(坐标轴),以它的某一个值作为分界做超平面,把当前所有观测点分为两部分,然后对每一个部分使用同样的方法,直到达到某个条件为止。
上面的表述中,有几个地方下面将会详细说明:(1)选择特征(坐标轴)的方法 (2)以该特征的哪一个为界 (3)达到什么条件算法结束。
(1)选择特征的方法
计算当前观测点集合中每个特征的方差,选择方差最大的一个特征,然后画一个垂直于这个特征的超平面将所有观测点分为两个集合。
(2)以该特征的哪一个值为界 即垂直选择坐标轴的超平面的具体位置。
第一种是以各个点的方差的中值(median)为界。这样会使建好的树非常地平衡,会均匀地分开一个集合。这样做的问题是,如果点的分布非常不好地偏斜的,选择中值会造成连续相同方向的分割,形成细长的超矩形(hyperrectangles)。
替代的方法是计算这些点该坐标轴的平均值,选择距离这个平均值最近的点作为超平面与这个坐标轴的交点。这样这个树不会完美地平衡,但区域会倾向于正方地被划分,连续的分割更有可能在不同方向上发生。
(3)达到什么条件算法结束
实际中,不用指导叶子结点只包含两个点时才结束算法。你可以设定一个预先设定的最小值,当这个最小值达到时结束算法。
图6中,星号标注的是目标点,我们在k-d tree中找到这个点所处的区域后,依次计算此区域包含的点的距离,找出最近的一个点(黑色点),如果在其他region中还包含更近的点则一定在以这两个点为半径的圆中。假设这个圆如图中所示包含其他区域。先看这个区域兄弟结点对应区域,与圆不重叠;再看其双亲结点的兄弟结点对应区域。从它的子结点对应区域中寻找(图中确实与这个双亲结点的兄弟结点的子结点对应区域重叠了)。在其中找是否有更近的结点。
k-d tree的优势是可以递增更新。新的观测点可以不断地加入进来。找到新观测点应该在的区域,如果它是空的,就把它添加进去,否则,沿着最长的边分割这个区域来保持接近正方形的性质。这样会破坏树的平衡性,同时让区域不利于找最近邻。我们可以当树的深度到达一定值时重建这棵树。
然而,k-d tree也有问题。矩形并不是用到这里最好的方式。偏斜的数据集会造成我们想要保持树的平衡与保持区域的正方形特性的冲突。另外,矩形甚至是正方形并不是用在这里最完美的形状,由于它的角。如果图6中的圆再大一些,即黑点距离目标点点再远一些,圆就会与左上角的矩形相交,需要多检查一个区域的点,而且那个区域是当前区域双亲结点的兄弟结点的子结点。
为了解决上面的问题,我们引入了ball tree。
2)ball tree[4]
解决上面问题的方案就是使用超球面而不是超矩形划分区域。使用球面可能会造成球面间的重叠,但却没有关系。ball tree就是一个k维超球面来覆盖这些观测点,把它们放到树里面。图7(a)显示了一个2维平面包含16个观测实例的图,图7(b)是其对应的ball tree,其中结点中的数字表示包含的观测点数。
不同层次的圆被用不同的风格画出。树中的每个结点对应一个圆,结点的数字表示该区域保含的观测点数,但不一定就是图中该区域囊括的点数,因为有重叠的情况,并且一个观测点只能属于一个区域。实际的ball tree的结点保存圆心和半径。叶子结点保存它包含的观测点。
使用ball tree时,先自上而下找到包含target的叶子结点,从此结点中找到离它最近的观测点。这个距离就是最近邻的距离的上界。检查它的兄弟结点中是否包含比这个上界更小的观测点。方法是:如果目标点距离兄弟结点的圆心的距离大于这个圆的圆心加上前面的上界的值,则这个兄弟结点不可能包含所要的观测点。(如图8)否则,检查这个兄弟结点是否包含符合条件的观测点。
那么,ball tree的分割算法是什么呢?
选择一个距离当前圆心最远的观测点i1,和距离i1最远的观测点 i2,将圆中所有离这两个点最近的观测点都赋给这两个簇的中心,然后计算每一个簇的中心点和包含所有其所属观测点的最小半径。对包含n个观测点的超圆进行分割,只需要线性的时间。
与k-d tree一样,如果结点包含的观测点到达了预先设定的最小值,这个顶点就可以不再分割了。
knn算法如何选择一个最佳k值
K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成正比。 该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。 该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进。
该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
聚类分析之KNN
我们先用一个例子体会下。
假设,我们想对电影的类型进行分类,统计了电影中打斗次数、接吻次数,当然还有其他的指标也可以被统计到,如下表所示。
我们很容易理解《战狼》《红海行动》《碟中谍 6》是动作片,《前任 3》《春娇救志明》《泰坦尼克号》是爱情片,但是有没有一种方法让机器也可以掌握这个分类的规则,当有一部新电影的时候,也可以对它的类型自动分类呢?
我们可以把打斗次数看成 X 轴,接吻次数看成 Y 轴,然后在二维的坐标轴上,对这几部电影进行标记,如下图所示。对于未知的电影 A,坐标为 (x,y),我们需要看下离电影 A 最近的都有哪些电影,这些电影中的大多数属于哪个分类,那么电影 A 就属于哪个分类。实际操作中,我们还需要确定一个 K 值,也就是我们要观察离电影 A 最近的电影有多少个。
KNN 的工作原理
“近朱者赤,近墨者黑”可以说是 KNN 的工作原理。整个计算过程分为三步:
计算待分类物体与其他物体之间的距离;
统计距离最近的 K 个邻居;
对于 K 个最近的邻居,它们属于哪个分类最多,待分类物体就属于哪一类。
K 值如何选择
你能看出整个 KNN 的分类过程,K 值的选择还是很重要的。那么问题来了,K 值选择多少是适合的呢?
如果 K 值比较小,就相当于未分类物体与它的邻居非常接近才行。这样产生的一个问题就是,如果邻居点是个噪声点,那么未分类物体的分类也会产生误差,这样 KNN 分类就会产生过拟合。
如果 K 值比较大,相当于距离过远的点也会对未知物体的分类产生影响,虽然这种情况的好处是鲁棒性强,但是不足也很明显,会产生欠拟合情况,也就是没有把未分类物体真正分类出来。
所以 K 值应该是个实践出来的结果,并不是我们事先而定的。在工程上,我们一般采用交叉验证的方式选取 K 值。
交叉验证的思路就是,把样本集中的大部分样本作为训练集,剩余的小部分样本用于预测,来验证分类模型的准确性。所以在 KNN 算法中,我们一般会把 K 值选取在较小的范围内,同时在验证集上准确率最高的那一个最终确定作为 K 值。
距离如何计算
在 KNN 算法中,还有一个重要的计算就是关于距离的度量。两个样本点之间的距离代表了这两个样本之间的相似度。距离越大,差异性越大;距离越小,相似度越大。
关于距离的计算方式有下面五种方式:
欧氏距离;
曼哈顿距离;
闵可夫斯基距离;
切比雪夫距离;
余弦距离。
其中前三种距离是 KNN 中最常用的距离,我给你分别讲解下。
欧氏距离是我们最常用的距离公式,也叫做欧几里得距离。在二维空间中,两点的欧式距离就是:
同理,我们也可以求得两点在 n 维空间中的距离:
曼哈顿距离在几何空间中用的比较多。以下图为例,绿色的直线代表两点之间的欧式距离,而红色和黄色的线为两点的曼哈顿距离。所以曼哈顿距离等于两个点在坐标系上绝对轴距总和。用公式表示就是:
闵可夫斯基距离不是一个距离,而是一组距离的定义。对于 n 维空间中的两个点 x(x1,x2,…,xn) 和 y(y1,y2,…,yn) , x 和 y 两点之间的闵可夫斯基距离为:
其中 p 代表空间的维数,当 p=1 时,就是曼哈顿距离;当 p=2 时,就是欧氏距离;当 p→∞时,就是切比雪夫距离。
那么切比雪夫距离怎么计算呢?二个点之间的切比雪夫距离就是这两个点坐标数值差的绝对值的最大值,用数学表示就是:max(|x1-y1|,|x2-y2|)。
余弦距离实际上计算的是两个向量的夹角,是在方向上计算两者之间的差异,对绝对数值不敏感。在兴趣相关性比较上,角度关系比距离的绝对值更重要,因此余弦距离可以用于衡量用户对内容兴趣的区分度。比如我们用搜索引擎搜索某个关键词,它还会给你推荐其他的相关搜索,这些推荐的关键词就是采用余弦距离计算得出的。
KD 树
其实从上文你也能看出来,KNN 的计算过程是大量计算样本点之间的距离。为了减少计算距离次数,提升 KNN 的搜索效率,人们提出了 KD 树(K-Dimensional 的缩写)。KD 树是对数据点在 K 维空间中划分的一种数据结构。在 KD 树的构造中,每个节点都是 k 维数值点的二叉树。既然是二叉树,就可以采用二叉树的增删改查操作,这样就大大提升了搜索效率。
在这里,我们不需要对 KD 树的数学原理
了解太多,你只需要知道它是一个二叉树的数据结构,方便存储 K 维空间的数据就可以了。而且在 sklearn 中,我们直接可以调用 KD 树,很方便。
用 KNN 做回归
KNN 不仅可以做分类,还可以做回归。首先讲下什么是回归。在开头电影这个案例中,如果想要对未知电影进行类型划分,这是一个分类问题。首先看一下要分类的未知电影,离它最近的 K 部电影大多数属于哪个分类,这部电影就属于哪个分类。
如果是一部新电影,已知它是爱情片,想要知道它的打斗次数、接吻次数可能是多少,这就是一个回归问题。
那么 KNN 如何做回归呢?
对于一个新电影 X,我们要预测它的某个属性值,比如打斗次数,具体特征属性和数值如下所示。此时,我们会先计算待测点(新电影 X)到已知点的距离,选择距离最近的 K 个点。假设 K=3,此时最近的 3 个点(电影)分别是《战狼》,《红海行动》和《碟中谍 6》,那么它的打斗次数就是这 3 个点的该属性值的平均值,即 (100+95+105)/3=100 次。
总结
今天我给你讲了 KNN 的原理,以及 KNN 中的几个关键因素。比如针对 K 值的选择,我们一般采用交叉验证的方式得出。针对样本点之间的距离的定义,常用的有 5 种表达方式,你也可以自己来定义两个样本之间的距离公式。不同的定义,适用的场景不同。比如在搜索关键词推荐中,余弦距离是更为常用的。
另外你也可以用 KNN 进行回归,通过 K 个邻居对新的点的属性进行值的预测。
KNN 的理论简单直接,针对 KNN 中的搜索也有相应的 KD 树这个数据结构。KNN 的理论成熟,可以应用到线性和非线性的分类问题中,也可以用于回归分析。
不过 KNN 需要计算测试点与样本点之间的距离,当数据量大的时候,计算量是非常庞大的,需要大量的存储空间和计算时间。另外如果样本分类不均衡,比如有些分类的样本非常少,那么该类别的分类准确率就会低很多。
当然在实际工作中,我们需要考虑到各种可能存在的情况,比如针对某类样本少的情况,可以增加该类别的权重。
同样 KNN 也可以用于推荐算法,虽然现在很多推荐系统的算法会使用 TD-IDF、协同过滤、Apriori 算法,不过针对数据量不大的情况下,采用 KNN 作为推荐算法也是可行的。
结语:以上就是首席CTO笔记为大家整理的关于pythonknn算法中k值取多少的全部内容了,感谢您花时间阅读本站内容,希望对您有所帮助,更多关于knn中的k值、pythonknn算法中k值取多少的相关内容别忘了在本站进行查找喔。