在处理这种不同取值范围的属性时,归一化是我们最常用的方法,如将取值范围压缩/扩展至[0,1]或者[-1,1]。下面的公式可以讲任意取值范围的属性值转化为[0,1]:
newValue=(oldValue-Min)/(Max-Min)
其中,Min和Max分别为数据集中最小属性值以及最大属性值。虽然改变数值的范围一定程度上增加了算法的时空复杂度,但是为了更好地利用数据间的信息,这么做是必须的。为此,我们新建一个名为autoNorm的函数,该函数将属性值压缩至[0,1],代码如下所示。
defautoNorm(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))
normDataSet=normDataSet/tile(ranges,(m,1))
returnnormDataSet,ranges,minVals
在python命令行下,加载kNN.py模块,执行autoNorm函数,如下所示。
这儿我们可以只把normMat作为函数返回值。
4.测试算法
本文中我们采用数据集的10%作为测试数据集,90%作为训练数据集(注意:训练数据集以及测试数据集的产生应该随机选取)。
创建名为classify0的函数作为kNN分类器,代码如下。
defclassify0(inX,dataSet,labels,k):dataSetSize=dataSet.shape[0]diffMat=tile(inX,(dataSetSize,1))-dataSetsqDiffMat=diffMat**2sqDistances=sqDiffMat.sum(axis=1)distances=sqDistances**0.5sortedDistIndicies=distances.argsort()classCount={}foriinrange(k):voteIlabel=labels[sortedDistIndicies[i]]classCount[voteIlabel]=classCount.get(voteIlabel,0)+1sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)returnsortedClassCount[0][0]为了测试分类器的效果,我们需要创建名为datingClassTest的函数,代码如下。
如图所示,处理约会数据集的错误率为6.4%,这是一个相当不错的结果。我们可以调试datingClassTest中的变量hoR安提哦你和变量k的值来降低错误率。为此,二丫完全可以输入未知对象的属性信息,有分类软件帮助她判定该队形属于哪一类(讨厌,一般喜欢以及非常喜欢)。