吴恩达Coursera深度学习课程 course2-week1 深度学习的实践层面 总结

                                                P0 前言

  • 第二门课 : Improving Deep Neural Networks: Hyperparameter turing,Regularization and Optimization (改善深层神经网络:超参数调试、正则化以及优化)
  • 第一周 : Practical aspects of Deep Learning (深度学习的实践层面)
  • 主要知识点 : (Train/Dev/Test sets)训练测试集划分、(Bias / Variance)偏差和方差、(Regulation)正则化、Dropout、(Normalizing inputs)输入归一化、(Vanishing / Exploding gradients)梯度消失与梯度爆炸、(Weight Initialization for Deep NN)权重初始化、(Gradient checking)梯度检验等

视频地址 :  https://mooc.study.163.com/course/2001281003

                                                P1 总结

1.训练,验证,测试集

样本数据通常会被分为三个部分:

  1. 训练集  : 用训练集对算法或模型进行训练过程
  2. 验证集  : 利用验证集或者又称为简单交叉验证集(hold-out cross validation set)进行交叉验证,选择出最好的模型
  3. 测试集  : 最后利用测试集对模型进行测试,获取模型运行的无偏估计

数据集的划分比例和数据集大小有关,一般来说分成下面几种情况:

  1. 小数据量(如100,1000,10000),可以将比例分为60%/20%/20%
  2. 大数据量(如百万级别),可以将比例分为98% / 1% / 1%
  3. 超百万数据量:99.5% / 0.25% / 0.25%(或者99.5% / 0.4% / 0.1%)

原因:

验证集的目的是为了验证不同的算法哪种更加有效,所以验证集只要足够大能够验证大约2-10种算法哪种更好就足够了,不需要使用20%的数据作为验证集。如百万数据中抽取1万的数据作为验证集就可以了。

测试集的主要目的是评估模型的效果,如在单个分类器中,往往在百万级别的数据中,我们选择其中1000条数据足以评估单个模型的效果。

2.偏差,方差

训练出来的模型有三种基本状态:

  1. 欠拟合(underfitting): 此时偏差较高(high bias),也就是训练集的误差贝叶斯误差(最优误差)相差太大
  2. 正常  (just right)      :利用训练集对模型进行训练就是为了使得模型在训练集上使 bias 最小化,避免出现underfitting的情况
  3. 过拟合(overfitting) : 此时方差较高(high variance),也就是训练集的误差验证集的误差相差太大

方差和偏差的博弈:

一方面,我们利用训练集对模型进行训练就是为了使得模型在train集上使 bias 最小化,避免出现underfitting的情况,但是如果模型设置的太复杂(帮助降低bias),虽然在train集上 bias 的值非常小,模型甚至可以将所有的数据点正确分类,但是当将训练好的模型应用在dev 集上的时候,却出现了较高的错误率。这是因为模型设置的太复杂则没有排除一些train集数据中的噪声,使得模型出现overfitting的情况,在dev 集上出现高 variance 的现象。

也就是说: 片面追求低bias可能要以高varience为代价,反之亦然.

例子:

以上为在人眼判别误差在0%的情况下,该最优误差通常也称为“贝叶斯误差”,如果“贝叶斯误差”大约为15%,那么图中第二种情况就是一种比较好的情况。

上述第三列的"双高"现象(高bias高varience)可能原因如下图:

 

原因:没有找到边界线,但却在部分数据点上出现了过拟合,则会导致这种高偏差和高方差的情况。

虽然在这里二维的情况下可能看起来较为奇怪,出现的可能性比较低;但是在高维的情况下,出现这种情况就成为可能。

 3.机器学习的基本方法

对模型的好坏评价,首先要看bias而不是varince(因为模型首先要能拟合训练集,如果连训练集都不能完好表示又怎么能用来搞验证集和测试集呢??)

因此首先要以降低bias为目标,在此基础上(bias达到一定阈值)降低varience.

一般来说,降低bias有如下几种方法(黑体加粗为常用方式):

  • 增加网络结构,如增加隐藏层数目;
  • 训练更长时间;
  • 寻找合适的网络架构,使用更大的NN结构;

降低varience有如下几种方法:

  • 获取更多的数据;
  • 正则化( regularization);
  • 寻找合适的网络结构;

基本过程见下图:

4.正则化

正则化之所以能够降低方差(减少过拟合),原因如下:

正则化在神经网络的cost function 中引入了一个正则项(下图紫色部分),作为模型复杂度的惩罚(过拟合就是因为模型太"复杂",把所有特征都学习到了,因此要惩罚他让他变"呆"一点)

J(w^{[1]},b^{[1]},\cdots,w^{[L]},b^{[L]})=\dfrac{1}{m}\sum\limits_{i=1}^{m}l(\hat y^{(i)},y^{(i)})+\dfrac{\lambda}{2m}\sum\limits_{l=1}^{L}||w^{[l]}||_{F}^{2}

直观上:

正则化因子λλ设置的足够大的情况下,为了使代价函数最小化,权重矩阵W就会被设置为接近于0的值。则相当于消除了很多神经元的影响,那么图中的大的神经网络就会变成一个较小的网络(当然上面这种解释是一种直观上的理解,但是实际上隐藏层的神经元依然存在,但是他们的影响变小了,便不会导致过拟合)。

数学上:

假设神经元中使用的激活函数为g(z)=\tanh(z),在加入正则化项后: 当\lambda增大,导致W^{[l]}减小,Z^{[l]}=W^{[l]}a^{[l-1]}+b^{[l]}便会减小,由上图可知,在z较小的区域里,tanh(z)函数近似线性,所以每层的函数就近似线性函数,整个网络就成为一个简单的近似线性的网络,从而不会发生过拟合

正则化举例:

Logistic regression

加入正则化项的代价函数:

J(w,b)=\dfrac{1}{m}\sum\limits_{i=1}^{m}l(\hat y^{(i)},y^{(i)})+\dfrac{\lambda}{2m}||w||_{2}^{2}

上式为逻辑回归的L2正则化。

  • L2正则化  \dfrac{\lambda}{2m}||w||_{2}^{2} = \dfrac{\lambda}{2m}\sum\limits_{j=1}^{n_{x}} w_{j}^{2}=\dfrac{\lambda}{2m}w^{T}w
  • L1正则化  \dfrac{\lambda}{m}||w||_{1}=\dfrac{\lambda}{m}\sum\limits_{j=1}^{n_{x}}|w_{j}|

其中λ为正则化因子。

注意:lambda在python中属于保留字,所以在编程的时候,用“lambd”代表这里的正则化因子λ。

Neural network

加入正则化项的代价函数: 

J(w^{[1]},b^{[1]},\cdots,w^{[L]},b^{[L]})=\dfrac{1}{m}\sum\limits_{i=1}^{m}l(\hat y^{(i)},y^{(i)})+\dfrac{\lambda}{2m}\sum\limits_{l=1}^{L}||w^{[l]}||_{F}^{2}

其中||w^{[l]}||_{F}^{2}=\sum\limits_{i=1}^{n^{[l-1]}}\sum\limits_{j=1}^{n^{[l]}}(w_{ij}^{[l]})^{2},因为w的大小为(n^{[l]},n^{[l-1]}),该矩阵范数被称为“Frobenius norm”

在加入正则化项后,梯度变为:

dW^{[l]} = (form\_backprop)+\dfrac{\lambda}{m}W^{[l]}

则梯度更新公式变为:

W^{[l]}:= W^{[l]}-\alpha dW^{[l]}

代入可得:

W^{[l]}:= W^{[l]}-\alpha [ (form\_backprop)+\dfrac{\lambda}{m}W^{[l]}]\\ = W^{[l]}-\alpha\dfrac{\lambda}{m}W^{[l]} -\alpha(form\_backprop)\\=(1-\dfrac{\alpha\lambda}{m})W^{[l]}-\alpha(form\_backprop)

其中,(1-\dfrac{\alpha\lambda}{m})为一个<1的项,会给原来的W[l]一个衰减的参数,所以L2范数正则化也被称为“权重衰减(Weight decay)”。

5.Dropout正则化

Dropout能够降低方差(减少过拟合),原因如下:

Dropout(随机失活)通过随机消除一些神经元,使得保留下来的节点较少,从而转变成一个规模较小的网络进行训练.

这里我们以单个神经元入手,单个神经元的工作就是接收输入,并产生一些有意义的输出,但是加入了Dropout以后,输入的特征都是有可能会被随机清除的.

(前一层的输出对于后一层而言相当于输入的特征,前一层一些神经元被随机失活相当于随机丢掉一些特征,因而后一层的神经元"不会再特别依赖于任何一个输入特征",也就是说不会给任何一个输入设置太大的权重)

所以通过传播过程,dropout将产生和L2范数相同的收缩权重的效果。

对于不同的层,设置的keep_prob也不同(如下图紫色),一般来说神经元较少的层(如最后两层),会设keep_prob =1.0 (相当于没有进行dropout),神经元多的层(如前两层),则会将keep_prob设置的较小.

 

dropout的缺点:

dropout的一大缺点就是其使得 Cost function不能再被明确的定义,因为每次迭代都会随机消除一些神经元节点,所以每次迭代的J(W,b)是不一样的,这就意味着不能在一张图中绘制损失函数的下降过程(正常的j下降如下所示)

Dropout的实现方法: 反向随机失活(Inverted dropout)

首先假设对 layer 3 进行dropout:

keep_prob = 0.8  # 设置神经元保留概率
d3 = np.random.rand(a3.shape[0], a3.shape[1]) < keep_prob
a3 = np.multiply(a3, d3)
a3 /= keep_prob

这里解释下为什么要有最后一步:a3 /= keep_prob

依照例子中的keep_prob = 0.8 ,那么就有大约20%的神经元被删除了,也就是说a[3]中有20%的元素被归零了,在下一层的计算中有Z^{[4]}=W^{[4]}\cdot a^{[3]}+b^{[4]},所以为了不影响Z[4]的期望值,所以需要W^{[4]}\cdot a^{[3]}的部分除以一个keep_prob。

Inverted dropout通过对“a3 /= keep_prob”,则保证无论keep_prob设置为多少,都不会对Z[4]的期望值产生影响。

Notation:在测试阶段不要用dropout,因为那样会使得预测结果变得随机

6.其他正则化方法

  • 数据广增(Data augmentation):通过图片的一些变换,得到更多的训练集和验证集; 

  • Early stopping:在交叉验证集的误差上升之前的点停止迭代,避免过拟合。这种方法的缺点是无法同时解决bias和variance之间的最优。 

7.归一化输入

使用归一化的原因:

如果输入特征处于不同的范围内,可能有些特征值从0到1,有些从1到1000,那么不使用归一化和使用归一化前后Cost function 的函数形状会有很大的区别(如下图所示)。

在不使用归一化的代价函数中,如果我们设置一个较小的学习率,那么很可能我们需要很多次迭代才能到达代价函数全局最优解;如果使用了归一化,那么无论从哪个位置开始迭代,我们都能以相对很少的迭代次数找到全局最优解。

如果特征值处于相似范围,那么归一化没有必要,但是使用归一化也不会带来坏处,因此归一化一般都是必做的步骤.

归一化方法:

对数据集特征x1,x2归一化的过程: 

  • 计算每个特征所有样本数据的均值:\mu = \dfrac{1}{m}\sum\limits_{i=1}^{m}x^{(i)}
  • 减去均值得到对称的分布:x : =x-\mu
  • 归一化方差:\sigma^{2} = \dfrac{1}{m}\sum\limits_{i=1}^{m}x^{(i)^{2}},x = x/\sigma^{2} (实际上应该是除以标准差??)

8.梯度消失与梯度爆炸

如下图所示的神经网络结构,以两个输入为例:


这里我们首先假定g(z)=z,b[l]=0 所以对于目标输出有:

\hat y = W^{[L]}W^{[L-1]}\cdots W^{[2]}W^{[1]}X

  1. W[l]的值大于1的情况:  激活函数的值将以指数级递增;
  2. W[l]的值小于1的情况:  激活函数的值将以指数级递减。

上面的情况对于导数也是同样的道理,所以在计算梯度时,根据情况的不同,梯度函数会以指数级递增或者递减,导致训练导数难度上升,梯度下降算法的步长会变得非常非常小,需要训练的时间将会非常长。

在梯度函数上出现的以指数级递增或者递减的情况就分别称为梯度爆炸或者梯度消失。

 

解决方法:利用初始化

以一个单个神经元为例子: 

由上图可知,当输入的数量n较大时,我们希望每个wi的值都小一些,这样它们的和得到的zz也较小。

这里为了得到较小的wi,设置Var(wi)=1/n(var即方差,1是wi的均值,n是n^{[l-1]}也就是第l-1层的神经元个数,也就是第l层神经元的输入特征数),这里称为Xavier initialization。 
对参数进行初始化:

WL = np.random.randn(WL.shape[0],WL.shape[1])* np.sqrt(1/n)
#sqrt用来求标准差,1/n是权重矩阵wl的方差

这么做是因为,如果激活函数的输入x近似设置成均值为0,标准方差1的情况,输出z也会调整到相似的范围内。虽然没有解决梯度消失和爆炸的问题,但其在一定程度上确实减缓了梯度消失和爆炸的速度。

不同激活函数的 Xavier initialization:

  1. 激活函数使用Relu:Var(w_{i})=\dfrac{2}{n}
  2. 激活函数使用tanh:Var(w_{i})=\dfrac{1}{n}

其中n是n^{[l-1]}

9.梯度检验

梯度的数值逼近:

双边导数:f'(\theta) = \lim\limits_{\varepsilon \to 0}=\dfrac{f(\theta+\varepsilon)-(\theta-\varepsilon)}{2\varepsilon}f'(\theta)     误差:O(\varepsilon^{2})

单边导数:f'(\theta) = \lim\limits_{\varepsilon \to 0}=\dfrac{f(\theta+\varepsilon)-(\theta)}{\varepsilon}                       误差:O(\varepsilon)

由图可以看出,双边误差逼近的误差是0.0001,相比单边逼近的误差0.03,其精度要高了很多。

进行梯度检验之前需要进行参数连接,将所有参数连接成一个大的向量

因为神经网络中有大量的参数:W^{[1]},b^{[1]},\cdots,W^{[L]},b^{[L]}为了做梯度检验,需要将这些参数全部连接起来,reshape成一个大的向量θ。

同时对dW^{[1]},db^{[1]},\cdots,dW^{[L]},db^{[L]}执行同样的操作:

接着利用双边导数进行梯度估算

 f'(\theta) = \lim\limits_{\varepsilon \to 0}=\dfrac{f(\theta+\varepsilon)-(\theta-\varepsilon)}{2\varepsilon}f'(\theta)

判断上图中的d\theta_{approx}\approx d\theta是否接近。

判断公式:\dfrac {||d\theta_{approx}-d\theta||_{2}}{||d\theta_{approx}||_{2}+||d\theta||_{2}}

其中||\cdot ||_{2}表示欧几里得范数,它是误差平方之和,然后求平方根,得到的欧氏距离。

实现梯度检验需要注意的问题:

  • 梯度检验是用来找bug的,不要在训练过程中使用梯度检验,只在debug的时候使用,使用完毕关闭梯度检验的功能;
  • 如果算法的梯度检验出现了错误,要检查每一项,找出错误,也就是说要找出哪个dθapprox[i]与dθ的值相差比较大
  • 求dθ不要忘记了正则化项
  • 梯度检验不能与dropout同时使用。因为每次迭代的过程中,dropout会随机消除隐层单元的不同神经元,这时是难以计算dropout在梯度下降上的代价函数J;
  • 在随机初始化的时候运行梯度检验,或许在训练几次后再进行。
     
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值