以Python代码实例展示kNN算法的实际运用


Posted in Javascript onOctober 26, 2015

邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。
kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。
以Python代码实例展示kNN算法的实际运用

上图中,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。
K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成反比。

用 kNN 算法预测豆瓣电影用户的性别
摘要

本文认为不同性别的人偏好的电影类型会有所不同,因此进行了此实验。利用较为活跃的274位豆瓣用户最近观看的100部电影,对其类型进行统计,以得到的37种电影类型作为属性特征,以用户性别作为标签构建样本集。使用kNN算法构建豆瓣电影用户性别分类器,使用样本中的90%作为训练样本,10%作为测试样本,准确率可以达到81.48%。

实验数据

本次实验所用数据为豆瓣用户标记的看过的电影,选取了274位豆瓣用户最近看过的100部电影。对每个用户的电影类型进行统计。本次实验所用数据中共有37个电影类型,因此将这37个类型作为用户的属性特征,各特征的值即为用户100部电影中该类型电影的数量。用户的标签为其性别,由于豆瓣没有用户性别信息,因此均为人工标注。

数据格式如下所示:

X1,1,X1,2,X1,3,X1,4……X1,36,X1,37,Y1
X2,1,X2,2,X2,3,X2,4……X2,36,X2,37,Y2
…………
X274,1,X274,2,X274,3,X274,4……X274,36,X274,37,Y274

示例:

0,0,0,3,1,34,5,0,0,0,11,31,0,0,38,40,0,0,15,8,3,9,14,2,3,0,4,1,1,15,0,0,1,13,0,0,1,1 0,1,0,2,2,24,8,0,0,0,10,37,0,0,44,34,0,0,3,0,4,10,15,5,3,0,0,7,2,13,0,0,2,12,0,0,0,0

像这样的数据一共有274行,表示274个样本。每一个的前37个数据是该样本的37个特征值,最后一个数据为标签,即性别:0表示男性,1表示女性。

在此次试验中取样本的前10%作为测试样本,其余作为训练样本。

首先对所有数据归一化。对矩阵中的每一列求取最大值(max_j)、最小值(min_j),对矩阵中的数据X_j,
X_j=(X_j-min_j)/(max_j-min_j) 。

然后对于每一条测试样本,计算其与所有训练样本的欧氏距离。测试样本i与训练样本j之间的距离为:
distance_i_j=sqrt((Xi,1-Xj,1)^2+(Xi,2-Xj,2)^2+……+(Xi,37-Xj,37)^2) ,
对样本i的所有距离从小到大排序,在前k个中选择出现次数最多的标签,即为样本i的预测值。

实验结果

首先选择一个合适的k值。 对于k=1,3,5,7,均使用同一个测试样本和训练样本,测试其正确率,结果如下表所示。

选取不同k值的正确率表

以Python代码实例展示kNN算法的实际运用

由上述结果可知,在k=3时,测试的平均正确率最高,为74.07%,最高可以达到81.48%。

上述不同的测试集均来自同一样本集中,为随机选取所得。

Python代码

这段代码并非原创,来自《机器学习实战》(Peter Harrington,2013),并有所改动。

#coding:utf-8

from numpy import *
import operator

def classify0(inX, dataSet, labels, k):
  dataSetSize = dataSet.shape[0]
  diffMat = tile(inX, (dataSetSize,1)) - dataSet
  sqDiffMat = diffMat**2
  sqDistances = sqDiffMat.sum(axis=1)
  distances = sqDistances**0.5
  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)
  return sortedClassCount[0][0]

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))  #element wise divide
  return normDataSet, ranges, minVals

def file2matrix(filename):
  fr = open(filename)
  numberOfLines = len(fr.readlines())     #get the number of lines in the file
  returnMat = zeros((numberOfLines,37))    #prepare matrix to return
  classLabelVector = []            #prepare labels return  
  fr = open(filename)
  index = 0
  for line in fr.readlines():
    line = line.strip()
    listFromLine = line.split(',')
    returnMat[index,:] = listFromLine[0:37]
    classLabelVector.append(int(listFromLine[-1]))
    index += 1
  fr.close()
  return returnMat,classLabelVector

def genderClassTest():
  hoRatio = 0.10   #hold out 10%
  datingDataMat,datingLabels = file2matrix('doubanMovieDataSet.txt')    #load data setfrom file
  normMat,ranges,minVals=autoNorm(datingDataMat)
  m = normMat.shape[0]
  numTestVecs = int(m*hoRatio)
  testMat=normMat[0:numTestVecs,:]
  trainMat=normMat[numTestVecs:m,:]
  trainLabels=datingLabels[numTestVecs:m]
  k=3
  errorCount = 0.0
  for i in range(numTestVecs):
    classifierResult = classify0(testMat[i,:],trainMat,trainLabels,k)
    print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])
    if (classifierResult != datingLabels[i]):
      errorCount += 1.0
  print "Total errors:%d" %errorCount
  print "The total accuracy rate is %f" %(1.0-errorCount/float(numTestVecs))
Javascript 相关文章推荐
JQUERY CHECKBOX全选,取消全选,反选方法三
Aug 30 Javascript
情人节专属 纯js脚本1k大小的3D玫瑰效果
Feb 11 Javascript
用Jquery实现滚动新闻
Feb 12 Javascript
浅析webapp框架AngularUI的demo
Dec 21 Javascript
JavaScript实现简单获取当前网页网址的方法
Nov 09 Javascript
详解AngularJS中$http缓存以及处理多个$http请求的方法
Feb 06 Javascript
js+html5实现复制文字按钮
Jul 15 Javascript
jQuery获取复选框选中的当前行的某个字段的值
Sep 15 jQuery
用vue-cli开发vue时的代理设置方法
Sep 20 Javascript
微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)
Jul 25 Javascript
微信小程序动态评分展示/五角星展示/半颗星展示/自定义长度展示功能的实现
Jul 22 Javascript
Openlayers学习之地图比例尺控件
Sep 28 Javascript
Windows下用PyCharm和Visual Studio开始Python编程
Oct 26 #Javascript
php利用curl获取远程图片实现方法
Oct 26 #Javascript
jQuery.trim() 函数及trim()用法详解
Oct 26 #Javascript
JavaScript中的数据类型转换方法小结
Oct 26 #Javascript
如何实现JavaScript动态加载CSS和JS文件
Dec 28 #Javascript
基于javascript实现漂亮的页面过渡动画效果附源码下载
Oct 26 #Javascript
JS实现的页面自定义滚动条效果
Oct 26 #Javascript
You might like
php面向对象全攻略 (十) final static const关键字的使用
2009/09/30 PHP
PHP中获取文件扩展名的N种方法小结
2012/02/27 PHP
php使用socket调用http和smtp协议实例小结
2019/07/26 PHP
js资料toString 方法
2007/03/13 Javascript
jQuery隔行变色与普通JS写法的对比
2013/04/21 Javascript
json实现前后台的相互传值详解
2015/01/05 Javascript
JavaScript获取当前cpu使用率的方法
2015/12/15 Javascript
jQuery定义插件的方法
2015/12/18 Javascript
jQuery EasyUI基础教程之EasyUI常用组件(推荐)
2016/07/15 Javascript
jQuery实现产品对比功能附源码下载
2016/08/09 Javascript
最棒的Angular2表格控件
2016/08/10 Javascript
JS实现弹出下载对话框及常见文件类型的下载
2017/07/13 Javascript
CentOS环境中MySQL修改root密码方法
2018/01/07 Javascript
关于jquery中attr()和prop()方法的区别
2018/05/28 jQuery
全面解析vue router 基本使用(动态路由,嵌套路由)
2018/09/02 Javascript
Vue项目中最新用到的一些实用小技巧
2018/11/06 Javascript
JavaScript使用ul中li标签实现删除效果
2019/04/15 Javascript
使用easyui从servlet传递json数据到前端页面的两种方法
2019/09/05 Javascript
vue+element树组件 实现树懒加载的过程详解
2019/10/21 Javascript
ant design vue中日期选择框混合时间选择器的用法说明
2020/10/27 Javascript
[01:02:07]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
[01:06:54]DOTA2-DPC中国联赛 正赛 SAG vs DLG BO3 第二场 2月28日
2021/03/11 DOTA
windows系统中python使用rar命令压缩多个文件夹示例
2014/05/06 Python
python3 爬取图片的实例代码
2018/11/06 Python
在Python中表示一个对象的方法
2019/06/25 Python
python下载的库包存放路径
2020/07/27 Python
纯CSS改变webkit内核浏览器的滚动条样式
2014/04/17 HTML / CSS
西班牙拥有最佳品牌的动物商店:Animalear.com
2018/01/05 全球购物
Michael Kors澳大利亚官网:世界知名的奢侈饰品和成衣设计师
2020/02/13 全球购物
会计实习生工作总结的自我评价
2013/10/07 职场文书
骨干教师培训制度
2014/01/13 职场文书
企业安全生产责任书
2014/04/14 职场文书
充分就业社区汇报材料
2014/05/07 职场文书
萤火虫之墓观后感
2015/06/05 职场文书
如何写新闻稿
2015/07/18 职场文书
IDEA 2022 Translation 未知错误 翻译文档失败
2022/04/24 Java/Android