入门 | 如何通过梯度检验帮助实现反向传播

选自imaddabbura

机器之心编译

参与:刘天赐、路

本文介绍了如何使用梯度检验方法确认反向传播代码是否准确。

在《Coding Neural Network - Forward Propagation and Backpropagation》一文中,我们借助 numpy 实现了前向传播和反向传播算法。但从头开始实现反向传播很容易遇到 bug 或者报错。因此,在训练数据上运行神经网络之前,必须检验反向传播的实现是否正确。不过首先,我们先复习一下反向传播的概念:从最后的节点开始,沿着拓扑排序的反方向遍历所有节点,计算每个边的尾节点相对于损失函数的导数。换言之,计算损失函数对所有参数的导数:∂J/∂θ,其中θ表示模型中的参数。

我们通过计算数值梯度并比较数值梯度和根据反向传播求出的梯度(解析梯度)间的差异,来测试我们的实现代码。这里有两种数值梯度的计算方法:

  • 右边形式:
  • (1) [J(θ+ϵ)−J(θ)]/ϵ
  • 双边形式(见图 2):
  • (2) [J(θ+ϵ)−J(θ−ϵ)]/2ϵ

图 2:双边数值梯度

逼近导数的双边形式比右边形式更接近真实值。我们以 f(x)=x^2 为例,在 x=3 处计算导数。

  • 解析导数:∇_xf(x)=2x ⇒∇_xf(3)=6
  • 双边数值导数:[(3+1e−2)^2−(3−1e−2)^2]/[2∗1e−2]=5.999999999999872
  • 右边数值导数:[(3+1e−2)^2−3^2]/[1e−2]=6.009999999999849

可以看到,解析梯度和双边数值梯度之间的差值几乎为零;而和右边形式的数值梯度之间的差值为 0.01。因此在下文中,我们使用双边形式计算数值梯度。

另外,我们使用下式对数值梯度和解析梯度间的差值进行标准化。

(3)

如果差值≤10^−7,可以认为反向传播的实现代码没有问题;否则,就需要回去检查代码,因为一定有什么地方出错了。

以下是完成梯度检验的步骤:

1. 随机从训练集中抽取一些样本,用来计算数值梯度和解析梯度(不要使用所有训练样本,因为梯度检验运行会很慢)。

2. 初始化参数。

3. 计算前向传播和交叉熵损失。

4. 利用写好的反向传播的实现代码计算梯度(解析梯度)。

5. 计算双边形式的数值梯度。

6. 计算数值梯度和解析解梯度的差值。

这里,我们使用《Coding Neural Network - Forward Propagation and Backpropagation》中所写的函数来实现参数初始化、前向传播、反向传播以及交叉熵损失的计算。

导入数据。

# Loading packages
import sys

import h5py
import matplotlib.pyplot as plt
import numpy as np
from numpy.linalg import norm
import seaborn as sns

sys.path.append("../scripts/")
from coding_neural_network_from_scratch import (initialize_parameters,
                                                L_model_forward,
                                                L_model_backward,
                                                compute_cost)
# Import the data
train_dataset = h5py.File("../data/train_catvnoncat.h5")
X_train = np.array(train_dataset["train_set_x"]).T
y_train = np.array(train_dataset["train_set_y"]).T
X_train = X_train.reshape(-1, 209)
y_train = y_train.reshape(-1, 209)

X_train.shape, y_train.shape
((12288, 209), (1, 209))

编写 helper 函数,帮助实现参数和梯度词典(gradients dictionary)到向量的相互转换。

最后,编写梯度检验函数,利用此函数计算解析梯度和数值梯度之间的差值,并借此判断反向传播的实现代码是否正确。我们随机抽取 1 个样本来计算差值:

# Set up neural network architecture
layers_dims = [X_train.shape[0], 5, 5, 1]

# Initialize parameters
parameters = initialize_parameters(layers_dims)

# Randomly selecting 1 example from training data
perms = np.random.permutation(X_train.shape[1])
index = perms[:1]

# Compute forward propagation
AL, caches = L_model_forward(X_train[:, index], parameters, "tanh")

# Compute analytical gradients
gradients = L_model_backward(AL, y_train[:, index], caches, "tanh")

# Compute difference of numerical and analytical gradients
difference = gradient_check(parameters, gradients, X_train[:, index], y_train[:, index], layers_dims)

反向传播的实现是 OK 的!这里的差值是 3.0220555297630148e-09

结论

以下是一些关键点:

  • 双边形式的数值梯度在逼近解析梯度时效果比单边形式的数值梯度更好。
  • 由于梯度检验的运行很慢,因此:
  • 进行梯度检验时,只使用一个或少数样本;
  • 在确认反向传播的实现代码无误后,训练神经网络时记得取消梯度检验函数的调用。
  • 如果使用了 drop-out 策略,(直接进行)梯度检验会失效。可以在进行梯度检验时,将 keep-prob 设置为 1,训练神经网络时,再进行修改。
  • 通常采用 e=10e-7 作为检查解析梯度和数值梯度间差值的基准。如果差值小于 10e-7,则反向传播的实现代码没有问题。
  • 幸运的是,在诸如 TensorFlow、PyTorch 等深度学习框架中,我们几乎不需要自己实现反向传播,因为这些框架已经帮我们计算好梯度了;但是,在成为一个深度学习工作者之前,动手实现这些算法是很好的练习,可以帮助我们理解其中的原理。

原文发布于微信公众号 - 机器之心(almosthuman2014)

原文发表时间:2018-05-09

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器之心

增加检测类别?这是一份目标检测的基础指南

1435
来自专栏专知

【最新TensorFlow1.4.0教程03】利用Eager Execution构建和训练卷积神经网络(CNN)

【导读】主题链路知识是我们专知的核心功能之一,为用户提供AI领域系统性的知识学习服务,一站式学习人工智能的知识,包含人工智能( 机器学习、自然语言处理、计算机视...

4115
来自专栏算法channel

机器学习逻辑回归:算法兑现为python代码

0 回顾 昨天推送了逻辑回归的基本原理:从逻辑回归的目标任务,到二分类模型的构建,再到如何用梯度下降求出二分类模型的权重参数。今天,我们将对这个算法兑现为代码...

3605
来自专栏新智元

Reddit 讨论:Hinton的Capsule网络真的比CNN效果更好吗?

【新智元导读】Hinton 提出用 Capsule 这个概念代替反向传播,引起广泛关注。本文来自Reddit上“Capsule networks为何与众不同,它...

3537
来自专栏marsggbo

论文笔记系列-Efficient Neural Architecture Search via Parameter Sharing

本文提出超越神经架构搜索(NAS)的高效神经架构搜索(ENAS),这是一种经济的自动化模型设计方法,通过强制所有子模型共享权重从而提升了NAS的效率,克服了NA...

5662
来自专栏CreateAMind

Deep Learning Book 中文5.7-6.2节 机器学习基础-深度前馈网络

监督学习算法、无监督学习算法、推动深度学习的挑战;基于梯度的学习:最大似然学习条件分布;不同的输出单元:多分类等。

812
来自专栏Petrichor的专栏

思考: 神经网络层 的 功能识别

卷积操作 即为 一系列 滤波操作 之和 。 有关卷积的概念,具体可参加我的这篇文章:深度学习: convolution (卷积) 。

1135
来自专栏人工智能头条

深度学习目标检测指南:如何过滤不感兴趣的分类及添加新分类?

1863
来自专栏ATYUN订阅号

【学术】一文教你如何正确利用kNN进行机器学习

AiTechYun 编辑:xiaoshan k最近邻算法(kNN)是机器学习中最简单的分类方法之一,并且是入门机器学习和分类的好方法。它基本上是通过在训练数据中...

2825
来自专栏Python中文社区

Python机器学习算法入门之梯度下降法实现线性回归

專 欄 ❈ ZZR,Python中文社区专栏作者,OpenStack工程师,曾经的NLP研究者。主要兴趣方向:OpenStack、Python爬虫、Pytho...

3415

扫码关注云+社区

领取腾讯云代金券