写在前面
分类是管理学、金融学、统计学等常用的实证分析方法之一,目前,分类的方法有逻辑回归、支持向量机、贝叶斯分类、决策树、支持向量机、卷积神经网络、线性判别分类器等等。
方法有很多,不同的方法适用于不同的环境,其难易度也不同。本文对k近邻算法进行实例分析,讲述在R语言中的建模过程与结果。
在开始建模前,首先说一下,为什么讲k近邻算法。
K最近邻(k-Nearest Neighbor,KNN)分类算法是最简单的机器学习算法之一,是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居), 这K个实例的多数属于某个类,就把该输入实例分类到这个类中。
说白话一点,就是“物以类聚”,所以在特征空间中,如果一个样本附近的k个最近(即特征空间中最邻近)样本的大多数属于某一个类别,则该样本也属于这个类别。
举一个现实生活中的例子:支付宝的芝麻信用分大家都有听过,里面有一项为人脉关系,人脉关系的分值越高,你的芝麻信用分越高。
那么人脉关系怎么衡量呢?
他们是通过你的通讯录中的人的信用历史、身份特质、财力、履约能力等来判断的,其实归根结底都是看通讯录中的人有没有钱。
在此过程中,秉持着的原则为“人以群分”,即他们有钱,所以你应该也不差。这个与kNN算法的思想是一致的。
对不起,我拖累了储存我手机号码的人的信用积分。但是,信息窃取与泄露这么猖狂的吗?谁给你授权使用我的通讯录了???
我们用张图片更形象的表述k近邻算法的思想,如上图所示:左中的黑点距离绿色三角和红色五角星的距离最近,且绿色三角形最多,所以大致上他应该也是一个绿色三角形。
正文
1、k近邻算法简介
k-近邻算法的一般流程:
(1)收集数据:可以来自于数据库、文件、网站采集等。
(2)准备数据:距离计算所需要的数值,最好是结构化的数据格式。
(3)分析数据:可以使用任何方法。
(4)训练算法:此步骤不适用于k-近部算法。
(5)测试算法:计算错误率。
(6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输 入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。
kNN算法最关键的地方在于k值的选取,k值指的就是未知样本近邻的个数。
1.1优点
1、简单,易于理解,易于实现,无需参数估计,无需训练;
2、精度高,对异常值不敏感(个别噪音数据对结果的影响不是很大);
3、适合对稀有事件进行分类;
4、特别适合于多分类问题(multi-modal,对象具有多个类别标签),KNN要比SVM表现要好;
5、无数据输入假定。
1.2缺点
1、对测试样本分类时的计算量大,空间开销大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本;
2、可解释性差,无法给出决策树那样的规则;
3、最大的缺点是当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。
该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进;
4、消极学习方法。
2、数据集介绍
1936年费希尔收集了三种鸢尾花(分别标记为setosa(山鸢尾)、versicolor(变色鸢尾)和virginica(维吉尼亚鸢尾))的花萼和花瓣数据。包括花萼的长度和宽度,以及花瓣的长度和宽度。改数据包为iris,共包含150条数据。
图2-1:从上到下依次为:山鸢尾、变色鸢尾和维吉尼亚鸢尾(资料来源:维基百科)
从照片来看,三者没有区别。但是内在是有区别的。
我们将根据这四个特征来建立支持向量机模型从而实现对鸢尾花的分类判别任务。如下图所示:iris数据集中更有三种品种的鸢尾,蓝色为山鸢尾、粉色为变色鸢尾,绿色为维吉尼亚鸢尾。
图2-2:iris数据集鸢尾花分类
3、代码运行
本文选取virginica(维吉尼亚鸢尾)作为评判,进行非维吉尼亚鸢尾(赋值为0)和维吉尼亚鸢尾(赋值为1)的判别分析。
3.1初始设置
set.seed(1)
data=iris
data$Species=as.factor(ifelse(data$Species=="virginica",1,0))#令data数据集里的Species那一列中的鸢尾类型变更为因子型0和1,其中0为其他类型,1为维吉尼亚鸢尾。
is = sample(1:150)#将1到150随机打乱。
z = data[is,]#将iris原本按分类排序的数据改为按照is里的顺序一一排序。
train= z[1:100,] #选取随机排序后数据的前100条作为训练集。
test= z[101:150,] #选取后50条数据作为测试集。
test.x= test[,1:4]#提取出测试集前四列的特征(花萼长、宽和花瓣的长、宽)作为预测时的输入。
test.y= test[,5]#提取测试集真实的分类结果。
library(class)#kNN算法需要class包来实现,所以需要加载class数据包。
K = 3#设定K值
ko = knn(train[,1:4],test.x[,1:4],train[,5],K)#选择kNN算法进行预测
(tb = table(ko, test.y))#输出2*2矩阵
test.y
ko 0 1
0 34 1
1 1 14
#通过上述结果可以看出,有两个数据预测出错了。
sum(diag(tb)) / sum(tb)
[1] 0.96
#kNN算法在k值取3的情况下,其对iris鸢尾类型的分类的准确度为96%。
Kmax = 10#做个循环试一下看看10以内的kNN算法,哪个k值得到的结果精确度最高
acc = numeric(Kmax)
for(k in 1:Kmax){
ko = knn(train[,1:4],test.x[,1:4],train[,5],k)
tb = table(ko,test.y)
acc[k] = sum(diag(tb)) / sum(tb)
}
plot(acc, pch=20, t='b', xlab='k')
图2-3:不同k值下,kNN算法在iris数据集分类的精确度
通过图2-3来看,当k值为4、8、9、10时,精确度最高,为98%,当k值为7时,精确度最低,只有94%。这只是针对iris数据集的分类结果,在其他数据集中,并不一定是这样。