我是靠谱客的博主 欢呼人生,最近开发中收集的这篇文章主要介绍『DL笔记』dropout正则化(Dropout Regularization),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

                                  dropout正则化(Dropout Regularization)

为了防止过拟合的问题,除了使用L2正则化,还有一个非常实用的正则化方法--“Dropout Regularization(随机失活或者翻译为丢弃)”,dropout正则化是Srivastava在2014年提出来的Dropout: A Simple Way to Prevent Neural Networks from Overfitting。Dropout的思想其实非常简单粗暴:对于网络的每一层,随机的丢弃一些单元。如下图所示(图片来自Srivastava的dropout论文): 

假设你在训练a图这样的神经网络,它存在过拟合,这就是dropout所要处理的,dropout会遍历网络的每一层,并设置消除神经网络节点的概率。假设网路中的每一层,每个节点都是以抛硬币的方式设置概率,每个节点得以保留和消除的概率都是0.5,设置完节点概率,我们会消除一些节点,然后删除掉从节点进出的连线,最后得到一个节点更少,规模更小的网络,让后用backprop方法进行训练。这是网络节点精简后的一个样本,对于其他样本,我们照旧以抛硬币的方式设置概率,保留一类节点集合,删除其他类型的节点集合。对于每个样本我们将采用一个精简后的神经网络训练它。

关于为什么dropout能够减轻过拟合,ng给出了两个比较直观的解释:

  • 正是因为在每一层随机的丢弃了一些单元,所以相当于训练出来的网络要比正常的网络小的多,在一定程度上解释了避免过拟合的问题。
  • 如下图所示的一个简单单层网络因为每一个特征都有可能被丢弃,所以整个网络不会偏向于某一个特征(把某特征的权重的值赋的很大),会把每一个特征的权重都赋的很小,这就有点类似于L2正则化了,能够起到减轻过拟合的作用。 

这个方法看起来有点疯狂,但是他确实是有效的。下面开始从技术实现方面来看下dropout正则项,这里最重要的一个参数就是 keep_prob,它表示保留某个隐藏单元的概率(同样,1−keep_prob则为丢弃概率),比如某一层的 keep_prob=0.8,则意味着某一层随机的保留80%的神经单元(也即有20%的单元被丢弃)。通常实现dropout regularization的技术称为 inverted dropout (反向随机失活),我们用一个3层的网络来举例说明。编码中会有很多涉及到3的地方,我只举例说明如何在某一层中实施dropout ,假设对于第三层,则inverted dropout的具体实现为:

1.  d3 = np.random.rand(a3.shape[0],a3.shape[1]) < keep_prob
2.  a3 = np.multiply(a3,d3)
3.  a3 = a3 / keep_prob
4.  z4 = np.dot(w4,a3) + b4

关于上面的步骤的一些说明:

  • 第1步,首先要定义向量d,d^{^{3}} 表示一个3层的dropout向量,大小和a3一样的概率矩阵,其实这一样代码,因为每次都是随机数,所以只能做到近似保留 keep_prob 这么多,比如, keep_prob=0.8可能d3只有79%的1,也就意味着只有79%的单元被保留,但是如果隐藏层单元数量越多,越能够逼近80%。 
  • 第2步,第3层中获取激活函数,这里我们叫它a^{^{3}} ,含有要计算的激活函数,a3等于a3与d3点乘,即保留keep_prob的单元,剩下的1−keep_prob 单元被失活,也就是过滤掉所有等于0的元素。 
  • 第3步,因为有1−keep_prob 的单元失活了,这样a3的期望值也就减少了1−keep_prob, 所以我们要用a3/keep_prob,这样可以确保a3的期望值不变。这就是inverted dropout

这就是inverted dropout的内容。下面用两个动态图来演示下dropout的过程(素材来自ng的deep learning课):

接下来主要来代码实现,假设我们的网络激活函数使用relu,输出层使用sigmoid,我们只要在前面一步步手写神经网络的基础上把前向传播(forward propagation)和后向传播(backward propagation)稍作修改就可以了:

前向传播(forward propagation)

def forward_propagation_with_dropout(X, parameters, keep_prob = 0.8):
    """
    X -- input dataset, of shape (input size, number of examples)
    parameters -- python dictionary containing your parameters "W1", "b1", "W2", "b2",...,"WL", "bL"
                    W -- weight matrix of shape (size of current layer, size of previous layer)
                    b -- bias vector of shape (size of current layer,1)
    keep_prob: probability of keeping a neuron active during drop-out, scalar
    :return:
    AL: the output of the last Layer(y_predict)
    caches: list, every element is a tuple:(W,b,z,A_pre)
    """
    np.random.seed(1)  #random seed
    L = len(parameters) // 2  #number of layer
    A = X
    caches = [(None,None,None,X,None)]  #用于存储每一层的,w,b,z,A,D第0层w,b,z用none代替
    # calculate from 1 to L-1 layer
    for l in range(1, L):
        A_pre = A
        W = parameters["W" + str(l)]
        b = parameters["b" + str(l)]
        z = np.dot(W, A_pre) + b  # 计算z = wx + b
        A = relu(z)  # relu activation function
        D = np.random.rand(A.shape[0], A.shape[1]) #initialize matrix D
        D = (D < keep_prob) #convert entries of D to 0 or 1 (using keep_prob as the threshold)
        A = np.multiply(A, D) #shut down some neurons of A
        A = A / keep_prob #scale the value of neurons that haven't been shut down
        caches.append((W, b, z, A,D))
    # calculate Lth layer
    WL = parameters["W" + str(L)]
    bL = parameters["b" + str(L)]
    zL = np.dot(WL, A) + bL
    AL = sigmoid(zL)
    caches.append((WL, bL, zL, A))
    return AL, caches

反向传播(backward propagation)

def backward_propagation_with_dropout(AL, Y, caches, keep_prob = 0.8):
    """
        Implement the backward propagation presented in figure 2.
        Arguments:
        X -- input dataset, of shape (input size, number of examples)
        Y -- true "label" vector (containing 0 if cat, 1 if non-cat)
        caches -- caches output from forward_propagation(),(W,b,z,pre_A)
        keep_prob: probability of keeping a neuron active during drop-out, scalar
        Returns:
        gradients -- A dictionary with the gradients with respect to dW,db
        """
    m = Y.shape[1]
    L = len(caches) - 1
    # print("L:   " + str(L))
    # calculate the Lth layer gradients
    prev_AL = caches[L - 1][3]
    dzL = 1. / m * (AL - Y)
    dWL = np.dot(dzL, prev_AL.T)
    dbL = np.sum(dzL, axis=1, keepdims=True)
    gradients = {"dW" + str(L): dWL, "db" + str(L): dbL}
    # calculate from L-1 to 1 layer gradients
    for l in reversed(range(1, L)): # L-1,L-2,...,1
        post_W = caches[l + 1][0]  # 要用后一层的W
        dz = dzL  # 用后一层的dz
        dal = np.dot(post_W.T, dz)
        Dl = caches[l][4] #当前层的D
        dal = np.multiply(dal, Dl) #Apply mask Dl to shut down the same neurons as during the forward propagation
        dal = dal / keep_prob #Scale the value of neurons that haven't been shut down
        Al = caches[l][3]  #当前层的A
        dzl = np.multiply(dal, relu_backward(Al))#也可以用dzl=np.multiply(dal, np.int64(Al > 0))来实现
        prev_A = caches[l-1][3]  # 前一层的A
        dWl = np.dot(dzl, prev_A.T)
        dbl = np.sum(dzl, axis=1, keepdims=True)

        gradients["dW" + str(l)] = dWl
        gradients["db" + str(l)] = dbl
        dzL = dzl  # 更新dz
    return gradients

关于dropout有几点是要非常注意的:

  • 只有在训练网络的时候使用dropout,在测试集上(预测的时候)不要使用dropout,也就意味着我们在预测(分类)的时候,用训练好的参数做前向传播的时候,要把dropout关掉!
  • dropout是一个正则化技术

参考了如下内容,在这里衷心感谢!

  1. 吴恩达(Ng)老师的深度学习课程。
  2. https://blog.csdn.net/u012328159/article/details/80210363

最后

以上就是欢呼人生为你收集整理的『DL笔记』dropout正则化(Dropout Regularization)的全部内容,希望文章能够帮你解决『DL笔记』dropout正则化(Dropout Regularization)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部