Python-DQN和DDQN代码对比阅读(14)-ddpn.py

DQN和DDQN都是三个文件,funcs.py、model.py和DQN.py或者DDQN.py。

两种算法的funcs.py、model.py文件完全一样,区别在第三个文件

目录

1.代码区别

1.1 定义ALGO变量来选择算法

1.2 使用if语句对两种算法做出选择

1.2.1 DQN

1.2.2 DDQN

2.问题


1.代码区别

1.1 定义ALGO变量来选择算法

GAME = "BreakoutDeterministic-v4" # "BreakoutDeterministic-v0"

# Atari Breakout actions: 0 (noop), 1 (fire), 2 (left) and 3 (right) 
VALID_ACTIONS = [0, 1, 2, 3]

ALGO = "DDQN" #"DQN"  # DDQN

这段代码定义了 Atari Breakout 游戏的名称和有效的动作列表:

GAME: 指定 Atari Breakout 游戏的环境名称,用于创建 Gym 环境对象。在这里可以选择不同的版本,例如 "BreakoutDeterministic-v4" 或 "BreakoutDeterministic-v0"。
VALID_ACTIONS: 定义了有效的动作列表,包含了可以在游戏中执行的动作的标识符。在 Atari Breakout 游戏中,有效的动作有 4 个,分别对应 "noop" (无操作), "fire" (发射球), "left" (向左移动板) 和 "right" (向右移动板)。

ALGO:定义一个变量ALGO,这个变量会存储DQN或者DDQN中的一个字符串通过这个变量来选择使用哪种算法。目的是为了可以方便使用哪种算法,而不删除DQN相关代码。

1.2 使用if语句对两种算法做出选择

                # calculate q values and targets 

                if (ALGO == 'DQN'): 

                   q_values_next = target_net.predict(sess, next_states_batch)
                   greedy_q = np.amax(q_values_next, axis=1) 
                   targets_batch = reward_batch + np.invert(done_batch).astype(np.float32) * gamma * greedy_q

                elif (ALGO == 'DDQN'):
                 
                   q_values_next = q_net.predict(sess, next_states_batch)
                   greedy_q = np.argmax(q_values_next, axis=1)
                   q_values_next_target = target_net.predict(sess, next_states_batch)
                   targets_batch = reward_batch + np.invert(done_batch).astype(np.float32) * gamma * q_values_next_target[np.arange(batch_size), greedy_q]

1.2.1 DQN

                # calculate q values and targets 

                if (ALGO == 'DQN'): 

                   q_values_next = target_net.predict(sess, next_states_batch)
                   greedy_q = np.amax(q_values_next, axis=1) 
                   targets_batch = reward_batch + np.invert(done_batch).astype(np.float32) * gamma * greedy_q

                

在这段代码中,在这段代码中,是实现了 DQN 算法中的 Q 值和目标值的计算。

首先通过 target_net.predict(sess, next_states_batch) 函数计算出下一状态的 Q 值。

然后,通过 np.amax(q_values_next, axis=1) 函数计算出在下一状态下的最大 Q 值,作为贪婪策略选择动作时使用的参考值。

最后,根据贝尔曼方程的定义,计算出目标值(target):targets_batch = reward_batch + np.invert(done_batch).astype(np.float32) * gamma * greedy_q

其中,reward_batch 是当前状态下的奖励值,done_batch 是一个布尔数组,表示是否达到终止状态,gamma 是折扣因子,greedy_q 是下一状态下的最大 Q 值。这段代码使用了贝尔曼方程的形式来更新目标值,从而用于计算损失函数,并进行神经网络的优化。

1.2.2 DDQN

代码总括

                # calculate q values and targets 

                elif (ALGO == 'DDQN'):
                 
                   q_values_next = q_net.predict(sess, next_states_batch)
                   greedy_q = np.argmax(q_values_next, axis=1)
                   q_values_next_target = target_net.predict(sess, next_states_batch)
                   targets_batch = reward_batch + np.invert(done_batch).astype(np.float32) * gamma * q_values_next_target[np.arange(batch_size), greedy_q]

在这段代码中,是实现了 DDQN(Double DQN)算法中的 Q 值和目标值的计算。

首先,通过 q_net.predict(sess, next_states_batch) 函数计算出下一状态的 Q 值。

然后,使用 np.argmax(q_values_next, axis=1) 函数找到在下一状态下具有最高 Q 值的动作,作为贪婪策略选择动作时使用的参考值。

接下来,通过 target_net.predict(sess, next_states_batch) 函数计算出下一状态的目标网络(Target Network)的 Q 值。这里使用了目标网络,是为了减小 DDQN 中的过估计(overestimation)现象。

最后,根据贝尔曼方程的定义,计算出目标值(target):

targets_batch = reward_batch + np.invert(done_batch).astype(np.float32) * gamma * q_values_next_target[np.arange(batch_size), greedy_q]

其中,reward_batch 是当前状态下的奖励值,done_batch 是一个布尔数组,表示是否达到终止状态,gamma 是折扣因子,q_values_next_target 是目标网络在下一状态下的 Q 值,greedy_q 是在下一状态下具有最高 Q 值的动作。这段代码使用了 DDQN 中的 Q 值和目标值计算方式,从而用于计算损失函数,并进行神经网络的优化。

代码分解

(1)q_values_next = q_net.predict(sess, next_states_batch)

q_values_next = q_net.predict(sess, next_states_batch)

这段代码中,使用了 q_net.predict(sess, next_states_batch) 函数来计算当前状态下的 Q 值。q_net 是 DDQN 算法中的 Q 网络(也称为本地网络),通过对输入的状态数据 next_states_batch 进行前向传播,得到当前状态下的 Q 值。

next_states_batch 是一个批次(batch)的状态数据,包含多个状态,其形状为 (batch_size, state_dim),其中 batch_size 是批次的大小,表示一次计算的状态数目,state_dim 是状态的维度。

q_net.predict() 函数的返回值是一个数组,表示对输入状态数据的 Q 值估计。其形状为 (batch_size, num_actions),其中 num_actions 是动作的数目,表示当前状态下可以选择的动作数目。

在DDQN 算法中,Q 网络的输出是对当前状态下所有可能动作的 Q 值估计,用于选择当前状态下的最优动作。这个 Q 值估计将在后续的计算中用于计算目标值、选择动作以及进行损失函数的计算和网络优化。

(2)greedy_q = np.argmax(q_values_next, axis=1)

greedy_q = np.argmax(q_values_next, axis=1)

这段代码中,使用了 np.argmax(q_values_next, axis=1) 函数来选择当前状态下的最优动作。

q_values_next 是通过 Q 网络(q_net)对下一状态(next_states_batch)进行前向传播得到的 Q 值估计。q_values_next 是一个数组,其形状为 (batch_size, num_actions),其中 batch_size 是批次的大小,表示一次计算的状态数目,num_actions 是动作的数目,表示当前状态下可以选择的动作数目。

np.argmax(q_values_next, axis=1) 函数会在每一行(即对每个状态)中选择具有最大值的动作的索引,即对每个状态选择对应的最优动作。这个索引值存储在 greedy_q 变量中,其形状为 (batch_size,),表示每个状态下的最优动作索引

在 DDQN 算法中,选择最优动作的方式可以是采用贪婪策略,即选择具有最大 Q 值估计的动作。这个最优动作将在后续的计算中用于计算目标值、更新网络参数等。

(3)q_values_next_target = target_net.predict(sess, next_states_batch)

q_values_next_target = target_net.predict(sess, next_states_batch)

这段代码中,使用了 target_net 来对下一状态 (next_states_batch) 进行前向传播,从而得到目标网络中对应的 Q 值估计 q_values_next_target

target_net 是一个目标网络,用于计算目标 Q 值。在 DDQN 算法中,目标网络是一个固定的网络,用于计算目标 Q 值,其参数不会在训练过程中更新,而是定期从主网络(也称为 Q 网络或者行动者网络)中复制得到。这样可以提高训练的稳定性。

q_values_next_target 是通过目标网络 target_net 对下一状态 next_states_batch 进行前向传播得到的 Q 值估计。q_values_next_target 是一个数组,其形状为 (batch_size, num_actions),其中 batch_size 是批次的大小,表示一次计算的状态数目,num_actions 是动作的数目,表示当前状态下可以选择的动作数目。

在 DDQN 算法中,使用目标网络的 Q 值估计作为计算目标值的基础,从而更新主网络的参数,从而实现训练过程中的优化。

(4)targets_batch = reward_batch + np.invert(done_batch).astype(np.float32) * gamma * q_values_next_target[np.arange(batch_size), greedy_q]

targets_batch = reward_batch + np.invert(done_batch).astype(np.float32) * gamma * q_values_next_target[np.arange(batch_size), greedy_q]

这段代码计算了更新目标值 targets_batch,用于在训练过程中更新主网络的参数。

reward_batch 是从环境中获取的奖励值,done_batch 是一个布尔值数组,表示在当前状态下是否已经结束了一个回合(即终止状态),gamma 是折扣因子,用于控制对未来奖励的权重,q_values_next_target 是目标网络对下一状态的 Q 值估计,greedy_q 是在下一状态下选择的最优动作的索引。

np.invert(done_batch).astype(np.float32)done_batch 取反并转换为浮点型,这样在更新目标值时可以保留终止状态的信息。np.arange(batch_size) 是一个数组,表示从 0 到 batch_size-1 的整数序列,用于在 q_values_next_target 中选择对应的 Q 值估计。

最终,targets_batch 的计算方式为将当前回合的奖励值 reward_batch 加上未终止状态的下一状态的最优动作的 Q 值估计 q_values_next_target 乘以折扣因子 gamma,从而得到更新目标值。这个目标值将用于计算主网络的损失函数,并通过反向传播更新主网络的参数,从而实现 DDQN 算法的训练。

2.问题

(1)为什么DQN算法使用 np.amax(),DDQN算法使用np.argmax(),二者的区别和联系?

np.amax()np.argmax() 都是 NumPy 库中的函数,用于在数组中找到最大值对应的索引

二者的区别在于返回值的形式和用途:

  • np.amax(arr, axis=None, keepdims=False) 返回数组 arr 中的最大值,可以指定沿某个轴(axis 参数)计算最大值。如果 keepdims 参数为 True,则保持结果的维度和输入数组一致,否则将降维。

  • np.argmax(arr, axis=None) 返回数组 arr 中最大值的索引,可以指定沿某个轴(axis 参数)计算最大值的索引。

在 DQN 算法中,使用 np.amax() 是因为它用于计算下一状态的最大 Q 值估计,即在下一状态下选择最优动作的 Q 值。这里需要返回最大值本身,因此使用 np.amax()

而在 DDQN 算法中,使用 np.argmax() 是因为它用于选择在下一状态下选择的最优动作的索引,即在下一状态下选择具有最大 Q 值的动作的索引。这里需要返回最大值的索引,因此使用 np.argmax()

需要注意的是,DQN 和 DDQN 算法是 Q 学习的两种变种,其中 DDQN 对 DQN 进行了一定的改进,解决了 DQN 算法中过高估计 Q 值的问题。因此在 DDQN 算法中,使用 np.argmax() 来选择动作的索引,而不是直接选择最大 Q 值。

(2)done_batch是怎么可以保留终止状态信息的

在强化学习中,done_batch 是一个布尔型数组,用于表示每个样本是否到达了终止状态。通常情况下,当一个智能体在环境中执行一个动作后,会观察到下一个状态和获得一个奖励信号。在某些情况下,执行的动作可能导致智能体到达了环境的终止状态,例如游戏结束或任务完成。done_batch 用于记录这些终止状态的信息。

在训练深度 Q 网络(DQN)和双重深度 Q 网络(DDQN)时,done_batch 的值可以从环境中获得,通常通过调用环境的 step() 函数获取下一个状态、奖励和终止状态信息。具体而言,当智能体执行一个动作并观察到下一个状态时,可以通过检查返回的终止状态信息来更新 done_batch。例如,done_batch 的对应样本为 True 时,表示智能体在该样本中的动作导致了终止状态,需要相应地处理。

在 DQN 和 DDQN 算法中,done_batch 主要用于控制目标 Q 值的计算当一个样本处于终止状态时,其目标 Q 值应该只包含当前状态下的立即奖励,而不包含下一状态的 Q 值估计。因此,np.invert(done_batch) 的作用是将 done_batch 中的 True 和 False 取反,以保留终止状态信息,并根据其值对目标 Q 值进行相应的调整。

(3)如何判断done_batch是true还是false?

在一般的强化学习环境中,done_batch 的取值通常由环境的状态信息决定。当智能体在执行一个动作后观察到环境的下一个状态时,可以通过检查这个状态来判断 done_batch 是否为 True 或 False。

在 OpenAI Gym 等常用的强化学习环境中,通常通过调用环境的 step() 函数获取下一个状态、奖励和终止状态信息。step() 函数的返回值通常包括三个元素:next_state 表示下一个状态,reward 表示在当前状态下执行的动作的即时奖励,done 表示当前状态是否为终止状态。例如,可以使用以下方式获取 done_batch

next_states, rewards, dones, _ = env.step(actions)
done_batch = np.array(dones, dtype=np.bool)

其中,actions 是智能体选择的动作,env 是环境对象,next_states 是下一个状态的数组,rewards 是即时奖励的数组,dones 是终止状态的数组。根据具体环境和问题的设置,done_batch 中的元素将根据终止状态的情况被设置为 True 或 False。

需要注意的是,不同的环境可能对终止状态的定义和表示方式有所不同,因此具体的实现方式可能会有所不同。在使用 done_batch 时,应根据环境的具体规定和要解决的问题进行相应的处理。

(4)DQN和DDQN算法的相同点和不同点?各自的优点和缺点?

DQN(Deep Q-Network)和DDQN(Double Deep Q-Network)是两种常用的强化学习算法,都是基于Q-learning的方法,用于解决离散动作空间的强化学习问题。

它们在一些方面有相同点,也有一些不同点,下面是它们的主要相同点和不同点以及各自的优点和缺点。

相同点:

①基于Q-learning:DQN和DDQN都是基于Q-learning算法的变种,使用了Q值函数来表示动作的价值。

②使用深度神经网络:DQN和DDQN都使用了深度神经网络来近似Q值函数,可以处理高维状态空间的问题。

③经验回放:DQN和DDQN都使用了经验回放(Experience Replay)技术,将智能体的经验存储在经验缓存中,并从中随机采样进行训练,可以提高样本的利用效率和稳定性。

不同点:

①目标网络更新方式:DDQN使用了目标网络(Target Network)来稳定训练过程,目标网络的更新方式是定期将主网络(Q网络)的参数复制给目标网络,而DQN则直接使用主网络的输出作为目标Q值。这是DDQN相对于DQN的一个改进,可以减轻DQN中因过度估计(overestimation)而导致的训练不稳定问题。

②动作选择方式:在计算目标Q值时,DDQN使用了贪心策略来选择下一个动作,即选择在当前状态下具有最大Q值的动作,而DQN则使用了在下一个状态下具有最大Q值的动作。这也是DDQN相对于DQN的一个改进,可以减轻DQN中因过度估计而导致的训练不稳定问题。

优点:

①强大的近似能力:DQN和DDQN都使用深度神经网络来近似Q值函数,可以处理高维状态空间的问题,具有强大的近似能力。

②经验回放:DQN和DDQN都使用了经验回放技术,可以提高样本的利用效率和稳定性,减轻样本间的关联性。

③可扩展性:DQN和DDQN可以扩展到复杂的问题,并且可以通过调整网络结构和超参数进行优化。

缺点:

①训练不稳定:DQN和DDQN在训练过程中可能会面临训练不稳定的问题,包括过度估计和过度探索等。

②高计算复杂度:DQN和DDQN使用了深度神经网络,需要大量的计算。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
DQN算法是一种基于Q-learning的深度强化学习算法,其目标是学习一个Q函数,使得该函数能够最大化累积奖励。DDQN算法是对DQN算法的改进,通过解决DQN算法中过高估计Q值的问题,提高了算法的性能。Dueling DQN算法则是在DDQN算法的基础上,提出了一种新的神经网络结构,使得算法的学习效率更高。 下面是DQN算法的公式推导分析: 1. Q-learning的更新公式为:$Q(s_t,a_t) \leftarrow Q(s_t,a_t) + \alpha(r_{t+1} + \gamma \max_{a} Q(s_{t+1},a) - Q(s_t,a_t))$ 2. DQN算法使用了深度神经网络来逼近Q函数,将更新公式改为:$Q(s_t,a_t) \leftarrow Q(s_t,a_t) + \alpha(r_{t+1} + \gamma \max_{a} Q(s_{t+1},a; \theta^-) - Q(s_t,a_t; \theta))$,其中$\theta$为当前网络的参数,$\theta^-$为目标网络的参数,$\max_{a} Q(s_{t+1},a; \theta^-)$表示在下一个状态$s_{t+1}$中,选择动作$a$所得到的最大Q值。 3. DDQN算法在DQN算法的基础上,使用了双网络结构,解决了DQN算法中过高估计Q值的问题。更新公式为:$Q(s_t,a_t) \leftarrow Q(s_t,a_t) + \alpha(r_{t+1} + \gamma Q(s_{t+1},\arg\max_{a} Q(s_{t+1},a; \theta); \theta^-) - Q(s_t,a_t; \theta))$,其中$\arg\max_{a} Q(s_{t+1},a; \theta)$表示在下一个状态$s_{t+1}$中,选择动作$a$所得到的最大Q值对应的动作。 4. Dueling DQN算法在DDQN算法的基础上,提出了一种新的神经网络结构,使得算法的学习效率更高。具体来说,Dueling DQN算法的输出包括两个分支,分别是该状态的状态价值V(标量)和每个动作的优势值A(与动作空间同维度的向量)。网络结构如下图所示: [Dueling DQN网络结构](https://img-blog.csdn.net/20170727145756345?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnhpYW9fYmFpZHUx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/q/80) 更新公式为:$Q(s_t,a_t) \leftarrow V(s_t) + (A(s_t,a_t) - \frac{1}{|\mathcal{A}|} \sum_{a} A(s_t,a))$,其中$V(s_t)$表示状态$s_t$的价值,$A(s_t,a_t)$表示在状态$s_t$下选择动作$a_t$的优势值,$\frac{1}{|\mathcal{A}|} \sum_{a} A(s_t,a)$表示所有动作的平均优势值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天寒心亦热

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值