Merge branch 'master' of github.com:Yangqing/caffe
[jacinto-ai/caffe-jacinto.git] / src / caffe / net.cpp
1 // Copyright Yangqing Jia 2013
3 #include <map>
4 #include <set>
5 #include <string>
6 #include <vector>
8 #include "caffe/proto/caffe.pb.h"
9 #include "caffe/layer_factory.hpp"
10 #include "caffe/net.hpp"
12 using std::pair;
13 using std::map;
14 using std::set;
16 namespace caffe {
18 template <typename Dtype>
19 Net<Dtype>::Net(const NetParameter& param,
20     const vector<Blob<Dtype>* >& bottom) {
21   // Basically, build all the layers and set up its connections.
22   name_ = param.name();
23   map<string, int> blob_name_to_idx;
24   set<string> available_blobs;
25   int num_layers = param.layers_size();
26   CHECK_EQ(bottom.size(), param.bottom_size())
27       << "Incorrect bottom blob size.";
28   // set the input blobs
29   for (int i = 0; i < param.bottom_size(); ++i) {
30     const string& blob_name = param.bottom(i);
31     blobs_.push_back(Blob<Dtype>(*bottom[i]));
32     blob_names_.push_back(blob_name);
33     net_input_blob_indices_.push_back(i);
34     blob_name_to_idx[blob_name] = i;
35     available_blobs.insert(blob_name);
36   }
37   // For each layer, set up their input and output
38   layers_.resize(param.layers_size());
39   bottom_vecs_.resize(param.layers_size());
40   top_vecs_.resize(param.layers_size());
41   for (int i = 0; i < param.top_size(); ++i) {
42     const LayerConnection& layer_connection = param.layers(i);
43     const LayerParameter& layer_param = layer_connection.layer();
44     layers_[i].reset(GetLayer<Dtype>(layer_param));
45     // Figure out this layer's input and output
46     for (int j = 0; j < layer_connection.bottom_size(); ++j) {
47       const string& blob_name = layer_connection.bottom(j);
48       if (available_blobs.find(blob_name) == available_blobs.end()) {
49         LOG(FATAL) << "Unknown blob input " << blob_name <<
50             " to layer" << j;
51       }
52       bottom_vecs_[i].push_back(
53           &blobs_[blob_name_to_idx[blob_name]]);
54       available_blobs.erase(blob_name);
55     }
56     for (int j = 0; j < layer_connection.top_size(); ++j) {
57       const string& blob_name = layer_connection.top(j);
58       if (blob_name_to_idx.find(blob_name) != blob_name_to_idx.end()) {
59         LOG(FATAL) << "Duplicate blobs produced by multiple sources.";
60       }
61       blobs_.push_back(Blob<Dtype>());
62       blob_names_.push_back(blob_name);
63       blob_name_to_idx[blob_name] = blob_names_.size() - 1;
64       available_blobs.insert(blob_name);
65       top_vecs_[i].push_back(&blobs_[blob_names_.size() - 1]);
66     }
67   }
68   // In the end, check if all remaining available blobs are top blobs.
69   for (int i = 0; i < param.top_size(); ++i) {
70     const string& blob_name = param.top(i);
71     if (blob_name_to_idx.find(blob_name) == blob_name_to_idx.end()) {
72       LOG(FATAL) << "Unknown blob input " << blob_name;
73     }
74     net_output_blob_indices_.push_back(blob_name_to_idx[blob_name]);
75     available_blobs.erase(blob_name);
76   }
77   if (!available_blobs.empty()) {
78     LOG(WARNING) << "There are some internal blobs not used:";
79     for (set<string>::iterator it = available_blobs.begin();
80         it != available_blobs.end(); ++it) {
81       LOG(WARNING) << "    " << *it;
82     }
83   }
85   LOG(INFO) << "Setting up the layers.";
86   for (int i = 0; i < layers_.size(); ++i) {
87     layers_[i]->SetUp(bottom_vecs_[i], &top_vecs_[i]);
88   }
89 }
91 template <typename Dtype>
92 void Net<Dtype>::Forward(const vector<Blob<Dtype>*> & bottom,
93     vector<Blob<Dtype>*>* top) {
94   // Copy bottom to internal bottom
95   for (int i = 0; i < bottom.size(); ++i) {
96     blobs_[net_input_blob_indices_[i]] = *bottom[i];
97   }
98   for (int i = 0; i < layers_.size(); ++i) {
99     layers_[i]->Forward(bottom_vecs_[i], &top_vecs_[i]);
100   }
101   // Copy internal top to top
102   for (int i = 0; i < (*top).size(); ++i) {
103     NOT_IMPLEMENTED;
104   }
107 template <typename Dtype>
108 Dtype Net<Dtype>::Backward() {
109   Dtype loss = 0;
110   // TODO(Yangqing): figure out those layers that do not need backward.
111   for (int i = layers_.size() - 1; i >= 0; --i) {
112     loss += layers_[i]->Backward(top_vecs_[i], true, &bottom_vecs_[i]);
113   }
114   return loss;
117 template <typename Dtype>
118 void Net<Dtype>::CopyTrainedLayersFrom(const NetParameter& param) {
119   int num_source_layers = param.layers_size();
120   for (int i = 0; i < num_source_layers; ++i) {
121     const LayerParameter& source_layer = param.layers(i).layer();
122     const string& source_layer_name = source_layer.name();
123     int target_layer_id = 0;
124     while (target_layer_id != layer_names_.size() &&
125         layer_names_[target_layer_id] != source_layer_name) {
126       ++target_layer_id;
127     }
128     if (target_layer_id == layer_names_.size()) {
129       LOG(INFO) << "Ignoring source layer " << source_layer_name;
130       continue;
131     }
132     LOG(INFO) << "Loading source layer " << source_layer_name;
133     vector<Blob<Dtype> >& target_blobs = layers_[target_layer_id]->params();
134     CHECK_EQ(target_blobs.size(), source_layer.blobs_size())
135         << "Incompatible number of blobs for layer " << source_layer_name;
136     for (int j = 0; j < target_blobs.size(); ++j) {
137       target_blobs[j].FromProto(source_layer.blobs(j));
138     }
139   }
142 template <typename Dtype>
143 void Net<Dtype>::ToProto(NetParameter* param, bool write_diff) {
144   param->Clear();
145   param->set_name(name_);
146   // Add bottom and top
147   for (int i = 0; i < net_input_blob_indices_.size(); ++i) {
148     param->add_bottom(blob_names_[net_input_blob_indices_[i]]);
149   }
150   for (int i = 0; i < net_input_blob_indices_.size(); ++i) {
151     param->add_bottom(blob_names_[net_input_blob_indices_[i]]);
152   }
153   for (int i = 0; i < layers_.size(); ++i) {
154     LayerConnection* layer_connection = param->add_layers();
155   }
158 INSTANTIATE_CLASS(Net);
160 }  // namespace caffe