【deeplearning.ai】Week 5 深度学习 正则化 & 初始化 & 标准化 & 对拍Debug

Week 5 正则化 & 初始化 & 标准化 & 对拍Debug

1 摘要

这一周主要是深度神经网络的很多配置设定问题,包括原因,解决思路和方法。

深度神经网络感觉确实只能从宏观调控,可能也是运算量过大,这使得随机化的一些算法居然很有用,比如dropout,因为大量导致产生了整体调整效果。

主要问题如下:

  • 调参思路

  • 正则化,解决过拟合问题,重点在于dropout算法

  • 初始化,breaks symmetry效应,Vanishing / Exploding gradients

  • 标准化

  • Gradient Checking,学会用这个debug

2 基本概念

训练集/测试集/dev 集合

训练集和测试集非常好理解,主要是测试集和验证集的区别。验证集主要用于调整超参数。关键在于,如果只有一个测试集,那么我们调整之后,容易对它过拟合,所以需要验证集来做调节,最终由测试集测试模型的泛化能力。

Bias/Variance

偏差和方差,一个是低拟合的到时候产生的误差,另一个是过拟合的时候产生的误差。通常,这是我们调参的风向标。

3 调参整体思路

在这里插入图片描述

对于偏差——低拟合,解决方式是Bigger network,train longer,nn architecture的优化。

对于方差——过拟合,解决方式是More data,Regulation,nn architecture的优化。

更大的网络,以及正则化,分别对应高偏差、高方差,而且这两个一般不会产生副作用,所以很多时候不需要考虑它们之间的权衡,只需要用好这两个主要方法就可以。

除了这两个方式,其他方法都很容易会在提高其一的同时降低另一个的表现,但好在更大的网络通常没有坏处,regulation对于偏差也影响不大,所以很多时候只需看着使用其一即可。因此,神经网路反倒比较少谈二者取舍。

后面再细谈过拟合的处理问题——基本所有因素都能导致过拟合,所以过拟合通常是比较大的问题。

4 初始化

不好的初始化会产生一些问题,这在浅层神经网路的时候就做过同样的问题,这里整理以下。

Q1:全零初始化为什么不行?全1会怎么样?

其实这是一个问题,重点在于权重相同的话,每一层的神经元上的值将会一模一样——输入w,a完全相同。那么所有节点计算的都是同一个特征,每个单元都是线性函数,那么组合出来的网络也是线性函数,这就是一个逻辑回归,神经网路结构没有意义。应该通过随机初始化来breaks symmetry。

Q2:随机初始化权重太大为什么不行?

可以想象,当特征数量非常大的时候,这种情况下,权重如果也非常大,那么z值就会很大,每一层叠加下来,将会产生vanishing/exploding gradients现象——梯度下降,本身就是非常慢的。

而且权重并不需要很大,只要大于1或者远小于1,那么就会出问题。

解决方法是,He和Xavier 初始化,其实原理很简单,只要所有权重加起来大致等于1就能很大程度避免这个问题,换句话说就是等于1/n。当然,其实只要建立这种和n的关系就是基本的思想。现在一般用得多的是He和Xavier 初始化——n[L-1]分之1的开方。

5 标准化

一般来讲是这样的。
x − μ s \frac{x-\mu}{s} sxμ
其中μ是均值,s可以是范围,可以是标准差等等。其实标准化目的是让x落在基本相同的范围内,所以并不需要那么精确。让特征处于相同的范围,这会使得梯度下降很快,是一种优化的方法。

6 Regulation

正则化的目的是为了处理过拟合问题,因为在数量极多,特征极多的情况下,很容易产生过拟合问题,尤其是计算机视觉领域。

思想:正则化其实基于一个很简单的思想,weight权重越低,模型就会越简单。可以形象地理解为生成的曲线越简单。

6.1 L2正则化

就是之前逻辑回归使用的正则化,之前也细谈过,在J中引入θ之后,使得J和θ之间自动权衡——θ太小误差就会变大,θ太大,J值就会变大。所以就会取一个比较合适的值,缓解过拟合。

从梯度下降来看,这个方法也叫weight decay,每次都会递减λ/m的偏导值。

这个方法引入了λ这个超参数,是很好用的方法之一。但缺点是,因为自动权衡,梯度下降会来回震荡,影响效率。

6.2 Dropout随机关闭神经元

这是一个有趣的方法,那么简单粗暴,却很有效果。而且非常有意思。

方法

以某个概率p随机关闭某一层的一些神经元(设置为0),给每一层设定一个概率,每次运行总是随机关闭掉一些。

原理

为什么这个有用?

理解这个问题,可以从这个角度。加入你把神经网络看成了是有主动向正确结果拟合的意识(其实就是梯度下降 + 损失函数),那么对于每个神经元来说,它便不会将权重集中在某个神经元上——因为它会被随机取消。所以神经元最好的选择是,分散投资,减少投资。

再者,inverse dropout的策略,为了使得z尽可能不变,弥补失去(1-p)的部分,会将A/p,大概使得整体尽可能不变。这因为着A变大,Z不变,而w就变小了。所以整体上,w会变得比较小。这就达成和L2正则化一样的目的。

很有意思的解释吧。其实我觉得,会出现这样的宏观结果,大概就是因为神经网路运算量大,可以视为随机分布,所以一层的每个单元都可以视为等概率消失,这使得,梯度下降并不会集中在某些权重上。

小结

dropout是一个很简单的策略,很奇怪,非常有用,特别是cv中,几乎成了默认选项。以下是实验结果,你可以看到,很有趣,在训练集上很低,在泛化测试集上表现得却特别好。

总的来说,它从全局上压制了w的取值。

On the train set:
Accuracy: 0.928909952607
On the test set:
Accuracy: 0.95

这个方法有些缺点,一是每层都有一个不那么重要的超参数,消失概率,再者,J变得不确定,很难从J下手调参。但这个方法很快,比正则化要快,因为它压制了w取值,但模型梯度下降却不会来回震荡,有点类似于无正则化的梯度下降。

6.3 其他方法

增加数据

这里指一种类型,比如对输入图片进行图像变化之后再做数据输入,比较简单,但会增加计算时间。

Early Stop

这个方法也很有意思,本来我们在训练集上训练完之后,会拿去Dev集上跑,图像一般如下。随着在训练集表现越来越好,在测试集上表现就会越来越差。

在这里插入图片描述

很自然的我们可以想到,在变化点停止迭代。这个方法不会引入超参数,但是缺点是:原本机器学习有个优点,我们只需关注J,而现在我们要权衡J和variance。

modeltrain accuracytest accuracy
3-layer NN without regularization95%91.5%
3-layer NN with L2-regularization94%93%
3-layer NN with dropout93%95%

7 Gradient Checking

神经网络模型太过复杂,所以debug也可想而知非常麻烦。这个主要是建立梯度的对拍程序,目的的检查向后传播或者向前传播是不是有问题。

7.1 原理

微积分的理论,直接设定epsilon,代入求数值化的偏导数,验证向后传播的计算是否正确。
∂ J ∂ θ = lim ⁡ ε → 0 J ( θ + ε ) − J ( θ − ε ) 2 ε \frac{\partial J}{\partial \theta}=\lim _{\varepsilon \rightarrow 0} \frac{J(\theta+\varepsilon)-J(\theta-\varepsilon)}{2 \varepsilon} θJ=ε0lim2εJ(θ+ε)J(θε)
验证的方法如下,结果只要小于2e-7,就认为其基本相同。这明显是一个经验的阈值。
d i f f e r e n c e = ∥ g r a d − gradapprox ∥ 2 ∥ grad ⁡ ∥ 2 + ∥ gradapprox ∥ 2 difference=\frac{ \| g r a d-\text {gradapprox} \|_{2}}{\|\operatorname{grad}\|_{2}+\| \text {gradapprox} \|_{2}} difference=grad2+gradapprox2gradgradapprox2

7.2 Debug

这个实在太有用了,所以记一下代码。keys中保存的用于定位bug的位置。

def dictionary_to_vector(parameters):
    """
    Roll all our parameters dictionary into a single vector satisfying our specific required shape.
    """
    keys = []
    count = 0
    for key in ["W1", "b1", "W2", "b2", "W3", "b3"]:
        
        # flatten parameter
        new_vector = np.reshape(parameters[key], (-1,1))
        keys = keys + [key]*new_vector.shape[0]
        
        if count == 0:
            theta = new_vector
        else:
            theta = np.concatenate((theta, new_vector), axis=0)
        count = count + 1

    return theta, keys

8 神经网络算法效率思考

这算是进一步思考,我是一直很奇怪,为什么数值化的计算效率会很慢,另外就是神经网络为什么那么快。

当成向量思考会简单很多——即只看一组数据。

for i=1:iter:
	L层向前传播()  -----------------> n*n1*n2*n3...nL -> O(K n)
    计算损失()     -----------------> nL = O(1)
    L层向后传播()  -----------------> 这类似于向前传播的逆运算->O(K n)
 

跨层次传播看成reLU,视为线性,那么就是A1· W1 · W2…,W1是个矩阵,nL x nL-1,矩阵乘法效率为O(N^3),因为W矩阵维度都是常量,所以最终效率为O(iter · K · n)。

由于iter迭代次数相对于特征数量n,数据量m是常数,所以m组数据下,最终效率为O(K n^2)。n的平方,且都为矩阵运算。常数K可能会很大。

数值化计算慢的原因,关键在于

没组数据:
    每次迭代:
        每个参数(特征n):
            向前传播计算损失(O(n))

所以结果是n的三次方。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值