深度神经网络 (第六部分)。 神经网络分类器的融合: 引导聚合·综合运用
📘

深度神经网络 (第六部分)。 神经网络分类器的融合: 引导聚合·综合运用

第 3/3 篇

极限学习机集成的R回测与贝叶斯调参

这段 R 脚本用 elmNN 包搭了一个极限学习机(ELM)集成,再用贝叶斯优化搜参数。外汇与贵金属行情用这类集成做方向分类时,样本外表现仅具概率意义,实盘高风险,别直接当信号源。 集成训练部分先按 rng 种子循环生成 n 个 ELM 模型,每个都用 holdout 按 ratio=r/10 切训练集;预测阶段把 n 个模型输出按列合并成 y.pr,再以 0.5 为阈值转 0/1,算 F1 选前 (numEns*2+1) 个最优模型做平均集成。 直接跑 fitnes(numFeature=10, r=7, nh=5, fact=2) 在本地耗时约 7.86 秒(elapsed),得到的样本外 F1 为 0.761。 换 BayesianOptimization 搜参,init_points=10、n_iter=20、ucb 采集函数、kappa=2.576,第 23 轮摸到最优:numFeature=8、r=3、nh=3、fact=7,F1 抬到 0.777;历史前二组分别是 (8,3,3,7)→0.777 与 (8,1,5,7)→0.767。MT5 侧虽跑不了 R,但可把这套特征数=8、隐藏节点=3 的设定挪到自编 ELM 指标里对照品种波动率验证。

MQL5 / C++
Ens <- foreach(i = class="num">1:n, .packages = "elmNN") %do% {
  rngtools::setRNG(rng[[k]])
  idx <- rminer::holdout(Ytrain, ratio = r/class="num">10, mode = "random")$tr
  k <- k + class="num">1
  elmtrain(x = Xtrain[idx, ], y = Ytrain[idx],
           nhid = nh, actfun = Fact[fact])
}
setMKLthreads(class="num">2)
#---predict---
Xtest <- X$train$x[ , bestF]
foreach(i = class="num">1:n, .packages = "elmNN", .combine = "cbind") %do% {
  predict(Ens[[i]], newdata = Xtest)
} -> y.pr #[ ,n]
#---best---
foreach(i = class="num">1:n, .combine = "c") %do% {
  ifelse(y.pr[ ,i] > class="num">0.5, class="num">1, class="num">0) -> Ypred
  Evaluate(actual = Ytest, predicted = Ypred)$Metrics$F1 %>%
    mean()
} -> Score
Score %>% order(decreasing = TRUE) %>%
  head((numEns*class="num">2 + class="num">1)) -> bestNN
#---test-aver--------
Xtest1 <- X$test$x[ , bestF]
foreach(i = class="num">1:n, .packages = "elmNN", .combine = "+") %:%
  when(i %in% bestNN) %do% {
    predict(Ens[[i]], newdata = Xtest1)} %>%
  divide_by(length(bestNN)) -> ensPred
ifelse(ensPred > class="num">0.5, class="num">1, class="num">0) -> ensPred
Evaluate(actual = Ytest1, predicted = ensPred)$Metrics$F1 %>%
  mean() %>% round(class="num">3) -> Score
class="kw">return(list(Score = Score, Pred = ensPred))
}
}, env)
#----------
evalq(
  system.time(
   res <- fitnes(numFeature = class="num">10, r = class="num">7, nh = class="num">5, fact = class="num">2)
  )
, env)
user  system elapsed
  class="num">8.65    class="num">0.19    class="num">7.86
> env$res$Score
[class="num">1] class="num">0.761
#------
evalq(
  OPT_Res <- BayesianOptimization(fitnes, bounds = bonds,
                            init_grid_dt = NULL, init_points = class="num">10,
                            n_iter = class="num">20, acq = "ucb", kappa = class="num">2.576,
                            eps = class="num">0.0, verbose = TRUE)
, envir = env)
Best Parameters Found:
  Round = class="num">23  numFeature = class="num">8.0000  r = class="num">3.0000  nh = class="num">3.0000  fact = class="num">7.0000      Value = class="num">0.7770
evalq({
  OPT_Res %$% History %>% dplyr::arrange(desc(Value)) %>% head(class="num">10) %>%
    dplyr::select(-Round) -> best.init
  best.init
}, env)
numFeature r nh fact Value
class="num">1          class="num">8 class="num">3  class="num">3    class="num">7 class="num">0.777
class="num">2          class="num">8 class="num">1  class="num">5    class="num">7 class="num">0.767

「集成模型在测试集上的衰减轨迹」

上面那组数字不是装饰,是某外汇品种特征筛选后逐轮训练集的规模与相关系数:第3轮 8/3/2/7 对应 0.760,到第10轮变成 11/2/24/4 对应 0.751,说明随着扰动样本放大,集成内单模型的相关性在缓慢走低。 这种走低不一定是好事——当第10轮出现 24 这个异常大的第三列值时,往往意味着某次 holdout 切分抽到了极端行情片段,外汇与贵金属的高波动特性会放大这类偏差。 下面这段 R 脚本做的是训练最优集成并做测试集平均预测,虽不是 MQL5 直接运行,但参数逻辑(numFeature=8、r=3、nh=3、fact=7)可直接映射到 MT5 特征工程的输入维度。 别把单次 F1 最高的模型当终局 代码里用 Score 排序取 head(numEns*2+1) 而不是只取 top1,是因为极端行情下单一 ELM 网容易过拟合;取 7 个做等权平均,测试集稳定性倾向更好,但回测收益仍可能随品种切换而漂移。

MQL5 / C++
#--class="num">1-Train--optEns-predict--best--test-average------------------------
evalq({
  Ytrain <- X$pretrain$y
  Ytest <- X$train$y
  Ytest1 <- X$test$y
  n <- class="num">500
  numEns <- class="num">3
  #--BestParams--------------------------
  best.par <- OPT_Res$Best_Par %>% unname
  numFeature <- best.par[class="num">1] # 8L
  r <- best.par[class="num">2]          # 3L
  nh <- best.par[class="num">3]         # 3L
  fact <- best.par[class="num">4]       # 7L
  bestF <- orderX %>% head(numFeature)
  Xtrain <- X$pretrain$x[ , bestF]
  setMKLthreads(class="num">1)
  k <- class="num">1
  rng <- RNGseq(n, class="num">12345)
  #---train---
  OptEns <- foreach(i = class="num">1:n, .packages = "elmNN") %do% {
    rngtools::setRNG(rng[[k]])
    idx <- rminer::holdout(Ytrain, ratio = r/class="num">10, mode = "random")$tr
    k <- k + class="num">1
    elmtrain(x = Xtrain[idx, ], y = Ytrain[idx],
             nhid = nh, actfun = Fact[fact])
  }
  setMKLthreads(class="num">2)
  #---predict---
  Xtest <- X$train$x[ , bestF]
  foreach(i = class="num">1:n, .packages = "elmNN", .combine = "cbind") %do% {
    predict(OptEns[[i]], newdata = Xtest)
  } -> y.pr #[ ,n]
  #---best---
  foreach(i = class="num">1:n, .combine = "c") %do% {
    ifelse(y.pr[ ,i] > class="num">0.5, class="num">1, class="num">0) -> Ypred
    Evaluate(actual = Ytest, predicted = Ypred)$Metrics$F1 %>%
      mean()
  } -> Score
  Score %>% order(decreasing = TRUE) %>%
    head((numEns*class="num">2 + class="num">1)) -> bestNN
  #---test-aver--------
  Xtest1 <- X$test$x[ , bestF]
  foreach(i = class="num">1:n, .packages = "elmNN", .combine = "+") %:%
    when(i %in% bestNN) %do% {
      predict(OptEns[[i]], newdata = Xtest1)} %>%
    divide_by(length(bestNN)) -> ensPred

◍ 集成模型在样本外集上的分类表现

把集成预测概率以 0.5 为阈值二值化后,在测试集 Ytest1 上跑混淆矩阵,整体准确率落在 0.778,Kappa 系数 0.5549,说明模型相较「无信息率 0.5269」的盲猜有实质提升,P 值小于 2e-16 基本排除了随机巧合。 分标签看,类 0 的精确率 0.751、召回 0.774、F1 0.762;类 1 的精确率 0.803、召回 0.782、F1 0.793。混淆矩阵里 178 例真 0 判对、212 例真 1 判对,误判各 52 与 59,两类错分较均衡。 最优神经网络的得分序列里,头部模型 Score 在 0.7099~0.7263 之间波动,bestNN 取最高 0.7263 那一只。外汇与贵金属行情受杠杆与跳空影响,这类统计优势只代表历史样本外概率倾向,实盘仍需以小仓位验证。

MQL5 / C++
  ifelse(ensPred > class="num">0.5, class="num">1, class="num">0) -> ensPred
  Evaluate(actual = Ytest1, predicted = ensPred)$Metrics[ ,class="num">2:class="num">5] %>%
    round(class="num">3) -> OptScore
  caret::confusionMatrix(Ytest1, ensPred) -> cm
}, env)
> env$Score[env$bestNN]
[class="num">1] class="num">0.7262701 class="num">0.7220685 class="num">0.7144137 class="num">0.7129644 class="num">0.7126606 class="num">0.7101981  class="num">0.7099502
> env$OptScore
  Accuracy Precision Recall    F1
class="num">0    class="num">0.778     class="num">0.751  class="num">0.774 class="num">0.762
class="num">1    class="num">0.778     class="num">0.803  class="num">0.782 class="num">0.793
> env$cm
Confusion Matrix and Statistics
             Reference
Prediction   class="num">0   class="num">1
           class="num">0 class="num">178  class="num">52
           class="num">1  class="num">59 class="num">212

               Accuracy : class="num">0.7784
                class="num">95% CI : (class="num">0.7395, class="num">0.8141)
 No Information Rate : class="num">0.5269
 P-Value [Acc > NIR] : <class="num">2e-16

                   Kappa : class="num">0.5549
Mcnemar&class="macro">#x27;s Test P-Value : class="num">0.569

            Sensitivity : class="num">0.7511
            Specificity : class="num">0.8030
         Pos Pred Value : class="num">0.7739
         Neg Pred Value : class="num">0.7823
             Prevalence : class="num">0.4731
         Detection Rate : class="num">0.3553
   Detection Prevalence : class="num">0.4591
     Balanced Accuracy : class="num">0.7770

       &class="macro">#x27;Positive&class="macro">#x27; Class : class="num">0

融合分类器在 MT5 里的有效期与提升空间

ELM 神经网络组成的轻量融合分类器,分类品质已能逼近更复杂的 DNN,但真正值得在 MT5 里验证的是它的「保鲜期」。回测显示,训练后的融合在脱离训练集一半深度后仍能保持品质,最长可维持约 750 根柱线,而同条件下 DNN 只能撑到 250 根柱线。 单体分类器超参数优化把准确率拉到 Acc=0.77(95% 置信区间 0.73–0.81),多数表决与平均融合效果接近。若把连续预测值用校准或遗传搜索找最优截止阈值,品质还能再抬一截。 用可训练模型做合并器(堆叠)是下一步值得试的路线,可以是单个神经网络,也可以是神经网络的再融合。外汇与贵金属行情高风险,这类概率型信号只作辅助,实盘前请在 MT5 用历史数据跑一遍柱线衰减曲线。

「把这条线请下神坛」

随文打包的 GitHub/PartVI 里是六份 R 语言素材:函数集、训练测试脚本、超参优化脚本,外加两份环境清单和 ELM 文献压缩包。想在本地复现融合实验,先把 FUN_Ensemble.R 和 RUN_Ensemble.R 按顺序跑通,SessionInfo 文件能帮你对齐包版本,少踩依赖坑。 作者自己在评论区留过一组实测:10 个 DNN Darch 片段做平均融合, ensemble 的 osh=33%,反而略差于单模型最佳的 31%,最差误差 34%。结论很直白——融合不是万能膏药,对训练充分的强模型,简单平均常常不灵;它更适配 ELM 这类弱而不稳的网络。 外汇与贵金属市场高波动、高杠杆,任何模型融合方案都只是概率工具,实盘前请用 MT5 做历史回测与样本外验证。这条技术线值得玩,但别把它供成必胜法器。

常见问题

对比训练集与测试集的准确率落差,若测试集掉点超过5%且样本外集继续下滑,大概率过拟合,需降基学习器数量。
多是基分类器相关性过高或贝叶斯调参只盯验证集,建议重采样拉开多样性,并留出独立样本外集复核。
小布会按品种页加载样本外表现与衰减曲线,标出有效期临界,你直接看预警色决定是否重训。
样本外观察倾向2~4周失效,靠滚动重训与降低学习率可缓衰,但外汇贵金属高风险,须严控仓位。
调参目标窄化导致择偶偏差,应改用分层K折加样本外早停,别把验证集当终极标准。