zoukankan      html  css  js  c++  java
  • Andrew Ng 深度学习课后测试记录-01-week2-答案

    代码标注及运行、调试结果

    tips:深度学习中的很多错误软件来自矩阵/向量的维度不匹配,要注意检查

    1.准备工作

    import numpy as np '''python用于科学计算的基础包'''
    
    import matplotlib.pyplot as plt '''python中绘制图形的库'''
    
    import h5py '''与存储在H5文件中的数据集交互的常见包'''
    
    import scipy
    from PIL import Image
    from scipy import ndimage
    from lr_utils import load_dataset
    
    %matplotlib inline
    
    ###加载设置好的数据集###
    
    train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
    index = 25
    
    plt.imshow(train_set_x_orig[index])
    print ("y = " + str(train_set_y[:, index]) + ", it's a '" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") + "' picture.")
    
    
    ###train_set_x_orig的数组形式:shape (m_train, num_px, num_px, 3)
    
    #例如可以通过访问:train_set_x_orig.shape[0] 访问到m_train(训练数量)
    ###应用###
    m_train = train_set_x_orig.shape[0]
    m_test = test_set_x_orig.shape[0]
    num_px = train_set_x_orig.shape[1]
    
    
    print ("Number of training examples: m_train = " + str(m_train))
    print ("Number of testing examples: m_test = " + str(m_test))
    print ("Height/Width of each image: num_px = " + str(num_px))
    print ("Each image is of size: (" + str(num_px) + ", " + str(num_px) + ", 3)")
    print ("train_set_x shape: " + str(train_set_x_orig.shape))
    print ("train_set_y shape: " + str(train_set_y.shape))
    print ("test_set_x shape: " + str(test_set_x_orig.shape))
    print ("test_set_y shape: " + str(test_set_y.shape))
    
    #转化训练和测试用例
    ###想要将一个形如(a,b,c,d)的矩阵转化为 (b ∗∗ c ∗∗ d, a) 的矩阵,使用X_flatten = X.reshape(X.shape[0], -1).T 其中X.T 是X的矩阵的转置###
    
    
    ###应用###
    train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
    test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
    
    
    print ("train_set_x_flatten shape: " + str(train_set_x_flatten.shape))
    print ("train_set_y shape: " + str(train_set_y.shape))
    print ("test_set_x_flatten shape: " + str(test_set_x_flatten.shape))
    print ("test_set_y shape: " + str(test_set_y.shape))
    print ("sanity check after reshaping: " + str(train_set_x_flatten[0:5,0])) #???????
    
    #要表示彩色图像,必须为每个像素指定红色,绿色和蓝色通道(RGB),因此像素值实际上是包含三个数字的向量,范围从0到255。
    #机器学习中一个常见的预处理步骤是对数据集进行居中和标准化,这意味着您从每个示例中减去整个numpy数组的平均值,
    #然后将每个示例除以整个numpy数组的标准偏差。 但是对于图片数据集,它更简单,更方便,几乎可以将数据集的每一行除以255(像素通道的最大值)。
    #将我们的数据集进行标准化。
    
    train_set_x = train_set_x_flatten/255.
    test_set_x = test_set_x_flatten/255.
    
    print ("train_set_x shape: " + str(train_set_x.shape))
    print ("train_set_y shape: " + str(train_set_y.shape))
    print ("test_set_x shape: " + str(test_set_x.shape))
    print ("test_set_y shape: " + str(test_set_y.shape))
    ###预处理新数据集的常用步骤如下:
    ###弄清楚问题的大小和形状(m_train,m_test,num_px,...)
    ###重塑数据集,使每个示例是一个大小为(num_px * num_px * 3,1)的向量的“标准化”数据

    结果:

    2.数组访问技巧

    train_set_x_orig的数组形式:shape (m_train, num_px, num_px, 3)
    
    #例如可以通过访问:train_set_x_orig.shape[0] 访问到m_train(训练数量)

    3.学习算法的一般体系结构

    设计一种简单的算法来区分猫图像和非猫图像。

    您将使用神经网络思维模式构建Logistic回归。 下图解释了为什么Logistic回归实际上是一个非常简单的神经网络!

    数学表达式:

    针对样例

    cost函数:

                                           

    接下来完成以下步骤:

    - 初始化模型的参数
    - 通过最小化成本来了解模型的参数
    - 使用学习的参数进行预测(在测试集上)
    - 分析结果并得出结论

    4.开始构建算法的各个部分   

    构建神经网络的主要步骤是:

              定义模型结构(例如输入元素的数量)
              初始化模型的参数
                     循环:
                           计算当前loss函数(前向传播)
                           计算当前梯度(反向传播)
                           更新参数(梯度下降)
              经常会单独构建以上三个循环,并将它们集成到一个我们称为model()的函数中。

    4.1 帮助函数

    使用“Python Basics”中的代码,实现sigmoid(),通过计算sigmoid,对其 进行预测,其中建议使用np.exp()

    import numpy as np
    
    def sigmoid(z):
        """
        计算z的sigmoid函数
    
        参数:
        z -- 任意大小的数组或者常量.
    
        返回值:
        s -- sigmoid(z)
        """
    
        ###应用###
        s = 1 / (1 + np.exp(-z))
        ###s = (1 + np.exp(-z))**(-1)  也可以
        
        return s
        #函数输出的测试(可以通过数组的方式一次输入多个)
    print ("sigmoid([3, 0]) = " + str(sigmoid(np.array([3,0]))))
    

    4.2 初始化参数

    如果输入的是图片,则w的维度设置为  (num_px ×× num_px ×× 3, 1).

    将w初始化为0,建议使用np.zeros() ,b的值根据实际情况进行设置

    import numpy as np
    def initialize_with_zeros(dim):
        """
        该函数创建一个维数为(dim,1),元素值为0的列向量,将b初始化为0
        参数:
        dim -- 我们想要设置的w向量的大小(或者是用例中的参数个数)
        
        返回值:
        w -- 初始化为 (dim, 1)的向量
        b -- 初始化标量(对应于偏差)
        """
        
        ### 应用###
        w = np.zeros((dim, 1), dtype=np.float)  #dtype指定数据类型
        b = 9
        #检测
        assert(w.shape == (dim, 1))
        assert(isinstance(b, float) or isinstance(b, int))
        
        return w, b

     验证输出: 

    dim = 7
    w, b = initialize_with_zeros(dim)
    print ("w = " + str(w))
    print ("b = " + str(b))
    

    4.3前向和反向传播

    目前参数已经进行初始化了,接下来可以通过执行前向和反向传播步骤进一步学习参数

    实现propagate() 函数,计算cost函数以及他的梯度下降

    提示:

    前向传播:

         1) 获得X矩阵

         2)计算

         3)计算cost函数 

     可能用到的公式:

         

    # 前向传播函数
    import numpy as np
    
    def sigmoid(z):
    
    
        ###应用###
        s = 1 / (1 + np.exp(-z))
        ###s = (1 + np.exp(-z))**(-1)  也可以
        
        return s
    def propagate(w, b, X, Y):
        """
        参数:
        w -- 权重,大小为(num_px * num_px * 3, 1)的数组
        b -- 偏差, 是个常量
        X -- 数据大小 (num_px * num_px * 3, 样本大小)
        Y --  "label" 向量(0表示不是猫, 1表示是猫),其维数为(1, 样本大小)
    
        返回值:
        cost -- 公式计算得出的值
        dw -- loss对w的导数, 因此维数与w一样
        db -- loss对b的导数, 因此维数与b一样
        
        提示:
        - 建议使用 np.log(), np.dot()
        """
        
        m = X.shape[1]
        
        #前向
        ### 应用np里面的内置函数
        A = sigmoid(np.dot(w.T,X)+b)                                  #计算激活函数
        cost =-1/m * np.sum(Y * np.log(A)+(1-Y)*np.log(1-A))                                  #计算cost函数,注意负号和A
        # 反向
        ###注意.dot的使用
        dw = 1/m*(np.dot(X,(A-Y).T))
        db = 1/m*np.sum(A-Y)
        ### END CODE HERE ###
    
        assert(dw.shape == w.shape)
        assert(db.dtype == float)
        cost = np.squeeze(cost)
        assert(cost.shape == ())
        
        grads = {"dw": dw,
                 "db": db}
        
        return grads, cost

    验证输出:

    w, b, X, Y = np.array([[1.],[2.]]), 2., np.array([[1.,2.,-1.],[3.,4.,-3.2]]), np.array([[1,0,1]])
    grads, cost = propagate(w, b, X, Y)
    print ("dw = " + str(grads["dw"]))
    print ("db = " + str(grads["db"]))
    print ("cost = " + str(cost))

     4.4优化函数

    目前已经初始化参数、计算cost函数及其梯度,现在要做的是使用梯度下降更新参数。

    构造优化函数,通过最小化cost函数J,找到合适的w和b的值

    对于参数θ,更新规则是θ=θ-αdθ,其中α为学习率

    def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
        """
        通过梯度下降算法,优化参数w和b
        参数:
        w -- 权重,大小为(num_px * num_px * 3, 1)的数组
        b -- 偏差, 是个常量
        X -- 数据大小 (num_px * num_px * 3, 样本大小)
        Y --  "label" 向量(0表示不是猫, 1表示是猫),其维数为(1, 样本大小)
        num_iterations -- 优化循环的迭代次数
        learning_rate --梯度下降更新规则的学习率
        print_cost --每100步打印一次loss函数
    
        返回值:
        params -- 一个dictionary 包含权重w和偏差b
        grads --  一个dictionary 包含所期望的cost函数中的权重的导数dw和偏差的导数db
        costs --  一个list       包含优化过程中计算的所有的cost函数值,用于绘制学习曲线
    
        提示:
        主要包含以下两个步骤并进行迭代:
           1)使用propagate() 计算当前参数的cost函数和梯度
           2)使用梯度下降规则中的w和b更新参数
        """
        
        costs = []
        
        for i in range(num_iterations):
            
            
            
            ###调用前向传播函数### 
            grads, cost = propagate(w, b, X, Y)
            
            
            # Retrieve derivatives from grads
            dw = grads["dw"]
            db = grads["db"]
            #更新规则
            ###注意转化为矩阵的相乘的形式###
            w = w - np.dot(learning_rate, dw)
            b = b - np.dot(learning_rate, db)
           
            
            # Record the costs
            if i % 100 == 0:
                costs.append(cost)
            
            # Print the cost every 100 training examples
            if print_cost and i % 100 == 0:
                print ("Cost after iteration %i: %f" %(i, cost))
        
        params = {"w": w,
                  "b": b}
        
        grads = {"dw": dw,
                 "db": db}
        
        return params, grads, costs

    仍然使用前面设定的值对函数进行结果测试:

    params, grads, costs = optimize(np.array([[1.],[2.]]), 2., np.array([[1.,2.,-1.],[3.,4.,-3.2]]), np.array([[1,0,1]]), num_iterations= 100, learning_rate = 0.009, print_cost = False)
    
    print ("w = " + str(params["w"]))
    print ("b = " + str(params["b"]))
    print ("dw = " + str(grads["dw"]))
    print ("db = " + str(grads["db"]))

    前面的函数将输出最终学习的w和b,我们可以用w和b的值去预测数据集X的标签,应用predict()函数,主要分为两个步骤来计算预测值

    1.计算  

    2.将a的值转换成0(激活函数<=0.5)或1(激活函数>0.5),将预测值存储在向量Y_prediction中(也可以通过在for循环中使用if...else实现)

    # GRADED FUNCTION: predict
    
    def predict(w, b, X):
        '''
        使用学习到的logistic 回归参数(w,b)来预测标签值是0还是1
        参数:
        w -- 权重,大小为(num_px * num_px * 3, 1)的数组
        b -- 偏差, 是个常量
        X -- 数据大小 (num_px * num_px * 3, 样本大小)
    
        返回值:
        Y_prediction -- 包含在X中的样本的所有预测值,是一个数组或者向量
        '''
        
        m = X.shape[1]
        Y_prediction = np.zeros((1,m))
        w = w.reshape(X.shape[0], 1)
        
        # Compute vector "A" predicting the probabilities of a cat being present in the picture
        ### START CODE HERE ###
        A = sigmoid(np.dot(w.T, X) + b)
        ### END CODE HERE ###
        print(A.shape[1])
        for i in range(A.shape[1]):
            if A[0,i] <= 0.5:
                Y_prediction[0, i] = 0
            else:
                Y_prediction[0, i] = 1
            # Convert probabilities A[0,i] to actual predictions p[0,i]
            ### START CODE HERE ### (≈ 4 lines of code)
            ### END CODE HERE ###
        
        assert(Y_prediction.shape == (1, m))
        
        return Y_prediction

    验证输出:

    w = np.array([[0.1124579],[0.23106775]])
    b = -0.3
    X = np.array([[1.,-1.1,-3.2],[1.2,2.,0.1]])
    print ("predictions = " + str(predict(w, b, X)))

    5.将所有函数合并到模型中

    通过以下提示,实现模型函数:

      --Y_prediction_test    测试集上的预测值

      --Y_prediction_train   训练集上的预测值

      --optimize()     优化输出的 w,costs,grads 值

    # GRADED FUNCTION: model
    def sigmoid(z):
    
        ###应用###
        s = 1 / (1 + np.exp(-z))
        ###s = (1 + np.exp(-z))**(-1)  也可以
        
        return s
    def initialize_with_zeros(dim):
        
        w = np.zeros((dim,1))
        b = 9
        
        assert(w.shape == (dim, 1))
        assert(isinstance(b, float) or isinstance(b, int))
        
        return w, b
    def propagate(w, b, X, Y):
       
        m = X.shape[1]
        
        #前向
        ### 应用np里面的内置函数
        A = sigmoid(np.dot(w.T,X)+b)                                  #计算激活函数
        cost =-1/m * np.sum(Y * np.log(A)+(1-Y)*np.log(1-A))                                  #计算cost函数,注意负号和A
        # 反向
        ###注意.dot的使用
        dw = 1/m*(np.dot(X,(A-Y).T))
        db = 1/m*np.sum(A-Y)
        ### END CODE HERE ###
    
        assert(dw.shape == w.shape)
        assert(db.dtype == float)
        cost = np.squeeze(cost)
        assert(cost.shape == ())
        
        grads = {"dw": dw,
                 "db": db}
        
        return grads, cost
    def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
        
        costs = []
        
        for i in range(num_iterations):
             
            ###调用前向传播函数### 
            grads, cost = propagate(w, b, X, Y)
            
            
            # Retrieve derivatives from grads
            dw = grads["dw"]
            db = grads["db"]
            #更新规则
            ###注意转化为矩阵的相乘的形式###
            w = w - np.dot(learning_rate, dw)
            b = b - np.dot(learning_rate, db)
           
            
            # Record the costs
            if i % 100 == 0:
                costs.append(cost)
            
            # Print the cost every 100 training examples
            if print_cost and i % 100 == 0:
                print ("Cost after iteration %i: %f" %(i, cost))
        
        params = {"w": w,
                  "b": b}
        
        grads = {"dw": dw,
                 "db": db}
        
        return params, grads, costs
    def predict(w, b, X):
    
        m = X.shape[1]
        Y_prediction = np.zeros((1,m))
        w = w.reshape(X.shape[0], 1)
        
        # Compute vector "A" predicting the probabilities of a cat being present in the picture
        ### START CODE HERE ###
        A = sigmoid(np.dot(w.T, X) + b)
        ### END CODE HERE ###
        print(A.shape[1])
        for i in range(A.shape[1]):
            if A[0,i] <= 0.5:
                Y_prediction[0, i] = 0
            else:
                Y_prediction[0, i] = 1
            # Convert probabilities A[0,i] to actual predictions p[0,i]
            ### START CODE HERE ### (≈ 4 lines of code)
            ### END CODE HERE ###
        
        assert(Y_prediction.shape == (1, m))
        
        return Y_prediction
    
    def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):
        """
        通过调用之前实现的函数构建logistic回归模型
        
        参数:
        X_train -- 维数为 (num_px * num_px * 3, m_train) 的训练集
        Y_train -- 维数为 (1, m_train) 的训练标签
        X_test --  维数为 (num_px * num_px * 3, m_test) 的测试集
        Y_test --  维数为(1, m_test) 的测试标签
        num_iterations -- 超参数,表示优化参数的迭代次数
        learning_rate --  超参数,表示在optimize()更新规则中使用的学习率
        print_cost --  设置为true,以每100次迭代打印cost函数的值
        
        返回值:
        d -- 一个dictionary,包含一个模型的基本信息.
        """
        
        ### START CODE HERE ###
        
        # initialize parameters with zeros (≈ 1 line of code)
        w, b = initialize_with_zeros(X_train.shape[0])
    
        # Gradient descent (≈ 1 line of code)
        parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
        
        # Retrieve parameters w and b from dictionary "parameters"
        w = parameters["w"]
        b = parameters["b"]
        
        # Predict test/train set examples (≈ 2 lines of code)
        Y_prediction_test = predict(w, b, X_test)
        Y_prediction_train = predict(w, b, X_train)
    
        ### END CODE HERE ###
    
        # Print train/test Errors
        print("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))
        print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))
    
        
        d = {"costs": costs,
             "Y_prediction_test": Y_prediction_test, 
             "Y_prediction_train" : Y_prediction_train, 
             "w" : w, 
             "b" : b,
             "learning_rate" : learning_rate,
             "num_iterations": num_iterations}
        
        return d

    验证输出:

    import numpy as np
    import matplotlib.pyplot as plt
    import h5py
    import scipy
    from PIL import Image
    from scipy import ndimage
    from lr_utils import load_dataset
    
    %matplotlib inline
    
    train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
    index = 25
    ###plt.imshow(test_set_x_orig[index])###
    plt.imshow(train_set_x_orig[index])
    print ("y = " + str(train_set_y[:, index]) + ", it's a '" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") +  "' picture.")
    
    
    ###train_set_x_orig的数组形式:shape (m_train, num_px, num_px, 3) 
    
    #例如可以通过访问:train_set_x_orig.shape[0]  访问到m_train(训练数量)
    ### START CODE HERE ### (≈ 3 lines of code)
    m_train = train_set_x_orig.shape[0]
    m_test = test_set_x_orig.shape[0]
    num_px = train_set_x_orig.shape[1]
    ### END CODE HERE ###
    
    ### START CODE HERE ### (≈ 2 lines of code)
    train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
    test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
    ### END CODE HERE ###
    
    train_set_x = train_set_x_flatten/255.
    test_set_x = test_set_x_flatten/255.
    
    print ("train_set_x shape: " + str(train_set_x.shape))
    print ("train_set_y shape: " + str(train_set_y.shape))
    print ("test_set_x shape: " + str(test_set_x.shape))
    print ("test_set_y shape: " + str(test_set_y.shape))
    
    d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)

    输出:

    分析:训练正确率接近100%。有一个不错的完整性检查:您的模型正在运行,并且具有足够的容量来适应训练数据。测试错误率约为40%(?),对于这个简单模型是可以接受的,我们使用的是比较少的数据集而且logistic回归是一个线性分类器,下周将尝试更加准确的分类器

    此外,可以看出,模型显然过度拟合了训练数据,之后将学习如何减少过拟合,例如:使用正规化,使用以下代码并改变index的值,可以看到测试集的预测值

    增加迭代次数,进行测试:

    d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 3000, learning_rate = 0.005, print_cost = True)    #更改 num_iterations = 3000 参数

    部分结果:

    绘制学习率曲线:

     

    解释:可以看出cost函数不断下降,这表明各项参数正在被学习。你会发现你可以在训练集上训练模型,试着增加上述单元的迭代次数并返回,会发现训练集的正确率增加,但是测试集的正确率下降,称之为过拟合(overfitting)

    6.附加题1

    通过以下提示,实现模型函数,测试学习率α可能的值

    提示:为了使得梯度下降更有效,应选择更加合适的学习率,学习率α决定了是否能快速更新参数。学习率过大,可能会“超”过最佳值,学习率过小,将需要更多的迭代来收敛(收敛)到最佳值。这就是为何选择一个“精调”的学习率的至关重要的原因

    运行以下代码,输入不同的学习率,观察结果:

    learning_rates = [0.01, 0.001, 0.0001]
    models = {}
    for i in learning_rates:
        print ("learning rate is: " + str(i))
        models[str(i)] = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 1500, learning_rate = i, print_cost = False)
        print ('
    ' + "-------------------------------------------------------" + '
    ')
    
    for i in learning_rates:
        plt.plot(np.squeeze(models[str(i)]["costs"]), label= str(models[str(i)]["learning_rate"]))
    
    plt.ylabel('cost')
    plt.xlabel('iterations (hundreds)')
    
    legend = plt.legend(loc='upper center', shadow=True)
    frame = legend.get_frame()
    frame.set_facecolor('0.90')
    plt.show()

     

    解释:

    1)不同的学习率会得到不同的cost值,因此会有不同的预测结果

    2)如果学习率过大(0.01),cost值将上下摆动,甚至会偏离(即使在这个例子中,使用0.01能最终收敛到cost的一个合适的值)

    3)cost值小不代表是一个好模型,必须检查会不会有可能过拟合,过拟合经常发生在训练正确率比测试正确率大很多的情况下

    4)在深度学习中,强烈推荐:

         选择合适的学习率来使cost函数尽可能小

         如果你的模型过拟合,选择其他技术来减少过拟合(之后继续学习)

    7.附加题2

    自己添加图片,测试模型如何处理:

    总结:

    1)对数据集进行预处理很重要

    2)分别实现每个函数功能,再将其合并到一个model()函数中

    3)调整学习率(这是“超参数”的一个例子)可以给算法带来很大不同,后面将看到更多的例子。

     

    深度学习小小白,欢迎加qq交流
  • 相关阅读:
    Fiddler给手机设置代理并抓取https链接
    速盘下载
    多版本firefox共存
    firefox45版本与seleniumIDE
    Linux基础快捷键
    解决虚拟机centOs不能上网问题
    HDU 4893 Wow! Such Sequence!(线段树)
    UVALive 7045 Last Defence
    POJ 3544 Journey with Pigs
    POJ 2499 Binary Tree
  • 原文地址:https://www.cnblogs.com/bask/p/9315486.html
Copyright © 2011-2022 走看看