深度学习(二)overfitting和regularization、dropout

Overfitting

1.过度拟合(从知乎上看到的)

  (1)对于机器来说,在使用学习算法学习数据的特征的时候,样本数据的特征可以分为局部特征和全局特征,全局特征就是任何你想学习的那个概念所对应的数据都具备的特征,而局部特征则是你用来训练机器的样本里头的数据专有的特征.

  (2)在学习算法的作用下,机器在学习过程中是无法区别局部特征和全局特征的,于是机器在完成学习后,除了学习到了数据的全局特征,也可能习得一部分局部特征,而习得的局部特征比重越多,那么新样本中不具有这些局部特征但具有所有全局特征的样本也越多,于是机器无法正确识别符合概念定义的“正确”样本的几率也会上升,也就是所谓的“泛化性”变差,这是过拟合会造成的最大问题.

  (3)所谓过拟合,就是指把学习进行的太彻底,把样本数据的所有特征几乎都习得了,于是机器学到了过多的局部特征,过多的由于噪声带来的假特征,造成模型的“泛化性”和识别正确率几乎达到谷点,于是你用你的机器识别新的样本的时候会发现就没几个是正确识别的.

  (4)解决过拟合的方法,其基本原理就是限制机器的学习,使机器学习特征时学得不那么彻底,因此这样就可以降低机器学到局部特征和错误特征的几率,使得识别正确率得到优化.

  打个形象的比方,给一群天鹅让机器来学习天鹅的特征,经过训练后,知道了天鹅是有翅膀的,天鹅的嘴巴是长长的弯曲的,天鹅的脖子是长长的有点曲度,天鹅的整个体型像一个“2”且略大于鸭子.这时候你的机器已经基本能区别天鹅和其他动物了。

  然后,很不巧你的天鹅全是白色的,于是机器经过学习后,会认为天鹅的羽毛都是白的,以后看到羽毛是黑的天鹅就会认为那不是天鹅.

  来分析一下上面这个例子:(1)中的规律都是对的,所有的天鹅都有的特征,是全局特征;然而,(2)中的规律:天鹅的羽毛是白的.这实际上并不是所有天鹅都有的特征,只是局部样本的特征。机器在学习全局特征的同时,又学习了局部特征,这才导致了不能识别黑天鹅的情况.

2。如何解决Overfitting?

增加训练数据集的量是减少overfitting的途径之一,减小神经网络的规模, 但是更深层更大的网络潜在有更强的学习能力

即使对于固定的神经网络和固定的训练集, 仍然可以减少overfitting
1.可以通过Regularization减少overfitting 
2.可以通过dropout

正则化(regularization)

下面简单介绍

1.最常见的一种Regularization:L2 Regularization
     

  在cross-entropy的基础上增加一项:权重之和(对于神经网络里面所有权重W相加)

    :regularization参数

      n :训练集实例的个数

      对于二次Cost: 

      regularization 二次Cost:

              

   综上:可以概括表示为

      

     regularization的cost偏向神经网络学习比较小的权重W

    :调整两项的相对重要程度, 较小的λ倾向于让第一项Co最小化. 较大的λ倾向与最小化增大的项(权重之和).

   深度学习(二)overfitting和regularization、dropout_第1张图片

   根据梯度下降算法,更新法则为:

      深度学习(二)overfitting和regularization、dropout_第2张图片

       

      深度学习(二)overfitting和regularization、dropout_第3张图片

加入regularization不仅减小了overfitting, 还对避免陷入局部最小点 (local minimum), 更容易重现实验结果

2.为什么regularization可以减少overfitting?

  因为在神经网络中,Regularized网络更鼓励小的权重, 小的权重的情况下, x一些随机的变化不会对神经网络的模型造成太大影响, 所以更小可能受到数据局部噪音的影响.
  Un-regularized神经网路, 权重更大, 容易通过神经网络模型比较大的改变来适应数据,更容易学习到局部数据的噪音
而Regularized更倾向于学到更简单一些的模型
  但是简单的模型不一定总是更好,要从大量数据实验中获得,目前添加regularization可以更好的泛化更多的从实验中得来,理论的支持还在研究之中

3. L1 Regularization

L1 Regularization cost函数为:
对C关于w求偏导得:
sgn(w)表示为符号函数,w为正,结果为1,w为负结果为-1。
权重的更新法则为:
与L2 Regularization对比: 两者都是减小权重,但方式不同:
L1减少一个常量(η,λ,n根据输入都是固定的,sgn(w)为1或-1,故为常量)
而L2减少的是权重的一个固定的比例;如果权重本身很大的话,L2减少的比L1减少的多
若权重小,则L1减少的更多。多以L1倾向于集中在少部分重要的连接上(w小)
这里要注意的是:sgn(w)在w=0时不可导,故要事先令sgn(w)在w=0时的导数为0

Dropout

Dropout的目的也是用来减少overfitting(过拟合)。而和L1,L2Regularization不同的是,Dropout不是针对cost函数,而是改变神经网络本身的结构。下面开始简单的假设Dropout。
假设有一个神经网络:
深度学习(二)overfitting和regularization、dropout_第4张图片
按照之前的方法,根据输入X,先正向更新神经网络,得到输出值,然后反向根据backpropagation算法来更新权重和偏向。而Dropout不同的是,
1)在开始,随机删除掉隐藏层一半的神经元,如图,虚线部分为开始时随机删除的神经元:
深度学习(二)overfitting和regularization、dropout_第5张图片
2)然后,在删除后的剩下一半的神经元上正向和反向更新权重和偏向;
3)再恢复之前删除的神经元,再重新随机删除一半的神经元,进行正向和反向更新w和b;
4)重复上述过程。
最后,学习出来的神经网络中的每个神经元都是在只有一半的神经元的基础上学习的,因为更新次数减半,那么学习的权重会偏大,所以当所有神经元被回复后(上述步骤2)),把得到的隐藏层的权重减半。
 
对于Dropout为什么可以减少overfitting的原因如下:
一般情况下,对于同一组训练数据,利用不同的神经网络训练之后,求其输出的平均值可以减少overfitting
Dropout就是利用这个原理,每次丢掉一半的一隐藏层神经元,相当于在不同的神经网络上进行训练,这样就减少了神经元之间的依赖性
即每个神经元不能依赖于某几个其他的神经元(指层与层之间相连接的神经元)
使神经网络更加能学习到与其他神经元之间的更加健壮robust的特征。
在Dropout的作者文章中,测试手写数字的准确率达到了98.7%!所以Dropout不仅减少overfitting,还能提高准确率

下面给出Dropout的Python代码:

注意:由于Dropout在训练的时候是用了一部分的神经元去做训练,在在测试阶段由于我们是用整个网络去训练,因此我们需要注意在训练的时候为每个存活下来的神经元做同采样比例的放大(除以p),注意,这只在训练时候做,用以保证训练得到的权重在组合之后不会太大;另外一种选择就是把测试结果根据采样比例缩小(乘于p)。

def dropout_forward(x, dropout_param):
  """
  Performs the forward pass for (inverted) dropout.

  Inputs:
  - x: Input data, of any shape
  - dropout_param: A dictionary with the following keys:
    - p: Dropout parameter. We drop each neuron output with probability p.
    - mode: 'test' or 'train'. If the mode is train, then perform dropout;
      if the mode is test, then just return the input.
    - seed: Seed for the random number generator. Passing seed makes this
      function deterministic, which is needed for gradient checking but not in
      real networks.

  Outputs:
  - out: Array of the same shape as x.
  - cache: A tuple (dropout_param, mask). In training mode, mask is the dropout
    mask that was used to multiply the input; in test mode, mask is None.
  """
  p, mode = dropout_param['p'], dropout_param['mode']
  if 'seed' in dropout_param:
    np.random.seed(dropout_param['seed'])

  mask = None
  out = None

  if mode == 'train':

    mask = (np.random.rand(*x.shape) < p)/p
    out = x*mask
    pass

  elif mode == 'test':

    out = x*(np.random.rand(*x.shape) < p)/p

    pass

  cache = (dropout_param, mask)
  out = out.astype(x.dtype, copy=False)

  return out, cache


def dropout_backward(dout, cache):
  """
  Perform the backward pass for (inverted) dropout.

  Inputs:
  - dout: Upstream derivatives, of any shape
  - cache: (dropout_param, mask) from dropout_forward.
  """
  dropout_param, mask = cache
  mode = dropout_param['mode']

  dx = None
  if mode == 'train':

    dx = dout * mask
    pass

  elif mode == 'test':
    dx = dout
  return dx

 更加深入地理解,可以看看Hinton和Alex两牛2012的论文《ImageNet Classification with Deep Convolutional Neural Networks》

你可能感兴趣的:(深度学习)