以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的高性能td和input切换并可修改内容实现代码
Jan 09 Javascript
javascript结合ajax读取txt文件内容
Dec 05 Javascript
浅谈JavaScript Date日期和时间对象
Dec 29 Javascript
jQuery创建DOM元素实例解析
Jan 19 Javascript
JavaScript中闭包的写法和作用详解
Jun 29 Javascript
详解Javascript几种跨域方式总结
Feb 27 Javascript
ES6使用let命令更简单的实现块级作用域实例分析
Mar 31 Javascript
three.js实现圆柱体
Dec 30 Javascript
说说如何使用Vuex进行状态管理(小结)
Apr 14 Javascript
原生js实现的移动端可拖动进度条插件功能详解
Aug 15 Javascript
在Vue.js中使用TypeScript的方法
Mar 19 Javascript
vue项目实现多语言切换的思路
Sep 17 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与MySQL开发的8个技巧小结
2010/12/17 PHP
在Mac OS下搭建LNMP开发环境的步骤详解
2017/03/10 PHP
PHP简单实现模拟登陆功能示例
2017/09/15 PHP
javascript 数据类型转换(parseInt,parseFloat)
2010/07/20 Javascript
javascript中的float运算精度实例分析
2010/08/21 Javascript
jquery随机展示头像代码
2011/12/21 Javascript
JS打印gridview实现原理及代码
2013/02/05 Javascript
js固定DIV高度,超出部分自动添加滚动条的简单方法
2013/07/10 Javascript
jquery、js操作checkbox全选反选
2014/03/12 Javascript
开源的javascript项目Kissy介绍
2014/11/28 Javascript
浅谈javascript中this在事件中的应用
2015/02/15 Javascript
JavaScript中操作字符串之localeCompare()方法的使用
2015/06/06 Javascript
AngularJs directive详解及示例代码
2016/09/01 Javascript
快速掌握jQuery插件开发
2017/01/19 Javascript
vue中实现滚动加载更多的示例
2017/11/08 Javascript
实例详解Node.js 函数
2018/06/10 Javascript
Vue实现双向绑定的原理以及响应式数据的方法
2018/07/02 Javascript
jQuery实现经典的网页3D轮播图封装功能【附源码下载】
2019/02/15 jQuery
vue-router二级导航切换路由及高亮显示的实现方法
2019/07/10 Javascript
javascript实现动态时钟的启动和停止
2020/07/29 Javascript
打包发布Python模块的方法详解
2016/09/18 Python
python实现爬山算法的思路详解
2019/04/09 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
Python爬虫:Request Payload和Form Data的简单区别说明
2020/04/30 Python
Django-simple-captcha验证码包使用方法详解
2020/11/28 Python
CSS3的column-fill属性对齐列内容高度的用法详解
2016/07/01 HTML / CSS
Pamela Love官网:纽约设计师Pamela Love的精美、时尚和穿孔珠宝
2020/10/19 全球购物
医学类个人求职信范文
2014/02/05 职场文书
团支部推优材料
2014/05/21 职场文书
学校消防安全责任书
2014/07/23 职场文书
学校元旦晚会开场白
2014/12/14 职场文书
天坛导游词
2015/02/02 职场文书
2015年教师师德师风承诺书
2015/04/28 职场文书
傲慢与偏见读书笔记
2015/06/29 职场文书
基于Python实现的购物商城管理系统
2021/04/27 Python
Python中for后接else的语法使用
2021/05/18 Python