边看书边看代码,结合自己的理解总结。
概括:
1.思想:计算测试样本与训练集对应特征值之间的距离(文中用的是欧式距离),认为与测试样本距离最近的k个样本可以用来描述这个测试样本,取这k个训练样本中出现最多次的类别,作为这个测试样本的类别。
2.优点:精度高,对异常值不敏感
3.缺点:复杂度高
4.适用范围:数值型和标称型
(数值型主要是指它的目标变量可以从无限的数值集合中取值,标称型指的是在有限目标机中取值)
算法分析:
0.训练集必须是已标记的样本,首先对训练集样本的特征值归一化
1.计算测试样本(测试样本同样要归一化)与所有训练样本的欧氏距离
2.按照距离递增排序,选择前k个样本点
3.确定这k个样本所在类别的出现频率,出现频率最高的类别即为测试样本的类别
4.文中给的评判分类器的标准是错误率=测试集中分类错误的个数/测试集样本数
#python 使用前安装numpy
from numpy import *
import operator
from os import listdir
def classify0(inX, dataSet, labels, k):
# kNN分类
# 输入测试集inX 训练集dataSet 训练集标签labels 前k个近邻,k可以自己设置
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
#测试样本每一个特征值都与训练集中所有样本的特征值做差,求平方,再开方,得到欧氏距离
sortedDistIndicies = distances.argsort()
#对距离排序,由小到大
classCount={}
for i in range(k):#选前k个样本
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#存储出现的类别的次数
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
#类别排序,选择出现次数最多的作为测试样本的类别
return sortedClassCount[0][0]
def autoNorm(dataSet):#归一化特征值
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m,1))
#归一化=(原-最小值)/(最大值-最小值)
#element wise divide
return normDataSet, ranges, minVals
def datingClassTest():#对分类器的测试
hoRatio = 0.20#选择样本的10%当做测试集,参数可调
datingDataMat,datingLabels = file2matrix('测试集.txt')
#从文件中读取数据 #load data setfrom file
normMat, ranges, minVals = autoNorm(datingDataMat)#归一化
m = normMat.shape[0]#样本总数
numTestVecs = int(m*hoRatio)#测试集总数
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
#每次输入测试集,训练集总样本,训练集标签,近邻k
#得到测试结果和测试集标签
if (classifierResult != datingLabels[i]): errorCount += 1.0
#如果预测错误,则错误个数加一
print "the total error rate is: %f" % (errorCount/float(numTestVecs))#最后算出错误率
print errorCount
从代码中也可以看出,knn的确是简单有效,但是算法必须保存全部的数据集,每一次测试时必须与所有样本计算距离,并且也无法给出数据的基础结构信息(比如特征具有什么样的特点)。