当前位置: 首页 > news >正文

深度探索:策略学习与神经网络在强化学习中的应用

深度探索:策略学习与神经网络在强化学习中的应用

  • 策略学习(Policy-Based Reinforcement Learning)
    • 一、策略函数
      • 1.1 策略函数输出的例子
    • 二、使用神经网络来近似策略函数:Policy Network ,策略网络
      • 2.1 策略网络运行的例子
      • 2.2需要的几个概念
      • 2.3神经网络近似策略函数
    • 三、策略学习的主要思想
      • 3.1 目标函数的定义
      • 3.2策略梯度算法
      • 3.2策略梯度的推导
      • 3.3策略梯度的两个公式推导
    • 四、策略梯度算法的的步骤分解
      • 4.1 动作空间离散的情况
      • 4.2使用蒙特卡洛近似来计算策略梯度
      • 步骤解释
      • 4.3 总结策略梯度算法
    • 五、动作价值函数 Q π ( s t , a t ) Q_{\pi}(s_t,a_t) Qπ(st,at)
      • 5.1 方法一:reinforce
      • 解释
      • 5.2 方法二:使用神经网络近似

策略学习(Policy-Based Reinforcement Learning)

我们可以用一个神经网络来近似一个策略函数,叫做Policy Network。可以用来控制agent的动作。

一、策略函数

π ( a ∣ s ) \pi (a|s) π(as),他是一个概率密度函数。

  • 策略函数的输入是状态
  • 输出是一个概率分布,给每个动作 a a a一个概率值

1.1 策略函数输出的例子

我们可以举一个超级玛丽的例子,把当前的状态 s s s作为输入,输出三个动作 a l e f t , r i g h t , j u m p a_{left,right,jump} aleft,right,jump的概率。是一个三维向量。
π ( l e f t ∣ s ) = 0.2 \pi(left|s) = 0.2 π(lefts)=0.2
π ( r i g h t ∣ s ) = 0.8 \pi(right|s) = 0.8 π(rights)=0.8
π ( j u m p ∣ s ) = 0.7 \pi(jump|s) = 0.7 π(jumps)=0.7

有了概率agent会进行一次随机抽样,三个动作都会被抽到,但是概率越大,被抽到的概率越大。这里会有一个误区,认为agent只会随机抽到概率最大的动作。

二、使用神经网络来近似策略函数:Policy Network ,策略网络

和价值学习一样,我们无法直接得到策略函数,但我们可以使用深度学习中的神经网络通过不断迭代来近似得到。
π ( a ∣ s , θ ) → π ( a ∣ s ) \pi(a|s,\theta) \rightarrow \pi(a|s) π(as,θ)π(as)

θ \theta θ是神经网络的参数,可以通过梯度下降来更新。

2.1 策略网络运行的例子

还是超级玛丽的游戏作为例子。

  • 我们首先对游戏的画面进行采样,得到某一帧的画面作为状态 s t s_t st
  • 我们对这一帧画面进行卷积、特征提取,得到一个特征向量
  • 我们将这个特征向量作为输入,通过神经网络后再进行softmax得到三个动作 a l e f t , r i g h t , j u m p a_{left,right,jump} aleft,right,jump的概率。
  • agent会对得到的概率进行采样,得到一个动作 a t a_t at

2.2需要的几个概念

  1. 回报 U t U_t Ut(Discounted Return)

U t = R t + γ R t + 1 + γ 2 R t + 2 + γ 3 R t + 3 + ⋅ ⋅ ⋅ U_t = R_t + \gamma R_{t+1} + \gamma^2 R_{t+2} + \gamma^3 R_{t+3} +··· Ut=Rt+γRt+1+γ2Rt+2+γ3Rt+3+⋅⋅⋅
回报依赖从 T T T时刻开始的所有的动作和所有的状态,是所有奖励的折扣和, γ \gamma γ是折扣系数。
2. 动作价值函数 Q π Q_{\pi} Qπ(Action Value Function)

Q π ( s t , a t ) = E [ U t ∣ s t , a t ] Q_{\pi}(s_t,a_t) = \mathbb{E}[U_t|s_t,a_t] Qπ(st,at)=E[Utst,at]

Q π Q_{\pi} Qπ仅仅依赖当前时刻的状态和动作和策略函数 π \pi π,动作价值函数可以评价在状态 s t s_t st下,执行动作 a t a_t at的回报是多少。它可以评估动作的好坏。
3. 状态价值函数 V π V_{\pi} Vπ(State Value Function)

V π ( s t ) = E A [ Q π ( s t , A ) ] V_{\pi}(s_t) = \mathbb{E}_A[Q_{\pi(s_t,A)}] Vπ(st)=EA[Qπ(st,A)]
V π V_{\pi} Vπ Q π Q_{\pi} Qπ的期望, V π V_{\pi} Vπ仅仅依赖当前时刻的状态和策略函数 π \pi π,它可以评估状态的好坏。,它越大,说明当前环境的胜算越大。

如果给定状态 s t s_t st V π ( s t ∣ A ) V_{\pi}(s_t|A) Vπ(stA)可以评估策略 π \pi π的好坏/

如果A是离散的变量,那么我们可以将上述的公式展开:

V π ( s t ) = ∑ a π ( a ∣ s t ) Q π ( s t , a ) V_{\pi}(s_t) = \sum_{a} \pi(a|s_t) Q_{\pi}(s_t,a) Vπ(st)=aπ(ast)Qπ(st,a)

2.3神经网络近似策略函数

我们使用神经网络来近似策略函数,神经网络的输入是状态,输出是动作的概率。
V π ( s t ) = V π ( s ; θ ) = ∑ a π ( a ∣ s ; θ ) Q π ( s , a ) V_{\pi}(s_t) = V_{\pi}(s;{\theta}) = \sum_{a} \pi(a|s;{\theta}) Q_{\pi}(s,a) Vπ(st)=Vπ(s;θ)=aπ(as;θ)Qπ(s,a)

其中,{\theta}是神经网络的参数。

三、策略学习的主要思想

由状态价值函数可以知道,给定环境 s s s,我们就可以评估一个策略函数 π \pi π的好坏。 V ( s ; θ ) V(s;{\theta}) V(s;θ)的值越大,策略函数就越好,我们可以改变参数 θ \theta θ来使得 V ( s ; θ ) V(s;{\theta}) V(s;θ)的值变大。

3.1 目标函数的定义

由以上思想,我们可以定义要更新的目标函数:

J ( θ ) = E S [ V π ( s t ; θ ) ] J(\theta) = \mathbb{E}_S[V_{\pi}(s_t;{\theta})] J(θ)=ES[Vπ(st;θ)]

我们将状态 S S S作为随机变量使用期望消去,这样我们定义的目标函数就只剩下 θ {\theta} θ

J ( θ ) J(\theta) J(θ)越大,我们的策略函数就越好

3.2策略梯度算法

大概思想

  1. 首先我们从环境中采样得到一个状态 s t s_t st
  2. 我们可以根据这个状态带入到 V ( s ; θ ) V(s;{\theta}) V(s;θ)中,计算他的梯度
  3. 进行梯度上升 θ = θ + β ∂ V ( s ; θ ) ∂ θ \theta = \theta + \beta \frac{\partial V(s;\theta)}{\partial \theta} θ=θ+βθV(s;θ)

$\beta 就是学习率它是一个随机梯度,随机性来源于 就是学习率 它是一个随机梯度,随机性来源于 就是学习率它是一个随机梯度,随机性来源于s$

∂ V ( s ; θ ) ∂ θ \frac{\partial V(s;\theta)}{\partial \theta} θV(s;θ)被称为策略梯度。

3.2策略梯度的推导

∂ V ( s ; θ ) ∂ θ = ∂ ∑ a π ( a ∣ s ; θ ) ∂ θ = ∑ a ∂ π ( a ∣ s ; θ ) ⋅ Q π ( s , a ) ∂ θ = ∑ a ∂ π ( a ∣ s ; θ ) ∂ θ ⋅ Q π ( s , a ) \begin{split} \frac{\partial V(s;\theta)}{\partial \theta} &=\frac{ \partial {\sum_{a}\pi(a|s;\theta)}} {\partial \theta } \\ &=\sum_{a} \frac{\partial \pi(a|s;\theta) \cdot Q_{\pi}(s,a)}{\partial \theta}\\ &=\sum_{a} \frac{\partial \pi(a|s;\theta)}{\partial \theta} \cdot Q_{\pi}(s,a)\\ \end{split} θV(s;θ)=θaπ(as;θ)=aθπ(as;θ)Qπ(s,a)=aθπ(as;θ)Qπ(s,a)
如果动作 A A A是离散的,直接带入就能把策略梯度算出来,但是实际运用中并不会直接使用这个公式,而是使用策略梯度的蒙特卡洛近似。

3.3策略梯度的两个公式推导

∂ V ( s ; θ ) ∂ θ = ∑ a ∂ π ( a ∣ s ; θ ) ∂ θ ⋅ Q π ( s , a ) = ∑ a π ( a ∣ s ; θ ) ⋅ ∂ log ⁡ π ( a ∣ s ; θ ) ∂ θ ⋅ Q π ( s , a ) \begin{split} \frac{\partial V(s;\theta)}{\partial \theta} &=\sum_{a} \frac{\partial \pi(a|s;\theta)}{\partial \theta} \cdot Q_{\pi}(s,a)\\ &= \sum_a \pi(a|s;\theta) \cdot \frac{\partial \log \pi(a|s;\theta)}{\partial \theta} \cdot Q_\pi(s, a) \end{split} θV(s;θ)=aθπ(as;θ)Qπ(s,a)=aπ(as;θ)θlogπ(as;θ)Qπ(s,a)

这一步从上往下不好推导,我们可以从下往上推导:

∂ log ⁡ [ π ( θ ) ] ∂ θ = 1 π ( θ ) ⋅ ∂ π ( θ ) ∂ θ \frac{\partial \log[\pi(\theta)]}{\partial \theta} = \frac{1}{\pi(\theta)} \cdot \frac{\partial \pi(\theta)}{\partial \theta} θlog[π(θ)]=π(θ)1θπ(θ)
⇒ π ( θ ) ⋅ ∂ log ⁡ [ π ( θ ) ] ∂ θ = π ( θ ) ⋅ 1 π ( θ ) ⋅ ∂ π ( θ ) ∂ θ = ∂ π ( θ ) ∂ θ \Rightarrow \pi(\theta) \cdot \frac{\partial \log[\pi(\theta)]}{\partial \theta} = \pi(\theta) \cdot \frac{1}{\pi(\theta)} \cdot \frac{\partial \pi(\theta)}{\partial \theta} = \frac{\partial \pi(\theta)}{\partial \theta} π(θ)θlog[π(θ)]=π(θ)π(θ)1θπ(θ)=θπ(θ)
这样我们就推导
π ( θ ) ⋅ ∂ log ⁡ [ π ( θ ) ] ∂ θ = ∂ π ( θ ) ∂ θ \pi(\theta) \cdot \frac{\partial \log[\pi(\theta)]}{\partial \theta} = \frac{\partial \pi(\theta)}{\partial \theta} π(θ)θlog[π(θ)]=θπ(θ)

我们接第一个推导继续推导

∂ V ( s ; θ ) ∂ θ = ∑ a ∂ π ( a ∣ s ; θ ) ∂ θ ⋅ Q π ( s , a ) = ∑ a π ( a ∣ s ; θ ) ⋅ ∂ log ⁡ π ( a ∣ s ; θ ) ∂ θ ⋅ Q π ( s , a ) = E A ∼ π ( ∙ ∣ s ; θ ) [ ∂ log ⁡ π ( A ∣ s ; θ ) ∂ θ ⋅ Q π ( s , A ) ] \begin{split} \frac{\partial V(s;\theta)}{\partial \theta} &= \sum_a \frac{\partial \pi(a|s;\theta)}{\partial \theta} \cdot Q_\pi(s, a)\\ &= \sum_a \pi(a|s;\theta) \cdot \frac{\partial \log \pi(a|s;\theta)}{\partial \theta} \cdot Q_\pi(s, a)\\ &= \mathbb{E}_{A \sim \pi(\bullet|s;\theta)} \left[ \frac{\partial \log \pi(A|s;\theta)}{\partial \theta} \cdot Q_\pi(s, A) \right] \end{split} θV(s;θ)=aθπ(as;θ)Qπ(s,a)=aπ(as;θ)θlogπ(as;θ)Qπ(s,a)=EAπ(s;θ)[θlogπ(As;θ)Qπ(s,A)]

实际上,下面中形式是等价的

∂ V ( s ; θ ) ∂ θ = ∑ a ∂ π ( a ∣ s ; θ ) ∂ θ ⋅ Q π ( s , a ) \frac{\partial V(s;\theta)}{\partial \theta} = \sum_{a} \frac{\partial \pi(a|s;\theta)}{\partial \theta} \cdot Q_{\pi}(s,a) θV(s;θ)=aθπ(as;θ)Qπ(s,a)

上面的公式对离散的动作空间适用,比如我们的超级玛丽游戏,我们只有三个动作。
∂ V ( s ; θ ) ∂ θ = E A ∼ π ( ∙ ∣ s ; θ ) [ ∂ log ⁡ π ( A ∣ s ; θ ) ∂ θ ⋅ Q π ( s , A ) ] \frac{\partial V(s;\theta)}{\partial \theta} = \mathbb{E}_{A \sim \pi(\bullet|s;\theta)} \left[ \frac{\partial \log \pi(A|s;\theta)}{\partial \theta} \cdot Q_\pi(s, A) \right] θV(s;θ)=EAπ(s;θ)[θlogπ(As;θ)Qπ(s,A)]
上面的公式对连续的动作空间使用,比如说对动作空间是零到一之间的所有实数,我们就用蒙特卡洛近似的公式。

四、策略梯度算法的的步骤分解

4.1 动作空间离散的情况

首先我们对于每一个 a ∈ A a \in \mathcal{A} aA都带入到策略梯度公式中,记为 f ( a , θ ) \mathbf{f}(a, \theta) f(a,θ)
f ( a , θ ) = ∂ π ( a ∣ s ; θ ) ∂ θ ⋅ Q π ( s , a ) \mathbf{f}(a, \theta) = \frac{\partial \pi(a|s;\theta)}{\partial \theta} \cdot Q_\pi(s, a) f(a,θ)=θπ(as;θ)Qπ(s,a)

计算出每个离散值的 f ( a , θ ) \mathbf{f}(a, \theta) f(a,θ),我们可以将他们累加起来,得到策略梯度公式
∂ V ( s ; θ ) ∂ θ = f ( "left" , θ ) + f ( "right" , θ ) + f ( "up" , θ ) \frac{\partial V(s;\theta)}{\partial \theta} = \mathbf{f}(\text{"left"}, \theta) + \mathbf{f}(\text{"right"}, \theta) + \mathbf{f}(\text{"up"}, \theta) θV(s;θ)=f("left",θ)+f("right",θ)+f("up",θ)

但是如果动作空间是连续的,那么将会由无穷多个动作,这时在进行累加就比较困难,如果我们选择积分的话,由于策略函数是一个神经网络,那么我们无法直接计算出策略梯度,所以我们需要使用蒙特卡洛方法来计算。

4.2使用蒙特卡洛近似来计算策略梯度

蒙特卡洛方法的基本思想是通过大量随机抽样来近似期望值。对于强化学习中的价值函数估计,蒙特卡洛方法通过多次抽样,用随机样本来近似期望来更新模型。

公式 2:
∂ V ( s ; θ ) ∂ θ = E A ∼ π ( ⋅ ∣ s ; θ ) [ ∂ log ⁡ π ( A ∣ s ; θ ) ∂ θ ⋅ Q π ( s , A ) ] \frac{\partial V(s;\theta)}{\partial \theta} = \mathbb{E}_{A \sim \pi(\cdot|s;\theta)} \left[ \frac{\partial \log \pi(A|s;\theta)}{\partial \theta} \cdot Q_\pi(s, A) \right] θV(s;θ)=EAπ(s;θ)[θlogπ(As;θ)Qπ(s,A)]
这个公式表示状态价值函数 V ( s ; θ ) V(s;\theta) V(s;θ) 关于参数 θ \theta θ 的梯度可以通过期望来计算。期望是在动作 A A A 根据策略 π ( ⋅ ∣ s ; θ ) \pi(\cdot|s;\theta) π(s;θ) 采样的情况下计算的,其中 Q π ( s , A ) Q_\pi(s, A) Qπ(s,A) 是在状态 s s s 下采取动作 A A A 的期望回报。

步骤解释

  1. 随机采样动作

    • 根据概率密度函数 π ( ⋅ ∣ s ; θ ) \pi(\cdot|s;\theta) π(s;θ) 随机采样一个动作 a ^ \hat{a} a^。这意味着从策略定义的动作分布中抽取一个动作。
  2. 计算 g ( a ^ , θ ) g(\hat{a}, \theta) g(a^,θ)

    • 计算 g ( a ^ , θ ) = ∂ log ⁡ π ( a ^ ∣ s ; θ ) ∂ θ ⋅ Q π ( s , a ^ ) g(\hat{a}, \theta) = \frac{\partial \log \pi(\hat{a}|s;\theta)}{\partial \theta} \cdot Q_\pi(s, \hat{a}) g(a^,θ)=θlogπ(a^s;θ)Qπ(s,a^)。这里, ∂ log ⁡ π ( a ^ ∣ s ; θ ) ∂ θ \frac{\partial \log \pi(\hat{a}|s;\theta)}{\partial \theta} θlogπ(a^s;θ) 是策略的对数关于参数 θ \theta θ 的梯度, Q π ( s , a ^ ) Q_\pi(s, \hat{a}) Qπ(s,a^) 是在状态 s s s 下采取动作 a ^ \hat{a} a^ 的期望回报。
  3. 使用 g ( a ^ , θ ) g(\hat{a}, \theta) g(a^,θ) 作为策略梯度的近似

    • 使用 g ( a ^ , θ ) g(\hat{a}, \theta) g(a^,θ) 作为策略梯度 ∂ V ( s ; θ ) ∂ θ \frac{\partial V(s;\theta)}{\partial \theta} θV(s;θ) 的近似。这意味着通过单个动作的采样和计算得到的 g ( a ^ , θ ) g(\hat{a}, \theta) g(a^,θ) 可以用来估计整个策略梯度。

这种方法对于离散的也是适用的。

4.3 总结策略梯度算法

  1. 观察状态 s t s_t st

    • 在时间步 t t t,观察或接收环境的当前状态 s t s_t st
  2. 根据策略 π ( ⋅ ∣ s t ; θ t ) \pi(\cdot | s_t; \theta_t) π(st;θt) 随机采样动作 a t a_t at

    • 根据当前策略 π \pi π(由参数 θ t \theta_t θt 定义)在状态 s t s_t st 下的概率分布,随机选择一个动作 a t a_t at
  3. 计算 q t ≈ Q π ( s t , a t ) q_t \approx Q_\pi(s_t, a_t) qtQπ(st,at)(某种估计)

    • 计算或估计在状态 s t s_t st 下采取动作 a t a_t at 的期望回报 Q π ( s t , a t ) Q_\pi(s_t, a_t) Qπ(st,at)。这里 q t q_t qt 是这个期望回报的估计值。
  4. 对策略网络求导

    • 计算策略网络关于参数 θ \theta θ 的梯度 d θ , t d_{\theta,t} dθ,t,即 ∂ log ⁡ π ( a t ∣ s t , θ ) ∂ θ \frac{\partial \log \pi(a_t | s_t, \theta)}{\partial \theta} θlogπ(atst,θ) θ = θ t \theta = \theta_t θ=θt 时的值。这个梯度表示策略参数如何影响选择特定动作 a t a_t at 的概率。
  5. (近似)策略梯度

    • 计算策略梯度的近似值 g ( a t , θ t ) = q t ⋅ d θ , t g(a_t, \theta_t) = q_t \cdot d_{\theta,t} g(at,θt)=qtdθ,t。这里, q t q_t qt 是步骤3中计算的期望回报的估计值, d θ , t d_{\theta,t} dθ,t 是步骤4中计算的梯度。
  6. 更新策略网络

    • 使用梯度上升方法更新策略网络的参数 θ \theta θ。更新公式为 θ t + 1 = θ t + β ⋅ g ( a t , θ t ) \theta_{t+1} = \theta_t + \beta \cdot g(a_t, \theta_t) θt+1=θt+βg(at,θt),其中 β \beta β 是学习率,控制更新步长的大小。

五、动作价值函数 Q π ( s t , a t ) Q_{\pi}(s_t,a_t) Qπ(st,at)

其实我们一直没有说明动作价值函数 Q π ( s t , a t ) Q_{\pi}(s_t,a_t) Qπ(st,at)是什么,该如何得到。

我们并不知道 Q π ( s t , a t ) Q_{\pi}(s_t,a_t) Qπ(st,at),并没有办法计算这个函数值,但是我们可以近似得到这个函数的值 q t ≈ Q π ( s t , a t ) q_t \approx Q_\pi(s_t, a_t) qtQπ(st,at),我们有两个方法来近似 q t q_t qt

5.1 方法一:reinforce

REINFORCE算法的核心思想是通过采样来估计策略梯度,并使用这个估计值来更新策略参数。

  1. 生成轨迹

    • 玩完一局游戏并生成轨迹: s 1 , a 1 , r 1 , s 2 , a 2 , r 2 , … , s T , a T , r T s_1, a_1, r_1, s_2, a_2, r_2, \ldots, s_T, a_T, r_T s1,a1,r1,s2,a2,r2,,sT,aT,rT。这里, s t s_t st 是时间步 t t t 的状态, a t a_t at 是时间步 t t t 的动作, r t r_t rt 是时间步 t t t 的奖励, T T T 是游戏的总时间步数。
  2. 计算折扣回报

    • 计算折扣回报 u t = ∑ k = t T γ k − t r k u_t = \sum_{k=t}^T \gamma^{k-t} r_k ut=k=tTγktrk,对于所有 t t t。这里, γ \gamma γ 是折扣因子,用于权衡未来奖励的重要性。
  3. 近似动作价值函数

    • 由于 Q π ( s t , a t ) = E [ U t ] Q_\pi(s_t, a_t) = \mathbb{E}[U_t] Qπ(st,at)=E[Ut],我们可以使用 u t u_t ut 来近似 Q π ( s t , a t ) Q_\pi(s_t, a_t) Qπ(st,at)。即 q t = u t q_t = u_t qt=ut

解释

  • 轨迹生成:通过与环境交互生成完整的轨迹,记录每个时间步的状态、动作和奖励。
  • 折扣回报:计算从当前时间步 t t t 到游戏结束的所有未来奖励的加权和,权重由折扣因子 γ \gamma γ 决定。
  • 近似动作价值:使用折扣回报 u t u_t ut 作为动作价值函数 Q π ( s t , a t ) Q_\pi(s_t, a_t) Qπ(st,at) 的估计值 q t q_t qt

这种方法的优点是简单且易于实现,但可能存在高方差的问题,因为折扣回报 u t u_t ut 可能对单个样本的波动非常敏感。为了降低方差,可以使用基线方法或优势函数等技术进行改进。

5.2 方法二:使用神经网络近似

这个方法比较复杂,我会放到下一期进行讲解。

相关文章:

深度探索:策略学习与神经网络在强化学习中的应用

深度探索:策略学习与神经网络在强化学习中的应用 策略学习(Policy-Based Reinforcement Learning)一、策略函数1.1 策略函数输出的例子 二、使用神经网络来近似策略函数:Policy Network ,策略网络2.1 策略网络运行的例子2.2需要的几个概念2.3神经网络近似…...

用VAE作为标题显示标题过短,所以标题变成了这样

VAE (Variational Autoencoder / 变分自编码器) 基本概念: VAE 是一种生成模型 (Generative Model),属于自编码器 (Autoencoder) 家族。 它的目标是学习数据的潜在表示 (Latent Representation),并利用这个表示来生成新的、与原始数据相似的数据。 与标…...

【day27】测试策略升级方案:需求阶段介入与业务规则覆盖矩阵设计

测试策略升级方案:需求阶段介入与业务规则覆盖矩阵设计 一、需求评审阶段:主动识别业务逻辑问题 在需求评审时,测试团队应通过结构化提问提前暴露潜在风险,避免后期返工。以下为提问框架与示例: 1. 业务逻辑澄清提问模…...

AI烘焙大赛中的算法:理解PPO、GRPO与DPO的罪简单的方式

🧠 向所有学习者致敬! “学习不是装满一桶水,而是点燃一把火。” —— 叶芝 我的博客主页: https://lizheng.blog.csdn.net 🌐 欢迎点击加入AI人工智能社区! 🚀 让我们一起努力,共创…...

二分 —— 基本算法刷题路程

一、1.求阶乘 - 蓝桥云课 算法代码&#xff1a; #include <bits/stdc.h> using namespace std; #define ll long long ll check(ll n) {ll cnt0;while(n){cnt(n/5);}return cnt; }int main() {ll k;cin>>k;ll L0,R1e19;while(L<R){ll mid(LR)>>1;if(che…...

内存序问题排查

1 内存序 2 简介 std::memory_order 是 C11 引入的一个枚举类型&#xff0c;用于和 <atomic> 原子操作一起使用&#xff0c;控制多线程环境下内存的可见性和执行顺序。 它的主要作用是&#xff1a;告诉编译器和 CPU&#xff0c;在执行某个原子操作时&#xff0c;哪些内…...

历年跨链合约恶意交易详解(四)——Chainswap20210711

漏洞合约函数 function receive(uint256 fromChainId, address to, uint256 nonce, uint256 volume, Signature[] memory signatures) virtual external payable {_chargeFee();require(received[fromChainId][to][nonce] 0, withdrawn already);uint N signatures.length;r…...

Johnson

理论 全源最短路算法 Floyd 算法&#xff0c;时间复杂度为 O(n)跑 n 次 Bellman - Ford 算法&#xff0c;时间复杂度是 O(nm)跑 n 次 Heap - Dijkstra 算法&#xff0c;时间复杂度是 O(nmlogm) 第 3 种算法被 Johnson 做了改造&#xff0c;可以求解带负权边的全源最短路。 J…...

spring boot + Prometheus + Grafana 实现项目监控

一、引入依赖 <dependencies><!-- Spring Boot Starter Actuator --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- Micrometer Reg…...

Mythical Beings:第八季即将回归,探索新的神话传承

Mythical Beings是由Tarasca Art & Games开发的、基于Ignis区块链的卡牌收集游戏。自发布以来&#xff0c;这款游戏以其独特的玩法和深厚的神话背景吸引了大量玩家的关注。每张卡牌不仅代表着独特的游戏属性&#xff0c;还融合了丰富的文化和神话故事&#xff0c;使玩家不仅…...

Linux中查看占用端口号的进程信息的方法

在 Linux 中查看占用 ** 端口&#xff08;eg:1717&#xff09;**的进程号&#xff08;PID&#xff09;&#xff0c;可以通过以下命令实现&#xff1a; 方法 1&#xff1a;使用 netstat 命令 sudo netstat -tulnp | grep :1717参数解释&#xff1a; -t&#xff1a;查看 TCP 端口…...

批量将 txt/html/json/xml/csv 等文本拆分成多个文件

我们的文本文件太大的时候&#xff0c;我们通常需要对文本文件进行拆分&#xff0c;比如按多少行一个文件将一个大的文本文件拆分成多个小的文本文件。这样我们在打开或者传输的时候都比较方便。今天就给大家介绍一种同时对多个文本文件进行批量拆分的方法&#xff0c;可以快速…...

爱普生高精度车规晶振助力激光雷达自动驾驶

在自动驾驶技术快速落地的今天&#xff0c;激光雷达作为车辆的“智慧之眼”&#xff0c;其测距精度与可靠性直接决定了自动驾驶系统的安全上限。而在这双“眼睛”的核心&#xff0c;爱普生&#xff08;EPSON&#xff09;的高精度车规晶振以卓越性能成为激光雷达实现毫米级感知的…...

Spring Boot 自定义 Redis Starter 开发指南(附动态 TTL 实现)

一、功能概述 本 Starter 基于 Spring Boot 2.7 实现以下核心能力&#xff1a; Redis 增强&#xff1a;标准化 RedisTemplate 配置&#xff08;JSON 序列化 LocalDateTime 支持&#xff09;缓存扩展&#xff1a;支持 Cacheable(value “key#60s”) 语法动态设置 TTL配置集中…...

区分CRI、OCI、containerd、Docker、CRI-O、runc等名词概念

这些概念可以分为&#xff1a; 一、容器运行时Container Runtimes a、规范OCI (Open Container Initiative) 定义&#xff1a;OCI 是一个开放标准&#xff0c;用于定义容器格式和运行时的规范。它旨在确保容器镜像的格式和容器运行时的操作方式在不同的实现之间保持兼容性。 •…...

#关于process.env.NODE_ENV 与 import.meta.env 相关了解

process.env.NODE_ENV 在前端 Vue 项目中非常重要&#xff0c;但它其实是个“假象”&#xff0c;在前端它并不是原生就有的变量。下面我从多个角度来给你通俗讲明白它的由来和使用方式 &#x1f447; &#x1f310; 一、process.env.NODE_ENV 是干嘛用的&#xff1f; 这是 一个…...

R语言赋能气象水文科研:从多维数据处理到学术级可视化

全球气候变化加剧了极端天气与水文事件的复杂性&#xff0c;气象卫星、雷达、地面观测站及水文传感器每天产生TB级‌时空异质数据‌。传统研究常面临四大瓶颈&#xff1a; ‌数据清洗低效‌&#xff1a;缺失值、异常值处理耗时&#xff1b;‌时空分析模型构建复杂‌&#xff1…...

MySQL 约束(入门版)

目录 一、约束的基本概念 二、约束演示 三、外键约束 &#xff08;一&#xff09;介绍 &#xff08;二&#xff09;外键约束语法 &#xff08;三&#xff09;删除/更新行为 一、约束的基本概念 1、概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储…...

【go】类型断言

接口-类型断言 Type Assertion Type Assertion&#xff08;中文名叫&#xff1a;类型断言&#xff09;&#xff0c;通过它可以做到以下几件事情 检查 i 是否为 nil&#xff08;是nil直接抛出panic&#xff09;检查 i 存储的值是否为某个类型 具体的使用方式有两种&#xff…...

(复看)CExercise_06_1指针和数组_2 给定一个double数组,求平均值,并且返回

题目&#xff1a; 求平均值&#xff0c;给定一个double数组&#xff0c;求平均值&#xff0c;并且返回。 要求使用while循环遍历数组&#xff0c;然后配合"*p"的语法实现。 函数的声明如下&#xff1a; double get_ave(double *arr, int len); 关键点 分析&#xff1…...

Ubuntu 服务器上运行相关命令,关闭终端就停止服务,怎么才能启动后在后台运行?

环境&#xff1a; Ubuntu 20.04 LTS 问题描述&#xff1a; Ubuntu 服务器上运行相关命令&#xff0c;关闭终端就停止服务&#xff0c;怎么才能启动后在后台运行&#xff1f; bash docker/entrypoint.sh解决方案&#xff1a; bash docker/entrypoint.sh 脚本在后台运行&…...

ffmpeg提取字幕

使用ffmpeg -i test.mkv 获取视频文件的字幕流信息如下 Stream #0:4(chi): Subtitle: subrip (srt) (default) Metadata: title : chs Stream #0:5(chi): Subtitle: subrip (srt) Metadata: title : cht Stream #0:6(jpn)…...

深入理解Socket编程:构建简单的计算器服务器

一、Socket通信基础 1. Socket通信基本流程 服务器端流程&#xff1a; 创建Socket (socket()) 绑定地址和端口 (bind()) 监听连接 (listen()) 接受连接 (accept()) 数据通信 (read()/write()) 关闭连接 (close()) 客户端流程&#xff1a; 创建Socket (socket()) 连接…...

CPU狂飙900%,该怎么处理

首先&#xff0c;说明一下问题&#xff1a;CPU飙升200% 以上是生产容易发生的场景 场景:1&#xff1a;MySQL进程飙升900% 大家在使用MySQL过程&#xff0c;想必都有遇到过CPU突然过高&#xff0c;或者达到200%以上的情况。 数据库执行查询或数据修改操作时&#xff0c;系统需…...

C++继承完全指南:从语法到设计模式----图解原理+工业级代码示例+陷阱规避

&#x1f52e;✨⚡️&#x1f30c; 欢迎来到张有志的量子编程次元 &#x1f30c;⚡️✨&#x1f52e; ▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ &#x1f6f8; 核心探索舱 &#x1f6f8; ⇩⇩⇩ 正在加载未来代码 ⇩⇩⇩ ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔…...

使用Pholcus编写Go爬虫示例

想用Pholcus库来写一个Go的爬虫程序。首先&#xff0c;我得确认Pholcus的当前状态&#xff0c;因为之前听说过它可能已经不再维护了。不过用户可能还是需要基于这个库的示例&#xff0c;所以得先提供一个基本的框架。 首先&#xff0c;我应该回忆一下Pholcus的基本用法。Pholc…...

R Excel 文件:高效数据处理与可视化工具的完美结合

R Excel 文件&#xff1a;高效数据处理与可视化工具的完美结合 引言 在数据分析和处理领域&#xff0c;R语言因其强大的数据处理能力和丰富的可视化功能而备受青睐。而Excel作为最常用的电子表格软件&#xff0c;其广泛的应用也使得R与Excel的结合成为数据处理与可视化的理想…...

Python设计模式:适配模式

1. 适配模式&#xff08;Adapter Pattern&#xff09;详解 适配模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一种接口。适配模式使得原本由于接口不兼容而无法一起工作的类可以协同工作。换句话说…...

Python设计模式:策略模式

1. 什么是策略模式 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;将每个算法封装起来&#xff0c;并使它们可以互换。策略模式使得算法的变化独立于使用算法的客户。换句话说&#xff0c;策略模式允许在运…...

Unity Internal-ScreenSpaceShadows 分析

一、代码结构 // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)Shader "Hidden/Internal-ScreenSpaceShadows" {Properties {_ShadowMapTexture ("", any) "" {} // 阴影贴图纹理&…...

nginx配置oss代理

工作中会有一些时候需要将图片,视频,音频等文件放到oss这种对象存储中进行存储,实现高性能的访问,这种情况叫做动静分离.这里只做了图片的配置,视频以及音频的配置是一样的. 以下是nginx.conf的配置信息,其中还有ssl的加密配置,以及后端服务器的代理模块配置,(这里不用的话可以…...

UML对象图

UML对象图 一、对象图核心概念 对象图&#xff08;Object Diagram&#xff09;描述的是系统在某一时刻对象&#xff08;实例&#xff09;的状态快照。它关注的是实际对象之间的实例关系&#xff0c;而不是类与类之间的静态结构。主要特点有&#xff1a; ​对象&#xff08;Ob…...

手机不同App音量自动调节软件

软件介绍 在日常使用手机的过程中&#xff0c;大家是不是经常会遇到在不同App之间切换时&#xff0c;需要频繁调整音量的情况呢&#xff1f;这样真的很不方便。而一款名为App Volume Control的软件就能很好地解决这个问题。 App Volume Control借助辅助功能服务&#xff0c;能…...

模板方法模式详解

模板方法模式详解及真实场景解决方案 推荐学习完策略模式和模板方法模式看这个案例&#xff1a; 策略与模板方法模式组合详解 模式定义 模板方法模式是一种行为设计模式&#xff0c;在父类中定义算法的骨架&#xff0c;允许子类在不改变算法结构的情况下重写特定步骤。核心思…...

基于SSM邮件收发管理系统(带源码、论文)

摘要 随着互联网技术的迅速发展和普及&#xff0c;网络通信已经成了人们离不开的通信手段。作为最早出现的网络通信方式还有世界上应用最为广泛的网络服务之一&#xff0c;电子邮件综合了电话通信和传统邮件的特点&#xff0c;具有传播速度快、价格低廉的优良特性。随着技术发…...

1990-2019年各地级市GDP数据

1990-2019年各地级市GDP数据 1、时间&#xff1a;1990-2019年 2、来源&#xff1a;城市年鉴 3、指标&#xff1a;行政区划代码、年份、省份、城市、经度、纬度、地区生产总值(万元) 4、范围&#xff1a;250地级市 5、指标解释&#xff1a;地区生产总值&#xff08;Gross R…...

Scala相关知识学习总结5

1、多维数组 定义&#xff1a; val arr Array.ofDim[Double](3,4) 表示二维数组中有三个一维数组&#xff0c;每个一维数组有四个元素。 2、列表 List 不可变 List&#xff1a;默认不可变&#xff0c;可创建有序且可重复的列表&#xff0c;可使用:从右向左增加数据&#xf…...

【LangChain Agent 】详解,构建自主决策的 LLM 应用

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《深度探秘&#xff1a;AI界的007》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是 Lang Chain 2、什么是 Agent 二、LangChain …...

Scala基础知识7

一&#xff0c;可变数组和不可变数组的转换方法: 不可变数组转换为可变数组使用 toBuffer 函数. 可变数组转换为不可变数组使用 toArray 函数。 转换过程中原始数组不会发生变化&#xff0c;而是返回一个新的数组。 二&#xff0c;多维数组 使用 Array of 函数创建多维数组&am…...

vmware、centos: 快照、redis集群克隆、启动异常

问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 启动虚拟机报错&#xff1a; 指定的虚拟磁盘需要进行修复 打不开磁盘“D:\Virtual Machines\CentOS 7 64 位\CentOS 7 64 位-000001.vmdk”或它所依赖的某个快照磁盘。 模块“Disk”启动失败。 未能启动虚拟机…...

visual studio断点无法进入

问题背景&#xff1a; 使用VSQt进行编码&#xff0c;新增函数处断点无法进入。 问题排查 查看moc文件&#xff0c;汇编代码以及设置调试选项均不生效。 原因分析 之前无意间进行了排版优化&#xff0c;导致新增的代码未正常编译进去&#xff0c;通过“文件-> 高级保存选…...

CNVD-2025-06046:Google Chrome沙箱逃逸漏洞大揭秘与防护指南

CNVD-2025-06046&#xff1a;Google Chrome沙箱逃逸漏洞大揭秘与防护指南 前言&#xff1a;浏览器界的“越狱”事件 嘿&#xff0c;小伙伴们&#xff01;今天咱们要聊的不是什么好莱坞大片&#xff0c;而是一出在浏览器世界里真实上演的“越狱”大戏&#xff01;你没听错&…...

androd的XML页面 跳转 Compose Activity 卡顿问题

解决 XML 点击跳转到 Compose Activity 卡顿问题 当从 XML 布局的 Activity 跳转到 Compose Activity 时出现卡顿现象&#xff0c;这通常是由以下几个原因导致的&#xff1a; 可能的原因及解决方案 1. Compose 首次初始化开销 问题&#xff1a;Compose 框架首次初始化需要时…...

Springboot同时支持不同的数据库,Oracle,Postgresql

关键字 Java&#xff0c;Springboot&#xff0c;Vscode&#xff0c;支持多种数据库 背景环境 我在实际项目开发工程中遇到这样一个问题&#xff0c;用户 A 使用 Oracle 数据库&#xff0c;用户 B 使用 Postgresql 数据库&#xff0c;但是用户 AB 都使用我们的项目。所以项目…...

【计网】TCP协议的拥塞控制与流量控制

拥塞控制与流量控制的区别 流量控制 流量控制主要是控制端到端&#xff08;发送端和接收端&#xff09;之间的数据传输量&#xff0c;是局部的机制。 目的&#xff1a;防止发送方发送数据过快导致接收方来不及处理实现方式&#xff1a;通过滑动窗口机制&#xff0c;接收方通…...

Redis - 字典(Hash)结构和 rehash 机制

字典结构 Redis中的字典由dict.h/dict结构表示: typedef struct dict ( //类型特定函数dictType *type;//私有数据 void "privdata;//哈希表 dictht ht[2];//rehash索引 //当rehash不在进行时,值为-1 in trehashidx; } dict; Redis字典所使用的哈希表由dict.h/dictht 结…...

Redis 与 MongoDB 对比分析

Redis 与 MongoDB 对比分析 1. 核心定位 Redis&#xff1a;内存键值数据库&#xff0c;侧重高性能读写和低延迟&#xff0c;常用于缓存、实时分析、消息队列等场景。MongoDB&#xff1a;分布式文档型数据库&#xff0c;侧重灵活的数据模型和大规模数据存储&#xff0c;支持复…...

【愚公系列】《高效使用DeepSeek》058-选题策划

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...

解决 Lettuce 在 Redis 集群模式下的故障转移问题

引言 在高可用系统中&#xff0c;故障转移是确保服务不中断的重要机制。当我们使用 Lettuce 作为 Redis 的 Java 客户端时&#xff0c;如何高效地处理故障转移成为一项关键任务。本篇文章将探讨如何在 Redis 集群模式下配置 Lettuce 以优化故障转移。 背景 在初期设置 Lettu…...

Vim搜索和替换

模式 命令模式 操作过程 键入/开始搜索&#xff0c;找到想要搜索的内容后直接回车&#xff0c;此时光标会从搜索框回到编辑器中。 之后可以 使用小写n跳到下一个符合条件的内容&#xff0c;使用大写N跳到上一个搜索的内容。也可以直接使用上下左右按钮调整光标位置。...