亚马逊AWS官方博客

利用深度强化学习实现金融决策自动化

Original URL:https://aws.amazon.com/blogs/machine-learning/automated-decision-making-with-deep-reinforcement-learning/

机器学习 (ML) 已经常态化应用于各个行业,但除了简单的预测场景之外,还有更为复杂的决策制定场景,为了支持长期的战略性目标,人们有时会选择,甚至必须作出非最优的短期决策。利用一种叫做强化学习 (RL) 的 ML 模型,可以学习如何优化策略,从而根据长期目标制定系列决策。

Amazon SageMaker 是一款模块化、完全托管的服务,它可帮助开发人员和数据科学家构建、训练和部署任意规模的 ML 模型。除构建有监督和无监督 ML 模型外,您还可以在 Amazon SageMaker 中构建 RL 模型。Amazon SageMaker RL 以 Amazon SageMaker 为基础构建,添加了预先打包的 RL 工具套件,可以轻松集成任何自定义模拟环境。训练和预测基础设施是完全托管的,让您可以专注于 RL 问题,而非服务器的管理。

在本文中,我将演示如何使用 RL 来训练智能代理,以在简单竞价环境中的每个时间步作出智能决策。该 RL 智能代理将选择是否按照给定的价格买入或卖出一项资产,以实现最大长期利润。我将首先介绍深度强化学习背后的数学概念,并描述 Amazon SageMaker RL 中的交易智能代理的一个简单自定义实现。我还将比较两种不同实现方法的基准测试结果。第一种方法也是最直接的方法,在这种方法中,智能代理将回顾过去 10 天的历史来预测买入、卖出以及什么也不做之间的最佳决策。在第二种方法中,我将设计一个进行时间序列预测深度学习的递归神经网络 (RNN),智能代理的动作将基于 RNN 作出的预测。在智能代理进行决策并学习最优的策略以实现最大长期利润过程中,RNN 编码器将扮演顾问的角色。

本文使用的数据由以美元为单位的财务时间序列组成,是一个无特定场景限制的竞价系统,代表任意资产的价格。您可以将此数据想象成 EC2 Spot 实例的价格或者公开上市股票的市值。

深度强化学习简介

事件的预测是容易理解的,但是决策的制定却相对复杂。强化学习的框架定义了一个系统,这个系统可以通过学习以作出动作和决策,从而达到既定的长期目标。这一部分将介绍深度强化学习背后的主要动机、概念和公式。如果您熟悉 RL 的概念,则可以跳过这一部分。

概念和术语

有监督学习利用模型训练中目标输出的标签来预测未知数据的目标输出。无监督学习不需要利用标签,而是学习训练数据中的固有模式,然后利用学习到的模式对未知数据进行分组。有时,带标签的数据仅部分可用,或者您只能够定义目标输出并且您需要了解如何拿到这些输出,或者需要根据总体结果进行权衡和妥协(例如,如何平衡日常工作与个人生活以保持长期幸福)。这些场景都是 RL 能够发挥作用的地方。需要 RL 的原因其实是因为您无法定义完整的监督过程,只能根据所作出的动作定义反馈信号,以及您需要学习如何逐步作出最优决策。

要定义 RL 框架,您需要一个智能代理(学习系统)、一个环境,这个智能代理将在这个环境中制定决策,您还需要为学习系统(即智能代理)定义一个目标,然后您需要将此目标转化为一个叫做 奖励函数的数学公式,该函数将在智能代理作出动作时进行奖励或惩罚,作为反馈环路,以帮助智能代理达到预定目标。RL 有三个关键要素:状态动作奖励;在每个时间步,智能代理都将收到一个有关环境状态st 的表达,然后根据 st 作出动作 at,最后根据 st+1 = (st, at) 收到一个数值奖励 rt+1

下图演示了强化学习的关键要素。

奖励函数的定义可能很容易,也可能需要丰富的经验。例如,在 AWS DeepRacer League 公告中,参与者必须发明自己的 RL 奖励函数才能参与全世界的虚拟和现场车赛,原因是,在编写本文之时,还没有人知道如何定义最佳策略才能使赛车赢得比赛。而对于交易智能代理,奖励函数可能就是累计总利润这样简单,因为这始终是交易员努力实现的一个关键绩效指标。

在大多数情况下,根据所作出的动作,智能代理遇到的新情况可能会随着时间推移而变化,因此 RL 问题需要将这些情况与特定情况下需要作出的最优动作映射起来。一般的 RL 问题包含为了最大化奖励而学习的整个动作序列,称为策略并标记为 ?(a|s)。

在探索寻找最优策略的方法之前,您可以首先确定学习的目标,即通过定义累计回报 Gt 的概念来最大化某个时间步 t 后的累计奖励:

如果有最终步,则每个动作子序列都叫做一个片段,并且说该 MDP(马尔可夫决策过程) 有限。如果智能代理与环境之间的交互无限持续,则说该 MDP 无限,在这种情况下,您可以举出折扣的概念来定义数学上统一的累计回报概念:

γ = 1 且 T 有限,则此公式是 Gt 的有限公式;若 γ < 1,则自然会出现片段,即使 T 无限,因为与具有较小值 k 的量相比,具有较大值 k 的量将以指数级加速变小。因此,无限 MDP 的和将会收敛,并且这一概念对有限和无限 MDP 都有效。

通过 RL 优化序列决策

为了解决这个一般的 RL 问题,人们已经开发了大量的优化方法。这些方法一般可以分为基于策略的方法或基于值的方法,或者两者的组合。我们将在下文重点介绍基于值的方法。

基于策略的 RL

在基于策略的 RL 中,策略是某些参数 θ 的有参函数:?θ = ?(a|s,θ) 并且可根据标准梯度法直接估计。这将通过定义性能指标来实现,通常该指标是给定策略的预期值 Gt,通过执行梯度上升法来寻找能够最大化此性能指标的 θ。只要 ? 对 θ 可导,那么 ?θ 就可以是 ? 的任何有参函数形式,因此可以使用神经网络来估计,其中参数 θ 是神经网络的权值参数,并且该神经网络将根据输入状态预测完整策略。

直接策略搜索则相对简单,但也非常有限,因为它试图直接利用之前的经验策略集估计完整策略。如将基于策略的 RL 与基于值的 RL 组合使用来优化 Gt 的估值,准确性和收敛性几乎肯定可以提高,因此本文将专注于基于值的 RL。

基于值的 RL

RL 过程属于马尔可夫决策过程 (MDP),这是连续决策的数学形式化,借此您可以对RL过程做出精确表达。一个 MDP 包含一个序列 (s0, a0, r1, s1, a1, r2, …, sn) 或更通用的 (st, at, rt+1, st+1)n,上图中演示的 MDP 动态的完整特征由一个转移概率 T(s,a,s’) = p(s’|s,a) 和一个奖励函数 r(s,a) = ?(r|s,a) 描述,前者定义了任何状态 s 将变为另一个状态 s’ 的概率,后者定义了给定状态 s 的期望奖励。

由于 RL 的目标是学习最大化 Gt 的最优策略,本文将首先介绍如何评估 MDP 中的策略,然后介绍如何找到最优策略。

要评估一个策略,您需要为状态 state s 定义一个叫做状态值函数 V(s) 的指标,该函数将估计作出特定动作时,它在 s 状态的优劣。即,对于特定的策略 ?:

在上一部分中我们提到,Gt 由从当前时间步 t 至最终时间步 T 的奖励的累加和定义。将 Gt 替换为上一部分中公式的右侧部分,并从求和公式中移除 rt+1,则得:

用全概率收益的和替换期望:

后者被称为贝尔曼公式;借助该公式,您可以根据 Tr 计算任意 ? 的 V?(s),以及根据时间步 t+1 的上一 V 值,递归计算时间步 t 的新 V 值。您可以通过统计所有观察到的在智能代理与环境之间的交互集中的转移以及奖励,估计 TrTr 决定了 MDP 的模型。

前面您学习了如何评估策略,现在可以将状态值函数的概念扩展到状态-动作值函数 Q(s,a),从而定义最优策略:

后者称为贝尔曼最优方程;它会估计在特定状态 s 作出特定动作 a 的值,并假设您之后将会作出最优动作。如果您将贝尔曼最优方程转换变为一个赋值函数,您将得到一个迭代算法,假设已知 Tr,从所有状态中的所有可能动作中随机采样,该算法将会保证收敛至最优策略。由于您可以按任何顺序执行此公式,此迭代算法被称为异步动态编程。

对于您可以轻松计算或采样 Tr 的系统,这种方法已能充分满足要求,被称为基于模型的 RL,因为转移动态(以 Tr 为特征)已知(之前已经计算出)。但对于大多数真实问题,更方便的做法是根据已经积累的经验生成对 Q 值的随机估计,从而让 RL 智能代理在每一步都实时学习,并最终朝 Q 值的真实估计收敛。为此需要将异步动态编程与移动平均值的概念结合使用:

并将 Gt(s) 替换为贝尔曼最优方程中定义的某个采样值:

后者被称为时序差分学习;通过它可以根据 Q*k(s,a) 与 Q*k(s’,a’) 之间的差来更新移动平均值 Q*k+1(s,a)。本文演示了一个单步时序差,这是 Q 学习算法中使用的最基础版本,当然您可以扩展此方程,以包含多步(n 步时序差)。同样,有定理证明若无限随机选择动作,Q 学习将会向最优策略 ?* 收敛。

RL 动作选择策略

您可以使用 ε-Greedy策略等更高效的随机动作选择策略,以增加对优化策略中常见状态的采样,减少对价值较低状态的采样,从而缓解无限随机动作选择条件。在 ε-Greedy策略中,智能代理将会选择具有概率 ε 的随机动作,而在其他时间(即概率为 1 – ε),智能代理将会根据最新 Q 值(定义为 )选择最优动作。

这种策略有利于您平衡利用最新 Q 值和探索新状态及动作的需要。一般来说,最初选择的 ε 将会较大,以利于探索状态动作空间,但会逐步降至较小的值。例如,ε = 1% 将会在大部分时间利用 Q 值,但同时可以保持探索和发现潜在的更好的策略。

将深度学习与强化学习结合使用

在许多情况下,例如在下国际象棋或围棋时,状态、动作及其组合的数量过大,以致存储 Q 值所需的内存和时间也将十分巨大。在围棋中,状态和动作的组合数量超过了宇宙中已知星辰的数量。深度 RL 不会在一个矩阵中存储所有状态和动作的 Q 值,因为这对于 围棋以及许多其他场景而言是不可能的,因此深度 RL 会尝试利用状态和动作的子集来泛化经验,形成新的状态和动作。下图是对使用查询表和函数近似进行 Q 学习的比较。

深度 Q 学习使用有监督学习函数逼近Q(s,a) ,并以 为标签,因为 Q 学习赋值函数相当于通用公式的 x  = x – ∝∇J(对于任意 x)的梯度更新,其中:

后者被称为平方贝尔曼损失;通过它可以使用深度学习网络,从状态和动作与 Q 值的映射的泛化中估计 Q 值,因此也被称为深度 Q 学习。

深度 Q 学习不再保证收敛,因为有监督学习使用的标签取决于网络权重的当前值,而网络权重本身又会根据标签值的学习进行更新,因此会导致遍历性毁坏的问题。但这种方法在实践中往往足够有用,可以泛化大部分的 RL 问题(例如自动驾驶、机器人、玩围棋等)。                                                                      

在深度 RL 中,每一步的训练集都会变化,因此您需要定义一个缓冲以支持批量训练,并制定计划,随着智能代理实时学习经验的积累定期刷新。这被称为经验回放,就好比生物系统的梦中学习:经验回放有利于您持续利用内存中保存的经验子集 (st, at, rt+1, st+1)n 优化策略。

前面我们介绍了有关强化学习的理论知识,尤其是流行的深度 Q 学习方法,它隐含了多种统计学习流派,例如异步动态编程、移动平均值、ε-Greedy和深度学习。除标准的深度 Q 学习方法外,还有多个 RL 变种,而 Amazon SageMaker RL 开箱即用式的直接提供了其中的大多数变种,因此在了解一种方法后,您就能够使用 Amazon SageMaker RL 对大多数方法进行测试。

在 Amazon SageMaker 中实施自定义 RL 模型

强化学习在金融服务行业的应用已经受到广泛关注,因为更好的金融决策会带来更高的回报。在本文中,我将实现一个金融交易机器人,演示如何开发一个能够通过研究过去期间的资产价格,然后根据实现最大长期利润的目标,决定是否买入、卖出或什么也不做的智能代理。

我将会把这种方法与另一个方法进行基准测试,在另一个方法中,我将会把强化学习与用于时间序列预测的递归深度神经网络组合使用。在第二个方法中,智能代理将使用来自多步界限预测的见解来作出交易决策,并根据事件的预测序列来学习策略,而非使用事件的历史序列。

此数据是雅虎财经网站上公开数据集的一个随机版本,代表了某项任意资产的价格序列。例如,您可以将此数据想象成 EC2 Spot 实例的价格或者公开上市股票的市值。

设置深度 Q 学习的内置预设置文件

Amazon SageMaker RL 中有一个预设置文件,它用于配置 RL 训练作业并定义 RL 算法的超参数。例如,下面的预设置文件实现了上一部分描述的深度 Q 学习智能代理,并设置了参数。它将步数设置为 200 万步。有关 Amazon SageMaker RL 超参数和训练作业配置的更多信息,请参阅通过 Amazon SageMaker RL 使用强化学习

# Preset file in Amazon SageMaker RL

#################
# Graph Scheduling 
#################

schedule_params = ScheduleParameters()
schedule_params.improve_steps = TrainingSteps(2000000)
schedule_params.steps_between_evaluation_periods = EnvironmentSteps(10000)
schedule_params.evaluation_steps = EnvironmentEpisodes(5)
schedule_params.heatup_steps = EnvironmentSteps(0)

############
# DQN Agent 
############

agent_params = DQNAgentParameters()

# DQN params
agent_params.algorithm.num_steps_between_copying_online_weights_to_target = EnvironmentSteps(100)
agent_params.algorithm.discount = 0.99
agent_params.algorithm.num_consecutive_playing_steps = EnvironmentSteps(1)

# NN configuration
agent_params.network_wrappers['main'].learning_rate = 0.00025
agent_params.network_wrappers['main'].replace_mse_with_huber_loss = False

# ER size
agent_params.memory.max_size = (MemoryGranularity.Transitions, 40000)

# E-Greedy schedule
agent_params.exploration.epsilon_schedule = LinearSchedule(1.0, 0.01, 200000)

#############
# Environment 
#############

env_params = GymVectorEnvironment(level='trading_env:TradingEnv')

##################
# Manage resources 
##################

preset_validation_params = PresetValidationParameters()
preset_validation_params.test = True

graph_manager = BasicRLGraphManager(agent_params=agent_params, env_params=env_params,
                                    schedule_params=schedule_params, vis_params=VisualizationParameters(),
                                    preset_validation_params=preset_validation_params)

设置自定义 OpenAI Gym RL 环境

在 Amazon SageMaker RL 中,上一部分描述的 RL 马尔可夫学习过程的大多数要素都已在环境文件中定义。您可以连接使用 OpenAI Gym 开发的开源和自定义环境,OpenAI Gym 是一个流行的接口集,可帮助定义 RL 环境并且与 Amazon SageMaker 完全集成。RL 环境可以是真实世界或是模拟的真实世界,其中 RL 智能代理将与这个世界交互。您可以利用每日历史价格序列来模拟真实世界。要将竞价问题转化为 RL 问题,您需要定义 MDP 的下列要素:

  • 环境 – 将会生成模拟价格的自定义环境,模拟价格具有每日和每周变化并且偶有峰值
  • 状态 – 资产在过去 10 天的每日价格
  • 动作 – 按日的卖出或买入资产,或者什么也不做
  • 目标 – 累计利润最大化
  • 奖励 – 正奖励等于每日利润(如有),买入任何资产支付的价格等于惩罚

一个叫做 TradingEnv.py 的自定义文件会指定所有这些要素。它位于 src/ 文件夹中,被之前定义的预设文件调用。特别是状态空间的大小 (n = 10 days) 和动作空间的大小 (m = 3) 将使用 OpenAI Gym 通过下列代码行来定义:

# Custom environment file in Open AI Gym and Amazon SageMaker RL

class TradingEnv(gym.Env):

    def __init__(self,casset = 'asset_prices', span = 10 ):
        
        self.asset = asset
        self.span = span
                
        # Read input data 
        datafile = DATA_DIR + asset + '.csv'
        self.data = pd.read_csv(datafile) 
        self.observations = self.getObservations(datafile)
        
        # Number of time steps in data file
        self.steps = len(self.observations) - 1
        
        # Output filename
        self.csv_file = CSV_DIR
        
        # Action 
        self.action_space = gym.spaces.Discrete(3)

        # Observation space is defined from the data min and max
        self.observation_space = gym.spaces.Box(low = -np.inf, high = np.inf, shape = (self.span,), dtype = np.float32)

        (…)

如上一部分解释的,goal 将被转换为一个的定量奖励函数,并且此奖励函数也在环境文件中配置。请参见以下代码:

# Definition of reward function
def step(self, action):
        
    # BUY:
    if action == 1: 		
        self.inventory.append(self.observations[self.t])
        margin = 0  
        reward = 0
    # SELL:
    elif action == 2 and len(self.inventory) > 0: 
        bought_price = self.inventory.pop(0)
        margin = self.observations[self.t] - bought_price
        reward = max(margin, 0)            
    # SIT:
    else: 
        margin = 0
        reward = 0

    self.total_profit += margin
            
    # Increment time
    self.t += 1
        
    # Store state for next day
    obs = self.getState(self.observations, self.t, self.span + 1, self.mode)
            
    # Stop episode when reaches last time step in file
    if self.t >= self.steps:
        done = True 
    else:
        done = False

   (…)             
   
    return obs, reward, done, info 

启动 Amazon SageMaker RL 拟合器

在 Amazon SageMaker RL 定义好预设置文件和 RL 环境后,您可以使用与在 Amazon SageMaker 使用任何其他 ML 拟合器类似的方法创建一个拟合器,然后进行智能代理训练。下面的代码演示了如何定义一个会调用预设置文件(它本身会调用自定义环境)的拟合器:

# Definition of the RL estimator in Amazon SageMaker RL

estimator = RLEstimator(source_dir='src',
                        entry_point=entryfile,
                        dependencies=["common/sagemaker_rl"],
                        toolkit=RLToolkit.COACH,
                        toolkit_version='0.11.0',
                        framework=RLFramework.MXNET,
                        role=role,
                        train_instance_count=1,
                        train_instance_type='ml.c5.9xlarge',
                        output_path=s3_output_path,
                        base_job_name=job_name_prefix,
                        hyperparameters = {"RLCOACH_PRESET" : "preset-trading"})

您通常会在 Amazon SageMaker RL 中使用一个 config.py 文件来定义全局变量,例如某个自定义数据文件在 Amazon SageMaker 容器中的位置。请参见以下代码:

# Configuration file (config.py) used to define global variables in Amazon SageMaker RL

import os
CUR_DIR = os.path.dirname(__file__)
DATA_DIR = CUR_DIR + '/datasets/' 
CSV_DIR = '/opt/ml/output/data/simulates.csv'

训练并评估 RL 智能代理的表现

这一部分将演示如何在使用七年的每日历史交易数据构建的模拟环境中训练 RL 竞价智能代理。您可以在训练期间评估学习效果,并在测试模拟中评估训练后的 RL 智能代理的泛化表现,此例中的测试模拟是使用额外三年的每日交易数据构建的。您可以可视化显示在训练和测试阶段每个片段的累计奖励和累计利润,从而评估智能代理的学习和泛化能力。

评估 RL 智能代理训练期间的学习效果

在强化学习中,您可以通过模拟与环境的交互 (st, at, rt+1, st+1) 并计算前面介绍的累计回报 Gt 来训练智能代理。完成初步探索阶段后,由于 ε-Greedy中 ε 的值会逐步减小,以便利用已学习的策略,在给定片段中的总累计奖励代表了所遵循策略的优劣。因此通过比较不同片段之间的总累计奖励,您可以评估已学策略的相对质量。下面两张图展示了 RL 智能代理在训练模拟期间积累的奖励和利润。x 轴为片段指数,y 轴为 RL 智能代理在各个片段积累的奖励或利润。

累计奖励图显示了一个具有三个实质阶段的趋势:前 300 个片段(探索阶段)的波动相对较大,第 300 到第 500 个片段之间稳步增长,最后在第 500 到 800 个片段时达到一个平台,这时总累计奖励达到收敛,并停留在相对稳定的 1800 美元 值附近。

在前 300 个片段期间,累计利润稳定保持在大约零的水平,而在第 500 个片段之后,则停留在相对稳定的 800 美元 附近。

总之,这些结果说明 RL 智能代理已经学会了如何以有利润的方式买卖资产,并且朝具有可复现策略的稳定行为收敛,从而在训练数据集上创造利润。

评估 RL 智能代理对测试数据集的泛化效果

为了评估智能代理在环境里对新交互的泛化能力,您可以将 ε 的值设为零以将智能代理约束为利用已学习的策略,并模拟与环境的新交互 (st, at, rt+1, st+1)。

下图显示了 RL 智能代理在测试模拟期间生成的利润。x 轴为片段索引,y 轴为 RL 智能代理在每个片段积累的利润。

图中显示在使用相同资产的三年新每日价格后,训练过的智能代理在 65 个测试片段创造的利润均值趋向于 2200 美元,标准差为 600 美元。与训练模拟形成对比,您可以看到在模拟的所有 65 个测试片段中,均值十分稳定,说明所学策略的收敛性极强。

通过上图可以确认 RL 智能代理拥有收敛的、学习到可复现的策略,可以以有利润的方式买卖资产,能够泛化到新的价格和趋势。

深度递归 RL 智能代理的基准测试

最后,我将之前深度 RL 方法的结果与深入递归 RL 方法的结果进行了基准测试。由于时间序列预测 RNN 并非将状态定义为过去 10 天的时间段,而是将状态作为一个 10 天期间的预测来编码,智能代理在学习最优交易策略时,从顾问获得的未来预期价格中获益,从而能够最大化长期回报。

实现基于预测的 RL 状态空间

下面的代码按照使用动态深度学习在 AWS 上预测金融时间序列一文中的例子,实现了一个简单的时间序列预测 RNN:

# Custom function to define a RNN for time series forecasting

def trainRNN(self, data, lag, horiz, nfeatures):

        # Set hyperparameters
        nunits = 64                          # Number of GRUs in recurrent layer
        nepochs = 1000                       # Number of epochs
        d = 0.2                              # Percent of neurons to drop at each epoch
        optimizer = 'adam'                   # Optimization algorithm
        activ = 'elu'                        # Activation function of neurons
        activr = 'hard_sigmoid'.             # Activation function of recurrent layer
        activd = 'linear'                    # Dense layer's activation function
        lossmetric = 'mean_absolute_error'   # Loss function for gradient descent
        verbose = False                      # Print results on standard output channel

        # Prepare data
        df = data
        df["Adjclose"] = df.Close 
        df.drop(['Date','Close','Adj Close'], 1, inplace=True)
        df = df.diff() 

        data = df.as_matrix()
        lags = []
        horizons = []
        nsample = len(data) - lag - horiz  
        for i in range(nsample):
                lags.append(data[i: i + lag , -nfeatures:])
                horizons.append(data[i + lag : i + lag + horiz, -1])
        lags = np.array(lags)
        horizons = np.array(horizons)
        lags = np.reshape(lags, (lags.shape[0], lags.shape[1], nfeatures))

        # Design RNN architecture
        rnn_in = Input(shape = (lag, nfeatures), dtype = 'float32', name = 'rnn_in')
        rnn_gru = GRU(units = nunits, return_sequences = False, activation = activ, recurrent_activation = activr, dropout = d)(rnn_in)
        rnn_out = Dense(horiz, activation = activd, name = 'rnn_out')(rnn_gru)
        model = Model(inputs = [rnn_in], outputs = [rnn_out])
        model.compile(optimizer = optimizer, loss = lossmetric)

        # Train model
        fcst = model.fit({'rnn_in': lags},{'rnn_out': horizons}, epochs=nepochs,verbose=verbose)

下面的函数会将智能代理重定向至某个基于历史期或预测期间的观察(本文中讨论的两种 RL 方法),具体取决于名为mode的自定义全局变量的值:

# Custom function to define a state at time t

def getState(self, observations, t, lag, mode):

# Mode "past": State at time t defined as n-day lag in the past
if mode == 'past':
     d = t - lag + 1
     block = observations[d:t + 1] if d >= 0 else -d * [observations[0]] + observations[0:t + 1] # pad with t0
     res = []
     for i in range(lag - 1):
             res.append(self.sigmoid(block[i + 1] - block[i]))
     return np.array([res])

# Mode "future": State at time t defined as the predicted n-day horizon in the future using RNN
elif mode == 'future':
     rnn = load_model(self.rnn_model)
     d = t - lag + 1
     block = observations[d:t + 1] if d >= 0 else -d * [observations[0]] + observations[0:t + 1] # pad with t0
     horiz = rnn.predict(block)
     res = []
     for i in range(lag - 1): 
             res.append(self.sigmoid(horiz[i + 1] - horiz[i]))
  

评估基于 RNN 的 RL 智能代理训练期间的学习能力

与上一部分一样,将RL 智能代理使用的状态定义为过去 10 个观察值的历史(参见基于历史期的 RL),您可以通过比较片段之间的总累计奖励来评估基于 RNN 的智能代理所学策略的相对质量。

下图演示了基于 RNN 的 RL 智能代理在训练模拟期间累计的奖励和利润。x 轴为片段索引,y 轴为 RL 智能代理在各个片段积累的奖励或利润。

累计奖励图显示在第 300 个片段后出现稳定增长,而第 500 个片段后的大多数片段都导致约 1000 美元 左右的累计奖励。但有多个片段导致相对很高的奖励,最高 8000 美元。

前 300 个片段的累计利润大约为零,在第 500 个片段之后保持在某个稳定值附近,并且也有多个片段的利润最高达到 7500 美元。

总之,这些结果说明 RL 智能代理已经学会了如何以有利润的方式买卖资产,并且收敛至某个行为,该行为具备的策略能够在训练数据集上创造 500–800 美元 的利润,或者相对很高的,最高可达 7500 美元 的利润。

评估基于 RNN 的 RL智能代理在测试数据集的泛化表现

下图演示了基于 RNN 的 RL 智能代理在测试模拟期间生成的利润。x 轴为片段索引,y 轴为 RL 智能代理在每个片段累计的利润。

图中显示基于 RNN 的 RL 智能代理可以泛化出新的价格和趋势。与训练期间观察到的情况一样,这说明在使用相同资产的三年新每日价格训练后,智能代理往往会生成大约 2000 美元 的利润,有时会高达 7500 美元。在65 个测试片段中,这种双重行为的特征表现为的总体均值 4900 美元,标准差 3000 美元。

所有 65 个模拟测试片段的最小利润为 1300 美元,而使用基于历史期的 RL 方法时为 1500 美元。最大利润为 7500 美元,累计利润经常超过 5000 美元,而基于历史期的 RL 方法仅为 2800 美元。因此,与基于历史期的 RL 方法相比,基于 RNN 的 RL 方法会导致更大的波动,但却会产生更高的利润,由于这个 RL 问题的目标是创造利润,因此这一 结果更好。

基于历史期间的 RL 智能代理与基于 RNN 的 RL 智能代理的结果证实,基于 RNN 的 RL 智能代理的收益更好。它已经学会了可复现的策略,可以按照与基于历史期的智能代理所学策略类似或明显更好的方式买卖资产,从而创造利润。

小结

在本文中,我介绍了深度强化学习背后的动机和相关理论概念,它是一个可让您学习并根据既定长期目标执行最优策略的ML 解决方案框架。您了解了如何使用 Amazon SageMaker RL 来开发和训练自定义的深度强化学习智能代理,从而在任意竞价环境中实时作出智能决策。

您还了解到如何评估深度强化学习智能代理在训练和测试模拟中的表现,并且了解到如何把它与更高级的、基于时序预测 RNN 的深度递归强化学习的智能代理做基准测试。

本文仅供教育学习之用。过往的交易表现不保证未来的表现。交易损失可能会十分巨大;投资者使用各种交易策略均应自行承担风险。

有关常用 RL 算法的更多信息,请参阅通过 Amazon SageMaker RL 使用强化学习。请访问 Amazon SageMaker 示例 GitHub 代码库,获取解决类似问题的 SageMaker 笔记本示例。


关于作者

Jeremy David Curuksu 是 AWS 的一名数据科学家,也是 Amazon Machine Learning 解决方案实验室的金融服务业务全球负责人。他拥有应用数学理学硕士和博士学位,是瑞士联邦理工学院洛桑分校 (EPFL) 和美国麻省理工学院 (MIT) 的研究员。他撰写了多篇科学同行审核文章,以及《Data Driven》一书,该书介绍了数据科学新时代的管理咨询。