梯度是如何计算的

引言

深度学习模型的训练本质上是一个优化问题,而常采用的优化算法是梯度下降法(SGD)。对于SGD算法,最重要的就是如何计算梯度。此时,估计跟多人会告诉你:采用BP(backpropagation)算法,这没有错,因为神经网络曾经的一大进展就是使用BP算法计算梯度提升训练速度。但是从BP的角度,很多人陷入了推导公式的深渊。如果你学过微积分,我相信你一定知道如何计算梯度,或者说计算导数。对于深度网络来说,其可以看成多层非线性函数的堆积,即:

而我们知道深度学习模型的优化目标L一般是output的函数,如果要你求L关于各个参数的导数,你会不假思索地想到:链式法则。因为output是一个复合函数。在微积分里面,求解复合函数的导数采用链式法则再合适不过了。其实本质上BP算法就是链式法则的一个调用。让我们先忘记BP算法,从链式法则开始说起。

链式法则

链式法则无非是将一个复杂的复合函数从上到下逐层求导,比如你要求导式子:f(x,y,z)=(x+y)(x+z)。当然这个例子是足够简单的,但是我们要使用链式法则的方式来求导。首先可以将f(x,y,z)看成两个函数p(x,y)=(x+y)与q(x,z)=(x+z)的复合:f=pq。假如你要求df/dz,首先我们先要求出df/dp与df/dq。很显然,df/dp=q,df/dq=p。然后要求dp/dx与dq/dx,显然,dp/dx=1.0,dq/dx=1.0。这个时候已经求到最底层了,可以利用链式法则求出最终的结果了:df/dx=(df/dp)(dp/dx)+(df/dq)(dq/dx)=q+p。同样的方法,可以求出:df/dy=q,df/dz=p。如果大家细致观察的话,可以看到要求出最终的导数,你需要计算出中间结果:p与q。计算中间结果的过程一般是前向(forward)过程,然后再反向(backward)计算出最终的导数。过程如下:

#程序1#
    #输入
    x, y, z = -3, 2, 5
    
    #执行前向过程
    p = x + y        #p = -1
    q = x + z        #q = 2
    
    #执行反向过程计算梯度
    #第一个层反向:f = pq
    dfdp = q        #df / dp = 2
    dfdq = p        #df / dq = -1
    
    #第二个层反向,并累积第一层梯度:
    #p = x + y, q = x + z
    dfdx = 1.0 * dfdp + 1.0 * dfdq    #df / dx = 1
    dfdy = 1.0 * dfdp    #df / dy = 2
    dfdz = 1.0 * dfdq    #df / dz = -1

上面的一个过程就是BP算法,包含两个过程:前向forward)过程与反向(backword)过程。前向过程是从输入计算得到输出,而反向过程就是一个梯度累积的过程,或者说是BP,即误差反向传播。这就是BP的思想。上面的例子应该是比较简单的,而对于深度学习模型来说,其只不过是函数复杂一点罢了,但是如果你严格按照链式法则来去推导,只要你会基本求导方法,应该都不是什么难事了。

矩阵运算

其实对于深度学习模型来说,其运算都是基于矩阵运算的。对于新手来说,矩阵运算的求导可能会是一件比较头疼的事。其实矩阵运算求导是一个纸老虎。对于元素级的矩阵运算来说,比如激活函数这种,你完全可以把看成普通的求导。但是对于矩阵乘法,你需要特别注意,这里先抛出例子:

#程序2#
   import numpy as np
      
   #前向过程
   W = np.random.randn(5,10)
   X = np.random.randn(10,3)
   D = W.dot(X)
   
   #反向过程
   #假定dD是后面传播过来的梯度项
   dD = np.random.randn(*D.shape)  
   dW = dD.dot(X.T)
   dX = W.T.dot(dD)

如果你认真推导的话,是可以得到上面的结果的。但是这里有其它捷径。对于两个矩阵相乘的话,在反向传播时反正是另外一个项与传播过来的梯度项相乘。差别就在于位置以及翻转。这里有个小窍门,就是最后计算出梯度肯定要与原来的矩阵是同样的shape。那么这就容易了,反正组合不多。比如你要计算dW,你知道要用dD与X两个矩阵相乘就可以得到。W的shape是[5,10],而dD的shape是[5,3],X的shape是[10,3]。要保证dW与W的shape一致,好吧,此时只能用dD.dot(X.T),真的没有其它选择了,那这就是对了。

活学活用:

实现一个简单的神经网络

上面我们讲了链式法则,也讲了BP的思想,并且也讲了如何对矩阵运算求梯度。下面我们基于Python中的Numpy库实现一个简单的神经网络模型,代码如下:

#程序3#
"""
一个简单两层神经网络回归模型
"""

   import numpy as np
   # batch size
    N = 32
   # 输入维度
    D = 100
   # 隐含层单元数
    H = 200
   # 输出维度
    O = 10

   # 训练样本(这里随机生成)
    X = np.random.randn(N, D)
    y = np.random.randn(N, O)
   # 初始化参数
    W1 = np.random.randn(D, H)
    b1 = np.zeros((H,))
    W2 = np.random.randn(H, O)
    b2 = np.zeros((O,))

   # 训练参数
    learning_rate = 1e-02
    iterations = 200

   # 训练过程
   for t in range(iterations):    # 前向过程
       h = X.dot(W1) + b1
       h_relu = np.maximum(h, 0)
       pred = h_relu.dot(W2) + b2    
     #定义loss,采用均方差
       loss = np.sum(np.square(y - pred))  
       print("Iteration %d loss: %f" % (t, loss))    
     # 反向过程计算梯度
       dpred = 2.0 * (pred - y)
       db2 = np.sum(dpred, axis=0)
       dW2 = h_relu.T.dot(db2)
       dh_relu = db2.dot(W2.T)
       dh = (h > 0) * dh_relu
       db1 = np.sum(dh, axis=0)
       dW1 = X.T.dot(dh)  
       # SGD更新梯度
       params = [W1, b1, W2, b2]
       grads = [dW1, db1, dW2, db2]    
     for p, g in zip(params, grads):
           p += -learning_rate * g

总结

这里我们简单介绍了梯度下降法中最重要的一部分,就是如何计算梯度。相信通过本文,大家对BP算法以及链式法则有更深刻的理解。

参考资料

cs231n教程:http://cs231n.github.io/optimization-2/

原文发布于微信公众号 - 机器学习算法全栈工程师(Jeemy110)

原文发表时间:2017-08-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能

机器学习实战之决策树

一、简介 决策树是一类常见的机器学习方法,以二分类任务为例,我们希望从给定训练数据集学得一个模型用以对新数据进行分类,比如通过一组数据通过模型训练得到以下的决策...

18610
来自专栏张俊红

决策树详解

总第79篇 01|背景: 我们在日常生活中经常会遇到一些选择需要去做一些选择,比如我们在找工作的时候每个人都希望能找到一个好的工作,但是公司那么多,工作种类那么...

2765
来自专栏ATYUN订阅号

Python机器学习的练习五:神经网络

在这篇文章中,我们将再次处理手写数字数据集,但这次使用反向传播的前馈神经网络。我们将通过反向传播算法实现神经网络成本函数的非正则化和正则化版本以及梯度计算。最后...

38511
来自专栏人工智能LeadAI

线性回归与最小二乘法 | 机器学习笔记

这篇笔记会将几本的线性回归概念和最小二乘法。 在机器学习中,一个重要而且常见的问题就是学习和预测特征变量(自变量)与响应的响应变量(应变量)之间的函数关系 ...

2907
来自专栏人工智能

什么是反向传播算法

神经网络的快速发展离不开底层数学算法的演进。反向传播算法作为神经网络中学习的主力,最初是在20世纪70年代引入的,但其重要性直到1986年由一篇着名的论文才得到...

17810
来自专栏desperate633

‘神经网络’初探

本文从感知器开始讲起,引入激活函数,最后引出了神经网络的基本概念和思想,希望能帮助读者对神经网络有一个初步的了解!

883
来自专栏达观数据

技术干货 | 一文详解高斯混合模型原理

高斯混合模型(Gaussian Mixture Model)通常简称GMM,是一种业界广泛使用的聚类算法,该方法使用了高斯分布作为参数模型,并使用了期望最大(E...

3716
来自专栏决胜机器学习

循环神经网络(三) ——词嵌入学习与余弦相似度

循环神经网络(三) ——词嵌入学习与余弦相似度 (原创内容,转载请注明来源,谢谢) 一、词汇表征 1、one-hot表示法 之前的学习中提到过,对于词汇库,可以...

3426
来自专栏智能算法

人脸识别经典算法:特征脸方法(Eigenface)

特征脸方法基本是将人脸识别推向真正可用的第一种方法,了解一下还是很有必要的。特征脸用到的理论基础PCA在之前的文章中已经讲过了。直接上特征脸方法的步骤:...

4175
来自专栏数据科学与人工智能

【深度学习】深度学习概述:从感知机到深度网络

近些年来,人工智能领域又活跃起来,除了传统了学术圈外,Google、Microsoft、facebook等工业界优秀企业也纷纷成立相关研究团队,并取得了很多令人...

28110

扫描关注云+社区