范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

神经网络变得轻松(第二十七部分)深度Q学习(DQN)

  内容概述 1. Q-函数的概念 2. 深度 Q-学习 2.1. 体验回放 2.2. 使用目标网络 3. 利用 MQL5 实现 4. 测试 结束语 参考文献列表 本文中用到的程序 概述
  在上一篇文章中,我们开始探索强化学习方法,并构建了我们的第一个交叉熵可训练模型。 在本文中,我们将继续研究强化学习方法。 我们将继续深度Q-学习方法。 于 2013年,运用深度 Q-学习,DeepMind 团队设法创建了一个可以成功玩七款 Atari 电脑游戏的模型。 值得注意的是,对于所有 7 款游戏,它们在不更改架构或超参数的情况下采用相同的模型进行训练。 根据训练结果,该模型能够继续提升之前所分析的 6 个游戏取得的结果。 此外,在三场游戏中,该模型的表现优于人类。 这项工作的发表开启了强化学习方法发展的新阶段。 我们来研究这种方法,并尝试运用它来解决交易相关的问题。
  1. Q-函数的概念
  首先,我们回到上一篇文章中研究的素材。 在强化学习中,我们构建了代理者与其环境之间的交互过程。 代理者分析环境的当前状态,并执行动作更改环境状态。 在动作响应中,环境返回奖励给代理者。 代理者不知道奖励是如何形成的。 代理者的目标只是得到所分析场次的最大可能总体奖励。
  请注意,代理者不会收到该动作的奖励。 它得到的是从一种状态过渡到另一种状态的奖励。 与此同时,在类似情况下执行某些动作并不能保证过渡到同一状态。 执行动作只能提供一定概率转移到预期状态。 代理者不知道状态、动作和转换的概率,以及依赖关系。 代理者必须从与环境的交互过程中学习它们。
  事实上,强化学习是基于这样的假设,即当前状态、采取的行动和奖励之间存在某种关系。 在数学术语中,有一个函数  Q ,它根据状态  s  和动作  a ,返回奖励  r 。 它表示为  Q(s|a) 。 此函数称为 动作功用函数 。
  代理者不知道此函数。 但如果它存在,那么在与环境交互的过程中,通过无限次重复动作,我们可以近似这个函数。
  在实际条件下,不可能无限次地重复状态和动作。 但经足够的重复,我们就可得到可接受误差的近似函数。 Q 函数表达式的形式可以有所不同。 在上一篇文章中,在判定每个动作的功用时,我们构建了一个状态、动作、和平均奖励的依赖关系表。 还有以其它形式表达的 Q 函数,均可完全接受,或可产生更好的结果。 这些可以是决策树、神经网络、等等。
  请注意,由代理者近似的 Q 函数并不能预测奖励。 它仅根据代理者过去与环境交互的经验返回预期回报。
  2. 深度 Q-学习
  您可能已经猜到了深度 Q-学习涉及运用神经网络来近似 Q 函数。 这种方式有什么优势? 请记住上一篇文章中交叉熵表格方法的实现。 我强调,表格方法的实现假定可能的状态和动作数量是有限的。 故此,我们通过初始数据聚类来限制可能的状态数量。 但它有那么好吗? 聚类总能产生更好的结果吗? 运用神经网络不会限制可能的状态数量。 我认为在解决交易相关问题时,这是一个极棒的优势。
  最明显的第一个方法是用神经网络替换上一篇文章中的表格。 但是,不幸的是,这并不容易。 在实践中,这种方式并不像看起来那么美好。 为了实现该方法,我们需要添加一些启发式方法。
  首先,我们来看看代理者训练目标。 一般来说,它的目标是总体奖励最大化。 请看下图。 代理者必须从  Start  单元格移动到  Finish  单元格。 代理者在到达  Finish  单元格时才会收到一次性奖励。 在所有其它状态,奖励均为零。
  该示意图展示了两条路径。 对我们来说,很明显,橙色路径更短、更可取。 但就奖励最大化而言,它们是等价的。
  与此类似,在交易中,立即获得收入,比之现在投入资金,并在遥远的将来获得收入更可取。 考虑到资金的价值:利率、通货膨胀、和许多其它变量。 我们在此也做同样的事。 为了解决这个问题,我们引入了折扣因子  ɣ ,其将降低未来的奖励值。
  折扣因子  ɣ  可在 0 到 1 的范围内。 如果折扣因子为 1,则不发生折扣。 折扣因子为 0 时,未来的奖励将被忽略。 实际上,折扣因子设置为接近 1。
  但这里还有另一个问题。 理论上看起来优良的东西,在实践中也许并不总是有效。 当我们有一个完整的转换与奖励映射时,我们就可以很容易地计算出未来的奖励。 其中,我们可以选择最后回报最大的最佳路径。 但在解决实际问题时,我们不知道执行某个动作后的下一个状态会是什么。 我们也不知道奖励多少。 所有这些都已应用到紧邻的下一步。 当我们谈论至场次结束的整个道路时,情况就更加严重了。 我们无法预见未来。 为了获得下一个奖励,代理者需要执行动作。 只有在转换到新状态之后,环境才会返回奖励。 甚至于,我们没有退路可言。 我们不能回到以前的状态,并采取另一个行动,以便之后能选择最好的状态。
  因此,我们将应用动态可编程方法。 特别是贝尔曼(Bellman)优化方法。 它言道,为了选择最优策略,有必要在每个步骤中选择最佳动作。 也就是说,通过选择每一步奖励最大的动作,我们将获得场次的最大累积奖励。 更新动作功用函数的数学公式如下所示。
  看看公式。 是否它让您想起随机梯度下降权重更新公式? 确是这样,为了更新动作功用函数的数值,我们需要函数的前期值加上一些偏差再乘以学习因子。
  在所呈现的函数中还可以注意到,为了判定时间点  t  处的函数值,我们需要得到下一个时间步骤,即在点  t+1  处的动作功用函数值。 换言之,在状态 st 中,我们采取操作 at,在我们转换到状态 st+1 后,我们得到奖励 rt+1。 为了更新动作功用函数的数值,我们需要在下一步中将动作功用函数的最大值添加到奖励之中。 这就是,我们加进下一步可获得的最大预期奖励。 当然,我们的代理者无法预见未来,并判定未来的奖励。 但它可用其近似函数:处于状态 st+1,它可以计算给定状态中所有可能动作的函数值,并从所获得值中选取最大值。 在学习的过程中,其数值距最开始会很远。 但总比没有好。 随着代理者不断学习,预测误差将随之减小。
  2.1. 体验回放
  随机梯度下降很优秀,因为它允许根据群体之中小规模样本的数值更新函数值。 实际上,它允许我们的代理者在场次的每个步骤更新动作功用函数值。 但在监督学习中,我们所用训练样本,其状态彼此独立。 为了加强这一属性,我们每次在选择新的训练数据集之前都对群体进行洗牌。
  然而现在,在监督学习中,我们的代理者在贯穿我们的环境中随时移动,执行一个动作,且每次都进入与前一个密切相关的新状态。 环顾您的四周。 无论您是走路还是坐着,并执行某些动作,您周围的环境都不会发生显著变化。 您的动作仅改变了动过打击处的一小部分。 与此类似,当代理者执行动作时,所研究环境的状态不会有太大变化。 这意味着连续的状态将在很大程度上相互关联。 我们的代理者将观察此类状态的自相关。
  而困难在于,即使采用较小的训练系数也无法阻止代理者将动作功用函数调整到当前状态,从而牺牲以往记忆的经验。
  在监督学习中,在大量迭代后采用独立状态可以平均模型的权重值。 在强化学习的情况下,当我们使用连接且几乎不变的状态训练模型时,模型会重新训练到当前状态。
  与任何时间序列一样,状态之间的关系随着它们之间的时间增加而减小。 因此,为了解决这个问题,我们需要在训练代理者模型时使用分散在时间轴上的状态。 如果我们拥有历史数据的话,这很容易完成。 但当沿着环境移动时,我们的代理者不曾拥有这样的记忆。 它只能看到当前状态,而不能从一个状态跳到另一个状态。
  那么,我们为什么不为代理者组织记忆呢? 看,要更新动作功用函数的值,我们需要以下数据集:
  状态 -> 动作 -> 奖励 -> 状态
  我们这样做,如此这般在沿环境移动时,代理者将必要的数据集保存到缓冲区之中。 缓冲区大小是一个超参数,由模型体系结构判定。 当缓冲区已满时,新到达的数据将取代较旧的数据。 为了训练模型,我们不会使用当前状态,但我们将使用从代理者记忆中随机选择的数据。 通过这种方式,我们最大限度地减少了各个状态之间的关系,并提高了模型概括分析数据的能力。
  2.2. 使用目标网络
  学习动作功用函数时应注意的另一点是该函数在下一步  maxQ(st+1|at+1)  的最大值。 请注意,这是"来自未来的数值"。 因此,我们根据近似动作功用函数获取预测值。 但在时间  t ,我们不能从时间  t+1  状态更改数值。 每次我们更新函数值时,我们都会更新模型的权重,从而更改下一个预测值。
  甚而,我们训练我们的代理者来获得最大的奖励。 因此,在每次模型更新迭代中,我们都会最大化预期值。 基于预测值以递归方式最大化更新的数值。 以这种方式,我们在级数中最大化我们的动作功用函数值。 这会导致高估我们的函数值,且增加了预测动作功用的误差。 这样并不太好。 因此,我们需要一个固定的机制来评估未来的动作功用。
  我们可通过创建一个额外的模型来预测未来动作功用,从而解决这个问题。 但这种方式需要额外的成本,因为要训练第二个模型。 这是我们极力避免的事情。 另一方面,我们已经在训练一个执行此功能的模型。 但在权重变化后,模型应当如更新之前一样返回函数的值。 这个有争议的问题可以通过复制模型来解决。 我们简单地创建同一动作功用函数模型的两个实例。 一个实例经过训练,另一个实例则用于预测未来动作功用。
  一旦动作功用函数的模型被固定,它很快就会在学习过程中变得无关紧要。 这会令进一步的训练效率低下。 为了消除这一因素的影响,我们需要在学习过程中更新预测值的模型。 第二个实例不会并行训练。 取而代之,我们从动作功用函数模型的已训练实例复制权重至具有一定周期性的第二个实例当中。 因此,仅通过训练一个模型,我们获得了动作功用函数模型的最新 2 个实例,并避免了递归造成的对预测值的高估。
  我们汇总以上内容: 为了训练代理者,我们运用神经网络。 神经网络经过训练,可预测动作功用 Q-函数的期望值。 为了令相邻状态之间的相关性最小化,学习过程使用记忆缓冲区,从中随机提取状态。 为了预测 Q-函数的未来值,准备了第二个目标网络模型,它是训练模型的"冻结"副本。 目标网络是周期性从已训练模型中复制权重矩阵来实现的。
  现在,我们来查看利用 MQL5 描述方式的实现。
  3. 利用 MQL5 实现
  为了利用 MQL5 实现深度 Q-学习算法,我们创建 "Q-learning.mq5" EA 文件。 完整的智能系统代码可在文后附件中找到。 在此,我们只关注深度 Q-学习方法的实现。
  在继续实现之前,我们来决定初始数据和奖励系统是什么。 初始数据与我们之前实验中所采用的数据相同。 那么,奖励系统呢? 我们早前研究的分形预测问题是出于人为。 当然,我们可以创建一个模型来判定最大可能的分形数。 但我们的主要目标是从交易操作中赚取最大的利润。
  以这种上下文状况,采用下一根蜡烛的大小作为奖励大小是完全有意义的。 当然,奖励的符号必须与所执行的操作相对应。 在简化模型中,我们有两种交易操作:买入和卖出。 我们也可能出位。
  在此,我们不会以判定持仓量、加仓、或部分平仓来令模型复杂化。 我们假设代理者可拥有固定手数的持仓。 此外,代理者可以清仓,并离场观望。
  此外,在奖励政策方面,我们必须明白,训练结果在很大程度上取决于精心准备的奖励系统。 强化学习的实践提供了大量示例,若其选择了不正确的奖励政策,则会导致出乎意料的结果。 模型可能学会得出错误的结论。 它也可能陷入试图获得最大奖励,却总也无法达到预期结果的困境。 例如,我们可以奖励模型开仓和平仓。 但若此奖励超过从交易中累积的利润,则模型可以学习简单地开仓和平仓。 那么因,该模型的奖励最大化,而我们的亏损最大化。
  另一方面,如果我们惩罚开仓和平仓模型,类似于一次操作的佣金,则模型可以简单地学会在场外观望。 没有利润,但也没有损失。
  考虑到全部上述所言,我决定创建一个具有三种可能动作的模型:买入、卖出、场外观望。
  代理者将预测每根新烛条的预期走势方向,并在不考虑前期动作的情况下选择一个动作。 因此,为了简化模型,我们不会在代理者中输入有关它是否有持仓或持仓方向的信息。 相应地,代理者不会跟踪开仓和平仓。 开仓和平仓也不会给予奖励。
  为了尽量减少"场外观望"的时间,我们将惩罚没有持仓的情况。 但这样的惩罚应低于持仓亏损的惩罚。
  故此,此为代理者的奖励政策: 一笔盈利持仓获得与烛条主体大小相等的奖励(分析每根烛条的系统状态;我们处于从烛条开盘到收盘的位置)。 "场外观望"状态按照烛台实体的大小(烛台主体大小带负号表示亏损)作为惩罚。 亏损持仓受到双倍烛台主体大小(亏损 + 利润损失)的惩罚。
  现在我们已经定义了奖励系统,我们可以直接转到方法实现。
  如上所述,我们的模型将用到两个神经网络。 为此,我们需要创建两个对象来操控神经网络。 我们将训练  StudyNet ,而  TargetNet  则用于预测 Q-函数的未来值。 CNet                StudyNet; CNet                TargetNet;
  为了规划深度 Q-学习方法的操作,我们还需要新的外部变量来判定构建和训练模型的超参数。 Batch  — 权重更新批量大小 UpdateTarget  — 在复制到"冻结"模型之前,预测未来 Q-函数值的已训练模型的权重矩阵的更新次数 Iterations  — 训练期间已训练模型更新的迭代总数 DiscountFactor  — 未来奖励折扣因子 input int                  Batch =  100; input int                  UpdateTarget = 20; input int                  Iterations = 1000; input double               DiscountFactor =   0.9;
  神经网络模型的创建将在此 EA 之外实现。 为了创建它,我们将取用与迁移学习相关的文章中的工具。 这种方式将允许我们采用各种架构进行实验,而无需修改 EA。 因此,在 EA 初始化方法中,仅实现加载先前创建的模型。 //---    float temp1, temp2;    if(!StudyNet.Load(FileName + ".nnw", dError, temp1, temp2, dtStudied, false) ||       !TargetNet.Load(FileName + ".nnw", dError, temp1, temp2, dtStudied, false))       return INIT_FAILED;
  请注意,由于我们使用同一模型的两个实例,因此两个模型都是从同一文件加载的。
  采用不同架构方案的可能性不仅意味着所采用隐藏层的不同架构及其大小,还意味着调整所分析历史深度的可能性。 之前,我们在 EA 代码中创建模型,历史深度则由外部参数判定。 现在,我们可以通过源数据层的大小来判定所分析的历史深度。 EA 将根据源数据层大小进行分析判定。 只有所分析历史的每根烛条的神经元数量和结果层的大小保持不变。 因为这些参数在结构上与所用的指标和可预测操作的数量有关。    if(!StudyNet.GetLayerOutput(0, TempData))       return INIT_FAILED;    HistoryBars = TempData.Total() / 12;    StudyNet.getResults(TempData);    if(TempData.Total() != Actions)       return INIT_PARAMETERS_INCORRECT;
  我们之前不曾讨论过深度 Q-学习模型中原始层的大小。 如上所述,Q-函数根据状态和所执行的动作返回预期奖励。 为了判定最有用的动作,我们需要计算当前状态下所有可能动作的函数值。 运用神经网络可以创建结果层,其中神经元的数量等于所有可能动作的数量。 在这种情况下,结果层的每个神经元将负责预测特定动作的功用。 神经网络的一次验算就能提供所有动过的功用值。 然后我们只需要选择最大值。
  EA 初始化函数的其余部分保持不变。 附件中提供了其完整代码。
  模型训练过程将在  Train  函数中创建。 在函数体的开头,判定训练场次的大小,并加载历史数据。 这类似于前面研究的有监督和无监督学习算法中的过程。 void Train(void)   { //---    MqlDateTime start_time;    TimeCurrent(start_time);    start_time.year -= StudyPeriod;    if(start_time.year <= 0)       start_time.year = 1900;    datetime st_time = StructToTime(start_time); //---    int bars = CopyRates(Symb.Name(), TimeFrame, st_time, TimeCurrent(), Rates);    if(!RSI.BufferResize(bars) || !CCI.BufferResize(bars) || !ATR.BufferResize(bars) || !MACD.BufferResize(bars))      {       ExpertRemove();       return;      }    if(!ArraySetAsSeries(Rates, true))      {       ExpertRemove();       return;      } //---    RSI.Refresh();    CCI.Refresh();    ATR.Refresh();    MACD.Refresh();
  由于我们采用历史数据来训练模型,因此无需创建记忆缓冲区。 我们可以简单地将所有历史数据当作单独的记忆缓冲区。 但如果模型是实时训练的,我们就需要添加记忆缓冲区,并对其进行管理。
  接下来,准备辅助变量: total  — 训练样本的大小 use_target  — 目标网络所用的标志,来预测未来奖励    int total = bars - (int)HistoryBars - 240;    bool use_target = false;
  我们用到  use_target  标志,因为我们需要在 Target Net 模型首次更新之前禁用预测未来奖励。 这实际上是一个非常微妙的观点。 在初始步骤中,以随机权重初始化模型。 因此,所有预测值都是随机的。 最有可能的是,它们与真实值相去甚远。 采用此类随机值可能会令模型学习过程失真。 在这种情况下,模型将近似的不是真实的奖励值,而是嵌入在模型本身中的随机值。 因此,在 Target Net 模型第一次迭代更新之前,我们应该剔除这种噪音。
  接下来,实现代理者训练循环系统。 外部循环将计算更新代理者权重矩阵的迭代总数。    for(int iter = 0; (iter < Iterations && !IsStopped()); iter += UpdateTarget)      {       int i = 0;
  在嵌套循环中,我们将计算权重更新批次大小,和 Target Net实现之前的更新次数。 这里应该注意的是,我们模型中的权重在反向传播验算的每次迭代中都会更新。 因此,使用更新批次看起来不太正确,因为对于我们的模型,它始终设置为 1。 然而,为了平衡 Target Net 实现之间的已处理状态数,其频率将等于封包大小与实现之间的更新次数的乘积。
  在循环体中,我们随机判定当前模型训练迭代的系统状态。 我们还清除缓冲区,以写入两个后续状态。 第一个状态将用于训练模型的前馈验算。 第二个将用于 Target Net.中的预测 Q-函数值。       for(int batch = 0; batch < Batch * UpdateTarget; batch++)         {          i = (int)((MathRand() * MathRand() / MathPow(32767, 2)) * (total));          State1.Clear();          State2.Clear();          int r = i + (int)HistoryBars;          if(r > bars)             continue;
  然后,在嵌套循环中,用历史数据填充准备好的缓冲区。 为避免不必要的操作,在填充第二个状态缓冲区之前,请检查 Target Net 标志的使用情况。 仅在必要时才会填充缓冲区。          for(int b = 0; b < (int)HistoryBars; b++)            {             int bar_t = r - b;             float open = (float)Rates[bar_t].open;             TimeToStruct(Rates[bar_t].time, sTime);             float rsi = (float)RSI.Main(bar_t);             float cci = (float)CCI.Main(bar_t);             float atr = (float)ATR.Main(bar_t);             float macd = (float)MACD.Main(bar_t);             float sign = (float)MACD.Signal(bar_t);             if(rsi == EMPTY_VALUE || cci == EMPTY_VALUE || atr == EMPTY_VALUE || macd == EMPTY_VALUE || sign == EMPTY_VALUE)                continue;             //---             if(!State1.Add((float)Rates[bar_t].close - open) || !State1.Add((float)Rates[bar_t].high - open) ||                !State1.Add((float)Rates[bar_t].low - open) || !State1.Add((float)Rates[bar_t].tick_volume / 1000.0f) ||                !State1.Add(sTime.hour) || !State1.Add(sTime.day_of_week) || !State1.Add(sTime.mon) ||                !State1.Add(rsi) || !State1.Add(cci) || !State1.Add(atr) || !State1.Add(macd) || !State1.Add(sign))                break;             if(!use_target)                continue;             //---             bar_t --;             open = (float)Rates[bar_t].open;             TimeToStruct(Rates[bar_t].time, sTime);             rsi = (float)RSI.Main(bar_t);             cci = (float)CCI.Main(bar_t);             atr = (float)ATR.Main(bar_t);             macd = (float)MACD.Main(bar_t);             sign = (float)MACD.Signal(bar_t);             if(rsi == EMPTY_VALUE || cci == EMPTY_VALUE || atr == EMPTY_VALUE || macd == EMPTY_VALUE || sign == EMPTY_VALUE)                continue;             //---             if(!State2.Add((float)Rates[bar_t].close - open) || !State2.Add((float)Rates[bar_t].high - open) ||                !State2.Add((float)Rates[bar_t].low - open) || !State2.Add((float)Rates[bar_t].tick_volume / 1000.0f) ||                !State2.Add(sTime.hour) || !State2.Add(sTime.day_of_week) || !State2.Add(sTime.mon) ||                !State2.Add(rsi) || !State2.Add(cci) || !State2.Add(atr) || !State2.Add(macd) || !State2.Add(sign))                break;            }
  用历史数据成功填充缓冲区之后,检查它们的大小,并执行两个模型的前馈验算。 不要忘记检查操作结果。          if(IsStopped())            {             ExpertRemove();             return;            }          if(State1.Total() < (int)HistoryBars * 12 ||             (use_target && State2.Total() < (int)HistoryBars * 12))             continue;          if(!StudyNet.feedForward(GetPointer(State1), 12, true))             return;          if(use_target)            {             if(!TargetNet.feedForward(GetPointer(State2), 12, true))                return;             TargetNet.getResults(TempData);            }
  前馈验算完成后,我们从环境中获得奖励,并根据上面定义的奖励政策为反向传播验算准备目标缓冲区。
  请注意以下两个时刻。 第一个点,我们检查 Target Net 标志的使用。 仅在结果为正面的情况下添加预测值。 如果将标志设置为 false,则 Q-函数的预测值应设置为 0。
  第二个点则是从贝尔曼方程偏转。 您还记得,贝尔曼方程采用未来奖励的最大值。 以这种方式,训练的模型能赚取最大的利润。 当然,这种方式可以带来最大的盈利能力。 但在交易的情况下,当价格图表充斥着很多噪音时,这会导致交易数量的增加。 甚至,噪声降低了预报的品质。 这可与在每根新蜡烛尝试预测进行比较。 着可能导致几乎在每根新蜡烛都开仓和平仓,取代判定趋势,并在趋势方向上开仓。
  为了消除上述因素的影响,我决定从贝尔曼方程中转移。 为了更新 Q-函数模型,我将采用单向值。 最大值则仅用于"场外观望"动作。          Rewards.Clear();          double reward = Rates[i - 1 + 240].close - Rates[i - 1 + 240].open;          if(reward >= 0)            {             if(!Rewards.Add((float)(reward + (use_target ? DiscountFactor * TempData.At(0) : 0))) ||                !Rewards.Add((float)(-2 * (use_target ? reward + DiscountFactor * TempData.At(1) : 0)))                ||                !Rewards.Add((float)(-reward + (use_target ? DiscountFactor * TempData.At(TempData.Maximum(0, 3)) : 0))))                return;            }          else             if(!Rewards.Add((float)(2 * reward + (use_target ? DiscountFactor * TempData.At(0) : 0))) ||                !Rewards.Add((float)(-reward + (use_target ? DiscountFactor * TempData.At(1) : 0))) ||                !Rewards.Add((float)(reward + (use_target ? DiscountFactor * TempData.At(TempData.Maximum(0, 3)) : 0))))                return;
  准备好奖励缓冲区后,在已训练模型中运行反向传播验算。 再次检查操作执行结果。          if(!StudyNet.backProp(GetPointer(Rewards)))             return;         }
  这样就完成了嵌套循环的操作,计算代理者训练的迭代次数。 完成后,更新 Target Net 模型。 我们的模型没有权重交换方法。 我决定不发明任何新东西。 取而代之,我们将采用现有机制来保存和加载模型。 在这种情况下,我们得到了模型及其所有内容的精确副本。
  因此,将已训练模型保存到文件中,并将保存的模型从该文件加载到 TargetNet。 不要忘记检查操作结果。       if(!StudyNet.Save(FileName + ".nnw", StudyNet.getRecentAverageError(), 0, 0, Rates[i].time, false))          return;       float temp1, temp2;       if(!TargetNet.Load(FileName + ".nnw", dError, temp1, temp2, dtStudied, false))          return;       use_target = true;       PrintFormat("Iteration %d, loss %.5f", iter, StudyNet.getRecentAverageError());      }
  成功更新 TargetNet 模型后,更改其使用标志,将包含信息的消息打印到日志,然后继续执行外部循环的下一次迭代。
  一旦训练过程完成后,清除注释,并启动关闭模型训练 EA。    Comment(""); //---    ExpertRemove();   }
  完整的智能系统代码可在文后附件中找到。
  4. 测试
  该方法已基于过去 2 年的 H1 时间帧 EURUSD 数据进行了测试。 在之前的所有实验中都采用相同的数据。 指标采用默认参数。
  出于测试目的,创建了以下架构的卷积模型: 初始数据层,240 个元素(20 根蜡烛,每根蜡烛含 12 个神经元)。 卷积层,输入数据窗口 24(2 根蜡烛),步长 12(1 根蜡烛),6 个滤波器输出。 卷积层,输入数据窗口 2,步长 1,2 个过滤器。 卷积层,输入数据窗口 3,步长 1,2 个过滤器。 卷积层,输入数据窗口 3,步长 1,2 个过滤器。 含有 1000 个元素的完全连接神经层。 含有 1000 个元素的完全连接神经层。 由 3 个元素组成的完全连接层(3 个操作的结果层)。
  从 2 到 7 层由 sigmoid 激活。 对于结果层,双曲正切用作激活函数。
  下图显示了误差动态图。 如您从图中可见,在学习过程中,预测预期奖励的误差正在迅速减少。 经过 500 次迭代后,它变得接近 0。 模型经过 1000 次迭代训练过程后以 0.00105 的误差结束。
  结束语
  在本文中,我们继续研究强化学习方法。 我们研究了 DeepMind 团队在 2013 年引入的深度 Q-学习方法。 这项工作的发表开启了强化学习方法发展的新阶段。 该方法展示了训练模型构建策略的可能性前景。 神hi,运用一个模型就可训练它来解决各种问题,而无需对其架构或超参数进行结构更改。 这些是训练算法优于 EA 结果的第一次实验。
  我们已见识到利用 MQL5 实现该方法。 模型测试结果证明了运用该方法构建工作交易模型的可能性。
  参考文献列表运用深度强化学习玩转 Atari 神经网络变得轻松(第二十五部分):实践迁移学习 神经网络变得轻松(第二十六部分):强化学习 本文中用到的程序
  #
  名称
  类型
  说明
  1
  Q-learning.mq5   EA   训练模型的智能系统   2
  NeuroNet.mqh   类库   创建神经网络模型的类库   3
  NeuroNet.cl   代码库   创建神经网络模型的 OpenCL 程序代码库

匈牙利华人华侨妇女联合会举行三八国际妇女节庆祝活动2023年3月8日,匈牙利华人华侨妇女联合会在布达佩斯九龙饭店举行三八国际妇女节庆祝活动,匈牙利妇女联盟组织代表匈牙利妇女儿童健康协会代表匈牙利VELENCE市市长匈牙利龙舟协会会怀孕初期要在饮食方面或者日常生活方面注意哪些事?10年妇产科护士长建议,孕妇再忙,这6件家务事都不能做!1。孕妇不能搬重物搬重物用力过猛,容易造成流产2。炒菜洗碗油烟味容易引起强烈孕吐,长期接触洗洁精也可能对胎儿有影响3。做宠物前辽足门将张振强疑似被带走调查,昨日还在参加比赛今天失联直播吧3月17日讯据博主浙江队情报小组报道,前辽足门将张振强被带走。媒体人李平康在个人微博中写道行动速度太快了,不同地点同时出击守门员少了好几个!媒体人杜立言在个人微博中写道不止一宠物保险陷阱调查定点医院随时变保额虚高实用性引质疑宠物医疗险定点医院随时变,致理赔扯皮,免责条款多且单次赔付有限额,保额虚高。有消费者为宠物看病花费460元,减去单次200元的免赔额,再减去255元非保障范围内金额,最后再按定点医孕期散步不是说走就走,这些讲究你知道吗?对于孕妇来说,散步是安全有效且又简单方便的运动方式。那么,一般多长时间合适呢?散步的时间要考虑自身的情况和孕期的运动时间,原则是时间由短到长,逐步增加,对正常孕妇,建议每天至少散步产妇补身第一周和第二周大有学问第一周以清除恶露促进伤口愈合为主,养血活血,帮助子宫排出污血,身体利水消肿,促进子宫收缩,恢复子宫正常机能,重点是开胃不是滋补,所以不能大补特补,胃好才会食之有味,吸收好。全英公开赛国羽全线晋级男单表现惊艳北京时间3月17日凌晨,正在伯明翰进行的2023全英羽毛球公开赛结束了第二轮16进8的全部争夺。在18决赛中,国羽在外战中保持全胜,共有13人(对)运动员闯入八强。也就是说,除了混11年前,被父亲逼迫在雪地裸跑的4岁小男孩,如今成就惊艳四方!2012年1月22日,一段视频突然在国外媒体平台上爆火。视频的内容是一名年仅3岁的小男孩身着一条黄色小短裤和白色运动鞋在零下13摄氏度美国纽约街头的寒冬里赤裸着身子裸跑,一边跑着一世界上寿命最长的王朝,至今还存在,已延续2680年,传位126代日本的菊花王朝,是世界上最长寿命的王朝之一,起源于日本神话,延续至今已经超过2680年,传位126代。其历史可以追溯到公元前660年,正是中国的东周春秋时期。在这个时期,中国已经经ChatGPT有关地球的恐怖故事很久以前,地球上生活着一种神秘的生物,它们被称为地球之眼。这种生物看起来像是一只巨大的蜘蛛,有着无数只锐利的触角和观察者的眼睛。它们能够穿透岩石和土壤,探测地下的一切事物,包括地下恐怖游戏逃生试炼抢先体验版5月18号推出开发商RedBarrels今日宣布恐怖游戏逃生系列新作逃生试炼的抢先体验版将于2023年5月18号发售,登陆Steam和EpicGamesStore。游戏简介故事发生在冷战时期,穆
房价复苏,二手房正在崛起!买房的时候到了吗?前两天统计局公布数据,春节以来部分重点城市销售出现回暖迹象,销售数据恢复超过此前市场预期。究其原因,主要在于年前因疫情积压的部分置业需求释放,开发商集体回收部分折扣助推购房情绪上涨硅谷银行在破产前提供给内部人员的贷款增加了两倍至2。19亿美元硅谷银行在破产前提供给内部人员的贷款增加了两倍至2。19亿美元财联社3月22日电,美国政府数据显示,硅谷银行在破产前,向该行高管董事和主要股东及其相关利益方提供的贷款在2022年最2月份湖南全社会用电量同比增长10。1来源中国经济网中国经济网2月份,湖南全社会用电量为178。79亿千瓦时,同比增长10。1。其中,工业用电量83。06亿千瓦时,增长62。3。数据显示,12月,湖南全社会用电量为36股价持续飙增,业绩却常年亏损,瑞尔集团后市怎么看?民间常说,金眼科银外科开着宝马口腔科在民营医疗几大热门赛道中,近几年口腔医疗领域展现了超高的吸金能力。据不完全统计,2022年中国口腔医疗市场投融资事件60余起,有金额披露部分总额CXO龙头业绩劲升,新技术新能力突破持续打开成长空间药明康德(603259。SH)3月21日披露了2022年年报,全年营收达393。55亿元,同比增长71。8,无论是营收规模还是增速均创下历史新高。同时,归母净利润增速亦首次超过收入祥生控股集团将延迟发布2022年全年业绩,股票自4月3日起停牌祥生IC资料图3月21日晚间,祥生控股集团(02599。HK)公告称,公司预计无法按照港交所的规定在2023年3月31日前刊登2022年全年业绩。根据公告内容,对于延迟发布2022实探全面通关以后,香港购物中心恢复人从众模式了吗?自2月3日,国务院港澳办宣布,取消所有香港和内地的通关限制,全面恢复通关以来,去香港游玩购物又成为热议的话题。苦等三年,小红书上的香港游玩攻略又支棱起来了,香港代表性交通工具双层有韩国2月外汇存款减少117。3亿美元,创11年多最大降幅韩国央行周三公布的数据显示,由于企业储蓄减少,2月份外汇存款出现了约11年来的最大降幅。截至2月底的居民外汇存款余额为975。2亿美元,比前一个月减少了117。3亿美元,是自201大量韩国游客涌向中国,不是为了来感受历史文化,而是来囤积白酒随着疫情的结束,很多旅游都开始提上日程了,特别是旅游,不仅可以给大家带来轻松愉悦,还能够使人增长知识。就像是我国的历史文化,本身就要比别的国家悠久许多,尤其是近两年,很多的外国人纷Filecoin虚拟机上线一周,数据表现如何?Filecoin的虚拟机上线一周了,大家肯定更关心它的数据表现,后山客带大家解读下FVM的运行数据情况,先做个说明,FVM刚上线一周,基于它构建的很多生态项目还未上线或者刚具备雏形马卡皇马方面尊重穆里尼奥,但未考虑过重邀其担任主帅直播吧3月22日讯马卡报的消息,皇马方面并没有考虑过重新请回穆里尼奥担任主帅一职。该媒体表示皇马方面对于穆里尼奥是欣赏且尊重的,但是没有考虑过重新邀请其回归担任主帅,皇马目前在联赛