深度神经网络 (第 III 部)。样品选择和降维·综合运用
📘

深度神经网络 (第 III 部)。样品选择和降维·综合运用

第 3/3 篇

用自编码器压出三类行情特征

这段 R 代码演示了把预处理后的行情数据(train/val/test)塞进一个 3 层自编码器,提取隐藏层表达作为新特征。外汇与贵金属市场波动聚集、尾部风险高,这类降维仅作特征工程辅助,不代表任何方向判定。 先对数据做 center、scale、spatialSign 三种标准化,再划分到三个集合。自编码器结构设为 nl=3、N.hidden=3、unit.type="tanh",权重衰减 lambda=0.0002,稀疏项 beta=0 且期望稀疏 rho=0.01,初始化 epsilon=0.001,用 BFGS 跑满 3000 轮。 训练完用 predict(..., hidden.output=TRUE) 把隐藏层 3 个节点输出当作压缩特征,分别拼回 train/val/test 的 Class 标签。你可以直接把 N.hidden 从 3 改成 5 或 8,看 MT5 导出的同类序列在隐藏层维度变化后,聚类边界是否更清晰。

MQL5 / C++
method <- c("center", "scale", "spatialSign")
preProcess(DTcap$train, method = method) -> preproc
list(train = predict(preproc, DTcap$train),
     val = predict(preproc, DTcap$val),
     test = predict(preproc, DTcap$test)
) -> DTcap.n
require(autoencoder)
train <- DTcap.n$train %>% select(-Class) %>% as.matrix()
val <- DTcap.n$val %>% select(-Class) %>% as.matrix()
test <- DTcap.n$test %>% select(-Class) %>% as.matrix()
nl = class="num">3
unit.type = "tanh"
N.class="kw">input = ncol(train)
N.hidden = class="num">3
lambda = class="num">0.0002
beta = class="num">0
rho = class="num">0.01
epsilon <- class="num">0.001
max.iterations = class="num">3000
AE_13 <- autoencode(X.train = train, X.test = val,
                    nl = nl, N.hidden = N.hidden,
                    unit.type = unit.type,
                    lambda = lambda,
                    beta = beta,
                    rho = rho,
                    epsilon = epsilon,
                    optim.method = "BFGS",
                    max.iterations = max.iterations,
                    rescale.flag = FALSE,
                    rescaling.offset = class="num">0.001)
pcTrain <- predict(AE_13, X.class="kw">input = train, hidden.output = TRUE)$X.output %>%
  tbl_df %>% cbind(., Class = DTcap.n$train$Class)
pcVal <- predict(AE_13, X.class="kw">input = val, hidden.output = TRUE)$X.output %>%
  tbl_df %>% cbind(., Class = DTcap.n$val$Class)
pcTest <- predict(AE_13, X.class="kw">input = test, hidden.output = TRUE)$X.output %>%
  tbl_df %>% cbind(., Class = DTcap.n$test$Class)

◍ 用配对图核对待验证集的类别分布

在主环境里通过 evalq 把绘图指令扔进 env,对 pcTrain、pcVal、pcTest 三套数据分别跑 ggpairs。columns 取 1 到 ncol(...) 全列,mapping 里用 color=Class 把样本类别上色,title 直接标数据集名,能在同一画布看到主成分两两散点、密度与相关系数。 这一步不是模型训练,而是肉眼排雷:若 pcVal 或 pcTest 的 Class 着色簇明显偏移 pcTrain,后续交叉验证的结论可能失真。外汇与贵金属行情的高风险在于,样本外分布漂移往往发生在流动性断层时段,配对图能提前暴露这类裂缝。 实操时把三段 evalq 块贴进 R 会话即可,ncol 会自动跟随各自数据集宽度,不用手改列数;跑完建议先截 pcVal 图,和 pcTrain 比对主对角线密度峰位。

MQL5 / C++
evalq({
  ggpairs(pcTrain,columns = class="num">1:ncol(pcTrain),
          mapping = aes(class="type">class="kw">color = Class),
          title = "pcTrain")},
  env)
evalq({
  ggpairs(pcVal,columns = class="num">1:ncol(pcVal),
          mapping = aes(class="type">class="kw">color = Class),
          title = "pcVal")},
  env)
evalq({
  ggpairs(pcTest,columns = class="num">1:ncol(pcTest),
          mapping = aes(class="type">class="kw">color = Class),
          title = "pcTest")},
  env)

「盲眼逆转下的非线性降维短板」

非线性 PCA 处理逆向问题时,本质上是盲眼逆转:既不知道模型也不知道数据生成过程,只靠自动关联网络(AE)的生成侧 Fgen 从低维 Z 反推高维 X。直接用 AE 第二部分(结构 3-7-12)做逆向 NLPCA,能把传播误差 σ 回灌到输入层 Z,但「一对多」映射让直接模型在非线性下失效——两组相同的 X 可能对应 Z 里不同值。 用 nlpca::pcaMethods 跑相同数据(约化 12→3),网络设 (3,8,12)、weightDecay=0.01、maxSteps=1100,R2 累计到 PC3 为 0.746(PC1 0.377 / PC2 0.272 / PC3 0.097)。图表上主分量按目标变量等级分割且相关性极低,第三个分量看起来多余。 致命点是 NLPCA 不返回权重矩阵 W3、W4,也就拿不到负载 P,无法在验证/测试集上算主分量分值。tSNE、ICS 也有同样坑。下面这段 R 脚本是 NLPCA 与 PPCA 的实跑代码,可直接丢进带 pcaMethods 的环境验证。 概率 PCA(PPCA)和贝叶斯 PCA 回带负载且速度快,能在 train/val/test 上直接取分值;但同等约化下 PPCA 按等级分割的品质未超过 AE 方案。外汇与贵金属行情序列做这类降维属高风险实验,结果只作特征参考,概率性结论勿当方向依据。

MQL5 / C++
require(pcaMethods)
evalq({
  DTcap.n$train %>% tbl_df %>
    select(-Class) %>% as.matrix() %>
    prep(scale = "none", center = TRUE) -> train
  resNLPCA <- pca(train,
                  method = "nlpca", weightDecay = class="num">0.01,
                  unitsPerLayer = c(class="num">3, class="num">8, class="num">12),
                  center = TRUE, scale = "none",# c("none", "pareto", "vector", "uv")
                  nPcs = class="num">3, completeObs = FALSE,
                  subset = NULL, cv = "none", # "none""q2"), ...)
                  maxSteps = class="num">1100)
  rm(train)},
  env)
#--------
evalq(
  pcTrain <- resNLPCA@scores %>% tbl_df %>
    cbind(., Class = DTcap.n$train$Class)
, env)
#------graph-------
require(GGally)
evalq({
  ggpairs(pcTrain,columns = class="num">1:ncol(pcTrain),
          mapping = aes(class="type">class="kw">color = Class),
          title = "pcTrain -> NLPCA(class="num">3-class="num">8-class="num">12) wd = class="num">0.01")},
  env)
#----------
> print(env$resNLPCA)
nlpca calculated PCA
Importance of component(s):
                 PC1     PC2     PC3
R2               class="num">0.3769 class="num">0.2718 class="num">0.09731
Cumulative R2    class="num">0.3769 class="num">0.6487 class="num">0.74599
class="num">12      Variables
class="num">2000    Samples
class="num">0       NAs( class="num">0 %)
class="num">3       Calculated component(s)
Data was mean centered before running PCA
Data was NOT scaled before running PCA
Scores structure:
[class="num">1] class="num">2000    class="num">3
Loadings structure:
Inverse hierarchical neural network architecture
class="num">3 class="num">8 class="num">12
Functions in layers
linr tanh linr
hierarchic layer: class="num">1
hierarchic coefficients: class="num">1 class="num">1 class="num">1 class="num">0.01
scaling factor: class="num">0.3260982
#=======PPCA===================
evalq({
  DTcap.n$train %>% tbl_df %>
    select(-Class) %>% as.matrix() -> train
  DTcap.n$val %>% tbl_df %>
    select(-Class) %>% as.matrix() -> val
  DTcap.n$test %>% tbl_df %>
    select(-Class) %>% as.matrix() -> test
  resPPCA <- pca(train, method = "ppca",

概率 PCA 的 R 侧落地与三主成分解释力

这段脚本走的是概率主成分分析(PPCA)路线,用 mean centering 但不做 scaling,把 12 个变量、2000 个样本压到 3 个主成分。参数里 nPcs=3、maxIterations=3000,cv 设成 none,说明只做静态拟合、不交叉验证,适合先快速看数据结构。 从 print 结果看,PC1/PC2/PC3 的 R2 分别是 0.2873、0.2499、0.1881,累计到 0.7253——也就是三个轴吃掉了约 72.5% 的方差。样本无缺失(0 NAs,占 0%),scores 结构是 2000×3,loadings 是 12×3,可直接拿去画双标图。 slplot 取 pc=1,2 出图,lcex=0.9 控制标签字号,sub 标成 Probabilistic PCA。在 MT5 之外用 R 复刻这套,能先判断哪些变量在第一、第二轴上载荷高,再回 Head 里挑对应指标做 EA 特征筛选;外汇与贵金属波动大,这类降维只是辅助,信号失效概率不低。

MQL5 / C++
center = TRUE, scale = "none",# c("none", "pareto", "vector", "uv")
              nPcs = class="num">3, completeObs = FALSE,
              subset = NULL, cv = "none", # "none""q2"), ...)
              maxIterations = class="num">3000)
  },
  env)
#-----------
>print(env$resPPCA)
ppca calculated PCA
Importance of component(s):
PC1 PC2 PC3
R2 class="num">0.2873 class="num">0.2499 class="num">0.1881
Cumulative R2 class="num">0.2873 class="num">0.5372 class="num">0.7253
class="num">12 	Variables
class="num">2000 	Samples
class="num">0 	NAs( class="num">0 %)
class="num">3 	Calculated component(s)
Data was mean centered before running PCA
Data was NOT scaled before running PCA
Scores structure:
[class="num">1] class="num">2000 class="num">3
Loadings structure:
[class="num">1] class="num">12 class="num">3
slplot(env$resPPCA, pcs = c(class="num">1,class="num">2),
       lcex = class="num">0.9, sub = "Probabilistic PCA")

◍ 训练验证测试集的切分与隐藏坑

这一节的操作约定和前面保持一致:训练、验证、测试三类集合照旧划分,配合滑动窗口、成长窗口以及间或引导来做样本推进;选模型阶段继续用交叉验证。唯一还没解决好的,是这三块集合到底该留多大才够——至今没有公认的下限公式。 有个值得警惕的细节来自 Win Wector 团队的实测提法:如果你在训练集上做了 PCA 主分量提取,那么模型真正训练时,应当改用验证集上算出来的主分量。换句话说,一旦某批数据参与了变换基准的确定,它就不再干净,不能回过头喂给模型当训练样本。 这个陷阱在神经网络训练里尤其容易踩。开 MT5 接自己的特征工程流程时,建议单独跑一段脚本核对:主分量矩阵究竟用的是哪个子集的协方差,避免无意中把验证信息泄露进训练回路。外汇与贵金属波动具有高风险,此类数据泄漏会直接放大过拟合概率,回测好看实盘未必成立。

「自动预处理包能替你省掉哪些活」

数据准备这条链路走到头会发现,真正卡进度的往往不是模型结构,而是前面清洗、变换、归一化这些琐碎阶段。MT5 里若不想手工逐个试参数组合,可直接调用 preprocomb 与 metaheur 两个包,让它们去搜相对合适的预处理阶段排列。 这两个包本质是枚举+启发式搜索,跑一次可能要扫几十到上百种组合,对 CPU 占用不低,外汇与贵金属数据波动大、过拟合风险高,自动出来的方案也要你手动回测确认。 实在懒得一步步调的人,用包先出基线,再拿自己的盘感去砍掉奇怪变换,比从零开始瞎试更快。

收束

这套 DNN 系列写到第七部分,实操脚本已在 Part_III 仓库放出,读者直接拉到 MT5 脚本目录就能跑通前文讲的袋封融合与堆叠逻辑。 作者 Vladimir Perervenko 在乌克兰署名的五篇续作里,从预测因子筛选一路推到超参数贝叶斯优化,说明纯价格行为特征喂给深度网络仍有可挖空间,但外汇与贵金属杠杆高,任何模型信号都只是概率倾向,实盘前务必用历史数据交叉验证。 代码层面没有新片段可贴,落点就是:把你验证过的网络结构存成云存储里的中间态,跨终端接力训练,别重复造轮子。

常见问题

把当前K线窗口输入训练好的编码器取隐层向量,比对历史三类簇中心距离,最近的一类即当前行情倾向。
说明特征区分度不足,优先回去调编码器维度或换输入特征,别直接拿重叠样本当信号。
可以,小布内置AIGC分析能直接对品种做非线性降维与类别分布可视化,打开对应页就能看结果。
贵金属外汇高风险,三主成分累计解释力超75%可先用,低于60%建议补特征或降噪。
按时间顺序切分时若验证集含未来信息会虚高胜率,必须用滚动窗口且禁止随机洗牌防泄漏。