PS:学习内容来自李宏毅机器学习2019版
平均误差(Average Error)会随着模型复杂增加呈指数上升趋势。更复杂的模型并不能给测试集带来更好的效果,而这些Error的主要来源是偏差(bias)和方差(variance)。
关于bias和variance,可以查看链接里的解答。机器学习中Bias(偏差)、Error(误差)Variance(方差)的区区别与联系。下面简单介绍自己对问题答复中的理解,不一定正确,因为有些回答有一些出入,如有错误,恳请指出改正。
在《机器学习》(周志华)一书中:泛化误差(Error) = 偏差(Bias) + 方差(Variance) + 噪声(Noise),其中:
偏差和方差计算公式,以及用于机器学习中模型的选择也可以通过链接进行更详细的学习,同时里面含有偏差与方差对机器学习模型选择相关内容。偏差(Bias)和方差(Variance)–机器学习中的模型选择。
然后对m求期望:
E [ m ] = E [ 1 N ∑ x n ] = μ E[m] = E[\frac 1 N \sum{x^n}] = \mu E[m]=E[N1∑xn]=μ
这个估计是 μ \mu μ的无偏估计。m对于 μ \mu μ的离散程度(方差):
V a r [ m ] = σ 2 N Var[m] = \frac {\sigma^2} N Var[m]=Nσ2
估测样本x的方差,则是用样本值与样本平均值只差的平均即: s 2 = 1 N ∑ n ( x n − m ) 2 s^2 = \frac 1 N\sum_n{(x^n - m)^2} s2=N1n∑(xn−m)2
对其求期望得到样本方差: E [ s 2 ] = N − 1 N σ 2 ≠ σ 2 E[s^2]=\frac {N-1} N \sigma^2\neq \sigma^2 E[s2]=NN−1σ2=σ2
用同意model,在不同的训练集中找到function就是不一样的。就像在靶心上射击,进行了横夺组(一组多次)。现在需要知道它的散布是怎样的,讲100个宇宙中的model画出来不同的数据集之前什么都有可能发生。
一次模型的方差比较小,也就是比较集中,离散程度较小。而五次模型的方差就比较大,同理散布比较广,离散程度较大。所以用比较简单的模型,方差是比较小的(就像射击的时候,每次射击的设置都集中在一个比较小的区域中)。如果用到了复杂的模型,方差就很大,散布比较开。这也是因为简单的模型收到不同训练集的影响是较小的。
将误差才分为偏差和方差。简单模型(左边)是偏差比较大造成的误差,这种情况叫做欠拟合,而复杂模型(右边)是方差过大造成的误差,这种情况叫做过拟合。
如果模型没有哼好的训练训练集,就是偏差过大,也就是欠拟合;如果模型很好的训练训练集,即再训练集上得到很小的错误,但在测试集上得到大的错误,这意味着模型可能方差比较大,就是过拟合。对于欠拟合和过拟合,使用不同的方式来处理的
此时应该重新设计模型。因为之前的函数集里面可能跟本没有包含f*。可以:
简单粗暴的方法:更多的数据。但是很多时候不一定能做到收集更多的data。可以针对问题的理解对数据集做调整。比如识别手写数字的时候,偏转角度的数据集不够,那就将正常的数据集左转15度,右转15度,类似这样处理。还有时,应当注意各类数据之间的比列。
现在在偏差和方差之间就需要一个权衡想选择的模型,可以平衡偏差和方差产生的错误,使得总错误最小,但是下面这件事最好不要做:
用训练集训练不同的模型,然后再测试集上比较误差,模型3的错误较小,就认为模型3好。但实际上这只是我们手上的测试集,真正完整的测试集并没有。比如再已有的测试集上错误是0.5,但又条件收集到更多的测试集后错误通常大于0.5。
图中public的测试集是已有的,private是没有的,不知道的。交叉验证就是将训练集再分为两部分,一部分作为训练集,一部分作为验证集。用训练集训练模型,然后再验证集上比较,确定出最好的模型之后(比如模型3),再用全部的训练集训练模型3,然后再用public的测试集进行测试,此时一般得到的错误都是大一些的。不过此时会比较想再回去调一下参数,调整模型,让在public的测试集上更好,但不太推荐这样。上述方法可能会出现训练集拆分的时候因为数据拆分情况,而使得模型效果较差,为此可以使用K折验证的方法。
将训练集分成K份,比如3份。每次将其中一份作为验证集,其他的作为训练集,分别得到同一模型的误差最后取平均得到平均误差,最后选择平均误差最小的模型,使用全部测试集数据进行训练模型。比如在下图中三份训练结果平均错误模型1最后,再用全部训练集训练模型1。
梯度下降的做法在回归模型中已经介绍了。
在回归问题的第三步中,需要解决下面的最优化问题:
θ ∗ = arg min θ L ( θ ) \theta^*=\argmin_\theta L(\theta) θ∗=θargminL(θ)
上图中左边黑色为损失函数的曲线,假设从左边最高点开始,如果学习率调整的的刚刚好,比如红色的线,就能顺利而且较快的找到最低点。如果学习率调整的太小了,比如蓝色的线,就会走的太慢,训练时间会较长,同时在局部最优时,可能难以离开局部最优形成的山谷去寻找全局最优。如果学习率调整的太大,如绿色的线,就会在上面震荡,走不下去,无法达到最低点。还有一种可能,学习率非常大,直接飞出去了,更新参数的时候只会发现损失函数越更新越大。
虽然这样可以可视化,但可视化尽可在参数是一维或者二维的时候进行,更高维则无法进行可视化了。解决方案是上图右边的方案,将参数改变对损失函数的影响进行可视化。比如学习率太小(蓝色的线),损失函数下降的非常慢;学习率太大(绿色的线),损失函数下降恒快,但是马上卡住不下降了;学习率特别大(黄色的线),损失函数就飞出去了;红色的差不多刚好,可以得到一个好的结果。
通常刚开始,初始点会距离最低点比较远,所以使用大一点的学习率。更新几次参数后,比较靠近最低点了,此时需要减少学习率。一个想法就是需要动态的调整学习率,其中对上述过程思考一种简单想法:随着次数增加,通过一些因子来减少学习率如: η t = η t t + 1 \eta^t = \frac {\eta^t} {\sqrt{t+1}} ηt=t+1ηt。学习率不能是一个值通用所有特征,因而不同的参数需要不同的学习率。
每个参数的学习率都除以之前微分的均方根。
普通的梯度下降为: w t + 1 ← w t − η t g t η t = η t t + 1 w^{t+1}\leftarrow w^t-\eta^tg^t \\ \eta^t = \frac {\eta^t} {\sqrt{t+1}} wt+1←wt−ηtgtηt=t+1ηt
其中 w w w是一个参数。Adagrad可以做的更好:
w t + 1 ← w t − η t σ t g t g t = ∂ L ( θ t ) ∂ w w^{t+1}\leftarrow w^t-\frac {\eta^t} {\sigma^t} g^t \\ g^t = \frac {\partial L(\theta^t)} {\partial w} wt+1←wt−σtηtgtgt=∂w∂L(θt)
其中 σ t \sigma^t σt:之前参数的所有微方的均方根,对于每个参数都是不一样的。下图是一个参数更新过程,可以直观理解 σ t \sigma^t σt的含义。
将Adagrad的式子进行化简:
在Adagrad中,当梯度越大的时候,步伐应该越大,但是梯度越大的时候,下面的分母也会越大,从而导致步伐会越小。因此分母会会造成反差。下面对梯度越大应该步伐进行解释:
比如初始点在 x 0 x_0 x0,最低点为 − b 2 a -\frac b {2a} −2ab,最佳步伐应该是 x 0 x_0 x0到最低点 − b 2 a -\frac b {2a} −2ab之间的距离 ∣ x 0 + b 2 a ∣ |x_0+\frac b {2a}| ∣x0+2ab∣,也可以写成 ∣ 2 a x 0 + b 2 a ∣ |\frac {2ax_0+b} {2a}| ∣2a2ax0+b∣。而2a刚好是 ∣ 2 a x 0 + b ∣ |2ax_0+b| ∣2ax0+b∣在 x 0 x_0 x0这一点的微分。
这样可以认为如果算出来的微分越大,则是距离最低点越远。而且最好的步伐和微分的大小成正比。所以如果使用的步长如果与微分成正比,它可能是比较好的。
结论1-1:梯度越大,就跟最低点的距离越远。这个结论在多个参数的时候不一定成立了。
上图左边是两个参数的损失函数,颜色代表损失函数的值。如果只考虑参数 w 1 w_1 w1,就像图中蓝色的线,得到右边上图结果;如果只考虑参数 w 2 w_2 w2,就像图中绿色的线,得到右边下图结果。确实对于a和b,结论1-1成立,同理c和b也成立。但是如果对比a和c,就不成立了,c比a大,但c距离最低点是比较远的。所以结论1-1是在没有考虑参数对比的情况下,才能成立的。所以还不完善。
之前说到的最佳距离 ∣ 2 a x 0 + b 2 a ∣ |\frac {2ax_0+b} {2a}| ∣2a2ax0+b∣,还有个分母2a。对function进行二次微分刚好可以得到: ∂ 2 y ∂ x 2 = 2 a \frac {\partial^2y} {\partial x^2} = 2a ∂x2∂2y=2a
所以最好的步伐应该是:
一次微分 二次微风 \frac {一次微分} {二次微风} 二次微风一次微分
即不仅和一次微分成正比,还和二次微分成反比。最好的步长应该考虑到二次微分。
再回到之前的Adagrad,对于 g t g^t gt是一次微分,显然 σ t \sigma^t σt不是二次微分,是否 σ t \sigma^t σt与二次微分有关呢?对于 σ t \sigma^t σt就是希望再尽可能不增加过多运算的情况下模拟二次微分。弱国计算二次微分,在实际情况中可能会增加很多的时间。
之前的梯度下降,需要考虑每一个样本点的损失:
L = ∑ n ( y ^ n − ( b + ∑ w i x i n ) ) 2 θ i = θ i − 1 − η ∇ L ( θ i − 1 ) L = \sum_n{(\hat{y}^n-(b+\sum{w_ix_i^n}))^2} \\ \theta^i = \theta^{i-1} - \eta \nabla L(\theta^{i-1}) L=n∑(y^n−(b+∑wixin))2θi=θi−1−η∇L(θi−1)
相脚之下随机梯度下降法更快,其损失函数不需要处理训练集所有的数据,选取一个例子 x n x^n xn L = ∑ n ( y ^ n − ( b + ∑ w i x i n ) ) 2 θ i = θ i − 1 − η ∇ L n ( θ i − 1 ) L = \sum_n{(\hat{y}^n-(b+\sum{w_ix_i^n}))^2} \\ \theta^i = \theta^{i-1} - \eta \nabla L^n(\theta^{i-1}) L=n∑(y^n−(b+∑wixin))2θi=θi−1−η∇Ln(θi−1)
此时不需要像之前那样对所有的数据进行处理,只需要计算某一个例子的损失函数 L n L_n Ln就可以赶紧更新梯度了。假设有20个数据样例,常规梯度下降法要处理到所有二十个例子,但随机梯度下降只需要处理一个例子就更新,因而同样的时间下,随机梯度更新已经走了二十步了。
比如有个函数: y = w 1 x 1 + w 2 x 2 + b y = w_1x_1+w_2x_2+b y=w1x1+w2x2+b
两个输入的分布的范围很不一样,数量级相差较大,建议把他们的范围缩放,使得不同输入的范围一样的或者数量级相差不是很大。
上图左边是 x 1 x_1 x1的范围比 x 2 x_2 x2要小很多,所以当 w 1 w_1 w1和 w 2 w_2 w2做同样变化时, x 1 x_1 x1对y的变化影响是较小的, x 2 x_2 x2对y的变化影响是比较大的。
坐标系中是两个参数的损失等高线,因为 w 1 w_1 w1对y的变化影响较小,所以 w 1 w_1 w1对损失函数的影响比较小,因而 w 1 w_1 w1对损失函数有比较小的微分,所以 w 1 w_1 w1方向上是比较平滑的。同理 w 2 w_2 w2对损失函数的影响比较大,因而 w 1 w_1 w1对损失函数有比较大的微分,所以 w 2 w_2 w2方向上是比较尖的峡谷。
上图右边是两个参数的范围比较接近,右边的绿色图就比较接近圆形。对于左边的情况,上面讲过这种狭长的情形如果不用Adagrad比较难处理,两个方向上需要不同的学习率,同一组学习率会搞不定它。而右边情形更新参数就会变得比较容易。左边的梯度下降并不是向着最低方向走的,而是顺着等高线切线的法向走的。但右边就可以向着原心(最低点)走,这样做参数更新也是比较有效率。
方法非常多,这里举例一种常见的作法,线性归一化的方式:
上图每一列都是一个样本数据,里面都有一组特征。对每一个二维度i(绿色框)求和计算平均数,记作 m i m_i mi,同时计算标准差,记作 σ i \sigma_i σi。然后每一个例子的第i个输入,减去平均数 m i m_i mi,然后除以标准差 σ i \sigma_i σi,得到的结果是所有的维数都是平均值为0,方差为1。
对于损失函数寻找最小值,比如再在 θ 0 \theta^0 θ0处,可以找到一个小范围圆圈内找到损失函数细小的 θ 1 \theta^1 θ1,不断的这样去寻找。接下来就是如何在小圆圈内快速找到最小值?
若 h ( x ) h(x) h(x)在 x = x 0 x = x_0 x=x0点的某个邻域内有无限阶倒数(即可无线微分,infinitely differentiable),那么在此邻域内有:
h ( x ) = ∑ k = 0 ∞ h k ( x 0 ) k ! ( x − x 0 ) k = h ( x 0 ) + h ′ ( x 0 ) ( x − x 0 ) + h ′ ′ ( x 0 ) 2 ! ( x − x 0 ) 2 + . . . \begin{aligned}h(x) &= \sum^\infty_{k=0}\frac {h^k(x_0)} {k!}(x-x_0)^k \\ &= h(x_0)+h^{'}(x_0)(x-x_0)+\frac {h^{''}(x_0)} {2!}(x-x_0)^2+...\end{aligned} h(x)=k=0∑∞k!hk(x0)(x−x0)k=h(x0)+h′(x0)(x−x0)+2!h′′(x0)(x−x0)2+...
当 x x x很接近 x 0 x_0 x0时,有 h ( x ) = h ( x 0 ) + h ′ ( x 0 ) ( x − x 0 ) h(x) = h(x_0)+h^{'}(x_0)(x-x_0) h(x)=h(x0)+h′(x0)(x−x0),该式就是函数 h ( x ) h(x) h(x)在 x = x 0 x=x_0 x=x0点附近关于 x x x的幂函数展开式,也叫泰勒展开式。
下面是两个变量的泰勒展开式
回到之前寻找圆圈内最小值部分。基于泰勒展开式,在(a,b)点的红色圆圈范围内,可以将损失函数用泰勒展开式进行简化:
将问题进而简化为下图:
不考虑s,可以看出身下的部分是两个向量 ( Δ θ 1 , Δ θ 2 ) (\Delta\theta_1,\Delta\theta_2) (Δθ1,Δθ2)和 ( u , v ) (u,v) (u,v)的内积,那么让它最小,就是和向量 ( u , v ) (u,v) (u,v)方向相反。
然后将 u u u和 v v v带入。
发现最后的式子就是梯度下降的式子。但这里用这种方法找到这个式子有个前提,泰勒展开式给的损失函数的估算值是要足够精确的,而这需要红色的圆圈足够小即学习率足够小来保证。所以理论上每次更新参数都想要损失函数减小的话即保证 d d d足够小,就需要保证学习率足够小。
所以在实际中,当更新参数的时候,如果学习率没有设好,那么无法保证 d d d足够小成立,所以导致做梯度下降的时候,损失函数没有越来越小。上述泰勒展开式是一次项的,如果考虑到二次项(如牛顿法),在实际应用中不是特别好,会涉及到二次微分等,多很多的运算,性价比不好。
容易陷入局部极值,还有可能卡在不是极值的驻点,还有可能实际中只是当微分值小于某一数值就停下来了,但这里只是比较平缓的,并不是极值点。