基本构件: 神经元 (Neuron)
神经网络的基本计算单元,它接收输入,通过权重和偏置进行计算,然后通过激活函数产生输出。
- 权重 (Weights): 调节输入信号的重要性。
- 偏置 (Bias): 一个额外的可调参数,用于微调输出。
- 激活函数 (Activation Function): 引入非线性,使网络能学习复杂模式。
神经网络的基本计算单元,它接收输入,通过权重和偏置进行计算,然后通过激活函数产生输出。
神经元被组织成不同的“层”:
激活函数的关键作用是引入非线性 (俗称“掰弯”),允许网络学习复杂的决策边界。下面是两种最常见的激活函数及其特性。
ReLU 是一种“铰链”式的掰弯方式,是目前最流行的激活函数,因为它计算高效且能有效缓解梯度消失。
Tanh 是一种“S形”平滑曲线,它将输出“挤压”到一个固定的范围内。
网络通过“训练”来学习。这个过程的目标是调整权重和偏置,以最小化预测错误。
根据用于计算梯度的样本数量,梯度下降有三种主要“风格”。
使用**所有**训练样本计算梯度并更新一次。方向最准,但计算量巨大,不适用于大数据集。
每处理**一个**样本就更新一次。速度快,但更新不稳定(抖动大)。
使用一小批(如 32, 64 个)样本计算梯度并更新。**这是目前的主流方法**,在速度和稳定性之间取得了最佳平衡。
在深层网络中,梯度在反向传播时逐层相乘,变得越来越小,导致底层网络学习缓慢或停止。
梯度逐层相乘变得过大,导致权重更新过猛,训练崩溃 (结果变为 NaN)。
作为梯度消失/爆炸的解决方案,合理的初始化能让网络在训练之初就处于一个易于学习的状态。
目标是保持信号方差稳定。适用: Tanh / Sigmoid。
Var(w) ≈ 1 / nin
补偿 ReLU 激活函数丢掉的那一半信号。适用: ReLU。
Var(w) ≈ 2 / nin
原理是保持向量长度不变(只旋转,不缩放),非常适用于 RNN。
QTQ = I
CNN 的核心定位是擅长处理图像等空间数据。它通过模仿人类视觉系统,逐层提取特征。
每个神经元只连接到输入的一小块区域(如 3x3 像素),用于提取局部特征。
一个滤波器(一组权重)在整个图像上滑动,用同一组权重检测同一个特征(如一条垂直线)。
CNN 逐层构建更复杂的特征:
边缘、颜色
形状、纹理 (如: 眼睛、耳朵)
目标部件 (如: 脸)
网络的核心,通过滤波器提取特征。
对特征图进行压缩(下采样),以减少计算量并保留关键信息。
在网络的最后,将所有提取到的高级特征组合起来,进行最终的分类(如判断“是猫”还是“不是猫”)。
这是一个详细的、重构后的单步训练过程。目标:预测 '是猫' (y_true=1.0), 使用逻辑回归 (Sigmoid) 和二元交叉熵损失。
输入 (X) (4x4):
[[1, 2, 0, 3], [0, 1, 1, 5], [2, 0, 1, 0], [4, 1, 0, 2]]
卷积权重 (W_conv) (2x2):
[[0.5, 0.1], [0.2, 0.3]]
FC 权重 (W_fc) (4x1):
[[0.5], [0.1], [-0.2], [0.3]]
FC 偏置 (b_fc): 0.1
目标 (y_true): 1.0 (是猫)
使用 2x2 滤波器 (W_conv) 在 4x4 输入 (X) 上滑动,步长S=1。输出为 3x3 矩阵 Z_conv。
例如, 左上角 z₁₁ = (1*0.5)+(2*0.1)+(0*0.2)+(1*0.3) = 1.0
右上角 z₁₃ = (0*0.5)+(3*0.1)+(1*0.2)+(5*0.3) = 2.0
输出 (Z_conv):
[[1.0, 1.5, 2.0], [0.5, 0.9, 1.2], [2.1, 0.3, 1.1]]
应用 max(0, x)。由于所有值都 > 0,输出不变。
输出 (A_conv):
[[1.0, 1.5, 2.0], [0.5, 0.9, 1.2], [2.1, 0.3, 1.1]]
使用 2x2 池化,步长S=1。输出为 2x2 矩阵 Z_pool。
z₁₁ = max(1.0, 1.5, 0.5, 0.9) = 1.5 (来自 A_conv[0,1])
z₁₂ = max(1.5, 2.0, 0.9, 1.2) = 2.0 (来自 A_conv[0,2])
z₂₁ = max(0.5, 0.9, 2.1, 0.3) = 2.1 (来自 A_conv[2,0])
z₂₂ = max(0.9, 1.2, 0.3, 1.1) = 1.2 (来自 A_conv[1,2])
输出 (Z_pool):
[[1.5, 2.0], [2.1, 1.2]]
将 2x2 矩阵变为 1x4 向量。
Z_flat = [1.5, 2.0, 2.1, 1.2]A. 计算 Logit (z) = (Z_flat · W_fc) + b_fc
z = (1.5*0.5) + (2.0*0.1) + (2.1*-0.2) + (1.2*0.3) + 0.1 = 0.99B. 计算 Sigmoid (y_pred)
y_pred = sigmoid(0.99) = 1 / (1 + e-0.99) ≈ 0.73L = -[y·log(y_pred) + (1-y)·log(1-y_pred)]
L = -[1.0 * log(0.73) + 0] ≈ 0.31传递给线性层 (Logit z) 的梯度 G_z 是:
G_z = y_pred - y_true = 0.73 - 1.0 = -0.27G_W_fc = G_z · Z_flatT
G_W_fc = -0.27 * [1.5, 2.0, 2.1, 1.2]T = [[-0.405], [-0.54], [-0.567], [-0.324]]
G_b_fc = G_z = -0.27
G_Z_flat (传给下一层) = G_z · W_fcT
G_Z_flat = -0.27 * [0.5, 0.1, -0.2, 0.3] = [-0.135, -0.027, 0.054, -0.081]将 1x4 梯度 G_Z_flat 恢复为 2x2 形状。
G_Z_pool (2x2):
[[-0.135, -0.027], [0.054, -0.081]]
[关键原理 1: 梯度路由] 梯度只通过前向传播时的“赢家”位置。 G_A_conv (3x3) 初始化为全 0。
-0.135 (来自 G_Z_pool[0,0]) → 路由到 A_conv[0,1] (赢家是 1.5)
-0.027 (来自 G_Z_pool[0,1]) → 路由到 A_conv[0,2] (赢家是 2.0)
0.054 (来自 G_Z_pool[1,0]) → 路由到 A_conv[2,0] (赢家是 2.1)
-0.081 (来自 G_Z_pool[1,1]) → 路由到 A_conv[1,2] (赢家是 1.2)
G_A_conv (3x3):
[[0, -0.135, -0.027], [0, 0, -0.081], [0.054, 0, 0]]
G_Z_conv = G_A_conv ⊙ ReLU'(Z_conv)。由于 Z_conv 全为正, ReLU' 全为 1。
G_Z_conv (3x3):
[[0, -0.135, -0.027], [0, 0, -0.081], [0.054, 0, 0]]
[关键原理 2: 梯度汇总] G_W_conv 的梯度 = G_Z_conv (输出梯度) 与 X (输入) 卷积的结果。G_w11 的梯度是所有使用 w11 的地方的梯度总和。
G_w11 = (G_Z_conv[0,0]·X[0,0]) + (G_Z_conv[0,1]·X[0,1]) + (G_Z_conv[0,2]·X[0,2]) + ...
G_w11 = (0·1) + (-0.135·2) + (-0.027·0) + (0·0) + (0·1) + (-0.081·1) + (0.054·2) + (0·0) + (0·1)
G_w11 = 0 - 0.27 - 0 + 0 + 0 - 0.081 + 0.108 + 0 + 0 = -0.243
对 W_conv 的所有 4 个权重重复此“汇总”过程:
G_w12 = -0.351
G_w21 = 0.054
G_w22 = 0.027
G_W_conv (2x2):
[[-0.243, -0.351], [0.054, 0.027]]
new_weight = old_weight - (LR * gradient)
new_W_fc = [0.5, 0.1, -0.2, 0.3]T - (0.1 * [-0.405, -0.54, -0.567, -0.324]T)
new_W_fc = [0.5405, 0.154, -0.1433, 0.3324]Tnew_W_conv = [[0.5, 0.1], [0.2, 0.3]] - (0.1 * [[-0.243, -0.351], [0.054, 0.027]])
new_W_conv = [[0.5243, 0.1351], [0.1946, 0.2973]]疑惑: 如果权重是共享的,但反向传播时在不同位置计算出的梯度(如 `-10` 和 `+4`)不同,如何更新?
答案: 汇总 (Summation)
网络会把一个共享权重 (如 `w1`) 在**所有**位置上计算出的局部梯度**全部加起来**,得到一个“总梯度”。最后,只用这个“总梯度”来对那个唯一的、共享的 `w1` 进行一次更新。
总梯度 = (-10) + (+4) + (-7) + ...
疑惑: 池化层不是激活层,它如何传递梯度?
答案: 梯度路由器 (Gradient Router)
池化层只把梯度传递给那些在前向传播中被选为最大值的神经元。
RNN 的核心定位是擅长处理序列数据(如语言、时间)。它通过内部的“循环”结构来拥有“记忆”。
RNN 的隐藏层在计算后,会把结果的一部分传回给自己,供下一步计算使用。这使得信息可以在时间步之间传递。
一个常见的混淆点是“每个时间步是不是一个新的隐藏层”。答案是:不,它是**同一个隐藏层**在不同的时间步被**重复使用**了。
简单的 RNN 很难将序列开头和结尾的信息联系起来(即“长期记忆”差)。
常用于机器翻译,由两个RNN组成:
读取输入序列 (如: 英文),将其压缩成一个“上下文向量”,即对原句的"理解"。
接收上下文向量,然后逐词生成输出序列 (如: 中文)。
对任意变量 w 或 x 的梯度计算:
∂Loss/∂w = ∂Loss/∂output × ∂output/∂w
每一步的梯度计算公式取决于正向计算使用的函数:
💡 直观理解:维度匹配
转置 (h)^T 是为了匹配矩阵维度,实现外积运算
🧮 数学原理:链式法则
目标:求 ∂L/∂W_ij (第i行第j列权重的梯度)
链式法则展开:
∂L/∂W_ij = Σ(∂L/∂s_k × ∂s_k/∂W_ij)
🔑 关键发现:逐元素分析
当 k ≠ j 时:
∂s_k/∂W_ij = 0
权重不影响该输出
当 k = j 时:
∂s_j/∂W_ij = h_i
梯度等于输入值
最终结果:
∂L/∂W_ij = h_i × g_j
✅ 外积验证
外积 h^T × g 产生的矩阵:
位置(i,j)的值 = h_i × g_j 🎯
💎 核心洞察:转置不是技巧,是数学必然!
外积运算正是链式法则逐元素应用后的矩阵重组
当正向计算存在权重共享或变量共享时:
Total_∂Loss/∂w = Σ(各时间步的 ∂Loss/∂w)
变量类似权重,变量被多个权重共享,点积过程正是累加过程:输出 (1×4): G(h₂ᵈᵉᶜ) ≈ [0.03, 0.04, 0.03, 0.04]
默认约定:
目标: 严格遵循"穿越时间的反向传播"(BPTT)原则,详细展示共享权重的梯度在所有时间步的累加过程。
编码结束。上下文向量 🧠 C = h₂ᵉⁿᶜ = [0.997, 0.999, 0.9996, 0.9999]
正向传播总结: Total Loss = L₁ + L₂ ≈ 2.52 + 0.12 = 2.64
我们的目标是计算 Total Loss 对所有共享权重的梯度。我们将从 t=2 开始,一步步向后传播。我们将使用 G(...) 来表示"...的梯度"。
这一步只受 Loss₂ 的影响。
公式: ∂L₂/∂Logits₂ = Probs₂ - t₂
公式: ∂L₂/∂W_out = (h₂ᵈᵉᶜ)ᵀ · G(Logits₂)
公式: ∂L₂/∂h₂ᵈᵉᶜ = G(Logits₂) · (W_out)ᵀ
通过 tanh 激活函数反向传播
公式: G(h₂ᵈᵉᶜ) · (1 - (h₂ᵈᵉᶜ)²)
公式: (y₂)ᵀ · G(Sum₂ᵈᵉᶜ)
公式: (h₁ᵈᵉᶜ)ᵀ · G(Sum₂ᵈᵉᶜ)
🔥 关键:流向 t=1 的梯度
公式: G(Sum₂ᵈᵉᶜ) · (W_hh)ᵀ
这一步同时接收 Loss₁ 的梯度和 t=2 传来的梯度。
来自 L₁
公式: Probs₁ - t₁
公式: (h₁ᵈᵉᶜ)ᵀ · G(Logits₁)
来自 L₁ 的梯度
公式: G(Logits₁) · (W_out)ᵀ
🔥 关键:梯度汇合
公式: G(h₁ᵈᵉᶜ)_from_L1 + G(h₁ᵈᵉᶜ)_from_t2
公式: G(h₁ᵈᵉᶜ)_Total · (1 - (h₁ᵈᵉᶜ)²)
公式: (y₁)ᵀ · G(Sum₁ᵈᵉᶜ)
公式: (h₀ᵈᵉᶜ)ᵀ · G(Sum₁ᵈᵉᶜ)
🔥 关键:流向 Encoder 的梯度
公式: G(h₀ᵈᵉᶜ) = G(Sum₁ᵈᵉᶜ) · (W_hh)ᵀ
公式: G(h₂ᵉⁿᶜ) · (1 - (h₂ᵉⁿᶜ)²)
公式: G(h₁ᵉⁿᶜ) · (1 - (h₁ᵉⁿᶜ)²)
现在,我们将所有共享权重的部分梯度加在一起,得到最终的总梯度。
我们将两个 (4×5) 矩阵相加
我们将四个 (3×4) 矩阵相加
我们将四个 (4×4) 矩阵相加
我们将四个 (1×4) 向量相加
最后,我们使用这些汇总后的总梯度来更新我们的权重(假设学习率为 α):
正如您所看到的,由于 tanh 函数的饱和(正向传播的输出值接近 1.0),梯度在反向传播时变得极小(例如 G(Sum₂ᵈᵉᶜ) ≈ [0.000012, ...])。
当这个极小的梯度 G(C) 传回编码器时,它变得几乎为零(例如 G(Sum₂ᵉⁿᶜ) ≈ [6e-8, ...])。
G(W_xh)_t1_enc)几乎没有收到任何更新信号核心思想是将词语映射为高维空间中的向量,使得词语的“语义”可以通过数学计算来衡量。
向量运算可以捕捉词语间的类比关系:
国王 - 男人 + 女人 ≈ 女王
巴黎 - 法国 + 德国 ≈ 柏林
使用**余弦相似度 (Cosine Similarity)** 来衡量两个词的相似性。
基于“观其伴而知其言”的思想,通过一个“伪任务”来学习词向量。
用上下文的词(如 "quick", "fox"),来预测中间的词 ("brown")。
用中间的词 (如 "brown"),来预测上下文的词 ("quick", "fox")。
将复杂的多分类问题,转换为简单的二分类问题 (是/否),极大提高了训练效率。
目标: 用 "brown" 预测 "fox"。这是原始的、计算量大的方法。 (LR=0.01)
输入 "brown" (v_brown / h):
[0.7, 0.8, 0.1]
目标 "fox" (t):
[0, 0, 0, 1, 0]
W_in (5x3, "brown" 行):
...
[0.7, 0.8, 0.1] <-- 索引 2
...
W_out (3x5):
[[0.1, 0.5, 0.9, 0.4, 0.8], [0.2, 0.6, 1.0, 0.3, 0.7], [0.3, 0.7, 1.1, 0.2, 0.6]]
这是 (Softmax+交叉熵) 的组合导数:
G_scores = p - t[0.05, 0.13, 0.26, -0.91, 0.47]
Grad(W_out) = hT · G_scores (3x1 外积 1x5 = 3x5)
[[0.035, 0.091, 0.182, -0.637, 0.329], [0.040, 0.104, 0.208, -0.728, 0.376], [0.005, 0.013, 0.026, -0.091, 0.047]]
Grad(h) = G_scores · W_outT (1x5 矩阵乘 5x3 = 1x3)
[0.316, 0.404, 0.492]梯度 Grad(h) 只应用于 "brown" 对应的行 (LR=0.01):
new_v_brown = [0.7, 0.8, 0.1] - (0.01 * [0.316, 0.404, 0.492]) new_v_brown = [0.697, 0.796, 0.095]目标: "拉近" ("brown", "fox"),"推开" ("brown", "jumps")。 (LR=0.1)
v_brown · u_fox
[0.7, 0.8, 0.1] · [0.4, 0.3, 0.2] = 0.54v_brown · u_jumps
[0.7, 0.8, 0.1] · [0.8, 0.7, 0.6] = 1.18Total_Grad(v_brown) = Grad(v_brown_pos) + Grad(v_brown_neg)
Total_Grad(v_brown) = [0.148, 0.111, 0.074] + [-0.608, -0.532, -0.456] Total_Grad(v_brown) = [-0.46, -0.421, -0.382]new_v_brown = v_brown + (0.1 * Total_Grad(v_brown))
new_v_brown = [0.7, 0.8, 0.1] + [-0.046, -0.0421, -0.0382] new_v_brown = [0.654, 0.7579, 0.0618]目标: 用 ["quick", "fox"] 预测 "brown"。 (LR=0.01)
v_quick:
[0.4, 0.5, 0.6]
v_fox:
[0.2, 0.3, 0.4]
目标 "brown" (t):
[0, 0, 1, 0, 0]
W_out (3x5): (同上)
Grad(W_out) = hT · G_scores (3x1 外积 1x5 = 3x5)
[[0.033, 0.045, -0.234, 0.036, 0.120], [0.044, 0.060, -0.312, 0.048, 0.160], [0.055, 0.075, -0.390, 0.060, 0.200]]
Grad(h) = G_scores · W_outT
Grad(h) = [-0.248, -0.352, -0.456]梯度被平分给所有上下文词 (除以2):
Grad(v_quick) = Grad(h) / 2 = [-0.124, -0.176, -0.228] Grad(v_fox) = Grad(h) / 2 = [-0.124, -0.176, -0.228]目标: 用 ["quick", "fox"] "拉近" "brown", "推开" "jumps"。 (LR=0.1)