各类神经网络学习:(三)RNN 循环神经网络(中集),同步多对多结构的详细解释
| 上一篇 | 下一篇 |
|---|---|
| RNN(上集) | RNN(下集) |
同步多对多结构
1)结构详解
①图解:

②参数含义:
- x t x_t xt :表示每一个时刻的输入;
- o t o_t ot :表示每一个时刻的输出;
- s t s_t st :表示每一个隐藏层的状态输出;
- 右侧小圆圈代表隐藏层的一个单元;
- U 、 V 、 W U、V、W U、V、W 参数共享,即所有的隐藏层都共用这三个参数。
③通用公式:
- s 0 = 0 s_0=0 s0=0 (实际计算中是 0 0 0 列向量)。
- s t = g 1 ( U ⋅ x t + W ⋅ s t − 1 + b s ) s_t=g1(U·x_t+W·s_{t-1}+b_s) st=g1(U⋅xt+W⋅st−1+bs) 。 g 1 ( ) g1() g1() 是激活函数, b s b_s bs 是偏置。
- o t = g 2 ( V ⋅ s t + b o ) o_t=g2(V·s_t+b_o) ot=g2(V⋅st+bo) 。 g 2 ( ) g2() g2() 是激活函数, b o b_o bo 是偏置。
通过将公式分解,可以发现: o t o_t ot 的值和前面每个时刻的输入都有关系(展开式形似 累乘 )。
④激活函数的选择
总结:多分类使用 t a n h tanh tanh + s o f t m a x softmax softmax ;单分类使用 t a n h tanh tanh + s i g m o i d sigmoid sigmoid 。
-
激活函数 g 1 ( ) g1() g1() 一般选用 t a n h tanh tanh 。不用其他的函数的原因如下:
-
梯度消失问题(相比于 s i g m o i d sigmoid sigmoid ):
s i g m o i d sigmoid sigmoid 函数的导数范围是 ( 0 , 0.25 ] (0,0.25] (0,0.25] , t a n h tanh tanh 函数的导数是 ( 0 , 1 ] (0,1] (0,1] 。由于 R N N RNN RNN 中会执行很多累乘,小于 1 1 1 的小数累乘会导致梯度越来越接近于 0 0 0 ,从而导致梯度消失现象。 t a n h tanh tanh 与 s i g m o i d sigmoid sigmoid 相比,梯度收敛速度更快并且相对不易出现梯度消失问题。
-
梯度爆炸问题(相比于 r e l u relu relu ):
虽然 r e l u relu relu 函数能有效缓解梯度消失,但是由于 r e l u relu relu 的导数不是 0 0 0 就是 1 1 1 ,恒为 1 1 1 的导数容易导致梯度爆炸,尤其是在会执行很多累乘的 R N N RNN RNN 中。
-
对称问题:
t a n h tanh tanh 的输出范围为 [ − 1 , 1 ] [−1,1] [−1,1] ,这使得它能够将输入值映射到一个对称的区间,有助于梯度的传播和模型的收敛。
-
-
激活函数 g 2 ( ) g2() g2() :
- 对于多分类问题,使用 s o f t m a x softmax softmax ;
- 对于单分类问题,使用 s i g m o i d sigmoid sigmoid 。
2)在同步多对多RNN网络中,句子如何作为输入
①首先将句子进行分词
分词就是将一个句子拆分成单词或字符,例如 “我喜欢打篮球” ,会被分词为 “我、喜欢、打、篮球” 。
-
对于英文,可用
NLTK的word_tokenize和sent_tokenize等工具;对于中文,可用Jieba等工具。 -
分词后,通常会过滤掉语料库中出现频率较低的词,以减少词汇表的规模并提高模型训练效率,低频词通常会被替换为
unknown_token。 -
为了帮助模型识别句子的开始和结束,通常会在句首和句尾添加标识符,如开始符
sentence_start和结束符sentence_end。
②将分词结果映射为向量
分词后的单词或字符需要被映射为向量表示。这通常通过构建一个词汇表,将每个单词或字符映射到一个唯一的索引,然后将这些索引转换为向量。例如,使用 O n e − H o t One-Hot One−Hot 编码或嵌入层( E m b e d d i n g L a y e r Embedding Layer EmbeddingLayer)将单词表示为向量( o n e − h o t one-hot one−hot 编码上网一搜便知,这里不做额外解释)。

将词典通过上述方法转换之后,就会得到右边的一个高维、稀疏的向量组( m m m 个词组成的向量组为 m m m 行, m m m 列)(稀疏指的是绝大部分元素都是 0 0 0 )。
之前提到的开始和结束标志也会在此向量组里,比如用 [1,0,0,...] 表示开始符, [...,0,0,1] 表示结束符。
③将分词后的结果按照时刻依次输入模型
以“我喜欢打篮球”→“我、喜欢、打、篮球”为例
模型的输出后续会给出图解。

3)模型训练过程中的矩阵运算是怎样的
仅代表模型在 t t t 时刻的矩阵运算
回顾通用公式:
- s 0 = 0 s_0=0 s0=0 (实际计算中是 0 0 0 列向量)。
- s t = g 1 ( U ⋅ x t + W ⋅ s t − 1 ) s_t=g1(U·x_t+W·s_{t-1}) st=g1(U⋅xt+W⋅st−1) 偏置 b s b_s bs 先省略。
- o t = g 2 ( V ⋅ s t ) o_t=g2(V·s_t) ot=g2(V⋅st) 偏置 b o b_o bo 先省略。
先确定输出向量的维度: o t o_t ot 为 [ m , 1 ] [m,1] [m,1] (维度和 x t x_t xt 一样), s t s_t st 为 [ n , 1 ] [n,1] [n,1] ( n n n 可自定义)。公式展开如下:
[ s t 1 : s t n ] = g 1 ( U ⋅ [ x t 1 ┇ x t m ] + W ⋅ [ s t − 1 1 : s t − 1 n ] ) − − − − − − − − − − − − − − − − − − − − − − − [ o t 1 ┇ o t m ] = g 2 ( V ⋅ [ s t 1 : s t n ] ) \large\left[ \begin{matrix} s^1_t\\ :\\ s^n_t\\ \end{matrix} \right]=g1(U·\left[ \begin{matrix} x^1_t\\ ┇\\ x^m_t\\ \end{matrix} \right]+W·\left[ \begin{matrix} s^1_{t-1}\\ :\\ s^n_{t-1}\\ \end{matrix} \right])\\ -----------------------\\ \large\left[ \begin{matrix} o^1_t\\ ┇\\ o^m_t\\ \end{matrix} \right]=g2(V·\left[ \begin{matrix} s^1_t\\ :\\ s^n_t\\ \end{matrix} \right])\\ st1:stn =g1(U⋅ xt1┇xtm +W⋅ st−11:st−1n )−−−−−−−−−−−−−−−−−−−−−−− ot1┇otm =g2(V⋅ st1:stn )
注意其中的 n n n 和 m m m 。参数矩阵 U 、 W 、 V U、W、V U、W、V 可由此确定维度( U U U 为 [ n , m ] [n,m] [n,m] , W W W 为 [ n , n ] [n,n] [n,n] , V V V 为 [ m , n ] [m,n] [m,n] )。
不难推出参数 b s b_s bs 为 [ n , 1 ] [n,1] [n,1] , b o bo bo 为 [ m , 1 ] [m,1] [m,1] 。
4)在同步多对多RNN网络中,模型的输出是什么
①以语言建模为例:输出激活函数使用softmax,即多分类
语言建模:输入一个句子并输出句子中每个词在下一个时刻最有可能的词,例如,给定句子 “The cat is on the”,RNN 会预测下一个词可能是 “mat”、“roof” 等,并给出每个词的概率。这个过程可以逐词进行,直到生成完整的句子或序列。
每一个时刻的输出是一条概率向量,表示下一个最可能的词。
概率向量构成:由预测概率组成的向量,长度为 N N N 。形如: [0.00001,...,0.018,...,0.00023,...] 。这些概率都由 s o f t m a x softmax softmax 函数计算得出。
例如下方图解:

模型的完整输入输出为(输入仍以“我、喜欢、打、篮球”为例):
(输出结果可以是其他的,但是这里图方便,就正好假设输出也是“我、喜欢、打、篮球”。)

举一个语言建模逐词进行的例子:
以句子 “The cat is on the” 为例,RNN 会逐词预测下一个词,并给出每个词的概率分布。以下是假设的逐词生成过程:
- 输入“The”:
RNN 会基于 “The” 预测下一个词,可能的输出概率分布为:- cat: 0.8
- dog: 0.1
- bird: 0.05
- …
- 输入“The cat”:
RNN 会基于 “The cat” 预测下一个词,可能的输出概率分布为:- is: 0.7
- was: 0.2
- jumped: 0.05
- …
- 输入“The cat is”:
RNN 会基于 “The cat is” 预测下一个词,可能的输出概率分布为:- on: 0.6
- under: 0.2
- sleeping: 0.1
- …
- 输入“The cat is on”:
RNN 会基于 “The cat is on” 预测下一个词,可能的输出概率分布为:- the: 0.7
- a: 0.2
- my: 0.05
- …
- 输入“The cat is on the”:
RNN 会基于 “The cat is on the” 预测下一个词,可能的输出概率分布为:- mat: 0.5
- roof: 0.3
- table: 0.1
- …
最终,RNN 可能会生成完整的句子,例如 “The cat is on the mat” 或 “The cat is on the roof” ,具体取决于概率分布和模型训练数据。
②输出激活函数使用sigmoid,即单分类
(这里就不展开了,随便找 D e e p S e e k DeepSeek DeepSeek 写了个例子):
假设我们有一个 R N N RNN RNN 模型用于预测某个事件是否会在每个时间步发生。模型的输入是一个时间序列数据,输出是一个与输入序列长度相同的二进制序列
( 0 0 0 表示不会, 1 1 1 表示会)。
具体步骤:
- 输入处理:输入序列被逐个时间步输入到 R N N RNN RNN 中。
- 隐藏状态更新: R N N RNN RNN 在每个时间步更新其隐藏状态,基于当前输入和前一隐藏状态。
- 输出生成:在每个时间步, R N N RNN RNN 的输出层使用 S i g m o i d Sigmoid Sigmoid 激活函数生成一个输出值,表示当前时间步的事件发生概率(概率 ≥ 0.5 ≥0.5 ≥0.5 时判为 1 1 1,否则为 0 0 0 )。
- 序列输出:最终,模型输出一个与输入序列长度相同的二进制序列,每个值表示对应时间步的事件是否会发生。
总结:在同步多对多结构的 R N N RNN RNN 中,使用 S i g m o i d Sigmoid Sigmoid 作为输出层的激活函数,可以生成一个二进制序列(一开始是概率序列,经过阈值判别后变成二进制序列),适用于二分类问题或概率预测任务。
5)模型训练中的损失
一般采用交叉熵损失函数。
一整个序列(句子)作为一个输入样本时,其损失为各个时刻词的损失之和。
损失计算公式定义:
- 时刻 t t t 的损失: E t ( y t , y t ^ ) = − y t ⋅ l o g ( y t ^ ) \large E_t(y_t,\hat{y_t}) =-y_t·log(\hat{y_t}) Et(yt,yt^)=−yt⋅log(yt^) ;
- 各时刻损失之和: E ( y , y ^ ) = ∑ t E t ( y t , y t ^ ) = − ∑ t y t ⋅ l o g ( y t ^ ) \large E(y,\hat{y})=\sum_t E_t(y_t,\hat{y_t}) =-\sum_ty_t·log(\hat{y_t}) E(y,y^)=∑tEt(yt,yt^)=−∑tyt⋅log(yt^) 。
这里和 C N N CNN CNN 的交叉熵损失函数有所不同,这里的 y t y_t yt 代表时刻 t t t 上正确词的向量, y t ^ \hat{y_t} yt^ 代表预测词的向量。
单个时刻的损失对模型输出 o t o_t ot 的导数为 ∂ J t ∂ o t = o t − y t \large \frac{\partial J_t}{\partial o_t} = o_t - y_t ∂ot∂Jt=ot−yt 。
单个时刻的损失对隐层状态输出 s t s_t st 的导数为 ∂ J t ∂ s t = V T ∗ ( o t − y t ) \large \frac{\partial J_t}{\partial s_t} = V^T * (o_t - y_t) ∂st∂Jt=VT∗(ot−yt) 。
6)时序反向传播算法(BPTT)
BPTT,Back Propagation Through Time,对 RNN 来说,梯度是沿时间通道反向传播的。
看看过程,理解一下就行,实际写代码不用亲自写,直接模块化调用就行。
再次回顾前向传播通用公式,并带入激活函数:
- 公式一: s t = t a n h ( z t ) = t a n h ( U ⋅ x t + W ⋅ s t − 1 + b s ) \large s_t=tanh(z_t)=tanh(U·x_t+W·s_{t-1}+b_s) st=tanh(zt)=tanh(U⋅xt+W⋅st−1+bs)
- 公式二: o t = s o f t m a x ( V ⋅ s t + b o ) \large o_t=softmax(V·s_t+b_o) ot=softmax(V⋅st+bo)
令损失为 J J J 。
①梯度计算要求及规则:
-
目标 是:计算损失 J J J 关于参数 U 、 V 、 W 、 b s 、 b o U、V、W、b_s、b_o U、V、W、bs、bo 的梯度;
-
因为上述五个参数在每个时刻都是共享的,所以每个时刻的梯度都得计算出来,求出所有时刻梯度之和,才可用于参数更新;
图解如下:

-
每个时刻的梯度计算 规则:
-
最后一个时刻:
- 第一步:依据交叉熵计算公式和公式二计算出: ∂ J t ∂ s t 、 ∂ J t ∂ V ( √ ) 、 ∂ J t ∂ b o ( √ ) \Large \frac{\partial J_t}{\partial s_t}、\frac{\partial J_t}{\partial V}(√)、\frac{\partial J_t}{\partial b_o}(√) ∂st∂Jt、∂V∂Jt(√)、∂bo∂Jt(√) ;
- 第二步:依据公式一可以计算出: ∂ s t ∂ z t 、 ∂ s t ∂ U 、 ∂ s t ∂ W 、 ∂ s t ∂ b s 、 ∂ s t ∂ x t \Large \frac{\partial s_t}{\partial z_t}、\frac{\partial s_t}{\partial U}、\frac{\partial s_t}{\partial W}、\frac{\partial s_t}{\partial b_s}、\frac{\partial s_t}{\partial x_t} ∂zt∂st、∂U∂st、∂W∂st、∂bs∂st、∂xt∂st ;
- 第三步:依据 链式法则 ,继续求出: ∂ J t ∂ U ( √ ) 、 ∂ J t ∂ W ( √ ) 、 ∂ J t ∂ b s ( √ ) \Large \frac{\partial J_t}{\partial U}(√)、\frac{\partial J_t}{\partial W}(√)、\frac{\partial J_t}{\partial b_s}(√) ∂U∂Jt(√)、∂W∂Jt(√)、∂bs∂Jt(√) 。
-
非最后一个时刻:
-
第一步:依据交叉熵计算公式、公式二计算出: ∂ J t ∂ s t 、 ∂ J t ∂ V 、 ∂ J t ∂ b o \Large \frac{\partial J_t}{\partial s_t}、\frac{\partial J_t}{\partial V}、\frac{\partial J_t}{\partial b_o} ∂st∂Jt、∂V∂Jt、∂bo∂Jt ;
-
第二步( 不同点 ):在下一个时刻 t + 1 t+1 t+1 (反向传播时,其实应称为上一个时刻)时,要求出 ∂ s t + 1 ∂ s t \Large \frac{\partial s_{t+1}}{\partial s_t} ∂st∂st+1 ,进一步求出 ∂ J t + 1 ∂ s t \Large \frac{\partial J_{t+1}}{\partial s_{t}} ∂st∂Jt+1 ,则此刻的 ∂ J t ∂ s t \Large \frac{\partial J_t}{\partial s_t} ∂st∂Jt 应再加上一部分: ∂ J t ∂ s t ( ☆ ) = ∂ J t ∂ s t + ∂ J t + 1 ∂ s t \Large \frac{\partial J_t}{\partial s_t}(☆)=\frac{\partial J_t}{\partial s_t}+\frac{\partial J_{t+1}}{\partial s_{t}} ∂st∂Jt(☆)=∂st∂Jt+∂st∂Jt+1 ;
即:当前时刻损失对于隐层状态输出值 s t s_t st 的梯度要再加上下一时刻损失对 s t s_{t} st 的导数。
-
第三步:照搬 “最后一个时刻” 的第二步;
-
第四步:照搬 “最后一个时刻” 的第三步。
-
-
单个时刻的反向传播可以借鉴此视频中的公式(引自《85.09_手写RNN案例:单个cell的反向传播_哔哩哔哩_bilibili》),内部公式推导不需要记住。
↑ ↑ ↑ 但是其中的 x x x (不是指 x t x^t xt )要改写成 z t z_t zt , ∂ x \partial x ∂x (不是指 ∂ x t \partial x^t ∂xt )要改写成 ∂ z t \partial z_t ∂zt ,右侧第六行的 ∂ W \partial W ∂W 改成 ∂ b s \partial bs ∂bs 。
补充(其中 y t y_t yt 为预测真实值):
∂ J t ∂ o t = o t − y t ∂ o t ∂ s t = V T ∂ J t ∂ s t = V T ∗ ( o t − y t ) ∂ J t ∂ V = ∑ t = 1 T ( o t − y t ) ∗ s t T ∂ J t ∂ b o = ∑ t = 1 T ( o t − y t ) \begin{align*} \frac{\partial J_t}{\partial o_t} &= o_t - y_t\\ \frac{\partial o_t}{\partial s_t} &= V^T\\ \frac{\partial J_t}{\partial s_t} &= V^T * (o_t - y_t)\\ \frac{\partial J_t}{\partial V} &= \sum^T_{t=1} (o_t - y_t) * s_t^T\\ \frac{\partial J_t}{\partial b_o} &= \sum^T_{t=1} (o_t - y_t) \end{align*} ∂ot∂Jt∂st∂ot∂st∂Jt∂V∂Jt∂bo∂Jt=ot−yt=VT=VT∗(ot−yt)=t=1∑T(ot−yt)∗stT=t=1∑T(ot−yt)
②参数更新
当每个时刻的参数梯度都计算出来,求和得出最终的梯度 ∂ J ∂ U 、 ∂ J ∂ W 、 ∂ J ∂ b s 、 ∂ J ∂ V 、 ∂ J ∂ b o \Large \frac{\partial J}{\partial U}、\frac{\partial J}{\partial W}、\frac{\partial J}{\partial b_s}、\frac{\partial J}{\partial V}、\frac{\partial J}{\partial b_o} ∂U∂J、∂W∂J、∂bs∂J、∂V∂J、∂bo∂J 时,可按照下方公式进行更新:
U = U − α ⋅ ∂ J ∂ U W = W − α ⋅ ∂ J ∂ W ⋅ ⋅ ⋅ b o = b o − α ⋅ ∂ J ∂ b o U=U-\alpha·\frac{\partial J}{\partial U}\\ W=W-\alpha·\frac{\partial J}{\partial W}\\ ···\\ b_o=b_o-\alpha·\frac{\partial J}{\partial b_o}\\ U=U−α⋅∂U∂JW=W−α⋅∂W∂J⋅⋅⋅bo=bo−α⋅∂bo∂J
其中 α \alpha α 为学习率。
7)相关理解性代码
下面的代码仅供参考,并且实际使用pytorch的时候,都是模块化的,可直接调用的。
这里就仅仅给读者看看,方便理解前向传播和反向传播的代码逻辑。
import numpy as np# Language modeling: 语言建模(简写为 LMing ), 本质上是多分类任务# ***************************** 语言建模 *****************************# softmax自定义函数
def softmax(x):e_x = np.exp(x - np.max(x))return e_x / e_x.sum(axis=0)# 单个时刻的模型前向传播过程
def rnn_LMing_moment_forwad(x_t, s_prev, parameters):"""单个时刻的模型前向传播过程:paramx_t: 当前时刻的分词输入s_prev: 上一个时刻的隐层状态输出parameters: 字典形式的其他参数,包括 U、W、V、bs、bo:return:当前隐层状态 s_t,输出 o_t,缓存参数 cache 元组"""U = parameters['U']W = parameters['W']V = parameters['V']bs = parameters['bs']bo = parameters['bo']# 计算公式一, 即当前隐层状态s_ts_t = np.tanh(np.dot(U, x_t) + np.dot(W, s_prev) + bs)# 计算公式二, 即输出o_to_t = softmax(np.dot(V, s_t) + bo)# 记录此时刻的一些参数(在反向传播中会用到)cache = (s_t, s_prev, x_t, parameters)return s_t, o_t, cache# 整体模型前向传播
def rnn_LMing_forwad(x, s_0, parameters):"""整体模型前向传播过程:paramx: 输入序列(分词矩阵), 尺寸为[m,1,T], T为该序列中分词个数s_0: 初始化隐层状态输入, 尺寸为[n,1]parameters: 字典形式的其他参数,包括 U、W、V、bs、bo:return:全部时刻的隐层状态输出 s_total,尺寸为[n,1,T];全部时刻的输出 o_total,尺寸为[m,1,T];全部缓存参数元组, 并整合进一个列表 caches 中"""m, _, T = x.shape # 获取分词的向量形式长度、时刻数(分词数)n, _ = parameters['U'].shape # 获取单个时刻隐层状态的向量形式长度# 初始化全部隐层状态输出矩阵、全部时刻输出、s_total = np.zeros((n, 1, T))o_total = np.zeros((m, 1, T))caches = []s_t = s_0for t in range(T):s_t, o_t, cache = rnn_LMing_moment_forwad(x[:, :, t], s_t, parameters) # 生成的 s_t 在下一个循环中就是 s_prevs_total[:, :, t] = s_to_total[:, :, t] = o_tcaches.append(cache) # 将中间参数元组添加进列表中return s_total, o_total, caches# 单个时刻的反向传播, 其中 ds_t、do_t 需要提前计算传入
def rnn_LMing_moment_backward(ds_t, do_t, cache):"""对单个时刻进行反向传播:paramds_t: 当前时刻损失对隐层输出结果的导数do_t: 当前时刻损失对模型输出结果的导数(do_t = o_t - y_t), y_t 为真实值cache: 当前时刻的缓存参数:return:gradients: 梯度字典"""# 获取缓存(s_t, s_prev, x_t, parameters) = cache# 获取参数U = parameters['U']W = parameters['W']V = parameters['V']bs = parameters['bs']bo = parameters['bo']dz_t = (1 - s_t ** 2) * ds_t # 计算 z_t 的梯度dx_t = np.dot(U.T, dz_t) # 计算 x_t 的梯度值dUt = np.dot(dz_t, x_t.T) # 计算 U 的梯度值ds_prev = np.dot(W.T, dz_t) # 计算 s_prev 的梯度值, s_prev 就是 s_t_1, ds_prev的含义是当前损失对前一时刻隐层状态输出的导数dWt = np.dot(dz_t, s_prev.T) # 计算 W 的梯度值dbst = np.sum(dz_t, axis=1, keepdims=True) # 计算 bs 的梯度dVt = np.dot(do_t, s_t.T) # 计算 V 的梯度值dbot = np.sum(do_t, axis=1, keepdims=True) # 计算 bo 的梯度值# 将所求梯度存进字典gradient = {"dz_t": dz_t, "dx_t": dx_t, "ds_prev": ds_prev, "dUt": dUt, "dWt": dWt, "dbst": dbst, "dVt": dVt,"dbot": dbot}return gradient# 整体反向传播, 其中 ds 为所有 ds_t 的集合, do 为所有 do_t 的集合, 两者需要提前计算传入
def rnn_LMing_backward(ds, do, caches):"""对单个时刻进行反向传播:paramds: 所有时刻损失对隐层输出结果的导数do: 所有时刻损失对模型输出结果的导数cache: 当前时刻的缓存参数:return:gradients: 梯度字典"""# 获取第一个时刻的数据, 参数, 输入输出值(s1, s0, x_1, parameters) = caches[0]# 获取时刻数以及 m 和 n 的值n, _, T = ds.shapem, _ = x_1.shape# 初始化梯度值dx = np.zeros((m, 1, T))dU = np.zeros((n, m))dW = np.zeros((n, n))dbs = np.zeros((n, 1))dV = np.zeros((m, n))dbo = np.zeros((m, 1))ds_prev = np.zeros((n, 1))# 循环从后往前进行反向传播for t in reversed(range(T)):# 根据时间 T 的 s 梯度,以及缓存计算当前时刻的反向传播梯度gradient = rnn_LMing_moment_backward((ds[:, :, t] + ds_prev), do[:, :, t], caches[t])# 获取梯度准备进行更新dx_t, ds_prev, dUt, dWt, dbst, dVt, dbot = gradient["dx_t"], gradient["ds_prev"], gradient["dUt"], gradient["dWt"], gradient["dbst"], gradient["dVt"], gradient["dbot"]# 进行每次 t 时间上的梯度接过相加, 作为最终更新的梯度dx[:, :, t] = dx_tdU += dUtdW += dWtdbs += dbstdV += dVtdbo += dbotds0 = ds_prevgradients = {"dU": dU, "dW": dW, "dbs": dbs, "dV": dV, "dbo": dbo, "dx": dx, "ds0": ds0}return gradients相关文章:
各类神经网络学习:(三)RNN 循环神经网络(中集),同步多对多结构的详细解释
上一篇下一篇RNN(上集)RNN(下集) 同步多对多结构 1)结构详解 ①图解: ②参数含义: x t x_t xt :表示每一个时刻的输入; o t o_t ot :表示每一个时刻的输…...
Python Web 框架 Django、Flask 和 FastAPI 对比
在探索 Python Web 框架时,Django、Flask 和 FastAPI 无疑是最常被提及的名字。根据我们最新的 Python 开发者调查,这三大框架继续稳坐后端 Web 开发的热门宝座。它们均为开源项目,并且与 Python 的最新版本无缝兼容。然而,面对不…...
Hyperlane 似乎是一个轻量级、高性能的 Rust HTTP 服务器库
关键要点 Hyperlane 是一个轻量级、高性能的 Rust HTTP 服务器库,适合简化网络服务开发。它支持 HTTP 请求解析、响应构建、TCP 通信,并提供中间件、WebSocket 和服务器发送事件(SSE)功能。安装通过 cargo add hyperlane 完成&am…...
【计算机网络运输层详解】
文章目录 一、前言二、运输层的功能1. 端到端通信2. 复用与分用3. 差错检测4. 流量控制5. 拥塞控制 三、运输层协议:TCP 和 UDP1. TCP:面向连接的可靠传输协议2. UDP:无连接的传输协议 四、端口号与进程通信1. 端口号分类2. 端口通信模型 五、…...
UR5e机器人位姿
UR5e 作为一款 6 自由度协作机器人,其末端执行器的位姿(位置与姿态的组合)控制是实现精准操作的核心。在笛卡尔坐标系中,位姿通常用齐次变换矩阵表示,包含末端的三维位置(x, y, z)和三维姿态&am…...
导入 Excel 规则批量修改或删除 PDF 文档内容
需要对 PDF 文档内容进行修改的时候,通常我们会需要借助一些专业的工具来帮我们完成。那我们如果需要修改的 PDF 文档较多的时候,有什么方法可以帮我们实现批量操作呢?今天这篇文章就给大家介绍一下当我们需要批量修改多个 PDF 文档的时候&am…...
大模型tokenizer重构流程
大模型tokenizer层再训练(选取Qwen7B试验,重构token层) 最近公司可能想训练一个蛋白质大模型,需要了解一下大模型tokenizer重构,之后可能要训练,这里做了一定的总结。 文章目录 1. 首先查看Qwen2.5 7B基本…...
JAVA线程安全的集合类分类
1. 传统同步集合类(早期实现,性能较低) Vector 动态数组实现,所有方法通过 synchronized 同步锁保证线程安全。 Stack 继承自 Vector,实现后进先出(LIFO)堆栈,同步锁机…...
ISIS-1 ISIS概述
前面几章我们介绍了OSPF的基础工作原理以及怎样交互LSA形成LSDB链路状态数据库的 这一章我们来介绍另一个链路状态路由协议,ISIS路由协议 一、概述 ISIS(Intermediate System to Intermediate System,中间系统到中间系统)是由ISO(International Organization for Standardiza…...
茱元游戏TV2.9.3 | 适配多设备的经典街机游戏集合
茱元游戏TV是一款专为TV端设计的游戏软件,同时适配手机、投影仪和车机等多种设备。尽管其兼容性一般,仅支持安卓9.0以上系统,但它提供了丰富的经典街机游戏资源,非常适合8090后怀旧游玩。注意,游戏需先下载才能玩&…...
RTD2525BE《HDMI转EDP,DP转EDP》显示器芯片
一、产品概述 瑞昱RTD2525BE是一款专为高端显示设备设计的多接口转换芯片,支持HDMI 2.0与DisplayPort(DP)1.4双输入,并高效转换为嵌入式DisplayPort(eDP)输出。该芯片集成先进信号处理技术,支持…...
SvelteKit 最新中文文档教程(10)—— 部署 Cloudflare Pages 和 Cloudflare Workers
前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte …...
springboot使用阿里限流框架-sentinel
当前项目源码 控制台下载 启动bin中的看板服务:账号密码:sentinel/sentinel 官方文档地址 项目引入依赖 <!-- sentinel注解支持 --> <dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-annotation-aspectj<…...
鸿蒙特效教程10-卡片展开/收起效果
鸿蒙特效教程10-卡片展开/收起效果 在移动应用开发中,卡片是一种常见且实用的UI元素,能够将信息以紧凑且易于理解的方式呈现给用户。 本教程将详细讲解如何在HarmonyOS中实现卡片的展开/收起效果,通过这个实例,你将掌握ArkUI中状…...
Qt在模块依靠情况下资源文件名称和资源名称的使用限制
概述 在Qt中使用添加资源文件的时候,对于资源文件名称的定义,往往是较为随意的。 但是当涉及到Qt库依赖的时候,则可能需要遵守一定的规则,否则可能出现文件找不到或者错误加载的问题。 环境 环境名称Qt 版本系统版本LinuxQt 5.…...
MTK Android12-Android13 设置系统默认语言
Android 系统,默认语言 文章目录 需求:场景 参考资料实现方案实现思路编译脚本熟悉-平台熟悉mssi_64_cnkernel-4.19 解决方案修改文件-实现方案 源码分析PRODUCT_LOCALES 引用PRODUCT_DEFAULT_LOCALE 定义get-default-product-locale 方法定义PRODUCT_DE…...
【003安卓开发方案调研】之ReactNative技术开发安卓
基于2025年最新行业动态和搜索资料,以下是针对国内使用React Native(RN)开发安卓应用的深度分析: 一、技术成熟度评估 1. 核心架构升级 新架构全面普及:2024年起,React Native的 新架构(Fabri…...
CSS3学习教程,从入门到精通,CSS3 浮动与清除浮动语法知识点及案例代码(14)
CSS3 浮动与清除浮动语法知识点及案例代码 一、浮动基础 浮动语法 选择器 {float: left|right|none|initial|inherit; }left:元素向左浮动。right:元素向右浮动。none:默认值,元素不浮动。initial:使用默认值。inhe…...
贪心算法——思路与例题
贪心算法:当我们分析一个问题时,我们往往先以最优的方式来解决问题,所以顾名思义为贪心。 例题1 题目分析:这题利用贪心算法来分析,最优解(可容纳人数最多时)一定是先考虑六人桌,然…...
网络华为HCIA+HCIP 防火墙
防火墙部署模式 路由模式 有路由器的功能 路由器干的活 他都得干 透明模式 旁挂模式 IDS 端口镜像 VPN...
WordPress超级菜单插件UberMenu v3.78汉化版
一、插件介绍 UberMenu 是一款功能强大的 WordPress 超级菜单插件,能够帮助站长创建响应式、可自定义的多级菜单。该插件支持动态内容加载、图标、图片、搜索框等丰富功能,并且兼容大多数 WordPress 主题。 UberMenu v3.78 经过完整汉化,适用于中文站点用户,让操作更加直观…...
SQL中体会多对多
我们可以根据学生与课程多对多关系的数据库模型,给出实际的表数据以及对应的查询结果示例,会用到JOINLEFT JOIN两种连接 1. 学生表(students) student_idstudent_name1张三2李四3王五 2. 课程表(courses)…...
23种设计模式-备忘录(Memento)设计模式
备忘录设计模式 🚩什么是备忘录设计模式?🚩备忘录设计模式的特点🚩备忘录设计模式的结构🚩备忘录设计模式的优缺点🚩备忘录设计模式的Java实现🚩代码总结🚩总结 🚩什么是…...
2024年3月全国计算机等级考试真题(二级C语言)
😀 第1题 下列叙述中正确的是 A. 矩阵是非线性结构 B. 数组是长度固定的线性表 C. 对线性表只能作插入与删除运算 D. 线性表中各元素的数据类型可以不同 题目解析: A. 矩阵是非线性结构 错误。矩阵通常是二维数组,属…...
计算机网络基础之三种交换技术及其性能分析
一. 交换技术基础 1. 三种交换技术 电路交换:用于电话网络报文交换:用于电报网络分组交换:用于现代计算机网络 2. 人类历史上的通信网络 #mermaid-svg-AeGvrkUbCkicFOIo {font-family:"trebuchet ms",verdana,arial,sans-serif;…...
使用python爬取网络资源
整体思路 网络资源爬取通常分为以下几个步骤: 发送 HTTP 请求:使用requests库向目标网站发送请求,获取网页的 HTML 内容。解析 HTML 内容:使用BeautifulSoup库解析 HTML 内容,从中提取所需的数据。处理数据ÿ…...
【MySQL】索引 事务
目录 一、索引 概念 作用 使用场景 使用 查看索引 创建索引 删除索引 背后的数据结构 二、事务 为什么使用事务 事务的概念 使用 开启事务 执行多条 SQL 语句 回滚或提交:rollback/commit; 事务的基本特性 原子性 一致性 持久性 隔离性 脏读 …...
平台与架构:深度解析与开发实践
平台与架构:深度解析与开发实践 1. 什么是平台与架构? 平台(Platform):指操作系统或运行环境,例如 linux、windows、darwin(macOS)、android 等。架构(Architecture&…...
【Springboot+JPA】存储过程Procedure使用及踩坑记录
SpringbootJPA存储过程调用 存储过程实现1.表结构2.上报数据分页查询2.1先查出总条数2.1.1 创建存储过程2.1.2 实体类声明存储过程2.1.3 仓库方法绑定存储过程2.1.4 服务调用存储过程 2.2返回分页数据2.2.1 创建存储过程2.2.2 实体类声明存储过程2.2.3 仓库方法绑定存储过程2.2…...
<template>标签的作用,在构建可复用 UI 片段时如何应用?
大白话标签的作用,在构建可复用 UI 片段时如何应用 <template>标签的作用 在前端开发里,<template>标签可是个超棒的工具。它就像是一个“代码仓库”,可以把一些 HTML 代码片段存起来,而且这些代码片段在页面刚加载…...
