ad6bcbb63116e1246b252add9e3074b4.jpeg

最近,突然想要用R来搞搞机器学习,这让我想起了一个被尘封的草稿,当初让我放弃使用R做嵌套交叉验证的想法。于是,决定好好完善一番再发出去。有些事情不捋清楚,它就会在将来的某个时候等着你,让你心神不宁。先从交叉验证开始。

交叉验证

交叉验证(Cross Validation; CV)用于检验机器学习的模型表现,选择模型。如下图显示的便是一个3-fold CV。其中loop都使用了相同的随机森林(RF)模型。

e985cfb4e9e038e2b3b99c5c7c011d1d.png

(https://ploomber.io/blog/nested-cv/)

使用同样的方法,可以对比不同模型的表现,例如,如果支持向量机(SVM)比随机森林(RF)的表现好,便选用支持向量机作为最终模型。同样地,每个loop都使用相同的模型超参数)。

f7db00b769624ee4248bd39391ec87df.png

(https://ploomber.io/blog/nested-cv/)

机器学习的模型都会涉及超参数(hypoparameters),选择不同的超参数可能会让模型表现改变。因此做交叉验证也可以用于调参。

e2d55312048de1f97a26295039b66194.png

(https://ploomber.io/blog/nested-cv/)

例如,这里使用交叉验证的结果说明,支持向量机(SVM)选择线性(Linear)内核比非线性(i.e., Poly)内核表现更好。这样做潜在的问题是,一旦选择了表现最好的超参数,该模型的表现通常会被报告为最优模型。由于这里每一次交叉验证的循环中,都使用了相同的数据来调参,因此存在着严重的优化偏差(bias)问题,可能导致对模型表现的乐观估计。

嵌套交叉验证fb6194068ff054e0acfde9d3628be322.png

(https://ploomber.io/blog/nested-cv/)

如图所示,嵌套交叉验证进而将外层(outer)每个循环中的训练集再做一个k折交叉验证进行调参,这里调参的是n_estimations的数量,结果表示n_esimations=5的第三个fold的表现好,因此选择该参数的模型作为第三个fold的模型。实际中,可能会使用grid.search等策略对多种参数进行评估,每一个组合都会做一次k折交叉验证计算平均模型表现,最好的选为一个外层的最优模型。

重复交叉验证(Repeated CV)

由于在做k折交叉验证时,将数据一次划分为了k组,这样的划分存在随机性。有可能某一次划分会得到较好的结果,而另一次划分得到较差的结果。因此做重复交叉验证能减小由于将数据划分而造成的随机变化。

7c1e162529f6921908367a42da0714a1.jpeg

R中的交叉验证

实际看一下caret的文档,调参类似于Python中的GridSearchCV。

f17866ec36530280083d196edaadf5ef.png

(https://topepo.github.io/caret/model-training-and-tuning.html)

例如使用重复交叉验证对一个SVM调参ff413c6760de672e1f7893887be29455.jpeg输出如下:6bcf36701b636ef49fdf3869fdadb686.png

(https://stats.stackexchange.com/questions/421701/tuning-svm-parameters-in-r)

输出的时候出现了Resampling,指的是对数据进行重采样的方式。交叉验证也算作一种重采样的方式。在trainControl的method中还有除了交叉验证的其他选项,例如resampling。

2b9ce2c4a5dc2344e96af4957529524d.png(http://appliedpredictivemodeling.com/blog/2017/9/2/njdc83d01pzysvvlgik02t5qnaljnd)

想在R中做Nested CV?

在R常用的工具包Caret并未提供Nested CV的做法,工具包作者首先质疑了做Nested CV的收益,然后加了工单。

d33f6c758a01806a84ade65f4ab94ac4.png

随后又嫌麻烦,写了个相关的blog,要做嵌套的就照着做吧。

5a7cd0bdb405a21273a19b2ca1f01f2e.png

博客中,作者使用数据说明了做嵌套过程的收益其实不大。

5598366890a496ca0012ab5f00beaf8d.png

(http://appliedpredictivemodeling.com/blog/2017/9/2/njdc83d01pzysvvlgik02t5qnaljnd)

类似的观点:

b92662181ccc714ea26b683adebefd5b.png9554d33ed4f2cd2ade131345076b1daa.jpeg

所以大部分时候,使用标准版的CV调参可以提高运行速度,对于200个参数组合,10-fold标准版CV计算量是2000,而10-fold嵌套CV的计算量则是20000。但是当参数数量>>样本量时就需要考虑嵌套交叉验证,Python很方便,在R中有以下几种思路:

  1. 在R中使用reticulate包调用Python代码。如果知道Python的嵌套怎么做,难度1星。

  2. 使用R工具包nestedcv,难度2星。

3. 手动增加外层循环或者参照caret作者的博客,难度4星。

aa5543b5768fff0962fbadbe4b94e09d.jpeg

(https://stats.stackexchange.com/questions/125843/outer-crossvalidation-cycle-in-caret-package-r)

df2e1185021e49a5c7d6478b34a45e23.png

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐