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, ¶m);
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())
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)
result = test_net_->Forward(bottom_vec, &iter_loss)
result_vec = result[j]->cpu_data()
test_score[idx++] += result_vec[k]
test_score.push_back(result_vec[k])
test_score[idx++] += result_vec[k]
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:
对于每一次层:
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)
略