RNN中远距离时间步梯度消失问题及解决办法

RNN中远距离时间步梯度消失问题及解决办法

  • RNN 远距离时间步梯度消失问题
  • LSTM如何解决远距离时间步梯度消失问题


RNN 远距离时间步梯度消失问题

经典的RNN结构如下图所示:
在这里插入图片描述
假设我们的时间序列只有三段, S 0 S_{0} S0 为给定值,神经元没有激活函数,则RNN最简单的前向传播过程如下:

S 1 = W x X 1 + W s S 0 + b 1 , O 1 = W 0 S 1 + b 2 S_{1} = W_{x} X_{1} + W_{s}S_{0} + b_{1},O_{1} = W_{0} S_{1} + b_{2} S1=WxX1+WsS0+b1O1=W0S1+b2

S 2 = W x X 2 + W s S 1 + b 1 , O 2 = W 0 S 2 + b 2 S_{2} = W_{x} X_{2} + W_{s}S_{1} + b_{1},O_{2} = W_{0} S_{2} + b_{2} S2=WxX2+WsS1+b1O2=W0S2+b2

S 3 = W x X 3 + W s S 2 + b 1 , O 3 = W 0 S 3 + b 2 S_{3} = W_{x} X_{3} + W_{s}S_{2} + b_{1},O_{3} = W_{0} S_{3} + b_{2} S3=WxX3+WsS2+b1O3=W0S3+b2

假设在 t = 3 t=3 t=3时刻,损失函数为 L 3 = 1 2 ( Y 3 − O 3 ) 2 L_3 = \frac{1}{2}(Y_3 - O_3)^2 L3=21(Y3O3)2 。则对于一次训练任务的损失函数为 L = ∑ t = 0 T L t L = \sum_{t=0}^{T} L_t L=t=0TLt ,即每一时刻损失值的累加。

使用随机梯度下降法训练RNN其实就是对 W x W_x Wx W s W_s Ws W o W_o Wo 以及 b 1 、 b 2 b_1 、 b_2 b1b2 求偏导,并不断调整它们以使 L L L尽可能达到最小的过程。

现在假设我们我们的时间序列只有三段:t1,t2,t3。我们只对 t 3 t3 t3时刻的 W x W_x Wx W s W_s Ws W o W_o Wo 求偏导(其他时刻类似):

∂ L 3 ∂ W 0 = ∂ L 3 ∂ O 3 ∂ O 3 ∂ W o = ∂ L 3 ∂ O 3 S 3 \frac{\partial L_3}{\partial W_0} = \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial W_o} = \frac{\partial L_3}{\partial O_3} S_3 W0L3=O3L3WoO3=O3L3S3

∂ L 3 ∂ W x = ∂ L 3 ∂ O 3 ∂ O 3 ∂ S 3 ∂ S 3 ∂ W x + ∂ L 3 ∂ O 3 ∂ O 3 ∂ S 3 ∂ S 3 ∂ S 2 ∂ S 2 ∂ W x + ∂ L 3 ∂ O 3 ∂ O 3 ∂ S 3 ∂ S 3 ∂ S 2 ∂ S 2 ∂ S 1 ∂ S 1 ∂ W x = ∂ L 3 ∂ O 3 W 0 ( X 3 + S 2 W s + S 1 W s 2 ) \frac{\partial L_3}{\partial W_x} = \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial W_x} + \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial W_x} + \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial S_1} \frac{\partial S_1}{\partial W_x} = \frac{\partial L_3}{\partial O_3} W_0 (X_3 + S_2 W_s + S_1 W_s^2) WxL3=O3L3S3O3WxS3+O3L3S3O3S2S3WxS2+O3L3S3O3S2S3S1S2WxS1=O3L3W0(X3+S2Ws+S1Ws2)

∂ L 3 ∂ W s = ∂ L 3 ∂ O 3 ∂ O 3 ∂ S 3 ∂ S 3 ∂ W s + ∂ L 3 ∂ O 3 ∂ O 3 ∂ S 3 ∂ S 3 ∂ S 2 ∂ S 2 ∂ W s + ∂ L 3 ∂ O 3 ∂ O 3 ∂ S 3 ∂ S 3 ∂ S 2 ∂ S 2 ∂ S 1 ∂ S 1 ∂ W s = ∂ L 3 ∂ O 3 W 0 ( S 2 + S 1 W s + S 0 W s 2 ) \frac{\partial L_3}{\partial W_s} = \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial W_s} + \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial W_s} + \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial S_1} \frac{\partial S_1}{\partial W_s} = \frac{\partial L_3}{\partial O_3} W_0 (S_2 + S_1 W_s + S_0 W_s^2) WsL3=O3L3S3O3WsS3+O3L3S3O3S2S3WsS2+O3L3S3O3S2S3S1S2WsS1=O3L3W0(S2+S1Ws+S0Ws2)

关于上面这个多元复合函数链式求导过程,通过如下对变量层级树的遍历可以更加直观理解这一点:
在这里插入图片描述
可以看出对于 W o W_o Wo 求偏导并没有长期依赖,但是对于 W x W_x Wx W s W_s Ws 求偏导,会随着时间序列产生长期依赖。因为 S t S_t St 随着时间序列向前传播,而 S t S_t St 又是 W x W_x Wx W s W_s Ws 的函数。

根据上述求偏导的过程,我们可以得出任意时刻对 W x W_x Wx W s W_s Ws 求偏导的公式:

∂ L t ∂ W x = ∑ k = 0 t ∂ L t ∂ O t ∂ O t ∂ S t ( ∏ j = k + 1 t ∂ S j ∂ S j − 1 ) ∂ S k ∂ W x \frac{\partial L_t}{\partial W_x} = \sum_{k=0}^{t} \frac{\partial L_t}{\partial O_t} \frac{\partial O_t}{\partial S_t} \left(\prod_{j=k+1}^{t} \frac{\partial S_j}{\partial S_{j-1}}\right) \frac{\partial S_k}{\partial W_x} WxLt=k=0tOtLtStOt j=k+1tSj1Sj WxSk

任意时刻对 W s W_s Ws 求偏导的公式同上。

如果加上激活函数: S j = tanh ⁡ ( W x X j + W s S j − 1 + b 1 ) S_j = \tanh(W_x X_j + W_s S_{j-1} + b_1) Sj=tanh(WxXj+WsSj1+b1)

∏ j = k + 1 t ∂ S j ∂ S j − 1 = ∏ j = k + 1 t tanh ⁡ ′ W s \prod_{j=k+1}^{t} \frac{\partial S_j}{\partial S_{j-1}} = \prod_{j=k+1}^{t} \tanh' W_s j=k+1tSj1Sj=j=k+1ttanhWs

加上激活函数tanh复合后的多元链式求导过程如下图所示:

在这里插入图片描述

激活函数tanh和它的导数图像如下。

在这里插入图片描述

由上图可以看出 tanh ⁡ ′ ≤ 1 \tanh' \leq 1 tanh1,对于训练过程大部分情况下tanh的导数是小于1的,因为很少情况下会出现 W x X j + W s S j − 1 + b 1 = 0 W_x X_j + W_s S_{j-1} + b_1 = 0 WxXj+WsSj1+b1=0,如果 W s W_s Ws 也是一个大于0小于1的值,则当t很大时 ∏ j = k + 1 t tanh ⁡ ′ W s \prod_{j=k+1}^{t} \tanh' W_s j=k+1ttanhWs,就会趋近于0,和 0.0 1 50 0.01^{50} 0.0150 趋近于0是一个道理。同理当 W s W_s Ws 很大时 ∏ j = k + 1 t tanh ⁡ ′ W s \prod_{j=k+1}^{t} \tanh' W_s j=k+1ttanhWs 就会趋近于无穷,这就是RNN中梯度消失和爆炸的原因。

至于怎么避免这种现象,再看看 ∂ L t ∂ W x = ∑ k = 0 t ∂ L t ∂ O t ∂ O t ∂ S t ( ∏ j = k + 1 t ∂ S j ∂ S j − 1 ) ∂ S k ∂ W x \frac{\partial L_t}{\partial W_x} = \sum_{k=0}^{t} \frac{\partial L_t}{\partial O_t} \frac{\partial O_t}{\partial S_t} \left(\prod_{j=k+1}^{t} \frac{\partial S_j}{\partial S_{j-1}}\right) \frac{\partial S_k}{\partial W_x} WxLt=k=0tOtLtStOt j=k+1tSj1Sj WxSk 梯度消失和爆炸的根本原因就是 ∏ j = k + 1 t ∂ S j ∂ S j − 1 \prod_{j=k+1}^{t} \frac{\partial S_j}{\partial S_{j-1}} j=k+1tSj1Sj 这一坨,要消除这种情况就需要把这一坨在求偏导的过程中去掉,至于怎么去掉,一种办法就是使 ∂ S j ∂ S j − 1 ≈ 1 \frac{\partial S_j}{\partial S_{j-1}} \approx 1 Sj1Sj1 另一种办法就是使 ∂ S j ∂ S j − 1 ≈ 0 \frac{\partial S_j}{\partial S_{j-1}} \approx 0 Sj1Sj0。其实这就是LSTM做的事情。

总结:

  • RNN 的梯度计算涉及到对激活函数的导数以及权重矩阵的连乘

    • 以 sigmoid 函数为例,其导数的值域在 0 到 0.25 之间,当进行多次连乘时,这些较小的值相乘会导致梯度迅速变小。
    • 如果权重矩阵的特征值也小于 1,那么在多个时间步的传递过程中,梯度就会呈指数级下降,导致越靠前的时间步,梯度回传的值越少。
  • 由于梯度消失,靠前时间步的参数更新幅度会非常小,甚至几乎不更新。这使得模型难以学习到序列数据中长距离的依赖关系,对于较早时间步的信息利用不足,从而影响模型的整体性能和对序列数据的建模能力。

注意 : 注意: 注意:

RNN梯度爆炸好理解,就是 ∂ L t ∂ W x \frac{\partial L_t}{\partial W_x} WxLt梯度数值发散,甚至慢慢就NaN了;

那梯度消失就是 ∂ L t ∂ W x \frac{\partial L_t}{\partial W_x} WxLt梯度变成零吗?

并不是,我们刚刚说梯度消失是 ∣ ∂ S j ∂ S j − 1 ∣ \left|\frac{\partial S_j}{\partial S_{j-1}}\right| Sj1Sj 一直小于1,历史梯度不断衰减,但不意味着总的梯度就为0了。RNN中梯度消失的含义是距离当前时间步越长,那么其反馈的梯度信号越不显著,最后可能完全没有起作用,这就意味着RNN对长距离语义的捕捉能力失效了

说白了,你优化过程都跟长距离的反馈没关系,怎么能保证学习出来的模型能有效捕捉长距离呢?

再次通俗解释一下RNN梯度消失,其指的不是 ∂ L t ∂ W x \frac{\partial L_t}{\partial W_x} WxLt梯度值接近于0,而是靠前时间步的梯度 ∂ L 3 ∂ O 3 ∂ O 3 ∂ S 3 ∂ S 3 ∂ S 2 ∂ S 2 ∂ S 1 ∂ S 1 ∂ W x \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial S_1} \frac{\partial S_1}{\partial W_x} O3L3S3O3S2S3S1S2WxS1值算出来很小,也就是靠前时间步计算出来的结果对序列最后一个预测词的生成影响很小,也就是常说的RNN难以去建模长距离的依赖关系的原因;这并不是因为序列靠前的词对最后一个词的预测输出不重要,而是由于损失函数在把有用的梯度更新信息反向回传的过程中,被若干小于0的偏导连乘给一点点削减掉了。


LSTM如何解决远距离时间步梯度消失问题

在这里插入图片描述

LSTM的更新公式比较复杂,它是:

f t = σ ( W f x t + U f h t − 1 + b f ) f_t = \sigma (W_f x_t + U_f h_{t-1} + b_f) ft=σ(Wfxt+Ufht1+bf)
i t = σ ( W i x t + U i h t − 1 + b i ) i_t = \sigma (W_i x_t + U_i h_{t-1} + b_i) it=σ(Wixt+Uiht1+bi)
o t = σ ( W o x t + U o h t − 1 + b o ) o_t = \sigma (W_o x_t + U_o h_{t-1} + b_o) ot=σ(Woxt+Uoht1+bo)
c ^ t = tanh ⁡ ( W c x t + U c h t − 1 + b c ) \hat{c}_t = \tanh (W_c x_t + U_c h_{t-1} + b_c) c^t=tanh(Wcxt+Ucht1+bc)
c t = f t ∘ c t − 1 + i t ∘ c ^ t c_t = f_t \circ c_{t-1} + i_t \circ \hat{c}_t ct=ftct1+itc^t
h t = o t ∘ tanh ⁡ ( c t ) h_t = o_t \circ \tanh(c_t) \qquad ht=ottanh(ct)

我们可以像上面一样计算 ∂ h t ∂ h t − 1 \frac{\partial h_t}{\partial h_{t-1}} ht1ht,但从 h t = o t ∘ tanh ⁡ ( c t ) h_t = o_t \circ \tanh(c_t) ht=ottanh(ct) 可以看出分析 c t c_t ct 就等价于分析 h t h_t ht,而计算 ∂ c t ∂ c t − 1 \frac{\partial c_t}{\partial c_{t-1}} ct1ct 显得更加简单一些,因此我们往这个方向走。

同样地,我们先只关心1维的情形,这时候根据求导公式,我们有

∂ c t ∂ c t − 1 = f t + c t − 1 ∂ f t ∂ c t − 1 + c ^ t ∂ i t ∂ c t − 1 + i t ∂ c ^ t ∂ c t − 1 \frac{\partial c_t}{\partial c_{t-1}} = f_t + c_{t-1} \frac{\partial f_t}{\partial c_{t-1}} + \hat{c}_t \frac{\partial i_t}{\partial c_{t-1}} + i_t \frac{\partial \hat{c}_t}{\partial c_{t-1}} \qquad ct1ct=ft+ct1ct1ft+c^tct1it+itct1c^t

右端第一项 f t f_t ft,也就是我们所说的“遗忘门”,从下面的论述我们可以知道一般情况下其余三项都是次要项,因此 f t f_t ft 是“主项”,由于 f t f_t ft 在0~1之间,因此就意味着梯度爆炸的风险将会很小,至于会不会梯度消失,取决于 f t f_t ft 是否接近于1。但非常碰巧的是,这里有个相当自洽的结论:如果我们的任务比较依赖于历史信息,那么 f t f_t ft 就会接近于1,这时候历史的梯度信息也正好不容易消失;如果 f t f_t ft 很接近于0,那么就说明我们的任务不依赖于历史信息,这时候就算梯度消失也无妨了

所以,现在的关键就是看“其余三项都是次要项”这个结论能否成立。后面的三项都是“一项乘以另一项的偏导”的形式,而且求偏导的项都是 σ \sigma σ tanh ⁡ \tanh tanh激活, σ \sigma σ tanh ⁡ \tanh tanh的偏导公式基本上是等价的,它们的导数均可以用它们自身来表示:

tanh ⁡ x = 2 σ ( 2 x ) − 1 \tanh x = 2\sigma(2x) - 1 tanhx=2σ(2x)1
σ ( x ) = 1 2 ( tanh ⁡ x 2 + 1 ) \sigma(x) = \frac{1}{2} \left( \tanh \frac{x}{2} + 1 \right) \qquad σ(x)=21(tanh2x+1)
( tanh ⁡ x ) ′ = 1 − tanh ⁡ 2 x (\tanh x)' = 1 - \tanh^2 x (tanhx)=1tanh2x
σ ′ ( x ) = σ ( x ) ( 1 − σ ( x ) ) \sigma'(x) = \sigma(x) (1 - \sigma(x)) σ(x)=σ(x)(1σ(x))

其中 σ ( x ) = 1 / ( 1 + e − x ) \sigma(x) = 1/(1 + e^{-x}) σ(x)=1/(1+ex) 是sigmoid函数。

因此后面三项是类似的,分析了其中一项就相当于分析了其余两项。以第二项为例,代入 h t − 1 = o t − 1 tanh ⁡ ( c t − 1 ) h_{t-1} = o_{t-1} \tanh(c_{t-1}) ht1=ot1tanh(ct1),可以算得

c t − 1 ∂ f t ∂ c t − 1 = f t ( 1 − f t ) o t − 1 ( 1 − tanh ⁡ 2 c t − 1 ) c t − 1 U f c_{t-1} \frac{\partial f_t}{\partial c_{t-1}} = f_t (1 - f_t) o_{t-1} (1 - \tanh^2 c_{t-1}) c_{t-1} U_f \qquad ct1ct1ft=ft(1ft)ot1(1tanh2ct1)ct1Uf

注意到 f t , 1 − f t , o t − 1 f_t, 1 - f_t, o_{t-1} ft,1ft,ot1都是在0~1之间,也可以证明 ∣ ( 1 − tanh ⁡ 2 c t − 1 ) c t − 1 ∣ < 0.45 |(1 - \tanh^2 c_{t-1}) c_{t-1}| < 0.45 (1tanh2ct1)ct1<0.45,因此它也在-1~1之间。所以 c t − 1 ∂ f t ∂ c t − 1 c_{t-1} \frac{\partial f_t}{\partial c_{t-1}} ct1ct1ft就相当于1个 U f U_f Uf乘上4个门,结果会变得更加小,所以只要初始化不是很糟糕,那么它都会被压缩得相当小,因此占不到主导作用。

剩下两项的结论也是类似的:

c ^ t ∂ i t ∂ c t − 1 = i t ( 1 − i t ) o t − 1 ( 1 − tanh ⁡ 2 c t − 1 ) c ^ t U i \hat{c}_t \frac{\partial i_t}{\partial c_{t-1}} = i_t (1 - i_t) o_{t-1} (1 - \tanh^2 c_{t-1}) \hat{c}_t U_i \qquad c^tct1it=it(1it)ot1(1tanh2ct1)c^tUi

i t ∂ c ^ t ∂ c t − 1 = ( 1 − c ^ t 2 ) o t − 1 ( 1 − tanh ⁡ 2 c t − 1 ) i t U c i_t \frac{\partial \hat{c}_t}{\partial c_{t-1}} = (1 - \hat{c}_t^2) o_{t-1} (1 - \tanh^2 c_{t-1}) i_t U_c itct1c^t=(1c^t2)ot1(1tanh2ct1)itUc

所以,后面三项的梯度带有更多的“门”,一般而言乘起来后会被压缩的更厉害,因此占主导的项还是 f t f_t ft f t f_t ft 在0~1之间这个特性决定了它梯度爆炸的风险很小,同时 f t f_t ft 表明了模型对历史信息的依赖性,也正好是历史梯度的保留程度,两者相互自洽,所以LSTM也能较好地缓解梯度消失问题。因此,LSTM同时较好地缓解了梯度消失/爆炸问题,现在我们训练LSTM时,多数情况下只需要直接调用Adam等自适应学习率优化器,不需要人为对梯度做什么调整了。


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

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

相关文章

Tomcat理论(Ⅰ)

目录 服务器流程图一览 一、JavaWeb前奏(了解) 1. C/S结构 2. B/S结构 3. 静态网页&动态网页 4.常见的网页 5.Web服务器 知名服务器&#xff1a; ​编辑 二、Tomcat安装&#xff08;熟练&#xff09; 1.Tomcat概述 2.Tomcat的作用 3.Tomcat安装 4.Tomcat测试 3.…

如何使用 DeepSeek R1 构建开源 ChatGPT Operator 替代方案

开源大型语言模型&#xff08;LLMs&#xff09;的兴起使得创建 AI 驱动的工具比以往任何时候都更容易&#xff0c;这些工具可以与 OpenAI 的 ChatGPT Operator 等专有解决方案相媲美。在这些开源模型中&#xff0c;DeepSeek R1 以其强大的推理能力、自由的可访问性和适应性而脱…

使用Docker Desktop部署GitLab

1. 环境准备 确保Windows 10/11系统支持虚拟化技术&#xff08;需在BIOS中开启Intel VT-x/AMD-V&#xff09;内存建议≥8GB&#xff0c;存储空间≥100GB 2. 安装Docker Desktop 访问Docker官网下载安装包安装时勾选"Use WSL 2 instead of Hyper-V"&#xff08;推荐…

【复习】Java集合

集合概念 集合与数组 数组是固定长度&#xff1b;集合是动态长度的数据结构&#xff0c;需要动态增加或删除元素 数组可以包含基本数据类型和对象&#xff1b;集合只能包含对象 数组可以直接访问元素&#xff1b;集合需要通过迭代器访问元素 线程安全的集合&#xff1f; …

vue3 文件类型传Form Data数据格式给后端

在 Vue 3 中&#xff0c;如果你想将文件&#xff08;例如上传的 Excel 文件&#xff09;以 FormData 格式发送到后端&#xff0c;可以通过以下步骤实现。这种方式通常用于处理文件上传&#xff0c;因为它可以将文件和其他数据一起发送到服务器。 首先&#xff0c;创建一个 Vue…

使用 INFINI Console 配置集群监控 Webhook 通知指南

在集群管理中&#xff0c;监控关键指标如CPU、内存、磁盘、JVM等是至关重要的。对于Easysearch及ES生态系统&#xff0c;还需要关注集群本身的指标&#xff0c;例如搜索延迟、集群状态、节点移除等。INFINI Console不仅提供了默认的监控指标&#xff0c;还支持用户自定义监控项…

WPF的页面设计和实用功能实现

目录 一、TextBlock和TextBox 1. 在TextBlock中实时显示当前时间 二、ListView 1.ListView显示数据 三、ComboBox 1. ComboBox和CheckBox组合实现下拉框多选 四、Button 1. 设计Button按钮的边框为圆角&#xff0c;并对指针悬停时的颜色进行设置 一、TextBlock和TextBox…

二级公共基础之数据结构与算法篇(八)排序技术

目录 前言 一、交换类排序 1.冒泡排序法 1. 冒泡排序的思想 2. 冒泡排序的实现步骤 3. 示例 4. 冒泡排序的特点 2.快速排序 1. 快速排序的核心思想 2. 快速排序的实现步骤 3. 示例代码(C语言) 4. 快速排序的特点 二、插入类排序 1. 简单插入排序 1.简单插入排…

记录一次 ALG 的处理过程

前几天朋友找我帮忙&#xff0c;说碰到很大困难了&#xff0c;实际上&#xff0c;不过如此 现象是这样的&#xff1a; FreeSWITCH mod_unimrcp 工作不正常 FS 和 mrcp-server 两边同时抓包&#xff0c;看到的是&#xff1a; sip 流程正常 FS TCP 连接到 mccp-server 失败&…

【Linux网络编程】IP协议格式,解包步骤

目录 解析步骤 1.版本字段&#xff08;大小&#xff1a;4比特位&#xff09; 2.首部长度&#xff08;大小&#xff1a;4比特位&#xff09;&#xff08;单位&#xff1a;4字节&#xff09; &#x1f35c;细节解释&#xff1a; 3.服务类型&#xff08;大小&#xff1a;8比特…

CSDN文章质量分查询系统【赠python爬虫、提分攻略】

CSDN文章质量分查询系统 https://www.csdn.net/qc 点击链接-----> CSDN文章质量分查询系统 <------点击链接 点击链接-----> https://www.csdn.net/qc <------点击链接 点击链接-----> CSDN文章质量分查询系统 <------点击链接 点击链…

HTML应用指南:利用GET请求获取全国泸溪河门店位置信息

随着新零售业态的快速发展,门店位置信息的获取变得越来越重要。作为新兴烘焙品牌之一,泸溪河自2013年在南京创立以来,一直坚持“健康美味,香飘世界”的企业使命,以匠人精神打造新中式糕点。为了更好地理解和利用这些数据,本篇文章将深入探讨GET请求的实际应用,并展示如何…

如何在 React 中测试高阶组件?

在 React 中测试高阶组件可以采用多种策略&#xff0c;以下是常见的测试方法&#xff1a; 1. 测试高阶组件返回的组件 高阶组件本身是一个函数&#xff0c;它返回一个新的组件。因此&#xff0c;可以通过测试这个返回的组件来间接测试高阶组件的功能。通常使用 Jest 作为测试…

R语言Stan贝叶斯空间条件自回归CAR模型分析死亡率多维度数据可视化

全文链接&#xff1a;https://tecdat.cn/?p40424 在空间数据分析领域&#xff0c;准确的模型和有效的工具对于研究人员至关重要。本文为区域数据的贝叶斯模型分析提供了一套完整的工作流程&#xff0c;基于Stan这一先进的贝叶斯建模平台构建&#xff0c;帮助客户为空间分析带来…

Casbin 权限管理介绍及在 Go 语言中的使用入门

引言 在现代软件开发过程中&#xff0c;权限管理是一个至关重要的环节&#xff0c;它关系到系统的安全性和用户体验。Casbin 是一个强大的访问控制库&#xff0c;支持多种访问控制模型&#xff0c;如 ACL&#xff08;访问控制列表&#xff09;、RBAC&#xff08;基于角色的访问…

快速入门——第三方组件element-ui

学习自哔哩哔哩上的“刘老师教编程”&#xff0c;具体学习的网站为&#xff1a;10.第三方组件element-ui_哔哩哔哩_bilibili&#xff0c;以下是看课后做的笔记&#xff0c;仅供参考。 第一节 组件间的传值 组件可以有内部Data提供数据&#xff0c;也可由父组件通过prop方式传…

【算法通关村 Day7】递归与二叉树遍历

递归与二叉树遍历青铜挑战 理解递归 递归算法是指一个方法在其执行过程中调用自身。它通常用于将一个问题分解为更小的子问题&#xff0c;通过重复调用相同的方法来解决这些子问题&#xff0c;直到达到基准情况&#xff08;终止条件&#xff09;。 递归算法通常包括两个主要…

朴素贝叶斯法

文章目录 贝叶斯定理朴素贝叶斯法的学习与分类条件独立假设朴素贝叶斯的后验概率最大化准则朴素贝叶斯的基本公式 朴素贝叶斯法的参数估计极大似然估计 贝叶斯定理 前置知识&#xff1a;条件概率、全概率、贝叶斯公式 推荐视频&#xff0c;看完视频后搜索博客了解先验概率、后…

《A++ 敏捷开发》- 20 从 AI 到最佳设计

“我们现在推行AIGC&#xff0c;服务端不需要UI交互设计的用AI自动产出代码&#xff0c;你建议的结对编程、TDD等是否还适用&#xff1f;” 这两年AI确实很火&#xff0c;是报纸、杂志的热门话题。例如&#xff0c;HBR杂志从2024年9月至2025年二月份3期&#xff0c;里面有接近一…

GO系列-IO 文件操作

os io 判断文件是否存在 func fileExist(filePath string) (bool, error) {_, err : os.Stat(filePath)if err nil {return true, nil}if os.IsNotExist(err) {return false, nil}return false, &CheckFileExistError{filePath} } 读取文件内容 func readFileContext(…