打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
机器学习之KNN分类算法介绍: Stata和R同步实现(附数据和代码)
稿件:econometrics666@126.com
所有计量经济圈方法论丛的code程序, 宏微观数据库和各种软件都放在社群里.欢迎到计量经济圈社群交流访问.
关于机器学习方法,可参阅如下文章:1机器学习方法出现在AER, JPE, QJE等顶刊上了!,2前沿: 机器学习在金融和能源经济领域的应用分类总结,3文本分析的步骤, 工具, 途径和可视化如何做?4文本大数据分析在经济学和金融学中的应用, 最全文献综述,5最全: 深度学习在经济金融管理领域的应用现状汇总与前沿瞻望, 中青年学者不能不关注!6Top前沿: 农业和应用经济学中的机器学习, 其与计量经济学的比较, 不读不懂你就out了!7机器学习和大数据计量经济学, 你必须阅读一下这篇,8机器学习与Econometrics的书籍推荐, 值得拥有的经典,9机器学习在微观计量的应用最新趋势: 大数据和因果推断,10机器学习第一书, 数据挖掘, 推理和预测,11Top, 机器学习是一种应用的计量经济学方法, 不懂将来面临淘汰危险!12最新: 运用机器学习和合成控制法研究武汉封城对空气污染和健康的影响! 13陈硕: 回顾与展望经济学研究中的机器学习,14机器学习对经济学研究的影响研究进展综述
正文作者:王标悦,北京大学软微学院;通信邮箱:wangbiaoyue@pku.edu.cnKNN中文里叫K近邻,全称是K-Nearest Neighbor,用来选出某个样本点k个最近的样本。作为机器学习一种入门级算法,KNN的NN虽然和计量经济学中PSM模型中的NN近邻匹配字面意思一样,但两者的算法原理却有着本质区别。
PSM:NN近邻匹配的依据是样本进入“干预组”的概率或得分(propensity score),通常用logit/Probit函数求出。两个观测值相近指的是两者的概率或得分相近。KNN:近邻的远近是通过距离来衡量。在Stata和R(knn3函数)中,默认的距离指欧式距离(Euclidean Distance,记为L2)。近年来计量经济学也已经把KNN纳入,当成一种非参估计的方法。KNN可看成一种基于实例的学习算法,通过局部近似及推迟所有计算到分类之后,故也被称为“惰性学习算法”。KNN分类通过最近的k个近邻样本的类别,来推测目标样本的类别。1 KNN算法原理
KNN作为机器学习中的常见算法,同时适用于分类和回归。1.1 分类算法原理
欧式距离定义:这里x和y代表两个样本观测值向量,表示x样本的第i个特征变量i的具体取值,表示y样本第i个特征变量的具体取值。KNN分类算法原理:某个对象的分类结果由其最近的N(通常是1到5)个邻居决定,也叫“vote,投票表决”。即K个最近的邻居中,频数最高的类别,就认为是我们要考虑的那个对象的类别。好比如我们讨论一个学生是学霸还是学渣(只有两种分类),我们观察ta身边最亲密的k个朋友,里面如果学霸比例最多,那么我们就将这个同学归类为学霸,反之学渣。这和常见的俗语“物以类聚,人以群分”表达的原理有点类似——距离最近的k个样本的性质,决定了目标样本的性质。1.2 回归算法原理
在KNN回归中,输出的是目标对象的K个最近邻样本的结果变量取值的平均值。比如某个个体的收入水平,就等于和ta关系最亲密的k个朋友收入水平的均值。限于篇幅,本文没有详细介绍KNN回归的应用案例。1.3 KNN算法大概步骤
(1)明确k的取值,且最好为奇数(偶数情况下可能出现ties);选择近邻距离的算法,默认是L2欧式距离。  (2)将原始数据切割为一定比例(如70%)的训练数据集和(如30%)测试数据集。(3)基于训练数据集建立学习算法模型。(4)基于测试数据做出预测,以评估学习算法模型的性能表现。(5)重复步骤(3)和(4),选出最优模型。1.4 KNN算法的优点
(1)简单但强大。逻辑简单,无需参数进行估计;易于理解,容易实现。(2)用途较多。可以出了二分类和多分类问题,也可以处理回归的问题。多分类预测中比另外一种常见的机器算法SVM(支持向量机)通常表现更好。(3)和朴素贝叶斯等算法相比,对异常值样本点不敏感。1.5 KNN算法的不足
首先,KNN算法对数据集的局部结构和K的取值非常敏感。可以想象,在学霸分类的例子中,如果k=1且刚好该同学是学霸,那么目标同学就被判断为学霸;若k=3,近邻中2位同学是学渣1位学霸,那目标同学就被判断为学渣;若k=5时,2位学渣3位学霸,目标同学又变成了学渣。从这个简单的例子可以看出,模型参数k的变动直接引起了分类结果的变化。其次,当k取值较小时,训练所使用的实例来源于较小的邻域,使得学习的近似误差变小但是预测误差变大。这意味着k越小,模型就会越复杂,越可能发生过拟合(过拟合指训练结果很好,但是预测能力很差)的情况。当k取值较大时,训练所使用的实例来源于较大的邻域,结果可以使得估计误差变小但近似误差会变大。k越大,模型就会越简单。在极端的情况下,考虑k=N样本观测值,分类算法的结果将全部变成数据集中最大的类别,回归算法的结果将全部变成数据集均值。第三,KNN在新数据上进行分类或预测的时候,必须通过测试数据来寻找最近邻的旧样本以进行判断。因此,当数据集较大的时候,KNN算法在Stata或R中就会消耗很大的内存并导致运行缓慢。在数据维度较大的时候,也会出现“维度灾难”的问题。最后,作为惰性的机器学习算法,KNN很懒,几乎就不怎么学习。2 KNN在Stata和R中的实现
2.1 KNN在Stata中的实现
Stata中实现KNN分类的命令是“discrim knn”。有点可惜的是,截至Stata 16官方和SSC尚未提供基于KNN的回归命令。“discrim knn”还可以通过“多种不同具体的算法来计算similarity和dissimilarity不相似性”。Syntax: discrim knn varlist [if] [in] [weight], group(groupvar) k(#) [options]说明:这里varlist指自(特征)变量列表;groupvar指分组变量或标签变量,即计量经济学中的结果变量或因变量。在机器学习中通过label标签变量,给不同类别的样本打上不同的标签,以示分类。options里面常用的包括以下几个:(1)k(#),#代表KNN的k,个数,默认是k=1。(2)priors,priors指分组的先验概率,默认是等概率。另外一个较常用的是proportional,按分组频数/总样本量作为对应比例的概率。(3)measure,默认是L2,欧式距离。(4)notable和lootable,分别用来报告压缩重新替换的分类结果表格,和报告leave-one-out分类结果表格。(5)ties,当最近距离的k个近邻样本出现分类结果相当而导致无法判断的情况下,处理的方法,包括标记为missing缺失值和随机选择等。我们在实际操作中可考虑使用奇数的k,这样一般就不会出现ties的问题了。2.2 KNN在R中的实现
R语言中实现KNN算法的常用函数有三个,(1)机器学习caret包中的knn3函数;(2)class包中的knn函数;(3)kknn包中的kknn函数。本文使用的是knn3函数,具体实现步骤见3.2部分。3 案例:街区的类型分类和预测
本案例的分析目标是通过某个街区的几个特征变量,来预测该街区的类型(富人区还是普通区)。接下简单介绍下本案例所使用的数据“houseprice_10000.csv”。该数据基于美国某州的真实房价数据改编:N=10000;以community街区为基本单位;其它变量从人均收入等其它方面对该街区进行刻画。在原始数据基础上,新生成了rich变量。全部变量的名称、含义和取值如下表所示。变量名称
变量类型含义和取值
communityid特征变量街区的编码id,从1到10000。不放入模型
income特征变量街区的人均收入水平,单位为美元
houseage特征变量街区房子的平均年龄,单位为年
rooms特征变量街区房子的平均房间数量,单位为个
population特征变量街区的总人口,单位为个
houseprice结果变量 – 连续型街区房子的平均价格,单位是美元
rich结果变量 – 分类型基于houseprice新生成,大于全体样本均值取1(富人区),否则取0(普通区)
3.1 Stata 建模和预测
Stata实现的具体过程如下(完整代码见do文件)。第一步,将数据整理为适合Stata建模的形式。. cd "D:\R" //更改工作目录                        . import delimited "D:\R\houseprice_10000.csv", clear //导入原始数据  * 查看关键变量的统计指标                          . tabstat income-houseprice, stat(max mean min sd) column(statistics)  
. gen rich = 1 if houseprice >= 2344341 //生成富人区rich变量(4,997 missing values generated). replace rich = 0 if mi(rich)(4,997 real changes made). tab rich
. label define rich_lb 0 "普通区" 1 "富人区". label values rich rich_lb. set seed 1898. gen rand=runiform() //生成随机数,以保证后面的模型训练取样是随机的. sort rand. **将几个关键的特征变量标准化,消除单位(量纲)的影响. foreach var of varlist income - population { 2.     egen var'_std = std(var') 3.     }**查看标准化后数据的大概情况. tabstat income_std-population_std houseprice rich, ///stat(max mean min sd) column(statistics)
第二步,在10000个原始样本随机抽取7000个作为训练数据集,建立KNN模型模型。* Stata 基于前7000个样本进行KNN分类模型建模。近邻k定为15    . discrim knn income_std-population_std in 1/7000, k(15) group(rich). dis (3089+3216)/7000  //训练数据本身的预测精确度是0.9007
第三步,基于剩余的3000个测试数据集,预测街区是富人区还是普通区。. predict rich_hat in 7001/10000, classification //基于3000个测试数据预测(7000 missing values generated). label values rich_hat rich_lb. tab rich rich_hat in 7001/10000  
第四步,将模型预测结果和真实的测试数据对比,评估预测的准确度。. dis (1369+1280)/3000 //训练数据本身的预测精确度是0.883.885由于数据本身相似度较高,本例中把k设定为15,最终的预测准确度是0.883。后经过笔者的尝试发现,k在约等于129的时候准确度达到.887;之后随着k的增大,准确度开始下降。大概可以估计,最优模型的k在129附近。3.2 R建模和预测
R语言中KNN分类算法建模过程和Stata中类似,但具体操作差异较大。第一步,将数据整理为适合R建模的形式。#使用KNN来对富人区和普通区进行分类###########################################载入相关的包library(caret)library(e1071) set.seed(1898) #在设定seed前,可能需要对原始数据进行排序,以保证可以重复结果####原始数据准备rm(list=ls()) #清除当前工作环境中的所有数据house <- read.delim("D:/R/houseprice_10000.csv", sep=",") #导入数据 summary(house$houseprice) #查看房价标量的大概情况
head(house) #查看数据头部
house$rich <- ifelse(house$houseprice >= mean(house$houseprice), 1, 0) #大于平均房价的街区定义为“富人区”,否则为“普通区” head(house)
house <- house[-c(1,7)] #删除无用的变量communityid和housepricehouse[1:5] <- apply(house[1:5], 2, scale) #将结果变量以外的变量标准化head(house)
第二步,在10000个原始数据中随机抽取7000个作为训练数据集,建立KNN模型模型;剩下的3000个样本构成测试数据集。####训练和测试数据准备house$rich <- factor(house$rich, #关键步骤!将rich变量转变为因子变量+  levels=c(0,1),+   labels=c("普通区", "富人区"))labels <- house$rich #将rich变量保存到labels向量#使用caret包中的creatDataPartition函数完成数据的随机取样和切割 index <- createDataPartition(house$rich, p=0.7) #70%为训练数据train_house <- house[index$Resample1, ] #从总样本总提取训练数据 train_lab <- labels[index$Resample1] #提取训练数据的分类标签 test_house <- house[-index$Resample1, ] #剩下的为测试数据test_lab <- labels[-index$Resample1] #提取测试数据的分类标签# View(train_lab) #查看训练数据的分类标签# View(test_lab) #查看测试数据的分类标签第三步,基于剩余的3000个测试数据集,预测街区的类型(是富人区还是普通区)####KNN建模house_m1 <- knn3(rich~., house, k=15) #rich是结果变量,其它是特征变量house_m1
第四步,将模型预测结果和真实的测试数据对比,评估预测的准确度。rich_hat <- predict(house_m1, test_house, type="class")test_lab <- as.factor(test_lab)rich_hat <- as.factor(rich_hat)confusionMatrix(test_lab, rich_hat) #用混淆矩阵函数展示测试的结果
混混淆矩阵的结果可以看出,该模型(k=15)的预测准确度为0.8973,和Stata的模型(k=15)的0.883比较接近。不管是Stata还是R,整体街区类型的预测精确度不是非常高,但也还过得去。本案例中k较大的原因在于数据部分是基于原有真实数据改编,相似度较高,故k取值较大。3.3 Stata和R建模对比
(1)实现效率:整体上来说,Stata操作更简单。作为商业性软件,Stata确实给用户提供了极致的简便高效。不过R语言的步骤虽多,但每一步都非常严谨清晰。顺便多说一句,相对Stata的命令式建模R才是真正的“编程”,所以说学习和使用R和Python等可以让一个人的思维变得清晰严谨是有一定道理的。(2)建模方法对比:这一点Stata完全不能和R比。Stata 到了2019年的16版本依然没有提供KNN的回归算法命令,但R已经有多个KNN的分类和回归算法函数(knn、kknn、knn3和knnreg)。R还另外提供了寻找最优模型的函数,方便用户快速的找出最优的k的个数,有兴趣的读者可以进一步研究。(3)建模后的分析。这一点Stata明显更出色,KNN建模后还提供一系列的命令进行postestimation,可以更详尽地展示学习算法模型。小结:R和Stata各有优缺。两者风格的差异主要是因为R代表着主流的机器学习潮流,算法和术语更接近Python,而Stata更强调从经济学和计量经济学的角度去引入KNN等机器学习模型。4. 写在最后
既然R或Python介绍机器学习算法的角度和计量经济学相差甚远,那么花费大量时间去学习它们还有必要么?考虑到目前Python已经成长全球第一编程语言,R是全球第一统计语言,同为开源软件的两者对传统商业统计软件的取代(或部分取代)是大势所趋。只有熟悉和掌握作为机器学习最主流的两种语言Python或R,我们才能紧跟人工智能时代的角度。至于R和Python相比,笔者个人更推荐R。毕竟Python是通用编程语言,思维和逻辑角度更偏计算机学科,而R天生是统计语言,和计量经济学关系更为接近,更适合经管学科的朋友们。总的来说,R+Stata的组合即可以帮助我们掌握主流的机器学习算法,还可以让我们更好地从计量经济学的角度去把握机器学习,在未来的经济学研究中用机器学习进行因果推断。PS: 关于R语言中使用KNN进行回归建模和预测的介绍,笔者已经完成初稿写作,后期将尽快发送出来,欢迎大家关注本公众号后续的KNN相关推文。5. 参考文献
(1) 陈强,《高级计量经济学及Stata应用》,第二版。(2) 薛震,孙玉林,《R语言统计分析与机器学习》。(3) Athey S , Imbens G W . Machine Learning Methods Economists Should Know About[J]. Research Papers, 2019.(4) Athey S . The Impact of Machine Learning on Economics[J]. Nber Chapters, 2018.(5) KNN算法Stata和R相关的大量的官方帮助文件。附数据和代码:
附数据和代码链接:https://pan.baidu.com/s/1nvnQdrky83H8GTeP9NHQtw提取码:jlsq关于相关计量方法视频课程,文章,数据和代码,参看 1.面板数据方法免费课程, 文章, 数据和代码全在这里, 优秀学人好好收藏学习!2.双重差分DID方法免费课程, 文章, 数据和代码全在这里, 优秀学人必须收藏学习!3.工具变量IV估计免费课程, 文章, 数据和代码全在这里, 不学习可不要后悔!4.各种匹配方法免费课程, 文章, 数据和代码全在这里, 掌握匹配方法不是梦!5.断点回归RD和合成控制法SCM免费课程, 文章, 数据和代码全在这里, 有必要认真研究学习!6.空间计量免费课程, 文章, 数据和代码全在这里, 空间相关学者注意查收!7.Stata, R和Python视频课程, 文章, 数据和代码全在这里, 真的受用无穷!
下面这些短链接文章属于合集,可以收藏起来阅读,不然以后都找不到了。
2.5年,计量经济圈近1000篇不重类计量文章,
可直接在公众号菜单栏搜索任何计量相关问题,
Econometrics Circle
数据系列:空间矩阵 | 工企数据 | PM2.5 | 市场化指数 | CO2数据 |  夜间灯光 | 官员方言  | 微观数据 | 内部数据计量系列:匹配方法 | 内生性 | 工具变量 | DID | 面板数据 | 常用TOOL | 中介调节 | 时间序列 | RDD断点 | 合成控制 | 200篇合辑 | 因果识别 | 社会网络 | 空间DID数据处理:Stata | R | Python | 缺失值 | CHIP/ CHNS/CHARLS/CFPS/CGSS等 |干货系列:能源环境 | 效率研究 | 空间计量 | 国际经贸 | 计量软件 | 商科研究 | 机器学习 | SSCI | CSSCI | SSCI查询 | 名家经验计量经济圈组织了一个计量社群,有如下特征:热情互助最多、前沿趋势最多、社科资料最多、社科数据最多、科研牛人最多、海外名校最多。因此,建议积极进取和有强烈研习激情的中青年学者到社群交流探讨,始终坚信优秀是通过感染优秀而互相成就彼此的。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
KNN分类算法补充
一分钟看完计量经济学!!!------开学后的计量笔记
小白学数据:教你用Python实现简单监督学习算法
数据挖掘十大算法——kNN
入门数据科学,初学者需要掌握的10大机器学习算法
机器学习之k-近邻(knn)算法与python实现 未 20181-28
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服