20170307#cs231n#7.Neural Networks Part 3: Learning and Evaluation

来源:互联网 发布:空间域名 编辑:程序博客网 时间:2024/05/22 14:54

Gradient Checks 梯度检查

即比较数值梯度和解析梯度

使用中心差分公式计算数值梯度

对于数值梯度

df(x)dx=f(x+h)f(x)h(bad, do not use)

不要用上面那个用下面的中心差分公式,h的值一般为1e-5
df(x)dx=f(x+h)f(xh)2h(use instead)

第二条公式虽然要计算两次Loss Function,不过梯度的近似值会更准确。对f(x+h)f(xh)进行Taylor展开可以得到第一个公式为O(h)第二个公式为O(h2),所以第二条更准确

使用relative error相对误差比较

numerical gradient数值梯度fn analytic gradient解析梯度fa
relative error:

fafnmax(fa,fn)

用max函数而不是直接选用其中之一是为了防止数值梯度或者解析梯度其中之一为0(在ReLU中很常见)导致式子无意义。
当然也得保证fnfa都为0的时候就要通过GradientCheck…

  • relative error > 1e-2:通常就意味着梯度错了
  • 1e-2 > relative error > 1e-4:这个结果也不大好
  • 1e-4 > relative error: 对于一些目标函数有弯折(其实就是不可导)的,那么这种情况是可以接受的。但如果没有弯折(例如tanh和softmax等非线性函数),1e-4还是太高
  • 1e-7或者更少:这个结果就不错

网络越深,相对误差越大。
对于一个10-layer的网络有1e-2的误差值可能也可以,毕竟误差会一直累积。当然如果对于一个可微函数1e-2表明梯度计算式错了

Use double precision 使用双精度

用双精度浮点型相对误差可能会降低。。。

Stick around active range of floating point 保持在浮点数的有效范围内

数太小可能会有一些数值问题,所以可以把原始的数值/解析梯度print出来,用来检查数字是不是太太太小了(绝对值大概为1e-10或更小就不大好很可能出错了)。如果真的太太太小了,可以用一个constant常数把loss function的值暂时扩展到一个更好的范围。 例如提高到1.0附近啊之类。

Kinks in the objective 目标函数的不可导点

在梯度检查中导致不正确的一个原因是不可导点(kinks)。
举个例子,ReLU中x=1e6这里的解析梯度为0,但是如果f(x+h)中如果h>1e6那么会导致最后的数值梯度 > 0 所以就出现了错误。
当然这种问题是可以被检测出来的…

Use only few datapoints 使用少的数据点

解决上面不可导点的问题的一个办法就是使用更少的数据点。数据点越少,在计算有限差值近似的时候越过不可导点的概率越小。
如果梯度检查对于2-3个数据点都有效,那么基本上对整个batch进行梯度检查也是没问题的。
所以用少量的数据点可以让梯度检查更快更有效

Be careful with the step size h 小心设置步长h

h并不是越小越好,h太小可能会有数值精度问题。有的时候梯度不能check,改一下h为1e-4或1e-6可能忽然就可以了。

梯度检查运用的时机

由于梯度检查的对象是一个点,即使这个点正确了也不代表全局都是正确的。而且随机初始化可能会出现一种特殊值,让梯度检查后的结果看起来是正确的,实际上没有。
所以一般做法是让网络运行一段时间,等到损失函数开始下降之后再进行梯度检查,第一次迭代就进行检查危险在于随机初始化可能出现特殊值,掩盖了梯度没有正确实现的事实。

不要令regularization吞没数据

正则化吞没数据意思就是,gradient主要来源于regularization项。
因此一般先关掉regularization,然后单独检查data loss。然后再对regularization做单独检查。

对regularization单独检查有两种方式:

  • 一种是修改代码,移除data loss 部分
  • 另一种是提高regularization strength,确保regularization的影响在gradient check中不可忽略,这样就可以观察到不正确的实现了

关闭dropout随机失活和augmentation数据扩张

在使用gradient check的时候一定要把网络中任何有不确定效果的操作关掉(例如dropout和随机数据扩张等)
因为他们会在计算numerical gradient的时候产生大误差。但关掉就无法在梯度检查中检查dropout等操作(例如dropout在反向传播实现过程中可能有错误)
所以更好的方法是在计算f(x+h)f(xh)之前先强制添加一个特别的random seed,在计算解析梯度之前也同样这样做

只检查少量维度

由于实际中梯度有很多很多参数,所以只能检查一些维度,
但要确保在所有不同参数中都抽取一部分来gradient check,可以看下面的例子

In some applications, people combine the parameters into a single large parameter vector for convenience. In these cases, for example, the biases could only take up a tiny number of parameters from the whole vector, so it is important to not sample at random but to take this into account and check that all parameters receive the correct gradients.

在学习之前的合理性检查


  1. 检查损失值
    随机初始化,不训练直接predict,loss在无reg项的时候有一个相对固定的值(对于softmax,10个class就是-log1/10也就是2.302(详见assignment))
    如果loss值和所希望的值不一致,说明初始化有问题
  2. 把regularization打开,loss值会增加,说明正常
  3. 对小数据子集实现overfit
    在对full dataset训练之前先用小数据(例如20个样本)进行训练,然后确保我们训练最后能达到0的loss值(要先把正则化项关了)
    0的loss值说明overfit了,也就是说明神经网络是完整的,这时候才可以把扩展到整个训练集full dataset。

=-=当然,结果能对小数据集过拟合不代表就一定是正确实现了。有可能是由于某些bug导致数据点特征是随机的

检查学习过程

在很多图中x轴通常都是epoch周期(一个epoch代表着每个样本数据都已经被观察过一次)。相较于iterations迭代次数,还是用epoch比较多。毕竟iteration与数据的batch size有关(batch size是可以任意设置)。

下面讲几个值得画图像跟踪的量

Loss Function

左图:低的lr会导致图像近似线性。太高的lr一开始会下降的很快,但会停留在不好的值上(绿线)。这是因为在最优化过程中”能量”太大,参数处于一种振荡状态,不能最优化到一个比较好的点上
右图:可能是lr太小了导致下降的很慢(但也不一定),然后因为噪声很大所以说明batch size可能太小了

loss的振荡程度和batch size有关。batch size为1时振荡很大,batch size为整个训练集时,loss function图像是单调的(除非lr设置得太太太高了)

有些人会用log函数画图像。把多个cross-validated图像画在一个loss图里面,差异会变得更明显


上图说明的是初始值选的不好使得一开始的loss的梯度接近0导致上图。

Train/Val accuracy 训练集/验证集正确率


gap代表着overfit的程度

上图中蓝线就是严重过拟合了,而且图像可能会在某一点之后下降,解决方法有增加regularization (更强的L2正则化惩罚, more dropout, etc.) or 收集更多数据。
另一种情况(绿线),一直跟随着训练集的正确率走,这说明模型容量还不够大,要通过增加参数的量提高模型的大小

Ratio of weights:updates weights的更新比例

这个比例其实就是权值增量除以权值。
一般来说每次更新,这个比例在1e-3左右会比较好。
如果更低,说明学习率可能太小,如果更高,说明学习率可能太高。

# assume parameter vector W and its gradient vector dWparam_scale = np.linalg.norm(W.ravel())update = -learning_rate*dW # simple SGD updateupdate_scale = np.linalg.norm(update.ravel())W += update # the actual updateprint update_scale / param_scale # want ~1e-3

当然有些人会去计算和跟踪梯度范式及其更新,得到结果也是差不多的

Activation / Gradient distributions per layer每层的激活数据分布和梯度分布

错误的初始化会减慢甚至停止学习过程。一种检测这个问她跌方法就是去画每层的activation/gradient的直方图,如果看到什么奇怪数据就说明有问题呐…

举个例子,tanh神经元中activation的值的分布应该是在[-1,1]整个范围内的,如果全部在0或者全部在1或-1,说明就有问题了…

First-layer Visualizations第一层可视化

如果数据是图像,那么把第一层的特征可视化或许有点用

上图是将神经网络第一层weight可视化的例子
左图中:特征充满了噪声,这暗示了可能:网络不收敛,学习率设置不恰当,正则化惩罚权重太低
右图中:这里的特征就挺好,特征很平滑干净而且种类很多,说明训练过程进行的挺好

Parameter updates 参数更新

SGD随机梯度下降和其他一些东西

普通更新

# Vanilla updatex += - learning_rate * dx

lr是个超参数,而且会被应用到每一个方向中

Momentum update

参考:
https://zhuanlan.zhihu.com/p/21798784?refer=intelligentunit

其实意思就是梯度不直接影响权重,通过一个中间变量再去影响

在普通版本中,梯度直接影响位置。而在这个版本的更新中,梯度只是影响速度,然后速度再影响位置
在这里引入了一个初始化为0的变量v和一个超参数mu。说得不恰当一点,这个变量(mu)在最优化的过程中被看做动量(一般值设为0.9),但其物理意义与摩擦系数更一致。)只是影响速度,然后速度再影响位置

# Momentum updatev = mu * v - learning_rate * dx # integrate velocityx += v # integrate position

在这里引入了用0初始化的变量v和一个超参数mu。这个变量(mu)在最优化的过程中被看做Momentum动量(一般设为0.9),但其物理意义与摩擦系数更一致。 这个变量有效地抑制了速度,降低了系统的动能,不然质点在山底永远不会停下来。

在交叉验证过程中,mu通常设置为[0.5, 0.9, 0.95, 0.99]

和学习率随着时间退火(下文有讨论)类似,Momentum随时间变化的设置有时能略微改善最优化的效果,其中Momentum在学习过程的后阶段会上升。一个典型的设置是刚开始将Momentum设为0.5而在后面的多个周期(epoch)中慢慢提升到0.99。

课程视频:
在梯度小的地方加速,在梯度大的地方利用阻尼和振荡逐步趋近最小值

Nesterov Momentum update

理论上它对凸函数能得到比普通的Momentum update更好的收敛,在实践中也确实比普通的Momentum更好一些

具体看cs231n还有上面的中文翻译链接

x_ahead = x + mu * v# evaluate dx_ahead (the gradient at x_ahead instead of at x)v = mu * v - learning_rate * dx_aheadx += v

Nesterov Momentum update中最重要的就是“lookahead”这种观点,把计算gradient的位置由f(θt1)变成了f(θt1+μvt1)

在这里做了一个变量代换

ϕt1=θt1+μvt1
,就可以得到以下代码

v_prev = v # back this upv = mu * v - learning_rate * dx # velocity update stays the samex += -mu * v_prev + (1 + mu) * v # position update changes form

对于NAG(Nesterov’s Accelerated Momentum)还有
Advances in optimizing Recurrent Networks by Yoshua Bengio, Section 3.5.
https://www.zhihu.com/question/24529483中陈永志的回答

Per-parameter adaptive learning rate methods 逐参数适应学习率方法

前面讨论的所有方法都是对学习率进行全局地操作,并且对所有的参数都是一样的。学习率调参是很耗费计算资源的过程,所以很多人开发出能够适应性地对学习率调参的方法,甚至是逐个参数适应学习率调参。很多这些方法依然需要其他的超参数设置,但是其观点是,对于更广范围的超参数,这些方法比原始的学习率方法有更良好的表现。

下面介绍一些实际中可能会遇到的常用适应性方法

AdaGrad

# Assume the gradient dx and parameter vector xcache += dx**2x += - learning_rate * dx / (np.sqrt(cache) + eps)

在这里根据视频里面的内容解释以下。cache的尺寸和gradient矩阵dx的尺寸是一样的。
而cache是一个随着迭代次数增加而累加的量,dx是每次更新中x方向的梯度,代码使得每次更新都在cache中增加(dx)2
这样的好处在于,随着迭代次数增加,cache会越来越大,lr除以的数越来越大,使得在x方向上获得的更新越来越小。

当我们在x方向上看到很多大的梯度的时候,学习率衰减就会更大(也就是学习率相对比较小),使得x方向上面更新的步长越来越小。
但如果x方向上梯度比较小,那cache就没有cache那么大,那么相对于上面说的x方向上,x方向的学习率相对而言就比较大,更新会更快一些
这是一种针对不同梯度方向补偿的措施

平方根的操作非常重要,如果去掉,算法的表现将会差很多。eps是一个平滑因子是一个超参数(一般设为1e-4到1e-8之间)是防止出现除以0的情况。cache初始化为0。
由于分母的值的大小,所以我们需要一个相应的学习率,但是,绝对步长仍然是由我们最后决定的。
AdaGrad的一个缺点是,在深度学习中单调的学习率,被证明通常过于激进且太早停止更新了。

在长时间的训练中,不断有正数加进去分母cache中,更新步长会逐渐衰减为0,最后停止为0。在凸优化问题里面这个衰减是可以的。但在神经网络里面这就不好了,因为我们需要在神经网络中不断提供活力去更新参数,去找到最优的解,而不是直接就衰减到更新停止。

http://blog.csdn.net/luo123n/article/details/48239963
http://blog.csdn.net/q375010308/article/details/47021779
这两个blog对公式解释的很清楚,结合上面的文字就可以理解AdaGrad了

RMSprop

它是一个很高效的适应性学习率方法
slide 29 of Lecture 6 of Geoff Hinton’s Coursera class

RMSprop简单修改了AdaGrad使得它不那么激进、单调地降低lr。

cache = decay_rate * cache + (1 - decay_rate) * dx**2x += - learning_rate * dx / (np.sqrt(cache) + eps)

decay_rate是一个超参数,比较典型的值有[0.9, 0.99, 0.999]。
RMSProp好处在于不会像AdaGrad一样使得更新最后停止

RMSProp仍然是基于梯度的大小来对每个权重的学习率进行修改。但是和AdaGrad不同,其更新不会让学习率单调变小。所以经常RMSProp结果都会很不错。

正因为decay_rate存在,所以RMSProp的cache其实只有最后的那几百几十个dx累加。

Adam

Adam有点像RMSProp的Momentum版

上图是不完整版Adam

m = beta1*m + (1-beta1)*dxv = beta2*v + (1-beta2)*(dx**2)x += - learning_rate * m / (np.sqrt(v) + eps)

在mini-batch中,由于每次的小批量数据集不同,前向传播中每次梯度噪声很大,相比于每次都只对当前梯度进行计算,我们实际上是利用前面几个梯度的衰减和,这样能稳定梯度的方向,这就是momentum动量的作用。
而(np.sqrt(v) + eps)的作用和之前是一样,对不同梯度方向起到补偿作用。
把Nesterov Momentum替换这里的常规momentum应该也是可行的


上图是完整版Adam
完整的Adam Update包含bias correction mechanism(偏置矫正机制),这个bias矫正机制用到了时间t,m、v初始化为0的补偿措施的时候,所以刚开始数据可能不准确,但是多次迭代之后m、v会逐渐变大,所以最后并不会得到这种bias估计
而且t增大使得mb=m/(1-beta1**t)mb=m/(1-beta1**t)中的分母趋于1,所以这个bias correction只会在最初几次更新中改变m、v的值,所以就m、v统计特性而言最后还是会以正确方式运行

Adam和RMSProp很像。论文中推荐的参数值eps=1e-8, beta1=0.9, beta2=0.999。
在实际中推荐使用Adam作为默认算法,而且它工作的也比RMSProp要更好。但是SGD+Nesterov Momentum也可以试试看。
论文:Adam

Additional References:

Unit Tests for Stochastic Optimization这里展示了对随机最优化的一系列测试




Annealing the learning rate 学习率退火

令学习率随着时间退火对训练深度网络很有作用。
退火其实就是逐渐衰减,以下介绍三种常用的实现学习率衰减的类型

  • Step decay随着步数衰减:每运行几个epochs就根据一些因素降低学习率。典型的是每5个epoch减少一半或每20个epoch减少到0.1。这个值是和具体问题有关的。在实际中,可能会是用一个固定的lr训练,同时观察validation error验证集误差,当验证集误差停止下降的时候,就乘一个常数(例如0.5)降低lr,再继续运行
  • Exponential decay指数衰减α=α0ekt,其中α0,k是超参数,t是迭代次数(或者是epoch周期数)
  • 1/t decay 1/t衰减α=α0/(1+kt),其中α0,k是超参数,t是迭代次数(或者是epoch周期数)

在实际中,使用随步数衰减的dropout更好。这是因为它包含了的超参数(衰减系数和以周期为时间单位的步数)比k,更好解释。
但如果有足够的计算资源,可以让decay更慢,让训练时间更长。

Second order methods 二阶方法

在深度学习的背景下,第二类最优化方法是基于Newton’s method牛顿法的,其迭代如下:

xx[Hf(x)]1f(x)

Hf(x)是Hessian矩阵(In mathematics, the Hessian matrix or Hessian is a square matrix of second-order partial derivatives of a scalar-valued function, or scalar field.)。f(x)是一个gradient vector梯度向量

Hessian描述了loss function的局部曲率,这使得我们可以使用更高效的更新方式。
在这里乘以Hessian的逆是为了在最优化过程中,在梯度平缓的地方步长大,在梯度陡峭的地方步长小。
需要重点注意的是,在这个公式中是没有lr这个超参数的,这相较于first-order methods一阶方法是一个巨大的优势。
然而,计算Hessian在深度学习的应用是不实际的,毕竟计算Hessian和其逆会使用大量的时间和空间。

For instance, a Neural Network with one million parameters would have a Hessian matrix of size [1,000,000 x 1,000,000], occupying approximately 3725 gigabytes of RAM.

所以大量的quasi-Newton methods拟牛顿法就被开发出来去寻找Hessian逆矩阵的近似。最流行的就是L-BFGS(Limited-memory BFGS),使用随着时间的梯度中的信息去建立近似,也就是说整个矩阵没有被完全计算

即使解决了内存问题,L-BFGS一个更大的问题是必须对整个训练集进行计算。和mini-batch SGD不同的是,L-BFGS在mini-batch上运行很tricky,也是研究热点。

在实际中,在深度学习和卷积神经网络领域,L-BFGS和类似的二阶方法并不常见’的了。基于(Nesterov’s) momentum的各种SGD更标准更常用,因为它们更加简单且容易扩展

如果可以承受起full batch update的话那就使用L-BFGS,但要记得去除噪声

Additional references:

  • Large Scale Distributed Deep Networks is a paper from the Google Brain team, comparing L-BFGS and SGD variants in large-scale distributed optimization.
  • SFO algorithm strives to combine the advantages of SGD with advantages of L-BFGS.

Hyperparameter optimization 超参数最优化

在本节中将介绍一些额外的调参要点和技巧:

实现

需要清楚的是,大的神经网络需要调参很久。
一种具体的设计是用一个worker仆程序持续随机选取超参数然后实行最优化。
worker会跟踪每个epoch后验证集的准确率,然后向文件记录一个model checkpoint模型检查点(其中有很多训练统计数据例如随着时间变化的loss),这个文件最好是可共享的。让worker文件名中包含验证集准确率或许有点用,这样就能方便查找和排序。
然后还需要一个master主程序。他可以启动或结束计算集群中的workers,或许还可以检查workers写的checkpoints,输出训练统计数据等等….

Prefer one validation fold to cross-validation. 使用一个验证集代替交叉验证

在大多数情况下,一个尺寸合理的验证集可以让代码更简单,不需要用几个数据集来交叉验证。你可能会听到人们说他们“交叉验证”一个参数,但是大多数情况下,他们实际是使用的一个验证集。

超参数范围

在对数尺度上搜索超参数的值
一个典型的lr应该是这样的learning_rate = 10 ** uniform(-6, 1)uniform(-6,1)指在(-6,1)内生成一个随机数),也就是我们从标准分布中随机生成了一个数字,然后让它成为10的指数倍。

对于regularization strength也可以采用同样的方法
直观地说,这是因为学习率和正则化强度都对于训练的动态进程有乘的效果。

例如,一个固定步长0.01对于lr是0.001有很大效果,但对lr是10的时候效果几乎没有。这是因为lr乘以了gradient。

因此比起对lr加上或减少固定步长,考虑一个lr的区间然后乘或除以某个值会更有用。 就像上文中的代码

但是一些参数(例如dropout)还是在原始尺度上搜索比较好(例如dropout = uniform(0,1))

在实际调参过程中,区间可以根据结果逐步缩小的,也就是逐步逼近最优区间

Prefer random search to grid search. 随机搜索优于网格搜索。

在Random Search for Hyper-Parameter Optimization中提到说,随机搜索在超参数优化过程中比网格化搜索效率高得多而且容易实现

其实意思就是随机选取超参数的效率会高于常规的固定步长选取。
这是因为通常情况下有部分超参数要比其他重要(上图中y轴的超参数不大重要,x轴的比较重要,可以看正方形上边线和左边线上的黄色和绿色山峰的起伏幅度)。
正是因为这个原因,所以随机搜索选取(右图)超参数相比于网格化搜索(左图),能更精确发现那些比较重要的超参数中的表现得好的数值

对于边界上的最优值要小心

有时候我们会在一个不好的范围内进行超参数搜索
举个lr的例子,learning_rate = 10 ** uniform(-6, 1)中一旦我们得到结果,一定要确认这个最后的学习率不是在这个区间(在这里指106~101)的边缘。否则可能会错过其他更好的超参数搜索范围。

从粗到细地分阶段搜索

在实践中,先进行初略范围(比如10 ** [-6, 1])搜索,然后根据好的结果出现的地方,缩小范围进行搜索。进行粗搜索的时候,让模型训练一个周期就可以了,因为很多超参数的设定会让模型没法学习,或者突然就爆出很大的损失值。第二个阶段就是对一个更小的范围进行搜索,这时可以让模型运行5个周期,而最后一个阶段就在最终的范围内进行仔细搜索,运行很多次周期。

在视频中提及的事:实际做法就是随机搜索找到一个准确率比较高的区间,然后继续在区间内随机选取,记得适当用对数尺度有助于搜索

Bayesian Hyperparameter Optimization 贝叶斯超参数最优化

 它是一整个研究领域,主要是研究在超参数空间中更高效的导航算法。其核心的思路是在不同超参数设置下查看算法性能时,要在探索和使用中进行合理的权衡。基于这些模型有很多库,比较有名的有Spearmint,SMAC和Hyperopt

然而在CNN实际使用中,贝叶斯超参数最优化,相比上面介绍的在一个认真挑选的范围内进行随机搜索,还是差了点

Evaluation 评价

Model Ensembles 模型集成

在实践中,有一个很可靠的方式去改善神经网络的效果,提高几个百分点:
训练多个独立模型,然后在test的时候平均他们的预测结果。随着集成模型的数量增加,算法的表现也单调增加(但是提升效果越来越少)。
还有,如果模型集成里面不同模型之间的差异性越大,提升可能会更明显。

以下有几种方法建立一个集成:

Same model, different initializations 相同模型,不同初始化

使用交叉验证集去确定最好的超参数,然后用这些超参数训练多个不同初始化的模型。这个方法风险在于多样性只来源于initialization初始化。

Top models discovered during cross-validation 在交叉验证集中找到最好的模型

用交叉验证集去确定最好得参数,然后取其中最好的几个(比如10个)进行模型集成。这样就提高了集成的多样性,但是风险在于可能包含不够理想的模型。
在实际中,这样操作起来比较简单,在交叉验证之后就不需要额外的训练了

Different checkpoints of a single model 一个模型设置多个记录点

如果训练非常耗时,那就在不同的训练时间对网络留下checkpoint记录点(比如每个周期结束),然后用它们来进行模型集成。很显然,这样做多样性不足,但是在实践中效果还是不错的,这种方法的优势是代价比较小。

Running average of parameters during training 在训练的时候跑参数的平均值

和上面一点相关的,还有一个也能得到1-2个百分点的提升的小代价方法,这个方法就是在训练过程中,如果损失值相较于前一次weights出现指数下降时,就在内存中对网络的weights进行一个备份。这样你就对前几次循环中的网络状态进行了平均。你会发现这个平均过的版本的weights总是能得到更少的误差。直观的理解就是目标函数是一个碗状的,你的网络在这个周围跳跃,所以对它们平均一下,就更可能跳到中心去。

模型集成的一个劣势就是在测试数据的时候会花费更多时间。

Geoff Hinton在“Dark Knowledge”上的工作:通过将集成的对数似然估计值纳入到修改的目标函数,从一个好的集成中提炼出一个单独model

总结

训练神经网络需要:

  • 用小批量数据进行梯度检查,注意各种错误
  • 进行合理性检查,确保初始loss正确,以及能在校数据集实现100%训练准确率
  • 在训练的时候监控loss,training/validation accuracy,the magnitude of updates in relation to parameter values (it should be ~1e-3),还有在处理卷积神经网络的时候,第一层的weights
  • 推荐的两个更新方法是SGD+Nesterov Momentum和Adam
  • 在训练周期中衰减学习率
  • 使用随机搜索(而不是grid search网格搜索)来搜索最优超参数。分阶段,由粗到细搜索
  • 建立模型集成获得额外的性能提高

参考:
https://zhuanlan.zhihu.com/p/21798784?refer=intelligentunit
https://cs231n.github.io/neural-networks-3/
http://study.163.com/course/courseLearn.htm?courseId=1003223001#/learn/video?lessonId=1003911120&courseId=1003223001
http://cs231n.stanford.edu/slides/winter1516_lecture6.pdf

视频中:
根据研究,神经网络越大,局部最小值之间最好和最坏的情况之间的损失值差值会随着时间推移而缩减,所以如果在最优化过程中最后陷入局部最小值,其实问题也不大,因为这个结果已经是可以接受的了。而且用不同的初始化,也很可能得到相同的最优化结果,所以基本不存在局部最小值的问题,尤其是网络比较大的时候

0 0