Keras深度学习实战(43)——深度Q学习算法
Posted 盼小辉丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Keras深度学习实战(43)——深度Q学习算法相关的知识,希望对你有一定的参考价值。
Keras深度学习实战(43)——深度Q学习算法
0. 前言
在《强化学习基础》一节中,我们学习了强化学习的基本概念,并且介绍了如何在给定状态下采取随机动作。此外,我们还使用自定义环境,计算下一个状态、动作和奖励。在本节中,我们首先介绍 Q 学习与深度 Q 学习的基本思想,然后利用 OpenAI
的 Gym
库模拟 Frozen Lake
和 CartPole
问题,并使用 Keras
实现 Q 学习解决这两个问题。
1. Q 学习简介
状态-动作值函数 (State-Action Value Function
),简称 Q 函数,定义为从状态
s
t
s_t
st 同时执行动作
a
t
a_t
at 的双重设定下,在策略
π
π
π 的控制下能获得的期望回报值:
Q π ( s t , a t ) = E τ ∼ p ( τ ) [ R ( τ t : T ) ∣ τ a t = a t , τ s t = s t ] Q^π(s_t, a_t) = E_τ∼p(τ)[R(τ_t:T)|τ_a_t = a_t , τ_s_t= s_t ] Qπ(st,at)=Eτ∼p(τ)[R(τt:T)∣τat=at,τst=st]
在最优策略 π ∗ ( a ∣ s ) π^*(a|s) π∗(a∣s) 下,具有以下关系:
Q ∗ ( s t , a t ) = m a x π Q π ( s t , a t ) π ∗ = a r g m a x a t Q ∗ ( s t , a t ) \\beginsplit Q^*(s_t, a_t)=\\undersetπmaxQ^π(s_t, a_t)\\\\ π^*=\\underseta_targmaxQ^*(s_t, a_t) \\endsplit Q∗(st,at)=πmaxQπ(st,at)π∗=atargmaxQ∗(st,at)
Q 学习 (Q Learning
) 算法通过下式估计
Q
∗
(
s
t
,
a
t
)
Q^*(s_t, a_t)
Q∗(st,at) 函数,并利用
π
ε
(
s
t
)
\\pi^\\varepsilon(s_t)
πε(st) 策略来获得策略改进:
Q ∗ ( s t , a t ) ← Q ∗ ( s t , a t ) + α ( r ( s t , a t ) + γ m a x a t + 1 Q ∗ ( s t + 1 , a t + 1 ) − Q ∗ ( s t , a t ) ) Q^*(s_t, a_t)\\larr Q^*(s_t, a_t)+\\alpha(r(s_t,a_t)+\\gamma\\underseta_t+1maxQ^*(s_t+1,a_t+1)-Q^*(s_t, a_t)) Q∗(st,at)←Q∗(st,at)+α(r(st,at)+γat+1maxQ∗(st+1,at+1)−Q∗(st,at))
深度 Q 网络 (Deep Q Network
, DQN
) 用深层的神经网络来参数化
Q
∗
(
s
t
,
a
t
)
Q^*(s_t, a_t)
Q∗(st,at) 函数,并利用梯度下降算法循环更新 Q 网络。
2. 使用 Q 学习进行 FrozenLake 游戏
2.1 FrozenLake 环境分析
FrozenLake
环境如下所示:
智能体从状态 S
开始,目标是通过尽可能避免状态 H
来达到状态 G
,智能体可以处于 16
种可能的状态。此外,智能体可以采取四种可能的动作(向上,向下,向右或向左移动)。
我们将定义一个 q-表
,其中有 16
行对应于 16
个状态,四列对应于在每种状态下可以采取的四个动作:
- 在当前状态下采取动作的值=在当前状态下采取动作的值+ 1*(奖励+折扣系数*在下一个状态下采取的最佳动作的值-在当前状态下采取动作的值)
我们将学习率设为 1
,以使状态下某个动作的值更新不会急剧变化:
- 在当前状态下采取动作的值=在当前状态下采取动作的值+学习率*(奖励+折扣系数*下一种状态采取的最佳可能行动的值-在当前状态下采取动作的值)
根据以上公式更新 q-表
,以便确定在不同状态下可以采取的最佳动作。
2.2 模型分析
在实际解决问题之前,我们将首先探讨用于解决 FrozenLake
问题的模型策略:
- 使用
OpenAI的Gym
实例化FrozenLake
环境 - 初始化形状为
16 x 4
的q-表
,其中所有元素值为0
- 在给定状态下选择动作时,采用探索-利用法:
- 在早期迭代中探索,因为我们不确定在游戏的最初几个回合中应采取的最佳动作。
- 但是,随着我们对游戏的了解越来越多,我们在采取可能的最佳动作的同时,仍然采取一定概率的随机行动(随着回合的增加,概率逐渐降低)来利用所学到的知识
- 在给定的回合中:
- 根据我们是否尝试探索或利用来选择动作
- 确定新的状态和奖励,并通过执行上一步中选择的动作来检查游戏是否结束
- 初始化学习率参数和折扣因子
- 通过使用上述公式来更新在
q-表
中的状态下采取所选动作的值 - 重复上述步骤,直到游戏结束
- 重复进行
1000
回合以上游戏 - 检查
q-表
以识别在给定状态下要采取的最佳动作 - 绘制智能体的路径,以使其根据
q-表
在状态下执行动作
2.3 使用 Q 学习算法解决 FrozenLake 问题
(1) 导入 Gym
以及其他相关库,Gym
是用于开发和比较强化学习算法的工具包,它支持多种模拟环境,关于 Gym
更多介绍,可以参考《强化学习环境配置》:
import gym
from gym.envs.registration import register
import random
(2) 注册并创建环境,为了简化游戏,我们修改了 FrozenLake
环境的默认设定,最重要的设置是令冰面并不滑,每一步动作的结果都是确定,而冰面滑时,即时指定向左的动作,智能体也可能会滑动到其他位置,例如向下滑:
register(
id = 'FrozenLakeNotSlippery-v1',
entry_point = 'gym.envs.toy_text:FrozenLakeEnv',
kwargs = 'map_name': '4x4', 'is_slippery': False,
max_episode_steps = 100,
reward_threshold = 0.8196
)
env = gym.make('FrozenLakeNotSlippery-v1')
(3) 检查创建的环境,reset()
方法用于重置游戏环境:
env.reset()
env.render()
渲染出的 FrozenLake
环境如下:
(4) 我们也可以检查环境中状态空间与动作空间数量,由于我们使用的 FrozenLake
环境包括 4 x 4
的网格,共有 16
个状态。因此,共有 16
个观测值:
print(env.observation_space)
print(env.action_space.n)
输出结果如下所示:
Discrete(16)
4
(5) 接下来,从动作空间中采样一个动作,并使用 step()
方法采取该动作,以生成新状态、奖励、是否完成游戏的标记以及有关该步骤的其他信息:
action = env.action_space.sample()
new_state, reward, is_done, info = env.step(action)
(6) 初始化 q-表
,因为有 16
种状态,每种状态有 4
种可能的动作,因此 q-表
的形状为 (16, 4)
:
import numpy as np
qtable = np.zeros((16,4))
(7) 初始化超参数后,运行 FrozenLake
游戏多个回合:
total_episodes=15000
learning_rate=0.8
max_steps=99
gamma=0.95
epsilon=1
max_epsilon=1
min_epsilon=0.01
decay_rate=0.005
rewards=[]
for episode in range(total_episodes):
state=env.reset()
step=0
done=False
total_rewards=0
(8) 定义要采取的策略。如果 eps
(一个介于 0
到 1
之间的随机数)小于 0.5
,我们将进行探索;否则,我们会进行利用(考虑 q-表
中的最佳操作):
rewards=[]
for episode in range(total_episodes):
state=env.reset()
step=0
done=False
total_rewards=0
for step in range(max_steps):
exp_exp_tradeoff=random.uniform(0,1)
# Exploitation:
if exp_exp_tradeoff>epsilon:
action=np.argmax(qtable[state,:])
else:
# Exploration
action=env.action_space.sample()
(9) 获取新状态和奖励,并通过在给定步骤中采取动作获取游戏是否完成:
new_state,reward,done,info=env.step(action)
(10) 基于当前状态状态执行的操作更新 q-表
,并使用在当前状态下执行动作后获得的新状态来更新状态:
# Update the Q
qtable[state,action]=qtable[state,action]+\\
learning_rate*(reward+gamma*np.max(qtable[new_state,:])-qtable[state,action])
total_rewards+=reward
state=new_state
(11) 当本次游戏回合结束后,我们继续进行下一个新的游戏回合,同时,我们更新用于决定要进行探索还是利用的随机因子 (eps
):
if done:
break
episode+=1
epsilon=min_epsilon+(max_epsilon-min_epsilon)*np.exp(decay_rate*episode)
rewards.append(total_rewards)
(12) 一旦建立了 q-表
,我们就可以根据 q-表
得到的最佳动作指导智能体以进行动作:
print("Score over Time:",sum(rewards)/total_episodes)
print(qtable)
打印出的 q-表
如下所示:
[[0.73509189 0.77378094 0.77378094 0.73509189]
[以上是关于Keras深度学习实战(43)——深度Q学习算法的主要内容,如果未能解决你的问题,请参考以下文章