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.问题
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相关代码。
# 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]
# 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 值。这段代码使用了贝尔曼方程的形式来更新目标值,从而用于计算损失函数,并进行神经网络的优化。
代码总括
# 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 算法的训练。
(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使用了深度神经网络,需要大量的计算。