下面的部分是机器学习实战(Machine Learning in Action)一书中关于KNN算法实现约会网站配对实例的代码整合。
1.示例描述如下:
海莉使用约会网站寻找适合自己的约会对象,她将自己的约会对象分为三类:不喜欢、一般喜欢、非常喜欢。海莉希望分类软件能很好的帮助她将匹配对象划分到确切的分类中,以便她在不同的时间约会不同的人。
海莉收集了一些曾经约会过的人的信息,并把这些信息放在文本文件dataTestSet.txt中。每个样本数据占一行。样本主要有以下三种特征:每年获得的飞行常客里程数、玩视频游戏所耗时间百分比、每周消耗的冰激淋公升数。每个样本对应着一个分类,用数字1、2、3代替。1代表不喜欢,2代表一般喜欢,3代表非常喜欢。
2.K-近邻算法实现约会网站配对的步骤如下:
1.准备数据:将文本文件dataTestSet.txt进行解析。
2.测试算法:将数据集中10%的数据作为测试数据,剩下的数据作为训练数据。并计算错误率。
3.使用算法:输入一个人的特征,判断这个人是否是海莉喜欢的类型。
3.此算法涉及的函数有一下这些:
1.file2matrix(filename)函数:将文本文件中的数据解析,返回一个样本集矩阵和一个标签向量。
2.classify(inX,dataSet,labels,k)函数:KNN分类算法,对样本inX进行分类,返回分类的结果,即样本所属类别。
3.autoNorm(dataSet)函数:归一化特征值,将特征值的取值范围约束在0-1内,防止某一特征对整体的结果影响过大。
4.Test()函数:利用分类器对数据进行测试,选取数据的前10%作为测试数据,剩下的数据作为训练数据,并计算错误率。
5.classifyPerson()函数:使用算法判断一个人是否是海莉喜欢的类型。
4.实现代码如下:
from numpy import *
import operator
#使用KNN算法为每组数据分类
def classify(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
diffMat=tile(inX,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
sqDistance=sqDiffMat.sum(axis=1)
distances=sqDistance**0.5
sortedDistIndicies=distances.argsort()
classCount={}
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]]
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
#从文本中解析数据
def file2matrix(filename):
with open(filename) as file:
#求得样例的个数
arrayOLines=file.readlines()
numberOfLines=len(arrayOLines)
#求KNN算法所使用的数据集dataSet和类别labels
returnMat=zeros((numberOfLines,3)) #初始化一个数据集矩阵
classLabelVector=[] #初始化一个类别向量
index=0
for line in arrayOLines:
line=line.split()
returnMat[index,:]=line[0:3] #矩阵的每一行表示一个测试样例
classLabelVector.append(int(line[-1])) #文本中每行的最后一个数据作为该样例所属的类别
index+=1
return returnMat,classLabelVector
#归一化特征值
def autoNorm(dataSet):
minVals=dataSet.min(0) #将每列最小的特征值放在minVals中,参数0表示使得函数可以从列中选取最小值
maxVals=dataSet.max(0) #将每列最大的特征值放在maxVals中
ranges=maxVals-minVals
normalDataSet=zeros(shape(dataSet))
m=dataSet.shape[0] #样本数量
normalDataSet=dataSet-tile(minVals,(m,1))
normalDataSet=normalDataSet/tile(ranges,(m,1))
return normalDataSet,ranges,minVals
#利用分类器针对数据进行测试(数据的前10%用做测试数据,剩下的数据用作训练数据),并计算错误率
def Test():
hoRatio=0.10
dataSet,labels=file2matrix('dataTestSet') #从文件中读取数据集和每组数据所属分类
normDataSet,ranges,minVals=autoNorm(dataSet) #对数据集进行归一化处理
m=normDataSet.shape[0] #一共有多少组数据
numTest=int(m*hoRatio) #用于测试的数据组数
errorCount=0.0
for i in range(numTest):
classifierResult=classify(dataSet[i,:],dataSet[numTest:m,:],labels[numTest:m],3)
#print('classifier result:%d, real answer:%d'%(classifierResult,labels[i]))
if (classifierResult!=labels[i]):
errorCount+=1.0
print('the total error rate is: %f'%(errorCount/float(numTest)))
#估计约会对象的类型
def classifyPerson():
resultList=['not at all','in small doses','in large doses']
#输入约会对象的一些特征
percentTats=float(input('percentage of time spent playing video games:'))
ffMiles=float(input('frequent flier miles earned per year:'))
iceCream=float(input('liters of ice cream consumed per year:'))
#从文本文件中解析数据
dataSet,labels=file2matrix('dataTestSet')
#特征归一化处理
normMat,ranges,minVals=autoNorm(dataSet)
inArr=array([ffMiles,percentTats,iceCream]) #输入的约会对象的特征
intX=(inArr-minVals)/ranges #对输入的数据进行归一化处理
classifierResult=classify(intX,normMat,labels,3)#判断约会对象的类型
print('you will probably like this person: ',resultList[classifierResult-1])
Test() #测试算法错误率的函数
classifyPerson() #使用这个算法为海莉判断约会对象的类型
运行结果如下:
the total error rate is: 0.240000
percentage of time spent playing video games:10
frequent flier miles earned per year:10000
liters of ice cream consumed per year:0.5
you will probably like this person: in small doses
6.上述代码中每个函数的详细解释请看:
- classify(inX,dataSet,labels,k):KNN分类算法:https://blog.csdn.net/beautiful77moon/article/details/96167323
- file2matrix(filename):从文本中解析数据:https://blog.csdn.net/beautiful77moon/article/details/96363070
- autoNorm(dataSet):归一化特征值:https://blog.csdn.net/beautiful77moon/article/details/98591575
- Test():测试分类算法,并计算错误率:https://blog.csdn.net/beautiful77moon/article/details/98637440