深度神经网络 (第 III 部)。样品选择和降维·综合运用
用自编码器压出三类行情特征
这段 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 导出的同类序列在隐藏层维度变化后,聚类边界是否更清晰。
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 比对主对角线密度峰位。
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 方案。外汇与贵金属行情序列做这类降维属高风险实验,结果只作特征参考,概率性结论勿当方向依据。
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 特征筛选;外汇与贵金属波动大,这类降维只是辅助,信号失效概率不低。
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 在乌克兰署名的五篇续作里,从预测因子筛选一路推到超参数贝叶斯优化,说明纯价格行为特征喂给深度网络仍有可挖空间,但外汇与贵金属杠杆高,任何模型信号都只是概率倾向,实盘前务必用历史数据交叉验证。 代码层面没有新片段可贴,落点就是:把你验证过的网络结构存成云存储里的中间态,跨终端接力训练,别重复造轮子。