以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 相关文章推荐
出现“不能执行已释放的Script代码”错误的原因及解决办法
Aug 29 Javascript
扩展JavaScript功能的正确方法(译文)
Apr 12 Javascript
js键盘事件的keyCode
Jul 29 Javascript
js选项卡的制作方法
Jan 23 Javascript
nuxt+axios解决前后端分离SSR的示例代码
Oct 24 Javascript
JavaScript实现的简单Tab点击切换功能示例
Jul 06 Javascript
webstorm中配置Eslint的两种方式及差异比较详解
Oct 19 Javascript
详解如何在vscode里面调试js和node.js的方法步骤
Dec 24 Javascript
vue项目中使用AES实现密码加密解密(ECB和CBC两种模式)
Aug 12 Javascript
微信小程序 点击切换样式scroll-view实现代码实例
Oct 11 Javascript
JavaScript中的惰性载入函数及优势
Feb 18 Javascript
vue 给数组添加新对象并赋值
Apr 20 Vue.js
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数组最大值,最小值的代码
2011/10/31 PHP
PHP return语句另类用法不止是在函数中
2014/09/17 PHP
Laravel学习教程之model validation的使用示例
2017/10/23 PHP
PHP实现的策略模式示例
2019/03/20 PHP
Laravel服务容器绑定的几种方法总结
2020/06/14 PHP
用JavaScript实现单继承和多继承的简单方法
2009/03/29 Javascript
jQuery中DOM树操作之使用反向插入方法实例分析
2015/01/23 Javascript
jQuery实现二级下拉菜单效果
2016/01/05 Javascript
浅谈jquery点击label触发2次的问题
2016/06/12 Javascript
JS基于递归实现倒计时效果的方法
2016/11/26 Javascript
微信小程序 页面跳转传递值几种方法详解
2017/01/12 Javascript
JS实现table表格固定表头且表头随横向滚动而滚动
2017/10/26 Javascript
微信小程序中上传图片并进行压缩的实现代码
2018/08/28 Javascript
微信小程序文章详情页面实现代码
2018/09/10 Javascript
vue中的过滤器及其时间格式化问题
2020/04/09 Javascript
学习 Vue.js 遇到的那些坑
2021/02/02 Vue.js
Python的几个高级语法概念浅析(lambda表达式闭包装饰器)
2016/05/28 Python
Python遍历文件夹和读写文件的实现代码
2016/08/28 Python
Python使用requests提交HTTP表单的方法
2018/12/26 Python
Linux上使用Python统计每天的键盘输入次数
2019/04/17 Python
python-pyinstaller、打包后获取路径的实例
2019/06/10 Python
python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例
2020/03/08 Python
阿里旅行:飞猪
2017/01/05 全球购物
Europcar意大利:汽车租赁
2019/07/07 全球购物
LORAC官网:美国彩妆品牌
2019/08/27 全球购物
我的五年职业生涯规划
2014/01/23 职场文书
料理师求职信
2014/01/30 职场文书
生产文员岗位职责
2014/04/05 职场文书
简单租房协议书范本
2014/08/20 职场文书
承诺书怎么写 ?
2019/04/16 职场文书
导游词之河北邯郸
2019/09/12 职场文书
导游词之烟台威海蓬莱
2019/11/14 职场文书
话题作文之诚信
2019/11/28 职场文书
spring boot项目application.properties文件存放及使用介绍
2021/06/30 Java/Android
Tomcat用户管理的优化配置详解
2022/03/31 Servers
HTML5页面打开微信小程序功能实现
2022/09/23 HTML / CSS