多层感知机Perceptron反向传播BP算法推导(Back Propagation)

本文深入解析BP算法,从多层感知器的线性输出到激活函数应用,详细推导BP算法中权重和偏置的更新过程。阐述了损失函数的选择及其对学习速率的影响,对比了MSE与交叉熵在不同场景下的表现。

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

看了很多BP的推导,都不够简洁直观,这里总结一下。多层Perceptron就是全连接的网络,定义第l层的输入为x(l)x^{(l)}x(l),那么全连接的线性输出z(l)=W(l)x(l)+b(l)z^{(l)}=W^{(l)}x^{(l)}+b^{(l)}z(l)=W(l)x(l)+b(l)

上面的(l)都表示第l层,如果到了第l+1层,当然要过一个激活函数f,那么
z(l+1)=W(l+1)x(l+1)+b(l+1)z^{(l+1)}=W^{(l+1)}x^{(l+1)}+b^{(l+1)}z(l+1)=W(l+1)x(l+1)+b(l+1)

如果把上面这个公式展开,考虑到x(l+1)x^{(l+1)}x(l+1)z(l)z^{(l)}z(l)的关系,那就变成了
zj(l+1)=∑iWji(l+1)f(zi(l))+bj(l+1) z_j^{(l+1)}=\sum_iW_{ji}^{(l+1)}f(z_i^{(l)})+b_j^{(l+1)} zj(l+1)=iWji(l+1)f(zi(l))+bj(l+1)

假设第l+1层就输出了,那么整理代价函数就是
J(W,b)=L[f(z(l+1)),y]+Ω(W)J(W,b)=L[f(z^{(l+1)}),y] + \Omega(W)J(W,b)=L[f(z(l+1)),y]+Ω(W)

Back Propagation就是想求每一层每个节点(第i层)的两个偏导∂J(W,b)∂W(i)\frac{\partial J(W,b)}{\partial W^{(i)}}W(i)J(W,b)∂J(W,b)∂b(i)\frac{\partial J(W,b)}{\partial b^{(i)}}b(i)J(W,b),好证明参数可以传递,不至于传着传着没货了,下面求导开始前,把刚才不严谨的公式画的更清楚一些,还是假设第l+1层后过了激活函数f就去算Loss了,同时定义第l层有SlS_lSl个节点,第l+1层有Sl+1S_{l+1}Sl+1个节点,对于第l层的第i个节点和loss J(W,b)J(W,b)J(W,b)可以得到如下图里的关系:
在这里插入图片描述
接下来开始求针对第l层参数的偏导,其中zi(l+1)z_i^{(l+1)}zi(l+1)表示第l+1层的第i个节点的线性输出,Wij(l+1)W_{ij}^{(l+1)}Wij(l+1)表示第l+1层第i个节点从前一层第j个节点过sigmoid后乘以的参数:
∂J(W,b)∂Wij(l+1)=∂J(W,b)∂zi(l+1)∂zi(l+1)∂Wij(l+1)=∂J(W,b)∂zi(l+1)xi(l+1)\frac{\partial J(W,b)}{\partial W_{ij}^{(l+1)}}=\frac{\partial J(W,b)}{\partial z_i^{(l+1)}}\frac{\partial z_i^{(l+1)}}{\partial W_{ij}^{(l+1)}} \\ = \frac{\partial J(W,b)}{\partial z_i^{(l+1)}} x_i^{(l+1)} Wij(l+1)J(W,b)=zi(l+1)J(W,b)Wij(l+1)zi(l+1)=zi(l+1)J(W,b)xi(l+1)

∂J(W,b)∂zi(l+1)\frac{\partial J(W,b)}{\partial z_i^{(l+1)}}zi(l+1)J(W,b)和J的具体表达式有关系,所以定义
δil+1=∂J(W,b)∂zi(l+1)\delta_i^{l+1}=\frac{\partial J(W,b)}{\partial z_i^{(l+1)}}δil+1=zi(l+1)J(W,b)

那么
∂J(W,b)∂Wij(l+1)=∂J(W,b)∂zi(l+1)∂zi(l+1)∂Wij(l+1)=δil+1xi(l+1)\frac{\partial J(W,b)}{\partial W_{ij}^{(l+1)}}=\frac{\partial J(W,b)}{\partial z_i^{(l+1)}}\frac{\partial z_i^{(l+1)}}{\partial W_{ij}^{(l+1)}} \\ = \delta_i^{l+1} x_i^{(l+1)} Wij(l+1)J(W,b)=zi(l+1)J(W,b)Wij(l+1)zi(l+1)=δil+1xi(l+1)

∂J(W,b)∂bi(l+1)=∂J(W,b)∂zi(l+1)∂zi(l+1)∂b(l+1)=δil+1\frac{\partial J(W,b)}{\partial b_i^{(l+1)}}=\frac{\partial J(W,b)}{\partial z_i^{(l+1)}}\frac{\partial z_i^{(l+1)}}{\partial b^{(l+1)}} \\ = \delta_i^{l+1} bi(l+1)J(W,b)=zi(l+1)J(W,b)b(l+1)zi(l+1)=δil+1
有了这俩,还想知道再向前一层是啥,比如针对W的:
∂J(W,b)∂Wij(l)=∂J(W,b)∂zi(l)∂zi(l)∂Wij(l)=δilxi(l)\frac{\partial J(W,b)}{\partial W_{ij}^{(l)}}=\frac{\partial J(W,b)}{\partial z_i^{(l)}}\frac{\partial z_i^{(l)}}{\partial W_{ij}^{(l)}} \\ = \delta_i^{l} x_i^{(l)} Wij(l)J(W,b)=zi(l)J(W,b)Wij(l)zi(l)=δilxi(l)
剩下的焦点问题就是δi(l)\delta_i^{(l)}δi(l)怎么求了,刚才那个图就用上了,这东西可以看成损失函数在第l层第i个节点产生的残差量,刚才那个图一目了然:
δi(l)=∂J(W,b)∂zi(l)=∑j=1Sl+1[∂J(W,b)∂zj(l+1)∂zj(l+1)∂zi(l)]=∑j=1Sl+1[δj(l+1)Wji(l+1)f′(zi(l))]\delta_i^{(l)}=\frac{\partial J(W,b)}{\partial z_i^{(l)}} \\ =\sum_{j=1}^{S_{l+1}}[\frac{\partial J(W,b)}{\partial z_j^{(l+1)}}\frac{\partial z_j^{(l+1)}}{\partial z_i^{(l)}}] \\ =\sum_{j=1}^{S_{l+1}}[\delta_j^{(l+1)}W_{ji}^{(l+1)}f'(z_i^{(l)})] δi(l)=zi(l)J(W,b)=j=1Sl+1[zj(l+1)J(W,b)zi(l)zj(l+1)]=j=1Sl+1[δj(l+1)Wji(l+1)f(zi(l))]

δi(l)\delta_i^{(l)}δi(l)就是整个BP的精髓,说明了参数可以传递,其实就是递推表达式。后面补充几个很重要的问题:

  1. 可以看到δi(l)\delta_i^{(l)}δi(l)再展开一层会带来一堆连乘,导致误差膨胀或者消失,ResNet的改进思路就是如此,把上一层的残差短接到下一层,收获了很好的效果

  2. 激活函数可以选sigmoid或者relu,最后L可以选平方误差损失或者交叉熵。一般来说平方损失函数输出为连续,交叉熵损失函数更适合二分类问题。但是注意平方损失函数最后一层不能含有Sigmoid或者softmax激活函数!!!原因就是假设用sigmoid,下面表达式中含有sigmoid的导数,这个值非常小,导致学习非常慢
    δil+1=∂J(W,b)∂zj(l+1)\delta_i^{l+1}=\frac{\partial J(W,b)}{\partial z_j^{(l+1)}} δil+1=zj(l+1)J(W,b)
    写更加具体一些,如果二分类的话用MSE的话:
    J(W,b)=(σ(zj(l+1))−y)22∂J(W,b)∂zj(l+1)=(σ(zj(l+1))−y)σ(zj(l+1))(1−σ(zj(l+1)))J(W,b)=\frac{(\sigma(z_j^{(l+1)})-y)^2}{2}\\ \frac{\partial J(W,b)}{\partial z_j^{(l+1)}}=(\sigma(z_j^{(l+1)})-y)\sigma(z_j^{(l+1)})(1-\sigma(z_j^{(l+1)})) J(W,b)=2(σ(zj(l+1))y)2zj(l+1)J(W,b)=(σ(zj(l+1))y)σ(zj(l+1))(1σ(zj(l+1)))
    但是如果是交叉熵的话,假设分为k类,k类中只有某一类为1,其他为0:
    J(W,b)=−∑k=1myklnσ(zj(l+1))∂J(W,b)∂zj(l+1)=yk(σ(zj(l+1)−1)J(W,b)=-\sum_{k=1}^my_kln\sigma(z_j^{(l+1)})\\ \frac{\partial J(W,b)}{\partial z_j^{(l+1)}}=y_k(\sigma(z_j^{(l+1)}-1)J(W,b)=k=1myklnσ(zj(l+1)zj(l+1)J(W,b)=yk(σ(zj(l+1)1)
    显然交叉熵下降会更快一些

  3. 最后写一下完整的J(W,b),用二元交叉熵损失函数来写吧:
    J(W,b)=L[f(z(l+1)),y]+Ω(W)=−1m∑i=1m[yilnoi+(1−yi)ln(1−oi))]+λ2∑l=1N−1∑i=1Sl∑j=1Sl+1(Wij(l))2J(W,b)=L[f(z^{(l+1)}),y] + \Omega(W) \\ = {{-\frac{1}{m}\sum_{i=1}^m[y_ilno_i+(1-y_i)ln(1-o_i))] }}+ \\ \frac{\lambda}{2}\sum_{l=1}^{N-1}\sum_{i=1}^{S_l}\sum_{j=1}^{S_{l+1}}(W_{ij}^{(l)})^2 J(W,b)=L[f(z(l+1)),y]+Ω(W)=m1i=1m[yilnoi+(1yi)ln(1oi))]+2λl=1N1i=1Slj=1Sl+1(Wij(l))2

英文博客可以参考: http://neuralnetworksanddeeplearning.com/chap2.html

### 多层感知机(MLP)工作原理 多层感知机(Multilayer Perceptron, MLP)是一种基于全连接层结构的人工神经网络,广泛应用于分类和回归任务中。该模型至少包含三个层次:输入层、隐藏层以及输出层[^3]。 #### 输入层到隐藏层的转换 在网络内部,各层之间的信息传递遵循特定模式。对于任意给定的一层而言,每一个节点都会接收到上一层所有节点传来的信号,并对其进行加权求和操作;之后再加上一个偏置参数b,形成净输入z=w*x+b的形式。这里w代表权重矩阵而x则是特征向量。随后这个值会被送入激活函数f()当中得到当前层的实际输出a=f(z)[^4]。 ```python import numpy as np def activation_function(x): """Sigmoid Activation Function""" return 1 / (1 + np.exp(-x)) # Example of computing activations for a single layer weights = np.array([0.5, -0.2]) # example weights bias = 0.1 # bias term input_vector = np.array([1.0, 0.8]) net_input = np.dot(weights, input_vector) + bias output = activation_function(net_input) print(f"Output after applying sigmoid function: {output}") ``` ### 反向传播算法详解 为了优化MLP性能,在训练过程中会利用梯度下降法调整各个连接上的权重值。具体来说就是先执行一次完整的前向遍历获得预测结果y_hat,再依据损失函数L(y,y_hat)评估误差大小并据此计算出关于每个参数θ_j的部分导数∂L/∂θ_j——即所谓的“敏感度”。接着按照链式法则沿着路径逐级回溯更新前面各层对应的参数直至收敛为止[^1]。 #### 更新规则 设η为学习率,则第k次迭代后的某权重W_ij的新估计可表示如下: \[ W_{ij}^{new}=W_{ij}-\eta \frac{\partial L}{\partial z_i}\cdot x_j \] 其中\( \frac{\partial L}{\partial z_i} \) 表示最后一层相对于其总输入的变化速率,可以通过下面的方式逐步向前推算至更早阶段: \[ \delta_k=\nabla_a C * f'(z_k)\quad,\text{for output neurons}\\ \delta_l=(\sum_m w_{ml}\delta_m)*f'(z_l),\forall l\notin OutputLayer \] 此处 \( \nabla_aC \) 是成本函数对激活值得一阶导数值,\( f'(\cdot )\) 则指代所选激活函数之微分形式。 ### 神经网络训练过程概述 整个训练流程大致分为以下几个部分: - 初始化随机初始权重; - 对于每一次epoch循环: - 执行批量或在线方式下的样本抽取; - 进行正向传播以获取预测标签; - 计算实际与预期间的差异作为反馈信号; - 应用BP机制完成一轮自我修正; - 当满足停止条件时结束本轮迭代。 通过不断重复上述步骤直到达到预设的最大轮次数或者连续若干次改进幅度低于阈值即可认为找到了较为满意的解空间位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值