源码
template <typename Dtype>
void Net<Dtype>::AppendTop(const NetParameter& param, const int layer_id,
const int top_id, set<string>* available_blobs,
map<string, int>* blob_name_to_idx) {
shared_ptr<LayerParameter> layer_param(
new LayerParameter(param.layer(layer_id)));
const string& blob_name = (layer_param->top_size() > top_id) ?
layer_param->top(top_id) : "(automatic)";
if (blob_name_to_idx && layer_param->bottom_size() > top_id &&
blob_name == layer_param->bottom(top_id)) {
LOG_IF(INFO, Caffe::root_solver())
<< layer_param->name() << " -> " << blob_name << " (in-place)";
top_vecs_[layer_id].push_back(blobs_[(*blob_name_to_idx)[blob_name]].get());
top_id_vecs_[layer_id].push_back((*blob_name_to_idx)[blob_name]);
} else if (blob_name_to_idx &&
blob_name_to_idx->find(blob_name) != blob_name_to_idx->end()) {
LOG(FATAL) << "Top blob '" << blob_name
<< "' produced by multiple sources.";
} else {
if (Caffe::root_solver()) {
LOG(INFO) << layer_param->name() << " -> " << blob_name;
}
shared_ptr<Blob<Dtype> > blob_pointer(new Blob<Dtype>());
const int blob_id = blobs_.size();
blobs_.push_back(blob_pointer);
blob_names_.push_back(blob_name);
blob_need_backward_.push_back(false);
if (blob_name_to_idx) { (*blob_name_to_idx)[blob_name] = blob_id; }
top_id_vecs_[layer_id].push_back(blob_id);
top_vecs_[layer_id].push_back(blob_pointer.get());
}
if (available_blobs) { available_blobs->insert(blob_name); }
}
template <typename Dtype>
int Net<Dtype>::AppendBottom(const NetParameter& param, const int layer_id,
const int bottom_id, set<string>* available_blobs,
map<string, int>* blob_name_to_idx) {
const LayerParameter& layer_param = param.layer(layer_id);
const string& blob_name = layer_param.bottom(bottom_id);
if (available_blobs->find(blob_name) == available_blobs->end()) {
LOG(FATAL) << "Unknown bottom blob '" << blob_name << "' (layer '"
<< layer_param.name() << "', bottom index " << bottom_id << ")";
}
const int blob_id = (*blob_name_to_idx)[blob_name];
LOG_IF(INFO, Caffe::root_solver())
<< layer_names_[layer_id] << " <- " << blob_name;
bottom_vecs_[layer_id].push_back(blobs_[blob_id].get());
bottom_id_vecs_[layer_id].push_back(blob_id);
available_blobs->erase(blob_name);
bool need_backward = blob_need_backward_[blob_id];
if (layer_param.propagate_down_size() > 0) {
need_backward = layer_param.propagate_down(bottom_id);
}
bottom_need_backward_[layer_id].push_back(need_backward);
return blob_id;
}
功能分析
假定网络结构如下:
过程分析
datan层
blobs_ | blob_names | blob_need_backward |
---|
blob_pointer0 | data | false |
blob_pointer1 | label | false |
top_id_vecs_[0] | top_vecs_[0] | bottom_vecs_[0] | bottom_id_vecs_[0] | bottom_need_backward_[1] |
---|
0 | blob_pointer0 | | | |
1 | blob_pointer1 | | | |
ipn层
blos_id | blobs_ | blob_names | blob_need_backward |
---|
0 | blob_pointer0 | data | false |
1 | blob_pointer1 | label | false |
2 | blob_pointer2 | ip | false |
top_id_vecs_[1] | top_vecs_[1] | bottom_vecs_[1] | bottom_id_vecs_[1] | bottom_need_backward_[1] |
---|
2 | blob_pointer2 | 0 | blob_pointer0 | propagate_down |
relu层
blos_id | blobs_ | blob_names | blob_need_backward |
---|
0 | blob_pointer0 | data | false |
1 | blob_pointer1 | label | false |
2 | blob_pointer2 | ip | false |
top_id_vecs_[2] | top_vecs_[2] | bottom_vecs_[2] | bottom_id_vecs_[2] | bottom_need_backward_[2] |
---|
2 | blob_pointer2 | 2 | blob_pointer2 | propagate_down |
loss层
blos_id | blobs_ | blob_names | blob_need_backward |
---|
0 | blob_pointer0 | data | false |
1 | blob_pointer1 | label | false |
2 | blob_pointer2 | ip | false |
3 | blob_pointer3 | loss | false |
top_id_vecs_[2] | top_vecs_[2] | bottom_vecs_[2] | bottom_id_vecs_[2] | bottom_need_backward_[2] |
---|
3 | blob_pointer3 | 2 | blob_pointer2 | propagate_down |
| | 1 | blob_pointer1 | propagate_down |
功能总结