记录网络模型的各种优化
超参数
比如算法中的learning rate $ a $ (学习率)、iterations (梯度下降法循环的数量) 、$ L $ (隐藏层数目)、$ n^{[l]} $ (隐藏层单元数目)、choice of activation function(激活函数的选择)都需要你来设置,这些数字实际上控制了最后的参数$ W $ 和 $ b $ 的值,所以它们被称作超参数。后面还有很多超参数我还有没学到,总的来讲就是能影响参数的更高级参数。
超参数的取值并没有明确的规定,这目前还是一个经验性的过程,新手上路最多的还是要不断的尝试,通过不断地修改超参数对比结果来不断修正最后找到一个相对合适的。
偏差和方差
假设这就是数据集,如果给这个数据集拟合一条直线,可能得到一个逻辑回归拟合,但它并不能很好地拟合该数据,这是高偏差(high bias)的情况,我们称为“欠拟合”(underfitting)。
相反的如果我们拟合一个非常复杂的分类器,比如深度神经网络或含有隐藏单元的神经网络,可能就非常适用于这个数据集,但是这看起来也不是一种很好的拟合方式分类器方差较高(high variance),数据过度拟合(overfitting)。
正则化
深度学习可能存在过拟合问题——高方差,有两个解决方法,一个是正则化,另一个是准备更多的数据,这是非常可靠的方法,但你可能无法时时刻刻准备足够多的训练数据或者获取更多数据的成本很高,但正则化通常有助于避免过拟合或减少你的网络误差。
L2范数
$\frac{\lambda}{2m}$乘以$w$范数的平方,其中$\left| w \right|2^2$是$w$的欧几里德范数的平方,等于$w{j}$($j$ 值从1到$n_{x}$)平方的和,也可表示为$w^{T}w$,也就是向量参数$w$ 的欧几里德范数(2范数)的平方,此方法称为$L2$正则化,因为这里用了欧几里德范数,被称为向量参数$w$的$L2$范数。
因为$w$通常是一个高维参数矢量,已经可以表达高偏差问题,$w$可能包含有很多参数,我们不可能拟合所有参数,而$b$只是单个数字,所以$w$几乎涵盖所有参数,而不是$b$,如果加了参数$b$,其实也没太大影响,因为$b$只是众多参数中的一个,所以通常省略不计。
L1范数
正则化,加的不是$L2$范数,而是正则项$\frac{\lambda}{m}$乘以$\sum_{j= 1}^{n_{x}}{|w|}$,$\sum_{j =1}^{n_{x}}{|w|}$也被称为参数$w$向量的$L1$范数,无论分母是$m$还是$2m$,它都是一个比例常量。
如果用的是$L1$正则化,$w$最终会是稀疏的,也就是说$w$向量中有很多0,有人说这样有利于压缩模型,因为集合中参数均为0,存储模型所占用的内存更少。实际上,虽然$L1$正则化使模型变得稀疏,却没有降低太多存储内存,所以我认为这并不是$L1$正则化的目的,至少不是为了压缩模型,人们在训练网络时,越来越倾向于使用$L2$正则化。
弗罗贝尼乌斯范数(矩阵L2范数)
正则项为$\frac{\lambda }{2m}{\sum\nolimits_{1}^{L}|| W{[l]}}||2$,我们称$||W{\left[l\right]}||2$为范数平方,这个矩阵范数$||W{\left[l\right]}||2$(即平方范数),被定义为矩阵中所有元素的平方求和。该矩阵范数被称作“弗罗贝尼乌斯范数”,用下标$F$标注”,鉴于线性代数中一些神秘晦涩的原因,我们不称之为“矩阵$L2$范数”,而称它为“弗罗贝尼乌斯范数”,矩阵$L2$范数听起来更自然,但鉴于一些大家无须知道的特殊原因,按照惯例,我们称之为“弗罗贝尼乌斯范数”,它表示一个矩阵中所有元素的平方和。
该如何使用该范数实现梯度下降呢?
这就是之前我们额外增加的正则化项,既然已经增加了这个正则项,现在我们要做的就是给$dW$加上这一项$\frac {\lambda}{m}W{[l]}$,然后计算这个更新项,使用新定义的$dW{[l]}$,它的定义含有相关参数代价函数导数和,以及最后添加的额外正则项,这也是$L2$正则化有时被称为“权重衰减”的原因。
我们用$ dW{[l]}$的定义替换此处的$dW{[l]}$,可以看到,$W{[l]}$的定义被更新为$W{[l]}$减去学习率$\alpha$ 乘以backprop 再加上$\frac{\lambda}{m}W^{[l]}$。
该正则项说明,不论$W^{[l]}$是什么,我们都试图让它变得更小,实际上,相当于我们给矩阵W乘以$(1 - \alpha\frac{\lambda}{m})$倍的权重,矩阵$W$减去$\alpha\frac{\lambda}{m}$倍的它,也就是用这个系数$(1-\alpha\frac{\lambda}{m})$乘以矩阵$W$,该系数小于1,因此$L2$范数正则化也被称为“权重衰减”,因为它就像一般的梯度下降,$W$被更新为少了$\alpha$乘以backprop输出的最初梯度值,同时$W$也乘以了这个系数,这个系数小于1,因此$L2$正则化也被称为“权重衰减”。
dropout 正则化(Dropout Regularization)
还有一个非常实用的正则化方法——“Dropout(随机失活)”,我们来看看它的工作原理。
dropout就是为每一层设置一个消除节点的概率,设置完节点概率,我们会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个节点更少,规模更小的网络,然后用backprop方法进行训练。
直观上理解:不愿意把所有赌注都放在一个节点上,不愿意给任何一个输入加上太多权重,因为它可能会被删除,因此该单元将通过这种方式积极地传播开,并为单元的四个输入增加一点权重,通过传播所有权重,dropout将产生收缩权重的平方范数的效果,和之前讲的$L2$正则化类似。
dropout一大缺点就是代价函数$J$不再被明确定义,每次迭代,都会随机移除一些节点,如果再三检查梯度下降的性能,实际上是很难进行复查的。
early stopping
就是让迭代提前停止,找到一个w大小适中的点
为什么正则化能防止过拟合
根据上面的正则化方法的描述我们可以看出正则化主要就是在控制参数W的大小,要让参数W不要太大,太复杂。直观理解就是把多隐藏单元的权重设为0,于是基本上消除了这些隐藏单元的许多影响。如果是这种情况,这个被大大简化了的神经网络会变成一个很小的网络,小到如同一个逻辑回归单元,它会使这个网络从过度拟合的状态更接近高偏差状态。
但是$\lambda$会存在一个中间值,于是会有一个接近“Just Right”的中间状态。
直观理解就是$\lambda$增加到足够大,$W$会接近于0,实际上是不会发生这种情况的,我们尝试消除或至少减少许多隐藏单元的影响,最终这个网络会变得更简单,这个神经网络越来越接近逻辑回归,我们直觉上认为大量隐藏单元被完全消除了,其实不然,实际上是该神经网络的所有隐藏单元依然存在,但是它们的影响变得更小了。神经网络变得更简单了,貌似这样更不容易发生过拟合。
其实这就是一个直觉经验,但是确实可以看到方差减小的结果。
归一化输入(Normalizing inputs)
- 零均值
- 归一化方差
梯度消失/爆炸
深度神经所面临的一个问题就是梯度消失或梯度爆炸,也就是你训练神经网络的时候,导数或坡度有时会变得非常大,或者非常小,甚至于根据深度以指数方式变小,这加大了训练的难度。
解决方法
这并不是完全的解决方法,但是可以减少影响。
$z = w_{1}x_{1} + w_{2}x_{2} + \ldots +w_{n}x_{n}$,$b=0$,暂时忽略$b$,为了预防$z$值过大或过小,你可以看到$n$越大,你希望$w_{i}$越小,因为$z$是$w_{i}x_{i}$的和,如果你把很多此类项相加,希望每项值更小,最合理的方法就是设置$Var(w_{i})=\frac{1}{n}$ 。即$w^{[l]} = np.random.randn( \text{shape})*\text{np.}\text{sqrt}(\frac{1}{n^{[l-1]}})$ , $n^{[l - 1]}$就是我喂给第$l$层神经单元的数量(即第$l-1$层神经元数量)
如果你是用的是Relu激活函数,而不是$\frac{1}{n}$,方差设置为$\frac{2}{n}$,效果会更好。
mini-batch梯度下降
现在是大数据时代,训练集的样本数可能成百万上千万,如果每次正向传播一遍之后再反向进行梯度下降,那么一次传播的处理时间太慢了。
可以把训练集分割为小一点的子集训练,这些子集被取名为mini-batch,假设每一个子集中只有1000个样本,那么把其中的$x{(1)}$到$x{(1000)}$取出来,将其称为第一个子训练集,也叫做mini-batch,然后你再取出接下来的1000个样本,从$x{(1001)}$到$x{(2000)}$,然后再取1000个样本,以此类推。
对$Y$也要进行相同处理,你也要相应地拆分$Y$的训练集,所以这是$Y1$,然后从$y{(1001)}$到$y{(2000)}$,这个叫$Y2$,一直到$Y^5000$。
使用mini-batch梯度下降法,如果你作出成本函数在整个过程中的图,则并不是每次迭代都是下降的,特别是在每次迭代中,你要处理的是 $ X^{大括号t大括号}$ (后五个也有大括号,但是显示不出来)和$Y{t}$,如果要作出成本函数$J{t}$的图,而$J{t}$只和$X{t}$,$Y^{t}$有关,也就是每次迭代下你都在训练不同的样本集或者说训练不同的mini-batch
指数加权平均数(Exponentially weighted averages)
什么是指数加权平均数
在我的理解里面这是一种参考当前时刻之前一部分时间段的内的数据的一中平均算法,这个时间段的长度由 $\beta$ 确定,时间长度大约为$\frac{1}{(1-\beta)}$ 。
计算指数加权平均数的关键方程。
$v_t=\beta v_{t-1}+(1-\beta )\theta_t$
$\beta=0.9$的时候,得到的结果是红线,如果它更接近于1,比如0.98,结果就是绿线,如果$\beta$小一点,如果是0.5,结果就是黄线。
同样的公式,${v}{t}=\beta {v}{t-1}+(1-\beta ){\theta }_{t}$
使$\beta=0.9$,写下相应的几个公式,所以在执行的时候,$t$从0到1到2到3,$t$的值在不断增加,为了更好地分析,我写的时候使得$t$的值不断减小,然后继续往下写。
如果你把这些式子合并,
$v_{100} = 0.1\theta_{100} + 0.1 \times 0.9 \theta_{99} + 0.1 \times {(0.9)}^{2}\theta_{98} + 0.1 \times {(0.9)}^{3}\theta_{97} + 0.1 \times {(0.9)}^{4}\theta_{96} + \ldots$
计算$v_{100}$是通过,把两个函数对应的元素,然后求和,用这个数值100号数据值乘以0.1,99号数据值乘以0.1乘以${(0.9)}^{2}$,这是第二项,以此类推,所以选取的是每日温度,将其与指数衰减函数相乘,然后求和,就得到了$v_{100}$。
指数加权平均数公式的好处之一在于,它占用极少内存,电脑内存中只占用一行数字而已,然后把最新数据代入公式,不断覆盖就可以了,正因为这个原因,其效率,它基本上只占用一行代码,计算指数加权平均数也只占用单行数字的存储和内存,当然它并不是最好的,也不是最精准的计算平均数的方法。如果你要计算移动窗,你直接算出过去10天的总和,过去50天的总和,除以10和50就好,如此往往会得到更好的估测。但缺点是,如果保存所有最近的温度数据,和过去10天的总和,必须占用更多的内存,执行更加复杂,计算成本也更加高昂。
指数加权平均的偏差修正(Bias correction in exponentially weighted averages)
在实际使用中因为我们初始化$v_{0} = 0$,所以在开始的时候可能会出现紫线的情况,与绿的的预估情况出现偏差,在前期不能很好的预测出当日温度。
有个办法可以修改这一估测,让估测变得更好,更准确,特别是在估测初期,也就是不用$v_{t}$,而是用$\frac{v_{t}}{1- \beta^{t}}$,t就是现在的天数。举个具体例子,当$t=2$时,$1 - \beta^{t} = 1 - {0.98}^{2} = 0.0396$,因此对第二天温度的估测变成了$\frac{v_{2}}{0.0396} =\frac{0.0196\theta_{1} + 0.02\theta_{2}}{0.0396}$,也就是$\theta_{1}$和$\theta_{2}$的加权平均数,并去除了偏差。你会发现随着$t$增加,$\beta^{t}$接近于0,所以当$t$很大的时候,偏差修正几乎没有作用,因此当$t$较大的时候,紫线基本和绿线重合了。不过在开始学习阶段,你才开始预测热身练习,偏差修正可以帮助你更好预测温度,偏差修正可以帮助你使结果从紫线变成绿线。
动量梯度下降法(Gradient descent with Momentum)
动量梯度下降法,运行速度几乎总是快于标准的梯度下降算法,简而言之,基本的想法就是计算梯度的指数加权平均数,并利用该梯度更新你的权重
在上图梯度中,你会发现这些纵轴上的摆动平均值接近于零,所以在纵轴方向,你希望放慢一点,平均过程中,正负数相互抵消,所以平均值接近于零。但在横轴方向,所有的微分都指向横轴方向,因此横轴方向的平均值仍然较大,因此用算法几次迭代后,你发现动量梯度下降法,最终纵轴方向的摆动变小了,横轴方向运动更快,因此你的算法走了一条更加直接的路径,在抵达最小值的路上减少了摆动。
RMSprop
你们知道了动量(Momentum)可以加快梯度下降,还有一个叫做RMSprop的算法,全称是root mean square prop算法,它也可以加速梯度下降。
回忆一下我们之前的例子,如果你执行梯度下降,虽然横轴方向正在推进,但纵轴方向会有大幅度摆动,为了分析这个例子,假设纵轴代表参数$b$,横轴代表参数$W$,可能有$W_{1}$,$W_{2}$或者其它重要的参数,为了便于理解,被称为$b$和$W$。
所以,你想减缓$b$方向的学习,即纵轴方向,同时加快,至少不是减缓横轴方向的学习,RMSprop算法可以实现这一点。
记得在横轴方向或者在例子中的$W$方向,我们希望学习速度快,而在垂直方向,也就是例子中的$b$方向,我们希望减缓纵轴上的摆动,所以有了$S_{dW}$和$S_{db}$。你看这些微分,垂直方向的要比水平方向的大得多,所以斜率在$b$方向特别大,所以这些微分中,$db$较大,$dW$较小,因为函数的倾斜程度,在纵轴上,也就是b方向上要大于在横轴上,也就是$W$方向上。$db$的平方较大,所以$S_{db}$也会较大,而相比之下,$dW$会小一些,亦或$dW$平方会小一些,因此$S_{dW}$会小一些,结果就是纵轴上的更新要被一个较大的数相除,就能消除摆动,而水平方向的更新则被较小的数相除。
如果$S_{dW}$的平方根趋近于0怎么办?得到的答案就非常大,为了确保数值稳定,在实际操练的时候,你要在分母上加上一个很小很小的$\varepsilon$,$\varepsilon$是多少没关系,$10^{-8}$是个不错的选择,这只是保证数值能稳定一些。
Adam 优化算法(Adam optimization algorithm)
Adam优化算法基本上就是将Momentum和RMSprop结合在一起
Adam算法结合了Momentum和RMSprop梯度下降法,并且是一种极其常用的学习算法,被证明能有效适用于不同神经网络,适用于广泛的结构。
本算法中有很多超参数,超参数学习率$a$很重要,也经常需要调试,你可以尝试一系列值,然后看哪个有效。$\beta_{1}$常用的缺省值为0.9,这是dW的移动平均数,也就是$dW$的加权平均数,这是Momentum涉及的项。至于超参数$\beta_{2}$,Adam论文作者,也就是Adam算法的发明者,推荐使用0.999,这是在计算${(dW)}{2}$以及${(db)}{2}$的移动加权平均值,关于$\varepsilon$的选择其实没那么重要,Adam论文的作者建议$\varepsilon$为$10^{-8}$,但你并不需要设置它,因为它并不会影响算法表现。但是在使用Adam的时候,人们往往使用缺省值即可,$\beta_{1}$,$\beta_{2}$和$\varepsilon$都是如此。
学习率衰减(Learning rate decay)
慢慢减少$a$的本质在于,在学习初期,你能承受较大的步伐,但当开始收敛的时候,小一些的学习率能让你步伐小一些。
你应该拆分成不同的mini-batch,第一次遍历训练集叫做第一代。第二次就是第二代,依此类推,你可以将$a$学习率设为$a= \frac{1}{1 + decayrate * \text{epoch}\text{-num}}a_{0}$(decay-rate称为衰减率,epoch-num为代数,$\alpha_{0}$为初始学习率),注意这个衰减率是另一个你需要调整的超参数。
除了这个学习率衰减的公式,人们还会用其它的公式。
调试超参数
最为广泛的学习应用是$a$,学习速率是需要调试的最重要的超参数。
除了$a$,还有一些参数需要调试,例如Momentum参数$\beta$,0.9就是个很好的默认值。我还会调试mini-batch的大小,以确保最优算法运行有效。我还会经常调试隐藏单元数目。
当应用Adam算法时,事实上,我从不调试$\beta_{1}$,${\beta}_{2}$和$\varepsilon$,我总是选定其分别为0.9,0.999和$10^{-8}$。
当你给超参数取值时,另一个惯例是采用由粗糙到精细的策略。
比如在二维的那个例子中,你进行了取值,也许你会发现效果最好的某个点,也许这个点周围的其他一些点效果也很好,那在接下来要做的是放大这块小区域(小蓝色方框内),然后在其中更密集得取值或随机取值,聚集更多的资源,在这个蓝色的方格中搜索,如果你怀疑这些超参数在这个区域的最优结果,那在整个的方格中进行粗略搜索后,你会知道接下来应该聚焦到更小的方格中。在更小的方格中,你可以更密集得取点。所以这种从粗到细的搜索也经常使用。
为超参数选择合适的范围(Using an appropriate scale to pick hyperparameters)
在超参数范围中,随机取值可以提升你的搜索效率。但随机取值并不是在有效范围内的随机均匀取值,而是选择合适的标尺,用于探究这些超参数,这很重要。
看看这个例子,假设你在搜索超参数$a$(学习速率),假设你怀疑其值最小是0.0001或最大是1。如果你画一条从0.0001到1的数轴,沿其随机均匀取值,那90%的数值将会落在0.1到1之间,结果就是,在0.1到1之间,应用了90%的资源,而在0.0001到0.1之间,只有10%的搜索资源,这看上去不太对。
反而,用对数标尺搜索超参数的方式会更合理,因此这里不使用线性轴,分别依次取0.0001,0.001,0.01,0.1,1,在对数轴上均匀随机取点,这样,在0.0001到0.001之间,就会有更多的搜索资源可用,还有在0.001到0.01之间等等。
所以在Python中,你可以这样做,使r=-4*np.random.rand()
,然后$a$随机取值,$ a =10^{r}$,所以,第一行可以得出$r \in [ 4,0]$,那么$a \in[10{-4},10{0}]$,所以最左边的数字是$10{-4}$,最右边是$10{0}$。
归一化网络的激活函数(Normalizing activations in a network)
对每一层的Z进行归一化
现在我们已把这些$z$值标准化,化为含平均值0和标准单位方差,所以$z$的每一个分量都含有平均值0和方差1,但我们不想让隐藏单元总是含有平均值0和方差1,也许隐藏单元有了不同的分布会有意义,所以我们所要做的就是计算,我们称之为${\tilde{z}}{(i)}$,${\tilde{z}}{(i)}= \gamma z_{\text{norm}}^{(i)} +\beta$,这里$\gamma$和$\beta$是你模型的学习参数,所以我们使用梯度下降或一些其它类似梯度下降的算法,比如Momentum或者Nesterov,Adam,你会更新$\gamma$和$\beta$,正如更新神经网络的权重一样。
请注意$\gamma$和$\beta$的作用是,你可以随意设置${\tilde{z}}^{(i)}$的平均值,事实上,如果$\gamma= \sqrt{\sigma^{2} +\varepsilon}$,如果$\gamma$等于这个分母项($z_{\text{norm}}^{(i)} = \frac{z^{(i)} -\mu}{\sqrt{\sigma^{2} +\varepsilon}}$中的分母),$\beta$等于$\mu$,这里的这个值是$z_{\text{norm}}^{(i)}= \frac{z^{(i)} - \mu}{\sqrt{\sigma^{2} + \varepsilon}}$中的$\mu$,那么$\gamma z_{\text{norm}}^{(i)} +\beta$的作用在于,它会精确转化这个方程,如果这些成立($\gamma =\sqrt{\sigma^{2} + \varepsilon},\beta =\mu$),那么${\tilde{z}}^{(i)} = z^{(i)}$。
通过对$\gamma$和$\beta$合理设定,规范化过程,即这四个等式,从根本来说,只是计算恒等函数,通过赋予$\gamma$和$\beta$其它值,可以使你构造含其它平均值和方差的隐藏单元值。
Softmax 回归(Softmax regression)
Softmax回归主要用来做多分类任务
让你的网络做到这一点的标准模型要用到Softmax层,以及输出层来生成输出,让我把式子写下来,然后回过头来,就会对Softmax的作用有一点感觉了。
损失函数:
梯度下降: