吳恩達深度學習第一課--第三週神經網絡基礎作業下代碼實現

聲明

首先聲明本文參考:https://blog.csdn.net/u013733326/article/details/79702148,我基於他的文章加以自己的理解發表這篇博客,力求理解吸收掌握吳恩達的視頻,如有不妥的地方歡迎大家指正。

前言

博主使用python版本3.7.0
我們要建立具有一個隱藏層的平面數據分類神經網絡。構建神經網絡的一般方法是:

  1. 定義神經網絡結構(輸入單元、隱藏單元、輸出單元數量等)
  2. 初始化模型的參數(w、b)
  3. 循環
  • 實施前向傳播
  • 計算損失
  • 實現後向傳播
  • 更新參數(梯度下降)
  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

#%matplotlib inline #如果你使用用的是Jupyter Notebook的話請取消註釋。

np.random.seed(1) #設置一個固定的隨機種子,以保證接下來的步驟中我們的結果是一致的。

加載和查看數據集

下面的代碼會將一個花的圖案的2類數據集加載到變量X和Y中。

X, Y = load_planar_dataset()

把數據集加載完成了,然後使用matplotlib可視化數據集,代碼如下:

t.scatter(X[0, :], X[1, :], c=Y, s=40, cmap=plt.cm.Spectral) #繪製散點圖

# 上一語句如出現問題,請使用下面的語句:
plt.scatter(X[0, :], X[1, :], c=np.squeeze(Y), s=40, cmap=plt.cm.Spectral) #繪製散點圖

在這裏插入圖片描述
數據看起來像一朵紅色(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) + " 個")

運行結果爲:

X的維度爲: (2, 400)
Y的維度爲: (1, 400)
數據集裏面的數據有:400

搭建神經網絡

我們要搭建的神經網絡模型如下圖:
在這裏插入圖片描述
構建神經網絡的一般方法是:

  1. 定義神經網絡結構(輸入單元、隱藏單元、輸出單元數量等)
  2. 初始化模型的參數(w、b)
  3. 循環
  • 實現前向傳播
  • 計算損失
  • 實現後向傳播
  • 更新參數(梯度下降)
  1. 將上訴功能合併到一個nn_model()函數中,構建好了nn_model(),並學習了正確的參數,就可以預測新的數據。

定義神經網絡結構

在構建之前,我們要先把神經網絡的結構給定義好:

n_x: 輸入層的數量
n_h: 隱藏層的數量(這裏設置爲4)
n_y: 輸出層的數量

def layer_sizes(X , Y):
    """
    參數:
     X - 輸入數據集,維度爲(輸入的數量,訓練/測試的數量)
     Y - 標籤,維度爲(輸出的數量,訓練/測試數量)
    
    返回:
     n_x - 輸入層的數量
     n_h - 隱藏層的數量
     n_y - 輸出層的數量
    """
    n_x = X.shape[0] #輸入層
    n_h = 4 #,隱藏層,硬編碼爲4
    n_y = Y.shape[0] #輸出層
    
    return (n_x,n_h,n_y)

#測試layer_sizes
print("=========================測試layer_sizes=========================")
X_asses , Y_asses = layer_sizes_test_case()
(n_x,n_h,n_y) =  layer_sizes(X_asses,Y_asses)
print("輸入層的節點數量爲: n_x = " + str(n_x))
print("隱藏層的節點數量爲: n_h = " + str(n_h))
print("輸出層的節點數量爲: n_y = " + str(n_y))

=========================測試layer_sizes=========================
輸入層的節點數量爲: n_x = 5
隱藏層的節點數量爲: n_h = 4
輸出層的節點數量爲: n_y = 2

初始化模型的參數

在這裏,我們要實現函數initialize_parameters()。我們要確保我們的參數大小合適,如果需要的話,請參考上面的神經網絡圖。
我們將會用隨機值初始化權重矩陣。

  • np.random.randn(a,b)* 0.01來隨機初始化一個維度爲(a,b)的矩陣。
    將偏向量初始化爲零。

  • np.zeros((a,b))用零初始化矩陣(a,b)。

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
#測試initialize_parameters
print("=========================測試initialize_parameters=========================")    
n_x , n_h , n_y = initialize_parameters_test_case()
parameters = initialize_parameters(n_x , n_h , n_y)
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
=========================測試initialize_parameters=========================
W1 = [[-0.00416758 -0.00056267]
 [-0.02136196  0.01640271]
 [-0.01793436 -0.00841747]
 [ 0.00502881 -0.01245288]]
b1 = [[ 0.]
 [ 0.]
 [ 0.]
 [ 0.]]
W2 = [[-0.01057952 -0.00909008  0.00551454  0.02292208]]
b2 = [[ 0.]]

實現前向傳播

我們現在要實現前向傳播函數forward_propagation()。
我們使用np.tanh()函數。
步驟如下:

  • 使用字典類型的parameters(它是initialize_parameters() 的輸出)檢索每個參數。
  • 實現向前傳播, 計算Z[1],A[1],Z[2],A[2]Z^{[1]},A^{[1]},Z^{[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)
#測試forward_propagation
print("=========================測試forward_propagation=========================") 
X_assess, parameters = forward_propagation_test_case()
A2, cache = forward_propagation(X_assess, parameters)
print(np.mean(cache["Z1"]), np.mean(cache["A1"]), np.mean(cache["Z2"]), np.mean(cache["A2"]))
=========================測試forward_propagation=========================
-0.000499755777742 -0.000496963353232 0.000438187450959 0.500109546852

現在我們已經計算了A[2]A^{[2]}現在我們就可以構建成本函數了。

計算損失

計算成本的公式如下:
J=1mi=0m(Ylog10A[2]+(1Y)log10(1A[2]))J=-\frac{1}{m} \sum_{i=0}^m (Ylog_{10}A^{[2]}+(1-Y)log_{10}(1-A^{[2]}))

def compute_cost(A2,Y,parameters):
    """
    計算方程(6)中給出的交叉熵成本,
    
    參數:
         A2 - 使用sigmoid()函數計算的第二次激活後的數值
         Y - "True"標籤向量,維度爲(1,數量)
         parameters - 一個包含W1,B1,W2和B2的字典類型的變量
    
    返回:
         成本 - 交叉熵成本給出方程(13)
    """
    m = Y.shape[1]
    #計算成本
    cost = float(-(np.sum(Y*np.log(A2)+(1-Y)*np.log(1-A2)))/m)
    assert(isinstance(cost,float))
    
    return cost

#測試compute_cost
print("=========================測試compute_cost=========================") 
A2 , Y_assess , parameters = compute_cost_test_case()
print("cost = " + str(compute_cost(A2,Y_assess,parameters)))

=========================測試compute_cost=========================
cost = 0.6929198937761266

使用正向傳播期間計算的cache,現在可以利用它實現反向傳播。
現在我們要開始實現函數backward_propagation()。

實現後向傳播

構建向量化實現,需要使用這下面的六個方程:
在這裏插入圖片描述
爲了計算dZ1,需要計算g[1](Z[1]),g[1](...)g^{[1]'}(Z^{[1]}),g^{[1]}(...)是tanh函數,若a=g[1](z)a=g^{[1]}(z),那麼g[1](z)=1a2g^{[1]'}(z)=1-a^2。所以我們需要使用(1-np.power(A1,2))來計算g[1](z)g^{[1]'}(z)

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
#測試backward_propagation
print("=========================測試backward_propagation=========================")
parameters, cache, X_assess, Y_assess = backward_propagation_test_case()

grads = backward_propagation(parameters, cache, X_assess, Y_assess)
print ("dW1 = "+ str(grads["dW1"]))
print ("db1 = "+ str(grads["db1"]))
print ("dW2 = "+ str(grads["dW2"]))
print ("db2 = "+ str(grads["db2"]))
=========================測試backward_propagation=========================
dW1 = [[ 0.01018708 -0.00708701]
 [ 0.00873447 -0.0060768 ]
 [-0.00530847  0.00369379]
 [-0.02206365  0.01535126]]
db1 = [[-0.00069728]
 [-0.00060606]
 [ 0.000364  ]
 [ 0.00151207]]
dW2 = [[ 0.00363613  0.03153604  0.01162914 -0.01318316]]
db2 = [[ 0.06589489]]

更新參數

我們需要使用(dW1, db1, dW2, db2)來更新(W1, b1, W2, b2)。需要用到:

  • α\alpha:學習速率。
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
#測試update_parameters
print("=========================測試update_parameters=========================")
parameters, grads = update_parameters_test_case()
parameters = update_parameters(parameters, grads)

print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
=========================測試update_parameters=========================
W1 = [[-0.00643025  0.01936718]
 [-0.02410458  0.03978052]
 [-0.01653973 -0.02096177]
 [ 0.01046864 -0.05990141]]
b1 = [[ -1.02420756e-06]
 [  1.27373948e-05]
 [  8.32996807e-07]
 [ -3.20136836e-06]]
W2 = [[-0.01041081 -0.04463285  0.01758031  0.04747113]]
b2 = [[ 0.00010457]]

整合

把上面的東西整合到nn_model()中,神經網絡模型必須以正確的順序使用先前的功能。

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
#測試nn_model
print("=========================測試nn_model=========================")
X_assess, Y_assess = nn_model_test_case()

parameters = nn_model(X_assess, Y_assess, 4, num_iterations=10000, print_cost=False)
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))
=========================測試nn_model=========================
W1 = [[-4.18494482  5.33220319]
 [-7.52989354  1.24306197]
 [-4.19295428  5.32631786]
 [ 7.52983748 -1.24309404]]
b1 = [[ 2.32926815]
 [ 3.7945905 ]
 [ 2.33002544]
 [-3.79468791]]
W2 = [[-6033.83672179 -6008.12981272 -6033.10095329  6008.06636901]]
b2 = [[-52.66607704]]

預測

構建predict()來使用模型進行預測, 使用向前傳播來預測結果。

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
#測試predict
print("=========================測試predict=========================")

parameters, X_assess = predict_test_case()

predictions = predict(parameters, X_assess)
print("預測的平均值 = " + str(np.mean(predictions)))
=========================測試predict=========================
預測的平均值 = 0.666666666667

試運行

parameters = nn_model(X, Y, n_h = 4, num_iterations=10000, print_cost=True)
predictions = predict(parameters, X)
print ('準確率: %d' % float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%')

#繪製邊界
#plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
#plt.title("Decision Boundary for hidden layer size " + str(4))
0  次循環,成本爲:0.69304802012398231000  次循環,成本爲:0.288083293569018352000  次循環,成本爲:0.254385494073244963000  次循環,成本爲:0.233864150389521964000  次循環,成本爲:0.226792487448540085000  次循環,成本爲:0.222644275492990156000  次循環,成本爲:0.219731404042813167000  次循環,成本爲:0.217503654051312948000  次循環,成本爲:0.219503964694673159000  次循環,成本爲:0.2185709575018246
準確率: 90%

完整代碼

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

#%matplotlib inline #如果你使用用的是Jupyter Notebook的話請取消註釋。

np.random.seed(1) #設置一個固定的隨機種子,以保證接下來的步驟中我們的結果是一致的。

X, Y = load_planar_dataset()
#plt.scatter(X[0, :], X[1, :], c=Y, s=40, cmap=plt.cm.Spectral) #繪製散點圖
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) + " 個")

def layer_sizes(X , Y):
    """
    參數:
     X - 輸入數據集,維度爲(輸入的數量,訓練/測試的數量)
     Y - 標籤,維度爲(輸出的數量,訓練/測試數量)

    返回:
     n_x - 輸入層的數量
     n_h - 隱藏層的數量
     n_y - 輸出層的數量
    """
    n_x = X.shape[0] #輸入層
    n_h = 4 #,隱藏層,硬編碼爲4
    n_y = Y.shape[0] #輸出層

    return (n_x,n_h,n_y)

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

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)

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

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

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

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

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

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))

predictions = predict(parameters, X)
print ('準確率: %d' % float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章