以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 相关文章推荐
js 加载时自动调整图片大小
May 28 Javascript
JavaScript数据库TaffyDB用法实例分析
Jul 27 Javascript
微信小程序  Mustache语法详细介绍
Oct 27 Javascript
Bootstrap导航条的使用和理解3
Dec 14 Javascript
jQuery加载及解析XML文件的方法实例分析
Jan 22 Javascript
JavaScript数据结构之二叉树的遍历算法示例
Apr 13 Javascript
浅谈angular.copy() 深拷贝
Sep 14 Javascript
改变vue请求过来的数据中的某一项值的方法(详解)
Mar 08 Javascript
详解如何快速配置webpack多入口脚手架
Dec 28 Javascript
Vue.js实现的购物车功能详解
Jan 27 Javascript
详解Vscode中使用Eslint终极配置大全
Nov 08 Javascript
vue实现单一筛选、删除筛选条件
Oct 26 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实现像JSP,ASP里Application那样的全局变量
2007/01/12 PHP
PHP 5.3和PHP 5.4出现FastCGI Error解决方法
2015/02/12 PHP
老生常谈PHP 文件写入和读取(必看篇)
2017/05/22 PHP
javascript之对系统的toFixed()方法的修正
2007/05/08 Javascript
用JTrackBar实现的模拟苹果风格的滚动条
2007/08/06 Javascript
jquery随机展示头像代码
2011/12/21 Javascript
js 控制下拉菜单刷新的方法
2013/03/03 Javascript
让新消息在网页标题闪烁提示的jQuery代码
2013/11/04 Javascript
setTimeout()递归调用不加引号出错的解决方法
2014/09/05 Javascript
AngularJS入门教程(二):AngularJS模板
2014/12/06 Javascript
jQuery中:lt选择器用法实例
2014/12/29 Javascript
jquery实现可横向和竖向展开的动态下滑菜单效果
2015/08/24 Javascript
js实现返回顶部效果
2017/03/10 Javascript
Vue2.0如何发布项目实战
2017/07/27 Javascript
Angular4学习笔记之根模块与Ng模块
2017/09/09 Javascript
vue全局使用axios的方法实例详解
2018/11/22 Javascript
Python爬取Coursera课程资源的详细过程
2014/11/04 Python
深入Python解释器理解Python中的字节码
2015/04/01 Python
通过Python来使用七牛云存储的方法详解
2015/08/07 Python
简单讲解Python中的数字类型及基本的数学计算
2016/03/11 Python
对pandas处理json数据的方法详解
2019/02/08 Python
Django网络框架之HelloDjango项目创建教程
2019/06/06 Python
win10下python2和python3共存问题解决方法
2019/12/23 Python
Django单元测试中Fixtures用法详解
2020/02/25 Python
html5 canvas简单封装一个echarts实现不了的饼图
2018/06/12 HTML / CSS
HTML5获取当前地理位置并在百度地图上展示的实例
2020/07/10 HTML / CSS
空字符串(“”)和null的区别
2012/11/13 面试题
2019年c语言经典面试题目
2016/08/17 面试题
木马的传播途径主要有哪些
2016/04/08 面试题
一套中级Java程序员笔试题
2015/01/14 面试题
求职信需要的五点内容
2014/02/01 职场文书
运动会跳远加油稿
2014/02/20 职场文书
2014年四风个人对照检查及整改措施
2014/10/28 职场文书
sql中mod()函数取余数的用法
2021/05/29 SQL Server
分位数回归模型quantile regeression应用详解及示例教程
2021/11/02 Python
nginx静态资源的服务器配置方法
2022/07/07 Servers