深层神经网络的构建18号的时候就已经学完了,自己写激活函数导数的时候遇到了一点困难,再加上懒癌发作,现在才弄到博客上来。

本次需要构建一个深层的神经网络,层数可以在训练时确定,主要流程跟之前的两次实践仍然是计算量的差别。主要流程还是一致的:

  1. 初始化参数Wb
  2. 根据Wb以及输入X求得输出ZA
  3. 根据输入X和输出ZA求得梯度下降量dWdb
  4. 使用dWdb来更新Wb
  5. 循环2-5直至满足学习终止条件,如迭代300次。

算法实现

假定训练集输入为X,训练集结果为Y
在实现流程之前依然是加载使用到的python

1
2
import numpy as np
import math

初始化参数Wb

因为我们构建的是一个深层网络,所以对每一层都需要进行参数初始化

1
2
3
4
5
6
7
8
9
10
11
def initial(layers_dims):
# layders_dims:每一层神经网络的神经元个数
L = len(layers_dims)
parameters = {}
for i in range(1, L):
W = np.randm.randn(layers[l], layers[l - 1]) * 0.01
b = np.zeros((layers[1], 1))
parameters["W" + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1])
parameters["b" + str(l)] = np.zeros((layers_dims[l]))

return parameters

根据Wb、输入X求得输出AZ

根据前向公式计算输出AZ

前向公式
前向公式

两个激活函数已经在math以及numpy中实现了,直接调用即可。

1
2
3
4
5
6
7
8
9
10
def forward(W, b, X, activation):

Z = np.dot(W, X) + b

if activation == "sigmoid":
A = sigmoid(Y)
elif activation == "relu":
A = relu(Y)

return A, Z

前向传播函数实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def forward_progate(parameters, X):

caches = []
A = X
L = len(parameters) // 2

for l in range(1, L):
cache = {}
A_pre = A
A, Z = forward(parameters["W" + str(l)], parameters["b" + str(l)], A_prev, "relu")
cache["A" + str(l)] = A
cache["Z" + str(l)] = Z
caches.append(cache)

AL, ZL = forward(parameters["W" + str(L)], parameters["b" + str(L)], caches[L]["A" + str(L - 1)], "sigmoid")

cache = {"A" + str(L): AL, "Z" + str(L): ZL}
caches.append(cache)

return AL, caches

根据XYAdWdb

根据反向传播公式求出dWdb,这一步主要由两个函数构成,一个是之前的反向求导,另外一个就是激活函数的导数了。

反向公式
反向公式
1
2
3
4
5
6
7
def activation_back(Z, activation):

if activation == "sigmoid":
Y = sigmoid(Z) * (1 - sigmoid(Z))
elif activation == "relu":
Y = (Y > 0)
return Y

反向求导

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def backward_progate(caches, AL, parameters):
m = Y.shape[1]
dAL = -(np.divide(Y, AL) - np.divide(1 - Y, 1 - AL))
grads = {}
L = parameters // 2

dZ = dAL * activation_back(Z, "relu")
dW = np.dot(dZ, A) / m
db = np.sum(dZ, axis = 1, keepdims = True) / m
dA = np.sot(parameters["W" + str(L)].T, dZ)
grads["db" + str(l)] = db
grads["dW" + str(l)] = dW

for l in reversed(range(L)):
cache = caches[l]
Z = cache["Z" + str(l)]
A = cache["A" + str[l]]
dZ = dA * activation_back(Z, "relu")
dW = np.dot(dZ, A) / m
db = np.sum(dZ, axis = 1, keepdims = True) / m
dA = np.sot(parameters["W" + str(L)].T, dZ)
grads["db" + str(l)] = db
grads["dW" + str(l)] = dW

return grads

使用dWdb来更新Wb

根据公式更新参数Wb

更新参数
更新参数
1
2
3
4
5
6
7
8
9
10
11
12
def update_parameters(parameters, grads, learning_rate = 1.2):
# learning process, update parameters with grads
# parameters: W1, W2, b1, b2
# grads: dW1, dW2, db1, db2

L = parameters // 2

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

return parameters

建立深层神经网络

为简单起见,这里建立一个4层的神经网络,每一层但神经单元分别是5,3,2,1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def nn_models(X, Y, iterations):
# whole netrue network model of 2 layer
# n_h: the number of units in the hidden layer
# iterations: times of learning


layers_dims = [X.shape[0], 5, 3, 2, Y.shape[0]]

parameters = random_initial(layers_dims)

for i in range(0, iterations):
# AL is the output of model
# cache store Z and A of each layer
AL, caches = forward_progate(parameters, X)

# get grads of each layer
grads = backward_progate(caches, AL, parameters)

# update parameters of each layer
parameters = update_parameters(parameters, grads)

return parameters

结果

使用这个神经网络对包含“猫”的图片进行识别,经过2500次的迭代学习,最终这个神经网络对训练集的识别准确率达到了98.5%,而测试集的准确率从第一次作业的72%提升到80%。不过这个神经网络其实还存在过拟合的问题,训练集与测试集的差距较大,之后的课程会对过拟合以及超参数进行优化。

至此,吴恩达老师的深度学习课程中的第一门课已经全部完成。