小奥的学习笔记

  • Home
  • Learning & Working
    • Speech Enhancement Notes
    • Programming language
    • Computer & DL
    • MOOC
  • Life
    • Life Time
    • Thinking & Comprehension
    • Volunteer
    • Plan
    • Travel
  • Footprints
  • GuestBook
  • About
    • About Me
    • 个人履历
    • 隐私策略
  1. 首页
  2. Study-notes
  3. Computer & DL
  4. Deep Learning
  5. 正文

吴恩达深度学习课程 DeepLearning.ai 编程作业(2-1)Part.3

2018年2月7日 2046点热度 0人点赞 0条评论

梯度检验

欢迎来到本周的最后作业! 在这个任务中,您将学习实现并使用梯度检验。

您是全球范围内开展移动支付的团队的一部分,并被要求建立一个深度学习模式来检测欺诈行为 - 每当有人付款时,您想要查看付款是否有欺诈行为,例如用户 帐户已被黑客占用。

但是反向传播实施起来相当具有挑战性,有时会有错误。 因为这是关键任务应用程序,所以贵公司的首席执行官要真正确定您的反向传播实施是正确的。 你的首席执行官说:“给我一个证明你的反向传播实际上是有效的!” 为了让这个保证,你将使用“梯度检验”。

我们开始做吧!

首先依旧是导入所有需要的包

# Packages
import numpy as np
from testCases import *
from gc_utils import sigmoid, relu,
from gc_utils import dictionary_to_vector, vector_to_dictionary
from gc_utils import gradients_to_vector

1) 梯度检验是如何工作的呢?

反向传播算法计算梯度(∂J/∂θ),其中θ表示模型的参数。J是利用前向传播算法和代价函数计算的结果。

由于前向传播算法相对容易执行,你对它非常有信心,所以你几乎100%的确认计算出来的J是正确的。因此,你可以用你的代码来计算J以便验证计算(∂J/∂θ)的代码。

让我们回顾一下梯度的概念:

1.png

我们可以知道:

(1)此式是你想验证计算正确的式子。

(2)由于你对于计算J非常有信心,你可以根据此计算出J(θ+ε)和J(θ−ε)。

2) 1维梯度检验

考虑一个1维线性函数 J(θ)=θX,这个模型只包含一个实值参数θ,并且X是输入。

你将运行代码来计算J以及它的导数,然后利用梯度检验确保J的导数计算是否正确。

2.jpg

上面的流程图展示了计算的步骤:首先从X开始,然后计算函数J(前向传播),最后计算其导数(反向传播)。

Exercise: 执行前向传播和反向传播代码。例如:compute both J(.) ("forward propagation") and its derivative with respect to θ ("backward propagation"), in two separate functions.

#GRADED FUNCTION: forward_propagation
def forward_propagation(x, theta):
    """
    Implement the linear forward propagation (compute J) 
    presented in Figure 1 (J(theta) = theta * x)
    Arguments:
    x -- a real-valued input
    theta -- our parameter, a real number as well
    Returns:
    J -- the value of function J, computed using 
    the formula J(theta) = theta * x
    """
    ### START CODE HERE ### (approx. 1 line)
    J = theta * x
    ### END CODE HERE ###
return J

测试一下:

x, theta = 2, 4
J = forward_propagation(x, theta)
print ("J = " + str(J))

结果为 J=8

Exercise: 执行反向传播(求导)代码。

# GRADED FUNCTION: backward_propagation
def backward_propagation(x, theta):
    """
    Computes the derivative of J with 
    respect to theta (see Figure 1).
    Arguments:
    x -- a real-valued input
    theta -- our parameter, a real number as well
    Returns:
    dtheta -- the gradient of the cost with 
     respect to theta
    """
    ### START CODE HERE ### (approx. 1 line)
    dtheta = x
    ### END CODE HERE ###
return dtheta

测试一下:

x, theta = 2, 4
dtheta = backward_propagation(x, theta)
print ("dtheta = " + str(dtheta))

Exercise: 为了展示函数backward_propagation() 正确的计算了梯度,让我们来做梯度检验。

Instructions:

l  首先利用最上面的式子和ε计算 "gradapprox" 。步骤如下:

3.png

l  然后,利用反向传播计算梯度,并把结果储存在变量"grad"中。

l  利用笔记2-1中的公式计算 “gradapprox”和“grad”之间的相对差值。

 

三步来计算这个公式:

l  利用np.linalg.norm(...)计算分子

l  调用np.linalg.norm(...)两次计算分母

l  分子除以分母

如果上面的二范数计算出来10−7,那么可以证明这个计算正确,否则计算错误。

# GRADED FUNCTION: gradient_check
def gradient_check(x, theta, epsilon = 1e-7):
    """
    Arguments:
    x -- a real-valued input
    theta -- our parameter, a real number
    as well
    epsilon -- tiny shift to the input to
   compute approximated gradient with formula(1)
    Returns:
    difference --
     difference (2) between the approximated gradient
     and the backward propagation gradient
    """
    # Compute gradapprox using left side of formula (1).
    #epsilon is small enough, you don't need to worry
#about the limit.
    ### START CODE HERE ### (approx. 5 lines)
    thetaplus=theta + epsilon# Step 1
    thetaminus=theta - epsilon   # Step 2
    J_plus=forward_propagation(x, thetaplus)
    J_minus=forward_propagation(x, thetaminus)
    gradapprox=(J_plus - J_minus)/(2 * epsilon)
    ### END CODE HERE ###
   
    # Check if gradapprox is close enough
#to the output of backward_propagation()
    ### START CODE HERE ### (approx. 1 line)
    grad = backward_propagation(x, theta)
    ### END CODE HERE ###
   
    ### START CODE HERE ### (approx. 1 line)
    numerator=np.linalg.norm(grad-gradapprox)
    denominator=np.linalg.norm(grad)+
                 np.linalg.norm(gradapprox)
    difference = numerator / denominator
    ### END CODE HERE ###
    if difference < 1e-7:
        print ("The gradient is correct!")
    else:
        print ("The gradient is wrong!")
return difference

测试一下:

x, theta = 2, 4
difference = gradient_check(x, theta)
print("difference = " + str(difference))

结果:

The gradient is correct!

difference = 2.91933588329e-10

现在,在更一般的情况下,您的成本函数J具有多于一个一维输入。当你训练一个神经网络时,θ实际上由多个矩阵W [l]组成,并且偏向b [l]!知道如何用更高维度的输入进行梯度检验是很重要的。我们开始做吧!

3) N维梯度检验

4.jpg

LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID

代码如下:

def forward_propagation_n(X, Y, parameters):
    """
    Implements the forward propagation
(and computes the cost) presented in Figure 3. 
    Arguments:
    X -- training set for m examples
    Y -- labels for m examples
    parameters -- python dictionary containing your
    parameters "W1", "b1", "W2", "b2", "W3", "b3":
     W1 -- weight matrix of shape (5, 4)
     b1 -- bias vector of shape (5, 1)
     W2 -- weight matrix of shape (3, 5)
     b2 -- bias vector of shape (3, 1)
     W3 -- weight matrix of shape (1, 3)
     b3 -- bias vector of shape (1, 1)  
    Returns:
    cost -- the cost function
(logistic cost for one example)
    """  
    # retrieve parameters
    m = X.shape[1]
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    W3 = parameters["W3"]
    b3 = parameters["b3"]
 #LINEAR->RELU->LINEAR->RELU->LINEAR->SIGMOID
    Z1 = np.dot(W1, X) + b1
    A1 = relu(Z1)
    Z2 = np.dot(W2, A1) + b2
    A2 = relu(Z2)
    Z3 = np.dot(W3, A2) + b3
    A3 = sigmoid(Z3)
    # Cost
    logprobs = np.multiply(-np.log(A3),Y)
    +np.multiply(-np.log(1 - A3), 1 - Y)
    cost = 1./m * np.sum(logprobs)
    cache = (Z1, A1, W1, b1, Z2, A2,
             W2, b2, Z3, A3, W3, b3)
return cost, cache

反向传播代码如下:

def backward_propagation_n(X, Y, cache):
    """
    Implement the backward propagation
  presented in figure 2.
    Arguments:
    X -- input datapoint, of shape (input size, 1)
    Y -- true "label"
    cache -- cache output from
    forward_propagation_n() 
    Returns:
    gradients -- A dictionary with the gradients of
    the cost with respect to each parameter, activation
    and pre-activation variables.
    """
    m = X.shape[1]
    (Z1, A1, W1, b1, Z2, A2, W2, b2, Z3, A3, W3, b3)
    = cache
   
    dZ3 = A3 - Y
    dW3 = 1./m * np.dot(dZ3, A2.T)
    db3 = 1./m * np.sum(dZ3, axis=1, keepdims = True)
   
    dA2 = np.dot(W3.T, dZ3)
    dZ2 = np.multiply(dA2, np.int64(A2 > 0))
    #print("dZ2:", dZ2)
    #dW2 = 1./m * np.dot(dZ2, A1.T) * 2
    dW2 = 1./m * np.dot(dZ2, A1.T)
    db2 = 1./m * np.sum(dZ2, axis=1, keepdims = True)
   
    dA1 = np.dot(W2.T, dZ2)
    dZ1 = np.multiply(dA1, np.int64(A1 > 0))
    #print("dZ1:", dZ1)
    dW1 = 1./m * np.dot(dZ1, X.T)
    #db1 = 4./m * np.sum(dZ1, axis=1, keepdims = True)
    db1 = 1./m * np.sum(dZ1, axis=1, keepdims = True)
   
    gradients = {"dZ3": dZ3, "dW3": dW3, "db3": db3,
       "dA2": dA2, "dZ2": dZ2, "dW2": dW2, "db2": db2,
       "dA1": dA1, "dZ1": dZ1, "dW1": dW1, "db1": db1}
   
return gradients

您在欺诈检测测试集中获得了一些结果,但您并不是100%确定您的模型。没有人是完美的!让我们实施梯度检验,以验证您的梯度是否正确。

梯度检验如何工作呢?

如1)和2)所示,您要将“gradapprox”与通过反向传播计算的梯度进行比较。公示依旧不变。

然而,θ就变成了一个字典parameters。我们运行函数"dictionary_to_vector()"。这个函数将字典转变成一个称为“value”的向量。这个函数是通过重组所有的元素(W1, b1, W2, b2, W3, b3)成为向量并连接他们。

反函数"vector_to_dictionary"是将输出返回为parameters字典。

5.jpg

1518026635299548.jpg

# GRADED FUNCTION: gradient_check_n
def gradient_check_n(parameters, 
gradients, X, Y, epsilon = 1e-7):
    """
    Checks if backward_propagation_n computes correctly
the gradient of the cost output by forward_propagation_n
    Arguments:
    parameters -- python dictionary containing your 
parameters "W1", "b1", "W2", "b2", "W3", "b3":
    grad -- output of backward_propagation_n, contains 
gradients of the cost with respect to the parameters. 
    x -- input datapoint, of shape (input size, 1)
    y -- true "label"
    epsilon -- tiny shift to the input to compute 
approximated gradient with formula(1)
    Returns:
    difference -- difference (2) between the approximated 
gradient and the backward propagation gradient
    """
    # Set-up variables
    parameters_values, _ = dictionary_to_vector(parameters)
    #print("parameters_values:", parameters_values)
    grad = gradients_to_vector(gradients)
    #print("grad:", grad)
    num_parameters = parameters_values.shape[0]
    J_plus = np.zeros((num_parameters, 1))
    J_minus = np.zeros((num_parameters, 1))
    gradapprox = np.zeros((num_parameters, 1))
    # Compute gradapprox
    for i in range(num_parameters):
        
        # Compute J_plus[i]. Inputs: "parameters_values, epsilon". 
#Output = "J_plus[i]".
        # "_" is used because the function you have to outputs two 
#parameters but we only care about the first one
        ### START CODE HERE ### (approx. 3 lines)
        thetaplus = np.copy(parameters_values)# Step 1
        thetaplus[i][0] = thetaplus[i][0] + epsilon# Step 2
        J_plus[i], _ = forward_propagation_n
(X, Y, vector_to_dictionary(thetaplus))     # Step 3
        ### END CODE HERE ###
        # Compute J_minus[i]. Inputs: "parameters_values, epsilon". 
        #Output = "J_minus[i]".
        ### START CODE HERE ### (approx. 3 lines)
        thetaminus = np.copy(parameters_values) 
        thetaminus[i][0] = thetaminus[i][0] - epsilon       
        J_minus[i], _ = forward_propagation_n
(X, Y, vector_to_dictionary(thetaminus))  
        ### END CODE HERE ### 
        # Compute gradapprox[i]
        ### START CODE HERE ### (approx. 1 line)
        gradapprox[i] = (J_plus[i] - J_minus[i]) / (2 * epsilon)
        ### END CODE HERE ###
    # Compare gradapprox to backward propagation gradients by 
#computing difference.
    ### START CODE HERE ### (approx. 1 line)
    numerator = np.linalg.norm(grad - gradapprox) 
    denominator = np.linalg.norm(grad) + np.linalg.norm(gradapprox) 
    difference = numerator / denominator 
    ### END CODE HERE ###
 
    if difference > 1e-7:
        print ("\033[93m" + "There is a mistake in the 
backward propagation! difference = " + str(difference) + "\033[0m")
    else:
        print ("\033[92m" + "Your backward propagation works
 perfectly fine! difference = " + str(difference) + "\033[0m")
    
    return difference

测试一下:

X, Y, parameters = gradient_check_n_test_case()
 
cost, cache = forward_propagation_n(X, Y, parameters)
gradients = backward_propagation_n(X, Y, cache)
difference = gradient_check_n(parameters, gradients, X, Y)

 

结果是:

There is a mistake in the backward propagation! difference = 1.18904178788e-07

看来我们给你的backward_propagation_n代码有错误! 很好,你已经实施了梯度检验。 返回到backward_propagation并尝试查找/更正错误(提示:检查dW2和db1)。 当你认为你已经修复了,重新运行渐变检查。 请记住,如果修改代码,则需要重新执行定义backward_propagation_n()的单元格。

 

你能得到梯度检验来声明你的派生计算是正确的吗? 即使这部分任务没有分级,但我们强烈建议您尝试查找错误并重新运行梯度检验,直到您确信backprop现在已正确实施。

 

牢记:

梯度检验验证反向传播梯度与梯度的数值近似(使用正向传播计算)之间的接近程度。

梯度检验很慢,所以我们不会在每次迭代训练中运行它。 你通常会运行它,只是为了确保你的代码是正确的,然后把它关闭,并使用backprop实际的学习过程。


本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 人工智能 神经网络
最后更新:2018年2月7日

davidcheung

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

搜索
欢迎关注我的个人公众号
最新 热点 随机
最新 热点 随机
DEEPFILTERNET:一种基于深度滤波的全频带音频低复杂度语音增强框架 奥地利匈牙利九日游旅程 论文阅读之Study of the General Kalman Filter for Echo Cancellation 小奥看房之鸿荣源珈誉府 杭州往返旅途及西溪喜来登和万怡的体验报告 2022年的第一篇碎碎念
奥地利匈牙利九日游旅程小奥看房之鸿荣源珈誉府论文阅读之Study of the General Kalman Filter for Echo CancellationDEEPFILTERNET:一种基于深度滤波的全频带音频低复杂度语音增强框架
2016年8月1日反思记录表 这几天很忙,很忙,很忙! 每日一感0814:杯具,我“被”送红裤头了 Python chapter 11 learning notes 下学期微机课的第一篇日志 Welcome to Beijing!
标签聚合
算法 linux 鸟哥的linux私房菜 生活 Java leetcode 高中 Python python学习 学习
最近评论
davidcheung 发布于 5 个月前(02月09日) The problem has been fixed. May I ask if you can s...
tk88 发布于 5 个月前(02月07日) Hmm is anyone else having problems with the pictur...
cuicui 发布于 8 个月前(10月20日) :wink:
niming 发布于 9 个月前(09月19日) 同级校友,能刷到太巧了
davidcheung 发布于 2 年前(08月16日) 我得找一下我之前整理的word文档看一下,如果找到了我就更新一下这篇文章。
Nolan 发布于 2 年前(07月25日) 您的笔记非常有帮助。贴图不显示了,可以更新一下吗?
davidcheung 发布于 3 年前(06月19日) 到没有看webrtc的代码。现在主要在看我们公司的代码了。。。只是偶尔看一看webrtc的东西。。。
aobai 发布于 3 年前(03月13日) gain_change_hangover_ 应该是每三个block 只能够调整一次,这样保证每帧...
匿名 发布于 5 年前(12月30日) 烫
小奥 发布于 5 年前(12月12日) webRTC里面的NS本身我记得就是在C++里面呀

COPYRIGHT © 2025 小奥的学习笔记. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

陕ICP备19003234号-1

鲁公网安备37120202000100号