#综述
kNN是一种基本分类与回归算法,在这里主要讨论分类算法。
基本思路是根据k个近邻的分类进行投票表决得出分类结果。
kNN没有显式的训练过程。
对于kNN最重要的三个基本要素是:k的选择、距离度量和分类决策规则。
kNN的一个常见实现方法是kd树。
#距离度量
特征空间的两点距离,距离一般采用欧氏距离。
#k值选择
k值取小可能会导致模型复杂度增加,发生过拟合现象
在实际操作中,往往先取一个较小的数值,采用交叉验证法进行验证
#分类决策规则
多数表决规则,即经验风险最小化
#kd树
当特征空间维度大和训练数据容量大时,全局计算距离再分类将导致计算时间过长。kd树解决如何队训练数据进行快速k近邻检索。
kd树是二叉树的一种形式,具体参见李航《统计学习方法》第三章
#python实现
该部分内容参照机器学习实战第二章内容。主要内容实现了约会网站配对效果。完整代码如下:
# -*- coding: utf-8 -*-
"""
Created on 10:27:00 2018.08.08
@author: maplefeng
kNN for Date
from <Machine Learing in Action> chapter 2
"""
import numpy as np
import operator
import matplotlib
import matplotlib.pyplot as plt
def readfile(filename):
"""read file return dataSet&label
:type filename: string
:rtype dataSet: array
labels: vector
"""
fr = open(filename)
text = fr.readlines()
lineNum = len(text)
#读入文件获取行数
dataSet = np.zeros([lineNum,3])
labels = []
#创建返回数据和类别
i = 0
for line in text:
line = line.strip()
linesept = line.split('\t')
dataSet[i,:] = linesept[0:3]
catg = linesept[-1][0]
labels.append(ord(catg))
i += 1
return dataSet, labels
def autoNorm(dataSet):
cmax = np.amax(dataSet,0)
cmin = np.amin(dataSet,0)
rangea = cmax - cmin
normdata = np.zeros(np.shape(dataSet))
r = dataSet.shape[0]
normdata = dataSet - np.tile(cmin,(r,1))
normdata = normdata/np.tile(rangea,(r,1))
return normdata, rangea, cmin
# for i in range(dataSet.shape[0]):
# dataSet[i] = (dataSet[i]-cmin)/(cmax - cmin)
#!!!矩阵计算的思想,通过矩阵计算代替循环处理!!!
def plot(data,label):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(data[:,0],data[:,1],0.5*np.array(label),0.5*np.array(label))
print(0.5*np.array(label))
plt.show()
def classify(inX, dataSet, labels, k):
'''
use for kNN
arg
inX:输入向量,list[int] 1x2
dataSet:训练集,array[] 4x2
labels:标签向量,list[string]
k:用于选择最近邻的数量,int
return
label for inX, string
'''
dataSetSize = dataSet.shape[0]
diffMat = np.tile(inX, (dataSetSize,1))-dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(1)
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort()
classCount = {}
for i in range(k):
votaLabel = labels[sortedDistIndicies[i]]
classCount[votaLabel] = classCount.get(votaLabel,0) + 1
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
def datingClassTest():
ratio = 0.1
errcount = 0
data,label = readfile('datingTestSet.txt')
m = data.shape[0]
normData, rangea, cmin = autoNorm(data)
testcount = int(ratio*m)
for i in range(testcount):
classifyresult = classify(normData[i,:],normData[testcount:m],label[testcount:m],3)
print('the classify result is {}; the real result is {}.'.format(classifyresult,label[i]))
if classifyresult != label[i]:
errcount += 1
print('the total error ratio is {:.2f}'.format(errcount/testcount))
def classifyPerson():
resultList = {100:'not at all', 115:'in small doses', 108:'inlarge doses'}
feature1 = float(input('feature1 of this person '))
feature2 = float(input('feature2 of this person '))
feature3 = float(input('feature3 of this person '))
data,label = readfile('datingTestSet.txt')
normData, rangea, cmin = autoNorm(data)
thisx = np.array([feature1,feature2,feature3])
classifyresult = classify((thisx-cmin)/rangea, normData, label, 3)
print('you will like this person {}'.format(resultList[classifyresult]))
#datingClassTest()
classifyPerson()
数据可以在机器学习实战相关文件中找到