@Perfect-Demo
2018-05-01T08:42:03.000000Z
字数 16353
阅读 1234
机器学习深度学习
代码已上传github:
https://github.com/PerfectDemoT/my_deeplearning_homework
先讲述了如何一步步设置建立这个神经网络,下一篇有讲用这个神经网络建立一个可以“检测图片之中是否有猫咪的分类器”
开始之前,你需要了解这些事情(后面的几个变量的意义)
# 如果要开始看这篇代码,需要先了解这些事情:# 代码中的linear_activation_forward(A_prev , W , b , activation)函数中,会进行cache缓存A_prev , W , b的操作,下面具体说:# linear_cache中存的是A_prev , W , b# activation_cache中存的是该层的 Z# 另外之后还会有一句将linear_cache 和 activation_cache合并为cache,并且这个cache还会作为一个返回参数# 并且在L_model_forward()函数中会有一句caches.append(cache)将每一层的cache加入比那辆caches中,并且该函数会返回改值
里面会用到的两个函数(sigmoid与relu)代码是先写好的:
def sigmoid(Z):"""Implements the sigmoid activation in numpyArguments:Z -- numpy array of any shapeReturns:A -- output of sigmoid(z), same shape as Zcache -- returns Z as well, useful during backpropagation"""A = 1/(1+np.exp(-Z))cache = Zreturn A, cache
def relu(Z):"""Implement the RELU function.Arguments:Z -- Output of the linear layer, of any shapeReturns:A -- Post-activation parameter, of the same shape as Zcache -- a python dictionary containing "A" ; stored for computing the backward pass efficiently"""A = np.maximum(0,Z)assert(A.shape == Z.shape)cache = Zreturn A, cache
好的,现在开始一步步建立你的神经网络啦
1.1老样子,先导入包
#老样子,首先先导入包import numpy as npimport h5pyimport matplotlib.pyplot as pltfrom testCases import *from dnn_utils import sigmoid, sigmoid_backward, relu, relu_backward#设置一下接下来画图会用到的一下参数plt.rcParams['figure.figsize'] = (5.0, 4.0) # set default size of plotsplt.rcParams['image.interpolation'] = 'nearest'plt.rcParams['image.cmap'] = 'gray'np.random.seed(1) #设置一个随机种子
1.2接下来开始随机初始化
#现在开始写生成随机参数的函数#首先是两层网络的参数(和上一次作业一样)# GRADED FUNCTION: initialize_parametersdef initialize_parameters(n_x, n_h, n_y):"""Argument:n_x -- size of the input layern_h -- size of the hidden layern_y -- size of the output layerReturns:parameters -- python dictionary containing your parameters:W1 -- weight matrix of shape (n_h, n_x)b1 -- bias vector of shape (n_h, 1)W2 -- weight matrix of shape (n_y, n_h)b2 -- bias vector of shape (n_y, 1)"""np.random.seed(1)### START CODE HERE ### (≈ 4 lines of code)W1 = np.random.randn(n_h , n_x) * 0.01b1 = np.zeros((n_h , 1))W2 = np.random.randn(n_y , n_h) * 0.01b2 = np.zeros((n_y , 1))### END CODE HERE ###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
输出看看结果
#下面输出一下初始化的参数parameters = initialize_parameters(2,2,1)print("W1 = " + str(parameters["W1"]))print("b1 = " + str(parameters["b1"]))print("W2 = " + str(parameters["W2"]))print("b2 = " + str(parameters["b2"]))print("=============================")
输出如下:
W1 = [[ 0.01624345 -0.00611756][-0.00528172 -0.01072969]]b1 = [[ 0.][ 0.]]W2 = [[ 0.00865408 -0.02301539]]b2 = [[ 0.]]
1.3 刚刚的还是两层的,现在开始真正初始化一下L层的
#现在我们来看看L层网络的参数随机初始化# GRADED FUNCTION: initialize_parameters_deepdef initialize_parameters_deep(layer_dims):"""Arguments:layer_dims -- python array (list) containing the dimensions of each layer in our networkReturns:parameters -- python dictionary containing your parameters "W1", "b1", ..., "WL", "bL":Wl -- weight matrix of shape (layer_dims[l], layer_dims[l-1])bl -- bias vector of shape (layer_dims[l], 1)"""np.random.seed(3)parameters = {}L = len(layer_dims) # number of layers in the networkfor l in range(1, L):### START CODE HERE ### (≈ 2 lines of code)parameters['W' + str(l)] = np.random.randn(layer_dims[l] , layer_dims[l-1]) * 0.01parameters['b' + str(l)] = np.zeros((layer_dims[l] , 1))### END CODE HERE ###assert (parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l - 1]))assert (parameters['b' + str(l)].shape == (layer_dims[l], 1))return parameters
现在开始输出
#好der,现在来输出一下这个可以用于好几层的神经网络参数parameters = initialize_parameters_deep([5,4,3])print(parameters)print("W1 = " + str(parameters["W1"]))print("b1 = " + str(parameters["b1"]))print("W2 = " + str(parameters["W2"]))print("b2 = " + str(parameters["b2"]))# print("W3 = " + str(parameters["W3"]))# print("b3 = " + str(parameters["b3"]))print("==================================")
这里只暂时输出前两层的参数
{'W1': array([[ 0.01788628, 0.0043651 , 0.00096497, -0.01863493, -0.00277388],[-0.00354759, -0.00082741, -0.00627001, -0.00043818, -0.00477218],[-0.01313865, 0.00884622, 0.00881318, 0.01709573, 0.00050034],[-0.00404677, -0.0054536 , -0.01546477, 0.00982367, -0.01101068]]), 'b1': array([[ 0.],[ 0.],[ 0.],[ 0.]]), 'W2': array([[-0.01185047, -0.0020565 , 0.01486148, 0.00236716],[-0.01023785, -0.00712993, 0.00625245, -0.00160513],[-0.00768836, -0.00230031, 0.00745056, 0.01976111]]), 'b2': array([[ 0.],[ 0.],[ 0.]])}W1 = [[ 0.01788628 0.0043651 0.00096497 -0.01863493 -0.00277388][-0.00354759 -0.00082741 -0.00627001 -0.00043818 -0.00477218][-0.01313865 0.00884622 0.00881318 0.01709573 0.00050034][-0.00404677 -0.0054536 -0.01546477 0.00982367 -0.01101068]]b1 = [[ 0.][ 0.][ 0.][ 0.]]W2 = [[-0.01185047 -0.0020565 0.01486148 0.00236716][-0.01023785 -0.00712993 0.00625245 -0.00160513][-0.00768836 -0.00230031 0.00745056 0.01976111]]b2 = [[ 0.][ 0.][ 0.]]
1.4 现在开始正向传播。
#OK,参数初始化完了,现在来正向传播吧#先写正向传播要用到的函数,比如说算Z# GRADED FUNCTION: linear_forwarddef linear_forward(A, W, b):"""Implement the linear part of a layer's forward propagation.Arguments:A -- activations from previous layer (or input data): (size of previous layer, number of examples)W -- weights matrix: numpy array of shape (size of current layer, size of previous layer)b -- bias vector, numpy array of shape (size of the current layer, 1)Returns:Z -- the input of the activation function, also called pre-activation parametercache -- a python dictionary containing "A", "W" and "b" ; stored for computing the backward pass efficiently"""### START CODE HERE ### (≈ 1 line of code)Z = np.dot(W , A) + b### END CODE HERE ###assert (Z.shape == (W.shape[0], A.shape[1]))cache = (A, W, b)return Z, cache
上面得出了A以及cache,其中cache里面包含了A,W,b
下面输出一下
#现在输出一下A, W, b = linear_forward_test_case()Z, linear_cache = linear_forward(A, W, b)print("Z = " + str(Z))print("===============================")
现在来看看得到的Z值
Z = [[ 3.26295337 -1.23429987]]
1.5 刚刚完成了Z的计算,现在来看看用sigmoid函数与relu函数计算A
#之前是算Z的函数,现在可以用sigmoid函数或者relu函数来算A啦# GRADED FUNCTION: linear_activation_forwarddef linear_activation_forward(A_prev, W, b, activation):"""Implement the forward propagation for the LINEAR->ACTIVATION layerArguments:A_prev -- activations from previous layer (or input data): (size of previous layer, number of examples)W -- weights matrix: numpy array of shape (size of current layer, size of previous layer)b -- bias vector, numpy array of shape (size of the current layer, 1)activation -- the activation to be used in this layer, stored as a text string: "sigmoid" or "relu"Returns:A -- the output of the activation function, also called the post-activation valuecache -- a python dictionary containing "linear_cache" and "activation_cache";stored for computing the backward pass efficiently"""if activation == "sigmoid":# Inputs: "A_prev, W, b". Outputs: "A, activation_cache".### START CODE HERE ### (≈ 2 lines of code)Z, linear_cache = linear_forward(A_prev, W , b)A, activation_cache = sigmoid(Z)### END CODE HERE ###elif activation == "relu":# Inputs: "A_prev, W, b". Outputs: "A, activation_cache".### START CODE HERE ### (≈ 2 lines of code)Z, linear_cache = linear_forward(A_prev, W, b)A, activation_cache = relu(Z)### END CODE HERE ###assert (A.shape == (W.shape[0], A_prev.shape[1]))cache = (linear_cache, activation_cache)return A, cache
(注意:这里就出现了之前谈到的linear_cache以及activation_cache,大家注意这里他们分别保存了什么)
下面来看看输出:
#我们来输出看一看A_prev, W, b = linear_activation_forward_test_case()A, linear_activation_cache = linear_activation_forward(A_prev, W, b, activation = "sigmoid")print("With sigmoid: A = " + str(A))A, linear_activation_cache = linear_activation_forward(A_prev, W, b, activation = "relu")print("With ReLU: A = " + str(A))print("==============================")
输出为:
With sigmoid: A = [[ 0.96890023 0.11013289]]With ReLU: A = [[ 3.43896131 0. ]]
1.6 上面两个函数都是在为前向传播做准备,现在可以写一个完整的前向传播函数了
#现在开始用之前写的函数完成真正的正向传播模型#L层神经网络前向传播模型函数,返回最终A和缓存各层的A_prev,W,b,Zdef L_model_forward(X, parameters):"""Implement forward propagation for the [LINEAR->RELU]*(L-1)->LINEAR->SIGMOID computationArguments:X -- data, numpy array of shape (input size, number of examples)parameters -- output of initialize_parameters_deep()Returns:AL -- last post-activation valuecaches -- list of caches containing:every cache of linear_relu_forward() (there are L-1 of them, indexed from 0 to L-2)the cache of linear_sigmoid_forward() (there is one, indexed L-1)"""caches = []A = XL = len(parameters) // 2 # number of layers in the neural network# Implement [LINEAR -> RELU]*(L-1). Add "cache" to the "caches" list.for l in range(1, L):A_prev = A### START CODE HERE ### (≈ 2 lines of code)A, cache = linear_activation_forward(A_prev , parameters['W' + str(l)] , parameters['b' + str(l)] , activation='relu')caches.append(cache) #将该层的cache加入到caches中### END CODE HERE #### Implement LINEAR -> SIGMOID. Add "cache" to the "caches" list.### START CODE HERE ### (≈ 2 lines of code)AL, cache = linear_activation_forward(A, parameters['W' + str(L)], parameters['b' + str(L)], activation="sigmoid")caches.append(cache)### END CODE HERE ###assert (AL.shape == (1, X.shape[1]))return AL, caches#其中,要注意的就是对于参数序列的选择(28,29 , 34 行)#另外每次过了一层神经网络,都要讲=将该层的cache存入caches中(35行)
现在来试验一下输出:
#现在开始看看输出的效果X, parameters = L_model_forward_test_case()AL, caches = L_model_forward(X, parameters)print("AL = " + str(AL))print("Length of caches list = " + str(len(caches)))print("======================================")
结果长这样:
AL = [[ 0.17007265 0.2524272 ]]Length of caches list = 2
1.7 老规矩,算完了正向传播,又到了cost函数时间
def compute_cost(AL, Y):"""Implement the cost function defined by equation (7).Arguments:AL -- probability vector corresponding to your label predictions, shape (1, number of examples)Y -- true "label" vector (for example: containing 0 if non-cat, 1 if cat), shape (1, number of examples)Returns:cost -- cross-entropy cost"""m = Y.shape[1]# Compute loss from aL and y.### START CODE HERE ### (≈ 1 lines of code)cost = (-1/m) * np.sum(Y * np.log(AL) + (1-Y) * np.log(1 - AL))### END CODE HERE ###cost = np.squeeze(cost) # To make sure your cost's shape is what we expect (e.g. this turns [[17]] into 17).assert (cost.shape == ())return cost
和普通的bp神经网络差不多,此不赘述
直接看测试代码吧:
#求cost的式子和上一次作业差别不大,下面看看效果Y, AL = compute_cost_test_case()print("cost = " + str(compute_cost(AL, Y)))print("==================================")
结果长这样:
cost = 0.414931599615
1.8 慢慢来,先来个最简单的。实现一步线性的反向传播,使用对应层前向传播的缓存A_prev , W , b
先看看函数:
# GRADED FUNCTION: linear_backwarddef linear_backward(dZ, cache):"""Implement the linear portion of backward propagation for a single layer (layer l)Arguments:dZ -- Gradient of the cost with respect to the linear output (of current layer l)cache -- tuple of values (A_prev, W, b) coming from the forward propagation in the current layerReturns:dA_prev -- Gradient of the cost with respect to the activation (of the previous layer l-1), same shape as A_prevdW -- Gradient of the cost with respect to W (current layer l), same shape as Wdb -- Gradient of the cost with respect to b (current layer l), same shape as b"""A_prev, W, b = cachem = A_prev.shape[1]### START CODE HERE ### (≈ 3 lines of code)dW = 1/m * np.dot(dZ , A_prev.T)db = 1/m * np.sum(dZ , axis=1 , keepdims=False)dA_prev = np.dot(W.T , dZ)### END CODE HERE ###assert (dA_prev.shape == A_prev.shape)assert (dW.shape == W.shape)# assert (db.shape == b.shape)return dA_prev, dW, db
1.9
这里我们先给出最后函数中会用到的relu_backward()函数与sigmoid_backward()函数的代码
def relu_backward(dA, cache):"""Implement the backward propagation for a single RELU unit.Arguments:dA -- post-activation gradient, of any shapecache -- 'Z' where we store for computing backward propagation efficientlyReturns:dZ -- Gradient of the cost with respect to Z"""Z = cachedZ = np.array(dA, copy=True) # just converting dz to a correct object.# When z <= 0, you should set dz to 0 as well.dZ[Z <= 0] = 0assert (dZ.shape == Z.shape)return dZ
def sigmoid_backward(dA, cache):"""Implement the backward propagation for a single SIGMOID unit.Arguments:dA -- post-activation gradient, of any shapecache -- 'Z' where we store for computing backward propagation efficientlyReturns:dZ -- Gradient of the cost with respect to Z"""Z = caches = 1/(1+np.exp(-Z))dZ = dA * s * (1-s)assert (dZ.shape == Z.shape)return dZ
现在开始真正"表演"......
# GRADED FUNCTION: linear_activation_backwarddef linear_activation_backward(dA, cache, activation):"""Implement the backward propagation for the LINEAR->ACTIVATION layer.Arguments:dA -- post-activation gradient for current layer lcache -- tuple of values (linear_cache, activation_cache) we store for computing backward propagation efficientlyactivation -- the activation to be used in this layer, stored as a text string: "sigmoid" or "relu"Returns:dA_prev -- Gradient of the cost with respect to the activation (of the previous layer l-1), same shape as A_prevdW -- Gradient of the cost with respect to W (current layer l), same shape as Wdb -- Gradient of the cost with respect to b (current layer l), same shape as b"""linear_cache, activation_cache = cacheif activation == "relu":### START CODE HERE ### (≈ 2 lines of code)dZ = relu_backward(dA, activation_cache)dA_prev, dW, db = linear_backward(dZ , linear_cache)### END CODE HERE ###elif activation == "sigmoid":### START CODE HERE ### (≈ 2 lines of code)dZ = sigmoid_backward(dA , activation_cache)dA_prev, dW, db = linear_backward(dZ , linear_cache)### END CODE HERE ###return dA_prev, dW, db
好了,输出检测一下:
#现在来看看效果AL, linear_activation_cache = linear_activation_backward_test_case()dA_prev, dW, db = linear_activation_backward(AL, linear_activation_cache, activation = "sigmoid")print ("sigmoid:")print ("dA_prev = "+ str(dA_prev))print ("dW = " + str(dW))print ("db = " + str(db) + "\n")dA_prev, dW, db = linear_activation_backward(AL, linear_activation_cache, activation = "relu")print ("relu:")print ("dA_prev = "+ str(dA_prev))print ("dW = " + str(dW))print ("db = " + str(db))print("========================================")
输出结果如下:
sigmoid:dA_prev = [[ 0.11017994 0.01105339][ 0.09466817 0.00949723][-0.05743092 -0.00576154]]dW = [[ 0.10266786 0.09778551 -0.01968084]]db = [-0.05729622]relu:dA_prev = [[ 0.44090989 -0. ][ 0.37883606 -0. ][-0.2298228 0. ]]dW = [[ 0.44513824 0.37371418 -0.10478989]]db = [-0.20837892]
1.10我们现在把上面的所有反向传播函数做一个整合:
#现在,我们将上面所有的函数整合起来# GRADED FUNCTION: L_model_backwarddef L_model_backward(AL, Y, caches):"""Implement the backward propagation for the [LINEAR->RELU] * (L-1) -> LINEAR -> SIGMOID groupArguments:AL -- probability vector, output of the forward propagation (L_model_forward())Y -- true "label" vector (containing 0 if non-cat, 1 if cat)caches -- list of caches containing:every cache of linear_activation_forward() with "relu" (it's caches[l], for l in range(L-1) i.e l = 0...L-2)the cache of linear_activation_forward() with "sigmoid" (it's caches[L-1])Returns:grads -- A dictionary with the gradientsgrads["dA" + str(l)] = ...grads["dW" + str(l)] = ...grads["db" + str(l)] = ..."""grads = {}L = len(caches) # the number of layersm = AL.shape[1]Y = Y.reshape(AL.shape) # after this line, Y is the same shape as AL# Initializing the backpropagation### START CODE HERE ### (1 line of code)dAL = -(np.divide(Y , AL) - np.divide(1 - Y , 1 - AL))### END CODE HERE #### Lth layer (SIGMOID -> LINEAR) gradients. Inputs: "AL, Y, caches". Outputs: "grads["dAL"], grads["dWL"], grads["dbL"]### START CODE HERE ### (approx. 2 lines)current_cache = caches[L-1]grads["dA" + str(L)], grads["dW" + str(L)], grads["db" + str(L)] = linear_activation_backward(dAL , current_cache , activation='sigmoid')#注意,这里传回来的dA其实为上一层的dA,即:dA_prev((这一点在下面的43行dA的标号里可以很好体现))### END CODE HERE ###for l in reversed(range(L - 1)):# lth layer: (RELU -> LINEAR) gradients.# Inputs: "grads["dA" + str(l + 2)], caches". Outputs: "grads["dA" + str(l + 1)] , grads["dW" + str(l + 1)] , grads["db" + str(l + 1)]### START CODE HERE ### (approx. 5 lines)current_cache = caches[l]#注意grads["dA"+str(l+2)],这里是正确的,结合第407行,一定要弄清楚grads["dA^[n]"]中每个dA表示第几层的dAdA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads["dA"+str(l + 2)] , current_cache , activation='relu')grads["dA" + str(l + 1)] = dA_prev_tempgrads["dW" + str(l + 1)] = dW_tempgrads["db" + str(l + 1)] = db_temp### END CODE HERE ###return grads
注意看上面代码中的注释,里面说明了几个很重要的点,特别是对于各个参数下标要准确知道他们都代表什么
下面来测试一下
AL, Y_assess, caches = L_model_backward_test_case()grads = L_model_backward(AL, Y_assess, caches)print ("dW1 = "+ str(grads["dW1"]))print ("db1 = "+ str(grads["db1"]))print ("dA1 = "+ str(grads["dA1"]))
结果长这样:
dW1 = [[ 0.41010002 0.07807203 0.13798444 0.10502167][ 0. 0. 0. 0. ][ 0.05283652 0.01005865 0.01777766 0.0135308 ]]db1 = [-0.22007063 0. -0.02835349]dA1 = [[ 0. 0.52257901][ 0. -0.3269206 ][ 0. -0.32070404][ 0. -0.74079187]]
1.11 最后,更新参数开始,这里注意一下参数的下标,其他没啥,噢,对了,里面的学习率很重要,这个一定要多实验多试试。
#最后,更新参数开始# GRADED FUNCTION: update_parametersdef update_parameters(parameters, grads, learning_rate):"""Update parameters using gradient descentArguments:parameters -- python dictionary containing your parametersgrads -- python dictionary containing your gradients, output of L_model_backwardReturns:parameters -- python dictionary containing your updated parametersparameters["W" + str(l)] = ...parameters["b" + str(l)] = ..."""L = len(parameters) // 2 # number of layers in the neural network# Update rule for each parameter. Use a for loop.### START CODE HERE ### (≈ 3 lines of code)for l in range(L):parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - learning_rate * grads["dW" + str(l + 1)]parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - learning_rate * grads["db" + str(l + 1)]### END CODE HERE ###return parameters
老规矩,输出试试效果:
parameters, grads = update_parameters_test_case()parameters = update_parameters(parameters, grads, 0.1)print ("W1 = "+ str(parameters["W1"]))print ("b1 = "+ str(parameters["b1"]))print ("W2 = "+ str(parameters["W2"]))print ("b2 = "+ str(parameters["b2"]))
结果如下:
W1 = [[-0.59562069 -0.09991781 -2.14584584 1.82662008][-1.76569676 -0.80627147 0.51115557 -1.18258802][-1.0535704 -0.86128581 0.68284052 2.20374577]]b1 = [[-0.04659241][-1.28888275][ 0.53405496]]W2 = [[-0.55569196 0.0354055 1.32964895]]b2 = [[-0.84610769]]
好了今天先到这里(刚和队友调完数据库,又总结了统计学习方法的一个比较短的一章(朴素贝叶斯,已经发布),又写了个这个。。。怪可怜的,,,头发要紧头发要紧),后面还有一个利用上方的函数来做一个检测图片中是否有猫的分类器,并且我还会把上面用到的原理公式码出来,不要慌,马上回来。