文章目录

  • 一、k-近邻算法概述
  • 二、K近邻算法--约会网站配对
    • 1、案例介绍
    • 2、准备数据、分析数据
    • 3、测试算法
    • 4、使用算法
    • 5、使用sklearn实现

一、k-近邻算法概述

简答的说k近邻算法采用测量不同特征值之间的距离方法进行分类。
工作原理是: 存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输人没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
k-近邻算法的一般流程
(1)收集数据:可以使用任何方法。
(2)准备数据:距离计算所需要的数值,最好是结构化的数据格式。
(3)分析数据:可以使用任何方法。
(4)训练算法:此步驟不适用于k 近邻算法。
(5)测试算法:计算错误率。
(6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行女-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

二、K近邻算法–约会网站配对

1、案例介绍

我的朋友海伦一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但她没有从中找到喜欢的人。经过一番总结,她发现曾交往过三种类型的人:
□ 不喜欢的人
□ 魅力一般的人
□ 极具魅力的人
海伦收集了自己的一些约会记录的数据信息。每个样本数据占据一行,总共有1000行。
数据文件 datingTestSet2.txt
海伦的样本数据局主要包含以下3种特征:
□ 每年获得的飞行常客里程数
□ 玩视频游戏所耗时间百分比
□ 每周消费的冰淇淋公升数
她希望通过以上这三个特征来进行判断自我感觉。

2、准备数据、分析数据

1、在将上述特征数据输人到分类器之前,必须将待处理数据的格式改变为分类器可以接受的格式。
2、接着我们需要了解数据的真实含义。当然我们可以直接浏览文本文件,但是这种方法非常不友好,一般来说,我们会采用图形化的方式直观地展示数据。

from numpy import *
from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
import operator     #导入需要用到的包def filematrix(filename):fr=open(filename)      #打开文件arrayoflines=fr.readlines()    #读取文件numberoflines=len(arrayoflines)     #得到文件的行数returnmat=zeros((numberoflines,3))      #returnmat是一个numberoflines行3列的0矩阵,用来存放featureclasslabelvector=[]        #设置一个空list来存labelindex=0for line in arrayoflines:     #一行一行读数据line=line.strip()     #截取所有回车字符listfromline=line.split('\t')    #将上一步得到的整行数据分割成一个列表returnmat[index,:]=listfromline[0:3]         #注意矩阵的索引和列表的索引    #1-3列是特征列,依次将特征存放到returnmat中#下面两行代码和下下面的代码。注意输出是数字还是字符串a = float(listfromline[-1])       # 列表转换为数字classlabelvector.append(a)     #最后一列也就是第4列是label列,存放到classlabelvector中#对于datingTestSet文档好使# if listfromline[-1] == 'didntLike':#     classlabelvector.append(1)# elif listfromline[-1] == 'smallDoses':#     classlabelvector.append(2)# elif listfromline[-1] == 'largeDoses':#     classlabelvector.append(3)index+=1return returnmat,classlabelvector    #返回特征矩阵和标签列表
def showdatas(datingDataMat, datingLabels):#设置汉字格式font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)#将fig画布分隔成1行1列,不共享x轴和y轴,fig画布的大小为(13,8)#当nrow=2,nclos=2时,代表fig画布被分为四个区域,axs[0][0]表示第一行第一个区域fig, axs = plt.subplots(nrows=2, ncols=2,sharex=False, sharey=False, figsize=(13,8))numberOfLabels = len(datingLabels)LabelsColors = []for i in datingLabels:if i == 1:LabelsColors.append('black')if i == 2:LabelsColors.append('orange')if i == 3:LabelsColors.append('red')#画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第二列(玩游戏)数据画散点数据,散点大小为15,透明度为0.5axs[0][0].scatter(x=datingDataMat[:,0], y=datingDataMat[:,1], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs0_title_text = axs[0][0].set_title(u'每年获得的飞行常客里程数与玩视频游戏所消耗时间占比',FontProperties=font)axs0_xlabel_text = axs[0][0].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font)axs0_ylabel_text = axs[0][0].set_ylabel(u'玩视频游戏所消耗时间占',FontProperties=font)plt.setp(axs0_title_text, size=9, weight='bold', color='red')plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black')#画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5axs[0][1].scatter(x=datingDataMat[:,0], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs1_title_text = axs[0][1].set_title(u'每年获得的飞行常客里程数与每周消费的冰激淋公升数',FontProperties=font)axs1_xlabel_text = axs[0][1].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font)axs1_ylabel_text = axs[0][1].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font)plt.setp(axs1_title_text, size=9, weight='bold', color='red')plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black')#画出散点图,以datingDataMat矩阵的第二(玩游戏)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5axs[1][0].scatter(x=datingDataMat[:,1], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs2_title_text = axs[1][0].set_title(u'玩视频游戏所消耗时间占比与每周消费的冰激淋公升数',FontProperties=font)axs2_xlabel_text = axs[1][0].set_xlabel(u'玩视频游戏所消耗时间占比',FontProperties=font)axs2_ylabel_text = axs[1][0].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font)plt.setp(axs2_title_text, size=9, weight='bold', color='red')plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black')#设置图例didntLike = mlines.Line2D([], [], color='black', marker='.',markersize=6, label='didntLike')smallDoses = mlines.Line2D([], [], color='orange', marker='.',markersize=6, label='smallDoses')largeDoses = mlines.Line2D([], [], color='red', marker='.',markersize=6, label='largeDoses')#添加图例axs[0][0].legend(handles=[didntLike,smallDoses,largeDoses])axs[0][1].legend(handles=[didntLike,smallDoses,largeDoses])axs[1][0].legend(handles=[didntLike,smallDoses,largeDoses])"""1.tight_layout命令:主要用于自动调整绘图区的大小及间距,使所有的绘图区及其标题、坐标轴标签等都可以不重叠的完整显示在画布上。2、tight_layout命令还有三个关键字参数:pad、w_pad、h_pad。pad用于设置绘图区边缘与画布边缘的距离大小w_pad用于设置绘图区间水平距离的大小h_pad用于设置绘图区间垂直距离的大小"""fig.tight_layout(pad=2, w_pad=3.0, h_pad=3.0)#显示图片plt.show()
datingdatamat,datinglabel=filematrix('datingTestSet2.txt')
showdatas(datingdatamat,datinglabel)

显示如下:

3、归一化数据:我们很容易发现,在用欧拉公式(如下)计算两个样本数据距离时,方程中数字差值最大的属性对计算结果的影响最大,也就是说,每年获取的飞行常客里程数对于计算结果的影响将远远大于其他两个特征— 玩视频游戏的和每周消费冰洪淋公升数— 的影响。

而产生这种现象的唯一原因,仅仅是因为飞行常客里程数远大于其他特征值。但海伦认为这三种特征是同等重要的,因此作为三个等权重的特征之一,飞行常客里程数并不应该如此严重地影响到计算结果。:在处理这种不同取值范围的特征值时,我们通常采用的方法是将数值归一化。

其中min和max分别是数据集中的最小特征值和最大特征值。虽然改变数值取值范围增加了分类器的复杂度,但为了得到准确结果,我们必须这样做。我们需要在程序中增加一个新函数autoMorm。 该函数可以自动将数字特征值转化为0到1的区间。

from numpy import *def filematrix(filename):fr=open(filename)      #打开文件arrayoflines=fr.readlines()    #读取文件numberoflines=len(arrayoflines)     #得到文件的行数returnmat=zeros((numberoflines,3))      #returnmat是一个numberoflines行3列的0矩阵,用来存放featureclasslabelvector=[]        #设置一个空list来存labelindex=0for line in arrayoflines:     #一行一行读数据line=line.strip()     #截取所有回车字符listfromline=line.split('\t')    #将上一步得到的整行数据分割成一个列表returnmat[index,:]=listfromline[0:3]         #注意矩阵的索引和列表的索引    #1-3列是特征列,依次将特征存放到returnmat中#下面两行代码和下下面的代码。注意输出是数字还是字符串a = float(listfromline[-1])       # 列表转换为数字classlabelvector.append(a)     #最后一列也就是第4列是label列,存放到classlabelvector中#对于datingTestSet文档好使# if listfromline[-1] == 'didntLike':#     classlabelvector.append(1)# elif listfromline[-1] == 'smallDoses':#     classlabelvector.append(2)# elif listfromline[-1] == 'largeDoses':#     classlabelvector.append(3)index+=1return returnmat,classlabelvector    #返回特征矩阵和标签列表
#  归一化函数
def autonorm(dataset):minvalue=dataset.min(0)    #每列的最小值maxvalue=dataset.max(0)    #每列的最大值ranges=maxvalue-minvaluenormdataset=zeros(shape(dataset))    #数据集大小的0矩阵m=dataset.shape[0]     #数据集行数normdataset=dataset-tile(minvalue,(m,1))     #数据集-m行的3列最小值normdataset=normdataset/tile(ranges,(m,1))   #数据集-m行的3列最大值return normdataset, ranges, minvalue    #返回归一化之后的数据
datingdatamat,datinglabel=filematrix('datingTestSet2.txt')
normdataset,ranges,minvalue=autonorm(datingdatamat)

3、测试算法

我们将测试分类器的效果,如果分类器的正确率满足要求,海伦就可以使用这个软件来处理约会网站提供的约会名单了。机器学习算法一个很重要的工作就是评估算法的正确率,通常我们只提供已有数据的90%作为训练样本来训练分类器,而使用其余的10%数据去测试分类器,检测分类器的正确率。其中classify0函数为分类函数。
下面代码显示错误率就是分类器给出错误结果的次数除以测试数据的总数,完美分类器的错误率为0,而错误率为1.0的分类器不会给出任何正确的分类结果。

from numpy import *
from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
import operator     #导入需要用到的包def classify0(inx, dataset, labels, k):     # inX是你要输入的要分类的“坐标”,dataSet是上面createDataSet的array,# 就是已经有的,分类过的坐标,label是相应分类的标签,k是KNN,k近邻里面的kdatasetsize = dataset.shape[0]  # dataSetSize是dataSet的行数,用上面的举例就是4行# .min(0)  读取每行最小值.max(0)   .shape[0]计算行数      .min(1)  读取每列最小值.max(1)    .shape[1]计算列数diffmat = tile(inx, (datasetsize, 1)) - dataset  # 前面用tile,把一行inX变成4行一模一样的(tile有重复的功能,# dataSetSize是重复4遍,后面的1保证重复完了是4行,而不是一行里有四个一样的),# 然后再减去dataSet,是为了求两点的距离,先要坐标相减,这个就是坐标相减sqdiffmat = diffmat ** 2sqdistances = sqdiffmat.sum(axis=1)  # axis=1是行相加,这样得到了(x1-x2)^2+(y1-y2)^2distance = sqdistances ** 0.5  # 这样求出来就是欧式距离sorteddistanceindicies = distance.argsort()  # argsort是排序,将元素按照由小到大的顺序返回下标,比如([3,1,2]),它返回的就是([1,2,0])classcount = {}for i in range(k):votelabel = labels[sorteddistanceindicies[i]]classcount[votelabel] = classcount.get(votelabel, 0) + 1  # 求每个类别的个数,有‘A’就让'A'的计数加1sortclass = sorted(classcount.items(), key=operator.itemgetter(1), reverse=True)  #classCount.items()将classCount字典分解为元组列表 ,operator.itemgetter(1)按照第二个元素的次序对元组进行排序,reverse=True是逆序,即按照从大到小的顺序排列return sortclass[0][0]  # 第一个就是最大的,返回最大的类别就是预测的类别def filematrix(filename):fr=open(filename)      #打开文件arrayoflines=fr.readlines()    #读取文件numberoflines=len(arrayoflines)     #得到文件的行数returnmat=zeros((numberoflines,3))      #returnmat是一个numberoflines行3列的0矩阵,用来存放featureclasslabelvector=[]        #设置一个空list来存labelindex=0for line in arrayoflines:     #一行一行读数据line=line.strip()     #截取所有回车字符listfromline=line.split('\t')    #将上一步得到的整行数据分割成一个列表returnmat[index,:]=listfromline[0:3]         #注意矩阵的索引和列表的索引    #1-3列是特征列,依次将特征存放到returnmat中#下面两行代码和下下面的代码。注意输出是数字还是字符串a = float(listfromline[-1])       # 列表转换为数字classlabelvector.append(a)     #最后一列也就是第4列是label列,存放到classlabelvector中index+=1return returnmat,classlabelvector    #返回特征矩阵和标签列表#将特征值归一化
def autonorm(dataset):minvalue=dataset.min(0)    #每列的最小值maxvalue=dataset.max(0)    #每列的最大值ranges=maxvalue-minvaluenormdataset=zeros(shape(dataset))    #数据集大小的0矩阵m=dataset.shape[0]     #数据集行数normdataset=dataset-tile(minvalue,(m,1))     #数据集-m行的3列最小值normdataset=normdataset/tile(ranges,(m,1))   #数据集-m行的3列最大值return normdataset,ranges,minvalue      #返回归一化之后的数据def showdatas(datingDataMat, datingLabels):#设置汉字格式font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)#将fig画布分隔成1行1列,不共享x轴和y轴,fig画布的大小为(13,8)#当nrow=2,nclos=2时,代表fig画布被分为四个区域,axs[0][0]表示第一行第一个区域fig, axs = plt.subplots(nrows=2, ncols=2,sharex=False, sharey=False, figsize=(13,8))numberOfLabels = len(datingLabels)LabelsColors = []for i in datingLabels:if i == 1:LabelsColors.append('black')if i == 2:LabelsColors.append('orange')if i == 3:LabelsColors.append('red')#画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第二列(玩游戏)数据画散点数据,散点大小为15,透明度为0.5axs[0][0].scatter(x=datingDataMat[:,0], y=datingDataMat[:,1], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs0_title_text = axs[0][0].set_title(u'每年获得的飞行常客里程数与玩视频游戏所消耗时间占比',FontProperties=font)axs0_xlabel_text = axs[0][0].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font)axs0_ylabel_text = axs[0][0].set_ylabel(u'玩视频游戏所消耗时间占',FontProperties=font)plt.setp(axs0_title_text, size=9, weight='bold', color='red')plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black')#画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5axs[0][1].scatter(x=datingDataMat[:,0], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs1_title_text = axs[0][1].set_title(u'每年获得的飞行常客里程数与每周消费的冰激淋公升数',FontProperties=font)axs1_xlabel_text = axs[0][1].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font)axs1_ylabel_text = axs[0][1].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font)plt.setp(axs1_title_text, size=9, weight='bold', color='red')plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black')#画出散点图,以datingDataMat矩阵的第二(玩游戏)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5axs[1][0].scatter(x=datingDataMat[:,1], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs2_title_text = axs[1][0].set_title(u'玩视频游戏所消耗时间占比与每周消费的冰激淋公升数',FontProperties=font)axs2_xlabel_text = axs[1][0].set_xlabel(u'玩视频游戏所消耗时间占比',FontProperties=font)axs2_ylabel_text = axs[1][0].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font)plt.setp(axs2_title_text, size=9, weight='bold', color='red')plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black')#设置图例didntLike = mlines.Line2D([], [], color='black', marker='.',markersize=6, label='didntLike')smallDoses = mlines.Line2D([], [], color='orange', marker='.',markersize=6, label='smallDoses')largeDoses = mlines.Line2D([], [], color='red', marker='.',markersize=6, label='largeDoses')#添加图例axs[0][0].legend(handles=[didntLike,smallDoses,largeDoses])axs[0][1].legend(handles=[didntLike,smallDoses,largeDoses])axs[1][0].legend(handles=[didntLike,smallDoses,largeDoses])#显示图片plt.show()#测试
def datingtest():horatio=0.10datingdatamat,datinglabel=filematrix('datingTestSet2.txt')  #打开文件,并把特征和标签都存到相应的矩阵和列表中showdatas(datingdatamat,datinglabel)normmat,ranges,minvalue=autonorm(datingdatamat)     #得到归一化后的数据m=normmat.shape[0]                     #得到数据的行数numtestvecs=int(m*horatio)           #得到10%的测试数据errorcount=0                         #初始错误个数设为0for i in range(numtestvecs):classifierresult=classify0(normmat[i],normmat[numtestvecs:m,:],datinglabel[numtestvecs:m],3)    #利用分类函数得到预测类别print('the classifier came back with:',classifierresult,'the real answer is:',datinglabel[i])if(classifierresult!=datinglabel[i]):errorcount+=1                                 #如果预测类别和真实类别不等的话,错误个数+1print('the error rate:',(errorcount/float(numtestvecs)))         #输出错误率
datingtest()

4、使用算法

已经在数据上对分类器进行了测试,得出一定的测试准确率,现在终于可以使用这个分类器为海伦来对人分类。通过该程序海伦会在约会网站上找到某个人并输入他的信息。程序会给出她对对方喜欢程度的预测值。.

from numpy import *
from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
import operator  # 导入需要用到的包def classify0(inx, dataset, labels, k):  # inX是你要输入的要分类的“坐标”,dataSet是上面createDataSet的array,# 就是已经有的,分类过的坐标,label是相应分类的标签,k是KNN,k近邻里面的kdatasetsize = dataset.shape[0]  # dataSetSize是dataSet的行数,用上面的举例就是4行# .min(0)  读取每行最小值.max(0)   .shape[0]计算行数      .min(1)  读取每列最小值.max(1)    .shape[1]计算列数diffmat = tile(inx, (datasetsize, 1)) - dataset  # 前面用tile,把一行inX变成4行一模一样的(tile有重复的功能,# dataSetSize是重复4遍,后面的1保证重复完了是4行,而不是一行里有四个一样的),# 然后再减去dataSet,是为了求两点的距离,先要坐标相减,这个就是坐标相减sqdiffmat = diffmat ** 2sqdistances = sqdiffmat.sum(axis=1)  # axis=1是行相加,这样得到了(x1-x2)^2+(y1-y2)^2distance = sqdistances ** 0.5  # 这样求出来就是欧式距离sorteddistanceindicies = distance.argsort()  # argsort是排序,将元素按照由小到大的顺序返回下标,比如([3,1,2]),它返回的就是([1,2,0])classcount = {}for i in range(k):votelabel = labels[sorteddistanceindicies[i]]classcount[votelabel] = classcount.get(votelabel, 0) + 1  # 求每个类别的个数,有‘A’就让'A'的计数加1sortclass = sorted(classcount.items(), key=operator.itemgetter(1),reverse=True)  # classCount.items()将classCount字典分解为元组列表 ,operator.itemgetter(1)按照第二个元素的次序对元组进行排序,reverse=True是逆序,即按照从大到小的顺序排列return sortclass[0][0]  # 第一个就是最大的,返回最大的类别就是预测的类别def filematrix(filename):fr = open(filename)  # 打开文件arrayoflines = fr.readlines()  # 读取文件numberoflines = len(arrayoflines)  # 得到文件的行数returnmat = zeros((numberoflines, 3))  # returnmat是一个numberoflines行3列的0矩阵,用来存放featureclasslabelvector = []  # 设置一个空list来存labelindex = 0for line in arrayoflines:  # 一行一行读数据line = line.strip()  # 截取所有回车字符listfromline = line.split('\t')  # 将上一步得到的整行数据分割成一个列表returnmat[index, :] = listfromline[0:3]  # 注意矩阵的索引和列表的索引    #1-3列是特征列,依次将特征存放到returnmat中# 下面两行代码和下下面的代码。注意输出是数字还是字符串a = float(listfromline[-1])  # 列表转换为数字classlabelvector.append(a)  # 最后一列也就是第4列是label列,存放到classlabelvector中index += 1return returnmat, classlabelvector  # 返回特征矩阵和标签列表# 将特征值归一化
def autonorm(dataset):minvalue = dataset.min(0)  # 每列的最小值maxvalue = dataset.max(0)  # 每列的最大值ranges = maxvalue - minvaluenormdataset = zeros(shape(dataset))  # 数据集大小的0矩阵m = dataset.shape[0]  # 数据集行数normdataset = dataset - tile(minvalue, (m, 1))  # 数据集-m行的3列最小值normdataset = normdataset / tile(ranges, (m, 1))  # 数据集-m行的3列最大值return normdataset, ranges, minvalue  # 返回归一化之后的数据def showdatas(datingDataMat, datingLabels):# 设置汉字格式font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)# 将fig画布分隔成1行1列,不共享x轴和y轴,fig画布的大小为(13,8)# 当nrow=2,nclos=2时,代表fig画布被分为四个区域,axs[0][0]表示第一行第一个区域fig, axs = plt.subplots(nrows=2, ncols=2, sharex=False, sharey=False, figsize=(13, 8))numberOfLabels = len(datingLabels)LabelsColors = []for i in datingLabels:if i == 1:LabelsColors.append('black')if i == 2:LabelsColors.append('orange')if i == 3:LabelsColors.append('red')# 画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第二列(玩游戏)数据画散点数据,散点大小为15,透明度为0.5axs[0][0].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 1], color=LabelsColors, s=15, alpha=.5)# 设置标题,x轴label,y轴labelaxs0_title_text = axs[0][0].set_title(u'每年获得的飞行常客里程数与玩视频游戏所消耗时间占比', FontProperties=font)axs0_xlabel_text = axs[0][0].set_xlabel(u'每年获得的飞行常客里程数', FontProperties=font)axs0_ylabel_text = axs[0][0].set_ylabel(u'玩视频游戏所消耗时间占', FontProperties=font)plt.setp(axs0_title_text, size=9, weight='bold', color='red')plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black')# 画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5axs[0][1].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 2], color=LabelsColors, s=15, alpha=.5)# 设置标题,x轴label,y轴labelaxs1_title_text = axs[0][1].set_title(u'每年获得的飞行常客里程数与每周消费的冰激淋公升数', FontProperties=font)axs1_xlabel_text = axs[0][1].set_xlabel(u'每年获得的飞行常客里程数', FontProperties=font)axs1_ylabel_text = axs[0][1].set_ylabel(u'每周消费的冰激淋公升数', FontProperties=font)plt.setp(axs1_title_text, size=9, weight='bold', color='red')plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black')# 画出散点图,以datingDataMat矩阵的第二(玩游戏)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5axs[1][0].scatter(x=datingDataMat[:, 1], y=datingDataMat[:, 2], color=LabelsColors, s=15, alpha=.5)# 设置标题,x轴label,y轴labelaxs2_title_text = axs[1][0].set_title(u'玩视频游戏所消耗时间占比与每周消费的冰激淋公升数', FontProperties=font)axs2_xlabel_text = axs[1][0].set_xlabel(u'玩视频游戏所消耗时间占比', FontProperties=font)axs2_ylabel_text = axs[1][0].set_ylabel(u'每周消费的冰激淋公升数', FontProperties=font)plt.setp(axs2_title_text, size=9, weight='bold', color='red')plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black')# 设置图例didntLike = mlines.Line2D([], [], color='black', marker='.',markersize=6, label='didntLike')smallDoses = mlines.Line2D([], [], color='orange', marker='.',markersize=6, label='smallDoses')largeDoses = mlines.Line2D([], [], color='red', marker='.',markersize=6, label='largeDoses')# 添加图例axs[0][0].legend(handles=[didntLike, smallDoses, largeDoses])axs[0][1].legend(handles=[didntLike, smallDoses, largeDoses])axs[1][0].legend(handles=[didntLike, smallDoses, largeDoses])# 显示图片plt.show()# 测试
def datingtest():horatio = 0.10datingdatamat, datinglabel = filematrix('datingTestSet2.txt')  # 打开文件,并把特征和标签都存到相应的矩阵和列表中showdatas(datingdatamat, datinglabel)normmat, ranges, minvalue = autonorm(datingdatamat)  # 得到归一化后的数据m = normmat.shape[0]  # 得到数据的行数numtestvecs = int(m * horatio)  # 得到10%的测试数据errorcount = 0  # 初始错误个数设为0for i in range(numtestvecs):classifierresult = classify0(normmat[i], normmat[numtestvecs:m, :], datinglabel[numtestvecs:m],3)  # 利用分类函数得到预测类别#print('the classifier came back with:', classifierresult, 'the real answer is:', datinglabel[i])if (classifierresult != datinglabel[i]):errorcount += 1  # 如果预测类别和真实类别不等的话,错误个数+1print('the error rate:', (errorcount / float(numtestvecs)))  # 输出错误率
#  使用算法
def classifyPerson():datingtest()resultList = ['不喜欢', '一般喜欢', '特别喜欢']percentTats = float(input("玩游戏占的百分比"))ffMiles = float(input("每年坐飞机多少公里"))iceCream = float(input("每年吃多少公升的冰激凌"))#  下面两行代码为数据的预处理  1、将文件读取,读出数据和标签  2、将数据归一化datingDataMat, datingLabels = filematrix('datingTestSet2.txt')normMat, ranges, minVals = autonorm(datingDataMat)inArr = array([ffMiles, percentTats, iceCream])classiferResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 3)print("你将有可能对这个人是:", resultList[int(classiferResult) - 1])classifyPerson()

5、使用sklearn实现

数据归一化和KNN预测使用sklearn实现
代码如下:

from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
from numpy import *
from sklearn.neighbors import KNeighborsClassifier as kNN
from sklearn.preprocessing import MinMaxScalerdef filematrix(filename):fr=open(filename)      #打开文件arrayoflines=fr.readlines()    #读取文件numberoflines=len(arrayoflines)     #得到文件的行数returnmat=zeros((numberoflines,3))      #returnmat是一个numberoflines行3列的0矩阵,用来存放featureclasslabelvector=[]        #设置一个空list来存labelindex=0for line in arrayoflines:     #一行一行读数据line=line.strip()     #截取所有回车字符     strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。listfromline=line.split('\t')    #将上一步得到的整行数据分割成一个列表returnmat[index,:]=listfromline[0:3]         #注意矩阵的索引和列表的索引    #1-3列是特征列,依次将特征存放到returnmat中#下面两行代码和下下面的代码。注意输出是数字还是字符串a = float(listfromline[-1])       # 列表转换为数字classlabelvector.append(a)     #最后一列也就是第4列是label列,存放到classlabelvector中index+=1return returnmat,classlabelvector    #返回特征矩阵和标签列表def showdatas(datingDataMat, datingLabels):#设置汉字格式font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)#将fig画布分隔成1行1列,不共享x轴和y轴,fig画布的大小为(13,8)#当nrow=2,nclos=2时,代表fig画布被分为四个区域,axs[0][0]表示第一行第一个区域fig, axs = plt.subplots(nrows=2, ncols=2,sharex=False, sharey=False, figsize=(13,8))numberOfLabels = len(datingLabels)LabelsColors = []for i in datingLabels:if i == 1:LabelsColors.append('black')if i == 2:LabelsColors.append('orange')if i == 3:LabelsColors.append('red')#画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第二列(玩游戏)数据画散点数据,散点大小为15,透明度为0.5axs[0][0].scatter(x=datingDataMat[:,0], y=datingDataMat[:,1], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs0_title_text = axs[0][0].set_title(u'每年获得的飞行常客里程数与玩视频游戏所消耗时间占比',FontProperties=font)axs0_xlabel_text = axs[0][0].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font)axs0_ylabel_text = axs[0][0].set_ylabel(u'玩视频游戏所消耗时间占',FontProperties=font)plt.setp(axs0_title_text, size=9, weight='bold', color='red')plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black')#画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5axs[0][1].scatter(x=datingDataMat[:,0], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs1_title_text = axs[0][1].set_title(u'每年获得的飞行常客里程数与每周消费的冰激淋公升数',FontProperties=font)axs1_xlabel_text = axs[0][1].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font)axs1_ylabel_text = axs[0][1].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font)plt.setp(axs1_title_text, size=9, weight='bold', color='red')plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black')#画出散点图,以datingDataMat矩阵的第二(玩游戏)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5axs[1][0].scatter(x=datingDataMat[:,1], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5)#设置标题,x轴label,y轴labelaxs2_title_text = axs[1][0].set_title(u'玩视频游戏所消耗时间占比与每周消费的冰激淋公升数',FontProperties=font)axs2_xlabel_text = axs[1][0].set_xlabel(u'玩视频游戏所消耗时间占比',FontProperties=font)axs2_ylabel_text = axs[1][0].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font)plt.setp(axs2_title_text, size=9, weight='bold', color='red')plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black')plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black')#设置图例didntLike = mlines.Line2D([], [], color='black', marker='.',markersize=6, label='didntLike')smallDoses = mlines.Line2D([], [], color='orange', marker='.',markersize=6, label='smallDoses')largeDoses = mlines.Line2D([], [], color='red', marker='.',markersize=6, label='largeDoses')#添加图例axs[0][0].legend(handles=[didntLike,smallDoses,largeDoses])axs[0][1].legend(handles=[didntLike,smallDoses,largeDoses])axs[1][0].legend(handles=[didntLike,smallDoses,largeDoses])#显示图片plt.show()#测试
def datingtest():horatio=0.10datingdatamat,datinglabel=filematrix('datingTestSet2.txt')  #打开文件,并把特征和标签都存到相应的矩阵和列表中showdatas(datingdatamat,datinglabel)#  进行数据最大最小归一化处理ss=MinMaxScaler()normmat=ss.fit_transform(datingdatamat)     #得到归一化后的数据m=normmat.shape[0]numtestvecs=int(m*horatio)           #得到10%的测试数据errorcount=0                         #初始错误个数设为0neigh = kNN(n_neighbors=3, algorithm='auto')neigh.fit(normmat[numtestvecs:m, :], datinglabel[numtestvecs:m])for i in range(numtestvecs):x_new = array(normmat[i]).reshape(1,-1)   #  进行neigh.predict前的测试数据处理reshape(1,-1)#print(normmat[i])print(x_new)classifierresult = neigh.predict(x_new)print('the classifier came back with:',classifierresult,'the real answer is:',datinglabel[i])if(classifierresult!=datinglabel[i]):errorcount+=1                                 #如果预测类别和真实类别不等的话,错误个数+1print('the error rate:',(errorcount/float(numtestvecs)))         #输出错误率
datingtest()

K近邻算法--约会网站配对相关推荐

  1. K近邻算法-约会网站配对实例

    背景 海伦女士一直使用在线约会网站寻找适合自己的约会对象.尽管约会网站会推荐不同的任选 但她并不是喜欢每一个人.经过一番总结,她发现自己交往过的人可以进行如下分类: (1)不喜欢的人 (2)魅力一般的 ...

  2. 模式识别和机器学习实战-K近邻算法(KNN)- Python实现 - 约会网站配对效果判断和手写数字识别

    文章目录 前言 一. k-近邻算法(KNN) 1.算法介绍 2.举个例子--电影分类 3.步骤描述 4.来了--代码实现 二.实战之约会网站配对效果判断 1.导入数据 2.分析数据 3.数据归一化 4 ...

  3. 【机器学习】机器学习从零到掌握之三 -- 教你使用K近邻算法改进约会网站

    本文是<机器学习从零到掌握>系列之第3篇 机器学习从零到掌握之一 -- 教你理解K近邻算法 机器学习从零到掌握之二 -- 教你实现K近邻算法 本篇使用的数据存放在文本文件datingTes ...

  4. 机器学习:K-近邻算法(二)约会网站配对效果

    目录 K-近邻算法实战(二):约会网站配对效果判断 实战 1.背景介绍 2.准备数据:数据分类 3.分析数据:数据可视化 4.准备数据:数据归一化 5.测试算法:验证分类器 6.使用算法:构建完整可用 ...

  5. 一文搞懂K近邻算法(KNN),附带多个实现案例

    简介:本文作者为 CSDN 博客作者董安勇,江苏泰州人,现就读于昆明理工大学电子与通信工程专业硕士,目前主要学习机器学习,深度学习以及大数据,主要使用python.Java编程语言.平时喜欢看书,打篮 ...

  6. 机器学习-分类之K近邻算法(KNN)原理及实战

    k近邻算法(KNN) 简介 KNN算法是数据挖掘分类技术中最简单的方法之一.它通过测量不同特征值之间的距离进行分类的.其基本思路为:如果一个样本在特征空间中的k个最近邻样本中的大多数属于某一个类别,则 ...

  7. 机器学习实战之K近邻算法

    k近邻算法概述 简单地说,K近邻算法采用测量不同特征值之间的距离方法进行分类. 优 点 :精度高.对异常值不敏感.无数据输入假定. 缺点:计算复杂度高.空间复杂度高. 适用数据范围:数值型和标称型. ...

  8. k近邻算法python解读_Python3《机器学习实战》学习笔记(一):k-近邻算法(史诗级干货长文)...

    运行平台: Windows IDE: Sublime text3 一.简单k-近邻算法 本文将从k-近邻 1.k-近邻法简介 k近邻法(k-nearest neighbor, k-NN)是1967年由 ...

  9. 《机器学习实战》——kNN(k近邻算法)

    原作者写的太好了,包括排版都特别整齐(其中有一个错误之处就是在约会网站配对效果判定的时候,列表顺序不对,导致结果有误,这里我已做出修改) 原作者和出处:http://blog.csdn.net/c40 ...

最新文章

  1. 深度学习 VS 传统计算机视觉
  2. python datetime模块
  3. 【linux排错】error while loading shared libraries: xxx.so.x 错误的原因和解决办法
  4. JavaUtil_00_资源帖
  5. 跨主机使用 Rex-Ray volume - 每天5分钟玩转 Docker 容器技术(77)
  6. jpa 自定义sql if_常用SQL语句大全总结
  7. 工业交换机和商用交换机对比
  8. C函数实现返回多个值的方法
  9. shell 中浮点数和整数的比较
  10. 跨年照片墙php源码,简单效果照片墙
  11. matebook14支持触摸屏吗_matebook 14有触屏吗
  12. 38. 重定向与负载均衡
  13. ACwing 829 模拟队列
  14. 计算机维护系统Win8PE,U盘启动计算机维护系统(Win8PEx64内核仅160M)
  15. 搜索计算机硬盘的索引恢复,如何修复Windows 10搜索索引 | MOS86
  16. 15家企业入选2020年中国最佳雇主榜单;《新形势下国企数字化转型之路》白皮书发布 | 美通企业日报...
  17. js 实现简单区块链
  18. 控制面板打印机显示不出来的解决办法
  19. vue 总结一项目建立及文件夹结构配置
  20. 计算机基础知识(基础入门小白专属)四

热门文章

  1. 软交换与硬交换的区别
  2. 3 个提高 Python 开发效率的小工具
  3. postman的RestClient引用库RestSharp
  4. 关于刘谦春晚魔术用托的一些想法
  5. 解决 网站404 Not Found 错误
  6. qt linux cpu id,Qt獲取CPU編號和硬盤序列號
  7. ADS1298学习笔记2——导联脱落检测正端和负端错位
  8. [Touch panel]Kernel-3.10上第五点触摸有问题如何解决?
  9. 支付宝收费惊呆小伙伴:都是微信给逼的
  10. 不到一百行python代码简单实现A星算法