使Caret的通用特征选择更快

3

我正在尝试使用Caret的遗传算法进行特征选择,以优化xgboost树

results <- gafs(iris[,1:4], iris[,5],
               iters = 2,
               method = "xgbTree",
               metric = "Accuracy",
               gafsControl = gafsControl(functions=caretGA, method="cv", repeats=2, verbose = TRUE),
               trConrol = trainControl(method = "cv", classProbs = TRUE, verboseIter = TRUE)
               )

然而,这非常缓慢,尽管我只使用了iters = 2,而不是更适合的iters = 200。我该怎么做才能使它更快?


并行化,减小“popSize”,“repeats = 1”,... - Julius Vainora
@JuliusVainora:我应该使用什么“popSize”,如何并行化? - Make42
不确定popSize的建议是什么。?gafs中"Details"部分的结尾是关于并行化的。 - Julius Vainora
1个回答

3
以下是使用doParallel包并修改其他参数以加速gafs()函数的并行化示例。在可能的情况下,我会包含运行时间。
原始代码使用交叉验证(method =“cv”),而不是重复交叉验证(method =“repeatedcv”),因此我认为repeats = 2参数被忽略了。我没有在并行化的示例中包含该选项。
首先,使用原始代码而没有任何修改或并行化:
> library(caret)
> data(iris)

> set.seed(1)
> st.01 <- system.time(results.01 <- gafs(iris[,1:4], iris[,5],
                                          iters  = 2, 
                                          method = "xgbTree", 
                                          metric = "Accuracy",
                                          gafsControl = gafsControl(functions = caretGA, 
                                                                    method  = "cv", 
                                                                    repeats = 2, 
                                                                    verbose = TRUE),
                                          trConrol = trainControl(method = "cv", 
                                                                  classProbs  = TRUE, 
                                                                  verboseIter = TRUE)))

Fold01 1 0.9596575 (1)
Fold01 2 0.9596575->0.9667641 (1->1, 100.0%) *
Fold02 1 0.9598146 (1)
Fold02 2 0.9598146->0.9641482 (1->1, 100.0%) *
Fold03 1 0.9502661 (1)

我运行了上述代码一整夜(8至10小时),但因为运行时间过长而停止了它的运行。非常粗略的估计,运行时间至少需要24小时。
其次,包括将popSize参数(从50降至20)、在gafsControl()中添加allowParallelgenParallel选项,以及在gafsControl()trControl()中将折叠数目(从10降至5)降低:
> library(doParallel)
> cl <- makePSOCKcluster(detectCores() - 1)
> registerDoParallel(cl)

> set.seed(1)
> st.09 <- system.time(results.09 <- gafs(iris[,1:4], iris[,5],
                                          iters   = 2, 
                                          popSize = 20, 
                                          method  = "xgbTree", 
                                          metric  = "Accuracy",
                                          gafsControl = gafsControl(functions = caretGA, 
                                                                    method    = "cv", 
                                                                    number    = 5, 
                                                                    verbose   = TRUE, 
                                                                    allowParallel = TRUE, 
                                                                    genParallel   = TRUE),
                                          trConrol = trainControl(method      = "cv", 
                                                                  number      = 5, 
                                                                  classProbs  = TRUE, 
                                                                  verboseIter = TRUE)))

 final GA
 1 0.9508099 (4)
 2 0.9508099->0.9561501 (4->1, 25.0%) *
 final model
> st.09
   user   system  elapsed
   3.536    0.173 4152.988

我的系统有4个核心,但按规定只使用了3个,我验证了它正在运行3个R进程。

gafsControl()文档描述了allowParallelgenParallel的含义:

  • allowParallel:如果加载并可用并行后端,函数是否应该使用它?

  • genParallel:如果加载并可用并行后端,'gafs'是否应该在一次重新采样中一个生成内并行化适应性计算?

caret文档建议allowParallel选项将比genParallel选项提供更大的运行时改进: https://topepo.github.io/caret/feature-selection-using-genetic-algorithms.html

我期望并行化代码与原始代码会略有不同的结果。这是并行化代码的结果:

> results.09

Genetic Algorithm Feature Selection

150 samples
4 predictors
3 classes: 'setosa', 'versicolor', 'virginica'

Maximum generations: 2
Population per generation: 20
Crossover probability: 0.8
Mutation probability: 0.1
Elitism: 0

Internal performance values: Accuracy, Kappa
Subset selection driven to maximize internal Accuracy

External performance values: Accuracy, Kappa
Best iteration chose by maximizing external Accuracy
External resampling method: Cross-Validated (5 fold)

During resampling:
  * the top 4 selected variables (out of a possible 4):
    Petal.Width (80%), Petal.Length (40%), Sepal.Length (20%), Sepal.Width (20%)
  * on average, 1.6 variables were selected (min = 1, max = 4)

In the final search using the entire training set:
   * 4 features selected at iteration 1 including:
     Sepal.Length, Sepal.Width, Petal.Length, Petal.Width
   * external performance at this iteration is

   Accuracy       Kappa
     0.9467      0.9200

1
这个训练时间太长了!鸢尾花数据集非常小。任何人都怎么可能希望xgboost在实际工业数据集上以合理的时间完成...我不是分类方面的专家(我主要研究无监督方法),所以我真的很惊讶 - 如果不是困惑的话...这里到底发生了什么? - Make42
第二个版本运行了多长时间? - Make42
我同意,培训时间太长了。不过有两个交叉验证级别。我敢打赌,除非gafs()被调用太多次,否则它在xgboost方面不会很慢。我猜它在遗传算法方面很慢。caret包中的另一种替代特征选择方法是“模拟退火特征选择”函数safs(),但这也有两个交叉验证级别。一个稍微不同的选择是使用正则化方法进行特征选择,比如glmnet,使用train()函数只需要一个交叉验证级别。 - makeyourownmaker
我尝试使用lineprof包对gafs()函数进行分析,以查看它在哪里花费了大部分时间。正如预期的那样,它运行得慢得多。我在3天后停止了分析。是否还有其他内容可以添加到这个答案中以使其被接受? - makeyourownmaker
1
我猜答案是“只能做这么多”;-)。我会接受的。 - Make42
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接