本文来源自知乎博客,作者:旺仔搬砖记
排版:OpenDeepRL
由于内容过长,本文仅展示部分内容,完整系列博客请文末阅读原文
离线强化学习(Offline RL)作为深度强化学习的子领域,其不需要与模拟环境进行交互就可以直接从数据中学习一套策略来完成相关任务,被认为是强化学习落地的重要技术之一。本文详细的阐述了强化学习到离线强化学习的发展过程,并就一些经典的问题进行了解释和说明。
强化学习发展的特别早,但一直不温不火,其中Sutton老爷子早在1998年就写了强化学习领域的圣经书籍:An Introduction : Reinforcement Learning ,但也并未开启强化学习发展的新局面。直到2012年,深度学习广泛兴起,大规模的神经网络被成功用于解决自然语言处理,计算机视觉等领域,人工智能的各个方向才开始快速发展,强化学习领域最典型的就是2013年DeepMind公司的Volodymyr Mnih发表Playing Atari with Deep Reinforcement Learning(DQN技术),可以说开启了深度强化学习技术发展的新高潮,2015年该论文的加强版Human-level control through deep reinforcement learning 登上Nature, 以及2016年Nature上的AlphaGo: Mastering the game of Go with deep neural networks and tree search 充分证明了深度强化学习技术的发展潜力。
传统的强化学习和监督学习、非监督学的区别在于,后两者是通过从已标记(Label)和无标记的数据中学习一套规律(我们可以理解为学习一个函数表达式),而前者强化学习则是通过行为交互来学习一套策略,以最大化累计期望奖励,结构如图所示:
其学习过程可以归纳为通过agent获取环境状态 , 根据自身学习到的知识做出action反馈给环境,并得到一个奖励,不断地迭代出一个可以一直玩游戏并且不会死的智能体。原理就是从一个四元组$<s, a,="" r,="" s^{'}="">$中学习出策略,不论出发点在哪里都可以得到一个最优的轨迹(trajectory)模型(不论起点,目前测试中一般通过多个随机seed去测试),具体可以参考博主的另外篇博文深度强化学习简介.
On-policy和Off-policy这两个词在强化学习领域非常重要,知乎上有很多关于其讨论强化学习中on-policy 与off-policy有什么区别?,最典型的莫过于李宏毅老师下棋形象例子解释,还可以从以下方式解释:
【补充】两者在学习方式上的区别:若agent与环境互动,则为On-policy(此时因为agent亲身参与,所以互动时的policy和目标的policy一致);若agent看别的agent与环境互动,自己不参与互动,则为Off-policy(此时因为互动的和目标优化的是两个agent,所以他们的policy不一致)。两者在采样数据利用上的区别:On-policy:采样所用的policy和目标policy一致,采样后进行学习,学习后目标policy更新,此时需要把采样的policy同步更新以保持和目标policy一致,这也就导致了需要重新采样。Off-policy:采样的policy和目标的policy不一样,所以你目标的policy随便更新,采样后的数据可以用很多次也可以参考。
其实最经典的莫过于Sutton老爷子Introduction中的解释:
原文:On-policy methods attempt to evaluate or improve the policy that is used to make decisions, whereas off-policy methods evaluate or improve a policy different from that used to generate the data.
此外莫过于Q-learning和sarsa算法的解释
最终总结一下两者的优缺点:
on-policy优点是直接了当,速度快,劣势是不一定找到最优策略。off-policy劣势是曲折,收敛慢,但优势是更为强大和通用。
本文之所以解释On-policy或者off-policy的相关内容,目的在于后文讨论以下几个问题:
监督学习中通常利用已知(已标记)的数据进行学习,其本质是从数据中总结规律,这和人从学1+1=2基本原理一致,强化学习的过程也是如此,仍然是从数据中学习,只不过强化学习中学习的数据是一系列的轨迹
所以重点来了,这里的数据才是最关键的一部分,这也强化学习中Online和offline学习中的关键, Online一方面是与环境有交互,通过采集数据学习、然后丢弃,而offline则是不用交互,直接通过采集到的轨迹数据学习,这也是off-policy到offline转换的重要原因。
目前atari, mujoco物理引擎等各类游戏中的模拟数据很轻松拿到,这也就是目前强化学习在游戏领域非常成功的原因之一,也是各种state of the art刷榜的体现,因为游戏数据可以很轻松就100million,总结起来就是
有模拟器,易产生数据,好用!
但强化学习在落地过程中就可能遇到很多问题,比如下图这个大家伙,
总不可能让他产生100 million数据吧(不知道他的额定寿命是多少次),因此产生如下几个问题:
所以有这样的方法吗?
答案: 有,OfflineRL,此处有矿,赶紧来挖!
离线强化学习最初英文名为:Batch Reinforcement Learning [3], 后来Sergey Levine等人在其2020年的综述中使用了Offline Reinforcement Learning(Offline RL), 现在普遍使用后者表示。下图是离线强化学习近年来论文的发表情况,间接反应发展状态
Offline RL 可以被定义为 data-driven 形式的强化学习问题,即在智能体(policy函数?)不和环境交互的情况下,来从获取的轨迹中学习经验知识,达到使目标最大化,其和Online的区别如图所示:
图片来源自:Offline Reinforcement Learning
后来Sergey在论文中归纳如下图所示:
本质上,智能体是通过静态的数据集 $<s_{t}^{i},a_{t}^{i},s_{t+1}^{i},r_{t}^{i}>
\pi(a|s)
\pi_{\beta}
D
s,a \in D
s \sim d^{\pi_{\beta}}(s)
a\sim \pi_{\beta}(a|s)
J(\pi)$</s_{t}^{i},a_{t}^{i},s_{t+1}^{i},r_{t}^{i}>
图中很明确的从数据可否store以及reused解释了是纯Online还是offline, 以及使用经验回放的NFQ等,其本质还是是否利用trajectory去学习优化模型。
备注:离线强化学习去学习数据可以使专家数据、预训练(Pre-Train)模型产生的数据、随机(random)数据等。
模仿学习(Imitation Learning, IL) 是指通过从专家(通常指人类的决策数据
)提供的范例中学习,,每个决策包含状态和动作序列 $\tau_{i}=
可能有人会问,模仿学习不也是从专家数据中学习一套策略吗?它和offline RL不就是一回事了?其实它们与息息相关,但有几个关键的区别:
另外一方面在数据组成方面有如下区别:
强化学习在与环境中交互学习的过程中,最关键的一个问题便是“Exploration vs Exploitation Dilemma”, Exploration是为了收集更多信息(尝试一些不可能等),而Exploitation则根据当前信息做出最佳决策,正如Sliver总结的:
这两者可以说对一个算法的训练精度、速度等各方面有重要影响,而Offline RL算法中需要完全的依赖于静态数据集
,但是没有办法提高exploration,因为不和环境进行交互,就无法知道探索得到的数据是否有效,是否有高质量的奖励反馈等,所以 Offline RL不可能通过探索发现高奖励的区域。而且,并没有办法解决此问题,这就变成了2.3.2中的经验最小化的问题了
深度学习的成功可以归结为数据集(ImageNet等)的准确强大,offline RL也不例外,思考以下问题:
这个问题其实Fujimoto在2019年的时候就提到了(如图所示),但直到现在仍然对Offline RL算法的训练非常大的影响。
备注:Final buffer: train a DDPG agent for 1 million time steps, adding N (0, 0.5) Gaussian noise to actions for high exploration, and store all experienced transitions.Concurrent:train the off-policy and behavioral DDPG agents, for 1 million time steps. To ensure sufficient exploration, a standard N (0, 0.1) Gaussian noise is added to actions taken by the behavioral policy.
分布偏移(Distribution shift) 在监督学习中一般指的是训练分布与测试分布不同,在离线强化学习中指的是训练策略与行为策略不一致。(Distribution shifts, in which the training distribution differs from the testing distribution, training policy are inconsist:ent with behavioral policy in offline reinforcement learning.),下面我们进行解释
在监督学习中,训练一个模型通常追求经验风险最小化(Empirical Risk Minimization,ERM),即:
也就是让图中的左子图的平均损失函数最小化,那么这里就存在一个问题,给定一个最优的 , 那么 也是最优的吗?(注意这里: )
那么问题就变成了:如何在不同的 下能够同样能够达到
同样的情况,在Offline RL中obejctive函数则变成了:
其中的 是我们从offline data中学习的策略, 而我们希望 , 这样就可以达到学习目的了。
总结起来就是:别走偏了,每一步都尽量让两个分布之间距离最小化的问题,不然累计起来不知道走哪里(有点TRPO的感觉)
对2.3.3.1中的定义 , 我们换种表达方式为 ,考虑时间步为 的情况下,在离线强化学习中误差上界和时间步之间是平方关系,直觉上造成这样的原因是因为,学习策略 可能会进入和训练分布差距很远的状态,这将导致 和 差距非常大。那么,当策略在 时刻遇到了分布之外(数据集中没见过)的状态时,策略在之后的 个时刻就有可能不断的犯错,所以累计误差 ,而且每一个时间步,都有可能进入分布外的状态,造成整体误差为 , 这对于算法的收敛来说无异于雪上加霜,关于解决这个问题的BCQ、CQL等算法将来后续博客讲解!(by Sergey)
下面是一些2012年前的offline reinforcement learning算法,最新的算法将在后面博客中详解。
至此,关于offline RL的简介到这里,下一篇是关于offline RL 中常用(最典型)的数据集D4RL的安装过程以及其中遇到的一些坑,以及如何设计一个高效的Offline RL算法
关于D4RL Benchmarks数据集[Github], [Paper]
(1) D4RL 收集了大型数据集,包括交互式环境中智能体的记录(即自动驾驶Carla、AntMaze、Mujoco等),且有简单和复杂分类,种类非常丰富,例如:
(2) D4RL提供了非常简单的API接口,方便于学习者直接去获取数据集完成智能体的训练。
import d4rl # Import required to register environments
env = gym.make('maze2d-umaze-v1')
dataset = env.get_dataset()
(3) D4RL定义了标准的衡量指标
(4) D4RL提供了丰富的baseline基准,包括了常见的Offline算法,包括BCQ、BEAR、BRAC等等
D4RL数据集目前来说是离线强化学习涵盖数据集非常丰富的一个数据集,数据质量非常高。其中最主要的是数据的采集综合了6类因素
D4RL 的安装相对来说比较容易,但其中也有很多的坑
git clone https://github.com/rail-berkeley/d4rl.git
cd d4rl
pip install -e .
另外一种简单的安装方法
pip install git+https://github.com/rail-berkeley/d4rl@master#egg=d4rl
其中会有很多坑,导致安装失败。
下面我们根据初始化安装文件setup.py分析安装
from distutils.core import setup
from platform import platform
from setuptools import find_packages
setup(
name='d4rl',
version='1.1',
install_requires=['gym',
'numpy',
'mujoco_py',
'pybullet',
'h5py',
'termcolor', # adept_envs dependency
'click', # adept_envs dependency
'dm_control' if 'macOS' in platform() else
'dm_control @ git+git://github.com/deepmind/dm_control@master#egg=dm_control',
'mjrl @ git+git://github.com/aravindr93/mjrl@master#egg=mjrl'],
packages=find_packages(),
package_data={'d4rl': ['locomotion/assets/*',
'hand_manipulation_suite/assets/*',
'hand_manipulation_suite/Adroit/*',
'hand_manipulation_suite/Adroit/gallery/*',
'hand_manipulation_suite/Adroit/resources/*',
'hand_manipulation_suite/Adroit/resources/meshes/*',
'hand_manipulation_suite/Adroit/resources/textures/*',
]},
include_package_data=True,
)
上述过程安装后我们会发现遇到很多问题,下面我就自己的安装过程以及遇到的问题一一列举
安装环境:Ubuntu18.04, anaconda3
# 下载地址 https://github.com/deepmind/mujoco/releases/tag/2.1.0
cd ~/Downloads/
wget https://github.com/deepmind/mujoco/releases/download/2.1.0/mujoco210-linux-x86_64.tar.gz
mv mujoco210-linux-x86_64.tar.gz mujoco210
tar -zxvf mujoco210-linux-x86_64.tar.gz
mkdir ~/mujoco
cp -r mujoco210 ~/mujoco
# 添加环境变量
sudo gedit ~/.bashrc
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.mujoco/mujoco210/bin
export MUJOCO_KEY_PATH=~/.mujoco${MUJOCO_KEY_PATH}
source ~/.bashrc
# 测试
cd ~/.mujoco/mujoco210/bin/
./simulate ../model/humanoid.xml
坑1:can't find /.mujoco/lib/libmujoco.so.2.1.1(可能安装mujoco200的伙伴会遇到)
解决办法:
(1)下载mujoco211安装包,解压
(2)在mujoco210/lib下找到libmujoco.so.2.1.1,并复制在~/.mujoco/bin在~/.bashrc下
(3)添加环境变量并source
export MJLIB_PATH=~/.mujoco/lib/libmujoco.so.2.1.1
source ~/.bashrc
# 本步跳过conda环境创建,直接进入虚拟环境(conda create -n d4rl python=3.7)
conda create -n d4rl python=3.7
conda activate d4rl
pip install mujoco_py
python
Python 3.7.11 (default, Jul 27 2021, 14:32:16)
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mujoco_py
>>>
# 备:没有报错表示安装成功
坑2:如果是fatal error: GL/osmesa.h: No such file or directory,那就安装libosmesa6-dev
Python 3.7.11 (default, Jul 27 2021, 14:32:16)
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mujoco_py
running build_ext
building 'mujoco_py.cymj' extension
gcc -pthread -B /home/jqw/anaconda3/envs/d4rl/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py -I/home/jqw/.mujoco/mujoco210/include -I/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/numpy/core/include -I/home/jqw/anaconda3/envs/d4rl/include/python3.7m -c /home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/cymj.c -o /home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/generated/_pyxbld_2.1.2.14_37_linuxcpuextensionbuilder/temp.linux-x86_64-3.7/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/cymj.o -fopenmp -w
gcc -pthread -B /home/jqw/anaconda3/envs/d4rl/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py -I/home/jqw/.mujoco/mujoco210/include -I/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/numpy/core/include -I/home/jqw/anaconda3/envs/d4rl/include/python3.7m -c /home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/gl/osmesashim.c -o /home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/generated/_pyxbld_2.1.2.14_37_linuxcpuextensionbuilder/temp.linux-x86_64-3.7/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/gl/osmesashim.o -fopenmp -w
/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/gl/osmesashim.c:1:10: fatal error: GL/osmesa.h: No such file or directory
1 | #include <GL/osmesa.h>
| ^~~~~~~~~~~~~
compilation terminated.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/__init__.py", line 2, in <module>
from mujoco_py.builder import cymj, ignore_mujoco_warnings, functions, MujocoException
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/builder.py", line 504, in <module>
cymj = load_cython_ext(mujoco_path)
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/builder.py", line 110, in load_cython_ext
cext_so_path = builder.build()
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/builder.py", line 226, in build
built_so_file_path = self._build_impl()
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/builder.py", line 278, in _build_impl
so_file_path = super()._build_impl()
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/builder.py", line 249, in _build_impl
dist.run_commands()
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/distutils/dist.py", line 966, in run_commands
self.run_command(cmd)
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/distutils/dist.py", line 985, in run_command
cmd_obj.run()
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/Cython/Distutils/old_build_ext.py", line 186, in run
_build_ext.build_ext.run(self)
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/distutils/command/build_ext.py", line 340, in run
self.build_extensions()
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/mujoco_py/builder.py", line 149, in build_extensions
build_ext.build_extensions(self)
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/site-packages/Cython/Distutils/old_build_ext.py", line 195, in build_extensions
_build_ext.build_ext.build_extensions(self)
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/distutils/command/build_ext.py", line 449, in build_extensions
self._build_extensions_serial()
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/distutils/command/build_ext.py", line 474, in _build_extensions_serial
self.build_extension(ext)
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/distutils/command/build_ext.py", line 534, in build_extension
depends=ext.depends)
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/distutils/ccompiler.py", line 574, in compile
self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
File "/home/jqw/anaconda3/envs/d4rl/lib/python3.7/distutils/unixccompiler.py", line 120, in _compile
raise CompileError(msg)
distutils.errors.CompileError: command 'gcc' failed with exit status 1
解决办法:
sudo apt install libosmesa6-dev
# 补充命令:sudo apt-get install libgl1-mesa-glx libosmesa6
坑3:如果是fatal error: GL/glew.h: No such file or directory,那么就安装Glew库
解决办法
sudo apt-get install libglew-dev glew-utils
坑4:如果是FileNotFoundError: [Errno 2] No such file or directory: 'patchelf': 'patchelf', 那就安装patchelf
解决办法:
sudo apt-get -y install patchelf
安装成功是这样的效果
pip install dm_control
克隆D4RL仓库
git clone https://github.com/rail-berkeley/d4rl.git
找到到d4rl目录下的setup.py文件,注释mujoco_py, dm_control
install_requires=['gym',
'numpy',
# 'mujoco_py',
'pybullet',
'h5py',
'termcolor', # adept_envs dependency
'click', # adept_envs dependency
# 'dm_control' if 'macOS' in platform() else
# 'dm_control @ git+git://github.com/deepmind/dm_control@master#egg=dm_control',
'mjrl @ git+git://github.com/aravindr93/mjrl@master#egg=mjrl'],
然后直接安装并测试
# installing
pip install -e .
# 测试,创建test_d4rlpy.py并添加如下内容 vim test_d4rl.py
import gym
import d4rl # Import required to register environments
# Create the environment
env = gym.make('maze2d-umaze-v1')
# d4rl abides by the OpenAI gym interface
env.reset()
env.step(env.action_space.sample())
# Each task is associated with a dataset
# dataset contains observations, actions, rewards, terminals, and infos
dataset = env.get_dataset()
print(dataset['observations']) # An N x dim_observation Numpy array of observations
# Alternatively, use d4rl.qlearning_dataset which
# also adds next_observations.
dataset = d4rl.qlearning_dataset(env)
python test_d4rlpy.py
坑5:如果遇到:下面问题,那就单独安装mjrl
ERROR: Could not find a version that satisfies the requirement mjrl (unavailable) (from d4rl) (from versions: none)
ERROR: No matching distribution found for mjrl (unavailable)
安装命令
pip install git+https://github.com/rail-berkeley/d4rl@master#egg=d4rl
最后的D4RL安装结果结果
最后贴出我的~/.bashrc文件,欢迎参考
# cuda、anaconda等环境变量可以设置在本部分以前
# 环境变量次序也很重要
# mujoco(这里我安装了两部分)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.mujoco/mujoco210/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.mujoco/mujoco211/bin
export MUJOCO_KEY_PATH=~/.mujoco${MUJOCO_KEY_PATH}
export MJLIB_PATH=~/.mujoco/lib/libmujoco.so.2.1.1
# nvidia
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/nvidia
export LD_PRELOAD=~/anaconda3/envs/d3rlpy/lib/python3.7/site-packages/d3rlpy/dataset.cpython-37m-x86_64-linux-gnu.so
# export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libGLEW.so:/usr/lib/nvidia-465/libGL.so
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libGLEW.so
更多的坑大家可以参阅issue: https://github.com/rail-berkeley/d4rl/issues
坑6:有的伙伴可能会用pycharm去运行mujoco会出现一个问题就是:有nvidia的环境变量没有mujoco的,有mujoco的没有nvidia的
Exception:
Missing path to your environment variable.
Current values LD_LIBRARY_PATH=
Please add following line to .bashrc:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/jqw/.mujoco/mujoco210/bin
# 或者这样的
Exception:
Missing path to your environment variable.
Current values LD_LIBRARY_PATH=LD_LIBRARY_PATH:/usr/lib/nvidia
Please add following line to .bashrc:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/jqw/.mujoco/mujoco210/bin
解决办法:
直接在pycharm运行配置中修改环境变量:python文件上右键后进入 Modify Run Configuration
重点就是两个变量之间用 冒号隔开":",不是分号";", 然后就ok了
PYTHONUNBUFFERED=1;LD_LIBRARY_PATH=LD_LIBRARY_PATH:/usr/lib/nvidia:$LD_LIBRARY_PATH:/home/jqw/.mujoco/mujoco210/bin
论文信息:Scott Fujimoto, Shixiang Shane Gu: “A Minimalist Approach to Offline Reinforcement Learning”, 2021; arXiv:2106.06860.
本文是Google Brain团队和McGill大学合作,由 TD3、BCQ的作者 Fujimoto 提出并发表在NeurIPS2020 顶会上的文章,本文方法最大的优点是:方法简单、无任何复杂数学公式、可实现性强(开源)、对比实验非常充分(满分推荐),正如标题一样(A minimalist approach)。
摘要:相比于几篇博客讲过的BCQ(通过扰动网络生成动作,不断将学习策略和行为策略拉进)、BEAR(通过支撑集匹配避免分布匹配的问题)、BRAC(通过VP和PR两个方法正则化)以及REM(通过随机集成混合方法对多个值函数求取凸优化最优的鲁棒性)方法。本文作者提出的TD3+BC方法,结构简单,仅在值函数上添加一个行为克隆(BC)的正则项,并对state进行normalizing,简单的对TD3修改了几行代码就可以与前几种方法相媲美,结果表明:TD3+BC效果好,训练时间也比其他少很多。
其实上述的这些问题并不是去解决offline RL中的一些诸如分布偏移、OOD、过估计以及等等这些问题,而是去解决如何简单、快速、高效的实现算法的实现与高效运行问题,因此作者面对这些问题,发出疑问并给出方法:
下图是TD3+BC算法相对于CQL、Fish-BRC算法的复杂性对比,从表中我们可以看到CQL和Fish-BRC在算法(algorithmic)上有了很多的变种,使用生成网络,近似 等,而TD3+BC仅仅添加了一个BC term和Normalized state,足够的简单。
对于经典的DDPG、TD3等算法来讲, 策略梯度的计算根据David sliver提出的如下定义,即求解状态-动作值函数的期望值。
本文中,作者为了尽可能的让两个动作接近添加了一个正则项 以及 ,
个人看法: 有点像BCQ中的让学习策略和行为策略之间的距离减少那种意思,只不过添加到正则项里面.
另外一个技术点就是从代码执行层面的优化,即Normalize State,具体的Normalize过程如公式所示:
其中的 表示一个normalization常量,作者在文中使用了 , 和 表示期望和标准差(standard deviation)。
实验效果(关于纵坐标Percent difference后文有说明,本部分只看效果)
最后一个技术点就是关于 的求解,作者给出了计算公式,并在后文中说取值为 的时候效果最好, 实验部分有作者做的ablation实验证明。
最后贴出作者在TD3代码上的改动部分==》TD3+BC算法实现
此外,我们看一下作者如何rebuttle这些OpenReview提出的审稿意见[1],[2]
其实这部分蛮有意思的,我们发现大多数普通人的工作还是集中在对算法的小部分优化(数学大佬和代码大神略过),这里作者教你手把手给审稿人回复(建议收藏,热别是第2条)
审稿人:(1)首先,该方法的新颖性似乎有点有限。作者似乎直接使 RL+BC 适应离线设置,只是他们添加了状态归一化,这也不是新的。作者也没有从理论上证明这种方法的合理性。例如,作者应该证明该方法可以保证安全的策略改进,并且享有可比或更好的策略改进保证 w.r.t.先前的方法。如果没有理论依据,并且考虑到该方法的当前形式,我认为该方法有点增量。(2)此外,实证评估并不彻底。作者仅在 D4RL 中的简单 mujoco 环境中评估了该方法。目前尚不清楚该方法是否可以很好地执行更多无向多任务数据集,例如蚂蚁迷宫和厨房,以及更复杂的操作任务,例如 D4RL 中的 adroit。似乎该方法在随机数据集上表现不佳。这是一个主要限制吗?我还认为作者应该将状态归一化添加到所有基线以确保公平比较,因为状态归一化不是 RL 中的新技术。(3)最后,我认为比较不完整。作者还应该将该方法与最近的无模型离线 RL 方法(如 [1])和基于模型的方法(如 [2,3])进行比较,后者在随机和中等重放数据集上获得了更好的性能。总的来说,鉴于上述评论,我会投票支持弱拒绝。
下面我们看作者的神奇巧妙回复
作者回复:(1)关于新颖性:我们完全不同意我们的算法在新颖性方面是递增的(我们在相关工作中强调了许多类似的算法)。然而,我们的主要主张/贡献与其说这是最好的离线 RL 算法,或者说它特别新颖,不如说是令人惊讶的观察,即使用非常简单的技术可以匹配/优于当前算法。希望 TD3+BC 可以用作易于实现的基线或其他添加(例如 S4RL)的起点,同时消除更复杂方法所需的许多不必要的复杂性、超参数调整或计算成本. (2)关于经验评估:据我们所知,我们最强的基线 Fisher-BRC 被认为是无模型算法的 SOTA,最近在 ICML 上发表。(3)由于 D4RL 结果的标准化,我们可以直接与建议的基线进行比较(我们会将这些结果包含在最终草案中)。我们在下面报告这些,但我们想说明两点:(4)MOReL 和 MOPO 来自不同的方法系列(基于模型),并且都使用特定于环境的超参数。S4RL 与我们的方法相切,只需将 CQL 替换为 TD3+BC,就可以很容易地将其添加到我们的方法中。我们的方法可以说更适合基础算法的这些类型的添加,因为超参数更少,这意味着我们不必担心变化之间的交互作用。最终,我们没有发现添加状态归一化可以为基线提供相同水平的好处,这可能是因为这些方法需要超参数调整来补偿额外的修改。
挺有意思的,学习收藏吧!
这部分是作者实验的一些基础,挺良心的,具体到了每一个实验环境的版本号
这部分特意说明一下作者的良心部分:代码版本都放出来了
这部分公式是作者实验的参考基准计算方式,其中在博客也提出了关于差距百分比的疑问,特意查了了一下计算过程[3](备注,有的地方可能用了绝对值):
说明:关于D4RL数据集的组成、安装和解释请参考博文 离线强化学习(Offline RL)系列2: (环境篇)D4RL数据集简介、安装及错误解决
本实验参数 HC = HalfCheetah, Hop = Hopper, W = Walker, r = random, m = medium, mr = medium-replay, me = medium-expert, e = expert. While online algorithms (TD3) typically have small episode variances per trained policy (as they should at convergence),
可以从实验结果中很直白的看到,CQL、FishBRC与TD3+BC( )的运行时间, 其实这与算法的复杂性紧密相关,对于TD3来说只需要去根据超参数学习网络即可,但对于CQL等算法,需要学习一堆的参数。
这部分其实对比了vanillaBC方法和区别,同时就参数 做了对比得出了最好的 。
分布偏移最主要的原因是learned policy 和 behavior policy之间的偏移(从图中我们可以清晰的看到两者之间的区别),这也是offlineRL相比于Online RL在不能交互学习的情况下造成的。
OOD问题在Offline RL中非常常见,简单的可以理解为状态-动作对可能不在我们的offline Dataset中,对应的分布也一样,即学习分布远在(far outside)训练(training distribution)分布之外。那么训练和优化过程如下:
结合上图,其实真正解决这个问题,第一直观的想法就是增大数据集的数量,让数据集尽可能包含训练分布,这样学习分布基本可能会在范围内,然而这个方法并不奏效:
作者在实验中使用了大小不一样的数量实验,结果表明即使增大train samples, 算法的性能并没有得到有效提升,同时也会引发下一个累计误差问题:
此外Q值误差居高不下,是什么原因造成的?
这就是本文的核心问题了,深度强化学习中动态规规划(MC,TD)最核心的就是Q函数,我们知道在Q-learning中学习的时候,目标函数Q的计算通常是利用自举(bootstrapping)的方式,从训练集分布中去最大化函数估计,但由于OOD之外的数据,导致这个过程的error不断累积,最终导致严重偏离学习策略。
我们在Online RL中知道,最优 函数 遵循最优贝尔曼方程,如下所示:
然后,强化学习对应于最小化该等式左侧和右侧之间的平方差,也称为均方贝尔曼误差 (MSBE),得到:
MSBE 在由行为策略 生成的数据集 中的转换样本上最小化。尽管最小化 MSBE 对应于有监督的回归问题,但该回归的目标本身是从当前 函数估计中得出的。于是对于迭代 次的Q-learning来说,总误差(error) 可以定义为:
其中当前的贝尔曼误差(Bellman error)为:
那么我们就可以得出以下结论:
所以说,当一个状态-动作分布处于OOD之外时,我们其实是希望 很高,因为我们的优化目标是不断将处于分布之外的策略分布与训练分布距离最小化。为了缓解这个问题,作者提出了一个解决方法就是让学习策略输出的动作处于训练分布的支撑集(Support-set)中。
所谓的Support-set, 其实就是"学习策略 只有在行为策略 的密度大于阈值 ,而不是对密度 和 的值的接近约束。" 原话:
下面我们结合例子解释一下 分布匹配(Distribution-matching 和 支撑集匹配(Support-set matching) 的区别,以及原理。
考虑一维的Lineworld Environment问题,我们从
点出发到达
点,动作集分为“向左”和“向右”两种,对应的奖励在上图中有标记。
那么,行为策略在 和 之间的状态下执行次优动作,可能性为 0.9,但是动作 和 的状态都在分布内(in-distribution)。
个人理解原因
如上图,分布匹配约束(distribution matching constraint)的学习策略可以是任意次优的,事实上,通过推出该策略达到目标 G 的概率非常小,并且随着环境的建立而趋于 0 较大。
然而,在support-constraint中,作者表明支持约束可以恢复概率为 1 的最优策略(其实原因很简单,就是阈值 的原因, 只要动作在训练行为策略分布的支持集内就可以)。
那么为什么Distribution-matching在这里会失败?
通过上述分析,我们得出一个结论:我们希望的不是学习策略和行为策略越像越好,而是学习策略能够在行为策略的支撑集的范围内去进行优化, 如果学习策略和行为策略无限接近那不就是Behavior clone了,但offline无法无限的去逼近online,所以问题仍然存在。
下图就是关于Distribution-matching 和support constraint选择动作的区别
从图中我们可以看到:以红色的行为策略
为基准,在distribution-matching中则仅有紫色的学习策略相符,但在support-matching中黄色的都是可以匹配的learned policy, 所以更通用。
那么support-set matching更通用,具体是怎么matching的呢?下文我们从论文的理论部分开始分析。
第一步:解决策略集定义及收敛,定义Distribution-constraint operators概念,如下所示:
这里面最关键的有以下几个地方:
为了分析在近似误差下执行backup的次优(suboptimality) 问题,作者提出两个方面:
这里定义了一个Concentrability,【 越小,就说明policy set 中的policy 与 behavior policy 越相似】
第二步:最后作者给出了一个边界(bound)
证明过程如下:
这里的[Error Bounds for Approximate Value Iteration] 中解释了
We choose policies only lying in high support regions of the behaviour policy.Allows for a tradeoff between: Keeping close to the data (minimizing amount of propagated error) Having freedom to find the optimal policy
这里作者不是对所有策略执行最大化,而是对集合 Pi_eps 执行受限最大值,为了实际执行此操作,使用执行支撑匹配的约束。
其中作者原话是:
We change the policy improvement step, where instead of performing a maximization over all policies, we perform the restricted max over the set and in order to do this practically, we use a constrained formulation, where we use a constraint that performs support matching. We constrain the maximum mean discrepancy distance between the dataset and the actor to a maximal limit, using samples.
通过以上的方法,问题最终化解为一个求解最优问题:
MMD [A Kernel Two-Sample Test] 方法是一种统计测试以确定两个样本是否来自不同的分布,检验统计量是再现 kernel Hilbertspace (RKHS) 的单位球中函数的最大期望差异。
def gaussian_kernel(x, y, sigma=0.1):
return exp(-(x - y).pow(2).sum() / (2 * sigma.pow(2)))
def compute_mmd(x, y):
k_x_x = gaussian_kernel(x, x)
k_x_y = gaussian_kernel(x, y)
k_y_y = gaussian_kernel(y, y)
return sqrt(k_x_x.mean() + k_y_y.mean() - 2*k_x_y.mean())
双梯度下降是一种在约束条件下优化目标的流行方法。在强化学习中,它可以帮助我们做出更好的决策。
本代码由原作者开源 [Github]
python main.py --buffer_name=buffer_walker_300_curr_action.pkl --eval_freq=1000 --algo_name=BEAR
--env_name=Walker2d-v2 --log_dir=data_walker_BEAR/ --lagrange_thresh=10.0
--distance_type=MMD --mode=auto --num_samples_match=5 --lamda=0.0 --version=0
--mmd_sigma=20.0 --kernel_type=gaussian --use_ensemble_variance="False"
本文来源自:
https://www.zhihu.com/column/c_1487193754071617536
更多博客请左下方阅读原文