本文共 13332 字,大约阅读时间需要 44 分钟。
欢迎来到“改进深层神经网络”的第一个任务。 训练神经网络需要指定权重的初始值,精心选择的初始化方法将有助于学习。 如果您完成了本专业的上一门课程,您可能会按照我们的说明进行重量初始化,并且到目前为止已经完成了。但是你如何为一个新的神经网络选择初始化?在本节中,您将看到不同的初始化如何导致不同的结果。
选择一个好的初始化可以:
要开始,请运行以下单元来导入分类所需的软件包和平面数据集。
import numpy as npimport matplotlib.pyplot as pltimport sklearnimport sklearn.datasetsfrom init_utils import sigmoid, relu, compute_loss, forward_propagation, backward_propagationfrom init_utils import update_parameters, predict, load_dataset, plot_decision_boundary, predict_dec%matplotlib inlineplt.rcParams['figure.figsize'] = (7.0, 4.0) # set default size of plotsplt.rcParams['image.interpolation'] = 'nearest'plt.rcParams['image.cmap'] = 'gray'# load image dataset: blue/red dots in circlestrain_X, train_Y, test_X, test_Y = load_dataset()
结果:
1 -神经网络模型
您将使用三层神经网络(已经为您实现)。以下是您将尝试的初始化方法:
parameters['W' + str(l)] = np.zeros((layers_dims[l], layers_dims[l - 1]))
parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) * 10
parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) * np.sqrt(2 / layers_dims[l - 1])
说明:请快速阅读下面的代码,并运行它。在下一部分中,您将实现该 model() 调用的三种初始化方法。
def model(X, Y, learning_rate = 0.01, num_iterations = 15000, print_cost = True, initialization = "he"): """ 实现一个三层的神经网络:LINEAR ->RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID 参数: X - 输入的数据,维度为(2, 要训练/测试的数量) Y - 标签,【0 | 1】,维度为(1,对应的是输入的数据的标签) learning_rate - 学习速率 num_iterations - 迭代的次数 print_cost - 是否打印成本值,每迭代1000次打印一次 initialization - 字符串类型,初始化的类型【"zeros" | "random" | "he"】 is_polt - 是否绘制梯度下降的曲线图 返回: parameters - 学习后的参数 """ grads = {} costs = [] # to keep track of the loss m = X.shape[1] # number of examples layers_dims = [X.shape[0], 10, 5, 1] # Initialize parameters dictionary. if initialization == "zeros": parameters = initialize_parameters_zeros(layers_dims) elif initialization == "random": parameters = initialize_parameters_random(layers_dims) elif initialization == "he": parameters = initialize_parameters_he(layers_dims) # Loop (gradient descent) for i in range(0, num_iterations): # 前向传播: LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID. a3, cache = forward_propagation(X, parameters) # Loss cost = compute_loss(a3, Y) # 反向传播 grads = backward_propagation(X, Y, cache) # 更新参数 parameters = update_parameters(parameters, grads, learning_rate) # Print the loss every 1000 iterations if print_cost and i % 1000 == 0: print("Cost after iteration {}: {}".format(i, cost)) costs.append(cost) # plot the loss plt.plot(costs) plt.ylabel('cost') plt.xlabel('iterations (per hundreds)') plt.title("Learning rate =" + str(learning_rate)) plt.show() return parameters
2 -零初始化
在神经网络中有两种类型的参数要初始化:
权重矩阵:(?[1],?[2],?[3],...,?[?−1],?[?] )
偏差向量:(?[1],?[2],?[3],...,?[?−1],?[?])
练习:执行以下功能将所有参数初始化为零。稍后您将会看到这种方法并不奏效,因为它无法“打破对称性”,但是无论如何让我们尝试一下,看看会发生什么。使用 np.zeros((..,..)) 具有正确的维度。
# GRADED FUNCTION: initialize_parameters_zeros def initialize_parameters_zeros(layers_dims): """ 将模型的参数全部设置为0 参数: layers_dims - 列表,模型的层数和对应每一层的节点的数量 返回 parameters - 包含了所有W和b的字典 W1 - 权重矩阵,维度为(layers_dims[1], layers_dims[0]) b1 - 偏置向量,维度为(layers_dims[1],1) ··· WL - 权重矩阵,维度为(layers_dims[L], layers_dims[L -1]) bL - 偏置向量,维度为(layers_dims[L],1) """ parameters = {} L = len(layers_dims) # 网络层数 for l in range(1, L): ### START CODE HERE ### (≈ 2 lines of code) parameters['W' + str(l)] = np.zeros((layers_dims[l],layers_dims[l-1])) parameters['b' + str(l)] = np.zeros((layers_dims[l],1)) ### END CODE HERE ### return parameters
测试:
parameters = initialize_parameters_zeros([3,2,1])print("W1 = " + str(parameters["W1"]))print("b1 = " + str(parameters["b1"]))print("W2 = " + str(parameters["W2"]))print("b2 = " + str(parameters["b2"]))
结果:
W1 = [[0. 0. 0.] [0. 0. 0.]]b1 = [[0.] [0.]]W2 = [[0. 0.]]b2 = [[0.]]
运行以下代码,使用零初始化在15,000次迭代中训练您的模型。
parameters = model(train_X, train_Y, initialization = "zeros")print ("On the train set:")predictions_train = predict(train_X, train_Y, parameters)print ("On the test set:")predictions_test = predict(test_X, test_Y, parameters)
结果:
Cost after iteration 0: 0.6931471805599453Cost after iteration 1000: 0.6931471805599453Cost after iteration 2000: 0.6931471805599453Cost after iteration 3000: 0.6931471805599453Cost after iteration 4000: 0.6931471805599453Cost after iteration 5000: 0.6931471805599453Cost after iteration 6000: 0.6931471805599453Cost after iteration 7000: 0.6931471805599453Cost after iteration 8000: 0.6931471805599453Cost after iteration 9000: 0.6931471805599453Cost after iteration 10000: 0.6931471805599455Cost after iteration 11000: 0.6931471805599453Cost after iteration 12000: 0.6931471805599453Cost after iteration 13000: 0.6931471805599453Cost after iteration 14000: 0.6931471805599453
On the train set:Accuracy: 0.5On the test set:Accuracy: 0.5
性能真的很差,成本也没有真正降低,算法的性能也不比随机猜测好。为什么?让我们来看看预测和决策边界的细节:
print ("predictions_train = " + str(predictions_train))print ("predictions_test = " + str(predictions_test))
结果:
predictions_train = [[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]predictions_test = [[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
绘制图像:
plt.title("Model with Zeros initialization")axes = plt.gca()axes.set_xlim([-1.5,1.5])axes.set_ylim([-1.5,1.5])plot_decision_boundary(lambda x: predict_dec(parameters, x.T), train_X, train_Y.flatten())
结果:
该模型预测每个示例为0。
通常,将所有权重初始化为零会导致网络无法打破对称性。这意味着每一层中的每一个神经元都将学习相同的东西,你也可以为每一层训练一个n[l]= 1的神经网络,而这个网络并不比逻辑回归这样的线性分类器强大多少。
3 -随机初始化
为了打破对称性,让我们随机初始化权重。随机初始化后,每个神经元可以继续学习其输入的不同函数。在本练习中,您将看到如果权重随机初始化,但值非常大,会发生什么情况。
练习:执行以下功能,将您的权重初始化为大的随机值(按*10缩放),并将您的偏差初始化为零。使用 np.random.randn(..,..)* 10 代表权重和 np.zeros((.., ..)) 代表偏差。我们正在使用固定的 np.random.seed(..) 来确保您的“随机”权重与我们的匹配,所以不要担心如果运行几次代码,参数的初始值总是相同的。
# GRADED FUNCTION: initialize_parameters_randomdef initialize_parameters_random(layers_dims): """ 参数: layers_dims - 列表,模型的层数和对应每一层的节点的数量 返回 parameters - 包含了所有W和b的字典 W1 - 权重矩阵,维度为(layers_dims[1], layers_dims[0]) b1 - 偏置向量,维度为(layers_dims[1],1) ··· WL - 权重矩阵,维度为(layers_dims[L], layers_dims[L -1]) b1 - 偏置向量,维度为(layers_dims[L],1) """ np.random.seed(3) # This seed makes sure your "random" numbers will be the as ours parameters = {} L = len(layers_dims) # integer representing the number of layers for l in range(1, L): ### START CODE HERE ### (≈ 2 lines of code) parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) * 10 parameters['b' + str(l)] = np.zeros((layers_dims[l], 1)) ### END CODE HERE ### return parameters
测试:
parameters = initialize_parameters_random([3, 2, 1])print("W1 = " + str(parameters["W1"]))print("b1 = " + str(parameters["b1"]))print("W2 = " + str(parameters["W2"]))print("b2 = " + str(parameters["b2"]))
结果:
W1 = [[ 17.88628473 4.36509851 0.96497468] [-18.63492703 -2.77388203 -3.54758979]]b1 = [[0.] [0.]]W2 = [[-0.82741481 -6.27000677]]b2 = [[0.]]
运行以下代码,使用随机初始化在15,000次迭代中训练您的模型。
parameters = model(train_X, train_Y, initialization = "random")print ("On the train set:")predictions_train = predict(train_X, train_Y, parameters)print ("On the test set:")predictions_test = predict(test_X, test_Y, parameters)
结果:
Cost after iteration 0: infCost after iteration 1000: 0.6250982793959966Cost after iteration 2000: 0.5981216596703697Cost after iteration 3000: 0.5638417572298645Cost after iteration 4000: 0.5501703049199763Cost after iteration 5000: 0.5444632909664456Cost after iteration 6000: 0.5374513807000807Cost after iteration 7000: 0.4764042074074983Cost after iteration 8000: 0.39781492295092263Cost after iteration 9000: 0.3934764028765484Cost after iteration 10000: 0.3920295461882659Cost after iteration 11000: 0.38924598135108Cost after iteration 12000: 0.3861547485712325Cost after iteration 13000: 0.384984728909703Cost after iteration 14000: 0.3827828308349524
On the train set:Accuracy: 0.83On the test set:Accuracy: 0.86
模型不再输出所有0。
print (predictions_train)print (predictions_test)
结果:
[[1 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 1 1 0 0 0 1 0 1 1 1 1 1 1 0 1 1 0 0 1 1 1 1 1 1 1 1 0 1 1 1 1 0 1 0 1 1 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 1 1 1 0 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 1 0 1 0 1 1 1 1 0 1 1 1 1 0 1 0 1 0 1 1 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 0 1 1 1 1 0 1 0 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 1 1 0 1 1 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0]][[1 1 1 1 0 1 0 1 1 0 1 1 1 0 0 0 0 1 0 1 0 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 1 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 0 1 0 0 1 0 0 0 1 1 0 1 1 0 0 0 1 1 0 1 1 0 0]]
绘制图像:
plt.title("Model with large random initialization")axes = plt.gca()axes.set_xlim([-1.5,1.5])axes.set_ylim([-1.5,1.5])plot_decision_boundary(lambda x: predict_dec(parameters, x.T), train_X, train_Y.flatten())
结果:
观察:
我们可以看到误差开始很高。这是因为由于具有较大的随机权重,最后一个激活(sigmoid)输出的结果非常接近于0或1,而当它出现错误时,它会导致非常高的损失。初始化参数如果没有很好地话会导致梯度消失、爆炸,这也会减慢优化算法。如果我们对这个网络进行更长时间的训练,我们将看到更好的结果,但是使用过大的随机数初始化会减慢优化的速度。
总而言之,将权重初始化为非常大的时候其实效果并不好,下面我们试试小一点的参数值。
4- 抑梯度异常初始化
练习:通过初始化实现以下功能来初始化参数。 该函数类似于前面的 initialize_parameters_random(...) ,而这里我们会使用到这个公式来初始化参数。
# GRADED FUNCTION: initialize_parameters_hedef initialize_parameters_he(layers_dims): """ 参数: layers_dims - 列表,模型的层数和对应每一层的节点的数量 返回 parameters - 包含了所有W和b的字典 W1 - 权重矩阵,维度为(layers_dims[1], layers_dims[0]) b1 - 偏置向量,维度为(layers_dims[1],1) ··· WL - 权重矩阵,维度为(layers_dims[L], layers_dims[L -1]) b1 - 偏置向量,维度为(layers_dims[L],1) """ np.random.seed(3) parameters = {} L = len(layers_dims) - 1 # integer representing the number of layers for l in range(1, L + 1): ### START CODE HERE ### (≈ 2 lines of code) parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) * np.sqrt(2 / layers_dims[l - 1]) parameters['b' + str(l)] = np.zeros((layers_dims[l], 1)) ### END CODE HERE ### return parameters
测试:
parameters = initialize_parameters_he([2, 4, 1])print("W1 = " + str(parameters["W1"]))print("b1 = " + str(parameters["b1"]))print("W2 = " + str(parameters["W2"]))print("b2 = " + str(parameters["b2"]))
结果:
W1 = [[ 1.78862847 0.43650985] [ 0.09649747 -1.8634927 ] [-0.2773882 -0.35475898] [-0.08274148 -0.62700068]]b1 = [[0.] [0.] [0.] [0.]]W2 = [[-0.03098412 -0.33744411 -0.92904268 0.62552248]]b2 = [[0.]]
运行下面的代码,使用抑梯度异常初始化在15,000次迭代中训练您的模型。
parameters = model(train_X, train_Y, initialization = "he")print ("On the train set:")predictions_train = predict(train_X, train_Y, parameters)print ("On the test set:")predictions_test = predict(test_X, test_Y, parameters)
结果:
Cost after iteration 0: 0.8830537463419761Cost after iteration 1000: 0.6879825919728063Cost after iteration 2000: 0.6751286264523371Cost after iteration 3000: 0.6526117768893807Cost after iteration 4000: 0.6082958970572938Cost after iteration 5000: 0.5304944491717495Cost after iteration 6000: 0.4138645817071795Cost after iteration 7000: 0.31178034648444414Cost after iteration 8000: 0.2369621533032257Cost after iteration 9000: 0.18597287209206845Cost after iteration 10000: 0.1501555628037181Cost after iteration 11000: 0.12325079292273548Cost after iteration 12000: 0.09917746546525937Cost after iteration 13000: 0.08457055954024273Cost after iteration 14000: 0.07357895962677366
On the train set:Accuracy: 0.9933333333333333On the test set:Accuracy: 0.96
绘制图像:
plt.title("Model with He initialization")axes = plt.gca()axes.set_xlim([-1.5,1.5])axes.set_ylim([-1.5,1.5])plot_decision_boundary(lambda x: predict_dec(parameters, x.T), train_X, train_Y.flatten())
结果:
观察: 具有抑梯度异常初始化的模型在少量迭代中很好地分离了蓝色和红色点。
5 -结论
您已经看到了三种不同类型的初始化。对于相同的迭代次数和相同的超参数,比较结果是:
模型 | 训练准确度 | 问题 |
零初始化的三层神经网络 | 50% | 不能打破对称性 |
大规模随机初始化的三层神经网络 | 83% | 过大的权重 |
抑梯度异常初始化的三层神经网络 | 99% | 推荐方法 |
转载地址:http://qpuvi.baihongyu.com/