caffe-阅读Log运行日志

接着笔记caffe-数据&模型-模型输出log,继续阅读Log。是关于内存磁盘间的通信。

从prototxt描述转换城内存表示方式

要构建一个Net,就需要解析两个超参数文件。对于模型结构参数文件:

1
2
3
4
5
6
# 解析
I0610 04:53:36.096751 13919 solver.cpp:102] Creating training net from net file: /media/junhui/DATA/caffe_workspace/my_linearReggresion/mylr.prototxt
# 这两行前面解释过了,区分哪些层用于TRAIN,哪些层用于TEST
I0610 04:53:36.097002 13919 net.cpp:296] The NetState phase (0) differed from the phase (1) specified by a rule in layer mnist
I0610 04:53:36.097012 13919 net.cpp:296] The NetState phase (0) differed from the phase (1) specified by a rule in layer accuracy
I0610 04:53:36.097085 13919 net.cpp:53] Initializing net from parameters:

找到对应位置:

1
2
3
4
5
6
7
8
9
10
void Solver<Dtype>::InitTrainNet() {
...
// param_是一个SolverParameter对象,如果mylr.prototxt文件中定义了Net结构,则如下
if (param_.has_net()) {
LOG_IF(INFO, Caffe::root_solver()) // 打印Log
<< "Creating training net from net file: " << param_.net();
// 解析mylr.prototxt中内容,将其内容存入 NetParameter 对象 net_param 中。
// 转换过程由ProtoBuffer工具完成的。
ReadNetParamsFromTextFileOrDie(param_.net(), &net_param);
}

如此就将磁盘中的prototxt描述转换到内存。

将内存中模型存储到磁盘

当需要保存当前模型和快照时:

1
2
I0610 04:53:38.909629 13919 solver.cpp:464] Snapshotting to binary proto file my_lr_iter_5000.caffemodel
I0610 04:53:38.910568 13919 sgd_solver.cpp:284] Snapshotting solver state to binary proto file my_lr_iter_5000.solverstate

solver.cpp:464 将模型存入磁盘:

1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename Dtype>
string Solver<Dtype>::SnapshotToBinaryProto() {
string model_filename = SnapshotFilename(".caffemodel");
// 文件名,只用提供后缀
LOG(INFO) << "Snapshotting to binary proto file " << model_filename;
// NetParameter 定义在 caffe.pb.h 中
NetParameter net_param;
// 序列化到 net_param,一个 ProtoBuffer 对象
net_->ToProto(&net_param, param_.snapshot_diff());
// 将这个 ProtoBuffer 对象写入磁盘
WriteProtoToBinaryFile(net_param, model_filename);
return model_filename;
}

上述写入磁盘过程在caffe-Blob-(1)解释过。

sgd_solver.cpp:284 将快照存入磁盘:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename Dtype>
void SGDSolver<Dtype>::SnapshotSolverStateToBinaryProto(
const string& model_filename) {
// SolverState 定义在 caffe.pb.h 中
// 创建一个序列化对象
SolverState state;
// 获得当前网络迭代参数
state.set_iter(this->iter_);
state.set_learned_net(model_filename);
state.set_current_step(this->current_step_);
state.clear_history();
for (int i = 0; i < history_.size(); ++i) {
// Add history
BlobProto* history_blob = state.add_history();
// 写入 ProtoBuffer 对象
history_[i]->ToProto(history_blob);
}
string snapshot_filename = Solver<Dtype>::SnapshotFilename(".solverstate");
LOG(INFO)
<< "Snapshotting solver state to binary proto file " << snapshot_filename;
// 将 ProtoBuffer 对象 写入磁盘
WriteProtoToBinaryFile(state, snapshot_filename.c_str());
}

NetParameter和类SolverState都是在caffe.pb.h文件中定义的。这个文件是编译时由 ProtoBuffer 的编译器自动生成的。其中定义了很多类,包括NetParameterSolverState。为什么会自动成成的文件中会有特定的类名? 和可能是ProtoBuffer根据caffe.proto协议生成的。

对比发现,caffe.pb.h 中所有的类名在 caffe.proto 中都是一个message 对象: message NAME {}

上述属于内存磁盘通信的内容。