神经网络变得轻松:分布式 Q-学习

分布式Q-学习是经典Q-学习的扩展,它通过估算奖励概率分布而不是单一值来改进策略。该方法使用LogLoss作为损失函数,通过SoftMax函数规范化每个动作的奖励概率。在MQL5环境中,通过修改神经网络的SoftMax层以适应分布估计,并利用目标网络稳定学习过程。在测试中,基于分布式Q-学习的模型在模拟交易中显示出盈利潜力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 分布式 Q-学习的特征

分布式 Q-学习与原始 Q-学习一样,近似估算动作功效函数。 同样,我们将近似估算 Q-函数,来预测预期奖励。 主要区别在于,我们不会针对已完成操作在特定状态下近似单独的奖励值,而是整体期望奖励的概率分布。 当然,由于资源有限,我们无法估算每个单独奖励值出现的概率。 但是我们能把可能的奖励范围划分为多个范围,即分位数。

引入了其它参数来判定分位数 这些是期望奖励范围内的最小(Vmin)和最大(Vmax)值,以及分位数(N)。 以下公式计算一个分位数的数值范围。

与暗示自然奖励值近似估算的原始 Q-学习方法不同,分布式 Q-学习算法在特定状态下执行特定操作时,近似估算在分位数内获得奖励的概率分布。 将问题转换为概率分布任务,我们就可以将 Q-函数近似问题转换为标准分类问题。 这会导致损失函数发生变化。 原本的 Q-学习采用标准差作为损失函数,但分布式 Q-学习方法将采用 LogLoss。 我们之前在研究政策梯度时曾研究过这个函数。

以这样方式,我们可以近似估算出每个状态-行动配对的奖励概率分布。 因此,在选择动作时,我们在判定预期奖励及其概率能得到更高的准确性。 另一个优点是能够估算特定奖励水平的概率,而非平均奖励的概率。 当评估从系统当前状态执行一个动作后,其获得正面和负面奖励的概率时,这样能够使用基于风险的方式。

若在类似情况下的相同行动,环境同时返回积极和消极的奖励时,其结果就会产生最大的成效。 原始的 Q-学习算法使用期望奖励的均值,在这种情况下,我们通常会得到的数值接近 0。 结果就是,将跳过该动作。 而改用分布式 Q-学习算法时,我们能够估算获得真实奖励的概率。 使用基于风险的方法将有助于做出正确的决定。

请注意,当代理者执行任何可能的动作时,环境肯定会给予奖励。 因此,对于从当前环境状态执行的代理的任何操作,我们期望获得奖励的概率 100%。 对于每个代理者动过的概率总和应等于 1。 此结果可以通过在可能的动作中调用 SoftMax 函数来达成。

我们仍将使用原始 Q-学习算法的所有工具。 其中包括体验重播缓冲区,和预测未来奖励的目标网络模型。 自然而然,我们将利用折扣因子来获得未来奖励。

模型训练基于原始 Q-学习的原理。 该过程本身基于贝尔曼(Bellman)方程。

正在上传…重新上传取消

如上所述,我们将利用目标网络来评估未来奖励的预测值,目标网络是正在训练模型的“冻结”副本。 我想详谈一下运用它的方式。

强化学习和 Q-学习的特点之一是能够建立动过策略,从而获得最佳结果。 为了能够构建策略,贝尔曼方程包括一个未来状态的数值。 事实上,对环境未来状态的评估应该包括从状态到场次结束的最大可能奖励。 缺了此标量,经训练的模型仅能预测当前过渡到新状态的预期奖励。

但我们从另一面看这个过程。 在场次结束之前,我们并没有真正得到全额奖励。 因此,我们利用第二个神经网络来预测缺失的数据。 为了避免并行训练两个模型,我们取具有冻结权重的可训练模型的副本,来预测未来状态的奖励。 来自未经训练的模型的预测是否准确? 它们很可能是完全随机的。 但通过为训练模型目标引入随机值,我们干扰了对环境的感知,并将训练引向错误的方向。

通过在初始阶段排除使用目标网络,我们能够训练模型以一定的准确性预测当前过度期的奖励。 好吧,该模型将无法构建策略。 但这只是学习的第一阶段。 如果我们有一个能够提前一步给出合理预测的模型,我们就能将其当作目标网络。 之后,我们能另外训练模型,从而提前两步构建策略。

这种方式经由目标网络分阶段更新,并采用合理的预测未来状态值,将令模型能够构建正确的策略。 以这种方式,我们就能得到想要的结果。

我想再补充几句关于未来奖励价值的折扣因子。 这是在策略构建中管理模型预见的工具。 此超参数在很大程度上影响正在构建的策略类型。 选取接近 1 的系数指示模型构建长线策略。 在这种情况下,该模型将构建长期投资策略。

与此对比,减少此参数且令值接近 0,会迫使模型忘记未来的奖励,而更加关注在短期内的盈利。 那么,该模型将构建剥头皮策略。 当然,持仓时间会受到所取时间帧的影响。

我们来总结一下以上内容。

  1. 分布式 Q-学习方法基于经典的 Q-学习,并对其进行了补充。
  2. 有一个神经网络当作模型。
  3. 在训练过程中,我们根据状态-操作配对,近似地估算过渡到新状态的预期奖励的概率分布。
  4. 分布由一组固定薪酬范围的分位数表示。
  5. 分位数和可能值的范围由超参数确定。
  6. 每个可能动作的分布由相同的概率向量表示。
  7. 为了规范化概率分布,我们在每个动作的关联中调用 SoftMax 函数。
  8. 该模型是基于贝尔曼方程进行训练的。
  9. 解决问题的概率方式需要调用 LogLoss 作为损失函数。
  10. 为了令学习过程稳定,我们利用原始 Q-学习算法(目标网络,体验回播缓冲区)的启发式方法。

与往常一样,理论部分之后就是利用 MQL5 实际实现。

2. 利用 MQL5 实现

在继续利用 MQL5 实现分布式 Q-学习方法之前,我们先来制定一个工作计划。 正如理论部分所述,该方法基于原始的 Q-学习算法。 我们之前已经实现了这个算法。 因此,我们可以基于先前所用的那个创建一个智能系统。

采用概率方式需要修改传输模型目标值所在的模块。

在模型输出中,我们需要调用 SoftMax 函数对数据进行归一化。 我们已在有关政策梯度的文章中遇到了这个函数,并实现了它。 在那篇文章中,我们还对概率进行了归一化。 那次,我们用到了选择动作的概率。 数据在整个神经层内归一化。 现在我们需要分别规范化每个动作的分布概率。 这意味着我们不能以纯净形式使用之前创建的 CNeuronSoftMaxOCL 类。

因此,我们有 2 个选项。 我们可以创建一个新类,或修改现有类。 我决定采取第二个选项。 之前创建的类其结构如下。

class CNeuronSoftMaxOCL    :  public CNeuronBaseOCL
  {
protected:
   virtual bool      feedForward(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) override { return true; }

public:
                     CNeuronSoftMaxOCL(void) {};
                    ~CNeuronSoftMaxOCL(void) {};
   virtual bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL);   
   virtual bool      calcOutputGradients(CArrayFloat *Target, float& error) override;
   //---
   virtual int       Type(void) override  const   {  return defNeuronSoftMaxOCL; }
  };

首先,我们添加一个变量来存储可规范化向量 iHeads 的数量,以及指定此参数的方法 - SetHeads。 默认情况下,我们将指定 1 个向量。 这对应于整个层内数据的规范化。

class CNeuronSoftMaxOCL    :  public CNeuronBaseOCL
  {
protected:
   uint              iHeads;
.........
.........
public:
                     CNeuronSoftMaxOCL(void) : iHeads(1) {};
                    ~CNeuronSoftMaxOCL(void) {};
.........
.........
   virtual void      SetHeads(int heads)  { iHeads = heads; }
.........
.........
  };

如您所知,添加新变量并不会更改类方法的逻辑。 接下来,我们应修改方法的算法。 我们主要对前馈和反向传播方法感兴趣。 前馈传递是通过 feedForward 方法实现的。 请注意,此方法仅实现了调用 OpenCL 程序相应内核的辅助算法。 所有计算都在 OpenCL 关联环境端的多线程模式下执行。 因此,在更改将内核放入执行队列相关的操作之前,我们需要在程序的 OpenCL 端进行更改。

我们说明一下原因。 SoftMax 函数的具体特征是对数据进行规范化,令整个结果向量的总和等于 1。 该函数的数学公式如下所示。

正在上传…重新上传取消

如您所见,规范化的数据取自整个源数据向量的指数值之合计。 使用局部数据数组,我们在同一内核的不同线程之间传输数据。 这样就可在 OpenCL 关联环境端创建函数的多线程实现。 我们创建的算法在一维问题空间中运行。 它规范化单个向量中的数据。 为了解决新算法的问题,我们需要将整个初始数据量划分成几个相等的部分,并分别对每个部分进行归一化。 此处的难题在于我们不知道这些散件的数量。

即便硬币也有好的一面。 每个单独的模块可以彼此独立地规范化。 这完全符合我们对于多线程计算的概念。 因此,对于分布式数据规范化,我们可以运行先前创建的内核的其它实例。

我们只需要将源数据缓冲区和结果缓冲区的总体积派发到相应的模块当中。 之前,我们是在一维任务空间中启动内核。 OpenCL 技术支持使用三维任务空间。 在这种情况下,我们不需要第三个维度。 无论如何,我们能够用第二维来识别规范化模块。

因此,为任务空间添加另一个维度,我们在之前创建的 SoftMax_FeedForward 类中启用了分布式规范化。 我们仍然需要在内核代码中进行修改。 但这些修改很微小。 我们需要将第二个任务空间维度的处理添加到内核算法当中。

内核参数保持不变。 在参数中,我们传递指向数据缓冲区的指针,和一个数据规范化向量的大小。

__kernel void SoftMax_FeedForward(__global float *inputs,
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值