目錄

@[toc]

前言

這次使用一個貓的數據集,我們使用深度神經網絡來識別這個是貓或者不是貓。

導包

這裏導入了兩個工具類,可以從這裏下載,這裏包含了這個函數和用到的數據集,其中用到了h5py,如果讀者沒有安裝的話,要先用pip安裝這個庫,還有以下用到的庫也要安裝。

# coding=utf-8
from dnn_utils_v2 import sigmoid, sigmoid_backward, relu, relu_backward
from lr_utils import load_dataset
import numpy as np
import matplotlib.pyplot as plt
import scipy
from scipy import ndimage

初始化網絡參數

在網絡定義之前,需要先對網絡的參數進行初始化,這裏分兩個來初始化,一個是兩層網絡的,另一個是L層網絡的。

兩層網絡的初始化

對兩層網絡的參數初始化要用到輸入層的大小、隱藏層的大小、輸出層的大小。

def initialize_parameters(n_x, n_h, n_y):
    """
    初始化參數
    :param n_x: 輸入層的大小。
    :param n_h: 隱藏層的大小。
    :param n_y: 輸出層的大小。
    :return: 
     parameters -- 包含您的參數的python字典:
                    W1 -- 形狀重量矩陣(n_h, n_x)
                    b1 -- 形狀的偏置向量(n_h, 1)
                    W2 -- 形狀重量矩陣(n_y, n_h)
                    b2 -- 形狀的偏置向量(n_y, 1)
    """
    W1 = np.random.randn(n_h, n_x) * 0.01
    b1 = np.zeros((n_h, 1))
    W2 = np.random.randn(n_y, n_h) * 0.01
    b2 = np.zeros((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

L層網絡的初始化

對於更深的網絡,需要的參數是網絡中每一層的尺寸的python數組。相關的計算如下:
| | Shape of W | Shape of b | Activation | Shape of Activation
:—: | :—: | :—: | :—: | :—:
| Layer 1 | \((n^{[1]},12288)\) | \((n^{[1]},1)\) | $Z^{[1]} = W^{[1]} X + b^{[1]} $ | \((n^{[1]},209)\)
|Layer 2|\((n^{[2]}, n^{[1]})\)|\((n^{[2]},1)\)|\(Z^{[2]} = W^{[2]} A^{[1]} + b^{[2]}\)|\((n^{[2]}, 209)\)
|\(\vdots\)|\(\vdots\)|\(\vdots\)|\(\vdots\)|\(\vdots\)
|Layer L-1|\((n^{[L-1]}, n^{[L-2]})\)|\((n^{[L-1]}, 1)\)|\(Z^{[L-1]} = W^{[L-1]} A^{[L-2]} + b^{[L-1]}\)|\((n^{[L-1]}, 209)\)
|Layer L|\((n^{[L]}, n^{[L-1]})\)| \((n^{[L]}, 1)\)|\(Z^{[L]} = W^{[L]} A^{[L-1]} + b^{[L]}\)|\((n^{[L]}, 209)\)

def initialize_parameters_deep(layer_dims):
    """
    初始化深度參數
    :param layer_dims: 包含我們網絡中每一層的尺寸的python數組(列表)。
    :return: 
     parameters -- python字典包含參數的"W1", "b1", ..., "WL", "bL":
                    Wl -- 形狀權重矩陣(layer_dims[l], layer_dims[l-1])
                    bl -- 形狀偏差向量(layer_dims[l], 1)
    """
    parameters = {}
    L = len(layer_dims)  # number of layers in the network

    for l in range(1, L):
        parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l - 1]) / np.sqrt(
            layer_dims[l - 1])  # *0.01
        parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))

        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

正向傳播模塊

一個完整的神經網絡流程是如圖所示:

在這一部分,我們要完成的是紫色部分的正向傳播,其中包括線性正向傳播、線性激活正向傳播和完成整個正向傳播的L層模型正向傳播。

線性正向傳播

構建前向傳播的線性部分,使用的線性公式如下:
\(\(Z^{[l]} = W^{[l]}A^{[l-1]} +b^{[l]}\tag{1}\)\)

def linear_forward(A, W, b):
    """
    實現一個層的正向傳播的線性部分。
    :param A: 前一層(或輸入數據)的激活:(前一層的大小,示例的數量)
    :param W: 權重矩陣:形狀的numpy數組(當前層的大小,上一層的大小)
    :param b: 偏置向量,形狀的numpy數組(當前層的大小,1)
    :return: 
    Z -- 激活函數的輸入,也稱爲預激活參數。
    cache -- :包含“a”、“W”和“b”的python字典;存儲用於有效地計算向後傳遞。
    """
    Z = np.dot(W, A) + b

    assert (Z.shape == (W.shape[0], A.shape[1]))
    cache = (A, W, b)

    return Z, cache

線性激活正向傳播

這裏使用到了兩個激活函數:

  • Sigmoid\(\sigma(Z) = \sigma(W A + b) = \frac{1}{ 1 + e^{-(W A + b)}}\)
  • ReLU\(A = ReLU(Z) = max(0, Z)\)

從線性到激活使用到的公式如下:
\(\(A^{[l]} = g(Z^{[l]}) = g(W^{[l]}A^{[l-1]} +b^{[l]})\tag{2}\)\)

def linear_activation_forward(A_prev, W, b, activation):
    """
    實現線性->激活層的正向傳播。
    :param A_prev: 前一層(或輸入數據)的激活:(前一層的大小,示例的數量)
    :param W: 權重矩陣:形狀的numpy數組(當前層的大小,上一層的大小)
    :param b: 偏置向量,形狀的numpy數組(當前層的大小,1)
    :param activation: 在此層中使用的激活,存儲爲文本字符串:“sigmoid”或“relu”
    :return: 
     A -- 激活函數的輸出,也稱爲激活後值。
    cache --包含“線性緩存”和“activation_cache”的python字典;
             存儲用於有效地計算向後傳遞
    """
    if activation == "sigmoid":
        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = sigmoid(Z)

    elif activation == "relu":
        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = relu(Z)

    assert (A.shape == (W.shape[0], A_prev.shape[1]))
    cache = (linear_cache, activation_cache)

    return A, cache

L層模型正向傳播

根據線性正向傳播和線性激活正向傳播的循環L次,得到一個L層的模型,如下圖:

代碼中使用到的AL是指公式的\(A^{[L]}\)
\(\(A^{[L]} = \sigma(Z^{[L]}) = \sigma(W^{[L]} A^{[L-1]} + b^{[L]})\tag{3}\)\)

def L_model_forward(X, parameters):
    """
    爲[LINEAR->RELU]*(L-1)->LINEAR->SIGMOID計算實現正向傳播。
    :param X: 數據,形狀的numpy數組(輸入大小,示例數量)
    :param parameters: initialize_parameters_deep()的輸出
    :return: 
    AL -- 最後激活後值
    caches -- 緩存包含列表:
                線性_activation_forward()的每個緩存(其中有L-1,從0到L-1的索引)
    """
    caches = []
    A = X
    L = len(parameters) // 2  # number of layers in the neural network

    # Implement [LINEAR -> RELU]*(L-1). Add "cache" to the "caches" list.
    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)

    # Implement LINEAR -> SIGMOID. Add "cache" to the "caches" list.
    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

計算損失函數

計算成本函數的公式如下:
\(\(cost = -\frac{1}{m} \sum\limits_{i = 1}^{m} (y^{(i)}\log\left(a^{[L] (i)}\right) + (1-y^{(i)})\log\left(1- a^{[L](i)}\right)) \tag{4}\)\)

def compute_cost(AL, Y):
    """
    實現由公式(7)定義的成本函數。
    :param AL: 對應於你的標籤預測的概率向量,形狀(1,例子數)
    :param Y: 正確的“標籤”矢量(例如:如果非cat,則包含0)、形狀(1、示例數量)
    :return: 
    cost -- 交叉熵損失
    """
    m = Y.shape[1]

    cost = -(np.sum(np.dot(Y, np.log(AL).T) + np.dot((1 - Y), np.log(1 - AL).T))) / m

    cost = np.squeeze(cost)
    assert (cost.shape == ())

    return cost

反向傳播模塊

就像向前傳播一樣,實現反向傳播的輔助函數。反向傳播用於計算損失函數與參數的梯度

線性反向傳播

在反向傳播的時候使用到公式如下:
$$ dW^{[l]} = \frac{\partial \mathcal{L} }{\partial W^{[l]}} = \frac{1}{m} dZ^{[l]} A^{[l-1] T} \tag{5}$$
$$ db^{[l]} = \frac{\partial \mathcal{L} }{\partial b^{[l]}} = \frac{1}{m} \sum_{i = 1}^{m} dZ^{l}\tag{6}$$
$$ dA^{[l-1]} = \frac{\partial \mathcal{L} }{\partial A^{[l-1]}} = W^{[l] T} dZ^{[l]} \tag{7}$$

def linear_backward(dZ, cache):
    """
    實現單層(l層)反向傳播的線性部分
    :param dZ: 線性輸出(當前層l)的成本梯度
    :param cache: 來自當前層的正向傳播元組(A_prev, W, b)的值
    :return: 
    dA_prev -- 關於激活(前一層l-1)的成本梯度,與A_prev相同。
    dW -- 關於W(當前層l)的成本梯度,與W相同。
    db -- :b(當前層l)的成本梯度,與b相同。
    """
    A_prev, W, b = cache
    m = A_prev.shape[1]

    dW = np.dot(dZ, A_prev.T) / m
    db = np.sum(dZ, axis=1, keepdims=True) / m
    dA_prev = np.dot(W.T, dZ)

    assert (dA_prev.shape == A_prev.shape)
    assert (dW.shape == W.shape)
    assert (db.shape == b.shape)

    return dA_prev, dW, db

線性激活反向傳播

在這裏使用到的計算公式如下:
\(\(dZ^{[l]} = dA^{[l]} * g'(Z^{[l]}) \tag{8}\)\)

def linear_activation_backward(dA, cache, activation):
    """
    實現 線性->激活層 的反向傳播。
    :param dA: 當前層的激活梯度
    :param cache: 我們存儲的值的元組(線性緩存,activation_cache)可以有效地計算反向傳播。
    :param activation: 在此層中使用的激活,存儲爲文本字符串:“sigmoid”或“relu”
    :return: 
     dA_prev -- 關於激活(前一層l-1)的成本梯度,與A_prev相同。
    dW -- 關於W(當前層l)的成本梯度,與W相同。
    db -- b(當前層l)的成本梯度,與b相同。
    """
    linear_cache, activation_cache = cache

    if activation == "relu":
        dZ = relu_backward(dA, activation_cache)
        dA_prev, dW, db = linear_backward(dZ, linear_cache)
    elif activation == "sigmoid":
        dZ = sigmoid_backward(dA, activation_cache)
        dA_prev, dW, db = linear_backward(dZ, linear_cache)

    return dA_prev, dW, db

L層模型反向傳播

L層模型反向傳播的流程,如圖所示:

使用這個公式實現反向傳播:
$$grads[“dW” + str(l)] = dW^{[l]}\tag{9} $$

def L_model_backward(AL, Y, caches):
    """
    實現[線性->RELU] * (L-1) ->線性-> SIGMOID組的反向傳播。
    :param AL: 概率向量,正向傳播的輸出(L_model_forward())
    :param Y: true“label”vector(如果非cat,則包含0)
    :param caches: 緩存包含列表:
                所有的緩存來自linear_activation_forward()的"relu" (它是caches[l], for l in range(L-1) i.e l = 0...L-2)
                緩存來自linear_activation_forward()的"sigmoid" (它是caches[L-1])
    :return: 梯度字典:
             grads["dA" + str(l)]
             grads["dW" + str(l)]
             grads["db" + str(l)]
    """
    grads = {}
    L = len(caches)  # the number of layers
    m = AL.shape[1]
    Y = Y.reshape(AL.shape)  # after this line, Y is the same shape as AL

    # Initializing the backpropagation
    dAL = - (np.divide(Y, AL) - np.divide(1 - Y, 1 - AL))

    # Lth layer (SIGMOID -> LINEAR) gradients. Inputs: "AL, Y, caches". Outputs: "grads["dAL"], grads["dWL"], grads["dbL"]
    current_cache = caches[L - 1]
    grads["dA" + str(L - 1)], grads["dW" + str(L)], grads["db" + str(L)] = linear_activation_backward(dAL,
                                                                                                      current_cache,
                                                                                                      activation="sigmoid")

    for l in reversed(range(L - 1)):
        # lth layer: (RELU -> LINEAR) gradients.
        current_cache = caches[l]
        dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads["dA" + str(l + 1)], current_cache,
                                                                    activation="relu")
        grads["dA" + str(l)] = dA_prev_temp
        grads["dW" + str(l + 1)] = dW_temp
        grads["db" + str(l + 1)] = db_temp

    return grads

更新模型參數

使用梯度下降來更新模型的參數,使用到的公式如下:
$$ W^{[l]} = W^{[l]} - \alpha \text{ } dW^{[l]} \tag{10}$$
$$ b^{[l]} = b^{[l]} - \alpha \text{ } db^{[l]} \tag{11}$$

def update_parameters(parameters, grads, learning_rate):
    """
    使用梯度下降來更新參數。
    :param parameters: 包含參數的python字典。
    :param grads: 包含您的梯度的python字典,l_model_back的輸出。
    :param learning_rate: 學習率
    :return: 
    parameters -- 包含更新參數的python字典。
                  parameters["W" + str(l)]
                  parameters["b" + str(l)]
    """
    L = len(parameters) // 2  # number of layers in the neural network

    for l in range(L):
        parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - learning_rate * grads["dW" + str(l + 1)]
        parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - learning_rate * grads["db" + str(l + 1)]
    return parameters

預測正確率

通過傳入數據和對於的標籤,還有模型參數就可以預測數據並計算準確率了。

def predict(X, y, parameters):
    """
    該函數用於預測l層神經網絡的結果。
    :param X: 您想要標記的示例數據集。
    :param y: 正確的標籤
    :param parameters: 訓練模式的參數。
    :return: 
     p -- 對給定數據集X的預測。
    """
    m = X.shape[1]
    n = len(parameters) // 2  # 神經網絡中的層數。
    p = np.zeros((1, m))

    # 正向傳播
    probas, caches = L_model_forward(X, parameters)

    # 將檢驗結果轉換爲0/1預測。
    for i in range(0, probas.shape[1]):
        if probas[0, i] > 0.5:
            p[0, i] = 1
        else:
            p[0, i] = 0

    m = float(m)
    print("Accuracy: " + str(np.sum((p == y) / m)))

    return p

兩層神經網絡模型

構建一個具有以下結構的2層神經網絡:LINEAR - > RELU - > LINEAR - > SIGMOID。

def two_layer_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False):
    """
    實現了兩層神經網絡:LINEAR>RELU->LINEAR->SIGMOID。
    :param X: 輸入數據,形狀(n_x,示例數量)
    :param Y: 真正的“標籤”向量(包含0如果貓,1如果是非貓),形狀(1,例子數量)
    :param layers_dims: 層的維數(n_x, n_h, n_y)
    :param learning_rate: 梯度下降更新規則的學習速率
    :param num_iterations: 優化循環的迭代次數。
    :param print_cost: 如果設置爲True,則每100次迭代將打印成本。
    :return: 
    parameters -- 包含W1、W2、b1和b2的字典
    """
    grads = {}
    costs = []
    m = X.shape[1]  # number of examples
    (n_x, n_h, n_y) = layers_dims

    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(0, num_iterations):

        # 正向傳播: LINEAR -> RELU -> LINEAR -> SIGMOID
        A1, cache1 = linear_activation_forward(X, W1, b1, activation="relu")
        A2, cache2 = linear_activation_forward(A1, W2, b2, activation="sigmoid")

        # 計算損失
        cost = compute_cost(A2, Y)

        # 初始化反向傳播
        dA2 = - (np.divide(Y, A2) - np.divide(1 - Y, 1 - A2))

        # 反向傳播
        dA1, dW2, db2 = linear_activation_backward(dA2, cache2, activation="sigmoid")
        dA0, dW1, db1 = linear_activation_backward(dA1, cache1, activation="relu")
        grads['dW1'] = dW1
        grads['db1'] = db1
        grads['dW2'] = dW2
        grads['db2'] = db2

        # 更新參數。
        parameters = update_parameters(parameters, grads, learning_rate)
        W1 = parameters["W1"]
        b1 = parameters["b1"]
        W2 = parameters["W2"]
        b2 = parameters["b2"]

        # 打印每100個培訓實例的成本。
        if print_cost and i % 100 == 0:
            print("Cost after iteration {}: {}".format(i, np.squeeze(cost)))
        if print_cost and i % 100 == 0:
            costs.append(cost)

    # plot the 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

L層神經網絡模型

構建一個 該該 具有以下結構的L層狀神經網絡:[LINEAR→RELU] * (L-1) - > LINEAR - > SIGMOID

def L_layer_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False):
    """
    實現一個l層神經網絡:[LINEAR->RELU]*(L-1)->LINEAR->SIGMOID。
    :param X: 數據,形狀的numpy數組(示例的數量,num_px * num_px * 3)
    :param Y: :真正的“標籤”向量(包含0如果貓,1如果是非貓),形狀(1,例子數量)
    :param layers_dims: 包含輸入大小和每層長度的列表(層數+ 1)。
    :param learning_rate: 梯度下降更新規則的學習速率。
    :param num_iterations: 優化循環的迭代次數。
    :param print_cost: 如果是真的,它將每100步打印成本。
    :return: 
    parameters -- 由模型學習的參數。他們可以被用來預測。
    """
    costs = []
    parameters = initialize_parameters_deep(layers_dims)
    # 循環(梯度下降)
    for i in range(0, num_iterations):
        # 正向傳播: [LINEAR -> RELU]*(L-1) -> LINEAR -> SIGMOID.
        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)

        # 打印每100個培訓實例的成本。
        if print_cost and i % 100 == 0:
            print ("Cost after iteration %i: %f" % (i, cost))
        if print_cost and i % 100 == 0:
            costs.append(cost)

    # plot the 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

預測自己的圖像

這個函數是用來預測自己的圖像的,可以自行修剪圖像的大小,滿足訓練時的大小。

def infer_image(my_image,parameters,num_px):
    my_label_y = [1]  # the true class of your image (1 -> cat, 0 -> non-cat)

    fname = "images/" + my_image
    image = np.array(ndimage.imread(fname, flatten=False))
    my_image = scipy.misc.imresize(image, size=(num_px, num_px)).reshape((num_px * num_px * 3, 1))
    my_image = my_image / 255.
    my_predicted_image = predict(my_image, my_label_y, parameters)

    plt.imshow(image)
    print ("y = " + str(np.squeeze(my_predicted_image)) + ", your L-layer model predicts a \"" + classes[
        int(np.squeeze(my_predicted_image)),].decode("utf-8") + "\" picture.")

模型的使用

這使用兩種模型,一個是兩層的模型,另一個是L層的模型。

兩層模型的使用

使用兩層神經網絡優化參數

if __name__ == "__main__":
    # 獲取數據
    train_x_orig, train_y, test_x_orig, test_y, classes = load_dataset()

    # 重塑培訓和測試範例。
    train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T
    test_x_flatten = test_x_orig.reshape(test_x_orig.shape[0], -1).T

    # 將數據標準化,使其具有0到1之間的特徵值
    train_x = train_x_flatten / 255.
    test_x = test_x_flatten / 255.

    layers_dims_two = (12288, 7, 1)  # n_x =  num_px * num_px * 3
    parameters = two_layer_model(train_x, train_y, layers_dims_two, num_iterations=2500, print_cost=True)
    predictions_train = predict(train_x, train_y, parameters)
    predictions_test = predict(test_x, test_y, parameters)

運行後輸出的結果是:

Cost after iteration 0: 0.694163741553
Cost after iteration 100: 0.648266362508
Cost after iteration 200: 0.637126344142
Cost after iteration 300: 0.611710351257
.......
Cost after iteration 2100: 0.0505762788807
Cost after iteration 2200: 0.0453126197353
Cost after iteration 2300: 0.0409255847312
Cost after iteration 2400: 0.0372231796013
Accuracy: 1.0
Accuracy: 0.68

其對應的折線圖:

L層模型的使用

使用深度神經網絡優化參數:

if __name__ == "__main__":
    # 獲取數據
    train_x_orig, train_y, test_x_orig, test_y, classes = load_dataset()

    # 重塑培訓和測試範例。
    train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T
    test_x_flatten = test_x_orig.reshape(test_x_orig.shape[0], -1).T

    # 將數據標準化,使其具有0到1之間的特徵值
    train_x = train_x_flatten / 255.
    test_x = test_x_flatten / 255.

    layers_dims_l = [12288, 20, 7, 5, 1]
    parameters = L_layer_model(train_x, train_y, layers_dims_l, num_iterations=2500, print_cost=True)
    pred_train = predict(train_x, train_y, parameters)
    pred_test = predict(test_x, test_y, parameters)

深度神經網絡輸出的日誌如下:

Cost after iteration 0: 0.693828
Cost after iteration 100: 0.533567
Cost after iteration 200: 0.500737
Cost after iteration 300: 0.409495
.....
Cost after iteration 2100: 0.023786
Cost after iteration 2200: 0.022884
Cost after iteration 2300: 0.022056
Cost after iteration 2400: 0.021382
Accuracy: 0.980861244019
Accuracy: 0.7

其對應的折線圖如下:

預測自己的圖像

訓練好的模型也可以用來預測模型自己的圖像:

if __name__ == "__main__":
    # 獲取數據
    train_x_orig, train_y, test_x_orig, test_y, classes = load_dataset()

    # 重塑培訓和測試範例。
    train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T
    test_x_flatten = test_x_orig.reshape(test_x_orig.shape[0], -1).T

    # 將數據標準化,使其具有0到1之間的特徵值
    train_x = train_x_flatten / 255.
    test_x = test_x_flatten / 255.

    layers_dims_l = [12288, 20, 7, 5, 1]
    parameters = L_layer_model(train_x, train_y, layers_dims_l, num_iterations=2500, print_cost=True)
    infer_image('images/cat2.jpg', parameters, train_x_orig.shape[1])

預測的結果如下:

y = 1.0, your L-layer model predicts a "cat" picture.

參考資料

  1. http://deeplearning.ai/




該筆記是學習吳恩達老師的課程寫的。初學者入門,如有理解有誤的,歡迎批評指正!

小夜