k-近邻算法

1 工作原理

we have an existing set of example data, our training set. We have labels for all of this data—we know what class each piece of the data should fall into. When we’re given a new piece of data without a label, we compare that new piece of data to the existing data, every piece of existing data. We then take the most similar pieces of data (the nearest neighbors) and look at their labels. We look at the top k most similar pieces of data from our known dataset; this is where the k comes from. (k is an integer and it’s usually less than 20.) Lastly, we take a majority vote from the k most similar pieces of data, and the majority is the new class we assign to the data we were asked to classify.

就是在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较(计算距离),找到训练集中与之最为相似的前K个数据(距离最小的数据),则该测试数据对应的类别就是K个数据中出现次数最多的那个分类。

2 算法流程

  1. 计算测试数据与各个训练数据之间的距离;
  2. 按照距离的递增关系进行排序;
  3. 选取距离最小的K个点;
  4. 确定K个点所在类别的出现频率;
  5. 返回K个点中出现频率最高的类别作为测试数据的预测分类。

3 距离计算

在KNN中,一般使用欧氏距离或曼哈顿距离:

https://i-blog.csdnimg.cn/blog_migrate/8672e2e1e3f616515122fa727f9ca194.jpeg

4 K值选取

下图中给出了KNN算法中K值选区的规则:

https://i-blog.csdnimg.cn/blog_migrate/abbbfbeefa69f20b9378cb474cf232ad.jpeg

图中的数据集都有对应的标签。一类是蓝色的正方形,一类是红色的三角形,那个绿色的圆形是待分类的数据。

当K=3时,范围内红色三角形多,这个待分类点属于红色三角形。K= 5时,范围内蓝色正方形多,这个待分类点属于蓝色正方形,由此也说明了KNN算法的结果很大程度取决于K的选择。如何选择一个最佳的K值取决于数据。一般情况下,在分类时较大的 K 值能够减小噪声的影响,但会使类别之间的界限变得模糊。因此K的取值一般比较小( K<20 )。

3.2.5 KNN算法的优缺点

优点:简单,易于理解,无需建模与训练,易于实现;适合对稀有事件进行分类;适合多分类问题,例如根据基因特征来判断其功能分类,KNN比SVM的表现要好。

缺点:惰性算法,内存开销大,对测试样本分类时计算量大,性能较低;可解释性差,无法给出决策树那样的规则。

3.2.6 KNN算法程序(python)

第一部分:算法部分,kNN.py

# -*- coding:utf-8 -*-
from numpy import *
import operator
###给出训练数据和对应的类别
###参数:group数据集,labels分类标签
def createDataSet():
	group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
	labels = ['A','A','B','B']
	return group,labels
"""通过KNN进行分类
Parameters:
	inX - 用于分类的数据(测试集)
    dataSet - 用于训练的数据(训练集)
    labels - 分类标签
    k - kNN算法参数,选择距离最小的k个点
Returns:
    sortedClassCount[0][0] - 分类结果
"""
def classify0(inX,dataSet,labels,k):
	#numpy函数shape[0]返回dataSet的行数
	dataSetSize = dataSet.shape[0]  
	print("dataSet行数为:",dataSetSize) 
	###计算欧式距离
	#tile用来重复某个数组
	#在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)
	diffMat = tile(inX,(dataSetSize,1)) - dataSet
	print("测试数据生成新的矩阵与所有数据相减后矩阵为:")
	print(diffMat)
	#二维特征相减后平方
	sqdiffMat = diffMat ** 2
	print("每一项平方后为:")
	print(sqdiffMat)
	#sum()所有元素相加,sum(0)列相加,sum(1)行相加
	sqDistance = sqdiffMat.sum(axis=1)
	print("行相加为:")
	print(sqDistance)
	#开发,计算出距离
	distance = sqDistance ** 0.5
	print("每一项开平方后为:")
	print(distance)
	###对元素进行排序,argsort函数返回的是数组值从小到大的索引值
	sortedDistIndicies = distance.argsort()
	print("排序后顺序从小到大为(下标):")
	print(sortedDistIndicies)
	#定义一个记录类别次数的字典
	classCount ={}
	for i in range(k):
		#取出前k个元素的类别
		voteIlabel = labels[sortedDistIndicies[i]]
		print("第", end=' ')
		print(i, end=' ')
		print("次取出的标签值为:")
		print(voteIlabel)
		#dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
		#计算类别次数,classCount键是‘A','B',对应的值是数字,首次肯定找不到,返回值为0,加上1后放入classCount中
		classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
	print("记录完类别次数后的字典为:")
	print(classCount)
    #python3中用items()替换python2中的iteritems()
    #key=operator.itemgetter(1)根据字典的值进行排序
    #key=operator.itemgetter(0)根据字典的键进行排序
    #reverse降序排序字典
	sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
	print("返回结果:")
	print(sortedClassCount)
	#返回次数最多的类别,即所要分类的类别
	return sortedClassCount[0][0]

第二部分:调用

# -*- coding:utf-8 -*-
import kNN
group,labels = kNN.createDataSet()
#打印数据集和标签
print("数据集为:")
print(group)
print("标签为:")
print(labels)
print()
#给出测试用例
test = [0.1,0.1]
test_class = kNN.classify0(test,group,labels,3)
print(test_class)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值