神经网络反向传播梯度计算数学原理

[神经网络]反向传播梯度计算数学原理

1 文章概述

本文通过一段来自于Pytorch官方的warm-up的例子:使用numpy来实现一个简单的神经网络。使用基本的数学原理,对其计算过程进行理论推导,以揭示这几句神奇的代码后面所包含的原理。

估计对大多数的同学来说,看完这个文章,肯定会是这样的感觉:字都认识,但是就是不知道讲的是啥~!不过对于有心人来说,本文确实能起到点睛之笔,就是你研究很久后,还差一点火候就顿悟了,希望本文能够帮你顿悟。

关键字:Numpy,神经网络,矩阵分析,反射传播,梯度下降

2 实现代码

numpy作为一个科学计算库,并不包含:计算图,尝试学习,梯度等等功能,但是我们可以简单的通过numpy去拟合一个二层的网络。

解决的问题:

  1. 随机生成一组输入数据,一组输出数据。
  2. 定义一个神经网络结构及其参数
  3. 根据输入数据正向传播,求出误差
  4. 根据误差反向传播梯度,更新神经元的各个节点的参数

代码如下:

# -*- coding: utf-8 -*-
import numpy as np

# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10

# Create random input and output data
x = np.random.randn(N, D_in)
y = np.random.randn(N, D_out)

# Randomly initialize weights
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)

learning_rate = 1e-6
for t in range(500):
    # Forward pass: compute predicted y
    h = x.dot(w1)
    h_relu = np.maximum(h, 0)
    y_pred = h_relu.dot(w2)

    # Compute and print loss
    loss = np.square(y_pred - y).sum()
    print(t, loss)

    # Backprop to compute gradients of w1 and w2 with respect to loss
    grad_y_pred = 2.0 * (y_pred - y)
    grad_w2 = h_relu.T.dot(grad_y_pred)
    grad_h_relu = grad_y_pred.dot(w2.T)
    grad_h = grad_h_relu.copy()
    grad_h[h < 0] = 0
    grad_w1 = x.T.dot(grad_h)

    # Update weights
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

原文见:Learning PyTorch with Examples

3 网络结构

将上面的代码结构及相应的参数维度绘图后如下所示:

然后本代码使用的是一个大小为64的batch,所以输入的值实际的大小实际上是(64,1000)。

把以上的代码转化成数学公式如下,括号里面是相应的矩阵的形状:

4 正向计算

数据流的正向传播

最后计算出损失函数loss,是实际预测值和先验数据矩阵的二范数,作为两组矩阵的距离测度。

正向传播比较简单,基本上大学的线性代数的基本知识看几章,就能很好的理解。这也是后续如果在深度学习框架下面设计网络的时候,注意设计神经元大小的时候,需要考虑矩阵乘法的可行性,即维度相容。

PS:关于矩阵的范数的定义,详情见P32的《1.4.3矩阵的内积和范数》

5 反向传播

5.1 实现代码

下面是反射传播的代码实现:

5.2 数学基础

关于反射传播的数学原理,可能就不是那么好理解了,因为这里面需要用到矩阵的高级算法,一般的理工科数学的《线性代数》甚至《高等代数》里面都没有提到相关的内容,所以基本上已经超过了大多数高校学生的知识范围了。在这个时候,就要祭出张贤达的《矩阵分析》了。

最开始我把自己大学时候的数学书《数学分析》,《高等代数》,《数值计算》都翻了一遍,但是都没有找到相关的内容。感觉对于矩阵的微分是一个“三不管”的地带,但是这个内容又是深度学习神经网络中用得最多的数学原理。然后到网上发现了《矩阵分析与应用》,想想这么厚的一本像百科全书的书,应该是无所不包吧,果然在里面找到了想要的内容。

当然在看书之前,也看了无数的网络文章,相对比较有价值的就下面两篇:

《矩阵求导-上》https://zhuanlan.zhihu.com/p/24709748

《矩阵求导-下》https://zhuanlan.zhihu.com/p/24863977

当然,像数学工具这种内容,建议大家还是去看书,因为书作为几十年的经典教材,其推导过程,内容的完整性,认证的严密性都是经得起推敲的。网络文章只能帮大家启蒙一下,学几个术语,但是具体想深入了解细节,建议还是看书。

言归正传。

上述的不到10行的反向传播梯度,更新参数的代码,在外行人看来是比较神来之笔,完全摸不着头脑,这是很正常的。因为要理解上述的代码,需要预先储备如下知识(《矩阵分析与应用》):

  1. 矩阵的基本运算。页面P4,章节编号1.1.2
  2. 矩阵的内积与范数。P32, 1.4.3
  3. 矩阵的迹。P49, 1.6.4
  4. 向量化和矩阵化。 P74, 1.11
  5. Jacobian矩阵和梯度矩阵。 P143, 3.1
  6. 一阶实矩阵微分与Jacobian矩阵辨识。 P152, 3.2

注意事项:函数有不同的分类,所以请大家不要全用《线性代数》里面变元全为实数标量的眼光来看待矩阵的变元和矩阵函数的运算。因为它们是不同的,即使你勉强得到符合代码的结论,那很可能也是“瞎猫碰到死耗子”。关于函数的微分的讨论,光实值函数的分类,就可以分如下几类(P143, 3.1):

矩阵和Jacobian矩阵在实值区间内是互为转置。在进行数学推导时,都是先根据Jacobian矩阵的辨识方法求出Jacobian矩阵,然后转置后就是相应的梯度。

当定义一个标量函数关于变量的偏导数时:

Jacobian矩阵和梯度矩阵是关于偏导的不同定义方式,分别是行向量偏导和列向量偏导。只是Jacobian矩阵是一种研究思维上更自然的选择,但是梯度向量却是优化和实际工程计算时更自然的选择。

5.3 预测值梯度

grad_y_pred = 2.0 * (y_pred - y)

下面是推导过程,红色笔迹是推导过程的依据,请查阅《矩阵分析与应用》

接着前面的公式,继续求微分:

5.4 参数W2梯度

grad_w2 = h_relu.T.dot(grad_y_pred)

5.5 参数H_relu 梯度

grad_h_relu = grad_y_pred.dot(w2.T)

5.6 Relu梯度

grad_h = grad_h_relu.copy()

grad_h[h < 0] = 0

grad_w1 = x.T.dot(grad_h)

5.7 参数W1梯度

然后后面就是使用梯度和学习率去批量更新参数,实现整个训练过程了。

6 参考资料

《矩阵分析与应用》(第2版) 张贤达 著,清华大学出版社,2011-11,第2版

原文地址:https://www.cnblogs.com/alan-blog-TsingHua/p/9981522.html

时间: 2024-10-11 17:13:18

神经网络反向传播梯度计算数学原理的相关文章

神经网络反向传播算法(4,5)

"反向传播"是最小化成本函数的神经网络术语,就像我们在logistic回归和线性回归中的梯度下降一样.我们的目标是计算: 也就是说,我们希望在θ中使用一组最优参数来最小化我们的成本函数j.在这一节中我们将看看我们用来计算J(Θ)的偏导数方程: 为此,我们使用下面的算法: 反向传播算法实现: 1.得到训练集 2.设置所有i,j,l(因此你最终有一个矩阵全零) 3.遍历训练样本t = 1到m: (1) (2)进行正向传播计算a(j)  j从1到m: (3)使用y(t),计算 其中L是我们的

前馈神经网络-反向传播(Back Propagation)公式推导走读

构造:输入神经元个数等于输入向量维度,输出神经元个数等于输出向量维度.(x1=(1,2,3),则需要三个输入神经元) 一 前向后传播 隐层: 输出层: 一般化,向量表示   二 反向传播 1计算梯度delta:均方误差,利用了sigmoid函数导数的有趣性. 输出层梯度: -->  eg.  隐层梯度:  -->   eg.  2更新权重: eg输出层: eg隐层: 备注 反向传播的公式推导 0目标函数: 1梯度下降法优化目标函数, 怎么计算出误差对于每个权重的偏导数呢? 2netj是第j个神

神经网络反向传播,通俗理解

前置知识: sigmod 函数 g(z) = 1 / (1 + np.exp(-z)) g'(z) = (1 / (1 + np.exp(-z))) * (1 - (1 / (1 + np.exp(-z)))) g'(z) = g(z) * (1 - g(z)) LR-----1层神经网络 dL/dz 简称dz_,L(a,y)使用交叉熵. da_ = dL/da = (-(y/a) + ((1-y)/(1-a))) dz_ = dL/da * da/dz = da_*   g'(z) dw_ =

卷积层,池化层等,前向/反向传播原理讲解

今天闲来无事,考虑到以前都没有好好研究过卷积层.池化层等等的前向/反向传播的原理,所以今天就研究了一下,参考了一篇微信好文,讲解如下: 参考链接:https://www.zybuluo.com/hanbingtao/note/485480 https://github.com/hanbt/learn_dl/blob/master/cnn.py 一.卷积层 (1)首先是卷积神经网络中的卷积操作: 计算公式为: 注意上式的使用场景:stride = 1 , channel = 1 我们可以将其扩展到

深度学习之反向传播算法

直观理解反向传播 反向传播算法是用来求那个复杂到爆的梯度的. 上一集中提到一点,13000维的梯度向量是难以想象的.换个思路,梯度向量每一项的大小,是在说代价函数对每个参数有多敏感. 如上图,我们可以这样里理解,第一个权重对代价函数的影响是是第二个的32倍. 我们来考虑一个还没有被训练好的网络.我们并不能直接改动这些激活值,只能改变权重和偏置值.但记住,我们想要输出层出现怎样的变动,还是有用的. 我们希望图像的最后分类结果是2,我们期望第3个输出值变大,其余输出值变小,并且变动的大小应该与现在值

神经网络系列之二 -- 反向传播与梯度下降

系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI, 点击star加星不要吝啬,星越多笔者越努力. 第2章 神经网络中的三个基本概念 2.0 通俗地理解三大概念 这三大概念是:反向传播,梯度下降,损失函数. 神经网络训练的最基本的思想就是:先"猜"一个结果,我们叫预测结果a,看看这个预测结果和事先标记好的训练集中的真实结果y之间的差距,然后调整策略,再试一次,这一次就不是"猜"了,而是有依据地向正确的方向靠近.如此反复多次

实现一个反向传播人工神经网络

为何实现一个BP神经网络? “What I cannot create, I do not understand” — Richard Feynman, February 1988 实现一个BP神经网络的7个步骤 选择神经网络 结构 随机 初始化权重 实现 前向传播 实现 成本函数 $J(\Theta)$ 实现反向传播算法并计算 偏微分 $\frac{\partial}{\partial\Theta_{jk}^{(i)}}J(\Theta)$ 使用 梯度检查 并在检查后关闭 使用梯度下降或其它优

神经网络训练中的Tricks之高效BP(反向传播算法)

神经网络训练中的Tricks之高效BP(反向传播算法) 神经网络训练中的Tricks之高效BP(反向传播算法) [email protected] http://blog.csdn.net/zouxy09 Tricks!这是一个让人听了充满神秘和好奇的词.对于我们这些所谓的尝试应用机器学习技术解决某些问题的人,更是如此.曾记得,我们绞尽脑汁,搓手顿足,大喊“为什么我跑的模型不work?”,“为什么我实现的效果那么差?”,“为什么我复现的结果没有他论文里面说的那么好?”.有人会和你说“你不懂调参!

循环神经网络(RNN)模型与前向反向传播算法

在前面我们讲到了DNN,以及DNN的特例CNN的模型和前向反向传播算法,这些算法都是前向反馈的,模型的输出和模型本身没有关联关系.今天我们就讨论另一类输出和模型间有反馈的神经网络:循环神经网络(Recurrent Neural Networks ,以下简称RNN),它广泛的用于自然语言处理中的语音识别,手写书别以及机器翻译等领域. 1. RNN概述 在前面讲到的DNN和CNN中,训练样本的输入和输出是比较的确定的.但是有一类问题DNN和CNN不好解决,就是训练样本输入是连续的序列,且序列的长短不