R语言与机器学习(1)K-近邻算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
K-近邻算法原理及举例
工作原理:我们知道样本集中每一个数据与所属分类的对应关系,输入没有标签的新数据后,将新数据与训练集的数据对应特征进行比较,找出“距离”最近的k(通常k<20)数据,选择这k个数据中出现最多的分类作为新数据的分类。
算法描述:
(1) 计算已知类别数据及中的点与当前点的距离;
(2) 按距离递增次序排序
(3) 选取与当前点距离最小的k个点
(4) 确定前K个点所在类别出现的频率
(5) 返回频率最高的类别作为当前类别的预测
这里我们使用最常见欧氏距离作为衡量标准,以鸢尾花数据集为例来说明K-近邻算法:鸢尾花数据集包含150个数据,测量变量为花瓣,花萼的长度与宽度,分类变量为setosa, versicolor, 和 virginica。
准备数据:
为了了解数据,我们先通过作图分析,相关分析来看看数据分类指标的合理性,这一点十分重要,有助于减少分类指标中的噪声。
从上图可以看出,我们通过这2个变量大致是可以把鸢尾花分类的,也就是说分类的特征变量选择是合理的,(同理可以分析另外2个,分类效果不如这两个,但大致上还是能区分的)当然我们也可以选择计算相关系数来看特征变量的合理性。
我们很容易发现,数值差最大的属性对距离的影响最大,所以在特征值等权重的假定下,我们先得归一化特征值,计算公式为:
Newvalue=(oldvalue-min)/(max-min)
R代码:
autonorm<-function(data){
for(iin 1:length(data))
data[i]<-(data[i]-min(data))/(max(data)-min(data))
return(data)
}
data<-as.matrix(apply(iris[,1:4],2,autonorm))
得到了归一化后的数据集,下面计算距离。我们在这里取三个数据作为验证集来看看分类的效果,首先将验证集归一化:
x<-iris[13,1:4]
y<-iris[79,1:4]
z<-iris[100,1:4]
x<-(x-apply(iris[c(-13,-79,-100),1:4],2,min))/(apply(iris[c(-13,-79,-100),1:4],2,max)-apply(iris[c(-13,-79,-100),1:4],2,min))
y<-(y-apply(iris[c(-13,-79,-100),1:4],2,min))/(apply(iris[c(-13,-79,-100),1:4],2,max)-apply(iris[c(-13,-79,-100),1:4],2,min))
z<-(z-apply(iris[c(-13,-79,-100),1:4],2,min))/(apply(iris[c(-13,-79,-100),1:4],2,max)-apply(iris[c(-13,-79,-100),1:4],2,min))
计算距离,仅以x为例,运行代码:(k取5)
dis<-rep(0,length(data[,1]))
for(iin 1:length(data[,1]))
dis[i]<-sqrt(sum((z-data[i,1:4])^2))
table(data[order(dis)[1:5],5])
x,y,z的输出结果为
标签xyyz
分类1233
频数5415
虽然对测试y出现了错误分类,但根据多数投票法x,y,z为setosa, versicolor, 和virginica,得到了正确分类结果。
值得一提的是,我们用同样的办法计算K=3时的情形,会发现没有出现误分类。这也就引出了一个值得思考的问题:k应该如何选取?k过小,噪声对分类的影响就会变得非常大,K过大,那么包含错误就理所当然,误分类也不足为奇。虽然这里我们对K的取值并未进行讨论,但在实际中,我们应该通过交叉验证的办法来确定k值。
R语言内置函数kknn简介
R语言里的kknn包也可以实现最邻近算法——使用kknn函数。
kknn(formula = formula(train),train, test, na.action = na.omit(),
k= 7, distance = 2, kernel = "optimal", ykernel = NULL, scale=TRUE, contrasts= c('unordered' = "contr.dummy", ordered ="contr.ordinal"))参数解释:
formula 一个回归模型,具体为:分类变量~特征变量
train 训练集
test 测试集
na.action 缺失值处理,默认为去掉缺失值
k k值选择,默认为7
distance 这个是明科夫斯基距离,p=2时为欧氏距离
其他参数略
上面的鸢尾花例子使用kknn包可以实现(k=5):
library(kknn)
data(iris)
m <- dim(iris)[1]
val <- sample(1:m, size =round(m/3), replace = FALSE,
prob= rep(1/m, m))
iris.learn <- iris[-val,]
iris.valid <- iris[val,]
iris.kknn <- kknn(Species~.,iris.learn, iris.valid, distance = 5, kernel= "triangular")
summary(iris.kknn)
fit <- fitted(iris.kknn)
table(iris.valid$Species, fit)
这里我们的训练集选取更随机化,得到结果是:
fit
setosa versicolor virginica
setosa 12 0 0
versicolor 0 22 0
virginica 0 0 16
分类完全正确。
应用举例:手写数字识别
下面我们来做一个规模大一些的数据处理,利用k-近邻实现一下数字的模式识别。这个例子来自《机器学习实战》,具体数据集已上传至百度云盘(点击这里下载)。数据为了简单起见,仅提供0~9,10个数字的识别。需要识别的数字你可以看做是被图像处理软件处理为了32*32的黑白图像。尽管文本格式储存图片不能够有效地利用存储空间,但是为了方便理解还是提供了这个文本版的图片数据。