zoukankan      html  css  js  c++  java
  • 吴恩达老师深度学习课程第三周编程作业--带有一个隐藏层的平面数据分类

    本博客是吴恩达老师深度学习课程第三周编程作业,参考博客https://blog.csdn.net/u013733326/article/details/79702148完成。

    此次编程作业要求建立一个简单的神经网络,包括一个隐藏层。功能是实现平面数据分类。

    1、准备工作

    首先是准备项目需要用到的软件包:

    • numpy:是用Python进行科学计算的基本软件包。
    • sklearn:为数据挖掘和数据分析提供的简单高效的工具。
    • matplotlib :是一个用于在Python中绘制图表的库。
    • testCases:提供了一些测试示例来评估函数的正确性,参见下载的资料或者在底部查看它的代码。
    • planar_utils :提供了在这个任务中使用的各种有用的功能,参见下载的资料或者在底部查看它的代码。
    import numpy as np
    import matplotlib.pyplot as plt
    from testCases import *
    import sklearn
    import sklearn.datasets
    import sklearn.linear_model
    from planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset, load_extra_datasets
    
    
    np.random.seed(1) #设置一个固定的随机种子,以保证接下来的步骤中我们的结果是一致的。

    planar_utils和testCases的代码在博客最后有,这两个代码是原博主给出的。

    2、加载数据

    主程序中首先把数据加载到变量X和Y中,我们可以把数据集绘制出来,利用matpotlib可视化数据集:

    plt.scatter(X[0, :], X[1, :], c=Y, s=40, cmap=plt.cm.Spectral) #绘制散点图
    plt.show()
    

    数据看起来是一朵花,由红色(y=0)和蓝色(y=1)的数据点组成的花朵的图案。此次项目的任务也是建立一个模型来适应这些数据,并把平面区域划分成两类。我们现在拥有的东西如下:

    • X:一个numpy的矩阵,包含了这些数据点的数值
    • Y:一个numpy的向量,对应着的是X的标签【0 | 1】(红色:0 , 蓝色 :1)

    我们观察变量的格式:

    shape_X = X.shape
    shape_Y = Y.shape
    m = Y.shape[1]  # 训练集里面的数量
    print ("X的维度为: " + str(shape_X))
    print ("Y的维度为: " + str(shape_Y))
    print ("数据集里面的数据有:" + str(m) + " 个")
    

    3、搭建神经网络

    我们要搭建的神经网络模型如下:

    理论基础

    计算成本的方法:

    构建神经网络的方法:

    1、定义网络结构

    2、初始化模型参数

    3、执行循环:a.前向传播计算A和Z。  b.计算损失函数。  c.后向传播计算导数。  d.梯度下降更新参数。

    我们要它们合并到一个nn_model() 函数中,当我们构建好了nn_model()并学习了正确的参数,我们就可以预测新的数据。

    4、定义网络结构

    def layer_sizes(X , Y):
        """
        参数:
         X - 输入数据集,维度为(输入的数量,训练/测试的数量)
         Y - 标签,维度为(输出的数量,训练/测试数量)
    
        返回:
         n_x - 输入层的数量
         n_h - 隐藏层的数量
         n_y - 输出层的数量
        """
    
        n_x = X.shape[0]  # 输入层shape_X
        n_h = 4 #,隐藏层,硬编码为4
        n_y = Y.shape[0] #输出层
    
        return (n_x,n_h,n_y)
    

    在此神经网络中,n_x是2,因为数据集中有两个特征,分别是两个坐标值,n_h是隐藏层,本次设定为4,n_y是2,表示红蓝两色的值。

    5、初始化参数

    def initialize_parameters(n_x, n_h, n_y):
        """
        参数:
            n_x - 输入层节点的数量
            n_h - 隐藏层节点的数量
            n_y - 输出层节点的数量
    
        返回:
            parameters - 包含参数的字典:
                W1 - 权重矩阵,维度为(n_h,n_x)
                b1 - 偏向量,维度为(n_h,1)
                W2 - 权重矩阵,维度为(n_y,n_h)
                b2 - 偏向量,维度为(n_y,1)
    
        """
    
        np.random.seed(2)  # 指定一个随机种子,以便你的输出与我们的一样。
        W1 = np.random.randn(n_h, n_x) * 0.01
        b1 = np.zeros(shape=(n_h, 1))
        W2 = np.random.randn(n_y, n_h) * 0.01
        b2 = np.zeros(shape=(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
    

    6、前向传播

    步骤如下:

    • 使用字典类型的parameters(它是initialize_parameters() 的输出)检索每个参数。
    • 实现向前传播, 计算Z[1],A[1],Z[2]Z^{[1]}, A^{[1]}, Z^{[2]}Z[1],A[1],Z[2] 和 A[2]A^{[2]}A[2]( 训练集里面所有例子的预测向量)。
    • 反向传播所需的值存储在“cache”中,cache将作为反向传播函数的输入。
    def forward_propagation(X, parameters):
        """
        参数:
             X - 维度为(n_x,m)的输入数据。
             parameters - 初始化函数(initialize_parameters)的输出
    
        返回:
             A2 - 使用sigmoid()函数计算的第二次激活后的数值
             cache - 包含“Z1”,“A1”,“Z2”和“A2”的字典类型变量
         """
        W1 = parameters["W1"]
        b1 = parameters["b1"]
        W2 = parameters["W2"]
        b2 = parameters["b2"]
        # 前向传播计算A2
        Z1 = np.dot(W1, X) + b1
        A1 = np.tanh(Z1)
        Z2 = np.dot(W2, A1) + b2
        A2 = sigmoid(Z2)
        # 使用断言确保我的数据格式是正确的
        assert (A2.shape == (1, X.shape[1]))
        cache = {"Z1": Z1,
                 "A1": A1,
                 "Z2": Z2,
                 "A2": A2}
    
        return (A2, cache)
    

    前向传播在计算时,第一层用的激活函数是tanh函数,第二层也就是输出层用的激活函数是sigmoid函数,因为分为是二分类,所以可以用该函数。

    7、计算损失

    def compute_cost(A2, Y, parameters):
        """
        计算方程(6)中给出的交叉熵成本,
    
        参数:
             A2 - 使用sigmoid()函数计算的第二次激活后的数值
             Y - "True"标签向量,维度为(1,数量)
             parameters - 一个包含W1,B1,W2和B2的字典类型的变量
    
        返回:
             成本 - 交叉熵成本给出方程(13)
        """
    
        m = Y.shape[1]
        W1 = parameters["W1"]
        W2 = parameters["W2"]
    
        # 计算成本
        logprobs = logprobs = np.multiply(np.log(A2), Y) + np.multiply((1 - Y), np.log(1 - A2))
        cost = - np.sum(logprobs) / m
        cost = float(np.squeeze(cost))
    
        assert (isinstance(cost, float))
    
        return cost
    

    8、反向传播

    反向传播时我们用到的六个方程如下:

    def backward_propagation(parameters, cache, X, Y):
        """
        使用上述说明搭建反向传播函数。
    
        参数:
         parameters - 包含我们的参数的一个字典类型的变量。
         cache - 包含“Z1”,“A1”,“Z2”和“A2”的字典类型的变量。
         X - 输入数据,维度为(2,数量)
         Y - “True”标签,维度为(1,数量)
    
        返回:
         grads - 包含W和b的导数一个字典类型的变量。
        """
        m = X.shape[1]
    
        W1 = parameters["W1"]
        W2 = parameters["W2"]
    
        A1 = cache["A1"]
        A2 = cache["A2"]
    
        dZ2 = A2 - Y
        dW2 = (1 / m) * np.dot(dZ2, A1.T)
        db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)
        dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.power(A1, 2))
        dW1 = (1 / m) * np.dot(dZ1, X.T)
        db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True)
        grads = {"dW1": dW1,
                 "db1": db1,
                 "dW2": dW2,
                 "db2": db2}
    
        return grads
    

    计算导数用到的公式上边都有。

    9、梯度下降更新参数

    def update_parameters(parameters, grads, learning_rate=1.2):
        """
        使用上面给出的梯度下降更新规则更新参数
    
        参数:
         parameters - 包含参数的字典类型的变量。
         grads - 包含导数值的字典类型的变量。
         learning_rate - 学习速率
    
        返回:
         parameters - 包含更新参数的字典类型的变量。
        """
        W1, W2 = parameters["W1"], parameters["W2"]
        b1, b2 = parameters["b1"], parameters["b2"]
    
        dW1, dW2 = grads["dW1"], grads["dW2"]
        db1, db2 = grads["db1"], grads["db2"]
    
        W1 = W1 - learning_rate * dW1
        b1 = b1 - learning_rate * db1
        W2 = W2 - learning_rate * dW2
        b2 = b2 - learning_rate * db2
    
        parameters = {"W1": W1,
                      "b1": b1,
                      "W2": W2,
                      "b2": b2}
    
        return parameters

    梯度下降算法的原理和步骤原来都学过,所以这里不讲了。

    10、整合

    最后,我们把这些函数正和在一起。

    def nn_model(X, Y, n_h, num_iterations, print_cost=False):
        """
        参数:
            X - 数据集,维度为(2,示例数)
            Y - 标签,维度为(1,示例数)
            n_h - 隐藏层的数量
            num_iterations - 梯度下降循环中的迭代次数
            print_cost - 如果为True,则每1000次迭代打印一次成本数值
    
        返回:
            parameters - 模型学习的参数,它们可以用来进行预测。
         """
    
        np.random.seed(3)  # 指定随机种子
        n_x = layer_sizes(X, Y)[0]
        n_y = layer_sizes(X, Y)[2]
    
        parameters = initialize_parameters(n_x, n_h, n_y)
        W1 = parameters["W1"]
        b1 = parameters["b1"]
        W2 = parameters["W2"]
        b2 = parameters["b2"]
    
        for i in range(num_iterations):
            A2, cache = forward_propagation(X, parameters)
            cost = compute_cost(A2, Y, parameters)
            grads = backward_propagation(parameters, cache, X, Y)
            parameters = update_parameters(parameters, grads, learning_rate=0.5)
    
            if print_cost:
                if i % 1000 == 0:
                    print("第 ", i, " 次循环,成本为:" + str(cost))
        return parameters
    

    整合代码执行流程:首先是利用加载好的数据集定义网络结构,并得出各层神经元个数。然后初始化模型参数,并把各层的参数存储到变量中以供使用。然后就是循环部分:先是利用前向循环计算A2的值和Z1、A1、Z2、A2并存储到变量中,然后利用A2,Y计算损失,然后利用反向传播算法计算导数,得出导数之后,再利用梯度下降算法更新参数,不断循环,最后得出合适的参数。

    11、预测

    参数得出之后,就可以利用参数预测。预测主要使用前向传播就可以。

    def predict(parameters, X):
        """
        使用学习的参数,为X中的每个示例预测一个类
    
        参数:
    		parameters - 包含参数的字典类型的变量。
    	    X - 输入数据(n_x,m)
    
        返回
    		predictions - 我们模型预测的向量(红色:0 /蓝色:1)
    
         """
        A2, cache = forward_propagation(X, parameters)
        predictions = np.round(A2)
    
        return predictions
    

    12、正式运行

     这样我们就做完了所有工作,接下来就是正式运行,首先是利用nn_model函数计算得出模型,然后再利用模型预测,之后利用python的绘制边界函数把平面划分成两类。这个绘制边界的函数我也不太懂。

    parameters = nn_model(X, Y, n_h = 4, num_iterations=10000, print_cost=True)
    #绘制边界
    plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
    plt.title("Decision Boundary for hidden layer size " + str(4))
    plt.show()
    predictions = predict(parameters, X)
    print ('准确率: %d' % float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%')

    这就是此次项目的所有细节,这是我第一次搭建简单的神经网络,总的来说,过程还是比较顺利,对于数学原理理解的还是不错,项目流程也都理解,只不过是对python代码不太熟悉,所以代码不是一个一个自己敲得。再次声明,本文参考博客https://blog.csdn.net/u013733326/article/details/79702148完成。

    testCases.py代码:
    import numpy as np
    
    def layer_sizes_test_case():
        np.random.seed(1)
        X_assess = np.random.randn(5, 3)
        Y_assess = np.random.randn(2, 3)
        return X_assess, Y_assess
    
    def initialize_parameters_test_case():
        n_x, n_h, n_y = 2, 4, 1
        return n_x, n_h, n_y
    
    def forward_propagation_test_case():
        np.random.seed(1)
        X_assess = np.random.randn(2, 3)
    
        parameters = {'W1': np.array([[-0.00416758, -0.00056267],
            [-0.02136196,  0.01640271],
            [-0.01793436, -0.00841747],
            [ 0.00502881, -0.01245288]]),
         'W2': np.array([[-0.01057952, -0.00909008,  0.00551454,  0.02292208]]),
         'b1': np.array([[ 0.],
            [ 0.],
            [ 0.],
            [ 0.]]),
         'b2': np.array([[ 0.]])}
    
        return X_assess, parameters
    
    def compute_cost_test_case():
        np.random.seed(1)
        Y_assess = np.random.randn(1, 3)
        parameters = {'W1': np.array([[-0.00416758, -0.00056267],
            [-0.02136196,  0.01640271],
            [-0.01793436, -0.00841747],
            [ 0.00502881, -0.01245288]]),
         'W2': np.array([[-0.01057952, -0.00909008,  0.00551454,  0.02292208]]),
         'b1': np.array([[ 0.],
            [ 0.],
            [ 0.],
            [ 0.]]),
         'b2': np.array([[ 0.]])}
    
        a2 = (np.array([[ 0.5002307 ,  0.49985831,  0.50023963]]))
    
        return a2, Y_assess, parameters
    
    def backward_propagation_test_case():
        np.random.seed(1)
        X_assess = np.random.randn(2, 3)
        Y_assess = np.random.randn(1, 3)
        parameters = {'W1': np.array([[-0.00416758, -0.00056267],
            [-0.02136196,  0.01640271],
            [-0.01793436, -0.00841747],
            [ 0.00502881, -0.01245288]]),
         'W2': np.array([[-0.01057952, -0.00909008,  0.00551454,  0.02292208]]),
         'b1': np.array([[ 0.],
            [ 0.],
            [ 0.],
            [ 0.]]),
         'b2': np.array([[ 0.]])}
    
        cache = {'A1': np.array([[-0.00616578,  0.0020626 ,  0.00349619],
             [-0.05225116,  0.02725659, -0.02646251],
             [-0.02009721,  0.0036869 ,  0.02883756],
             [ 0.02152675, -0.01385234,  0.02599885]]),
      'A2': np.array([[ 0.5002307 ,  0.49985831,  0.50023963]]),
      'Z1': np.array([[-0.00616586,  0.0020626 ,  0.0034962 ],
             [-0.05229879,  0.02726335, -0.02646869],
             [-0.02009991,  0.00368692,  0.02884556],
             [ 0.02153007, -0.01385322,  0.02600471]]),
      'Z2': np.array([[ 0.00092281, -0.00056678,  0.00095853]])}
        return parameters, cache, X_assess, Y_assess
    
    def update_parameters_test_case():
        parameters = {'W1': np.array([[-0.00615039,  0.0169021 ],
            [-0.02311792,  0.03137121],
            [-0.0169217 , -0.01752545],
            [ 0.00935436, -0.05018221]]),
     'W2': np.array([[-0.0104319 , -0.04019007,  0.01607211,  0.04440255]]),
     'b1': np.array([[ -8.97523455e-07],
            [  8.15562092e-06],
            [  6.04810633e-07],
            [ -2.54560700e-06]]),
     'b2': np.array([[  9.14954378e-05]])}
    
        grads = {'dW1': np.array([[ 0.00023322, -0.00205423],
            [ 0.00082222, -0.00700776],
            [-0.00031831,  0.0028636 ],
            [-0.00092857,  0.00809933]]),
     'dW2': np.array([[ -1.75740039e-05,   3.70231337e-03,  -1.25683095e-03,
              -2.55715317e-03]]),
     'db1': np.array([[  1.05570087e-07],
            [ -3.81814487e-06],
            [ -1.90155145e-07],
            [  5.46467802e-07]]),
     'db2': np.array([[ -1.08923140e-05]])}
        return parameters, grads
    
    def nn_model_test_case():
        np.random.seed(1)
        X_assess = np.random.randn(2, 3)
        Y_assess = np.random.randn(1, 3)
        return X_assess, Y_assess
    
    def predict_test_case():
        np.random.seed(1)
        X_assess = np.random.randn(2, 3)
        parameters = {'W1': np.array([[-0.00615039,  0.0169021 ],
            [-0.02311792,  0.03137121],
            [-0.0169217 , -0.01752545],
            [ 0.00935436, -0.05018221]]),
         'W2': np.array([[-0.0104319 , -0.04019007,  0.01607211,  0.04440255]]),
         'b1': np.array([[ -8.97523455e-07],
            [  8.15562092e-06],
            [  6.04810633e-07],
            [ -2.54560700e-06]]),
         'b2': np.array([[  9.14954378e-05]])}
        return parameters, X_assess

    planar_utils.py代码:

    import matplotlib.pyplot as plt
    import numpy as np
    import sklearn
    import sklearn.datasets
    import sklearn.linear_model
    
    def plot_decision_boundary(model, X, y):
        # Set min and max values and give it some padding
        x_min, x_max = X[0, :].min() - 1, X[0, :].max() + 1
        y_min, y_max = X[1, :].min() - 1, X[1, :].max() + 1
        h = 0.01
        # Generate a grid of points with distance h between them
        xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
        # Predict the function value for the whole grid
        Z = model(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        # Plot the contour and training examples
        plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
        plt.ylabel('x2')
        plt.xlabel('x1')
        plt.scatter(X[0, :], X[1, :], c=y, cmap=plt.cm.Spectral)
    
    
    def sigmoid(x):
        s = 1/(1+np.exp(-x))
        return s
    
    def load_planar_dataset():
        np.random.seed(1)
        m = 400 # number of examples
        N = int(m/2) # number of points per class
        D = 2 # dimensionality
        X = np.zeros((m,D)) # data matrix where each row is a single example
        Y = np.zeros((m,1), dtype='uint8') # labels vector (0 for red, 1 for blue)
        a = 4 # maximum ray of the flower
    
        for j in range(2):
            ix = range(N*j,N*(j+1))
            t = np.linspace(j*3.12,(j+1)*3.12,N) + np.random.randn(N)*0.2 # theta
            r = a*np.sin(4*t) + np.random.randn(N)*0.2 # radius
            X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
            Y[ix] = j
    
        X = X.T
        Y = Y.T
    
        return X, Y
    
    def load_extra_datasets():  
        N = 200
        noisy_circles = sklearn.datasets.make_circles(n_samples=N, factor=.5, noise=.3)
        noisy_moons = sklearn.datasets.make_moons(n_samples=N, noise=.2)
        blobs = sklearn.datasets.make_blobs(n_samples=N, random_state=5, n_features=2, centers=6)
        gaussian_quantiles = sklearn.datasets.make_gaussian_quantiles(mean=None, cov=0.5, n_samples=N, n_features=2, n_classes=2, shuffle=True, random_state=None)
        no_structure = np.random.rand(N, 2), np.random.rand(N, 2)
    
        return noisy_circles, noisy_moons, blobs, gaussian_quantiles, no_structure
    

      

     
  • 相关阅读:
    Git 基础
    SharePoint 2013 对象模型操作"网站设置"菜单
    SharePoint 2013 隐藏部分Ribbon菜单
    SharePoint 2013 Designer系列之数据视图筛选
    SharePoint 2013 Designer系列之数据视图
    SharePoint 2013 Designer系列之自定义列表表单
    SharePoint 2013 设置自定义布局页
    SharePoint 2013 "通知我"功能简介
    SharePoint 2013 创建web应用程序报错"This page can’t be displayed"
    SharePoint 禁用本地回环的两个方法
  • 原文地址:https://www.cnblogs.com/zhangliqiangvictory/p/13454370.html
Copyright © 2011-2022 走看看