DQN的过拟合问题

建议在学完 DQN 之后有不了解的再看本笔记,本文的环境都是 OpenAI 的开源库 gymnasium 的 Pendulum-v1,其给的最大奖赏是 0,也便是直立状况,其他状况都给负奖赏,因而能够以 0 为基准讨论过拟合问题。

强化学习笔记:DQN的过拟合问题

深度 Q 网络

中心了解

在一般DQN中,咱们会树立两个网络,一个 Q 网络,参数为 \omega,另一个是方针 Q 网络,参数为 ∗\omega^*,方针 Q 网络的参数是若干回合更新一次,而 Q 网络是每个状况动作之后都会更新,由于 Q 网络要追方针 Q 网络,而且方针 Q 网络的动作挑选是 Q 值最大的那个,假如只树立一个网络,那么 Q 值大的动作会被更多地挑选,也就被更多地高估;但这种状况下依然会被高估,由于方针网络总是挑选最大的 Q 值。

深度 Q 网络的关键在于时序差分方法更新网络参数 \theta,方针 Q 值是用方针 Q 网络得来的,rr表明本轮环境反馈的奖赏,\gamma表明折扣因子,\omega是网络的参数,s′s’a′a’表明方针 Q 网络对下一状况 Q 值的估量,由于网络输出的是若干动作的若干 Q 值,因而选其间最大的 Q 值,得出 QtargetQ_{target}作为方针 Q 值;而本轮 Q 值很简单,便是 Q(s,a)Q_{\omega}(s,a),用均方差 MSE 即可算出丢失,进而梯度更新。

Qtarget=r+max⁡a′∈AQ∗(s′,a′)Q=Q(s,a)loss=12(Qtarget−Q)2\begin{align} & Q_{target} = r + \gamma \mathop{\max} \limits_{a’\in A} Q_{\omega^*}(s’,a’) \nonumber \\ & Q = Q_{\omega}(s,a) \nonumber \\ & loss = \frac{1}{2}(Q_{target} – Q)^2 \nonumber \end{align}

其间 QtargetQ_{target} 也能够写成如下式子,由于 s′s’ 是给定了的,a′a’ 的选取便是使得 Q∗Q_{\omega^*} 最大的那个动作

Qtarget=r+Q∗(s′,argmax⁡a′Q∗(s′,a′))Q_{target}=r+\gamma Q_{\omega^*}\left(s’, \mathop{\operatorname{argmax}} \limits_{a’} Q_{\omega^*}(s’,a’)\right)

完好丢失函数能够写为

loss=argmin⁡12N∑i=1N[Q(si,ai)−(ri+max⁡a′Q∗(si′,a′))]2loss = \mathop{\operatorname{argmin}} \limits_{\omega} \frac{1}{2N} \sum^N_{i=1}\left[Q_{\omega}(s_i,a_i) – ( r_i + \gamma \mathop{\operatorname{max}} \limits_{a’} Q_{\omega^*}(s_i’,a’)) \right]^2

其间 1N\frac{1}{N} 是批量均值,12\frac{1}{2} 是最后两个值的均值,该公式求使丢失最小的参数 \omega,在程序中不必写这么杂乱:

# pytorch 2.0.1
# states和actions等都是一个批量的数据,tensor类
import torch.nn.functional as F
import torch
q_net = Qnet().to('cuda')
target_q_net = Qnet().to('cuda')
optimizer = torch.optim.Adam(q_net.parameters(), lr=learning_rate) # Adam优化器
...
Q_target = r + gamma * target_q_net(next_states).max(1)[0].view(-1, 1) * (1 - dones | truncated) # 直接选出最大的Q值
Q_value = q_net(states).gather(1, actions) # 根据当时动作选出该动作的Q值
loss = torch.mean(F.mes_loss(Q_value, Q_target)) # 求批量的均方差之后再求均值,即1/2N
optimizer.zero_grad() # 设置0梯度避免堆集
loss.backward() # 反向传达核算梯度
optimizer.step() # 执行梯度下降

改进方案

Double DQN

在一般 DQN 中,方针网络总是挑选最大的 Q 值,虽然比从原网络直接估量 Q 值要好,但也有或许过拟合,比如对一个奖赏最大便是 0 的环境来说,Q 网络要拟合它的奖赏,尽管越往后总体会越趋近于 0,可是它有或许输出会大于 0,方针 Q 网络同理,因而假如总是选方针 Q 网络估量的最大 Q 值,那就有或许把原 Q 网络往输出大于 0 的方向引导,形成过拟合,或许说过高的 Q 值估量。

前面提到方针 Q 网络的更新是比较慢的,假设原网络已通过拟合了,咱们的方针 Q 值还是用方针 Q 网络估量,但不挑选最大的那个 Q 值,而挑选原网络最大 Q 值对应的那个动作,依照这个动作去挑选方针 Q 网络给出的 Q 值,由于方针 Q 网络更新的比较慢,所以或许没有原网络那么过拟合,所以选到的 Q 会比较低,这样原 Q 网络的参数就会调整得不那么过拟合,然后必定程度按捺了过拟合。

这样的修改能够写成如下公式,区别便是挑选动作的网络变了,变成原网络,从参数上看得出来

原DQN⁡:Qtarget=r+Q∗(s′,argmaxa′Q∗(s′,a′))DoubleDQN⁡:Qtarget=r+Q∗(s′,argmaxa′Q(s′,a′))\begin{align} 原\operatorname{DQN}:& Q_{target}=r+\gamma Q_{\omega^*}(s’, \mathop{\mathrm{argmax}} \limits_{a’} Q_{\omega^*}(s’,a’)) \\ \operatorname{Double~DQN}:& Q_{target}=r+\gamma Q_{\omega^*}(s’, \mathop{\mathrm{argmax}} \limits_{a’} Q_{\omega}(s’,a’)) \\ \end{align}

代码方面有如下改动

# ======> # 下个状况的最大Q值, Double DQN的区别
if self.dqn_type == 'DoubleDQN' or 'DuelingDQN':  # 先在q网络确认动作, 再对应到方针网络的价值上
    max_action = self.q_net(next_states).max(1)[1].view(-1, 1)
    max_next_q_values = self.target_q_net(next_states).gather(1, max_action)
else:  # DQN的情况, 直接用方针网络估量价值
    max_next_q_values = self.target_q_net(next_states).max(1)[0].view(-1, 1)

这样的改动是有作用的,左面是一般 DQN,右边是 Double DQN,如下图

强化学习笔记:DQN的过拟合问题
强化学习笔记:DQN的过拟合问题

本文的环境是 Pendulum-v1,其给的最大奖赏是 0,也便是直立状况,其他状况都给负奖赏,一般 DQN 在一些次序中,估量的 Q 值比较大,有的挨近 10,也便是过拟合,右边的 Double DQN 中,在 epsilon下降之后的训练中呈现了严重过拟合,可是在后期安稳之后就很少过拟合了,但还有一个缺陷,便是有的次序的 Q 值突然下降,阐明关于该次序挑选的动作学习的不好,由于网络每次只是针对挑选的一个动作形成的差错进行梯度下降,这样就疏忽了其他动作的学习,假如有状况动作没有被采样到,就没有被很好的学习到。

Dueling DQN

首要区别是网络规划上,一般 DQN 的网络一般如下

class Qnet(torch.nn.Module):
    ''' 只要一层躲藏层的Q网络 '''
    def __init__(self, state_dim, hidden_dim, action_dim):
        super(Qnet, self).__init__()
        self.fc1 = torch.nn.Linear(state_dim, hidden_dim)
        self.fc2 = torch.nn.Linear(hidden_dim, action_dim)
    def forward(self, x):
        x = F.relu(self.fc1(x))  # 输出一个Q值
        return self.fc2(x)

Dueling DQN 选用对偶输出的规划,共用一个躲藏层,可是输出层输出两个值,而且加和作为终究输出,其规划如下

class VAnet(torch.nn.Module):
    ''' 只要一层躲藏层的A网络和V网络 '''
    def __init__(self, state_dim, hidden_dim, action_dim):
        super(VAnet, self).__init__()
        self.fc1 = torch.nn.Linear(state_dim, hidden_dim)  # 同享网络部分
        self.fc_A = torch.nn.Linear(hidden_dim, action_dim)
        self.fc_V = torch.nn.Linear(hidden_dim, 1)
    def forward(self, x):
        A = self.fc_A(F.relu(self.fc1(x)))  # 状况动作优势
        V = self.fc_V(F.relu(self.fc1(x)))  # 状况价值
        Q = V + A - A.mean(-1).view(-1, 1)  # Q值由V值和A值核算得到
        return Q

实际上开始想的是 A = Q - V,即估量的 Q 值减去当时状况的价值 V 等于动作优势 A,这样更好了解,可是咱们需求网络给出 Q 值,因而改写成 Q = V + A

注:A 和 Q 有两个参数 s,a,所以叫 状况动作优势/价值;V 只要一个参数 s,所以叫 状况价值。

V 值,代表当时状况的价值,假如是一个批量,那么有两个维度,巨细是(批量数, 1);另一个是 A,表明当时动作的相对优势(人为定义的),它类似传统的 Q 值,即给出了该状况下每个动作的 Q 值,假如输入的是一个批量,那么巨细是(批量, 动作空间);其间 A 一般是多维的,类似之前输出 Q 值,由于每个状况都对应一个 Q 值,而且有一个状况批量,而 V 是一维的,代表每个状况的一个状况价值。所谓状况价值,能够了解为有的状况很差,无论选用什么动作都很难取得比较好的报答,那么这时候状况价值就很低,反之同理。

在网络中需求约束 A 的更新,Q=V+(A−A)Q = V + (A – \bar{A})AA 减去 A\bar{A},会使得 A 全体更挨近 0,而且均值为 0,这是为了削减 A 在梯度下降中的调整巨细,然后使得梯度下降首要影响 V,V 的输出比较简单,也好调整一些,而改变了 V,也就一起改变了一切动作的 A 值(矩阵运算的广播机制),等于改变了一切动作的 Q 值(一起添加或许削减),因而在某个状况下的学习会对一切动作的估量产生影响,而不是只改变 Q 值最大的那个动作的估量。

在前面的一般 DQN 和 Double DQN 中,没有 A 和 V 的概念,网络直接输出 Q,在反向传达中,只考虑了 Q 值最大的那个动作,就只是考虑了该动作形成的差错。

这样的改动也是有作用的,左面是 Double DQN,右边是 Deuling DQN,后者后期 Q 值呈现大幅下降的情况削减了,而且下降的幅度也变小了,如下图

强化学习笔记:DQN的过拟合问题
强化学习笔记:DQN的过拟合问题

关于过拟合的研讨

Double DQN 的意图是按捺过拟合,可是无法完全避免,实际上动作空间越大越简单过拟合。

设动作空间为 m,也便是有 m 个动作可供挑选,假设状况 ss 下一切动作 a′a’ 的期望报答无差异,都为 Q∗(s,a′)Q^*(s,a’),网络估量的 Q 值是 Q(s,a)Q_{\omega}(s,a),那么差错能够表明为 a=max⁡aQ(s,a)−Q∗(s,a′)\epsilon_a = \mathop{\max}\limits_{a} Q_{\omega}(s,a) -Q^*(s,a’),假设差错 a\epsilon_a 遵守[-1, 1]的均匀散布,而且各动作 aa 相互独立,有 E(max⁡aa)=(m−1)2m−1m+1E(\max\limits_{a} \epsilon_a)=\frac{(m-1)2^{m-1}}{m+1},这是跟着 m 的增大而增大的。证明如下:

a\epsilon_a 的散布函数如下:

P(a≤x)={0,x<−11+x2,−1≤x<11,1≤xP(\epsilon_a \le x) = \begin{cases} \begin{align} &0, & x<-1 \nonumber \\ &\frac{1+x}{2}, & -1 \le x <1 \nonumber \\ &1, & 1\le x \nonumber \\ \end{align} \end{cases}

又由于各动作是独立的,一共有 m 个动作,因而关于使得差错最大的动作 aa 有散布函数:

P(max⁡aa≤x)={0,x<−1(1+x2)m,−1≤x<11,1≤xP(\max\limits_{a} \epsilon_a \le x) = \begin{cases} \begin{align} &0, & x<-1 \nonumber \\ &\left(\frac{1+x}{2}\right)^m, & -1 \le x <1 \nonumber \\ &1, & 1\le x \nonumber \\ \end{align} \end{cases}

对该散布函数求期望:

E(max⁡aa)=∫−11xd⁡(1+x)m2=[x(1+x)m2]−11−∫−11(1+x)m2dx=2m−1−[(1+x)m+12(m+1)]−11=2m−1−2mm+1=2m−1(m+1)−2m−12m+1=(m−1)2m−1m+1\begin{align} E(\max\limits_{a} \epsilon_a) & = \int_{-1}^1 x \operatorname{d}\frac{(1+x)^m}{2} \nonumber \\ & = \left[\frac{x(1+x)^m}{2}\right]^1_{-1} – \int_{-1}^1 \frac{(1+x)^m}{2}\mathrm{d}x \nonumber \\ & = 2^{m-1} – \left[\frac{(1+x)^{m+1}}{2(m+1)}\right]^1_{-1} \nonumber \\ & = 2^{m-1} – \frac{2^m}{m+1} \nonumber \\ & = \frac{2^{m-1}(m+1)-2^{m-1}\times2}{m+1} \nonumber \\ & = \frac{(m-1)2^{m-1}}{m+1} \nonumber \end{align}

内容参考

强化学习教程》,《着手学深度学习》