机器学习模型的变量评估和选择·综合运用
🧠

机器学习模型的变量评估和选择·综合运用

(3/3)·从清理、规范化到RandomUniformForests与RoughSets双视角,收尾变量集与训练集协同筛选

进阶 第 3/3 篇
直接把原始OHLC丢进模型训练,是多数自研EA跑不出稳定回测的第一坑。预测因子若不做缺失值与近零方差清理,RandomUniformForests这类包会在仿真前就崩给你看。本篇用R语言把变量评估到样本集优化全链路拆开。

◍ 均匀随机森林的分类基线表现

用 300 棵树的均匀随机森林跑二分类,训练集与测试集各传入 x/y,mtry=1、nodesize=2、双线程。模型类型明确为 Classification,OOB 错误率 20.2%,1% 偏差边界 21.26%,袋外 AUC 0.798,说明在不调参的裸配置下已有可参考的判别力。 测试集独立验证错误率 19.97%,ROC 面积 0.8003,F1 0.7966,与 OOB 估计几乎一致,过拟合迹象弱。Breiman 边界给出期望误差 18.42%、上界 27.76%,树间平均相关性仅 0.0472,森林多样性足够。 全局变量重要度里 cci 的 score 2568、在 class 1 中出现频率 0.50 且覆盖 100% 样本,signal 的 score 2438、频率 0.51 覆盖 94.92%。这两者是目前最具预测性的特征,开 R 终端复述 summary(ruf) 就能看到完整排序。 外汇与贵金属行情受宏观事件扰动,这类信号仅代表历史样本中的概率倾向,实盘使用前建议在 MT5 用对应周期数据重算特征分布。

MQL5 / C++
randomUniformForest.class="kw">default(X = x.train, Y = y.train, xtest = x.test,
  ytest = y.test, ntree = class="num">300, mtry = class="num">1, nodesize = class="num">2, threads = class="num">2)

特征贡献排名里 slowD 排在最前

上面这张表是某次特征筛选后,按重要性得分排出来的指标序列。slowD 以 2437 分排第一,oscK 2410 分紧随,ADX 2400 分、vol 2395 分、atr 2392 分依次往下,到第 15 位的 tr 也有 2217 分,整体分差并不大,说明这些指标在模型里权重接近。 所有列入的 15 个特征,percent.importance 一列清一色是 7,等于说筛选器没有给任何一个特征打更低的重要等级,它们都被视为同档有效输入。 做外汇或贵金属策略时,这种平权结果提示你:别只盯 slowD,ADX、ATR 这类趋势与波动因子同样在起作用。MT5 里把这几列指标拉进特征矩阵跑一遍,看看你的样本集是否也给出类似的紧凑分数带。

「随机森林在 EURUSD 信号集上的实测表现」

把 15 分钟 EURUSD 的 13 个技术指标丢进随机森林做二分类(-1 空头 / 1 多头),单棵树平均节点数 1213、中位数 1313,叶节点平均 607 个,树深实测 10 层,接近平衡树的 11 层理论值。 测试集误判率 19.97%,ROC 曲线下面积 0.8003,PR 曲线下面积 0.7991,F1 分数 0.7969。混淆矩阵里空头类错判率 0.2105、多头类 0.1881,说明模型对反向样本略敏感,外汇品种高杠杆下这种偏差可能放大滑点风险。 变量重要度排前三的是 CCI(score 2568,100% 频率出现在判别路径)、signal(2438,94.92%)、slowD(2437,94.90%),ADX 虽 score 2400 但 class 标为 -1,提示它更多在空头分支起作用。 跑这套只需在 MT5 导出的 CSV 上用 R 的 randomUniformForest 包:predict 后 model.stats 直接出误差与曲线,importance 设 maxInteractions=3 就能拿到上面的交互重要度表。

◍ 变量重要度与相互作用的排序表

上面这张表是某次特征筛选后,按重要度降序列出的 15 个技术指标变量。第 6 行 vol 的索引值为 2395、符号位为 1、权重 0.51、累计重要度 93.24;到第 15 行 tr 时索引降到 2217、权重 0.52、累计重要度仅剩 86.31,说明越靠后的变量对模型的边际贡献越小。 紧随其后的 percent.importance 列给出了每个变量的局部重要度百分比:前 12 个变量(索引 1~12)统一为 7,第 13~15 个掉到 6。这个跳变点提示,在构建 MT5 上的自定义指标或 EA 特征集时,排名 13 以后的变量可能已不值得保留。 原文还提到,变量间的相互作用会针对 10 个一阶和二阶最重要的变量进行计算——也就是对每个变量,去算它和其他变量在同一顺序上的相互影响。外汇与贵金属市场波动剧烈、杠杆风险高,这类相互作用分析只能作为特征降维的参考,实际信号概率仍受行情结构影响。 开 MT5 把 vol、atr、sign、vsig、ar 这几个排前面的变量先接进你的指标原型,跑一遍样本外数据,看看累计重要度掉到 90 以下时是不是正好对应着过拟合拐点。

指标互相关矩阵里的隐性层级

把 11 个常用震荡与波动指标两两算相关系数,会得到一张对称的互相关表。上半部分以 cmo 为行首时,cmo 对 cci 的相关系数为 0.1933,对 cmo 自身当然是 1,但对 slowD 只有 0.1345,对 atr 跌到 0.1088,对 chv 仅 0.1062。 下半部分换以 ADX、tr、ar 等列为参照,cmo 对 ADX 相关系数 0.1026,对 tr 0.1022,对 ar 0.1013,对 vsig 0.1000,到 sign 剩 0.0964。cci 对 ADX 则更低,只有 0.0864。 这张表透露一件事:趋势类(ADX、DX)和波动类(atr、tr)与摆动类(cmo、cci、slowD)的相关性普遍低于 0.11,说明在 MT5 里把它们直接叠进同一个信号加权池,大概率会引入冗余度偏低的噪声而非互补。 开 MT5 用 OnTester 跑一遍 Correlation 矩阵,把自己常用的 5 个指标贴进去,看对角外最大值是否超过 0.19,超过就考虑降权其中一个。外汇与贵金属杠杆高,这类统计结论只代表样本内倾向,实盘仍可能失真。

「随机森林挑出的关键指标排序」

把 EURUSD 的 1 小时序列喂进随机均匀森林做变量重要度评估,基于相互作用的前 10 个变量里,cmo 拿到 0.1447、cci 0.1419,两者明显甩开第三名 slowD 的 0.0877,说明动量类指标在样本内对方向区分贡献最大。 按分类标签拆开看,Class -1(跌)和 Class 1(涨)的重要度分布有偏移:cci 在涨侧冲到 0.23、跌侧 0.16,cmo 则是跌侧 0.20、涨侧 0.18,意味着同一指标在多空两端的判别权重并不对称。 代码里用 Cs() 把 cci、cmo、slowD、oscK、signal、tr、ADX、chv、atr、ar 这 10 个变量锁成 best,再分别切出训练集和测试集的对应列。你在 MT5 里导出这 10 个指标到 csv,用 R 的 randomUniformForest 跑一遍,能复现上面那张重要度表。 外汇与贵金属为高杠杆品种,模型重要度只反映历史样本结构,实盘信号失效概率不低,参数和品种切换后需重测。

MQL5 / C++
> best <- Cs(cci, cmo,  slowD, oscK, signal, tr, ADX. chv, atr, ar)
> x.tr <- x.train[ ,best]
> x.tst <- x.test[ ,best]
> ruf.opt <- randomUniformForest(X = x.tr,
+                                 Y = y.train,
+                                 xtest = x.tst,

◍ 随机均匀森林的袋外评估与测试集误差

把分类标记从 -1/1 转成 1/2 只是内部替换的便利操作,不影响模型对外判定的逻辑。真正要看的是 randomUniformForest 在 300 棵树、nodesize=1、mtry='random'、双线程下的实际表现。 袋外(OOB)误差率落在 18.69%,1% 偏差边界为 19.67%;OOB 混淆矩阵里 -1 类错分 253 个、1 类错分 241 个,两类 class.error 分别为 0.1899 与 0.1838,说明样本均衡度尚可。OOB 的 AUC 读到 0.8131,AUPR 0.7381,F1 0.8125。 Breiman 边界给出:在近似平衡类下期望预测误差 14.98%,上界 28.18%;树间平均相关仅 0.0666,强度 margin 0.5548。低相关性是高维外汇特征下泛化倾向不崩的底气。 用 predict 对 x.tst 跑响应预测,再拿 model.stats 核对 y.test,测试集错误率 17.55%,略优于 OOB 估计。外汇与贵金属行情高风险,这套指标只代表历史样本概率,实盘须以 MT5 接数据重跑验证。

MQL5 / C++
ytest = y.test,
ntree = class="num">300,
mtry = "random",
nodesize = class="num">1,
threads = class="num">2)

随机森林的特征重要度拆解

用优化后的随机森林跑测试集,混淆矩阵显示 -1 类错分 124 个、1 类错分 108 个,class.error 分别为 0.1834 与 0.1672;ROC 曲线下面积 0.8245,PR 曲线下面积 0.8212,F1 0.8226,几何均值 0.8244,说明这套特征组合在样本外有中等偏上的判别力。 通过 importance(ruf.opt, Xtest = x.tst) 提取全局重要度,按信息增益 score 排序取前 10:atr(3556)、oscK(3487)、chv(3465)、signal(3432)、cci(3424)、slowD(3415)、ADX(3397)、ar(3369)、tr(3221)、cmo(3177)。其中 atr、oscK、ADX、ar、cmo 更倾向判别 -1 类,chv、signal、cci、slowD、tr 更倾向判别 1 类,class.frequency 都在 0.50~0.53 之间。 光看 score 不够,还得把 class 与 class.frequency 一起核对,才能知道哪些变量是真正具判别能力的,而不是单纯信息量大。外汇与贵金属波动受事件驱动,模型外推存在失效可能,实盘前务必在 MT5 用历史数据复算一遍重要度排名。 局部变量重要度可进一步看单样本贡献,避免被全局均值掩盖个别行情下的特征反转。

MQL5 / C++
> imp.ruf.opt <- importance(ruf.opt, Xtest = x.tst)

「指标交叉影响的量化读数」

把 10 个一阶与二阶关键变量两两配对,能算出每个变量在各自排序位上对其它变量的相互作用强度。表格里横纵都是 atr、cci、oscK、slowD、ADX、tr、chv 等常见波动与摆动类指标,数值越大代表该组合的解释权重越高。 以 cci 行为例,它对 atr 的作用读数为 0.1748,对 cci 自身排序后的首变量为 0.1625,对 oscK 为 0.1620,随后 slowD、ADX、tr、chv 依次落到 0.1439–0.1349 区间。atr 作为行首时,对同列变量的读数从 0.1650 递减到 0.1251,整体比 cci 行低约 0.01 个点,说明在样本里 cci 的边缘影响力略占优。 二阶部分(avg2ndOrder 列)把信号、ar、cmo 等再压缩一层:cci 对应的二阶值为 0.1412,atr 为 0.1313,oscK 为 0.1249,越往后越小。做特征筛选时,可以直接砍掉 cmo 这类二阶值仅 0.0939 的尾段变量,给 MT5 上的自定义 EA 减负。 别把正态当圣经 这些相互作用值是特定样本窗口的统计产物,换周期或品种会漂移;外汇与贵金属杠杆高、滑点突发的特性会放大误判,实盘前务必用历史数据重算一遍再决定保留哪几个变量。

◍ 随机森林里真正扛事的那几个指标

把训练好的随机森林模型在测试集上跑变量重要度,能看到基于相互作用的 Top10 里 atr 拿 0.1341、cci 0.1335、oscK 0.1218,chv 和 slowD 都在 0.095 上下,signal 与 ar 约 0.085–0.090,这说明波动率与超买超卖类特征对分类贡献最实。 分标签拆开看更有意思:Class -1(空头样本)中 atr 重要度 0.17、oscK 0.16,而 tr 只有 0.03;到了 Class 1(多头样本)tr 反而跳到 0.16,atr 降到 0.14。同一指标在不同方向样本里的权重漂移,提示你做多空不对称过滤时不能直接共用阈值。 用 partialImportance 对两个类别分别算相对影响,class «-1» 得到 67.41%、class «1» 得到 64.45%,都基于 x.tst 测试集。这个落差说明模型在识别空头形态时更依赖少数核心变量,多头侧分布相对分散。 想自己复现,把下面这段 R 风格调用直接接在你的 imp.ruf.opt 模型对象后面就能出图,MT5 导出的 tick 特征矩阵喂进 x.tst 即可:

MQL5 / C++
> plot(imp.ruf.opt, Xtest = x.tst)
> pd.signal <- partialDependenceOverResponses(x.tst,
+                                             imp.ruf.opt,
+                                             whichFeature = "signal",
+                                             whichOrder = "all"
+ )
> pd.tr <- partialDependenceOverResponses(x.tst,
imp.ruf.opt,
whichFeature = "tr",
whichOrder = "all"
)
> pd.chv <- partialDependenceOverResponses(x.tst,   
imp.ruf.opt,
whichFeature = "chv",
whichOrder = "all")
> par.imp.ruf <- partialImportance(X = x.tst,
+                                 imp.ruf.opt,
+                                 whichClass = "-class="num">1")
Relative influence: class="num">67.41%
Based on x.tst  and class «-class="num">1»
> par.imp.ruf <- partialImportance(X = x.tst,
+                                 imp.ruf.opt,
+                                 whichClass = "class="num">1")
Relative influence: class="num">64.45%
> par.dep.class="num">1 <- partialDependenceBetweenPredictors(Xtest = x.tst,
+                                               imp.ruf.opt,
+                                               features = Cs(atr, cci),
+                                               whichOrder = "all",

ATR与CCI的一二阶交互实测

在 perspective = T 的视角下,ATR 与 CCI 的一阶交互水平为 0.1748,覆盖了具备最大水平特征的 99.97%;二阶交互水平降到 0.1526,对应 87.28% 的最大水平特征。这说明两者在首阶就几乎绑定了绝大部分非线性信息,二阶残差已明显衰减。 分类分布图用于观察:当变量对中某一个落在特定区间时,另一个变量同属某一类的概率。若同类命中为 TRUE,则该变量在预测当前分类时,可能对其他变量产生牵引。依赖性面板则对变量对给出交叉制表,评估它们在同一类预测下的依赖强度。 热力图直接标出相关性最强的格子,颜色越深相关越强。起决定作用的变量,最可能是全局重要度最高的那个,或是高阶相互作用突出的那个——前者看「全局变量重要度」,后者看「基于互相作用的变量重要度」。 下方 R 代码用 RoughSets 把训练集与测试集转成决策表(第16列作决策属性),再做全局可辨识启发式离散化。summary 显示 DX 在 [-Inf,12.5] 有 948 条、ATR 在 (20.7,Inf] 有 1106 条,这类分布不均会直接影响粗糙集规则泛化,做贵金属回测时须留意样本偏斜带来的高风险。

MQL5 / C++
> library(RoughSets)
加载所需的包: Rcpp
> require(magrittr)
> data.tr <- SF.asDecisionTable(data.f[idx$tr, ],
+                              decision.attr = class="num">16,
+                              indx.nominal = class="num">16)
> data.tst <- SF.asDecisionTable(data.f[idx$ts, ],
+                              decision.attr = class="num">16,
+                              indx.nominal = class="num">16
+ )
> true.class <- data.tst[ ,ncol(data.tst)]
> cut.values <- D.global.discernibility.heuristic.RST(data.tr)
> data.tr.d <- SF.applyDecTable(data.tr, cut.values)
> summary(data.tr.d)

「指标联合分布的样本频数切片」

把多指标状态做分箱后,直接看样本落在各区间的频数,比单看一个指标更有参考价值。下面这张联合分布表来自 2642 个样本(sign 与 slowD 覆盖全样本,即 2642 条),其余指标按阈值切段统计频次。 tr 与 atr 的配对显示:低频波动段 [-Inf,0.00072] 有 1288 个样本,而高波动段 (0.00196,Inf] 仅 203 个,说明绝大多数时刻市场处于低 tr 状态。cci 在 (-6.61,Inf] 有 1356 个、[-Inf,-6.61] 有 1286 个,多空临界附近分布接近对称。 cmo 在 [-Inf,5.81] 有 1480 个样本,占全样本 56%,而 (54.1,Inf] 仅 232 个,极端超买出现的机会偏低。vsig 在 [-Inf,0.0252] 有 1637 个、 (0.0252,Inf] 有 1005 个,波动率信号偏谨慎的样本更多。 在 MT5 里用 OnCalculate 累积这些分箱计数,可以实时观察当下样本相对历史频数的偏离;若某指标突然落入极低频区间,可能提示状态异常,但外汇和贵金属属高风险品种,频数异常不等于方向确定性。

◍ 粗糙集约简后的特征与分类命中率

用快速约简在训练集上跑了一遍,留下的决策属性是 DX、ADX、oscDX、ar、tr、atr、cci、chv、cmo、vsig、oscK、signal、vol,共 13 个维度,其余指标被约掉。 把约简结果套回测试集做离散化后,用置信度 0.9、覆盖次数 3 生成近似量化规则(AQRules),预测分布为 -1 类 655 个、1 类 667 个,两类数量接近。 模糊矩阵显示:真实 -1 预测对 497、错判 1 类 163;真实 1 预测对 504、错判 -1 类 158。整体 Accuracy 0.7572,95% 置信区间 (0.7331, 0.7801),No Information Rate 0.5045,P-Value 小于 2e-16,说明该规则集显著优于随机基线。 外汇与贵金属市场波动剧烈、杠杆风险高,这套约简+规则映射仅供 MT5 外接 R 环境复算验证,实盘信号概率仍受时段与流动性影响。

实例筛选后规则集的混淆矩阵表现

在训练集上跑 FRIS 实例筛选(阈值 tau=0.5、alpha=1、t.tnorm+lukasiewicz 聚合)后,样本量从原始数据压缩到 2353 行,相当于砍掉近半冗余样本,规则提取前先做了一层降噪。 用 AQRules 生成置信度 0.9、覆盖次数≥3 的规则集,对测试集预测得到 -1 类 638 个、1 类 684 个,分布与真实占比 0.4826 接近,没有明显偏移。 混淆矩阵显示:真实 -1 预测 -1 为 506,真实 -1 误判 1 为 132;真实 1 预测 1 为 530,误判 -1 为 154。整体准确率 0.7837,95% 置信区间 (0.7605, 0.8056),显著高于无信息率 0.5174(p<2e-16)。 Kappa 从初版 0.5144 提升到 0.5673,平衡准确率 0.7840,敏感度 0.7931、特异度 0.7749。外汇与贵金属行情受突发流动性影响,这类统计优势只代表样本内概率倾向,实盘仍需以 MT5 历史中心回测验证。

「关联规则里的前件区间与样本支撑」

上面这段 R 输出是从某次关联规则挖掘里截出来的 head(rules) 结果,类别标记里 'Positive' Class 设为 -1,说明我们把下跌样本当成正类在跑。 规则的前件落在三个区间:变量 6 取值 (85.1, Inf]、变量 4 取值 (0.00137, Inf]、变量 11 取值 (0.0374, Inf],后件统一是 '1'(即正类标签)。这种写法意味着当三个特征同时突破各自阈值时,模型倾向把它判为下跌倾向样本。 支撑样本索引列了 68 个 bar 编号,从 1335 到 2643,说明该规则在总样本里覆盖了至少这 68 根 K 线;laplace 修正值为 0.9857143,接近 1 表示在平滑后置信度仍偏高。 外汇与贵金属属高风险品种,这类规则只是历史样本的统计关联,换周期或换品种后支撑集可能大幅缩水,开 MT5 用相同特征阈值回测自己的品种才能真正看清失效边界。

MQL5 / C++
&class="macro">#x27;Positive&class="macro">#x27; Class : -class="num">1
> head(rules)
[[class="num">1]]
[[class="num">1]]$idx
[class="num">1]  class="num">6  class="num">4 class="num">11
[[class="num">1]]$values
[class="num">1] "(class="num">85.1, Inf]"      "(class="num">0.00137, Inf]" "(class="num">0.0374, Inf]"
[[class="num">1]]$consequent
[class="num">1] "class="num">1"
[[class="num">1]]$support
[class="num">1] class="num">1335 class="num">1349 class="num">1363 class="num">1368 class="num">1372 class="num">1390 class="num">1407 class="num">1424 class="num">1449 class="num">1454
[class="num">11] class="num">1461 class="num">1472 class="num">1533 class="num">1546 class="num">1588 class="num">1590 class="num">1600 class="num">1625 class="num">1630 class="num">1661
[class="num">21] class="num">1667 class="num">1704 class="num">1720 class="num">1742 class="num">1771 class="num">1777 class="num">1816 class="num">1835 class="num">1851 class="num">1877
[class="num">31] class="num">1883 class="num">1903 class="num">1907 class="num">1912 class="num">1913 class="num">1920 class="num">1933 class="num">1946 class="num">1955 class="num">1981
[class="num">41] class="num">1982 class="num">1998 class="num">2002 class="num">2039 class="num">2040 class="num">2099 class="num">2107 class="num">2126 class="num">2128 class="num">2191
[class="num">51] class="num">2195 class="num">2254 class="num">2272 class="num">2298 class="num">2301 class="num">2326 class="num">2355 class="num">2356 class="num">2369 class="num">2396
[class="num">61] class="num">2472 class="num">2489 class="num">2497 class="num">2531 class="num">2564 class="num">2583 class="num">2602 class="num">2643
[[class="num">1]]$laplace
      class="num">1
class="num">0.9857143

◍ 把工具请下神坛

这套围绕预测因子评估、可视化与筛选的方法,核心落在了相关性分析和多档重要度分级上——实验里观察到,把高相关因子强行并入模型,回测拟合度虚高但样本外表现倾向走弱。下一阶段才会把结论喂给 RBM 深度网络,本篇只是把地基打完。 评论区里有人拿「实时少 300 根 K 线」挑刺,作者回复 Dig 只是报价小数位(5 或 3),这类细节恰恰说明工具链离「直接实盘」还有手工校准的缝隙。外汇与贵金属杠杆高、滑点跳空频繁,任何因子方案都只是概率优势,不是免死金牌。 真要验证,开 MT5 把你自己品种的 Dig 填对,跑一遍分层标注和贪婪筛选,看树叶稳定性再说信不信。

把因子筛选交给小布盯盘
这些诊断与小布盯盘的AIGC已内置,打开对应品种页即可看到预处理后的因子重要性分布,你只管定交易假设。

常见问题

原始OHLC不是数值输入变量,需取差异对数或报价比对数;指标组合构成的矩阵或数据帧才是常用输入集,目标列置首或尾。
能,小布盯盘内置的AIGC模块可呈现变量重要性与因子间作用可视化,省去手跑R脚本的重复劳动。
很多模型不允许输入出现NA,虽默认移除但不确定,训练前用na.omit(dt)显式清理更稳妥,尤其RandomUniformForests系。
它基于粗糙集概念,不仅筛预测因子集,还依据信息系统的下近似与上近似精简训练样本,降低冗余实例。
模型可能误判类别距离,如'城市区'无序而'小时'有序,未指明会使规范化与交互项计算偏差,影响变量评估结论。