Hyperparameter tuning, Regularization and Optimization
改善深层神经网络:超参数调试、正则化以及优化
深度学习的实践层面(Practical aspects of Deep Learning)
训练、验证、测试集
在机器学习中,我们通常将样本分成训练集,验证集和测试集三部分,数据集规模相对较小,适用传统的划分比例,数据集规模较大的,验证集和测试集要小于数据总量的20%或10%。
训练集(train set):用训练集对算法或模型进行训练过程。
验证集(development set):利用验证集进行交叉验证,也叫简单交叉验证集,目的是选择出最好的模型。
测试集(test set):最后利用测试集对模型进行测试,获取模型运行的无偏估计。
类比举例:形象上来说训练集就像是学生的课本,学生 根据课本里的内容来掌握知识,验证集就像是作业,通过作业可以知道 不同学生学习情况、进步的速度快慢,而最终的测试集就像是考试,考的题是平常都没有见过,考察学生举一反三的能力。
小数据时代
三七分即70%训练集,30%测试集;若设置了验证集,60%训练集,20%验证集和20%测试集。
大数据时代
数据量可能是百万级别,验证集和测试集占数据总量的比例会趋向于变得更小。验证集的目的就是验证不同的算法,检验哪种算法更有效。
例:100万条数据,取1万条数据进行评估,找出其中表现最好的1-2种算法;1000条数据,评估单个分类器,并且准确评估该分类器的性能。100万条数据,其中1万条作为验证集,1万条作为测试集,100万里取1万比例是1%即:训练集占98%,验证集和测试集各占1%。
训练神经网络时到决策因素
- 神经网络分为多少层
- 每层含有多少个隐藏单元
- 学习率是多少
- 各层采用哪些激活函数
应用型机器学习是一个高度迭代的过程,在项目启动时,先有一个初步想法,例如:构建一个含有特定层数,隐藏单元数量或数据集个数的神经网络,再编码,并尝试运行这些代码,通过运行和测试得到该神经网络或这些配置信息的运行结果,根据输出结果重新完善想法,改变策略,或者为了找到更好的神经网络不断迭代更新的方案。
应用深度学习是一个典型的迭代过程,需要多次循环往复,才能为应用程序找到一个合适的神经网络,因此循环该过程的效率是决定项目进展速度的一个关键因素,而创建高质量的训练数据集,验证集和测试集也有助于提高循环效率。
偏差方差(Bias /Variance)
训练集进行模型训练通常会存在两种问题,“过拟合(overfitting)”和“欠拟合(underfitting)”,分别对应高方差(high variance)和高偏差(high bias)。
高方差(high variance):拟合程度过好,以至于过拟合,无法泛化新的样本数据。
高偏差(high bias):拟合程度太差,以至于欠拟合,存在很大的误差。
理解偏差和方差的两个关键数据是训练集误差(Train set error)和验证集误差(Dev set error)。
- 假定训练集误差是1%,验证集误差是11%,可以看出训练集设置得非常好,而验证集设置相对较差,所以可能过度拟合了训练集,验证集并没有充分利用交叉验证集的作用,像这种情况,我们称之为“高方差”。
- 假设训练集误差是15%,验证集误差是16%,算法并没有在训练集中得到很好训练,如果训练数据的拟合度不高就是数据欠拟合,就可以说这种算法偏差比较高。相反,它对于验证集产生的结果却是合理的,验证集中的错误率只比训练集的多了1%,所以这种算法偏差高。
- 假设训练集误差是15%,偏差相当高,但是,验证集的评估结果更糟糕,错误率达到30%,在这种情况下,我会认为这种算法偏差高,因为它在训练集上结果不理想,而且方差也很高,这是方差偏差都很糟糕的情况。
- 假设训练集误差是0.5%,验证集误差是1%,看到这样的结果会很开心,只有1%的错误率,偏差和方差都很低。
机器学习基础
训练神经网络时用到地基本方法,初始模型训练完成后,首先要知道算法的偏差高不高,如果偏差较高,试着评估训练集或训练数据的性能。如果偏差很高,甚至无法拟合训练集,那么要做的就是选择一个新的网络,比如含有更多隐藏层或者隐藏单元的网络,或者花费更多时间来训练网络,或者尝试更先进的优化算法。一旦偏差降低到可以接受的数值,检查一下方差有没有问题,为了评估方差,要查看验证集性能,我们能从一个性能理想的训练集推断出验证集的性能是否也理想,如果方差高,最好的解决办法就是采用更多数据,但有时候,无法获得更多数据,也可以尝试通过正则化来减少过拟合,有时候不得不反复尝试,但是,如果能找到更合适的神经网络框架,有时它可能会一箭双雕,同时减少方差和偏差。不断重复尝试,直到找到一个低偏差,低方差的框架。
注意
第一点,高偏差和高方差是两种不同的情况,要尝试的方法也可能完全不同,通常会用训练验证集来诊断算法是否存在偏差或方差问题,然后根据结果选择尝试部分方法。举个例子,如果算法存在高偏差问题,准备更多训练数据其实也没什么用处,这不是更有效的方法,所以要清楚存在的问题是偏差还是方差,还是两者都有问题,明确这一点有助于我们选择出最有效的方法。
第二点,在机器学习的初期阶段,关于所谓的偏差方差权衡的讨论屡见不鲜,原因是我们能尝试的方法有很多。可以增加偏差,减少方差,也可以减少偏差,增加方差,但是在深度学习的早期阶段,没有太多工具可以做到只减少偏差或方差却不影响到另一方。但在当前的深度学习和大数据时代,只要持续训练一个更大的网络,只要准备了更多数据,那么也并非只有这两种情况,我们假定是这样,那么,只要正则适度,通常构建一个更大的网络便可以,在不影响方差的同时减少偏差,而采用更多数据通常可以在不过多影响偏差的同时减少方差。这两步实际要做的工作是:训练网络,选择网络或者准备更多数据,现在我们有工具可以做到在减少偏差或方差的同时,不对另一方产生过多不良影响。
正则化(Regularization)
深度学习可能存在过拟合问题——高方差,有两个解决方法,一个是正则化,另一个是准备更多的数据。正则化通常有助于避免过拟合或减少误差。
如何更好的拟合数据
- 去收集更多的数据
- 尝试更少的特征值
- 尝试更多的特征值
- 增加多项式
- 增大\减小正则化参数
代价函数
例:$h_{\theta}(x)=\theta_{0}+\theta_{1} x_{1}+\theta_{2} x_{2}^{2}+\theta_{3} x_{3}^{3}+\theta_{4} x_{4}^{4}$
正是由于高次项导致的过拟合的发生,如果能够让那些高次项的系数接近于0的话,就能够很好的拟合数据集。所以我们要做的就是在一定程度上减小这些参数的值,这就是正则化的基本方法。
我们要减少$\theta_{3}$和$\theta_{4}$的大小,要做的便是修改代价函数,在其中$\theta_{3}$和$\theta_{4}$设置一点惩罚。这样做的话,我们在尝试最小化代价时也需要将这个惩罚纳入考虑中,并最终导致选择较小一些的$\theta_{3}$和$\theta_{4}$。
修改后的代价函数:
$\min {\theta}\frac{1}{2 m}\left[\sum{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}+1000 \theta_{3}^{2}+10000 \theta_{4}^{2}\right]$
通过这样的代价函数选择出的$\theta_{3}$和$\theta_{4}$对预测结果的影响就比之前要小许多。
假如我们有非常多的特征,我们并不知道其中哪些特征我们要惩罚,我们将对所有的特征进行惩罚,并且让代价函数最优化的软件来选择这些惩罚的程度。这样的结果是得到了一个较为简单的能防止过拟合问题的假设:
$J(\theta)=\frac{1}{2 m}\left[\sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}+\lambda \sum_{j=1}^{n} \theta_{j}^{2}\right]$
其中$\lambda$ 又被称为正则化参数(Regularization Parameter)。注:按照惯例我们对$\theta_{0}$不进行惩罚。
正则化为何利于预防过拟合
$\lambda$: 可以控制两个不同目标之间的取舍。
$J(\theta)=\frac{1}{2 m}\sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}+\frac{\lambda}{2m}\sum_{j=1}^{n} \theta_{j}^{2}$
- 前一项$\frac{1}{2 m}\sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}$可以去更好的拟合数据集(训练集)
- 后一项$\frac{\lambda}{2m}\sum_{j=1}^{n} \theta_{j}^{2}$使参数大小变小,从而使得假设函数变得“简单”。
两者相互平衡,从而达到一种相互制约的关系,最终找到一个平衡点,从而更好地拟合训练集并且具有良好的泛化能力。
如果令$\lambda$ 的值很大的话,为了使Cost Function 尽可能的小,所有的 的值(不包括$\theta_{0}$ )都会在一定程度上减小。如果$\lambda$ 取值非常大,那么除了$\theta_{0}$ 之外的所有参数都趋近于0,模型成为一条直线。
正则化线性回归
正则化线性回归的代价函数为:$J(\theta)=\frac{1}{2 m} \sum_{i=1}^{m}\left[\left(\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}+\lambda \sum_{j=1}^{n} \theta_{j}^{2}\right)\right]$
Repeat until convergence {
$\begin{array}{c}{\theta_{0} :=\theta_{0}-a \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{0}^{(i)}} \ {\theta_{j} :=\theta_{j}-a\left[\frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)}+\frac{\lambda}{m} \theta_{j}\right]}\end{array}$
}
对上面的算法中 = 1,2,…, 时的更新式子进行调整可得:
$\theta_{j} :=\theta_{j}\left(1-a \frac{\lambda}{m}\right)-a \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)}$
正则化线性回归的梯度下降算法的变化在于,每次都在原有算法更新规则的基础上令值减少了一个额外的值。
正则化逻辑回归
给代价函数增加一个正则化的表达式得到代价函数
$J(\theta)=\frac{1}{m} \sum_{i=1}^{m}\left[-y^{(i)} \log \left(h_{\theta}\left(x^{(i)}\right)\right)-\left(1-y^{(i)}\right) \log \left(1-h_{\theta}\left(x^{(i)}\right)\right)\right]+\frac{\lambda}{2 m} \sum_{j=1}^{n} \theta_{j}^{2}$
dropout正则化(Dropout Regularization)
除了L2正则化,还有一个很实用的正则化方法——“Dropout(随机失活)”
在训练上图这样的神经网络,它过拟合,复制这个神经网络,dropout会遍历网络的每一层,并设置消除神经网络中节点的概率。假设网络中的每一层,每个节点都以抛硬币的方式设置概率,每个节点得以保留和消除的概率都是0.5,设置完节点概率,我们会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个节点更少,规模更小的网络,
对于每个训练样本,都将采用一个精简后神经网络来训练它,这种方法似乎有点怪,单纯遍历节点,编码也是随机的,针对每个训练样本训练规模小得多的网络。
理解dropout
Dropout可以随机删除网络中的神经单元
直观理解:不依赖于任何一个特征,该单元的输入可能随时被清除,因此该单元通过这种方式传播下去,并为单元的四个输入增加一点权重,通过传播所有权重,dropout将产生收缩权重的平方范数的效果,和之前讲的L2正则化类似,实施dropout的结果实它会压缩权重,并完成一些预防过拟合的外层正则化,L2对不同权重的衰减是不同的,它取决于激活函数倍增的大小。
dropout的功能类似于L2正则化,与L2正则化不同的是应用方式不同会带来一点点小变化,甚至更适用于不同的输入范围。
第二个直观认识是,从单个神经元入手,如图,这个单元的工作就是输入并生成一些输出。通过dropout,该单元的输入几乎被消除,有时这两个单元会被删除,有时会删除其它单元,这个紫色单元它不能依靠任何特征,因为特征都有可能被随机清除,或者说该单元的输入也都可能被随机清除。不把所有赌注都放在一个节点上,不给任何一个输入加上太多权重,因为它可能会被删除,因此该单元将通过这种方式积极地传播开,并为单元的四个输入增加一点权重,通过传播所有权重,dropout将产生收缩权重的平方范数的效果,和我们之前的L2正则化类似,实施dropout的结果是它会压缩权重,并完成一些预防过拟合的外层正则化。
事实证明,dropout被正式地作为一种正则化的替代形式,L2对不同权重的衰减是不同的,它取决于倍增的激活函数的大小。dropout的功能类似于L2正则化,与L2正则化不同的是,被应用的方式不同,dropout也会有所不同,甚至更适用于不同的输入范围。
缺点
dropout一大缺点就是代价函数J不再被明确定义,每次迭代,都会随机移除一些节点,如果再三检查梯度下降的性能,实际上是很难进行复查的。定义明确的代价函数J每次迭代后都会下降,因为我们所优化的代价函数J实际上并没有明确定义,或者说在某种程度上很难计算,所以我们失去了调试工具来绘制这样的图片。
其他正则化方法
数据扩增(Data augmentation)
)例:猫咪图片,水平翻转图片、裁剪图片,并把它添加到训练集。增大数据集,额外生成假训练数据。和全新的,独立的猫咪图片数据相比,这些额外的假的数据无法包含像全新数据那么多的信息,但这么做基本没有花费,代价几乎为零,除了一些对抗性代价。以这种方式扩增算法数据,进而正则化数据集,减少过拟合比较廉价。
early stopping
还有另外一种常用的方法叫作early stopping,运行梯度下降时,我们可以绘制训练误差,或只绘制代价函数J的优化过程,在训练集上用0-1记录分类误差次数。呈单调下降趋势,如图。
在训练过程中,我们希望训练误差、代价函数$J$ 都在下降。通过early stopping,不单可以绘制上面这些内容,还可以绘制dev set error(验证集误差)。
它可以是验证集上的分类误差,或验证集上的代价函数(cost function)、逻辑损失(logistic loss)、对数损失(log loss)等。
缺点
early stopping的主要缺点就是不能独立地处理两个问题,因为提早停止梯度下降,也就是停止了优化代价函数$J$,因为现在你不再尝试降低代价函数$J$,所以代价函数$J$的值可能不够小,同时你又希望不出现过拟合,你没有采取不同的方式来解决这两个问题,而是用一种方法同时解决两个问题,这样做的结果是我要考虑的东西变得更复杂。
如果不用early stopping,另一种方法就是L2正则化,训练神经网络的时间就可能很长。我发现,这导致超级参数搜索空间更容易分解,也更容易搜索,但是缺点在于,你必须尝试很多正则化参数$\lambda$的值,这也导致搜索大量$\lambda$值的计算代价太高。
优点
Early stopping的优点是,只运行一次梯度下降,你可以找出$w$的较小值,中间值和较大值,而无需尝试$L2$正则化超级参数$\lambda$的很多值。
机器学习过程包括几个步骤,其中一步是选择一个算法来优化代价函数J,有很多种工具来解决这个问题,如梯度下降,后面我会介绍其它算法,例如Momentum,RMSprop和Adam等等,但是优化代价函数J之后,我也不想发生过拟合,也有一些工具可以解决该问题,比如正则化,扩增数据等等。
在机器学习中,超级参数激增,选出可行的算法也变得越来越复杂。如果用一组工具优化代价函数$J$,机器学习就会变得更简单,在重点优化代价函数$J$时,只需要留意$w$和$b$,$J(w,b)$的值越小越好,你只需要想办法减小这个值。
归一化输入(normalizing inputs)
如果不归一化特征,代价函数有可能会像下面的左图,像一个狭长的碗,因为输入特征的不同维度可能取值范围相差很大,所以对应参数的取值范围或比率就会非常不同。在这个代价函数上运行梯度下降,学习率的取值将和参数的初始位置有关。但如果函数是一个更圆的球形轮廓,那么无论从哪个位置开始,梯度下降法都能够较容易找到最小值。如果特征值处于相似范围内,那么归一化就不是很重要了。但执行这类归一化并不会产生什么危害,所以一般都可以加上这个步骤。
梯度消失/爆炸(Vanishing / Exploding gradients)
训练神经网络,尤其是深度神经所面临的一个问题就是梯度消失或梯度爆炸,也就是训练神经网络的时候,导数或坡度有时会变得非常大,或者非常小,甚至于以指数方式变小,这加大了训练的难度。
如图是一个四层的全连接网络,假设每一层网络激活后的输出为 $\ f_i(x)$, 其中$i$为第 $i$ 层, $x$代表第 $i$ 层的输入,也就是第 $i-1$层的输出,$f$是激活函数,那么就有 $\ f_{i+1} = f( f_iw_{i+1} + b_{i+1} )$,为了简便设 $b_{i+1}$为 0 , 那么记为 : $f_{i+1}=f(f_iw_{i+1})$ . BackPropagation 算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,参数的更新为 $w \leftarrow w+ \Delta w$ , 给定学习率 , 则 $\Delta w = - \alpha \frac{\partial Loss}{\partial w}$ , 如果要更新第二隐藏层的权值信息,根据链式求导法则,更新梯度信息:
$链式求导 : \Delta w_1 = \frac{\partial Loss}{\partial w_2} = \frac{\partial Loss}{\partial f_4} \cdot \frac{\partial f_4}{\partial f_3} \cdot \frac{\partial f_3}{\partial f_2} \cdot \frac{\partial f_2}{\partial w_2}$ 很容易看出来 $\frac{ \partial f_2}{\partial w_2} =f_1$ , $f_1$ 就是第二隐藏层的输入 , 所以说$\frac{\partial f_4}{\partial f_3} \cdot \frac{\partial f_3}{\partial f_2}$ 就是对激活函数进行求导, 如果此部分大于1 ,那么越深的网络 , 层数越多, 最终求出的梯度就会以指数形式增长 , 即发生梯度爆炸 , 那么如果求导部分小于 1 , 那么随着层数越多, 求出的梯度信息就会以指数形式递减 , 即发生梯度消失 ,
关于梯度下降方式的训练速度 : 从深层网络角度来讲,不同的层学习的速度差异很大,表现为网络中靠近输出的层学习的情况很好,靠近输入的层学习的很慢,有时甚至训练了很久,前几层的权值和刚开始随机初始化的值差不多。因此,梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足计算权值更新信息的时候需要计算前层偏导信息,因此如果激活函数选择不合适,比如使用sigmoid,梯度消失就会很明显,如果使用 sigmoid 作为损失函数,其梯度是不可能超过 0.25 的,这样经过链式求导之后,很容易发生梯度消失。
梯度爆炸/梯度消失解决方案
慎地选择随机初始化参数,为权重矩阵初始化合理的值,使他既不会增长过快,也不会太快下降到 0,从而得到权重或梯度不会增长或消失过快的深度网络。
先看只有一个神经元的情况,然后才是深度网络。
单个神经元可能有4个输入特征,从$x_{1}$到$x_{4}$,经过$a=g(z)$处理,最终得到$\hat{y}$,深度网络中,这些输入表示为$a^{[l]}$,这里暂时用$x$表示。
$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}$的和,如果把很多此类项相加,希望每项值更小,最合理的方法就是设置$w_{i}=\frac{1}{n}$,$n$表示神经元的输入特征数量,你要做的就是设置某层权重矩阵$w^{[l]} = np.random.randn( \text{shape})*\text{np.}\text{sqrt}(\frac{1}{n^{[l-1]}})$,$n^{[l - 1]}$就是我喂给第$l$层神经单元的数量(即第$l-1$l-1层神经元数量)。
如果激活函数的输入特征被零均值化, 标准方差是1 , $z$ 也会调整到相似的范围 , 如果激活函数是$tanh$,一般选择这样的初始化方法。被称为 Xavier 初始化 .如果激活函数是 ReLU ,权重$w$的初始化一般令其方差为 $\frac{2}{n}$, $w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(\frac{2}{n[l-1]} )$ ,
除此之外,Yoshua Bengio 提出了另外一种初始化$w$的方法,令其方差为 $\frac{2}{n^{[l-1]}n^{[l]}}$,至于选择哪种初始化方法因人而异,可以根据不同的激活函数选择不同方法。另外,我们可以对这些初始化方法中设置某些参数,作为超参数,通过验证集进行验证,得到最优参数,来优化神经网络。
梯度的数值逼近(Numerical approximation of gradients)
反向传播(Back Propagation,backprop)神经网络有一项重要的测试是梯度检验(gradient checking)。目的是检查反向传播过程中梯度下降算法是否正确。
$f(x)$在点$\theta$处的梯度可以表示成:$g(\theta)=\frac{f(\theta+\varepsilon)-f(\theta-\varepsilon)}{2\varepsilon}$ 这个叫做双边误差 . 双边误差对于一个非零的 $\epsilon$,他的逼近误差可以写成$O(\epsilon^2)$, 但是如果是单边误差的话, 逼近误差就只有$O(\epsilon)$.
梯度检验(Gradient checking)
将 $W^{[1]} , b^{[1]} , W^{[2]} , b^{[2]} , … , W^{[L]} , b^{[L]}$ 组合成一个向量 ( Take $ W^{[1]} , b^{[1]} , W^{[2]} , b^{[2]} , … , W^{[L]} , b^{[L]} $ and reshape into a big vector )这样 Cost function就可以由 $J( W^{[1]} , b^{[1]} , … , W^{[L]} , b^{[L]} )$ 表示成 , 然后将反向传播过程通过梯度下降算法得到的 $dW^{[1]} , db^{[1]} , … dW^{[L]} , db^{[L]}$ 按照一样的方式组合成一个一维向量 $d\theta$ . $d\theta$ 的维度和 $\theta$ 一样 .
之后我们的 $J(\theta)$ 要对每一个 $\theta_{i}$ 计算偏导数 , 对于这第 $i$ 个值 :
$d\theta_{approx}[i]=\frac{J(\theta_1,\theta_2,\cdots,\theta_i+\varepsilon,\cdots)-J(\theta_1,\theta_2,\cdots,\theta_i-\varepsilon,\cdots)}{2\varepsilon}$ 双边误差算出 $J(\theta)$ 对 $\theta$ 的导数
把这个值和 BackPropagation 得到的值作比较 , 看他们之间是否足够接近 。
应用注意事项
在进行梯度检查的过程中有几点需要注意的地方:
- 不要在整个训练过程中都进行梯度检查,仅仅作为debug使用。
- 如果梯度检查出现错误,找到对应出错的梯度,检查其推导是否出现错误。
- 注意不要忽略正则化项,计算近似梯度的时候要包括进去。
- 梯度检查时关闭dropout,检查完毕后再打开dropout。
- 随机初始化时运行梯度检查,经过一些训练后再进行梯度检查(不常用)。
优化算法 (Optimization algorithms)
Mini-batch gradient descent
学习优化算法能让神经网络运行得更快。机器学习的应用是一个高度依赖经验的过程,伴随着大量迭代的过程,需要训练诸多模型,才能找到合适的那一个,优化算法能够帮助你快速训练模型。
其中一个难点在于,深度学习没有在大数据领域发挥最大的效果,我们可以利用一个巨大的数据集来训练神经网络,而在巨大的数据集基础上进行训练速度很慢。因此使用快速的优化算法,使用好用的优化算法能够大大提高效率,那么,首先来看看mini-batch梯度下降法。
例如,如果$m$是500万或5000万或者更大的一个数,在对整个训练集执行梯度下降法时,必须处理整个训练集,然后才能进行一步梯度下降法,然后需要再重新处理500万个训练样本,才能进行下一步梯度下降法。如果你在处理完整个500万个样本的训练集之前,先让梯度下降法处理一部分,算法速度会更快。
可以把训练集分割为小一点的子集训练,这些子集被取名为mini-batch,假设每一个子集中只有1000个样本,那么把其中的$x^{(1)}$到$x^{(1000)}$取出来,将其称为第一个子训练集,然后再取出接下来的1000个样本,从$x^{(1001)}$到$x^{(2000)}$,然后再取1000个样本,以此类推。
符号
把$x^{(1)}$到$x^{(1000)}$称为$X^1$,$x^{(1001)}$到$x^{(2000)}$称为$X^2$,例如你的训练样本一共有500万个,每个mini-batch都有1000个样本,那么你就有5000个mini-batch,最后得到是 $X^{ {5000 } }$。
对$Y$也要进行相同处理,相应地拆分$Y$的训练集,$Y^1$、$Y^2$、$y^{(1001)}$到$y^{(2000)}$一直到$Y^5000$。mini-batch的数量$t$组成了$X^$和$Y^$,这就是1000个训练样本,包含相应的输入输出对。
理解 Mini-batch
对于普通的梯度下降法,一个epoch(一代,一代这个词意味着只是一次遍历了训练集。)只能进行一次梯度下降;而对于Mini-batch梯度下降法,一个epoch可以进行Mini-batch的个数次梯度下降。
batch梯度下降
- 对所有m个训练样本执行一次梯度下降,每一次迭代时间较长,每次迭代都需要历遍整个训练集;
- Cost function 总是向减小的方向下降。
随机梯度下降
假设mini-batch大小为1,就有了新的算法,叫做随机梯度下降法,每个样本都是独立的mini-batch。
- 对每一个训练样本执行一次梯度下降,但是丢失了向量化带来的计算加速;
- Cost function总体的趋势向最小值的方向下降,但是无法到达全局最小值点,呈现波动的形式。
Mini-batch梯度下降
- 选择一个 $1<size<m$ 的合适的size进行Mini-batch梯度下降,可以实现快速学习,也应用了向量化带来的好处;
- Cost function的下降处于前两者之间。
Mini-batch 大小的选择
- 如果训练样本的大小比较小时,如\gs 时 —— 选择batch梯度下降法;
- 如果训练样本的大小比较大时,典型的大小为(2的n次方)例: $2^6$,$2^9$,;
- Mini-batch的大小要符合CPU/GPU内存。
指数加权平均数(Exponentially weighted averages)
指数加权平均,在统计中也叫做指数加权移动平均,
例子:伦敦温度
图片里的公式,$v_{t} = 0.9v_{t - 1} +0.1\theta_{t}$,把0.9这个常数变成$\beta$,将之前的0.1变成$(1 - \beta)$,即
$v_{t}=\beta v_{t-1}+(1-\beta)\theta_{t}$
- 当 $\beta=0.9$ 时,在计算时可视$v_{t}$大概是$\frac{1}{(1 -\beta)}$的每日温度,如果$\beta$是0.9,这是十天的平均值,也就是红线部分指数加权平均最后的结果如图中红色线所示;
- 当 $\beta=0.98$ 时,将$\beta$设置为接近1的一个值,比如0.98,计算$\frac{1}{(1 - 0.98)} =50$,这就是粗略平均了一下,过去50天的温度,指数加权平均最后的结果如图中绿色线所示;
- 当 $\beta=0.5$ 时,$\beta$是另一个极端值,比如说0.5,根据右边的公式$(\frac{1}{(1-\beta)})$,这是平均了两天的温度。指数加权平均最后的结果如图中黄色线所示;
理解指数加权平均数
同样的公式,$v_{t}=\beta v_{t-1}+(1-\beta)\theta_{t}$使$\beta=0.9$,写下相应的几个公式,所以在执行的时候,$t$从0到1到2到3,$t$的值在不断增加,为了更好地分析,这里写的时候使得t的值不断减小,然后继续往下写,
$v_{100}=0.9v_{99}+0.1\theta{100}$,$v_{99}=0.9v_{98}+0.1\theta{99}$,$v_{98}=0.9v_{97}+0.1\theta{98}$………
展开式子有:$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$
上式中所有 $\theta$ 前面的系数相加起来为1或者接近于1,称之为偏差修正。
总体来说存在, $(1-\varepsilon)^{1/\varepsilon}=\dfrac{1}{e}$ ,在我们的例子中, $(1-\varepsilon)^{1/\varepsilon}=\dfrac{1}{e}$ ,即 $0.9^{10}\approx 0.35\approx\dfrac{1}{e}$ 。相当于大约10天后,系数的峰值(这里是0.1)下降到原来的 $\dfrac{1}{e}$,只关注了过去10天的天气。
指数加权平均实现
现在解释一下算法,可以将$v_{0},v_{1},v_{2}$等等写成明确的变量,在实际中执行的要做的是,一开始将$v_{0}$初始化为0,然后在第一天使$v:= \beta v + (1 - \beta)\theta_{1}$,然后第二天,更新v值,$v: = \beta v + (1 -\beta)\theta_{2}$,以此类推,有些人会把v加下标,来表示v是用来计算数据的指数加权平均数。
换个说法就是,$v_{\theta} =0$,然后每一天,拿到第t天的数据,把v更新为$v: = \beta v_{\theta} + (1 -\beta)\theta_{t}$。
$v_{0} =0\ v_{1}= \beta v_{0}+(1-\beta)\theta_{1}\ v_{2}= \beta v_{1}+(1-\beta)\theta_{2}\ v_{3}= \beta v_{2}+(1-\beta)\theta_{3}\ \ldots$
在计算当前时刻的平均值,只需要前一天的平均值和当前时刻的值,所以在数据量非常大的情况下,指数加权平均在节约计算成本的方面是一种非常有效的方式,可以很大程度上减少计算机资源存储和内存的占用。
优点
指数加权平均数公式的好处之一在于,它占用极少内存,电脑内存中只占用一行数字而已,然后把最新数据代入公式,不断覆盖就可以了,正因为这个原因,其效率基本上只占用一行代码,计算指数加权平均数也只占用单行数字的存储和内存。
当然它并不是最好的,也不是最精准的计算平均数的方法。如果你要计算移动窗,你直接算出过去10天的总和,过去50天的总和,除以10和50就好,如此往往会得到更好的估测。但缺点是,如果保存所有最近的温度数据,和过去10天的总和,必须占用更多的内存,执行更加复杂,计算成本也更加高昂。
指数加权平均的偏差修正(Bias correction in exponentially weighted averages)
在我们执行指数加权平均的公式时,当 $\beta=0.98$ 时,我们得到的并不是图中的绿色曲线,而是下图中的紫色曲线,其起点比较低。
原因
初始化$v_{0} = 0$,$v_{1} = 0.98v_{0} +0.02\theta_{1}$,但是$v_{0} =0$,所以这部分没有了第一项$(0.98v_{0}$),所以就变成了$v_{1} =0.02\theta_{1}$,所以如果一天温度是40华氏度,那么$v_{1} = 0.02\theta_{1} =0.02 \times 40 = 8$,因此得到的值会小很多,所以第一天温度的估测不准。
$v_{2} = 0.98v_{1} + 0.02\theta_{2}$,如果代入$v_{1}$,然后相乘,所以$v_{2}= 0.98 \times 0.02\theta_{1} + 0.02\theta_{2} = 0.0196\theta_{1} +0.02\theta_{2}$,假设$\theta_{1}$和$\theta_{2}$都是正数,计算后$v_{2}$要远小于$\theta_{1}$和$\theta_{2}$,所以$v_{2}$不能很好估测出这一年前两天的温度。
偏差修正
有个办法可以修改这一估测,让估测变得更好,更准确,特别是在估测初期,就是不用$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)
动量梯度下降的基本思想就是计算梯度的指数加权平均数,并利用该梯度来更新权重。在我们优化 Cost function 的时候,以下图所示的函数图为例:
在利用梯度下降法来最小化该函数的时候,每一次迭代所更新的代价函数值如图中蓝色线所示在上下波动,而这种幅度比较大波动,减缓了梯度下降的速度,而且我们只能使用一个较小的学习率来进行迭代。
如果用较大的学习率,结果可能会如紫色线一样偏离函数的范围,所以为了避免这种情况,只能用较小的学习率。
但是我们又希望在如图的纵轴方向梯度下降的缓慢一些,不要有如此大的上下波动,在横轴方向梯度下降的快速一些,使得能够更快的到达最小值点,而这里用动量梯度下降法既可以实现,如红色线所示。
算法实现
两个超参数,学习率$a$以及参数$\beta$,$\beta$控制着指数加权平均数,$\beta$常用的值是0.9。
在我们进行动量梯度下降算法的时候,由于使用了指数加权平均的方法。原来在纵轴方向上的上下波动,经过平均以后,接近于0,纵轴上的波动变得非常的小;但在横轴方向上,所有的微分都指向横轴方向,因此其平均值仍然很大。最终实现红色线所示的梯度下降曲线。
算法本质解释
在对应上面的计算公式中,将Cost function想象为一个碗状,想象从顶部往下滚球,其中:
- 微分项 $dw,db$ 想象为球提供的加速度;
- 动量项 $v_{dw},v_{db}$ 相当于速度;
小球在向下滚动的过程中,因为加速度的存在使得速度会变快,但是由于 $\beta$ 的存在,其值小于1,可以认为是摩擦力,所以球不会无限加速下去。
RMSprop
动量(Momentum)可以加快梯度下降,还有一个叫做RMSprop的算法,全称是root mean square prop算法,它也可以加速梯度下降,
这里假设参数b的梯度处于纵轴方向,参数w的梯度处于横轴方向(当然实际中是处于高维度的情况),利用RMSprop算法,可以减小某些维度梯度更新波动较大的情况,如图中蓝色线所示,使其梯度下降的速度变得更快,如图绿色线所示。
在如图所示的实现中,RMSprop将微分项进行平方,然后使用平方根进行梯度更新,同时为了确保算法不会除以0,平方根分母中在实际使用会加入一个很小的值如 $\varepsilon=10^{-8}$ 。
Adam 优化算法(Adam optimization algorithm)
Adam (Adaptive Moment Estimation)优化算法的基本思想就是将 Momentum 和 RMSprop 结合起来形成的一种适用于不同深度学习结构的优化算法。
算法实现
- 初始化: $V_{dw} = 0,S_{dw}=0,V_{db}=0,S_{db} = 0$
- 第 $t$ 次迭代:
- Compute $dw,db$ on the current mini-batch
- $V_{dw}=\beta_{1}V_{dw}+(1-\beta_{1})dw,V_{db}=\beta_{1}V_{db}+(1-\beta_{1})db$ —– “Momentum”
- $S_{dw}=\beta_{2}S_{dw}+(1-\beta_{2})(dw)^{2},S_{db}=\beta_{2}S_{db}+(1-\beta_{2})(db)^{2}$ —– “RMSprop”
- $V_{dw}^{corrected} = V_{dw}/(1-\beta_{1}^{t}),V_{db}^{corrected} = V_{db}/(1-\beta_{1}^{t})$ —– 偏差修正
- $S_{dw}^{corrected} = S_{dw}/(1-\beta_{2}^{t}),S_{db}^{corrected} = S_{db}/(1-\beta_{2}^{t})$ —– 偏差修正
- $w:=w-\alpha\dfrac{V_{dw}^{corrected}}{\sqrt{S_{dw}^{corrected}}+\varepsilon},b:=b-\alpha\dfrac{V_{db}^{corrected}}{\sqrt{S_{db}^{corrected}}+\varepsilon}$
超参数的选择
- $a$ :需要进行调试;
- $\beta$ :常用缺省值为0.9, $dw$ 的加权平均;
- $\beta_{2}$ :推荐使用0.999, $dw^2$ 的加权平均值;
- $\varepsilon$ :推荐使用 $10^{-8}$。
学习率衰减(Learning rate decay)
在我们利用 mini-batch 梯度下降法来寻找Cost function的最小值的时候,如果我们设置一个固定的学习速率 $\alpha$,则算法在到达最小值点附近后,由于不同batch中存在一定的噪声,使得不会精确收敛,而一直会在一个最小值点较大的范围内波动,如下图中蓝色线所示。
但是如果我们使用学习率衰减,逐渐减小学习速率 $\alpha$ ,在算法开始的时候,学习速率还是相对较快,能够相对快速的向最小值点的方向下降。但随着 $\alpha$ 的减小,下降的步伐也会逐渐变小,最终会在最小值附近的一块更小的区域里波动,如图中绿色线所示。
学习率衰减的实现
- 常用: $\alpha = \dfrac{1}{1+decay_rate*epoch_num}\alpha_{0}$
- 指数衰减: $\alpha = 0.95^{epoch_num}\alpha_{0}$
- 其他: $\alpha = \dfrac{k}{epoch_num}\cdot\alpha_{0}$
- 离散下降(不同阶段使用不同的学习速率)
局部最优的问题(The problem of local optima)
在低维度的情形下,我们可能会想象到一个Cost function 如左图所示,存在一些局部最小值点,在初始化参数的时候,如果初始值选取的不得当,会存在陷入局部最优点的可能性。
但是,如果我们建立一个高维度的神经网络。通常梯度为零的点,并不是如左图中的局部最优点,而是右图中的鞍点(叫鞍点是因为其形状像马鞍的形状)。
在一个具有高维度空间的函数中,如果梯度为0,那么在每个方向,Cost function可能是凸函数,也有可能是凹函数。但如果参数维度为2万维,想要得到局部最优解,那么所有维度均需要是凹函数,其概率为 $2^{-20000}$ ,可能性非常的小。也就是说,在低维度中的局部最优点的情况,并不适用于高维度,在梯度为0的点更有可能是鞍点,而不是局部最小值点。
在高纬度的情况下:
- 几乎不可能陷入局部最小值点;
- 处于鞍点的停滞区会减缓学习过程,利用如Adam等算法进行改善。
超参数调试、Batch正则化和程序框架(Hyperparameter tuning)
调试处理(Tuning process)
训练深度最难的事情之一是处理的参数的数量,从学习速率a到Momentum(动量梯度下降法)的参数$\beta$。如果使用Momentum或Adam优化算法的参数,$\beta_{1}$,${\beta}_{2}$和$\varepsilon$,也许还需要选择层数,也许你还需要选择不同层中隐藏单元的数量,也许你还想使用学习率衰减。所以,使用的不是单一的学习率,可能还需要选择mini-batch的大小。结果证实一些超参数比其它的更为重要,最为广泛的学习应用是a,学习速率是需要调试的最重要的超参数。
- 在机器学习领域,超参数比较少的情况下,我们之前利用设置网格点的方式来调试超参数;
- 但在深度学习领域,超参数较多的情况下,不是设置规则的网格点,而是随机选择点进行调试。这样做是因为在我们处理问题的时候,是无法知道哪个超参数是更重要的,所以随机的方式去测试超参数点的性能,更为合理,这样可以探究更超参数的潜在价值。
选择合适的范围
随机取值可以提升搜索效率,但随机取值并不是在有效范围内的随机均匀取值,而是选择合适的标尺,用于探究这些超参数。
在超参数选择的时候,一些超参数是在一个范围内进行均匀随机取值,如隐藏层神经元结点的个数、隐藏层的层数等。但是有一些超参数的选择做均匀随机取值是不合适的,这里需要按照一定的比例在不同的小范围内进行均匀随机取值,以学习率 $\alpha$ 的选择为例,在 $0.001,\ldots,1$ 范围内进行选择:
如上图所示,如果在$0.001,\ldots,1$的范围内进行进行均匀随机取值,则有90%的概率 选择范围在$0.1\sim1$之间,而只有10%的概率才能选择到$0.001\sim0.1$之间,显然是不合理的。
所以在选择的时候,在不同比例范围内进行均匀随机取值,如 $0.001\sim0.01$ 、 $0.01\sim0.1$ 、 $0.1\sim1$ 范围内选择。
一般地,如果在 $10^a\sim10^b$ 之间的范围内进行按比例的选择,则 $r \in [a, b]$, $\alpha=10^r$ 。
同样,在使用指数加权平均的时候,超参数 $\beta$ 也需要用上面这种方向进行选择。
超参数调试的实践
如今的深度学习已经应用到许多不同的领域,某个应用领域的超参数设定,有可能通用于另一领域,不同的应用领域出现相互交融。深度学习领域中,不同应用领域的人们会阅读越来越多其它研究领域的文章,跨领域去寻找灵感。
如何搜索超参数
- 熊猫方式,在计算资源有限的情况下(通常是有庞大的数据组,但没有许多计算资源或足够的CPU和GPU的前提下),仅调试一个模型,每天不断优化。
- 鱼子酱方式,在计算资源充足的情况下,同时并行调试多个模型,选取其中最好的模型。
归一化网络的激活函数(Normalizing activations in a network)
在深度学习兴起后,最重要的一个思想是它的一种算法,叫做Batch归一化,由Sergey loffe和Christian Szegedy两位研究者创造。Batch归一化会使你的参数搜索问题变得很容易,使神经网络对超参数的选择更加稳定,超参数的范围会更加庞大,工作效果也很好,也会是你的训练更加容易,甚至是深层网络。
logistic回归时,归一化输入特征可以加快学习过程。计算了平均值,从训练集中减去平均值,计算了方差,接着根据方差归一化数据集,把学习问题的轮廓,从很长的东西,变成更圆的东西,更易于算法优化,对logistic回归和神经网络的归一化输入特征值而言这是有效的。
实践中,经常做的是归一化将隐藏层的经过激活函数前的$z^{[l]}$,Batch归一化。
Batch Norm 的实现
以神经网络中某一隐藏层的中间值为例: $z^{(1)},z^{(2)},\ldots,z^{(m)}$
$\mu = \dfrac{1}{m}\sum\limits_{i}z^{(i)}$
$\sigma^{2}=\dfrac{1}{m}\sum\limits_{i}(z^{(i)}-\mu)^{2}$
$z^{(i)}{\rm norm} = \dfrac{z^{(i)}-\mu}{\sqrt{\sigma^{2}+\varepsilon}}$
这里加上 $\varepsilon$ 是为了保证数值的稳定。到这里所有 $z$ 的分量都是平均值为0和方差为1的分布,但是我们不希望隐藏层的单元总是如此,也许不同的分布会更有意义,所以我们再进行计算:
$\widetilde z^{(i)} = \gamma z^{(i)}{\rm norm}+\beta$
这里 $\gamma$ 和 $\beta$ 是可以更新学习的参数,如神经网络的权重 $w$ 一样,两个参数的值来确定 $\widetilde z^{(i)}$ 所属的分布。
Batch归一化的作用是它适用的归一化过程,不只是输入层,甚至同样适用于神经网络中的深度隐藏层。应用Batch归一化了一些隐藏单元值中的平均值和方差,训练输入和这些隐藏单元值的一个区别是,你也许不想隐藏单元值必须是平均值0和方差1。比如,如果你有sigmoid激活函数,你不想让你的值总是全部集中在这里,你想使它们有更大的方差,或不是0的平均值,以便更好的利用非线性的sigmoid函数,而不是使所有的值都集中于这个线性版本中,这就是为什么有了$\gamma$和$\beta$两个参数后,你可以确保所有的$z^{(i)}$值可以是你想赋予的任意值,或者它的作用是保证隐藏的单元已使均值和方差标准化。那均值和方差由两参数控制,即$\gamma$和$\beta$,学习算法可以设置为任何值,所以它真正的作用是,使隐藏单元值的均值和方差标准化,即$z^{(i)}$有固定的均值和方差,均值和方差可以是0和1,也可以是其它值,它是由$\gamma$和$\beta$两参数控制的。
将 Batch Norm 拟合进神经网络(Fitting Batch Norm into a neural network)
在深度神经网络中应用Batch Norm,这里以一个简单的神经网络为例,前向传播的计算流程如下图所示:
实现梯度下降
- for t = 1 … num (这里num 为Mini Batch 的数量):
- 在每一个$X^{t}$上进行前向传播(forward prop)的计算:
- 在每个隐藏层都用 Batch Norm 将 $z^{[l]}$ 替换为 $\widetilde z^{[l]}$
- 使用反向传播(Back prop)计算各个参数的梯度: $dw^{[l]}$、$d\gamma^{[l]}$、$d\beta^{[l]}$
- 更新参数:
- $w^{[l]}:=w^{[l]}-\alpha dw^{[l]}$
- $\gamma^{[l]}:=\gamma^{[l]}-\alpha d\gamma^{[l]}$
- $\beta^{[l]}:=\beta^{[l]}-\alpha d\beta^{[l]}$
- 在每一个$X^{t}$上进行前向传播(forward prop)的计算:
- 同样与Mini-batch 梯度下降法相同,Batch Norm同样适用于momentum、RMSprop、Adam的梯度下降法来进行参数更新。
Batch Norm 起作用的原因
首先Batch Norm 可以加速神经网络训练的原因和输入层的输入特征进行归一化,从而改变Cost function的形状,使得每一次梯度下降都可以更快的接近函数的最小值点,从而加速模型训练过程的原理是有相同的道理。只是Batch Norm 不是单纯的将输入的特征进行归一化,而是将各个隐藏层的激活函数的激活值进行的归一化,并调整到另外的分布。
你已经看到如何归一化输入特征值x,使其均值为0,方差1,它又是怎样加速学习的,有一些从0到1而不是从1到1000的特征值,通过归一化所有的输入特征值x,以获得类似范围的值,可以加速学习。所以Batch归一化起的作用的原因,直观的一点就是,它在做类似的工作,但不仅仅对于这里的输入值,还有隐藏单元的值,这只是Batch归一化作用的冰山一角,还有些深层的原理,它会有助于你对Batch归一化的作用有更深的理解。
Batch归一化有效的第二个原因是,它可以使权重比网络更滞后或更深层,比如,第10层的权重更能经受得住变化,相比于神经网络中前层(例如第1层)的权重。
举例猫分类
下面是一个判别是否是猫的分类问题,假设第一训练样本的集合中的猫均是黑猫,而第二个训练样本集合中的猫是各种颜色的猫。如果我们将第二个训练样本直接输入到用第一个训练样本集合训练出的模型进行分类判别,那么我们在很大程度上是无法保证能够得到很好的判别结果。
这是因为第一个训练集合中均是黑猫,而第二个训练集合中各色猫均有,虽然都是猫,但是很大程度上样本的分布情况是不同的,所以我们无法保证模型可以仅仅通过黑色猫的样本就可以完美的找到完整的决策边界。第二个样本集合相当于第一个样本的分布的改变。称为:Covariate shift。
“Covariate shift”的问题怎么应用于神经网络呢?就是利用Batch Norm来实现。如下面的网络结构,网络的目的是通过不断的训练,最后输出一个更加接近于真实值的 $\hat y$。现在以第2个隐藏层为输入来看:
对于后面的神经网络,是以第二层隐层的输出值 $a^{[2]}$ 作为输入特征的,通过前向传播得到最终的 $\hat y$ ,但是因为我们的网络还有前面两层,由于训练过程,参数 $w^{[1]},w^{[2]}$ 是不断变化的,那么也就是说对于后面的网络, $a^{[2]}$ 的值也是处于不断变化之中,所以就有了Covariate shift的问题。
那么如果对 $z^{[2]}$ 使用了Batch Norm,那么即使其值不断的变化,但是其均值和方差却会保持。那么Batch Norm的作用便是其限制了前层的参数更新导致对后面网络数值分布程度的影响,使得输入后层的数值变得更加稳定。另一个角度就是可以看作,Batch Norm 削弱了前层参数与后层参数之间的联系,使得网络的每层都可以自己进行学习,相对其他层有一定的独立性,这会有助于加速整个网络的学习。
Batch Norm 正则化效果
Batch Norm还有轻微的正则化效果。
这是因为在使用Mini-batch梯度下降的时候,每次计算均值和偏差都是在一个Mini-batch上进行计算,而不是在整个数据样集上。这样就在均值和偏差上带来一些比较小的噪声。那么用均值和偏差计算得到的 $\widetilde z^{[l]}$ 也将会加入一定的噪声。
所以和Dropout相似,其在每个隐藏层的激活值上加入了一些噪声,(这里因为Dropout以一定的概率给神经元乘上0或者1)。所以和Dropout相似,Batch Norm 也有轻微的正则化效果。
这里引入一个小的细节就是,如果使用Batch Norm ,那么使用大的Mini-batch如256,相比使用小的Mini-batch如64,会引入跟少的噪声,那么就会减少正则化的效果。
测试时的 Batch Norm(Batch Norm at test time)
Batch归一化将你的数据以mini-batch的形式逐一处理,但在测试时,你可能需要对每个样本逐一处理。
训练过程中,我们是在每个Mini-batch使用Batch Norm,来计算所需要的均值 $\mu$ 和方差 $\sigma^{2}$ 。但是在测试的时候,我们需要对每一个测试样本进行预测,无法计算均值和方差。
此时,我们需要单独进行估算均值 $\mu$ 和方差 $\sigma^{2}$ 。通常的方法就是在我们训练的过程中,对于训练集的Mini-batch,使用指数加权平均,当训练结束的时候,得到指数加权平均后的均值 $\mu$ 和方差 $\sigma^{2}$ ,而这些值直接用于Batch Norm公式的计算,用以对测试样本进行预测。
Softmax 回归(Softmax regression)
在多分类问题中,有一种 logistic regression的一般形式,叫做Softmax regression。Softmax回归可以将多分类任务的输出转换为各个类别可能的概率,从而将最大的概率值所对应的类别作为输入样本的输出类别。
在这个例子中,我们将建立一个神经网络,其输出层有4个,或者说$C$个输出单元,因此$n$,即输出层也就是$L$层的单元数量,等于4,或者一般而言等于$C$。我们想要输出层单元的数字告诉我们这4种类型中每个的概率有多大,所以这里的第一个节点(最后输出的第1个方格+圆圈)输出的应该是或者说我们希望它输出“其它”类的概率。在输入$X$的情况下,这个(最后输出的第2个方格+圆圈)会输出猫的概率。在输入$X$的情况下,这个会输出狗的概率(最后输出的第3个方格+圆圈)。在输入$X$的情况下,输出小鸡的概率(最后输出的第4个方格+圆圈),我把小鸡缩写为bc(baby chick)。因此这里的$\hat y$将是一个4×1维向量,因为它必须输出四个数字,给你这四种概率,因为它们加起来应该等于1,输出中的四个数字加起来应该等于1。可以看出Softmax通过向量 $z{[l]}$ 计算出总和为1的四个概率。
在没有隐藏隐藏层的时候,直接对Softmax层输入样本的特点,则在不同数量的类别下,Sotfmax层的作用:
$C$为3,4,5,6。
训练一个 Softmax 分类器(Training a Softmax classifier)
通常我们判定模型的输出类别,是将输出的最大值对应的类别判定为该模型的类别,也就是说最大值为的位置1,其余位置为0,这也就是所谓的“hardmax”。而Sotfmax将模型判定的类别由原来的最大数字5,变为了一个最大的概率0.842,这相对于“hardmax”而言,输出更加“soft”而没有那么“hard”。
Sotfmax回归 将 logistic回归 从二分类问题推广到了多分类问题上。
Softmax 的 Loss function
在使用Sotfmax层时,对应的目标值 以及训练结束前某次的输出的概率值 分别为:
$y=\left[ \begin{array}{l} 0\1\0\0 \end{array} \right] , \ \hat y=\left[ \begin{array}{l} 0.3\0.2\0.1\0.4 \end{array} \right]$
Sotfmax使用的 Loss function 为:
$L(\hat y,y)=-\sum\limits_{j=1}^{4}y_{j}\log \hat y_{j}$
在训练过程中,我们的目标是最小化Loss function,由目标值我们可以知道, $y_{1}=y_{3}=y_{4}=0,y_{2}=1$ ,所以代入 $L(\hat y,y)$ 中,有:
$L(\hat y,y)=-\sum\limits_{j=1}^{4}y_{j}\log \hat y_{j}=-y_{2}\log \hat y_{2}=-\log \hat y_{2}$
所以为了最小化Loss function,我们的目标就变成了使得 $\hat y_2$ 的概率尽可能的大。
也就是说,这里的损失函数的作用就是找到你训练集中的真实的类别,然后使得该类别相应的概率尽可能地高,这其实是最大似然估计的一种形式。
对应的Cost function如下:
$J(w^{[1]},b^{[1]},\ldots)=\dfrac{1}{m}\sum\limits_{i=1}^{m}L(\hat y^{(i)},y^{(i)})$**
Softmax 的梯度下降**
在Softmax层的梯度计算公式为:
$\dfrac{\partial J}{\partial z^{[L]}}=dz^{[L]} = \hat y -y$
Softmax分类可以运用学习算法将输入分成不止两类,而是$C$个不同类别。
深度学习框架(Deep Learning frameworks)
如何选择
- 便于编程,既包括神经网络的开发和迭代,还包括为产品进行配置,为了成千上百万,甚至上亿用户的实际使用,取决于你想要做什么。
- 运行速度,特别是训练大数据集时,一些框架能让你更高效地运行和训练神经网络。
- 框架是否真的开放,要是一个框架真的开放,它不仅需要开源,而且需要良好的管理。