浏览量:4825 最近编辑于:2022-06-15 19:27:25
# 前言
最近在入门强化学习(RL)及DQN,看了一些博文和文章,花了2天时间跑了下DQN的经典demo--**CartPole**。其中踩过一些坑,本篇文章就简单谈一谈强化学习、DQN和我跑的入门demo。
# 什么是强化学习?
强化学习是一类算法,是让计算机实现从一开始完全随机的进行操作,通过不断地尝试,从错误中学习,最后找到规律,学会了达到目的的方法。这就是一个完整的强化学习过程。让计算机在不断的尝试中更新自己的行为,从而一步步学习如何操自己的行为得到高分。
强化学习的常见模型是标准的马尔可夫决策过程(Markov Decision Process, MDP)。按给定条件,强化学习可分为基于模式的强化学习(model-based RL)和无模式强化学习(model-free RL),以及主动强化学习(active RL)和被动强化学习(passive RL)。
它主要包含四个元素,**Agent、环境状态、行动、奖励**,强化学习的目标就是获得最多的累计奖励。
我的理解是,强化学习就是智能体(Agent)根据环境(Environment)做出行动(action)并得到反馈、奖励(reward),并根据这些反馈改进自身,以期望获得最大奖励的过程。Agent的训练是在不断的**试错**中完成的,先期对环境的行动可能是随机的,不好的行为会得到环境的惩罚,好的行为会得到奖赏,随着强化的进行,智能体的行为逐渐趋向于获得大的奖励。
# Q-Learning
Q-Learning是强化学习算法中value-based的算法,Q即为Q(s,a),就是在某一个时刻的state状态下,采取动作action能够获得收益的期望,环境会根据agent的动作反馈相应的reward奖赏,所以算法的主要思想就是将state和action构建成一张Q_table表来存储Q值,然后根据Q值来选取能够获得最大收益的动作。
Q-learning的主要优势就是使用了时序差分法(融合了蒙特卡洛和动态规划)能够进行off-policy的学习,使用**贝尔曼方程**可以对马尔科夫过程求解最优策略,本文对其中算法不进行详细推导,不过强烈建议先了解下,因为后面所说的DQN基于Q-Learning的思想。
> BellMan方程:Q(s,a)←Q(s,a)+α[ r+γmaxQ(s',a')-Q(s,a) ]
# DQN
深度Q网络(DQN)是将Q-learning和卷积神经网络(CNN)结合在一起,由Mnih等人在2013年首次提出:
[https://arxiv.org/pdf/1312.5602.pdf](https://arxiv.org/pdf/1312.5602.pdf)
强化学习算法可以分为三大类:value based, policy based 和 actor critic。常见的是以DQN为代表的value based算法,这种算法中只有一个值函数网络,没有policy网络,以及以DDPG,TRPO为代表的actor-critic算法,这种算法中既有值函数网络,又有policy网络。
说到DQN中有值函数网络,这里简单介绍一下强化学习中的一个概念,叫值函数近似。一个state action pair (s,a)(s,a)对应一个值函数Q(s,a)Q(s,a)。理论上对于任意的(s,a)(s,a)我们都可以由公式求出它的值函数,即用一个查询表lookup table来表示值函数。但是当state或action的个数过多时,分别去求每一个值函数会很慢。因此我们用函数近似的方式去估计值函数:^Q(s,a,w)≈Qπ(s,a)Q^(s,a,w)≈Qπ(s,a)
上面说过DQN使用神经网络来近似值函数,即神经网络的输入是state s,输出是Q(s,a),∀a∈AQ(s,a),∀a∈A (action space)。通过神经网络计算出值函数后,DQN使用ϵ−greedy策略来输出action。值函数网络与ϵ−greedy策略之间的联系是这样的:首先环境会给出一个obs,智能体根据值函数网络得到关于这个obs的所有Q(s,a)Q(s,a),然后利用ϵ−greedy选择action并做出决策,环境接收到此action后会给出一个奖励Reward及下一个obs。这是一个step。此时我们根据Reward去更新值函数网络的参数。接着进入下一个step。如此循环下去,直到我们训练出了一个好的值函数网络。附上论文原文算法伪代码:
![](/files/album/20200917-3.png)
* **简单来说,DQN就是用神经网络代替Q-Learning中的求Q值函数**
# CartPole Demo
## 前期工作
好了,目前为止,已经介绍了前期的一些概念,下面我们直接从经典入门项目CartPole开始,简单实现一下DQN,CartPole项目介绍详见gym官网:[http://gym.openai.com/](http://gym.openai.com/)
简单来说它是一个学习控制倒立摆的游戏,我们先通过`pip install gym`安装python的gym模块,再在项目中导入gym模块。
![](/files/album/20200917-1.png)
[项目演示视频](http://183.207.33.39:9011/s3-us-west-2.amazonaws.com/c3pr90ntc0td/rl-gym-doc/cartpole-no-reset.mp4)
## 算法设计
如上图所示,为了让倒立摆能稳稳地竖立,我们需要控制底座的移动,这正好对应我们上文提到地action,即对环境产生地动作。在本例中,action有0,1两个值,对应左移和右移。对环境做出动作以后,environment会返回reward和state'(下一个状态),state表示当前状态。我们构建神经网络,用于接受环境当前状态state,输出为action(0/1),另外还需要一个ReplayMemory数据结构用于存放从环境接受到的四元组:state,action,reward,state_。损失为
loss=y-Q(s,a)=[r+γ*maxQ(s',a')-Q(s,a)]²,loss function选用MSE。
## 核心代码
下面为模型训练代码:
```python
def train(eval_net, target_net, replay_memory, batch_size, optimizer):
# copy eval net parameters to target net according to update freq
if train_count % target_update_freq == 0:
print('Copy eval net parameters to target net')
target_net.load_state_dict(eval_net.state_dict())
# get batch samples
samples = replay_memory.get_random_samples(batch_size)
# convert numpy data to tensor
batch_state = Variable(torch.FloatTensor(
samples[:, :4]), requires_grad=True)
batch_action = Variable(torch.LongTensor(
samples[:, 4].astype(int)))
batch_reward = Variable(torch.FloatTensor(
samples[:, 5]), requires_grad=True)
batch_state_ = Variable(torch.FloatTensor(
samples[:, 6:]), requires_grad=True)
# calculate value of 'Q' and 'target Q', Bellman: Q(s,a)=r+γ*maxQ(s',a')
q_eval = eval_net(batch_state).gather(
1, batch_action.unsqueeze(1)).view(batch_size)
q_target = batch_reward+GAMMA*target_net(batch_state_).max(1)[0].detach()
# calculate loss and update gradients
# loss=y-Q(s,a)=[r+γ*maxQ(s',a')-Q(s,a)]²
loss = F.mse_loss(q_eval, q_target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
```
完整代码详见:
[https://github.com/ivanwhaf/DL/blob/master/gym_demo.py](https://github.com/ivanwhaf/DL/blob/master/gym_demo.py)