/--->【DL-CV】更高级的参数更新/优化(一)
【DL-CV】批量归一化(BN算法)<前篇---后篇>
/--->【DL-CV】更高级的参数更新/优化(二)python
在损失函数那篇文章中,咱们引入了正则化并简单介绍了L2正则化。其做用是防止网络过拟合,提升网络的泛化能力。本文将介绍一些防止过拟合的方法,算法
所谓过拟合,就是网络对训练集极度适应,以致于训练出来的权重几乎只服务于训练集,致使在训练好的网络在跑训练集的时候表现得很好(准确率高),而跑测试集或其余数据表现得不好。过拟合的出现将下降网络的泛化能力,是很是糟糕的事情。segmentfault
正则化是抑制网络过拟合,提升网络泛化能力的一种方法。Dropout是其替代品,也能防止过拟合提升泛化能力。下面介绍这两种方法网络
正则化经过在损失函数上加上正则化损失来实现,根据正则化损失定义的不一样,正则化又能分为好几种。dom
$$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正则化能够直观地理解为对于大数值的权重向量进行严厉惩罚(平方惩罚),驱使权重往更加均匀的方向发展而不是某些权重绝对值很大某些权重绝对值很小,这样能提升网络的泛化能力。学习
$$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。不过没这么经常使用就是了spa
Dropout堪称对付过拟合的超级武器,其使用简单,效果强劲。咱们先来介绍dropout的使用:
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避免了特征间的相互适应。如上图,假如网络中的神经元学到了如上特征,“有耳朵”,“有尾巴”,“毛毛的”等等特征,这些特征组合起来判断是不是猫。正常来讲(做为人来讲),特征越多越好,但在这种状况下(深度学习),彻底依靠这些特征将可能致使过拟合的发生。使用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,兴趣自查