- 不要抄作业!
- 我只是把思路整理了,供个人学习。
- 不要抄作业!
本周的作业分了两个部分,第一部分先构建神经网络的基本函数,第二部分才是构建出模型并预测。
Part1
构建的函数有:
- Initialize the parameters
- two-layer
- L-layer
- forworad propagation
- Linear part 先构建一个线性的计算函数
- linear->activation 在构建某一个神经元的线性和激活函数
- L_model_forward funciton 再融合 L-1次的Relu 和 一次 的 sigmoid最后一层
- Compute loss
- backward propagation
- Linear part
- linear->activation
- L_model_backward funciton
Initialization
初始化使用:
w : np.random.randn(shape)*0.01
b : np.zeros(shape)
1. two-layer
先写了个两层的初始化函数,上周已经写过了。
1 | def initialize_parameters(n_x, n_h, n_y): |
2. L-layer
然后写了个L层的初始化函数,其中,输入的参数是一个列表,如[12,4,3,1],表示一共4层:
1 | def initialize_parameters_deep(layer_dims): |
Forward propagation module
1. Linear Forward
利用公式:
$$Z^{[l]} = W^{[l]}A^{[l-1]} +b^{[l]}$$
where $A^{[0]} = X$.
这个时候,输入的参数是 A,W,b,输出是计算得到的Z,以及cache=(A, W, b)保存起来
1 | def linear_forward(A, W, b): |
2. Linear-Activation Forward
在这里就是把刚才得到的Z,通过$A = g(Z)$激活函数,合并成一个
这个时候,notebook已经给了我们现成的sigmoid和relu函数了,只要调用就行,不过在里面好像没有说明源代码,输出都是A和cache=Z,这里贴出来:
1 | def sigmoid(Z): |
1 | def relu(Z): |
而后利用之前的linear_forward,可以写出某层神经元的前向函数了,输入是$A^{[l-1]},W,b$,还有一个是说明sigmoid还是relu的字符串activation。
输出是$A^{[l]}$和cache,这里的cache已经包含的4个参数了,分别是$A^{[l-1]},W^{[l]},b^{[l]},Z^{[l]}$
1 |
|
3. L-Layer Model
这一步就把多层的神经网络从头到尾串起来了。前面有L-1层的Relu,第L层是sigmoid。
输入是X,也就是$A^{[0]}$,和 parameters包含了各个层的W,b
输出是最后一层的$A^{[L]}$,也就是预测结果$Y_hat$,以及每一层的caches : $A^{[l-1]},W^{[l]},b^{[l]},Z^{[l]}$
1 | def L_model_forward(X, parameters): |
Cost function
$$-\frac{1}{m} \sum\limits_{i = 1}^{m} (y^{(i)}\log\left(a^{[L] (i)}\right) + (1-y^{(i)})\log\left(1- a^{L}\right)) $$
利用np.multiply
and np.sum
求得交叉熵
1 |
|
Backward propagation module
1. Linear backward
首先假设知道 $dZ^{[l]} = \frac{\partial \mathcal{L} }{\partial Z^{[l]}}$,然后想要求得的是$(dW^{[l]}, db^{[l]} dA^{[l-1]})$.
公式已经给你了:
$$ dW^{[l]} = \frac{\partial \mathcal{L} }{\partial W^{[l]}} = \frac{1}{m} dZ^{[l]} A^{[l-1] T} $$
$$db^{[l]} = \frac{\partial \mathcal{L} }{\partial b^{[l]}} = \frac{1}{m} \sum_{i = 1}^{m} dZ^{[l] (i)}$$
$$ dA^{[l-1]} = \frac{\partial \mathcal{L} }{\partial A^{[l-1]}} = W^{[l] T} dZ^{[l]} $$
cache是linear cache: A_prev,W,b
1 | def linear_backward(dZ, cache): |
2. Linear-Activation backward
dA通过激活函数的导数可以求得dZ,再由上面的函数,最终:
输入$dA^{[l]} , cache$
输出$dA^{[l-1]} ,dW,db$
这个时候它有给了两个现成的函数dZ = sigmoid_backward(dA, activation_cache)
、dZ = relu_backward(dA, activation_cache)
源代码如下,输入的都是dA,和 cache=Z,输出是dZ:
$$dZ^{[l]} = dA^{[l]} * g’(Z^{[l]})$$
1 | def sigmoid_backward(dA, cache): |
1 | def relu_backward(dA, cache): |
然后得到了函数如下,注意这里面的cache已经是4个元素了linear_cache=A_prev,W,b
、activation_cache=Z
:
1 | # GRADED FUNCTION: linear_activation_backward |
3. L-Model Backward
可以把前面的函数穿起来,从后面往前面传播了,先算最后一层的sigmoid,然后往前算L-1的循环relu。其中,dAL是损失函数的导数,这个是预先求得知道的,也就是
$$-\frac{y}{a}-\frac{1-y}{1-a}$$
numpy表示为:
1 | dAL = - (np.divide(Y, AL) - np.divide(1 - Y, 1 - AL)) |
整个backward中,我们的输入只有AL,Y和caches,
输出则是每一层的grads,包括了$dA,dW,db$
1 | # GRADED FUNCTION: L_model_backward |
Update Parameters
1 | # GRADED FUNCTION: update_parameters |
Part2
有了part1中的函数,就很容易在part2中搭建模型和训练了。
依旧是识别猫猫的图片。
开始先用两层的layer做训练,得到了精确度是72%,这里贴代码就好了,L层再详细说说
1 | ### CONSTANTS DEFINING THE MODEL #### |
L-layer Neural Network
使用之前的函数:
1 | def initialize_parameters_deep(layers_dims): |
这里一共4层:
1 | layers_dims = [12288, 20, 7, 5, 1] # 4-layer model |
思路是:
- 初始化参数
- 进入for的n次迭代循环:
- L_model_forward(X, parameters) 得到 AL,caches
- 计算cost
- L_model_backward(AL, Y, caches)计算grads
- update_parameters(parameters, grads, learning_rate)更新参数
- 每100层记录一下cost的值
- 画出cost梯度下降图
1 | # GRADED FUNCTION: L_layer_model |
2500的迭代次数,精度达到了80%!
小结
过程其实是很清晰的,就是先初始化参数;再开始循环,循环中先计算前向传播,得到最后一层的AL,以及每一层的cache,其中cache包括了 A_prev,W,b,Z;然后计算一下每一次迭代的cost;再进行反向传播,得到每一层的梯度dA,dW,db;记得每100次迭代记录一下cost值,这样就可以画出cost是如何下降的了。
part1构建的那些函数,一步步来是比较简单的,但是如果自己要一下子想出来的话,也很难想得到。所以思路要清晰,一步一步来,才能构建好函数!