目錄¶
@[toc]
前言¶
數據集是一個紅色和藍色的的分佈。其分佈圖如下:

導包¶
導入依賴包,這個兩個分別是加載數據的工具函數和數據集,這個兩個程序可以在這裏下載。這個工具函數中使用到sklearn包,使用之前還要使用pip安裝該函數。
from planar_utils import sigmoid, load_planar_dataset
from testCases_v2 import *
加載數據¶
加載數據和獲取數據的形狀
# 加載數據
X, Y = load_planar_dataset()
# 獲取數據的形狀
shape_X = X.shape
shape_Y = Y.shape
m = shape_X[1]
神經網絡模型¶
定義神經網絡結構¶
定義神經網絡結構,比如數據的大小,對應的標籤和有多少個隱層。
def layer_sizes(X, Y):
"""
定義神經網絡結構
:param X: 形狀的輸入數據集(輸入大小,示例數量)
:param Y: 形狀標籤(輸出尺寸,示例數量)
:return:
n_x -- 輸入層的大小。
n_h -- 隱藏層的大小。
n_y -- 隱藏層的大小。。
"""
n_x = X.shape[0]
n_h = 4
n_y = Y.shape[0]
return (n_x, n_h, n_y)
初始化模型的參數¶
根據神經網絡的結構來初始化模型權重和偏置值,並把權重和偏置值存放在參數字典中。權重向量使用隨機初始化,偏置向量初始化爲零矩陣。
def initialize_parameters(n_x, n_h, n_y):
"""
初始化模型的參數
:param n_x: 輸入層的大小
:param n_h: 隱藏層的大小
:param n_y: 隱藏層的大小
:return:
params --包含您的參數的python字典:
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((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
正向傳播¶
這個正向傳播使用了兩個激活函數,一個是tanh函數,另一個是sigmoid函數。
def forward_propagation(X, parameters):
"""
向前傳播
:param X: 輸入數據大小(n_x, m)
:param parameters: 包含參數的python字典(初始化函數的輸出)
:return:
A2 -- 第二個激活的sigmoid輸出。
cache -- 包含“Z1”、“A1”、“Z2”和“A2”的字典
"""
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
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
計算損失函數¶
以下就是要計算的損失函數的公式:
\(\(J = - \frac{1}{m} \sum\limits_{i = 0}^{m} \large{(} \small y^{(i)}\log\left(a^{[2] (i)}\right) + (1-y^{(i)})\log\left(1- a^{[2] (i)}\right) \large{)} \small\tag{1}\)\)
def compute_cost(A2, Y):
"""
計算公式(1)中的交叉熵成本
:param A2: 第二次激活的sigmoid輸出,形狀(1,示例數量)
:param Y: “真”標籤向量的形狀(1,樣本數目)
:return:
cost -- 交叉熵成本方程(1)
"""
m = Y.shape[1] # number of example
logprobs = np.multiply(np.log(A2), Y) + np.multiply(1 - Y, np.log(1 - A2))
cost = -(np.sum(logprobs)) / m
cost = np.squeeze(cost) # 確保成本是我們期望的尺寸。
assert (isinstance(cost, float))
return cost
反向傳播¶
反向傳播使用到了以下這些公式:

def backward_propagation(parameters, cache, X, Y):
"""
使用上面的說明實現反向傳播。
:param parameters: 包含我們的參數的python字典。
:param cache: 包含“Z1”、“A1”、“Z2”和“A2”的字典。
:param X: 形狀輸入數據(2,實例數)
:param Y: “真”標籤向量的形狀(1,樣本數目)
:return:
grads -- 包含不同參數的漸變的python字典
"""
m = X.shape[1]
m = float(m)
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.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
更新參數¶
實施更新規則。使用梯度下降。您必須使用(dW1,db1,dW2,db2)才能更新(W1,b1,W2,b2),使用到更新的規則公式如下:
$$ \theta = \theta - \alpha \frac{\partial J }{ \partial \theta }\tag{2}$$
def update_parameters(parameters, grads, learning_rate=1.2):
"""
使用上面給出的梯度下降更新規則更新參數。
:param parameters: 包含參數的python字典。
:param grads: 包含梯度的python字典。
:param learning_rate: 學習率
:return:
parameters -- 包含更新參數的python字典。
"""
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
dW1 = grads["dW1"]
db1 = grads["db1"]
dW2 = grads["dW2"]
db2 = 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
集成model函數¶
把上面定義的神經網絡結構的函數集成到這個函數中,形成一個完整的神經網絡。
def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False):
"""
把上面定義的神經網絡集成到這個函數
:param X: 形狀數據集(2,樣本數目)
:param Y: 形狀標籤(1,樣本數目)
:param n_h: 隱藏層的大小
:param num_iterations: 梯度下降循環的迭代次數。
:param print_cost: 如果是真的,打印每1000次迭代的成本。
:return:
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)
for i in range(0, num_iterations):
A2, cache = forward_propagation(X, parameters)
cost = compute_cost(A2, Y)
grads = backward_propagation(parameters, cache, X, Y)
parameters = update_parameters(parameters, grads)
if print_cost and i % 1000 == 0:
print ("Cost after iteration %i: %f" % (i, cost))
return parameters
預測結果¶
使用您的模型通過構建predict()來進行預測。使用向前傳播來預測結果。
\(\(y_{prediction} = \mathbb 1 \text{{activation > 0.5}} = \begin{cases}
1 & \text{if}\ activation > 0.5 \\
0 & \text{otherwise}
\end{cases}\tag{3}\)\)
def predict(parameters, X):
"""
使用學習的參數,爲X中的每個例子預測一個類。
:param parameters: 包含參數的python字典。
:param X: 輸入數據大小(n_x, m)
:return:
predictions -- 模型預測向量(紅色:0 / blue: 1)
"""
A2, cache = forward_propagation(X, parameters)
predictions = A2 > 0.5
return predictions
測試其他隱層¶
通過測試不用的隱層數量,觀察模型的預測效果,獲得最優的隱層數量。
def test_anther_hidden():
"""
使用不同的隱層訓練
:return:
"""
hidden_layer_sizes = [1, 2, 3, 4, 5, 20, 50]
for i, n_h in enumerate(hidden_layer_sizes):
parameters = nn_model(X, Y, n_h, num_iterations=1000)
predictions = predict(parameters, X)
accuracy = float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100)
print ("Accuracy for {} hidden units: {} %".format(n_h, accuracy))
調用函數訓練¶
通過調用剛纔集成的神經網絡函數nn_model()來訓練參數,獲得參數之後就可以是參數預測數據了。
if __name__ == "__main__":
parameters = nn_model(X, Y, n_h=4, num_iterations=10000, print_cost=True)
predictions = predict(parameters, X)
print 'Accuracy: %d' % float(
(np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%'
訓練和預測輸出的結果是:
Cost after iteration 0: 0.693048
Cost after iteration 1000: 0.288083
Cost after iteration 2000: 0.254385
Cost after iteration 3000: 0.233864
Cost after iteration 4000: 0.226792
Cost after iteration 5000: 0.222644
Cost after iteration 6000: 0.219731
Cost after iteration 7000: 0.217504
Cost after iteration 8000: 0.219415
Cost after iteration 9000: 0.218547
Accuracy: 90%
這個使用的是不同的隱層訓練和預測
if __name__ == "__main__":
test_anther_hidden()
以下就是不同的隱層訓練後得到的不同準確率。
Accuracy for 1 hidden units: 67.75 %
Accuracy for 2 hidden units: 65.25 %
Accuracy for 3 hidden units: 89.5 %
Accuracy for 4 hidden units: 89.25 %
Accuracy for 5 hidden units: 89.5 %
Accuracy for 20 hidden units: 88.0 %
Accuracy for 50 hidden units: 88.0 %
所有代碼¶
爲了方便讀者閱讀代碼,這裏放出了所有的代碼(除了那兩個工具類):
# coding=utf-8
from planar_utils import sigmoid, load_planar_dataset
from testCases_v2 import *
# 加載數據
X, Y = load_planar_dataset()
# 獲取數據的形狀
shape_X = X.shape
shape_Y = Y.shape
m = shape_X[1]
def layer_sizes(X, Y):
"""
定義神經網絡結構
:param X: 形狀的輸入數據集(輸入大小,示例數量)
:param Y: 形狀標籤(輸出尺寸,示例數量)
:return:
n_x -- 輸入層的大小。
n_h -- 隱藏層的大小。
n_y -- 隱藏層的大小。。
"""
n_x = X.shape[0]
n_h = 4
n_y = Y.shape[0]
return (n_x, n_h, n_y)
def initialize_parameters(n_x, n_h, n_y):
"""
初始化模型的參數
:param n_x: 輸入層的大小
:param n_h: 隱藏層的大小
:param n_y: 隱藏層的大小
:return:
params --包含您的參數的python字典:
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((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
def forward_propagation(X, parameters):
"""
向前傳播
:param X: 輸入數據大小(n_x, m)
:param parameters: 包含參數的python字典(初始化函數的輸出)
:return:
A2 -- 第二個激活的sigmoid輸出。
cache -- 包含“Z1”、“A1”、“Z2”和“A2”的字典
"""
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
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):
"""
計算公式(13)中的交叉熵成本
:param A2: 第二次激活的sigmoid輸出,形狀(1,示例數量)
:param Y: “真”標籤向量的形狀(1,樣本數目)
:return:
cost -- 交叉熵成本方程(13)
"""
m = Y.shape[1] # number of example
logprobs = np.multiply(np.log(A2), Y) + np.multiply(1 - Y, np.log(1 - A2))
cost = -(np.sum(logprobs)) / m
cost = np.squeeze(cost) # 確保成本是我們期望的尺寸。
assert (isinstance(cost, float))
return cost
def backward_propagation(parameters, cache, X, Y):
"""
使用上面的說明實現反向傳播。
:param parameters: 包含我們的參數的python字典。
:param cache: 包含“Z1”、“A1”、“Z2”和“A2”的字典。
:param X: 形狀輸入數據(2,實例數)
:param Y: “真”標籤向量的形狀(1,樣本數目)
:return:
grads -- 包含不同參數的漸變的python字典
"""
m = X.shape[1]
m = float(m)
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.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):
"""
使用上面給出的梯度下降更新規則更新參數。
:param parameters: 包含參數的python字典。
:param grads: 包含梯度的python字典。
:param learning_rate: 學習率
:return:
parameters -- 包含更新參數的python字典。
"""
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
dW1 = grads["dW1"]
db1 = grads["db1"]
dW2 = grads["dW2"]
db2 = 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=10000, print_cost=False):
"""
把上面定義的神經網絡集成到這個函數
:param X: 形狀數據集(2,樣本數目)
:param Y: 形狀標籤(1,樣本數目)
:param n_h: 隱藏層的大小
:param num_iterations: 梯度下降循環的迭代次數。
:param print_cost: 如果是真的,打印每1000次迭代的成本。
:return:
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)
for i in range(0, num_iterations):
A2, cache = forward_propagation(X, parameters)
cost = compute_cost(A2, Y)
grads = backward_propagation(parameters, cache, X, Y)
parameters = update_parameters(parameters, grads)
if print_cost and i % 1000 == 0:
print ("Cost after iteration %i: %f" % (i, cost))
return parameters
def predict(parameters, X):
"""
使用學習的參數,爲X中的每個例子預測一個類。
:param parameters: 包含參數的python字典。
:param X: 輸入數據大小(n_x, m)
:return:
predictions -- 模型預測向量(紅色:0 / blue: 1)
"""
A2, cache = forward_propagation(X, parameters)
predictions = A2 > 0.5
return predictions
def test_anther_hidden():
"""
使用不同的隱層訓練
:return:
"""
hidden_layer_sizes = [1, 2, 3, 4, 5, 20, 50]
for i, n_h in enumerate(hidden_layer_sizes):
parameters = nn_model(X, Y, n_h, num_iterations=1000)
predictions = predict(parameters, X)
accuracy = float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100)
print ("Accuracy for {} hidden units: {} %".format(n_h, accuracy))
if __name__ == "__main__":
parameters = nn_model(X, Y, n_h=4, num_iterations=10000, print_cost=True)
predictions = predict(parameters, X)
print 'Accuracy: %d' % float(
(np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%'
# test_anther_hidden()
參考資料¶
- http://deeplearning.ai/
該筆記是學習吳恩達老師的課程寫的。初學者入門,如有理解有誤的,歡迎批評指正!