Dueling Network

Dueling Network —— Dueling Network Architectures for Deep Reinforcement Learning

  • 论文下载地址

  • 论文介绍

    在这里插入图片描述

    图9. Dueling Network 模型结果示意图

    Dueling Network与传统DQN的区别在于神经网络结构的不同,Dueling Netowrk在传统DQN的基础上只进行了微小的改动,但能大幅提升DQN的表现。从图9中可以看出,在传统DQN中,DQN的神经网络直接输出Q函数的值,即某个状态下不同动作对应的动作价值,输出层的前一层是全连接层。

    Dueling Network对DQN的结构改进主要在全连接层上,它在全连接层和输出层之间进行修改,将全连接层改为两条流,其中一条输出关于状态的价值,另外一条输出关于动作的优势函数的值,最终将两条流合并得到Q动作价值。

    在某些情况下,Dueling Network可以了解哪些状态有价值或没有价值,而不必了解每个动作对状态的影响(在一些状态中,不管选择哪个动作的影响都不大),这在agent的行为不会以任何方式影响到环境的情况下特别有用。
    在这里插入图

    图10. 不同情况下agent的侧重点

    如图10所示,agent注意力集中的部分被标记为橙色,当agent前面没有车时,agent自身动作对于环境并没有太大差异,此时agent更加关注状态价值,当agent前面有车时(agent需要躲避车辆或者超车),agent需要关注不同动作优势值的差异。

  • 理论分析

    假设在Atari游戏中,智能体在时间步 t t t根据由 M M M个视频帧组成的 s t = ( x t − M + 1 , . . . , x t ) ∈ S s_t=(x_{t-M+1},...,x_t)\in S st=(xtM+1,...,xt)S,从动作空间 A = { 1 , . . . , ∣ A ∣ } \mathcal{A}=\{1,...,|\mathcal{A}|\} A={1,...,A}选择动作 a t a_t at ,并观测由模拟器产生的奖励信号 r t r_t rt

    在一局游戏中,把从起始到结束的所有奖励记作 r 1 , . . . , r t , . . . , r n r_1,...,r_t,...,r_n r1,...,rt,...,rn,定义折扣回报率为 γ ∈ [ 0 , 1 ] \gamma \in [0,1] γ[0,1]。折扣回报的定义如公式(1)所示: R t = r t + γ ⋅ r t + 1 + γ 2 ⋅ r t + 2 + ⋯ + γ n − t ⋅ r n (1) R_t=r_t+\gamma \cdot r_{t+1}+\gamma^2 \cdot r_{t+2}+\cdots+\gamma^{n-t} \cdot r_n \tag{1} Rt=rt+γrt+1+γ2rt+2++γntrn(1)在游戏尚未结束的 t t t时刻, R t R_t Rt是一个随机变量,其随机性来自于 t t t时刻之后的所有状态和动作。动作价值函数的定义如公式(2)所示: Q π ( s t , a t ) = E [ R t ∣ S t = s t , A t = a t ] (2) Q_\pi\left(s_t, a_t\right)=\mathbb{E}\left[R_t \mid S_t=s_t, A_t=a_t\right] \tag{2} Qπ(st,at)=E[RtSt=st,At=at](2)公式(2)中的期望消除了 t t t时刻之后的所有状态 S t + 1 , . . . , S n S_{t+1},...,{S_n} St+1,...,Sn 与所有动作 A t + 1 , . . . , A n A_{t+1},...,A_n At+1,...,An,期望只与当前的状态 s t s_t st和动作 a t a_t at相关。上面介绍的状态动作价值函数可以用动态规划递归计算,如公式(3)所示: Q π ( s t , a t ) = E S t + 1 [ r + γ E A t + 1 [ Q π ( s t + 1 , a t + 1 ) ] ∣ S t = s t , A t = a t ] (3) Q_\pi(s_t, a_t)=\mathbb{E}_{S_{t+1}}\left[r+\gamma \mathbb{E}_{A_{t+1} }\left[Q_\pi\left(s_{t+1}, a_{t+1}\right)\right] \mid S_t=s_t, A_t=a_t\right] \tag{3} Qπ(st,at)=ESt+1[r+γEAt+1[Qπ(st+1,at+1)]St=st,At=at](3) 动作价值函数 Q π ( s t , a t ) Q_\pi(s_t,a_t) Qπ(st,at)依赖于 s t s_t st a t a_t at π \pi π,不依赖于 t + 1 t+1 t+1时刻及之后的状态和动作,因为随机变量 S t + 1 , A t + 1 , . . . , S n , A n S_{t+1},A_{t+1},...,S_n,A_n St+1,At+1,...,Sn,An 都被期望消除了。

    为了消除策略 π \pi π的影响,只评价当前状态 s t s_t st和动作 a t a_t at的好坏,引出了最优动作价值函数,如公式(4)所示: Q ⋆ ( s t , a t ) = max ⁡ π Q π ( s t , a t ) , ∀ s t ∈ S , a t ∈ A (4) Q_{\star}\left(s_t, a_t\right)=\max _\pi Q_\pi\left(s_t, a_t\right), \quad \forall s_t \in \mathcal{S}, \quad a_t \in \mathcal{A} \tag{4} Q(st,at)=πmaxQπ(st,at),stS,atA(4)最优动作价值函数可以理解为有很多种策略函数 π \pi π可以选择,我们选择最好的策略函数,如公式(5)所示: π ⋆ = argmax ⁡ π Q π ( s t , a t ) , ∀ s t ∈ S , a t ∈ A (5) \pi^{\star}=\underset{\pi}{\operatorname{argmax}} Q_\pi\left(s_t, a_t\right), \quad \forall s_t \in \mathcal{S}, \quad a_t \in \mathcal{A} \tag{5} π=πargmaxQπ(st,at),stS,atA(5)

    状态价值函数的定义如公式(6)所示: V π ( s t ) = E A t ∼ π ( ⋅ ∣ s t ) [ Q π ( s t , A t ) ] = ∑ a ∈ A π ( a ∣ s t ) ⋅ Q π ( s t , a ) . (6) \begin{aligned} V_\pi\left(s_t\right) & =\mathbb{E}_{A_t \sim \pi\left(\cdot \mid s_t\right)}\left[Q_\pi\left(s_t, A_t\right)\right] \\ & =\sum_{a \in \mathcal{A}} \pi\left(a \mid s_t\right) \cdot Q_\pi\left(s_t, a\right) . \end{aligned} \tag{6} Vπ(st)=EAtπ(st)[Qπ(st,At)]=aAπ(ast)Qπ(st,a).(6)公式(6)中把动作 A t A_t At作为随机变量,然后关于 A t A_t At求期望,把 A t A_t At消掉。状态价值函数 V π ( s t ) V_{\pi}(s_t) Vπ(st)只依赖于策略 π \pi π与当前状态 s t s_t st,不依赖于动作。状态价值函数 V π ( s t ) V_{\pi}(s_t) Vπ(st)也是折扣回报 R t R_t Rt的期望,如公式(7)所示: V π ( s t ) = E A t , S t + 1 , A t + 1 , ⋯ , S n , A n [ R t ∣ S t = s t ] (7) V_\pi\left(s_t\right)=\mathbb{E}_{A_t, S_{t+1}, A_{t+1}, \cdots, S_n, A_n}\left[R_t \mid S_t=s_t\right] \tag{7} Vπ(st)=EAt,St+1,At+1,,Sn,An[RtSt=st](7)公式(7)中消除了 R t R_t Rt依赖的随机变量 A t , S t + 1 , A t + 1 , . . . , S n , A n A_t,S_{t+1},A_{t+1},...,S_n,A_n At,St+1,At+1,...,Sn,An,状态价值函数值越大,表示当前状态 S t S_t St回报的期望越大,用状态价值可以衡量策略 π \pi π与状态 s t s_t st的好坏。

    为了消除策略 π \pi π的影响,只评价当前状态 s t s_t st的好坏,引出了最优状态价值函数,如公式(8)所示: V ⋆ ( s ) = max ⁡ π V π ( s ) , ∀ s ∈ S (8) V_{\star}(s)=\max _\pi V_\pi(s), \quad \forall s \in \mathcal{S} \tag{8} V(s)=πmaxVπ(s),sS(8)

    我们定义优势函数,将状态值函数和状态动作值函数联系起来,如公式(9)所示: A π ( s , a ) = Q π ( s , a ) − V π ( s ) (9) A_\pi(s, a)=Q_\pi(s, a)-V_\pi(s) \tag{9} Aπ(s,a)=Qπ(s,a)Vπ(s)(9) 公式(9)中, V ( s ) V(s) V(s)可以理解为在该状态 s s s下所有可能动作所对应的动作值函数乘以采取该动作的概率之和;通俗来说,值函数 V ( s ) V(s) V(s)是该状态下所有动作值函数关于动作概率的期望。而动作价值函数 Q ( s , a ) Q(s,a) Q(s,a)是单个动作所对应的值函数, Q ( s , a ) − V ( s ) Q(s,a)-V(s) Q(s,a)V(s)表示当前动作值函数相对于平均值的大小。

    所以优势函数表示的是当前动作值函数相比于当前状态值函数的优势,如果优势值大于零,表示当前动作比平均动作好,如果优势函数值小于0,表示当前动作比平均动作差。优势函数表示在当前状态下各个动作的相对好坏程度。

    根据优势函数的定义,我们可以知道优势函数有以下性质,如公式(10)所示: E a ∼ π ( s ) [ A π ( s , a ) ] = E a ∼ π ( s ) [ Q π ( s , a ) − V π ( s ) ] = E a ∼ π ( s ) [ Q π ( s , a ) ] − V π ( s ) = V π ( s ) − V π ( s ) = 0 (10) \mathbb{E}_{a \sim \pi(s)}\left[A^\pi(s, a)\right]= \mathbb{E}_{a \sim \pi(s)}\left[Q_\pi(s, a)-V_\pi(s)\right] = \mathbb{E}_{a \sim \pi(s)}\left[Q_\pi(s, a)\right]-V_\pi(s)= V_\pi(s) - V_\pi(s) = 0\tag{10} Eaπ(s)[Aπ(s,a)]=Eaπ(s)[Qπ(s,a)Vπ(s)]=Eaπ(s)[Qπ(s,a)]Vπ(s)=Vπ(s)Vπ(s)=0(10)

    优势函数刻画的是某个动作相对于平均值函数的“优势”。例如,在状态 s s s下有3个动作 a 1 a_1 a1 a 2 a_2 a2 a 3 a_3 a3,对应的 Q Q Q函数分别为 Q ( s , a 1 ) = 0.9 Q(s,a_1)=0.9 Q(s,a1)=0.9 Q ( s , a 2 ) = 1 Q(s,a_2)=1 Q(s,a2)=1 Q ( s , a 3 ) = 1.1 Q(s,a_3)=1.1 Q(s,a3)=1.1状态 s s s的状态值函数为: V ( s ) = E a [ Q ( s , a ) ] = ( 0.9 + 1 + 1.1 ) / 3 = 1.0 V(s)=\mathbb{E}_a[Q(s,a)]=(0.9+1+1.1)/3=1.0 V(s)=Ea[Q(s,a)]=(0.9+1+1.1)/3=1.0根据优势函数的定义,三个动作的优势函数值分别为: A ( s , a 1 ) = − 0.1 A(s,a_1)=-0.1 A(s,a1)=0.1 A ( s , a 2 ) = 0 A(s,a_2)=0 A(s,a2)=0 A ( s , a 3 ) = 0.1 A(s,a_3)=0.1 A(s,a3)=0.1因此 a 1 a_1 a1对于平均水平(由 V V V定义)的优势为-0.1,表示该动作低于平均的值函数水平, a 2 a_2 a2等于平均水平, a 3 a_3 a3的优势高于平均水平,因此如果按照贪心策略来选择动作,应该选择动作 a 3 a_3 a3,最优动作的选择可以仅通过优势函数 A ( s , a ) A(s,a) A(s,a)得到,即如公式(11)所示: a ∗ = a r g max ⁡ a A ( s , a ) = a r g max ⁡ a [ A ( s , a ) + V ( s ) ] = a r g max ⁡ a Q ( s , a ) (11) a^*=arg\space \max_{a}A(s,a)=arg \space \max_{a} [A(s,a) + V(s)] = arg \space \max_{a}Q(s,a) \tag{11} a=arg amaxA(s,a)=arg amax[A(s,a)+V(s)]=arg amaxQ(s,a)(11)

    Dueling Network的核心思想是将动作值 Q ( s , a ) Q(s,a) Q(s,a)的计算分解成两部分:状态值和优势函数,即如公式(12)所示: Q ( s , a ) = V ( s ) + A ( s , a ) (12) Q(s,a)=V(s)+A(s,a) \tag{12} Q(s,a)=V(s)+A(s,a)(12)但是Dueling Network并不是直接基于公式(12)实现的,因为这会导致不唯一性。假如基于公式(12)实现Dueling Network,那么 V ( s ) V(s) V(s) A ( s , a ) A(s,a) A(s,a)可以随意上下波动,比如一个增大100,另一个减小100,这样的上下波动不影响最终的输出,如公式(13)所示: V ( s ; w ~ V ) ≜ V ( s ; w V ) + 100 , A ( s , a ; w ~ A ) ≜ A ( s , a ; w A ) − 100 V ( s ; w V ) + A ( s , a ; w A ) = V ( s ; w ~ V ) + A ( s , a ; w ~ A ) (13) \begin{aligned} V\left(s ; \tilde{\boldsymbol{w}}^V\right) & \triangleq V\left(s ; \boldsymbol{w}^V\right)+100, \\ A\left(s, a ; \tilde{\boldsymbol{w}}^A\right) & \triangleq A\left(s, a ; \boldsymbol{w}^A\right)-100 \tag{13}\\ V\left(s ; \boldsymbol{w}^V\right)+A\left(s, a ; \boldsymbol{w}^A\right) & =V\left(s ; \tilde{\boldsymbol{w}}^V\right)+A\left(s, a ; \tilde{\boldsymbol{w}}^A\right) \end{aligned} V(s;w~V)A(s,a;w~A)V(s;wV)+A(s,a;wA)V(s;wV)+100,A(s,a;wA)100=V(s;w~V)+A(s,a;w~A)(13)这意味着 V V V D D D的参数可以很随意的变化却不会影响输出的 Q Q Q,这会导致训练过程中参数的不稳定,这不是我们希望看到的。为了解决这个问题,论文中强制令动作的优势函数的最大值最大只能为0,即对每个动作的优势函数减去最优动作的优势函数值,如公式(14)所示: Q ( s , a ; θ , α , β ) = V ( s ; θ , β ) + ( A ( s , a ; θ , α ) − max ⁡ a ′ ∈ ∣ A ∣ A ( s , a ′ ; θ , α ) ) (14) Q(s, a ; \theta, \alpha, \beta)=V(s ; \theta, \beta)+ \left(A(s, a ; \theta, \alpha)-\max _{a^{\prime} \in|\mathcal{A}|} A\left(s, a^{\prime} ; \theta, \alpha\right)\right) \tag{14} Q(s,a;θ,α,β)=V(s;θ,β)+(A(s,a;θ,α)aAmaxA(s,a;θ,α))(14)在公式(12)的基础上加上 max ⁡ a ′ ∈ ∣ A ∣ A ( s , a ′ ; θ , α ) \max _{a^{\prime} \in|\mathcal{A}|} A\left(s, a^{\prime} ; \theta, \alpha\right) maxaAA(s,a;θ,α)之后,它使得 V V V A A A不能随意上下波动。假如让 V V V变大00,让 A A A变小100,则Dueling Network的输出会增大100,不会再是公式(13)展示的结果,其影响如公式(15)所示: V ( s ; w V ) + A ( s , a ; w A ) − m a x a A ( s , a ; w A ) + 100 = V ( s ; w ~ V ) + A ( s , a ; w ~ A ) − m a x a A ( s , a ; w ~ A ) (15) V\left(s ; \boldsymbol{w}^V\right)+A\left(s, a ; \boldsymbol{w}^A\right) - max_aA(s,a;{\boldsymbol{w}}^{A}) + 100=V\left(s ; \tilde{\boldsymbol{w}}^V\right)+A\left(s, a ; \tilde{\boldsymbol{w}}^A\right) - max_aA(s,a;\tilde{\boldsymbol{w}}^A) \tag{15} V(s;wV)+A(s,a;wA)maxaA(s,a;wA)+100=V(s;w~V)+A(s,a;w~A)maxaA(s,a;w~A)(15)基于当前状态 s s s的最优动作 a ⋆ a^{\star} a的获取如公式(16)所示: a ⋆ = a r g m a x a ′ ∈ A Q ( s , a ′ ; θ , α , β ) = a r g m a x a ′ ∈ A A ( s , a ′ ; θ , α , β ) (16) a^{\star}=arg\space max_{a' \in \mathcal{A}}Q(s,a';\theta,\alpha,\beta)=arg\space max_{a' \in \mathcal{A}}A(s,a';\theta,\alpha,\beta) \tag{16} a=arg maxaAQ(s,a;θ,α,β)=arg maxaAA(s,a;θ,α,β)(16)根据公式(14)和公式(16),可以得到 Q ( s , a ∗ ; θ , α , β ) = V ( s ; θ , β ) Q\left(s, a^* ; \theta, \alpha, \beta\right)=V(s;\theta,\beta) Q(s,a;θ,α,β)=V(s;θ,β)除了使用 m a x max max方法外,论文中提到可以使用期望的方式来求解 Q Q Q动作价值函数,如公式(17)所示: Q ( s , a ; θ , α , β ) = V ( s ; θ , β ) + ( A ( s , a ; θ , α ) − 1 ∣ A ∣ ∑ a ′ A ( s , a ′ ; θ , α ) ) (17) \begin{aligned} & Q(s, a ; \theta, \alpha, \beta)=V(s ; \theta, \beta)+ \left(A(s, a ; \theta, \alpha)-\frac{1}{|\mathcal{A}|} \sum_{a^{\prime}} A\left(s, a^{\prime} ; \theta, \alpha\right)\right) \end{aligned} \tag{17} Q(s,a;θ,α,β)=V(s;θ,β)+(A(s,a;θ,α)A1aA(s,a;θ,α))(17)公式(14)和公式(17)使用了两种不同的方式来展示Dueling Network的工作原理,两个公式分别通过求解最大值或者期望的形式使得Dueling Network训练过程更加稳定(这也使得 V V V A A A失去了其原始语义,因为它们现在偏离目标一个常量)。

    Dueling Network的优势在于其能够有效学习状态值函数 V V V,随着Dueling Network更新 Q Q Q动作价值函数, V V V状态价值函数也会更新,这与传统的DQN或者Double DQN是不相同的,传统的DQN或者Double DQN只更新对应动作的 Q Q Q动作价值函数,其它动作的 Q Q Q并不会更新。在Dueling Network中,更新 V V V可以影响其它动作的 Q Q Q动作价值函数,使得Dueling Network能够有更好的训练效果。

  • 基于gym的Dueling Network代码实现:

    • requirement:

      • python: 3.8
      • gym: 0.17.3
      • tensorflow: 2.9
    • code(代码主要参考书籍【动手学强化学习】(张伟楠,沈键,俞勇),京东购买链接 | 当当购买链接)

    import gym
    import random
    import tf_rl_utils
    import collections
    import numpy as np
    from tqdm import tqdm
    import tensorflow as tf
    import matplotlib.pyplot as pltclass ReplayBuffer:"""经验回放池"""def __init__(self, capacity):self.buffer = collections.deque(maxlen=capacity)  # 队列,先进先出def add(self, state, action, reward, next_state, done):  # 将数据加入bufferself.buffer.append((state, action, reward, next_state, done))def sample(self, batch_size):  # 从buffer中采样数据,数量为batch_sizetransitions = random.sample(self.buffer, batch_size)state, action, reward, next_state, done = zip(*transitions)return np.array(state), action, reward, np.array(next_state), donedef size(self):  # 目前buffer中数据的数量return len(self.buffer)class VAnet(tf.keras.Model):""" 只有一层隐藏层的A网络和V网络 """def __init__(self, hidden_dim, action_dim):super(VAnet, self).__init__()self.fc1 = tf.keras.layers.Dense(hidden_dim, activation=tf.keras.activations.relu)  # 共享网络部分self.fc_A = tf.keras.layers.Dense(action_dim)self.fc_V = tf.keras.layers.Dense(1)def call(self, x):A = self.fc_A(self.fc1(x))V = self.fc_V(self.fc1(x))Q = V + A - tf.reduce_mean(A, axis=1, keepdims=True)  # Q值由V值和A值计算得到return Qclass DQN:def __init__(self, hidden_dim, action_dim, learning_rate, gamma,epsilon, target_update, dqn_type='VanillaDQN'):self.action_dim = action_dimself.q_net = VAnet(hidden_dim, self.action_dim)  # Q网络# 目标网络self.target_q_net = VAnet(hidden_dim, self.action_dim)# 使用Adam优化器self.optimizer = tf.optimizers.Adam(learning_rate=learning_rate)self.gamma = gamma  # 折扣因子self.epsilon = epsilon  # epsilon-贪婪策略self.target_update = target_update  # 目标网络更新频率self.count = 0  # 计数器,记录更新次数self.dqn_type = dqn_typedef take_action(self, state):  # epsilon-贪婪策略采取动作if np.random.random() < self.epsilon:action = np.random.randint(self.action_dim)else:state = tf.cast(tf.expand_dims(state, axis=0), dtype=tf.float32)action = tf.argmax(self.q_net.call(state), axis=1).numpy()[0]return actiondef max_q_value(self, state):state = tf.cast(tf.expand_dims(state, axis=0), dtype=tf.float32)return tf.reduce_max(self.q_net.call(state)).numpy()def update(self, transition_dict):states = tf.cast(transition_dict['states'], dtype=tf.float32)actions = tf.reshape(transition_dict['actions'], shape=(-1))rewards = tf.reshape(tf.cast(transition_dict['rewards'], dtype=tf.float32), shape=(-1, 1))next_states = tf.cast(transition_dict['next_states'], dtype=tf.float32)dones = tf.reshape(tf.cast(transition_dict['dones'], dtype=tf.float32), shape=(-1, 1))with tf.GradientTape() as tape:q_values = tf.gather(self.q_net.call(states), actions, batch_dims=1)  # Q值# 下个状态的最大Q值if self.dqn_type == 'DoubleDQN':  # DQN与Double DQN的区别max_action = tf.argmax(self.q_net.call(next_states), axis=1, output_type=tf.int32)max_next_q_values = tf.reshape(tf.gather(self.target_q_net.call(next_states), max_action, batch_dims=1), shape=(-1,1))  # Q值else:max_next_q_values = tf.reduce_max(self.target_q_net.call(next_states), axis=1, keepdims=True)q_targets = rewards + self.gamma * max_next_q_values * (1 - dones)  # TD误差目标loss_func = tf.keras.losses.MeanSquaredError()dqn_loss = tf.reduce_mean(loss_func(q_values, q_targets))  # 均方误差损失函数grads = tape.gradient(dqn_loss, self.q_net.trainable_variables)self.optimizer.apply_gradients(zip(grads, self.q_net.trainable_variables))if self.count % self.target_update == 0:self.target_q_net.set_weights(self.q_net.get_weights())  # 更新目标网络self.count += 1lr = 1e-2
    num_episodes = 200
    hidden_dim = 128
    gamma = 0.98
    epsilon = 0.01
    target_update = 50
    buffer_size = 5000
    minimal_size = 1000
    batch_size = 64env_name = 'Pendulum-v0'
    env = gym.make(env_name)
    state_dim = env.observation_space.shape[0]
    action_dim = 11  # 将连续动作分成11个离散动作def dis_to_con(discrete_action, env, action_dim):  # 离散动作转回连续的函数action_lowbound = env.action_space.low[0]  # 连续动作的最小值action_upbound = env.action_space.high[0]  # 连续动作的最大值return action_lowbound + (discrete_action / (action_dim - 1)) * (action_upbound - action_lowbound)def train_DQN(agent, env, num_episodes, replay_buffer, minimal_size,batch_size):return_list = []max_q_value_list = []max_q_value = 0for i in range(10):with tqdm(total=int(num_episodes / 10),desc='Iteration %d' % i) as pbar:for i_episode in range(int(num_episodes / 10)):episode_return = 0state = env.reset()done = Falsewhile not done:action = agent.take_action(state)max_q_value = agent.max_q_value(state) * 0.005 + max_q_value * 0.995  # 平滑处理max_q_value_list.append(max_q_value)  # 保存每个状态的最大Q值action_continuous = dis_to_con(action, env,agent.action_dim)next_state, reward, done, _ = env.step([action_continuous])replay_buffer.add(state, action, reward, next_state, done)state = next_stateepisode_return += rewardif replay_buffer.size() > minimal_size:b_s, b_a, b_r, b_ns, b_d = replay_buffer.sample(batch_size)transition_dict = {'states': b_s,'actions': b_a,'next_states': b_ns,'rewards': b_r,'dones': b_d}agent.update(transition_dict)return_list.append(episode_return)if (i_episode + 1) % 10 == 0:pbar.set_postfix({'episode':'%d' % (num_episodes / 10 * i + i_episode + 1),'return':'%.3f' % np.mean(return_list[-10:])})pbar.update(1)return return_list, max_q_value_listrandom.seed(0)
    np.random.seed(0)
    env.seed(0)
    tf.random.set_seed(0)
    replay_buffer = ReplayBuffer(buffer_size)
    agent = DQN(hidden_dim, action_dim, lr, gamma, epsilon, target_update, "DoubleDQN")
    return_list, max_q_value_list = train_DQN(agent, env, num_episodes,replay_buffer, minimal_size,batch_size)episodes_list = list(range(len(return_list)))
    mv_return = tf_rl_utils.moving_average(return_list, 5)
    plt.plot(episodes_list, mv_return)
    plt.xlabel('Episodes')
    plt.ylabel('Returns')
    plt.title('Double DQN on {}'.format(env_name))
    plt.show()
  • result
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/25433.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flowise AI:用于构建LLM流的拖放UI

推荐&#xff1a;使用NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是Flowise AI&#xff1f; Flowise AI是一个开源的UI可视化工具&#xff0c;用于帮助开发LangChain应用程序。在我们详细介绍 Flowise AI 之前&#xff0c;让我们快速定义 LangChain。LangChain是…

MapTR论文笔记

MAPTR: STRUCTURED MODELING AND LEARNING FOR ONLINE VECTORIZED HD MAP CONSTRUCTION 目的 传统高精地图 通过一些离线的基于 SLAM 的方法生成&#xff0c;需要复杂的流程以及高昂的维护费用。基于 bev 分割的建图方法&#xff0c;缺少向量化 实例级的信息&#xff0c;比如…

基于Vue+wangeditor实现富文本编辑

目录 前言分析实现具体解决的问题有具体代码实现如下效果图总结前言 一个网站需要富文本编辑器功能的原因有很多,以下是一些常见的原因: 方便用户编辑内容:富文本编辑器提供了类似于Office Word的编辑功能,使得那些不太懂HTML的用户也能够方便地编辑网站内容。提高用户体验…

从零开始实现一个 mini-Retrofit 框架

前言 本篇文章将采用循序渐进的编码方式&#xff0c;从零开始实现一个Retorift框架&#xff0c;在实现过程中不断提出问题并分析实现&#xff0c;最终开发出一个mini版的Retrofit框架 演示一个使用OkHttp的项目Demo 为了更好的演示框架的实现过程&#xff0c;这里我先创建了一…

Compose应用案例(利用docker compose安装lnmp实例)

目录 Compose应用案例 一、前提配置 &#xff08;一&#xff09;安装docker-ce&#xff08;Linux安装Docker&#xff09; &#xff08;二&#xff09;安装docker-compose 二、安装docker compose部署lnmp &#xff08;一&#xff09;目录结构&#xff1a; &#xff08;二…

SPM(Swift Package Manager)开发及常见事项

SPM怎么使用的不再赘述&#xff0c;其优点是Cocoapods这样的远古产物难以望其项背的&#xff0c;而且最重要的是可二进制化、对xcproj项目无侵入&#xff0c;除了网络之外简直就是为团队开发的项目库依赖最好的管理工具&#xff0c;是时候抛弃繁杂低下的cocoapods了。 一&…

c语言——杨辉三角

//杨辉三角 #include<stdio.h> int main() {int i,j,k,n0,a[10][10];while(n<0||n>13){/*行数不超过13&#xff0c;为了显示规范*/printf("n即输入行数");scanf("%d",&n);}printf("%d行杨辉三角如下&#xff1a;\n",n);for(i1;i…

SpringCloud(29):Nacos简介

1 什么是配置中心 1.1 什么是配置 应用程序在启动和运行的时候往往需要读取一些配置信息&#xff0c;配置基本上伴随着应用程序的整个生命周期&#xff0c;比如&#xff1a;数据库连接参数、启动参数等。 配置主要有以下几个特点&#xff1a; 配置是独立于程序的只读变量 …

IPsec

数据认证 数据认证是指验证数据的真实性、完整性和可信度的过程。它确保数据在传输、存储和处理过程中没有被篡改或损坏&#xff0c;并且数据的来源可信。 数据认证的主要作用包括&#xff1a; 数据完整性保护&#xff1a;通过校验和、哈希算法等方法&#xff0c;检测数据是否…

GoogLeNet卷积神经网络-笔记

GoogLeNet卷积神经网络-笔记 GoogLeNet是2014年ImageNet比赛的冠军&#xff0c; 它的主要特点是网络不仅有深度&#xff0c; 还在横向上具有“宽度”。 由于图像信息在空间尺寸上的巨大差异&#xff0c; 如何选择合适的卷积核来提取特征就显得比较困难了。 空间分布范围更广的…

On Evaluation of Embodied Navigation Agents 论文阅读

论文信息 题目&#xff1a;On Evaluation of Embodied Navigation Agents 作者&#xff1a;Peter Anderson&#xff0c;Angel Chang 来源&#xff1a;arXiv 时间&#xff1a;2018 Abstract 过去两年&#xff0c;导航方面的创造性工作激增。这种创造性的输出产生了大量有时不…

MyBatis快速入门

MyBatis快速入门 MyBatis简介 什么是MyBatis? MyBatis 是一款优秀的持久层框架&#xff0c;用于简化JDBC开发MyBatis本是Apache 的一个开源项目iBatis,2010年这个项目由apache softwarefoundation 迁移到了google code&#xff0c;并且改名为MyBatis 2013年11月迁移到Githu…

如何推导椭圆的参数方程

椭圆基础知识 椭圆定义&#xff1a;椭圆上任意一点到两焦点的距离之和为2a 如何由椭圆定义推出椭圆标准方程呢&#xff1f; 如上图所示。 由定义可得已知条件为 ∣ M C 1 ∣ ∣ M C 2 ∣ 2 a 当 M 落在顶点 P 上时&#xff0c;可得另一已知条件 a 2 − b 2 c 2 当有了已…

unity行为决策树实战详解

一、行为决策树的概念 行为决策树是一种用于游戏AI的决策模型&#xff0c;它将游戏AI的行为分解为一系列的决策节点&#xff0c;并通过节点之间的连接关系来描述游戏AI的行为逻辑。在行为决策树中&#xff0c;每个节点都代表一个行为或决策&#xff0c;例如移动、攻击、逃跑等…

SpringBoot3 整合Prometheus + Grafana

通过Prometheus Grafana对线上应用进行观测、监控、预警… 健康状况【组件状态、存活状态】Health运行指标【cpu、内存、垃圾回收、吞吐量、响应成功率…】Metrics… 1. SpringBoot Actuator 1. 基本使用 1. 场景引入 <dependency><groupId>org.springframew…

Docker Compose 使用方法

目录 前言 安装 Docker Compose Ubuntu 安装与更新 Red Hat 安装与更新 验证是否安装 Docker Compose 创建 docker-compose.yml 文件 创建一个MySQL 与 tomcat 示例 使用Docker Compose启动服务 前言 Docker Compose 是一个工具&#xff0c;旨在帮助定义和 共享多容器…

CADintosh X for mac CAD绘图软件2D CAD 程序 兼容 M1

CADintosh X for Mac是一个功能强大的2D CAD绘图程序&#xff0c;专为Mac用户设计。它由Lemke Software开发&#xff0c;提供了一套丰富的工具和功能&#xff0c;使用户能够轻松创建高质量的技术图纸&#xff0c;平面图和设计。 CADintosh X for Mac具有直观的用户界面&#x…

【架构】Java 系统架构演进的思考

文章目录 1 前言2 单体应用架构3 垂直应用架构4 分布式架构5 SOA 架构6 微服务云架构7 总结 1 前言 随着移动互联的发展&#xff0c;网站、H5、移动端的应用规模也不断扩大&#xff0c;不管是应用的数量还是质量都得到了指数级的提升。开发者的数量与日俱增&#xff0c;应用的…

SpringMVC -- REST风格开发,RESTful快速开发、RESTful注解开发

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaweb 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 REST 一、REST简介1.1REST风格简介 二、RESTful入门案例2.…