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


猜你喜欢
- 问题描述MySQL 启动成功,使用 ps -ef |grep mysql 可以看到进程,如下图:也可以在服务器登陆,如下图:但是使用 net
- import socketimport Queueimport threadingdef worker(): &nbs
- 不管学习什么编程语言一开始都会经历的四步开发工具安装IDE安装设置 依赖/包 国内镜像项目构建工具,管理依赖/包一、Golang 开发工具安
- 为何选Nuxt.js?在前后端分离出现之前,传统的web页面都是服务端渲染的,如JSP、PHP、Python Django,还有各种模板技术
- 上次学会了爬取图片,这次就想着试试爬取商家的联系电话,当然,这里纯属个人技术学习,爬取过后及时删除,不得用于其它违法用途,一切后果自负。首先
- 程序说明:本程序实现将开发程序服务器中的打包文件通过该脚本上传到正式生产环境(注:生产环境和开发环境不互通)程序基本思路:将开发环境中的程序
- 前言在实际应用中经常会用到固定字段的长度,但往往有些数据不能达到规定的长度,这是就需要我们用其他的字符来填充, 在Oracle中有函数解决这
- 一、new做了哪些事先看看new的使用场景:// 1、创建一个构造函数function Vehicle(name, price) { &nb
- 当我们使用访问一个没有声明的变量时,JS会报错;而当我们给一个没有声明的变量赋值时,JS不会报错误,相反它会认为我们是要隐式申明一个全局变量
- 一、简介shutil是 python 中的高级文件操作模块,与os模块形成互补的关系,os主要提供了文件或文件夹的新建、删除、查看等方法,还
- 1.webpack里面配置自动注册组件第一个参数是匹配路径,第二个是深度匹配,第三个是匹配规则const requireComponent
- Oracle的执行计划一句话命令:set autotrace on
- 以下代码是保存视频# coding:utf-8import cv2import sysreload(sys)sys.setdefaulten
- 本文实例讲述了Python使用pyautogui模块实现自动化鼠标和键盘操作。分享给大家供大家参考,具体如下:一、pyautogui模块简要
- 模块:包含定义函数和变量的python文件,可以被别的程序引入。os模块是操作系统接口模块,提供了一些方便使用操作系统相关功能函数,这里介绍
- 在使用Python绘制图表前,我们需要先安装两个库文件numpy和matplotlib。Numpy是Python开源的数值计算扩展,可用来存
- eval是Python的一个内置函数,功能十分强大,这个函数的作用是,返回传入字符串的表达式的结果。就是说:将字符串当成有效的表达式 来求值
- Python中的array模块是一个预定义的数组,因此其在内存中占用的空间比标准列表小得多,同时也可以执行快速的元素级别操作,例如添加、删除
- 前言 网传的七天学Python的路线如下,我觉得可以在学过此表中前几天的内容后,就可以回头来学习一下列表推导式:它综合了列表、fo
- 用asp程序进行网页设计,大多因为需要访问数据库,然后再将数据显示到页面,如果数据很多的话,页面的访问速度也就变慢了,为了解决这个问题,可以