【ML】反向传播 —BackPropagation

本文深入讲解反向传播算法原理,包括链式法则的应用、正向与反向传递过程及偏导数计算方法,帮助读者理解神经网络训练的核心机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



反向传播 —BackPropagation

Grandient Descent

  • 梯度下降通过使用Loss function 对model中的每个参数进行求偏微分 最后通过learnig rate 对model进行更新
  • image-20210721101448965

但是一般大型的神经网络都会有上百万个类似于w\b 这样的参数,如何计算这样的梯度是Backprogation要做的事情。

Backprogation就是一个特殊的梯度下降算法

链式求导

image-20210721101755104

BackProgation——Forward pass(正向传导)

  • 定义一个函数**Cn**表示yn和y’^n的距离
  • 所以当前network的paramter的loss就是image-20210721102059009

image-20210721102146804 对某一参数进行偏微分时

我们使用一种方法,不需要对所有的paramer进行偏微分,而是对某一笔data进行偏微分就能得到得到grandet

我们以一个genurel举例:

image-20210721102503523

如何计算偏导? 首先使用链式法则:image-20210721102620759

  • image-20210721102659749

  • image-20210721102711336

所以我们得到一个规则: 一个神经元对一个paramer的求导就是相应路径上的输入

image-20210721103107823

所以我们可以得到每一个paramer,前的nuerel对相依参数的偏微分:就是前一层传入的input

BackProgation——Backward pass(反向传导)

  • 首先我们求解image-20210721103551930

    image-20210721103618911

根据图片我们可以看到如下思路:image-20210721103646574

  • image-20210721103711210sigmoid 函数和它的微分函数图像

C对A的偏微分可以分解:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-foF9m1zW-1637154131172)(…/…/…/AppData/Roaming/Typora/typora-user-images/image-20210721103841464.png)]

前一项好理解,但是如何理解第二项的偏微分呢?

image-20210721103928003

根据图片我们可以看到z对C的影响通过影响z’和z’'来实现的,所以有链式法则:

image-20210721103917776

根据之前得到的规则有:

image-20210721104205824

可以得到w3,w4分别是其中两项的值;

现在我们的目标是求出C对z’的偏微分和C对z’'的偏微分:

我们使用逆向思维:

image-20210721104439920
  • z是一个常数,一个固定的值,在我们做正向传导的时候我们已经知道它是多少了,所以他是一个常数,所以image-20210721104648398也是一个常数。

    所以,目前我们的目标就是计算image-20210721104810332image-20210721104826944

  • 此时,计算这两项的思路仍然和之前一样:

    image-20210721104942386
image-20210721105104617

但是如果存在第二层的话:又要进行之前的操作,所以这是一种思想:递归,我们可以通过计算机计算出最终的结果

就是反向计算偏微分利用规律来计算偏微分;

image-20210721105416204

这就是Backpropagation。

### 反向传播算法的工作原理及公式推导 反向传播算法(Backpropagation Algorithm,简称 BP)是一种用于训练人工神经网络的学习算法。它基于梯度下降法的核心思想,通过误差信号的逆向传递逐步调整网络中的权重参数,使得预测输出逐渐逼近真实标签。 --- #### **1. 神经网络的基本结构** 一个典型的前馈神经网络由多个层次组成,包括输入层、隐藏层和输出层。每一层包含若干个神经元,这些神经元之间通过连接权重相互关联。假设第 $l$ 层有 $n_l$ 个神经元,第 $l+1$ 层有 $n_{l+1}$ 个神经元,则它们之间的关系可以用以下公式表示: $$ z^{[l]} = W^{[l]}a^{[l-1]} + b^{[l]} $$ $$ a^{[l]} = g(z^{[l]}) $$ 其中: - $W^{[l]}$: 第 $l$ 层的权重矩阵; - $b^{[l]}$: 第 $l$ 层的偏置项; - $g(\cdot)$: 激活函数(如 Sigmoid 或 ReLU)[^1]。 --- #### **2. 前向传播与损失函数** 在前向传播阶段,数据从输入层逐层传递至输出层,最终生成预测值 $\hat{y}$. 设真实的标签为 $y$, 则可以通过定义损失函数衡量两者之间的差异。常用的损失函数形式如下: - 对于回归问题:均方误差 (MSE) $$ L(y, \hat{y}) = \frac{1}{2}(y - \hat{y})^2 $$ - 对于分类问题:交叉熵损失 $$ L(y, \hat{y}) = -\sum_i y_i \log(\hat{y}_i) $$ 整个网络的目标是最小化总损失函数 $J(W,b)=\frac{1}{m}\sum_{i=1}^mL(y^{(i)},\hat{y}^{(i)})$, 其中 $m$ 表示样本数量[^2]. --- #### **3. 反向传播的核心思想** 反向传播的主要目的是计算损失函数关于各层权重和偏置的梯度 ($\partial J / \partial W^{[l]}, \partial J / \partial b^{[l]}$), 并依据梯度下降规则更新参数: $$ W^{[l]} := W^{[l]} - \alpha \frac{\partial J}{\partial W^{[l]}} $$ $$ b^{[l]} := b^{[l]} - \alpha \frac{\partial J}{\partial b^{[l]}} $$ 这里的关键在于如何高效地求解梯度。BP 算法借助链式法则实现了这一点。 --- #### **4. 反向传播的具体步骤** ##### (1)定义误差信号 设第 $l$ 层的误差信号为 $\delta^{[l]}$, 它描述了当前层对整体损失的影响程度。对于输出层而言,可以直接根据损失函数的形式写出表达式: $$ \delta^{[L]} = (\hat{y}-y) \odot g'(z^{[L]}) $$ 而对于隐藏层,则需递归地从前一层回传的信息计算得出: $$ \delta^{[l]} = ((W^{[l+1]})^\top \delta^{[l+1]}) \odot g'(z^{[l]}) $$ 这里的符号含义分别为: - $(W^{[l+1]})^\top$: 权重矩阵转置; - $\odot$: Hadamard 积(逐元素相乘)[^3]。 ##### (2)计算梯度 有了误差信号后,即可进一步求得所需梯度: $$ \frac{\partial J}{\partial W^{[l]}} = \delta^{[l]} (a^{[l-1]})^\top $$ $$ \frac{\partial J}{\partial b^{[l]}} = \delta^{[l]} $$ 以上公式的直观意义是:$\delta^{[l]}$ 提供了局部敏感性的信息,而激活值 $a^{[l-1]}$ 则代表全局特征分布。 --- #### **5. 总结与特点分析** 反向传播算法的优势体现在以下几个方面: - **效率高**: 利用链式法则避免重复计算中间结果; - **通用性强**: 能够适应各种类型的神经网络架构; - **理论支持充分**: 数学推导严谨,适用于复杂的非线性映射场景。 然而也存在一些局限之处,比如容易陷入局部最优解以及对超参调节较为敏感等问题。 --- ### 示例代码演示 以下是使用 Python 和 NumPy 手动实现简单 BP 过程的一个片段: ```python import numpy as np def sigmoid(x): return 1 / (1 + np.exp(-x)) def forward(X, weights, biases): Zs, As = [], [] A_curr = X for w, b in zip(weights, biases): Z = np.dot(A_curr, w.T) + b A_next = sigmoid(Z) Zs.append(Z); As.append(A_curr) A_curr = A_next return Zs, As, A_curr def backward(Y_hat, Y, Zs, As, weights, lr=0.1): dWs, dbs = [], [] m = Y.shape[0] delta_L = (Y_hat - Y) * Y_hat * (1 - Y_hat) for l in range(len(weights)-1, -1, -1): dw = np.dot(delta_L.T, As[l]) / m db = np.sum(delta_L, axis=0, keepdims=True) / m dWs.insert(0, dw); dbs.insert(0, db) if l != 0: delta_prev = np.dot(delta_L, weights[l]) delta_L = delta_prev * As[l] * (1 - As[l]) # Update parameters for i in range(len(weights)): weights[i] -= lr * dWs[i] biases[i] -= lr * dbs[i] return weights, biases ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值