CNN的两个问题:
1. max pooling架构中用到的max无法微分,那在gradient descent的时候该如何处理?
2. L1 的Regression
DL的3步骤
1. define the function set(network structure)
2. goodness of function(loss function如cross entropy)
3. pick the best function(optimization如gradient descent)
得到一个neural network,接下来要如何改进?
结果表现不好改进方法
1、在training set上准确率不高:
换激活函数:ReLU、Maxout
自适应(adaptive)学习率:Adagrad、RMSProp、Momentum、Adam
2、在testing set上准确率不高:Early Stopping、Regularization、Dropout
目录
分析改进方向
训练的流程:
DL三步训练完之后, 检查训练集结果,
训练集表现不好, 则回DL三步调整,
训练集表现好, 则看测试集结果,
测试集表现不好, 则解决过拟合, 解决过拟合过程中使训练集结果变差, 重回DL三步调整,
测试集训练集表现都好, 就成功了.
检查训练集正确率
先检查训练集上的表现是DL独特之处. deep learning虽然参数多,overfitting往往不会是第一个问题. 训练集结果不好时, 需要重新修改之前的步骤.
方法如k-nearest neighbor,decision tree在训练集上正确率100%,不必检查, 但容易overfitting.
提高测试集上的正确率
训练集表现很好后,把模型应用到测试集. 当训练集结果好,测试集结果不好, 为Overfitting.
解决overfitting问题时,可能会使训练集结果变坏, 需要回头检查,如果变坏,从头调整训练过程. 同时得到好结果即可.
不要看到测试集表现不好就认定overfitting
看testing data的图,横坐标是梯度下降更新次数,纵坐标则是error rate(越低说明model表现得越好),黄线表示20层神经网络,红色表示56层的神经网络.
56层网络的error rate高,表现较差,20层的表现较好,56层是overfitting吗?
这个问题要检查训练集表现, 神经网络在训练集结果:
20层本来就比56层表现更好,所以测试集结果不能说明56层overfitting.
神经网络在训练集表现不好的原因很多,如局部极小,鞍点(saddle point),高原点(plateau). 该56层神经网络压根没训练好.
广义上将训练集表现不好称为underfitting,但准确来说underfitting本意为模型复杂度不足,参数不够多,能力不足以解出这个问题;但该56层网络参数是比20层的多,不应该被称为underfitting,就只是没有训练好.
结论
看到DL中用到某种方法, 要思考其解决以下哪个问题:
1. 在训练集表现不够好
2. 在测试集表现不够好
如dropout只用在测试集结果不好时,训练集结果不好时不能用.
下面介绍训练集, 测试集两个问题优化方法.
改善训练集结果
更换激活函数
训练不好的原因可能是设计得不好, 如激活函数不合适,尝试更换.
sigmoid function作为激活函数,更深不一定结果更好. 图为在MNIST手写数字识别上的结果,层数增多, 精度持平,接着精度下降, 此时并非overfitting, 因为这张图就是训练集结果.
梯度消失
上面这个问题的原因不是overfitting,而是Vanishing Gradient(梯度消失):
Backpropagation用sigmoid function时, 当网络过深,靠近input的参数梯度(即对loss function的微分)较小;靠近output处梯度较大. 学习率不变,靠近输入的参数更新慢;靠近输出的参数更新快.
靠近输入的参数还几乎random,找到local minima,然后converge(收敛). 接着参数的loss下降的速度很慢,梯度接近0,基于random的参数收敛,模型参数没有训练充分.
梯度前小后大原因
某一个参数w对总损失l的偏微分,即梯度∂l/∂w,其含义为参数变化对损失值的影响:
$$ \frac{\partial l}{\partial w} \approx \frac{\mathrm{\Delta}l}{\mathrm{\Delta}w} $$
因此可以通过令第一层参数w加Δw,观察对loss(output和target差距)影响:
sigmoid function图像,把负无穷大到正无穷大之间的值都挤压到0~1之间,较大input处的增减对输出影响小.
Δw通过sigmoid function之后,输出变小,影响随层数(被sigmoid压缩次数)的递增而衰减.
即使值很大,每经过一个sigmoid function被缩小一次,越深衰减次数越多,对output影响小,也即input对loss的影响小,靠近input的weight对loss的梯度远小于靠近output的梯度.
解决方法
1. RBM,先训练第1层再训练第2层. Backpropagation时,尽管第一个layer没被训练到,但pre-train时已经训练好了.
2.改激活函数
ReLU
激活函数Rectified Linear Unit(整流线性单元函数,又称修正线性单元).
$$ \begin{equation} ReLU(x) = \begin{cases} x & if\ x> 0\\ 0 & if\ x\le 0 \end{cases} \end{equation} $$
令z为输入,a为输出, 图像为:
ReLU优点:
1.运算比sigmoid function快很多
2. 生物理由(Biological reason)
3. 等同于无穷多个bias不同的sigmoid叠加(Infinite sigmoid with different biases)
4. 可以处理梯度消失
处理梯度消失
ReLU 作用在两个范围. 1. input>0激活函数是线性的;2. input<=0, output=0的神经元没有任何作用可以拿掉.
拿掉后网络变成瘦长的linear network,linear即output=input,不会出现激活函数使input产生的影响逐层递减的问题.
问题1: DL目标是构建non-linear、复杂的function. ReLU后变成linear function网络会变弱吗?
ReLU的network整体还是non-linear,当input改变没有导致神经元operation region改变,可看作linear function;当导致神经元operation region改变,output=0变为output=input,还是non-linear function.
问题2:对loss function梯度下降要求可微,但ReLU分段函数,不可微(在z=0点).
region处于z>0时,微分值(gradient)为1;当region处于z<0时,微分值(gradient)为0;很难出现z为0情况, 可设微分为0然后不用管它.
ReLU变形
1. Leaky ReLU: 当input<0的时候,output=0,此时微分值梯度也为0,无法更新参数,input<0的时候,微分后还应有一点点的值,令a=0.01z
2. Parametric ReLU: z的系数可以不固定,令a=α*z,系数作为网络参数,训练集梯度下降学得,每个neuron都可以有不同的值.
Maxout
ReLU可以看作Maxout的特例. Maxout让network自动学习激活函数(Learnable activation function),由training data决定.
所有方法通用的第一步: 给定input x1, x2,乘上几组不同的weight分别得到5,7,-1,1.
原方法直接输入不同神经元,通过激活函数后输出;
Maxout network将输入分组,比如5,7分一个group,然后在group里选最大值7作为output. 该过程类似Max Pooling,把原来几个神经元的输入组成group,不再加激活函数,直接选取最大值作为输出. 原神经元被合并看做一个新神经元,其input为原来几个“neuron”的input组成的vector,output则取input的最大值.
几个element被分为一个group作为网络中超参数要调.
Maxout -> RELU
Maxout可以模仿ReLU.
1. ReLU
ReLU的neuron输入x乘上weight w,加bias b,得到z, z输入激活函数ReLU,得输出a.
输入: z=wx+b为蓝线. 输出: a=z或a=0为绿线.
2. Maxout z1参数w和b与ReLU的参数一致,z2参数w和b全部设为0,然后做Max Pooling,选取z1 z2的较大值作为a.
神经元的输入为[z1, z2]. z1=wx+b为蓝线, z2=0为红线. 输出为max[z1, z2]绿线.
此时ReLU和Maxout输出相同,为相同激活函数.
Maxout -> More than ReLU
除了ReLU,Maxout还可以实现更多不同的激活函数
当z2参数w和b不是0,而是w' b'.
神经元的输入为[z1, z2]. z1=wx+b为蓝线, z2=w'x+b'为红线. 输出为max[z1, z2]绿线.
此时激活函数(绿线),由network参数决定,为Learnable Activation Function,形状可根据训练集生成
Maxout总结
Maxout为Learnable Activation Function.
可以实现任何piecewise linear convex activation function(分段线性凸激活函数);
其中激活函数分多少段(piece),取决于多少个element z放同一组.
如何训练Maxout
需要解决Max不能微分的问题.
Maxout中圈出神经元output(即最大值).
此时Max operation为 linear operation,它仅接在group中一个element上,可把没有连接到的element去除,得到细长的linear network.
真正训练时网络并不含有max函数,而是一个化简后的linear network;没有开始训练时这个含有max函数无法微分,但只要丢进去了一笔data,形状确定转化为细长 linear network,可以根据这笔训练数据使用反向传播训练被network留下来的参数.
问题: 一次训练只涉及留下的那些参数,剩下被拿掉的参数?
也是理论上的问题,实际操作每个linear network结构由输入数据来决定的,数据不同structure不同,留下参数不同,network的structure不断变换,实际上每一个weight参数都会train到.
自适应学习率
Adaptive learning rate, 可参考之前的一篇笔记:
https://blog.csdn.net/lagoon_lala/article/details/116212939
Adagrad
更新公式:
$$ \left. w^{t + 1}\leftarrow w^{t} - \frac{\eta}{\sqrt{\sum_{i = 0}^{t}\left( g^{i} \right)^{2}}}g^{t} \right. $$
Adagrad将固定的学习率除以所有过去梯度值的平方和开根号:
$$ \sqrt{\sum_{i = 0}^{t}\left( g^{i} \right)^{2}} $$
考虑两个参数,如果给定方向上,平常梯度都比较小,说明比较平坦,给较大学习率;反之, 平常梯度大陡峭的,给较小学习率.
RMSProp
实际问题可能更复杂,线性回归优化(optimization)的对象,即loss function,是凸函数(convex);DL的loss function可以是任何形状.
对convex loss function, 每个方向的平坦或陡峭状态不变,只需要判断该方向整体的平坦陡峭情况. 但复杂情况中,即使是在同一个方向上(如w1方向),loss function一会儿平坦一会儿陡峭,要随时根据梯度快速地调整学习率.
DL用Adagrad不够,需要动态调整学习率, 升级为RMSProp.
RMSProp的做法:
学习率η为定值, 除以变化值σ,σ等于上一个σ和当前梯度g的加权方均根Root Mean Squares(在第一次更新时即为梯度值):
$$ \left. w^{1}\leftarrow w^{0} - \frac{\eta}{\sigma^{0}}g^{0},\sigma^{0} = g^{0} \right.\\ \left. w^{2}\leftarrow w^{1} - \frac{\eta}{\sigma^{1}}g^{1},\sigma^{1} = \sqrt{{\alpha\left( \sigma^{0} \right)}^{2} + \left( {1 - \alpha} \right)\left( g^{1} \right)^{2}} \right.\\ \left. w^{t + 1}\leftarrow w^{t} - \frac{\eta}{\sigma^{t}}g^{t},\sigma^{t} = \sqrt{{\alpha\left( \sigma^{t - 1} \right)}^{2} + \left( {1 - \alpha} \right)\left( g^{t} \right)^{2}} \right. $$
权重α作为超参数可以自由调整的(通常设0.9), RMSProp跟Adagrad不同之处在于,Adagrad的分母是对所有已知梯度取平方和开根号,考虑整个过程平均梯度信息;RMSProp虽然也含有所有梯度,用α调整不同梯度使用程度,α小则更倾向于新的梯度描绘的error surface平滑或陡峭程度,无视旧的梯度信息.
Momentum
解决卡在local minimum、saddle point或plateau问题.
出现local minima时必须在每个维度都是低谷形状,假设低谷出现的概率为p,由于参数较多(假设1000个), 每个参数位于低谷概率为,p^1000. 网络越复杂,参数越多,概率越低.
所以在大型神经网络没那么多的local minima,被卡住很有可能是接近global minima处.
Momentum灵感来自真实世界.
球从左上角滚下来,到plateau、local minima由于惯性会继续往前走一段, 有可能翻过山坡,走到比local minima还要好的地方. 惯性放入梯度下降即为Momentum.
普通的梯度下降是算一个梯度, 挪一次更新:
加上Momentum的更新方向,不只考虑梯度方向,还考虑上一次更新方向,用一个变量v去记录前一个时间点update的方向. 随机选一个初始点θ^0,v记录上次update(初始为0),接下来计算θ^0处的梯度,移动的方向是由上次移动方向v和梯度反方向-L来决定的,即:
$$ v^{1}~ = ~\lambda v^{0} - ~\eta\nabla L\left( \theta^{0} \right) $$
其中λ也是手动调整的参数,表示惯性对前进方向的影响有多大.
走第一步, 根据初始点计算的动量移动到θ1, 并计算θ1点的梯度和动量, 即第二个时间点要走的方向,绿色虚线,代表动量λv (惯性想要继续走的方向);红色虚线,代表负梯度-ηg;蓝色实线为两者矢量和, 即移动方向.
每一个时间点移动的步伐,包括大小和方向,是过去所有gradient的加权和.
由于的λ小于1,因此越早的梯度权重就越小.
在加入Momentum以后,每一次移动的方向,就是负梯度加上Momentum方向,Momentum其实就是上一个时间点的movement(移动).
图中,红色实线是负梯度方向,即坡度要走的方向;绿色虚线是Momentum方向,即上一次移动的方向;蓝色实线则是最终真正走的方向.
走到local minimum处梯度为0,红色箭头没有指向,Momentum绿色箭头,指向右侧(即之前是要走向右边),所以参数更新方向继续向右.
Adam
RMSProp + Momentum=Adam
算法algorithm:
先初始化. m0是Momentum, 前一个时间点的movement. v0就是RMSProp里计算梯度的root mean square的σ. t表示时间点.
先算出梯度g_t.
根据动量和梯度,算出现在要走的方向m_t——Momentum思想
根据动量和梯度平方,算一下放在分母的v_t——RMSProp思想
接下来是RMSProp和Momentum里没有的,偏差修正(bias correction),m_t和v_t都除以一个值得m_t hat, v_t hat,这个值本来比较小,后来会越来越接近于1.
最后更新参数,把修正后的Momentum 乘学习率α,再除掉normalize的RMSProp后建议的学习率分母.
改善测试集结果
主要有三个方法Early Stopping、Regularization和Dropout. Early Stopping和Regularization是经典通用的做法;Dropout是DL特色做法.
早停
当学习率调得很好,随着训练的进行,训练集loss逐渐减小,在测试集上的loss先降后升.
理想上在测试集的loss最小的时候停下来,而不是训练集loss最小;但测试集未知, 用验证集替代.
正则化
regularization重新定义了要最小化的损失函数. 原本的loss增加一项正则项Regularization, “惩罚”复杂度高的模型.
L2 正则化
损失函数:
$$ L^{'}\left( \theta \right) = L\left( \theta \right) + \lambda\frac{1}{2}\left\| \theta \right\|_{2} $$
正则项为参数的L2 norm(L2范数),即参数集里的每一个参数平方和:
$$ \left\| \theta \right\|_{2} = \left( w_{1} \right)^{2} + \left( w_{2} \right)^{2} + \ldots $$
通常正则项不考虑bias项,因为正则化目的是使function更平滑,bias与平滑程度没有关系.
正则项中的1/2是为了求微分方便而凑,梯度为对损失函数求微分:
$$ \frac{\partial L^{'}}{\partial w} = \frac{\partial L}{\partial w} + \lambda w $$
参数更新公式为:
$$ \begin{aligned} w_{}^{t + 1} &\rightarrow w_{}^{t} - \eta\frac{\partial L^{'}}{\partial w} \\&= w_{}^{t} - \eta\left( {\frac{\partial L}{\partial w} + \lambda w_{}^{t}} \right) \\&= \left( {1 - \eta\lambda} \right)w_{}^{t} - \eta\frac{\partial L}{\partial w} \end{aligned} $$
每次更新参数之前,都会乘(1-ηλ),而η和λ通常设为很小值,因此该因子接近于1,比如0.99, 即每次更新先把原参数减小点再说. 随着更新次数增加,即使原梯度(未加正则项)为0, 参数每次会减小一点. 即权重衰减Weight Decay.
问题: 参数会全变0?
不会, 最后微分项会和前面这一项取得平衡.
DL中正则化的重要性没有SVM这类方法高,Early Stopping减少更新次数,可类似地避免参数离0太远. SVM把正则化写在了objective function(目标函数)里面,SVM直接求解凸优化问题,无需迭代,用不上Early Stopping, 而是一步走到最好结果, 只能用正则化.
L1 正则化
L1正则在神经网络不常用,因为很难得到稀疏解而且算起来很复杂.
L1正则项每一个参数的绝对值累加,即:
$$ \left\| \theta \right\|_{1} = \left| w_{1} \right| + \left| w_{2} \right| + \ldots $$
损失函数:
$$ L^{'}\left( \theta \right) = L\left( \theta \right) + \lambda\frac{1}{2}\left\| \theta \right\|_{1} $$
绝对值不能微分怎么处理?
绝对值就是一个V字形的函数,左边微分值-1,右边微分值1,只有0不能微分的,真的0了就胡乱给它一个值,比如0,就好了. (参考广义函数里的弱导数)
w>0,微分为+1,w<0,微分为-1,故微分后可看作sgn function:
$$ \frac{\partial L^{'}}{\partial w} = \frac{\partial L}{\partial w} + \lambda{{sgn}\left( w \right)} $$
L1正则化更新公式:
$$ \begin{aligned} w_{}^{t + 1}&\rightarrow w_{}^{t} - \eta\frac{\partial L^{'}}{\partial w}\\ &= w_{}^{t} - \eta\left( {\frac{\partial L}{\partial w} + \lambda{\mathit{sgn}\left( w^{t} \right)}} \right)\\& = w_{}^{t} - \eta\frac{\partial L}{\partial w} - \eta\lambda{\mathit{sgn}\left( w^{t} \right)}\\& = \left( {1 - \eta\lambda} \right)w_{}^{t} - \eta\frac{\partial L}{\partial w} \end{aligned} $$
更新参数时将固定减去一部分, 使参数绝对值更接近0.
L1 对比L2, 同样是让参数的绝对值变小,L1每次更新减掉一个值, L2乘上一个小于1的固定值. 当参数w的绝对值比较大的时候,L2让w下降得更快,当参数w的绝对值比较小的时候,L2下降慢. L1训练得参数是比较稀疏(sparse)的,即一些接近0,一些很大.
Dropout
训练
使用dropout方法训练, 每次update参数之前,对神经元(包括输入层不包括输出层)做sampling(抽样) ,每个neuron都有p%的几率被丢掉,跟它相连的weight也都要被丢掉.
sampling后,神经网络变细长了,然后训练该细长网络.
与maxout区别: Maxout是每一笔data对应的一种网络,而Dropout每一次更新的网络结构不同(一个minibatch对应一次update,一个minibatch含多笔data).
使用dropout后在训练集表现变差,在测试集上的结果变好.
如果训练集上表现都不好, 就不适合dropout.
测试
注意:
1. 测试的时候不做抽样,所有的neuron都要被用到.
2. 训练时dropout rate为p%,则所有weight要乘(1-p%)才能被当做测试的weight使用.
训练测试使用参数不一样原因:
假设现在的dropout rate是50%,训练时, 按照每次丢掉一半神经元的情况学习,测试时没有dropout,如果使用同一组weight,则得到输出是真实需要输出的2倍, 造成结果不match.
dropout理解
让一个神经网络里总是有队友会拖后腿dropout,其他神经元就更努力做,才能carry这个队友.
dropout是一种终极的ensemble的方法, ensemble指每次都只从训练集抽一部分数据训练.
bias和variance折衷时提过两种误差:
1. bias大(参数过少)
2. variance大(参数过多)
复杂模型往往是bias比较准,但variance很大. 很多个笨重复杂的model,虽然variance都很大,但最后平均起来,结果往往会很准.
ensemble利用这个特性,抽很多子集,训练很多model,每个结构不一样;测试时的数据通过所有的model,得到一大堆的结果, 把这些结果平均起来当做最后的output.
如果model很复杂,这一招往往有用,如random forest(随机森林)也实践这个精神,决策树很容易overfitting,random forest不会.
dropout与ensemble对比
dropout方法训练时, 每次拿一个minibatch出来就做一次update,对神经元进行sample,每个minibatch训练的network不同. 设神经元有M个,总共可能的网络数量有2^M个;相当于用很多个minibatch分别去训练很多个network(minibatch一般设100笔data),每个network都只用一个minibatch的data来train,可能会让人感到不安,才100笔data,但这些不同的network参数共享,同一个weight在不同的network里被不同的minibatch 训练, 它是拿所有这些network的minibatch合起来一起train的效果.
ensemble测试时,把训练好的一大把network通通拿出来,把所有network的结果平均起来得到输出. 但是在实际操作上,network实在太多了,每一个network都丢一个input运算量太大了. 用一个完整的network,weight由之前那一把network 训练, 对应weight乘(1-p%),测试时输出跟network分开考虑的ensemble输出相似.
如果训练的神经网络如下:
用不同的network structure做ensemble:
用一整个network训练时dropout,把weight乘上一个值而不做ensemble:
只有linear的network,dropout与ensemble等价,非线性不等价但也能改善其表现.
network接近linear时,dropout得到结果更好,如ReLU和Maxout. 所以常配合使用.