机器学习笔记(十)---- KNN(K Nearst Neighbor)

举报
云上有未来 发表于 2019/09/20 09:10:26 2019/09/20
【摘要】 KNN是一种常见的监督学习算法,工作机制很好理解:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个“邻居”的信息来进行预测。总结一句话就是“近朱者赤,近墨者黑”。

    KNN是一种常见的监督学习算法,工作机制很好理解:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个“邻居”的信息来进行预测。总结一句话就是“近朱者赤,近墨者黑”。

       KNN可用作分类也可用于回归,在分类任务中可使用“投票法”,即选择这k个样本中出现最多的类别标记作为测试结果;在回归任务中可使用“平均法”将这k个样本的标记平均值作为预测结果;还可以基于距离远近进行加权平均或加权投票,距离越近的样本权重越大。
       KNN和之前介绍的监督学习算法有一个很大的不同,它没有前期的训练过程,是一种“懒惰学习”的算法,只有收到测试样本后,再和训练样本进行比较处理。
       初学者容易把KNN和K-means搞混淆,虽然都有K,:-)但这是两种不同的算法,二者区别如下:



KNNK-Means
不同点是一种分类算法,属于监督学习的范畴,训练数据是带有label的是一种聚类算法,属于非监督学习的范畴,训练数据没有label,杂乱无章的
没有明显的训练过程,属于lazy learning有明确的训练过程
K的含义:与预测样本距离最近的K个样本K的含义:K是事前人工定好的参数,假设数据集可分为K个簇
相同点都用到了NN(nearst Neighbor)算法,一般用KD树来实现。


--KNN算法基本原理
KNN算法简单的步骤如下:
(1)计算距离:给定测试对象,计算它与训练集中每个对象的距离,空间距离的计算方法有多种,有欧式距离、夹角余弦(多在文本分类中使用)等。
(2)找邻居:圈定距离最近的k个对象,作为测试对象的近邻。
(3)做分类:根据这k个近邻归属的主要类别,对测试对象进行分类。


    下面通过一个简单的示例说明下KNN算法是怎么进行分类的:

                                                        KNN算法示例.png

      上图的蓝色方块和红色三角是已经打好label的数据,绿色圆圈是待分类的测试数据。

      如果我们让K=3,那么上图实心圆圈中的两个三角和一个方块就是离测试数据最近的3个点,那么通过投票法则,测试数据会被分类为红色三角;

      如果我们让K=5,那么上图虚线圆圈中的两个三角和三个方块就是离测试数据最近的5个点,通过投票法则,测试数据则会被分类为蓝色方块;

      整个算法的原理是不是很简单?但实际上并没有那么简单,K如何选择?数据之间的距离怎么计算?


--K值的选择

     如果K值太小,整体模型会变得复杂,容易发生过拟合,容易将一些噪声学习进来,二忽略数据的真实分布。

     如果K值过大,模型会变得相对简单,可以减少学习的估计误差,但近似误差会变大,比如极端情况下K=N(N维训练样本数),则不论预测对象是什么,预测结果都将是训练集中最多的类型,这显然是一个过渡简化的模型,无法实际应用。

     k值一般采用交叉验证或者Grid Search的方法确定。


--距离计算

    提取数据的特征值,根据特征值组成一个n维实数向量空间(特征空间),然后计算向量之间的空间距离,如欧式距离、余弦相似度等。

    对于数据512c626001e1d4cd31af_26x20.png@900-0-90-f.png5fa1126001e250eb96d5_27x22.png@900-0-90-f.png,其特征空间为n维实数向量空间:7479e26001e33cc4e695_205x27.png@900-0-90-f.png95e1626001e3e83d162b_213x23.png@900-0-90-f.png

    欧式距离计算公式为:欧式距离计算公式.png

    余弦相似度计算公式为: 余弦相似度计算公式.png

    余弦相似度的值越接近1表示其越相似,接近0表示其差异越大。余弦相似度更多应用在文本类任务中。


--代码示例

       依旧以sklearn中的cancer数据集为例,做一个通过30维特征判断是否患癌症的示例,示例中数据量很少,只有569条数据,每条数据各有30个特征数值。采用sklearn中的KNN分类器,除k外都采用默认参数,距离度量采用欧式距离 。通过交叉验证法来确定最佳的K值,从下图可见,K=14时,验证准确率最高。


交叉验证法.png

-

Python 代码


查看代码

01__author__ = 'z00421185'
02
03import pandas as pd
04from sklearn import datasets
05import matplotlib.pyplot as plt
06from sklearn.model_selection import cross_val_score
07from sklearn.model_selection import train_test_split
08from sklearn.metrics import accuracy_score
09from sklearn.neighbors import KNeighborsClassifier
10
11breast_data = datasets.load_breast_cancer()
12data = pd.DataFrame(datasets.load_breast_cancer().data)
13data.columns = breast_data['feature_names']
14
15data_np = breast_data['data']
16target_np = breast_data['target']
17print(data_np.shape)
18
19x_train, x_test, y_train, y_test = train_test_split(data_np, target_np, test_size=0.3, random_state=0)
20
21# 设定交叉验证k的范围,一般从1~样本数的开方
22k_range = range(124)
23scores = []
24for in k_range:
25    knn = KNeighborsClassifier(k, metric='euclidean')
26    score = cross_val_score(knn, x_train, y_train, cv=10, scoring='accuracy')
27    scores.append(score.mean())
28
29# 从折线图上看最佳K取值
30plt.plot(k_range, scores)
31plt.xlabel('K')
32plt.ylabel('Accuracy')
33plt.show()
34
35model = KNeighborsClassifier(n_neighbors=13)
36model.fit(x_train, y_train)
37y_pred = model.predict(x_test)
38print(accuracy_score(y_test, y_pred))
39---------------------------------
400.9649122807017544


 本文作者周捷

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。