原理解析

KNN-全称K-Nearest Neighbor,最近邻算法,可以做分类任务,也可以做回归任务,KNN是一种简单的机器学习方法,它没有传统意义上训练和学习过程,实现流程如下:
1、在训练数据集中,找到和需要预测样本最近邻的K个实例;
2、分别统计这K个实例所属的类别,最多的那个类别就是样本预测的类别(多数表决法);
对于回归任务而言,则是求这K个实例输出值的平均值(选择平均法);

因此,该算法的几个重点在于:
1、K值的选取,K值的不同直接会导致最终结果的不同;
选择较小的k值,就相当于用较小的领域中的训练实例进行预测,训练误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是泛化误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合;
选择较大的k值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少泛化误差,但缺点是训练误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单,容易欠拟合;
一般的,最佳K值的选取,我们可以用交叉验证法来寻找,分类准确率最高的(回归问题中就是均方误差最小的),就是最佳的K值;

2、距离的计算,计算最近邻的K个样本时,用哪种度量方式,最常用的是欧氏距离;

3、决策规则,一般就是多数表决法或者选择平均法,但是,K个近邻数据,到样本的距离也不一样,都一视同仁,也不太合理;

代码实现

根据上面的KNN原理解析,我们来编写python代码(分类任务代码):

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.metrics import classification_report class Knn():
#默认k=5,设置和sklearn中的一样
def __init__(self,k=5):
self.k = k def fit(self,x,y):
self.x = x
self.y = y def predict(self,x_test):
labels = []
#这里可以看出,KNN的计算复杂度很高,一个样本就是O(m * n)
for i in range(len(x_test)): #初始化一个y标签的统计字典
dict_y = {}
#计算第i个测试数据到所有训练样本的欧氏距离
diff = self.x - x_test[i]
distances = np.sqrt(np.square(diff).sum(axis=1)) #对距离排名,取最小的k个样本对应的y标签
rank = np.argsort(distances)
rank_k = rank[:self.k]
y_labels = self.y[rank_k] #生成类别字典,key为类别,value为样本个数
for j in y_labels:
if j not in dict_y:
dict_y.setdefault(j,1)
else:
dict_y[j] += 1 #取得y_labels里面,value值最大对应的类别标签即为测试样本的预测标签 #label = sorted(dict_y.items(),key = lambda x:x[1],reverse=True)[0][0]
#下面这种实现方式更加优雅
label = max(dict_y,key = dict_y.get) labels.append(label) return labels

实例展示

利用sklearn生成实验数据集:

#有同学私信我,为什么每次都是生成2维数据,因为2维数据方便画图,哈哈
x,y = make_classification(n_features=2,n_redundant=0,random_state=2019)
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()


数据表现如上,来看看分类效果:

#预测
knn = Knn()
knn.fit(x,y)
labels = knn.predict(x) #查看分类报告
print(classification_report(y,labels))


f1的值为94%,下面画图看看分类边界:

#画等高线图
x_min,x_max = x[:,0].min() - 1,x[:,0].max() + 1
y_min,y_max = x[:,1].min() - 1,x[:,1].max() + 1 xx = np.arange(x_min,x_max,0.02)
yy = np.arange(y_min,y_max,0.02) xx,yy = np.meshgrid(xx,yy) x_1 = np.c_[xx.ravel(),yy.ravel()]
y_1 = knn.predict(x_1) #list没有reshape方法,转为np.array的格式
plt.contourf(xx,yy,np.array(y_1).reshape(xx.shape),cmap='GnBu')
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()


看起来还是很好的。

sklearn对比

下面调用sklearn里面的KNN库对比效果:

from sklearn.neighbors import KNeighborsClassifier
clf = KNeighborsClassifier(n_neighbors=5)
clf.fit(x,y) #输出分类报告
print(classification_report(y,clf.predict(x))) #画图
y_pred = clf.predict(x_1) plt.contourf(xx,yy,y_pred.reshape(xx.shape),cmap='GnBu')
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()


结果基本上是一样的。

总结

上面我们写了python代码,来实现基本的KNN分类,实际上sklearn里面的KNeighborsClassifier分类器,封装的内容则很多:

我们python代码中采用的办法称为蛮力实现(brute-force),即需要计算每一个测试样本到所有训练样本的距离,才能确定最终的预测标签,当数据集很大,特征很多,并且测试样本也很多时,需要的计算量大家可以想象一下,基本上跑不出来结果,这点我自己是有实际案例的;

而sklearn里面则对这点做出了优化,除了蛮力实现(brute-force),还有KD树实现(KDTree)和球树(BallTree)实现,后两者则大大提高了处理大数据集时的效率(感兴趣的同学可自行去查找这两者的资料),对于这三个算法,sklearn会根据输入的样本,自动选择一种算法(默认参数algorithm=‘auto’)。

对于距离的计算,我们直接用的欧氏距离,在sklearn里面,封装了很多种距离的度量方式,比如欧氏距离、曼哈顿距离、马氏距离、闵可夫斯基距离等,默认的是p=2的闵可夫斯基距离,也就是欧氏距离。

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理

想要获取更多Python学习资料可以加
QQ:2955637827私聊
或加Q群630390733
大家一起来学习讨论吧!

最新文章

  1. 学号20145332 《信息安全系统设计基础》实验五 简单嵌入式WEB服务器实验
  2. d3 中exit() remove()正确工作的方式
  3. SQL函数
  4. IE7下如何判断复选框是否被选中(利用jquery)
  5. 找回消失的ASUS显卡
  6. iOS 开发之路(使用WKWebView加载Html5) 四
  7. makefile中的target到底代表什么?
  8. GitHub for Windows离线安装的方法
  9. C++:运算符重载函数之成员运算符重载函数
  10. SQL点滴之编辑数据(转)
  11. 灰度图像--图像增强 直方图均衡化(Histogram equalization)
  12. 推荐大家一本学习php模式的书
  13. TMemoryStream、String与OleVariant互转
  14. Windows核心编程&线程
  15. android使用百度地图最新sdk5.0后后代码混淆时,地图无法显示闪退问题
  16. 22 python 初学(类,面向对象)
  17. [Flume][Kafka]Flume 与 Kakfa结合例子(Kakfa 作为flume 的sink 输出到 Kafka topic)
  18. HoloLens开发手记 - HoloLens真机上手简评
  19. AndroidStudio 导包遇到so文件的解决方案----------JPush推送
  20. Android多个Module统一配置相同jar或库的版本号

热门文章

  1. yii2.0 模态框简单使用
  2. Go 大数据生态迎来重要产品 CDS
  3. Matlab 补充知识
  4. C语言讲义——函数递归
  5. rest-framework:频率控制
  6. Asp.NetCore之AutoMapper基础篇
  7. Cys_Control(一) 项目搭建
  8. 老猿学5G扫盲贴:中移动的5G计费架构中Nchf'服务化接口以及CHF中的AGF
  9. PyQt(Python+Qt)学习随笔:containers容器部件GroupBox分组框介绍
  10. Python(Python+Qt)学习随笔:使用xlwings新建Execl文件和sheet的方法