博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NG深度学习第二门课作业1-1 深度学习的实践
阅读量:4127 次
发布时间:2019-05-25

本文共 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 -神经网络模型

您将使用三层神经网络(已经为您实现)。以下是您将尝试的初始化方法:

  • 零初始化 - 输入参数全部初始化为0,在输入参数中设置 initialization = "zeros"。
  • parameters['W' + str(l)] = np.zeros((layers_dims[l], layers_dims[l - 1]))

  • 随机初始化 - 把输入参数设置为随机值,权重初始化为大的随机值,在输入参数中设置 initialization = "random" 。这将权重初始化为大的随机值。
  • parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) * 10

  • 抑梯度异常初始化 - 参见梯度消失和梯度爆炸的那一个视频,在输入参数中设置 initialization = "he"。这将权重初始化为根据何等人2015年的论文缩放的随机值。
  • 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/

你可能感兴趣的文章
100道+ JavaScript 面试题,助你查漏补缺
查看>>
JavaScript深入理解之闭包
查看>>
这才是学习Vite2的正确姿势!
查看>>
7 个适用于所有前端开发人员的很棒API,你需要了解一下
查看>>
25个构建Web项目的HTML建议,你需要了解一下!
查看>>
【web素材】02-10款大气的购物商城网站模板
查看>>
6种方式实现JavaScript数组扁平化(flat)方法的总结
查看>>
如何实现a===1 && a===2 && a===3返回true?
查看>>
49个在工作中常用且容易遗忘的CSS样式清单整理
查看>>
20种在学习编程的同时也可以在线赚钱的方法
查看>>
隐藏搜索框:CSS 动画正反向序列
查看>>
12 个JavaScript 特性技巧你可能从未使用过
查看>>
127个超级实用的JavaScript 代码片段,你千万要收藏好(上)
查看>>
【视频教程】Javascript ES6 教程27—ES6 构建一个Promise
查看>>
【5分钟代码练习】01—导航栏鼠标悬停效果的实现
查看>>
127个超级实用的JavaScript 代码片段,你千万要收藏好(中)
查看>>
8种ES6中扩展运算符的用法
查看>>
【视频教程】Javascript ES6 教程28—ES6 Promise 实例应用
查看>>
127个超级实用的JavaScript 代码片段,你千万要收藏好(下)
查看>>
【web素材】03-24款后台管理系统网站模板
查看>>