Action-Gap RL:基于动作间隙的强化学习实验代码库运行与原理指南
2026/9/19 20:12:59 网站建设 项目流程

Action-Gap RL:基于动作间隙的强化学习实验代码库运行与原理指南

【免费下载链接】google-researchGoogle Research项目地址: https://gitcode.com/gh_mirrors/go/google-research

本指南围绕 google-research 仓库中的action_gap_rl子项目展开,介绍其在 Pendulum 环境上"收集数据 → 训练价值函数 → 评估策略"的完整研究实验流程,以及指数族策略(Exponential Family Policy)、L-Norm 策略、Soft-Hot 特征嵌入等核心实现原理。读完本文,你将掌握该代码库的环境搭建、数据采集、离线训练与评估的具体操作方法,并理解各源码模块之间的调用关系,可直接复现作者在连续动作强化学习上的实验管线。

项目定位与实验思想

action_gap_rl(Action-Gap RL)是 google-research 仓库中的一个独立研究子项目,由danabo@google.comschuurmans@google.com合作维护,核心聚焦于强化学习中"动作间隙"(action gap)相关的学习问题。从代码库结构来看,它围绕 OpenAI Gym 的Pendulum-v0(连续控制摆)环境搭建了一条完整的实验链路:

  • 离线数据收集:用均匀随机行为策略(uniform behavior policy)与环境交互,把经验存入 replay buffer 并序列化为 pickle 文件;
  • 价值回归训练:通过 Monte Carlo(MC)回报构造回归目标,使用 TensorFlow Keras 模型拟合状态-动作价值函数;
  • 策略评估:加载训练好的 checkpoint,在环境中采样 episode,记录 return 与 episode length 等指标。

该代码库(action_gap_rl/)以 Python 为主,依赖 TensorFlow 2.x 与 Gym,运行入口包括命令行脚本与 Jupyter Notebook 两类,下文将逐层展开。

环境搭建

仓库根目录下的 action_gap_rl/README.md 给出了官方的环境安装步骤,核心是先创建独立的 Python 虚拟环境,再安装依赖。以下命令需在仓库根目录(即google-research/)执行。

1. 创建 Python 虚拟环境

sudo apt-get install python3-pip python3 -m pip install --user virtualenv python3 -m virtualenv ~/env source ~/env/bin/activate

前三步分别安装 pip、安装virtualenv工具并创建名为env的虚拟环境(位于用户主目录下),最后一步激活该环境,后续所有依赖安装与实验命令都应在激活后的 shell 中执行。

提示:也可以参考 action_gap_rl/run.sh 中的写法,直接在仓库内创建虚拟环境并一键启动演示:

virtualenv -p python3 . source ./bin/activate pip install -r action_gap_rl/requirements.txt python -m action_gap_rl.demo --logtostderr

2. 安装依赖

激活虚拟环境后,安装项目声明的全部依赖:

pip3 install -r requirements.txt

其中requirements.txt位于仓库根目录,而子项目自身的依赖清单为 action_gap_rl/requirements.txt,内容如下:

absl-py>=0.5.0 numpy>=1.13.3 tensorflow==2.1.0 gym>=0.12.1 pyyaml>=3.12.0

各依赖在项目中的作用:

依赖版本约束在项目中的用途
absl-py>=0.5.0提供absl.app/absl.flags/absl.logging,所有命令行脚本的参数解析与日志输出均基于它
numpy>=1.13.3经验回放数组的存储与序列化、MC 回报的向量化计算
tensorflow==2.1.0(固定版本)构建价值网络(Keras Model)、checkpoint 保存与恢复、Summary 指标记录
gym>=0.12.1提供Pendulum-v0连续控制环境
pyyaml>=3.12.0评估阶段解析实验目录下的config.yaml配置文件

需要特别说明的是:项目代码统一使用tensorflow.compat.v2 as tf导入方式(见 demo.py、evaluate.py),并在入口处调用tf.enable_v2_behavior(),因此运行时要求 TensorFlow 2.x 环境;requirements.txt将版本锁定为2.1.0,如需在其他 TensorFlow 2.x 版本上运行,请自行验证兼容性。

项目文件结构与运行入口

从仓库文件列表可以看到,action_gap_rl目录由三部分组成:

action_gap_rl/ ├── notebooks/ # Colab 式 Notebook:数据收集、训练、模式回归演示 │ ├── pendulum_collect_data.ipynb │ ├── pendulum_train.ipynb │ ├── mode_regression.ipynb │ └── mode_regression_nn.ipynb ├── policies/ # 策略(价值函数)实现 │ ├── exponential_family.py │ ├── l_norm.py │ └── layers_lib.py ├── README.md ├── __init__.py ├── collect_data.py # 命令行:随机策略收集数据并保存 pickle ├── demo.py # 命令行:随机策略采样一条 episode 并打印 ├── evaluate.py # 命令行:加载 checkpoint 评估策略 ├── replay.py # 经验回放缓冲区(Memory) ├── requirements.txt ├── run.sh # 一键:建环境 → 装依赖 → 跑 demo ├── util.py # AttrDict 工具 └── value.py # Monte Carlo 回报计算

整体调用关系可以概括为:collect_data.py / Notebook 负责产生离线数据集 → replay.py 存储经验 → value.py 将奖励序列折叠为 MC 回报 → policies/中的 Keras 模型拟合回报 → evaluate.py 加载模型权重做在线评估*。

快速演示:demo.py

demo.py 是理解环境交互流程的最小示例。它创建Pendulum-v0环境,用UniformContinuousAgent(直接调用action_space.sample()均匀采样动作)运行一个最多 1000 步的 episode,并将每一步的TimeStep(t, a, s, r)元组记录下来后打印:

env = gym.make('Pendulum-v0') agent = UniformContinuousAgent(env.action_space) rollout = sample_episode(env, agent, max_episode_length=1000)

值得注意的细节是,sample_episode中对奖励做了裁剪:reward = max(min(reward, 1), -1),即将单步奖励限制在[-1, 1]区间,这有助于稳定后续的价值回归训练。运行方式为:

python -m action_gap_rl.demo --logtostderr

一键脚本:run.sh

action_gap_rl/run.sh 把"建环境、装依赖、跑演示"串成一条命令(脚本开头已用set -e保证任一步失败即终止):

virtualenv -p python3 . source ./bin/activate pip install -r action_gap_rl/requirements.txt python -m action_gap_rl.demo --logtostderr

离线数据收集:collect_data.py 与 replay.py

实验的第一阶段是用行为策略采集数据。命令行入口 collect_data.py 的实现非常简洁:

  1. 创建Pendulum-v0环境;
  2. 以均匀随机策略lambda obs: env.action_space.sample()作为行为策略(代码中注释掉的null_policy则始终输出零动作,可作为一种对比行为策略);
  3. 采集100 个 episode、每个 200 步
  4. 将经验写入replay.Memory,序列化后保存为pendulum.pickle
  5. 反序列化做一次一致性检查(sanity check),对比entered_statesexited_statesattempted_actionsobserved_rewards四个视图是否一致。

运行方式:

python -m action_gap_rl.collect_data --outdir=/tmp/action_gap_rl/datasets/v2

其中outdir是唯一的必填 flag(flags.DEFINE_string('outdir', None, ...)),数据最终写入<outdir>/pendulum.pickle

底层的经验容器是 replay.py 中的Memory类,它按 episode 组织数据:

  • log_init(obs):开始记录一个新 episode(初始化状态列表、动作列表、奖励列表);
  • log_experience(obs, act, reward, next_obs, data):追加一步经验,并断言当前 obs 与上一记录的 next_obs 一致(assert (self.observations[-1][-1] == obs).all()),从实现细节上防止数据错位;
  • entered_states()/exited_states():分别返回进入/离开的状态(后者去掉每段轨迹的最后一个状态);
  • attempted_actions()/observed_rewards():展平返回所有动作与奖励;
  • serialize()/unserialize():基于pickle.dumps将观测、动作、奖励及扩展数据data一起序列化/反序列化。

Memory还支持通过data_keys构造器参数携带额外的扩展数据字段,为后续研究(如记录行为策略的额外统计量)留出了接口。

将轨迹折算为回报:value.py

离线训练需要"状态-动作 → 目标价值"的监督信号。value.py 中的max_q_iteration(memory, gamma)提供了最朴素的Monte Carlo 回报计算:从每个 episode 的倒数第二步开始,按q_values[i][j] += gamma * q_values[i][j+1]从后向前累积折扣奖励,最终把所有 episode 的回报拼成一个一维数组返回。这里的gamma即折扣因子,在 Notebook 中通常取1.0(无折扣)。

训练与评估:Notebook 与 evaluate.py

训练:notebooks/pendulum_train.ipynb

训练流程主要在 notebooks/pendulum_train.ipynb 中演示,其关键步骤包括:

  1. 加载DATASET_FILES指定的训练/评估 pickle 数据集(如/tmp/action_gap_rl/datasets/v2/pendulum_train.picklependulum_eval.pickle),并通过down_sample构造不同时间分辨率(1IR10IR)的多个数据集视图,以研究"信息分辨率"对学习的影响;
  2. load_datasets(dataset_files, horizon, gamma, irresolution, scale)将原始轨迹切成片段、折算回报并按比例缩放(如scale=1/16);
  3. 定义 Keras 价值模型(如CategoricalPolicy、或复用policies/中的策略类),以l2_loss/l1_loss为损失函数,用sample_batch随机采样 mini-batch 进行离线回归;
  4. 支持通过device_string''表示 CPU、'/device:GPU:0'表示 GPU、'/device:TPU:0'表示 TPU)切换训练设备,并设置BATCH_SIZE = 1000ITERATIONS = 200(注释中给出过 1000 的设置);
  5. 训练结束后对每个策略切换到对应_eval数据集,打印 L1/L2 损失,并对预测残差做 sanity check。

配套的 notebooks/pendulum_collect_data.ipynb 则完成了与collect_data.py等价的采集工作,并将数据导出到/tmp/action_gap_rl/datasets/,供训练 Notebook 直接消费。另外两个 Notebook(mode_regression.ipynbmode_regression_nn.ipynb)聚焦于"模式回归"(即学习价值函数的 argmax 模式),用于验证价值面形状与策略模式的关系。

评估:evaluate.py

evaluate.py 提供命令行评估入口,用法为:

python -m action_gap_rl.evaluate \ --experiment_path=/path/to/experiment \ --num_episodes=100

它按以下逻辑工作:

  1. 加载配置:在experiment_path目录中找到最新的config.yaml(通过most_recent_file(..., r'config.yaml')按修改时间选取),用yaml.load读取并用 util.py 中的AttrDict转成属性访问式字典(config.envconfig.policy等);
  2. 构建策略:从全局符号表中按config.policy字符串动态取出策略类(如ExponentialFamilyPolicyLNormPolicy),传入config实例化,并通过一次policy.argmax(...)前向调用完成变量初始化;
  3. 恢复 checkpoint:查找model.ckpt-[0-9]+模式的最新 checkpoint,用tf.train.Checkpoint(policy=policy)恢复权重(assert_consumed()确保权重全部对齐),找不到则抛RuntimeError
  4. 在线采样:每个 episode 调用sample_episodepolicy.argmax决策,最大 200 步),用tf.summary.create_file_writer把每轮的return(奖励和)与length(episode 长度)写入 TensorBoard summary。

其中sample_episode(env, policy, memory, max_episode_length=200)使用策略的argmax输出作为确定性动作,与训练阶段的随机/回归行为形成对照。

策略(价值函数)实现:两类核心模型

训练的本质是让模型输出逼近"状态-动作价值"(或等价的目标),policies/目录提供了两种可配置的 Keras 模型,它们都实现了统一的接口:call(states, actions)输出预测值、loss(states, actions, targets)定义回归损失、argmax(states)返回最优动作(模式)。

指数族策略:exponential_family.py

exponential_family.py 的核心思想是:用一个神经网络输出分布参数,把"非归一化 log-pdf"作为价值预测器。文件顶部定义了Distribution = namedtuple('Distribution', 'params, log_pdf, mode'),并通过全局DISTS字典把"分布名字符串"映射到具体的 log-pdf 与 mode 函数,这样配置文件里只需保存字符串名即可。

当前内置的分布是quadratic(二次型):

'quadratic': Distribution( params=[1, 0, 0], # p0 非负,p1、p2 覆盖整个实数域 log_pdf=lambda a, p0, p1, p2: -a**2*p0 + a*p1 + p2, # 非归一化 log-pdf mode=lambda p0, p1, _: p1/p0), # 解析 argmax:p1/p0 )

params是一个二进制列表:1表示该分布参数必须非负(网络输出端套softplus),0表示参数可覆盖整个实数域。ExponentialFamilyPolicy的网络结构为:

[可选 soft_hot 嵌入层] + [若干 Dense(relu)] + Dense(len(params)) + 按 params 做 softplus/恒等 的 Lambda

loss为 L2 损失tf.reduce_mean(tf.square(pred - targets))argmax直接调用分布定义中的mode函数,对quadratic而言即解析解p1/p0。文件注释还给出了扩展新分布的模板(在DISTS中新增条目、保证参数个数一致即可),方便研究者自定义分布族。

L-Norm 策略:l_norm.py

l_norm.py 提供另一种价值参数化:LNormPolicy的网络输出单个标量(Dense(1)),预测值定义为self._body(states) - actions,损失函数为:

loss = tf.reduce_mean(tf.abs(-tf.abs(self(states, actions))**self.p - targets)**self.q)

其中pq均来自配置(config.pconfig.q),用于控制损失的范数形态;argmax(states)即网络输出本身self._body(states)。这类策略的价值面以L_p范数刻画动作依赖,是研究动作间隙结构的一种直观建模方式。

共享特征嵌入:layers_lib.py 中的 Soft-Hot 层

两个策略类都支持config.embed指定的输入变换层,实现位于 layers_lib.py:

  • soft_hot_layer(offsets, scales):为每个标量观测生成一组高斯核(soft-hot)嵌入,输出维度为input_dim * soft_hot_dim。其实现是用tf.exp(-(x - offsets)**2 / scales)构造径向基式特征,再用tf.reshape展平;
  • obs_embedding_kwargs(...):自动从一批数据(batch)或手工指定的bounds/variance生成offsetsscales。其中stretch(low, high, fraction)会把特征取值区间向外扩张(默认spillover=0.05),容纳少量越界值;offsetsnp.linspace在拉伸后的区间内均匀布点生成,scales取各特征方差,从而控制核宽度。

在 Notebook 的训练流程中同样可以见到该嵌入层的应用(通过layers_lib构造特征变换),它与策略网络共同构成"观测嵌入 → 价值回归"的前馈通路。

复现实验的完整路径

综合以上模块,在本地复现action_gap_rl实验的推荐路径是:

  1. 环境准备:按 README 创建 virtualenv 并安装 action_gap_rl/requirements.txt 中的依赖(注意 TensorFlow 锁定 2.1.0);
  2. 数据采集:运行python -m action_gap_rl.collect_data --outdir=<你的目录>(或在 pendulum_collect_data.ipynb 中采集),得到pendulum.pickle训练数据与评估数据;
  3. 离线训练:在 pendulum_train.ipynb 中指定DATASET_FILES指向第 2 步产物,选择策略(ExponentialFamilyPolicy/LNormPolicy)与设备,训练并保存 checkpoint 到实验目录;
  4. 在线评估:在实验目录放置config.yaml(包含envpolicyhidden_widthsembeddist_namep/q等字段),运行python -m action_gap_rl.evaluate --experiment_path=<实验目录> --num_episodes=<N>,用 TensorBoard 查看returnlength曲线。

需要提醒的是,Pendulum-v0是 Gym 早期版本的环境 ID,在较新的 Gymnasium 生态中已被Pendulum-v1取代,运行前请确认你的 Gym 版本与gym.make('Pendulum-v0')的兼容性(collect_data.py、evaluate.py 均硬编码了该环境名)。此外,requirements.txt锁定的 TensorFlow 版本较早,建议在隔离的虚拟环境或容器中运行,避免影响其他项目。

通过阅读 replay.py、value.py、policies/ 三处核心源码,再配合 README 的安装步骤,你即可完整掌握该研究代码库从环境交互、离线数据集构造到价值回归与策略评估的全链路,并在此基础上扩展自己的动作间隙相关实验。

【免费下载链接】google-researchGoogle Research项目地址: https://gitcode.com/gh_mirrors/go/google-research

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询