aihot  2017-12-29 19:04:53  机器学习 |   查看评论   

Caffe代码阅读——Solver

      前面我们聊了Net组装的内容,接下来我们来看看Solver的内容。Solver主体有两部分:初始化和训练。初始化内容相对比较简单,这里就不说了;下面我们来说说训练中的几个关键函数。

核心函数:Step

      真正的训练在Step函数内,这里有多卡训练的关键回调函数:on_start()和on_gradient_ready(),具体的调用方法我们后面再说,在这两个回调函数中间有两个重要的过程:ForwardBackward和UpdateSmoothedLoss。在on_gradient_ready之后有一个关键函数ApplyUpdate(),这里面的代码在Sgd_solver中。下面我们详细看一下。

ForwardBackward

      这里主要调用了Net中的代码,主要完成了前向后向的计算,前向用于计算模型的最终输出和Loss,后向用于计算每一层网络和参数的梯度。对于前向后向的具体内容这里需要详细叙述了,唯一值得一提的是前向的Loss计算,这部分代码实际上实在Layer里面,具体涉及到loss_weight这个参数相关的初始化和loss()的判断,同时还有Loss_Layer在Setup函数中的初始化。

UpdateSmoothedLoss

      这个函数主要做Loss的平滑。由于Caffe的训练方式是SGD,我们无法把所有的数据同时放入模型进行训练,那么部分数据产生的Loss就可能会和全样本的平均Loss不同,在必要时候将Loss和历史过程中更新的Loss求平均就可以减少Loss的震荡问题。代码中的平滑方法比较简单,大家一看便知。

      下面就是ApplyUpdate函数,这个函数真正完成了参数更新的任务。Caffe的参数更新只利用了模型的梯度信息,没有利用二阶信息。下面就详细介绍下更新参数的几个过程:

  • GetLearningRate
  • ClipGradients
  • Normalize
  • Regularize
  • ComputeUpdateValue

 

GetLearningRate

      learning rate的故事我们前面已经聊过了,在CNN训练中这确实是个大问题。Caffe为了让learning rate的设计更灵活,提供了一系列的learning rate方案:

  • fixed:lr永远不变
  • steplr=baselr*gamma^{iter / stepsize}
  • explr=baselr*gamma^{iter}
  • invlr=baselr*(1+gamma*iter)^{-power}
  • multistep:直接写iter在某个范围内时lr应该是多少
  • polylr=baselr*(1-\frac{iter}{maxiter})^{power}
  • sigmoidlr=baselr*\frac{1}{1+e^{-gamma*(iter-stepsize)}}

 

      这些方案各有优劣,选择自己顺手的就好。

ClipGradients

      这一步主要是对梯度值做一个限制,如果梯度值过大,那么这里就会对梯度做一个修剪,对所有的参数乘以一个缩放因子,使得所有参数的平方和不超过参数中设定的梯度总值。这个功能感觉上像是对全局函数设置了一个Trust Region,可以防止更新的量过大二导致梯度发散。我认为这一步的想法是很好的,但是实际操作中可能会有问题。实际中可能只有部分参数的梯度比较大,而其他参数的梯度本身比较小,那么对所有的参数乘以相同的因子会让一些本来比较小的参数变得更小,这样会带来一些不公平。

Normalize

      这一步同样考虑了一些单一Batch不足以完成训练的问题,通过限制每个Batch的更新量来控制更新总量,代码比较简单。

Regularize

  
 

除特别注明外,本站所有文章均为 人工智能学习网 原创,转载请注明出处来自Caffe代码阅读——Solver

留言与评论(共有 0 条评论)
   
验证码: