提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、KNN算法是什么?
读者本人的理解是这样的:在一个类别为X(未知)的样本点周围找N个点离它最近的点,并统计这些点的类别(A,B,C),哪种类别多,那么X就是这种类别。举个例子来说离类别为X的最近50个点中 A类有31个,B类有14个,C类有5个,那么X的类别就是A
二、代码编写
1.引入库
from numpy import * import operator import matplotlib import matplotlib.pyplot as plt
def creatdata() :
random.seed(0)
# 设置随机种子以获得可重复的结果
# 生成特征矩阵 X,50个样本,每个样本2个特征
group= random.rand(50, 2)*10
labels= random.choice(['A', 'B','C'], 50)
return group, labels
3.主要算法 KNN (教材)
欧式距离:
def classify0(inX, dataSet, labels, k):## kkn 最近几个样本来决定目标样本的类别
#欧式距离计算
dateSetSize = dataSet.shape[0]
##shape[0]:表示矩阵的行数 shape[1]:表示矩阵的列数
diffMat = tile(inX, (1, 1)) - dataSet
#先沿x轴复制1次,再沿y轴复制dataSetSize次
# 二维特征相减 X1-X2 OR Y1-Y2
# tile函数的功能是重复某个数组。比如tile(A, reps),它的作用就是把A重复reps次,
sqDiffMat = diffMat ** 2
sqDiffstances = sqDiffMat.sum(axis=1)
##axis= 0 对a的横轴(行)进行操作,在运算的过程中其运算的方向表现为纵向(列)运算
#axis= 1 对a的纵轴(列)进行操作,在运算的过程中其运算的方向表现为横向(行)运算
distances = sqDiffstances ** 0.5
##选择距离最小的k个点
sortedDistances = distances.argsort()
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistances[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),reverse=True)# 返回次数最多的类别,即所要分类的类别
#python3中用items()替换python2中的iteritems() 课本中使用的iteritems 在这里要用items
#key=operator.itemgetter(1)根据字典的值进行排序
# key=operator.itemgetter(0)根据字典的键进行排序
# reverse降序排序字典
return sortedClassCount[0][0]
4.数据合理化
在我们日常生活中数据差值有时候会很大,为了避免数据差值过大带来的误差,因此我们会对数据进行处理在本文中我们就采取归一化操作,以此降低数据差距过大带来的影响
公式:newValue=(oldValue-minValue)/(maxValue-minValue)
代码如下
def Guiyihua(dataset,intx): #归一化 dateset :数据集中数据 intx 样本数据
x = [i[0] for i in dataset]# 用i来遍历dateset 中 二维[x,y]中x 存入x数组中
y = [i[1] for i in dataset]#用i来遍历dateset 中 二维[x,y]中y 存入y数组中
minx,miny = min(x),min(y)
maxx,maxy = max(x),max(y)
x.append(intx[0])#样本x 存入x
y.append(intx[1])#样本y 存入y
rangeminmax_x = maxx-minx
rangeminmax_y = maxy-miny
for i in range(len(dataset)):#更新二维数组
dataset[i][0] = (dataset[i][0] - minx)/rangeminmax_x
dataset[i][1] = (dataset[i][1] - miny)/rangeminmax_y
#重置样本数据
intx[0] = (intx[0]-minx)/rangeminmax_x
intx[1] = (intx[1]-miny)/rangeminmax_y
return dataset,intx
5.可视化
为了让数据看得更加简单明了,我使用matplotlib让数据可视化
代码如下
def makematlab(intx,dataset,labels): #散点图
plt.rcParams['font.sans-serif']=['SimHei'] #设置字体
plt.rcParams['axes.unicode_minus']=False #字符显示
choosecolors = ['r', 'g', 'y', 'b', 'r', 'c', 'g', 'b', 'k', 'm']
labelcolors = {}
setlabels = set(labels)#将labels 变为一个集合
count = 0
for i in setlabels: #给集合每个元素上色
labelcolors.update({i:choosecolors[count]})
count+=1
n = dataset.shape[0]#表示个数
fig = plt.figure()
x = [i[0] for i in dataset]
y = [i[1] for i in dataset]
for i in range(len(x)):
plt.scatter(x[i],y[i],color = labelcolors[labels[i]],label = labels[i])
plt.text(x[i], y[i], labels[i], fontsize=12)
plt.scatter(intx[0],intx[1],color = 'gray')
plt.xticks(arange(min(x)-1,max(x)+1,step=0.5)) #刻度
plt.yticks(arange(min(y)-1,max(y)+1,step=0.5))
plt.title("散点分布")
print(x)
plt.show()
return
三、实验结果
归一化前: 数据较为分散
归一化后:
总结
通过课本来学习了knn算法,了解knn用途,懂得如何对数据进行一个基本分类,由于本人能力有限,故随机生成数据集不具有现实含义。实验过程中查询课本与网上内容加深knn的理解,并初步学习makematlab