# 案例 ![image.png|1000](https://imagehosting4picgo.oss-cn-beijing.aliyuncs.com/imagehosting/fix-dir%2Fpicgo%2Fpicgo-clipboard-images%2F2025%2F01%2F26%2F17-11-08-23b92ea8f94d137be070996366dea9a6-202501261711777-7e48d7.png) # 前向传播 ## 1. 输入层到隐藏层的计算 $z^{(1)} = W^{(1)}x + b^{(1)}$ $a^{(1)} = \sigma(z^{(1)})$ ```Java 第一步: 计算加权和 z¹ = W¹x + b¹ [0.2 -0.5 0.1] [2] [0.3] [0.2(2) + (-0.5)(3) + 0.1(-1) + 0.3] [-0.3 0.4 0.2] × [3] + [-0.1] = [-0.3(2) + 0.4(3) + 0.2(-1) - 0.1] [-1] 详细计算: z₁ = 0.2(2) + (-0.5)(3) + 0.1(-1) + 0.3 = 0.4 - 1.5 - 0.1 + 0.3 = -0.9 z₂ = -0.3(2) + 0.4(3) + 0.2(-1) - 0.1 = -0.6 + 1.2 - 0.2 - 0.1 = 0.3 第二步: 应用Sigmoid激活函数 a¹ = σ(z¹) a₁ = σ(-0.9) = 1/(1 + e⁰·⁹) ≈ 0.29 a₂ = σ(0.3) = 1/(1 + e⁻⁰·³) ≈ 0.57 ``` ## 2. 隐藏层到输出层的计算 $z^{(2)} = W^{(2)}a^{(1)} + b^{(2)}$ $a^{(2)} = \sigma(z^{(2)})$ ```Java 第一步: 计算加权和 z² = W²a¹ + b² [0.5 0.2] × [0.29] + [0.1] = [0.5(0.29) + 0.2(0.57) + 0.1] [0.57] 详细计算: z² = 0.5(0.29) + 0.2(0.57) + 0.1 = 0.145 + 0.114 + 0.1 = 0.359 第二步: 应用Sigmoid激活函数 a² = σ(z²) 输出 = σ(0.359) = 1/(1 + e⁻⁰·³⁵⁹) ≈ 0.589 ``` # 3. [[损失函数]] 对于使用均方误差(MSE)作为损失函数 $C_0 = (a^{(L)} - y)^2$ - $a^{(L)}$ 是神经网络的输出值(预测值),在我们前面的例子中是 0.589 - $y$ 是我们希望网络输出的正确答案,也就是训练数据中的目标值(比如如果这是一个二分类问题,y 可能是 0 或 1) # 4. 链式法则 & 反向传播 ![image.png|1000](https://imagehosting4picgo.oss-cn-beijing.aliyuncs.com/imagehosting/fix-dir%2Fpicgo%2Fpicgo-clipboard-images%2F2025%2F01%2F26%2F16-50-06-45c7ca7e2b4d7d5b0fa4b7bd39c27beb-202501261650495-d0f96e.png) $\frac{\partial C_0}{\partial w^{(L)}} = \frac{\partial z^{(L)}}{\partial w^{(L)}} \frac{\partial a^{(L)}}{\partial z^{(L)}} \frac{\partial C_0}{\partial a^{(L)}}$ 其中: 1. $\frac{\partial C_0}{\partial a^{(L)}} = 2(a^{(L)} - y)$ 2. $\frac{\partial a^{(L)}}{\partial z^{(L)}} = \sigma'(z^{(L)})$ 3. $\frac{\partial z^{(L)}}{\partial w^{(L)}} = a^{(L-1)}$ ## 输出层参数梯度计算 对于权重 $W^{(2)}=[0.5,0.2]$ 的梯度: 1. $\frac{\partial C_0}{\partial a^{(2)}} = 2(a^{(2)} - y) = 2(0.589 - 1) = -0.822$ 2. $\frac{\partial a^{(2)}}{\partial z^{(2)}} = \sigma'(z^{(2)}) = a^{(2)}(1-a^{(2)}) = 0.589(1-0.589) = 0.242$ 3. $\frac{\partial z^{(2)}}{\partial W^{(2)}} = a^{(1)} =[0.289, 0.574]$,因为$z^{(2)} = W^{(2)}a^{(1)} + b^{(2)}$ $W^{(2)} =[0.5, 0.2]$ 所以对于 $W_1^{(2)}$: 也就是 0.5 $\frac{\partial C_0}{\partial W_1^{(2)}} = (-0.822) \times 0.242 \times 0.289 \approx -0.0287$ 对于 $W_2^{(2)}$: 也就是 0.2 $\frac{\partial C_0}{\partial W_2^{(2)}} = (-0.822) \times 0.242 \times 0.574 \approx -0.0572$ 这样的表示更清晰地展示了每个导数项的来源和计算过程。每个导数项都有其明确的物理含义: - $\frac{\partial C_0}{\partial a^{(L)}}$ 表示损失相对于输出的敏感度 - $\frac{\partial a^{(L)}}{\partial z^{(L)}}$ 表示激活函数的导数 - $\frac{\partial z^{(L)}}{\partial w^{(L)}}$ 表示上一层的激活值 这种链式表示方法使得我们能更好地理解梯度是如何从输出层一步步反向传播的。 来推导对偏置 $b^{(2)}$ 的偏导数。 我们仍然使用链式法则: $\frac{\partial C_0}{\partial b^{(2)}} = \frac{\partial z^{(2)}}{\partial b^{(2)}} \frac{\partial a^{(2)}}{\partial z^{(2)}} \frac{\partial C_0}{\partial a^{(2)}}$ 其中: 1. $\frac{\partial C_0}{\partial a^{(2)}} = 2(a^{(2)} - y) = -0.822$ (与之前相同) 2. $\frac{\partial a^{(2)}}{\partial z^{(2)}} = \sigma'(z^{(2)}) = 0.242$ (与之前相同) 3. $\frac{\partial z^{(2)}}{\partial b^{(2)}} = 1$ (因为 $z^{(2)} = W^{(2)}a^{(1)} + b^{(2)}$,对 $b^{(2)}$ 求导就是 1) 所以: $\frac{\partial C_0}{\partial b^{(2)}} = (-0.822) \times 0.242 \times 1 \approx -0.199$ # 5. 参数更新 假设学习率 η = 0.1,参数更新公式为: ```Java W = W - η * ∂C/∂W b = b - η * ∂C/∂b ``` 对于输出层的参数更新: ```Java W₁² = 0.5 - 0.1 * (-0.0287) = 0.50287 W₂² = 0.2 - 0.1 * (-0.0572) = 0.20572 b² = 0.1 - 0.1 * (-0.199) = 0.1199 ``` 是的,参数更新后需要进行前向传播计算新的输出值,然后计算新的损失值,这就是一次完整的训练迭代。让我们用更新后的参数计算一次: # 6. 使用更新后的参数进行前向传播 隐藏层计算(这部分参数未更新,结果不变) ```Java z₁ = -0.9, a₁ = 0.289 z₂ = 0.3, a₂ = 0.574 ``` 输出层计算(使用更新后的参数) ```Java z² = W₁²a₁ + W₂²a₂ + b² = 0.50287(0.289) + 0.20572(0.574) + 0.1199 = 0.145329 + 0.118083 + 0.1199 = 0.383312 a² = σ(0.383312) ≈ 0.595 ``` 计算新的损失值 ```Java 对于目标值 y = 1: C_new = (a² - y)² = (0.595 - 1)² = 0.164025 ``` 对比原来的损失值: ```Java C_old = (0.589 - 1)² = 0.168921 ``` 可以看到损失值从 0.168921 降到了 0.164025,说明这次参数更新是有效的。这就是一次完整的训练迭代。 训练过程会不断重复这个循环: 1. 前向传播 2. 计算损失 3. 反向传播计算梯度 4. 更新参数 5. 重复以上步骤 直到满足停止条件,比如: - 达到预设的迭代次数 - 损失值小于某个阈值 - 损失值的变化小于某个阈值(收敛) 每次迭代损失值都会略有下降,这样经过多次迭代后,网络的输出会越来越接近目标值。 ```mermaid flowchart TD A[开始训练] --> B[前向传播] B --> C[计算损失] C --> D[反向传播计算梯度] D --> E[更新参数] E --> F{检查停止条件} F -->|否| G{判断停止条件} G -->|达到最大迭代次数| H[结束训练] G -->|损失值小于阈值| H G -->|损失值变化小于阈值| H G -->|继续训练| B F -->|是| H style A fill:#d0f4de style H fill:#f4d0d0 style F fill:#f4e5d0 style G fill:#f4e5d0 ``` # 神经网络反向传播完整教程 ## 网络结构 ![image.png|1000](https://imagehosting4picgo.oss-cn-beijing.aliyuncs.com/imagehosting/fix-dir%2Fpicgo%2Fpicgo-clipboard-images%2F2025%2F01%2F26%2F17-11-08-23b92ea8f94d137be070996366dea9a6-202501261711777-7e48d7.png) ### 网络参数初始化 **输入层到隐藏层:** - 权重矩阵:$W^{(1)} = \begin{bmatrix} 0.2 & -0.5 & 0.1 \ -0.3 & 0.4 & 0.2 \end{bmatrix}$ - 偏置向量:$b^{(1)} = \begin{bmatrix} 0.3 \ -0.1 \end{bmatrix}$ **隐藏层到输出层:** - 权重矩阵:$W^{(2)} = \begin{bmatrix} 0.5 & 0.2 \end{bmatrix}$ - 偏置:$b^{(2)} = 0.1$ **输入数据:** - $x = \begin{bmatrix} 2 \ 3 \ -1 \end{bmatrix}$ - 目标值:$y = 1$ ## 一、前向传播 ### 1. 输入层到隐藏层的计算 **公式:** $z^{(1)} = W^{(1)}x + b^{(1)}$ $a^{(1)} = \sigma(z^{(1)})$ **矩阵计算:** $z^{(1)} = \begin{bmatrix} 0.2 & -0.5 & 0.1 \ -0.3 & 0.4 & 0.2 \end{bmatrix} \begin{bmatrix} 2 \ 3 \ -1 \end{bmatrix} + \begin{bmatrix} 0.3 \ -0.1 \end{bmatrix}$ **详细展开:** $\begin{align} z_1^{(1)} &= 0.2 \times 2 + (-0.5) \times 3 + 0.1 \times (-1) + 0.3 \ &= 0.4 - 1.5 - 0.1 + 0.3 = -0.9 \end{align}$ $\begin{align} z_2^{(1)} &= (-0.3) \times 2 + 0.4 \times 3 + 0.2 \times (-1) + (-0.1) \ &= -0.6 + 1.2 - 0.2 - 0.1 = 0.3 \end{align}$ **结果:** $z^{(1)} = \begin{bmatrix} -0.9 \ 0.3 \end{bmatrix}$ **激活函数:** $a^{(1)} = \sigma(z^{(1)}) = \begin{bmatrix} \sigma(-0.9) \ \sigma(0.3) \end{bmatrix} = \begin{bmatrix} \frac{1}{1 + e^{0.9}} \ \frac{1}{1 + e^{-0.3}} \end{bmatrix} = \begin{bmatrix} 0.289 \ 0.574 \end{bmatrix}$ ### 2. 隐藏层到输出层的计算 **公式:** $z^{(2)} = W^{(2)}a^{(1)} + b^{(2)}$ $a^{(2)} = \sigma(z^{(2)})$ **矩阵计算:** $z^{(2)} = \begin{bmatrix} 0.5 & 0.2 \end{bmatrix} \begin{bmatrix} 0.289 \ 0.574 \end{bmatrix} + 0.1$ **详细展开:** $\begin{align} z^{(2)} &= 0.5 \times 0.289 + 0.2 \times 0.574 + 0.1 \ &= 0.1445 + 0.1148 + 0.1 = 0.3593 \end{align}$ **激活函数:** $a^{(2)} = \sigma(0.3593) = \frac{1}{1 + e^{-0.3593}} = 0.589$ ## 二、[[损失函数]]计算 **均方误差(MSE):** $C_0 = (a^{(2)} - y)^2 = (0.589 - 1)^2 = (-0.411)^2 = 0.169$ ## 三、反向传播 ### 1. 计算输出层的误差信号 **定义误差信号:** $\delta^{(2)} = \frac{\partial C_0}{\partial z^{(2)}}$ **链式法则展开:** $\delta^{(2)} = \frac{\partial C_0}{\partial a^{(2)}} \cdot \frac{\partial a^{(2)}}{\partial z^{(2)}}$ **各项计算:** - $\frac{\partial C_0}{\partial a^{(2)}} = 2(a^{(2)} - y) = 2(0.589 - 1) = -0.822$ - $\frac{\partial a^{(2)}}{\partial z^{(2)}} = \sigma'(z^{(2)}) = a^{(2)}(1 - a^{(2)}) = 0.589 \times 0.411 = 0.242$ **结果:** $\delta^{(2)} = -0.822 \times 0.242 = -0.199$ ### 2. 计算输出层参数的梯度 **权重梯度公式:** $\frac{\partial C_0}{\partial W^{(2)}} = \delta^{(2)} \cdot (a^{(1)})^T$ **矩阵计算:** $\frac{\partial C_0}{\partial W^{(2)}} = -0.199 \times \begin{bmatrix} 0.289 & 0.574 \end{bmatrix} = \begin{bmatrix} -0.0575 & -0.1142 \end{bmatrix}$ **偏置梯度公式:** $\frac{\partial C_0}{\partial b^{(2)}} = \delta^{(2)} = -0.199$ ### 3. 计算隐藏层的误差信号 **公式:** $\delta^{(1)} = (W^{(2)})^T \delta^{(2)} \odot \sigma'(z^{(1)})$ **步骤分解:** **第一步:计算反向传播的误差** $(W^{(2)})^T \delta^{(2)} = \begin{bmatrix} 0.5 \ 0.2 \end{bmatrix} \times (-0.199) = \begin{bmatrix} -0.0995 \ -0.0398 \end{bmatrix}$ **第二步:计算激活函数导数** $\sigma'(z^{(1)}) = a^{(1)} \odot (1 - a^{(1)}) = \begin{bmatrix} 0.289 \ 0.574 \end{bmatrix} \odot \begin{bmatrix} 0.711 \ 0.426 \end{bmatrix} = \begin{bmatrix} 0.2055 \ 0.2445 \end{bmatrix}$ **第三步:Hadamard积** $\delta^{(1)} = \begin{bmatrix} -0.0995 \ -0.0398 \end{bmatrix} \odot \begin{bmatrix} 0.2055 \ 0.2445 \end{bmatrix} = \begin{bmatrix} -0.0204 \ -0.0097 \end{bmatrix}$ ### 4. 计算隐藏层参数的梯度 **权重梯度公式:** $\frac{\partial C_0}{\partial W^{(1)}} = \delta^{(1)} \cdot x^T$ **矩阵计算:** $\frac{\partial C_0}{\partial W^{(1)}} = \begin{bmatrix} -0.0204 \ -0.0097 \end{bmatrix} \times \begin{bmatrix} 2 & 3 & -1 \end{bmatrix} = \begin{bmatrix} -0.0408 & -0.0612 & 0.0204 \ -0.0194 & -0.0291 & 0.0097 \end{bmatrix}$ **偏置梯度公式:** $\frac{\partial C_0}{\partial b^{(1)}} = \delta^{(1)} = \begin{bmatrix} -0.0204 \ -0.0097 \end{bmatrix}$ ## 四、参数更新 **学习率:** $\eta = 0.1$ **更新公式:** $\theta_{new} = \theta_{old} - \eta \cdot \frac{\partial C_0}{\partial \theta}$ ### 输出层参数更新 **权重更新:** $W^{(2)}_{new} = \begin{bmatrix} 0.5 & 0.2 \end{bmatrix} - 0.1 \times \begin{bmatrix} -0.0575 & -0.1142 \end{bmatrix} = \begin{bmatrix} 0.5058 & 0.2114 \end{bmatrix}$ **偏置更新:** $b^{(2)}_{new} = 0.1 - 0.1 \times (-0.199) = 0.1199$ ### 隐藏层参数更新 **权重更新:** $W^{(1)}_{new} = \begin{bmatrix} 0.2 & -0.5 & 0.1 \ -0.3 & 0.4 & 0.2 \end{bmatrix} - 0.1 \times \begin{bmatrix} -0.0408 & -0.0612 & 0.0204 \ -0.0194 & -0.0291 & 0.0097 \end{bmatrix}$ $W^{(1)}_{new} = \begin{bmatrix} 0.2041 & -0.4939 & 0.0980 \ -0.2981 & 0.4029 & 0.1990 \end{bmatrix}$ **偏置更新:** $b^{(1)}_{new} = \begin{bmatrix} 0.3 \ -0.1 \end{bmatrix} - 0.1 \times \begin{bmatrix} -0.0204 \ -0.0097 \end{bmatrix} = \begin{bmatrix} 0.3020 \ -0.0990 \end{bmatrix}$ ## 五、验证:使用更新后的参数进行前向传播 ### 隐藏层计算(使用更新后的参数) $z^{(1)}_{new} = W^{(1)}_{new} \cdot x + b^{(1)}_{new}$ $a^{(1)}_{new} = \sigma(z^{(1)}_{new})$ ### 输出层计算(使用更新后的参数) $z^{(2)}_{new} = W^{(2)}_{new} \cdot a^{(1)}_{new} + b^{(2)}_{new}$ $a^{(2)}_{new} = \sigma(z^{(2)}_{new}) \approx 0.595$ ### 新的损失值 $C_{new} = (0.595 - 1)^2 = 0.164$ **改进效果:** - 原损失值:$C_{old} = 0.169$ - 新损失值:$C_{new} = 0.164$ - 损失减少:$\Delta C = 0.005$ ## 六、训练流程图 ```mermaid flowchart TD A[初始化参数] --> B[前向传播] B --> C[计算损失 C₀] C --> D[计算输出层误差 δ²] D --> E[计算输出层梯度] E --> F[反向传播误差到隐藏层] F --> G[计算隐藏层梯度] G --> H[更新所有参数] H --> I{检查停止条件} I -->|继续| B I -->|停止| J[训练完成] style A fill:#d0f4de style J fill:#f4d0d0 style I fill:#f4e5d0 ``` ## 总结 本教程完整展示了一个两层神经网络的前向传播和反向传播过程,包括: 1. **前向传播**:逐层计算激活值 2. **损失计算**:使用均方误差 3. **反向传播**:从输出层向输入层计算梯度 4. **参数更新**:使用梯度下降法 5. **验证效果**:损失值降低 每个步骤都提供了公式推导和具体的矩阵计算,帮助理解神经网络的训练原理。