神经网络-深度神经网络

在这里插入图片描述
python代码如下,使用该深度网络运行单神经网络使用的判断有无猫的数据集集,训练集准确率达到98.08%,测试集准确率达到82%,测试集准确率比单神经网络高12%,比浅层神经网络高6%。成本曲线图如下图所示:
在这里插入图片描述

 该函数用于初始化所有层的参数w和b
import numpy as np

def initialize_parameters_deep(layer_dims):
    """
    参数:
    layer_dims -- 这个list列表里面,包含了每层的神经元个数。
    例如,layer_dims=[5,4,3],表示第一层有5个神经元,第二层有4个,最后一层有3个神经元
    
    返回值:
    parameters -- 这个字典里面包含了每层对应的已经初始化了的W和b。
    例如,parameters['W1']装载了第一层的w,parameters['b1']装载了第一层的b
    """
    np.random.seed(1)
    parameters = {}
    L = len(layer_dims) # 获取神经网络总共有几层

    # 遍历每一层,为每一层的W和b进行初始化
    for l in range(1, L):
        # 构建并随机初始化该层的W。
        parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l - 1]) / np.sqrt(layer_dims[l-1])
        # 构建并初始化b
        parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))
        
        # 核对一下W和b的维度是预期的维度
        assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l - 1]))
        assert(parameters['b' + str(l)].shape == (layer_dims[l], 1))
     
    return parameters
def sigmoid(Z):
    """
    Implements the sigmoid activation in numpy
    """
    
    A = 1/(1+np.exp(-Z))
    
    return A
def relu(Z):
    """
    Implement the RELU function.
    """
    
    A = np.maximum(0,Z)
    
    assert(A.shape == Z.shape)
    return A
def relu_backward(dA, cache):
    """
    Implement the backward propagation for a single RELU unit.
    """
    
    Z = cache
    dZ = np.array(dA, copy=True) # just converting dz to a correct object.
    
    # When z <= 0, you should set dz to 0 as well. 
    dZ[Z <= 0] = 0
    
    assert (dZ.shape == Z.shape)
    
    return dZ
def sigmoid_backward(dA, cache):
    """
    Implement the backward propagation for a single SIGMOID unit.
    
    """
    
    Z = cache
    
    s = 1/(1+np.exp(-Z))
    dZ = dA * s * (1-s)
    
    assert (dZ.shape == Z.shape)
    
    return dZ
#单层前向传播
def linear_forward(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
#单层前向传播
def linear_activation_forward(A_prev, W, b, activation):
    """
    Arguments:
    A_prev -- 上一层得到的A,输入到本层来计算Z和本层的A。第一层时A_prev就是特征输入X
    W -- 本层相关的W
    b -- 本层相关的b
    activation -- 两个字符串,"sigmoid"或"relu",指示该层应该使用哪种激活函数
    """
    
    Z, linear_cache = linear_forward(A_prev, W, b)
    
    if activation == "sigmoid": # 如果该层使用sigmoid        
        A = sigmoid(Z) 
    elif activation == "relu":
        A = relu(Z)
        
    assert (A.shape == (W.shape[0], A_prev.shape[1]))
    cache = (linear_cache, Z) 

    return A, cache
# 这个函数构建了一个完整的前向传播过程。这个前向传播一共有L层,前面的L-1层用的激活函数是relu,最后一层使用sigmoid。
def L_model_forward(X, parameters):
    """
    参数:
    X -- 输入的特征数据
    parameters -- 这个list列表里面包含了每一层的参数w和b
    """

    caches = []
    A = X
    
    # 获取参数列表的长度,这个长度的一半就是神经网络的层数。
    L = len(parameters) // 2  
    
    # 循环L-1次,即进行L-1步前向传播,每一步使用的激活函数都是relu
    for l in range(1, L):
        A_prev = A 
        A, cache = linear_activation_forward(A_prev,
                                             parameters['W' + str(l)], 
                                             parameters['b' + str(l)],
                                             activation='relu')
        caches.append(cache)# 把一些变量数据保存起来,以便后面的反向传播使用
        
    
    # 进行最后一层的前向传播,这一层的激活函数是sigmoid。得出的AL就是y'预测值
    AL, cache = linear_activation_forward(A, 
                                          parameters['W' + str(L)], 
                                          parameters['b' + str(L)], 
                                          activation='sigmoid')
    caches.append(cache)
   
    assert(AL.shape == (1, X.shape[1]))
            
    return AL, caches
# 这个函数用于计算成本(单个样本时是损失,多个样本时是成本)。
def compute_cost(AL, Y):
       
    m = Y.shape[1]
    cost = (-1 / m) * np.sum(np.multiply(Y, np.log(AL)) + np.multiply(1 - Y, np.log(1 - AL)))
    
    cost = np.squeeze(cost)# 确保cost是一个数值而不是一个数组的形式
    assert(cost.shape == ())
    
    return cost
def linear_backward(dZ, cache):
    """
    反向传播参数:
    dZ -- 后面一层的dZ
    cache -- 前向传播时我们保存下来的关于本层的一些变量
    """
    A_prev, W, b = cache
    m = A_prev.shape[1]

    dW = np.dot(dZ, cache[0].T) / m
    db = np.sum(dZ, axis=1, keepdims=True) / m
    dA_prev = np.dot(cache[1].T, dZ)
    
    assert (dA_prev.shape == A_prev.shape)
    assert (dW.shape == W.shape)
    assert (db.shape == b.shape)
    
    return dA_prev, dW, db
def linear_activation_backward(dA, cache, activation):
    """
    参数:
    dA -- 本层的dA 
    cache -- 前向传播时保存的本层的相关变量
    activation -- 指示该层使用的是什么激活函数: "sigmoid" 或 "relu"
    """
    linear_cache, activation_cache = cache
    
    if activation == "relu":
        dZ = relu_backward(dA, activation_cache)        
    elif activation == "sigmoid":
        dZ = sigmoid_backward(dA, activation_cache)
    
    # 根据本层的dZ算出本层的dW和db以及前一层的dA
    dA_prev, dW, db = linear_backward(dZ, linear_cache)
    
    return dA_prev, dW, db
# 构建出整个反向传播。
def L_model_backward(AL, Y, caches):
    """
    参数:
    AL -- 最后一层的A,也就是y',预测出的标签
    Y -- 真实标签
    caches -- 前向传播时保存的每一层的相关变量,用于辅助计算反向传播
    """
    grads = {}
    L = len(caches) # 获取神经网络层数。caches列表的长度就等于神经网络的层数
    Y = Y.reshape(AL.shape) # 让真实标签的维度和预测标签的维度一致
    
    # 计算出最后一层的dA
    dAL = - (np.divide(Y, AL) - np.divide(1 - Y, 1 - AL))
    
    # 计算最后一层的dW和db,因为最后一层使用的激活函数是sigmoid
    current_cache = caches[-1]
    grads["dA" + str(L-1)], grads["dW" + str(L)], grads["db" + str(L)] = linear_activation_backward(
                                                                                            dAL, 
                                                                                            current_cache,
                                                                                            activation = "sigmoid")

    # 计算前面L-1层到第一层的每层的梯度,这些层都使用relu激活函数
    for c in reversed(range(1,L)): # reversed(range(1,L))的结果是L-1,L-2...1。是不包括L的。第0层是输入层,不必计算。
        # 这里的c表示当前层
        grads["dA" + str(c-1)], grads["dW" + str(c)], grads["db" + str(c)] = linear_activation_backward(
            grads["dA" + str(c)], 
            caches[c-1],
            activation = "relu")

    return grads
def update_parameters(parameters, grads, learning_rate):
    """
    Arguments:
    parameters -- 每一层的参数w和b 
    grads -- 每一层的梯度
    learning_rate -- 是学习率,学习步进
    """
    
    L = len(parameters) // 2 # 获取层数。//除法可以得到整数

    for l in range(1,L+1):
        parameters["W" + str(l)] = parameters["W" + str(l)] - learning_rate * grads["dW" + str(l)]
        parameters["b" + str(l)] = parameters["b" + str(l)] - learning_rate * grads["db" + str(l)]
        
    return parameters
# 利用上面的工具函数构建一个深度神经网络训练模型
def dnn_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False): 
    """    
    参数:
    X -- 数据集
    Y -- 数据集标签
    layers_dims -- 指示该深度神经网络用多少层,每层有多少个神经元
    learning_rate -- 学习率
    num_iterations -- 指示需要训练多少次
    print_cost -- 指示是否需要在将训练过程中的成本信息打印出来,好知道训练的进度好坏。
    
    返回值:
    parameters -- 返回训练好的参数。以后就可以用这些参数来识别新的陌生的图片
    """

    np.random.seed(1)
    costs = []                  

    # 初始化每层的参数w和b
    parameters = initialize_parameters_deep(layers_dims)
    
    # 按照指示的次数来训练深度神经网络
    for i in range(0, num_iterations):
        # 进行前向传播
        AL, caches = L_model_forward(X, parameters)
        # 计算成本
        cost = compute_cost(AL, Y)
        # 进行反向传播
        grads = L_model_backward(AL, Y, caches)
        # 更新参数,好用这些参数进行下一轮的前向传播
        parameters = update_parameters(parameters, grads, learning_rate)

        # 打印出成本
        if i % 100 == 0:
            if print_cost and i > 0:
                print ("训练%i次后成本是: %f" % (i, cost))
            costs.append(cost)
            
    # 画出成本曲线图
    plt.plot(np.squeeze(costs))
    plt.ylabel('cost')
    plt.xlabel('iterations (per tens)')
    plt.title("Learning rate =" + str(learning_rate))
    plt.show()
    
    return parameters
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值