您的位置:首页 > 其它

【十三】机器学习之路——k-近邻算法(KNN)

2017-11-16 09:35 232 查看
  有几天没写博客了,最近工作上的事情比较多,没抽出时间来看书学习。趁今天有点空,一起学习一下k-近邻算法(KNN),这个算法是监督学习里的分类问题,主要是用来根据数据的特征,将样本分为不同类别的算法,咱们下面慢慢来学习。

KNN算法定义:

  KNN算法是比较容易理解的分类算法,KNN是通过测量不同特征值之间的距离进行分类。它的的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。K通常是不大于20的整数。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。

KNN算法例子说明:

  看了上面的定义是不是有点懵懵的,没关系我举一个简单的例子来说明如何利用kNN算法来对新的样本进行分类,让大家更容易理解,举的例子有略微不严谨之处,不要在意细节。

  由于人类DNA的延续,我们都长得像自己的爸爸妈妈,甚至爷爷奶奶,所以每一个大家族的人长得还是都比较相似的。假设我们现在有两个大家族,王家和李家(样本的两大类别,样本就是每个人的长相),我们外人看到这两大家族里的这么多人,只能通过简单的长相来分辨哪些人是王大家族的,哪些人是李大家族的,因为我们知道一家人长得都比较相似。假设现在我们已经有了一组训练集,我们知道10个王大家族的人的长相和10个李大家族人的长相,相当于我们有20个人的长相数据以及他们对应的家族分类。好了,现在打东边来了一个喇叭,问,这个喇叭更有可能是哪个家族的人?

  在这个例子中,KNN算法的判断方式就是,将这个喇叭的长相分别和王家、李家10个人的长相作对比,然后计算出喇叭的长相和这20个人长相的差别有多大(这里为了方便理解,假设我们分不同等级来表示差别:1,2,3,4,5等,最终输出的差别为一个数字,即KNN里的“距离”),最后将这些差别值从小到大排列,假设我们认为差别最小的5个人(这里的5就是KNN里的k值)里,王家人占多数,那我们认为这个喇叭就是王家人;如果差别最小的5个人里,李家人占多数,那我们就认为这个喇叭是李家人。这样就通过KNN算法将预测的数据进行了分类,达到了我们的目的。

KNN算法实现:

  在《机器学习实战》这本书里讲到一个利用KNN实现的问题,也是一个很简单的例子。我们在网上搜电影的时候,都会分类的搜索,比如说你喜欢看战争片,或者爱情片,或者动作片。可是我们怎么将这些电影分类呢,什么样的电影算是爱情片,什么样的电影算是动作片?

  假设我们用电影里出现接吻的次数和打斗的次数来分类爱情片和动作片,当然爱情片里可能打斗和接吻场面都会有,动作片里打斗和接吻场面也都会有,那么我们就用出现的次数来判别电影的种类。如下图所示(该图摘自《机器学习实战》)

  在这个电影分类问题里,每部电影都有两个特征值就是(x1(i)接吻次数,x2(i)打斗次数),现在我们要给新的一部电影进行分类,这部电影两个特征值为(x1(n),x2(m))。

1. 首先,KNN算法第一步就是计算这部电影特征值与训练数据集中所有电影特征值的距离。这里的距离我们可以用曼哈顿距离或者欧拉距离:

欧式距离:distance=∑k1((x1(i)−xn)2+(x2(i)−xm)2)−−−−−−−−−−−−−−−−−−−−−−−−−−−√

曼哈顿距离:distance=∑k1(|(x1(i)−xn)|+|(x2(i)−xm)|)−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−√

2. 计算好预测点与样本点的距离后,将结果从小到大进行排序;

3. 选取距离最近的k个点,确定这k个点数据所在分类的出现频率;

4. 选择频率最高的分类作为预测数据的分类输出;

Python实现:

【代码参考《机器学习实战》】

首先生成DataSet,即训练集数据:

import numpy as np
def createDataSet():
#将样本的特征值放入一个Array里,这里共4个样本数据
group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
#对应的分类用List来装载
labels = ['A','A','B','B']
return group, labels


接下来就是KNN的分类器的定义:

#分类器函数共有4个输入,inX是咱们要预测分类的数据,dataSet是训练集的特征值数据,labels则是训练集的每个样本类别,k为kNN算法里的参数;
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]#计算dataSet里总共有多少样本
diffMat = tile(inX, (dataSetSize,1)) - dataSet#利用tile函数扩展预测数据,与每一个训练样本求距离
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5#求欧式距离
sortedDistIndicies = distances.argsort()#argsort()函数用法见下
classCount={} #定义一个字典,用于储存K个最近点对应的分类以及出现的频次
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#以下代码将不同labels的出现频次由大到小排列,输出次数最多的类别
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
#同样可以用以下代码实现
"""
maxCount = 0
for key,value in classCount.items():
if value > maxCount:
maxCount = value
classes = key
"""


以上代码包含了一些python内置函数,第一次接触的话可能会有所困惑,下面给出相应函数学习的链接,或者大家可以自行百度。

tile函数:python 科学计算库NumPy—tile函数Python-Numpy函数-tile函数

argsort、sort、sorted函数:浅述python中argsort()函数的用法

item、iteritems函数:【Python】字典items返回列表,iteritems返回迭代器Python中dictionary items()系列函数的用法实例

  接下来在python shell里输入以下代码来调用KNN分类器进行分类:

#-*-coding:utf-8 -*-
import sys
sys.path.append("...文件路径...")#导入.py文件路径
import KNN
dataSet,labels = KNN.createDataSet()
input = array([1.1,0.3])
K = 3
output = KNN.classify(input,dataSet,labels,K)
print("测试数据为:",input,"分类结果为:",output)


最终输出;

测试数据为: [ 1.1  0.3] 分类为: A


以上讲的是KNN的算法以及一个很简单的python实例,今天就先讲到这里,下篇博客来讲一个通过KNN算法改进约会网站的实战问题,同样也是参考《机器学习实战》。感谢阅读!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  机器学习 算法