k临近算法(kNN)采用测量不同特征值之间的距离方法进行分类,也是一种非常直观的方法。本文主要记录了使用kNN算法改进约会网站的例子。
任务一:分类算法classify0
就是使用距离公式计算特征值之间的距离,选择最邻近的k个点,通过统计这k个点的结果来得出样本的预测值。
tile函数用法在这里
argsort函数在这里
def classify0(inX,dataset,labels,k):
#shape 返回行列数,shape[0]是行数,有多少元组
datasetsize = dataset.shape[0]
#tile 复制inX,使其与dataset一样大小
diffmat = tile(inX,(datasetsize,1)) - dataset
#**表示乘方
sqdiffmat = diffmat ** 2
#按行将计算结果求和
sqdistances = sqdiffmat.sum(axis=1)
distances = sqdistances ** 0.5
#使用argsort排序,返回索引值
sortedDistIndicies = distances.argsort()
#用于计数,计算结果
classcount = {}
for i in range(k) :
voteIlabel = labels[sortedDistIndicies[i]]
classcount[voteIlabel] = classcount.get(voteIlabel,0)+1
#按照第二个元素降序排列
sortedClasscount = sorted(classcount.iteritems(),key=operator.itemgetter(1),reverse=True)
#返回出现次数最多的那一个label的值
return sortedClasscount[0][0]
任务二:读入数据
注意这里书上写错了,应该读入的是datingTestSet2.txt而不是datingTestSet.txt
书上的数据和例子下载:在这里
def file2matrix(filename):
fr = open(filename)
#打开文件,按行读入
arrayOLines = fr.readlines()
#获得文件行数
numberOfLines = len(arrayOLines)
#创建m行n列的零矩阵
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
任务三:使用Matplotlib画图
安装Matplotlib时还需要numpy, dateutil, pytz, pyparsing, six, setuptools这几个包。可以在这里下载到,挺全的。加入到python27\Lib\site-packages目录下。
在powershell中cd到datingTestSet2.txt所在文件夹
输入python命令并且输入以下命令
粘贴:
import numpy
import matplotlib
import matplotlib.pyplot as plt
import kNN
reload(kNN)
datingDataMat,datingLabels=kNN.file2matrix(‘datingTestSet2.txt‘)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*numpy.array(datingLabels),15.0*numpy.array(datingLabels))
plt.show()
下面使用后两个特征的图片
将scatter函数修改为:
ax.scatter(datingDataMat[:,0],datingDataMat[:,1],15.0*numpy.array(datingLabels),15.0*numpy.array(datingLabels))
使用前两个特征的图片
任务四:归一化
免除较大数值的数据给分类带来的影响,将每一项数据归一化为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
#从datingTestSet2.txt中获取数据
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))
print errorCount
出错率为5%
最后是kNN.py文件
#encoding:utf-8
from numpy import *
import operator
#创建数据集
def createDataSet():
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = [‘A‘,‘A‘,‘B‘,‘B‘]
return group, labels
#kNN实现0
def classify0(inX,dataset,labels,k):
#shape 返回行列数,shape[0]是行数,有多少元组
datasetsize = dataset.shape[0]
#tile 复制inX,使其与dataset一样大小
diffmat = tile(inX,(datasetsize,1)) - dataset
#**表示乘方
sqdiffmat = diffmat ** 2
#按行将计算结果求和
sqdistances = sqdiffmat.sum(axis=1)
distances = sqdistances ** 0.5
#使用argsort排序,返回索引值
sortedDistIndicies = distances.argsort()
#用于计数,计算结果
classcount = {}
for i in range(k) :
voteIlabel = labels[sortedDistIndicies[i]]
classcount[voteIlabel] = classcount.get(voteIlabel,0)+1
#按照第二个元素降序排列
sortedClasscount = sorted(classcount.iteritems(),key=operator.itemgetter(1),reverse=True)
#返回出现次数最多的那一个label的值
return sortedClasscount[0][0]
#从txt中读入数据
def file2matrix(filename):
fr = open(filename)
#打开文件,按行读入
arrayOLines = fr.readlines()
#获得文件行数
numberOfLines = len(arrayOLines)
#创建m行n列的零矩阵
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
#归一化数据
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.50
#从datingTestSet2.txt中获取数据
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))
print errorCount
原文地址:http://blog.csdn.net/iboxty/article/details/44982013