◇【code】PPO: Proximal Policy Optimization

news2024/10/9 16:10:27

整理的代码库:https://github.com/Gaoshu-root/Code-related-courses/tree/main/RL2024/PPO

OpenAI 文档 —— PPO-Clip

OpenAI 文档 界面链接

PPO: on-policy 算法、适用于 离散 或 连续动作空间。可能局部最优

PPO 的动机与 TRPO 一样:如何利用现有的数据在策略上采取最大可能的改进 step,而不会改动过大而意外导致性能崩溃?

  • TRPO 试图用一种复杂的二阶方法来解决这个问题,PPO 则是一种一阶方法,它使用了一些其他技巧来保持 新策略接近旧策略。
  • PPO 方法的实现要简单得多,而且从经验上看,其执行效果至少与 TRPO 一样好。

PPO 有两种主要的变体:PPO-Penalty 和 PPO-Clip。

  • PPO-Penalty 近似地解决了像 TRPO 这样的 KL 约束更新,但在目标函数中惩罚了 KL-divergence,而不是使其成为硬约束,并在训练过程中自动调整惩罚系数,使其适当缩放。
  • PPO-Clip 在目标函数中没有 KL-divergence 项,也没有约束。而是依靠对目标函数的特定裁剪来去除 新策略远离旧策略 的激励。
    PPO-Clip (OpenAl 使用的主要变体)。

关键公式

PPO-clip 更新策略: θ k + 1 = arg ⁡ max ⁡ θ E s , a ∼ π θ k [ L ( s , a , θ k , θ ) ] \theta_{k+1}=\arg\max\limits_{\theta}\underset{s,a\sim {\pi_{\theta_k}}}{\mathbb E}[L(s,a,\theta_k,\theta)] θk+1=argθmaxs,aπθkE[L(s,a,θk,θ)]

通常采取多步(通常是小批量) SGD 来最大化目标

L ( s , a , θ k , θ ) = min ⁡ ( π θ ( a ∣ s ) π θ k ( a ∣ s ) A π θ k ( s , a ) , clip ( π θ ( a ∣ s ) π θ k ( a ∣ s ) , 1 − ϵ , 1 + ϵ ) A π θ k ( s , a ) ) L(s,a,\theta_k,\theta)=\min\bigg(\frac{\pi_\theta(a|s)}{\pi_{\theta_k}(a|s)}A^{\pi_{\theta_k}}(s,a),\text{clip}\Big(\frac{\pi_\theta(a|s)}{\pi_{\theta_k}(a|s)},1-\epsilon,1+\epsilon\Big)A^{\pi_{\theta_k}}(s,a)\bigg) L(s,a,θk,θ)=min(πθk(as)πθ(as)Aπθk(s,a),clip(πθk(as)πθ(as),1ϵ,1+ϵ)Aπθk(s,a))

  • 其中 ϵ \epsilon ϵ 是一个(小)超参数,它大致表示新策略 与 旧策略之间的距离。

这是一个相当复杂的表达式,乍一看很难看出它在做什么,或者它如何帮助保持新策略接近旧策略。事实证明,这个目标有一个相当简化的版本[1],更容易处理(也是我们在代码中实现的版本):

L ( s , a , θ k , θ ) = min ⁡ ( π θ ( a ∣ s ) π θ k ( a ∣ s ) A π θ k ( s , a ) , g ( ϵ , A π θ k ( s , a ) ) ) L(s,a,\theta_k,\theta)=\min\bigg(\frac{\pi_\theta(a|s)}{\pi_{\theta_k}(a|s)}A^{\pi_{\theta_k}}(s, a), g\Big(\epsilon, A^{\pi_{\theta_k}}(s,a)\Big)\bigg) L(s,a,θk,θ)=min(πθk(as)πθ(as)Aπθk(s,a),g(ϵ,Aπθk(s,a)))

  • 其中 g ( ϵ , A ) = { ( 1 + ϵ ) A         A ≥ 0 ( 1 − ϵ ) A         A < 0 g(\epsilon,A)=\left\{\begin{aligned}(1+\epsilon)A&~~~~~~~A\geq0\\ (1-\epsilon)A&~~~~~~~A<0\end{aligned}\right. g(ϵ,A)={(1+ϵ)A(1ϵ)A       A0       A<0

————————————————

简化版本的 PPO-Clip 目标 推导

整理自 链接 (20180730)

命题 1: PPO-Clip 目标可简化成

L θ k C L I P ( θ ) = E s , a ∼ θ k [ min ⁡ ( π θ ( a ∣ s ) π θ k ( a ∣ s ) A θ k ( s , a ) , g ( ϵ , A θ k ( s , a ) ) ) ] L^{\rm CLIP}_{\theta_k}(\theta)=\underset{s, a\sim\theta_k}{\mathbb E}\bigg[\min\bigg(\frac{\pi_\theta(a|s)}{\pi_{\theta_k}(a|s)}A^{\theta_k}(s, a), g\Big(\epsilon, A^{\theta_k}(s,a)\Big)\bigg)\bigg] LθkCLIP(θ)=s,aθkE[min(πθk(as)πθ(as)Aθk(s,a),g(ϵ,Aθk(s,a)))]

  • 其中 g ( ϵ , A ) = { ( 1 + ϵ ) A         A ≥ 0 ( 1 − ϵ ) A        otherwise g(\epsilon,A)=\left\{\begin{aligned}(1+\epsilon)A&~~~~~~~A\geq0\\ (1-\epsilon)A&~~~~~~~\text{otherwise}\end{aligned}\right. g(ϵ,A)={(1+ϵ)A(1ϵ)A       A0       otherwise

简化过程:
PPO-Clip 的目标函数为:
  ~  
L θ k C L I P ( θ ) ≐ E s , a ∼ θ k [ min ⁡ ( π θ ( a ∣ s ) π θ k ( a ∣ s ) A θ k ( s , a ) , c l i p ( π θ ( a ∣ s ) π θ k ( a ∣ s ) , 1 − ϵ , 1 + ϵ ) A θ k ( s , a ) ) ] L^{\rm CLIP}_{\theta_k}(\theta)\doteq\underset{s, a\sim\theta_k}{\mathbb E}\bigg[\min\bigg(\frac{\pi_\theta(a|s)}{\pi_{\theta_k}(a|s)}A^{\theta_k}(s, a), {\rm clip}\Big(\frac{\pi_\theta(a|s)}{\pi_{\theta_k}(a|s)},1-\epsilon, 1+\epsilon\Big)A^{\theta_k}(s, a)\bigg)\bigg] LθkCLIP(θ)s,aθkE[min(πθk(as)πθ(as)Aθk(s,a),clip(πθk(as)πθ(as),1ϵ,1+ϵ)Aθk(s,a))]
  ~  
$\underset{s, a\sim\theta_k}{\mathbb E}$     E s , a ∼ θ k ~~~\underset{s, a\sim\theta_k}{\mathbb E}    s,aθkE

  • 其中 θ k \theta_k θk 为第 k k k 次迭代 的策略的参数 , ϵ \epsilon ϵ 为 小的超参数。

  ~  
ϵ ∈ ( 0 , 1 ) \epsilon\in(0,1) ϵ(0,1), 定义
F ( r , A , ϵ ) ≐ min ⁡ ( r A , c l i p ( r , 1 − ϵ , 1 + ϵ ) A ) F(r,A,\epsilon)\doteq\min\bigg(rA,{\rm clip}(r,1-\epsilon,1+\epsilon)A\bigg) F(r,A,ϵ)min(rA,clip(r,1ϵ,1+ϵ)A)
A ≥ 0 A\geq0 A0
F ( r , A , ϵ ) = min ⁡ ( r A , c l i p ( r , 1 − ϵ , 1 + ϵ ) A ) = A min ⁡ ( r , c l i p ( r , 1 − ϵ , 1 + ϵ ) ) = A min ⁡ ( r , { 1 + ϵ    r ≥ 1 + ϵ r r ∈ ( 1 − ϵ , 1 + ϵ ) 1 − ϵ r ≤ 1 − ϵ } ) = A { min ⁡ ( r , 1 + ϵ )    r ≥ 1 + ϵ min ⁡ ( r , r ) r ∈ ( 1 − ϵ , 1 + ϵ ) min ⁡ ( r , 1 − ϵ ) r ≤ 1 − ϵ } = A { 1 + ϵ    r ≥ 1 + ϵ r r ∈ ( 1 − ϵ , 1 + ϵ ) r r ≤ 1 − ϵ }       根据右侧的范围 = A min ⁡ ( r , 1 + ϵ ) = min ⁡ ( r A , ( 1 + ϵ ) A ) \begin{aligned}F(r,A,\epsilon)&=\min\bigg(rA,{\rm clip}(r,1-\epsilon,1+\epsilon)A\bigg)\\ &=A\min\bigg(r,{\rm clip}(r,1-\epsilon,1+\epsilon)\bigg)\\ &=A\min\bigg(r,\left\{\begin{aligned}&1+\epsilon~~&r\geq1+\epsilon\\ &r &r\in(1-\epsilon,1+\epsilon)\\ &1-\epsilon &r\leq1-\epsilon\\ \end{aligned}\right\}\bigg)\\ &=A\left\{\begin{aligned}&\min(r,1+\epsilon)~~&r\geq1+\epsilon\\ &\min(r,r) &r\in(1-\epsilon,1+\epsilon)\\ &\min(r,1-\epsilon) &r\leq1-\epsilon\\ \end{aligned}\right\}\\ &=A\left\{\begin{aligned}&1+\epsilon~~&r\geq1+\epsilon\\ &r &r\in(1-\epsilon,1+\epsilon)\\ &r &r\leq1-\epsilon\\ \end{aligned}\right\}~~~~~\textcolor{blue}{根据右侧的范围}\\ &=A\min(r, 1+\epsilon)\\ &=\min\bigg(rA, (1+\epsilon)A\bigg) \end{aligned} F(r,A,ϵ)=min(rA,clip(r,1ϵ,1+ϵ)A)=Amin(r,clip(r,1ϵ,1+ϵ))=Amin(r, 1+ϵ  r1ϵr1+ϵr(1ϵ,1+ϵ)r1ϵ )=A min(r,1+ϵ)  min(r,r)min(r,1ϵ)r1+ϵr(1ϵ,1+ϵ)r1ϵ =A 1+ϵ  rrr1+ϵr(1ϵ,1+ϵ)r1ϵ      根据右侧的范围=Amin(r,1+ϵ)=min(rA,(1+ϵ)A)
  ~  
A < 0 A<0 A<0
F ( r , A , ϵ ) = min ⁡ ( r A , c l i p ( r , 1 − ϵ , 1 + ϵ ) A ) = A max ⁡ ( r , c l i p ( r , 1 − ϵ , 1 + ϵ ) ) = A max ⁡ ( r , { 1 + ϵ    r ≥ 1 + ϵ r r ∈ ( 1 − ϵ , 1 + ϵ ) 1 − ϵ r ≤ 1 − ϵ } ) = A { max ⁡ ( r , 1 + ϵ )    r ≥ 1 + ϵ max ⁡ ( r , r ) r ∈ ( 1 − ϵ , 1 + ϵ ) max ⁡ ( r , 1 − ϵ ) r ≤ 1 − ϵ } = A { r    r ≥ 1 + ϵ r r ∈ ( 1 − ϵ , 1 + ϵ ) 1 − ϵ r ≤ 1 − ϵ }       根据右侧的范围 = A max ⁡ ( r , 1 − ϵ ) = min ⁡ ( r A , ( 1 − ϵ ) A ) \begin{aligned}F(r,A,\epsilon)&=\min\bigg(rA,{\rm clip}(r,1-\epsilon,1+\epsilon)A\bigg)\\ &=A\textcolor{blue}{\max}\bigg(r,{\rm clip}(r,1-\epsilon,1+\epsilon)\bigg)\\ &=A\max\bigg(r,\left\{\begin{aligned}&1+\epsilon~~&r\geq1+\epsilon\\ &r &r\in(1-\epsilon,1+\epsilon)\\ &1-\epsilon &r\leq1-\epsilon\\ \end{aligned}\right\}\bigg)\\ &=A\left\{\begin{aligned}&\max(r,1+\epsilon)~~&r\geq1+\epsilon\\ &\max(r,r) &r\in(1-\epsilon,1+\epsilon)\\ &\max(r,1-\epsilon) &r\leq1-\epsilon\\ \end{aligned}\right\}\\ &=A\left\{\begin{aligned}&r~~&r\geq1+\epsilon\\ &r &r\in(1-\epsilon,1+\epsilon)\\ &1-\epsilon &r\leq1-\epsilon\\ \end{aligned}\right\}~~~~~\textcolor{blue}{根据右侧的范围}\\ &=A\max(r, 1-\epsilon)\\ &=\textcolor{blue}{\min}\bigg(rA,(1-\epsilon)A\bigg) \end{aligned} F(r,A,ϵ)=min(rA,clip(r,1ϵ,1+ϵ)A)=Amax(r,clip(r,1ϵ,1+ϵ))=Amax(r, 1+ϵ  r1ϵr1+ϵr(1ϵ,1+ϵ)r1ϵ )=A max(r,1+ϵ)  max(r,r)max(r,1ϵ)r1+ϵr(1ϵ,1+ϵ)r1ϵ =A r  r1ϵr1+ϵr(1ϵ,1+ϵ)r1ϵ      根据右侧的范围=Amax(r,1ϵ)=min(rA,(1ϵ)A)
  ~  
综上:可定义 g ( ϵ , A ) g(\epsilon,A) g(ϵ,A)
  ~  
g ( ϵ , A ) = { ( 1 + ϵ ) A      A ≥ 0 ( 1 − ϵ ) A A < 0 g(\epsilon,A)=\left\{\begin{aligned}&(1+\epsilon)A ~~~~&A\geq0\\ &(1-\epsilon)A&A<0\end{aligned}\right. g(ϵ,A)={(1+ϵ)A    (1ϵ)AA0A<0
在这里插入图片描述
动机: 如果给定的 状态-动作 对 具有负的优势 A A A,优化想要让 π θ ( a ∣ s ) \pi_\theta(a|s) πθ(as) 更小,但让 π θ ( a ∣ s ) \pi_\theta(a|s) πθ(as) ( 1 − ϵ ) π θ ( a ∣ s ) (1-\epsilon)\pi_\theta(a|s) (1ϵ)πθ(as) 小对目标函数并没有额外的益处。
如果给定的 状态-动作 对 具有正的优势 A A A,优化想要让 π θ ( a ∣ s ) \pi_\theta(a|s) πθ(as) 更大,但让 π θ ( a ∣ s ) \pi_\theta(a|s) πθ(as) ( 1 + ϵ ) π θ ( a ∣ s ) (1+\epsilon)\pi_\theta(a|s) (1+ϵ)πθ(as) 大对目标函数并没有额外的益处。

————————————————

1、当 advantage优势 为正

L ( s , a , θ k , θ ) = min ⁡ ( π θ ( a ∣ s )   ↑ π θ k ( a ∣ s ) , 1 + ϵ ) A π θ k ( s , a ) L(s,a,\theta_k, \theta)=\min\bigg(\frac{\pi_\theta(a|s)~\textcolor{blue}{↑}}{\pi_{\theta_k}(a|s)}, 1+\epsilon\bigg)A^{\pi_{\theta_k}}(s, a) L(s,a,θk,θ)=min(πθk(as)πθ(as) ,1+ϵ)Aπθk(s,a)

当 状态-动作对 的优势是正的,希望拟习得的策略增大动作 a a a 被执行的概率,即增大 π θ ( a ∣ s ) \pi_\theta(a|s) πθ(as) ,这将会使得目标增大。
但该项中的 min 限制了 目标函数只能增大到某个值
一旦 π θ ( a ∣ s ) > ( 1 + ϵ ) π θ k ( a ∣ s ) \pi_\theta(a|s)>(1+\epsilon)\pi_{\theta_k}(a|s) πθ(as)>(1+ϵ)πθk(as), min 触发,限制该项值为 ( 1 + ϵ ) π θ k ( a ∣ s ) (1+\epsilon)\pi_{\theta_k}(a|s) (1+ϵ)πθk(as)
the new policy does not benefit by going far away from the old policy.
新策略 不会因远离 旧策略而受益。
——> 策略将会习得 不要与原策略相差过大。

2、当 advantage优势为负

L ( s , a , θ k , θ ) = max ⁡ ( π θ ( a ∣ s )   ↓ π θ k ( a ∣ s ) , 1 − ϵ ) A π θ k ( s , a ) L(s,a,\theta_k, \theta)=\max\bigg(\frac{\pi_\theta(a|s) ~\textcolor{blue}{↓}}{\pi_{\theta_k}(a|s)}, 1-\epsilon\bigg)A^{\pi_{\theta_k}}(s, a) L(s,a,θk,θ)=max(πθk(as)πθ(as) ,1ϵ)Aπθk(s,a)

当 某个状态-动作对 的优势的,希望拟习得的策略减小该动作 a a a 被执行的概率 ,即 减小 π θ ( a ∣ s ) π_\theta(a|s) πθ(as) ,此时目标函数就会增大。但是该项中的 max 限制了目标函数可以增大到多少。
一旦 π θ ( a ∣ s ) < ( 1 − ϵ ) π θ k ( a ∣ s ) \pi_\theta(a|s)<(1-\epsilon)\pi_{\theta_k}(a|s) πθ(as)<(1ϵ)πθk(as), max 触发,限制该项值为 ( 1 − ϵ ) π θ k ( a ∣ s ) (1-\epsilon)\pi_{\theta_k}(a|s) (1ϵ)πθk(as)

再次说明:the new policy does not benefit by going far away from the old policy.
新策略 不会因远离 旧策略而受益。

注意: 这种 clipping 最终仍有可能得到一个与旧策略相去甚远的新策略,在这里的实现中,我们使用了一个特别简单的方法:提前停止。如果新策略与旧策略的平均 KL -散度超过一个阈值,我们就停止执行梯度步骤。

探索 vs. 利用

PPO 以一种 on-policy 的方式训练随机策略。
这意味着它根据随机策略的最新版本通过抽样动作进行探索
动作选择的随机性取决于初始条件和训练过程。
在训练过程中,策略通常会逐渐变得不那么随机,因为更新规则会鼓励它利用已经找到的奖励。这可能导致策略陷入局部最优状态。

PPO-Clip 算法伪码

在这里插入图片描述

算法: PPO-Clip
1:输入:策略的初始参数 θ 0 \theta_0 θ0,价值函数的初始参数 ϕ 0 \phi_0 ϕ0
2: f o r   k = 0 , 1 , 2 , …   d o {\bf for} ~ k=0,1,2,\dots~ {\bf do} for k=0,1,2, do每个 epoch轮次      ~~~~     未过拟合的前提下,轮次越多越好
3:        ~~~~~~       通过在环境中运行策略 π k = π ( θ k ) \pi_k=\pi(\theta_k) πk=π(θk) 收集轨迹集 D k = { τ i }       {\cal D}_k=\{\tau_i\}~~~~~ Dk={τi}      ∣ D k ∣ |{\cal D}_k| Dk 个并行 actors,每个 actor 收集 长度为 T T T 个时间步 的数据
4:        ~~~~~~       计算奖励 (rewards-to-go) R ^ t       \hat R_t~~~~~ R^t      有些实现用的 td_target          R ^ t = ∑ t ′ = t T R ( s t ′ , a t ′ , s t ′ + 1 ) ~~~~~~~~\hat R_t=\sum\limits_{t^\prime=t}^TR(s_{t^\prime},a_{t^\prime},s_{t^\prime +1})         R^t=t=tTR(st,at,st+1) 【参考链接】       ~~~~~       R ( τ ) = ∑ t = 0 ∞ γ t r t R(\tau)=\sum\limits_{t=0}^\infty \gamma^tr_t R(τ)=t=0γtrt 【参考链接】
5:        ~~~~~~       计算优势估计,基于当前价值函数 V ϕ k V_{\phi_k} Vϕk A ^ t \hat A_t A^t (使用任何优势估计方法)       ~~~~~      GAE

在这里插入图片描述

6:        ~~~~~~       通过最大化 PPO-Clip 目标 更新策略:
            ~~~~~~~~~~~            
            θ k + 1 = arg ⁡ max ⁡ θ 1 ∣ D k ∣ T ∑ τ ∈ D k ∑ t = 0 T min ⁡ ( π θ ( a t ∣ s t ) π θ k ( a t ∣ s t ) A π θ k ( s t , a t ) , g ( ϵ , A π θ k ( s t , a t ) ) ) ~~~~~~~~~~~\theta_{k+1}=\arg\max\limits_\theta\frac{1}{|{\cal D}_k|T}\sum\limits_{\tau\in{\cal D}_k}\sum\limits_{t=0}^T\min\Big(\frac{\pi_{\theta} (a_t|s_t)}{\pi_{\theta_k}(a_t|s_t)}A^{\pi_{\theta_k}}(s_t,a_t),g(\epsilon,A^{\pi_{\theta_k}}(s_t,a_t))\Big)            θk+1=argθmaxDkT1τDkt=0Tmin(πθk(atst)πθ(atst)Aπθk(st,at),g(ϵ,Aπθk(st,at)))
            ~~~~~~~~~~~            
            ~~~~~~~~~~~            在这里插入图片描述
            ~~~~~~~~~~~            一般 随机梯度上升 + Adam
7:        ~~~~~~       均方误差回归 拟合 价值函数:
            ~~~~~~~~~~~            
            ϕ k + 1 = arg ⁡ min ⁡ ϕ 1 ∣ D k ∣ T ∑ τ ∈ D k ∑ t = 0 T ( V ϕ ( s t ) − R ^ t ) 2 ~~~~~~~~~~~\phi_{k+1}=\arg \min\limits_\phi\frac{1}{|{\cal D}_k|T}\sum\limits_{\tau\in{\cal D}_k}\sum\limits_{t=0}^T\Big(V_\phi(s_t)-\hat R_t\Big)^2            ϕk+1=argϕminDkT1τDkt=0T(Vϕ(st)R^t)2
            ~~~~~~~~~~~            
            ~~~~~~~~~~~            一般 梯度下降
8: e n d   f o r \bf end ~for end for

在这里插入图片描述

$\dots$     … ~~~\dots    

spinup 关于 R ^ t \hat R_t R^t 的计算

        # the next two lines implement GAE-Lambda advantage calculation
        deltas = rews[:-1] + self.gamma * vals[1:] - vals[:-1]
        self.adv_buf[path_slice] = core.discount_cumsum(deltas, self.gamma * self.lam)
        
        # the next line computes rewards-to-go, to be targets for the value function
        self.ret_buf[path_slice] = core.discount_cumsum(rews, self.gamma)[:-1]
def discount_cumsum(x, discount):
    """
    magic from rllab for computing discounted cumulative sums of vectors.

    input: 
        vector x, 
        [x0, 
         x1, 
         x2]

    output:
        [x0 + discount * x1 + discount^2 * x2,  
         x1 + discount * x2,
         x2]
    """
    return scipy.signal.lfilter([1], [1, float(-discount)], x[::-1], axis=0)[::-1]

  • spinup/algos/pytorch/ppo
  • rllib/algorithms/ppo/torch

第 12 章 PPO 算法 【上交】

整理自 链接

TRPO : 计算过程复杂,每一步更新的运算量非常大

paperswithcode 页面相关整理

paperswithcode 页面 链接
在这里插入图片描述

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

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

相关文章

Scott Brinker:企业正在更换更多的Martech,专注集成和API,不断扩大技术栈

营销技术替代因素&#xff1a;集成和API排在第二位 MarTech.org组织了2024年Martech替代调查&#xff0c;它能够深入了解营销技术栈是如何演变的。在496名受访者中&#xff0c;有65%的人表示他们在过去一年中更换了他们技术栈中的一个或多个营销技术解决方案。这些是最常被替代…

Tableau|三 数据连接与管理

一 Tableau的数据架构 数据连接层&#xff08;Connection&#xff09;、数据模型层&#xff08;DataModel&#xff09;和数据可视化层&#xff08;VizQL&#xff09;。 1.数据连接层 决定了如何访问源数据和获取哪些数据。 数据连接层的数据连接信息包括数据库、数据表、数据视…

华为大咖说 | 新时代,智能电动车车联网有哪些发展趋势?(下篇)

本文作者&#xff1a;朱行健&#xff08;华为专家&#xff09;全文约4252字&#xff0c;阅读约需9分钟 近年来&#xff0c;汽车产业逐步向电动化、自动化、网联化、共享化发展&#xff0c;车联网开始成为新的竞争主体&#xff0c;汽车市场开始出现新的市场发展驱动力、形成新的…

E36.C语言模拟试卷1第一大题选题解析与提示(未完)

点我去下载C语言模拟试卷1的文件 备注:ZIP文件中的参考答案仅仅提供最终结果 目录 第3题 第5题 第7题 第9题 第14题 第16题 第19题 第20题 第22题 第24题 第26题 第27题 第28题 第3题 3.若有说明语句&#xff1a;char c ‘\64’ ; 则变量C包含&#xff1a; …

python19_加减乘除(二)

加减乘除 a hello b world c 2 d 4# 字符串加法 def str_add(A, B):result A Breturn result# 字符串乘法 def str_mul(A, B):result A * Breturn result# 字符串除法 def str_div(A, B):result B / Areturn result# 字符串减法 def str_sub(A, B):result B - Aretur…

A股牛市来袭,资本涌动:加密市场的出路与机遇

近期&#xff0c;随着A股的强劲反弹&#xff0c;不少加密市场的投资者&#xff0c;尤其是一些KOL&#xff08;关键意见领袖&#xff09;&#xff0c;开始转移资金并公开建议进军A股。这种趋势反映出部分投资者对加密市场的信心动摇&#xff0c;尤其是在全球宏观经济不确定性加剧…

python兴农购物网站系统—计算机毕业设计源码38256

摘 要 助农工作是当前我国全面建成小康社会的重点工作&#xff0c;由于我国农村地域广大&#xff0c;贫困人口多&#xff0c;区域差异大&#xff0c;因此&#xff0c;不同区域的扶贫方法也是不一样的。近年来&#xff0c;随着网络的普及。许多农村地区物产丰富&#xff0c;但由…

【解决方案】基于数据库驱动的自定义 TypeHandler 处理器

前言 笔者在最近的项目开发中&#xff0c;频繁地遇到了 Java 类型与 JDBC 类型之间的2个转换问题&#xff1a; 数据库的 varchar 类型字段&#xff0c;需要存储 Java 实体中的 JSON 字符串 数据库的 int 类型字段&#xff0c;需要存储 Java 实体中的 Enum 枚举 其实要处理也不…

数据库软题6.2-关系模式-范式

一、判断部分函数依赖&#xff08;1NF有部分函数依赖&#xff09; 题型&#xff1a;给出函数依赖集和属性&#xff0c;判断该关系模式属于第几范式。 求出候选码 若是候选码为属性的组合&#xff0c;则可能有部分函数依赖&#xff1b;&#xff08;存在部分函数依赖&#xff0…

苹果AI重磅升级!ChatGPT正式登陆iPhone,开启智能生活新时代

苹果AI重磅升级&#xff01;ChatGPT正式登陆iPhone&#xff0c;开启智能生活新时代 在今年的全球开发者大会&#xff08;WWDC 2024&#xff09;上&#xff0c;苹果公司引爆了科技圈——通过与OpenAI合作&#xff0c;苹果宣布将人工智能技术与iPhone深度融合。通过这个合作&…

自由学习记录(2)

Unity打包图集相关 Draw Call 实验设置&#xff1a; 我们将创建两个场景&#xff0c;一个场景有高 Draw Call&#xff0c;另一个场景通过优化减少 Draw Call。然后对比它们的帧率&#xff08;FPS&#xff09;。 场景 1&#xff1a;高 Draw Call 场景&#xff08;无优化&…

浙大数据结构:07-图5 Saving James Bond - Hard Version

这道题也是很有难度&#xff0c;我最开始尝试用Dijkstra来做&#xff0c;发现不是很好处理&#xff0c;用bfs还不错。 机翻&#xff1a; 1、条件准备 n为鳄鱼数量&#xff0c;jump为跳跃距离&#xff0c;headjump为第一次跳跃距离&#xff0c;包括了岛的半径。 isalive标识…

求职书与求职经历 - Chap01.

节前定点在智联投了几家&#xff0c;智联上之前的简历还在&#xff0c;稍稍维护了一下&#xff0c;现在有两三家再看看。然后节后&#xff0c;今天&#xff0c;注册了职友网的7天会员。正在整理简历。 专利证书&#xff0c;通过soopat查&#xff0c;很不友好。国家产权局后来直…

docker部署langfuse 本地

下载langfuse地址:https://api.github.com/repos/langfuse/langfuse/tarball/v2.43.2 tips&#xff1a;这里有的博主说需要clone到本地&#xff0c;但是我的docker clone langfuse到本地使用docker安装页面提示如下错误: 最后使用下载地址 上传到服务器后 解压再安装 反正没有…

PIFA天线工作原理:【图文讲解】

1&#xff1a;什么是PIFA天线 PIFA ( Planar Inverted F-shaped Antenna)天线即平面倒F形天线&#xff0c;因为整个天线的形状像个倒写的英文字母F而得名 2&#xff1a;PIFA天线的应用 PIFA常见于手机天线设计&#xff0c;占手机内置天线的60%-80% 3&#xff1a;PIFA天线结构…

5.错误处理在存储过程中的重要性(5/10)

错误处理在存储过程中的重要性 引言 在数据库编程中&#xff0c;存储过程是一种重要的组件&#xff0c;它允许用户将一系列SQL语句封装成一个单元&#xff0c;以便重用和简化数据库操作。然而&#xff0c;像任何编程任务一样&#xff0c;存储过程中的代码可能会遇到错误或异常…

封装vue-cropper,图片裁剪组件

组件基本使用: 这里的action同时也可以传相对路径&#xff0c;比如封装了axios&#xff0c;那么组件源码里就不需要引入原生axios&#xff0c;可以替换为封装的axios。传 action"/upload/file" 源代码&#xff1a; <script setup> import WuyuCropper from /c…

PyTorch单机多卡训练(无废话)

目前大家基本都在使用DistributedDataParallel&#xff08;简称DDP&#xff09;用来训练&#xff0c;该方法主要用于分布式训练&#xff0c;但也可以用在单机多卡。 第一步&#xff1a;初始化分布式环境&#xff0c;主要用来帮助进程间通信 torch.distributed.init_process_g…

Notepad-- 程序员日常用法

一、快速查找标记&#xff0c;提取指定的字符串 1.使用正则表达式查找并标记&#xff0c;将标记的内容复制到新文本中 标记中输入&#xff1a;.*"staffNo": "([^"])".* 这个正则表达式可以匹配整个行&#xff0c;并将 staffNo 后面的内容标记出来。…

修复WordPress .htaccess文件中的常见问题

在搭建WordPress网站时&#xff0c;.htaccess文件非常重要。它可以帮助我们管理网站的重定向、优化URL结构、提高网站安全性等。然而&#xff0c;有时可能会出现由.htaccess文件引起的问题&#xff0c;比如500内部服务器错误、重定向次数过多和文章返回404错误等。本文将详细介…