吳恩達學習-深層神經網路
深度學習是指神經網路包含了很多層的隱層,比如說10層20層這樣,有些問題用淺層神經網路不能得到很好的優化,只能通過深層神經網路優化,這是因為深層神經網路有其獨特的優勢,下面我們就先介紹深層神經網路的優勢。
1.深層神經網路的優勢
1.深層神經網路的一大優勢就是優化演算法的區域性最優解問題
之前訓練淺層神經網路時,經常會陷入區域性最優解,而無法找到全域性最優解,如下圖所示(圖來自吳恩達老師講義)。
這種問題出現在深度學習網路的概率非常小,我們假設深度神經網路中有n個引數,每個引數在某點取得極小值的概率為p,則所有引數在同一點取得極小值的概率為p的n次方,這個概率是相當小的。在深度學習裡,會經常出現的是鞍點,如下圖所示(圖來自吳恩達老師講義):
鞍點處的梯度為0,所有在鞍點時,同樣會被困住。但是困在鞍點並不容易發生,只是存在一定的概率。可怕的是在處於馬鞍面上時,梯度接近於0,這時候下降速度將會非常緩慢。所幸的是已經有很多方法加快收斂速度(比如mini-batch、momentum、Adam等),從而避免這種情況的發生。所以,在深度學習中,不很在意區域性最優解問題,而會在意加快收斂速度問題。
2.深度學習為什麼會奏效
吳老師給了一個直觀的解釋,如下圖(圖來自吳恩達老師講義),用深度學習做人臉時,第一層節點可能就是做簡單的邊緣檢測,第二層將第一層的結果組合,出來簡單的器官,比如眼睛、眉毛等,第三層再將這些器官組合,一直到最後一層。每走一層,都會更加複雜,最後組合出人臉的樣子。
2.前向傳播
深度學習前向傳播與淺層神經網路前向傳播一樣,假設有L層,則前向傳播如下:
3.成本函式
深度學習的成本函式和淺層神經網路的成本函式形式相同,不同的是深度學習的成本函式包含更多的引數。
深度學習的損失函式:
對於多個樣本,成本函式為:
4.反向傳播
深度學習的反向傳播與淺層神經網路的反向傳播相同,都是反向優化引數,不同的是深度學習的反向傳播有多層引數優化,需要逐層逐層的優化,反向傳播的公式如下(推導過程略):
對於單個樣本而言,反向傳播如下
對於多個樣本而言,反向傳播如下
5.初始化引數
在深度學習中初始化引數極為重要,在Logistic Regression中可以將W和b都初始化為0。但是在深度學習中,如果將W初始化為0,則每層節點的輸出都是相同的,假設某層節點有10個,則10個節點只能當一個用,這就無法發揮出深度學習的優勢。深度學習中,將隨機生成W。當然在隨機生成W時,為了防止梯度爆炸或消失,還需要一定的技巧,這在優化引數時再講。
6.Python原始碼
將以上過程寫成Python程式碼如下,在寫反向傳播時隱藏了一個bug,調了整整兩天,才找到bug,其實就是一個很小的錯誤,但影響是很大的,所以還是要多加細心啊☺!
import numpy as np
import matplotlib.pyplot as plt
from testCases import *
import sklearn
import sklearn.datasets
import sklearn.learning_curve
from planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset, load_extra_datasets
%matplotlib inline
np.random.seed(1)
def layer_sizes(X, Y, n_h):
n_x = X.shape[0]
n_y = Y.shape[0]
n_h.insert(0, n_x)
n_h.append(n_y)
return n_h
def initialize_parameters(n_h):
np.random.seed(2)
W = []
b = []
layer_size = np.shape(n_h)[0]
for i in range(layer_size - 1):
W_i = np.random.randn(n_h[i + 1], n_h[i]) / np.sqrt(n_h[i] / 2)
b_i = np.zeros((n_h[i + 1], 1))
W.append(W_i)
b.append(b_i)
assert(np.shape(W)[0] == layer_size - 1)
assert(np.shape(b)[0] == layer_size - 1)
paramters = {"W":W,
"b":b}
return paramters
def forword_propagation(X, parameters):
W = parameters["W"]
b = parameters["b"]
n_size = np.shape(W)[0]
Z = []
A = [X]
A_i_former = X
for i in range(n_size):
W_i = W[i]
b_i = b[i]
Z_i = np.dot(W_i, A_i_former) + b_i
A_i = np.zeros((W_i.shape[0], A_i_former.shape[1]))
if(i == n_size - 1):
A_i = sigmoid(Z_i)
else:
A_i = np.tanh(Z_i)
#A_i = np.maximum(Z_i, 0)
Z.append(Z_i)
A.append(A_i)
A_i_former = A_i
A_final = A[np.shape(A)[0] - 1]
cache = {"A": A,
"Z": Z}
return A_final, cache
def compute_cost(A_final, Y):
m = float(Y.shape[1])
loss = np.dot(Y, np.log(A_final).T) + np.dot(1 - Y, np.log(1 - A_final).T)
cost = -1 / m * np.sum(loss)
cost = np.squeeze(cost)
assert(isinstance(cost, float))
return cost
def backword_propagation(Y, parameters, cache):
W = parameters["W"]
b = parameters["b"]
Z = cache["Z"]
A = cache["A"]
n = np.shape(A)[0]
m = float(Y.shape[1])
dW_n = np.shape(W)[0]
db_n = np.shape(b)[0]
dW = range(dW_n)
db = range(db_n)
dZ_final = A[n - 1] - Y
dW_final = 1 / m * np.dot(dZ_final, A[n - 2].T)
db_final = 1 / m * np.sum(dZ_final, axis=1, keepdims=True)
dW[dW_n - 1] = dW_final
db[dW_n - 1] = db_final
dZ_last = dZ_final
i = dW_n - 2
while i >= 0:
#print "dZ_last" + str(dZ_last)
dW_last = dW[i + 1]
dZ_i = np.dot(W[i + 1].T, dZ_last) * (1 - np.power(A[i + 1], 2))
#dZ_i = np.dot(W[i + 1].T, dZ_last) * np.int64(A[i + 1] > 0)
dW_i = 1 / m * np.dot(dZ_i, A[i].T)
db_i = 1 / m * np.sum(dZ_i, axis=1, keepdims=True)
dZ_last = dZ_i
dW[i] = dW_i
db[i] = db_i
i = i - 1
#print "dZ_i" + str(dZ_i)
#print "dW_last" + str(dW_last)
#print "A" + str(A[1])
grads = {"dW":dW,
"db":db}
return grads
def update_parameters(parameters, grads, learning_rate = 1.2):
W = parameters["W"]
b = parameters["b"]
dW = grads["dW"]
db = grads["db"]
for i in range(np.shape(W)[0]):
W[i] = W[i] - learning_rate * dW[i]
b[i] = b[i] - learning_rate * db[i]
parameters = {"W": W,
"b": b}
return parameters
def deep_learning_model(X, Y, n_h, iteration_num = 10000, learning_rate = 1.2, show_cost = True):
np.random.seed(3)
n_h = layer_sizes(X, Y, n_h)
parameters = initialize_parameters(n_h)
for i in range(iteration_num):
A_final, cache = forword_propagation(X, parameters)
#print A_final, cache
cost = compute_cost(A_final, Y)
#print cost
grads = backword_propagation(Y, parameters, cache)
#print grads
parameters = update_parameters(parameters, grads, learning_rate)
#print parameters
if show_cost and i % 1000 == 0:
print cost
return parameters
def predict(X, parameters):
A_final, cache = forword_propagation(X, parameters)
predictions = (A_final >= 0.5)
return predictions