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>
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"
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);
21 bool UpgradeNetAsNeeded(const string& param_file, NetParameter* param) {
23 if (NetNeedsV0ToV1Upgrade(*param)) {
24 // NetParameter was specified using the old style (V0LayerParameter); try to
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)) {
31 LOG(ERROR) << "Warning: had one or more problems upgrading "
32 << "V0NetParameter to NetParameter (see above); continuing anyway.";
34 LOG(INFO) << "Successfully upgraded file specified using deprecated "
35 << "V0LayerParameter";
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.";
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.";
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)) {
58 LOG(ERROR) << "Warning: had one or more problems upgrading "
59 << "V1LayerParameter (see above); continuing anyway.";
61 LOG(INFO) << "Successfully upgraded file specified using deprecated "
62 << "V1LayerParameter";
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 "
72 LOG(WARNING) << "Note that future Caffe releases will only support "
73 << "input layers and not input fields.";
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 "
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);
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);
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()) {
109 bool NetNeedsV1ToV2Upgrade(const NetParameter& net_param) {
110 return net_param.layers_size() > 0;
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;
121 if (v0_net_param.has_name()) {
122 net_param->set_name(v0_net_param.name());
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());
128 for (int i = 0; i < v0_net_param.input_size(); ++i) {
129 net_param->add_input(v0_net_param.input(i));
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));
134 if (v0_net_param.has_force_backward()) {
135 net_param->set_force_backward(v0_net_param.force_backward());
137 return is_fully_compatible;
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;
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);
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;
165 const int top_idx = blob_name_to_last_top_idx[blob_name];
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));
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;
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));
206 for (int i = 0; i < v0_layer_connection.top_size(); ++i) {
207 layer_param->add_top(v0_layer_connection.top(i));
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());
214 const string& type = v0_layer_param.type();
215 if (v0_layer_param.has_type()) {
216 layer_param->set_type(UpgradeV0LayerType(type));
218 for (int i = 0; i < v0_layer_param.blobs_size(); ++i) {
219 layer_param->add_blobs()->CopyFrom(v0_layer_param.blobs(i));
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));
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));
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());
235 LOG(ERROR) << "Unknown parameter num_output for layer type " << type;
236 is_fully_compatible = false;
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());
247 LOG(ERROR) << "Unknown parameter biasterm for layer type " << type;
248 is_fully_compatible = false;
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());
259 LOG(ERROR) << "Unknown parameter weight_filler for layer type " << type;
260 is_fully_compatible = false;
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());
271 LOG(ERROR) << "Unknown parameter bias_filler for layer type " << type;
272 is_fully_compatible = false;
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());
281 LOG(ERROR) << "Unknown parameter pad for layer type " << type;
282 is_fully_compatible = false;
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());
293 LOG(ERROR) << "Unknown parameter kernelsize for layer type " << type;
294 is_fully_compatible = false;
297 if (v0_layer_param.has_group()) {
298 if (type == "conv") {
299 layer_param->mutable_convolution_param()->set_group(
300 v0_layer_param.group());
302 LOG(ERROR) << "Unknown parameter group for layer type " << type;
303 is_fully_compatible = false;
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());
314 LOG(ERROR) << "Unknown parameter stride for layer type " << type;
315 is_fully_compatible = false;
318 if (v0_layer_param.has_pool()) {
319 if (type == "pool") {
320 V0LayerParameter_PoolMethod pool = v0_layer_param.pool();
322 case V0LayerParameter_PoolMethod_MAX:
323 layer_param->mutable_pooling_param()->set_pool(
324 PoolingParameter_PoolMethod_MAX);
326 case V0LayerParameter_PoolMethod_AVE:
327 layer_param->mutable_pooling_param()->set_pool(
328 PoolingParameter_PoolMethod_AVE);
330 case V0LayerParameter_PoolMethod_STOCHASTIC:
331 layer_param->mutable_pooling_param()->set_pool(
332 PoolingParameter_PoolMethod_STOCHASTIC);
335 LOG(ERROR) << "Unknown pool method " << pool;
336 is_fully_compatible = false;
339 LOG(ERROR) << "Unknown parameter pool for layer type " << type;
340 is_fully_compatible = false;
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());
348 LOG(ERROR) << "Unknown parameter dropout_ratio for layer type " << type;
349 is_fully_compatible = false;
352 if (v0_layer_param.has_local_size()) {
354 layer_param->mutable_lrn_param()->set_local_size(
355 v0_layer_param.local_size());
357 LOG(ERROR) << "Unknown parameter local_size for layer type " << type;
358 is_fully_compatible = false;
361 if (v0_layer_param.has_alpha()) {
363 layer_param->mutable_lrn_param()->set_alpha(v0_layer_param.alpha());
365 LOG(ERROR) << "Unknown parameter alpha for layer type " << type;
366 is_fully_compatible = false;
369 if (v0_layer_param.has_beta()) {
371 layer_param->mutable_lrn_param()->set_beta(v0_layer_param.beta());
373 LOG(ERROR) << "Unknown parameter beta for layer type " << type;
374 is_fully_compatible = false;
377 if (v0_layer_param.has_k()) {
379 layer_param->mutable_lrn_param()->set_k(v0_layer_param.k());
381 LOG(ERROR) << "Unknown parameter k for layer type " << type;
382 is_fully_compatible = false;
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());
401 LOG(ERROR) << "Unknown parameter source for layer type " << type;
402 is_fully_compatible = false;
405 if (v0_layer_param.has_scale()) {
406 layer_param->mutable_transform_param()->
407 set_scale(v0_layer_param.scale());
409 if (v0_layer_param.has_meanfile()) {
410 layer_param->mutable_transform_param()->
411 set_mean_file(v0_layer_param.meanfile());
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());
427 LOG(ERROR) << "Unknown parameter batchsize for layer type " << type;
428 is_fully_compatible = false;
431 if (v0_layer_param.has_cropsize()) {
432 layer_param->mutable_transform_param()->
433 set_crop_size(v0_layer_param.cropsize());
435 if (v0_layer_param.has_mirror()) {
436 layer_param->mutable_transform_param()->
437 set_mirror(v0_layer_param.mirror());
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());
447 LOG(ERROR) << "Unknown parameter rand_skip for layer type " << type;
448 is_fully_compatible = false;
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());
456 LOG(ERROR) << "Unknown parameter shuffle for layer type " << type;
457 is_fully_compatible = false;
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());
465 LOG(ERROR) << "Unknown parameter new_height for layer type " << type;
466 is_fully_compatible = false;
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());
474 LOG(ERROR) << "Unknown parameter new_width for layer type " << type;
475 is_fully_compatible = false;
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());
483 LOG(ERROR) << "Unknown parameter concat_dim for layer type " << type;
484 is_fully_compatible = false;
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());
492 LOG(ERROR) << "Unknown parameter det_fg_threshold for layer type "
494 is_fully_compatible = false;
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());
502 LOG(ERROR) << "Unknown parameter det_bg_threshold for layer type "
504 is_fully_compatible = false;
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());
512 LOG(ERROR) << "Unknown parameter det_fg_fraction for layer type "
514 is_fully_compatible = false;
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());
522 LOG(ERROR) << "Unknown parameter det_context_pad for layer type "
524 is_fully_compatible = false;
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());
532 LOG(ERROR) << "Unknown parameter det_crop_mode for layer type "
534 is_fully_compatible = false;
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());
542 LOG(ERROR) << "Unknown parameter hdf5_output_param for layer type "
544 is_fully_compatible = false;
548 return is_fully_compatible;
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;
601 LOG(FATAL) << "Unknown layer name: " << type;
602 return V1LayerParameter_LayerType_NONE;
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; }
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; }
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; }
633 #define CONVERT_LAYER_TRANSFORM_PARAM(TYPE, Name, param_name) \
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(); \
644 if (layer_param->has_mean_file()) { \
645 transform_param->set_mean_file(layer_param->mean_file()); \
646 layer_param->clear_mean_file(); \
648 if (layer_param->has_crop_size()) { \
649 transform_param->set_crop_size(layer_param->crop_size()); \
650 layer_param->clear_crop_size(); \
652 if (layer_param->has_mirror()) { \
653 transform_param->set_mirror(layer_param->mirror()); \
654 layer_param->clear_mirror(); \
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);
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.";
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;
686 return is_fully_compatible;
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));
696 for (int i = 0; i < v1_layer_param.top_size(); ++i) {
697 layer_param->add_top(v1_layer_param.top(i));
699 if (v1_layer_param.has_name()) {
700 layer_param->set_name(v1_layer_param.name());
702 for (int i = 0; i < v1_layer_param.include_size(); ++i) {
703 layer_param->add_include()->CopyFrom(v1_layer_param.include(i));
705 for (int i = 0; i < v1_layer_param.exclude_size(); ++i) {
706 layer_param->add_exclude()->CopyFrom(v1_layer_param.exclude(i));
708 if (v1_layer_param.has_type()) {
709 layer_param->set_type(UpgradeV1LayerType(v1_layer_param.type()));
711 for (int i = 0; i < v1_layer_param.blobs_size(); ++i) {
712 layer_param->add_blobs()->CopyFrom(v1_layer_param.blobs(i));
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));
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;
725 case V1LayerParameter_DimCheckMode_PERMISSIVE:
726 mode = ParamSpec_DimCheckMode_PERMISSIVE;
729 LOG(FATAL) << "Unknown blob_share_mode: "
730 << v1_layer_param.blob_share_mode(i);
733 layer_param->mutable_param(i)->set_share_mode(mode);
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));
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));
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));
747 if (v1_layer_param.has_accuracy_param()) {
748 layer_param->mutable_accuracy_param()->CopyFrom(
749 v1_layer_param.accuracy_param());
751 if (v1_layer_param.has_argmax_param()) {
752 layer_param->mutable_argmax_param()->CopyFrom(
753 v1_layer_param.argmax_param());
755 if (v1_layer_param.has_concat_param()) {
756 layer_param->mutable_concat_param()->CopyFrom(
757 v1_layer_param.concat_param());
759 if (v1_layer_param.has_contrastive_loss_param()) {
760 layer_param->mutable_contrastive_loss_param()->CopyFrom(
761 v1_layer_param.contrastive_loss_param());
763 if (v1_layer_param.has_convolution_param()) {
764 layer_param->mutable_convolution_param()->CopyFrom(
765 v1_layer_param.convolution_param());
767 if (v1_layer_param.has_data_param()) {
768 layer_param->mutable_data_param()->CopyFrom(
769 v1_layer_param.data_param());
771 if (v1_layer_param.has_dropout_param()) {
772 layer_param->mutable_dropout_param()->CopyFrom(
773 v1_layer_param.dropout_param());
775 if (v1_layer_param.has_dummy_data_param()) {
776 layer_param->mutable_dummy_data_param()->CopyFrom(
777 v1_layer_param.dummy_data_param());
779 if (v1_layer_param.has_eltwise_param()) {
780 layer_param->mutable_eltwise_param()->CopyFrom(
781 v1_layer_param.eltwise_param());
783 if (v1_layer_param.has_exp_param()) {
784 layer_param->mutable_exp_param()->CopyFrom(
785 v1_layer_param.exp_param());
787 if (v1_layer_param.has_hdf5_data_param()) {
788 layer_param->mutable_hdf5_data_param()->CopyFrom(
789 v1_layer_param.hdf5_data_param());
791 if (v1_layer_param.has_hdf5_output_param()) {
792 layer_param->mutable_hdf5_output_param()->CopyFrom(
793 v1_layer_param.hdf5_output_param());
795 if (v1_layer_param.has_hinge_loss_param()) {
796 layer_param->mutable_hinge_loss_param()->CopyFrom(
797 v1_layer_param.hinge_loss_param());
799 if (v1_layer_param.has_image_data_param()) {
800 layer_param->mutable_image_data_param()->CopyFrom(
801 v1_layer_param.image_data_param());
803 if (v1_layer_param.has_infogain_loss_param()) {
804 layer_param->mutable_infogain_loss_param()->CopyFrom(
805 v1_layer_param.infogain_loss_param());
807 if (v1_layer_param.has_inner_product_param()) {
808 layer_param->mutable_inner_product_param()->CopyFrom(
809 v1_layer_param.inner_product_param());
811 if (v1_layer_param.has_lrn_param()) {
812 layer_param->mutable_lrn_param()->CopyFrom(
813 v1_layer_param.lrn_param());
815 if (v1_layer_param.has_memory_data_param()) {
816 layer_param->mutable_memory_data_param()->CopyFrom(
817 v1_layer_param.memory_data_param());
819 if (v1_layer_param.has_mvn_param()) {
820 layer_param->mutable_mvn_param()->CopyFrom(
821 v1_layer_param.mvn_param());
823 if (v1_layer_param.has_pooling_param()) {
824 layer_param->mutable_pooling_param()->CopyFrom(
825 v1_layer_param.pooling_param());
827 if (v1_layer_param.has_power_param()) {
828 layer_param->mutable_power_param()->CopyFrom(
829 v1_layer_param.power_param());
831 if (v1_layer_param.has_relu_param()) {
832 layer_param->mutable_relu_param()->CopyFrom(
833 v1_layer_param.relu_param());
835 if (v1_layer_param.has_sigmoid_param()) {
836 layer_param->mutable_sigmoid_param()->CopyFrom(
837 v1_layer_param.sigmoid_param());
839 if (v1_layer_param.has_softmax_param()) {
840 layer_param->mutable_softmax_param()->CopyFrom(
841 v1_layer_param.softmax_param());
843 if (v1_layer_param.has_slice_param()) {
844 layer_param->mutable_slice_param()->CopyFrom(
845 v1_layer_param.slice_param());
847 if (v1_layer_param.has_tanh_param()) {
848 layer_param->mutable_tanh_param()->CopyFrom(
849 v1_layer_param.tanh_param());
851 if (v1_layer_param.has_threshold_param()) {
852 layer_param->mutable_threshold_param()->CopyFrom(
853 v1_layer_param.threshold_param());
855 if (v1_layer_param.has_window_data_param()) {
856 layer_param->mutable_window_data_param()->CopyFrom(
857 v1_layer_param.window_data_param());
859 if (v1_layer_param.has_transform_param()) {
860 layer_param->mutable_transform_param()->CopyFrom(
861 v1_layer_param.transform_param());
863 if (v1_layer_param.has_loss_param()) {
864 layer_param->mutable_loss_param()->CopyFrom(
865 v1_layer_param.loss_param());
867 if (v1_layer_param.has_layer()) {
868 LOG(ERROR) << "Input NetParameter has V0 layer -- ignoring.";
869 is_fully_compatible = false;
871 return is_fully_compatible;
874 const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type) {
876 case V1LayerParameter_LayerType_NONE:
878 case V1LayerParameter_LayerType_ABSVAL:
880 case V1LayerParameter_LayerType_ACCURACY:
882 case V1LayerParameter_LayerType_ARGMAX:
884 case V1LayerParameter_LayerType_BNLL:
886 case V1LayerParameter_LayerType_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:
896 case V1LayerParameter_LayerType_DROPOUT:
898 case V1LayerParameter_LayerType_DUMMY_DATA:
900 case V1LayerParameter_LayerType_EUCLIDEAN_LOSS:
901 return "EuclideanLoss";
902 case V1LayerParameter_LayerType_ELTWISE:
904 case V1LayerParameter_LayerType_EXP:
906 case V1LayerParameter_LayerType_FLATTEN:
908 case V1LayerParameter_LayerType_HDF5_DATA:
910 case V1LayerParameter_LayerType_HDF5_OUTPUT:
912 case V1LayerParameter_LayerType_HINGE_LOSS:
914 case V1LayerParameter_LayerType_IM2COL:
916 case V1LayerParameter_LayerType_IMAGE_DATA:
918 case V1LayerParameter_LayerType_INFOGAIN_LOSS:
919 return "InfogainLoss";
920 case V1LayerParameter_LayerType_INNER_PRODUCT:
921 return "InnerProduct";
922 case V1LayerParameter_LayerType_LRN:
924 case V1LayerParameter_LayerType_MEMORY_DATA:
926 case V1LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS:
927 return "MultinomialLogisticLoss";
928 case V1LayerParameter_LayerType_MVN:
930 case V1LayerParameter_LayerType_POOLING:
932 case V1LayerParameter_LayerType_POWER:
934 case V1LayerParameter_LayerType_RELU:
936 case V1LayerParameter_LayerType_SIGMOID:
938 case V1LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS:
939 return "SigmoidCrossEntropyLoss";
940 case V1LayerParameter_LayerType_SILENCE:
942 case V1LayerParameter_LayerType_SOFTMAX:
944 case V1LayerParameter_LayerType_SOFTMAX_LOSS:
945 return "SoftmaxWithLoss";
946 case V1LayerParameter_LayerType_SPLIT:
948 case V1LayerParameter_LayerType_SLICE:
950 case V1LayerParameter_LayerType_TANH:
952 case V1LayerParameter_LayerType_WINDOW_DATA:
954 case V1LayerParameter_LayerType_THRESHOLD:
957 LOG(FATAL) << "Unknown V1LayerParameter layer type: " << type;
962 bool NetNeedsInputUpgrade(const NetParameter& net_param) {
963 return net_param.input_size() > 0;
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));
981 input_param->add_shape()->CopyFrom(net_param->input_shape(i));
983 // Turn legacy input dimensions into shape.
984 BlobShape* shape = input_param->add_shape();
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));
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));
998 net_param->clear_input();
999 net_param->clear_input_shape();
1000 net_param->clear_input_dim();
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) {
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);
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()) {
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()) {
1046 switch (solver_param->solver_type()) {
1047 case SolverParameter_SolverType_SGD:
1050 case SolverParameter_SolverType_NESTEROV:
1053 case SolverParameter_SolverType_ADAGRAD:
1056 case SolverParameter_SolverType_RMSPROP:
1059 case SolverParameter_SolverType_ADADELTA:
1062 case SolverParameter_SolverType_ADAM:
1066 LOG(FATAL) << "Unknown SolverParameter solver_type: " << type;
1068 solver_param->set_type(type);
1069 solver_param->clear_solver_type();
1071 LOG(ERROR) << "Warning: solver type already up to date. ";
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)) {
1086 LOG(ERROR) << "Warning: had one or more problems upgrading "
1087 << "SolverType (see above).";
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.";
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);
1106 } // namespace caffe