标签归档:反向传播

微积分——自动微分

  梯度下降法(Gradient Descendent)是机器学习的核心算法之一,自动微分则是梯度下降法的核心;
  梯度下降法用于求损失函数的最优值,前面的文章中我们说过梯度下降是通过计算参数与损失函数的梯度并在梯度的方向不断迭代求得极值;但是在机器学习、深度学习中很多求导往往是很复杂的,手动使用链式法则求导很容易出错,借助于计算机也只能是硬编码;
  这时候就需要借助于自动微分了,求导主要有这么四种:手动微分法数值微分法符号微分法自动微分法,这里分别说说这几种求导方法;

手动微分法(Manual Differentiation)
  手动微分法需要我们手动编写出代价函数激活函数的求导代码,硬编码这些函数的求导方法,如果这些函数后面有调整该函数的求导方法又要重新实现,可以说是又麻烦又容易出错;
数值微分法(Numerical Differentiation)
  通过使用函数值来估计函数的导数,该方法主要是计算速度慢,精度差等问题;
符号微分法(Symbolic Differentiation)
  符号微分广泛用在各种数学软件中如Matlab、Octave等,它通关过使用符号表达式进行求导,符号微分是基于求导法则进行的;

  如表达式:f(x) = 2y + x^2
  表达式树为:
    enter image description here

  通过符号微分法求得:

  enter image description here

  符号微分有个缺陷就是得到的导数不一定是最简的,函数较为复杂时表达式树会很复杂,可能会出现表达式爆炸的情况出现;

自动微分法(Autodiff)

  自动微分法介于数值微分符号微分 之间,数值微分是直接代入数值近似求解而符号微分为直接通过表达式树对表达式进行求解;自动微分先将符号微分用于基本的算子,带入数值并保存中间结果,后应用于整个函数;自动微分本质上就是图计算,容易做很多优化所以广泛应用于各种机器学习深度学习框架中;
  自动微分又分为前向模式(Forward mode Autodiff)反向模式(Reverse-Mode Atuodiff)求导;

前向模式(Forward mode Autodiff)

  前向模式引入二元数(dual number),同时会先将表达式转换为计算图然后会依次从下往上计算每一步的导数,由于每步都使用了上一步的导数所以不会导致重复计算不会出现像符号微分一样的表达式膨胀问题,但由于深度学习的参数比较多所以前向模式的效率还是有些差;一个前向过程就可以求出其函数值与导数,下面简单举个例子:

  二元数:a+bꜫ
  a与b都是实数,ꜫ为无穷小的数,且ꜫ^2=0,并满足加分与乘法法则,且还有:
    enter image description here
  这样是要求出f( a+ꜫ)就可以得出f(a)与f(a)的导数;
  还是上面的表达式:f(x) = 2y + x^2

    enter image description here

  如上图当x=2,y=3时,我们可以得出:二元数 10+4ꜫ,即函数f(x)关于x的偏导数为:4,函数值为10;

反向模式(Reverse mode autodiff)

  反向模式为先通过正向遍历计算图求出每个节点的值,然后通过反向遍历整个图,计算出每个节点的偏导,其原理为微积分链式法则,这里所说的反向模式其实也就是我们在深度学习中所说的BP算法(反向传播算法),只需要一个前向传播、一个反向传播就可以求得所有参数的导数,所以性能很高,非常适用于深度学习中的自动求导;

          enter image description here

  上图为经过反向传播的计算图,根据链式法则:
enter image description here
enter image description here

  正如上面所说的,经过一次正向传播求出所有的节点值后再经过一次反向传播就求得了所有输入参数的导数效率很高,而且避免符号微分、数值微分所带来的问题;目前Tensoflow、MXNet等深度学习框架中也都使用了反向模式实现自动微分只是各种具体算法还是有不少差异;

参考资料:
https://blog.csdn.net/aws3217150/article/details/70214422
https://arxiv.org/pdf/1502.05767.pdf

BP神经网络

神经网络理论

  BP神经网络(Back Propagation Neural Network)为多层前馈神经网络用得比较广泛,该神经网络先通过前向传播取得估计值,后再使用误差进行反向传播通过梯度下降来不断地更新权重从而取得最小误差从中学习得最佳权重系数;从BP神经网络的名字也知道该算法的核心为反向传播算法,神经网络由多个神经元组成神经元结构如下:
  enter image description here

  如上图每个神经元结构由输入、权重、阈值、激活函数、输出组成;

  输入:接受上层的输出作为该神经元的输入
  权重:连接上层神经元与该神经元
  阈值:现在通常把该阈值独立为每层的一个偏置神经元参与权重与输入的加权和运算
  输出:输入与权重加权和并通过激活函数产生的结果,并且该输出为下层神经元的输入
  激活函数:作用为神经网络添加非线性因素,解决线性不可分问题,使神经网络能够处理更复杂的问题;
  下图为两层神经网络,该网络的结构为:输入层、隐含层、输出层,称为两层神经网络是因为去掉输入层就只有两层,圆圈中为1的为偏置神经元,输入层节点数据属性并非神经元;神经网络可以有一个或多个隐含层,超过两个隐含层通过就可以称作深度神经网络,BP神经网络通常隐含层不会超过两个;
enter image description here

BP神经网络结构:

enter image description here
enter image description here
enter image description here

训练

  一个BP神经网络流程主要以下几个步骤:正向传播、反向传播、计算误差、更新权重;下面通过一个示例来说明 BP神经网络的整个训练过程; 数据集:D={(x_1,y_1 ),(x_2,y_2 )},x_1∈R^2,y_1∈R^2,数据集包含2两个属性,2维输出向量;根据该数据集构建了神经网络结构如下图,两层神经网络拥有两个输入属性、两个输出神经元、两个隐含神经元、两个偏置神经元,总共2 x 2 x 2 = 8条权重; BP神经网络为迭代算法,我们通过不断的反向传播迭代更新权重w,从而神经元的输出也会随着调整,直到输出层得到的值与数据集的真实值误差总和最小或达到了迭代次数,此时终止模型训练,这些得到的权重w便是该神经网络的最佳参数;
enter image description here

符号定义:
  1、x1、x2…为输入层属性
  2、h1、h2…为隐含层神经元
  3、o1、o2…为输出层神经元
  4、输入层节点中的数字为该输入属性值
  5、v_xh为输入层第x个节点与隐含层第h个神经元的权重
  6、w_ho为隐含层第h个神经元与输出层第o个神经元的权重
  由于使用实数运算描述会有所复杂并且在代码层面实现时会存在大量的循环操作,所以这里会在有些地方使用向量来代替,下面看到加粗大写字母均为向量;如X表示为该神经网络的输入向量;

正向传播

  通过从输入层、隐含层、输出层逐层计算每层神经元输出值;

enter image description here

1、输入层——》隐含层
计算隐含层h1、h2神经元的输入加权和:

enter image description here

神经元h1输出:

enter image description here

2、隐含层——》输出层

计算输出层o1的输入加权和

enter image description here
enter image description here

神经元o1输出:

enter image description here

此时求得的输出为:[0.79751046、0.83401102]

反向传播

enter image description here

上一步在正向传播时已经求得初步的估计值,现在先求出O1、O2的误差、总误差:

enter image description here
enter image description here

1、隐含层到输出层权重更新
通过求出总误差关于输出层权重的偏导,可以得到每个权重对总误差的影响,便可用于更新输出层权重;

enter image description here

  从上图可以看出总误差关于权重的偏导数可以应用微积分的链式法则,可分解为:总误差关于输出的偏导、输出关于加权和的偏导、加权和关于权重的偏导,三者的乘积;

总误差关于权重w11的偏导:

enter image description here

总误差关于输出的偏导:

enter image description here

输出关于加权和的偏导:

enter image description here

加权和关于权重的偏导:

enter image description here

总误差关于权重的偏导数:

enter image description here
enter image description here

同理,连接隐含层与输出层其他权重更新如下:

enter image description here

2、输入层到隐含层权重更新

与上面求隐含层到输出层权重的更新一样,这里也是求总误差关于权重的偏导;

enter image description here

  从上图可以看出隐含层h1神经元的输出有来自输出层O1、O2神经元传来的误差; 总误差关于h1输出的偏导数=O1误差关于h1输出的偏导数+ O2s误差关于h1输出的偏导数:

enter image description here

输出层O1神经元误差关于隐含层h1神经元输出的偏导:

enter image description here

输出层O2神经元误差关于隐含层h1神经元输出的偏导:

enter image description here

总误差关于h1输出的偏导数

enter image description here

隐含层输出关于加权和的偏导:

enter image description here
加权和关于权重的偏导:

enter image description here
总误差关于权重的偏导数:

enter image description here

w_11权重更新(ε为学习率):

enter image description here

同理输入层与隐含层其他权重更新:

enter image description here

参考资料:
周志华 西瓜书
https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/