深度学习笔记导航
- 前言
- 传送门
- 改善深层神经网络:超参数调整,正则化,最优化(Improving Deep Neural Networks: Hyperparameter Tuning, Regularization, and Optimization)
-
- 深度学习实践(Practical Aspects of Deep Learning)
-
- 基础
-
- 数据集分割
- 偏差/方差(bias/variance)
- 基本分析方法
- 正则化(regularization)
-
- L2正则化(L2 regularization)
- L2正则化降低过拟合的理解
- 随机失活(Dropout Regularization)
- 数据增广(data augmentation)
- 提前终止(early stopping)
- 加速
-
- 归一化/标准化输入(normalizing training sets)
- 梯度消失/爆炸的应对(vanishing/exploding gradient)
- 梯度检验
- 优化算法(Optimization Algorithms)
-
- Mini-batch gradient descent
- 稳定波动的算法
-
- 指数加权平均(exponentially weighted moving average)
- 动量梯度下降(Gradient Descent with Momentum)
- RMSprop(root mean square prop)
- 综合稳定方法:Adam(Adaptive Momentum Estimation)
- 学习率衰减(learning rate decay)
- 局部最优问题(local optima)
- 超参数调优,批量归一化,框架(Hyperparameter tuning, Batch Normalization, and Programming Frameworks)
-
- 基础知识
-
- 超参数重要性直觉
- 参数选点的组织方法(organize your search process)
- batch-normalization
-
- 应用到单层上:
- 应用到神经网络中:
- 理解:
- 应用到测试集上:
- soft-max regression
-
- 与logistic regression的紧密联系
- 符号约定
- 概要
- 训练过程
- 由sigmoid推广到softmax激活函数
- 深度学习框架
前言
本系列文章是吴恩达深度学习攻城狮系列课程的笔记,分为五部分。
这一章讲了关于优化神经网络的一系列trick,注重实践,否则会忘掉。
我的笔记不同于一般的笔记,我的笔记更加凝练,除了结论以及公式,更多的是对知识的理解,结合课程可以加速理解,省去很多时间,但是请注意,笔记不能替代课程,应该结合使用。
传送门
结构化机器学习项目,我建议放在最后看。
首先学这一节对你后面的学习没有影响,我就是跳过去学的。而且他更多的讲的是策略,尤其是举了很多后面的例子,你听了不仅不太好懂,而且没啥意思,所以我建议放在最后看。
神经网络与深度学习(Neural Networks and Deep Learning)
改善深层神经网络:超参数调整,正则化,最优化(Hyperparameter Tuning)
卷积神经网络(Convolutional Neural Networks)
序列模型与循环神经网络(Sequence Models)
结构化机器学习项目(Structuring Machine Learning Projects)
改善深层神经网络:超参数调整,正则化,最优化(Improving Deep Neural Networks: Hyperparameter Tuning, Regularization, and Optimization)
深度学习实践(Practical Aspects of Deep Learning)
基础
数据集分割
- 训练集 train set
用来训练算法
- 开发集 dev set(hold-out cross validation)
调整参数,选择特征,以及对学习算法做出其他决定
- 测试集 test set
从开发集中选出最优的几个模型在测试集上进行评估
- 数据集划分比例
以前数据量小的时候,是622分,但是当数据量变大,dev set和test set的增长没有那么快,所以后面这两个的比例会缩小,比如98 1 1的比例
一般小样本会习惯于7的训练3的测试,但是实际上严格来说,开发和测试是不可以混为一谈的,其两者的目的不一样
目前的理解也仅限于此,至于dev和test的区别,网上的总结千篇一律,都是抄吴恩达的讲义,我还需要后面进一步在实践中感悟。
偏差/方差(bias/variance)
- 欠拟合/过拟合(under-fitting/over-fitting):
欠拟合就是没把大头当回事,过拟合就是将偶然太当真。欠拟合准确率不够,过拟合不具有普遍适应性。
- 错误率(error):
字面意思
- 偏差(bias):
模型对测试集的准确率高,则偏差低
- 方差(variance):
模型在测试集和开发集上的差距小,则方差低。为什么叫方差呢?因为同一个模型,两个集上差距不大,说明两个集本身的差距就不大,均匀分布,就是方差小。还可以体现出模型是否过拟合,过拟合会加大方差。
- 最优误差/基本误差(base error):
一般来说,默认0,这是假设人工识别准确率极高。如果这个是15%,那么在训练集上16%的错误率就是很完美的拟合。毕竟,机器的效果是要和人对比的,人不行,机器也没必要做到极致。
基本分析方法
-
解决高偏差
- 这是首要的,先降低bias
- Bigger Network:最常用的,模型够复杂,拟合的就可以够好
- Longer Training:训练更久
- advanced optimization algorithm:换优化算法
- NN architecture search:换架构
-
解决高方差
- regularization:正则化可以减少过拟合,抵消掉更大网络带来的过拟合。
- more data:最常用的,通常来说,方差大就是不够均匀,那我们只需要获取更多数据,就很容易解决均匀问题
- NN architecture search:最后的杀招
-
最终得到一个双低模型。一般来说,采用更多数据和更大网络可以更好的实现trade-off,
正则化(regularization)
说白了,正则化就是减弱联系,制造干扰,来提高抗干扰行。
这里要用到范数,所以可以参考这篇文章
常见范数公式
L2正则化(L2 regularization)
正则化是对J(cost function)下手的,进而影响到反向传播中的参数调整过程。
对Logistic Regression,我们可以采用L2和L1
- L2 Regularization
J ( w , b ) = 1 m ∑ i = 1 m L ( y ( i ) ^ , y ( i ) ) + λ 2 m ∣ ∣ w ∣ ∣ 2 + λ 2 m b 2 J(w,b)=\dfrac{1}{m}\sum_{\mathclap{i=1}}^{m}L(\hat{y^{(i)}},y^{(i)})+\dfrac{\lambda}{2m}||w||_2+\dfrac{\lambda}{2m}b^2 J(w,b)=m1i=1∑mL(y(i)^,y(i))+2mλ∣∣w∣∣2+2mλb2
理论上,b那一项不用写,因为和高维度的w比,b那一项没什么影响。
- L1 Regularization
J ( w , b ) = 原有项 + λ 2 m ∣ ∣ w ∣ ∣ 1 J(w,b)=原有项+\dfrac{\lambda}{2m}||w||_1 J(w,b)=原有项+2mλ∣∣w∣∣1
L1的特点是,最后生成的w中0会多一些,有人说可以压缩模型体积,但是实际上体积没什么明显变化,所以目前主流还是采用L2
在深层神经网络中,就直接用L2了,但是需要注意的是,L2并不是用2范数,而是用Frobenius范数,就一种arcane的玄学原因导致明明是2范数的特征却使用Frobenius范数的名称
- cost function的变化
J = 原有项 + λ 2 m ∑ i = 1 L ∣ ∣ W [ i ] ∣ ∣ F J=原有项+\dfrac{\lambda}{2m}\sum_{\mathclap{i=1}}^{L}||W^{[i]}||_F J=原有项+2mλi=1∑L∣∣W[i]∣∣F
可以理解为加上所有元素的平方和根号
- dW的变化
d W [ i ] = 原有项 + λ m W [ i ] dW^{[i]}=原有项+\dfrac{\lambda}{m}W^{[i]} dW[i]=原有项+mλW[i]
形式上,F范数里是有平方项的,所以求个导把2分母消掉就好说。
- W的更新
仍然是用原有的公式,但是因为dW变化,所以W更新公式可以重写:
W [ i ] = W [ i ] − α [ 原有项 + λ m W [ i ] ] W^{[i]}=W^{[i]}-\alpha [原有项+\dfrac{\lambda}{m}W^{[i]}] W[i]=W[i]−α[原有项+mλW[i]]
W [ i ] = ( 1 − λ m ) W [ i ] − α 原有项 W^{[i]}=(1-\dfrac{\lambda}{m})W^{[i]}-\alpha 原有项 W[i]=(1−mλ)W[i]−α原有项
从这个角度理解,相当于W在更新之前先进行了缩放,常被称作weight decay。不过吴恩达不喜欢这么叫,或许这么理解没什么用。
L2正则化降低过拟合的理解
从效果上来说,L2正则化的效果是将W的权值缩小。正则化参数 λ \lambda λ 越大,W的权值下降的更快,而且越小。
而且,即使是新增了一项,从效果上来说,新的J函数依然凸的,依然随着迭代次数的增加而monotonically减少。
反过来说,如果你使用正则化计算方法但是画图的时候还是用的旧的cost function,那你的函数图可能就不是单调的了。
- 理解方式1
当W的权值减少,那么部分神经元的效果就会打折扣,效果上相当于收缩了神经网络的规模。随着收缩,逐渐从过拟合转移到欠拟合高偏差状态,最后就变成了Logistic Regression。
- 理解方式2
当W权值减小,那么Z的值也会小,那么无论是ReLU还是sigmoid或者tanh函数,0附近的是g函数近似于线性的,前面也说过,如果一个神经网络都是线性的,那么就会被简化,所以这种理解方式其实也是从简化神经网络的角度理解的。
随机失活(Dropout Regularization)
思想:随机让一部分神经元失效,生成一个简化的子神经网络。
常用方法:反向随机失活(inverted dropout)
步骤:
- D [ i ] = n p . r a n d o m . r a n d ( A [ i ] . s h a p e [ 0 ] , A [ i ] . s h a p e [ 1 ] ) D^{[i]}=np.random.rand(A^{[i]}.shape[0],A^{[i]}.shape[1]) D[i]=np.random.rand(A[i].shape[0],A[i].shape[1])
- A [ i ] ∗ = D [ i ] A^{[i]}*=D^{[i]} A[i]∗=D[i]
- A [ i ] / = A^{[i]}/= A[i]/=keep_prob
理解:
- 生成一个矩阵,决定我们要把哪些输出元素毙掉,然后将输出元素毙掉,最后放大其他元素来保持Z的范数期望不变。
- 直到现在,我仍然搞不明白如何毙掉一个神经元,按我的理解,应该是先算出A,然后 A ∗ = d A*=d A∗=d这个时候d是一个列向量,利用广播特性,一次性毙掉一行,实现毙掉神经元的操作。然而实际上只是随机毙掉元素。或许我们可以从另一个角度理解,对不同的样本,
- 注意测试集里不要这样干,因为我们已经有一个泛化的模型了,不需要继续泛化。
- 每次迭代,都会随机毙掉一些元素,所以可以避免两个神经元之间有紧密的联系,让模型的适应性更强。
- 不同层之间也可以选择不同的keep_prob参数来控制drop的比例
- dropout尤其适用于小样本情况,这种情况往往会出现过拟合。比如CNN。
- 缺点就是,bp和cost function会变得模糊,所以在打开drop开关之前先确保cost function是单调递减的。
数据增广(data augmentation)
将数据进行轻微改变,比如翻转之类的,制造类似的数据,可以实现类似于正则化的效果,减弱过拟合。
提前终止(early stopping)
将J函数和dev error画在一个图上,然后在要发生过拟合的附近终止训练即可。
优点:简单快速。
缺点:无法发挥出其他工具的力量,试图使用一个方法同时降低bias和variance,难以取得极致的效果。
加速
归一化/标准化输入(normalizing training sets)
- 归一化均值
μ n × 1 = 1 m ∑ i = 1 m X ( i ) \mu_{n\times 1} = \dfrac{1}{m}\sum_{\mathclap{i=1}}^mX^{(i)} μn×1=m1i=1∑mX(i)
X − = μ X-=\mu X−=μ
- 归一化方差
σ n × 1 2 = 1 m ∑ i = 1 m X ( i ) ∗ ∗ 2 \sigma^2_{n\times 1}=\dfrac{1}{m}\sum_{\mathclap{i=1}}^mX^{(i)}**2 σn×12=m1i=1∑mX(i)∗∗2
X / = σ 2 X/=\sqrt{\sigma^2} X/=σ2
- 注意,通过训练集计算出的 μ \mu μ和 σ \sigma σ要直接用在测试集上,不要用测试集自己算 μ \mu μ和 σ \sigma σ,因为我们对数据集总体做出的处理应该是统一的。
理解:
经过实验可以观察出:归一化后,即使是相差比较悬殊的维度,最后的范围也会相近,最多只是几倍的差距。如果不归一化,正常情况的cost function是一个狭长的(elongated)碗,对于狭窄维,需要定很小的步长来保证尽量收敛。
如果归一化,就可以选择尽量大的步长,学习率。
点击跳转batch-normalization
梯度消失/爆炸的应对(vanishing/exploding gradient)
之前说过最后的结果是类似于W矩阵的累乘,那么在深度学习中很明显会产生一种指数效应,W的整体权小于1就会产生梯度消失,大于1会产生梯度爆炸,拖慢训练速度。所以我们要让W的初值权重大约为1附近
引理:如果输入特征 A [ i − 1 ] A^{[i-1]} A[i−1]就是大约标准化的,经过权重为1的W矩阵处理, Z [ i ] Z^{[i]} Z[i]仍然保持近似标准化的。
常用方法是进一步特殊地初始化W矩阵,不仅要更趋近于0,而且要自适应样本数量。
首先,假设 v a r ( W ) = 1 n var(W)=\dfrac{1}{n} var(W)=n1
然后:
W [ i ] = n p . r a n d o m . r a n d n ( W [ i ] . s h a p e ) ∗ n p . s q r t ( 1 n i − 1 ) W^{[i]}=np.random.randn(W^{[i]}.shape)*np.sqrt(\dfrac{1}{n^{{i-1}}}) W[i]=np.random.randn(W[i].shape)∗np.sqrt(ni−11)
方差选择
- 如果g=ReLU,那么使用 v a r ( W ) = 2 n var(W)=\dfrac{2}{n} var(W)=n2会更好
- Xavier初始化:如果是sigmoid或者tanh,使用 1 n \dfrac{1}{n} n1或者 2 n [ i − 1 ] + n [ i ] \dfrac{2}{n^{[i-1]}+n^{[i]}} n[i−1]+n[i]2
- 方差也可以作为超参数调整,前面加一个乘子,但是优先级比较低。
梯度检验
偏导的近似求法:
应该使用双边误差, f ′ ( θ ) = f ( θ + ϵ ) − f ( θ − ϵ ) 2 ϵ f^\prime(\theta)=\dfrac{f(\theta+\epsilon)-f(\theta-\epsilon)}{2\epsilon} f′(θ)=2ϵf(θ+ϵ)−f(θ−ϵ)
其误差为 O ( ϵ 2 ) O(\epsilon^2) O(ϵ2)比单边误差的 O ( ϵ ) O(\epsilon) O(ϵ)要小很多
求解过程(Grad Check):
- 将所有W,B,dW,dB,reshape为两个向量, θ , d θ \theta, d\theta θ,dθ
- 对每一个元素,进行双边误差计算偏导,最后形成一个向量 d θ a p p r o x d\theta_{approx} dθapprox
- 比较 d θ d\theta dθ和 d θ a p p r o x d\theta_{approx} dθapprox, ∣ ∣ d θ − d θ a p p r o x ∣ ∣ 2 ∣ ∣ d θ ∣ ∣ 2 + ∣ ∣ d θ a p p r o x ∣ ∣ 2 < 1 0 − 7 \dfrac{||d\theta-d\theta_{approx}||_2}{||d\theta||_2+||d\theta_{approx}||_2}<10^{-7} ∣∣dθ∣∣2+∣∣dθapprox∣∣2∣∣dθ−dθapprox∣∣2<10−7是理想情况,-5就要多看一眼,-3必然是有突出的误差,需要去仔细寻找。
注意:
- 只有在debug中才需要使用,在训练的时候加入grad checking会极大地拖慢速度。
- 发现问题后寻找是那一个下标出现了问题,然后从下标反推是那一层出现了问题。
- 如果使用了正则化,你的J要变化。
- grad check不可以和dropout同时打开,仅仅是dropout就让cost function难以计算,因为要求和,但是你并不知道是哪些部分被丢弃了。
- 这是一种意外情况,假设W和B的理想值是0附近,然后初始化也是0附近,但是随着迭代,W和B越来越大。这个时候就先检查一下再初始化,后训练再检查。
优化算法(Optimization Algorithms)
Mini-batch gradient descent
方法:
- 将X分割为若干个Mini-batch,用 { 大括号上标 } 来区分不同的batch, X { t } , Y { t } , J { t } X^{\{t\}},Y^{\{t\}},J^{\{t\}} X{t},Y{t},J{t}
- 进行while循环训练,每一次迭代,都要遍历所有batch,每一个batch都进行一次W和B的调整,所以从效果上来说,曾经一次迭代只能调整一次W和B,现在可以调整若干次。
- 从此以后,iteration和一次mini-batch对应,epoch和mini-batch的总体对应。
理解:
- 相当于牺牲一点准确度,去换取快速的前进。因此,对每一个batch,他的图像 J { t } J^{\{t\}} J{t}并不是单调的,而是伴随着噪声趋势向下,这是因为其他batch在这次迭代中也会干扰W和B,但是总的方向应该正确。可以通过减少 α \alpha α来改善(ameliorate)噪声。
- 要选择适当的mini-batch size。
- 选择m,虽然方向总是正确,也充分利用了向量化,但是调整次数太少,单次迭代太慢。
- 如果选择1,则变成随机梯度下降,stochastic gradient descent不会收敛,只会oscillate在最值附近。而且,在提升每一次迭代的调整次数的同时,也会降低向量化的程度,不见得就比m快。
- 所以应该选择1-m之间作为mini-batch size,去平衡向量化和调整次数的平衡。
- 还需要注意的是,size最好为 2 n 2^n 2n,这是为了适应CPU-GPU的内存。
稳定波动的算法
指数加权平均(exponentially weighted moving average)
说白了,指数加权平均就是牺牲一点精准度来快速计算平均值。
在趋势预测中,我们要得出拟合线,拟合线的计算公式为:
v t = β v t − 1 + ( 1 − β ) θ t v_t=\beta v_{t-1}+(1-\beta)\theta_t vt=βvt−1+(1−β)θt
其中,v代表拟合值, θ \theta θ代表样本值
具体执行就是对v不断更新覆盖,如果想记录可以用一个列表来记录。这样求平均比直接求效率高很多,是一种替代方法。
我们可以这样理解:
- 可以很明显看出来这个公式具有记忆效应,对越近的样本记忆效应越强(权重大),越远的样本,就会被越多的 β \beta β作用,权重不断减少
- 可以得出结论, β \beta β越趋近于1,平均的样本就越多,曲线受当天的影响就越小,优点就是抗噪声,缺点就是呈现一种延迟(latency),对样本的适应性下降。
- 从更数学的角度理解,我们把公式写完整了,会发现所有 θ \theta θ的系数之和为下式,整体是逼近1的,所以有类似加权过往所有样本的效果。
( 1 − β ) ∑ i = 0 m − 1 β i = 1 − β m (1-\beta)\sum_{\mathclap{i=0}}^{m-1}\beta^i=1-\beta^m (1−β)i=0∑m−1βi=1−βm
- 从效果上说,实际上 v t v_t vt是大致相当于 1 1 − β \dfrac{1}{1-\beta} 1−β1,已知 ( 1 − ϵ ) 1 ϵ = 1 e ≈ 0.35 (1-\epsilon)^{\dfrac{1}{\epsilon}}=\dfrac{1}{e}\approx 0.35 (1−ϵ)ϵ1=e1≈0.35,也就是 1 1 − β \dfrac{1}{1-\beta} 1−β1个距离前的样本的效果只有不到当前样本的35%,所以可以认为均值主要由这几个样本贡献。
偏差修正:
在初期求平均时,因为前面没有积累,会造成结果远低于真实值的偏差,这个时候就可以使用 v t = v t 1 − β t v_t=\dfrac{v_t}{1-\beta^t} vt=1−βtvt来修正,天数越少,放大效应越明显。
最终,原来的线会收敛到修正线上。
动量梯度下降(Gradient Descent with Momentum)
实际上,无论是batch还是mini-batch,梯度下降的方向并不总是最好的方向,存在着非最优方向的波动,这限制了我们对学习率的加大。反过来说,如果能保持接近正确的方向,就意味着我们可以加大学习率。
具体执行:
- 我们使用 v d W [ i ] v_{dW^{[i]}} vdW[i]和 v d B [ i ] v_{dB^{[i]}} vdB[i]代替 d W 和 d B dW和dB dW和dB,计算过程同指数加权平均。
- v d W = β v d W + ( 1 − β ) d W v_{dW}=\beta v_{dW}+(1-\beta)dW vdW=βvdW+(1−β)dW , v d B = β v d B + ( 1 − β ) d B v_{dB}=\beta v_{dB}+(1-\beta)dB vdB=βvdB+(1−β)dB
理解公式:
- 核心就在指数加权平均上,第一项可以理解为一种动量,第二项可以理解为冲量,冲量会对动量造成影响,但是因为动量的束缚,不会彻底改变方向。
- 可调超参数为 α , β \alpha,\beta α,β,当我们选择了合适的 β \beta β来降低了波动,保持正确方向,就可以提高学习率来加速
RMSprop(root mean square prop)
这同样是用来稳定方向的。
对每一次更新:
- S d W = β S d W + ( 1 − β ) d W 2 ; S d B = β S d B + ( 1 − β ) d B 2 S_{dW}=\beta S_{dW}+(1-\beta)dW^2 ; S_{dB}=\beta S_{dB}+(1-\beta)dB^2 SdW=βSdW+(1−β)dW2;SdB=βSdB+(1−β)dB2
- W = W − α d W S d W W=W-\alpha\dfrac{dW}{\sqrt{S_{dW}}} W=W−αSdW dW ; B = B − α d B S d B B=B-\alpha\dfrac{dB}{\sqrt{S_{dB}}} B=B−αSdB dB
理解:
- 首先 S d W S_{dW} SdW从数量级上是平方级别的,所以后面要加根号
- 假设 S d W S_{dW} SdW大,那么代表波动大,然后作用到分母上,就把大的变小。同理,小的就会变大,这样就变相的把大小给平衡了。从效果上,感觉就像是把一个长条碗变成了一个圆碗。
- 之后就可以使用更大的学习率了。
偏差修正:
- 可能碰到的意外就是分母太小,所以可以选择 W = W − α d W S d W + ϵ W=W-\alpha\dfrac{dW}{\sqrt{S_{dW}}+\epsilon} W=W−αSdW +ϵdW, ϵ \epsilon ϵ的数量级可以在 1 0 − 8 10^{-8} 10−8,防止分母过小的情况。
综合稳定方法:Adam(Adaptive Momentum Estimation)
综合Momentum和RMSProp,以及两种方法的修正,一种广泛适用且有效的优化算法Adam诞生了。
对t次mini-batch:
- 分别计算Momentum的v和RMSProp的s
v d W = β 1 v d W + ( 1 − β 1 ) d W , v d B = β 1 v d B + ( 1 − β 1 ) d B v_{dW}=\beta_1v_{dW}+(1-\beta_1)dW,v_{dB}=\beta_1v_{dB}+(1-\beta_1)dB vdW=β1vdW+(1−β1)dW,vdB=β1vdB+(1−β1)dB
s d W = β 2 s d W + ( 1 − β 2 ) d W 2 , s d B = β 2 s d B + ( 1 − β 2 ) d B 2 s_{dW}=\beta_2s_{dW}+(1-\beta_2)dW^2,s_{dB}=\beta_2s_{dB}+(1-\beta_2)dB^2 sdW=β2sdW+(1−β2)dW2,sdB=β2sdB+(1−β2)dB2
- 分别修正v和s的偏差(可选)
v d W c o r r e c t = v d W 1 − β 1 t , v d B c o r r e c t = v d B 1 − β 1 t v_{dW}^{correct}=\dfrac{v_{dW}}{1-\beta_1^t},v_{dB}^{correct}=\dfrac{v_{dB}}{1-\beta_1^t} vdWcorrect=1−β1tvdW,vdBcorrect=1−β1tvdB
s d W c o r r e c t = s d W 1 − β 2 t , s d B c o r r e c t = s d B 1 − β 2 t s_{dW}^{correct}=\dfrac{s_{dW}}{1-\beta_2^t},s_{dB}^{correct}=\dfrac{s_{dB}}{1-\beta_2^t} sdWcorrect=1−β2tsdW,sdBcorrect=1−β2tsdB
- 综合更新,修正0分母问题
W = W − α v d W c o r r e c t s d W c o r r e c t + ϵ W=W-\alpha\dfrac{v_{dW}^{correct}}{\sqrt{s_{dW}^{correct}}+\epsilon} W=W−αsdWcorrect +ϵvdWcorrect
B = B − α v d B c o r r e c t s d B c o r r e c t + ϵ B=B-\alpha\dfrac{v_{dB}^{correct}}{\sqrt{s_{dB}^{correct}}+\epsilon} B=B−αsdBcorrect +ϵvdBcorrect
可调节超参数:
- α \alpha α是最常调节的
- β 1 \beta_1 β1默认为0.9
- β 2 \beta_2 β2默认为0.999
- ϵ \epsilon ϵ默认为 1 0 − 8 10^{-8} 10−8
学习率衰减(learning rate decay)
为了最后的收敛(converge),在最后阶段学习率不能太大。但是并不意味着在初始阶段学习率就不能大。理论上,刚开始大后面小是最佳选择。
使得初期快速向最低点迈进,后期快速收敛。
随epoch减少的各种实现方法:
-
α = 1 1 + D e c a y − r a t e × E p o c h − n u m × α 0 \alpha=\dfrac{1}{1+Decay-rate\times Epoch-num}\times \alpha_0 α=1+Decay−rate×Epoch−num1×α0
此方法需要调节的超参数为 α 0 , D e c a y − r a t e \alpha_0,Decay-rate α0,Decay−rate
-
指数衰减(exponentially decay)
α = b a s e e p o c h − n u m × α 0 \alpha=base^{epoch-num}\times \alpha_0 α=baseepoch−num×α0
此方法需要调节的超参数为 b a s e , α 0 base,\alpha_0 base,α0
-
还有其他各种方法,总之就是一个随着epoch-num增加而递减的系数。
α = k e p o c h − n u m × α 0 \alpha=\dfrac{k}{\sqrt{epoch-num}}\times \alpha_0 α=epoch−num k×α0
α = k t × α 0 \alpha=\dfrac{k}{\sqrt{t}}\times \alpha_0 α=t k×α0
α = d i s c r e t e − s t a i r c a s e \alpha=discrete-staircase α=discrete−staircase,使用一个离散的分段函数来搞定。
还有手动调节方法:
就是你盯着你的模型,如果发现慢了,就自己调一下,有很多人在这么干,但是如果同时训练太多模型,这种方式就不实用了。
局部最优问题(local optima)
曾经人们担心出现大量的局部最优点,因为在二维空间上很容易产生。
但是实际上二维空间的直觉并不总是适应高维空间,比如20000维的空间,要让所有维度都是凸函数,可能性为 2 − 20000 ≈ 0 2^{-20000}\approx 0 2−20000≈0,也就是说,非全局最优点以外,导数为0的点,在高位空间大多是鞍点(saddle point)。
虽然不会造成局部最优问题,但是鞍点的平稳段(plateaus)仍然会造成学习缓慢的问题,所以优化算法就是用来加速来解决学习缓慢的问题的。
超参数调优,批量归一化,框架(Hyperparameter tuning, Batch Normalization, and Programming Frameworks)
基础知识
超参数重要性直觉
一般来说,超参数虽然多,但是也有个主次,以下是顺序
第一梯队:
- 学习率 α \alpha α
第二梯队:
- 动量系数 β \beta β
- 子集尺寸 mini-batch size
- 隐层神经元个数 hidden units
第三梯队:
- 隐层数量 layers
- 学习率衰减 learning rate decay
- Adam中的 β 1 , b e t a 2 , ϵ \beta_1, beta_2, \epsilon β1,beta2,ϵ,但是这个基本不用调
参数选点的组织方法(organize your search process)
首先就是有一个参数空间,维数和超参数数量相同。
有以下惯例(common practice):
- 在合适的范围内随机选点。 因为参数太多,所以网格化枚举选点不合适。
- 逐步缩小搜索区域(coarse to fine search)。
其他技巧——非均匀选点:
一般来说,均匀选点是可以应付的。
但有时候,靠近0的要取得密集一点,也就是灵敏性会发生变化。这种时候就应该先进行线性变换,然后取对数,再均匀随机取点,最后用指数变回去,实现非均匀化,从一端到另一端逐渐稀疏。
比如:
α [ 0.0001 , 1 ] \alpha [0.0001,1] α[0.0001,1],我们用
[ l g 1 0 − 4 , l g 1 ] [lg10^{-4},lg1] [lg10−4,lg1] 的区间
代码实现就是 r = − 4 ∗ n p . r a n d o m . r a n d ( ) r=-4*np.random.rand() r=−4∗np.random.rand() α = 1 0 r \alpha=10^r α=10r
又比如:
β [ 0.9 , 0.999 ] \beta [0.9,0.999] β[0.9,0.999],然后对我们来说, 1 1 − β \dfrac{1}{1-\beta} 1−β1才是重要的。取不取倒数对于均匀分布不影响,所以我们这里直接用 1 − β 1-\beta 1−β,即 r ∈ [ − 3 , − 1 ] , 1 − β = 1 0 r r \in [-3,-1],1-\beta=10^r r∈[−3,−1],1−β=10r 。从这个案例可以看出,用1做个减法就可以实现密集端的互换。
最后,再加几条技巧:
- 隔几个月就重新测试或者评估超参数。
- pandas训练法(穷人法):如果数据过多或者资源不够,一次只能训练少量模型,一个模型训练个几天,可以选择盯着随时改(babysit)
- caviar训练法(土豪法):计算资源充足,就可以同时(parallel)训练多个模型,把cost function同时画在一个图上,选择最好的
batch-normalization
这是logistic regression归一化的深层版本batch-normalization可以让参数优化变得更加容易,神经网络更鲁棒。
应用到单层上:
- 学术界也在争论是对A还是Z归一化,而实际上常用Z,有一点反直觉,毕竟我们认为A才是输入的。
- from i=1 to m:
对 Z ( i ) Z^{(i)} Z(i),求均值以及方差具体点击这里查看,然后 Z n o r m ( i ) = Z ( i ) − μ σ 2 + ϵ Z_{norm}^{(i)}=\dfrac{Z^{(i)}-\mu}{\sqrt{\sigma^2+\epsilon}} Znorm(i)=σ2+ϵ Z(i)−μ,现在 Z n o r m ( i ) 已经是 0 均值 1 方差的了 Z^{(i)}_{norm}已经是0均值1方差的了 Znorm(i)已经是0均值1方差的了
- from i=1 to m:
进一步定制化均值和方差, Z ~ ( i ) = γ ∗ Z n o r m ( i ) + β \tilde{Z}^{(i)}=\gamma *Z^{(i)}_{norm}+\beta Z~(i)=γ∗Znorm(i)+β,其中 γ 是目标标准差, β \gamma是目标标准差,\beta γ是目标标准差,β是目标均值,从目前的观察来看,可以对不同层的不同节点进行定制
应用到神经网络中:
通常和mini-batch一起使用,对iteration t:
- 修改原有的Z计算步骤。 Z [ i ] = W [ i ] Z [ i ] Z^{[i]}=W^{[i]}Z^{[i]} Z[i]=W[i]Z[i],$B^{[i]}可以去掉,因为后面是要重新指定均值的
- 计算 Z ~ [ i ] \tilde{Z}^{[i]} Z~[i]。使用Batch Norm计算,先计算归一化,再定制均值方差。 Z [ i ] ~ = γ [ i ] ∗ Z n o r m [ i ] + β [ i ] \tilde{Z^{[i]}}=\gamma^{[i]}*Z^{[i]}_{norm}+\beta^{[i]} Z[i]~=γ[i]∗Znorm[i]+β[i],注意,我们这个是element-wise计算,并且广播,可以看到,一个神经元(一行)会被一个 γ i 和 β i \gamma_i和\beta_i γi和βi作用。
- 反向传播。计算出 d W , d γ , d β dW,d\gamma,d\beta dW,dγ,dβ,可以直接用gradient descent来更新,也可以使用momentum,rms,adam来更新
理解:
- 就是参数空间变形,把所有参数归一化,可以使整体的参数空间尽量均匀。防止elongated情况出现。
- 对每一层的输出强制性修改为目标方差和均值,起到稳定作用,来提高鲁棒性,适应性。
- 由此,层与层之间的联系会减弱,前一层对后一层的影响下降,呈现一种轻微的独立性,独立学习,就学的更快了????(迷惑)
- 这种隔离性会产生轻微regularization的副作用。但是请注意,我们的本意只是加速!对每一个mini-batch约束均值和方差,都会产生一点噪音。可以通过增大mini-batch size(也就是少弄点组)来减小正则化效果。其实就是这种约束的次数越少,自然噪音就越少。
应用到测试集上:
- 模型是归一化的,所以测试数据也要归一化,而且归一化的 μ , γ \mu, \gamma μ,γ应该和训练集整体相符合,否则训练就没意义了。
- 因为测试集是一个一个数据向量喂进去测试结果,所以不能对测试集求均值和方差,但是又不能对一个数据求,没意义,所以要估算。
- 一般来说,最后的 μ [ i ] , γ [ i ] \mu^{[i]},\gamma^{[i]} μ[i],γ[i]估计值应该为所有mini-batch在该层的指数加权平均,这样也符合我们的第1点。至于为什么不用平均,具体我没有深究,指数加权肯定是比较省事。
soft-max regression
与logistic regression的紧密联系
结果不止两种,这种判断叫soft-max regression。
实际上,softmax是logistic彻头彻尾的推广。激活函数的算法都是sigmoid的推广。(具体细节在最后)
符号约定
- C=classes:种类总数
- 维度发生变化,垂直方向扩展 Y C × m Y_{C\times m} YC×m
- 损失函数定义:实际上就是Logistic regression的推广,C=2的时候,就是logistic regression的形式。
L ( y , y ^ ) = − ∑ j = 1 C y i l o g y i ^ = − ∑ j = 1 C y i l o g a i L(y,\hat{y})=-\sum_{\mathclap{j=1}}^Cy_i log\hat{y_i}=-\sum_{\mathclap{j=1}}^Cy_i log a_i L(y,y^)=−j=1∑Cyilogyi^=−j=1∑Cyilogai
- 成本函数定义,同Logistic Regression,因为我们仅仅在垂直维度推广了,水平维度没有变化。
概要
类比logistic regression,我们把输出层的sigmoid单节点层换成soft-max层,神经元个数由1变为C,激活函数使用其他的。
- soft-max函数也可以作为激活函数,sigmoid只不过是把1分为2种情况,而soft-max将1分为多种情况
- 具体表现为,原来的 y ^ 1 × m \hat{y}_{1\times m} y^1×m变成了 y ^ C × m \hat{y}_{C\times m} y^C×m,每一行代表种类,每一列之和都是1,每一个元素代表概率
- 实际上这就是logistic regression的推广(generalize),之所以Logistic Regression不用2高度,只是因为两种情况下有一个就好了。
训练过程
fp:
只需要推广最后一层的激活函数即可, g [ L ] 如下 g^{[L]}如下 g[L]如下:
- 先指数作用,保持概率大于0:
t = e Z [ L ] t=e^{Z^{[L]}} t=eZ[L]
- 求和+在广播机制下求0维度占比:
A [ L ] = t n p . s u m ( t , a x i s = ( 0 , ) , k e e p d i m s = T r u e ) A^{[L]} = \dfrac{t}{np.sum(t,axis=(0,),keepdims=True)} A[L]=np.sum(t,axis=(0,),keepdims=True)t
bp:
- 这是非常神奇的一点,形式竟然没有变化:(这其实就是在暗示你我们的激活函数也是sigmoid的推广!)
d Z [ L ] = Y ^ − Y = A [ L ] − Y dZ^{[L]}=\hat{Y}-Y=A^{[L]}-Y dZ[L]=Y^−Y=A[L]−Y
- 实际上,如果使用深度学习框架,不需要具体来进行bp,你只需要专注于fp
由sigmoid推广到softmax激活函数
令C=2,然后用一个样本实验。之所以用 z 2 = 0 z_2=0 z2=0是因为sigmoid的单样本实际上只接收一个特征。
输入:
[ z 1 z 2 = 0 ] \begin{bmatrix} z_1 \\ z_2=0 \\ \end{bmatrix} [z1z2=0]
输出:
[ e z 1 e z 1 + e z 2 e z 2 e z 1 + e z 2 ] \begin{bmatrix} \dfrac{e^{z_1}}{e^{z_1}+e^{z_2}} \\ \\ \dfrac{e^{z_2}}{e^{z_1}+e^{z_2}}\\ \end{bmatrix} ⎣ ⎡ez1+ez2ez1ez1+ez2ez2⎦ ⎤
化简得:
[ 1 1 + e − z 1 1 − 1 1 + e − z 1 ] = [ s i g m o i d ( z 1 ) 1 − s i g m o i d ( z 1 ) ] \begin{bmatrix} \dfrac{1}{1+e^{-z_1}} \\ \\ 1-\dfrac{1}{1+e^{-z_1}} \\ \end{bmatrix} = \begin{bmatrix} sigmoid(z_1) \\ 1-sigmoid(z_1) \\ \end{bmatrix} ⎣ ⎡1+e−z111−1+e−z11⎦ ⎤=[sigmoid(z1)1−sigmoid(z1)]
是不是一下就明了了。
深度学习框架
之前我们都是白手起家(from scratch)的,现在为了提高效率,我们要使用框架了。
框架的核心在于使用计算图实现链式法则的自动求导,解放双手,让数据科学家能够专注于fp,而bp这种机械的工作交给机器。
存在即合理,现在大量的框架都在高速发展,所以吴恩达没有强烈推荐(endorse)某一个框架,只是给出了评选标准(criteria):
- 易于编程是首要的。以及便于迭代和部署(deploying)
- 速度,也是硬性要求。
- 真正地开放,即长期保持开源。不仅仅是开源,而且最好管理好,否则可能出现后期公司逐渐私有化的情况。
- 其他的就是语言接口,应用领域。
如果非要提出几个,其实无非就是两个,tensorflow和pytorch,一个工业,一个学术。具体用法也不必举出,涉及的东西比较多,需要独立搜索。