Caffe原始碼解讀:防止梯度爆炸的措施-梯度裁剪
阿新 • • 發佈:2019-01-10
梯度裁剪是一種在非常深度的網路(通常是迴圈神經網路)中用於防止梯度爆炸(exploding gradient)的技術。
執行梯度裁剪的方法有很多,但常見的一種是當引數向量的 L2 範數(L2 norm)超過一個特定閾值時對引數向量的梯
度進行標準化,這個特定閾值根據函式:新梯度=梯度 * 閾值 / 梯度L2範數
new_gradients = gradients * threshold / l2_norm(gradients)。
Caffe實現程式碼如下:
//梯度裁剪,用來防止梯度爆炸 template <typename Dtype> void SGDSolver<Dtype>::ClipGradients() { const Dtype clip_gradients = this->param_.clip_gradients(); if (clip_gradients < 0) { return; } const vector<Blob<Dtype>*>& 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); } } }