一 算法过程:
1 首先存在一个数据集作为训练样本集DataSet,比如训练样本的数据中,每一条数据都包含一个城市的某一天空气中的PM2.5,NO2浓度等维度的特征值。每一条数据同时包含一个标签,比如这一天的空气质量是优,良,轻度污染,中度污染,重度污染中的一个。
2 现在我们输入一条数据inX,如包含某一天的各项空气参数。计算这一条数据inX中各个特征的特征值与样本集DataSet中各条数据之间的相似度或者距离(距离的算法有很多种,这个例子中使用欧氏距离),并且将这些相似度/距离从小到大排序。
3 选择排序后的距离中前k条样本数据(k一般是不大于20的整数,这20怎么来的?),提取这k个样本集的标签,统计这些标签中出现次数最多的分类,作为我们输入数据inX的分类。
简单总结就是计算数据点与样本集中的每一个样本点的相似度,选取前k个相似的数据最为样本点的分类结果
二 算法优缺点
kNN算法的输入参数只有,样本集DataSet,样本点inX,以及人为选取的k。因为输入都是确定的参数,所以不需要训练算法。
(下面是参考《机器学习实战》,还没理解,后面待补充TODO)
优点:精度高,对异常值不敏感,无数据输入假定
缺点:计算复杂度高,空间复杂度高
三 Python实践
# -*- coding:utf-8 -*-
import numpy as np
import operator
def createData():
group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
lables = ['A','A','B','B']
return group,lables
def kNN(inX,dataSet,lables,k):
#计算inX与各个点的距离
dataSetSize = dataSet.shape[0]
diffMat = np.tile(inX,(dataSetSize,1)) - dataSet
sqDiffMat = diffMat ** 2
sqDistance = sqDiffMat.sum(axis=1)
distance = sqDistance ** 0.5
#对所有点间的距离从小到大排序
sortedDistIndecies = distance.argsort()#argsort()函数返回的是原数组排序后的索引
#选取前k个距离,分别比较k个结果里,inX各被分为什么类
clasCount = {}
for i in range(k):
voteLable = lables[sortedDistIndecies[i]]
clasCount[voteLable] = clasCount.get(voteLable,0)+1
sortedClassCount = sorted(clasCount.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
if __name__ == '__main__':
group,lables = createData()
result = kNN((1,1.1),group,lables,3)
print '分类结果为' + result + '类'
四 利用kNN对空气质量分类
DataSet:
特征:AQI指数 当天AQI排名 PM2.5 PM10 No2 So2 Co O3
特征值:77 146 56 77 40 9 1.27 40
特征值:76 186 55 75 47 12 1.40 14
Lables: 优 良 轻度污染 中毒污染 重度污染