视频地址 : https://mooc.study.163.com/course/2001281003
样本数据通常会被分为三个部分:
数据集的划分比例和数据集大小有关,一般来说分成下面几种情况:
原因:
验证集的目的是为了验证不同的算法哪种更加有效,所以验证集只要足够大能够验证大约2-10种算法哪种更好就足够了,不需要使用20%的数据作为验证集。如百万数据中抽取1万的数据作为验证集就可以了。
测试集的主要目的是评估模型的效果,如在单个分类器中,往往在百万级别的数据中,我们选择其中1000条数据足以评估单个模型的效果。
训练出来的模型有三种基本状态:
方差和偏差的博弈:
一方面,我们利用训练集对模型进行训练就是为了使得模型在train集上使 bias 最小化,避免出现underfitting的情况,但是如果模型设置的太复杂(帮助降低bias),虽然在train集上 bias 的值非常小,模型甚至可以将所有的数据点正确分类,但是当将训练好的模型应用在dev 集上的时候,却出现了较高的错误率。这是因为模型设置的太复杂则没有排除一些train集数据中的噪声,使得模型出现overfitting的情况,在dev 集上出现高 variance 的现象。
也就是说: 片面追求低bias可能要以高varience为代价,反之亦然.
例子:
以上为在人眼判别误差在0%的情况下,该最优误差通常也称为“贝叶斯误差”,如果“贝叶斯误差”大约为15%,那么图中第二种情况就是一种比较好的情况。
上述第三列的"双高"现象(高bias高varience)可能原因如下图:
原因:没有找到边界线,但却在部分数据点上出现了过拟合,则会导致这种高偏差和高方差的情况。
虽然在这里二维的情况下可能看起来较为奇怪,出现的可能性比较低;但是在高维的情况下,出现这种情况就成为可能。
对模型的好坏评价,首先要看bias而不是varince(因为模型首先要能拟合训练集,如果连训练集都不能完好表示又怎么能用来搞验证集和测试集呢??)
因此首先要以降低bias为目标,在此基础上(bias达到一定阈值)降低varience.
一般来说,降低bias有如下几种方法(黑体加粗为常用方式):
降低varience有如下几种方法:
基本过程见下图:
正则化之所以能够降低方差(减少过拟合),原因如下:
正则化在神经网络的cost function 中引入了一个正则项(下图紫色部分),作为模型复杂度的惩罚(过拟合就是因为模型太"复杂",把所有特征都学习到了,因此要惩罚他让他变"呆"一点)
直观上:
正则化因子λλ设置的足够大的情况下,为了使代价函数最小化,权重矩阵W就会被设置为接近于0的值。则相当于消除了很多神经元的影响,那么图中的大的神经网络就会变成一个较小的网络(当然上面这种解释是一种直观上的理解,但是实际上隐藏层的神经元依然存在,但是他们的影响变小了,便不会导致过拟合)。
数学上:
假设神经元中使用的激活函数为,在加入正则化项后: 当增大,导致减小,便会减小,由上图可知,在z较小的区域里,tanh(z)函数近似线性,所以每层的函数就近似线性函数,整个网络就成为一个简单的近似线性的网络,从而不会发生过拟合。
正则化举例:
Logistic regression
加入正则化项的代价函数:
上式为逻辑回归的L2正则化。
- L2正则化
- L1正则化
其中λ为正则化因子。
注意:
lambda
在python中属于保留字,所以在编程的时候,用“lambd”代表这里的正则化因子λ。
Neural network
加入正则化项的代价函数:
其中,因为w的大小为,该矩阵范数被称为“Frobenius norm”
在加入正则化项后,梯度变为:
则梯度更新公式变为:
代入可得:
其中,为一个<1的项,会给原来的W[l]一个衰减的参数,所以L2范数正则化也被称为“权重衰减(Weight decay)”。
Dropout能够降低方差(减少过拟合),原因如下:
Dropout(随机失活)通过随机消除一些神经元,使得保留下来的节点较少,从而转变成一个规模较小的网络进行训练.
这里我们以单个神经元入手,单个神经元的工作就是接收输入,并产生一些有意义的输出,但是加入了Dropout以后,输入的特征都是有可能会被随机清除的.
(前一层的输出对于后一层而言相当于输入的特征,前一层一些神经元被随机失活相当于随机丢掉一些特征,因而后一层的神经元"不会再特别依赖于任何一个输入特征",也就是说不会给任何一个输入设置太大的权重)
所以通过传播过程,dropout将产生和L2范数相同的收缩权重的效果。
对于不同的层,设置的keep_prob也不同(如下图紫色),一般来说神经元较少的层(如最后两层),会设keep_prob =1.0 (相当于没有进行dropout),神经元多的层(如前两层),则会将keep_prob设置的较小.
dropout的缺点:
dropout的一大缺点就是其使得 Cost function不能再被明确的定义,因为每次迭代都会随机消除一些神经元节点,所以每次迭代的是不一样的,这就意味着不能在一张图中绘制损失函数的下降过程(正常的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]的期望值,所以需要的部分除以一个keep_prob。
Inverted dropout通过对“a3 /= keep_prob”,则保证无论keep_prob设置为多少,都不会对Z[4]的期望值产生影响。
Notation:在测试阶段不要用dropout,因为那样会使得预测结果变得随机。
使用归一化的原因:
如果输入特征处于不同的范围内,可能有些特征值从0到1,有些从1到1000,那么不使用归一化和使用归一化前后Cost function 的函数形状会有很大的区别(如下图所示)。
在不使用归一化的代价函数中,如果我们设置一个较小的学习率,那么很可能我们需要很多次迭代才能到达代价函数全局最优解;如果使用了归一化,那么无论从哪个位置开始迭代,我们都能以相对很少的迭代次数找到全局最优解。
如果特征值处于相似范围,那么归一化没有必要,但是使用归一化也不会带来坏处,因此归一化一般都是必做的步骤.
归一化方法:
对数据集特征x1,x2归一化的过程:
- 计算每个特征所有样本数据的均值:
- 减去均值得到对称的分布:
- 归一化方差:, (实际上应该是除以标准差??)
如下图所示的神经网络结构,以两个输入为例:
这里我们首先假定g(z)=z,b[l]=0 所以对于目标输出有:
- W[l]的值大于1的情况: 激活函数的值将以指数级递增;
- W[l]的值小于1的情况: 激活函数的值将以指数级递减。
上面的情况对于导数也是同样的道理,所以在计算梯度时,根据情况的不同,梯度函数会以指数级递增或者递减,导致训练导数难度上升,梯度下降算法的步长会变得非常非常小,需要训练的时间将会非常长。
在梯度函数上出现的以指数级递增或者递减的情况就分别称为梯度爆炸或者梯度消失。
解决方法:利用初始化
以一个单个神经元为例子:
由上图可知,当输入的数量n较大时,我们希望每个wi的值都小一些,这样它们的和得到的zz也较小。
这里为了得到较小的wi,设置Var(wi)=1/n(var即方差,1是wi的均值,n是也就是第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:
- 激活函数使用Relu:
- 激活函数使用tanh:
其中n是
梯度的数值逼近:
双边导数: 误差:
单边导数: 误差:
由图可以看出,双边误差逼近的误差是0.0001,相比单边逼近的误差0.03,其精度要高了很多。
进行梯度检验之前需要进行参数连接,将所有参数连接成一个大的向量
因为神经网络中有大量的参数:为了做梯度检验,需要将这些参数全部连接起来,reshape成一个大的向量θ。
同时对执行同样的操作:
接着利用双边导数进行梯度估算
判断上图中的是否接近。
判断公式:
其中表示欧几里得范数,它是误差平方之和,然后求平方根,得到的欧氏距离。
实现梯度检验需要注意的问题:
- 梯度检验是用来找bug的,不要在训练过程中使用梯度检验,只在debug的时候使用,使用完毕关闭梯度检验的功能;
- 如果算法的梯度检验出现了错误,要检查每一项,找出错误,也就是说要找出哪个dθapprox[i]与dθ的值相差比较大;
- 求dθ不要忘记了正则化项;
- 梯度检验不能与dropout同时使用。因为每次迭代的过程中,dropout会随机消除隐层单元的不同神经元,这时是难以计算dropout在梯度下降上的代价函数J;
- 在随机初始化的时候运行梯度检验,或许在训练几次后再进行。