Python 3.6 WIN10环境下,PyCharm IDE写代码,前半部分(电影分类问题)使用cmd执行数据输入,后半部分(约会网站问题开始)直接在IDE的Console区域执行数据输入;path环境路径使用aconda,暂时发现其他的环境路径遇到matplotlib无法安装成功的问题:

k-近邻算法思想如下:

1.计算已知类别数据集中的点与当前点之间的距离

2.按照距离递增次序排序

3.选取与当前点距离最小的k个点

4.确定前k个点所在类别的出现频率

5.返回前k个点出现频率最高的类别作为当前点的预测分类

主要运用到高中数学知识,求欧几里得空间两点距离:

创建kNN.py文件,cmd环境需要cd到kNN.py所在目录。

1.电影分类问题,代码如下:

①收集数据:可使用任何方法

②准备数据:距离计算所需要的数值,最好是结构化的数据格式

③分析数据:可使用任何方法

④训练算法:此步骤不适用于k-近邻算法

⑤测试算法:计算错误率

⑥使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

首先创建数据集:

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

其cmd对应执行命令如下:

>>> group,labels = kNN.createDataSet()
>>> group
array([[ 1. ,  1.1],[ 1. ,  1. ],[ 0. ,  0. ],[ 0. ,  0.1]])
>>> labels
['A', 'A', 'B', 'B']

分类方法,在cmd中调用执行:inX-要分类的输入量; dataSet-输入的训练样本集;labels-标签向量;k-旋转最近邻居的数目

最后返回的就是,该输入量最可能所属的元素标签,即发生频率最高的标签。

def classify0(inX, dataSet, labels, k):#求出样本集的行数,也就是labels标签的数目dataSetSize = dataSet.shape[0]#构造输入值和样本集的差值矩阵diffMat = tile(inX, (dataSetSize,1)) - dataSet#计算欧式距离sqDiffMat = diffMat**2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances**0.5#求距离从小到大排序的序号sortedDistIndicies = distances.argsort()#对距离最小的k个点统计对应的样本标签classCount={}for i in range(k): #选择距离最小的k个点#取第i+1邻近的样本对应的类别标签voteIlabel = labels[sortedDistIndicies[i]]#以标签为key,标签出现的次数为value将统计到的标签及出现次数写进字典classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#对字典按value从大到小排序sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1), reverse=True) #排序#返回排序后字典中最大value对应的keyreturn sortedClassCount[0][0]

其对应的cmd命令执行操作:

>>> kNN.classify0([0,0], group, labels, 3)
'B'
>>> kNN.classify0([0,1], group, labels, 3)
'B'
>>> kNN.classify0([1,1.1], group, labels, 3)
'A'

2.约会网站问题

解析已知样本数据,样本数据包含特征值和目标值。将未知对象(由特征值定义)归类(目标值),三类:1.不喜欢的人 2.魅力一般的人 3.极具魅力的人

流程如下:

①收集数据:提供文本文件datingTestSet.txt

②准备数据:使用Python解析文本文件

③分析数据:使用Matplotlib画二维扩散图

④训练算法:此步骤不适用于k-近邻算法

⑤测试算法:使用部分数据作为测试样本。

测试样本和非测试样本的区别在于:测试样本时已经完成分类的数据,如果预测分类与实际类别不同,则标记为一个错误。

⑥使用算法:产生简单的命令行程序,然后可输入一些特征数据以判断对方是否为自己喜欢的类型

代码如下:

def file2matrix(filename):#打开文件fr = open(filename)#得到文件的行数arrayOLines = fr.readlines()numberOfLines = len(arrayOLines)#创建以零填充的矩阵,为了简化处理,将该矩阵的另一维度设置为固定值3,可按照自己的实际需求增加相应的代码以适应变化的输入值returnMat = zeros((numberOfLines, 3))classLabelVector = []index = 0for line in arrayOLines:line = line.strip()#截取掉所有的回车字符listFromLine = line.split('\t') #然后使用tab字符\t将上一步得到的整行数据分割成一个元素列表returnMat[index,:] = listFromLine[0:3] #选取前3个元素,将它们存储到特征矩阵中if(listFromLine[-1] == 'largeDoses'): #Python语言可使用索引值-1表示列表中的最后一列元素,利用该负索引,可方便地将列表的最后一列存储到向量classLabelVector中classLabelVector.append(3)#listFromLine[-1] = '3' #为之后的使用该算法来判断是否喜欢一个人时而改elif (listFromLine[-1] == 'smallDoses'):classLabelVector.append(2)#listFromLine[-1] = '2' #为之后的使用该算法来判断是否喜欢一个人时而改else:classLabelVector.append(1)#listFromLine[-1] = '1' #为之后的使用该算法来判断是否喜欢一个人时而改#classLabelVector.append(float(listFromLine[-1]))#必须明确地通知解释器,告诉它列表中存储的元素值为整型,否则Python语言会将这些元素当做字符串处理index += 1return returnMat,classLabelVector

cmd下命令如下,包括使用matplotlib图像化:

>>> import kNN
>>> from numpy import *
>>> datingDataMat,datingLabels = kNN.file2matrix('datingTestSet.txt')
>>> import matplotlib
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))
<matplotlib.collections.PathCollection object at 0x000002B853F7F860>
>>> plt.show()

若报错:

Traceback (most recent call last):File "<stdin>", line 1, in <module>
NameError: name 'array' is not defined

则添加:

>>>from numpy import *

效果如下,带有样本分类标签的约会数据散点图,虽然能够比较容易地区分数据点从属类别,但依然很难根据这张图得出结论性信息:

将数据列1,2改为0,1:

ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))

改为:

ax.scatter(datingDataMat[:,0], datingDataMat[:,1], 15.0*array(datingLabels), 15.0*array(datingLabels))

效果如下,每年获取的飞行常客里程数与玩视频游戏所占百分比的约会数据散点图。约会数据有三个特征,通过图中展示的两个特征更容易区分数据点从属的类别:

归一化处理:

由欧式距离公式可知,每年获得的飞行常客里程数,对计算结果影响最大。而一般认为这三种特征值应该是同等重要的,因此作为三个等权重的特征之一,飞行常客里程数不应该如此严重地影响到计算结果,因此要对数值进行归一化处理,如将取值范围处理为0到1或-1到1之间。下面的公式可以将任意取值范围的特征值转化为0到1区间内的值:

newValue = (oldValue - min)/(max - min)

其中min和max分别是数据集中的最小特征值和最大特征值。虽然改变数值取值范围增加了分类器的复杂度,但为了得到准确结果,必须这么做。因此就需要再增加一个新函数autoNorm()来将数字特征值转化为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)) #tile将变量内容复制成输入矩阵同样大小的矩阵normDataSet = normDataSet/tile(ranges, (m,1)) #特征值相除,为了归一化特征值,必须使用当前值减去最小值,然后除以取值范围;在某些数值处理软件包,/可能意味着矩阵除法,NumPy库中,return normDataSet,ranges,minVals            #矩阵除法需要使用函数linalg.solve(matA,matB)

cmd:

>>> import kNN
>>> datingDataMat,datingLabels=kNN.file2matrix('datingTestSet.txt')
>>> normMat,ranges,minVals = kNN.autoNorm(datingDataMat)
>>> normMat
array([[ 0.44832535,  0.39805139,  0.56233353],[ 0.15873259,  0.34195467,  0.98724416],[ 0.28542943,  0.06892523,  0.47449629],...,[ 0.29115949,  0.50910294,  0.51079493],[ 0.52711097,  0.43665451,  0.4290048 ],[ 0.47940793,  0.3768091 ,  0.78571804]])
>>> ranges
array([  9.12730000e+04,   2.09193490e+01,   1.69436100e+00])
>>> minVals
array([ 0.      ,  0.      ,  0.001156])

测试算法,验证分类器:

测试分类器,若分类器的正确率满足要求,则可使用该软件来处理约会网站提供的约会名单了。机器学习算法一个很重要的工作就是评估算法的正确率,通常只提供已有数据的90%作为训练样本来训练分类器,而使用其余的10%数据去测试分类器,检测分类器的正确率。需注意的是,10%的测试数据应该是随机选择的,由于datingTestSet.txt提供的数据并没有按照特定目的来排序,所以可随意选择10%数据而影响其随机性。

要测试分类器效果,在文件中再添加函数datingClassTest,该函数是自包含的,可在任何时候在Python运行环境中使用该函数测试分类器效果,代码如下:

def datingClassTest():hoRatio = 0.1 #前10%的数据作为测试数据集,后90%数据作为训练数据集#从文件中读取数据并将其转换为归一化特征值datingDataMat,datingLabels = file2matrix('datingTestSet.txt')normMat,ranges,minVals = autoNorm(datingDataMat)#计算测试向量的数量,决定了normMat向量中哪些数据用于测试,哪些数据用于分类器的训练样本m = normMat.shape[0]numTestVecs = int(m*hoRatio)errorCount = 0.0for i in range(numTestVecs):#将测试数据和训练数据输入到分类器中#normMat[i,:] 取出第i行的所有数据#normMat[numTestVecs:m,:]取出numTestVecs之后到m的每行数据#datingLabels[numTestVecs:m]取出numTestVecs之后到m的每行的标签#k值为3classifierResult = 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]))#如果错误不一致,则错误数加1if(classifierResult != datingLabels[i]):errorCount += 1.0#计算出错误率并输出结果print("the total error rate is:%f"%(errorCount/float(numTestVecs)))

cmd,错误率为5%:

>>> import kNN
>>> from numpy import *
>>> kNN.datingClassTest()
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 1
the total error rate is:0.050000

其中,若改变hoRatio的值为0.01,也就是前1%的数据作为测试数据集,后99%的数据作为训练数据集,可看到,测试数据样本为10个,同时错误率也变为了0%:

>>> import kNN
>>> from numpy import *
>>> kNN.datingClassTest()
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the total error rate is:0.000000

若hoRation改为0.2,也就是前20%数据作为测试数据集,后80%作为样本数据集,则可看到错误率为8%。

最后使用该算法来判断是否喜欢一个人:直接在PyCharm IDE中运行了,不再cmd中去运行了,再添加如下代码:

def classifyPerson():#输出结果resultList = ['不喜欢','有些喜欢','非常喜欢']#三维特征用户输入precentTats = float(input("玩视频游戏所耗时间百分比:"))ffMiles = float(input("每年获得的飞行常客里程数:"))iceCream = float(input("每周消费的冰激淋公升数:"))#打开的文件名filename = "datingTestSet.txt"#打开并处理数据datingDataMat, datingLabels = file2matrix(filename)#训练集归一化normMat, ranges, minVals = autoNorm(datingDataMat)#生成NumPy数组,测试集inArr = np.array([ffMiles, precentTats, iceCream])#测试集归一化norminArr = (inArr - minVals) / ranges#返回分类结果classifierResult = classify0(norminArr, normMat, datingLabels, 3)#打印结果print("你可能%s这个人" % (resultList[classifierResult-1]))if __name__ == '__main__':# datingClassTest()classifyPerson()

直接Run kNN.py,在Console区域输出结果如下:

玩视频游戏所耗时间百分比:10
每年获得的飞行常客里程数:10000
每周消费的冰激淋公升数:0.5
你可能有些喜欢这个人

到此,约会网站的算法已基本完成,之后只要具有某个人的三个特征值:玩视频游戏所耗时间百分比,每年获得的飞行常客里程数,每周消费的冰激凌公升数;然后将它们输入该算法,即可判断出对此人的喜欢程度。该模型所谓的喜欢程度的判断标准完全基于之前的样本训练数据,因此这个数据选择的前提也很重要。

整个完整代码如下:

from numpy import *
import numpy as np
import operator#分类器,k-近邻算法
def classify0(inX, dataSet, labels, k):#求出样本集的行数,也就是labels标签的数目dataSetSize = dataSet.shape[0]#构造输入值和样本集的差值矩阵diffMat = np.tile(inX, (dataSetSize,1)) - dataSet#计算欧式距离sqDiffMat = diffMat**2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances**0.5#求距离从小到大排序的序号sortedDistIndicies = distances.argsort()#对距离最小的k个点统计对应的样本标签classCount={}for i in range(k): #选择距离最小的k个点#取第i+1邻近的样本对应的类别标签voteIlabel = labels[sortedDistIndicies[i]]#以标签为key,标签出现的次数为value将统计到的标签及出现次数写进字典classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#对字典按value从大到小排序sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1), reverse=True) #排序#返回排序后字典中最大value对应的keyreturn sortedClassCount[0][0]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#解析文本记录
def file2matrix(filename):#打开文件fr = open(filename)#得到文件的行数arrayOLines = fr.readlines()numberOfLines = len(arrayOLines)#创建以零填充的矩阵,为了简化处理,将该矩阵的另一维度设置为固定值3,可按照自己的实际需求增加相应的代码以适应变化的输入值returnMat = zeros((numberOfLines, 3))classLabelVector = []index = 0for line in arrayOLines:line = line.strip()#截取掉所有的回车字符listFromLine = line.split('\t') #然后使用tab字符\t将上一步得到的整行数据分割成一个元素列表returnMat[index,:] = listFromLine[0:3] #选取前3个元素,将它们存储到特征矩阵中if(listFromLine[-1] == 'largeDoses'): #Python语言可使用索引值-1表示列表中的最后一列元素,利用该负索引,可方便地将列表的最后一列存储到向量classLabelVector中classLabelVector.append(3)# listFromLine[-1] = '3'elif (listFromLine[-1] == 'smallDoses'):classLabelVector.append(2)#listFromLine[-1] = '2'else:classLabelVector.append(1)#listFromLine[-1] = '1'#  classLabelVector.append(float(listFromLine[-1]))#必须明确地通知解释器,告诉它列表中存储的元素值为整型,否则Python语言会将这些元素当做字符串处理index += 1return 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 - np.tile(minVals, (m,1)) #tile将变量内容复制成输入矩阵同样大小的矩阵normDataSet = normDataSet/np.tile(ranges, (m,1)) #特征值相除,为了归一化特征值,必须使用当前值减去最小值,然后除以取值范围;在某些数值处理软件包,/可能意味着矩阵除法,NumPy库中,return normDataSet,ranges,minVals            #矩阵除法需要使用函数linalg.solve(matA,matB)#测试算法:作为完整程序验证分类器
def datingClassTest():hoRatio = 0.1#从文件中读取数据并将其转换为归一化特征值datingDataMat,datingLabels = file2matrix('datingTestSet.txt')normMat,ranges,minVals = autoNorm(datingDataMat)#计算测试向量的数量,决定了normMat向量中哪些数据用于测试,哪些数据用于分类器的训练样本m = normMat.shape[0]numTestVecs = int(m*hoRatio)errorCount = 0.0for i in range(numTestVecs):#将测试数据和训练数据输入到分类器中#normMat[i,:] 取出第i行的所有数据#normMat[numTestVecs:m,:]取出numTestVecs之后到m的每行数据#datingLabels[numTestVecs:m]取出numTestVecs之后到m的每行的标签#k值为3classifierResult = 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]))#如果错误不一致,则错误数加1if(classifierResult != datingLabels[i]):errorCount += 1.0#计算出错误率并输出结果print("the total error rate is:%f"%(errorCount/float(numTestVecs)))#预测函数:
"""
def classifyPerson():resultList = ['不喜欢', '有点喜欢', '非常喜欢']percentTats = float(input("玩视频游戏所耗时间百分比: "))ffMiles = float(input("每年获得飞行常客里程数: "))iceCream = float(input("每周消费冰激凌公升数: "))datingDataMat,datingLabels = file2matrix('datingTestSet.txt')normMat,ranges,minVals = autoNorm(datingDataMat)inArr = np.array([percentTats, ffMiles, iceCream])norminArr = (inArr - minVals) / rangesclassifierResult = classify0(norminArr, normMat, datingLabels, 3)print("你可能对这个人:", resultList[classifierResult-1])
"""
def classifyPerson():#输出结果resultList = ['不喜欢','有些喜欢','非常喜欢']#三维特征用户输入precentTats = float(input("玩视频游戏所耗时间百分比:"))ffMiles = float(input("每年获得的飞行常客里程数:"))iceCream = float(input("每周消费的冰激淋公升数:"))#打开的文件名filename = "datingTestSet.txt"#打开并处理数据datingDataMat, datingLabels = file2matrix(filename)#训练集归一化normMat, ranges, minVals = autoNorm(datingDataMat)#生成NumPy数组,测试集inArr = np.array([ffMiles, precentTats, iceCream])#测试集归一化norminArr = (inArr - minVals) / ranges#返回分类结果classifierResult = classify0(norminArr, normMat, datingLabels, 3)#打印结果print("你可能%s这个人" % (resultList[classifierResult-1]))if __name__ == '__main__':# datingClassTest()classifyPerson()

手写识别系统:

from numpy import *
import numpy as np
import operator
from os import listdir
import time#分类器,k-近邻算法
def classify0(inX, dataSet, labels, k):#求出样本集的行数,也就是labels标签的数目dataSetSize = dataSet.shape[0]#构造输入值和样本集的差值矩阵diffMat = np.tile(inX, (dataSetSize,1)) - dataSet#计算欧式距离sqDiffMat = diffMat**2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances**0.5#求距离从小到大排序的序号sortedDistIndicies = distances.argsort()#对距离最小的k个点统计对应的样本标签classCount={}for i in range(k): #选择距离最小的k个点#取第i+1邻近的样本对应的类别标签voteIlabel = labels[sortedDistIndicies[i]]#以标签为key,标签出现的次数为value将统计到的标签及出现次数写进字典classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#对字典按value从大到小排序sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1), reverse=True) #排序#返回排序后字典中最大value对应的keyreturn sortedClassCount[0][0]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#解析文本记录
def file2matrix(filename):#打开文件fr = open(filename)#得到文件的行数arrayOLines = fr.readlines()numberOfLines = len(arrayOLines)#创建以零填充的矩阵,为了简化处理,将该矩阵的另一维度设置为固定值3,可按照自己的实际需求增加相应的代码以适应变化的输入值returnMat = zeros((numberOfLines, 3))classLabelVector = []index = 0for line in arrayOLines:line = line.strip()#截取掉所有的回车字符listFromLine = line.split('\t') #然后使用tab字符\t将上一步得到的整行数据分割成一个元素列表returnMat[index,:] = listFromLine[0:3] #选取前3个元素,将它们存储到特征矩阵中if(listFromLine[-1] == 'largeDoses'): #Python语言可使用索引值-1表示列表中的最后一列元素,利用该负索引,可方便地将列表的最后一列存储到向量classLabelVector中classLabelVector.append(3)# listFromLine[-1] = '3'elif (listFromLine[-1] == 'smallDoses'):classLabelVector.append(2)#listFromLine[-1] = '2'else:classLabelVector.append(1)#listFromLine[-1] = '1'#  classLabelVector.append(float(listFromLine[-1]))#必须明确地通知解释器,告诉它列表中存储的元素值为整型,否则Python语言会将这些元素当做字符串处理index += 1return 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 - np.tile(minVals, (m,1)) #tile将变量内容复制成输入矩阵同样大小的矩阵normDataSet = normDataSet/np.tile(ranges, (m,1)) #特征值相除,为了归一化特征值,必须使用当前值减去最小值,然后除以取值范围;在某些数值处理软件包,/可能意味着矩阵除法,NumPy库中,return normDataSet,ranges,minVals            #矩阵除法需要使用函数linalg.solve(matA,matB)#测试算法:作为完整程序验证分类器
def datingClassTest():hoRatio = 0.1#从文件中读取数据并将其转换为归一化特征值datingDataMat,datingLabels = file2matrix('datingTestSet.txt')normMat,ranges,minVals = autoNorm(datingDataMat)#计算测试向量的数量,决定了normMat向量中哪些数据用于测试,哪些数据用于分类器的训练样本m = normMat.shape[0]numTestVecs = int(m*hoRatio)errorCount = 0.0for i in range(numTestVecs):#将测试数据和训练数据输入到分类器中#normMat[i,:] 取出第i行的所有数据#normMat[numTestVecs:m,:]取出numTestVecs之后到m的每行数据#datingLabels[numTestVecs:m]取出numTestVecs之后到m的每行的标签#k值为3classifierResult = 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]))#如果错误不一致,则错误数加1if(classifierResult != datingLabels[i]):errorCount += 1.0#计算出错误率并输出结果print("the total error rate is:%f"%(errorCount/float(numTestVecs)))#预测函数:
"""
def classifyPerson():resultList = ['不喜欢', '有点喜欢', '非常喜欢']percentTats = float(input("玩视频游戏所耗时间百分比: "))ffMiles = float(input("每年获得飞行常客里程数: "))iceCream = float(input("每周消费冰激凌公升数: "))datingDataMat,datingLabels = file2matrix('datingTestSet.txt')normMat,ranges,minVals = autoNorm(datingDataMat)inArr = np.array([percentTats, ffMiles, iceCream])norminArr = (inArr - minVals) / rangesclassifierResult = classify0(norminArr, normMat, datingLabels, 3)print("你可能对这个人:", resultList[classifierResult-1])
"""
def classifyPerson():#输出结果resultList = ['不喜欢','有些喜欢','非常喜欢']#三维特征用户输入precentTats = float(input("玩视频游戏所耗时间百分比:"))ffMiles = float(input("每年获得的飞行常客里程数:"))iceCream = float(input("每周消费的冰激淋公升数:"))#打开的文件名filename = "datingTestSet.txt"#打开并处理数据datingDataMat, datingLabels = file2matrix(filename)#训练集归一化normMat, ranges, minVals = autoNorm(datingDataMat)#生成NumPy数组,测试集inArr = np.array([ffMiles, precentTats, iceCream])#测试集归一化norminArr = (inArr - minVals) / ranges#返回分类结果classifierResult = classify0(norminArr, normMat, datingLabels, 3)#打印结果print("你可能%s这个人" % (resultList[classifierResult-1]))def img2vector(filename):returnVect = zeros((1,1024))fr = open(filename)for i in range(32):lineStr = fr.readline()for j in range(32):returnVect[0,32*i+j] = int(lineStr[j])return returnVect#把一个32x32的二进制图像矩阵转换为1x1024的向量,就可使用前面的分类器处理数字图像信息。
def handwritingClassTest():cpu_start = time.time()print('start:%f' % cpu_start)hwLabels = []#获取目录内容trainingFileList = listdir('trainingDigits')m = len(trainingFileList)trainingMat = zeros([m,1024])for i in range(m):#从文件名解析分类数字fileNameStr = trainingFileList[i]fileStr = fileNameStr.split('.')[0]classNumStr = int(fileStr.split('_')[0])hwLabels.append(classNumStr)trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)testFileList = listdir('testDigits')errorCount = 0.0mTest = len(testFileList)#循环读出文件的前32个字符值存储在NumPy数组中,最后返回数组for i in range(mTest):fileNameStr = testFileList[i]fileStr = fileNameStr.split('.')[0]classNumStr = int(fileNameStr.split('_')[0])vectorUnderTest = img2vector('testDigits/%s' %fileNameStr)classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)print("分类器返回值为:%d, 实际值为:%d" %(classifierResult, classNumStr))if(classifierResult != classNumStr): errorCount += 1.0print("\n错误总数为: %d" % errorCount)print("\n总错误率为: %f" %(errorCount/float(mTest)))cpu_end = time.time()print('end:%f' % cpu_end)print("total time: %f S" % (cpu_end - cpu_start))
if __name__ == '__main__':# datingClassTest()#classifyPerson()# testVector=img2vector('testDigits/0_13.txt')#print(testVector[0,0:31])# print(testVector[0,32:63])handwritingClassTest()

运行结果类似如下:

分类器返回值为:9, 实际值为:9
分类器返回值为:9, 实际值为:9
分类器返回值为:9, 实际值为:9错误总数为: 10总错误率为: 0.010571
end:1516780726.425686
total time: 33.872470 S

错误个数10个,错误率1.05%,耗时太长33.8s,这个还可以用其他方法改进。修改变量k值,函数handwritingClassTest随机选取训练样本、改变训练样本的数目,都会对k-近邻算法的错误率产生影响。

执行效率不高,k决策树就是k-近邻算法的优化版,可节省大量的计算开销。

testDigits以及trainingDigits

datingTestSet.txt如下:

第1列为每年获得的飞行常客里程数,第2列为玩视频游戏所耗时间百分比,第3列为每周消费的冰淇淋公升数,第4列为目标值:非常喜欢-largeDoses 有点喜欢-smallDoses 不喜欢-didntLike:

40920    8.326976    0.953952    largeDoses
14488   7.153469    1.673904    smallDoses
26052   1.441871    0.805124    didntLike
75136   13.147394   0.428964    didntLike
38344   1.669788    0.134296    didntLike

总结:k-近邻算法是分类数据最简单最有效的算法。本篇通过约会问题和手写识别系统使用k-近邻算法构造的分类器。k-近邻算法是基于实例的学习,使用算法时需要有接近实际数据的训练样本数据。k-近邻算法必须保存全部数据集,若训练数据集越大,则使用的存储空间也会越大,此外,由于必须对数据集中的每个数据计算距离值,实际使用时会非常耗时,由上面的手写识别系统可知。
k-近邻算法的另一个缺陷是它无法给出如何数据的基础结构信息,因此也无法知晓平均实例样本和典型是两样本具有什么特征。在使用概率测量方法处理分类问题时,可解决该问题。

k-近邻算法 From Machine Learning相关推荐

  1. 【Machine Learning】TensorFlow实现K近邻算法预测房屋价格

    1前言 机器学习KNN算法(K近邻算法)的总体理论很简单不在这里赘述了. 这篇文章主要问题在于如果利用tensorflow深度学习框架来实现KNN完成预测问题,而不是分类问题,这篇文章中涉及很多维度和 ...

  2. 距离产生美?k近邻算法python实现

    https://blog.csdn.net/red_stone1/article/details/80607960 1. 什么是k近邻算法? k最近邻(k-Nearest Neighbor,kNN)分 ...

  3. python k近邻算法_python中的k最近邻居算法示例

    python k近邻算法 K最近邻居(KNN) (K-Nearest Neighbors (KNN)) KNN is a supervised machine learning algorithm t ...

  4. [机器学习]K近邻算法及其应用--WEKA工具

    K近邻算法理论基础 k近邻模型 距离度量 k值的选择 分类决策规则 WEKA实战 问题背景 数据预处理 得到分类器 对未知的数据进行分类预测 K近邻算法理论基础 (本节内容参考了:李航<统计学习 ...

  5. 机器学习——聚类之k近邻算法及python使用

    聚类算法之k近邻及python使用 什么是k近邻算法 k近邻算法流程 使用sklearn进行代码实现 数据集介绍 标准化 代码实现 写在开头,套用我的老师的一句话目前所有自然学科的前沿都是在研究数学, ...

  6. k近邻算法_机器学习之K近邻分类算法的实现

    K近邻算法(k-nearest neighbors, KNN)是最基本的机器学习算法之一.所谓的K,就是距离最近的K个邻居的意思.其实,KNN在我们平常的生活中也会不自主的应用,比如,俗语说的&quo ...

  7. 机器学习[k近邻算法]

    k近邻算法简称kNN算法,由Thomas等人在1967年提出[1].它基于以下思想:要确定一个样本的类别,可以计算它与所有训练样本的距离,然后找出和该样本最接近的k个样本,统计这些样本的类别进行投票, ...

  8. 从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

    原文出自:http://blog.csdn.net/v_JULY_v/article/details/8203674 前言 前两日,在微博上说:"到今天为止,我至少亏欠了3篇文章待写:1.K ...

  9. 【转】从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

    最近在看<统计学习方法>,发现这么一篇好文章,与大家分享 转自:http://blog.csdn.net/v_july_v/article/details/8203674?reload 前 ...

  10. knn k的选取_KNN - 初窥K近邻算法

    1>算法概述 KNN: 全名K-NearestNeighbor,K近邻算法,简单讲就是每个样本都可以用最接近的k个邻居表示,或者说共享同一个标签.KNN是一种分类(classification) ...

最新文章

  1. js控制table中tr位置互换
  2. C++远航之封装篇——深拷贝、浅拷贝
  3. Yslow-23条规则
  4. python移动平均线绘图_对python pandas 画移动平均线的方法详解
  5. 8 一点就消失_消失的莉莉安(25)
  6. 局域网中传输介质的应用分析
  7. Redis的hotkey和bigkey的一些拆解方式
  8. SQL server中如何使用return,break和continue
  9. (IT)这个行当里你应该知道的10个小秘密
  10. VBA 代码如何跟随Excel保存
  11. Confluence使用教程 用户手册
  12. 720全景制作 - 微信、PC、移动web
  13. 【计算机科学】【2017】无组织三维点云的边缘检测
  14. 【转】专家:制造业将大批死亡 都怪马云
  15. STM32 ADC 单次模式、连续模式、扫描模式
  16. oracle递归查询实例
  17. 计算机新建表格2,(Word表格的制作计算机基础2.doc
  18. uni-app转小程序遇到的问题 (组件使用插槽的问题)(跨端兼容、条件编译)(小程序自定义胶囊按钮封装)(uni-app挂载原型链)
  19. Python实现文件简单加解密
  20. AWS EC2 and EBS

热门文章

  1. 在quartus中使用FFT IP核最全教程(从入门到放弃)
  2. 信号灯管理服务器CPU型号,正文-新华三集团-H3C
  3. clickhouse列转行
  4. 操作Excel工具类:ExcelUtils.java
  5. 计算机电源维修如何知道好坏,怎么判断电脑电源坏了 主板不通电解决方法
  6. 【电路】自用人体感应灯(HC-SR501人体感应模块)
  7. 全国计算机二级很难得吗,全国计算机二级考试难吗?
  8. 张孝祥正在整理Java就业面试题大全20100602版本(一)
  9. C# DevExpress控件Gridview和GridControl学习总结
  10. PostMan接口参数化、接口返回值传递