接着上次的博客,再讲讲KNN算法的具体应用。这里用到了书本中提供的数据集datingTestSet2。
数据集的有三个特征,第四列是类别标签。但是仔细观察会发现第一列的数值明显比其他两列大,这就回造成一个问题就是,当计算位置数据与数据集中每个数据的距离时,第一个参数的作用远大于其他两列,这就需要将数据进行归一化。在之前先要将txt文件中的数据转化为一个矩阵。
def file2matrix(filename):
with open(filename) as fr:
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat = zeros((numberOfLines, 3))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip()
listFromLine = line.split("\t")
returnMat[index, :] = listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat, classLabelVector
在进行归一化,归一化公式为newvalue = (oldvalue - min) / (max - min),得到的新值得范围为0~1,具体代码如下。
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))
normDataSet = normDataSet / tile(ranges, (m, 1))
return normDataSet, ranges, minVals
def datingClassTest():
hoRatio = 0.10
datingDataMat, datingLabels = file2matrix("datingTestSet2.txt")
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)
print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])
if (classifierResult != datingLabels[i]):
errorCount += 1.0
print "the total error rate is: %f" % (errorCount / float(numTestVecs))
运行一下的结果: