编程实践-Week2

这是整个深度学习课程1的第一个编程作业,这次编程的目的是设计实现Logistic Regression并对猫的图片进行分类。在第一次的编程过程中,提升了许多我对Numpy,包括Python的理解。下面是学习中的一些误区和心得。

整个深度学习框架中用到python包如下:

 

import numpy as np                  # numpy是一个科学计算包
import
matplotlib.pyplot as plt import h5py # h5py是一个用于与存储在H5文件中的数据集进行交互的包

import scipy
from PIL import Image
from scipy import ndimage
from lr_utils import load_dataset   # 数据集

%matplotlib inline                  # Notebook的魔法命令。意思是将那些用matplotlib绘制的图显示在页面里而不是弹出一个窗口 

在学习的最开始,我们有如下训练集:

(1) m_train个带标签(猫=0,不是猫=1)的训练集。

(2) m_test个带标签的测试集。

(3) 每张图片的大小为(height, width, 3),其中3表示RGB三色通道。

通过X.shape函数,我们可以获得m_train,m_test,height和width。

m_train = train_set_x_orig.shape[0]
m_test =  test_set_x_orig.shape[0]
num_px =  train_set_x_orig.shape[2]

为了方便数据的处理,我们应将图片大小(height, width, 3)转换为(height * width * 3, 1)。

使用reshape函数来重新构造数组,这里可以使用一个trick:如果我们打算将矩阵X(a,b,c,d)变为矩阵X_f (b * c * d, ),可以使用如下函数:

X_f = X.reshape(X.shape[0] ,-1). T

# Reshape the training and test examples

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

  train_set_x = train_set_x_flatten/255.
  test_set_x = test_set_x_flatten/255.

同时上述代码对数据进行了标准化(Standardize)的处理,因为RGB最大像素值为255,因此可以将输入像素映射到[0,1]上。

一个普通的逻辑回归过程如图所示:

对于每个样本xi,前向传播计算的公式为:

同样的,计算损失函数的公式为:

在我们设计神经网络时,整个的思路可以分为以下3步:

      1. 定义网络中的超参数(层数,隐藏单元数等)

      2. 初始化模型中的参数

      3. 循环以下操作

              (1) 计算损失函数(前向传播)

              (2) 计算梯度(反向传播)

              (3) 梯度下降

首先使用 Numpy实现最基本的sigmoid函数,

def sigmoid(z):
    """
    Compute the sigmoid of z

    Arguments:
    z -- A numpy array.

    Return:
    s -- sigmoid(z)
    """

    s = 1.0/( 1+ np.exp(-z))  #使用np.exe(a) 可以实现矩阵的指数运算
    
    return s

sigmoid(np.array([0,2]))

接下来初始化模型中的参数,使用np.zeros(a, b)来初始化W,b。

def initialize_with_zeros(dim):
    """
    This function creates a vector of zeros of shape (dim, 1) for w and initializes b to 0.
    
    Argument:
    dim -- size of the w vector we want (or number of parameters in this case)
    
    Returns:
    w -- initialized vector of shape (dim, 1)
    b -- initialized scalar (corresponds to the bias)
    """
    
    w=np.zeros((dim,1),dtype=float)     #注意函数中的dtype
    b=0

    assert(w.shape == (dim, 1))
    assert(isinstance(b, float) or isinstance(b, int))
    
    return w, b

dim = 2
w, b = initialize_with_zeros(dim)

初始化参数后,我们可以执行神经网络中的前向传播算法方程,

 

 反向传播方程:

    (注意:在反向传播中,理解在下一步梯度下降的意义:寻找最小的参数W,b使得cost函数J得到最小值(如图所示))

 (为什么梯度下降算法 A = A - learning_rate * dA 是有效的梯度下降算法? )

       如图所示,在我们仅考虑一个参数的影响(如W)时,随机选取一个初始点,如左边箭头所指向的A点,A点处 dW < 0,因此更新后的W = W - learning_rate *dW会使得W增大,即往最低点的方向靠近,右边箭头所指的B点同理,在B点 dW>0,因此更新后W会减小,同样向最低点靠近。·

        回到逻辑回归中的正向传播和反向传播具体实现如下:

def propagate(w, b, X, Y):
    """
    Implement the cost function and its gradient for the propagation explained above

    Arguments:
    w -- weights, a numpy array of size (num_px * num_px * 3, 1)
    b -- bias, a scalar
    X -- data of size (num_px * num_px * 3, number of examples)
    Y -- true "label" vector (containing 0 if non-cat, 1 if cat) of size (1, number of examples)

    Return:
    cost -- negative log-likelihood cost for logistic regression
    dw -- gradient of the loss with respect to w, thus same shape as w
    db -- gradient of the loss with respect to b, thus same shape as b
    
    Tips:
    - Write your code step by step for the propagation. np.log(), np.dot()
    """
    
    m = X.shape[1]
    
    # FORWARD PROPAGATION (FROM X TO COST)
    A = sigmoid(np.dot((w.T),X) + b)                                    # compute activation
    cost = (-1/m)*np.sum((np.multiply(Y,np.log(A)))+ np.multiply((1-(Y)),np.log(1-A)))    # compute cost
  
    # BACKWARD PROPAGATION (TO FIND GRAD)
    dw = np.dot(X,(A - Y).T)/m
    db = (np.sum(A - Y))/m
  

    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],[3,4]]), np.array([[1,0]])
grads, cost = propagate(w, b, X, Y)

 

  梯度下降的代码如下:

def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
    """
    This function optimizes w and b by running a gradient descent algorithm
    
    Arguments:
    w -- weights, a numpy array of size (num_px * num_px * 3, 1)
    b -- bias, a scalar
    X -- data of shape (num_px * num_px * 3, number of examples)
    Y -- true "label" vector (containing 0 if non-cat, 1 if cat), of shape (1, number of examples)
    num_iterations -- number of iterations of the optimization loop
    learning_rate -- learning rate of the gradient descent update rule
    print_cost -- True to print the loss every 100 steps
    
    Returns:
    params -- dictionary containing the weights w and bias b
    grads -- dictionary containing the gradients of the weights and bias with respect to the cost function
    costs -- list of all the costs computed during the optimization, this will be used to plot the learning curve.
    
    Tips:
    You basically need to write down two steps and iterate through them:
        1) Calculate the cost and the gradient for the current parameters. Use propagate().
        2) Update the parameters using gradient descent rule for w and b.
    """
    
    costs = []
    
    for i in range(num_iterations):
        
        
        # Cost and gradient calculation
        grads, cost = propagate(w, b, X, Y)
        
        # Retrieve derivatives from grads
        dw = grads["dw"]
        db = grads["db"]
        
        # update rule 
        w = w-learning_rate*dw
        b = b-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(w, b, X, Y, num_iterations= 100, learning_rate = 0.009, print_cost = False)

 

再次回顾整个神经网络的方法过程,从设计神经网络的超参数,到执行前向传播和反向传播,再进行梯度下降的更新。在执行完所有的以上过程后,就可以将数据输入训练好的模型中进行预测:

def predict(w, b, X):
    '''
    Predict whether the label is 0 or 1 using learned logistic regression parameters (w, b)
    
    Arguments:
    w -- weights, a numpy array of size (num_px * num_px * 3, 1)
    b -- bias, a scalar
    X -- data of size (num_px * num_px * 3, number of examples)
    
    Returns:
    Y_prediction -- a numpy array (vector) containing all predictions (0/1) for the examples in 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
    A = sigmoid(np.dot((w.T),X) + b)
    for i in range(A.shape[1]):
        
        # Convert probabilities A[0,i] to actual predictions p[0,i]

        Y_prediction[0,i] = A[0,i]>0.5    #判断大小这一行代码就够了
                 
  
    assert(Y_prediction.shape == (1, m))

    return Y_prediction

predict(w, b, X)

 

到此,我们已经完成了整个逻辑回归网络中所有小模块的设计,下一步是将这些小模块整合起来,形成完整的代码:

def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):
    """
    Builds the logistic regression model by calling the function you've implemented previously
    
    Arguments:
    X_train -- training set represented by a numpy array of shape (num_px * num_px * 3, m_train)
    Y_train -- training labels represented by a numpy array (vector) of shape (1, m_train)
    X_test -- test set represented by a numpy array of shape (num_px * num_px * 3, m_test)
    Y_test -- test labels represented by a numpy array (vector) of shape (1, m_test)
    num_iterations -- hyperparameter representing the number of iterations to optimize the parameters
    learning_rate -- hyperparameter representing the learning rate used in the update rule of optimize()
    print_cost -- Set to true to print the cost every 100 iterations
    
    Returns:
    d -- dictionary containing information about the model.
    """
    
    ### START CODE HERE ###
    
    # initialize parameters with zeros
    w, b = initialize_with_zeros(X_train.shape[0])

    # Gradient descent 
    parameters, grads, costs  = optimize(w, b, X_train, Y_train, num_iterations= 100, learning_rate = 0.009, print_cost = False)
    
    # Retrieve parameters w and b from dictionary "parameters"
    w = parameters["w"]
    b = parameters["b"]
    
    # Predict test/train set examples 
    Y_prediction_test = predict(w, b, X_test)
    Y_prediction_train = predict(w, b, X_train)


    # 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

d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)

 

 最终的实验结果为

   由最后的实验结果看出,虽然逻辑回归算法在训练集上有较好的效果,但是在测试集中只有70%的正确率,因此,我们需要寻找更复杂的神经网络来获得更高的准确率。

   通过这第一次编程,发现自己对Python和Numpy的掌握上连入门都谈不上,还是应该去多动手多试验才能加深对知识的理解。

 

 

 

 

 

posted @ 2017-09-15 10:16  BlueBluelueluelue  阅读(382)  评论(0)    收藏  举报