[置顶] caffe源码解析 — solver.cpp

Solver<Dtype>::Solver(const SolverParameter& param)
功能:构造函数
步骤:初始化两个Net类,net_和test_net_,并调用Init()函数
输入:SolverParameter类型的param
输出:无

Solver<Dtype>::Solver(const string& param_file)
功能:构造函数
步骤:初始化两个Net类,net_和test_net_,并调用Init()函数
输入:string类型的param_file
输出:无

void Solver<Dtype>::Init(const SolverParameter& param)
功能:初始化网络
步骤:
1. 设置随机数种子
2. 申请一块Net空间以下面的构造函数进行初始化
param_file=train_net_,net_指向这块空间
3. 如果有test_net,则申请一块Net空间,test_net_指向这块空间
输入:SolverParameter类型的param
输出:无

Net<Dtype>::Net(const string& param_file) { NetParameter param;
  ReadNetParamsFromTextFileOrDie(param_file, &param);
  Init(param);
}

void Solver<Dtype>::Solve(const char* resume_file)
功能:训练网络
步骤:
1. 设置Caffe的mode(GPU还是CPU)
2. 如果是GPU且有GPU芯片的ID,则设置GPU
3. 设置当前阶段(TRAIN还是TEST/TRAIN)
4. 调用PreSolve函数:PreSolve()
5. 调用Restore函数:Restore(resume_file)
6. 调用一遍Test(),判断内存是否够
7. 对于每一次训练时的迭代(遍历整个网络):while (iter_++ < param_.max_iter())

  1. 计算loss:loss = net_->ForwardBackward(bottom_vec)其中:
*************** ForwardBackward() ************
Dtype ForwardBackward(const vector<Blob<Dtype>* > & bottom) {
    Dtype loss;
    Forward(bottom, &loss);
    Backward();
    return loss;
  }
*************** Forward() ***********
const vector<Blob<Dtype>*>& Net<Dtype>::Forward(
    const vector<Blob<Dtype>*> & bottom, Dtype* loss) {
  // Copy bottom to internal bottom
  for (int i = 0; i < bottom.size(); ++i) 
    net_input_blobs_[i]->CopyFrom(*bottom[i]){;
  }
  return ForwardPrefilled(loss);
}
*************** ForwardPrefilled() ************
const vector<Blob<Dtype>*>& Net<Dtype>::ForwardPrefilled(Dtype* loss) {
  if (loss != NULL) {
    *loss = Dtype(0.);
  }
  for (int i = 0; i < layers_.size(); ++i) {
    // LOG(ERROR) << "Forwarding " << layer_names_[i];
    Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], &top_vecs_[i]);
    if (loss != NULL) {
      *loss += layer_loss;//对于非loss层都会返回0:return Dtype(0.);
    }
  }
  return net_output_blobs_;
}
*************** Layer::Forward() ************
inline Dtype Layer<Dtype>::Forward(const vector<Blob<Dtype>*>& bottom,
    vector<Blob<Dtype>*>* top) {
  switch (Caffe::mode()) {
  case Caffe::CPU:
    return Forward_cpu(bottom, top);//虚函数,不同层有不同层的计算方法
  case Caffe::GPU:
    return Forward_gpu(bottom, top);
  default:
    LOG(FATAL) << "Unknown caffe mode.";
    return Dtype(0);
  }
}
*************** Backward() ************
void Net<Dtype>::Backward() {
  for (int i = layers_.size() - 1; i >= 0; --i) {
    if (layer_need_backward_[i]) {
      layers_[i]->Backward(top_vecs_[i], true, &bottom_vecs_[i]);
    }
  }
}

2.调用ComputeUpdateValue函数:ComputeUpdateValue()
3. 输出loss
4. 达到test_interval时调用Test()
5. 达到snapshot时调用snapshot()
6. 调用Snapshot函数:Snapshot()
输入:char*类型的resume_file
输出:无

void Solver<Dtype>::Test()
功能:测试网络
输入:无
输出:无
步骤:
1. 设置当前阶段(TRAIN还是TEST/TEST)
2. 将test_net_指向net_,即对同一个网络操作
3. 对于每一次测试时的迭代:for (int i = 0; i < param_.test_iter(); ++i)

  1. 用下面语句给result赋值net_output_blobs_ //result是所有的输出层blob
    同时得到这次测试的iter_loss
    result = test_net_->Forward(bottom_vec, &iter_loss)
  2. 第一次测试时:
    1. 取每一个输出层的blob result_vec = result[j]->cpu_data()
    2. 把每一个blob的数据(降为一维)存入一个vector–“test_score”
  3. 不是第一次测试:
    1. test_score[idx++] += result_vec[k]
      而不是 test_score.push_back(result_vec[k])
    2. 把输出层对应位置的blob值累加
      test_score[idx++] += result_vec[k]
  4. 是否要输出Test loss
  5. 是否要输出test_score
  6. 设置当前阶段(TRAIN还是TEST/TRAIN)

void Solver<Dtype>::Snapshot()
功能:输出当前网络状态到一个文件中,不重要
输入:无
输出:无

void Solver<Dtype>::Restore(const char* state_file)
功能:从一个文件中读入网络状态,并可以从那个状态恢复,不重要
输入:文件名
输出:无

Dtype SGDSolver<Dtype>::GetLearningRate()
功能:得到学习率
步骤:
1. 得到学习率类型 const string& lr_policy = this->param_.lr_policy()
2. 判断学习率类型(注释有介绍)
3. 返回学习率
输入:无
输出:Dtype类型的rate

void SGDSolver<Dtype>::PreSolve()
功能:提前训练
步骤:
1. 将训练网络net_的参数读到net_params net_params = this->net_->params()
其中params_是一个存blob指针的vector
2. 清空历史残留值
3. 向history压入与网络的每一层blob相同大小的空间
输入:无
输出:无

void SGDSolver<Dtype>::ComputeUpdateValue()
功能:用随机梯度下降法计算更新值
输入:无
输出:无
步骤:
1. (所有的)读取网络参数net_params,网络学习速率 net_params_lr,
权值衰减net_params_weight_decay 读取学习速率rate
2. (当前层)读取动量,权值衰减
3. 如果是CPU:
对于每一次层:

  1. 计算local_rate,local_decay
  2. 调用caffe_cpu_axpby,caffe_axpy,caffe_copy函数:
caffe_cpu_axpby(net_params[param_id]->count(), local_rate, net_params[param_id]->cpu_diff(), momentum, history_[param_id]->mutable_cpu_data());
caffe_axpy(net_params[param_id]->count(), local_decay*local_rate, net_params[param_id]->cpu_data(),history_[param_id]->mutable_cpu_data());
void caffe_cpu_axpby<float>(const int N, const float alpha, const float* X,const float beta, float* Y)
{
  cblas_saxpby(N, alpha, X, 1, beta, Y, 1);
}
其中:
inline void cblas_saxpby(const int N, const float alpha, const float* X,const int incX, const float beta, float* Y, const int incY)
{
  cblas_sscal(N, beta, Y, incY);
  cblas_saxpy(N, alpha, X, incX, Y, incY);
}

caffe_cpu_axpby调用了cblas_saxpby,即调用了cblas_sscal和cblas_saxpy

void caffe_axpy<float>(const int N, const float alpha, const float* X,float* Y)
{
  cblas_saxpy(N, alpha, X, 1, Y, 1);
}

caffe_axpy调用了cblas_saxpy,即调用了cblas_saxpy
所以caffe_cpu_axpby比caffe_axpy多输入了一个beta参数,多调用了cblas_sscal(N, beta, Y, incY);
4. GPU同理

void SGDSolver<Dtype>::SnapshotSolverState(SolverState* state)

void SGDSolver<Dtype>::RestoreSolverState(const SolverState& state)

你可能感兴趣的:(源码)