#include #include "caffe/filler.hpp" #include "caffe/layers/dummy_data_layer.hpp" namespace caffe { template void DummyDataLayer::LayerSetUp(const vector*>& bottom, const vector*>& top) { const int num_top = top.size(); const DummyDataParameter& param = this->layer_param_.dummy_data_param(); const int num_data_filler = param.data_filler_size(); CHECK(num_data_filler == 0 || num_data_filler == 1 || num_data_filler == num_top) << "Number of data fillers must be 0, 1 or equal to the number of tops: " << num_top << "; you specified " << num_data_filler << " data fillers."; const bool legacy_dims = param.num_size() || param.channels_size() || param.height_size() || param.width_size(); if (legacy_dims) { CHECK_EQ(0, param.shape_size()) << "Both shape and legacy fields were specified"; // Using deprecated 4D output dim specifiers. CHECK(param.num_size() == 1 || param.num_size() == num_top) << "Must specify 'num' once, or once per top blob " << "(" << num_top << "); specified " << param.num_size() << "."; CHECK(param.channels_size() == 1 || param.channels_size() == num_top) << "Must specify 'channels' once, or once per top blob " << "(" << num_top << "); specified " << param.channels_size() << "."; CHECK(param.height_size() == 1 || param.height_size() == num_top) << "Must specify 'height' once, or once per top blob " << "(" << num_top << "); specified " << param.height_size() << "."; CHECK(param.width_size() == 1 || param.width_size() == num_top) << "Must specify 'width' once, or once per top blob " << "(" << num_top << "); specified " << param.width_size() << "."; } else { CHECK(param.shape_size() == 1 || param.shape_size() == num_top) << "Must specify 'shape' once, or once per top blob " << "(" << num_top << "); specified " << param.shape_size() << "."; } // refill_[i] tells Forward i whether or not to actually refill top Blob i. // If refill_[i] is false, Forward does nothing for Blob i. We use this to // avoid wastefully refilling "constant" Blobs in every forward pass. // We first fill refill_ in with the INVERSE of its final values. // The first time we run Forward from the LayerSetUp method, we'll fill only // Blobs for which refill_ is normally false. These Blobs will never be // filled again. refill_.clear(); fillers_.clear(); if (num_data_filler <= 1) { FillerParameter filler_param; if (num_data_filler == 0) { filler_param.set_type("constant"); filler_param.set_value(0); } else { filler_param.CopyFrom(param.data_filler(0)); } // Refill on each iteration iff not using a constant filler, // but use the inverse of this rule for the first run. refill_.resize(1); refill_[0] = (strcmp(filler_param.type().c_str(), "constant") == 0); fillers_.resize(1); fillers_[0].reset(GetFiller(filler_param)); } else { refill_.resize(num_top); fillers_.resize(num_top); for (int i = 0; i < num_top; ++i) { fillers_[i].reset(GetFiller(param.data_filler(i))); // Refill on each iteration iff not using a constant filler, // but use the inverse of this rule for the first run. refill_[i] = (strcmp(param.data_filler(i).type().c_str(), "constant") == 0); } } for (int i = 0; i < num_top; ++i) { if (legacy_dims) { const int num = (param.num_size() == 1) ? param.num(0) : param.num(i); const int channels = (param.channels_size() == 1) ? param.channels(0) : param.channels(i); const int height = (param.height_size() == 1) ? param.height(0) : param.height(i); const int width = (param.width_size() == 1) ? param.width(0) : param.width(i); top[i]->Reshape(num, channels, height, width); } else { const int shape_index = (param.shape_size() == 1) ? 0 : i; top[i]->Reshape(param.shape(shape_index)); } } // Run Forward once, with refill_ inverted, to fill the constant Blobs. this->Forward(bottom, top); // Invert the inverted refill_ values to refill the desired (non-constant) // Blobs in every usual forward pass. for (int i = 0; i < refill_.size(); ++i) { refill_[i] = !refill_[i]; } } template void DummyDataLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { for (int i = 0; i < top.size(); ++i) { const int filler_id = (fillers_.size() > 1) ? i : 0; if (refill_[filler_id]) { fillers_[filler_id]->Fill(top[i]); } } } INSTANTIATE_CLASS(DummyDataLayer); REGISTER_LAYER_CLASS(DummyData); } // namespace caffe