> 文章列表 > Python-DQN和DDQN代码对比阅读(14)-ddpn.py

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

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_qelif (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使用了深度神经网络,需要大量的计算。