Un marco de código de red neuronal simple para capas ocultas

https://www.deeplearning.ai/ La tarea de programación de la tercera semana de la primera lección presenta cómo implementar una red neuronal de capa oculta. Las tareas de programación están disponibles aquí en
https://github.com/stormstone/deeplearning.ai

Marco general
Lo que se hace aquí es un problema de clasificación binaria: X es la característica de la entrada, Y es la etiqueta de clasificación y n_h es el número de muestras.
Aquí, entrenar un modelo se divide en cinco pasos:

  1. Parámetros de inicialización W1, b1, W2, b2
  2. Propagación hacia adelante, calcule la entrada actual A2 en función de W1, b1, W2, b2 y guarde Z1, A1, Z2 en ella para una propagación hacia atrás posterior.
  3. Según el valor previsto A2 y el valor real Y, utilice la función de pérdida para calcular el error de todas las muestras, es decir, el valor del costo (observe los cambios en el valor del costo en tiempo real)
  4. Propagación hacia atrás, según la función de activación utilizada, W1, W2, A1, A2, X, Y, derivación de la regla de la cadena, obtenemos dW1, db1, dW2, db2
  5. Según los dW1, db1, dW2 y db2 obtenidos, actualice W1, b1, W2 y b2. Luego repita los pasos 2 a 5 hasta alcanzar el número establecido de ciclos.
def nn_model(X, Y, n_h, num_iterations = 10000, print_cost=False):
    """
    Arguments:
    X -- dataset of shape (2, number of examples)
    Y -- labels of shape (1, number of examples)
    n_h -- size of the hidden layer
    num_iterations -- Number of iterations in gradient descent loop
    print_cost -- if True, print the cost every 1000 iterations

    Returns:
    parameters -- parameters learnt by the model. They can then be used to predict.
    """

    np.random.seed(3)
    n_x = layer_sizes(X, Y)[0]
    n_y = layer_sizes(X, Y)[2]

    # Initialize parameters, then retrieve W1, b1, W2, b2. Inputs: "n_x, n_h, n_y". Outputs = "W1, b1, W2, b2, parameters".
    ### START CODE HERE ### (≈ 5 lines of code)
    parameters = initialize_parameters(n_x, n_h, n_y)
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    ### END CODE HERE ###

    # Loop (gradient descent)

    for i in range(0, num_iterations):

        ### START CODE HERE ### (≈ 4 lines of code)
        # Forward propagation. Inputs: "X, parameters". Outputs: "A2, cache".
        A2, cache = forward_propagation(X, parameters)

        # Cost function. Inputs: "A2, Y, parameters". Outputs: "cost".
        cost = compute_cost(A2, Y, parameters)

        # Backpropagation. Inputs: "parameters, cache, X, Y". Outputs: "grads".
        grads = backward_propagation(parameters, cache, X, Y)

        # Gradient descent parameter update. Inputs: "parameters, grads". Outputs: "parameters".
        parameters = update_parameters(parameters, grads,learning_rate = 0.1)

        ### END CODE HERE ###

        # Print the cost every 1000 iterations
        if print_cost and i % 1000 == 0:
            print ("Cost after iteration %i: %f" %(i, cost))

    return parameters

consejos

  1. El papel de la función de activación. Cuando no existe una función de activación, la operación realizada por cada neurona es y = kx + b. Si lo calculas, encontrarás que no importa cuántas capas haya y cuántas neuronas en cada capa. , al final en realidad es solo y=kx.+b. En la vida real, muchos problemas de clasificación no se pueden resolver linealmente, por lo que se necesita una función de activación para doblar la línea de clasificación.
  2. La diferencia entre diferentes funciones de activación como sigmoide, tanh y ReLU es que la salida de sigmoide es (0,1), por lo que es adecuada para problemas de clasificación binaria y representa la probabilidad de estar en la misma clase. ¿Se dice que la ventaja de tanh sobre sigmoide es la simetría de datos? No entiendo esto. La ventaja de ReLU es que cuando la entrada es demasiado pequeña o demasiado grande, la pendiente no será demasiado pequeña, lo que mejora la eficiencia. (Las pendientes de las curvas sigmoidea y tanh tienden a cero cuando la entrada es demasiado pequeña o demasiado grande)

q

  1. ¿Cuáles son las ventajas de tanh sobre sigmoide?
  2. La función de pérdida usa L = y*log(a) + (1-y) * log(1-a), a es el valor predicho, habrá una situación en la que la pendiente sea cero, es decir, dW1, dW2, db1 y db2 son todos cero, pero ¿puede que este no sea el valor óptimo? ¿Cómo deberíamos conocer esta situación para diferentes funciones de pérdida?

apéndice

La siguiente es la implementación de la función: la función de activación de la capa oculta aquí usa tanh y la función de activación de la capa de salida usa sigmoide, por lo que la propagación hacia atrás es una derivación como esta.

# GRADED FUNCTION: initialize_parameters

def initialize_parameters(n_x, n_h, n_y):
    """
    Argument:
    n_x -- size of the input layer
    n_h -- size of the hidden layer
    n_y -- size of the output layer

    Returns:
    params -- python dictionary containing your parameters:
                    W1 -- weight matrix of shape (n_h, n_x)
                    b1 -- bias vector of shape (n_h, 1)
                    W2 -- weight matrix of shape (n_y, n_h)
                    b2 -- bias vector of shape (n_y, 1)
    """

    np.random.seed(2) # we set up a seed so that your output matches ours although the initialization is random.

    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = np.random.rand(n_h, n_x) * 0.01
    b1 = np.zeros((n_h,1))
    W2 = np.random.rand(n_y, n_h) * 0.01
    b2 = np.zeros((n_y,1))
    ### END CODE HERE ###

    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

# GRADED FUNCTION: forward_propagation

def forward_propagation(X, parameters):
    """
    Argument:
    X -- input data of size (n_x, m)
    parameters -- python dictionary containing your parameters (output of initialization function)

    Returns:
    A2 -- The sigmoid output of the second activation
    cache -- a dictionary containing "Z1", "A1", "Z2" and "A2"
    """
    # Retrieve each parameter from the dictionary "parameters"
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    ### END CODE HERE ###

    # Implement Forward Propagation to calculate A2 (probabilities)
    ### START CODE HERE ### (≈ 4 lines of code)
    Z1 = np.dot(W1,X)+b1
    A1 = np.tanh(Z1)
    Z2 = np.dot(W2,A1)+b2
    A2 = sigmoid(Z2)
    ### END CODE HERE ###

    assert(A2.shape == (1, X.shape[1]))

    cache = {
   
   "Z1": Z1,
             "A1": A1,
             "Z2": Z2,
             "A2": A2}

    return A2, cache

# GRADED FUNCTION: compute_cost

def compute_cost(A2, Y, parameters):
    """
    Computes the cross-entropy cost given in equation (13)

    Arguments:
    A2 -- The sigmoid output of the second activation, of shape (1, number of examples)
    Y -- "true" labels vector of shape (1, number of examples)
    parameters -- python dictionary containing your parameters W1, b1, W2 and b2

    Returns:
    cost -- cross-entropy cost given equation (13)
    """

    m = Y.shape[1] # number of example

    # Compute the cross-entropy cost
    ### START CODE HERE ### (≈ 2 lines of code)
    logprobs = np.log(A2) * Y + (1-Y)* np.log(1-A2)
    cost = -np.sum(logprobs)/m
    ### END CODE HERE ###

    cost = np.squeeze(cost)     # makes sure cost is the dimension we expect. 
                                # E.g., turns [[17]] into 17 
    assert(isinstance(cost, float))

    return cost    

# GRADED FUNCTION: backward_propagation

def backward_propagation(parameters, cache, X, Y):
    """
    Implement the backward propagation using the instructions above.

    Arguments:
    parameters -- python dictionary containing our parameters 
    cache -- a dictionary containing "Z1", "A1", "Z2" and "A2".
    X -- input data of shape (2, number of examples)
    Y -- "true" labels vector of shape (1, number of examples)

    Returns:
    grads -- python dictionary containing your gradients with respect to different parameters
    """
    m = X.shape[1]

    # First, retrieve W1 and W2 from the dictionary "parameters".
    ### START CODE HERE ### (≈ 2 lines of code)
    W1 = parameters["W1"]
    W2 = parameters["W2"]
    ### END CODE HERE ###

    # Retrieve also A1 and A2 from dictionary "cache".
    ### START CODE HERE ### (≈ 2 lines of code)
    A1 = cache["A1"]
    A2 = cache["A2"]
    ### END CODE HERE ###

    # Backward propagation: calculate dW1, db1, dW2, db2. 
    ### START CODE HERE ### (≈ 6 lines of code, corresponding to 6 equations on slide above)
    dZ2 = A2 - Y
    dW2 = np.dot(dZ2,A1.T) / m
    db2 = np.sum(dZ2,axis = 1, keepdims = True) / m
    dZ1 = np.dot(W2.T,dZ2) * (1 - np.power(A1, 2))
    dW1 = np.dot(dZ1,X.T) / m
    db1 = np.sum(dZ1,axis = 1, keepdims = True) / m
    ### END CODE HERE ###

    grads = {
   
   "dW1": dW1,
             "db1": db1,
             "dW2": dW2,
             "db2": db2}

    return grads

# GRADED FUNCTION: update_parameters

def update_parameters(parameters, grads, learning_rate = 1.2):
    """
    Updates parameters using the gradient descent update rule given above

    Arguments:
    parameters -- python dictionary containing your parameters 
    grads -- python dictionary containing your gradients 

    Returns:
    parameters -- python dictionary containing your updated parameters 
    """
    # Retrieve each parameter from the dictionary "parameters"
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    ### END CODE HERE ###

    # Retrieve each gradient from the dictionary "grads"
    ### START CODE HERE ### (≈ 4 lines of code)
    dW1 = grads["dW1"]
    db1 = grads["db1"]
    dW2 = grads["dW2"]
    db2 = grads["db2"]
    ## END CODE HERE ###

    # Update rule for each parameter
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 -= learning_rate * dW1
    b1 -= learning_rate * db1
    W2 -= learning_rate * dW2
    b2 -= learning_rate * db2
    ### END CODE HERE ###

    parameters = {
   
   "W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}

    return parameters

Supongo que te gusta

Origin blog.csdn.net/ZhaoBuDaoFangXia/article/details/79971088
Recomendado
Clasificación