## npreg glu bp skin ## Min. : 0.00 Min. : 56.0 Min. : 38.00 Min. : 7.00 ## 1st Qu.: 1.00 1st Qu.:100.0 1st Qu.: 64.00 1st Qu.:20.75 ## Median : 2.00 Median :120.5 Median : 70.00 Median :29.00 ## Mean : 3.57 Mean :124.0 Mean : 71.26 Mean :29.21 ## 3rd Qu.: 6.00 3rd Qu.:144.0 3rd Qu.: 78.00 3rd Qu.:36.00 ## Max. :14.00 Max. :199.0 Max. :110.00 Max. :99.00 ## bmi ped age type ## Min. :18.20 Min. :0.0850 Min. :21.00 No :132 ## 1st Qu.:27.57 1st Qu.:0.2535 1st Qu.:23.00 Yes: 68 ## Median :32.80 Median :0.3725 Median :28.00 ## Mean :32.31 Mean :0.4608 Mean :32.11 ## 3rd Qu.:36.50 3rd Qu.:0.6160 3rd Qu.:39.25 ## Max. :47.90 Max. :2.2880 Max. :63.00技术支持
# Set the seed
set.seed(150)# Fit the ensemble model
model <- SuperLearner(y,
x,
family=binomial(),
SL.library=list("SL.ranger","SL.ksvm","SL.ipredbagg","SL.bayesglm"))# Return the model
model技术支持
要理解每个模型对整体模型的具体贡献及其变异性,您可以使用 SuperLearner 的内部交叉验证函数 CV.SuperLearner()。可用 V 参数设置折数,此处设为 5:
# Set the seed
set.seed(150)# Get V-fold cross-validated risk estimate
cv.model <- CV.SuperLearner(y,
x,
V=5,
SL.library=list("SL.ranger","SL.ksvm","SL.ipredbagg","SL.bayesglm"))# Print out the summary statistics
summary(cv.model)技术支持
## ## Call: ## CV.SuperLearner(Y = y, X = x, V = 5, SL.library = list("SL.ranger", ## "SL.ksvm", "SL.ipredbagg", "SL.bayesglm")) ## ## Risk is based on: Mean Squared Error## ## All risk estimates are based on V = 5 ## ## Algorithm Ave se Min Max## Super Learner 0.17277 0.014801 0.16250 0.19557## Discrete SL 0.17964 0.014761 0.16363 0.19244## SL.ranger_All 0.17866 0.015004 0.14811 0.20518## SL.ksvm_All 0.19382 0.020301 0.15685 0.26215## SL.ipredbagg_All 0.17791 0.015858 0.15831 0.19244## SL.bayesglm_All 0.16628 0.014318 0.15322 0.18022技术支持
# Set the seed
set.seed(150)# Tune the model
cv.model.tune <- CV.SuperLearner(y,
x,
V=5,
SL.library=list("SL.ranger","SL.ksvm","SL.ipredbagg","SL.bayesglm","SL.ranger.tune","SL.ipredbagg.tune"))# Get summary statistics
summary(cv.model.tune)技术支持
## ## Call: ## CV.SuperLearner(Y = y, X = x, V = 5, SL.library = list("SL.ranger", ## "SL.ksvm", "SL.ipredbagg", "SL.bayesglm", "SL.ranger.tune", "SL.ipredbagg.tune")) ## ## ## Risk is based on: Mean Squared Error## ## All risk estimates are based on V = 5 ## ## Algorithm Ave se Min Max## Super Learner 0.17272 0.014969 0.15849 0.19844## Discrete SL 0.17250 0.014989 0.15645 0.18430## SL.ranger_All 0.17897 0.015084 0.15388 0.19920## SL.ksvm_All 0.19573 0.020278 0.16095 0.26304## SL.ipredbagg_All 0.17667 0.015629 0.16473 0.18898## SL.bayesglm_All 0.16628 0.014318 0.15322 0.18022## SL.ranger.tune_All 0.17637 0.014882 0.15218 0.19793## SL.ipredbagg.tune_All 0.17813 0.015869 0.16455 0.19260技术支持
# Set the seed
set.seed(150)# Create the tuned model
model.tune <- SuperLearner(y,
x,
SL.library=list("SL.ranger","SL.ksvm","SL.ipredbagg","SL.bayesglm","SL.ranger.tune","SL.ipredbagg.tune"))# Return the tuned model
model.tune技术支持
# Set the seed
set.seed(150)# Create a second tuned model
cv.model.tune2 <- CV.SuperLearner(y,
x,
V=5,
SL.library=list("SL.ranger","SL.ksvm","SL.ipredbagg","SL.bayesglm",
learner$names,
learner2$names))# Get summary statistics
summary(cv.model.tune2)技术支持
## ## Call: ## CV.SuperLearner(Y = y, X = x, V = 5, SL.library = list("SL.ranger", ## "SL.ksvm", "SL.ipredbagg", "SL.bayesglm", learner$names, learner2$names)) ## ## ## Risk is based on: Mean Squared Error## ## All risk estimates are based on V = 5 ## ## Algorithm Ave se Min Max## Super Learner 0.17272 0.014969 0.15849 0.19844## Discrete SL 0.17250 0.014989 0.15645 0.18430## SL.ranger_All 0.17897 0.015084 0.15388 0.19920## SL.ksvm_All 0.19573 0.020278 0.16095 0.26304## SL.ipredbagg_All 0.17667 0.015629 0.16473 0.18898## SL.bayesglm_All 0.16628 0.014318 0.15322 0.18022## SL.ranger_1_All 0.17637 0.014882 0.15218 0.19793## SL.ipredbagg_1_All 0.17813 0.015869 0.16455 0.19260技术支持
您是否曾想构建一个机器学习集成模型,却不知道从何入手?本教程将通过
SuperLearner带您上手。这个 R 包通过提供标准化封装器,调用诸如glmnet、knn、randomForest等流行 R 机器学习库,用高级函数轻松创建机器学习集成模型!在本教程中,您将学习以下主题:
SuperLearner,它到底做什么?SuperLearner在 R 中进行集成学习:本节将教您如何安装所需包、准备数据并创建您的第一个集成模型!您还将看到如何训练模型并用其进行预测。在此过程中,您将涉及核支持向量机、贝叶斯广义线性模型以及袋装法。最后,您将了解如何调参以进一步提升模型表现!完成后,您将训练出第一个集成模型、对新数据进行预测,并对集成中的部分组件进行了调优。
什么是集成?
这些都很棒,但集成究竟是什么?
集成是将多个机器学习模型的概率预测或数值预测进行组合:可以取平均、对各模型加权后求和,或在分类问题中采用多数表决。这会形成“多票决策”的情形,更可能将预测推向正确的类别,或在回归中更接近真实数值。集成往往在各基模型存在分歧时效果最佳。实践中,组合多个模型通常表现良好,往往优于单一算法的实现。
您可以通过分别拟合多个模型、分别预测并再将其结果合并的方式手动创建集成。
为什么选择
SuperLearner?既然您已经了解什么是集成,您可能会问
SuperLearner库究竟做什么。简单来说,SuperLearner是一种算法,它使用交叉验证来评估多个机器学习模型(或同一模型在不同设置下)的性能。随后,它基于测试数据上的性能,为这些模型创建一个最优加权平均,也就是所谓的“集成”。但为什么要使用
SuperLearner?尽管您将在教程中进一步体会这个R 包的强大之处,您已经可以先参考以下优势:
SuperLearner允许您只需添加算法即可拟合集成模型SuperLearner使用交叉验证,本质上用来估计所有模型的风险。这使其非常适合模型比较!SuperLearner通过自动估计集成权重,让集成更高效。这通常是一项繁琐且需要大量试验的任务。SuperLearner会自动移除对集成预测能力无贡献的模型,让您可以放心尝试大量算法!下面来看一下使用
SuperLearner的流程。使用
SuperLearner在 R 中进行集成学习安装
SuperLearner包可以使用
install.packages()从 CRAN 安装SuperLearner,然后用library()加载到工作空间:准备数据
为演示
SuperLearner,您将使用MASS包中的 Pima 印第安妇女数据集。MASS 包包含训练集(用于训练模型)和测试集(用于评估模型在未见数据上的性能)。该数据集提供了有关 Pima 印第安妇女的一些描述性特征,如怀孕次数、年龄以及是否患有糖尿病。数据集的目标是预测糖尿病。type列用于指示是否患有糖尿病。它是一个二元Yes/No列,这意味着它服从二项分布。注意,不做过多理论展开,二项分布是伯努利试验(成功/失败概率试验)的集合。二项分布很容易识别,因为只有两种可能的响应,在这里即
Yes或No。为什么要提这个?因为SuperLearner需要您定义模型所属问题的分布族。稍后在拟合模型时,您将更详细地看到这一点。提示:如果想获取关于该数据集变量的更多信息,可像这样使用
help()函数:运行上述命令后,您会得出
type列表示糖尿病。在分类问题中,
SuperLearner还要求对响应变量进行编码。由于您在解决二项分类问题,您将把type变量的因子编码为 0-1:由于
type列是因子,R 会将其编码为 1 和 2,但这并非您想要的:理想情况下,类型应编码为 0 和 1,分别对应 "No" 和 "Yes"。在上述代码中,您对整列减去1来得到 0-1 编码。R 也会按照因子顺序进行编码。该包还要求将预测变量(
X)和响应(Y)放在各自的数据结构中。您已在上文拆出了Y,现在需要拆出X。同时也拆分测试集:注意,有些算法不仅需要数据框,还需要以数据框保存的模型矩阵。
nnet算法就是一个例子。在回归问题中,几乎总是会使用模型矩阵来为 SuperLearner 存储数据。模型矩阵的作用是将因子变量拆分为各自的列,并将其从文本值重编码为 0-1 值。它不会影响数值列。模型矩阵会增加算法需要处理的列数,因此可能增加计算时间。对于像本例这样的小数据集,影响很小,但更大的数据集可能会受到较大影响。结论是:在拟合模型前,先决定您要尝试哪些算法。在这个简单示例中,您将直接使用已有的数据框结构。使用
SuperLearner训练您的第一个集成模型要开始创建第一个模型,您可以用以下命令预览包中可用的模型:
您会注意到有预测算法封装器和筛选算法封装器。其中包含了一些可用于分类、回归或两者皆可的流行库。筛选算法由
SuperLearner用于自动变量选择。当您要使用上述列表中的某个算法时,需要在环境中安装对应的包。这是因为
SuperLearner实际会调用这些包并在使用该方法时拟合模型。这也意味着,例如如果您从不使用SL.caret方法,就不需要安装caret包。拟合模型很简单,但我们将用单模型示例一步步走过。
您将拟合 Ranger 算法,它是著名随机森林的更快实现。
回顾:随机森林是一种强大的方法,本质上是对决策树的集成。决策树通过观察数据并在模型中的各变量之间计算概率划分,从而为您的预测提供路径。决策树容易对数据过拟合,也就是对新数据泛化较差。随机森林通过基于多次数据样本生长多棵决策树,并对这些预测取平均来解决该问题。它还会在每个样本中仅选择特征子集,这也是它区别于树的袋装法之处。这样构建出的模型不会对数据过拟合。是不是很酷?
在本例中,您可能需要先用
install.packages()安装ranger包,才能开始拟合模型。完成后,您可以在
SuperLearner()函数中使用SL.ranger。由于随机森林(以及 Ranger)在算法中包含随机采样,多次拟合将不会得到相同结果。因此在本练习中,您将设置随机种子,以便复现实验并在同一随机基线下比较多个模型。R 使用
set.seed()设置随机种子。种子可以是任意数字,这里使用150。SuperLearner需要Y(目标/响应变量)、X(预测变量)、family(可为高斯或二项),以及以列表形式给出的库。在此即SL.ranger。还记得之前关于二项分布的讨论吗?现在您就明白了:若使用高斯族,您的 0-1 范围预测将不合适。
接着,简单打印模型将给出系数(算法在模型中的权重)和风险(算法产生的误差)。在幕后,包会拟合集成中使用的每个算法以产生风险指标。
此处风险小于 0.20。当然,这需要通过外部交叉验证和测试集进一步检验,但这是个不错的开始。
SuperLearner的妙处在于它尝试通过交叉验证自动构建集成。当然,如果只有一个模型,它就会获得集成的全部权重。单模型不错,但不借助
SuperLearner也能做到。那如何拟合集成模型呢?在 R 中训练集成:核支持向量机、贝叶斯 GLM 与袋装法
使用 SuperLearner 进行集成就是选择要用的算法这么简单。本例中,我们添加来自
kernlab包的核支持向量机(KSVM)、来自arm包的贝叶斯广义线性模型(GLM),以及来自ipred包的袋装法。但 KSVM 和贝叶斯 GLM 是什么?
KSVM 使用所谓的“核技巧”来计算点与点之间的距离。相比在特征空间中绘图并计算坐标,核方法计算点之间的内积,从而更快。随后,支持向量机用于在分类中学习点之间的非线性边界。支持向量机尝试在常常非线性的机器学习问题中为两类创建一条“间隔”。然后根据新点在空间中的位置,将其分类到间隔两侧之一。
贝叶斯 GLM 模型在这里可以看作是逻辑回归的一种实现,至少在您处理 0-1 分类时如此。贝叶斯 GLM 与 KSVM 的不同在于它使用扩展的回归算法在每一步更新系数。袋装法与上述随机森林相似,但不对子特征进行抽样。这意味着您将从随机样本中生长多棵决策树,并将它们的预测取平均来得到最终预测。
现在,让我们拟合第一个集成!
提示:别忘了先安装这些包!此外,您可能还会被提示安装其他依赖包。
加入这些算法后模型得到了改进,格局也随之改变。Ranger 和 KVSM 的系数为 0,意味着它们不再被加权到集成中。贝叶斯 GLM 和袋装法构成了模型权重的其余部分。您会注意到
SuperLearner在为您计算风险并决定能降低误差的最优模型组合。要理解每个模型对整体模型的具体贡献及其变异性,您可以使用
SuperLearner的内部交叉验证函数CV.SuperLearner()。可用V参数设置折数,此处设为5:交叉验证的摘要显示了模型的平均风险、模型的变异性以及风险的范围。
绘图还能直观展示所用模型及其变异性:
很容易看出,贝叶斯 GLM 的平均表现最好,而 KSVM 表现最差,且相较其他模型具有更大的变异性。
SuperLearner的妙处在于:若某个模型拟合不佳或贡献不大,它的权重会被设为 0!除非您计划今后重新训练模型,否则无需移除并重训。只要记住,合理的模型训练应包括对整个模型进行交叉验证。在真实场景中,这就是在预测新数据前评估模型风险的方式。使用 SuperLearner 进行预测
使用专用命令
predict.SuperLearner(),您可以轻松对新数据集进行预测。这意味着您不能使用普通的predict()函数!predict.SuperLearner()接受一个模型参数(SuperLearner 拟合对象)以及待预测的新数据。预测结果首先返回整体集成的预测:它还会返回各基学习器的单独预测:
这可让您查看每个模型如何对每个观测进行分类,有助于调试模型或一次性拟合多个模型以决定后续使用哪一个。
您可能注意到返回的是概率形式的预测量。这意味着您需要一个阈值来判定分类为 1 还是 0。只有在二项分类情形下需要这样做,回归不需要。
通常应在训练时通过交叉验证来确定阈值,但为简化起见,这里使用 0.50。由于这是一个简单的二项问题,您将使用
dplyr的ifelse()将概率重编码:现在,您可以用
caret构建混淆矩阵来查看结果:在该数据集上,您的准确率约为 0.7921687,这个表现不错。虽然许多算法可以得到更高分数,但对于一个快速集成来说已经很好了。通过在训练中使用交叉验证并尝试不同模型,您很容易进一步提升分数。
超参数调优
虽然当前表现并不差,但您可以通过调优集成中某些模型的超参数来进一步提升性能。Ranger 在您的模型中权重不高,可能是因为需要更多的树并调优 mtry 参数。您也许还能通过将
nbagg参数从默认的25提升到250来改进袋装法。有两种方法可以做到:要么定义一个函数来调用学习器并修改参数,要么使用
create.Learner()函数。接下来您将了解这些选项。定义函数
第一种方法借助
function()。您可以定义一个函数来调用学习器并修改参数。函数调用使用省略号...传递附加参数。三个点允许对公式进行修改,而无需在函数中显式指定修改内容。这意味着如果要更改 10 个参数,无需在函数中创建 10 个对象与之对应。这是一种通用的函数写法。SL.ranger.tune是您修改后的ranger方法名,SL.ipredbagg.tune是您修改后的ipredbagg方法名。现在已经创建了新的学习器函数,您可以将它们传递给交叉验证公式,看看性能是否提升。注意,您会在算法列表中保留原始的
SL.ranger和SL.ipredbagg,以比较调优版本是否带来提升。从图中可以看到,随着在
SL.ipredbagg.tune中增大nbagg参数,ipredbagg似乎有所提升。Ranger在调参后似乎变差,但我们先保留它,看看 SuperLearner 是否认为它仍有用。再次强调,妙处在于如果某算法无关紧要,
SuperLearner会直接将其权重设为 0。请记住,最好的集成并非由单个表现最好的算法组成,而是由彼此互补、共同完成分类任务的算法组成。让我们用调好的参数拟合新模型,看看权重如何:
现在,
SL.bayesglm和SL.ipredbagg.tune成为仅有的两个带权算法。用测试集进行预测得到如下结果:这在测试集上带来了小幅提升,并展示了使用
SuperLearner进行模型调优的思路。create.Learner()第二种调参方法是使用
create.Learner()函数。它允许您定制现有的SuperLearner:create.Learner()的第一个参数是学习器名称字符串。然后传递一个参数列表以修改。这会创建一个对象:现在,将该学习器传给 SuperLearner 时,使用该对象中的 names 成员:
最终结果与第一种方法相同。使用哪种方式取决于您的偏好。
更多 R 中的集成模型与机器学习
哇,您已经覆盖了很多内容!现在,您应当已经熟悉 SuperLearner,并成功用它训练了第一个集成。这个包让快速添加模型变得非常容易。需要注意的是,方法和数据形式上有一些细微之处。不过,如果拿不准,将模型矩阵以数据框保存几乎总能奏效。
回顾一下,您安装并加载了
SuperLearner,整理了数据集,拟合了单个模型,训练了第一个集成,用集成进行了预测,并调优了一些超参数!下一步可以尝试该包的一些高级主题,如并行化、特征选择与筛选、使用模型矩阵、编写您自己的 SuperLearner,以及集成交叉验证。
查看 DataCamp 的R 机器学习入门教程。