【DL-CV】正则化,Dropout

1

                      /--->【DL-CV】更高级的参数更新/优化(一)
【DL-CV】批量归一化(BN算法)<前篇---后篇>
                      /--->【DL-CV】更高级的参数更新/优化(二)


在损失函数那篇文章中,我们引入了正则化并简单介绍了L2正则化。其作用是防止网络过拟合,提高网络的泛化能力。本文将介绍一些防止过拟合的方法,

过拟合

所谓过拟合,就是网络对训练集极度适应,以至于训练出来的权重几乎只服务于训练集,导致在训练好的网络在跑训练集的时候表现得很好(准确率高),而跑测试集或其他数据表现得很差。过拟合的出现将降低网络的泛化能力,是非常糟糕的事情。


正则化是抑制网络过拟合,提高网络泛化能力的一种方法。Dropout是其替代品,也能防止过拟合提高泛化能力。下面介绍这两种方法

正则化

正则化通过在损失函数上加上正则化损失来实现,根据正则化损失定义的不同,正则化又能分为好几种。

L2正则化

$$R(W)=\sum_k \sum_l W^2_{k,l}$$
L2正则化是是最常用的正则化方法,即对于网络中的每个权重值$w$,向损失函数中增加一个$\frac{1}{2}\lambda w^2$作为正则化惩罚,其中$\lambda$是正则化强度;乘了个$\frac{1}{2}$是很常见的事,因为这样式子关于 $w$ 梯度就是 $\lambda w$ 而不是 $2\lambda w$ 了。

L2正则化可以直观地理解为对于大数值的权重向量进行严厉惩罚(平方惩罚),驱使权重往更加均匀的方向发展而不是某些权重绝对值很大某些权重绝对值很小,这样能提高网络的泛化能力。

L1正则化

$$R(W)=\sum_k \sum_l| W_{k,l}|$$
L1正则化是另一个常用的正则化方法,即对于网络中每个权重值$w$,向损失函数增加一个$\lambda|w|$作为其正则化惩罚,其中$\lambda$是正则化强度。

L1正则化相对于L2正则化对大数值权重的惩罚没那么重(没有平方惩罚),他会让权值在最训练的过程中非常接近零(L2则是让权重变成分散的小数值)。在实践中,如果不是特别关注某些明确的特征选择,一般说来L2正则化都会比L1正则化效果好


L1正则化也可以和L2正则化组合使用变成$\lambda_1|w|+\lambda_2w^2$,这也被称作Elastic net regularizaton。不过没这么常用就是了

随机失活(Dropout)

Dropout堪称对付过拟合的超级武器,其使用简单,效果强劲。我们先来介绍dropout的使用:

  • 在训练的时候,Dropout的实现方法是让隐层神经元以超参数$1-p$的概率被设置为0,$p$的概率维持激活值(随机失活,加入随机性)
  • 在预测时不使用随机失活,但是每层的输出要乘以$p$(因为训练时每层只有有p的激活值被维持,为维持同样的输出,预测时每层激活值要乘以p,抵消随机性)

clipboard.png

Dropout可以理解为,在每次训练时,随机抽取一部分神经元组成一个子网络,基于输入数据只更新子网络的参数(子网络并不相互独立,因为他们共享着参数)。最后在测试时不使用随机失活,可以理解为对子网络们做了模型集成,以此来计算出一个平均的预测。

p = 0.5 # 激活神经元的概率. p值更高 = 随机失活更弱

def train_step(X):
  """ X中是输入数据 """
  
  # 3层neural network的前向传播
  H1 = np.maximum(0, np.dot(X, W1 ) + b1)
  U1 = np.random.rand(*H1.shape) < p # 第一个随机失活遮罩
  H1 *= U1 # drop!
  H2 = np.maximum(0, np.dot(H1, W2) + b2)
  U2 = np.random.rand(*H2.shape) < p # 第二个随机失活遮罩
  H2 *= U2 # drop!
  out = np.dot(H2, W3) + b3
  
  # 反向传播略
  # 参数更新略
  
def predict(X):
  H1 = np.maximum(0, np.dot(W1, X) + b1) * p # 注意:激活数据要乘以p
  H2 = np.maximum(0, np.dot(W2, H1) + b2) * p # 注意:激活数据要乘以p
  out = np.dot(W3, H2) + b3

Dropout的理解

clipboard.png

一种理解是Dropout避免了特征间的相互适应。如上图,假如网络中的神经元学到了如上特征,“有耳朵”,“有尾巴”,“毛毛的”等等特征,这些特征组合起来判断是否是猫。正常来说(作为人来说),特征越多越好,但在这种情况下(深度学习),完全依靠这些特征将可能导致过拟合的发生。使用Dropout后,网络的部分连接将被中断,网络不能依赖这些特征的组合来给出结果,而是只能使用零散的特征来给出判断,这在某种程度上防止了过拟合,提高了网路的泛化能力。

更多解释和理解可参考此文

推荐:反向随机失活(Inverted Dropout)

上面提到的Dropout方法在测试时每层激活值是要乘$p$的,额外的乘法操作会降低测试时的效率。所以更多时候我们会使用一个叫Inverted Dropout 的方法,他把随机性抵消的操作从预测阶段搬到了训练阶段:在训练阶段的Dropout操作后,我们对神经元的激活值除以$p$来抵消随机性。这样预测阶段会更高效。

p = 0.5 # 激活神经元的概率. p值更高 = 随机失活更弱

def train_step(X):
  """ X中是输入数据 """
  
  # 3层neural network的前向传播
  H1 = np.maximum(0, np.dot(X, W1 ) + b1)
  U1 = (np.random.rand(*H1.shape) < p) / p # 第一个随机失活遮罩,/p
  H1 *= U1 # drop!
  H2 = np.maximum(0, np.dot(H1, W2) + b2)
  U2 = (np.random.rand(*H2.shape) < p) / p # 第二个随机失活遮罩
  H2 *= U2 # drop!
  out = np.dot(H2, W3) + b3
  
  # 反向传播略
  # 参数更新略
  
def predict(X):
  H1 = np.maximum(0, np.dot(X, W1) + b1)  # 免去*p
  H2 = np.maximum(0, np.dot(H1, W2) + b2) 
  out = np.dot(H2, W3) + b3

除了将神经元随机置0的Dropout外,还有将权重值随机置0的DropConnect,兴趣自查

你可能感兴趣的

载入中...