5. 模型训练和调参
内容:
- Model Training and Parameter Tuning
- An Example
- Basic Parameter Tuning
- Notes on Reproducibility
- Customizing the Tuning Process
- Pre-Processing Options
- Alternate Tuning Grids
- Plotting the Resampling Profile
- The trainControl Function
- Alternate Performance Metrics
- Choosing the Final Model
- Extracting Predictions and Class Probabilities
- Exploring and Comparing Resampling Distributions
- Within-Model
- Between-Models
- Fitting Models Without Parameter Tuning
5.1 Model Training and Parameter Tuning
caret包有很多函数试图精简构建模型和评估模型的过程。
train
函数能用于:
* 评估,应用抽样,模型调参的影响
* 通过参数选择最优模型
* 从训练集中评估模型表现
首先,需要选择一个具体地模型。现在,有233个可以使用;详情请看train Model List 或 train Model By Tag,在这些介绍中,有一个可被优化的参数列表。用户也可以自定义模型。
第一步就是调整模型(算法中的第一行就是选择一系列要估计的参数。例如,如果要拟合一个偏最小二乘模型,需要设定PLS估计的参数。)
一旦模型和要调整的参数值被定义,重抽样的类型也就被设定了。现在,在train中可以使用k折交叉验证(一次或重复的),留一交叉验证和自助法等抽样方法。重抽样过后,这个过程将会指导用户选择哪个参数。默认地,函数自动选择具有拥有最佳值的参数,尽管可以使用不同的算法。
5.2 An Example
mlbench
包中有一个Sonar数据集,这里,我们载入数据集:函数
createDataPartition
能创建一个分层的随机样本进入训练集和测试集:
- 1
- 2
- 3
- 4
- 5
我们将会使用这些数据来说明这些函数功能。
5.3 Basic Parameter Tuning
默认为,简单自助抽样用于上图算法的第3行。像重复k折交叉验证和留一法也可以使用。函数
trainControl
用来设动抽样类型:
- 1
- 2
- 3
- 4
- 5
更多关于
trainControl
的信息可以看下面章节。
对于一个GBM模型,有三个主要的参数:
train
的前两个参数是预测变量和结果数据对象。第三个参数method
设定模型类型(看train Model List 或 trian Model By Tag)。为了说明问题,我们会通过gbm包拟合一个boot tree模型。用重复交叉验证来拟合模型的基础语法为:
* 迭代次数, 例如,树(在gbm函数中叫做n.trees)
* 树的复杂度,称作interaction.depth
* 学习率:算法适应的有多快,叫做shrinkage
* 训练样本的最小数目(n.minobsinnode
)
检测模型的默认值在前两列给出(shrinkage
和n.minobsinnode
没有给出是因为拥有这些参数的候选模型使用同样的值)。标有accuracy
的这一列是通过交叉验证计算出的准确率。准确率的标准差从交叉验证结果中计算出。Kappa
这一列是通过重抽样结果计算的Cohen Kappa统计量(非加权)。train
函数用于具体的模型(见train Model List 和 train Mode By Tag)。对于这些模型,train
函数创建一个调整参数组。默认的,如果p是调整参数的个数,那么,参数组的大小为 3p 。做为另一个例子,正则判别分析(RDA)模型有两个参数(gamma
和lambda
),两个参数数值都在0和1之间。默认的训练参数组将会在二维空间中产生9种组合。
在为train
函数设定模型时有一些要点。在下一节将介绍train
的额外其他功能。
5.4 Notes on Reproducibility
很多模型在参数估计阶段应用随机数,重抽样切片也使用随机数,有两种主要的方法可以控制随机子以确保结果可重复。
* 有两种方法确保在调用train
函数的时候有相同的重抽样本。第一种是在调用train
之前使用set.seed
函数。随机数生成重抽样信息。另外的,如果你愿意使用特定的数据分割,可以使用trainControl
函数的index
,这将会在下面讲到。
* 当使用重抽样的模型创建后,自己自也已经创建了。在调用train
函数之前设定随机子能保证使用了相同 的随机数,当使用并行处理时这并不是一个问题。为了设定模型拟合随机子,trainControl
需要调用另外一个参数seeds
。这个参数是使用一个整数向量列表作为随机子。trainControl
的帮助页面描述了这个选项的格式。随机数怎样使用高度依赖包的作者。很少有目标模型没有控制生成随机数的,特别是在C代码中进行计算的。
5.5 Customizing the Tuning Process
有一些方法可以自定义参数选取和构建模型过程。
5.5.1 Pre-Processing Options
就像先前所提到的,
train
函数在模型拟合之前可以使用多种方法进行数据预处理。preProcess
函数可以用来中心化和标准化,插值,空间符号变换和通过PCA或独立成分分析进行特征提取。
要怎么进行预处理,train
函数有一个参数叫preProcess
,这个参数会把方法传递到preProcess
函数中,另外,preProcess
也可以通过trainControl
传递。
这些处理步骤将会应用于任何的预测过程,像predict.train, extractPrediction
或extractProbs
。预处理不会应用于直接使用object$finalModel
这种对象的预测。
对于插值,有三种主要的实施方法:如果在训练集中有缺失值,PCA和ICA只用其中的完整的样本。
- k最近邻处理带有缺失值的样本,并能在训练集中找到k个最近的样本。这k个训练集的值作为原始数据集的替代。当计算到训练集样本的距离的时候,用于计算的预测变量要求没有缺失值。
- 另一种方法是使用训练集对每一个预测变量拟合一个bag树。这是一个具有正常准确率的模型,并能处理缺失值。当一个预测变量需要插值的时候,其他预测变量将会通过bag树返回值,并且通过他们预测的值作为一个新值,但模型可能有很大的计算开销。
- 预测变量的中位数也可以用来估计缺失值。
5.5.2 Alternate Tuning Grids
调参网格可以由用户设定。参数
tuneGrid
可以传入一个数据框,列包含设定的参数。列名需要和拟合模型的参数名一致。对于前面提到的RDA的例子,参数名为gamma,lambda
.train
函数将会对每一行的参数值进行调整模型。
对于boost树模型,我们需要固定学习率,而去调整n.trees的参数:
gbmGrid <- expand.grid(interaction.depth = c(1,5,9), n.trees = (1:30)*50, shrinkage = 0.1,n.minobsinnode =20)
nrow(gbmGrid)
set.seed(825)
gbmFit2 <- train(Class ~ ., data = training, method ="gbm", trControl = fitControl, verbose = FALSE,
## Now specify the exact models
## to evaluate:
tuneGrid = gbmGrid)
gbmFit2
如果训练集中有缺失值,PCA和ICA模型只会用完整的样本。
另一个选项是应用一个随机的参数组合,例如“随机搜索”,这个函数将在下面介绍。
要应用随机搜索,那就在调用trainControl
的时候使用选项search = "random
。这种情况下,tuneLength
参数定义了要估计的参数组合的长度。
5.5.3 Plotting the Resampling Profile
plot
函数用于检验模型性能和调参之间的关系。例如,函数的调用展示了第一次拟合的结果:
可以使用
metric
选项度量性能:为了使用这个准则重新建立boost tree模型,我们可以使用下面代码观察参数和ROC曲线下面积的关系:
在这个案例中,最优参数的ROC曲线下的平均面积是0.896。
5.6 Choosing the Final Model
另一个自定义参数的过程就是修正用来选择最佳参数的算法。默认的,
train
函数选择具有最大性能值的模型,也可以使用其他模型的方案。Breiman等人建议简单的基于树的模型使用单个标准差规则。在这个案例中,识别了具有最佳性能值的模型,应用重抽样方法,我们能估计性能的标准误。最终的模型就是使用但标准差的最简单的模型。当基于树的模型刚开始出现过拟合,后来越来越适应模型的时候,这是有意义的。
train
函数允许用户设定选取最终的的规则。参数selectionFunction
用来提供能决定最终模型的函数。包中有三个函数:best
选择最大或最小值,oneSE
试图捕获Breiman等人的观点,tolerance
选择具有一定最佳值忍耐度的最简单的模型。详情请看best
。
只要拥有以下参数,用户也能自定义函数:
x
是一个数据框,包括调整参数和与他们相关联的性能度量。每一行对应一个不同参数的组合。metric
字符向量,指定那个性能度量应被优化(可以直接传递到train
函数)。maximize
逻辑值,表明一个性能度量的更大的值是否更好(可以直接传递到train
函数)。
函数应该输出一个整数值,表明x
的哪一行被选择。
作为一个例子,如果我们选择先前基于准确率的boost树模型,我们会选择:n.tree = 650,interaction.depth = 5, shrinkage = 0.1, n.minobsinnode = 20。然而,这张图中的刻度非常紧密,准确率在0.859至0.896之间。一个更简单的模型也可能有这样的准确率。
忍耐函数可以使用 (x−xbest)/xbest×100 来找出一个更简单的函数。例如,选择一个基于2%的性能损失的参数值。
whichTwoPct <- tolerance(gbmFit3$results, metric = "ROC",tol = 2, maximize = TRUE)cat("best model within 2 pct of best:\n")## best model within 2 pct of best:gbmFit3$results[whichTwoPct, 1 : 6 ]
这表明我们能得到一个更简单的模型,和具有最佳值的ROC面积0.896相比,这个模型的ROC面积为0.881.
这些函数的主要问题是怎样对模型的复杂性排序。在一些案例中,这很简单(例如简单树模型,偏最小二乘),但是在这样的模型中,模型排序是主观的。例如,一个有100次迭代,树的深度为2的boost树模型比50次迭代,深度为8的boost树更复杂吗?依据顺序,包会做出一些选择。在boost树模型案例中,包认为增加迭代次数比增加树的深度计算更快,所以,模型是先按照迭代排序然后再按照树深度排序。查看更多例子请看best
。
5.7 Extracting Predictions and Class Probabilities
先前所提到的,
train
函数产生的对象包括finalModel
里的最优模型。通过这些对象能够作出预测。在一些例子中,像pls
或gbm
对象,额外的参数需要设定。trian
的对象应用参数优化的结果对新样本进行预测。例如,如果用predict.gbm
作出预测,用户将不得不直接设定树的个数(没有默认值)。对于二分类问题,函数预测值是一种概率的形式,所以额外的步骤是要把它转化为因子向量。predict.train
会自动处理这些细节。
在R中,有很少的标准语句来进行模型的预测。例如,为了获得类概率,很多predict
方法会有一个参数type
,用它来设定生成类概率或类别。不同的包使用不同的type
值,像prob,posterior,response,probability
或raw
。在另外一些案例中,可能使用另外一些语句。
对于predict.train
函数,type
只取两个值class
和prob
。例如:
predict(gbmFit3, newdata = head(testing))
predict(gbmFit3, newdata = head(testing), type = "prob")
5.8 Exploring and Comparing Resampling Distributions
5.8.1 Within-Model
对于一个特定的模型,有很多
lattice
函数探索参数调整和重抽样结果的关系:
xyplot
和stripplot
用于画出重抽样统计量。hisstogram
和densityplot
用于查看参数调整的分布。例如,下图创建了一个密度函数:
注意到,通过多个调整参数画出重抽样结果,如果你对这个感兴趣,那么
resamples="all"
应该放入控制选项中。
5.8.2 Between-Models
set .seed( 825 )
caret
包包含一些函数,它可以通过重抽样分布把模型间的差别字符化。这些函数是基于Hothorn和Eugster等人的工作。
首先,用SVM模型拟合Sonar数据,数据通过preProc
参数进行中心化和标准化。注意到随机数要先于模型设置,并且是和boost树模型使用的随机数是一样的。这保证抽到相同的样本,这对于我们比较两个模型有帮助。svmFit <- train(Class ~ ., data = training, method = "svmRadial",trControl = fitControl, preProc = c("center","scale"),tuneLength = 8, metric = "ROC")svmFit正则判别分析模型拟合数据:
set.seed(825)rdaFit <- train(Class ~ ., data = training,method = "rda", trControl = fitControl,tuneLength = 4, metric = "ROC")rdaFit
给出这些模型,我们能做出判断谁的性能比较好吗?我们首先用
summary(resamps)resamples
收集重抽样结果。
注意到,在这个例子中,选项
trellis .par .set (theme1)resamples = "final"
应该由用户自定义。
有很多lattice作图方法用于重抽样分布的可视化:density plots,box-whiker plots, scatterplot matrices和scatterplots of summary statistics.例如:xyplot(resamps, what = "BlandAltman")
splom(resamps)
也可以应用像
fitControl <- trainControl( method = "none", classProbs = TRUE)densityplot.resamples
和parallel.resamples
的可视化。
由于模型拟合相同的数据,所以比较模型的差异显得有意义。这样,我们减少可能存在的重抽样的相关性,计算差异,然后用t检验来检验模型是否有差异。set.seed(825)gbmFit4 <- train(Class ~ ., data = training,method = "gbm", trControl = fitControl,verbose = FALSE,## Only a single model can be passed to the##function when no resamplingis used:tuneGrid = data.frame(interaction.depth = 4,n.trees = 100, shrinkage = .1,n.minobsinnode = 20),metric = "ROC")gbmFit4
注意到plot.train,resamples,confusionMatrix.train
和其他一些函数不能和这个gbmFit4对象一起使用,但是predict.train
可以:
predict(gbmFit4, newdata = head(testing))
predict(gbmFit4, newdata = head(testing), type = "prob")