百度百科:
邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。
kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。
1.分析算法
该算法首先需要取一个参数K,假设取的K为3,对于每个新的样本点,K邻近算法就是再所有样本中找离这个新点最近的三个点,统计三个点所属类别,然后统计出数量最多的那个类别,就是新样本的类别
2.数学理论
通过分析K邻近算法,邻近就是计算两者之间的距离,常用的计算距离的公式一般用欧氏距离:
二维空间中两个点的距离等于x,y两坐标差的平方和在开根
import numpy as np
##十个样本点,两列值分别是颜色深度和酒精浓度,前5个都是红酒类型,后5个都是啤酒类型
X_sample=[[14.23,5.64],
[13.2,4.38],
[13.16,5.68],
[14.37,4.80],
[13.24,4.32],
[12.07,2.76],
[12.43,3.94],
[11.79,3.0],
[12.37,2.12],
[12.04,2.6]]
##0表示红酒,1表示啤酒
y_sample=[0,0,0,0,0,1,1,1,1,1]
##在机器学习值中常用的numpy的array数组而不是列别list,因为array速度快也能执行向量运算
##新的一杯酒的信息:
x_test=np.array([12.8,4.1])
##样本点的数组形式
X_train=np.array(X_sample)
##样本类型的数组形式
y_train=np.array(y_sample)
##有了x,y坐标就可以绘制一张散点图
import matplotlib.pyplot as plt
# 使用自带的样式进行美化
plt.style.use('ggplot')
##表示figure 的大小为宽、长(单位为英寸),关于参数可分析源代码
plt.figure(figsize=(10,6))
plt.scatter(X_train[y_train==1,0],X_train[y_train==1,1],s=100,c='g',label='啤酒')
plt.scatter(X_train[y_train==0,0],X_train[y_train==0,1],s=100,c='r',label='红酒')
plt.scatter(x_test[0],x_test[1],s=100,c='y')
##显示中文
from pylab import *
##this is the instance used by the matplotlib classes
##指定字体
mpl.rcParams['font.sans-serif'] = ['SimSun']
##将True改为False,作用就是解决负号'-'显示为方块的问题
plt.rcParams['axes.unicode_minus']=False
##x轴名称
plt.xlabel('酒精浓度')
##y轴名称
plt.ylabel('颜色浓度')
##显示图例 添加数据的是后写入label参数
plt.legend(loc='lower right')
##plt.tight_layout()会自动调整子图参数,使之填充整个图像区域,不会出现图重叠之类的问题
plt.tight_layout()
plt.savefig('酒的样本.png')
##计算距离的公式由很多,一般常用欧式距离:二维空间中两个点的距离等于x,y两坐标差的平方和在开根
from math import sqrt
##根据欧拉公式计算新样本点到每个样本点的距离
distances=[sqrt(np.sum((x-x_test)**2))for x in X_train]
# print(distances)
##接着找出距离新样本最近的3个点
##np.argsort()返回样本点的索引位置
sort=np.argsort(distances)
##通过索引值就能在y_train找出酒的类型,再统计排名前3的
top=[y_train[i] for i in sort[:3]]
print(top)
##获取数组中数量最多的元素,也就是最频繁的那个元素
##1.max方法:
s=max(top, key=top.count)
print(s)
##2.用collections包的Counter函数
from collections import Counter
v=Counter(top).most_common(1)[0][0]
if v==0:
print("新样本为:红酒")
else:
print("新样本为啤酒")
##结果:
[1, 0, 0]
0
新样本为:红酒
遇到的问题:
matplotlib.pyplot作出的图不显示中文
解决:
##查看matplotlib下fonts
[kiosk@asimov ~/anaconda3/envs/python3/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf]$ ls
cmb10.ttf LICENSE_DEJAVU
cmex10.ttf LICENSE_STIX
cmmi10.ttf local.conf
cmr10.ttf STIXGeneralBolIta.ttf
cmss10.ttf STIXGeneralBol.ttf
cmsy10.ttf STIXGeneralItalic.ttf
/home/kiosk/anaconda3/envs/python3/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf
[root@asimov ~]#fc-list :lang=zh ##查找本地 中文字体
/usr/share/fonts/wqy-microhei/wqy-microhei.ttc: WenQuanYi Micro Hei Mono,文泉驛>等寬微米黑,文泉驿等宽微米黑:style=Regular
##下载个宋体的ttf字体并解压
[root@asimov /home/kiosk/repod]#cp simsun.ttf /usr/share/fonts/simsun/
##安装字体:
[root@asimov /usr/share/fonts/simsun]#mkfontscale
[root@asimov /usr/share/fonts/simsun]#mkfontdir
[root@asimov /usr/share/fonts/simsun]#fc-cache
[root@asimov /usr/share/fonts/simsun]#ls
fonts.dir fonts.scale simsun.ttf
[root@asimov ~]#fc-list :lang=zh
/usr/share/fonts/simsun/simsun.ttf: SimSun,宋体
##将simsun.ttf cp到matplotlib的字体库中
[root@asimov /usr/share/fonts/simsun]#cp simsun.ttf /home/kiosk/anaconda3/envs/python3/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf
##删除matplotlib的缓存目录
[kiosk@asimov ~/.cache]$ rm -fr matplotlib/
##指定字体,然后运行代码就可以显示中文了
mpl.rcParams['font.sans-serif'] = ['SimSun']
参考博客:https://blog.csdn.net/dgatiger/article/details/50414549