作者:Leihua Ye, UC Santa Barbara

翻译:陈超

校对:冯羽

本文约2300字,建议阅读10分钟

本文介绍了一种针对初学者的K临近算法在R语言中的实现方法。

本文呈现了一种在R语言中建立起KNN模型的方式,其中包含了多种测量指标。

Mathyas Kurmann拍摄,来自于Unsplash

“如果你有5分钟时间可以离开比尔·盖茨生活,我敢打赌你很富有。”

背景

在机器学习的世界里,我发现K邻近算法(KNN)分类器是最直观、最容易上手的,甚至不需要引入任何数学符号。

为了决定观测样本的标签,我们观察它的邻近样本们并把邻近样本们的标签贴给感兴趣的观测样本。当然,观察一个邻近样本可能会产生偏差和错误,KNN方法就制定了一系列的规则和流程来决定最优化的邻近样本数量,比如,检验k>1的邻近样本并且采纳取大多数的规则来决定分类。

“为了决定新观测样本的标签,我们就看最邻近样本。”

距离度量

为了选择最邻近的样本,我们必须定义距离的大小。对于类别数据,有汉明距离和编辑距离。详情请见

https://en.m.wikipedia.org/wiki/Knearest_neighbors_algorithm

,本文将不会过多讨论数学问题。

什么是K折交叉验证?

在机器学习当中,交叉验证(CV)在模型选择中起着关键作用,并且拥有一系列的应用。事实上,CV有着更加直观的设计理念,并且也很直观。

简要介绍如下:

1. 将数据分成K个均匀分布的块/层

2. 选择一个块/层集作为测试集,剩下的K-1块/层作为训练集

3. 基于训练集建立ML模型

4. 仅比较测试集当中的预测值和真实值

5. 将ML模型应用到测试集,并使用每个块重复测试K次

6. 把模型的度量得分加和并求K层的平均值

如何选择K?

如同你注意到的,交叉验证比较的一点是如何为K设置值。我们记总样本量为n。从技术上来看,K可设置从1到n的任意值。

如果k=n,我们取出1个观测值作为训练集并把剩余的n-1个值作为测试集。然后在整个数据集中重复这个过程。这就叫做“留一交叉验证法” (LOOCV)。

留一交叉验证法要求较大的计算力,并且如果你的数据集过大,该法可能会无法终止。

退一步来讲,即使没有最优k值,也不能说k值越大更好。

为了选择最合适的k值,我们必须在偏差和方差之间权衡。如果k很小,我们在估计测试误差时会获得较大的偏差但方差会较小;如果k值比较大,我们的偏差会较小,方差会较大。

Jon Tyson拍摄,来自于Unsplash

“你好邻居!快进来吧。”

R语言实现

1. 软件准备

# install.packages(“ISLR”)

# install.packages(“ggplot2”) # install.packages(“plyr”)

# install.packages(“dplyr”) # install.packages(“class”)# Load libraries

library(ISLR)

library(ggplot2)

library(reshape2)

library(plyr)

library(dplyr)

library(class)# load data and clean the dataset

banking=read.csv(“bank-additional-full.csv”,sep=”;”,header=T)##check for missing data and make sure no missing data

banking[!complete.cases(banking),]#re-code qualitative (factor) variables into numeric

banking$job=recode(banking$job,“‘admin.’=1;’blue-collar’=2;’entrepreneur’=3;’

housemaid’=4;’management’=5;’retired’=6;’self-employed’=7;’services’=8;

’student’=9;’technician’=10;’unemployed’=11;’unknown’=12”)#recode variable again

banking$marital=recode(banking$marital,“‘divorced’=1;’married’=2;’single’=3;’unknown’=4”)

banking$education=recode(banking$education,“‘basic.4y’=1;’basic.6y’=2;’basic.9y’=3;’high.school’=4;’illiterate’=5;’professional.course’=6;’university.degree’=7;’unknown’=8”)

banking$default = recode(banking$default, “‘no’=1;’yes’=2;’unknown’=3”)

banking$housing = recode(banking$housing, “‘no’=1;’yes’=2;’unknown’=3”)

banking$loan=recode(banking$loan,“‘no’=1;’yes’=2;’unknown’=3”)banking$contact=recode(banking$loan,“‘cellular’=1;’telephone’=2;”)

banking$month=recode(banking$month,“‘mar’=1;’apr’=2;’may’=3;’jun’=4;’jul’=5;’aug’=6;’sep’=7;’oct’=8;’nov’=9;’dec’=10”)

banking$day_of_week=recode(banking$day_of_week,“‘mon’=1;’tue’=2;’wed’=3;’thu’=4;’fri’=5;”)

banking$poutcome = recode(banking$poutcome,“‘failure’=1;’nonexistent’=2;’success’=3;”)#remove variable “pdays”, b/c it has no variation

banking$pdays=NULL #remove variable “duration”, b/c itis collinear with the DV

banking$duration=NULL

在加载并清空初始数据集之后,通常的做法是将变量的分布可视化,检查季节性,模式,异常值,等等。

#EDA of the DV

plot(banking$y,main="Plot 1: Distribution of Dependent Variable")

如图所示,结果变量(银行服务订阅)并不满足均匀分布,“否”比“是”多得多。

当我们尽力想正确分类标签的时候,监督学习是不太方便的。正如意料之中,如果大量的少数案例被分类为多数标签,假阳性的比率会变高。

事实上,不均匀分布可能会更偏好非参数ML分类器,在我的另一篇文章(使用5个分类器对罕见事件进行分类,https://medium.com/m/global-identity?

redirectUrl=https%3A%2F%2Ftowardsdatascience.com%2Fclassifying-rare-events-using-five-machine-learning-techniques-fab464573233)中介绍了KNN在与其他ML方法进行比较之后表现得更好。这个可能是参数和非参数模型中潜在的数学和统计假设导致的。

2. 数据分组

如上所述,我们需要将数据集进行分组,分为训练集和测试集,并采取k层交叉验证来选择最佳的ML模型。根据经验法则,我们通常使用“80-20”比:我们用80%的数据训练ML用剩余20%进行测试。而时间序列数据略有不同,我们将比例改为90%对10%。

#split the dataset into training and test sets randomly, but we need to set seed so as to generate the same value each time we run the codeset.seed(1)#create an index to split the data: 80% training and 20% test

index = round(nrow(banking)*0.2,digits=0)#sample randomly throughout the dataset and keep the total number equal to the value of index

test.indices = sample(1:nrow(banking), index)#80% training set

banking.train=banking[-test.indices,] #20% test set

banking.test=banking[test.indices,] #Select the training set except the DV

YTrain = banking.train$y

XTrain = banking.train %>% select(-y)# Select the test set except the DV

YTest = banking.test$y

XTest = banking.test %>% select(-y)

到目前为止,我们已经完成了数据准备并开始模型选择。

3. 训练模型

让我们编写一个新的函数(“calc_error_rate”)来记录错误分类率。该函数计算当使用训练集得到的预测标签与真正的结果标签不相匹配的比率。它测量了分类的正确性。

#define an error rate function and apply it to obtain test/training errorscalc_error_rate

return(mean(true.value!=predicted.value))

}

然后,我们需要另外一个函数“do.chunk()”来做k层交叉验证。该函数返回层的可能值的数据框。这一步的主要目的是为KNN选择最佳的K值。

nfold = 10

set.seed(1)# cut() divides the range into several intervals

folds = seq.int(nrow(banking.train)) %>%

cut(breaks = nfold, labels=FALSE) %>%

sampledo.chunk

train = (folddef!=chunkid)# training indexXtr = Xdat[train,] # training set by the indexYtr = Ydat[train] # true label in training setXvl = Xdat[!train,] # test setYvl = Ydat[!train] # true label in test setpredYtr = knn(train = Xtr, test = Xtr, cl = Ytr, k = k) # predict training labelspredYvl = knn(train = Xtr, test = Xvl, cl = Ytr, k = k) # predict test labelsdata.frame(fold =chunkid, # k folds

train.error = calc_error_rate(predYtr, Ytr),#training error per fold

val.error = calc_error_rate(predYvl, Yvl)) # test error per fold

}# set error.folds to save validation errors

error.folds=NULL# create a sequence of data with an interval of 10

kvec = c(1, seq(10, 50, length.out=5))set.seed(1)for (j in kvec){

tmp = ldply(1:nfold, do.chunk, # apply do.function to each fold

folddef=folds, Xdat=XTrain, Ydat=YTrain, k=j) # required arguments

tmp$neighbors = j # track each value of neighbors

error.folds = rbind(error.folds, tmp) # combine the results

}#melt() in the package reshape2 melts wide-format data into long-format data

errors = melt(error.folds, id.vars=c(“fold”,”neighbors”), value.name= “error”)

接下来的一步是为了找到使得验证错误最小化的k值。

val.error.means = errors %>%

#select all rows of validation errors

filter(variable== “val.error” ) %>%

#group the selected data by neighbors

group_by(neighbors, variable) %>%

#cacluate CV error for each k

summarise_each(funs(mean), error) %>%

#remove existing grouping

ungroup() %>%

filter(error==min(error))#the best number of neighbors

numneighbor = max(val.error.means$neighbors)

numneighbor## [20]

在使用10层交叉验证之后,最优的邻近值数为20。

Nick Youngson

4. 一些模型的度量

#training error

set.seed(20)

pred.YTtrain = knn(train=XTrain, test=XTrain, cl=YTrain, k=20)

knn_traing_error

knn_traing_error

[1] 0.101214

训练误差为0.1。

#test error

set.seed(20)

pred.YTest = knn(train=XTrain, test=XTest, cl=YTrain, k=20)

knn_test_error

knn_test_error

[1] 0.1100995

测试误差为0.11。

#confusion matrixconf.matrix = table(predicted=pred.YTest, true=YTest)

基于以上的混淆矩阵(confusion matrix),我们可以计算以下的值并且准备好画出ROC曲线。

Accuracy = (TP +TN)/(TP+FP+FN+TN)

TPR/Recall/Sensitivity = TP/(TP+FN)

Precision = TP/(TP+FP)

Specificity = TN/(TN+FP)

FPR = 1 — Specificity = FP/(TN+FP)

F1 Score = 2*TP/(2*TP+FP+FN) = Precision*Recall /(Precision +Recall)

# Test accuracy ratesum(diag(conf.matrix)/sum(conf.matrix))[1] 0.8899005# Test error rate1 - sum(drag(conf.matrix)/sum(conf.matrix))[1] 0.1100995

你可能会注意到,测试正确率+测试错误率=1,我也提供了多种方法来计算每个值。

# ROC and AUC

knn_model = knn(train=XTrain, test=XTrain, cl=YTrain, k=20,prob=TRUE)prob

综上所述,我们学习了什么是KNN并且在R语言当中建立了KNN模型。更重要的是,我们已经学到了K层交叉验证法背后的机制以及如何在R语言中实现交叉验证。

作者简介:

雷华·叶(@leihua_ye)是加州大学圣巴巴拉分校的博士生。他在定量用户体验研究、实验与因果推理、机器学习和数据科学方面有5年以上的研究和专业经验。

原文标题:

Beginner’s Guide to K-Nearest Neighbors in R: from Zero to Hero

原文链接:

https://www.kdnuggets.com/2020/01/beginners-guide-nearest-neighbors-r.html

编辑:于腾凯

校对:谭佳瑶

译者简介

陈超,北京大学应用心理硕士在读。本科曾混迹于计算机专业,后又在心理学的道路上不懈求索。越来越发现数据分析和编程已然成为了两门必修的生存技能,因此在日常生活中尽一切努力更好地去接触和了解相关知识,但前路漫漫,我仍在路上。

—完—

关注清华-青岛数据科学研究院官方微信公众平台“ THU数据派 ”及姊妹号“ 数据派THU ”获取更多讲座福利及优质内容。

k折交叉验证优缺点_R语言中K邻近算法的初学者指南:从菜鸟到大神(附代码&链接)...相关推荐

  1. k折交叉验证优缺点_都说K折交叉验证最常见,你会做吗?

    在临床研究领域,大家特别希望能够未仆先知,于是临床研究者尝试去建立各种预测模型.比如,凭借孕妇的信息预测低出生体重儿的结局.怎么建立预测模型呢?常见的做法是这样的:以低出生体重儿为因变量,以相关的孕妇 ...

  2. k折交叉验证优缺点_K最近邻(KNN)算法

    (一)算法思想 最近邻法 Cover, Hart, 1968年提出,非参数法中最重要的方法之一: 基本思想:分段线性判别的极端情况,计算测试样本与 "代表点",即所有训练样本的距离 ...

  3. k折交叉验证优缺点_k折交叉验证(R语言)

    "机器学习中需要把数据分为训练集和测试集,因此如何划分训练集和测试集就成为影响模型效果的重要因素.本文介绍一种常用的划分最优训练集和测试集的方法--k折交叉验证." k折交叉验证 ...

  4. 5折交叉验证_[Machine Learning] 模型评估——交叉验证/K折交叉验证

    首先区分两个概念:'模型评估' 与 '模型性能度量' 模型评估:这里强调的是如何划分和利用数据,对模型学习能力的评估,重点在数据的划分方法. Keywords: 划分.利用数据 模型性能度量:是在研究 ...

  5. python 实现k折交叉验证

    k折交叉验证原理: k折交叉验证是将数据分为k份,选取其中的k-1份为训练数据,剩余的一份为测试数据.k份数据循环做测试集进行测试.此原理适用于数据量小的数据. # k-折交叉验证(此处设置k=10) ...

  6. Kaggle上分技巧——单模K折交叉验证训练+多模型融合

    一.K折交叉验证训练单个模型 1.1 k 折交叉验证(K-Fold Cross Validation)原理 通过对 k 个不同分组训练的结果进行平均来减少方差,因此模型的性能对数据的划分就不那么敏感, ...

  7. matlab-K折交叉验证与分层K折交叉验证

    文章目录 K折交叉验证有什么用? 如何实现K折交叉验证? K折交叉验证的要点:(文字版) 如何实现K折交叉验证(图片版) 如何实现K折交叉验证(matlab版) 为啥我们需要分层K折交叉验证? 如何实 ...

  8. 参数调优:K折交叉验证与GridSearch网格搜索

    本文代码及数据集来自<Python大数据分析与机器学习商业案例实战> 一.K折交叉验证 在机器学习中,因为训练集和测试集的数据划分是随机的,所以有时会重复地使用数据,以便更好地评估模型的有 ...

  9. 交叉验证(cross validation)是什么?K折交叉验证(k-fold crossValidation)是什么?

    交叉验证(cross validation)是什么?K折交叉验证(k-fold crossValidation)是什么? 交叉验证(cross validation)是什么?  交叉验证是一种模型的验 ...

最新文章

  1. [ASP.NET入门随想七]主角与配角——OO思想的多态、接口与委托
  2. MySQL Windows ZIP 免费安装和启动设置
  3. Qt Creator将应用程序部署到通用远程Linux设备
  4. oa提醒模块要素_OA系统进军贸易行业,高效完成CRM管理
  5. python的调用函数_Python函数调用
  6. PPA 软件源 ppa:ondrej/php 在哪里找到的
  7. 如何在python中安装包_如何给python安装包
  8. 羊年祝福语(羊年祝福大全)
  9. linux 安装minio并设置开机自启动
  10. 一个故事贯穿设计模式小例子练习源码
  11. 计算机组成ar什么意思,到底什么是AR技术?
  12. (收藏)让你从骨子里爱上英文
  13. 小学六年级数学教案:圆柱与圆锥
  14. 基于滴滴云服务器搭建 Consul 集群
  15. konga 连接postgresql 12+启动异常:error: column r.consrc does not exist
  16. php三个错误报告级别,php三个错误报告级别类型是什么
  17. android edittext 过滤英文名称,Android 限制edittext 整数和小数位数 过滤器(详解)
  18. Java SE 01 概述
  19. No URLs will be polled as dynamic configuration sources警告处理
  20. 区块链 实验十 DAPP开发

热门文章

  1. Powershell管理系列(四)Lync server 2013 批量启用语音及分配分机号
  2. 解决ORA-01578错误一例
  3. 第四篇: UpdatePanel 控件--触发机制Triggers
  4. 堆栈的缓冲区溢出进不了系统_一文理解缓冲区溢出
  5. c语言 判断一个图是否全连通_【连载】(判断执行语句)乐创DIY C语言讲义——3.8节(2)...
  6. html blob处理图片,将Blob图像预览为HTML5
  7. java数字高低呼唤_记录某电话交换台 5 分钟内接到的呼唤次数,则样本空间 S={0,1,2, … ,n, … }_Java答案_学小易找答案...
  8. oracle pl sql安装配置,oracle的安装与plsql的环境配置
  9. mysql密码自动被改_每日一shell(十一)mysql强制自动修改密码
  10. python中config方法作用,python中ConfigParse模块的用法