第三周 超参数调试、Batch正则化和程序框架(Hyperparameter tuning)
1. 超参调试
按重要性来排序,需要调整的超参有:
- 最重要的是学习率
。
- 其次重要的有三个:Momentum参数
,0.9就是个很好的默认值;mini-batch的大小,以确保最优算法运行有效;以及隐藏单元。
- 重要性排第三位的是 层数 和 学习率衰减。
当应用Adam算法时,事实上,
和
几乎从不调试,总是设置为0.9,0.999和
,如果你想的话也可以调试它们。但这不是严格且快速的标准,其它深度学习的研究者可能会很不同意我的观点或有着不同的直觉。
调试超参时如何选择调试值呢?
早期常见的做法是在网格中取样点,当参数的数量相对较少时,这个方法很实用。
在深度学习领域,我们常做的是随机选择点。之所以这么做是因为,对于你要解决的问题而言,你很难提前知道哪个超参数最重要。
取一个极端的例子,假设超参数1是(学习速率),超参数2是Adam算法中的
。在这种情况下,
的取值很重要,而
取值则无关紧要。如果你在网格中取点,接着,你试验了
的5个取值,那你会发现,无论
取何值,结果基本上都是一样的。所以,你知道共有25种模型,但进行试验的
值只有5个。
对比而言,如果你随机取值,你会试验25个独立的,似乎你更有可能发现效果最好的那个。
实践中,你搜索的超参数可能不止两个。假如,你有三个超参数,这时你搜索的不是一个方格,而是一个立方体,超参数3代表第三维,接着,在三维立方体中取值,你会试验大量的更多的值,三个超参数中每个都是。
当你给超参数取值时,另一个惯例是采用由粗糙到精细的策略。
比如在二维的那个例子中,你进行了取值,也许你会发现效果最好的某个点,也许这个点周围的其他一些点效果也很好,那在接下来要做的是放大这块小区域(小蓝色方框内),然后在其中更密集得取值或随机取值,聚集更多的资源。接下来在这个蓝色的方格中搜索,聚焦到更小的方格中。在更小的方格中,你可以更密集得取点。这种从粗到细的搜索也经常使用。
2. 超参的合适范围
在超参数范围中,随机取值可以提升你的搜索效率。但随机取值并不是在有效范围内的随机均匀取值,而是选择合适的标尺,用于探究这些超参数。
- 线性轴上均匀取值
假设你要选取隐藏单元的数量,假设,你选取的取值范围是从50到100中某点,这种情况下,看到这条从50-100的数轴,你可以随机在其取点,这是一个搜索特定超参数的很直观的方式。
或者,如果你要选取神经网络的层数,我们称之为字母,你也许会选择层数为2到4中的某个值,接着顺着2,3,4随机均匀取样才比较合理,你还可以应用网格搜索,这是在几个在你考虑范围内随机均匀取值的例子,这些取值还蛮合理的,但对某些超参数而言不适用。
- 对数轴上均匀取值
看看这个例子,假设你在搜索超参数(学习速率),假设你怀疑其值最小是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 =10^{r}
r \in [ 4,0]
a \in[10{-4},10{0}]$,所以最左边的数字是
,最右边是
。
更常见的情况是,如果你在和
之间取值,在此例中,这是
(0.0001),你可以通过
算出
的值,即-4,在右边的值是
,你可以算出
的值
,即0。你要做的就是在
区间随机均匀地给
取值,这个例子中
,然后你可以设置
的值,基于随机取样的超参数
。
所以总结一下,在对数坐标下取值,取最小值的对数就得到的值,取最大值的对数就得到
值,所以现在你在对数轴上的
到
区间取值,在
,
间随意均匀的选取
值,将超参数设置为
,这就是在对数轴上取值的过程。
- 指数的加权平均值的超参
最后,另一个棘手的例子是给 取值,用于计算指数的加权平均值。假设你认为
是0.9到0.999之间的某个值,也许这就是你想搜索的范围。记住,当计算指数的加权平均值时,取0.9就像在10个值中计算平均值,有点类似于计算10天的温度平均值,而取0.999就是在1000个值中取平均。
和上一条类似,不要随机均匀在0.9到0.999此区间取值,考虑这个问题最好的方法是探究,此值在0.1到0.001区间内,所以我们会给
取值,大概是从0.1到0.001。应用上一条对数标尺的方法,你要做的就是在
里随机均匀的给 r 取值,
,然后这就变成了在特定的选择范围内超参数随机取值。希望用这种方式得到想要的结果,你在0.9到0.99区间探究的资源,和在0.99到0.999区间探究的一样多。
关于为什么用线性轴取值不是个好办法,这是因为当 接近1时,所得结果的灵敏度会变化。
比如从0.999到0.9995,从1000个值的指数加权平均值,变成2000个值(记住公式
)。而
在0.9到0.9005之间取值,始终是10个数的加权平均值,你的结果几乎不会变化。
所以整个取值过程中,你需要在 接近1的区间内更加密集地取值,这样,你就可以更加有效的分布取样点,更有效率地探究可能的结果。
3. 如何搜索超参数
有2种方式,由你拥有的计算资源决定。
- Babysitting one model
在数据量庞大且没有足够的CPU或GPU的情况下,你一次只能负担起试验一个模型或一小批模型。但即使当它在试验时,你也可以逐渐改良。
比如,第0天,你将随机参数初始化,然后开始试验,然后你逐渐观察自己的学习曲线,也许是损失函数J,或者数据设置误差或其它的东西,在第1天内逐渐减少,那这一天末的时候,你可能会说,看,它学习得真不错。我试着增加一点学习速率,看看它会怎样,也许结果证明它做得更好,那是你第二天的表现。两天后,你会说,它依旧做得不错,也许我现在可以填充下Momentum或减少变量。然后进入第三天……每天,你都会观察它,不断调整你的参数。也许有一天,你会发现你的学习率太大了,所以你可能又回归之前的模型,像这样,但你可以说是在每天花时间照看此模型,即使是它在许多天或许多星期的试验过程中。所以这是一个人们照料一个模型的方法,观察它的表现,耐心地调试学习率,但那通常是因为你没有足够的计算能力,不能在同一时间试验大量模型时才采取的办法。
- Training many models in parallel
设置不同的超参数或者不同的模型,同时试验它们。用这种方式你可以试验许多不同的参数设定,然后只是最后快速选择工作效果最好的那个,不对其中任何一个多加照料。在这个例子中,也许这条看起来是最好的(下方绿色曲线)。
4. Batch归一化激活函数
Batch norm
Batch归一化会使你的参数搜索问题变得很容易,使神经网络对超参数的选择更加稳定,超参数的范围会更加庞大,工作效果也很好,也会是你的训练更加容易,甚至是深层网络。
训练模型时,归一化输入特征可以加快学习过程。你计算了平均值,从训练集中减去平均值,计算了方差,接着根据方差归一化你的数据集。
在之前的视频中我们看到,这是如何把学习问题的轮廓,从很长的东西,变成更圆的东西,更易于算法优化。
那么更深的模型呢?你不仅输入了特征值,而且有激活值
,
等等。如果你想训练这些参数,比如
,
,那归一化
的平均值和方差岂不是很好?因为
是下一层的输入值,所以就会影响
,
的训练。严格来说,我们真正归一化的不是
,而是
。
在logistic回归的例子中,我们看到了如何归一化,
,
,会帮助你更有效的训练
和
。(以下我我省略层数
及方括号)
给定一个深度神经网络,对于第 层,你要将
值标准化,使其均值为0且方差为1,会进行如下计算:
但我们不想让隐藏单元总是含有平均值0和方差1,因为也许隐藏单元有不同的分布会有意义,所以我们所要计算的替换为%7D%3D%20%5Cgamma%20z%7B%5Ctext%7Bnorm%7D%7D%5E%7B(i)%7D%20%2B%5Cbeta%0A#card=math&code=%7B%5Ctilde%7Bz%7D%7D%5E%7B%28i%29%7D%3D%20%5Cgamma%20z%7B%5Ctext%7Bnorm%7D%7D%5E%7B%28i%29%7D%20%2B%5Cbeta%0A&id=cgLpI)
这里和
是你模型的学习参数,所以我们使用梯度下降(或Momentum, Nesterov,Adam)更新
和
,正如更新神经网络的权重一样。
请注意和
的作用是使你可以随意设置
%7D#card=math&code=%7B%5Ctilde%7Bz%7D%7D%5E%7B%28i%29%7D&id=YC684)的平均值。特殊的,如果
(
%7D%20%3D%20%5Cfrac%7Bz%5E%7B(i)%7D%20-%5Cmu%7D%7B%5Csqrt%7B%5Csigma%5E%7B2%7D%20%2B%5Cvarepsilon%7D%7D#card=math&code=z%7B%5Ctext%7Bnorm%7D%7D%5E%7B%28i%29%7D%20%3D%20%5Cfrac%7Bz%5E%7B%28i%29%7D%20-%5Cmu%7D%7B%5Csqrt%7B%5Csigma%5E%7B2%7D%20%2B%5Cvarepsilon%7D%7D&id=TnHv9)中的分母),
等于
(%7D%3D%20%5Cfrac%7Bz%5E%7B(i)%7D%20-%20%5Cmu%7D%7B%5Csqrt%7B%5Csigma%5E%7B2%7D%20%2B%20%5Cvarepsilon%7D%7D#card=math&code=z_%7B%5Ctext%7Bnorm%7D%7D%5E%7B%28i%29%7D%3D%20%5Cfrac%7Bz%5E%7B%28i%29%7D%20-%20%5Cmu%7D%7B%5Csqrt%7B%5Csigma%5E%7B2%7D%20%2B%20%5Cvarepsilon%7D%7D&id=LBTIo)中的
),那么
%7D%20%3D%20z%5E%7B(i)%7D#card=math&code=%7B%5Ctilde%7Bz%7D%7D%5E%7B%28i%29%7D%20%3D%20z%5E%7B%28i%29%7D&id=aOx0V)。
通过对和
合理设定,这个规范化过程,即这四个等式,从根本来说,只是计算恒等函数。但是它可以使你构造含其它平均值和方差的隐藏单元值。
Batch归一化的作用是使隐藏层单元值的均值和方差标准化,而同样适用于隐藏层。输入层和这些隐藏单元值的一个区别是,你也许不想隐藏单元值必须是平均值0和方差1,也可以是其它值,它是由和
两参数控制的。
将 BN 拟合进神经网络
我们可以认为每个单元负责计算两件事。第一,它先计算z,然后应用其到激活函数中再计算a,所以我可以认为,每个圆圈代表着两步的计算过程。同样的,对于下一层而言,那就是和
等,这是由
和
两个参数控制的。如果应用了Batch归一化,给你一个新的规范化的
值(
),然后将其输入激活函数中得到
,即
#card=math&code=a%5E%7B%5B1%5D%7D%20%3D%20g%5E%7B%5B1%5D%7D%28%7B%5Ctilde%7Bz%7D%7D%5E%7B%5B%20l%5D%7D%29&id=LLoSh),此过程将由
和
两参数控制。
需要强调的是Batch归一化是发生在计算和
之间的。实践中你不必自己操作所有这些具体的细节,比如说,在TensorFlow框架中,你可以用这个函数(
tf.nn.batch_normalization
)来实现Batch归一化。但知道它是如何作用的,你可以更好地理解代码的作用。
实践中,Batch归一化通常和训练集的mini-batch一起使用。你应用Batch归一化的方式就是,你用第一个mini-batch(),然后应用参数
和
计算
。接着,继续第二个mini-batch(
),Batch归一化会减去均值,除以标准差,由
和
重新缩放,这样就得到了
,再应用激活函数得到
。然后用
和
计算
,等等,所以你做的这一切都是为了在第一个mini-batch(
)上进行一步梯度下降法。类似的工作,你会在第二个mini-batch(
)上计算
,然后用Batch归一化来计算
…
现在,我想澄清此参数的一个细节。先前我说过每层的参数是和
,还有
和
,请注意计算
的方式如下,
。Batch归一化做的是,在每个mini-batch,先将
归一化,结果为均值0和标准方差,再由
和
重缩放。但这意味着,无论
的值是多少,都是要被减去的。因为在Batch归一化的过程中,你要计算
的均值,再减去平均值,增加任何常数都不会改变结果,因为加上的常数将会被均值减去所抵消。
所以,如果你在使用Batch归一化,其实你可以消除这个参数(),或者你也可以,暂时把它设置为0,那么,参数变成
,然后你计算归一化的
,
,你最后会用参数
,以便决定
的取值。
让我们总结一下关于如何用Batch归一化来应用梯度下降法,假设你在使用mini-batch梯度下降法,运行到batch数量的for循环,你会在mini-batch
上应用正向prop,每个隐藏层都应用正向prop,用Batch归一化代替
为
。接下来,它确保在这个mini-batch中,
值有归一化的均值和方差,归一化均值和方差后是
,然后,你用反向prop计算
和
,及所有l层所有的参数,
和
。尽管严格来说,因为你要去掉
,这部分其实已经去掉了。最后,你更新这些参数:
,和以前一样,
,对于
也是如此
。
如果你已将梯度计算如下,你就可以使用梯度下降法了,这就是我写到这里的,但也适用于有Momentum、RMSprop、Adam的梯度下降法。与其使用梯度下降法更新mini-batch,你可以使用这些其它算法来更新,我们在之前几个星期中的视频中讨论过的,也可以应用其它的一些优化算法来更新由Batch归一化添加到算法中的 和
参数。
Why does Batch Norm work?
为什么Batch归一化会起作用呢?
一个原因是,你已经看到如何归一化输入特征值,使其均值为0,方差1,它又是怎样加速学习的,有一些从0到1而不是从1到1000的特征值,通过归一化所有的输入特征值
,以获得类似范围的值,可以加速学习。
Batch归一化有效的第二个原因是,它可以使你的网络中更深层的权重比前面层的权重更能经受得住变化。
举个例子,假设你已经在所有黑猫的图像上训练了数据集,如果现在你要把此网络应用于有色猫,这种情况下,正面的例子不只是左边的黑猫,还有右边其它颜色的猫,那么你的cosfa可能适用的不会很好。所以当你已经学习了到
的映射,而
的分布改变时,那么你可能需要重新训练你的学习算法。这种问题称为“Covariate shift”。
“Covariate shift”的问题怎么应用于神经网络呢?让我们从这层(第三层)来看看学习过程。此网络已经学习了参数和
,从第三隐藏层的角度来看,它从前层中取得一些值,接着它需要做些什么,使希望输出值
接近真实值
。
Batch归一化做的,是它减少了隐藏值分布变化的数量。如果是绘制这些隐藏的单元值的分布,也许这是重整值,这其实是
,
,我要绘制两个值而不是四个值,以便我们设想为2D,Batch归一化讲的是
,
的值可以改变,它们的确会改变,当神经网络在之前层中更新参数,Batch归一化可以确保无论其怎样变化
,
的均值和方差保持不变,所以即使
,
的值改变,至少他们的均值和方差也会是均值0,方差1(是由
和
决定的均值方差)。Batch归一化限制了前层的参数更新影响下一层数值分布的程度。
Batch归一化减少了输入值改变的问题,它的确使这些值变得更稳定,神经网络的之后层就会有更坚实的基础。即使使输入分布改变了一些,它会改变得更少。你可以这样想,它减弱了前层参数的作用与后层参数的作用之间的联系,使得网络每层都可以自己学习,稍稍独立于其它层,这有助于加速整个网络的学习。
Batch归一化还有一个作用,它有轻微的正则化效果。
Batch归一化中非直观的一件事是,因为是在mini-batch上计算的均值和方差,而不是在整个数据集上,所以均值和方差有一些小的噪声。缩放过程从到
,过程也有一些噪音,因为它是用有些噪音的均值和方差计算得出的。
所以和dropout相似,它往每个隐藏层的激活值上增加了噪音,dropout有增加噪音的方式,它使一个隐藏的单元,以一定的概率乘以0,以一定的概率乘以1,所以你的dropout含几重噪音,因为它乘以0或1。
对比而言,Batch归一化含几重噪音,因为标准偏差的缩放和减去均值带来的额外噪音。这里的均值和标准差的估计值也是有噪音的,所以类似于dropout,Batch归一化有轻微的正则化效果,因为给隐藏单元添加了噪音,这迫使后部单元不过分依赖任何一个隐藏单元,因此有轻微的正则化效果。又因为添加的噪音很微小,所以并不是巨大的正则化效果,你可以将Batch归一化和dropout一起使用,如果你想得到dropout更强大的正则化效果。
也许另一个轻微非直观的效果是,如果你应用了较大的mini-batch,对,比如说,你用了512而不是64,通过应用较大的min-batch,你减少了噪音,因此减少了正则化效果,这是dropout的一个奇怪的性质,就是应用较大的mini-batch可以减少正则化效果。
说到这儿,我会把Batch归一化当成一种正则化,这确实不是其目的,但有时它会对你的算法有额外的期望效应或非期望效应。但是不要把Batch归一化当作正则化,把它当作将你归一化隐藏单元激活值并加速学习的方式,我认为正则化几乎是一个意想不到的副作用。
在我们结束Batch归一化的讨论之前,我想确保你还知道一个细节。Batch归一化一次只能处理一个mini-batch数据,它在mini-batch上计算均值和方差。所以测试时,你试图做出预测,试着评估神经网络,你也许没有mini-batch的例子,你也许一次只能进行一个简单的例子,所以测试时,你需要做一些不同的东西以确保你的预测有意义。
Batch Norm at test time
在测试时,你可能需要对每个样本逐一处理,我们来看一下怎样调整你的网络来做到这一点。
回想一下,在训练时,左列式子就是用来执行Batch归一化的等式。一个mini-batch中,你将mini-batch的%7D#card=math&code=z%5E%7B%28i%29%7D&id=opIau)值求和,计算均值,m表示这个mini-batch中的样本数量,而不是整个训练集。然后计算方差,再算
%7D#card=math&code=z%7B%5Ctext%7Bnorm%7D%7D%5E%7B%28i%29%7D&id=fe1kX),即用均值和标准差来调整,加上
是为了数值稳定性。
是用
和
再次调整得到的。
请注意用于调节计算的和
是在整个mini-batch上进行计算,但是在测试时,你可能不能将一个mini-batch中的6428或2056个样本同时处理,因此你需要用其它方式来得到
和
。那么为了将你的神经网络运用于测试,就需要单独估算
和
。
在典型的Batch归一化运用中,你需要用一个指数加权平均来估算,这个平均数涵盖了所有mini-batch,接下来我会具体解释。
我们选择层,假设我们有mini-batch,
,
,
……以及对应的
值等等,那么在为
层训练
时,你就得到了
(为了区分batch,写作
)。当你训练第二个mini-batch,在这一层和这个mini-batch中,你就会得到第二个
(
)值。然后在这一隐藏层的第三个mini-batch,你得到了第三个
(
)值。正如我们之前用的指数加权平均来计算
,
,
的均值,当时是试着计算当前气温的指数加权平均,这里追踪你看到的这个均值向量的最新平均值,于是这个指数加权平均就成了你对这一隐藏层的
均值的估值。同样的,你可以用指数加权平均来追踪你在这一层的第一个mini-batch中所见的
的值,以及第二个mini-batch中所见的
的值等等。因此在用不同的mini-batch训练神经网络的同时,能够得到你所查看的每一层的
和
的平均数的实时数值。
最后在测试时,对应这个等式(%7D%20%3D%20%5Cfrac%7Bz%5E%7B(i)%7D%20-%5Cmu%7D%7B%5Csqrt%7B%5Csigma%5E%7B2%7D%20%2B%5Cvarepsilon%7D%7D#card=math&code=z%7B%5Ctext%7Bnorm%7D%7D%5E%7B%28i%29%7D%20%3D%20%5Cfrac%7Bz%5E%7B%28i%29%7D%20-%5Cmu%7D%7B%5Csqrt%7B%5Csigma%5E%7B2%7D%20%2B%5Cvarepsilon%7D%7D&id=YFbKA)),你只需要用你的
值来计算%7D#card=math&code=z%7B%5Ctext%7Bnorm%7D%7D%5E%7B%28i%29%7D&id=r4vBc),用
和
的指数加权平均,用你手头的最新数值来做调整,然后你可以用左边我们刚算出来的和你在神经网络训练过程中得到的
和
参数来计算你那个测试样本的
值。
总结一下就是,在训练时,和
是在整个mini-batch上计算出来的,但在测试时,你可能需要逐一处理样本,方法是根据你的训练集估算
和
。估算的方式有很多种,在实际操作中,我们通常运用指数加权平均(也叫做流动平均)来追踪在训练过程中你看到的
和
的值,然后在测试中使用
和
的值来进行你所需要的隐藏单元
值的调整。如果你使用的是某种深度学习框架,通常会有默认的估算
和
的方式,应该一样会起到比较好的效果。任何合理的估算你的隐藏单元
值的均值和方差的方式,在测试中应该都会有效。
Batch归一化就讲到这里,使用Batch归一化,你能够训练更深的网络,让你的学习算法运行速度更快。
5. Softmax regression
到目前为止,我们讲到过的分类的例子使用的都是二分类,如果我们有多种可能的类型的话呢?有一种logistic回归的一般形式,叫做Softmax回归,能让你在试图识别某一分类时做出预测,或者说是多种分类中的一个,不只是识别两个分类。
假设你不单需要识别猫,而是想识别猫,狗和小鸡,我把猫加做类1,狗为类2,小鸡是类3,如果不属于以上任何一类,就分到“其它”或者说“以上均不符合”这一类,我把它叫做类0。我用大写的来表示输入会被分入的类别总个数,这里C=4。
我们将建立一个神经网络,其输出层有4个,或者说个输出单元。因此输出层也就是
层的单元数量等于
。我们想要输出层单元的数字告诉我们这4种类型中每个的概率有多大,所以我们希望这里的第一个节点输出样本属于“0”类的概率,第2个节点会输出是猫“1”的概率,第3个节点输出是狗的概率,第4个是小鸡(缩写为bc,baby chick)的概率。因此这里的
将是一个
维向量,因为它必须输出四个数字,给你这四种概率,且加起来应该等于1。
让你的网络做到这一点的标准模型要用到Softmax层,以及输出层来生成输出。
在神经网络的最后一层,你将会像往常一样计算各层的线性部分,这是最后一层的
变量,注意这是大写
层。和往常一样,计算方法是
,算出了
之后,你需要应用Softmax激活函数,这个激活函数对于Softmax层而言有些不同,它的作用是这样的。
首先,我们要计算一个临时变量,我们把它叫做t,它等于,这适用于每个元素,在我们的例子中,
是4×1的,
,所以
也是一个4×1维向量,然后输出的
,基本上就是归一化向量
,使其元素和为1,因此
,以防这里的计算不够清晰易懂,我们举个例子来详细解释。
假设你算出了,
是一个四维向量,假设为
,我们要做的就是用这个元素取幂方法来计算
,所以
,如果你按一下计算器就会得到以下值
,我们从向量
得到向量
就只需要将这些项目归一化,使总和为1。如果你把
的元素都加起来,把这四个数字加起来,得到176.3,最终
。例如这里的第一个节点,它会输出
。对于这张图片,神经网络的输出
,也就是
,算出来的结果是(
),分别对应4个类别的概率。
我们总结一下从到
的计算步骤。整个计算过程,从计算幂到得出临时变量
,再归一化,我们可以将此概括为一个Softmax激活函数。设
#card=math&code=a%5E%7B%5Bl%5D%7D%20%3D%20g%5E%7B%5Bl%5D%7D%28z%5E%7B%5Bl%5D%7D%29&id=yhQ6H),这一激活函数的与众不同之处在于,这个激活函数
输入一个4×1维向量,输出也是一个4×1维向量。之前,我们的激活函数都是接受单行数值输入,例如Sigmoid和ReLu激活函数,输入一个实数,输出一个实数。
那么Softmax分类器还可以代表其它的什么东西么?我来举几个例子,你有两个输入,
,它们直接输入到Softmax层,它有三四个或者更多的输出节点,且没有隐藏层的。它所做的就是计算
,而输出的出
,或者说
,
#card=math&code=a%5E%7B%5Bl%5D%7D%20%3D%20y%20%3D%20g%28z%5E%7B%5B1%5D%7D%29&id=QGG26),
#card=math&code=g%28%29&id=EjtOu)就是
的Softmax激活函数,这个没有隐藏层的神经网络应该能让你对Softmax函数能够代表的东西有所了解。下面是它的分类举例。
上图中的6个例子都是原始输入只有和
,而有
个输出分类。Softmax层能够代表这种类型的决策边界(请注意这是几条线性决策边界),使得它能够将数据分到
个类别中。图中的颜色显示了Softmax分类器的输出的阈值,我们可以看到这是logistic回归的一般形式,有类似线性的决策边界,但有超过两个分类,分类不只有0和1,而是可以是0,1,2……
这显示了Softmax分类器在没有隐藏层的情况下能够做到的事情,当然更深的神经网络会有,然后是一些隐藏单元,以及更多隐藏单元等等,你就可以学习更复杂的非线性决策边界,来区分多种不同分类。
训练一个 Softmax 分类器
Softmax这个名称的来源是与所谓hardmax对比,对于向量,hardmax会把向量
变成这个向量
,也就是最大的元素的输出为1,其它的输出都为0。与之相反,Softmax所做的从
到这些概率的映射更为温和,用临时变量
将它归一化,使总和为1,最后得到
。
在Softmax分类中,我们一般用到的损失函数是%20%3D%20-%20%5Csum%7Bj%20%3D%201%7D%5E%7BC%7D%7By%7Bj%7Dlog%5Chat%20y%7Bj%7D%7D#card=math&code=L%28%5Chat%20y%2Cy%20%29%20%3D%20-%20%5Csum%7Bj%20%3D%201%7D%5E%7BC%7D%7By%7Bj%7Dlog%5Chat%20y%7Bj%7D%7D&id=CcrCr),假设某单个样本属于类别2-猫,那么
,只有
,因此这个求和只剩下
,
%20%3D%20-%20%5Csum%7Bj%20%3D%201%7D%5E%7B4%7D%7By%7Bj%7D%5Clog%20%5Chat%20y%7Bj%7D%7D%20%3D%20-%20y%7B2%7D%7B%5C%20log%7D%20%5Chat%20y%7B2%7D%20%3D%20-%20%7B%5C%20log%7D%20%5Chat%20y%7B2%7D#card=math&code=L%5Cleft%28%20%5Chat%20y%2Cy%20%5Cright%29%20%3D%20-%20%5Csum%7Bj%20%3D%201%7D%5E%7B4%7D%7By%7Bj%7D%5Clog%20%5Chat%20y%7Bj%7D%7D%20%3D%20-%20y%7B2%7D%7B%5C%20log%7D%20%5Chat%20y%7B2%7D%20%3D%20-%20%7B%5C%20log%7D%20%5Chat%20y%7B2%7D&id=MVX7m).
概括来讲,损失函数所做的就是它找到你的训练集中的真实类别,然后试图使该类别相应的概率尽可能地高。整个训练集损失的总和,是把你的训练算法对所有训练样本的预测都加起来,
%20%3D%20%5Cfrac%7B1%7D%7Bm%7D%5Csum%7Bi%20%3D%201%7D%5E%7Bm%7D%7BL(%20%5Chat%20y%5E%7B(i)%7D%2Cy%5E%7B(i)%7D)%7D#card=math&code=J%28%20w%5E%7B%5B1%5D%7D%2Cb%5E%7B%5B1%5D%7D%2C%5Cldots%5Cldots%29%20%3D%20%5Cfrac%7B1%7D%7Bm%7D%5Csum%7Bi%20%3D%201%7D%5E%7Bm%7D%7BL%28%20%5Chat%20y%5E%7B%28i%29%7D%2Cy%5E%7B%28i%29%7D%29%7D&id=oYXJt)
因此你要做的就是用梯度下降法,使这里的损失最小化。
在这周的初级练习中,我们将开始使用一种深度学习编程框架,对于这些编程框架,通常你只需要专注于把前向传播做对,只要你将它指明为编程框架,前向传播,它自己会弄明白怎样反向传播,会帮你实现反向传播。