Couresra-吴恩达-深度学习-第一章:Neural Network and Deep Learning- 第四周

本博客详细介绍了Coursera吴恩达深度学习课程的第一章内容,重点讲解了深度L-layer神经网络的前向传播、反向传播以及参数更新。通过两个任务——逐步建立神经网络和应用深度神经网络,帮助理解神经网络的结构和实现过程。
摘要由CSDN通过智能技术生成

本周学习内容

  1. Key Concepts on Deep Neural Network
    • Deep L-layer neural network (深层神经网络)
    • Forward Propagation in a Deep Network (前向算法)
    • Getting your matrix dimensions right (核对矩阵的维数)
    • Why deep representations (为什么用深层表示)
    • Building blocks of deep neural networks (搭建深层神经网络)
    • Forward and Backward Propagation (前向和后向算法)
    • Parameters vs Hyperparameters (参数 vs 超参数)
    • What does this have to do with brain (这和大脑有什么关系)

测验

本周题目都比较简单,主要考察参数的维度:
W [ l ] : ( n [ l ] , n [ l − 1 ] ) W^{[l]} : (n^{[l]},n^{[l-1]}) W[l]:(n[l],n[l1])
b [ l ] : ( n [ l ] , 1 ) b^{[l]} : (n^{[l]},1) b[l]:(n[l],1)

代码练习

任务1:Building your Deep Neural Network: Step by Step

目标

  1. Develop an intuition of the over all structure of a neural network.
  2. Write functions (e.g. forward propagation, backward propagation, logistic loss, etc…) that would help you decompose your code and ease the process of building a neural network.
  3. Initialize/update parameters according to your desired structure.

大纲(Outline of the Assignment)

我们将构建两个神经网络,一个是两层的,一个是多层的。必须的步骤有:

  • 初始化参数
  • 前向传播(图中紫色部分)
    • LINEAR part - 生成 Z [ l [ Z^{[l[} Z[l[ Z = np.dot(W,A) + b
    • LINEAR > ACTIVATION forward function
      • LINEAR > ReLU (L-1层) A = relu(Z)
      • LINEAR > Sigmoid(最后一层L) A = sigmoid(Z)
  • 计算损失函数
  • 反向传播 (图中红色部分)
    • 线性部分的反向传播
    • 激活函数部分的反向传播
    • 结合线性部分与激活函数的反向传播公式
  • 更新参数
  • 在这里插入图片描述

1. 初始化参数(Initialization)

两层的:

def initialize_parameters(n_x,n_h,n_y):
    """
    此函数是为了初始化两层网络参数而使用的函数。
    参数:
        n_x - 输入层节点数量
        n_h - 隐藏层节点数量
        n_y - 输出层节点数量
    
    返回:
        parameters - 包含你的参数的python字典:
            W1 - 权重矩阵,维度为(n_h,n_x)
            b1 - 偏向量,维度为(n_h,1)
            W2 - 权重矩阵,维度为(n_y,n_h)
            b2 - 偏向量,维度为(n_y,1)

    """
    W1 = np.random.randn(n_h, n_x) * 0.01
    b1 = np.zeros((n_h, 1))
    W2 = np.random.randn(n_y, n_h) * 0.01
    b2 = np.zeros((n_y, 1))
    
    #使用断言确保我的数据格式是正确的
    assert(W1.shape == (n_h, n_x))
    assert(b1.shape == (n_h, 1))
    assert(W2.shape == (n_y, n_h))
    assert(b2.shape == (n_y, 1))
    
    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}
    
    return parameters  

L层的参数初始化稍复杂,另外涉及到一点broadcasting,但只要记住 w , b w,b w,b的维度即可
在这里插入图片描述

def initialize_parameters_deep(layers_dims):
    """
    此函数是为了初始化多层网络参数而使用的函数。
    参数:
        layers_dims - 包含我们网络中每个图层的节点数量的列表
    
    返回:
        parameters - 包含参数“W1”,“b1”,...,“WL”,“bL”的字典:
                     W1 - 权重矩阵,维度为(layers_dims [1],layers_dims [1-1])
                     bl - 偏向量,维度为(layers_dims [1],1)
    """
    np.random.seed(3)
    parameters = {}
    L = len(layers_dims)
    
    for l in range(1,L):
	    parameters["W" + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) / np.sqrt(layers_dims[l - 1])
        parameters["b" + str(l)] = np.zeros((layers_dims[l], 1))
        
        #确保我要的数据的格式是正确的
        assert(parameters["W" + str(l)].shape == (layers_dims[l], layers_dims[l-1]))
        assert(parameters["b" + str(l)].shape == (layers_dims[l], 1))
        
    return parameters


2.前向传播

线性(Linear)
def linear_forward(A,W,b):
    """
    实现前向传播的线性部分。

    参数:
        A - 来自上一层(或输入数据)的激活,维度为(上一层的节点数量,示例的数量)
        W - 权重矩阵,numpy数组,维度为(当前图层的节点数量,前一图层的节点数量)
        b - 偏向量,numpy向量,维度为(当前图层节点数量,1)

    返回:
         Z - 激活功能的输入,也称为预激活参数
         cache - 一个包含“A”,“W”和“b”的字典,存储这些变量以有效地计算后向传递
    """
    Z = np.dot(W,A) + b
    assert(Z.shape == (W.shape[0],A.shape[1]))
    cache = (A,W,b)
     
    return Z,cache

线性激活(Linear-Activation)
def linear_activation_forward(A_prev,W,b,activation):
    """
    实现LINEAR-> ACTIVATION 这一层的前向传播

    参数:
        A_prev - 来自上一层(或输入层)的激活,维度为(上一层的节点数量,示例数)
        W - 权重矩阵,numpy数组,维度为(当前层的节点数量,前一层的大小)
        b - 偏向量,numpy阵列,维度为(当前层的节点数量,1)
        activation - 选择在此层中使用的激活函数名,字符串类型,【"sigmoid" | "relu"】

    返回:
        A - 激活函数的输出,也称为激活后的值
        cache - 一个包含“linear_cache”和“activation_cache”的字典,我们需要存储它以有效地计算后向传递
    """
    
    if activation == "sigmoid":
        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = sigmoid(Z)
    elif activation == "relu":
        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = relu(Z)
    
    assert(A.shape == (W.shape[0],A_prev.shape[1]))
    cache = (linear_cache,activation_cache)
    
    return A,cache

我们把两层模型需要的前向传播函数做完了,那多层模型的呢?
我们调用上面的两个函数实现它,为了在实现L层神经网络时更加方便,我们需要一个函数来复制前一个函数(带有RELU的linear-activation_forward)L-1次,最后用一个sigmoid函数。
在这里插入图片描述

def L_model_forward(X,parameters):
    """
    实现[LINEAR-> RELU] *(L-1) - > LINEAR-> SIGMOID计算前向传播,也就是多层网络的前向传播,为后面每一层都执行LINEAR和ACTIVATION
    
    参数:
        X - 数据,numpy数组,维度为(输入节点数量,示例数)
        parameters - initialize_parameters_deep()的输出
    
    返回:
        AL - 最后的激活值
        caches - 包含以下内容的缓存列表:
                 linear_relu_forward()的每个cache(有L-1个,索引为从0到L-2)
                 linear_sigmoid_forward()的cache(只有一个,索引为L-1)
    """
    caches = []
    A = X
    L = len(parameters) // 2
    for l in range(1,L):
        A_prev = A 
        A, cache = linear_activation_forward(A_prev, parameters['W' + str(l)], parameters['b' + str(l)], "relu")
        caches.append(cache)
    
    AL, cache = linear_activation_forward(A, parameters['W' + str(L)], parameters['b' + str(L)], "sigmoid")
    caches.append(cache)
    
    assert(AL.shape == (1,X.shape[1]))
    
    return AL,caches


3.计算损失函数

def compute_cost(AL,Y):
    """
    实施等式(4)定义的成本函数。

    参数:
        AL - 与标签预测相对应的概率向量,维度为(1,示例数量)
        Y - 标签向量(例如:如果不是猫,则为0,如果是猫则为1),维度为(1,数量)

    返回:
        cost - 交叉熵成本
    """
    m = Y.shape[1]
    cost = -np.sum(np.multiply(np.log(AL),Y) + np.multiply(np.log(1 - AL), 1 - Y)) / m
        
    cost = np.squeeze(cost)
    assert(cost.shape == ())

    return cost


4.后向传播

需要使用 d Z [ l ] dZ^{[l]} dZ[l]来计算三个输出 d W [ l ] dW^{[l]} dW[l] d b [ l ] db^{[l]} db[l] d A [ l ] dA^{[l]} dA[l], 需要用到以下三个公式:

d W [ l ] = ∂ L ∂ W [ l ] = 1 m d Z [ l ] A [ l − 1 ] T d W^{[l]}=\frac{\partial \mathcal{L}}{\partial W^{[l]}}=\frac{1}{m} d Z^{[l]} A^{[l-1] T} dW[l]=W[l]L=m1dZ[l]A[l1]T

d b [ l ] = ∂ L ∂ b [ l ] = 1 m ∑ i = 1 m d Z [ l ] ( i ) d b^{[l]}=\frac{\partial \mathcal{L}}{\partial b^{[l]}}=\frac{1}{m} \sum_{i=1}^{m} d Z^{[l](i)} db[l]=b[l]L=m1i=1mdZ[l](i)

d A [ l − 1 ] = ∂ L ∂ A [ l − 1 ] = W [ l ] T d Z [ l ] d A^{[l-1]}=\frac{\partial \mathcal{L}}{\partial A^{[l-1]}}=W^{[l] T} d Z^{[l]} dA[l1]=A[l1]L=W[l]TdZ[l]

线性部分
def linear_backward(dZ,cache):
    """
    为单层实现反向传播的线性部分(第L层)

    参数:
         dZ - 相对于(当前第l层的)线性输出的成本梯度
         cache - 来自当前层前向传播的值的元组(A_prev,W,b)

    返回:
         dA_prev - 相对于激活(前一层l-1)的成本梯度,与A_prev维度相同
         dW - 相对于W(当前层l)的成本梯度,与W的维度相同
         db - 相对于b(当前层l)的成本梯度,与b维度相同
    """
    A_prev, W, b = cache
    m = A_prev.shape[1]
    dW = np.dot(dZ, A_prev.T) / m
    db = np.sum(dZ, axis=1, keepdims=True) / m
    dA_prev = np.dot(W.T, dZ)
    
    assert (dA_prev.shape == A_prev.shape)
    assert (dW.shape == W.shape)
    assert (db.shape == b.shape)
    
    return dA_prev, dW, db


线性激活部分(Linear-Activation backward)

此部分需要两个函数sigmoid_backwardrelu_backward

def linear_activation_backward(dA,cache,activation="relu"):
    """
    实现LINEAR-> ACTIVATION层的后向传播。
    
    参数:
         dA - 当前层l的激活后的梯度值
         cache - 我们存储的用于有效计算反向传播的值的元组(值为linear_cache,activation_cache)
         activation - 要在此层中使用的激活函数名,字符串类型,【"sigmoid" | "relu"】
    返回:
         dA_prev - 相对于激活(前一层l-1)的成本梯度值,与A_prev维度相同
         dW - 相对于W(当前层l)的成本梯度值,与W的维度相同
         db - 相对于b(当前层l)的成本梯度值,与b的维度相同
    """
    linear_cache, activation_cache = cache
    if activation == "relu":
        dZ = relu_backward(dA, activation_cache)
        dA_prev, dW, db = linear_backward(dZ, linear_cache)
    elif activation == "sigmoid":
        dZ = sigmoid_backward(dA, activation_cache)
        dA_prev, dW, db = linear_backward(dZ, linear_cache)
    
    return dA_prev,dW,db

5.更新参数

参数更新公式:

W [ l ] = W [ l ] − α d W [ l ] W^{[l]}=W^{[l]}-\alpha d W^{[l]} W[l]=W[l]αdW[l]
b [ l ] = b [ l ] − α d b [ l ] b^{[l]}=b^{[l]}-\alpha d b^{[l]} b[l]=b[l]αdb[l]

def update_parameters(parameters, grads, learning_rate):
    """
    使用梯度下降更新参数
    
    参数:
     parameters - 包含你的参数的字典
     grads - 包含梯度值的字典,是L_model_backward的输出
    
    返回:
     parameters - 包含更新参数的字典
                   参数[“W”+ str(l)] = ...
                   参数[“b”+ str(l)] = ...
    """
    L = len(parameters) // 2 #整除
    for l in range(L):
        parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - learning_rate * grads["dW" + str(l + 1)]
        parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - learning_rate * grads["db" + str(l + 1)]
        
    return parameters

至此为止,我们已经定义了神经网络所需要的函数,接下来的作业当中将使用这些函数来构成一个神经网络。


任务2:Deep Neural Network - Application

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值