本文将带您一起实践深度学习与强化学习联合解决问题的一个经典算法:深度Q学习网络(DQN)。深度学习算法在强化学习领域的应用主要体现在价值函数或策略函数的近似表示上,理解了这一点将有助于您直击深度强化学习问题的本质。正因为如此,我们也可以使用不基于深度学习的其他函数近似工具。
由于训练、调试一个深度学习网络需要较长的时间,并且我基本上是使用自己的风格来写这些代码和博客,因此后续的进度会不固定,成熟一个算法释放一篇文章。不过我这里可以贴一些别人已经写好的基于深度学习算法的一些链接:
- borgwang/reinforce_py 用不同的机器学习库实现了各种深度强化学习算法
- Reinforcement Learning (DQN) tutorial PyTorch官方教程提供直接基于游戏界面的CNN+DQN组合实现
在此对提供这些链接的作者一并表示感谢。
接下来我来按照自己的节奏和风格解释我的DQN算法实现。在我的代码里,我将把使用神经网络的价值函数的近似表示封装到一个Approximator类中,然后再实现包含此价值函数的继承自Agent基类的个体类:ApproxQAgent,最后我们将观察其在不同环境中的训练效果,并讲讲我自身的编程体会,基于深度学习库的代码我将使用PyTorch库。
好的,我们开始!
Approximator类的实现
Approximator类作为价值函数的近似函数,其要实现的功能很简单:一是输出基于一个状态行为对s,a在参数w描述的函数下的价值Q(s,a,w);另一个是调整参数来更新某型状态行为对s,a的价值。在先前基于GridWorld环境的SarsaAgent实现中,对应这两个函数的分别是读取和设置价值Q表:get_Q和set_Q,读者还记得吗?在基于价值函数的近似表示中,我们调整的不是直接的Q值,而是通过调整生成Q值的参数w来达到这个目的。
在第六讲中,我们学习到使用神经网络来近似价值函数,根据输入和输出数据的不同选择可以有三种不同的网络搭建方式,其中适用于Q学习的两种方式分别是:使用(s,a)为输入,单一的Q为输出,和使用基于s为输入不同行为对应的Q值组成的向量为输出。前者适用范围较广,后者更多见于行为空间为离散值的时候。本例中,我们使用的是后者。我们在__init__方法中声明这样的基于一个隐藏层的简单神经网络(近似价值函数):
import numpy as np
import torch
from torch.autograd import Variable
import copy
class Approximator(torch.nn.Module):
'''base class of different function approximator subclasses
'''
def __init__(self, dim_input = 1, dim_output = 1, dim_hidden = 16):
super(Approximator, self).__init__()
self.dim_input = dim_input
self.dim_output = dim_output
self.dim_hidden = dim_hidden
self.linear1 = torch.nn.Linear(self.dim_input, self.dim_hidden)
self.linear2 = torch.nn.Linear(self.dim_hidden, self.dim_output)
我们主要是定义了两个nn.Module来实现线性变换,具体下文在进行网络的前向运算时会使用到ReLU激活函数。
设计一个_forward方法来预测基于某状态的价值:
def _forward(self, x):
h_relu = self.linear1(x).clamp(min=0) # 实现了ReLU
y_pred = self.linear2(h_relu)
return y_pred
再写一个方法fit来进行训练,更新网络参数以更好的符合个体基于Q学习对于价值的判断:
def fit(self, x,
y,
criterion=None,
optimizer=None,