fixing upgrade_proto for BatchNorm layer: be more conservative leave "name" in param...
[platform/upstream/caffeonacl.git] / src / caffe / util / upgrade_proto.cpp
1 #include <google/protobuf/io/coded_stream.h>
2 #include <google/protobuf/io/zero_copy_stream_impl.h>
3 #include <google/protobuf/text_format.h>
4
5 #include <map>
6 #include <string>
7
8 #include "caffe/common.hpp"
9 #include "caffe/proto/caffe.pb.h"
10 #include "caffe/util/io.hpp"
11 #include "caffe/util/upgrade_proto.hpp"
12
13 namespace caffe {
14
15 bool NetNeedsUpgrade(const NetParameter& net_param) {
16   return NetNeedsV0ToV1Upgrade(net_param) || NetNeedsV1ToV2Upgrade(net_param)
17       || NetNeedsDataUpgrade(net_param) || NetNeedsInputUpgrade(net_param)
18       || NetNeedsBatchNormUpgrade(net_param);
19 }
20
21 bool UpgradeNetAsNeeded(const string& param_file, NetParameter* param) {
22   bool success = true;
23   if (NetNeedsV0ToV1Upgrade(*param)) {
24     // NetParameter was specified using the old style (V0LayerParameter); try to
25     // upgrade it.
26     LOG(INFO) << "Attempting to upgrade input file specified using deprecated "
27               << "V0LayerParameter: " << param_file;
28     NetParameter original_param(*param);
29     if (!UpgradeV0Net(original_param, param)) {
30       success = false;
31       LOG(ERROR) << "Warning: had one or more problems upgrading "
32           << "V0NetParameter to NetParameter (see above); continuing anyway.";
33     } else {
34       LOG(INFO) << "Successfully upgraded file specified using deprecated "
35                 << "V0LayerParameter";
36     }
37     LOG(WARNING) << "Note that future Caffe releases will not support "
38         << "V0NetParameter; use ./build/tools/upgrade_net_proto_text for "
39         << "prototxt and ./build/tools/upgrade_net_proto_binary for model "
40         << "weights upgrade this and any other net protos to the new format.";
41   }
42   // NetParameter uses old style data transformation fields; try to upgrade it.
43   if (NetNeedsDataUpgrade(*param)) {
44     LOG(INFO) << "Attempting to upgrade input file specified using deprecated "
45               << "transformation parameters: " << param_file;
46     UpgradeNetDataTransformation(param);
47     LOG(INFO) << "Successfully upgraded file specified using deprecated "
48               << "data transformation parameters.";
49     LOG(WARNING) << "Note that future Caffe releases will only support "
50                  << "transform_param messages for transformation fields.";
51   }
52   if (NetNeedsV1ToV2Upgrade(*param)) {
53     LOG(INFO) << "Attempting to upgrade input file specified using deprecated "
54               << "V1LayerParameter: " << param_file;
55     NetParameter original_param(*param);
56     if (!UpgradeV1Net(original_param, param)) {
57       success = false;
58       LOG(ERROR) << "Warning: had one or more problems upgrading "
59                  << "V1LayerParameter (see above); continuing anyway.";
60     } else {
61       LOG(INFO) << "Successfully upgraded file specified using deprecated "
62                 << "V1LayerParameter";
63     }
64   }
65   // NetParameter uses old style input fields; try to upgrade it.
66   if (NetNeedsInputUpgrade(*param)) {
67     LOG(INFO) << "Attempting to upgrade input file specified using deprecated "
68               << "input fields: " << param_file;
69     UpgradeNetInput(param);
70     LOG(INFO) << "Successfully upgraded file specified using deprecated "
71               << "input fields.";
72     LOG(WARNING) << "Note that future Caffe releases will only support "
73                  << "input layers and not input fields.";
74   }
75   // NetParameter uses old style batch norm layers; try to upgrade it.
76   if (NetNeedsBatchNormUpgrade(*param)) {
77     LOG(INFO) << "Attempting to upgrade batch norm layers using deprecated "
78               << "params: " << param_file;
79     UpgradeNetBatchNorm(param);
80     LOG(INFO) << "Successfully upgraded batch norm layers using deprecated "
81               << "params.";
82   }
83   return success;
84 }
85
86 void ReadNetParamsFromTextFileOrDie(const string& param_file,
87                                     NetParameter* param) {
88   CHECK(ReadProtoFromTextFile(param_file, param))
89       << "Failed to parse NetParameter file: " << param_file;
90   UpgradeNetAsNeeded(param_file, param);
91 }
92
93 void ReadNetParamsFromBinaryFileOrDie(const string& param_file,
94                                       NetParameter* param) {
95   CHECK(ReadProtoFromBinaryFile(param_file, param))
96       << "Failed to parse NetParameter file: " << param_file;
97   UpgradeNetAsNeeded(param_file, param);
98 }
99
100 bool NetNeedsV0ToV1Upgrade(const NetParameter& net_param) {
101   for (int i = 0; i < net_param.layers_size(); ++i) {
102     if (net_param.layers(i).has_layer()) {
103       return true;
104     }
105   }
106   return false;
107 }
108
109 bool NetNeedsV1ToV2Upgrade(const NetParameter& net_param) {
110   return net_param.layers_size() > 0;
111 }
112
113 bool UpgradeV0Net(const NetParameter& v0_net_param_padding_layers,
114                   NetParameter* net_param) {
115   // First upgrade padding layers to padded conv layers.
116   NetParameter v0_net_param;
117   UpgradeV0PaddingLayers(v0_net_param_padding_layers, &v0_net_param);
118   // Now upgrade layer parameters.
119   bool is_fully_compatible = true;
120   net_param->Clear();
121   if (v0_net_param.has_name()) {
122     net_param->set_name(v0_net_param.name());
123   }
124   for (int i = 0; i < v0_net_param.layers_size(); ++i) {
125     is_fully_compatible &= UpgradeV0LayerParameter(v0_net_param.layers(i),
126                                                    net_param->add_layers());
127   }
128   for (int i = 0; i < v0_net_param.input_size(); ++i) {
129     net_param->add_input(v0_net_param.input(i));
130   }
131   for (int i = 0; i < v0_net_param.input_dim_size(); ++i) {
132     net_param->add_input_dim(v0_net_param.input_dim(i));
133   }
134   if (v0_net_param.has_force_backward()) {
135     net_param->set_force_backward(v0_net_param.force_backward());
136   }
137   return is_fully_compatible;
138 }
139
140 void UpgradeV0PaddingLayers(const NetParameter& param,
141                             NetParameter* param_upgraded_pad) {
142   // Copy everything other than the layers from the original param.
143   param_upgraded_pad->Clear();
144   param_upgraded_pad->CopyFrom(param);
145   param_upgraded_pad->clear_layers();
146   // Figure out which layer each bottom blob comes from.
147   map<string, int> blob_name_to_last_top_idx;
148   for (int i = 0; i < param.input_size(); ++i) {
149     const string& blob_name = param.input(i);
150     blob_name_to_last_top_idx[blob_name] = -1;
151   }
152   for (int i = 0; i < param.layers_size(); ++i) {
153     const V1LayerParameter& layer_connection = param.layers(i);
154     const V0LayerParameter& layer_param = layer_connection.layer();
155     // Add the layer to the new net, unless it's a padding layer.
156     if (layer_param.type() != "padding") {
157       param_upgraded_pad->add_layers()->CopyFrom(layer_connection);
158     }
159     for (int j = 0; j < layer_connection.bottom_size(); ++j) {
160       const string& blob_name = layer_connection.bottom(j);
161       if (blob_name_to_last_top_idx.find(blob_name) ==
162           blob_name_to_last_top_idx.end()) {
163         LOG(FATAL) << "Unknown blob input " << blob_name << " to layer " << j;
164       }
165       const int top_idx = blob_name_to_last_top_idx[blob_name];
166       if (top_idx == -1) {
167         continue;
168       }
169       const V1LayerParameter& source_layer = param.layers(top_idx);
170       if (source_layer.layer().type() == "padding") {
171         // This layer has a padding layer as input -- check that it is a conv
172         // layer or a pooling layer and takes only one input.  Also check that
173         // the padding layer input has only one input and one output.  Other
174         // cases have undefined behavior in Caffe.
175         CHECK((layer_param.type() == "conv") || (layer_param.type() == "pool"))
176             << "Padding layer input to "
177             "non-convolutional / non-pooling layer type "
178             << layer_param.type();
179         CHECK_EQ(layer_connection.bottom_size(), 1)
180             << "Conv Layer takes a single blob as input.";
181         CHECK_EQ(source_layer.bottom_size(), 1)
182             << "Padding Layer takes a single blob as input.";
183         CHECK_EQ(source_layer.top_size(), 1)
184             << "Padding Layer produces a single blob as output.";
185         int layer_index = param_upgraded_pad->layers_size() - 1;
186         param_upgraded_pad->mutable_layers(layer_index)->mutable_layer()
187             ->set_pad(source_layer.layer().pad());
188         param_upgraded_pad->mutable_layers(layer_index)
189             ->set_bottom(j, source_layer.bottom(0));
190       }
191     }
192     for (int j = 0; j < layer_connection.top_size(); ++j) {
193       const string& blob_name = layer_connection.top(j);
194       blob_name_to_last_top_idx[blob_name] = i;
195     }
196   }
197 }
198
199 bool UpgradeV0LayerParameter(const V1LayerParameter& v0_layer_connection,
200                              V1LayerParameter* layer_param) {
201   bool is_fully_compatible = true;
202   layer_param->Clear();
203   for (int i = 0; i < v0_layer_connection.bottom_size(); ++i) {
204     layer_param->add_bottom(v0_layer_connection.bottom(i));
205   }
206   for (int i = 0; i < v0_layer_connection.top_size(); ++i) {
207     layer_param->add_top(v0_layer_connection.top(i));
208   }
209   if (v0_layer_connection.has_layer()) {
210     const V0LayerParameter& v0_layer_param = v0_layer_connection.layer();
211     if (v0_layer_param.has_name()) {
212       layer_param->set_name(v0_layer_param.name());
213     }
214     const string& type = v0_layer_param.type();
215     if (v0_layer_param.has_type()) {
216       layer_param->set_type(UpgradeV0LayerType(type));
217     }
218     for (int i = 0; i < v0_layer_param.blobs_size(); ++i) {
219       layer_param->add_blobs()->CopyFrom(v0_layer_param.blobs(i));
220     }
221     for (int i = 0; i < v0_layer_param.blobs_lr_size(); ++i) {
222       layer_param->add_blobs_lr(v0_layer_param.blobs_lr(i));
223     }
224     for (int i = 0; i < v0_layer_param.weight_decay_size(); ++i) {
225       layer_param->add_weight_decay(v0_layer_param.weight_decay(i));
226     }
227     if (v0_layer_param.has_num_output()) {
228       if (type == "conv") {
229         layer_param->mutable_convolution_param()->set_num_output(
230             v0_layer_param.num_output());
231       } else if (type == "innerproduct") {
232         layer_param->mutable_inner_product_param()->set_num_output(
233             v0_layer_param.num_output());
234       } else {
235         LOG(ERROR) << "Unknown parameter num_output for layer type " << type;
236         is_fully_compatible = false;
237       }
238     }
239     if (v0_layer_param.has_biasterm()) {
240       if (type == "conv") {
241         layer_param->mutable_convolution_param()->set_bias_term(
242             v0_layer_param.biasterm());
243       } else if (type == "innerproduct") {
244         layer_param->mutable_inner_product_param()->set_bias_term(
245             v0_layer_param.biasterm());
246       } else {
247         LOG(ERROR) << "Unknown parameter biasterm for layer type " << type;
248         is_fully_compatible = false;
249       }
250     }
251     if (v0_layer_param.has_weight_filler()) {
252       if (type == "conv") {
253         layer_param->mutable_convolution_param()->
254             mutable_weight_filler()->CopyFrom(v0_layer_param.weight_filler());
255       } else if (type == "innerproduct") {
256         layer_param->mutable_inner_product_param()->
257             mutable_weight_filler()->CopyFrom(v0_layer_param.weight_filler());
258       } else {
259         LOG(ERROR) << "Unknown parameter weight_filler for layer type " << type;
260         is_fully_compatible = false;
261       }
262     }
263     if (v0_layer_param.has_bias_filler()) {
264       if (type == "conv") {
265         layer_param->mutable_convolution_param()->
266             mutable_bias_filler()->CopyFrom(v0_layer_param.bias_filler());
267       } else if (type == "innerproduct") {
268         layer_param->mutable_inner_product_param()->
269             mutable_bias_filler()->CopyFrom(v0_layer_param.bias_filler());
270       } else {
271         LOG(ERROR) << "Unknown parameter bias_filler for layer type " << type;
272         is_fully_compatible = false;
273       }
274     }
275     if (v0_layer_param.has_pad()) {
276       if (type == "conv") {
277         layer_param->mutable_convolution_param()->add_pad(v0_layer_param.pad());
278       } else if (type == "pool") {
279         layer_param->mutable_pooling_param()->set_pad(v0_layer_param.pad());
280       } else {
281         LOG(ERROR) << "Unknown parameter pad for layer type " << type;
282         is_fully_compatible = false;
283       }
284     }
285     if (v0_layer_param.has_kernelsize()) {
286       if (type == "conv") {
287         layer_param->mutable_convolution_param()->add_kernel_size(
288             v0_layer_param.kernelsize());
289       } else if (type == "pool") {
290         layer_param->mutable_pooling_param()->set_kernel_size(
291             v0_layer_param.kernelsize());
292       } else {
293         LOG(ERROR) << "Unknown parameter kernelsize for layer type " << type;
294         is_fully_compatible = false;
295       }
296     }
297     if (v0_layer_param.has_group()) {
298       if (type == "conv") {
299         layer_param->mutable_convolution_param()->set_group(
300             v0_layer_param.group());
301       } else {
302         LOG(ERROR) << "Unknown parameter group for layer type " << type;
303         is_fully_compatible = false;
304       }
305     }
306     if (v0_layer_param.has_stride()) {
307       if (type == "conv") {
308         layer_param->mutable_convolution_param()->add_stride(
309             v0_layer_param.stride());
310       } else if (type == "pool") {
311         layer_param->mutable_pooling_param()->set_stride(
312             v0_layer_param.stride());
313       } else {
314         LOG(ERROR) << "Unknown parameter stride for layer type " << type;
315         is_fully_compatible = false;
316       }
317     }
318     if (v0_layer_param.has_pool()) {
319       if (type == "pool") {
320         V0LayerParameter_PoolMethod pool = v0_layer_param.pool();
321         switch (pool) {
322         case V0LayerParameter_PoolMethod_MAX:
323           layer_param->mutable_pooling_param()->set_pool(
324               PoolingParameter_PoolMethod_MAX);
325           break;
326         case V0LayerParameter_PoolMethod_AVE:
327           layer_param->mutable_pooling_param()->set_pool(
328               PoolingParameter_PoolMethod_AVE);
329           break;
330         case V0LayerParameter_PoolMethod_STOCHASTIC:
331           layer_param->mutable_pooling_param()->set_pool(
332               PoolingParameter_PoolMethod_STOCHASTIC);
333           break;
334         default:
335           LOG(ERROR) << "Unknown pool method " << pool;
336           is_fully_compatible = false;
337         }
338       } else {
339         LOG(ERROR) << "Unknown parameter pool for layer type " << type;
340         is_fully_compatible = false;
341       }
342     }
343     if (v0_layer_param.has_dropout_ratio()) {
344       if (type == "dropout") {
345         layer_param->mutable_dropout_param()->set_dropout_ratio(
346             v0_layer_param.dropout_ratio());
347       } else {
348         LOG(ERROR) << "Unknown parameter dropout_ratio for layer type " << type;
349         is_fully_compatible = false;
350       }
351     }
352     if (v0_layer_param.has_local_size()) {
353       if (type == "lrn") {
354         layer_param->mutable_lrn_param()->set_local_size(
355             v0_layer_param.local_size());
356       } else {
357         LOG(ERROR) << "Unknown parameter local_size for layer type " << type;
358         is_fully_compatible = false;
359       }
360     }
361     if (v0_layer_param.has_alpha()) {
362       if (type == "lrn") {
363         layer_param->mutable_lrn_param()->set_alpha(v0_layer_param.alpha());
364       } else {
365         LOG(ERROR) << "Unknown parameter alpha for layer type " << type;
366         is_fully_compatible = false;
367       }
368     }
369     if (v0_layer_param.has_beta()) {
370       if (type == "lrn") {
371         layer_param->mutable_lrn_param()->set_beta(v0_layer_param.beta());
372       } else {
373         LOG(ERROR) << "Unknown parameter beta for layer type " << type;
374         is_fully_compatible = false;
375       }
376     }
377     if (v0_layer_param.has_k()) {
378       if (type == "lrn") {
379         layer_param->mutable_lrn_param()->set_k(v0_layer_param.k());
380       } else {
381         LOG(ERROR) << "Unknown parameter k for layer type " << type;
382         is_fully_compatible = false;
383       }
384     }
385     if (v0_layer_param.has_source()) {
386       if (type == "data") {
387         layer_param->mutable_data_param()->set_source(v0_layer_param.source());
388       } else if (type == "hdf5_data") {
389         layer_param->mutable_hdf5_data_param()->set_source(
390             v0_layer_param.source());
391       } else if (type == "images") {
392         layer_param->mutable_image_data_param()->set_source(
393             v0_layer_param.source());
394       } else if (type == "window_data") {
395         layer_param->mutable_window_data_param()->set_source(
396             v0_layer_param.source());
397       } else if (type == "infogain_loss") {
398         layer_param->mutable_infogain_loss_param()->set_source(
399             v0_layer_param.source());
400       } else {
401         LOG(ERROR) << "Unknown parameter source for layer type " << type;
402         is_fully_compatible = false;
403       }
404     }
405     if (v0_layer_param.has_scale()) {
406       layer_param->mutable_transform_param()->
407           set_scale(v0_layer_param.scale());
408     }
409     if (v0_layer_param.has_meanfile()) {
410       layer_param->mutable_transform_param()->
411           set_mean_file(v0_layer_param.meanfile());
412     }
413     if (v0_layer_param.has_batchsize()) {
414       if (type == "data") {
415         layer_param->mutable_data_param()->set_batch_size(
416             v0_layer_param.batchsize());
417       } else if (type == "hdf5_data") {
418         layer_param->mutable_hdf5_data_param()->set_batch_size(
419             v0_layer_param.batchsize());
420       } else if (type == "images") {
421         layer_param->mutable_image_data_param()->set_batch_size(
422             v0_layer_param.batchsize());
423       } else if (type == "window_data") {
424         layer_param->mutable_window_data_param()->set_batch_size(
425             v0_layer_param.batchsize());
426       } else {
427         LOG(ERROR) << "Unknown parameter batchsize for layer type " << type;
428         is_fully_compatible = false;
429       }
430     }
431     if (v0_layer_param.has_cropsize()) {
432       layer_param->mutable_transform_param()->
433           set_crop_size(v0_layer_param.cropsize());
434     }
435     if (v0_layer_param.has_mirror()) {
436       layer_param->mutable_transform_param()->
437           set_mirror(v0_layer_param.mirror());
438     }
439     if (v0_layer_param.has_rand_skip()) {
440       if (type == "data") {
441         layer_param->mutable_data_param()->set_rand_skip(
442             v0_layer_param.rand_skip());
443       } else if (type == "images") {
444         layer_param->mutable_image_data_param()->set_rand_skip(
445             v0_layer_param.rand_skip());
446       } else {
447         LOG(ERROR) << "Unknown parameter rand_skip for layer type " << type;
448         is_fully_compatible = false;
449       }
450     }
451     if (v0_layer_param.has_shuffle_images()) {
452       if (type == "images") {
453         layer_param->mutable_image_data_param()->set_shuffle(
454             v0_layer_param.shuffle_images());
455       } else {
456         LOG(ERROR) << "Unknown parameter shuffle for layer type " << type;
457         is_fully_compatible = false;
458       }
459     }
460     if (v0_layer_param.has_new_height()) {
461       if (type == "images") {
462         layer_param->mutable_image_data_param()->set_new_height(
463             v0_layer_param.new_height());
464       } else {
465         LOG(ERROR) << "Unknown parameter new_height for layer type " << type;
466         is_fully_compatible = false;
467       }
468     }
469     if (v0_layer_param.has_new_width()) {
470       if (type == "images") {
471         layer_param->mutable_image_data_param()->set_new_width(
472             v0_layer_param.new_width());
473       } else {
474         LOG(ERROR) << "Unknown parameter new_width for layer type " << type;
475         is_fully_compatible = false;
476       }
477     }
478     if (v0_layer_param.has_concat_dim()) {
479       if (type == "concat") {
480         layer_param->mutable_concat_param()->set_concat_dim(
481             v0_layer_param.concat_dim());
482       } else {
483         LOG(ERROR) << "Unknown parameter concat_dim for layer type " << type;
484         is_fully_compatible = false;
485       }
486     }
487     if (v0_layer_param.has_det_fg_threshold()) {
488       if (type == "window_data") {
489         layer_param->mutable_window_data_param()->set_fg_threshold(
490             v0_layer_param.det_fg_threshold());
491       } else {
492         LOG(ERROR) << "Unknown parameter det_fg_threshold for layer type "
493                    << type;
494         is_fully_compatible = false;
495       }
496     }
497     if (v0_layer_param.has_det_bg_threshold()) {
498       if (type == "window_data") {
499         layer_param->mutable_window_data_param()->set_bg_threshold(
500             v0_layer_param.det_bg_threshold());
501       } else {
502         LOG(ERROR) << "Unknown parameter det_bg_threshold for layer type "
503                    << type;
504         is_fully_compatible = false;
505       }
506     }
507     if (v0_layer_param.has_det_fg_fraction()) {
508       if (type == "window_data") {
509         layer_param->mutable_window_data_param()->set_fg_fraction(
510             v0_layer_param.det_fg_fraction());
511       } else {
512         LOG(ERROR) << "Unknown parameter det_fg_fraction for layer type "
513                    << type;
514         is_fully_compatible = false;
515       }
516     }
517     if (v0_layer_param.has_det_context_pad()) {
518       if (type == "window_data") {
519         layer_param->mutable_window_data_param()->set_context_pad(
520             v0_layer_param.det_context_pad());
521       } else {
522         LOG(ERROR) << "Unknown parameter det_context_pad for layer type "
523                    << type;
524         is_fully_compatible = false;
525       }
526     }
527     if (v0_layer_param.has_det_crop_mode()) {
528       if (type == "window_data") {
529         layer_param->mutable_window_data_param()->set_crop_mode(
530             v0_layer_param.det_crop_mode());
531       } else {
532         LOG(ERROR) << "Unknown parameter det_crop_mode for layer type "
533                    << type;
534         is_fully_compatible = false;
535       }
536     }
537     if (v0_layer_param.has_hdf5_output_param()) {
538       if (type == "hdf5_output") {
539         layer_param->mutable_hdf5_output_param()->CopyFrom(
540             v0_layer_param.hdf5_output_param());
541       } else {
542         LOG(ERROR) << "Unknown parameter hdf5_output_param for layer type "
543                    << type;
544         is_fully_compatible = false;
545       }
546     }
547   }
548   return is_fully_compatible;
549 }
550
551 V1LayerParameter_LayerType UpgradeV0LayerType(const string& type) {
552   if (type == "accuracy") {
553     return V1LayerParameter_LayerType_ACCURACY;
554   } else if (type == "bnll") {
555     return V1LayerParameter_LayerType_BNLL;
556   } else if (type == "concat") {
557     return V1LayerParameter_LayerType_CONCAT;
558   } else if (type == "conv") {
559     return V1LayerParameter_LayerType_CONVOLUTION;
560   } else if (type == "data") {
561     return V1LayerParameter_LayerType_DATA;
562   } else if (type == "dropout") {
563     return V1LayerParameter_LayerType_DROPOUT;
564   } else if (type == "euclidean_loss") {
565     return V1LayerParameter_LayerType_EUCLIDEAN_LOSS;
566   } else if (type == "flatten") {
567     return V1LayerParameter_LayerType_FLATTEN;
568   } else if (type == "hdf5_data") {
569     return V1LayerParameter_LayerType_HDF5_DATA;
570   } else if (type == "hdf5_output") {
571     return V1LayerParameter_LayerType_HDF5_OUTPUT;
572   } else if (type == "im2col") {
573     return V1LayerParameter_LayerType_IM2COL;
574   } else if (type == "images") {
575     return V1LayerParameter_LayerType_IMAGE_DATA;
576   } else if (type == "infogain_loss") {
577     return V1LayerParameter_LayerType_INFOGAIN_LOSS;
578   } else if (type == "innerproduct") {
579     return V1LayerParameter_LayerType_INNER_PRODUCT;
580   } else if (type == "lrn") {
581     return V1LayerParameter_LayerType_LRN;
582   } else if (type == "multinomial_logistic_loss") {
583     return V1LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS;
584   } else if (type == "pool") {
585     return V1LayerParameter_LayerType_POOLING;
586   } else if (type == "relu") {
587     return V1LayerParameter_LayerType_RELU;
588   } else if (type == "sigmoid") {
589     return V1LayerParameter_LayerType_SIGMOID;
590   } else if (type == "softmax") {
591     return V1LayerParameter_LayerType_SOFTMAX;
592   } else if (type == "softmax_loss") {
593     return V1LayerParameter_LayerType_SOFTMAX_LOSS;
594   } else if (type == "split") {
595     return V1LayerParameter_LayerType_SPLIT;
596   } else if (type == "tanh") {
597     return V1LayerParameter_LayerType_TANH;
598   } else if (type == "window_data") {
599     return V1LayerParameter_LayerType_WINDOW_DATA;
600   } else {
601     LOG(FATAL) << "Unknown layer name: " << type;
602     return V1LayerParameter_LayerType_NONE;
603   }
604 }
605
606 bool NetNeedsDataUpgrade(const NetParameter& net_param) {
607   for (int i = 0; i < net_param.layers_size(); ++i) {
608     if (net_param.layers(i).type() == V1LayerParameter_LayerType_DATA) {
609       DataParameter layer_param = net_param.layers(i).data_param();
610       if (layer_param.has_scale()) { return true; }
611       if (layer_param.has_mean_file()) { return true; }
612       if (layer_param.has_crop_size()) { return true; }
613       if (layer_param.has_mirror()) { return true; }
614     }
615     if (net_param.layers(i).type() == V1LayerParameter_LayerType_IMAGE_DATA) {
616       ImageDataParameter layer_param = net_param.layers(i).image_data_param();
617       if (layer_param.has_scale()) { return true; }
618       if (layer_param.has_mean_file()) { return true; }
619       if (layer_param.has_crop_size()) { return true; }
620       if (layer_param.has_mirror()) { return true; }
621     }
622     if (net_param.layers(i).type() == V1LayerParameter_LayerType_WINDOW_DATA) {
623       WindowDataParameter layer_param = net_param.layers(i).window_data_param();
624       if (layer_param.has_scale()) { return true; }
625       if (layer_param.has_mean_file()) { return true; }
626       if (layer_param.has_crop_size()) { return true; }
627       if (layer_param.has_mirror()) { return true; }
628     }
629   }
630   return false;
631 }
632
633 #define CONVERT_LAYER_TRANSFORM_PARAM(TYPE, Name, param_name) \
634   do { \
635     if (net_param->layers(i).type() == V1LayerParameter_LayerType_##TYPE) { \
636       Name##Parameter* layer_param = \
637           net_param->mutable_layers(i)->mutable_##param_name##_param(); \
638       TransformationParameter* transform_param = \
639           net_param->mutable_layers(i)->mutable_transform_param(); \
640       if (layer_param->has_scale()) { \
641         transform_param->set_scale(layer_param->scale()); \
642         layer_param->clear_scale(); \
643       } \
644       if (layer_param->has_mean_file()) { \
645         transform_param->set_mean_file(layer_param->mean_file()); \
646         layer_param->clear_mean_file(); \
647       } \
648       if (layer_param->has_crop_size()) { \
649         transform_param->set_crop_size(layer_param->crop_size()); \
650         layer_param->clear_crop_size(); \
651       } \
652       if (layer_param->has_mirror()) { \
653         transform_param->set_mirror(layer_param->mirror()); \
654         layer_param->clear_mirror(); \
655       } \
656     } \
657   } while (0)
658
659 void UpgradeNetDataTransformation(NetParameter* net_param) {
660   for (int i = 0; i < net_param->layers_size(); ++i) {
661     CONVERT_LAYER_TRANSFORM_PARAM(DATA, Data, data);
662     CONVERT_LAYER_TRANSFORM_PARAM(IMAGE_DATA, ImageData, image_data);
663     CONVERT_LAYER_TRANSFORM_PARAM(WINDOW_DATA, WindowData, window_data);
664   }
665 }
666
667 bool UpgradeV1Net(const NetParameter& v1_net_param, NetParameter* net_param) {
668   if (v1_net_param.layer_size() > 0) {
669     LOG(FATAL) << "Refusing to upgrade inconsistent NetParameter input; "
670         << "the definition includes both 'layer' and 'layers' fields. "
671         << "The current format defines 'layer' fields with string type like "
672         << "layer { type: 'Layer' ... } and not layers { type: LAYER ... }. "
673         << "Manually switch the definition to 'layer' format to continue.";
674   }
675   bool is_fully_compatible = true;
676   net_param->CopyFrom(v1_net_param);
677   net_param->clear_layers();
678   net_param->clear_layer();
679   for (int i = 0; i < v1_net_param.layers_size(); ++i) {
680     if (!UpgradeV1LayerParameter(v1_net_param.layers(i),
681                                  net_param->add_layer())) {
682       LOG(ERROR) << "Upgrade of input layer " << i << " failed.";
683       is_fully_compatible = false;
684     }
685   }
686   return is_fully_compatible;
687 }
688
689 bool UpgradeV1LayerParameter(const V1LayerParameter& v1_layer_param,
690                              LayerParameter* layer_param) {
691   layer_param->Clear();
692   bool is_fully_compatible = true;
693   for (int i = 0; i < v1_layer_param.bottom_size(); ++i) {
694     layer_param->add_bottom(v1_layer_param.bottom(i));
695   }
696   for (int i = 0; i < v1_layer_param.top_size(); ++i) {
697     layer_param->add_top(v1_layer_param.top(i));
698   }
699   if (v1_layer_param.has_name()) {
700     layer_param->set_name(v1_layer_param.name());
701   }
702   for (int i = 0; i < v1_layer_param.include_size(); ++i) {
703     layer_param->add_include()->CopyFrom(v1_layer_param.include(i));
704   }
705   for (int i = 0; i < v1_layer_param.exclude_size(); ++i) {
706     layer_param->add_exclude()->CopyFrom(v1_layer_param.exclude(i));
707   }
708   if (v1_layer_param.has_type()) {
709     layer_param->set_type(UpgradeV1LayerType(v1_layer_param.type()));
710   }
711   for (int i = 0; i < v1_layer_param.blobs_size(); ++i) {
712     layer_param->add_blobs()->CopyFrom(v1_layer_param.blobs(i));
713   }
714   for (int i = 0; i < v1_layer_param.param_size(); ++i) {
715     while (layer_param->param_size() <= i) { layer_param->add_param(); }
716     layer_param->mutable_param(i)->set_name(v1_layer_param.param(i));
717   }
718   ParamSpec_DimCheckMode mode;
719   for (int i = 0; i < v1_layer_param.blob_share_mode_size(); ++i) {
720     while (layer_param->param_size() <= i) { layer_param->add_param(); }
721     switch (v1_layer_param.blob_share_mode(i)) {
722     case V1LayerParameter_DimCheckMode_STRICT:
723       mode = ParamSpec_DimCheckMode_STRICT;
724       break;
725     case V1LayerParameter_DimCheckMode_PERMISSIVE:
726       mode = ParamSpec_DimCheckMode_PERMISSIVE;
727       break;
728     default:
729       LOG(FATAL) << "Unknown blob_share_mode: "
730                  << v1_layer_param.blob_share_mode(i);
731       break;
732     }
733     layer_param->mutable_param(i)->set_share_mode(mode);
734   }
735   for (int i = 0; i < v1_layer_param.blobs_lr_size(); ++i) {
736     while (layer_param->param_size() <= i) { layer_param->add_param(); }
737     layer_param->mutable_param(i)->set_lr_mult(v1_layer_param.blobs_lr(i));
738   }
739   for (int i = 0; i < v1_layer_param.weight_decay_size(); ++i) {
740     while (layer_param->param_size() <= i) { layer_param->add_param(); }
741     layer_param->mutable_param(i)->set_decay_mult(
742         v1_layer_param.weight_decay(i));
743   }
744   for (int i = 0; i < v1_layer_param.loss_weight_size(); ++i) {
745     layer_param->add_loss_weight(v1_layer_param.loss_weight(i));
746   }
747   if (v1_layer_param.has_accuracy_param()) {
748     layer_param->mutable_accuracy_param()->CopyFrom(
749         v1_layer_param.accuracy_param());
750   }
751   if (v1_layer_param.has_argmax_param()) {
752     layer_param->mutable_argmax_param()->CopyFrom(
753         v1_layer_param.argmax_param());
754   }
755   if (v1_layer_param.has_concat_param()) {
756     layer_param->mutable_concat_param()->CopyFrom(
757         v1_layer_param.concat_param());
758   }
759   if (v1_layer_param.has_contrastive_loss_param()) {
760     layer_param->mutable_contrastive_loss_param()->CopyFrom(
761         v1_layer_param.contrastive_loss_param());
762   }
763   if (v1_layer_param.has_convolution_param()) {
764     layer_param->mutable_convolution_param()->CopyFrom(
765         v1_layer_param.convolution_param());
766   }
767   if (v1_layer_param.has_data_param()) {
768     layer_param->mutable_data_param()->CopyFrom(
769         v1_layer_param.data_param());
770   }
771   if (v1_layer_param.has_dropout_param()) {
772     layer_param->mutable_dropout_param()->CopyFrom(
773         v1_layer_param.dropout_param());
774   }
775   if (v1_layer_param.has_dummy_data_param()) {
776     layer_param->mutable_dummy_data_param()->CopyFrom(
777         v1_layer_param.dummy_data_param());
778   }
779   if (v1_layer_param.has_eltwise_param()) {
780     layer_param->mutable_eltwise_param()->CopyFrom(
781         v1_layer_param.eltwise_param());
782   }
783   if (v1_layer_param.has_exp_param()) {
784     layer_param->mutable_exp_param()->CopyFrom(
785         v1_layer_param.exp_param());
786   }
787   if (v1_layer_param.has_hdf5_data_param()) {
788     layer_param->mutable_hdf5_data_param()->CopyFrom(
789         v1_layer_param.hdf5_data_param());
790   }
791   if (v1_layer_param.has_hdf5_output_param()) {
792     layer_param->mutable_hdf5_output_param()->CopyFrom(
793         v1_layer_param.hdf5_output_param());
794   }
795   if (v1_layer_param.has_hinge_loss_param()) {
796     layer_param->mutable_hinge_loss_param()->CopyFrom(
797         v1_layer_param.hinge_loss_param());
798   }
799   if (v1_layer_param.has_image_data_param()) {
800     layer_param->mutable_image_data_param()->CopyFrom(
801         v1_layer_param.image_data_param());
802   }
803   if (v1_layer_param.has_infogain_loss_param()) {
804     layer_param->mutable_infogain_loss_param()->CopyFrom(
805         v1_layer_param.infogain_loss_param());
806   }
807   if (v1_layer_param.has_inner_product_param()) {
808     layer_param->mutable_inner_product_param()->CopyFrom(
809         v1_layer_param.inner_product_param());
810   }
811   if (v1_layer_param.has_lrn_param()) {
812     layer_param->mutable_lrn_param()->CopyFrom(
813         v1_layer_param.lrn_param());
814   }
815   if (v1_layer_param.has_memory_data_param()) {
816     layer_param->mutable_memory_data_param()->CopyFrom(
817         v1_layer_param.memory_data_param());
818   }
819   if (v1_layer_param.has_mvn_param()) {
820     layer_param->mutable_mvn_param()->CopyFrom(
821         v1_layer_param.mvn_param());
822   }
823   if (v1_layer_param.has_pooling_param()) {
824     layer_param->mutable_pooling_param()->CopyFrom(
825         v1_layer_param.pooling_param());
826   }
827   if (v1_layer_param.has_power_param()) {
828     layer_param->mutable_power_param()->CopyFrom(
829         v1_layer_param.power_param());
830   }
831   if (v1_layer_param.has_relu_param()) {
832     layer_param->mutable_relu_param()->CopyFrom(
833         v1_layer_param.relu_param());
834   }
835   if (v1_layer_param.has_sigmoid_param()) {
836     layer_param->mutable_sigmoid_param()->CopyFrom(
837         v1_layer_param.sigmoid_param());
838   }
839   if (v1_layer_param.has_softmax_param()) {
840     layer_param->mutable_softmax_param()->CopyFrom(
841         v1_layer_param.softmax_param());
842   }
843   if (v1_layer_param.has_slice_param()) {
844     layer_param->mutable_slice_param()->CopyFrom(
845         v1_layer_param.slice_param());
846   }
847   if (v1_layer_param.has_tanh_param()) {
848     layer_param->mutable_tanh_param()->CopyFrom(
849         v1_layer_param.tanh_param());
850   }
851   if (v1_layer_param.has_threshold_param()) {
852     layer_param->mutable_threshold_param()->CopyFrom(
853         v1_layer_param.threshold_param());
854   }
855   if (v1_layer_param.has_window_data_param()) {
856     layer_param->mutable_window_data_param()->CopyFrom(
857         v1_layer_param.window_data_param());
858   }
859   if (v1_layer_param.has_transform_param()) {
860     layer_param->mutable_transform_param()->CopyFrom(
861         v1_layer_param.transform_param());
862   }
863   if (v1_layer_param.has_loss_param()) {
864     layer_param->mutable_loss_param()->CopyFrom(
865         v1_layer_param.loss_param());
866   }
867   if (v1_layer_param.has_layer()) {
868     LOG(ERROR) << "Input NetParameter has V0 layer -- ignoring.";
869     is_fully_compatible = false;
870   }
871   return is_fully_compatible;
872 }
873
874 const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type) {
875   switch (type) {
876   case V1LayerParameter_LayerType_NONE:
877     return "";
878   case V1LayerParameter_LayerType_ABSVAL:
879     return "AbsVal";
880   case V1LayerParameter_LayerType_ACCURACY:
881     return "Accuracy";
882   case V1LayerParameter_LayerType_ARGMAX:
883     return "ArgMax";
884   case V1LayerParameter_LayerType_BNLL:
885     return "BNLL";
886   case V1LayerParameter_LayerType_CONCAT:
887     return "Concat";
888   case V1LayerParameter_LayerType_CONTRASTIVE_LOSS:
889     return "ContrastiveLoss";
890   case V1LayerParameter_LayerType_CONVOLUTION:
891     return "Convolution";
892   case V1LayerParameter_LayerType_DECONVOLUTION:
893     return "Deconvolution";
894   case V1LayerParameter_LayerType_DATA:
895     return "Data";
896   case V1LayerParameter_LayerType_DROPOUT:
897     return "Dropout";
898   case V1LayerParameter_LayerType_DUMMY_DATA:
899     return "DummyData";
900   case V1LayerParameter_LayerType_EUCLIDEAN_LOSS:
901     return "EuclideanLoss";
902   case V1LayerParameter_LayerType_ELTWISE:
903     return "Eltwise";
904   case V1LayerParameter_LayerType_EXP:
905     return "Exp";
906   case V1LayerParameter_LayerType_FLATTEN:
907     return "Flatten";
908   case V1LayerParameter_LayerType_HDF5_DATA:
909     return "HDF5Data";
910   case V1LayerParameter_LayerType_HDF5_OUTPUT:
911     return "HDF5Output";
912   case V1LayerParameter_LayerType_HINGE_LOSS:
913     return "HingeLoss";
914   case V1LayerParameter_LayerType_IM2COL:
915     return "Im2col";
916   case V1LayerParameter_LayerType_IMAGE_DATA:
917     return "ImageData";
918   case V1LayerParameter_LayerType_INFOGAIN_LOSS:
919     return "InfogainLoss";
920   case V1LayerParameter_LayerType_INNER_PRODUCT:
921     return "InnerProduct";
922   case V1LayerParameter_LayerType_LRN:
923     return "LRN";
924   case V1LayerParameter_LayerType_MEMORY_DATA:
925     return "MemoryData";
926   case V1LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS:
927     return "MultinomialLogisticLoss";
928   case V1LayerParameter_LayerType_MVN:
929     return "MVN";
930   case V1LayerParameter_LayerType_POOLING:
931     return "Pooling";
932   case V1LayerParameter_LayerType_POWER:
933     return "Power";
934   case V1LayerParameter_LayerType_RELU:
935     return "ReLU";
936   case V1LayerParameter_LayerType_SIGMOID:
937     return "Sigmoid";
938   case V1LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS:
939     return "SigmoidCrossEntropyLoss";
940   case V1LayerParameter_LayerType_SILENCE:
941     return "Silence";
942   case V1LayerParameter_LayerType_SOFTMAX:
943     return "Softmax";
944   case V1LayerParameter_LayerType_SOFTMAX_LOSS:
945     return "SoftmaxWithLoss";
946   case V1LayerParameter_LayerType_SPLIT:
947     return "Split";
948   case V1LayerParameter_LayerType_SLICE:
949     return "Slice";
950   case V1LayerParameter_LayerType_TANH:
951     return "TanH";
952   case V1LayerParameter_LayerType_WINDOW_DATA:
953     return "WindowData";
954   case V1LayerParameter_LayerType_THRESHOLD:
955     return "Threshold";
956   default:
957     LOG(FATAL) << "Unknown V1LayerParameter layer type: " << type;
958     return "";
959   }
960 }
961
962 bool NetNeedsInputUpgrade(const NetParameter& net_param) {
963   return net_param.input_size() > 0;
964 }
965
966 void UpgradeNetInput(NetParameter* net_param) {
967   // Collect inputs and convert to Input layer definitions.
968   // If the NetParameter holds an input alone, without shape/dim, then
969   // it's a legacy caffemodel and simply stripping the input field is enough.
970   bool has_shape = net_param->input_shape_size() > 0;
971   bool has_dim = net_param->input_dim_size() > 0;
972   if (has_shape || has_dim) {
973     LayerParameter* layer_param = net_param->add_layer();
974     layer_param->set_name("input");
975     layer_param->set_type("Input");
976     InputParameter* input_param = layer_param->mutable_input_param();
977     // Convert input fields into a layer.
978     for (int i = 0; i < net_param->input_size(); ++i) {
979       layer_param->add_top(net_param->input(i));
980       if (has_shape) {
981         input_param->add_shape()->CopyFrom(net_param->input_shape(i));
982       } else {
983         // Turn legacy input dimensions into shape.
984         BlobShape* shape = input_param->add_shape();
985         int first_dim = i*4;
986         int last_dim = first_dim + 4;
987         for (int j = first_dim; j < last_dim; j++) {
988           shape->add_dim(net_param->input_dim(j));
989         }
990       }
991     }
992     // Swap input layer to beginning of net to satisfy layer dependencies.
993     for (int i = net_param->layer_size() - 1; i > 0; --i) {
994       net_param->mutable_layer(i-1)->Swap(net_param->mutable_layer(i));
995     }
996   }
997   // Clear inputs.
998   net_param->clear_input();
999   net_param->clear_input_shape();
1000   net_param->clear_input_dim();
1001 }
1002
1003 bool NetNeedsBatchNormUpgrade(const NetParameter& net_param) {
1004   for (int i = 0; i < net_param.layer_size(); ++i) {
1005     // Check if BatchNorm layers declare three parameters, as required by
1006     // the previous BatchNorm layer definition.
1007     if (net_param.layer(i).type() == "BatchNorm"
1008         && net_param.layer(i).param_size() == 3) {
1009       return true;
1010     }
1011   }
1012   return false;
1013 }
1014
1015 void UpgradeNetBatchNorm(NetParameter* net_param) {
1016   for (int i = 0; i < net_param->layer_size(); ++i) {
1017     // Check if BatchNorm layers declare three parameters, as required by
1018     // the previous BatchNorm layer definition.
1019     if (net_param->layer(i).type() == "BatchNorm"
1020         && net_param->layer(i).param_size() == 3) {
1021       // set lr_mult and decay_mult to zero. leave all other param intact.
1022       for (int ip = 0; ip < net_param->layer(i).param_size(); ip++) {
1023         ParamSpec* fixed_param_spec =
1024           net_param->mutable_layer(i)->mutable_param(ip);
1025         fixed_param_spec->set_lr_mult(0.f);
1026         fixed_param_spec->set_decay_mult(0.f);
1027       }
1028     }
1029   }
1030 }
1031
1032 // Return true iff the solver contains any old solver_type specified as enums
1033 bool SolverNeedsTypeUpgrade(const SolverParameter& solver_param) {
1034   if (solver_param.has_solver_type()) {
1035     return true;
1036   }
1037   return false;
1038 }
1039
1040 bool UpgradeSolverType(SolverParameter* solver_param) {
1041   CHECK(!solver_param->has_solver_type() || !solver_param->has_type())
1042       << "Failed to upgrade solver: old solver_type field (enum) and new type "
1043       << "field (string) cannot be both specified in solver proto text.";
1044   if (solver_param->has_solver_type()) {
1045     string type;
1046     switch (solver_param->solver_type()) {
1047     case SolverParameter_SolverType_SGD:
1048       type = "SGD";
1049       break;
1050     case SolverParameter_SolverType_NESTEROV:
1051       type = "Nesterov";
1052       break;
1053     case SolverParameter_SolverType_ADAGRAD:
1054       type = "AdaGrad";
1055       break;
1056     case SolverParameter_SolverType_RMSPROP:
1057       type = "RMSProp";
1058       break;
1059     case SolverParameter_SolverType_ADADELTA:
1060       type = "AdaDelta";
1061       break;
1062     case SolverParameter_SolverType_ADAM:
1063       type = "Adam";
1064       break;
1065     default:
1066       LOG(FATAL) << "Unknown SolverParameter solver_type: " << type;
1067     }
1068     solver_param->set_type(type);
1069     solver_param->clear_solver_type();
1070   } else {
1071     LOG(ERROR) << "Warning: solver type already up to date. ";
1072     return false;
1073   }
1074   return true;
1075 }
1076
1077 // Check for deprecations and upgrade the SolverParameter as needed.
1078 bool UpgradeSolverAsNeeded(const string& param_file, SolverParameter* param) {
1079   bool success = true;
1080   // Try to upgrade old style solver_type enum fields into new string type
1081   if (SolverNeedsTypeUpgrade(*param)) {
1082     LOG(INFO) << "Attempting to upgrade input file specified using deprecated "
1083               << "'solver_type' field (enum)': " << param_file;
1084     if (!UpgradeSolverType(param)) {
1085       success = false;
1086       LOG(ERROR) << "Warning: had one or more problems upgrading "
1087                  << "SolverType (see above).";
1088     } else {
1089       LOG(INFO) << "Successfully upgraded file specified using deprecated "
1090                 << "'solver_type' field (enum) to 'type' field (string).";
1091       LOG(WARNING) << "Note that future Caffe releases will only support "
1092                    << "'type' field (string) for a solver's type.";
1093     }
1094   }
1095   return success;
1096 }
1097
1098 // Read parameters from a file into a SolverParameter proto message.
1099 void ReadSolverParamsFromTextFileOrDie(const string& param_file,
1100                                        SolverParameter* param) {
1101   CHECK(ReadProtoFromTextFile(param_file, param))
1102       << "Failed to parse SolverParameter file: " << param_file;
1103   UpgradeSolverAsNeeded(param_file, param);
1104 }
1105
1106 }  // namespace caffe