赞
踩
强化学习(reinforcement learning,RL)讨论的问题是智能体(agent)怎么在复杂、不确定的环境(environment)中最大化它能获得的奖励。如图1.1所示。
强化学习由两部分组成:智能体和环境。在强化学习过程中,智能体与环境一直在交互。智能体在环境中获取某个状态后,它会利用该状态输出一个动作 (action),这个动作也称为决策(decision)。然后这个动作会在环境中被执行,环境会根据智能体采取的动作,输出下一个状态以及当前这个动作带来的奖励。智能体的目的就是尽可能多地从环境中获取奖励。
Q&A环节:
Q:强化学习的基本结构?
A: 本质上是智能体与环境的交互。具体地,当智能体在环境中得到当前时刻的状态后,其会基于此状态输出一个动作,这个动作会在环境中被执行并输出下一个状态和当前的这个动作得到的奖励。智能体在环境里存在的目标是最大化期望累积奖励。
以cv为例,监督学习通常有如下假设:
强化学习的数据是不满足上述两条假设的。
强化学习 | 监督学习 | |
---|---|---|
输入样本 | 时间序列 | 独立同分布样本 |
反馈方式 | 延迟奖励 | 直接反馈 |
获取反馈的方式 | 探索和利用 | 直接获取 |
上限 | 环境 | 标注的数据 |
Q&A环节:
Q: 强化学习相对于监督学习为什么训练过程会更加困难?
A: 1)强化学习处理的大多是序列数据,其很难像监督学习的样本一样满足独立同分布条件。 2)强化学习有奖励的延迟,即智能体的动作作用在环境中时,环境对于智能体状态的奖励存在延迟,使得反馈不实时。3)监督学习有正确的标签,模型可以通过标签修正自己的预测来更新模型,而强化学习相当于一个“试错”的过程,其完全根据环境的“反馈”更新对自己最有利的动作。
Q: 强化学习、监督学习和无监督学习三者有什么区别呢?
A: 首先强化学习和无监督学习是不需要有标签样本的,而监督学习需要许多有标签样本来进行模型的构建和训练。其次对于强化学习与无监督学习,无监督学习直接基于给定的数据进行建模,寻找数据或特征中隐藏的结构,一般对应聚类问题;强化学习需要通过延迟奖励学习策略来得到模型与目标的距离,这个距离可以通过奖励函数进行定量判断,这里我们可以将奖励函数视为正确目标的一个稀疏、延迟形式。另外,强化学习处理的多是序列数据,样本之间通常具有强相关性,但其很难像监督学习的样本一样满足独立同分布条件
标准强化学习 --------> 深度强化学习
标准强化学习:设计特征 ----> 训练价值函数,如图 1.2 所示。标准强化学习先设计很多特征,这些特征可以描述现在整个状态。 得到这些特征后,我们就可以通过训练一个分类网络或者分别训练一个价值估计函数来采取动作。
深度强化学习:深度学习 + 标准强化学习,自从我们有了深度学习,有了神经网络,就可以把智能体玩游戏的过程改进成一个端到端训练(end-to-end training)的过程,如图 1.3所示。我们不需要设计特征,直接输入状态就可以输出动作。我们可以用一个神经网络来拟合价值函数或策略网络,省去特征工程(feature engineering)的过程。
在一个强化学习环境里面,智能体的目的就是选取一系列的动作来最大化奖励,所以这些选取的动作必须有长期的影响。但在这个过程里面,智能体的奖励其实是被延迟了的,就是我们现在选取的某一步动作,可能要等到很久后才知道这一步到底产生了什么样的影响。如图 1.13 所示,在玩雅达利的 Pong 游戏时,我们可能只有到最后游戏结束时,才知道球到底有没有被击打过去。过程中我们采取的上升(up)或 下降(down)动作,并不会直接产生奖励。强化学习里面一个重要的课题就是近期奖励和远期奖励的权衡(trade-off),研究怎么让智能体取得更多的远期奖励。在与环境的交互过程中,智能体会获得很多观测。针对每一个观测,智能体会采取一个动作,也会得到一个奖励。所以历史是观测、动作、奖励的序列:
智能体在采取当前动作的时候会依赖于它之前得到的历史,所以我们可以把整个游戏的状态看成关于这个历史的函数:
状态是对世界的完整描述,不会隐藏世界的信息。观测是对状态的部分描述,可能会遗漏一些信息。环境有自己的函数来更新状态,在智能体的内部也有一个函数来更新状态。当智能体的状态与环境的状态等价的时候,即当智能体能够观察到环境的所有状态时,我们称这个环境是完全可观测的(fully observed)。在这种情况下面,强化学习通常被建模成一个马尔可夫决策过程 (Markov decision process,MDP)的问题。在马尔可夫决策过程中,。 当智能体只能看到部分的观测,我们就称这个环境是部分可观测的(partially observed)。 在这种情况下,强化学习通常被建模成部分可观测马尔可夫决策过程(partially observable Markov decision process, POMDP)的问题。部分可观测马尔可夫决策过程是马尔可夫决策过程的一种泛化。 部分可观测马尔可夫决策过程依然具有马尔可夫性质,但是假设智能体无法感知环境的状态,只能知道 部分观测值。比如在自动驾驶中,智能体只能感知传感器采集的有限的环境信息。部分可观测马尔可夫决策过程可以用一个七元组描述: (S,A,T,R,Ω,O,γ)。其中 S 表示状态空间,为隐变量,A 为动作空间,T(s′∣s,a) 为状态转移概率,R 为奖励函数,Ω(o∣s,a) 为观测概率,O 为观测空间,γ 为折扣系数。
不同的环境允许不同种类的动作。在给定的环境中,有效动作的集合经常被称为动作空间(action space)。智能体的动作数量是有限的,在物理世界中控制一个智能体,在这个环境中就有连续动作空间(continuous action space)。在连续动作空间中,动作是实值的向量。例如,走迷宫机器人如果只有东南西北这4种移动方式,则其动作空间为离散动作空间;如果机器人可以向 360 度中的任意角度进行移动,则其动作空间为连续动作空间。
对于一个强化学习智能体,它可能有一个或多个如下的组成成分。
策略(policy)。智能体会用策略来选取下一步的动作。
价值函数(value function)。我们用价值函数来对当前状态进行评估。价值函数用于评估智能体进 入某个状态后,可以对后面的奖励带来多大的影响。价值函数值越大,说明智能体进入这个状态越有利。
模型(model)。模型表示智能体对环境的状态进行理解,它决定了环境中世界的运行方式。
策略是智能体的动作模型,它决定了智能体的动作。它其实是一个函数,用于把输入的状态变成动作。策略可分为两种:随机性策略和确定性策略。随机性策略(stochastic policy)就是 π 函数,即。输入一个状态 s,输出一个概率。 这个概率是智能体所有动作的概率,然后对这个概率分布进行采样,可得到智能体将采取的动作。比如可能是有 0.7 的概率往左,0.3 的概率往右,那么通过采样就可以得到智能体将采取的动作。确定性策略(deterministic policy)就是智能体直接采取最有可能的动作,即。通常情况下,强化学习一般使用随机性策略,随机性策略有很多优点。比如,在学习时可以通过引入一定的随机性来更好地探索环境; 随机性策略的动作具有多样性,这一点在多个智能体博弈时非常重要。采用确定性策略的智能体总是对同样的状态采取相同的动作,这会导致它的策略很容易被对手预测。
价值函数的值是对未来奖励的预测,我们用它来评估状态的好坏。 价值函数里面有一个折扣因子(discount factor),我们希望在尽可能短的时间里面得到尽可能多的奖励。比如现在给我们两个选择:10天后给我们100块钱或者现在给我们100块钱。我们肯定更希望现在就给我们 100 块钱,因为我们可以把这 100 块钱存在银行里面,这样就会有一些利息。因此,我们可以把折扣因子放到价值函数的定义里面,价值函数的定义为:
,对所有的
期望的下标是 π 函数, π函数的值可反映在我们使用策略π的时候,到底可以得到多少奖励。我们还有一种价值函数: Q函数。Q函数里面包含两个变量:状态和动作。其定义:
所以我们未来可以获得奖励的期望取决于当前的状态和当前的动作。Q 函数是强化学习算法里面要学习的一个函数。因为当我们得到 Q 函数后,进入某个状态要采取的最优动作可以通过 Q 函数得到。
模型决定了下一步的状态。下一步的状态取决于当前的状态以及当前采取的动作。它由状态转移概率和奖励函数两个部分组成。状态转移概率:
奖励函数是指我们在当前状态采取了某个动作,可以得到多大的奖励,即
当我们有了策略、价值函数和模型3个组成部分后,就形成了一个马尔可夫决策过程(Markov decision process)。如图 1.5 所示,这个决策过程可视化了状态之间的转移以及采取的动作。
根据智能体学习的事物不同:
根据智能体是否学习环境模型分类。
Q&A环节
Q:强化学习中所谓的损失函数与深度学习中的损失函数有什么区别呢?
A: 深度学习中的损失函数的目的是使预测值和真实值之间的差距尽可能小,而强化学习中的损失函数的目的是使总奖励的期望尽可能大。
OpenAI 的 Gym库是一个环境仿真库,里面包含很多现有的环境。针对不同的场景,我们可以选择不同的环境。离散控制场景(输出的动作是可数的,比如Pong游戏中输出的向上或向下动作)一般使用雅达利环境评估;连续控制场景(输出的动作是不可数的,比如机器人走路时不仅有方向,还有角度,角度就是不可数的,是一个连续的量 )一般使用 MuJoCo 环境评估。Gym Retro是对 Gym 环境的进一步扩展,包含更多的游戏。由于 Gym 库 0.26.0 及其之后的版本对之前的代码不兼容,所以我们安装 0.26.0 之前的 Gym,比如 0.25.2
- pip install gym==0.25.2
- pip install pygame ##显示图形界面
简单的环境配置见:Mountain Car Continuous - Gym Documentation (gymlibrary.dev)
如图 1.7 所示,CartPole-v0 环境有两个动作:将小车向左移动和将小车向右移动。我们还可以得到观测:小车当前的位置,小车当前往左、往右移的速度,杆的角度以及杆的最高点(顶端)的速度。 观测越详细,我们就可以更好地描述当前所有的状态。这里有奖励的定义,如果能多走一步,我们就会得到一个奖励(奖励值为1),所以我们需要存活尽可能多的时间来得到更多的奖励。当杆的角度大于某一个角度(没能保持平衡),或者小车的中心到达图形界面窗口的边缘,或者累积步数大于200,游戏就结束了,我们就输了。所以智能体的目的是控制杆,让它尽可能地保持平衡以及尽可能保持在环境的中央。
- import gym
- env = gym.make('CartPole-v0')
- env.reset()
- for _ in range(1000):
- env.render()
- action = env.action_space.sample()
- observation, reward, done, info = env.step(action) ##完成 S-->A-->R-->S'
- print(observation)
- env.close()
输出:
- [ 0.01653398 0.19114579 0.02013859 -0.28050058]
- [ 0.0203569 -0.00425755 0.01452858 0.01846535]
- [ 0.02027175 -0.19958481 0.01489789 0.31569658]
- ......
我们只要不断观测这样的过程,并让智能体在其中用相应的算法完成训练,就能得到一个高质量的强化学习模型。Gym 库已注册的环境可以通过以下代码查看:
- from gym import envs
- env_specs = envs.registry.all()
- envs_ids = [env_spec.id for env_spec in env_specs]
- print(envs_ids)
输出:
['CartPole-v0', 'CartPole-v1', 'MountainCar-v0', 'MountainCarContinuous-v0', 'Pendulum-v1', 'Acrobot-v1', 'LunarLander-v2', 'LunarLanderContinuous-v2', 'BipedalWalker-v3', 'BipedalWalkerHardcore-v3', 'CarRacing-v2', 'Blackjack-v1', 'FrozenLake-v1', 'FrozenLake8x8-v1', 'CliffWalking-v0', 'Taxi-v3', 'Reacher-v2', 'Reacher-v4', 'Pusher-v2', 'Pusher-v4', 'InvertedPendulum-v2', 'InvertedPendulum-v4', 'InvertedDoublePendulum-v2', 'InvertedDoublePendulum-v4', 'HalfCheetah-v2', 'HalfCheetah-v3', 'HalfCheetah-v4', 'Hopper-v2', 'Hopper-v3', 'Hopper-v4', 'Swimmer-v2', 'Swimmer-v3', 'Swimmer-v4', 'Walker2d-v2', 'Walker2d-v3', 'Walker2d-v4', 'Ant-v2', 'Ant-v3', 'Ant-v4', 'Humanoid-v2', 'Humanoid-v3', 'Humanoid-v4', 'HumanoidStandup-v2', 'HumanoidStandup-v4']
'运行
Gym 库中的每个环境都定义了观测空间和动作空间。观测空间和动作空间可以是离散的(取值为有限个离散的值),也可以是连续的(取值为连续的值)。
2. MountainCar-v0 例子
首先查看观测空间和动作空间
- ###MountainCar-v0示例
- import gym
- env = gym.make('MountainCar-v0') ##环境创建
- print('观测空间 = {}'.format(env.observation_space))
- print('动作空间 = {}'.format(env.action_space))
- print('观测范围 = {} ~ {}'.format(env.observation_space.low,
- env.observation_space.high))
- print('动作数 = {}'.format(env.action_space.n))
输出:
- 观测空间 = Box([-1.2 -0.07], [0.6 0.07], (2,), float32)
- 动作空间 = Discrete(3)
- 观测范围 = [-1.2 -0.07] ~ [0.6 0.07]
- 动作数 = 3
其中离散空间用 gym.spaces.Discrete 类表示,连续空间用 gym.spaces.Box 类表示。对于离散空间,Discrete (n) 表示可能取值的数量为 n;对于连续空间,Box类实例成员中的 low 和 high 表示每个浮点数的取值范围。MountainCar-v0 中的观测是长度为 2 的 numpy 数组,数组中值的类型为 float。MountainCar-v0 中的动作是整数,取值范围为 {0,1,2}。
gym库的操作总结:Gym库官方操作文档
- import gym
-
- env=gym.make(env_name) ##env_name:环境名,取出环境
- env.reset() ##初始化环境
- env.step(action) ##action:动作,执行一步环境
- env.render() ##显示环境
- env.close() ##关闭环境
具体代码如下:
- ###MountainCar-v0示例
- import gym
- import numpy as np
-
- ###实现对智能体的控制
- class SimpleAgent:
- def __init__(self, env):
- pass
-
- def decide(self, observation): # 决策
- position, velocity = observation
- lb = min(-0.09 * (position + 0.25) ** 2 + 0.03,
- 0.3 * (position + 0.9) ** 4 - 0.008)
- ub = -0.07 * (position + 0.38) ** 2 + 0.07
- if lb < velocity < ub:
- action = 2
- else:
- action = 0
- return action # 返回动作
-
- def learn(self, *args): # 学习
- pass
-
- ###实现是智能体与环境的交互
- def play(env, agent, render=False, train=False):
- '''
- env: 环境
- agent: 智能体
- render: 确定是否需要图形化界面
- train: 是否需要训练智能体,训练时为true, 测试的时候为false
- '''
-
- episode_reward = 0. # 记录回合总奖励,初始值为0
- observation = env.reset() # 重置游戏环境,开始新回合
- while True: # 不断循环,直到回合结束
- if render: # 判断是否显示
- env.render() # 显示图形界面
- action = agent.decide(observation)
- next_observation, reward, done, _ = env.step(action) # 执行动作
- episode_reward += reward # 收集回合奖励
- if train: # 判断是否训练智能体
- agent.learn(observation, action, reward, done) # 学习
- if done: # 回合结束,跳出循环
- break
- observation = next_observation
- return episode_reward # 返回回合总奖励
-
- env = gym.make('MountainCar-v0')
- env.seed(3) # 设置随机种子,让结果可复现
- agent = SimpleAgent(env)
- print('观测空间 = {}'.format(env.observation_space))
- print('动作空间 = {}'.format(env.action_space))
- print('观测范围 = {} ~ {}'.format(env.observation_space.low,env.observation_space.high))
- print('动作数 = {}'.format(env.action_space.n))
-
- ###实现智能体和环境交互一个回合
- episode_reward = play(env, agent, render=True) #单次调用表示一个回合
- print('回合奖励 = {}'.format(episode_reward))
- env.close() # 关闭图形界面
-
- ###性能评估 要求:连续100回合奖励大于-110
- episode_rewards = [play(env, agent) for _ in range(100)]
- print('平均回合奖励 = {}'.format(np.mean(episode_rewards)))
-
-
-
注:vscode安装的notebook在运行代码的时候不会显示图形化界面,但是脚本运行可以显示图形化界面,这个问题浅试了下没有搜到合适的方法,期待大佬解释下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。