问题:
在deeplearning.ai的课程1『神经网络与深度学习』中的第4周的编程作业『Building your Deep Neural Network: Step by Step』中,为什么多层神经网络的权重初始化是
parameters["W" + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) / np.sqrt(layers_dims[l-1])? 即:。其中,
是第
层网络的权重,
是第
层的神经元数量。
为什么不是parameters["W" + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) * 0.01?
答案:
1、在课程2『改善深层神经网络:超参数调试、正则化以及优化』中第一周的第11讲『神经网络的权重初始化』中有详细解释:
2、只有2层及以下神经网络的权重初始化才是*0.01,而多层神经网络都要 /np.sqrt(layers_dims[l-1]),即要除以其前一层神经元数量的平方根。
2、原因:因为,我们希望初始时
要足够小,不能太大,否则会进入激活函数的饱和区使得梯度下降很慢,产生梯度消失。 但是如果第
层神经元数量n越大,那么
值必须设置越小,所以某层W值一定要同它的输入神经元数(即前一层神经元数)挂钩,因此才会有:
。
说白了就是除个根号下n[l-1]来平衡W值
总结:
1、Xavier初始化:如果激活函数是tanh函数,初始化时:也是要乘以,这叫Xavier初始化。在一篇论文中提到出了这个。而bengio提出的初始化方法是乘以
。
2、He初始化:如果激活函数是relu函数,初始化时:是要乘以,因为它的方差是这个,这种初始化叫He初始化。
正则化的时候

所以在L2的正则化成本计算中
cross_entropy_cost = reg_utils.compute_cost(A3,Y)
L2_regularization_cost = lambd * (np.sum(np.square(W1)) + np.sum(np.square(W2)) + np.sum(np.square(W3))) / (2 * m)
cost = cross_entropy_cost + L2_regularization_cost
因为J(w,b)=原始+lambda/2m ||w||^2
所以求导后,dw[l]项因为正则化影响,变成 原式+lambda/W(l)
dW3 = (1 / m) * np.dot(dZ3,A2.T) + ((lambd * W3) / m )
梯度检验



1 def gradient_check(x,theta,epsilon=1e-7): 2 """ 3 4 实现图中的反向传播。 5 6 参数: 7 x - 一个实值输入 8 theta - 参数,也是一个实数 9 epsilon - 使用公式(3)计算输入的微小偏移以计算近似梯度 10 11 返回: 12 近似梯度和后向传播梯度之间的差异 13 """ 14 15 #使用公式(3)的左侧计算gradapprox。 16 thetaplus = theta + epsilon # Step 1 17 thetaminus = theta - epsilon # Step 2 18 J_plus = forward_propagation(x, thetaplus) # Step 3 19 J_minus = forward_propagation(x, thetaminus) # Step 4 20 gradapprox = (J_plus - J_minus) / (2 * epsilon) # Step 5 21 22 23 #检查gradapprox是否足够接近backward_propagation()的输出 24 grad = backward_propagation(x, theta) 25 26 numerator = np.linalg.norm(grad - gradapprox) # Step 1' 27 denominator = np.linalg.norm(grad) + np.linalg.norm(gradapprox) # Step 2' 28 difference = numerator / denominator # Step 3' 29 30 if difference < 1e-7: 31 print("梯度检查:梯度正常!") 32 else: 33 print("梯度检查:梯度超出阈值!") 34 35 return difference
解释一下np.linalg.norm()
1、linalg=linear(线性)+algebra(代数),norm则表示范数。
2、函数参数
x_norm=np.linalg.norm(x, ord=None, axis=None, keepdims=False)
①x: 表示矩阵(也可以是一维)
②ord:范数类型

多维:

def forward_propagation_n(X,Y,parameters): """ 实现图中的前向传播(并计算成本)。 参数: X - 训练集为m个例子 Y - m个示例的标签 parameters - 包含参数“W1”,“b1”,“W2”,“b2”,“W3”,“b3”的python字典: W1 - 权重矩阵,维度为(5,4) b1 - 偏向量,维度为(5,1) W2 - 权重矩阵,维度为(3,5) b2 - 偏向量,维度为(3,1) W3 - 权重矩阵,维度为(1,3) b3 - 偏向量,维度为(1,1) 返回: cost - 成本函数(logistic) """ m = X.shape[1] W1 = parameters["W1"] b1 = parameters["b1"] W2 = parameters["W2"] b2 = parameters["b2"] W3 = parameters["W3"] b3 = parameters["b3"] # LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID Z1 = np.dot(W1,X) + b1 A1 = gc_utils.relu(Z1) Z2 = np.dot(W2,A1) + b2 A2 = gc_utils.relu(Z2) Z3 = np.dot(W3,A2) + b3 A3 = gc_utils.sigmoid(Z3) #计算成本 logprobs = np.multiply(-np.log(A3), Y) + np.multiply(-np.log(1 - A3), 1 - Y) cost = (1 / m) * np.sum(logprobs) cache = (Z1, A1, W1, b1, Z2, A2, W2, b2, Z3, A3, W3, b3) return cost, cache def backward_propagation_n(X,Y,cache): """ 实现图中所示的反向传播。 参数: X - 输入数据点(输入节点数量,1) Y - 标签 cache - 来自forward_propagation_n()的cache输出 返回: gradients - 一个字典,其中包含与每个参数、激活和激活前变量相关的成本梯度。 """ m = X.shape[1] (Z1, A1, W1, b1, Z2, A2, W2, b2, Z3, A3, W3, b3) = cache dZ3 = A3 - Y dW3 = (1. / m) * np.dot(dZ3,A2.T) dW3 = 1. / m * np.dot(dZ3, A2.T) db3 = 1. / m * np.sum(dZ3, axis=1, keepdims=True) dA2 = np.dot(W3.T, dZ3) dZ2 = np.multiply(dA2, np.int64(A2 > 0)) #dW2 = 1. / m * np.dot(dZ2, A1.T) * 2 # Should not multiply by 2 dW2 = 1. / m * np.dot(dZ2, A1.T) db2 = 1. / m * np.sum(dZ2, axis=1, keepdims=True) dA1 = np.dot(W2.T, dZ2) dZ1 = np.multiply(dA1, np.int64(A1 > 0)) dW1 = 1. / m * np.dot(dZ1, X.T) #db1 = 4. / m * np.sum(dZ1, axis=1, keepdims=True) # Should not multiply by 4 db1 = 1. / m * np.sum(dZ1, axis=1, keepdims=True) gradients = {"dZ3": dZ3, "dW3": dW3, "db3": db3, "dA2": dA2, "dZ2": dZ2, "dW2": dW2, "db2": db2, "dA1": dA1, "dZ1": dZ1, "dW1": dW1, "db1": db1} return gradients
如果想比较“gradapprox”与反向传播计算的梯度
θ\thetaθ不再是标量。 这是一个名为“parameters”的字典。 我们为你实现了一个函数“dictionary_to_vector()”。 它将“parameters”字典转换为一个称为“values”的向量,通过将所有参数(W1,b1,W2,b2,W3,b3)整形为向量并将它们连接起来而获得。
反函数是“vector_to_dictionary”,它返回“parameters”字典。

def gradient_check_n(parameters,gradients,X,Y,epsilon=1e-7): """ 检查backward_propagation_n是否正确计算forward_propagation_n输出的成本梯度 参数: parameters - 包含参数“W1”,“b1”,“W2”,“b2”,“W3”,“b3”的python字典: grad_output_propagation_n的输出包含与参数相关的成本梯度。 x - 输入数据点,维度为(输入节点数量,1) y - 标签 epsilon - 计算输入的微小偏移以计算近似梯度 返回: difference - 近似梯度和后向传播梯度之间的差异 """ #初始化参数 parameters_values , keys = gc_utils.dictionary_to_vector(parameters) #keys用不到,把parameters参数转成向量传给p_v grad = gc_utils.gradients_to_vector(gradients) #从梯度字典变成一个单一的向量 num_parameters = parameters_values.shape[0] J_plus = np.zeros((num_parameters,1)) J_minus = np.zeros((num_parameters,1)) gradapprox = np.zeros((num_parameters,1)) #计算gradapprox for i in range(num_parameters): #计算J_plus [i]。输入:“parameters_values,epsilon”。输出=“J_plus [i]” thetaplus = np.copy(parameters_values) # Step 1 thetaplus[i][0] = thetaplus[i][0] + epsilon # Step 2 J_plus[i], cache = forward_propagation_n(X,Y,gc_utils.vector_to_dictionary(thetaplus)) # Step 3 ,cache用不到 #计算J_minus [i]。输入:“parameters_values,epsilon”。输出=“J_minus [i]”。 thetaminus = np.copy(parameters_values) # Step 1 thetaminus[i][0] = thetaminus[i][0] - epsilon # Step 2 J_minus[i], cache = forward_propagation_n(X,Y,gc_utils.vector_to_dictionary(thetaminus))# Step 3 ,cache用不到 #计算gradapprox[i] gradapprox[i] = (J_plus[i] - J_minus[i]) / (2 * epsilon) #通过计算差异比较gradapprox和后向传播梯度。 numerator = np.linalg.norm(grad - gradapprox) # Step 1' denominator = np.linalg.norm(grad) + np.linalg.norm(gradapprox) # Step 2' difference = numerator / denominator # Step 3' if difference < 1e-7: print("梯度检查:梯度正常!") else: print("梯度检查:梯度超出阈值!") return difference
浙公网安备 33010602011771号