深度强化学习(王树森)笔记09

深度强化学习(DRL)

本文是学习笔记,如有侵权,请联系删除。本文在ChatGPT辅助下完成。

参考链接

Deep Reinforcement Learning官方链接:https://github.com/wangshusen/DRL

源代码链接:https://github.com/DeepRLChinese/DeepRL-Chinese

B站视频:【王树森】深度强化学习(DRL)

豆瓣: 深度强化学习

文章目录

  • 深度强化学习(DRL)
  • 带基线的策略梯度方法
    • 策略梯度中的基线
      • 基线 (Baseline)
      • 基线的直观解释
    • 带基线的 REINFORCE 算法
      • 策略网络和价值网络
      • 算法的推导
      • 训练流程
    • Advantage Actor-Critic (A2C)
      • 算法推导
      • 训练流程
      • 用目标网络改进训练
    • 总结
  • 后记

带baseline的策略梯度方法:REINFORCE with baseline和advantage actor-critic (A2C)

带基线的策略梯度方法

上一章推导出策略梯度,并介绍了两种策略梯度方法——REINFORCE 和 actor-critic。
虽然上一章的方法在理论上是正确的,但是在实践中效果并不理想。本章介绍的带基线的策略梯度 (policy gradient with baseline) 可以大幅提升策略梯度方法的表现。使用基线(baseline) 之后,REINFORCE 变成 REINFORCE with baseline, actor-critic 变成 advantage actor-critic (A2C)。

策略梯度中的基线

首先回顾上一章的内容。策略学习通过最大化目标函数 J ( θ ) = E S [ V π ( S ) ] J(\theta)=\mathbb{E}_S[V_\pi(S)] J(θ)=ES[Vπ(S)], 训练出策略网络 π ( a ∣ s ; θ ) \pi(a|s;\theta) π(as;θ)。可以用策略梯度 ∇ θ J ( θ ) \nabla_{\theta}J(\theta) θJ(θ) 来更新参数 θ \theta θ:

θ n e w   ←   θ n o w + β ⋅ ∇ θ   J ( θ n o w ) . \theta_{\mathrm{new}}\:\leftarrow\:\theta_{\mathrm{now}}+\beta\cdot\nabla_{\theta}\:J(\boldsymbol{\theta_{now}}). θnewθnow+βθJ(θnow).

策略梯度定理证明:

∇ θ J ( θ )   =   E S [ E A ∼ π ( ⋅ ∣ S , θ ) [   Q π ( S , A )   ⋅   ∇ θ   ln ⁡ π ( A ∣ S ; θ ) ] ] . ( 8.1 ) \boxed{\quad\nabla_\theta J(\boldsymbol{\theta})~=~\mathbb{E}_S\biggl[\mathbb{E}_{A\sim\pi(\cdot|S,\boldsymbol{\theta})}\biggl[\:Q_\pi(S,A)~\cdot~\nabla_\theta\:\ln\pi(A\mid S;\boldsymbol{\theta})\biggr]\biggr].} \quad{(8.1)} θJ(θ) = ES[EAπ(S,θ)[Qπ(S,A)  θlnπ(AS;θ)]].(8.1)
上一章中,我们对策略梯度 ∇ θ J ( θ ) \nabla_{\theta}J(\theta) θJ(θ) 做近似,推导出 REINFORCE 和 actor-critic; 两种方法区别在于具体如何做近似。

基线 (Baseline)

基于策略梯度公式 (8.1) 得出的 REINFORCE 和 actor-critic 方法效果通常不好。只需对策略梯度公式 (8.1) 做一个微小的改动,就能大幅提升表现:把 b b b 作为动作价值函数 Q π ( S , A ) Q_{\pi}(S,A) Qπ(S,A) 的基线 (baseline), 用 Q π ( S , A ) − b Q_{\pi}(S,A)-b Qπ(S,A)b 替换掉 Q π Q_{\pi} Qπ。设 b b b 是任意的函数,只要不依赖于动作 A A A 就可以,例如 b b b 可以是状态价值函数 V π ( S ) V_\pi(S) Vπ(S)

定理 8.1. 带基线的策略梯度定理

b b b 是任意的函数,但是 b b b 不能依赖于 A A A。把 b b b 作为动作价值函数 Q π ( S , A ) Q_\pi(S,A) Qπ(S,A) 的基线,对策略梯度没有影响:
∇ θ   J ( θ )   =   E S [ E A ∼ π ( ⋅ ∣ S ; θ ) [ (   Q π ( S , A )   −   b )   ⋅   ∇ θ   ln ⁡ π ( A ∣ S ; θ ) ] ] \nabla_{\theta}\:J(\boldsymbol{\theta})\:=\:\mathbb{E}_{S}\bigg[\mathbb{E}_{A\sim\pi(\cdot|S;\boldsymbol{\theta})}\bigg[\bigg(\:Q_{\pi}(S,A)\:-\:{b}\bigg)\:\cdot\:\nabla_{\boldsymbol{\theta}}\:\ln\pi(A|S;\boldsymbol{\theta})\bigg]\bigg]\bigg. θJ(θ)=ES[EAπ(S;θ)[(Qπ(S,A)b)θlnπ(AS;θ)]]

在这里插入图片描述

定理 8.1 说明 b b b 的取值不影响策略梯度的正确性。不论是让 b = 0 b=0 b=0 还是让 b = V π ( S ) b=V_\pi(S) b=Vπ(S) , 对期望的结果毫无影响,期望的结果都会等于 ∇ θ J ( θ ) \nabla_{\theta}J(\theta) θJ(θ)。其原因在于
E S [ E A ∼ π ( ⋅ ∣ S ; θ ) [ b   ⋅   ∇ θ   ln ⁡ π ( A ∣ S ;   θ ) ] ]   =   0. \mathbb{E}_{S}\Big[\mathbb{E}_{A\sim\pi(\cdot|S;\boldsymbol{\theta})}\Big[b\:\cdot\:\nabla_{\boldsymbol{\theta}}\:\ln\pi\big(A|S;\:\boldsymbol{\theta}\big)\Big]\Big]\:=\:0. ES[EAπ(S;θ)[bθlnπ(AS;θ)]]=0.

定理中的策略梯度表示成了期望的形式,我们对期望做蒙特卡洛近似。从环境中观测到一个状态 s s s,然后根据策略网络抽样得到 a ∼ π ( ⋅ ∣ s ; θ ) a\sim\pi(\cdot|s;\boldsymbol{\theta}) aπ(s;θ)。那么策略梯度 ∇ θ J ( θ ) \nabla_\theta J(\theta) θJ(θ) 可以近似为下面的随机梯度:

g b ( s , a ; θ ) = [ Q π ( s , a ) − b ] ⋅ ∇ θ ln ⁡ π ( a ∣ s ; θ ) . \boxed{\quad\boldsymbol{g}_b(s,a;\boldsymbol{\theta})=\left[Q_\pi(s,a)-b\right]\cdot\nabla_\theta\ln\pi(a|s;\boldsymbol{\theta}).} gb(s,a;θ)=[Qπ(s,a)b]θlnπ(as;θ).

不论 b b b 的取值是 0 还是 V π ( s ) V_\pi(s) Vπ(s), 得到的随机梯度 g b ( s , a ; θ ) g_b(s,a;\boldsymbol{\theta}) gb(s,a;θ) 都是 ∇ θ J ( θ ) \nabla_{\boldsymbol{\theta}}J(\boldsymbol{\theta}) θJ(θ) 的无偏估计:

Bias = E S , A [ g b ( S , A ; θ ) ]   −   ∇ θ J ( θ )   =   0. \begin{array}{rcl}{\text{Bias}}&{=}&{\mathbb{E}_{S,A}\left[\boldsymbol{g}_{b}(S,A;\boldsymbol{\theta})\right]\:-\:\nabla_{\theta}J(\boldsymbol{\theta})\:=\:\mathbf{0}.}\\\end{array} Bias=ES,A[gb(S,A;θ)]θJ(θ)=0.

虽然 b b b 的取值对 E S , A [ g b ( S , A ; θ ) ] \mathbb{E}_{S,A}[\boldsymbol{g}_b(S,A;\boldsymbol{\theta})] ES,A[gb(S,A;θ)] 毫无影响,但是 b b b 对随机梯度 g b ( s , a ; θ ) g_b(s,a;\theta) gb(s,a;θ) 是有影响的。用不同的 b b b, 得到的方差

Var   =   E S , A [ ∥ g b ( S , A ;   θ )   −   ∇ θ J ( θ ) ∥ 2 ] \text{Var}\:=\:\mathbb{E}_{S,A}\left[\left\|g_{b}(S,A;\:\theta)\:-\:\nabla_{\theta}J(\boldsymbol{\theta})\right\|^{2}\right] Var=ES,A[gb(S,A;θ)θJ(θ)2]

会有所不同。如果 b b b 很接近 Q π ( s , a ) Q_\pi(s,a) Qπ(s,a) 关于 a a a 的均值,那么方差会比较小。因此, b = V π ( s ) b=V_\pi(s) b=Vπ(s) 是很好的基线。

基线的直观解释

策略梯度公式 (8.1) 期望中的 Q π ( S , A ) ⋅ ∇ θ ln ⁡ π ( A ∣ S ; θ ) Q_\pi(S,A)\cdot\nabla_\theta\ln\pi(A|S;\boldsymbol{\theta}) Qπ(S,A)θlnπ(AS;θ) 的意义是什么呢?以图 8.1中的左图为例。

在这里插入图片描述

给定状态 s t s_t st, 动作空间是 A = { 左,右,上 } A= \{ 左,右,上\} A={左,右,上}, 动作价值函数给每个动作打分:
Q π ( s t , 左 )   =   80 , Q π ( s t , 右 )   =   − 20 , Q π ( s t , 上 )   =   180 , Q_{\pi}(s_{t},\text{左})\:=\:80,\quad Q_{\pi}(s_{t},\text{右})\:=\:-20,\quad Q_{\pi}(s_{t},\text{上})\:=\:180, Qπ(st,)=80,Qπ(st,)=20,Qπ(st,)=180,

这些分值会乘到梯度 ∇ θ ln ⁡ π ( A ∣ S ; θ ) \nabla_{\boldsymbol{\theta}}\ln\pi(A|S;\boldsymbol{\theta}) θlnπ(AS;θ) 上。在做完梯度上升之后,新的策略会倾向于分值高的动作。

  • 动作价值 Q π ( s t , 上 ) = 180 Q_\pi(s_t,上)=180 Qπ(st,)=180 很大,说明基于状态 s t s_t st 选择动作“上”是很好的决策。让梯度 ∇ θ ln ⁡ π ( 上 ∣ s t ; θ ) \nabla_{\theta}\ln\pi(上|s_t;\theta) θlnπ(st;θ) 乘以大的系数 Q π ( s t , 上 ) = 180 Q_{\pi}(s_{t}, 上)=180 Qπ(st,)=180, 那么做梯度上升更新 θ \theta θ 之后,会让 π ( 上 ∣ s t ; θ ) \pi(上|s_t;\theta) π(st;θ) 变大,在状态 s t s_t st 的情况下更倾向于动作“上”。

  • 相反, Q π ( s t , 右 ) = − 20 Q_\pi( s_t, 右) = - 20 Qπ(st,)=20 说明基于状态 s t s_t st 选择动作“右”是糟糕的决策。让梯度 ∇ θ ln ⁡ π ( 右 ∣ s t ; θ ) \nabla_{\boldsymbol{\theta}}\ln \pi(右|s_t; \boldsymbol\theta) θlnπ(st;θ) 乘以负的系数 Q π ( s t , 右 ) = − 20 Q_\pi( s_t, 右) = - 20 Qπ(st,)=20,那么做梯度上升更新 θ \theta θ 之后, 会让 π ( 右 ∣ s t ; θ ) \pi(右|s_t; \boldsymbol\theta) π(st;θ) 变小,在状态 s t s_t st的情况下选择动作“右”的概率更小。

根据上述分析,我们在乎的是动作价值 Q π ( s t , 左 ) Q_\pi( s_t, 左) Qπ(st,) Q π ( s t , 右 ) Q_\pi( s_t, 右) Qπ(st,) Q π ( s t , 上 ) Q_\pi(s_t,上) Qπ(st,) 三者的相对大小,而非绝对大小。如果给三者都减去 b = 60 b=60 b=60,那么三者的相对大小是不变的;动作“上”仍然是最好的,动作“右”仍然是最差的。见图 8.1 中的右图。因此

[ Q π ( s t , a t ) − b ] ⋅ ∇ θ ln ⁡ π ( A   ∣   S ;   θ ) \begin{bmatrix}Q_\pi(s_t,a_t)-b\end{bmatrix}\cdot\nabla_{\boldsymbol{\theta}}\ln\pi(A\:|\:S;\:\boldsymbol{\theta}) [Qπ(st,at)b]θlnπ(AS;θ)

依然能指导 θ \theta θ做调整,使得 π ( 上 ∣ s t ; θ ) \pi(上|s_t;\theta) π(st;θ)变大,而 π ( 右 ∣ s t ; θ ) \pi(右|s_t;\theta) π(st;θ)变小。

带基线的 REINFORCE 算法

上一节推导出了带基线的策略梯度,并且对策略梯度做了蒙特卡洛近似。本节中,我们使用状态价值 V π ( s ) V_{\pi}(s) Vπ(s) 作基线,得到策略梯度的一个无偏估计:

g ( s , a ; θ ) = [ Q π ( s , a ) − V π ( s ) ] ⋅ ∇ θ ln ⁡ π ( a ∣ s ; θ ) . \boxed{\boldsymbol{g}(s,a;\boldsymbol{\theta})=\left[Q_{\pi}(s,a)-V_{\pi}(s)\right]\cdot\nabla_{\boldsymbol{\theta}}\ln\pi(a|s;\boldsymbol{\theta}).} g(s,a;θ)=[Qπ(s,a)Vπ(s)]θlnπ(as;θ).

我们在深度强化学习(王树森)笔记03: 主要介绍policy network, policy gradient,REINFORCE 中学过 REINFORCE, 它使用实际观测的回报 u u u 来代替动作价值 Q π ( s , a ) Q_\pi(s,a) Qπ(s,a)。 此处我们同样用 u u u 代替 Q π ( s , a ) Q_\pi(s,a) Qπ(s,a)。此外,我们还用一个神经网络 v ( s ; w ) v(s;\boldsymbol{w}) v(s;w) 近似状态价值函数 V π ( s ) V_{\pi}(s) Vπ(s)。这样一来, g ( s , a ; θ ) g(s,a;\theta) g(s,a;θ) 就被近似成了:

g ~ ( s , a ; θ ) = [ u − v ( s ; w ) ] ⋅ ∇ θ ln ⁡ π ( a ∣ s ; θ ) . \boxed{\quad\tilde{\boldsymbol{g}}(s,a;\boldsymbol{\theta})=\left[u-v(s;\boldsymbol{w})\right]\cdot\nabla_\theta\ln\pi(a|s;\boldsymbol{\theta}).} g~(s,a;θ)=[uv(s;w)]θlnπ(as;θ).

可以用 g ~ ( s , a ; θ ) \tilde{g}(s,a;\boldsymbol{\theta}) g~(s,a;θ) 作为策略梯度 ∇ θ J ( θ ) \nabla_{\theta}J(\theta) θJ(θ) 的近似,更新策略网络参数:

θ   ←   θ   +   β ⋅ g ~ ( s , a ;   θ ) \theta\:\leftarrow\:\theta\:+\:\beta\cdot\tilde{\boldsymbol{g}}(s,a;\:\boldsymbol{\theta}) θθ+βg~(s,a;θ)

策略网络和价值网络

带基线的 REINFORCE 需要两个神经网络:策略网络 π ( a ∣ s ; θ ) \pi(a|s;\theta) π(as;θ) 和价值网络 v ( s ; w ) v(s;\boldsymbol{w}) v(s;w) ;
神经网络结构如图 8.2 和 8.3 所示。策略网络与之前章节一样:输入是状态 s s s, 输出是一个向量,每个元素表示一个动作的概率。

在这里插入图片描述

此处的价值网络 v ( s ; w ) v(s;\boldsymbol{w}) v(s;w) 与之前使用的价值网络 q ( s , a ; w ) q(s,a;\boldsymbol{w}) q(s,a;w) 区别较大。此处的 v ( s ; w ) v(s;\boldsymbol{w}) v(s;w) 是对状态价值 V π V_\mathrm{\pi} Vπ的近似,而非对动作价值 Q π Q_\mathrm{\pi} Qπ 的近似。 v ( s ; w ) v(s;\boldsymbol{w}) v(s;w) 的输入是状态 s s s, 输出是一个实数,作为基线。策略网络和价值网络的输入都是状态 s s s,因此可以让两个神经网络共享卷积网络的参数,这是编程实现中常用的技巧。

虽然带基线的 REINFOKCE 有一个策略网络和一个价值网络,但是这种方法不是actor-critic。价值网络没有起到“评委”的作用,只是作为基线而已,目的在于降低方差,加速收敛。真正帮助策略网络(演员)改进参数 θ \theta θ(演员的演技)的不是价值网络,而是实际观测到的回报 u u u

算法的推导

训练策略网络的方法是近似的策略梯度上升。从 t t t 时刻开始,智能体完成一局游戏,观测到全部奖励 r t , r t + 1 , ⋯   , r n r_t,r_{t+1},\cdots,r_n rt,rt+1,,rn,然后计算回报 u t = ∑ k = t n γ k − t ⋅ r k u_t=\sum_{k=t}^n\gamma^{k-t}\cdot r_k ut=k=tnγktrk。让价值网络做出预测 v ^ t = v ( s t ; w ) \widehat{v}_t=v(s_t;\boldsymbol{w}) v t=v(st;w), 作为基线。这样就得到了带基线的策略梯度:
g ~ ( s t , a t ;   θ )   =   (   u t − v ^ t )   ⋅   ∇ θ   ln ⁡ π ( a t ∣   s t ;   θ ) . \tilde{\boldsymbol{g}}\big(s_{t},a_{t};\:\boldsymbol{\theta}\big)\:=\:\big(\:u_{t}-\widehat{v}_{t}\big)\:\cdot\:\nabla_{\boldsymbol{\theta}}\:\ln\pi\big(a_{t}\big|\:s_{t};\:\boldsymbol{\theta}\big). g~(st,at;θ)=(utv t)θlnπ(at st;θ).

它是策略梯度 ∇ θ J ( θ ) \nabla_{\theta}J(\theta) θJ(θ) 的近似。最后做梯度上升更新 θ : \theta: θ:

θ   ←   θ + β ⋅ g ~ ( s t , a t ;   θ ) . \theta\:\leftarrow\:\theta+\beta\cdot\tilde{\boldsymbol{g}}(s_{t},a_{t};\:\theta). θθ+βg~(st,at;θ).

这样可以让目标函数 J ( θ ) J(\boldsymbol{\theta}) J(θ) 逐渐增大。

训练价值网络的方法是回归 (regression)。回忆一下,状态价值是回报的期望:

V π ( s t ) = E [ U t ∣ S t = s t ] , V_\pi(s_t)=\mathbb{E}[U_t|S_t=s_t], Vπ(st)=E[UtSt=st],

期望消掉了动作 A t , A t + 1 , ⋯   , A n A_t,A_{t+1},\cdots,A_n At,At+1,,An 和状态 S t + 1 , ⋯   , S n S_{t+1},\cdots,S_n St+1,,Sn。训练价值网络的目的是让 v ( s t ; w ) v(s_t;\boldsymbol{w}) v(st;w) 拟合 V π ( s t ) V_\pi(s_t) Vπ(st),即拟合 u t u_t ut 的期望。定义损失函数:

L ( w )   =   1 2 n ∑ t = 1 n [ v ( s t ; w )   −   u t ] 2 . L(\boldsymbol{w})\:=\:\frac{1}{2n}\sum_{t=1}^{n}\big[v(s_{t};\boldsymbol{w})\:-\:u_{t}\big]^{2}. L(w)=2n1t=1n[v(st;w)ut]2.

v ^ t = v ( s t ; w ) \widehat{v}_t=v(s_t;w) v t=v(st;w)。损失函数的梯度是:

∇ w L ( w )   =   1 n ∑ t = 1 n ( v ^ t − u t )   ⋅   ∇ w v ( s t ; w ) . \nabla_{\boldsymbol{w}}L(\boldsymbol{w})\:=\:\frac{1}{n}\sum_{t=1}^{n}\left(\widehat{v}_{t}-u_{t}\right)\:\cdot\:\nabla_{\boldsymbol{w}}v(s_{t};\boldsymbol{w}). wL(w)=n1t=1n(v tut)wv(st;w).

做一次梯度下降更新 w w w:

w   ←   w   −   α ⋅ ∇ w L ( w ) . w\:\leftarrow\:w\:-\:\alpha\cdot\nabla_{\boldsymbol{w}}L(\boldsymbol{w}). wwαwL(w).

训练流程

当前策略网络的参数是 θ n o w \theta_\mathrm{now} θnow,价值网络的参数是 w n o w w_\mathrm{now} wnow。执行下面的步骤,对参数做一轮更新。

  1. 用策略网络 θ n o w \theta_\mathrm{now} θnow 控制智能体从头开始玩一局游戏,得到一条轨迹 (trajectory):

s 1 , a 1 , r 1 , s 2 , a 2 , r 2 , ⋯   , s n , a n , r n . s_{1},a_{1},r_{1},\quad s_{2},a_{2},r_{2},\quad\cdots,\quad s_{n},a_{n},r_{n}. s1,a1,r1,s2,a2,r2,,sn,an,rn.

  1. 计算所有的回报:

u t   =   ∑ k = t n γ k − t ⋅ r k , ∀   t = 1 , ⋯   , n . u_{t}\:=\:\sum_{k=t}^{n}\gamma^{k-t}\cdot r_{k},\quad\forall\:t=1,\cdots,n. ut=k=tnγktrk,t=1,,n.

  1. 让价值网络做预测:
    v ^ t   =   v ( s t ; w n o w ) , ∀   t = 1 , ⋯   , n . \widehat v_{t}\:=\:v(s_{t};\boldsymbol{w_{\mathrm{now}}}),\quad\forall\:t=1,\cdots,n. v t=v(st;wnow),t=1,,n.

  2. 计算误差 δ t = v t ^ − u t ,   ∀ t = 1 , ⋯   , n \delta_t=\widehat{v_t}-u_t,\:\forall t=1,\cdots,n δt=vt ut,t=1,,n

  3. { s t } t = 1 n \{s_t\}_{t=1}^n {st}t=1n 作为价值网络输入,做反向传播计算:
    ∇ w   v ( s t ;   w n o w ) , ∀   t = 1 , ⋯   , n . \nabla_{\boldsymbol{w}}\:v\big(s_{t};\:\boldsymbol{w}_{\mathrm{now}}\big),\quad\forall\:t=1,\cdots,n. wv(st;wnow),t=1,,n.

  4. 更新价值网络参数:
    w n e w   ←   w n o w   −   α ⋅ ∑ t = 1 n δ t ⋅ ∇ w   v ( s t ;   w n o w ) . w_{\mathrm{new}}\:\leftarrow\:w_{\mathrm{now}}\:-\:\alpha\cdot\sum_{t=1}^{n}\delta_{t}\cdot\nabla_{\boldsymbol{w}}\:v\big(s_{t};\:\boldsymbol{w_{\mathrm{now}}}\big). wnewwnowαt=1nδtwv(st;wnow).

  5. { ( s t , a t ) } t = 1 n \{(s_t,a_t)\}_{t=1}^n {(st,at)}t=1n 作为数据,做反向传播计算:

∇ θ ln ⁡ π ( a t   ∣   s t ;   θ n o w ) , ∀   t = 1 , ⋯   , n . \nabla_{\boldsymbol{\theta}}\ln\pi(a_{t}\:|\:s_{t};\:\boldsymbol{\theta}_{\mathrm{now}}),\quad\forall\:t=1,\cdots,n. θlnπ(atst;θnow),t=1,,n.
8. 做随机梯度上升更新策略网络参数:

θ n e w   ←   θ n o w   −   β   ⋅   ∑ t = 1 n γ t − 1   ⋅   δ t   ⋅   ∇ θ ln ⁡ π ( a t   ∣   s t ;   θ n o w ) ⏟ 负的近似梯度  − g ~ ( s t , a t ; θ n o w )   . \theta_{\mathrm{new}}\:\leftarrow\:\theta_{\mathrm{now}}\:-\:\beta\:\cdot\:\sum_{t=1}^{n}\gamma^{t-1}\:\cdot\:\underbrace{\delta_{t}\:\cdot\:\nabla_{\theta}\ln\pi(a_{t}\:\big|\:s_{t};\:\theta_{\mathrm{now}}\big)}_{\text{负的近似梯度 }-\tilde{g}(s_{t},a_{t};\boldsymbol{\theta_{\mathrm{now}}})}\:. θnewθnowβt=1nγt1负的近似梯度 g~(st,at;θnow) δtθlnπ(at st;θnow).

Advantage Actor-Critic (A2C)

之前我们推导出了带基线的策略梯度,并且对策略梯度做了蒙特卡洛近似,得到策略梯度的一个无偏估计:

g ( s , a ; θ ) = [ Q π ( s , a ) − V π ( s ) ⏟ 优势函数 ] ⋅ ∇ θ ln ⁡ π ( a ∣ s ; θ ) . ( 8.2 ) \boldsymbol{g}(s,a;\boldsymbol{\theta})=\left[\underbrace{Q_{\pi}(s,a)-V_{\pi}(s)}_{\text{优势函数}}\right]\cdot\nabla_{\boldsymbol{\theta}}\ln\pi(a|s;\boldsymbol{\theta}).\quad{(8.2)} g(s,a;θ)= 优势函数 Qπ(s,a)Vπ(s) θlnπ(as;θ).(8.2)

公式中的 Q π − V π Q_\pi-V_\pi QπVπ 被称作优势函数 (advantage function)。因此,基于上面公式得到的actor-critic 方法被称为 advantage actor-critic, 缩写 A2C。

A2C 属于 actor-critic 方法。有一个策略网络 π ( a ∣ s ; θ ) \pi(a|s;\theta) π(as;θ),相当于演员,用于控制智能体运动。还有一个价值网络 v ( s ; w ) v(s;w) v(s;w),相当于评委,他的评分可以帮助策略网络 (演员) 改进技术。两个神经网络的结构与上一节中的完全相同,但是本节和上一节用不同的方法训练两个神经网络。

算法推导

训练价值网络:训练价值网络 v ( s ; w ) v(s;w) v(s;w) 的算法是从贝尔曼公式来的:
V π ( s t )   =   E A t ∼ π ( ⋅ ∣ s t ; θ ) [ E S t + 1 ∼ p ( ⋅ ∣ s t , A t ) [ R t   +   γ ⋅ V π ( S t + 1 ) ] ] . V_{\pi}(s_{t})\:=\:\mathbb{E}_{A_{t}\sim\pi(\cdot|s_{t};\theta)}\Big[\mathbb{E}_{S_{t+1}\sim p(\cdot|s_{t},A_{t})}\Big[R_{t}\:+\:\gamma\cdot V_{\pi}\big(S_{t+1}\big)\Big]\Big]. Vπ(st)=EAtπ(st;θ)[ESt+1p(st,At)[Rt+γVπ(St+1)]].

我们对贝尔曼方程左右两边做近似:

  • 方程左边的 V π ( s t ) V_\pi(s_t) Vπ(st)可以近似成 v ( s t ; w ) v(s_t;\boldsymbol{w}) v(st;w) v ( s t ; w ) v(s_t;\boldsymbol{w}) v(st;w) 是价值网络在 t t t 时刻对 V π ( s t ) V_\pi(s_t) Vπ(st) 做出的估计。
  • 方程右边的期望是关于当前时刻动作 A t A_t At 与下一时刻状态 S t + 1 S_{t+1} St+1 求的。给定当前状态 s t s_t st,智能体执行动作 a t a_t at,环境会给出奖励 r t r_t rt 和新的状态 s t + 1 s_{t+1} st+1。用观测到的 r t r_t rt s t + 1 s_{t+1} st+1 对期望做蒙特卡洛近似,得到:

r t + γ ⋅ V π ( s t + 1 ) . ( 8.3 ) r_{t}+\gamma\cdot V_{\pi}(s_{t+1}). \quad(8.3) rt+γVπ(st+1).(8.3)

  • 进一步把公式 (8.3) 中的 V π ( s t + 1 ) V_{\pi}(s_{t+1}) Vπ(st+1) 近似成 v ( s t + 1 ; w ) v(s_{t+1};\boldsymbol{w}) v(st+1;w), 得到

y ^ t ≜ r t + γ ⋅ v ( s t + 1 ; w ) . \boxed{\widehat{y}_{t}\triangleq r_{t}+\gamma\cdot v(s_{t+1};\boldsymbol{w}).} y trt+γv(st+1;w).

​ 把它称作 TD 目标。它是价值网络在 t + 1 t+1 t+1 时刻对 V π ( s t ) V_{\pi}(s_t) Vπ(st) 做出的估计。

v ( s t ; w ) v(s_t;\boldsymbol{w}) v(st;w) y ^ t \widehat{y}_t y t 都是对动作价值 V π ( s t ) V_{\pi}(s_t) Vπ(st) 的估计。由于 y ^ t \widehat{y}_t y t 部分基于真实观测到的奖励 r t r_t rt,我们认为 y ^ t \widehat{y}_t y t v ( s t ; w ) v(s_t;w) v(st;w) 更可靠。所以把 y ^ t \widehat{y}_t y t 固定住,更新 w w w, 使得 v ( s t ; w ) v(s_t;\boldsymbol{w}) v(st;w) 更接近 y ^ t \widehat{y}_t y t

具体这样更新价值网络参数 w w w。定义损失函数

L ( w )   ≜   1 2 [ v ( s t ; w )   −   y ^ t ] 2 . L(\boldsymbol{w})\:\triangleq\:\frac{1}{2}\Big[v(s_{t};\boldsymbol{w})\:-\:\widehat{y}_{t}\Big]^{2}. L(w)21[v(st;w)y t]2.

v ^ t ≜ v ( s t ; w ) \widehat{v}_t\triangleq v(s_t;w) v tv(st;w)。损失函数的梯度是:

∇ w L ( w )   =   ( v ^ t − y ^ t ) ⏟ T D   误差  δ t ⋅ ∇ w   v ( s t ; w ) . \nabla_{\boldsymbol{w}}L\big(\boldsymbol{w}\big)\:=\:\underbrace{\left(\widehat{v}_{t}-\widehat{y}_{t}\right)}_{\mathrm{TD~}\text{误差 }\delta_{t}}\cdot\nabla_{\boldsymbol{w}}\:v\big(s_{t};\boldsymbol{w}\big). wL(w)=TD 误差 δt (v ty t)wv(st;w).
定义 TD 误差为 δ t ≜ v ^ t − y ^ t \delta_t\triangleq\widehat{v}_t-\widehat{y}_t δtv ty t。做一轮梯度下降更新 w : w: w:

w   ←   w   −   α ⋅ δ t   ⋅   ∇ w   v ( s t ; w ) . \boxed{\boldsymbol{w}\:\leftarrow\:\boldsymbol{w}\:-\:\alpha\cdot\delta_{t}\:\cdot\:\nabla_{\boldsymbol{w}}\:v(s_{t};\boldsymbol{w}).} wwαδtwv(st;w).

这样可以让价值网络的预测 v ( s t ; w ) v(s_t;\boldsymbol{w}) v(st;w) 更接近 y ^ t \widehat{y}_t y t

训练策略网络:A2C 从公式 (8.2)出发,对 g ( s , a ; θ ) g(s,a;\theta) g(s,a;θ) 做近似,记作 g ~ \tilde{g} g~, 然后用 g ~ \tilde{g} g~ 更新策略网络参数 θ \theta θ。下面我们做数学推导。回忆一下贝尔曼公式:
Q π ( s t , a t )   =   E S t + 1 ∼ p ( ⋅ ∣ s t , a t ) [   R t   +   γ ⋅ V π ( S t + 1 )   ] . Q_{\pi}\big(s_{t},a_{t}\big)\:=\:\mathbb{E}_{S_{t+1}\sim p(\cdot|s_{t},a_{t}\big)}\Big[\:R_{t}\:+\:\gamma\cdot V_{\pi}\big(S_{t+1}\big)\:\Big]. Qπ(st,at)=ESt+1p(st,at)[Rt+γVπ(St+1)].
把近似策略梯度 g ( s t , u t ; θ ) g(s_t,u_t;\boldsymbol{\theta}) g(st,ut;θ) 中的 Q π ( s t , a t ) Q_\pi(s_t,a_t) Qπ(st,at) 替换成上面的期望,得到:

g ( s t , a t ; θ ) = [ Q π ( s t , a t ) − V π ( s t ) ] ⋅ ∇ θ ln ⁡ π ( a t ∣ s t ; θ ) = [ E S t + 1 [ R t + γ ⋅ V π ( S t + 1 ) ] − V π ( s t ) ] ⋅ ∇ θ ln ⁡ π ( a t ∣ s t ; θ ) . \begin{aligned} \boldsymbol{g}(s_{t},a_{t};\boldsymbol{\theta})& =\left[Q_{\pi}\left(s_{t},a_{t}\right)-V_{\pi}\big(s_{t}\big)\right]\cdot\nabla_{\boldsymbol{\theta}}\ln\pi(a_{t}|s_{t};\boldsymbol{\theta}) \\ &\begin{array}{rcl}{=}&{{}\left[\mathbb{E}_{S_{t+1}}\right[R_{t}+\gamma\cdot V_{\pi}\big(S_{t+1}\big)]-V_{\pi}\big(s_{t}\big)]\cdot\nabla_{\theta}\ln\pi\big(a_{t}\big|s_{t};\theta\big).}\end{array} \end{aligned} g(st,at;θ)=[Qπ(st,at)Vπ(st)]θlnπ(atst;θ)=[ESt+1[Rt+γVπ(St+1)]Vπ(st)]θlnπ(at st;θ).

当智能体执行动作 a t a_t at 之后,环境给出新的状态 s t + 1 s_{t+1} st+1 和奖励 r t r_t rt; 利用 s t + 1 s_{t+1} st+1 r t r_t rt 对上面的期望做蒙特卡洛近似,得到:
g ( s t , a t ;   θ ) ≈ [   r t   +   γ ⋅ V π ( s t + 1 )   −   V π ( s t )   ]   ⋅   ∇ θ   ln ⁡ π ( a t   ∣   s t ;   θ ) . \begin{array}{rcl}g(s_t,a_t;\:\theta)&\approx&\Big[\:r_t\:+\:\gamma\cdot V_\pi\big(s_{t+1}\big)\:-\:V_\pi\big(s_t\big)\:\Big]\:\cdot\:\nabla_\theta\:\ln\pi\big(a_t\:\big|\:s_t;\:\theta\big).\end{array} g(st,at;θ)[rt+γVπ(st+1)Vπ(st)]θlnπ(at st;θ).

进一步把状态价值函数 V π ( s ) V_{\pi}(s) Vπ(s) 替换成价值网络 v ( s ; w ) v(s;w) v(s;w), 得到:

g ~ ( s t , a t ; θ ) ≜ [ r t   +   γ ⋅ v ( s t + 1 ; w ) ⏟ TD 目标  y ^ t − v ( s t ; w )   ]   ⋅   ∇ θ ln ⁡ π ( a t   ∣   s t ; θ ) . \begin{array}{rcl}\tilde{\boldsymbol{g}}(s_t,a_t;\boldsymbol{\theta})&\triangleq&\Big[\underbrace{r_t\:+\:\gamma\cdot v(s_{t+1};\boldsymbol{w})}_{\text{TD 目标 }\widehat{y}_t}-v(s_t;\boldsymbol{w})\:\Big]\:\cdot\:\nabla_{\boldsymbol{\theta}}\ln\pi(a_t\:|\:s_t;\boldsymbol{\theta}).\end{array} g~(st,at;θ)[TD 目标 y t rt+γv(st+1;w)v(st;w)]θlnπ(atst;θ).
前面定义了 TD 目标和 TD 误差:

y ^ t   ≜   r t   +   γ ⋅ v ( s t + 1 ;   w ) 和 δ t   ≜   v ( s t ;   w )   −   y ^ t . \widehat{y}_{t}\:\triangleq\:r_{t}\:+\:\gamma\cdot v(s_{t+1};\:\boldsymbol{w})\quad\text{和}\quad\delta_{t}\:\triangleq\:v(s_{t};\:\boldsymbol{w})\:-\:\widehat{y}_{t}. y trt+γv(st+1;w)δtv(st;w)y t.
因此,可以把 g ~ \tilde{g} g~写成:

g ~ ( s t , a t ; θ ) ≜ − δ t ⋅ ∇ θ ln ⁡ π ( a t ∣ s t ; θ ) . \boxed{\tilde{\boldsymbol{g}}(s_t,a_t;\boldsymbol{\theta})\triangleq-\delta_t\cdot\nabla_{\boldsymbol{\theta}}\ln\pi(a_t|s_t;\boldsymbol{\theta}).} g~(st,at;θ)δtθlnπ(atst;θ).

g ~ \tilde{g} g~ g g g 的近似,所以也是策略梯度 ∇ θ J ( θ ) \nabla_{\theta}J(\theta) θJ(θ) 的近似。用 g ~ \tilde{g} g~ 更新策略网络参数 θ \theta θ:
θ   ←   θ   +   β ⋅ g ~ ( s t , a t ;   θ ) . \theta\:\leftarrow\:\theta\:+\:\beta\cdot\tilde{\boldsymbol{g}}\left(s_t,a_t;\:\boldsymbol{\theta}\right). θθ+βg~(st,at;θ).

这样可以让目标函数 J ( θ ) J(\theta) J(θ) 变大。

策略网络与价值网络的关系 : A2C 中策略网络 (演员) 和价值网络 (评委) 的关系如图 8.4 所示。

在这里插入图片描述

智能体由策略网络 π 控制,与环境交互,并收集状态、动作、奖励。策略网络(演员) 基于状态 s t s_t st 做出动作 a t a_t at。价值网络 (评委) 基于 s t s_t st s t + 1 s_{t+1} st+1 r t r_t rt 算出 TD 误差 δ t \delta_t δt。策略网络(演员) 依靠 δ t \delta_t δt 来判断自己动作的好坏,从而改进自己的演技 (即参数 θ \theta θ)。

读者可能会有疑问: 价值网络 v v v 只知道两个状态 s t s_t st s t + 1 s_{t+1} st+1,而并不知道动作 a t a_t at,那么价值网络为什么能评价 a t a_t at 的好坏呢?价值网络 v v v 告诉策略网络 π \pi π 的唯一信息是 δ t \delta_{t} δt。回顾一下 δ t \delta_t δt 的定义:
− δ t = r t   +   γ ⋅ v ( s t + 1 ;   w ) ⏟ TD 目标   y ^ t   −   v ( s t ;   w ) ⏟ 基线 . \begin{array}{rcl}-\delta_t&=&\underbrace{r_t\:+\:\gamma\cdot v(s_{t+1};\:\boldsymbol{w})}_{\text{TD 目标}\:\widehat{y}_t}\:-\:\underbrace{v(s_t;\:\boldsymbol{w})}_\text{基线}.\end{array} δt=TD 目标y t rt+γv(st+1;w)基线 v(st;w).

基线 v ( s t ; w ) v(s_t;\boldsymbol{w}) v(st;w) 是价值网络在 t t t 时刻对 E [ U t ] \mathbb{E}[U_t] E[Ut] 的估计;此时智能体尚未执行动作 a t a_t at。而 TD 目标 y ^ t \widehat{y}_t y t 是价值网络在 t + 1 t+1 t+1 时刻对 E [ U t ] \mathbb{E}[U_t] E[Ut] 的估计;此时智能体已经执行动作 a t a_t at

  • 如果 y ^ t > v ( s t ; w ) \widehat{y}_t>v(s_t;\boldsymbol{w}) y t>v(st;w),说明动作 a t a_t at 很好,使得奖励 r t r_t rt 超出预期,或者新的状态 s t + 1 s_{t+1} st+1 比预期好;这种情况下应该更新 θ \theta θ,使得 π ( a t ∣ s t ; θ ) \pi(a_t|s_t;\theta) π(atst;θ) 变大。
  • 如果 y ^ t < v ( s t ; w ) \widehat{y}_t<v(s_t;\boldsymbol{w}) y t<v(st;w),说明动作 a t a_t at 不好,导致奖励 r t r_t rt不及预期,或者新的状态 s t + 1 s_{t+1} st+1比预期差;这种情况下应该更新 θ \theta θ,使得 π ( a t ∣ s t ; θ ) \pi(a_t|s_t;\theta) π(atst;θ) 减小。

综上所述, δ t \delta_t δt 中虽然不包含动作 a t a_t at,但是 δ t \delta_t δt 可以间接反映出动作 a t a_t at 的好坏,可以帮助策略网络(演员) 改进演技。

训练流程

下面概括 A2C 训练流程。设当前策略网络参数是 θ n o w \theta_\mathrm{now} θnow,价值网络参数是 w n o w w_\mathrm{now} wnow。执行下面的步骤,将参数更新成 θ n e w \theta_\mathrm{new} θnew w n e w w_\mathrm{new} wnew:

  1. 观测到当前状态 s t s_t st,根据策略网络做决策 : a t ∼ π ( ⋅ ∣ s t ; θ n o w ) :a_t\sim\pi(\cdot|s_t;\theta_\mathrm{now}) :atπ(st;θnow),并让智能体执行动作 a t a_t at

  2. 从环境中观测到奖励 r t r_t rt 和新的状态 s t + 1 s_{t+1} st+1

  3. 让价值网络打分:

v t ^   =   v ( s t ;   w n o w ) 和 v ^ t + 1   =   v ( s t + 1 ;   w n o w ) \widehat{v_{t}}\:=\:v\big(s_{t};\:\boldsymbol{w_{\mathrm{now}}}\big)\quad\text{和}\quad\widehat{v}_{t+1}\:=\:v\big(s_{t+1};\:\boldsymbol{w_{\mathrm{now}}}\big) vt =v(st;wnow)v t+1=v(st+1;wnow)

  1. 计算 TD 目标和 TD 误差:

y t ^   =   r t + γ ⋅ v ^ t + 1 和 δ t   =   v ^ t − y ^ t . \widehat{y_{t}}\:=\:r_{t}+\gamma\cdot\widehat{v}_{t+1}\quad\text{和}\quad\delta_{t}\:=\:\widehat{v}_{t}-\widehat{y}_{t}. yt =rt+γv t+1δt=v ty t.

  1. 更新价值网络:

w n e w   ←   w n o w   −   α ⋅ δ t ⋅ ∇ w v ( s t ;   w n o w ) . w_{\mathrm{new}}\:\leftarrow\:w_{\mathrm{now}}\:-\:\alpha\cdot\delta_{t}\cdot\nabla_{\boldsymbol{w}}v\left(s_{t};\:\boldsymbol{w_{\mathrm{now}}}\right). wnewwnowαδtwv(st;wnow).

  1. 更新策略网络:

θ n e w   ←   θ n o w   −   β ⋅ δ t ⋅ ∇ θ ln ⁡ π ( a t   ∣   s t ;   θ n o w ) . \theta_{\mathrm{new}}\:\leftarrow\:\theta_{\mathrm{now}}\:-\:\beta\cdot\delta_{t}\cdot\nabla_{\boldsymbol{\theta}}\ln\pi(a_{t}\:|\:s_{t};\:\boldsymbol{\theta}_{\mathrm{now}}). θnewθnowβδtθlnπ(atst;θnow).

注 此处训练策略网络和价值网络的方法属于同策略(on-policy),要求行为策略(behavion policy)与目标策略 (target policy) 相同,都是最新的策略网络 π ( a ∣ s ; θ n o w ) \pi(a|s;\theta_\mathrm{now}) π(as;θnow)。不能使用经验回放,因为经验回放数组中的数据是用旧的策略网络 π ( a ∣ s ; θ o l d ) \pi(a|s;\theta_\mathrm{old}) π(as;θold) 获取的,不能在当前重复利用。

用目标网络改进训练

上述训练价值网络的算法存在自举——即用价值网络自己的估值 v ^ t + 1 \widehat{v}_{t+1} v t+1去更新价值网络自己。为了缓解自举造成的偏差,可以使用目标网络(target network) 计算 TD 目标。把目标网络记作 v ( s ; w − ) v(s;w^-) v(s;w), 它的结构与价值网络的结构相同,但是参数不同。使用目标网络计算 TD 目标,那么 A2C 的训练就变成了:

  1. 观测到当前状态 s t s_t st,根据策略网络做决策 : a t ∼ π ( ⋅ ∣ s t ; θ n o w ) :a_t\sim\pi(\cdot|s_t;\theta_\mathrm{now}) :atπ(st;θnow), 并让智能体执行动作 a t a_t at
  2. 从环境中观测到奖励 r t r_t rt 和新的状态 s t + 1 s_{t+1} st+1
  3. 让价值网络给 s t s_t st 打分:

v t ^   =   v ( s t ;   w n o w ) . \widehat{v_{t}}\:=\:v\big(s_{t};\:\boldsymbol{w_{\mathrm{now}}}\big). vt =v(st;wnow).

  1. 让目标网络给 s t + 1 s_{t+1} st+1 打分:

v ^ t + 1 −   =   v ( s t + 1 ;   w n o w − ) . \widehat v_{t+1}^{-}\:=\:v\big(s_{t+1};\:\boldsymbol{w_{\mathrm{now}}^{-}}\big). v t+1=v(st+1;wnow).

  1. 计算 TD 目标和 TD 误差:

y ^ t −   =   r t + γ ⋅ v ^ t + 1 − 和 δ t   =   v ^ t − y ^ t − . \widehat{y}_{t}^{-}\:=\:r_{t}+\gamma\cdot\widehat{v}_{t+1}^{-}\quad\text{和}\quad\delta_{t}\:=\:\widehat{v}_{t}-\widehat{y}_{t}^{-}. y t=rt+γv t+1δt=v ty t.

  1. 更新价值网络:

w n e w   ←   w n o w − α ⋅ δ t ⋅ ∇ w v ( s t ;   w n o w ) . w_{\mathrm{new}}\:\leftarrow\:w_{\mathrm{now}}-\alpha\cdot\delta_{t}\cdot\nabla_{\boldsymbol{w}}v\big(s_{t};\:\boldsymbol{w}_{\mathrm{now}}\big). wnewwnowαδtwv(st;wnow).

  1. 更新策略网络:

θ n e w   ←   θ n o w   −   β ⋅ δ t ⋅ ∇ θ ln ⁡ π ( a t   ∣   s t ;   θ n o w ) . \theta_{\mathrm{new}}\:\leftarrow\:\theta_{\mathrm{now}}\:-\:\beta\cdot\delta_{t}\cdot\nabla_{\boldsymbol{\theta}}\ln\pi(a_{t}\:|\:s_{t};\:\boldsymbol{\theta}_{\mathrm{now}}). θnewθnowβδtθlnπ(atst;θnow).

  1. τ ∈ ( 0 , 1 ) \tau\in(0,1) τ(0,1) 是需要手动调的超参数。做加权平均更新目标网络的参数:

w n e w ˉ   ←   τ ⋅ w n e w   +   ( 1 − τ ) ⋅ w n o w − . \bar{w_{\mathrm{new}}}\:\leftarrow\:\tau\cdot w_{\mathrm{new}}\:+\:\left(1-\tau\right)\cdot\boldsymbol{w_{\mathrm{now}}^{-}}. wnewˉτwnew+(1τ)wnow.

总结

  • 在策略梯度中加入基线 (baseline) 可以降低方差,显著提升实验效果。实践中常用 b = V π ( s ) b=V_{\pi}(s) b=Vπ(s) 作为基线。

  • 可以用基线来改进 REINFORCE 算法。价值网络 v ( s ; w ) v(s;\boldsymbol{w}) v(s;w) 近似状态价值函数 V π ( s ) V_\pi(s) Vπ(s) ,把 v ( s ; w ) v(s;\boldsymbol{w}) v(s;w) 作为基线。用策略梯度上升来更新策略网络 π ( a ∣ s ; θ ) \pi(a|s;\theta) π(as;θ)。用蒙特卡洛(而非自举) 来更新价值网络 v ( s ; w ) v(s;\boldsymbol{w}) v(s;w)

  • 可以用基线来改进 actor-critic, 得到的方法叫做 advantage actor-critic(A2C),它也有一个策略网络 π ( a ∣ s ; θ ) \pi(a|s;\boldsymbol{\theta}) π(as;θ) 和一个价值网络 v ( s ; θ ) v(s;\boldsymbol{\theta}) v(s;θ)。用策略梯度上升来更新策略网络,用 TD 算法来更新价值网络。

后记

截至2024年1月29日20点11分,学习完这一章的内容:带baseline的策略梯度方法。明天是最后学习的一天,看是否能够结束这个系列。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Servlet】Smart Tomcat插件简化Servlet开发流程及解决常见问题

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Servlet】 本专栏旨在分享学习Servlet的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、Smart Tomcat插件二…

【2023地理设计组一等奖】基于GIS的桥梁隧道三维建模与可视化

作品介绍 1 设计背景和意义 随着我国基础建设规模不断扩大和深入,构建桥梁可视化管理模型,全面推动智慧桥梁,已成为现代隧道桥梁建设行业的发展趋势。传统的桥梁建模工作需要复杂的算法设计并需要熟练编程实践技能,实现周期长。开发自主知识版权的桥梁建模软件系统或专用插…

时间复杂度解释

时空复杂度概述 首先o(1), o(n), o(logn), o(nlogn)是用来表示对应算法的时间复杂度,这是算法的时间复杂度的表示。不仅仅用于表示时间复杂度&#xff0c;也用于表示空间复杂度。 算法复杂度分为时间复杂度和空间复杂度。其作用&#xff1a; 时间复杂度是指执行这个算法所需要…

Keepalived + DR 集群

目录 1、Keepalive VRRP 说明 故障切换 工作原理 核心组件 2、Keepalived DR 集群 拓扑规划 前期准备 配置 Httpd 服务 配置 Nginx 服务 配置 LVS 主 node_01 配置 LVS 从 node_02 测试 LVS 集群 测试主备切换 3、Keepalived 脑裂现象 4、Keepalived 心态检测 …

C++字符串的常用操作函数全总结

文章目录 1.string、string.h和cstring的区别2.字符串定义3.求字符串的长度&#xff08;也可以求array对象长度&#xff09;4.输入字符串5.分割截取字符串4.在字符串中查找指定子字符串,并返回其第一次出现的位置5.替换字符串中的一部分6.在字符串指定位置插入字符串7.复制字符…

【漏洞通告】 Jenkins CLI 任意文件读取漏洞

漏洞概况 Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件项目可以进行持续集成。Jenkins 有一个内置的命令行界面&#xff08;CLI&#xff09;&…

安装elasticsearch、kibana、IK分词器

1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net 1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像&#xff0c;这个镜像体积非常大&#xff0…

在Spring Boot中使用iTextPDF创建动态PDF文档

最近&#xff0c;我们的系统新增了一个客服模块&#xff0c;其中一个重要功能是能够以PDF格式导出客服与用户之间的聊天记录。这些聊天记录包含文字、图片和文件等多种内容。为了实现这一功能&#xff0c;我们首先使用了itextpdf 5.x版本制作了一个Demo。今天&#xff0c;我将与…

kubernetes-快速部署一套k8s集群

1、前置知识点 1.1 生产环境可部署Kubernetes集群的两种方式 目前生产部署Kubernetes集群主要有两种方式&#xff1a; kubeadm Kubeadm是一个K8s部署工具&#xff0c;提供kubeadm init和kubeadm join&#xff0c;用于快速部署Kubernetes集群。 二进制包 从github下载发行…

力扣题目训练(5)

2024年1月29日力扣题目训练 2024年1月29日力扣题目训练345. 反转字符串中的元音字母349. 两个数组的交集350. 两个数组的交集 II96. 不同的二叉搜索树97. 交错字符串44. 通配符匹配 2024年1月29日力扣题目训练 2024年1月29日第五天编程训练&#xff0c;今天主要是进行一些题训…

短视频与小程序:如何实现完美结合?

在短视频日益成为人们娱乐、社交和信息获取的重要渠道的今天&#xff0c;如何在短视频平台进行小程序推广成为了许多企业和品牌关注的焦点。本文将介绍如何利用短视频平台进行小程序推广&#xff0c;提升品牌曝光和用户互动。 首先&#xff0c;打开乔拓云-门店系统的后台&#…

使用new操作符,一定是在堆上申请内存么?

《法华经》曰&#xff1a;“ 世尊导师&#xff0c;安隐天人&#xff0c;我等闻记&#xff0c;心安具足。” 一、引言 我们常常张嘴就来&#xff0c;我们在堆上申请内存使用malloc() 或者new操作符&#xff0c;但是反过来说&#xff0c;使用new操作符&#xff0c;就一定是在堆…

###C语言程序设计-----C语言学习(7)#(调试篇)

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 一. 程序调试 1.程序调试介绍&#xff1a; 程序调试是软件开发过程中非常重…

海外云手机对于亚马逊卖家的作用

近年来&#xff0c;海外云手机作为一种新型模式迅速崭露头角&#xff0c;成为专业的出海SaaS平台软件。海外云手机在云端运行和存储数据&#xff0c;通过网页端操作&#xff0c;将手机芯片放置在机房&#xff0c;通过网络连接到服务器&#xff0c;为用户提供便捷的上网功能。因…

电气自动化行业,全面数字化工作流程

电气自动化行业数字化转型所需流程软件&#xff0c;与大家分享如下&#xff1a; D-Hub企业数字化协同平台、SuperHarness数字线束软件、SuperPanel母排设计软件、D-Hub生产管理系统&#xff0c;全面的数字化工作流程&#xff0c;智能降本增效&#xff01; D-Hub D-Hub是一款…

Hive(15)中使用sum() over()实现累积求和和滑动求和

目的&#xff1a; 三个常用的排序函数row_number(),rank()和dense_rank()。这三个函数需要配合开窗函数over()来实现排序功能。但over()的用法远不止于此&#xff0c;本文咱们来介绍如何实现累计求和和滑动求和。 1、数据介绍 三列数据&#xff0c;分别是员工的姓名、月份和…

Python+uiautomator2 框架搭建

一、安装整体步骤 01 开发环境安装 jdk安装&#xff08;version "1.8.0_361"&#xff09;python安装 &#xff08;Python37&#xff09;python编辑器安装 &#xff08;PyCharm2021&#xff09; 02 运行环境安装 adb安装 &#xff08;Android Debug Bridge versio…

处理Servlet生命周期事件

处理Servlet生命周期事件 接收关于 Servlet生命周期事件通知的类称为事件侦听器。这些侦听器实现Servlet API中定义的一个或多个servlet事件侦听器接口。侦听器类的逻辑分类如下: servlet请求侦听器Servlet上下文侦听器HTTP会话侦听器1. servlet请求侦听器 servlet请求侦听器…

vivado 硬块规划器

硬块规划器 Versal自适应SoC的硬块规划GT组件从通用/通道更新为AMD的GT_QUAD粒度Versal™ 自适应SoC。为了启用某些GT共享用例&#xff0c;对GT向导流进行了修改使用Vivado IP集成商。使用Vivado IP集成商构建使用单个或多个GT_ QUAD。连接到GT_QUAD的自定义IP的设计条目为通过…

如何一键导出多张图片二维码?图片批量建码生成的方法

现在很多的物品信息都会生成一张单独的图片&#xff0c;然后生成二维码印刷到包装或者其他地方上使用&#xff0c;那么如何快速将多张图片多批量生码处理&#xff0c;相信有很多的小伙伴都不太清楚该怎么完成。其实&#xff0c;大量图片生成二维码的方法是很简单的&#xff0c;…