Caffe源码解读:防止梯度爆炸的措施-梯度裁剪

       梯度裁剪是一种在非常深度的网络(通常是循环神经网络)中用于防止梯度爆炸(exploding gradient)的技术。

执行梯度裁剪的方法有很多,但常见的一种是当参数矢量的 L2 范数(L2 norm)超过一个特定阈值时对参数矢量的梯

度进行标准化,这个特定阈值根据函数:新梯度=梯度 * 阈值 / 梯度L2范数

                         new_gradients = gradients * threshold / l2_norm(gradients)。


Caffe实现代码如下:

//梯度裁剪,用来防止梯度爆炸
template 
void SGDSolver::ClipGradients() {
  const Dtype clip_gradients = this->param_.clip_gradients();
  if (clip_gradients < 0) { return; }
  const vector*>& net_params = this->net_->learnable_params();
  Dtype sumsq_diff = 0;
  //diff进行累加
  for (int i = 0; i < net_params.size(); ++i) {
    sumsq_diff += net_params[i]->sumsq_diff();
  }
  //sqrt(sumsq_diff)
  const Dtype l2norm_diff = std::sqrt(sumsq_diff);
  //如果梯度的L2范数大于clip_gradients
  //diff = diff *  clip_gradients / l2norm_diff
  if (l2norm_diff > clip_gradients) {
    Dtype scale_factor = clip_gradients / l2norm_diff;
    LOG(INFO) << "Gradient clipping: scaling down gradients (L2 norm "
        << l2norm_diff << " > " << clip_gradients << ") "
        << "by scale factor " << scale_factor;
    for (int i = 0; i < net_params.size(); ++i) {
      net_params[i]->scale_diff(scale_factor);
    }
  }
}


你可能感兴趣的:(caffe)