当前位置: 首页 > article >正文

【通俗易懂说模型】反向传播(附多元分类与Softmax函数)

🌈 个人主页:十二月的猫-CSDN博客
🔥 系列专栏: 🏀深度学习_十二月的猫的博客-CSDN博客

💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 

目录

1. 前言

2. 多元分类

2.1 softmax函数

2.2 Softmax函数对比Sigmoid函数

3. 反向传播

3.1 反向传播与神经网络

3.2 总体观

3.3 逐级观(数学推理,仅仅想会使用不需要理解)

3.4 反向传播思想总结

4. 梯度反向传播的完整例子

Step1:前向传播

Step2:反向传播

Step3:梯度下降

5. 总结


1. 前言

        进入这篇文章之前,想必大家已经阅读过前面的系列文章:【通俗易懂说模型】线性回归(附深度学习、机器学习发展史)-CSDN博客

【通俗易懂说模型】非线性回归和逻辑回归(附神经网络图详细解释)-CSDN博客

        通过前面的文章, 猫猫希望友友们对机器学习、深度学习等基础概念,以及发展历史有一个宏观的理解。同时对回归(线性、非线性、逻辑回归)有一个深入的认识。然后接下来,就让我们收拾收拾行囊,准备出发!下一站——多元分类、反向传播🥰🥰~

        网络上有很多关于反向传播的文章,但是猫猫看了都不是很满意。之前一遍又一遍看结果就是仍然不能理解。直到最近重新拿起反向传播思考才有更深入的认识,于是打算写这样一篇文章,希望能为大家入门深度学习理解反向传播提供一个全新的思路~~

2. 多元分类

        逻辑回归是二元分类,属于多元分类的一种特殊情况。在生活中,多元分类问题十分常见。无论是看完一部电影,给电影评星,还是将一本书归到某一类的书架上,都属于多元分类的问题。这一节,我们就详细介绍如何用神经网络进行多元分类。

2.1 softmax函数

        多元分类问题与二元分类问题类似,区别在于用softmax函数替代sigmoid函数。多元分类的神经网络要求输出层的神经元数目与所需分类的类别数保持一致。图3-26展示了多元分类的模型结构。假设分类的类别数为k,那么softmax函数需要输人k个值(n1,n2,...,nk),然后输出k个概率(π1,π2,...,πk)。softmax函数实际上是sigmoid函数的推广。softmax函数将所有分类的分数值(n1,n2,...,nk)转化为概率(π1,π2,...,πk),且各概率的和为1。

softmax函数的数学公式如下:

\pi_l=\frac{\mathrm{e}^{n_l}}{\sum_{j=1}^k\mathrm{e}^{\eta_l}}

softmax函数可以巧妙地将多个分类的分数转化为(0,1)的值并且和为1

\sum_{i=1}^{k}\pi_{i}=1

2.2 Softmax函数对比Sigmoid函数

Sigmoid函数:

        线性神经元的输出为\overrightarrow{x}*\overrightarrow{w},随后经过一个非线性的sigmoid函数(公式中常把它简写作sign),此函数的图像如下图所示。sigmoid函数的定义域为(-\infty,+\infty),值域为(0,1),表达式为:

\operatorname{sigm}(x)=\frac{1}{1+\mathrm{e}^{-x}}

Softmax函数:

        Softmax函数是用于多类分类问题的激活函数,在多类分类问题中,超过两个类标签则需要类成员关系。对于长度为K的任意实向量,Softmax函数可以将其压缩为长度为K,值在[0,1]范围内,并且向量中元素的总和为1的实向量。

\pi_l=\frac{\mathrm{e}^{n_l}}{\sum_{j=1}^k\mathrm{e}^{\eta_l}}

区别

  • Softmax所有分类概率总和为1。
  • Sigmoid值是为1这个类的概率a。无论输出结果多大,通过Sigmoid都限制在[0,1]之间。
  • Sigmoid另一个类0的概率就是1-a。

3. 反向传播

        反向传播算法(BackpropagationAlgorithm),又被业界称为BP算法,是深度神经网络取得成功的奠基石。深度神经网络实际上是多隐含层神经网络,在早期就已经被提出,但是当时没有找到很好的训练方法,使得深度神经网络的强大实力得不到发挥。直到反向传播算法的出现,深度神经网络才得以崭露头角。如今,反向传播是深度神经网络最重要的训练方法。

3.1 反向传播与神经网络

  1. 神经网络算法很早就被提出来了,但是对于如何找到合适的参数去拟合数据一直是个问题,人工找显然不现实。
  2. 后面梯度下降算法被提出来,我们也就知道了给出一个模型评价标志——loss。也就可以根据loss将目标改为降低loss从而训练模型参数。这时的问题就在于梯度下降算法需要知道函数的梯度。手工通过法则去计算每一个参数在loss中的梯度是不合适的。
  3. 反向传播的出现让求解参数的梯度变得非常简单。利用链式法则从函数的输出结果loss,逐级向前传播就可以一级一级求出每一个参数的梯度值
  4. 于是神经网络的训练模型才被完全建立起来,神经网络模型才有工作的可能性 

3.2 总体观

        现在,我们先讨论一个最简单的例子:隐含层的层数为1的神经网络的前向传播及反向传播的过程。如下图所示,我们的前向传播过程为:输入\overrightarrow{z}^1,经过隐含层得到\overrightarrow{z}^2,再经过输出层得到\overrightarrow{z}^3,经过损失函数得到损失值{z}^4

        接着进行反向传播,为了方便计算和推导,我们定义\overrightarrow{\delta }变量,暂时不去考虑\overrightarrow{\delta }代表什么。我们可以用一种抽象的方式去审视反向传播的过程,如下图所示。这个过程首先将\delta ^4=\frac{dL}{dL}=1作为输入,然后由\delta ^4反向传播至第3层各节点得到\overrightarrow{\delta ^3}\overrightarrow{\delta ^3}反向传播经过第2层各节点得到\overrightarrow{\delta ^2},利用\overrightarrow{z^3}\overrightarrow{\delta ^3}及第2层到第3层之间的权重矩阵W^{(2,3)}求得梯度值\frac{\partial L}{\partial W^{(2,3)} }。接着,\overrightarrow{\delta ^2}继续反向传播得到\overrightarrow{\delta ^1},我们利用\overrightarrow{z^2}\overrightarrow{\delta ^2}及第1层到第2层之间的权重矩阵W^{(1,2)}可以求得梯度值\frac{\partial L}{\partial W^{(1,2)} }

反向传播的理解:

  • 前向传播中一个数据点会生成三个下一层中的中间值。那么在反向传播中,每一个下一层中的中间值都会反向来调整数据点的参数。
  • 反向传播本质上是求解参数相对于最终输出Loss的影响大小(梯度)的
  • 上面有一个词用的非常模糊——反向传播。你可能会很疑惑,这个反向传播是怎么工作的,为什么就求出梯度大小了。下面的逐级观将给你答案
  • 总体观只要关注到\overrightarrow{\delta }即可,不用考虑\overrightarrow{\delta }具体值是什么,这个值又是如何求解的

3.3 逐级观(数学推理,仅仅想会使用不需要理解)

        上面猫猫展示了反向传播的总体过程,如果你还没有完全理解也没关系,下面我们要探讨每
层的细节。如下图所示,我们将神经网络的第1层作为代表进行观察,第1层的输人是,设第I层到第I+1层之间的权重矩阵为W^{(l,l+1)},于是可以将数据经过该层的变换看作函数f^l的运算。

前向传播的数学表达式如下:

\vec{z}^{l+1}=f^{l}(\vec{z}^{l},W^{(l,l+1)})

为了方便描述反向传播的过程,我们定义{\delta ^l_j},数学表达如下:

\delta_{j}^{l}=\frac{\partial L}{\partial z_{j}^{l}}

根据微积分的链式法则,可以得到:

\delta_{j}^{l}=\frac{\partial L}{\partial z_{j}^{l}}=\sum_{k}\frac{\partial L}{\partial z_{k}^{l+1}}\cdot\frac{\partial z_{k}^{l+1}}{\partial z_{j}^{l}}=\sum_{k}\delta_{k}^{l+1}\frac{\partial z_{k}^{l+1}}{\partial z_{j}^{l}}

        上面公式表明想要求解出l层神经元相对于最终输出L的影响度,则需要求解出\frac{\partial z_k^{l+1}}{\partial z_j^l}的值,同时利用后一层也就是l+1层神经元相对于最终输出L的影响度。而\frac{\partial z_k^{l+1}}{\partial z_j^l}的值就是第l层和第l+1层之间的权重值W,因此核心就在于求出每一层之间的权重。到这里我们就求出了每一个神经元对于输出Loss的梯度。接下去就要思考,这个梯度如何用来更新权重

        知道神经元对于Loss的梯度值后,我们就要根据梯度方向的相反方向去修正神经元的值。修正神经元的值本质就是修正神经元W权重的值。因此为了更新权重,需要计算出损失函数关于神经网络内每个权重的梯度,损失函数关于第l层到第I+1层之间权重矩阵W^{(l,l+1)}的梯度为:

\frac{\partial L}{\partial W^{(l,l+1)}}=\sum_{j}\frac{\partial L}{\partial z_{j}^{l+1}}\frac{\partial z_{j}^{l+1}}{\partial W^{(l,l+1)}}=\sum_{j}\delta_{j}^{l+1}\frac{\partial z_{j}^{l+1}}{\partial W^{(l,l+1)}}

        再来看下图,假设我们要修正W^{(2,3)},此时就需要知道W^{(2,3)}对于L的梯度。这个梯度的求解就要利用到z^3W^{(2,3)}\delta ^3,而这些我们都是已知的,因此这个梯度\frac{\partial L}{\partial W^{(2,3)}}就是已知的,那么就可以根据梯度下降法去梯度更新W^{(2,3)}的值了。​

3.4 反向传播思想总结

        网络上有许多关于反向传播的总结,基本都是带大家走一遍反向传播的流程。这样做自然有它的用处,但是猫猫发现很多时候我们都是走的时候能够看懂,但是让自己写一遍就不能理解了。究其原因就是仅仅知其然,并没有知其所以然。于是我想了这样一个角度去理解反向传播——总体观 和 局部观(逐级观)

        总体观想要告诉我们:

  1. 反向传播从输出值Loss向前面逐级传播
  2. 反向传播研究的是神经元相对于输出Loss的梯度(影响程度),也就是\delta
  3. 总体观要给我们灌输一个思想:神经元对于Loss的梯度本质上就是权重W对于Loss的梯度
  4. 前向传播一个第l层的神经元会参与计算第l+1层所有的神经元。因此反向传播时,所有第l+1层的神经元会反向作用于这个第l层的神经元,影响它的参数变化

        局部观想要告诉我们:

  1. 为什么神经元对于Loss的梯度本质上就是权重W对于Loss的梯度?
  2. 权重W对于Loss的梯度是多少?
  3. 所有第l+1层的神经元会反向作用于这个第l层的神经元,影响它的参数变化
  4. 链式法则的运用使得梯度可以逐层传播

4. 梯度反向传播的完整例子

        现在我们用一个例子来讲解BP,如下图所示,我们选取的例子是最简单的feed forward neural network,它有两层,输入层有两个神经元 x1,x2,隐藏层有两个神经元 h1,h2,最终输出只
有一个神经元y,各个神经元之间全连接。为了直观起见,我们给各个参数赋上具体的数值。我
们令下x1=1,x2=0.5,然后我们令W1,W2,W3,W4的真实值分别是1,2,3,4,令W5,W6的真实值是0.5,0.6。这样我们可以算出 y的真实目标值是t= 4。

        那么为了模拟一个Back Propagation的过程,我们假设我们只知道 x1=1,x2=0.5 ,以及对应的目标 t=4 。我们不知道 w1,w2,w3,w4,w5,w6 的真实值,现在我们需要随机为他们初始化值,假设我们的随机化结果是 w1=0.5,w2=1.5,w3=2.3,w4=3,w5=1,w6=1 。下面我们就开始来一步步进行Back Propagation吧。

Step1:前向传播

        首先,在计算反向传播之前我们需要计算Feed Forward Pass,也即是预测的 h1,h2,y 和误差项 E ,其中E=\frac{1}{2}(t-y)^2 。根据网络结构示意图,各个变量的计算公式为:

Step2:反向传播

        现在Feed Forward Pass算完了,我们来计算Backward Pass。 y 是神经网络预测的值,真实的输出是 t=4 。那么,要更新 w5 的值我们就要算\frac{ \partial E}{\partial w_5} ,根据链式法则有:

\frac{\partial E}{\partial w_5}=\frac{\partial E}{\partial y}\cdot\frac{\partial y}{\partial w_5}

因为 E=\frac{1}{2}(t-y)^2,所以:

\begin{aligned}\frac{\partial E}{\partial y}&=2\cdot\frac{1}{2}\cdot(t-y)\cdot(-1)\\&=y-t\\&=5.05-4=1.05\end{aligned}

y=w_5*h1+w_6*h2,所以 :

\frac{\partial y}{\partial w_5}=h_1+0=h_1=1.25

把上面两项相乘我们得到:

\begin{gathered}\frac{\partial E}{\partial w_5}=\frac{\partial E}{\partial y}\cdot\frac{\partial y}{\partial w_5}=(y-t)\cdot h_1\\=1.05\cdot1.25=1.3125\end{gathered}

Step3:梯度下降

        运用之前梯度下降法的公式更新 w5 ,得到新的 w5’ 。其中我们假设 η=0.1 (并且后面所有的 η 都等于 0.1 ):

\begin{aligned}w_5^{'}&=w_5-\eta\cdot\frac{\partial E}{\partial w_5}\\&&\mathrm{25}\\&=0.86875\end{aligned}

同理,我们可以按照相同的步骤计算 w6' 的更新公式:

\begin{aligned}w_6^{'}&=w_6-\eta\cdot\frac{\partial E}{\partial w_6}\\&=1-0.1\cdot3.99\\&=0.601\end{aligned}

        下面我们再来看 w1,w2,w3,w4 ,由于这四个参数在同一层,所以求梯度的方法是相同的,因此我们这里仅展示对 w1 的推导。根据链式法则:

 \frac{\partial E}{\partial w_1}=\frac{\partial E}{\partial y}\cdot\frac{\partial y}{\partial h_1}\cdot\frac{\partial h_1}{\partial w_1}

        其中\frac{\partial E}{\partial y}=y-t 在求\frac{\partial E}{\partial w_5}的时候已经求过了。而根据y=w_5\cdot h_1+w_6\cdot h_2我们可以得到:

\frac{\partial y}{\partial h_1}=w_5+0=w_5

又根据 h1=w1⋅x1+w2⋅x2 我们可以得到:

\frac{\partial h_1}{\partial w_1}=x_1+0=x_1

因此我们有下面的公式:

\frac{\partial E}{\partial w_1}=(y-t)\cdot w_5\cdot x_1

现在我们代入数字并使用梯度下降法更新 w1

\begin{aligned}w_1^{'}&=w_1-\eta\cdot\frac{\partial E}{\partial w_1}\\&=w_1-\eta\cdot(y-t)\cdot w_5\cdot x_1\\&=0.5-0.1\cdot1.05\cdot1\cdot1\\&=0.395\end{aligned}

然后重复这个步骤更新w2、w3、w4

\begin{aligned}&w_2^{'}=w_2-\eta\cdot\frac{\partial E}{\partial w_2}\\&=w_2-\eta\cdot(y-t)\cdot w_5\cdot x_2\\&=1.5-0.1\cdot1.05\cdot1\cdot0.5\\&=1.4475\\&w_3^{'}=w_3-\eta\cdot\frac{\partial E}{\partial w_3}\\&=w_3-\eta\cdot(y-t)\cdot w_6\cdot x_1\\&=2.3-0.1\cdot1.05\cdot1\cdot1\\&=2.195\\&w_4^{'}=w_4-\eta\cdot\frac{\partial E}{\partial w_4}\\&=w_2-\eta\cdot(y-t)\cdot w_5\cdot x_2\\&=3-0.1\cdot1.05\cdot1\cdot0.5\\&=2.9475\end{aligned}

        现在我们已经更新了所有的梯度,完成了一次梯度下降法。我们用得到的新的 w+ 再来预测一次网络输出值,根据Feed Forward Pass得到 y’=3.1768 ,那么新的误差是 E‘=0.3388 ,相比于之前的 E=0.55125 确实是下降了呢,说明我们的模型预测稍微准了一点。只要重复这个步骤,不断更新网络参数我们就能学习到更准确的模型啦。

5. 总结

如果想要学习更多深度学习知识,大家可以点个关注并订阅,持续学习、天天进步

你的点赞就是我更新的动力,如果觉得对你有帮助,辛苦友友点个赞,收个藏呀~~~


http://www.kler.cn/a/540814.html

相关文章:

  • IDEA查看项目依赖包及其版本
  • 第三个Qt开发实例:利用之前已经开发好的LED驱动在Qt生成的界面中控制LED2的亮和灭
  • Spring Boot中实现多租户架构
  • fps动作系统9:动画音频
  • DFS+回溯+剪枝(深度优先搜索)——搜索算法
  • Compose笔记(四)--derivedStateOf
  • 深度学习|表示学习|Mini-Batch Normalization 具体计算举例|23
  • Intellij IDEA调整栈内存空间大小详细教程,添加参数-Xss....
  • 【推荐】爽,在 IDE 中做 LeetCode 题目的插件
  • 基于 FFmpeg 和 OpenGLES 的 iOS 视频预览和录制技术方案设计
  • Spring容器初始化扩展点:ApplicationContextInitializer
  • MVVM设计模式
  • 大模型基础面试问题汇总
  • 1.2 环境搭建
  • 「vue3-element-admin」告别 vite-plugin-svg-icons!用 @unocss/preset-icons 加载本地 SVG 图标
  • 2.1 Mockito核心API详解
  • PriorityQueue优先级队列的使用和Top-k问题
  • 小白零基础学习深度学习之张量
  • 【C++语言】类和对象(下)
  • 备战蓝桥杯:二分算法详解以及模板题
  • Redis持久化机制详解
  • Proxy vs DefineProperty
  • 车载工具报错分析:CANoe、CANalyzer问题:Stuff Error
  • Java 大视界 -- Java 大数据在智能家居中的应用与场景构建(79)
  • Vue:Table合并行于列
  • 用Go实现 SSE 实时推送消息(消息通知)——思悟项目技术4