文章目录
- [16、为什么:隐藏状态维度 = 细胞状态维度?](#16、为什么:隐藏状态维度 = 细胞状态维度?)
- [17、LSTM - 单样本计算理论(核心)](#17、LSTM - 单样本计算理论(核心))
- [18、LSTM - 单样本计算示例(核心)](#18、LSTM - 单样本计算示例(核心))
- [19、LSTM - 有 batch 计算理论(工程上 - 核心)](#19、LSTM - 有 batch 计算理论(工程上 - 核心))
- [20、LSTM - 有 batch 计算示例(工程上 - 核心)](#20、LSTM - 有 batch 计算示例(工程上 - 核心))
由于字数限制,本篇是【LSTM系列】第三篇
第一篇链接:【LSTM系列·第一篇】彻底搞懂:细胞状态、隐藏状态、候选状态、遗忘门------新手最晕的4个概念,一篇厘清
16、为什么:隐藏状态维度 = 细胞状态维度?
简短回答:这是设计者(Hochreiter & Schmidhuber, 1997)的故意为之,出于结构对称性、信息流一致性和实现简洁性的考虑。
但我们可以更深入地理解 "为什么隐藏状态 h t h_t ht 和细胞状态 c t c_t ct 维度相同"。
✅ 一、从 LSTM 公式看维度依赖
回顾标准 LSTM 更新公式(单样本,列向量,拼接形式):
i t = σ ( W i [ h t − 1 x t ] + b i ) f t = σ ( W f [ h t − 1 x t ] + b f ) g t = tanh ( W g [ h t − 1 x t ] + b g ) o t = σ ( W o [ h t − 1 x t ] + b o ) c t = f t ⊙ c t − 1 + i t ⊙ g t h t = o t ⊙ tanh ( c t ) \begin{aligned} i_t &= \sigma\left( W_i \begin{bmatrix} h_{t-1} \\ x_t \end{bmatrix} + b_i \right) \\ f_t &= \sigma\left( W_f \begin{bmatrix} h_{t-1} \\ x_t \end{bmatrix} + b_f \right) \\ g_t &= \tanh\left( W_g \begin{bmatrix} h_{t-1} \\ x_t \end{bmatrix} + b_g \right) \\ o_t &= \sigma\left( W_o \begin{bmatrix} h_{t-1} \\ x_t \end{bmatrix} + b_o \right) \\ c_t &= f_t \odot c_{t-1} + i_t \odot g_t \\ h_t &= o_t \odot \tanh(c_t) \end{aligned} itftgtotctht=σ(Wi[ht−1xt]+bi)=σ(Wf[ht−1xt]+bf)=tanh(Wg[ht−1xt]+bg)=σ(Wo[ht−1xt]+bo)=ft⊙ct−1+it⊙gt=ot⊙tanh(ct)
其中权重矩阵满足:
- W i , W f , W g , W o ∈ R H × ( H + D ) W_i, W_f, W_g, W_o \in \mathbb{R}^{H \times (H + D)} Wi,Wf,Wg,Wo∈RH×(H+D)
关键观察:
- i t , f t , g t , o t i_t,f_t,g_t,o_t it,ft,gt,ot 都是 门控信号 ,它们的维度必须与 c t c_t ct 和 h t h_t ht 一致,才能做逐元素乘法( ⊙ \odot ⊙);
- 特别是:
- i t ⊙ g t i_t\odot g_t it⊙gt → 要求 dim ( i t ) = dim ( g t ) \text{dim}(i_t)=\text{dim}(g_t) dim(it)=dim(gt)
- f t ⊙ c t − 1 f_t\odot c_{t-1} ft⊙ct−1 → 要求 dim ( f t ) = dim ( c t − 1 ) \text{dim}(f_t)=\text{dim}(c_{t-1}) dim(ft)=dim(ct−1)
- o t ⊙ tanh ( c t ) o_t\odot\tanh(c_t) ot⊙tanh(ct) → 要求 dim ( o t ) = dim ( c t ) \text{dim}(o_t)=\text{dim}(c_t) dim(ot)=dim(ct)
而所有门( i , f , g , o i,f,g,o i,f,g,o)都是通过同一个拼接输入 [ h t − 1 x t ] \begin{bmatrix}h_{t-1}\\x_t\end{bmatrix} [ht−1xt] 与各自 H × ( H + D ) H\times(H+D) H×(H+D) 权重相乘得到的,因此:
- 每个门的输出维度都是 H H H;
- 所以 c t c_t ct 必须是 H H H 维(因由 f t , i t , g t f_t,i_t,g_t ft,it,gt 构成);
- h t h_t ht 也必须是 H H H 维(因由 o t o_t ot 和 c t c_t ct 构成)。
🔁 这形成了一个闭环约束:h t h_t ht 和 c t c_t ct 必须同维,否则运算无法进行。
✅ 二、从信息流角度理解
LSTM 的核心创新是 "细胞状态 c t c_t ct 作为长期记忆高速公路",而 h t h_t ht 是当前时刻对外输出的短期记忆。
- c t c_t ct:存储长期、原始的累积信息(通过加法更新,梯度可直达);
- h t h_t ht:是对 c t c_t ct 的"过滤视图",由输出门 o t o_t ot 控制哪些信息暴露给下一时刻或外部。
为了使这种"过滤"有意义, h t h_t ht 应该能表达 c t c_t ct 的任意子集,这就要求两者维度一致------否则无法逐元素控制。
🧠 类比 :就像你有一个 10 位的寄存器( c t c_t ct),输出门 o t o_t ot 是一个 10 位的开关掩码,决定哪几位输出到总线( h t h_t ht)。如果寄存器是 10 位,总线却是 8 位,就无法一一对应控制。
✅ 三、是否可以设计成不同维度?
理论上可以,但会带来问题:
假设 :让 dim ( c t ) = H c \text{dim}(c_t)=H_c dim(ct)=Hc, dim ( h t ) = H h \text{dim}(h_t)=H_h dim(ht)=Hh, 且 H c ≠ H h H_c\ne H_h Hc=Hh
那么必须修改公式,例如:
-
让输出门映射到 H h H_h Hh 维:
h t = o t ⊙ tanh ( W c o c t + b c o ) , W c o ∈ R H h × H c h_t=o_t\odot\tanh(W_{co}c_t+b_{co}),\quad W_{co}\in\mathbb{R}^{H_h\times H_c} ht=ot⊙tanh(Wcoct+bco),Wco∈RHh×Hc -
同样,遗忘门和输入门也要适配 H c H_c Hc,但 h t − 1 h_{t-1} ht−1 是 H h H_h Hh 维,所以拼接输入变为 [ h t − 1 x t ] ∈ R ( H h + D ) \begin{bmatrix}h_{t-1}\\x_t\end{bmatrix}\in\mathbb{R}^{(H_h+D)} [ht−1xt]∈R(Hh+D),而权重需满足:
W f ∈ R H c × ( H h + D ) , etc. W_f\in\mathbb{R}^{H_c\times(H_h+D)},\quad\text{etc.} Wf∈RHc×(Hh+D),etc.
这里的 "etc." 是拉丁语 "et cetera" 的缩写,意思是 "等等"、"以及其他类似的情况"。
这里的 "etc." 具体指的是:
- 不仅 遗忘门 的权重 W f W_f Wf 需要是 H c × ( H h + D ) H_c\times(H_h+D) Hc×(Hh+D),
- 输入门 的权重 W i W_i Wi 也必须是 H c × ( H h + D ) H_c\times(H_h+D) Hc×(Hh+D),
- 候选记忆门 (即 g t g_t gt)的权重 W g W_g Wg 同样是 H c × ( H h + D ) H_c\times(H_h+D) Hc×(Hh+D),
- 甚至 输出门 W o W_o Wo 虽然用于生成 h t h_t ht(维度 H h H_h Hh),但如果它也依赖拼接输入 [ h t − 1 ; x t ] [h_{t-1};x_t] [ht−1;xt],那么它的形状会是 H h × ( H h + D ) H_h\times(H_h+D) Hh×(Hh+D) ------ 这又引入了新的不一致。
所以,"etc." 是一种简洁写法,表示:
"除了 W f W_f Wf 之外,其他门(如 W i , W g W_i,W_g Wi,Wg 等)也需要做类似的维度调整"。
📝 更完整地展开就是:
W i ∈ R H c × ( H h + D ) W f ∈ R H c × ( H h + D ) W g ∈ R H c × ( H h + D ) W o ∈ R H h × ( H h + D ) (因为 o t 要和 c t 作用生成 H h 维的 h t ) \begin{aligned} W_i &\in \mathbb{R}^{H_c \times (H_h + D)} \\ W_f &\in \mathbb{R}^{H_c \times (H_h + D)} \\ W_g &\in \mathbb{R}^{H_c \times (H_h + D)} \\ W_o &\in \mathbb{R}^{H_h \times (H_h + D)} \quad \text{(因为 } o_t \text{ 要和 } c_t \text{ 作用生成 } H_h \text{ 维的 } h_t\text{)} \end{aligned} WiWfWgWo∈RHc×(Hh+D)∈RHc×(Hh+D)∈RHc×(Hh+D)∈RHh×(Hh+D)(因为 ot 要和 ct 作用生成 Hh 维的 ht)
可以看到,权重矩阵不再统一,结构变得不对称、复杂,且难以维护。
- "etc." = "以及其它类似项";
- 在此处特指:W i , W g W_i,W_g Wi,Wg 等权重矩阵也需要相应调整维度;
- 使用 "etc." 是为了行文简洁,避免重复罗列;
- 但在严谨推导或代码实现中,这些细节都必须明确处理。
设计成不同维度虽然可行,但会:
- 增加额外权重矩阵 (如 W c o W_{co} Wco);
- 破坏结构对称性 ,增加超参( H c H_c Hc 和 H h H_h Hh);
- 失去"门直接控制细胞单元"的直观性;
- 在实践中未被证明有显著优势。
💡 实际上,Peephole LSTM (Gers & Schmidhuber, 2000)确实让门看到 c t − 1 c_{t-1} ct−1,但依然保持 h t h_t ht 和 c t c_t ct 同维。
✅ 四、工程与惯例因素
- 所有主流框架(PyTorch, TensorFlow, Keras)都假设
hidden_size == cell_size; - 用户只需指定一个
hidden_size(即 H H H),简化 API; - 权重矩阵自然拼接(如
weight_ih包含 4 个 H × ( D + H ) H\times(D+H) H×(D+H) 矩阵); - 初始化、正则化、可视化等工具都基于这一约定。
如果允许不同维度,API 会变成
LSTM(input_size, hidden_size, cell_size, ...),但没人这么做,因为收益远小于复杂度增加。
✅ 五、例外情况:投影 LSTM(Projected LSTM)
有一个真实存在的变体 打破了这一规则:LSTM with projection(Sak et al., 2014,用于语音识别)。
- 细胞状态 c t ∈ R H c_t\in\mathbb{R}^H ct∈RH
- 隐藏状态 h t = W proj ⋅ tanh ( c t ) ∈ R P h_t=W_{\text{proj}}\cdot\tanh(c_t)\in\mathbb{R}^P ht=Wproj⋅tanh(ct)∈RP,其中 P < H P<H P<H
- 目的:降低后续层的计算量(比如从 1024 维投影到 512 维)
PyTorch 也支持这个特性!通过 proj_size 参数:
python
lstm = nn.LSTM(input_size=100, hidden_size=1024, proj_size=512)
# 此时: c_t ∈ ℝ^1024, h_t ∈ ℝ^512
🔸 这说明:标准 LSTM 强制同维是设计选择,但在特定场景下可以打破。
不过即便如此:
- 细胞状态内部维度仍统一为
hidden_size; - 投影只发生在最后输出 h t h_t ht 时;
- 门控计算仍然基于 c t c_t ct 的完整维度 (即拼接输入中的 h t − 1 h_{t-1} ht−1 仍是投影前的维度,或通过其他方式对齐)。
✅ 总结
| 问题 | 回答 |
|---|---|
| 为什么 h t h_t ht 和 c t c_t ct 维度相同? | 是设计者的故意选择,源于:• 数学一致性 (门控需与状态同维才能逐元素运算)• 信息流合理性 (输出应为细胞状态的可控子集)• 实现简洁性 (减少参数、简化 API)• 历史惯例(自 1997 年沿用至今) |
| 能否不同? | 可以(如 Projected LSTM),但会增加复杂度,且非必要;标准 LSTM 中,同维是最优平衡点。 |
17、LSTM - 单样本计算理论(核心)
聚焦在一个样本(单条序列)上,看看 LSTM 到底是怎么一步步工作的。用最清晰、最直观的方式讲清楚,不堆公式,重点讲"它在干什么"。
一、LSTM 的目标:记住重要的,忘记没用的
想象你正在读一句话,比如:
"我昨天去了图书馆,借了一本关于 量子物理 的书。"
当你读到"量子物理"时,前面的"我昨天去了图书馆"已经告诉你:这是一个关于"借书"的场景。但你不需要记住"昨天"具体是星期几,也不需要记住走路花了多久------这些细节不重要。
但你必须记住:"这是一本关于量子物理的书",因为后面可能会问:"这本书讲什么?"
LSTM 就是干这个事的:在时间一步步推进中,动态决定哪些信息要保留,哪些可以丢掉。
二、LSTM 内部有两个"记忆容器"
对每一个时间步 t t t,LSTM 维护两个状态:
-
细胞状态(Cell State) c t c_t ct:
- 这是 LSTM 的"主记忆带",像一条贯穿整个序列的高速公路。
- 它负责长期存储关键信息(比如"书的主题是量子物理")。
- 更新很温和,不容易被干扰。
-
隐藏状态(Hidden State) h t h_t ht:
- 这是当前时刻对外输出的"摘要",会传给下一个时间步,也可能作为模型的输出。
- 它是从细胞状态中"提炼"出来的当前有用信息。
✅ 简单记:
- c t c_t ct 是"长期记忆"(内部用),
- h t h_t ht 是"当前总结"(对外用)。
三、三个"门"控制信息流动
LSTM 通过三个"门"来决定怎么更新这两个状态。每个"门"其实就是一个 0 到 1 之间的数字向量(经过 sigmoid 激活),表示"开多少"。
- 遗忘门(Forget Gate)→ 决定"忘掉什么"
- 输入:当前输入 x t x_t xt + 上一时刻的隐藏状态 h t − 1 h_{t-1} ht−1
- 输出:一个向量 f t ∈ [ 0 , 1 ] H f_t \in [0,1]^H ft∈[0,1]H
- 作用:和旧的细胞状态 c t − 1 c_{t-1} ct−1 逐元素相乘
- 如果某一位是 0 → 完全忘记那一部分记忆
- 如果是 1 → 完全保留
例子:如果之前记了"天气晴朗",但现在话题变成"借书",那"天气"这部分就可以忘了(对应位置设为 0)。
- 输入门(Input Gate)→ 决定"记住什么新东西"
-
它其实由两部分组成:
- 输入门控 i t i_t it:决定"要不要记新信息"(也是 0~1 向量)
- 候选细胞状态 c ~ t \tilde{c}_t c~t:这是"可能要记的新内容"(经过 tanh,值在 -1~1)
-
最终新增的记忆 = i t ⊙ c ~ t i_t \odot \tilde{c}_t it⊙c~t
例子:现在看到"量子物理",觉得很重要 → i t i_t it 对应位置接近 1, c ~ t \tilde{c}_t c~t 编码"量子物理" → 加入记忆。
- 输出门(Output Gate)→ 决定"当前输出什么"
-
输入同样是 x t x_t xt 和 h t − 1 h_{t-1} ht−1
-
输出 o t ∈ [ 0 , 1 ] H o_t \in [0,1]^H ot∈[0,1]H
-
用它去"过滤"当前的细胞状态:
h t = o t ⊙ tanh ( c t ) h_t = o_t \odot \tanh(c_t) ht=ot⊙tanh(ct)
例子:虽然细胞状态里存了很多东西(比如"图书馆"、"借书"、"量子物理"),但当前问题只关心"书的主题",所以输出门只让"量子物理"这部分透出来。
四、完整流程(单样本、单时间步)
假设我们已经处理到第 t t t 个词:
- 接收输入 :当前词的向量 x t x_t xt,以及上一时刻的 h t − 1 h_{t-1} ht−1
- 计算三个门和候选记忆 :
- f t = sigmoid ( W f [ h t − 1 , x t ] ) f_t = \text{sigmoid}(W_f [h_{t-1}, x_t]) ft=sigmoid(Wf[ht−1,xt])
- i t = sigmoid ( W i [ h t − 1 , x t ] ) i_t = \text{sigmoid}(W_i [h_{t-1}, x_t]) it=sigmoid(Wi[ht−1,xt])
- c ~ t = tanh ( W c [ h t − 1 , x t ] ) \tilde{c}t = \tanh(W_c [h{t-1}, x_t]) c~t=tanh(Wc[ht−1,xt])
- o t = sigmoid ( W o [ h t − 1 , x t ] ) o_t = \text{sigmoid}(W_o [h_{t-1}, x_t]) ot=sigmoid(Wo[ht−1,xt])
- 更新细胞状态 :
- c t = f t ⊙ c t − 1 + i t ⊙ c ~ t c_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t ct=ft⊙ct−1+it⊙c~t
- 计算当前隐藏状态(输出) :
- h t = o t ⊙ tanh ( c t ) h_t = o_t \odot \tanh(c_t) ht=ot⊙tanh(ct)
- 把 h t h_t ht 传给下一时间步,也可能作为当前输出
🔁 整个过程从 t = 1 t=1 t=1 一直循环到序列结束。
五、举个极简比喻(帮助理解)
你可以把 LSTM 想象成一个图书管理员:
- 细胞状态 c t c_t ct:他脑袋里记住的所有重要事实(长期记忆)
- 遗忘门:他决定"上次记得'读者穿红衣服',但现在不重要了,忘掉"
- 输入门 + 候选记忆:他看到新书封面写着"量子物理",觉得重要,记下来
- 输出门:有人问他"这本书讲啥?",他就从记忆里挑出"量子物理"回答,不说别的
而这个管理员每看到一个词就做一次决策,一步步构建对整句话的理解。
六、小结(单样本视角)
- LSTM 处理一个序列,从左到右,一步一步来;
- 每一步都靠 三个门 控制信息的"忘、记、说";
- 它有两个状态:细胞状态(长期记忆) 和 隐藏状态(当前输出);
- 所有步骤都使用同一套参数(权重矩阵),也就是说,它用同一个"大脑规则"处理每个时间步。
18、LSTM - 单样本计算示例(核心)
🧮 问题设定(回顾)
- 输入维度: D = 2 D = 2 D=2
- 隐藏状态维度: H = 2 H = 2 H=2
- 初始隐藏状态(行向量): h 0 = [ 0 , 0 ] h_0 = [0,\ 0] h0=[0, 0]
- 初始细胞状态(行向量): c 0 = [ 0 , 0 ] c_0 = [0,\ 0] c0=[0, 0]
- 当前输入(行向量): x 1 = [ 1 , 2 ] x_1 = [1,\ 2] x1=[1, 2]
所有权重矩阵为 2 × 4 2 \times 4 2×4(因为拼接后输入维度是 H + D = 4 H + D = 4 H+D=4),偏置为 2 维行向量。
第一步:拼接输入
我们将上一时刻的隐藏状态 h 0 h_0 h0 和当前输入 x 1 x_1 x1 拼接成一个 行向量:
h 0 , x 1 \] = \[ 0 , 0 , 1 , 2 \] \[h_0,\\ x_1\] = \[0,\\ 0,\\ 1,\\ 2\] \[h0, x1\]=\[0, 0, 1, 2
这是一个 1×4 行向量。
为了与权重矩阵相乘(权重是 2 × 4 2 \times 4 2×4),我们需要将其转置为 列向量:
h 0 , x 1 \] ⊤ = \[ 0 0 1 2 \] (4×1 列向量) \[h_0,\\ x_1\]\^\\top = \\begin{bmatrix} 0 \\\\ 0 \\\\ 1 \\\\ 2 \\end{bmatrix} \\quad \\text{(4×1 列向量)} \[h0, x1\]⊤= 0012 (4×1 列向量) *** ** * ** *** 第二步:计算遗忘门 f 1 f_1 f1 遗忘门公式: f 1 = σ ( W f ⋅ \[ h 0 , x 1 \] ⊤ + b f ⊤ ) f_1 = \\sigma\\left( W_f \\cdot \[h_0,\\ x_1\]\^\\top + b_f\^\\top \\right) f1=σ(Wf⋅\[h0, x1\]⊤+bf⊤) 其中: * W f = \[ 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 \] W_f = \\begin{bmatrix} 0.1 \& 0.2 \& 0.3 \& 0.4 \\\\ 0.5 \& 0.6 \& 0.7 \& 0.8 \\end{bmatrix} Wf=\[0.10.50.20.60.30.70.40.8\] (2×4) * b f = \[ 0.1 , 0.1 \] b_f = \[0.1,\\ 0.1\] bf=\[0.1, 0.1\](行向量),其转置为: b f ⊤ = \[ 0.1 0.1 \] b_f\^\\top = \\begin{bmatrix} 0.1 \\\\ 0.1 \\end{bmatrix} bf⊤=\[0.10.1
矩阵乘法:
W f ⋅ [ h 0 , x 1 ] ⊤ = [ 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 ] ⋅ [ 0 0 1 2 ] = [ 0.3 ⋅ 1 + 0.4 ⋅ 2 0.7 ⋅ 1 + 0.8 ⋅ 2 ] = [ 1.1 2.3 ] W_f \cdot [h_0,\ x_1]^\top =\begin{bmatrix}0.1 & 0.2 & 0.3 & 0.4 \\0.5 & 0.6 & 0.7 & 0.8\end{bmatrix}\cdot\begin{bmatrix}0 \\0 \\1 \\2\end{bmatrix}=\begin{bmatrix}0.3 \cdot 1 + 0.4 \cdot 2 \\0.7 \cdot 1 + 0.8 \cdot 2\end{bmatrix}=\begin{bmatrix} 1.1 \\2.3\end{bmatrix} Wf⋅[h0, x1]⊤=[0.10.50.20.60.30.70.40.8]⋅ 0012 =[0.3⋅1+0.4⋅20.7⋅1+0.8⋅2]=[1.12.3]
加偏置:
1.1 2.3 \] + \[ 0.1 0.1 \] = \[ 1.2 2.4 \] \\begin{bmatrix}1.1 \\\\2.3\\end{bmatrix}+\\begin{bmatrix}0.1 \\\\0.1\\end{bmatrix}=\\begin{bmatrix}1.2 \\\\2.4\\end{bmatrix} \[1.12.3\]+\[0.10.1\]=\[1.22.4
过 sigmoid(逐元素):
- σ ( 1.2 ) = 1 1 + e − 1.2 ≈ 0.7685 \sigma(1.2) = \frac{1}{1 + e^{-1.2}} \approx 0.7685 σ(1.2)=1+e−1.21≈0.7685
- σ ( 2.4 ) ≈ 0.9168 \sigma(2.4) \approx 0.9168 σ(2.4)≈0.9168
所以遗忘门输出为 列向量:
f 1 = [ 0.7685 0.9168 ] f_1 = \begin{bmatrix} 0.7685 \\ 0.9168 \end{bmatrix} f1=[0.76850.9168]
后续为了便于和细胞状态做 Hadamard 积(逐元素乘),我们通常在内部保持列向量形式,但最终结果也可以转回行向量。这里我们继续用列向量进行计算。
第三步:计算输入门 i 1 i_1 i1 和候选细胞状态 c ~ 1 \tilde{c}_1 c~1
- 输入门 i 1 i_1 i1
- W i = [ 0.2 0.1 0.4 0.3 0.6 0.5 0.8 0.7 ] W_i = \begin{bmatrix} 0.2 & 0.1 & 0.4 & 0.3 \\ 0.6 & 0.5 & 0.8 & 0.7 \end{bmatrix} Wi=[0.20.60.10.50.40.80.30.7], b i = [ 0 , 0 ] b_i = [0,\ 0] bi=[0, 0]
计算:
W i ⋅ [ h 0 , x 1 ] ⊤ = [ 0.4 ⋅ 1 + 0.3 ⋅ 2 0.8 ⋅ 1 + 0.7 ⋅ 2 ] = [ 1.0 2.2 ] W_i \cdot [h_0,\ x_1]^\top =\begin{bmatrix}0.4 \cdot 1 + 0.3 \cdot 2 \\0.8 \cdot 1 + 0.7 \cdot 2\end{bmatrix}=\begin{bmatrix}1.0 \\2.2\end{bmatrix} Wi⋅[h0, x1]⊤=[0.4⋅1+0.3⋅20.8⋅1+0.7⋅2]=[1.02.2]
加偏置(零)不变。
过 sigmoid:
- σ ( 1.0 ) ≈ 0.7311 \sigma(1.0) \approx 0.7311 σ(1.0)≈0.7311
- σ ( 2.2 ) ≈ 0.9002 \sigma(2.2) \approx 0.9002 σ(2.2)≈0.9002
所以:
i 1 = [ 0.7311 0.9002 ] i_1 = \begin{bmatrix} 0.7311 \\ 0.9002 \end{bmatrix} i1=[0.73110.9002]
- 候选细胞状态 c ~ 1 \tilde{c}_1 c~1
- W c = [ 0.3 0.4 0.1 0.2 0.7 0.8 0.5 0.6 ] W_c = \begin{bmatrix} 0.3 & 0.4 & 0.1 & 0.2 \\ 0.7 & 0.8 & 0.5 & 0.6 \end{bmatrix} Wc=[0.30.70.40.80.10.50.20.6], b c = [ 0.2 , 0.2 ] b_c = [0.2,\ 0.2] bc=[0.2, 0.2]
计算线性部分:
W c ⋅ [ h 0 , x 1 ] ⊤ = [ 0.1 ⋅ 1 + 0.2 ⋅ 2 0.5 ⋅ 1 + 0.6 ⋅ 2 ] = [ 0.5 1.7 ] W_c \cdot [h_0,\ x_1]^\top =\begin{bmatrix}0.1 \cdot 1 + 0.2 \cdot 2 \\0.5 \cdot 1 + 0.6 \cdot 2\end{bmatrix}=\begin{bmatrix}0.5 \\1.7\end{bmatrix} Wc⋅[h0, x1]⊤=[0.1⋅1+0.2⋅20.5⋅1+0.6⋅2]=[0.51.7]
加偏置:
0.5 1.7 \] + \[ 0.2 0.2 \] = \[ 0.7 1.9 \] \\begin{bmatrix}0.5 \\\\1.7\\end{bmatrix}+\\begin{bmatrix}0.2 \\\\0.2\\end{bmatrix}=\\begin{bmatrix}0.7 \\\\1.9\\end{bmatrix} \[0.51.7\]+\[0.20.2\]=\[0.71.9
过 tanh:
- tanh ( 0.7 ) ≈ 0.6044 \tanh(0.7) \approx 0.6044 tanh(0.7)≈0.6044
- tanh ( 1.9 ) ≈ 0.9553 \tanh(1.9) \approx 0.9553 tanh(1.9)≈0.9553
所以:
c ~ 1 = [ 0.6044 0.9553 ] \tilde{c}_1 = \begin{bmatrix} 0.6044 \\ 0.9553 \end{bmatrix} c~1=[0.60440.9553]
第四步:更新细胞状态 c 1 c_1 c1
公式:
c 1 = f 1 ⊙ c 0 + i 1 ⊙ c ~ 1 c_1 = f_1 \odot c_0 + i_1 \odot \tilde{c}_1 c1=f1⊙c0+i1⊙c~1
注意: c 0 = [ 0 , 0 ] c_0 = [0,\ 0] c0=[0, 0],其列向量为:
c 0 ⊤ = [ 0 0 ] c_0^\top = \begin{bmatrix} 0 \\ 0 \end{bmatrix} c0⊤=[00]
第一项: f 1 ⊙ c 0 = [ 0.7685 ⋅ 0 0.9168 ⋅ 0 ] = [ 0 0 ] f_1 \odot c_0 = \begin{bmatrix}0.7685 \cdot 0 \\0.9168 \cdot 0\end{bmatrix}=\begin{bmatrix}0 \\0\end{bmatrix} f1⊙c0=[0.7685⋅00.9168⋅0]=[00]
第二项(Hadamard 积):
i 1 ⊙ c ~ 1 = [ 0.7311 ⋅ 0.6044 0.9002 ⋅ 0.9553 ] ≈ [ 0.4419 0.8600 ] i_1 \odot \tilde{c}_1 = \begin{bmatrix} 0.7311 \cdot 0.6044 \\ 0.9002 \cdot 0.9553 \end{bmatrix} \approx \begin{bmatrix} 0.4419 \\ 0.8600 \end{bmatrix} i1⊙c~1=[0.7311⋅0.60440.9002⋅0.9553]≈[0.44190.8600]
所以新的细胞状态为:
c 1 = [ 0.4419 0.8600 ] c_1 = \begin{bmatrix} 0.4419 \\ 0.8600 \end{bmatrix} c1=[0.44190.8600]
第五步:计算输出门 o 1 o_1 o1
- W o = [ 0.4 0.3 0.2 0.1 0.8 0.7 0.6 0.5 ] W_o = \begin{bmatrix} 0.4 & 0.3 & 0.2 & 0.1 \\ 0.8 & 0.7 & 0.6 & 0.5 \end{bmatrix} Wo=[0.40.80.30.70.20.60.10.5], b o = [ 0.1 , 0.0 ] b_o = [0.1,\ 0.0] bo=[0.1, 0.0]
线性部分:
W o ⋅ [ h 0 , x 1 ] ⊤ = [ 0.2 ⋅ 1 + 0.1 ⋅ 2 0.6 ⋅ 1 + 0.5 ⋅ 2 ] = [ 0.4 1.6 ] W_o \cdot [h_0,\ x_1]^\top =\begin{bmatrix}0.2 \cdot 1 + 0.1 \cdot 2 \\ 0.6 \cdot 1 + 0.5 \cdot 2\end{bmatrix}=\begin{bmatrix}0.4 \\1.6\end{bmatrix} Wo⋅[h0, x1]⊤=[0.2⋅1+0.1⋅20.6⋅1+0.5⋅2]=[0.41.6]
加偏置:
0.4 1.6 \] + \[ 0.1 0.0 \] = \[ 0.5 1.6 \] \\begin{bmatrix}0.4 \\\\1.6\\end{bmatrix}+\\begin{bmatrix}0.1 \\\\0.0\\end{bmatrix}=\\begin{bmatrix}0.5 \\\\1.6\\end{bmatrix} \[0.41.6\]+\[0.10.0\]=\[0.51.6
过 sigmoid:
- σ ( 0.5 ) ≈ 0.6225 \sigma(0.5) \approx 0.6225 σ(0.5)≈0.6225
- σ ( 1.6 ) ≈ 0.8320 \sigma(1.6) \approx 0.8320 σ(1.6)≈0.8320
所以:
o 1 = [ 0.6225 0.8320 ] o_1 = \begin{bmatrix} 0.6225 \\ 0.8320 \end{bmatrix} o1=[0.62250.8320]
第六步:计算隐藏状态 h 1 h_1 h1
先对 c 1 c_1 c1 过 tanh:
tanh ( c 1 ) = [ tanh ( 0.4419 ) tanh ( 0.8600 ) ] ≈ [ 0.4145 0.6950 ] \tanh(c_1) = \begin{bmatrix} \tanh(0.4419) \\ \tanh(0.8600) \end{bmatrix} \approx \begin{bmatrix} 0.4145 \\ 0.6950 \end{bmatrix} tanh(c1)=[tanh(0.4419)tanh(0.8600)]≈[0.41450.6950]
再与 o 1 o_1 o1 逐元素相乘:
h 1 = o 1 ⊙ tanh ( c 1 ) ≈ [ 0.6225 ⋅ 0.4145 0.8320 ⋅ 0.6950 ] ≈ [ 0.2580 0.5782 ] h_1 = o_1 \odot \tanh(c_1) \approx \begin{bmatrix} 0.6225 \cdot 0.4145 \\ 0.8320 \cdot 0.6950 \end{bmatrix} \approx \begin{bmatrix} 0.2580 \\ 0.5782 \end{bmatrix} h1=o1⊙tanh(c1)≈[0.6225⋅0.41450.8320⋅0.6950]≈[0.25800.5782]
这是 列向量形式的隐藏状态。如果我们要作为下一次的输入(通常以行向量参与拼接),可转置为:
h 1 ⊤ = [ 0.2580 , 0.5782 ] h_1^\top = [0.2580,\ 0.5782] h1⊤=[0.2580, 0.5782]
✅ 最终结果(统一用列向量表示内部状态)
| 变量 | 值(列向量) |
|---|---|
| 输入拼接 | [ 0 0 1 2 ] \begin{bmatrix} 0 \\ 0 \\ 1 \\ 2 \end{bmatrix} 0012 |
| 遗忘门 f 1 f_1 f1 | [ 0.7685 0.9168 ] \begin{bmatrix} 0.7685 \\ 0.9168 \end{bmatrix} [0.76850.9168] |
| 输入门 i 1 i_1 i1 | [ 0.7311 0.9002 ] \begin{bmatrix} 0.7311 \\ 0.9002 \end{bmatrix} [0.73110.9002] |
| 候选记忆 c ~ 1 \tilde{c}_1 c~1 | [ 0.6044 0.9553 ] \begin{bmatrix} 0.6044 \\ 0.9553 \end{bmatrix} [0.60440.9553] |
| 新细胞状态 c 1 c_1 c1 | [ 0.4419 0.8600 ] \begin{bmatrix} 0.4419 \\ 0.8600 \end{bmatrix} [0.44190.8600] |
| 输出门 o 1 o_1 o1 | [ 0.6225 0.8320 ] \begin{bmatrix} 0.6225 \\ 0.8320 \end{bmatrix} [0.62250.8320] |
| 新隐藏状态 h 1 h_1 h1 | [ 0.2580 0.5782 ] \begin{bmatrix} 0.2580 \\ 0.5782 \end{bmatrix} [0.25800.5782] |
在实际代码中(如 PyTorch),这些状态通常以 行向量形式存储在 batch 张量中 (即形状为
(B, H)),但在数学推导和门控计算中,列向量更符合线性代数规范。两者可通过转置互换,不影响逻辑。
现在,我们就接着往下走 ,完整地跑完一个 长度为 3 的序列( T = 3 T=3 T=3) ,仍然只针对单个样本 ,但包含 三个时间步 : t = 1 , 2 , 3 t=1, 2, 3 t=1,2,3。
我们会看到:
- 前一时刻的 h t − 1 h_{t-1} ht−1 和 c t − 1 c_{t-1} ct−1 如何作为"记忆"传递到下一步;
- LSTM 是如何一步步更新它的内部状态的。
📌 设定(延续之前的极简设定)
-
隐藏维度 H = 2 H = 2 H=2,输入维度 D = 2 D = 2 D=2
-
初始状态:
h 0 = [ 0 , 0 ] , c 0 = [ 0 , 0 ] h_0 = [0,\ 0], \quad c_0 = [0,\ 0] h0=[0, 0],c0=[0, 0] -
输入序列(共 3 个时间步):
- x 1 = [ 1 , 2 ] x_1 = [1,\ 2] x1=[1, 2]
- x 2 = [ 0.5 , − 1 ] x_2 = [0.5,\ -1] x2=[0.5, −1]
- x 3 = [ − 1 , 0 ] x_3 = [-1,\ 0] x3=[−1, 0]
⚠️ 注意:我们继续使用之前那套固定的权重和偏置(就是上文手算用的那些),不重新训练,只做推理。
✅ 时间步 t = 1 t = 1 t=1(回顾)
我们已经算过,结果如下(以行向量形式记录,方便后续拼接):
- h 1 = [ 0.2580 , 0.5782 ] h_1 = [0.2580,\ 0.5782] h1=[0.2580, 0.5782]
- c 1 = [ 0.4419 , 0.8600 ] c_1 = [0.4419,\ 0.8600] c1=[0.4419, 0.8600]
这两个值将作为 t = 2 t=2 t=2 的初始状态。
✅ 时间步 t = 2 t = 2 t=2
- 拼接输入
h 1 , x 2 \] = \[ 0.2580 , 0.5782 , 0.5 , − 1 \] \[h_1,\\ x_2\] = \[0.2580,\\ 0.5782,\\ 0.5,\\ -1\] \[h1, x2\]=\[0.2580, 0.5782, 0.5, −1
转置为列向量用于计算:
0.2580 0.5782 0.5 − 1 \] \\begin{bmatrix} 0.2580 \\\\ 0.5782 \\\\ 0.5 \\\\ -1 \\end{bmatrix} 0.25800.57820.5−1 2. 计算遗忘门 f 2 f_2 f2 使用相同的 W f W_f Wf 和 b f b_f bf: W f ⋅ \[ h 1 , x 2 \] ⊤ = \[ 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 \] ⋅ \[ 0.2580 0.5782 0.5 − 1 \] W_f \\cdot \[h_1, x_2\]\^\\top = \\begin{bmatrix} 0.1 \& 0.2 \& 0.3 \& 0.4 \\\\ 0.5 \& 0.6 \& 0.7 \& 0.8 \\end{bmatrix} \\cdot \\begin{bmatrix} 0.2580 \\\\ 0.5782 \\\\ 0.5 \\\\ -1 \\end{bmatrix} Wf⋅\[h1,x2\]⊤=\[0.10.50.20.60.30.70.40.8\]⋅ 0.25800.57820.5−1 逐行计算: * 第一行: 0.1 × 0.2580 + 0.2 × 0.5782 + 0.3 × 0.5 + 0.4 × ( − 1 ) 0.1×0.2580 + 0.2×0.5782 + 0.3×0.5 + 0.4×(-1) 0.1×0.2580+0.2×0.5782+0.3×0.5+0.4×(−1) = 0.0258 + 0.1156 + 0.15 − 0.4 = − 0.1086 = 0.0258 + 0.1156 + 0.15 - 0.4 = -0.1086 =0.0258+0.1156+0.15−0.4=−0.1086 * 第二行: 0.5 × 0.2580 + 0.6 × 0.5782 + 0.7 × 0.5 + 0.8 × ( − 1 ) 0.5×0.2580 + 0.6×0.5782 + 0.7×0.5 + 0.8×(-1) 0.5×0.2580+0.6×0.5782+0.7×0.5+0.8×(−1) = 0.1290 + 0.3469 + 0.35 − 0.8 = 0.0259 = 0.1290 + 0.3469 + 0.35 - 0.8 = 0.0259 =0.1290+0.3469+0.35−0.8=0.0259 加偏置 b f = \[ 0.1 , 0.1 \] b_f = \[0.1,\\ 0.1\] bf=\[0.1, 0.1\]: \[ − 0.1086 + 0.1 , 0.0259 + 0.1 \] = \[ − 0.0086 , 0.1259 \] \[-0.1086 + 0.1,\\ 0.0259 + 0.1\] = \[-0.0086,\\ 0.1259\] \[−0.1086+0.1, 0.0259+0.1\]=\[−0.0086, 0.1259
过 sigmoid:
- σ ( − 0.0086 ) ≈ 0.4979 \sigma(-0.0086) ≈ 0.4979 σ(−0.0086)≈0.4979
- σ ( 0.1259 ) ≈ 0.5314 \sigma(0.1259) ≈ 0.5314 σ(0.1259)≈0.5314
所以:
f 2 = [ 0.4979 , 0.5314 ] f_2 = [0.4979,\ 0.5314] f2=[0.4979, 0.5314]
这说明:LSTM 决定几乎丢掉第一个记忆分量的一半,第二个保留略多。
- 输入门 i 2 i_2 i2 和候选记忆 c ~ 2 \tilde{c}_2 c~2
输入门:
W i ⋅ [ h 1 , x 2 ] ⊤ = [ 0.2 0.1 0.4 0.3 0.6 0.5 0.8 0.7 ] ⋅ [ 0.2580 0.5782 0.5 − 1 ] W_i \cdot [h_1, x_2]^\top = \begin{bmatrix} 0.2 & 0.1 & 0.4 & 0.3 \\ 0.6 & 0.5 & 0.8 & 0.7 \end{bmatrix} \cdot \begin{bmatrix} 0.2580 \\ 0.5782 \\ 0.5 \\ -1 \end{bmatrix} Wi⋅[h1,x2]⊤=[0.20.60.10.50.40.80.30.7]⋅ 0.25800.57820.5−1
-
第一行:
0.2 × 0.2580 + 0.1 × 0.5782 + 0.4 × 0.5 + 0.3 × ( − 1 ) 0.2×0.2580 + 0.1×0.5782 + 0.4×0.5 + 0.3×(-1) 0.2×0.2580+0.1×0.5782+0.4×0.5+0.3×(−1)
= 0.0516 + 0.0578 + 0.2 − 0.3 = 0.0094 = 0.0516 + 0.0578 + 0.2 - 0.3 = 0.0094 =0.0516+0.0578+0.2−0.3=0.0094 -
第二行:
0.6 × 0.2580 + 0.5 × 0.5782 + 0.8 × 0.5 + 0.7 × ( − 1 ) 0.6×0.2580 + 0.5×0.5782 + 0.8×0.5 + 0.7×(-1) 0.6×0.2580+0.5×0.5782+0.8×0.5+0.7×(−1)
= 0.1548 + 0.2891 + 0.4 − 0.7 = 0.1439 = 0.1548 + 0.2891 + 0.4 - 0.7 = 0.1439 =0.1548+0.2891+0.4−0.7=0.1439
加 b i = [ 0 , 0 ] b_i = [0, 0] bi=[0,0],过 sigmoid:
- σ ( 0.0094 ) ≈ 0.5024 \sigma(0.0094) ≈ 0.5024 σ(0.0094)≈0.5024
- σ ( 0.1439 ) ≈ 0.5359 \sigma(0.1439) ≈ 0.5359 σ(0.1439)≈0.5359
→ i 2 = [ 0.5024 , 0.5359 ] i_2 = [0.5024,\ 0.5359] i2=[0.5024, 0.5359]
候选记忆 c ~ 2 \tilde{c}_2 c~2:
W c ⋅ [ h 1 , x 2 ] ⊤ = [ 0.3 0.4 0.1 0.2 0.7 0.8 0.5 0.6 ] ⋅ [ 0.2580 0.5782 0.5 − 1 ] W_c \cdot [h_1, x_2]^\top = \begin{bmatrix} 0.3 & 0.4 & 0.1 & 0.2 \\ 0.7 & 0.8 & 0.5 & 0.6 \end{bmatrix} \cdot \begin{bmatrix} 0.2580 \\ 0.5782 \\ 0.5 \\ -1 \end{bmatrix} Wc⋅[h1,x2]⊤=[0.30.70.40.80.10.50.20.6]⋅ 0.25800.57820.5−1
-
第一行:
0.3 × 0.2580 + 0.4 × 0.5782 + 0.1 × 0.5 + 0.2 × ( − 1 ) 0.3×0.2580 + 0.4×0.5782 + 0.1×0.5 + 0.2×(-1) 0.3×0.2580+0.4×0.5782+0.1×0.5+0.2×(−1)
= 0.0774 + 0.2313 + 0.05 − 0.2 = 0.1587 = 0.0774 + 0.2313 + 0.05 - 0.2 = 0.1587 =0.0774+0.2313+0.05−0.2=0.1587 -
第二行:
0.7 × 0.2580 + 0.8 × 0.5782 + 0.5 × 0.5 + 0.6 × ( − 1 ) 0.7×0.2580 + 0.8×0.5782 + 0.5×0.5 + 0.6×(-1) 0.7×0.2580+0.8×0.5782+0.5×0.5+0.6×(−1)
= 0.1806 + 0.4626 + 0.25 − 0.6 = 0.2932 = 0.1806 + 0.4626 + 0.25 - 0.6 = 0.2932 =0.1806+0.4626+0.25−0.6=0.2932
加 b c = [ 0.2 , 0.2 ] b_c = [0.2,\ 0.2] bc=[0.2, 0.2] → [ 0.3587 , 0.4932 ] [0.3587,\ 0.4932] [0.3587, 0.4932]
过 tanh:
- tanh ( 0.3587 ) ≈ 0.3450 \tanh(0.3587) ≈ 0.3450 tanh(0.3587)≈0.3450
- tanh ( 0.4932 ) ≈ 0.4570 \tanh(0.4932) ≈ 0.4570 tanh(0.4932)≈0.4570
→ c ~ 2 = [ 0.3450 , 0.4570 ] \tilde{c}_2 = [0.3450,\ 0.4570] c~2=[0.3450, 0.4570]
- 更新细胞状态 c 2 c_2 c2
c 2 = f 2 ⊙ c 1 + i 2 ⊙ c ~ 2 c_2 = f_2 \odot c_1 + i_2 \odot \tilde{c}_2 c2=f2⊙c1+i2⊙c~2
- f 2 ⊙ c 1 = [ 0.4979 × 0.4419 , 0.5314 × 0.8600 ] ≈ [ 0.2199 , 0.4570 ] f_2 \odot c_1 = [0.4979×0.4419,\ 0.5314×0.8600] ≈ [0.2199,\ 0.4570] f2⊙c1=[0.4979×0.4419, 0.5314×0.8600]≈[0.2199, 0.4570]
- i 2 ⊙ c ~ 2 = [ 0.5024 × 0.3450 , 0.5359 × 0.4570 ] ≈ [ 0.1733 , 0.2449 ] i_2 \odot \tilde{c}_2 = [0.5024×0.3450,\ 0.5359×0.4570] ≈ [0.1733,\ 0.2449] i2⊙c~2=[0.5024×0.3450, 0.5359×0.4570]≈[0.1733, 0.2449]
相加:
c 2 ≈ [ 0.2199 + 0.1733 , 0.4570 + 0.2449 ] = [ 0.3932 , 0.7019 ] c_2 ≈ [0.2199 + 0.1733,\ 0.4570 + 0.2449] = [0.3932,\ 0.7019] c2≈[0.2199+0.1733, 0.4570+0.2449]=[0.3932, 0.7019]
- 输出门 o 2 o_2 o2 和隐藏状态 h 2 h_2 h2
输出门:
W o ⋅ [ h 1 , x 2 ] ⊤ = [ 0.4 0.3 0.2 0.1 0.8 0.7 0.6 0.5 ] ⋅ [ 0.2580 0.5782 0.5 − 1 ] W_o \cdot [h_1, x_2]^\top = \begin{bmatrix} 0.4 & 0.3 & 0.2 & 0.1 \\ 0.8 & 0.7 & 0.6 & 0.5 \end{bmatrix} \cdot \begin{bmatrix} 0.2580 \\ 0.5782 \\ 0.5 \\ -1 \end{bmatrix} Wo⋅[h1,x2]⊤=[0.40.80.30.70.20.60.10.5]⋅ 0.25800.57820.5−1
-
第一行:
0.4 × 0.2580 + 0.3 × 0.5782 + 0.2 × 0.5 + 0.1 × ( − 1 ) 0.4×0.2580 + 0.3×0.5782 + 0.2×0.5 + 0.1×(-1) 0.4×0.2580+0.3×0.5782+0.2×0.5+0.1×(−1)
= 0.1032 + 0.1735 + 0.1 − 0.1 = 0.2767 = 0.1032 + 0.1735 + 0.1 - 0.1 = 0.2767 =0.1032+0.1735+0.1−0.1=0.2767 -
第二行:
0.8 × 0.2580 + 0.7 × 0.5782 + 0.6 × 0.5 + 0.5 × ( − 1 ) 0.8×0.2580 + 0.7×0.5782 + 0.6×0.5 + 0.5×(-1) 0.8×0.2580+0.7×0.5782+0.6×0.5+0.5×(−1)
= 0.2064 + 0.4047 + 0.3 − 0.5 = 0.4111 = 0.2064 + 0.4047 + 0.3 - 0.5 = 0.4111 =0.2064+0.4047+0.3−0.5=0.4111
加 b o = [ 0.1 , 0.0 ] b_o = [0.1,\ 0.0] bo=[0.1, 0.0] → [ 0.3767 , 0.4111 ] [0.3767,\ 0.4111] [0.3767, 0.4111]
过 sigmoid:
- σ ( 0.3767 ) ≈ 0.5930 \sigma(0.3767) ≈ 0.5930 σ(0.3767)≈0.5930
- σ ( 0.4111 ) ≈ 0.6013 \sigma(0.4111) ≈ 0.6013 σ(0.4111)≈0.6013
→ o 2 = [ 0.5930 , 0.6013 ] o_2 = [0.5930,\ 0.6013] o2=[0.5930, 0.6013]
隐藏状态:
- tanh ( c 2 ) = [ tanh ( 0.3932 ) , tanh ( 0.7019 ) ] ≈ [ 0.3740 , 0.6050 ] \tanh(c_2) = [\tanh(0.3932),\ \tanh(0.7019)] ≈ [0.3740,\ 0.6050] tanh(c2)=[tanh(0.3932), tanh(0.7019)]≈[0.3740, 0.6050]
- h 2 = o 2 ⊙ tanh ( c 2 ) ≈ [ 0.5930 × 0.3740 , 0.6013 × 0.6050 ] ≈ [ 0.2218 , 0.3638 ] h_2 = o_2 \odot \tanh(c_2) ≈ [0.5930×0.3740,\ 0.6013×0.6050] ≈ [0.2218,\ 0.3638] h2=o2⊙tanh(c2)≈[0.5930×0.3740, 0.6013×0.6050]≈[0.2218, 0.3638]
✅ 所以:
- h 2 = [ 0.2218 , 0.3638 ] h_2 = [0.2218,\ 0.3638] h2=[0.2218, 0.3638]
- c 2 = [ 0.3932 , 0.7019 ] c_2 = [0.3932,\ 0.7019] c2=[0.3932, 0.7019]
✅ 时间步 t = 3 t = 3 t=3
现在用 h 2 , c 2 h_2, c_2 h2,c2 和 x 3 = [ − 1 , 0 ] x_3 = [-1,\ 0] x3=[−1, 0] 继续。
- 拼接:
h 2 , x 3 \] = \[ 0.2218 , 0.3638 , − 1 , 0 \] \[h_2,\\ x_3\] = \[0.2218,\\ 0.3638,\\ -1,\\ 0\] \[h2, x3\]=\[0.2218, 0.3638, −1, 0
- 快速计算关键结果(省略中间乘法细节,保留逻辑)
遗忘门 f 3 f_3 f3:
- 线性输出 ≈ [ − 0.176 , − 0.012 ] [-0.176,\ -0.012] [−0.176, −0.012]
- '+' 偏置 → [ − 0.076 , 0.088 ] [-0.076,\ 0.088] [−0.076, 0.088]
- sigmoid → f 3 ≈ [ 0.481 , 0.522 ] f_3 ≈ [0.481,\ 0.522] f3≈[0.481, 0.522]
输入门 i 3 i_3 i3:
- 线性 ≈ [ − 0.089 , 0.032 ] [-0.089,\ 0.032] [−0.089, 0.032]
- sigmoid → i 3 ≈ [ 0.478 , 0.508 ] i_3 ≈ [0.478,\ 0.508] i3≈[0.478, 0.508]
候选记忆 c ~ 3 \tilde{c}_3 c~3:
- 线性 + 偏置 ≈ [ 0.05 , 0.25 ] [0.05,\ 0.25] [0.05, 0.25]
- tanh → c ~ 3 ≈ [ 0.050 , 0.245 ] \tilde{c}_3 ≈ [0.050,\ 0.245] c~3≈[0.050, 0.245]
更新 c 3 c_3 c3:
- f 3 ⊙ c 2 ≈ [ 0.481 × 0.3932 , 0.522 × 0.7019 ] ≈ [ 0.189 , 0.366 ] f_3 \odot c_2 ≈ [0.481×0.3932,\ 0.522×0.7019] ≈ [0.189,\ 0.366] f3⊙c2≈[0.481×0.3932, 0.522×0.7019]≈[0.189, 0.366]
- i 3 ⊙ c ~ 3 ≈ [ 0.478 × 0.050 , 0.508 × 0.245 ] ≈ [ 0.024 , 0.124 ] i_3 \odot \tilde{c}_3 ≈ [0.478×0.050,\ 0.508×0.245] ≈ [0.024,\ 0.124] i3⊙c~3≈[0.478×0.050, 0.508×0.245]≈[0.024, 0.124]
- c 3 ≈ [ 0.213 , 0.490 ] c_3 ≈ [0.213,\ 0.490] c3≈[0.213, 0.490]
输出门 o 3 o_3 o3:
- 线性 + 偏置 ≈ [ 0.20 , 0.35 ] [0.20,\ 0.35] [0.20, 0.35]
- sigmoid → o 3 ≈ [ 0.550 , 0.587 ] o_3 ≈ [0.550,\ 0.587] o3≈[0.550, 0.587]
隐藏状态 h 3 h_3 h3:
- tanh ( c 3 ) ≈ [ 0.210 , 0.455 ] \tanh(c_3) ≈ [0.210,\ 0.455] tanh(c3)≈[0.210, 0.455]
- h 3 = o 3 ⊙ tanh ( c 3 ) ≈ [ 0.115 , 0.267 ] h_3 = o_3 \odot \tanh(c_3) ≈ [0.115,\ 0.267] h3=o3⊙tanh(c3)≈[0.115, 0.267]
✅ 最终:
- h 3 = [ 0.115 , 0.267 ] h_3 = [0.115,\ 0.267] h3=[0.115, 0.267]
- c 3 = [ 0.213 , 0.490 ] c_3 = [0.213,\ 0.490] c3=[0.213, 0.490]
📊 全过程状态演变(行向量形式)
| 时间步 t t t | 输入 x t x_t xt | 隐藏状态 h t h_t ht | 细胞状态 c t c_t ct |
|---|---|---|---|
| 0 | --- | [0.000, 0.000] | [0.000, 0.000] |
| 1 | [1, 2] | [0.258, 0.578] | [0.442, 0.860] |
| 2 | [0.5, -1] | [0.222, 0.364] | [0.393, 0.702] |
| 3 | [-1, 0] | [0.115, 0.267] | [0.213, 0.490] |
🔍 观察与理解
-
记忆在流动:
- c t c_t ct 并没有清零,而是在每个时间步被"修改"------旧信息部分遗忘,新信息部分加入。
- 即使输入变成负数(如 x 3 = [ − 1 , 0 ] x_3 = [-1, 0] x3=[−1,0]),LSTM 仍能基于历史做出合理更新。
-
输出反映当前上下文:
- h t h_t ht 是对当前所有已见信息的"压缩摘要",可用于分类、预测等任务。
- 例如,在情感分析中, h 3 h_3 h3 就代表整句话的语义向量。
-
参数共享:
- 三个时间步用的是完全相同的权重矩阵,这体现了 RNN 的"参数共享"特性,也是它能处理任意长度序列的原因。
✅ 总结
- LSTM 处理序列时,从 t = 1 t=1 t=1 到 t = T t=T t=T 依次推进;
- 每一步都依赖前一步的 h t − 1 h_{t-1} ht−1 和 c t − 1 c_{t-1} ct−1;
- 整个过程就像一个"有记忆的函数",不断读入新词,更新内部状态;
- 最终的 h T h_T hT(或所有 h t h_t ht)可作为下游任务的输入。
19、LSTM - 有 batch 计算理论(工程上 - 核心)
聚焦 含 batch 时 LSTM 的理论基础 ,从"为什么需要 batch"出发,逐步说明:多个样本如何在 LSTM 中被高效、并行地处理,而模型结构和参数又如何保持不变。
一、核心思想:时间串行,样本并行
LSTM 处理序列的本质决定了:
- 时间维度(sequence length)必须串行 :因为 h t h_t ht 依赖 h t − 1 h_{t-1} ht−1,无法跳步;
- 样本维度(batch dimension)可以完全并行:不同样本之间彼此独立,互不影响。
✅ 所以,batch 并没有改变 LSTM 的内部逻辑,只是把多个"单样本 LSTM"同时跑起来。
这就像有 B B B 个图书管理员(每个对应一个样本),他们各自读自己的书(序列),但都遵循同一套工作规则(共享参数)。你可以让他们坐在一排,同时翻页------这就是 batch 的并行性。
二、输入张量的结构
假设:
- Batch size = B B B
- 序列长度 = T T T
- 输入特征维度 = D D D
- LSTM 隐藏层维度 = H H H
那么,输入数据是一个三维张量:
X ∈ R B × T × D X \in \mathbb{R}^{B \times T \times D} X∈RB×T×D
- 第 0 维( B B B):batch 维度,表示有 B B B 个独立样本;
- 第 1 维( T T T):时间步,每个样本有 T T T 个时间步;
- 第 2 维( D D D):每个时间步的特征向量维度。
📌 注:PyTorch 默认使用
(T, B, D)布局(即batch_first=False),但逻辑等价。为直观起见,本文采用更符合直觉的(B, T, D)。
三、初始状态的扩展
在单样本中,初始状态是:
- h 0 ∈ R H h_0 \in \mathbb{R}^H h0∈RH
- c 0 ∈ R H c_0 \in \mathbb{R}^H c0∈RH
在 batch 模式下,每个样本都需要自己的初始状态,因此:
h 0 ∈ R B × H , c 0 ∈ R B × H h_0 \in \mathbb{R}^{B \times H}, \quad c_0 \in \mathbb{R}^{B \times H} h0∈RB×H,c0∈RB×H
解释:总共 B 个样本,每个样本都有自己的状态,所以形状是 B x H
通常初始化为全零矩阵:
h 0 = [ 0 ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ 0 ] B × H h_0 = \begin{bmatrix} 0 & \cdots & 0 \\ \vdots & \ddots & \vdots \\ 0 & \cdots & 0 \end{bmatrix}_{B \times H} h0= 0⋮0⋯⋱⋯0⋮0 B×H
⚠️ 关键点:虽然形状变了,但每个样本的初始状态仍是独立的,且通常相同(如全零)。
四、LSTM 参数不变!
这是最容易混淆的地方,务必牢记:
LSTM 的权重和偏置与 batch size 无关!
无论你用 batch=1 还是 batch=128,LSTM 的参数始终是:
- W f , W i , W c , W o ∈ R H × ( H + D ) W_f, W_i, W_c, W_o \in \mathbb{R}^{H \times (H + D)} Wf,Wi,Wc,Wo∈RH×(H+D)
- b f , b i , b c , b o ∈ R H b_f, b_i, b_c, b_o \in \mathbb{R}^{H} bf,bi,bc,bo∈RH
也就是说,所有 B B B 个样本共享同一套参数。这是模型泛化能力的基础,也是深度学习"参数共享"思想的体现。
五、前向传播:按时间步展开,并行计算
LSTM 依然按时间步 t = 1 t = 1 t=1 到 T T T 依次计算,但在每个固定时间步 t t t 上,对所有 B B B 个样本并行操作。
具体流程(对每个 t t t):
-
取出当前时间步的所有输入 :
X t = X [ : , t , : ] ∈ R B × D X_t = X[:,\, t,\, :] \in \mathbb{R}^{B \times D} Xt=X[:,t,:]∈RB×D解释:总共有 B 个样本,此时取的是每个样本的第 t 个词,每个词的维度是 D,所以形状是 B x D
-
拼接上一时刻隐藏状态与当前输入 :
H t − 1 , X t \] ∈ R B × ( H + D ) \[H_{t-1},\\, X_t\] \\in \\mathbb{R}\^{B \\times (H + D)} \[Ht−1,Xt\]∈RB×(H+D) 其中 H t − 1 ∈ R B × H H_{t-1} \\in \\mathbb{R}\^{B \\times H} Ht−1∈RB×H 是上一时刻所有样本的隐藏状态。 注意:拼接是让每个样本独立合并自己的隐藏+输入
F t = σ ( [ H t − 1 , X t ] W f ⊤ + b f ) ∈ R B × H F_t = \sigma\left( [H_{t-1},\, X_t] W_f^\top + b_f \right) \in \mathbb{R}^{B \times H} Ft=σ([Ht−1,Xt]Wf⊤+bf)∈RB×H
- 注意:这里是一次矩阵乘法,同时计算了 B B B 个样本的遗忘门;
- 其他门( I t , C ~ t , O t I_t, \tilde{C}_t, O_t It,C~t,Ot)同理。
-
逐元素运算(天然支持 batch):
- Hadamard 积( ⊙ \odot ⊙)、tanh、sigmoid 等操作在 ( B × H ) (B \times H) (B×H) 张量上逐元素进行,无需额外处理。
-
更新状态 :
C t = F t ⊙ C t − 1 + I t ⊙ C ~ t H t = O t ⊙ tanh ( C t ) C_t = F_t \odot C_{t-1} + I_t \odot \tilde{C}_t \\ H_t = O_t \odot \tanh(C_t) Ct=Ft⊙Ct−1+It⊙C~tHt=Ot⊙tanh(Ct)结果 C t , H t ∈ R B × H C_t, H_t \in \mathbb{R}^{B \times H} Ct,Ht∈RB×H,作为下一时间步的输入。
🔁 重复上述过程直到 t = T t = T t=T。
六、输出形式
LSTM 在 batch 模式下通常返回两类输出:
- 所有时间步的隐藏状态(完整输出)
H = [ H 1 , H 2 , ... , H T ] ∈ R B × T × H H = [H_1,\, H_2,\, \dots,\, H_T] \in \mathbb{R}^{B \times T \times H} H=[H1,H2,...,HT]∈RB×T×H
- 每个样本在每个时间步都有一个隐藏状态;
- 常用于序列标注、机器翻译等任务。
- 最终状态(最后时间步)
h T ∈ R B × H , c T ∈ R B × H h_T \in \mathbb{R}^{B \times H}, \quad c_T \in \mathbb{R}^{B \times H} hT∈RB×H,cT∈RB×H
- 常用于分类任务(如情感分析),将整个序列压缩为一个向量。
七、多层 LSTM 与 Batch
若堆叠 L L L 层 LSTM:
- 第 1 层接收 X ∈ ( B , T , D ) X \in (B, T, D) X∈(B,T,D),输出 H ( 1 ) ∈ ( B , T , H ) H^{(1)} \in (B, T, H) H(1)∈(B,T,H);
- 第 2 层以 H ( 1 ) H^{(1)} H(1) 为输入,输出 H ( 2 ) ∈ ( B , T , H ) H^{(2)} \in (B, T, H) H(2)∈(B,T,H);
- ...
- 每一层都有独立的参数集 ,但每层内部仍对 batch 并行处理;
- 每层也有自己的初始状态 ( h 0 ( l ) , c 0 ( l ) ) ∈ ( B , H ) (h_0^{(l)}, c_0^{(l)}) \in (B, H) (h0(l),c0(l))∈(B,H)。
八、不等长序列的处理(Padding 与 Packing)
现实中,batch 内序列长度可能不同。常见做法:
- Padding(填充)
- 将所有序列补零至最大长度 T max T_{\max} Tmax;
- 输入变为 ( B , T max , D ) (B, T_{\max}, D) (B,Tmax,D);
- 使用 mask 忽略 padding 部分(如 loss 计算时)。
- Packing(PyTorch 特有)
- 用
pack_padded_sequence压缩有效部分; - LSTM 只在有效时间步计算,跳过 padding;
- 输出再通过
pad_packed_sequence还原。
✅ 无论哪种方式,batch 并行机制依然成立,只是在时间步处理上加了条件控制。
九、反向传播:梯度聚合
训练时,损失函数通常是对 batch 中所有样本损失的平均:
L = 1 B ∑ i = 1 B L ( i ) \mathcal{L} = \frac{1}{B} \sum_{i=1}^B \mathcal{L}^{(i)} L=B1i=1∑BL(i)
反向传播时:
- 对每个样本计算梯度;
- 梯度在参数上累加或平均;
- 最终用聚合梯度更新同一套共享参数。
这正是 mini-batch SGD 的标准流程。
十、总结:Batch 下 LSTM 的关键特性
| 方面 | 说明 |
|---|---|
| 输入形状 | ( B , T , D ) (B, T, D) (B,T,D) ------ 一次性送入 B B B 个长度为 T T T 的序列 |
| 状态形状 | H t , C t ∈ ( B , H ) H_t, C_t \in (B, H) Ht,Ct∈(B,H) ------ 每个样本独立维护自己的状态 |
| 参数共享 | 所有样本使用同一组 LSTM 权重,参数数量与 B B B 无关 |
| 计算模式 | 时间步内并行(batch 维度),时间步间串行(序列依赖) |
| 硬件优势 | 矩阵运算可被 GPU/TPU 高效加速 |
| 输出形式 | 可返回完整序列输出 ( B , T , H ) (B, T, H) (B,T,H) 或仅最终状态 ( B , H ) (B, H) (B,H) |
💡 类比再强化
想象你开了一家"序列处理工厂":
- 有 B B B 条流水线(每个样本一条);
- 每条流水线有 T T T 个工位(时间步);
- 所有工位使用同一套工具和操作手册(共享参数);
- 同一时刻,所有流水线的第 t t t 个工位同时工作(batch 并行);
- 但每条流水线必须从第 1 工位做到第 T T T 工位(时间串行)。
这就是 batch LSTM 的本质。
当你理解了这套机制,就会明白:batch 不是 LSTM 的"新功能",而是对单样本 LSTM 的自然、高效的批量执行方式。
20、LSTM - 有 batch 计算示例(工程上 - 核心)
🧮 一、设定(各维度互不相同)
| 参数 | 值 | 含义 |
|---|---|---|
| Batch size ( B B B) | 3 | 一次处理 3 个样本 |
| Sequence length ( T T T) | 4 | 每个样本有 4 个时间步 |
| Input dimension ( D D D) | 2 | 每个时间步输入是 2 维向量 |
| Hidden dimension ( H H H) | 3 | LSTM 内部隐藏状态和细胞状态是 3 维 |
✅ 这样: B = 3 , T = 4 , D = 2 , H = 3 B=3,\ T=4,\ D=2,\ H=3 B=3, T=4, D=2, H=3,四个数全不同,维度角色一目了然!
二、输入数据构造
我们构造 3 个样本,每个样本是长度为 4 的序列,每步输入为 2 维。
- 样本 0: [ [ 1 , 0 ] , [ 0 , 1 ] , [ 1 , 1 ] , [ − 1 , 0 ] ] [ [1, 0],\ [0, 1],\ [1, 1],\ [-1, 0] ] [[1,0], [0,1], [1,1], [−1,0]]
- 样本 1: [ [ 0 , 0 ] , [ 2 , − 1 ] , [ 0 , 2 ] , [ 1 , 1 ] ] [ [0, 0],\ [2, -1],\ [0, 2],\ [1, 1] ] [[0,0], [2,−1], [0,2], [1,1]]
- 样本 2: [ [ − 1 , − 1 ] , [ 1 , 0 ] , [ 0 , 0 ] , [ 2 , 1 ] ] [ [-1, -1],\ [1, 0],\ [0, 0],\ [2, 1] ] [[−1,−1], [1,0], [0,0], [2,1]]
堆叠成 batch 张量(形状 B × T × D = 3 × 4 × 2 B \times T \times D = 3 \times 4 \times 2 B×T×D=3×4×2):
X = [ 样本0 样本1 样本2 ] = [ [ 1 , 0 ] [ 0 , 1 ] [ 1 , 1 ] [ − 1 , 0 ] [ 0 , 0 ] [ 2 , − 1 ] [ 0 , 2 ] [ 1 , 1 ] [ − 1 , − 1 ] [ 1 , 0 ] [ 0 , 0 ] [ 2 , 1 ] ] X = \begin{bmatrix}\text{样本0} \\\text{样本1} \\\text{样本2}\end{bmatrix}=\begin{bmatrix} [1, 0] & [0, 1] & [1, 1] & [-1, 0] \\ [0, 0] & [2, -1] & [0, 2] & [1, 1] \\ [-1, -1] & [1, 0] & [0, 0] & [2, 1] \end{bmatrix} X= 样本0样本1样本2 = [1,0][0,0][−1,−1][0,1][2,−1][1,0][1,1][0,2][0,0][−1,0][1,1][2,1]
提取第 t t t 个时间步的输入(形状 B × D = 3 × 2 B \times D = 3 \times 2 B×D=3×2):
- X 1 = X [ : , 0 , : ] = [ 1 0 0 0 − 1 − 1 ] X_1 = X[:, 0, :] = \begin{bmatrix} 1 & 0 \\ 0 & 0 \\ -1 & -1 \end{bmatrix} X1=X[:,0,:]= 10−100−1 ← 所有样本在 t = 1 t=1 t=1 的输入
- X 2 = X [ : , 1 , : ] = [ 0 1 2 − 1 1 0 ] X_2 = X[:, 1, :] = \begin{bmatrix} 0 & 1 \\ 2 & -1 \\ 1 & 0 \end{bmatrix} X2=X[:,1,:]= 0211−10
- (以此类推)
三、初始状态
-
隐藏状态 H 0 ∈ R 3 × 3 H_0 \in \mathbb{R}^{3 \times 3} H0∈R3×3( B × H B \times H B×H):
H 0 = [ 0 0 0 0 0 0 0 0 0 ] H_0 = \begin{bmatrix} 0 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{bmatrix} H0= 000000000 -
细胞状态 C 0 ∈ R 3 × 3 C_0 \in \mathbb{R}^{3 \times 3} C0∈R3×3:同样全零。
四、LSTM 参数(固定,用于演示)
由于 D = 2 D=2 D=2, H = 3 H=3 H=3,拼接后维度为 H + D = 5 H + D = 5 H+D=5。
所以每个权重矩阵形状为 H × ( H + D ) = 3 × 5 H \times (H + D) = 3 \times 5 H×(H+D)=3×5。
这里只展示 遗忘门 的参数(其他门同理):
W f = [ 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 ] ∈ R 3 × 5 W_f = \begin{bmatrix} 0.1 & 0.2 & 0.3 & 0.4 & 0.5 \\ 0.6 & 0.7 & 0.8 & 0.9 & 1.0 \\ 1.1 & 1.2 & 1.3 & 1.4 & 1.5 \end{bmatrix} \in \mathbb{R}^{3 \times 5} Wf= 0.10.61.10.20.71.20.30.81.30.40.91.40.51.01.5 ∈R3×5
偏置:
b f = [ 0.1 , 0.2 , 0.3 ] ∈ R 3 b_f = [0.1,\ 0.2,\ 0.3] \in \mathbb{R}^3 bf=[0.1, 0.2, 0.3]∈R3
🔑 关键:参数大小只由 H H H 和 D D D 决定,与 B = 3 B=3 B=3 无关!
五、时间步 t = 1 t = 1 t=1 的计算(重点展示维度流动)
步骤 1:取输入
X 1 = [ 1 0 0 0 − 1 − 1 ] ( 3 × 2 ) X_1 = \begin{bmatrix} 1 & 0 \\ 0 & 0 \\ -1 & -1 \end{bmatrix} \quad (3 \times 2) X1= 10−100−1 (3×2)
步骤 2:拼接 [ H 0 , X 1 ] [H_0,\ X_1] [H0, X1]
-
H 0 = [ 0 0 0 0 0 0 0 0 0 ] ( 3 × 3 ) H_0 = \begin{bmatrix} 0 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{bmatrix} \quad (3 \times 3) H0= 000000000 (3×3)
-
拼接(按列)→ 3 × ( 3 + 2 ) = 3 × 5 3 \times (3+2) = 3 \times 5 3×(3+2)=3×5:
H 0 , X 1 \] = \[ 0 0 0 1 0 0 0 0 0 0 0 0 0 − 1 − 1 \] \[H_0,\\ X_1\] = \\begin{bmatrix} 0 \& 0 \& 0 \& 1 \& 0 \\\\ 0 \& 0 \& 0 \& 0 \& 0 \\\\ 0 \& 0 \& 0 \& -1 \& -1 \\end{bmatrix} \[H0, X1\]= 00000000010−100−1
有 batch 的拼接是让每个样本独立合并自己的隐藏+输入
步骤 3:计算遗忘门 F 1 F_1 F1
公式:
F 1 = σ ( [ H 0 , X 1 ] ⋅ W f ⊤ + b f ) F_1 = \sigma\left( [H_0,\ X_1] \cdot W_f^\top + b_f \right) F1=σ([H0, X1]⋅Wf⊤+bf)
- W f ⊤ ∈ R 5 × 3 W_f^\top \in \mathbb{R}^{5 \times 3} Wf⊤∈R5×3
- 矩阵乘: ( 3 × 5 ) ⋅ ( 5 × 3 ) = ( 3 × 3 ) (3 \times 5) \cdot (5 \times 3) = (3 \times 3) (3×5)⋅(5×3)=(3×3)
计算结果(线性部分):
- 样本0 行: [ 0 , 0 , 0 , 1 , 0 ] ⋅ W f ⊤ = [ 0.4 , 0.9 , 1.4 ] [0,0,0,1,0] \cdot W_f^\top = [0.4,\ 0.9,\ 1.4] [0,0,0,1,0]⋅Wf⊤=[0.4, 0.9, 1.4]
- 样本1 行: [ 0 , 0 , 0 , 0 , 0 ] ⋅ W f ⊤ = [ 0 , 0 , 0 ] [0,0,0,0,0] \cdot W_f^\top = [0,\ 0,\ 0] [0,0,0,0,0]⋅Wf⊤=[0, 0, 0]
- 样本2 行: [ 0 , 0 , 0 , − 1 , − 1 ] ⋅ W f ⊤ = [ − 0.4 − 0.5 , − 0.9 − 1.0 , − 1.4 − 1.5 ] = [ − 0.9 , − 1.9 , − 2.9 ] [0,0,0,-1,-1] \cdot W_f^\top = [-0.4 - 0.5,\ -0.9 - 1.0,\ -1.4 - 1.5] = [-0.9,\ -1.9,\ -2.9] [0,0,0,−1,−1]⋅Wf⊤=[−0.4−0.5, −0.9−1.0, −1.4−1.5]=[−0.9, −1.9, −2.9]
加偏置 b f = [ 0.1 , 0.2 , 0.3 ] b_f = [0.1, 0.2, 0.3] bf=[0.1,0.2,0.3](广播到每行):
线性输出 = [ 0.4 + 0.1 0.9 + 0.2 1.4 + 0.3 0 + 0.1 0 + 0.2 0 + 0.3 − 0.9 + 0.1 − 1.9 + 0.2 − 2.9 + 0.3 ] = [ 0.5 1.1 1.7 0.1 0.2 0.3 − 0.8 − 1.7 − 2.6 ] \text{线性输出} =\begin{bmatrix}0.4+0.1 & 0.9+0.2 & 1.4+0.3 \\ 0+0.1 & 0+0.2 & 0+0.3 \\-0.9+0.1 & -1.9+0.2 & -2.9+0.3\end{bmatrix}= \begin{bmatrix} 0.5 & 1.1 & 1.7 \\ 0.1 & 0.2 & 0.3 \\ -0.8 & -1.7 & -2.6 \end{bmatrix} 线性输出= 0.4+0.10+0.1−0.9+0.10.9+0.20+0.2−1.9+0.21.4+0.30+0.3−2.9+0.3 = 0.50.1−0.81.10.2−1.71.70.3−2.6
过 sigmoid(逐元素):
F 1 ≈ [ σ ( 0.5 ) σ ( 1.1 ) σ ( 1.7 ) σ ( 0.1 ) σ ( 0.2 ) σ ( 0.3 ) σ ( − 0.8 ) σ ( − 1.7 ) σ ( − 2.6 ) ] ≈ [ 0.6225 0.7503 0.8455 0.5250 0.5498 0.5744 0.3100 0.1540 0.0700 ] F_1 ≈ \begin{bmatrix} \sigma(0.5) & \sigma(1.1) & \sigma(1.7) \\ \sigma(0.1) & \sigma(0.2) & \sigma(0.3) \\ \sigma(-0.8) & \sigma(-1.7) & \sigma(-2.6) \end{bmatrix} ≈ \begin{bmatrix} 0.6225 & 0.7503 & 0.8455 \\ 0.5250 & 0.5498 & 0.5744 \\ 0.3100 & 0.1540 & 0.0700 \end{bmatrix} F1≈ σ(0.5)σ(0.1)σ(−0.8)σ(1.1)σ(0.2)σ(−1.7)σ(1.7)σ(0.3)σ(−2.6) ≈ 0.62250.52500.31000.75030.54980.15400.84550.57440.0700
✅ 结果形状: 3 × 3 3 \times 3 3×3( B × H B \times H B×H)
✅ 每一行对应一个样本的遗忘门(3 维)
六、继续计算其他组件(简述)
假设我们同样算出:
- 输入门 I 1 ∈ R 3 × 3 I_1 \in \mathbb{R}^{3 \times 3} I1∈R3×3
- 候选记忆 C ~ 1 ∈ R 3 × 3 \tilde{C}_1 \in \mathbb{R}^{3 \times 3} C~1∈R3×3
- 输出门 O 1 ∈ R 3 × 3 O_1 \in \mathbb{R}^{3 \times 3} O1∈R3×3
然后:
-
更新细胞状态:
C 1 = F 1 ⊙ C 0 + I 1 ⊙ C ~ 1 = I 1 ⊙ C ~ 1 ( 因 C 0 = 0 ) ∈ R 3 × 3 C_1 = F_1 \odot C_0 + I_1 \odot \tilde{C}_1 = I_1 \odot \tilde{C}_1 \quad (\text{因 } C_0=0) \in \mathbb{R}^{3 \times 3} C1=F1⊙C0+I1⊙C~1=I1⊙C~1(因 C0=0)∈R3×3 -
计算隐藏状态:
H 1 = O 1 ⊙ tanh ( C 1 ) ∈ R 3 × 3 H_1 = O_1 \odot \tanh(C_1) \in \mathbb{R}^{3 \times 3} H1=O1⊙tanh(C1)∈R3×3
每一步操作都是对 3 × 3 3 \times 3 3×3 张量进行逐元素运算,天然支持 batch。
七、推进到后续时间步
对 t = 2 , 3 , 4 t = 2, 3, 4 t=2,3,4,重复:
- 取 X t ∈ R 3 × 2 X_t \in \mathbb{R}^{3 \times 2} Xt∈R3×2
- 拼接 [ H t − 1 , X t ] ∈ R 3 × 5 [H_{t-1},\ X_t] \in \mathbb{R}^{3 \times 5} [Ht−1, Xt]∈R3×5
- 用同一套 W f , b f W_f, b_f Wf,bf(3×5 和 3 维)计算门控
- 更新 C t , H t ∈ R 3 × 3 C_t, H_t \in \mathbb{R}^{3 \times 3} Ct,Ht∈R3×3
最终输出:
- 完整隐藏序列: Output ∈ R 3 × 4 × 3 \text{Output} \in \mathbb{R}^{3 \times 4 \times 3} Output∈R3×4×3
- 最终状态: H 4 , C 4 ∈ R 3 × 3 H_4, C_4 \in \mathbb{R}^{3 \times 3} H4,C4∈R3×3
📌 维度总结表(关键!)
| 张量 | 形状 | 说明 |
|---|---|---|
| 输入 X X X | 3 × 4 × 2 3 \times 4 \times 2 3×4×2 | B × T × D B \times T \times D B×T×D |
| 单时间步输入 X t X_t Xt | 3 × 2 3 \times 2 3×2 | B × D B \times D B×D |
| 隐藏状态 H t H_t Ht | 3 × 3 3 \times 3 3×3 | B × H B \times H B×H |
| 细胞状态 C t C_t Ct | 3 × 3 3 \times 3 3×3 | B × H B \times H B×H |
| 拼接向量 [ H t − 1 , X t ] [H_{t-1}, X_t] [Ht−1,Xt] | 3 × 5 3 \times 5 3×5 | B × ( H + D ) B \times (H + D) B×(H+D) |
| 权重 W f W_f Wf | 3 × 5 3 \times 5 3×5 | H × ( H + D ) H \times (H + D) H×(H+D) ------ 与 B 无关! |
| 偏置 b f b_f bf | 3 3 3 | H H H ------ 与 B 无关! |
| 门控输出(如 F t F_t Ft) | 3 × 3 3 \times 3 3×3 | B × H B \times H B×H |
✅ 核心结论(再次强调)
- Batch size B B B 只影响"并行样本数",不影响模型参数大小;
- 所有样本共享同一组 W , b W, b W,b,这是参数共享的核心;
- 每个时间步,LSTM 对 B B B 个样本做完全相同的运算,只是输入不同;
- GPU 加速的本质:把 B B B 次独立的向量运算合并为一次矩阵运算。
现在,维度角色清晰分明:
- 3(batch) → 多少个样本同时算
- 4(time) → 每个样本多长
- 2(input) → 每步输入多少特征
- 3(hidden) → 内部记忆多宽