分类问题学习笔记-KNN原理

最邻近算法-KNN

案例:

kNN算法的指导思想是“近朱者赤,近墨者黑”,由你的邻居来推断出你的类别。
俗话讲“物以类聚,人以群分”。 试想有甲乙两个人,甲住进了汤臣一品的豪宅,乙住进了郊区老破小,那我们最直观的判断就是:甲大概率是个有钱人,乙嘛,平平无奇。即时我们没见过甲乙的银行卡余额,但通过甲住进了富人小区仍然可以做出判断。引出KNN算法思路“你住的离谁近,就大概率跟他是同一类人”。

定义——From Wikipedia:

In pattern recognition, the k-nearest neighbors algorithm (k-NN) is a non-parametric method proposed by Thomas Cover used for classification and regression.[1] In both cases, the input consists of the k closest training examples in the feature space. The output depends on whether k-NN is used for classification or regression:

  • In k-NN classification, the output is a class membership. An object
    is classified by a plurality vote of its neighbors, with the object
    being assigned to the class most common among its k nearest neighbors
    (k is a positive integer, typically small). If k = 1, then the object
    is simply assigned to the class of that single nearest neighbor.
  • In k-NN regression, the output is the property value for the object.
    This value is the average of the values of k nearest neighbors.

原理:

用一句话来解释 KNN 算法原理,那就是找到 K 个与新数据最近的样本,取样本中最多的一个类别作为新数据的类别。
引自维基百科上的一幅图:
在这里插入图片描述
如上图所示,有两类不同的样本数据,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的那个绿色的圆所标示的数据则是待分类的数据。

  • 如果K=3,绿色圆点的最邻近的3个点是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。
  • 如果K=5,绿色圆点的最邻近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。

所以细节的东西主要有两个,K值的选取和点距离的计算。

优缺点:

优点:

1、简单易实现: KNN 算法最后实际上并没有抽象出任何模型,而是把全部的数据集直接当作模型本身,当一条新数据来了之后跟数据集里面的每一条数据进行对比。所以可以看到 KNN 算法的一些优点,首当其冲的就是这个算法简单,简单到都不需要进行什么训练了,只要把样本数据整理好了,就结束了,来一条新数据就可以进行预测了。
2、对于边界不规则的数据效果较好: 可以想到,我们最终的预测是把未知数据作为中心点,然后画一个圈,使得圈里有 K 个数据,所以对于边界不规则的数据,要比线性的分类器效果更好。因为线性分类器可以理解成画一条线来分类,不规则的数据则很难找到一条线将其分成左右两边。

缺点:

1、只适合小数据集: 正是因为这个算法太简单,每次预测新数据都需要使用全部的数据集,所以如果数据集太大,就会消耗非常长的时间,占用非常大的存储空间。
2、数据不平衡效果不好: 如果数据集中的数据不平衡,有的类别数据特别多,有的类别数据特别少,那么这种方法就会失效了,因为特别多的数据最后在投票的时候会更有竞争优势。
3、必须要做数据标准化: 由于使用距离来进行计算,如果数据量纲不同,数值较大的字段影响就会变大,所以需要对数据进行标准化,比如都转换到 0-1 的区间。
4、不适合特征维度太多的数据: 由于我们只能处理小数据集,如果数据的维度太多,那么样本在每个维度上的分布就很少。比如我们只有三个样本,每个样本只有一个维度,这比每个样本有三个维度特征要明显很多。

距离计算:

各种“距离”的应用场景简单概括为:
空间:欧氏距离,
路径:曼哈顿距离,
国际象棋国王:切比雪夫距离,以上三种的统一形式:闵可夫斯基距离,
加权:标准化欧氏距离,
排除量纲和依存:马氏距离,
向量差距:夹角余弦,
编码差别:汉明距离,
集合近似度:杰卡德类似系数与距离,
相关:相关系数与相关距离。

(感兴趣的同学可以自行查询)
常用如欧氏距离:
拿二维平面为例,,二维空间两个点的欧式距离计算公式如下:

在这里插入图片描述
这个初中就有接触到的了,其实就是计算(x1,y1)和(x2,y2)的距离。拓展到多维空间,则公式变成这样:
在这里插入图片描述
KNN算法最简单粗暴的就是将预测点与所有点距离进行计算,然后保存并排序,选出前面K个值看看哪些类别比较多。
拓展阅读闵氏距离:
在这里插入图片描述

  • 当p=1时,就是曼哈顿距离
  • 当p=2时,就是欧氏距离
  • 当p→∞时,就是切比雪夫距离

根据变参数的不同,闵氏距离可以表示一类的距离。
标准化欧氏距离 (Standardized Euclidean distance ),标准化欧氏距离是针对简单欧氏距离的缺点而作的一种改进方案。标准欧氏距离的思路:既然数据各维分量的分布不一样,那先将各个分量都“标准化”到均值、方差相等。
假设样本集X的数学期望或均值(mean)为m,标准差(standard deviation,方差开根)为s,那么X的“标准化变量”X*表示为:(X-m)/s,而且标准化变量的数学期望为0,方差为1。
即,样本集的标准化过程(standardization)用公式描述就是:
在这里插入图片描述

标准化后的值 = ( 标准化前的值 - 分量的均值 ) /分量的标准差
经过简单的推导就可以得到两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的标准化欧氏距离的公式:
在这里插入图片描述

K值的选择:

一般通过交叉验证(将样本数据按照一定比例,拆分出训练用的数据和验证用的数据,比如6:4拆分出部分训练数据和验证数据),从选取一个较小的K值开始,不断增加K的值,然后计算验证集合的方差,最终找到一个比较合适的K值。通过交叉验证计算方差后你大致会得到下面这样的图:
在这里插入图片描述

当你增大k的时候,一般错误率会先降低,因为有周围更多的样本可以借鉴了,分类效果会变好。当K值更大的时候,错误率会更高,比如说你一共就35个样本,当你K增大到30的时候,KNN基本上就没意义了。所以选择K点的时候可以选择一个较大的临界K点,当它继续增大或减小的时候,错误率都会上升.
经验规则:k一般低于训练样本数的平方根

接下来对KNN算法的思想总结一下:

就是在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类,其算法的描述为:
1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

python鸢尾花案例:

from sklearn import datasets 
#sklearn模块的KNN类
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
np.random.seed(0)
#设置随机种子,不设置的话默认是按系统时间作为参数,设置后可以保证我们每次产生的随机数是一样的

iris=datasets.load_iris() #获取鸢尾花数据集
iris_x=iris.data #数据部分
iris_y=iris.target #类别部分
#从150条数据中选140条作为训练集,10条作为测试集。permutation 接收一个数作为参数(这里为数据集长度150),产生一个0-149乱序一维数组
randomarr= np.random.permutation(len(iris_x))
iris_x_train = iris_x[randomarr[:-10]] #训练集数据
iris_y_train = iris_y[randomarr[:-10]] #训练集标签
iris_x_test = iris_x[randomarr[-10:]] #测试集数据
iris_y_test = iris_y[randomarr[-10:]] #测试集标签
#定义一个knn分类器对象
knn = KNeighborsClassifier()
#调用该对象的训练方法,主要接收两个参数:训练数据集及其类别标签
knn.fit(iris_x_train, iris_y_train)
#调用预测方法,主要接收一个参数:测试数据集
iris_y_predict = knn.predict(iris_x_test)
#计算各测试样本预测的概率值 这里我们没有用概率值,但是在实际工作中可能会参考概率值来进行最后结果的筛选,而不是直接使用给出的预测标签
probility=knn.predict_proba(iris_x_test)
#计算与最后一个测试样本距离最近的5个点,返回的是这些样本的序号组成的数组
neighborpoint=knn.kneighbors([iris_x_test[-1]],5)
#调用该对象的打分方法,计算出准确率
score=knn.score(iris_x_test,iris_y_test,sample_weight=None)
#输出测试的结果
print('iris_y_predict = ')
print(iris_y_predict)
#输出原始测试数据集的正确标签,以方便对比
print('iris_y_test = ')
print(iris_y_test)
#输出准确率计算结果
print('Accuracy:',score)
"""
输出结果:
iris_y_predict = 
[1 2 1 0 0 0 2 1 2 0]
iris_y_test = 
[1 1 1 0 0 0 2 1 2 0]
Accuracy: 0.9
"""
可以看到,该模型的准确率为0.9,其中第二个数据预测错误了。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用Python实现的PSO-KNN分类算法的示例代码: ```python import numpy as np from sklearn.neighbors import KNeighborsClassifier from pyswarm import pso def knn_pso(X, y, n_neighbors, p): # 定义适应度函数 def fitness_function(x): model = KNeighborsClassifier(n_neighbors=int(x[0]), p=int(x[1])) model.fit(X, y) return -model.score(X, y) # 定义PSO算法的参数 lb = [1, 1] # 最近邻居的数量和距离度量方法的参数下限 ub = [10, p] # 最近邻居的数量和距离度量方法的参数上限 # 使用PSO算法来优化KNN算法的参数 xopt, fopt = pso(fitness_function, lb, ub) # 训练最优的KNN分类器 model = KNeighborsClassifier(n_neighbors=int(xopt[0]), p=int(xopt[1])) model.fit(X, y) return model # 示例 X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([0, 1, 1, 0]) n_neighbors = 5 p = 2 model = knn_pso(X, y, n_neighbors, p) print(model.predict(X)) ``` 在上述代码中,我们使用了Python中的`pyswarm`库来实现PSO算法。首先,我们定义了适应度函数`fitness_function`,它接受一个长度为2的向量x作为输入,其中x[0]表示最近邻居的数量K,x[1]表示距离度量方法的参数p。该函数返回在该参数设置下的KNN分类器在训练数据集上的分类准确率的负值(因为PSO算法是最小化问题)。 然后,我们使用`pso`函数来运行PSO算法,传入适应度函数、参数下限和上限。该函数返回最优的参数设置和适应度函数值。 最后,我们使用最优的参数设置来训练一个KNN分类器,并使用该分类器进行预测。 需要注意的是,上述代码中的示例数据集是二分类数据集。如果要处理多分类问题,需要将KNN分类器改为多分类KNN分类器,例如`KNeighborsClassifier(n_neighbors=int(x[0]), p=int(x[1]), weights='distance')`,同时需要将适应度函数改为多分类准确率的负值,例如`return -model.score(X, y)`改为`return -model.score(X, y, sample_weight=None)`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值