一、算法介绍
1、算法简介
2、核心思想
二、距离测算
三、k值的选择
1、选取的k值大小的区别:
2、k值选择:
四、算法实现
KNN(K- Nearest Neighbor)法即K最邻近法,最初由 Cover和Hart于1968年提出,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路非常简单直观:如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
KNN算法的核心思想是,如果一个样本在特征空间中的K个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。KNN方法在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
k-近邻算法中常用的距离计算方式有曼哈顿距离和欧式距离。
曼哈顿距离:
欧式距离:
算法流程
总体来说,KNN分类算法包括以下4个步骤:
①准备数据,对数据进行预处理 。
②计算测试样本点(也就是待分类点)到其他每个样本点的距离 。
③对每个距离进行排序,然后选择出距离最小的K个点 。
④对K个点所属的类别进行比较,根据少数服从多数的原则,将测试样本点归入在K个点中占比最高的那一类 。
算法实现
集美大学有两个食堂,一个万人食堂,一个西苑餐厅。已知一位学生的宿舍区域,不是在第五社区,就是在第六社区。能否通过该学生上学期去两个食堂的次数得出该学生的宿舍是第五社区还是第六社区的?(第五社区靠近西苑餐厅,第六社区靠近万人食堂)
import numpy as np
import operator
from os import listdir
def classify0(inX, dataSet, labels, k):
#返回dataSet的行数,即已知数据集中的所有点的数量
num = len(dataSet)
#行向量方向上将inX复制m次,然后和dataSet矩阵做相减运算
n=num-1
ans=np.asarray(inX)
tmp=np.asarray(inX)
while n!=0:
ans = np.append(ans,tmp)
n-=1
ans = np.reshape(ans,[num,2])
ans = ans-dataSet
#减完后,对每个数做平方
ans = ans*ans
#平方后按行求和,axis=0表 示列相加,axis-1表示行相加
dis = np.zeros([num,1],dtype=int)
#开方计算出欧式距离
for i in range(num):
dis[i] = ans[i][0]+ans[i][1]
ans = np.reshape(dis,[1,num])
#对距离从小到大排序,注意argsort函数返回的是数组值从小到大的索引值2
y = np.argsort(ans)
#用于类别/次数的字典,key为类别, value为次数
y=list(y[0])
#取出第近的元素对应的类别
dic = dict.fromkeys(list(set(labels)), 0)
#对类别次数进行累加
for i in range(k):
dic[labels[y[i]]]+=1
#根据字典的值从大到小排序
dic = sorted(dic.items(),key =lambda item:item[1],reverse=True)
#返回次数最多的类别,即所要分类的类别
return dic[0][0]
训练数据集:
去 万人食堂 | 西苑餐厅 次数 | 学生所在宿舍区域 |
[250,100] |
第六社区 |
[270,120] |
第六社区 |
[111,230] |
第五社区 |
[130,260] |
第五社区 |
[200,80] |
第六社区 |
[70,190] |
第五社区 |
[65,225] |
第五社区 |
#自定义训练集
dataSet=np.array([[250,100],[270,120],[111,230],[130,260],[200,80],[70,190],[65,225]])
labels=["第六社区","第六社区","第五社区","第五社区","第六社区","第五社区","第五社区"]
#自定义测试集
inX=[105,210]
inY=[68,250]
inZ=[111,36]
print("测试数据集:\n 去 万人食堂 | 西苑餐厅 (次)")
print(inX)
print("判断学生所在宿舍为:" + classify0(inX,dataSet,labels,3))
print(inY)
print("判断学生所在宿舍为:" + classify0(inY,dataSet,labels,3))
print(inZ)
print("判断学生所在宿舍为:" + classify0(inZ,dataSet,labels,3))