k-近邻算法1(kNN)使用kNN算法改进约会网站的配对效果
最近边看NG老师的机器学习课程和西瓜书,无奈交织着各种数学推导,有些晦涩难懂,看到网上推荐了《machine learning in action》比较适合新手入门,
书中数据和源码在此 http://pan.baidu.com/s/1miIcMPM
书中也有代码实现。便开始混着看。顺便学一下python。这是廖雪峰老师的课程网站 https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
首先是第二章 k-近邻算法 (k-Nearest Neighbor 土话就是k个最近的邻居)
简单的说,k-近邻算法采用测量不同特征值之间的距离方法进行分类,注:本文参考了https://www.cnblogs.com/xiaoyesoso/p/5208079.html的内容,侵删
主要有5个步骤
(1)计算已知类别数据集中的点与当前点之间的距离
(2)按照距离递增次序排序
(3)选取与当前点距离最小的k个点
(4)确定前k个点所在类别的出现频率
(5)返回前k个点出现频率最高的类别作为当前点的预测分类
示例代码
from numpy import * import operatordef createDataSet():group = array([[1.0, 1.1], [1.0, 1.], [0, 0.], [0, 0.1]])labels = ['A', 'A', 'B', 'B']return group, labelsdef classify0(inX, dataSet, labels, k):dataSetSize = dataSet.shape[0]#1距离计算diffMat = tile(inX, (dataSetSize, 1)) - dataSetsqDiffMat = diffMat ** 2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances ** 0.5sortedDistIndicies = distances.argsort()#2选择距离最小的k个点classCount = {}for i in range(k):voteIlabel = labels[sortedDistIndicies[i]]classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1#3排序sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)return sortedClassCount[0][0]
注意点:
(1)tile函数说明 代码来源 http://blog.csdn.net/ksearch/article/details/21388985
>>> import numpy >>> numpy.tile([0,0],5)#在列方向上重复[0,0]5次,默认行1次 array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) >>> numpy.tile([0,0],(1,1))#在列方向上重复[0,0]1次,行1次 array([[0, 0]]) >>> numpy.tile([0,0],(2,1))#在列方向上重复[0,0]1次,行2次 array([[0, 0], [0, 0]]) >>> numpy.tile([0,0],(3,1)) array([[0, 0], [0, 0], [0, 0]]) >>> numpy.tile([0,0],(1,3))#在列方向上重复[0,0]3次,行1次 array([[0, 0, 0, 0, 0, 0]]) >>> numpy.tile([0,0],(2,3))<span style="font-family: Arial, Helvetica, sans-serif;">#在列方向上重复[0,0]3次,行2次</span> array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]])
tileDetails.py
简单说就是tile([a,b],(x,y)) 把矩阵[a,b]在行方向重复x次,在列方向重复y次
(2)sum函数说明 代码来源 http://blog.csdn.net/ikerpeng/article/details/17026011
1.python的sum
>>> sum([0,1,2]) 3 >>> sum([0,1,2],3) 6 >>> sum([0,1,2],[3,2,1]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "int") to list
pythonSum
2.numpy的sum
>>> import numpy as np >>> a=np.sum([[0,1,2],[2,1,3]]) >>> a 9 >>> a.shape () >>> a=np.sum([[0,1,2],[2,1,3]],axis=0) >>> a array([2, 2, 5]) >>> a.shape (3,) >>> a=np.sum([[0,1,2],[2,1,3]],axis=1) >>> a array([3, 6]) >>> a.shape (2,)
numpuSum
所以上面的axis=1就是按行相加
函数的前五行即算出了输出点和样本集的欧氏距离
(3)argsort函数说明 好吧,我又要引用了,来源 https://www.zhihu.com/question/24029886/answer/26444149
所以就能选择到前k个距离最近的点。我比较笨。。想了一会儿才明白
(4)sorted函数 继续引用..
来源 https://www.cnblogs.com/xiaoyesoso/p/5208079.html
https://www.cnblogs.com/sysu-blackbear/p/3283993.html
这里我第一个参数用的是classCount.items()。而书上用的是classCount.iteritems()。因为前者py3后者py2。所以上面的代码只要改这个地方就可以在2下运行。
详情见 http://www.runoob.com/python/att-dictionary-items.html Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组。
所以上面最后是将字典分解为元组列表,然后按照第二个元素的次序对元组进行逆序排序,最后返回发生频率最高的元素标签。
测试一下
然而这并没有什么卵用,下面继续。
Demo:使用kNN算法改进约会网站的配对效果
(1)准备数据:从文本文件中解析数据
文本文件下载地址 https://pan.baidu.com/s/1o8BSXWu
def file2matrix(filename):fr = open(filename)arrayOLines = fr.readlines()#得到文件行数numberOfLines = len(arrayOLines)#创建以0填充的矩阵returnMat = zeros((numberOfLines, 3))classLabelVector = []index = 0for line in arrayOLines:#截取掉所有回车字符line = line.strip()#将整行数据分割成一个元素列表listFromLine = line.split('\t')returnMat[index, :] = listFromLine[0:3]classLabelVector.append(int(listFromLine[-1]))index += 1return returnMat, classLabelVector
测试一下
(2)分析数据:使用Matplotlib创建散点图(在命令行中或main函数)
import matplotlibimport matplotlib.pyplot as pltfig = plt.figure() # figure创建一个绘图对象ax = fig.add_subplot(111) # 若参数为349,意思是:将画布分割成3行4列,图像画在从左到右从上到下的第9块,datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2])plt.show()
散点图使用datingDataMat矩阵的第二、三列数据,分别表示特征值“玩视频游戏所耗时间百分比”和“每周所消耗的冰淇淋公升数”。
可以用色彩或者其他的几号来标记不同样本分类,以便更好的理解数据信息。
改进如下
import matplotlibimport matplotlib.pyplot as pltfig = plt.figure() # figure创建一个绘图对象ax = fig.add_subplot(111) # 若参数为349,意思是:将画布分割成3行4列,图像画在从左到右从上到下的第9块,datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')'''matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o', cmap=None,norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, hold=None,**kwargs)其中,xy是点的坐标,s是点的大小maker是形状可以maker=(5,1)5表示形状是5边型,1表示是星型(0表示多边形,2放射型,3圆形)alpha表示透明度;facecolor=‘none’表示不填充。'''# ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2])# 设置字体防止中文乱码zhfont = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\STXINGKA.TTF')plt.xlabel('玩视频游戏所耗时间百分比', fontproperties=zhfont)plt.ylabel('每周消费的冰淇淋公升数', fontproperties=zhfont)ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2],15.0 * array(datingLabels), 15.0 * array(datingLabels))plt.show()
其中设置字体的说明可以参照 https://www.cnblogs.com/nolonely/p/6944150.html 和 http://blog.csdn.net/u012705410/article/details/47379957
scatter函数使用说明可以参照 https://www.cnblogs.com/shanlizi/p/6850318.html
效果图
基本上可以看到数据点所属三个样本分类的区域轮廓,但是用矩阵的第一第二列属性可以得到更好的展示效果。
emmmm。。。这里画图例又参照了
https://www.zhihu.com/question/37146648
https://www.zhihu.com/question/37146648/answer/80425957
def draw():fig = plt.figure() # figure创建一个绘图对象ax = fig.add_subplot(111) # 若参数为349,意思是:将画布分割成3行4列,图像画在从左到右从上到下的第9块,datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')type1_x = []type1_y = []type2_x = []type2_y = []type3_x = []type3_y = []for i in range(len(datingLabels)):if datingLabels[i] == 1: # 不喜欢 type1_x.append(datingDataMat[i][0])type1_y.append(datingDataMat[i][1])if datingLabels[i] == 2: # 魅力一般 type2_x.append(datingDataMat[i][0])type2_y.append(datingDataMat[i][1])if datingLabels[i] == 3: # 极具魅力 type3_x.append(datingDataMat[i][0])type3_y.append(datingDataMat[i][1])type1 = ax.scatter(type1_x, type1_y, s=20, c='red')type2 = ax.scatter(type2_x, type2_y, s=30, c='green')type3 = ax.scatter(type3_x, type3_y, s=40, c='blue')# 设置字体防止中文乱码zhfont = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\STXINGKA.TTF')plt.xlabel('每年获取的飞行常客里程数', fontproperties=zhfont)plt.ylabel('玩视频游戏所耗时间百分比', fontproperties=zhfont)ax.legend((type1, type2, type3), (u'不喜欢', u'魅力一般', u'极具魅力'), loc=2, prop=zhfont)plt.show()
(3)准备数据:归一化数值
写了这么长,然而我们的重点刚要开始...真是一篇又臭又长各种引用的博客
我们发现,欧式距离方程中,数字差值最大的属性对计算结果的影响最大,即每年获取的飞行常客里程数对于计算结果的影响将远远大于其他两个特征。
然而这仅仅是因为此特征值远大于其他特征值,不应该如此严重的影响到计算结果。(这里假设三个特征同等重要)
在处理不同取值范围的特征值时,采用数值归一化,如将取值范围处理为0-到1或-1到1。
下面的公式可以将任意取值范围的特征值转化为0到1区间内的值:
newValue=(oldValue-min)/(max-min)
实现函数如下
# newValue=(oldValue-min)/(max-min) def autoNorm(dataSet):# 参数0使得函数可以从列中选取最小值minVals = dataSet.min(0)maxVals = dataSet.max(0)ranges = maxVals - minValsnormDataSet = zeros(shape(dataSet))m = dataSet.shape[0]normDataSet = dataSet - tile(minVals, (m, 1))normDataSet = normDataSet / tile(ranges, (m, 1))return normDataSet, ranges, minVals
(4)测试算法:作为完整程序验证分类器
def datingClassTest():#测试数据所占的比例hoRatio = 0.1datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')normMat, ranges, minVals = autoNorm(datingDataMat)# 矩阵第一维大小m = normMat.shape[0]# 测试向量的数量numTestVecs = int(m * hoRatio)errorCount = 0.0for 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.0print("the total error rate is: %f" % (errorCount / float(numTestVecs)))
测试结果
(5)使用算法:构建完整可用系统
def classifyPerson():resultList = ['not at all', 'in small doses', 'in large doses']percentTats = float(input("percentage of time spent playing video games?"))ffMiles = float(input("frequent flier miles earned per year?"))iceCream = float(input("liters of ice cream consumed per year?"))datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')normMat, ranges, minVals = autoNorm(datingDataMat)inArr = array([ffMiles, percentTats, iceCream])classifierResult = classify0(inArr, datingDataMat, datingLabels, 3)print("You will probably like this person: ", resultList[classifierResult - 1])
注:python3中 raw_input() 变成了 input()
emmmmmm....运行结果如下
完整代码如下
#!usr/bin/env python3 # -*-coding:utf-8 -*-from numpy import * import operator import matplotlib import matplotlib.pyplot as pltdef createDataSet():group = array([[1.0, 1.1], [1.0, 1.], [0, 0.], [0, 0.1]])labels = ['A', 'A', 'B', 'B']return group, labelsdef classify0(inX, dataSet, labels, k):dataSetSize = dataSet.shape[0]# 1距离计算diffMat = tile(inX, (dataSetSize, 1)) - dataSetsqDiffMat = diffMat ** 2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances ** 0.5sortedDistIndicies = distances.argsort()# 2选择距离最小的k个点classCount = {}for i in range(k):voteIlabel = labels[sortedDistIndicies[i]]classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1# 3排序sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)return sortedClassCount[0][0]def file2matrix(filename):fr = open(filename)arrayOLines = fr.readlines()# 得到文件行数numberOfLines = len(arrayOLines)# 创建以0填充的矩阵returnMat = zeros((numberOfLines, 3))classLabelVector = []index = 0for line in arrayOLines:# 截取掉所有回车字符line = line.strip()# 将整行数据分割成一个元素列表listFromLine = line.split('\t')returnMat[index, :] = listFromLine[0:3]classLabelVector.append(int(listFromLine[-1]))index += 1return returnMat, classLabelVector# newValue=(oldValue-min)/(max-min) def autoNorm(dataSet):# 参数0使得函数可以从列中选取最小值minVals = dataSet.min(0)maxVals = dataSet.max(0)ranges = maxVals - minValsnormDataSet = zeros(shape(dataSet))m = dataSet.shape[0]normDataSet = dataSet - tile(minVals, (m, 1))normDataSet = normDataSet / tile(ranges, (m, 1))return normDataSet, ranges, minValsdef datingClassTest():# 测试数据所占的比例hoRatio = 0.1datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')normMat, ranges, minVals = autoNorm(datingDataMat)# 矩阵第一维大小m = normMat.shape[0]# 测试向量的数量numTestVecs = int(m * hoRatio)errorCount = 0.0for 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.0print("the total error rate is: %f" % (errorCount / float(numTestVecs)))def classifyPerson():resultList = ['not at all', 'in small doses', 'in large doses']percentTats = float(input("percentage of time spent playing video games?"))ffMiles = float(input("frequent flier miles earned per year?"))iceCream = float(input("liters of ice cream consumed per year?"))datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')normMat, ranges, minVals = autoNorm(datingDataMat)inArr = array([ffMiles, percentTats, iceCream])classifierResult = classify0(inArr, datingDataMat, datingLabels, 3)print("You will probably like this person: ", resultList[classifierResult - 1])def draw():fig = plt.figure() # figure创建一个绘图对象ax = fig.add_subplot(111) # 若参数为349,意思是:将画布分割成3行4列,图像画在从左到右从上到下的第9块,datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')'''matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o', cmap=None,norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, hold=None,**kwargs)其中,xy是点的坐标,s是点的大小maker是形状可以maker=(5,1)5表示形状是5边型,1表示是星型(0表示多边形,2放射型,3圆形)alpha表示透明度;facecolor=‘none’表示不填充。'''type1_x = []type1_y = []type2_x = []type2_y = []type3_x = []type3_y = []for i in range(len(datingLabels)):if datingLabels[i] == 1: # 不喜欢 type1_x.append(datingDataMat[i][0])type1_y.append(datingDataMat[i][1])if datingLabels[i] == 2: # 魅力一般 type2_x.append(datingDataMat[i][0])type2_y.append(datingDataMat[i][1])if datingLabels[i] == 3: # 极具魅力 type3_x.append(datingDataMat[i][0])type3_y.append(datingDataMat[i][1])type1 = ax.scatter(type1_x, type1_y, s=20, c='red')type2 = ax.scatter(type2_x, type2_y, s=30, c='green')type3 = ax.scatter(type3_x, type3_y, s=40, c='blue')# ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2])# 设置字体防止中文乱码zhfont = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\STXINGKA.TTF')plt.xlabel('每年获取的飞行常客里程数', fontproperties=zhfont)plt.ylabel('玩视频游戏所耗时间百分比', fontproperties=zhfont)# ax.scatter(datingDataMat[:, 0], datingDataMat[:, 1],# 15.0 * array(datingLabels), 15.0 * array(datingLabels))ax.legend((type1, type2, type3), (u'不喜欢', u'魅力一般', u'极具魅力'), loc=2, prop=zhfont)plt.show()if __name__ == "__main__":classifyPerson()
转载于:https://www.cnblogs.com/wangkaipeng/p/7872516.html
k-近邻算法1(kNN)使用kNN算法改进约会网站的配对效果相关推荐
- 使用k-近邻算法改进约会网站的配对效果
2.2 使用k-近邻算法改进约会网站的配对效果 Helen交往过三种类型的人: 不喜欢的人 魅力一般的人 极具魅力的人 示例:在约会网站上使用k-近邻算法 (1)收集数据:提供文本文件: dating ...
- 【机器学习实战】k-近邻算法案例——改进约会网站的配对效果
上一篇:k-近邻算法实战概述 文章目录 背景: 步骤: 准备数据:从文本文件中解析数据 分析数据:使用Matplotlib创建散点图 准备数据:归一化数值 测试算法:作为完整程序验证分类器 使用算法: ...
- k-近邻算法-优化约会网站的配对效果
KNN原理 1. 假设有一个带有标签的样本数据集(训练样本集),其中包含每条数据与所属分类的对应关系. 2. 输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较. a. 计算新 ...
- 机器学习实战2.2. k-近邻算法例子-优化约会网站的配对效果
k-近邻算法例子-优化约会网站的配对效果 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多机器学习干货 csdn:https://blog.csdn.net/baidu_ ...
- K近邻(k-Nearest Neighbor,KNN)算法,一种基于实例的学习方法
1. 基于实例的学习算法 0x1:数据挖掘的一些相关知识脉络 本文是一篇介绍K近邻数据挖掘算法的文章,而所谓数据挖掘,就是讨论如何在数据中寻找模式的一门学科. 其实人类的科学技术发展的历史,就一直伴随 ...
- 【机器学习实验二】k-NN算法—改进约会网站以及手写体数字识别
目录 一.改进约会网站 1.项目背景 2.数据收集 3.在约会网站中使用k-近邻算法的流程 4.代码实现 二.手写体数字识别 1.了解手写体数字识别 2.手写体数字识别思路 3.1.导入模块 3.2. ...
- KNN算法改进约会网站匹配效果
文章目录 实验 一.示例:KNN改进约会网站配对 二.实验过程 1.准备数据:从文本文件中解析数据 2.分析数据:使用Matplotlib创建散点图 3.准备数据:归一化数值 4.测试算法:作为完整程 ...
- 机器学习-监督学习之分类算法:K近邻法 (K-Nearest Neighbor,KNN)
目录 KNN概述 举个例子: K值选取 距离计算 曼哈顿距离,切比雪夫距离关系(相互转化) k-近邻(KNN)算法步骤 相关代码实现 简单实例:判断电影类别 创建数据集 数据可视化 分类测试 运行结果 ...
- K 近邻法(K-Nearest Neighbor, K-NN)
文章目录 1. k近邻算法 2. k近邻模型 2.1 模型 2.2 距离度量 2.2.1 距离计算代码 Python 2.3 kkk 值的选择 2.4 分类决策规则 3. 实现方法, kd树 3.1 ...
最新文章
- python类_python类和对象
- 牛客网 在线编程 局部最小值位置
- 《FPGA入门教程》看书随笔——RTL设计
- Android网络通信的六种方式示例代码
- 2016 - 2 - 20 ARC知识总结(二 autorelease概念及实现)
- MSSQLSERVER数据库- 配置数据库邮件配置的操作过程
- SpringMVC测试框架(转载)
- 正反向数据库及生成设计报告
- vba模拟鼠标点击_网页自动输入录入用阿冲全能点击王轻松完成
- Kettle 数据迁移
- zip 的ZipEntry转换为InputStream
- uni-app创建并运行微信小程序项目
- 定义复数java_java怎么定义复数?
- 计算机word加边框,Word2010怎样为段落加上边框
- Oracle创建用户与授予表空间与权限
- cocos creator2.3.5休闲游戏英文版(连连看)源码H5+安卓+IOS三端源码
- linux下几种目标文件的分析
- 很佩服的一个Google大佬,离职了。。
- php微信当面付,微信当面付(c#源码)
- llmp重启mysql_LNMP使用中mysql宕机挂掉后自动重启脚本 - 老牛博客