Actor-Critic方法【A2C,A3C,Policy Gradient】

强化学习笔记系列目录

第一章 强化学习基本概念
第二章 贝尔曼方程
第三章 贝尔曼最优方程
第四章 值迭代和策略迭代
第五章 强化学习实例分析:GridWorld
第六章 蒙特卡洛方法
第七章 Robbins-Monro算法
第八章 多臂老虎机
第九章 强化学习实例分析:CartPole
第十章 时序差分法
第十一章 值函数近似【DQN】
第十二章 基于强化学习DQN的股票预测
第十三章 策略梯度方法
第十四章 Actor-Critic 方法


文章目录

  • 强化学习笔记系列目录
  • 一、基本思想
  • 二、Advantage Actor-Critic (A2C)
    • 1 基线策略
    • 2 A2C算法
  • 三、A3C
  • 参考资料


本文主要基于b站西湖大学赵世钰老师的【强化学习的数学原理】课程,个人觉得赵老师的课件深入浅出,很适合入门.

上一章,在 策略梯度方法 中我们介绍了策略梯度的基本思想,以及最重要的策略梯度定理,并且介绍了一个利用策略梯度求最优策略的算法——REINFORCE.本文继续介绍基于策略梯度的其他算法——Actor-Critic算法【A2C,A3C等】.

一、基本思想

我们知道用于最大化 J ( θ ) J(\theta) J(θ) 的梯度上升算法为

θ t + 1 = θ t + α ∇ θ J ( θ t ) = θ t + α E [ ∇ θ ln ⁡ π ( A ∣ S , θ t ) q π ( S , A ) ] , (1) \begin{aligned} \theta_{t+1} &= \theta_{t} + \alpha \nabla_{\theta} J(\theta_{t})\\ &= \theta_{t} + \alpha \mathbb{E} \left[ \nabla_{\theta} \ln \pi(A | S, \theta_{t}) q_{\pi}(S, A) \right], \end{aligned} \tag{1} θt+1=θt+αθJ(θt)=θt+αE[θlnπ(AS,θt)qπ(S,A)],(1)
其中 α > 0 \alpha > 0 α>0 是一个常数学习率。由于上式中的真实梯度未知(期望不好直接获得),我们可以用随机梯度替代真实梯度,以获得以下算法:
θ t + 1 = θ t + α ∇ θ ln ⁡ π ( a t ∣ s t , θ t ) q t ( s t , a t ) , (2) \theta_{t+1} = \theta_{t} + \alpha \nabla_{\theta} \ln \pi(a_{t} | s_{t}, \theta_{t}) q_{t}(s_{t}, a_{t}), \tag{2} θt+1=θt+αθlnπ(atst,θt)qt(st,at),(2)
其中 q t ( s t , a t ) q_{t}(s_{t}, a_{t}) qt(st,at) q π ( s t , a t ) q_{\pi}(s_{t}, a_{t}) qπ(st,at) 的一个近似值。在前面介绍的 REINFORCE 算法中,我们是通过蒙特卡洛方法来进行采样,每次需要根据一个策略采集一条完整的轨迹,并计算这条轨迹上的回报。我们也指出这种采样方式的方差比较大,学习效率也比较低。我们可以借鉴时序差分学习的思想,使用动态规划方法来提高采样效率,即从状态 s 开始的总回报可以通过当前动作的即时奖励 r ( s , a , s ′ ) r(s,a,s') r(s,a,s) 和下一个状态 s ′ s' s的值函数来近似估计。

Actor-Critic算法是一种结合策略梯度和时序差分学习的强化学习方法,其中:

  • 演员是指策略函数 π θ \pi_\theta πθ,即学习一个策略以得到尽可能高的回报。
  • 评论员是指值函数( v ( s ) v(s) v(s) q ( s , a ) q(s,a) q(s,a)),对当前策略的值函数进行估计,即评估演员的好坏。借助于价值函数,演员-评论员算法可以进行单步参数更新,不需要等到回合结束才进行更新。

Actor-Critic算法示意图如下(图源1):

img

最简单的actor-critic算法的流程如下面的伪代码所示(图源2):

截屏2024-11-07 11.02.50其中:

  • Actor同REINFORCE算法中策略更新步骤一样,根据采样,更新参数 θ \theta θ.
  • Critic对应于通过Sarsa算法执行的动作值值更新步骤,动作值函数由一个参数化的函数 q ( s , a , w ) q(s, a, w) q(s,a,w)表示.
  • 可以看到这个算法和REINFORCE算法的唯一区别就是将对 q q q值的估计,由蒙特卡洛方法,换成了TD方法.

该actor-critic算法有时被称为Q actor-critic(QAC)。尽管它很简单,但QAC揭示了actor-critic方法的核心思想,它可以扩展为许多高级算法.

二、Advantage Actor-Critic (A2C)

1 基线策略

策略梯度一个有趣的性质是加入额外的基线函数,梯度期望是不变的,也就是说:

E S ∼ η , A ∼ π [ ∇ θ ln ⁡ π ( A ∣ S , θ t ) q π ( S , A ) ] = E S ∼ η , A ∼ π [ ∇ θ ln ⁡ π ( A ∣ S , θ t ) ( q π ( S , A ) − b ( S ) ) ] , \mathbb{E}_{S \sim \eta, A \sim \pi} \left[ \nabla_\theta \ln \pi(A|S, \theta_t) q_\pi(S, A) \right] = \mathbb{E}_{S \sim \eta, A \sim \pi} \left[ \nabla_\theta \ln \pi(A|S, \theta_t) (q_\pi(S, A) - b(S)) \right], ESη,Aπ[θlnπ(AS,θt)qπ(S,A)]=ESη,Aπ[θlnπ(AS,θt)(qπ(S,A)b(S))],

其中,基线函数 b ( S ) b(S) b(S) 是关于 S S S 的标量函数。上面等式成立当且仅当

E S ∼ η , A ∼ π [ ∇ θ ln ⁡ π ( A ∣ S , θ t ) b ( S ) ] = 0. \mathbb{E}_{S \sim \eta, A \sim \pi} \left[ \nabla_\theta \ln \pi(A|S, \theta_t) b(S) \right] = 0. ESη,Aπ[θlnπ(AS,θt)b(S)]=0.

该等式成立是因为:

E S ∼ η , A ∼ π [ ∇ θ ln ⁡ π ( A ∣ S , θ t ) b ( S ) ] = ∑ s ∈ S η ( s ) ∑ a ∈ A π ( a ∣ s , θ t ) ∇ θ ln ⁡ π ( a ∣ s , θ t ) b ( s ) = ∑ s ∈ S η ( s ) ∑ a ∈ A ∇ θ π ( a ∣ s , θ t ) b ( s ) = ∑ s ∈ S η ( s ) b ( s ) ∑ a ∈ A ∇ θ π ( a ∣ s , θ t ) = ∑ s ∈ S η ( s ) b ( s ) ∇ θ ∑ a ∈ A π ( a ∣ s , θ t ) = ∑ s ∈ S η ( s ) b ( s ) ∇ θ 1 = 0. \begin{aligned} \mathbb{E}_{S \sim \eta, A \sim \pi} \left[ \nabla_\theta \ln \pi(A|S, \theta_t) b(S) \right] &= \sum_{s \in \mathcal{S}} \eta(s) \sum_{a \in \mathcal{A}} \pi(a|s, \theta_t) \nabla_\theta \ln \pi(a|s, \theta_t) b(s) \\ &= \sum_{s \in \mathcal{S}} \eta(s) \sum_{a \in \mathcal{A}} \nabla_\theta \pi(a|s, \theta_t) b(s) \\ & = \sum_{s \in \mathcal{S}} \eta(s) b(s) \sum_{a \in \mathcal{A}} \nabla_\theta \pi(a|s, \theta_t) \\ & = \sum_{s \in \mathcal{S}} \eta(s) b(s) \nabla_\theta \sum_{a \in \mathcal{A}} \pi(a|s, \theta_t)\\ & = \sum_{s \in \mathcal{S}} \eta(s) b(s) \nabla_\theta 1 = 0. \end{aligned} ESη,Aπ[θlnπ(AS,θt)b(S)]=sSη(s)aAπ(as,θt)θlnπ(as,θt)b(s)=sSη(s)aAθπ(as,θt)b(s)=sSη(s)b(s)aAθπ(as,θt)=sSη(s)b(s)θaAπ(as,θt)=sSη(s)b(s)θ1=0.
基线函数有什么用呢?引入基线函数可以减少使用样本逼近真实梯度时的近似方差。我们令
X ( S , A ) ≐ ∇ θ ln ⁡ π ( A ∣ S , θ t ) [ q π ( S , A ) − b ( S ) ] . X(S, A) \doteq \nabla_\theta \ln \pi(A|S, \theta_t) [q_\pi(S, A) - b(S)]. X(S,A)θlnπ(AS,θt)[qπ(S,A)b(S)].

我们知道真实梯度是 E [ X ( S , A ) ] \mathbb{E}[X(S, A)] E[X(S,A)]。但是这个期望不好求,在REINFORCE算法和QAC算法中,我们都是采样来近似这个期望。由于我们需要使用一个随机样本 x x x 来逼近 E [ X ] \mathbb{E}[X] E[X],我们希望方差 var ⁡ ( X ) \operatorname{var}(X) var(X) 越小越好。原因如下:

  • 如果 var ⁡ ( X ) \operatorname{var}(X) var(X) 接近零(样本都在期望值附近波动),那么任何样本 x x x 都可以比较准确地逼近 E [ X ] \mathbb{E}[X] E[X].
  • 相反,如果 var ⁡ ( X ) \operatorname{var}(X) var(X) 很大,则样本值可能会与 E [ X ] \mathbb{E}[X] E[X] 相差很远,也就是说方差大,样本离期望(均值)的波动更大.

因为刚刚我们证明了 E [ X ] \mathbb{E}[X] E[X] 对加入基线函数是不变的,但方差 var ⁡ ( X ) \operatorname{var}(X) var(X) 并非如此。所以我们需要设计一个好的基线函数以最小化 var ⁡ ( X ) \operatorname{var}(X) var(X)。在 REINFORCE 和 QAC 算法中,我们设定 b = 0 b = 0 b=0,但这并是一个好的基线函数。事实上,最小化 var ⁡ ( X ) \operatorname{var}(X) var(X) 的最优基线函数是

b ∗ ( s ) = E A ∼ π [ ∥ ∇ θ ln ⁡ π ( A ∣ s , θ t ) ∥ 2 q π ( s , A ) ] E A ∼ π [ ∥ ∇ θ ln ⁡ π ( A ∣ s , θ t ) ∥ 2 ] , s ∈ S . b^*(s) = \frac{\mathbb{E}_{A \sim \pi} \left[ \|\nabla_\theta \ln \pi(A|s, \theta_t)\|^2 q_\pi(s, A) \right]}{\mathbb{E}_{A \sim \pi} \left[ \|\nabla_\theta \ln \pi(A|s, \theta_t)\|^2 \right]}, \quad s \in \mathcal{S}. b(s)=EAπ[θlnπ(As,θt)2]EAπ[θlnπ(As,θt)2qπ(s,A)],sS.

证明见参考资料2的第10章.尽管上式给出的基线函数是最优的,但它过于复杂在实际中无法使用。如果去掉公式中的权重 ∥ ∇ θ ln ⁡ π ( A ∣ s , θ t ) ∥ 2 \|\nabla_\theta \ln \pi(A|s, \theta_t)\|^2 θlnπ(As,θt)2,我们可以得到一个具有简洁表达式的次优基线函数:

b † ( s ) = E A ∼ π [ q π ( s , A ) ] = v π ( s ) , s ∈ S . b^\dagger(s) = \mathbb{E}_{A \sim \pi} [q_\pi(s, A)] = v_\pi(s), \quad s \in \mathcal{S}. b(s)=EAπ[qπ(s,A)]=vπ(s),sS.

可以发现,这个次优基线函数即为状态值函数!

2 A2C算法

b ( s ) = v π ( s ) b(s) = v_\pi(s) b(s)=vπ(s) 时,梯度上升算法(1)变为

θ t + 1 = θ t + α E [ ∇ θ ln ⁡ π ( A ∣ S , θ t ) [ q π ( S , A ) − v π ( S ) ] ] = θ t + α E [ ∇ θ ln ⁡ π ( A ∣ S , θ t ) δ π ( S , A ) ] . (3) \begin{aligned} \theta_{t+1} &= \theta_t + \alpha \mathbb{E} \left[ \nabla_\theta \ln \pi(A|S, \theta_t) [q_\pi(S, A) - v_\pi(S)] \right]\\ &= \theta_t + \alpha \mathbb{E} \left[ \nabla_\theta \ln \pi(A|S, \theta_t) \delta_\pi(S, A) \right]. \end{aligned} \tag{3} θt+1=θt+αE[θlnπ(AS,θt)[qπ(S,A)vπ(S)]]=θt+αE[θlnπ(AS,θt)δπ(S,A)].(3)

其中,

δ π ( S , A ) ≐ q π ( S , A ) − v π ( S ) \delta_\pi(S, A) \doteq q_\pi(S, A) - v_\pi(S) δπ(S,A)qπ(S,A)vπ(S)

被称为优势函数,它反映了一个动作相对于其他动作的优势。更具体地,注意到
v π ( s ) = ∑ a ∈ A π ( a ∣ s ) q π ( s , a ) v_\pi(s) = \sum_{a \in \mathcal{A}} \pi(a|s) q_\pi(s, a) vπ(s)=aAπ(as)qπ(s,a)
是动作值的均值。如果 δ π ( s , a ) > 0 \delta_\pi(s, a) > 0 δπ(s,a)>0则意味着相应的动作具有高于均值的价值。

公式 (3) 的随机版本是

θ t + 1 = θ t + α ∇ θ ln ⁡ π ( a t ∣ s t , θ t ) [ q t ( s t , a t ) − v t ( s t ) ] = θ t + α ∇ θ ln ⁡ π ( a t ∣ s t , θ t ) δ t ( s t , a t ) , (4) \begin{aligned} \theta_{t+1} &= \theta_t + \alpha \nabla_\theta \ln \pi(a_t|s_t, \theta_t) [q_t(s_t, a_t) - v_t(s_t)]\\ &=\theta_t + \alpha \nabla_\theta \ln \pi(a_t|s_t, \theta_t) \delta_t(s_t, a_t), \end{aligned} \tag{4} θt+1=θt+αθlnπ(atst,θt)[qt(st,at)vt(st)]=θt+αθlnπ(atst,θt)δt(st,at),(4)

其中, s t , a t s_t, a_t st,at 是时刻 t t t S , A S, A S,A 的样本。 q t ( s t , a t ) q_t(s_t, a_t) qt(st,at) v t ( s t ) v_t(s_t) vt(st) 分别是 q π ( s t , a t ) q_\pi(s_t, a_t) qπ(st,at) v π ( s t ) v_\pi(s_t) vπ(st) 的近似值。公式 (4) 中的算法根据 q t q_t qt 相对于 v t v_t vt 的相对值更新策略,而不是 q t q_t qt 的绝对值。这在直觉上是合理的,因为当我们尝试在一个状态上选择一个动作时,我们只关心相对于其他动作具有最大价值的动作。

  • 如果 q t ( s t , a t ) q_t(s_t, a_t) qt(st,at) v t ( s t ) v_t(s_t) vt(st) 是通过蒙特卡洛学习估计的,那么公式 (4) 中的算法被称为带基线的 REINFORCE算法.
  • 如果 q t ( s t , a t ) q_t(s_t, a_t) qt(st,at) v t ( s t ) v_t(s_t) vt(st) 是通过 TD 学习估计的,则该算法通常称为Avantage Actor-Critic(A2C).

A2C 算法的伪代码如下所示(图源2):

截屏2024-11-07 12.35.23需要注意的是,此实现中的优势函数是通过 TD Error(什么是TD Error可以参考我的这篇博客:强化学习:时序差分法)近似的:
q t ( s t , a t ) − v t ( s t ) ≈ r t + 1 + γ v t ( s t + 1 ) − v t ( s t ) . (5) q_t(s_t, a_t) - v_t(s_t) \approx r_{t+1} + \gamma v_t(s_{t+1}) - v_t(s_t). \tag{5} qt(st,at)vt(st)rt+1+γvt(st+1)vt(st).(5)

该近似是合理的,因为

q π ( s t , a t ) − v π ( s t ) = E [ R t + 1 + γ v π ( S t + 1 ) − v π ( S t ) ∣ S t = s t , A t = a t ] , (6) q_\pi(s_t, a_t) - v_\pi(s_t) = \mathbb{E} \left[ R_{t+1} + \gamma v_\pi(S_{t+1}) - v_\pi(S_t) \bigg| S_t = s_t, A_t = a_t \right],\tag{6} qπ(st,at)vπ(st)=E[Rt+1+γvπ(St+1)vπ(St) St=st,At=at],(6)

该公式根据 q π ( s t , a t ) q_\pi(s_t, a_t) qπ(st,at) 的定义(动作值函数的贝尔曼方程)是成立的。所以公式(5)相当于公式(6)的一个采样样本来近似期望。

使用 TD Error近似优势函数一个好处是我们只需要使用一个神经网络来表示 v π ( s ) v_\pi(s) vπ(s)。否则,如果 δ t = q t ( s t , a t ) − v t ( s t ) \delta_t = q_t(s_t, a_t) - v_t(s_t) δt=qt(st,at)vt(st),则我们需要维护两个网络来表示 v π ( s ) v_\pi(s) vπ(s) q π ( s , a ) q_\pi(s, a) qπ(s,a)。当我们使用 TD Error时,该算法可能也被称为 TD Actor Critic.此外,值得注意的是,策略 π ( θ ) \pi(\theta) π(θ) 是随机的,因此具有探索性。

三、A3C

下面介绍异步优势动作评价(Asynchronous Advantage Actor Critic,A3C)算法,本质是异步的A2C方法.

A3C算法示意图如下,其思想非常像分布式学习和联邦学习

  • 维护一个全局网络,全局网络包含策略网络和价值网络.
  • 有多个进程(或者说worker),每一个进程在工作前都会把全局网络的参数复制过来
    • 接下来演员就与环境交互,每一个演员与环境交互的时候,都要收集到比较多样的数据。例如,如果是走迷宫,可能每一个演员起始的位置都不一样,这样它们能够收集到比较多样的数据。
    • 每一个演员与环境交互完之后,我们就会计算出梯度。计算出梯度以后,要用梯度去更新参数。
    • 就是这个进程算出梯度以后,就把梯度传回给中央的控制中心,中央的控制中心就会用这个梯度去更新原来的参数。

img

注意,A3C使用了平行探索的方法,所有的演员都是平行跑的,每一个演员各做各的,不管彼此。所以每个演员都是去要了一个参数以后,做完就把梯度传回去。当第一个进程做完想要把梯度传回去的时候,本来它是根据 θ 1 \theta_1 θ1求得的梯度,等它要把梯度传回去的时候,可能别人已经把原来的参数覆盖掉,网络已经变成 θ 2 \theta_2 θ2了。但是没有关系,我们利用这个梯度在 θ 2 \theta_2 θ2的基础上进行更新。

下图是A3C的对比实验3

image-20241107141757488

a single Nvidia K40 GPU while the asynchronous methods were trained using 16 CPU cores

可以看到A3C效率确实会高很多!

参考资料


  1. 王琦,杨毅远,江季,Easy RL:强化学习教程,人民邮电出版社,https://github.com/datawhalechina/easy-rl. ↩︎

  2. Zhao, S… Mathematical Foundations of Reinforcement Learning. Springer Nature Press and Tsinghua University Press. ↩︎ ↩︎ ↩︎

  3. Volodymyr Mnih et al. Asynchronous Methods for Deep Reinforcement Learning. NIPS 2016. ↩︎

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

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

相关文章

若依管理系统使用已有 Nacos 部署流程整理

背景 玩了一下开源项目 RuoYi 管理系统Cloud 版,卡住的地方是:它用到了 nacos 配置管理,如果用的 nacos 环境是单机且是内置数据库的话,该怎么配置呢? 本文整理本机启动 RuoYi Cloud 应用本地部署的过程,…

数字信号处理-FPGA插入不同误码率的模拟源

module data_error_injector (input clk, // 时钟信号,50MHzinput reset, // 复位信号,高有效input DIN_EN, // 数据输入使能,高有效input [7:0] ERROR_LEVEL, // 错误等级…

对称二叉树(力扣101)

题目如下: 思路 对于这道题, 我会采用递归的解法. 看着对称的二叉树, 写下判断对称的条件, 再进入递归即可. 值得注意的是, 代码中会有两个函数, 第一个是isSymmetric,第二个是judge. 因为这里会考虑到一种特殊情况, 那就是 二叉树的根结点(最上面的那个),它会单独用…

山东布谷科技:关于直播源码|语音源码|一对一直播源码提交App Store的流程及重构建议

自从YY、六间房开启国内聊天室和秀场等网红盛行的网络红利时代以来,紧随其后国内各大音视频平台相应出现,先有映客花椒等直播平台的风头正劲,后有功能板块更丰富的头条抖音Tiktok等,盈利功能点不仅仅有直播PK连麦等礼物打赏功能&a…

k8s图形化显示(KRM)

在master节点 kubectl get po -n kube-system 这个命令会列出 kube-system 命名空间中的所有 Pod 的状态和相关信息,比如名称、状态、重启次数等。 systemctl status kubelet #查看kubelet状态 yum install git #下载git命令 git clone https://gitee.com/duk…

ArcGIS地理空间平台 manager 任意文件读取漏洞复现

0x01 产品描述: ‌ ArcGIS‌是一个综合的地理空间平台,由Esri开发,旨在为专业人士和组织提供全面的地理信息系统(GIS)功能。ArcGIS通过集成和连接地理环境中的数据,支持创建、管理、分析、映射和共享…

【Rust实现命令模式】

Rust实现命令模式 什么是命令模式命令模式的应用场景命令模式的在Rust中的关系图Rust中的命令模式代码示例运行结果总结 什么是命令模式 命令模式,即通过统一接口,如C#interface,亦或C中的抽象类的0方法,通过定义统一的接口,在定义不同的对象,为之接口实现具体的方法逻辑,再通…

【学术论文投稿】React全攻略:构建高性能前端应用的黄金法则

第六届国际科技创新学术交流大会暨管理科学信息化与经济创新发展学术会议(MSIEID 2024)_艾思科蓝_学术一站式服务平台 更多学术会议论文投稿请看:https://ais.cn/u/nuyAF3 目录 引言 1. React简介 2. React的三大核心概念 2.1 JSX 2.2…

鸿蒙应用App测试-专项测试(DevEco Testing)

注意:大家记得先学通用测试在学专项测试 鸿蒙应用App测试-通用测试-CSDN博客 注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注&am…

AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。

2024-10-31,由清华大学和北京大学共同创建的AndroidLab数据集,为安卓自主代理的训练和评估提供了一个包含操作环境、行动空间和可复现基准的系统框架,这对于推动安卓代理技术的发展具有重要意义。 数据集地址:Android Instruct|A…

如何在算家云搭建Aatrox-Bert-VITS2(音频生成)

一、模型介绍 ‌ Aatrox - Bert -VITS2 模型是一种基于深度学习的语音合成系统,结合了 BERT 的预训练能力和 VITS2 的微调技术,旨在实现高质量的个性化语音合成。 二、模型搭建流程 1. 创建容器实例 进入算家云的“应用社区”,点击搜索找到…

OpenEuler 使用ffmpeg x11grab捕获屏幕流,rtsp推流,并用vlc播放

环境准备 安装x11grab(用于捕获屏幕流)和libx264(用于编码) # 基础开发环境&x11grab sudo dnf install -y \autoconf \automake \bzip2 \bzip2-devel \cmake \freetype-devel \gcc \gcc-c \git \libtool \make \mercurial \pkgconfig \zlib-devel \libX11-devel \libXext…

QCustomPlot添加自定义的图例,实现隐藏、删除功能(二)

文章目录 QCustomPlot初识和基本效果图实现步骤:详细代码示例:实现原理和解释:使用方法:其他参考要实现一个支持复选框来控制曲线显示和隐藏的自定义 QCPLegend 类,可以通过继承 QCPLegend 并重写绘制和事件处理方法来实现,同时发出信号通知曲线的状态变更。 QCustomPl…

聊一聊Elasticsearch的基本原理与形成机制

1、搜索引擎的基本原理 通常搜索引擎包括:数据采集、文本分析、索引存储、搜索等模块,它们之间的协作流程如下图: 数据采集模块负责采集需要搜索的数据源。 文本分析模块是将结构化数据中的长文本切分成有实际意义的词,这样用户…

PyCharm 导入本地包目录

PyCharm 是最新版 声明一下是野路子 现在我工程目录下有个 gen-py 文件夹,这是我 thrift 编译出来的 Python 依赖包 使用的话,我们可以在代码里加入系统路径 sys.path.append("./gen-py/") 但是这样写,PyCharm 没有提示&#…

80端口被进程 System PID=4 IIS导致的解决方法

是因为80端口被IIS占用。解决办法打开IIS管理器,然后停止:

异步4位计数器(Quartus与Modelsim联合仿真)

异步计数器(也称为ripple-through counter)的特点是每一位触发器的输出作为下一位触发器的时钟输入,因此计数速度会因为级联触发器的传播延迟而受到限制。这种计数器的最大工作频率通常低于同步计数器。 一、电路符号 输入信号:时…

若依cloud版集成微信扫码登录-绑定篇

前言 集成微信扫码登录的话,需要把项目的账号和微信账号进行绑定,然后才可以进行扫码登录 本篇内容是项目绑定微信 还需要申请一个微信开放平台账号 微信公众平台申请(测试平台)-CSDN博客 平台的项目回调接口可以先不写&…

鸿蒙应用App测试-通用测试

注意:大家记得学完通用测试记得再学鸿蒙专项测试 鸿蒙应用App测试-专项测试(DevEco Testing)-CSDN博客 注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得…

Linux 配置JDK

文章目录 一、下载Oracle-JDK1.1、如何正确的下载JDK二、配置JDK环境变量2.1 环境变量配置2.1.1、修改vim /etc/profile 添加jdk的路径一、下载Oracle-JDK 1.1、如何正确的下载JDK 首先我要安装的是oracle-jdk,这个时候什么地方都不要去,就去oracle的官网,然后找到,jdk的下…