神经网络变得简单(第 71 部分):目标条件预测编码(GCPC)·进阶篇
(2/3)·行为克隆只管模仿,轨迹怎么压缩才不丢信息?这篇拆开 GCPC 的预训练与政策学习双阶段
不少团队直接把离线轨迹喂给决策转换器,却从没追问过:那些次优轨迹里哪些片段真值得被编码。忽略轨迹表示学习目标与政策学习目标的差异,模型很容易在长周期任务里失焦。
◍ 编码器与解码器的层栈拼装
这段逻辑在 CNetDescription 的构建函数里,负责把编码器(encoder)和解码器(decoder)的每一层描述对象 CLayerDescription 逐个 new 出来并挂到容器上。任何一层 Add 失败就 delete 描述符并返回 false,只有全部通过才在末尾 return true。 编码器从第 11 层开始:第 11 层是 MLMHAttentionOCL 类型,节点数取上一层的两倍(prev_count * 2),滑动步长 step=4、输出窗口 window_out=16、子层 layers=4,优化器用 ADAM。第 12 层退回到 BaseOCL,count 直接等于 EmbeddingSize,激活函数为 None。第 13 层是 SoftMaxOCL,count 沿用 prev_count,step=1,同样无激活。 解码器先 Clear 再搭:输入层是 BaseOCL,count=EmbeddingSize;layer 1 把 (HistoryBars + PrecoderBars) * EmbeddingSize 个节点压成一层,激活用 LReLU。layer 2 又是 MLMHAttentionOCL,把节点数除回 EmbeddingSize,window=EmbeddingSize、step=4、window_out=16、layers=2。layer 3 换成 MultiModels,count=3、window=prev_wout、step=prev_count、无激活。 在 MT5 里跑这套网络描述时,若你改了 EmbeddingSize 或 HistoryBars,解码器 layer 1 的节点数会线性放大,可能明显拖慢 OpenCL 前向计算。建议先打印各层 descr.count 确认维度链没断。
} class=class="str">"cmt">//--- layer class="num">11 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronMLMHAttentionOCL; descr.count = prev_count * class="num">2; descr.window = prev_wout; descr.step = class="num">4; descr.window_out = class="num">16; descr.layers = class="num">4; descr.optimization = ADAM; if(!encoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">12 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; prev_count = descr.count = EmbeddingSize; descr.optimization = ADAM; descr.activation = None; if(!encoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">13 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronSoftMaxOCL; descr.count = prev_count; descr.step = class="num">1; descr.optimization = ADAM; descr.activation = None; if(!encoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- Decoder decoder.Clear(); class=class="str">"cmt">//--- Input layer if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; descr.count = EmbeddingSize; descr.activation = None; descr.optimization = ADAM; if(!decoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">1 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; prev_count = descr.count = (HistoryBars + PrecoderBars) * EmbeddingSize; descr.activation = LReLU; descr.optimization = ADAM; if(!decoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">2 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronMLMHAttentionOCL; prev_count = descr.count = prev_count / EmbeddingSize; prev_wout = descr.window = EmbeddingSize; descr.step = class="num">4; descr.window_out = class="num">16; descr.layers = class="num">2; descr.optimization = ADAM; if(!decoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">3 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronMultiModels; descr.count = class="num">3; descr.window = prev_wout; descr.step = prev_count; descr.activation = None; descr.optimization = ADAM; if(!decoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- class="kw">return true; }
「给强化学习网络搭描述层」
在 MT5 里用面向对象方式堆策略网络时,先要把 actor、goal、encoder 三组层描述容器准备好。函数入口处若传入空指针就当场 new 一个 CArrayObj,任一分配失败直接 return false,避免后面挂空引用把 EA 拖崩。 状态编码器(encoder)第一层用 defNeuronBaseOCL 类型,节点数等于 EmbeddingSize,优化器选 ADAM、激活函数 None;第二层切到 defNeuronConcatenate,count 设 LatentCount,window 接上一层节点数、step 取 AccountDescr,激活走 SIGMOID。这两层构成了把账户状态压成隐变量的前端。 actor 侧稍重一些:输入层同样是 defNeuronBaseOCL + LatentCount,随后 concatenate 层 step 换成 NRewards、激活改 LReLU;再叠两层 base 层,倒数第二层 SIGMOID,末层节点数直接拉到 2 * NActions 且不带激活——输出成对参数供后续采样动作。外汇与贵金属波动剧烈,这类网络只是概率建模,实盘前务必在策略测试器跑多周期回测。 逐行看这段构建代码,能发现所有 Add 失败分支都先 delete descr 再返 false,防止描述对象泄漏。复制进你的 .mqh 头文件,把 EmbeddingSize / LatentCount / NActions 换成自己的宏,就能在终端里编译验证结构是否撑得住。
class="type">bool CreateDescriptions(CArrayObj *actor, CArrayObj *goal, CArrayObj *encoder) { class=class="str">"cmt">//--- CLayerDescription *descr; class=class="str">"cmt">//--- if(!actor) { actor = new CArrayObj(); if(!actor) class="kw">return false; } if(!goal) { goal = new CArrayObj(); if(!goal) class="kw">return false; } if(!encoder) { encoder = new CArrayObj(); if(!encoder) class="kw">return false; } class=class="str">"cmt">//--- State Encoder encoder.Clear(); class=class="str">"cmt">//--- Input layer if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; class="type">int prev_count = descr.count = EmbeddingSize; descr.activation = None; descr.optimization = ADAM; if(!encoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">1 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronConcatenate; descr.count = LatentCount; descr.window = prev_count; descr.step = AccountDescr; descr.optimization = ADAM; descr.activation = SIGMOID; if(!encoder.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- Actor actor.Clear(); class=class="str">"cmt">//--- Input layer if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; prev_count = descr.count = LatentCount; descr.activation = None; descr.optimization = ADAM; if(!actor.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">1 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronConcatenate; descr.count = LatentCount; descr.window = prev_count; descr.step = NRewards; descr.optimization = ADAM; descr.activation = LReLU; if(!actor.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">2 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; descr.count = LatentCount; descr.activation = SIGMOID; descr.optimization = ADAM; if(!actor.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">3 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; descr.count = class="num">2 * NActions; descr.activation = None; descr.optimization = ADAM; if(!actor.Add(descr)) { class="kw">delete descr;
Actor 与 Goal 网络的层定义和初始化加载
这段逻辑在构建强化学习智能体的两个子网络:Actor 负责输出动作,Goal 网络评估状态价值与目标偏差。第四层 Actor 用了 defNeuronVAEOCL 类型,节点数绑定 NActions,优化器统一走 ADAM;若 Add 失败立即 delete 描述符并返回 false,避免内存泄漏。 Goal 网络则从输入层开始:首层 defNeuronBaseOCL,节点数等于 EmbeddingSize,激活函数为 None;随后两层隐层均为 LatentCount 个节点、LReLU 激活。最后输出层用 defNeuronFQF 类型,节点数 NRewards,window_out 显式设为 32,这是分位数回归输出窗口,影响奖励分布的分位粒度。 网络对象在类域声明为 Encoder、StateEncoder、Actor、Goal 四个 CNet 实例。OnInit 里先尝试从 FileName+"Enc.nnw" 加载已训练模型,三个 temp 浮点作占位参数;若加载失败则现场 new 两个 CArrayObj 描述符容器,调用 CreateTrajNetDescriptions 重建结构,任一环节失败返回 INIT_FAILED,EA 不会启动。 外汇与贵金属市场高杠杆、高波动,此类模型在实盘仅具概率优势,请先在 MT5 策略测试器用历史数据验证层参数与加载逻辑。
class="kw">return false; } class=class="str">"cmt">//--- layer class="num">4 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronVAEOCL; descr.count = NActions; descr.optimization = ADAM; if(!actor.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- Goal goal.Clear(); class=class="str">"cmt">//--- Input layer if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; prev_count = descr.count = EmbeddingSize; descr.activation = None; descr.optimization = ADAM; if(!goal.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">1 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; descr.count = LatentCount; descr.activation = LReLU; descr.optimization = ADAM; if(!goal.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">3 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronBaseOCL; descr.count = LatentCount; descr.activation = LReLU; descr.optimization = ADAM; if(!goal.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- layer class="num">4 if(!(descr = new CLayerDescription())) class="kw">return false; descr.type = defNeuronFQF; descr.count = NRewards; descr.window_out = class="num">32; descr.optimization = ADAM; descr.activation = None; if(!goal.Add(descr)) { class="kw">delete descr; class="kw">return false; } class=class="str">"cmt">//--- class="kw">return true; } CNet Encoder; CNet StateEncoder; CNet Actor; CNet Goal; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert initialization function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- ........ ........ class=class="str">"cmt">//--- load models class="type">float temp; if(!Encoder.Load(FileName + "Enc.nnw", temp, temp, temp, dtStudied, true)) { CArrayObj *encoder = new CArrayObj(); CArrayObj *decoder = new CArrayObj(); if(!CreateTrajNetDescriptions(encoder, decoder)) { class="kw">delete encoder; class="kw">delete decoder; class="kw">return INIT_FAILED; }
◍ EA初始化时神经网络模型的加载与维度校验
在 MT5 智能交易系统的 OnInit 阶段,若本地已存在训练好的网络文件(后缀 StEnc.nnw、Goal.nnw、Act.nnw),会直接 Load 载入;任一文件载入失败则进入重建分支,用 CreateDescriptions 生成 actor / goal / encoder 的三套网络描述对象并 Create 构建,任何一步返回 false 都 delete 掉相关指针并以 INIT_FAILED 退出。 载入或构建完成后,代码会把 Actor 的 OpenCL 上下文同步给 StateEncoder、Encoder、Goal,并关闭 Encoder 的训练模式(TrainMode(false))。随后立刻做维度对账:Actor 输出节点数必须等于 NActions,Encoder 输出必须等于 EmbeddingSize,二者不符就 PrintFormat 报错并 INIT_FAILED。 Encoder 第 0 层输出维度还要等于 HistoryBars * BarDescr,例如 HistoryBars=30、BarDescr=5 时期望 150 维,错位会触发 'Input size of Encoder doesn't match state description' 并终止初始化。最后把账户余额与净值读入 PrevBalance / PrevEquity 作为回合基线,返回 INIT_SUCCEEDED 才算过闸。 外汇与贵金属市场杠杆高、滑点随机,这类依赖神经网络的 EA 在模型维度校验未过闸时绝不会下单,但过闸后实盘仍可能因分布偏移而表现漂移,需先在策略测试器用历史数据验证网络文件与参数匹配。
if(!Encoder.Create(encoder)) { class="kw">delete encoder; class="kw">delete decoder; class="kw">return INIT_FAILED; } class="kw">delete encoder; class="kw">delete decoder; class=class="str">"cmt">//--- } if(!StateEncoder.Load(FileName + "StEnc.nnw", temp, temp, temp, dtStudied, true) || !Goal.Load(FileName + "Goal.nnw", temp, temp, temp, dtStudied, true) || !Actor.Load(FileName + "Act.nnw", temp, temp, temp, dtStudied, true)) { CArrayObj *actor = new CArrayObj(); CArrayObj *goal = new CArrayObj(); CArrayObj *encoder = new CArrayObj(); if(!CreateDescriptions(actor, goal, encoder)) { class="kw">delete actor; class="kw">delete goal; class="kw">delete encoder; class="kw">return INIT_FAILED; } if(!Actor.Create(actor) || !StateEncoder.Create(encoder) || !Goal.Create(goal)) { class="kw">delete actor; class="kw">delete goal; class="kw">delete encoder; class="kw">return INIT_FAILED; } class="kw">delete actor; class="kw">delete goal; class="kw">delete encoder; class=class="str">"cmt">//--- } StateEncoder.SetOpenCL(Actor.GetOpenCL()); Encoder.SetOpenCL(Actor.GetOpenCL()); Goal.SetOpenCL(Actor.GetOpenCL()); Encoder.TrainMode(false); Actor.getResults(Result); if(Result.Total() != NActions) { PrintFormat("The scope of the actor does not match the actions count(%d <> %d)", NActions, Result.Total()); class="kw">return INIT_FAILED; } Encoder.getResults(Result); if(Result.Total() != EmbeddingSize) { PrintFormat("The scope of the Encoder does not match the embedding size(%d <> %d)", EmbeddingSize, Result.Total()); class="kw">return INIT_FAILED; } class=class="str">"cmt">//--- Encoder.GetLayerOutput(class="num">0, Result); if(Result.Total() != (HistoryBars * BarDescr)) { PrintFormat("Input size of Encoder doesn&class="macro">#x27;t match state description(%d <> %d)", Result.Total(), (HistoryBars * BarDescr)); class="kw">return INIT_FAILED; } class=class="str">"cmt">//--- PrevBalance = AccountInfoDouble(ACCOUNT_BALANCE); PrevEquity = AccountInfoDouble(ACCOUNT_EQUITY); class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); }
「编码器前向传播与模型懒加载」
这段逻辑把轨迹自编码器的推理链路直接铺在 EA 初始化与逐帧计算里。先看前向部分:先把缓冲状态 bState 喂给 Encoder 做一层前向(feedForward 第三个参数 false 表示不训练),再把 Encoder 输出转交 StateEncoder 得到账户状态向量 bAccount,随后 Goal 网络以 NULL 为输出缓冲只算表征,最后 Actor 基于 StateEncoder 出动作。任意一步返回 false 就直接 return,避免脏状态往下传。 初始化函数 OnInit 里先 ResetLastError,再 LoadTotalBase 装载学习数据;若失败会打印错误码并回 INIT_FAILED。模型文件默认从 FileName+"Enc.nnw" 与 "Dec.nnw" 读取,读取时传入 dtStudied 与 true 标记。 若本地没有现成神经网络权重,代码会走新建分支:建两个 CArrayObj 描述编码器与解码器结构,调 CreateTrajNetDescriptions 填充层定义,再分别 Encoder.Create / Decoder.Create。注意 Iterations 输入参数写死 1e4(即 10000 次),这是训练或回放轨迹的生成上限,开 MT5 改这个值能直接拉长轨迹缓冲。 OpenCL 上下文在模型创建或加载后由 Encoder.GetOpenCL() 统一取出,后续若接小布盯盘的 GPU 批处理脚本,可复用同一设备句柄省去重复初始化。外汇与贵金属行情下用这类自编码推理,信号延迟和过拟合风险都偏高,参数务必在模拟盘先验证。
class=class="str">"cmt">//--- if(!Encoder.feedForward((CBufferFloat*)GetPointer(bState), class="num">1, false, (CNet*)GetPointer(Encoder)) || !StateEncoder.feedForward((CNet *)GetPointer(Encoder), -class="num">1, (CBufferFloat *)GetPointer(bAccount)) || !Goal.feedForward((CNet *)GetPointer(Encoder), -class="num">1, (CBufferFloat *)NULL) || !Actor.feedForward((CNet *)GetPointer(StateEncoder), -class="num">1, (CNet *)GetPointer(Goal))) class="kw">return; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Input parameters | class=class="str">"cmt">//+------------------------------------------------------------------+ class="kw">input class="type">int Iterations = class="num">1e4; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ STrajectory Buffer[]; CNet Encoder; CNet Decoder; CBufferFloat LastEncoder; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert initialization function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- ResetLastError(); if(!LoadTotalBase()) { PrintFormat("Error of load study data: %d", GetLastError()); class="kw">return INIT_FAILED; } class=class="str">"cmt">//--- load models class="type">float temp; if(!Encoder.Load(FileName + "Enc.nnw", temp, temp, temp, dtStudied, true) || !Decoder.Load(FileName + "Dec.nnw", temp, temp, temp, dtStudied, true)) { Print("Init new models"); CArrayObj *encoder = new CArrayObj(); CArrayObj *decoder = new CArrayObj(); if(!CreateTrajNetDescriptions(encoder, decoder)) { class="kw">delete encoder; class="kw">delete decoder; class="kw">return INIT_FAILED; } if(!Encoder.Create(encoder) || !Decoder.Create(decoder)) { class="kw">delete encoder; class="kw">delete decoder; class="kw">return INIT_FAILED; } class="kw">delete encoder; class="kw">delete decoder; class=class="str">"cmt">//--- } OpenCL = Encoder.GetOpenCL();
初始化校验与训练循环的真实落点
在 MT5 里跑自编码器类策略,初始化阶段最容易栽在维度不匹配上。下面这段校验逻辑强制要求 Encoder 输出维度等于 EmbeddingSize,且第一层输出必须等于 HistoryBars * BarDescr;Decoder 输入也必须等于 EmbeddingSize,否则直接 INIT_FAILED。 [CODE] Decoder.SetOpenCL(OpenCL); Encoder.getResults(Result); if(Result.Total() != EmbeddingSize) { PrintFormat("The scope of the Encoder does not match the embedding size count (%d <> %d)", EmbeddingSize, Result.Total()); return INIT_FAILED; } //--- Encoder.GetLayerOutput(0, Result); if(Result.Total() != (HistoryBars * BarDescr)) { PrintFormat("Input size of Encoder doesn't match state description (%d <> %d)", Result.Total(), (HistoryBars * BarDescr)); return INIT_FAILED; } //--- Decoder.GetLayerOutput(0, Result); if(Result.Total() != EmbeddingSize) { PrintFormat("Input size of Decoder doesn't match Encoder output (%d <> %d)", Result.Total(), EmbeddingSize); return INIT_FAILED; }
| if(!LastEncoder.BufferInit(EmbeddingSize,0) |
|---|
| !Gradient.BufferInit(EmbeddingSize,0) |
| !LastEncoder.BufferCreate(OpenCL) |
!Gradient.BufferCreate(OpenCL)) { PrintFormat("Error of create buffers: %d", GetLastError()); return INIT_FAILED; } if(!EventChartCustom(ChartID(), 1, 0, 0, "Init")) { PrintFormat("Error of create study event: %d", GetLastError()); return INIT_FAILED; } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
| // | Train function |
|---|
//+------------------------------------------------------------------+ void Train(void) { //--- vector<float> probability = GetProbTrajectories(Buffer, 0.9); vector<float> result, target; matrix<float> targets; STD = vector<float>::Zeros((HistoryBars + PrecoderBars) * 3); int std_count = 0; uint ticks = GetTickCount(); for(int iter = 0; (iter < Iterations && !IsStopped()); iter ++) { int tr = SampleTrajectory(probability); int batch = GPTBars + 50; int state = (int)((MathRand() * MathRand() / MathPow(32767, 2)) * (Buffer[tr].Total - 3 - PrecoderBars - batch)); if(state <= 0) { iter--; continue; } Encoder.Clear(); Decoder.Clear(); LastEncoder.BufferInit(EmbeddingSize,0); [/CODE] 代码逐行拆解:Decoder.SetOpenCL 把计算丢给 OpenCL 设备;Encoder.getResults 取回结构输出,随后三个 if 分别卡死嵌入维数、状态描述长度、解码器输入维数。LastEncoder 与 Gradient 的 BufferInit/BufferCreate 失败会打印 GetLastError 并退出。EventChartCustom 发自定义事件 "Init" 通知图表端。 Train 函数里 probability 用 0.9 温度采样轨迹;batch 固定为 GPTBars+50;state 用 MathRand 平方归一化做偏置抽样,若算出小于等于 0 就重试本次迭代。外汇与贵金属行情高波动,这类模型维度错配会直接让 EA 加载失败,开 MT5 把 EmbeddingSize 和 HistoryBars*BarDescr 打印出来对一遍再编译。
Decoder.SetOpenCL(OpenCL); Encoder.getResults(Result); if(Result.Total() != EmbeddingSize) { PrintFormat("The scope of the Encoder does not match the embedding size count(%d <> %d)", EmbeddingSize, Result.Total()); class="kw">return INIT_FAILED; } class=class="str">"cmt">//--- Encoder.GetLayerOutput(class="num">0, Result); if(Result.Total() != (HistoryBars * BarDescr)) { PrintFormat("Input size of Encoder doesn&class="macro">#x27;t match state description(%d <> %d)", Result.Total(), (HistoryBars * BarDescr)); class="kw">return INIT_FAILED; } class=class="str">"cmt">//--- Decoder.GetLayerOutput(class="num">0, Result); if(Result.Total() != EmbeddingSize) { PrintFormat("Input size of Decoder doesn&class="macro">#x27;t match Encoder output(%d <> %d)", Result.Total(), EmbeddingSize); class="kw">return INIT_FAILED; } if(!LastEncoder.BufferInit(EmbeddingSize,class="num">0) || !Gradient.BufferInit(EmbeddingSize,class="num">0) || !LastEncoder.BufferCreate(OpenCL) || !Gradient.BufferCreate(OpenCL)) { PrintFormat("Error of create buffers: %d", GetLastError()); class="kw">return INIT_FAILED; } if(!EventChartCustom(ChartID(), class="num">1, class="num">0, class="num">0, "Init")) { PrintFormat("Error of create study event: %d", GetLastError()); class="kw">return INIT_FAILED; } class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Train function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void Train(class="type">void) { class=class="str">"cmt">//--- vector<class="type">float> probability = GetProbTrajectories(Buffer, class="num">0.9); vector<class="type">float> result, target; matrix<class="type">float> targets; STD = vector<class="type">float>::Zeros((HistoryBars + PrecoderBars) * class="num">3); class="type">int std_count = class="num">0; class="type">uint ticks = GetTickCount(); for(class="type">int iter = class="num">0; (iter < Iterations && !IsStopped()); iter ++) { class="type">int tr = SampleTrajectory(probability); class="type">int batch = GPTBars + class="num">50; class="type">int state = (class="type">int)((MathRand() * MathRand() / MathPow(class="num">32767, class="num">2)) * (Buffer[tr].Total - class="num">3 - PrecoderBars - batch)); if(state <= class="num">0) { iter--; class="kw">continue; } Encoder.Clear(); Decoder.Clear(); LastEncoder.BufferInit(EmbeddingSize,class="num">0);