From 1b5ef7402d9e486f1c00af5e7f0e735633d94118 Mon Sep 17 00:00:00 2001 From: "R. Gokberk Cinbis" Date: Wed, 20 Aug 2014 07:53:31 +0300 Subject: [PATCH 001/798] Lock the mex file to avoid Matlab crashes. Commands like "clear all" and "clear function" causes segmentation faults or errors like these (especially after an 'init'): libprotobuf ERROR google/protobuf/descriptor_database.cc:57] File already exists in database: caffe/proto/caffe.proto libprotobuf FATAL google/protobuf/descriptor.cc:862] CHECK failed: generated_database_->Add(encoded_file_descriptor, size): [libprotobuf ERROR google/protobuf/message.cc:333] Type appears to be in generated pool but wasn't registered: caffe.LayerParameter Attempt to restart MATLAB? To avoid these, lock the the mex file. --- matlab/caffe/matcaffe.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/matlab/caffe/matcaffe.cpp b/matlab/caffe/matcaffe.cpp index 83786caed0d..db8896da6ae 100644 --- a/matlab/caffe/matcaffe.cpp +++ b/matlab/caffe/matcaffe.cpp @@ -372,6 +372,7 @@ static handler_registry handlers[] = { ** matlab entry point: caffe(api_command, arg1, arg2, ...) **/ void mexFunction(MEX_ARGS) { + mexLock(); // Avoid clearing the mex file. if (nrhs == 0) { LOG(ERROR) << "No API command given"; mexErrMsgTxt("An API command is requires"); From 03e0e01fce7361194b599c53c1f23d77cbb07086 Mon Sep 17 00:00:00 2001 From: qipeng Date: Tue, 16 Sep 2014 19:59:53 -0700 Subject: [PATCH 002/798] Display averaged loss over the last several iterations --- src/caffe/proto/caffe.proto | 4 +++- src/caffe/solver.cpp | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 493bfa7ab17..ba4c41cbf67 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -63,7 +63,7 @@ message NetParameter { // NOTE // Update the next available ID when you add a new SolverParameter field. // -// SolverParameter next available ID: 33 (last added: test_initialization) +// SolverParameter next available ID: 34 (last added: average_loss) message SolverParameter { ////////////////////////////////////////////////////////////////////////////// // Specifying the train and test networks @@ -113,6 +113,8 @@ message SolverParameter { // the number of iterations between displaying info. If display = 0, no info // will be displayed. optional int32 display = 6; + // Display the cost averaged over the last average_cost iterations + optional int32 average_loss = 33 [default = 1]; optional int32 max_iter = 7; // the maximum number of iterations optional string lr_policy = 8; // The learning rate decay policy. optional float gamma = 9; // The parameter to compute the learning rate. diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 0ea4edcf9b8..0810f487fab 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -169,6 +169,13 @@ void Solver::Solve(const char* resume_file) { // resume_file above. const int start_iter = iter_; + int average_loss = this->param_.average_loss(); + + CHECK_GE(average_loss, 1) << "average_cost should be non-negative."; + + vector losses; + Dtype smoothed_loss; + // For a network that is trained by the solver, no bottom or top vecs // should be given, and we will just provide dummy vecs. vector*> bottom_vec; @@ -187,8 +194,17 @@ void Solver::Solve(const char* resume_file) { const bool display = param_.display() && iter_ % param_.display() == 0; net_->set_debug_info(display && param_.debug_info()); Dtype loss = net_->ForwardBackward(bottom_vec); + if (losses.size() < average_loss) { + losses.push_back(loss); + int size = losses.size(); + smoothed_loss = (smoothed_loss * (size - 1) + loss) / size; + } else { + int idx = (iter_ - start_iter) % average_loss; + smoothed_loss += (loss - losses[idx]) / average_loss; + losses[idx] = loss; + } if (display) { - LOG(INFO) << "Iteration " << iter_ << ", loss = " << loss; + LOG(INFO) << "Iteration " << iter_ << ", loss = " << smoothed_loss; const vector*>& result = net_->output_blobs(); int score_index = 0; for (int j = 0; j < result.size(); ++j) { From 7a688c70f04498ee7cb34cbede2176800c11544d Mon Sep 17 00:00:00 2001 From: qipeng Date: Thu, 18 Sep 2014 15:13:44 -0700 Subject: [PATCH 003/798] fix warning --- src/caffe/solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 0810f487fab..cca32998d62 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -174,7 +174,7 @@ void Solver::Solve(const char* resume_file) { CHECK_GE(average_loss, 1) << "average_cost should be non-negative."; vector losses; - Dtype smoothed_loss; + Dtype smoothed_loss = 0; // For a network that is trained by the solver, no bottom or top vecs // should be given, and we will just provide dummy vecs. From 8fd17a32e45f4e9b01ea58e87514acefcde0b6f4 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Fri, 19 Sep 2014 12:38:39 -0700 Subject: [PATCH 004/798] fix cifar10 paths so they can be run from caffe root --- examples/cifar10/train_full.sh | 13 +++++++------ examples/cifar10/train_quick.sh | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/examples/cifar10/train_full.sh b/examples/cifar10/train_full.sh index 9dd9ad79822..4285a5d6468 100755 --- a/examples/cifar10/train_full.sh +++ b/examples/cifar10/train_full.sh @@ -1,15 +1,16 @@ #!/usr/bin/env sh -TOOLS=../../build/tools +TOOLS=./build/tools -$TOOLS/caffe train --solver=cifar10_full_solver.prototxt +$TOOLS/caffe train \ + --solver=examples/cifar10/cifar10_full_solver.prototxt # reduce learning rate by factor of 10 $TOOLS/caffe train \ - --solver=cifar10_full_solver_lr1.prototxt \ - --snapshot=cifar10_full_iter_60000.solverstate + --solver=examples/cifar10/cifar10_full_solver_lr1.prototxt \ + --snapshot=examples/cifar10/cifar10_full_iter_60000.solverstate # reduce learning rate by factor of 10 $TOOLS/caffe train \ - --solver=cifar10_full_solver_lr2.prototxt \ - --snapshot=cifar10_full_iter_65000.solverstate + --solver=examples/cifar10/cifar10_full_solver_lr2.prototxt \ + --snapshot=examples/cifar10/cifar10_full_iter_65000.solverstate diff --git a/examples/cifar10/train_quick.sh b/examples/cifar10/train_quick.sh index e348e12fd94..2830c40945c 100755 --- a/examples/cifar10/train_quick.sh +++ b/examples/cifar10/train_quick.sh @@ -1,10 +1,11 @@ #!/usr/bin/env sh -TOOLS=../../build/tools +TOOLS=./build/tools -$TOOLS/caffe.bin train --solver=cifar10_quick_solver.prototxt +$TOOLS/caffe train \ + --solver=examples/cifar10/cifar10_quick_solver.prototxt -# reduce learning rate by fctor of 10 after 8 epochs -$TOOLS/caffe.bin train \ - --solver=cifar10_quick_solver_lr1.prototxt \ - --snapshot=cifar10_quick_iter_4000.solverstate +# reduce learning rate by factor of 10 after 8 epochs +$TOOLS/caffe train \ + --solver=examples/cifar10/cifar10_quick_solver_lr1.prototxt \ + --snapshot=examples/cifar10/cifar10_quick_iter_4000.solverstate From 31326a111bcb5ac5a9adeec13cfe6330e78ef31e Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Fri, 19 Sep 2014 16:04:37 -0700 Subject: [PATCH 005/798] fix types of (Layer)SetUp, Reshape, Forward, and Backward calls Using the type vector* for outputs allows modification of the vector itself, while it is only okay to modify the blobs pointed to by the elements of the vector. Switching the types to const vector*>& makes them more correct. --- include/caffe/common_layers.hpp | 114 +++++++++--------- include/caffe/data_layers.hpp | 60 ++++----- include/caffe/layer.hpp | 51 ++++---- include/caffe/loss_layers.hpp | 74 ++++++------ include/caffe/neuron_layers.hpp | 98 +++++++-------- .../caffe/test/test_gradient_check_util.hpp | 85 ++++++------- include/caffe/util/device_alternate.hpp | 8 +- include/caffe/vision_layers.hpp | 76 ++++++------ src/caffe/layers/absval_layer.cpp | 16 +-- src/caffe/layers/absval_layer.cu | 12 +- src/caffe/layers/accuracy_layer.cpp | 10 +- src/caffe/layers/argmax_layer.cpp | 16 +-- src/caffe/layers/base_data_layer.cpp | 12 +- src/caffe/layers/base_data_layer.cu | 6 +- src/caffe/layers/bnll_layer.cpp | 12 +- src/caffe/layers/bnll_layer.cu | 12 +- src/caffe/layers/concat_layer.cpp | 26 ++-- src/caffe/layers/concat_layer.cu | 18 +-- src/caffe/layers/contrastive_loss_layer.cpp | 18 +-- src/caffe/layers/contrastive_loss_layer.cu | 16 +-- src/caffe/layers/conv_layer.cpp | 30 ++--- src/caffe/layers/conv_layer.cu | 18 +-- src/caffe/layers/cudnn_conv_layer.cpp | 4 +- src/caffe/layers/cudnn_conv_layer.cu | 10 +- src/caffe/layers/cudnn_pooling_layer.cpp | 4 +- src/caffe/layers/cudnn_pooling_layer.cu | 12 +- src/caffe/layers/cudnn_relu_layer.cpp | 4 +- src/caffe/layers/cudnn_relu_layer.cu | 10 +- src/caffe/layers/cudnn_sigmoid_layer.cpp | 4 +- src/caffe/layers/cudnn_sigmoid_layer.cu | 10 +- src/caffe/layers/cudnn_softmax_layer.cpp | 4 +- src/caffe/layers/cudnn_softmax_layer.cu | 10 +- src/caffe/layers/cudnn_tanh_layer.cpp | 4 +- src/caffe/layers/cudnn_tanh_layer.cu | 10 +- src/caffe/layers/data_layer.cpp | 14 +-- src/caffe/layers/dropout_layer.cpp | 14 +-- src/caffe/layers/dropout_layer.cu | 10 +- src/caffe/layers/dummy_data_layer.cpp | 12 +- src/caffe/layers/eltwise_layer.cpp | 28 ++--- src/caffe/layers/eltwise_layer.cu | 20 +-- src/caffe/layers/euclidean_loss_layer.cpp | 14 +-- src/caffe/layers/euclidean_loss_layer.cu | 12 +- src/caffe/layers/flatten_layer.cpp | 14 +-- src/caffe/layers/flatten_layer.cu | 8 +- src/caffe/layers/hdf5_data_layer.cpp | 22 ++-- src/caffe/layers/hdf5_data_layer.cu | 10 +- src/caffe/layers/hdf5_output_layer.cpp | 4 +- src/caffe/layers/hdf5_output_layer.cu | 4 +- src/caffe/layers/hinge_loss_layer.cpp | 14 +-- src/caffe/layers/im2col_layer.cpp | 18 +-- src/caffe/layers/im2col_layer.cu | 12 +- src/caffe/layers/image_data_layer.cpp | 14 +-- src/caffe/layers/infogain_loss_layer.cpp | 24 ++-- src/caffe/layers/inner_product_layer.cpp | 16 +-- src/caffe/layers/inner_product_layer.cu | 10 +- src/caffe/layers/loss_layer.cpp | 6 +- src/caffe/layers/lrn_layer.cpp | 56 ++++----- src/caffe/layers/lrn_layer.cu | 14 +-- src/caffe/layers/memory_data_layer.cpp | 12 +- .../multinomial_logistic_loss_layer.cpp | 20 +-- src/caffe/layers/mvn_layer.cpp | 20 +-- src/caffe/layers/mvn_layer.cu | 16 +-- src/caffe/layers/neuron_layer.cpp | 4 +- src/caffe/layers/pooling_layer.cpp | 40 +++--- src/caffe/layers/pooling_layer.cu | 16 +-- src/caffe/layers/power_layer.cpp | 14 +-- src/caffe/layers/power_layer.cu | 12 +- src/caffe/layers/relu_layer.cpp | 12 +- src/caffe/layers/relu_layer.cu | 12 +- .../sigmoid_cross_entropy_loss_layer.cpp | 24 ++-- .../sigmoid_cross_entropy_loss_layer.cu | 16 +-- src/caffe/layers/sigmoid_layer.cpp | 10 +- src/caffe/layers/sigmoid_layer.cu | 10 +- src/caffe/layers/silence_layer.cpp | 8 +- src/caffe/layers/silence_layer.cu | 10 +- src/caffe/layers/slice_layer.cpp | 58 ++++----- src/caffe/layers/slice_layer.cu | 18 +-- src/caffe/layers/softmax_layer.cpp | 16 +-- src/caffe/layers/softmax_layer.cu | 8 +- src/caffe/layers/softmax_loss_layer.cpp | 28 ++--- src/caffe/layers/softmax_loss_layer.cu | 4 +- src/caffe/layers/split_layer.cpp | 24 ++-- src/caffe/layers/split_layer.cu | 14 +-- src/caffe/layers/tanh_layer.cpp | 10 +- src/caffe/layers/tanh_layer.cu | 10 +- src/caffe/layers/threshold_layer.cpp | 6 +- src/caffe/layers/threshold_layer.cu | 4 +- src/caffe/layers/window_data_layer.cpp | 20 +-- src/caffe/net.cpp | 10 +- src/caffe/test/test_accuracy_layer.cpp | 12 +- src/caffe/test/test_argmax_layer.cpp | 20 +-- src/caffe/test/test_concat_layer.cpp | 12 +- .../test/test_contrastive_loss_layer.cpp | 14 +-- src/caffe/test/test_convolution_layer.cpp | 64 +++++----- src/caffe/test/test_data_layer.cpp | 24 ++-- src/caffe/test/test_dummy_data_layer.cpp | 14 +-- src/caffe/test/test_eltwise_layer.cpp | 38 +++--- src/caffe/test/test_euclidean_loss_layer.cpp | 14 +-- src/caffe/test/test_flatten_layer.cpp | 10 +- src/caffe/test/test_hdf5_output_layer.cpp | 4 +- src/caffe/test/test_hdf5data_layer.cpp | 6 +- src/caffe/test/test_hinge_loss_layer.cpp | 8 +- src/caffe/test/test_im2col_layer.cpp | 18 +-- src/caffe/test/test_image_data_layer.cpp | 12 +- src/caffe/test/test_infogain_loss_layer.cpp | 4 +- src/caffe/test/test_inner_product_layer.cpp | 10 +- src/caffe/test/test_lrn_layer.cpp | 30 ++--- .../test/test_maxpool_dropout_layers.cpp | 26 ++-- src/caffe/test/test_memory_data_layer.cpp | 10 +- .../test_multinomial_logistic_loss_layer.cpp | 6 +- src/caffe/test/test_mvn_layer.cpp | 24 ++-- src/caffe/test/test_neuron_layer.cpp | 96 +++++++-------- src/caffe/test/test_pooling_layer.cpp | 92 +++++++------- src/caffe/test/test_power_layer.cpp | 8 +- .../test_sigmoid_cross_entropy_loss_layer.cpp | 10 +- src/caffe/test/test_slice_layer.cpp | 20 +-- src/caffe/test/test_softmax_layer.cpp | 16 +-- .../test/test_softmax_with_loss_layer.cpp | 4 +- src/caffe/test/test_split_layer.cpp | 10 +- src/caffe/test/test_stochastic_pooling.cpp | 14 +-- src/caffe/test/test_threshold_layer.cpp | 10 +- tools/caffe.cpp | 6 +- 122 files changed, 1199 insertions(+), 1197 deletions(-) diff --git a/include/caffe/common_layers.hpp b/include/caffe/common_layers.hpp index 1f945ca34e9..9718b825b14 100644 --- a/include/caffe/common_layers.hpp +++ b/include/caffe/common_layers.hpp @@ -39,9 +39,9 @@ class ArgMaxLayer : public Layer { explicit ArgMaxLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_ARGMAX; @@ -62,10 +62,10 @@ class ArgMaxLayer : public Layer { * @f$ (for @f$ K = 1 @f$). */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /// @brief Not implemented (non-differentiable function) virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { NOT_IMPLEMENTED; } bool out_max_val_; @@ -82,9 +82,9 @@ class ConcatLayer : public Layer { explicit ConcatLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_CONCAT; @@ -110,9 +110,9 @@ class ConcatLayer : public Layer { * @f$ */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the error gradient w.r.t. the concatenate inputs. @@ -137,9 +137,9 @@ class ConcatLayer : public Layer { * @f$ */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); Blob col_bob_; int count_; @@ -162,9 +162,9 @@ class EltwiseLayer : public Layer { explicit EltwiseLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_ELTWISE; @@ -174,13 +174,13 @@ class EltwiseLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); EltwiseParameter_EltwiseOp op_; vector coeffs_; @@ -205,7 +205,7 @@ class FlattenLayer : public Layer { explicit FlattenLayer(const LayerParameter& param) : Layer(param) {} virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_FLATTEN; @@ -223,9 +223,9 @@ class FlattenLayer : public Layer { * the outputs -- i.e., the (virtually) copied, flattened inputs */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the error gradient w.r.t. the concatenate inputs. @@ -237,9 +237,9 @@ class FlattenLayer : public Layer { * gradient is (virtually) copied */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); int count_; }; @@ -256,9 +256,9 @@ class InnerProductLayer : public Layer { explicit InnerProductLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_INNER_PRODUCT; @@ -268,13 +268,13 @@ class InnerProductLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); int M_; int K_; @@ -294,7 +294,7 @@ class MVNLayer : public Layer { explicit MVNLayer(const LayerParameter& param) : Layer(param) {} virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_MVN; @@ -304,13 +304,13 @@ class MVNLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); Blob mean_, variance_, temp_; @@ -328,7 +328,7 @@ class SilenceLayer : public Layer { explicit SilenceLayer(const LayerParameter& param) : Layer(param) {} virtual void Reshape(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_SILENCE; @@ -338,15 +338,15 @@ class SilenceLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} // We can't define Forward_gpu here, since STUB_GPU will provide // its own definition for CPU_ONLY mode. virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); }; /** @@ -360,7 +360,7 @@ class SoftmaxLayer : public Layer { explicit SoftmaxLayer(const LayerParameter& param) : Layer(param) {} virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_SOFTMAX; @@ -370,13 +370,13 @@ class SoftmaxLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); /// sum_multiplier is used to carry out sum using BLAS Blob sum_multiplier_; @@ -395,16 +395,16 @@ class CuDNNSoftmaxLayer : public SoftmaxLayer { explicit CuDNNSoftmaxLayer(const LayerParameter& param) : SoftmaxLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual ~CuDNNSoftmaxLayer(); protected: virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_; @@ -424,7 +424,7 @@ class SplitLayer : public Layer { explicit SplitLayer(const LayerParameter& param) : Layer(param) {} virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_SPLIT; @@ -434,13 +434,13 @@ class SplitLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); int count_; }; @@ -457,9 +457,9 @@ class SliceLayer : public Layer { explicit SliceLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_SLICE; @@ -469,13 +469,13 @@ class SliceLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); Blob col_bob_; int count_; diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index 8e2637b0658..b3f93cea19e 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -37,17 +37,17 @@ class BaseDataLayer : public Layer { // DataLayerSetUp to do special data layer setup for individual layer types. // This method may not be overridden except by the BasePrefetchingDataLayer. virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void DataLayerSetUp(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} // Data layers have no bottoms, so reshaping is trivial. virtual void Reshape(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) {} + const vector& propagate_down, const vector*>& bottom) {} virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) {} + const vector& propagate_down, const vector*>& bottom) {} int datum_channels() const { return datum_channels_; } int datum_height() const { return datum_height_; } @@ -78,12 +78,12 @@ class BasePrefetchingDataLayer : // DataLayerSetUp to do special data layer setup for individual layer types. // This method may not be overridden. void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void CreatePrefetchThread(); virtual void JoinPrefetchThread(); @@ -102,7 +102,7 @@ class DataLayer : public BasePrefetchingDataLayer { : BasePrefetchingDataLayer(param) {} virtual ~DataLayer(); virtual void DataLayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_DATA; @@ -136,10 +136,10 @@ class DummyDataLayer : public Layer { explicit DummyDataLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); // Data layers have no bottoms, so reshaping is trivial. virtual void Reshape(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_DUMMY_DATA; @@ -149,11 +149,11 @@ class DummyDataLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) {} + const vector& propagate_down, const vector*>& bottom) {} virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) {} + const vector& propagate_down, const vector*>& bottom) {} vector > > fillers_; vector refill_; @@ -171,10 +171,10 @@ class HDF5DataLayer : public Layer { : Layer(param) {} virtual ~HDF5DataLayer(); virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); // Data layers have no bottoms, so reshaping is trivial. virtual void Reshape(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_HDF5_DATA; @@ -184,13 +184,13 @@ class HDF5DataLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) {} + const vector& propagate_down, const vector*>& bottom) {} virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) {} + const vector& propagate_down, const vector*>& bottom) {} virtual void LoadHDF5FileData(const char* filename); std::vector hdf_filenames_; @@ -212,10 +212,10 @@ class HDF5OutputLayer : public Layer { explicit HDF5OutputLayer(const LayerParameter& param); virtual ~HDF5OutputLayer(); virtual void LayerSetUp(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} // Data layers have no bottoms, so reshaping is trivial. virtual void Reshape(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_HDF5_OUTPUT; @@ -228,13 +228,13 @@ class HDF5OutputLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void SaveBlobs(); std::string file_name_; @@ -255,7 +255,7 @@ class ImageDataLayer : public BasePrefetchingDataLayer { : BasePrefetchingDataLayer(param) {} virtual ~ImageDataLayer(); virtual void DataLayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_IMAGE_DATA; @@ -283,7 +283,7 @@ class MemoryDataLayer : public BaseDataLayer { explicit MemoryDataLayer(const LayerParameter& param) : BaseDataLayer(param), has_new_data_(false) {} virtual void DataLayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_MEMORY_DATA; @@ -301,7 +301,7 @@ class MemoryDataLayer : public BaseDataLayer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); int batch_size_; Dtype* data_; @@ -326,7 +326,7 @@ class WindowDataLayer : public BasePrefetchingDataLayer { : BasePrefetchingDataLayer(param) {} virtual ~WindowDataLayer(); virtual void DataLayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_WINDOW_DATA; diff --git a/include/caffe/layer.hpp b/include/caffe/layer.hpp index e160075b939..18ff2743719 100644 --- a/include/caffe/layer.hpp +++ b/include/caffe/layer.hpp @@ -56,8 +56,9 @@ class Layer { * Sets up the loss weight multiplier blobs for any non-zero loss weights. * This method may not be overridden. */ - void SetUp(const vector*>& bottom, vector*>* top) { - CheckBlobCounts(bottom, *top); + void SetUp(const vector*>& bottom, + const vector*>& top) { + CheckBlobCounts(bottom, top); LayerSetUp(bottom, top); Reshape(bottom, top); SetLossWeights(top); @@ -80,7 +81,7 @@ class Layer { * adjust the top blob sizes. */ virtual void LayerSetUp(const vector*>& bottom, - vector*>* top) {} + const vector*>& top) {} /** * @brief Adjust the shapes of top blobs and internal buffers to accomodate @@ -95,7 +96,7 @@ class Layer { * accomodate the bottom blobs. */ virtual void Reshape(const vector*>& bottom, - vector*>* top) = 0; + const vector*>& top) = 0; /** * @brief Given the bottom blobs, compute the top blobs and the loss. @@ -115,7 +116,7 @@ class Layer { * Your layer should implement Forward_cpu and (optionally) Forward_gpu. */ inline Dtype Forward(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Given the top blob error gradients, compute the bottom blob error @@ -140,7 +141,7 @@ class Layer { */ inline void Backward(const vector*>& top, const vector& propagate_down, - vector*>* bottom); + const vector*>& bottom); /** * @brief Returns the vector of learnable parameter blobs. @@ -306,13 +307,13 @@ class Layer { /** @brief Using the CPU device, compute the layer output. */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top) = 0; + const vector*>& top) = 0; /** * @brief Using the GPU device, compute the layer output. * Fall back to Forward_cpu() if unavailable. */ virtual void Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // LOG(WARNING) << "Using CPU code as backup."; return Forward_cpu(bottom, top); } @@ -323,7 +324,7 @@ class Layer { */ virtual void Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) = 0; + const vector*>& bottom) = 0; /** * @brief Using the GPU device, compute the gradients for any parameters and * for the bottom blobs if propagate_down is true. @@ -331,7 +332,7 @@ class Layer { */ virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { // LOG(WARNING) << "Using CPU code as backup."; Backward_cpu(top, propagate_down, bottom); } @@ -384,17 +385,17 @@ class Layer { * Called by SetUp to initialize the weights associated with any top blobs in * the loss function. Store non-zero loss weights in the diff blob. */ - inline void SetLossWeights(vector*>* top) { + inline void SetLossWeights(const vector*>& top) { const int num_loss_weights = layer_param_.loss_weight_size(); if (num_loss_weights) { - CHECK_EQ(top->size(), num_loss_weights) << "loss_weight must be " + CHECK_EQ(top.size(), num_loss_weights) << "loss_weight must be " "unspecified or specified once per top blob."; - for (int top_id = 0; top_id < top->size(); ++top_id) { + for (int top_id = 0; top_id < top.size(); ++top_id) { const Dtype loss_weight = layer_param_.loss_weight(top_id); if (loss_weight == Dtype(0)) { continue; } this->set_loss(top_id, loss_weight); - const int count = (*top)[top_id]->count(); - Dtype* loss_multiplier = (*top)[top_id]->mutable_cpu_diff(); + const int count = top[top_id]->count(); + Dtype* loss_multiplier = top[top_id]->mutable_cpu_diff(); caffe_set(count, loss_weight, loss_multiplier); } } @@ -408,27 +409,27 @@ class Layer { // functions. template inline Dtype Layer::Forward(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { Dtype loss = 0; switch (Caffe::mode()) { case Caffe::CPU: Forward_cpu(bottom, top); - for (int top_id = 0; top_id < top->size(); ++top_id) { + for (int top_id = 0; top_id < top.size(); ++top_id) { if (!this->loss(top_id)) { continue; } - const int count = (*top)[top_id]->count(); - const Dtype* data = (*top)[top_id]->cpu_data(); - const Dtype* loss_weights = (*top)[top_id]->cpu_diff(); + const int count = top[top_id]->count(); + const Dtype* data = top[top_id]->cpu_data(); + const Dtype* loss_weights = top[top_id]->cpu_diff(); loss += caffe_cpu_dot(count, data, loss_weights); } break; case Caffe::GPU: Forward_gpu(bottom, top); #ifndef CPU_ONLY - for (int top_id = 0; top_id < top->size(); ++top_id) { + for (int top_id = 0; top_id < top.size(); ++top_id) { if (!this->loss(top_id)) { continue; } - const int count = (*top)[top_id]->count(); - const Dtype* data = (*top)[top_id]->gpu_data(); - const Dtype* loss_weights = (*top)[top_id]->gpu_diff(); + const int count = top[top_id]->count(); + const Dtype* data = top[top_id]->gpu_data(); + const Dtype* loss_weights = top[top_id]->gpu_diff(); Dtype blob_loss = 0; caffe_gpu_dot(count, data, loss_weights, &blob_loss); loss += blob_loss; @@ -444,7 +445,7 @@ inline Dtype Layer::Forward(const vector*>& bottom, template inline void Layer::Backward(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { switch (Caffe::mode()) { case Caffe::CPU: Backward_cpu(top, propagate_down, bottom); diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 08aa7752d4a..9fe58cd97bc 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -33,9 +33,9 @@ class AccuracyLayer : public Layer { explicit AccuracyLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_ACCURACY; @@ -70,12 +70,12 @@ class AccuracyLayer : public Layer { * @f$ */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /// @brief Not implemented -- AccuracyLayer cannot be used as a loss. virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { for (int i = 0; i < propagate_down.size(); ++i) { if (propagate_down[i]) { NOT_IMPLEMENTED; } } @@ -98,9 +98,9 @@ class LossLayer : public Layer { explicit LossLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp( - const vector*>& bottom, vector*>* top); + const vector*>& bottom, const vector*>& top); virtual void Reshape( - const vector*>& bottom, vector*>* top); + const vector*>& bottom, const vector*>& top); virtual inline int ExactNumBottomBlobs() const { return 2; } @@ -151,7 +151,7 @@ class ContrastiveLossLayer : public LossLayer { explicit ContrastiveLossLayer(const LayerParameter& param) : LossLayer(param), diff_() {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline int ExactNumBottomBlobs() const { return 3; } virtual inline LayerParameter_LayerType type() const { @@ -168,9 +168,9 @@ class ContrastiveLossLayer : public LossLayer { protected: /// @copydoc ContrastiveLossLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the Contrastive error gradient w.r.t. the inputs. @@ -198,9 +198,9 @@ class ContrastiveLossLayer : public LossLayer { * propagate_down[1] */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); Blob diff_; // cached for backward pass Blob dist_sq_; // cached for backward pass @@ -240,7 +240,7 @@ class EuclideanLossLayer : public LossLayer { explicit EuclideanLossLayer(const LayerParameter& param) : LossLayer(param), diff_() {} virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_EUCLIDEAN_LOSS; @@ -257,9 +257,9 @@ class EuclideanLossLayer : public LossLayer { protected: /// @copydoc EuclideanLossLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the Euclidean error gradient w.r.t. the inputs. @@ -295,9 +295,9 @@ class EuclideanLossLayer : public LossLayer { * @f$ if propagate_down[1] */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); Blob diff_; }; @@ -358,7 +358,7 @@ class HingeLossLayer : public LossLayer { protected: /// @copydoc HingeLossLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the hinge loss error gradient w.r.t. the predictions. @@ -388,7 +388,7 @@ class HingeLossLayer : public LossLayer { * the labels -- ignored as we can't compute their error gradients */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); }; /** @@ -429,9 +429,9 @@ class InfogainLossLayer : public LossLayer { explicit InfogainLossLayer(const LayerParameter& param) : LossLayer(param), infogain_() {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); // InfogainLossLayer takes 2-3 bottom Blobs; if there are 3 the third should // be the infogain matrix. (Otherwise the infogain matrix is loaded from a @@ -447,7 +447,7 @@ class InfogainLossLayer : public LossLayer { protected: /// @copydoc InfogainLossLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the infogain loss error gradient w.r.t. the predictions. @@ -482,7 +482,7 @@ class InfogainLossLayer : public LossLayer { * gradient computation is not implemented. */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); Blob infogain_; }; @@ -522,7 +522,7 @@ class MultinomialLogisticLossLayer : public LossLayer { explicit MultinomialLogisticLossLayer(const LayerParameter& param) : LossLayer(param) {} virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS; @@ -531,7 +531,7 @@ class MultinomialLogisticLossLayer : public LossLayer { protected: /// @copydoc MultinomialLogisticLossLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the multinomial logistic loss error gradient w.r.t. the @@ -562,7 +562,7 @@ class MultinomialLogisticLossLayer : public LossLayer { * the labels -- ignored as we can't compute their error gradients */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); }; /** @@ -602,9 +602,9 @@ class SigmoidCrossEntropyLossLayer : public LossLayer { sigmoid_layer_(new SigmoidLayer(param)), sigmoid_output_(new Blob()) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS; @@ -613,9 +613,9 @@ class SigmoidCrossEntropyLossLayer : public LossLayer { protected: /// @copydoc SigmoidCrossEntropyLossLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the sigmoid cross-entropy loss error gradient w.r.t. the @@ -648,9 +648,9 @@ class SigmoidCrossEntropyLossLayer : public LossLayer { * the labels -- ignored as we can't compute their error gradients */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); /// The internal SigmoidLayer used to map predictions to probabilities. shared_ptr > sigmoid_layer_; @@ -700,9 +700,9 @@ class SoftmaxWithLossLayer : public LossLayer { : LossLayer(param), softmax_layer_(new SoftmaxLayer(param)) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_SOFTMAX_LOSS; @@ -717,9 +717,9 @@ class SoftmaxWithLossLayer : public LossLayer { protected: /// @copydoc SoftmaxWithLossLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the softmax loss error gradient w.r.t. the predictions. @@ -749,9 +749,9 @@ class SoftmaxWithLossLayer : public LossLayer { * the labels -- ignored as we can't compute their error gradients */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); /// The internal SoftmaxLayer used to map predictions to a distribution. shared_ptr > softmax_layer_; diff --git a/include/caffe/neuron_layers.hpp b/include/caffe/neuron_layers.hpp index 0968a2007dc..64a1fd325ad 100644 --- a/include/caffe/neuron_layers.hpp +++ b/include/caffe/neuron_layers.hpp @@ -27,7 +27,7 @@ class NeuronLayer : public Layer { explicit NeuronLayer(const LayerParameter& param) : Layer(param) {} virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_NONE; @@ -52,7 +52,7 @@ class AbsValLayer : public NeuronLayer { explicit AbsValLayer(const LayerParameter& param) : NeuronLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_ABSVAL; @@ -63,9 +63,9 @@ class AbsValLayer : public NeuronLayer { protected: /// @copydoc AbsValLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the error gradient w.r.t. the absolute value inputs. @@ -85,9 +85,9 @@ class AbsValLayer : public NeuronLayer { * @f$ if propagate_down[0] */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); }; /** @@ -120,9 +120,9 @@ class BNLLLayer : public NeuronLayer { protected: /// @copydoc BNLLLayer virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the error gradient w.r.t. the BNLL inputs. @@ -141,9 +141,9 @@ class BNLLLayer : public NeuronLayer { * @f$ if propagate_down[0] */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); }; /** @@ -169,9 +169,9 @@ class DropoutLayer : public NeuronLayer { explicit DropoutLayer(const LayerParameter& param) : NeuronLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_DROPOUT; @@ -195,13 +195,13 @@ class DropoutLayer : public NeuronLayer { * @f$ y_{\mbox{test}} = \mathbb{E}[y_{\mbox{train}}] = x @f$. */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); /// when divided by UINT_MAX, the randomly generated values @f$u\sim U(0,1)@f$ Blob rand_vec_; @@ -230,7 +230,7 @@ class PowerLayer : public NeuronLayer { explicit PowerLayer(const LayerParameter& param) : NeuronLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_POWER; @@ -248,9 +248,9 @@ class PowerLayer : public NeuronLayer { * @f$ */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the error gradient w.r.t. the power inputs. @@ -273,9 +273,9 @@ class PowerLayer : public NeuronLayer { * @f$ if propagate_down[0] */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); /// @brief @f$ \gamma @f$ from layer_param_.power_param() Dtype power_; @@ -320,9 +320,9 @@ class ReLULayer : public NeuronLayer { * the computed outputs are @f$ y = \max(0, x) + \nu \min(0, x) @f$. */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the error gradient w.r.t. the ReLU inputs. @@ -353,9 +353,9 @@ class ReLULayer : public NeuronLayer { * @f$. */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); }; #ifdef USE_CUDNN @@ -368,16 +368,16 @@ class CuDNNReLULayer : public ReLULayer { explicit CuDNNReLULayer(const LayerParameter& param) : ReLULayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual ~CuDNNReLULayer(); protected: virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_; @@ -415,9 +415,9 @@ class SigmoidLayer : public NeuronLayer { * @f$ */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the error gradient w.r.t. the sigmoid inputs. @@ -437,9 +437,9 @@ class SigmoidLayer : public NeuronLayer { * @f$ if propagate_down[0] */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); }; #ifdef USE_CUDNN @@ -452,16 +452,16 @@ class CuDNNSigmoidLayer : public SigmoidLayer { explicit CuDNNSigmoidLayer(const LayerParameter& param) : SigmoidLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual ~CuDNNSigmoidLayer(); protected: virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_; @@ -499,9 +499,9 @@ class TanHLayer : public NeuronLayer { * @f$ */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /** * @brief Computes the error gradient w.r.t. the sigmoid inputs. @@ -523,9 +523,9 @@ class TanHLayer : public NeuronLayer { * @f$ if propagate_down[0] */ virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); }; #ifdef USE_CUDNN @@ -538,16 +538,16 @@ class CuDNNTanHLayer : public TanHLayer { explicit CuDNNTanHLayer(const LayerParameter& param) : TanHLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual ~CuDNNTanHLayer(); protected: virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_; @@ -571,7 +571,7 @@ class ThresholdLayer : public NeuronLayer { explicit ThresholdLayer(const LayerParameter& param) : NeuronLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_THRESHOLD; @@ -593,12 +593,12 @@ class ThresholdLayer : public NeuronLayer { * @f$ */ virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); /// @brief Not implemented (non-differentiable function) virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { NOT_IMPLEMENTED; } diff --git a/include/caffe/test/test_gradient_check_util.hpp b/include/caffe/test/test_gradient_check_util.hpp index 5a8d382ff26..22937711b58 100644 --- a/include/caffe/test/test_gradient_check_util.hpp +++ b/include/caffe/test/test_gradient_check_util.hpp @@ -30,24 +30,24 @@ class GradientChecker { // layers. // Note that after the gradient check, we do not guarantee that the data // stored in the layer parameters and the blobs are unchanged. - void CheckGradient(Layer* layer, vector*>* bottom, - vector*>* top, int check_bottom = -1) { - layer->SetUp(*bottom, top); + void CheckGradient(Layer* layer, const vector*>& bottom, + const vector*>& top, int check_bottom = -1) { + layer->SetUp(bottom, top); CheckGradientSingle(layer, bottom, top, check_bottom, -1, -1); } void CheckGradientExhaustive(Layer* layer, - vector*>* bottom, vector*>* top, + const vector*>& bottom, const vector*>& top, int check_bottom = -1); // CheckGradientEltwise can be used to test layers that perform element-wise // computation only (e.g., neuron layers) -- where (d y_i) / (d x_j) = 0 when // i != j. void CheckGradientEltwise(Layer* layer, - vector*>* bottom, vector*>* top); + const vector*>& bottom, const vector*>& top); - void CheckGradientSingle(Layer* layer, vector*>* bottom, - vector*>* top, int check_bottom, int top_id, - int top_data_id, bool element_wise = false); + void CheckGradientSingle(Layer* layer, + const vector*>& bottom, const vector*>& top, + int check_bottom, int top_id, int top_data_id, bool element_wise = false); // Checks the gradient of a network. This network should not have any data // layers or loss layers, since the function does not explicitly deal with @@ -57,8 +57,8 @@ class GradientChecker { const vector*>& input); protected: - Dtype GetObjAndGradient(const Layer& layer, vector*>* top, - int top_id = -1, int top_data_id = -1); + Dtype GetObjAndGradient(const Layer& layer, + const vector*>& top, int top_id = -1, int top_data_id = -1); Dtype stepsize_; Dtype threshold_; unsigned int seed_; @@ -69,40 +69,40 @@ class GradientChecker { template void GradientChecker::CheckGradientSingle(Layer* layer, - vector*>* bottom, vector*>* top, + const vector*>& bottom, const vector*>& top, int check_bottom, int top_id, int top_data_id, bool element_wise) { if (element_wise) { CHECK_EQ(0, layer->blobs().size()); CHECK_LE(0, top_id); CHECK_LE(0, top_data_id); - const int top_count = (*top)[top_id]->count(); - for (int blob_id = 0; blob_id < bottom->size(); ++blob_id) { - CHECK_EQ(top_count, (*bottom)[blob_id]->count()); + const int top_count = top[top_id]->count(); + for (int blob_id = 0; blob_id < bottom.size(); ++blob_id) { + CHECK_EQ(top_count, bottom[blob_id]->count()); } } // First, figure out what blobs we need to check against. vector*> blobs_to_check; - vector propagate_down(bottom->size(), check_bottom < 0); + vector propagate_down(bottom.size(), check_bottom < 0); for (int i = 0; i < layer->blobs().size(); ++i) { blobs_to_check.push_back(layer->blobs()[i].get()); } if (check_bottom < 0) { - for (int i = 0; i < bottom->size(); ++i) { - blobs_to_check.push_back((*bottom)[i]); + for (int i = 0; i < bottom.size(); ++i) { + blobs_to_check.push_back(bottom[i]); } } else { - CHECK_LT(check_bottom, bottom->size()); - blobs_to_check.push_back((*bottom)[check_bottom]); + CHECK_LT(check_bottom, bottom.size()); + blobs_to_check.push_back(bottom[check_bottom]); propagate_down[check_bottom] = true; } // Compute the gradient analytically using Backward Caffe::set_random_seed(seed_); // Ignore the loss from the layer (it's just the weighted sum of the losses // from the top blobs, whose gradients we may want to test individually). - layer->Forward(*bottom, top); + layer->Forward(bottom, top); // Get additional loss from the objective GetObjAndGradient(*layer, top, top_id, top_data_id); - layer->Backward(*top, propagate_down, bottom); + layer->Backward(top, propagate_down, bottom); // Store computed gradients for all checked blobs vector > > computed_gradient_blobs(blobs_to_check.size()); @@ -127,8 +127,8 @@ void GradientChecker::CheckGradientSingle(Layer* layer, // << current_blob->count() << " parameters."; for (int feat_id = 0; feat_id < current_blob->count(); ++feat_id) { // For an element-wise layer, we only need to do finite differencing to - // compute the derivative of (*top)[top_id][top_data_id] w.r.t. - // (*bottom)[blob_id][i] only for i == top_data_id. For any other + // compute the derivative of top[top_id][top_data_id] w.r.t. + // bottom[blob_id][i] only for i == top_data_id. For any other // i != top_data_id, we know the derivative is 0 by definition, and simply // check that that's true. Dtype estimated_gradient = 0; @@ -139,13 +139,13 @@ void GradientChecker::CheckGradientSingle(Layer* layer, // Compute loss with stepsize_ added to input. current_blob->mutable_cpu_data()[feat_id] += stepsize_; Caffe::set_random_seed(seed_); - layer->Forward(*bottom, top); + layer->Forward(bottom, top); positive_objective = GetObjAndGradient(*layer, top, top_id, top_data_id); // Compute loss with stepsize_ subtracted from input. current_blob->mutable_cpu_data()[feat_id] -= stepsize_ * 2; Caffe::set_random_seed(seed_); - layer->Forward(*bottom, top); + layer->Forward(bottom, top); negative_objective = GetObjAndGradient(*layer, top, top_id, top_data_id); // Recover original input value. @@ -179,13 +179,14 @@ void GradientChecker::CheckGradientSingle(Layer* layer, template void GradientChecker::CheckGradientExhaustive(Layer* layer, - vector*>* bottom, vector*>* top, int check_bottom) { - layer->SetUp(*bottom, top); - CHECK_GT(top->size(), 0) << "Exhaustive mode requires at least one top blob."; + const vector*>& bottom, const vector*>& top, + int check_bottom) { + layer->SetUp(bottom, top); + CHECK_GT(top.size(), 0) << "Exhaustive mode requires at least one top blob."; // LOG(ERROR) << "Exhaustive Mode."; - for (int i = 0; i < top->size(); ++i) { + for (int i = 0; i < top.size(); ++i) { // LOG(ERROR) << "Exhaustive: blob " << i << " size " << top[i]->count(); - for (int j = 0; j < (*top)[i]->count(); ++j) { + for (int j = 0; j < top[i]->count(); ++j) { // LOG(ERROR) << "Exhaustive: blob " << i << " data " << j; CheckGradientSingle(layer, bottom, top, check_bottom, i, j); } @@ -194,13 +195,13 @@ void GradientChecker::CheckGradientExhaustive(Layer* layer, template void GradientChecker::CheckGradientEltwise(Layer* layer, - vector*>* bottom, vector*>* top) { - layer->SetUp(*bottom, top); - CHECK_GT(top->size(), 0) << "Eltwise mode requires at least one top blob."; + const vector*>& bottom, const vector*>& top) { + layer->SetUp(bottom, top); + CHECK_GT(top.size(), 0) << "Eltwise mode requires at least one top blob."; const int check_bottom = -1; const bool element_wise = true; - for (int i = 0; i < top->size(); ++i) { - for (int j = 0; j < (*top)[i]->count(); ++j) { + for (int i = 0; i < top.size(); ++i) { + for (int j = 0; j < top[i]->count(); ++j) { CheckGradientSingle(layer, bottom, top, check_bottom, i, j, element_wise); } } @@ -221,12 +222,12 @@ void GradientChecker::CheckGradientNet( template Dtype GradientChecker::GetObjAndGradient(const Layer& layer, - vector*>* top, int top_id, int top_data_id) { + const vector*>& top, int top_id, int top_data_id) { Dtype loss = 0; if (top_id < 0) { // the loss will be half of the sum of squares of all outputs - for (int i = 0; i < top->size(); ++i) { - Blob* top_blob = (*top)[i]; + for (int i = 0; i < top.size(); ++i) { + Blob* top_blob = top[i]; const Dtype* top_blob_data = top_blob->cpu_data(); Dtype* top_blob_diff = top_blob->mutable_cpu_diff(); int count = top_blob->count(); @@ -239,14 +240,14 @@ Dtype GradientChecker::GetObjAndGradient(const Layer& layer, loss /= 2.; } else { // the loss will be the top_data_id-th element in the top_id-th blob. - for (int i = 0; i < top->size(); ++i) { - Blob* top_blob = (*top)[i]; + for (int i = 0; i < top.size(); ++i) { + Blob* top_blob = top[i]; Dtype* top_blob_diff = top_blob->mutable_cpu_diff(); caffe_set(top_blob->count(), Dtype(0), top_blob_diff); } const Dtype loss_weight = 2; - loss = (*top)[top_id]->cpu_data()[top_data_id] * loss_weight; - (*top)[top_id]->mutable_cpu_diff()[top_data_id] = loss_weight; + loss = top[top_id]->cpu_data()[top_data_id] * loss_weight; + top[top_id]->mutable_cpu_diff()[top_data_id] = loss_weight; } return loss; } diff --git a/include/caffe/util/device_alternate.hpp b/include/caffe/util/device_alternate.hpp index 3df28a49ac3..5a45691bb17 100644 --- a/include/caffe/util/device_alternate.hpp +++ b/include/caffe/util/device_alternate.hpp @@ -12,22 +12,22 @@ #define STUB_GPU(classname) \ template \ void classname::Forward_gpu(const vector*>& bottom, \ - vector*>* top) { NO_GPU; } \ + const vector*>& top) { NO_GPU; } \ template \ void classname::Backward_gpu(const vector*>& top, \ const vector& propagate_down, \ - vector*>* bottom) { NO_GPU; } \ + const vector*>& bottom) { NO_GPU; } \ #define STUB_GPU_FORWARD(classname, funcname) \ template \ void classname::funcname##_##gpu(const vector*>& bottom, \ - vector*>* top) { NO_GPU; } \ + const vector*>& top) { NO_GPU; } \ #define STUB_GPU_BACKWARD(classname, funcname) \ template \ void classname::funcname##_##gpu(const vector*>& top, \ const vector& propagate_down, \ - vector*>* bottom) { NO_GPU; } \ + const vector*>& bottom) { NO_GPU; } \ #else // Normal GPU + CPU Caffe. diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 1e7f3fcb297..0f1b2d9e529 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -66,9 +66,9 @@ class ConvolutionLayer : public Layer { explicit ConvolutionLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_CONVOLUTION; @@ -79,13 +79,13 @@ class ConvolutionLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); int kernel_h_, kernel_w_; int stride_h_, stride_w_; @@ -132,16 +132,16 @@ class CuDNNConvolutionLayer : public ConvolutionLayer { explicit CuDNNConvolutionLayer(const LayerParameter& param) : ConvolutionLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual ~CuDNNConvolutionLayer(); protected: virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); cudnnHandle_t* handle_; cudaStream_t* stream_; @@ -166,9 +166,9 @@ class Im2colLayer : public Layer { explicit Im2colLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_IM2COL; @@ -178,13 +178,13 @@ class Im2colLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); int kernel_h_, kernel_w_; int stride_h_, stride_w_; @@ -208,9 +208,9 @@ class LRNLayer : public Layer { explicit LRNLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_LRN; @@ -220,26 +220,26 @@ class LRNLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void CrossChannelForward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void CrossChannelForward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void WithinChannelForward(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void CrossChannelBackward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void CrossChannelBackward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void WithinChannelBackward(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); int size_; int pre_pad_; @@ -285,9 +285,9 @@ class PoolingLayer : public Layer { explicit PoolingLayer(const LayerParameter& param) : Layer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_POOLING; @@ -303,13 +303,13 @@ class PoolingLayer : public Layer { protected: virtual void Forward_cpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); int kernel_h_, kernel_w_; int stride_h_, stride_w_; @@ -332,16 +332,16 @@ class CuDNNPoolingLayer : public PoolingLayer { explicit CuDNNPoolingLayer(const LayerParameter& param) : PoolingLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Reshape(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual ~CuDNNPoolingLayer(); protected: virtual void Forward_gpu(const vector*>& bottom, - vector*>* top); + const vector*>& top); virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom); + const vector& propagate_down, const vector*>& bottom); cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_, top_desc_; diff --git a/src/caffe/layers/absval_layer.cpp b/src/caffe/layers/absval_layer.cpp index ce9d05cc764..54e484b115d 100644 --- a/src/caffe/layers/absval_layer.cpp +++ b/src/caffe/layers/absval_layer.cpp @@ -8,29 +8,29 @@ namespace caffe { template void AbsValLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { NeuronLayer::LayerSetUp(bottom, top); - CHECK_NE((*top)[0], bottom[0]) << this->type_name() << " Layer does not " + CHECK_NE(top[0], bottom[0]) << this->type_name() << " Layer does not " "allow in-place computation."; } template void AbsValLayer::Forward_cpu( - const vector*>& bottom, vector*>* top) { - const int count = (*top)[0]->count(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const vector*>& bottom, const vector*>& top) { + const int count = top[0]->count(); + Dtype* top_data = top[0]->mutable_cpu_data(); caffe_abs(count, bottom[0]->cpu_data(), top_data); } template void AbsValLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const int count = top[0]->count(); const Dtype* top_data = top[0]->cpu_data(); const Dtype* top_diff = top[0]->cpu_diff(); if (propagate_down[0]) { - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); caffe_div(count, top_data, bottom_data, bottom_diff); caffe_mul(count, bottom_diff, top_diff, bottom_diff); } diff --git a/src/caffe/layers/absval_layer.cu b/src/caffe/layers/absval_layer.cu index 46778aa79b1..48c766465fa 100644 --- a/src/caffe/layers/absval_layer.cu +++ b/src/caffe/layers/absval_layer.cu @@ -8,21 +8,21 @@ namespace caffe { template void AbsValLayer::Forward_gpu( - const vector*>& bottom, vector*>* top) { - const int count = (*top)[0]->count(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const vector*>& bottom, const vector*>& top) { + const int count = top[0]->count(); + Dtype* top_data = top[0]->mutable_gpu_data(); caffe_gpu_abs(count, bottom[0]->gpu_data(), top_data); } template void AbsValLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const int count = top[0]->count(); const Dtype* top_data = top[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); if (propagate_down[0]) { - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); caffe_gpu_div(count, top_data, bottom_data, bottom_diff); caffe_gpu_mul(count, bottom_diff, top_diff, bottom_diff); } diff --git a/src/caffe/layers/accuracy_layer.cpp b/src/caffe/layers/accuracy_layer.cpp index 3e69bc84faa..399cf2a3585 100644 --- a/src/caffe/layers/accuracy_layer.cpp +++ b/src/caffe/layers/accuracy_layer.cpp @@ -12,13 +12,13 @@ namespace caffe { template void AccuracyLayer::LayerSetUp( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { top_k_ = this->layer_param_.accuracy_param().top_k(); } template void AccuracyLayer::Reshape( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { CHECK_EQ(bottom[0]->num(), bottom[1]->num()) << "The data and label should have the same number."; CHECK_LE(top_k_, bottom[0]->count() / bottom[0]->num()) @@ -26,12 +26,12 @@ void AccuracyLayer::Reshape( CHECK_EQ(bottom[1]->channels(), 1); CHECK_EQ(bottom[1]->height(), 1); CHECK_EQ(bottom[1]->width(), 1); - (*top)[0]->Reshape(1, 1, 1, 1); + top[0]->Reshape(1, 1, 1, 1); } template void AccuracyLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { Dtype accuracy = 0; const Dtype* bottom_data = bottom[0]->cpu_data(); const Dtype* bottom_label = bottom[1]->cpu_data(); @@ -59,7 +59,7 @@ void AccuracyLayer::Forward_cpu(const vector*>& bottom, } // LOG(INFO) << "Accuracy: " << accuracy; - (*top)[0]->mutable_cpu_data()[0] = accuracy / num; + top[0]->mutable_cpu_data()[0] = accuracy / num; // Accuracy layer should not be used as a loss function. } diff --git a/src/caffe/layers/argmax_layer.cpp b/src/caffe/layers/argmax_layer.cpp index 0d1a107257b..dbe0a834aa5 100644 --- a/src/caffe/layers/argmax_layer.cpp +++ b/src/caffe/layers/argmax_layer.cpp @@ -10,7 +10,7 @@ namespace caffe { template void ArgMaxLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { out_max_val_ = this->layer_param_.argmax_param().out_max_val(); top_k_ = this->layer_param_.argmax_param().top_k(); CHECK_GE(top_k_, 1) << " top k must not be less than 1."; @@ -20,21 +20,21 @@ void ArgMaxLayer::LayerSetUp(const vector*>& bottom, template void ArgMaxLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { if (out_max_val_) { // Produces max_ind and max_val - (*top)[0]->Reshape(bottom[0]->num(), 2, top_k_, 1); + top[0]->Reshape(bottom[0]->num(), 2, top_k_, 1); } else { // Produces only max_ind - (*top)[0]->Reshape(bottom[0]->num(), 1, top_k_, 1); + top[0]->Reshape(bottom[0]->num(), 1, top_k_, 1); } } template void ArgMaxLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); int num = bottom[0]->num(); int dim = bottom[0]->count() / bottom[0]->num(); for (int i = 0; i < num; ++i) { @@ -47,11 +47,11 @@ void ArgMaxLayer::Forward_cpu(const vector*>& bottom, bottom_data_vector.begin(), bottom_data_vector.begin() + top_k_, bottom_data_vector.end(), std::greater >()); for (int j = 0; j < top_k_; ++j) { - top_data[(*top)[0]->offset(i, 0, j)] = bottom_data_vector[j].second; + top_data[top[0]->offset(i, 0, j)] = bottom_data_vector[j].second; } if (out_max_val_) { for (int j = 0; j < top_k_; ++j) { - top_data[(*top)[0]->offset(i, 1, j)] = bottom_data_vector[j].first; + top_data[top[0]->offset(i, 1, j)] = bottom_data_vector[j].first; } } } diff --git a/src/caffe/layers/base_data_layer.cpp b/src/caffe/layers/base_data_layer.cpp index 9b1d55831a7..86abbae8f4c 100644 --- a/src/caffe/layers/base_data_layer.cpp +++ b/src/caffe/layers/base_data_layer.cpp @@ -15,8 +15,8 @@ BaseDataLayer::BaseDataLayer(const LayerParameter& param) template void BaseDataLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { - if (top->size() == 1) { + const vector*>& top) { + if (top.size() == 1) { output_labels_ = false; } else { output_labels_ = true; @@ -51,7 +51,7 @@ void BaseDataLayer::LayerSetUp(const vector*>& bottom, template void BasePrefetchingDataLayer::LayerSetUp( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { BaseDataLayer::LayerSetUp(bottom, top); // Now, start the prefetch thread. Before calling prefetch, we make two // cpu_data calls so that the prefetch thread does not accidentally make @@ -80,15 +80,15 @@ void BasePrefetchingDataLayer::JoinPrefetchThread() { template void BasePrefetchingDataLayer::Forward_cpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { // First, join the thread JoinPrefetchThread(); // Copy the data caffe_copy(prefetch_data_.count(), prefetch_data_.cpu_data(), - (*top)[0]->mutable_cpu_data()); + top[0]->mutable_cpu_data()); if (this->output_labels_) { caffe_copy(prefetch_label_.count(), prefetch_label_.cpu_data(), - (*top)[1]->mutable_cpu_data()); + top[1]->mutable_cpu_data()); } // Start a new prefetch thread CreatePrefetchThread(); diff --git a/src/caffe/layers/base_data_layer.cu b/src/caffe/layers/base_data_layer.cu index 8189c79c9d4..ff1510361b6 100644 --- a/src/caffe/layers/base_data_layer.cu +++ b/src/caffe/layers/base_data_layer.cu @@ -6,15 +6,15 @@ namespace caffe { template void BasePrefetchingDataLayer::Forward_gpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { // First, join the thread JoinPrefetchThread(); // Copy the data caffe_copy(prefetch_data_.count(), prefetch_data_.cpu_data(), - (*top)[0]->mutable_gpu_data()); + top[0]->mutable_gpu_data()); if (this->output_labels_) { caffe_copy(prefetch_label_.count(), prefetch_label_.cpu_data(), - (*top)[1]->mutable_gpu_data()); + top[1]->mutable_gpu_data()); } // Start a new prefetch thread CreatePrefetchThread(); diff --git a/src/caffe/layers/bnll_layer.cpp b/src/caffe/layers/bnll_layer.cpp index ef98326a23e..bae692509e3 100644 --- a/src/caffe/layers/bnll_layer.cpp +++ b/src/caffe/layers/bnll_layer.cpp @@ -10,9 +10,9 @@ const float kBNLL_THRESHOLD = 50.; template void BNLLLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); const int count = bottom[0]->count(); for (int i = 0; i < count; ++i) { top_data[i] = bottom_data[i] > 0 ? @@ -24,12 +24,12 @@ void BNLLLayer::Forward_cpu(const vector*>& bottom, template void BNLLLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* bottom_data = bottom[0]->cpu_data(); const Dtype* top_diff = top[0]->cpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + const int count = bottom[0]->count(); Dtype expval; for (int i = 0; i < count; ++i) { expval = exp(std::min(bottom_data[i], Dtype(kBNLL_THRESHOLD))); diff --git a/src/caffe/layers/bnll_layer.cu b/src/caffe/layers/bnll_layer.cu index b940133b4b3..3993bccd9b5 100644 --- a/src/caffe/layers/bnll_layer.cu +++ b/src/caffe/layers/bnll_layer.cu @@ -19,9 +19,9 @@ __global__ void BNLLForward(const int n, const Dtype* in, Dtype* out) { template void BNLLLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); const int count = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) BNLLForward<<>>( @@ -41,12 +41,12 @@ __global__ void BNLLBackward(const int n, const Dtype* in_diff, template void BNLLLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + const Dtype* bottom_data = bottom[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); + const int count = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) BNLLBackward<<>>( count, top_diff, bottom_data, bottom_diff); diff --git a/src/caffe/layers/concat_layer.cpp b/src/caffe/layers/concat_layer.cpp index 10a11f1bb7c..f8f73564a6f 100644 --- a/src/caffe/layers/concat_layer.cpp +++ b/src/caffe/layers/concat_layer.cpp @@ -8,7 +8,7 @@ namespace caffe { template void ConcatLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { concat_dim_ = this->layer_param_.concat_param().concat_dim(); CHECK_GE(concat_dim_, 0) << "concat_dim should be >= 0"; @@ -18,7 +18,7 @@ void ConcatLayer::LayerSetUp(const vector*>& bottom, template void ConcatLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // Initialize with the first blob. count_ = bottom[0]->count(); num_ = bottom[0]->num(); @@ -37,20 +37,20 @@ void ConcatLayer::Reshape(const vector*>& bottom, width_ += bottom[i]->width(); } } - (*top)[0]->Reshape(num_, channels_, height_, width_); - CHECK_EQ(count_, (*top)[0]->count()); + top[0]->Reshape(num_, channels_, height_, width_); + CHECK_EQ(count_, top[0]->count()); } template void ConcatLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const vector*>& top) { + Dtype* top_data = top[0]->mutable_cpu_data(); if (concat_dim_== 0) { int offset_num = 0; for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->cpu_data(); int num_elem = bottom[i]->count(); - caffe_copy(num_elem, bottom_data, top_data+(*top)[0]->offset(offset_num)); + caffe_copy(num_elem, bottom_data, top_data+top[0]->offset(offset_num)); offset_num += bottom[i]->num(); } } else if (concat_dim_ == 1) { @@ -61,7 +61,7 @@ void ConcatLayer::Forward_cpu(const vector*>& bottom, bottom[i]->channels()*bottom[i]->height()*bottom[i]->width(); for (int n = 0; n < num_; ++n) { caffe_copy(num_elem, bottom_data+bottom[i]->offset(n), - top_data+(*top)[0]->offset(n, offset_channel)); + top_data+top[0]->offset(n, offset_channel)); } offset_channel += bottom[i]->channels(); } // concat_dim_ is guaranteed to be 0 or 1 by LayerSetUp. @@ -70,12 +70,12 @@ void ConcatLayer::Forward_cpu(const vector*>& bottom, template void ConcatLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const Dtype* top_diff = top[0]->cpu_diff(); if (concat_dim_ == 0) { int offset_num = 0; - for (int i = 0; i < bottom->size(); ++i) { - Blob* blob = (*bottom)[i]; + for (int i = 0; i < bottom.size(); ++i) { + Blob* blob = bottom[i]; if (propagate_down[i]) { Dtype* bottom_diff = blob->mutable_cpu_diff(); caffe_copy(blob->count(), top_diff + top[0]->offset(offset_num), @@ -85,8 +85,8 @@ void ConcatLayer::Backward_cpu(const vector*>& top, } } else if (concat_dim_ == 1) { int offset_channel = 0; - for (int i = 0; i < bottom->size(); ++i) { - Blob* blob = (*bottom)[i]; + for (int i = 0; i < bottom.size(); ++i) { + Blob* blob = bottom[i]; if (propagate_down[i]) { Dtype* bottom_diff = blob->mutable_cpu_diff(); int num_elem = blob->channels()*blob->height()*blob->width(); diff --git a/src/caffe/layers/concat_layer.cu b/src/caffe/layers/concat_layer.cu index 99c55da25cb..1b4e40aa415 100644 --- a/src/caffe/layers/concat_layer.cu +++ b/src/caffe/layers/concat_layer.cu @@ -8,14 +8,14 @@ namespace caffe { template void ConcatLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const vector*>& top) { + Dtype* top_data = top[0]->mutable_gpu_data(); if (concat_dim_ == 0) { int offset_num = 0; for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->gpu_data(); caffe_copy(bottom[i]->count(), bottom_data, - top_data + (*top)[0]->offset(offset_num)); + top_data + top[0]->offset(offset_num)); offset_num += bottom[i]->num(); } } else if (concat_dim_ == 1) { @@ -26,7 +26,7 @@ void ConcatLayer::Forward_gpu(const vector*>& bottom, bottom[i]->channels() * bottom[i]->height() * bottom[i]->width(); for (int n = 0; n < num_; ++n) { caffe_copy(num_elem, bottom_data+bottom[i]->offset(n), - top_data + (*top)[0]->offset(n, offset_channel)); + top_data + top[0]->offset(n, offset_channel)); } offset_channel += bottom[i]->channels(); } @@ -38,12 +38,12 @@ void ConcatLayer::Forward_gpu(const vector*>& bottom, template void ConcatLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const Dtype* top_diff = top[0]->gpu_diff(); if (concat_dim_ == 0) { int offset_num = 0; - for (int i = 0; i < bottom->size(); ++i) { - Blob* blob = (*bottom)[i]; + for (int i = 0; i < bottom.size(); ++i) { + Blob* blob = bottom[i]; if (propagate_down[i]) { Dtype* bottom_diff = blob->mutable_gpu_diff(); caffe_copy(blob->count(), top_diff + top[0]->offset(offset_num), @@ -53,8 +53,8 @@ void ConcatLayer::Backward_gpu(const vector*>& top, } } else if (concat_dim_ == 1) { int offset_channel = 0; - for (int i = 0; i < bottom->size(); ++i) { - Blob* blob = (*bottom)[i]; + for (int i = 0; i < bottom.size(); ++i) { + Blob* blob = bottom[i]; if (propagate_down[i]) { Dtype* bottom_diff = blob->mutable_gpu_diff(); int num_elem = blob->channels()*blob->height()*blob->width(); diff --git a/src/caffe/layers/contrastive_loss_layer.cpp b/src/caffe/layers/contrastive_loss_layer.cpp index 072a5a535be..d716d140ea0 100644 --- a/src/caffe/layers/contrastive_loss_layer.cpp +++ b/src/caffe/layers/contrastive_loss_layer.cpp @@ -10,7 +10,7 @@ namespace caffe { template void ContrastiveLossLayer::LayerSetUp( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::LayerSetUp(bottom, top); CHECK_EQ(bottom[0]->channels(), bottom[1]->channels()); CHECK_EQ(bottom[0]->height(), 1); @@ -32,7 +32,7 @@ void ContrastiveLossLayer::LayerSetUp( template void ContrastiveLossLayer::Forward_cpu( const vector*>& bottom, - vector*>* top) { + const vector*>& top) { int count = bottom[0]->count(); caffe_sub( count, @@ -52,23 +52,23 @@ void ContrastiveLossLayer::Forward_cpu( } } loss = loss / static_cast(bottom[0]->num()) / Dtype(2); - (*top)[0]->mutable_cpu_data()[0] = loss; + top[0]->mutable_cpu_data()[0] = loss; } template void ContrastiveLossLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { Dtype margin = this->layer_param_.contrastive_loss_param().margin(); for (int i = 0; i < 2; ++i) { if (propagate_down[i]) { const Dtype sign = (i == 0) ? 1 : -1; const Dtype alpha = sign * top[0]->cpu_diff()[0] / - static_cast((*bottom)[i]->num()); - int num = (*bottom)[i]->num(); - int channels = (*bottom)[i]->channels(); + static_cast(bottom[i]->num()); + int num = bottom[i]->num(); + int channels = bottom[i]->channels(); for (int j = 0; j < num; ++j) { - Dtype* bout = (*bottom)[i]->mutable_cpu_diff(); - if (static_cast((*bottom)[2]->cpu_data()[j])) { // similar pairs + Dtype* bout = bottom[i]->mutable_cpu_diff(); + if (static_cast(bottom[2]->cpu_data()[j])) { // similar pairs caffe_cpu_axpby( channels, alpha, diff --git a/src/caffe/layers/contrastive_loss_layer.cu b/src/caffe/layers/contrastive_loss_layer.cu index 672ad5bc2f8..14b55b37173 100644 --- a/src/caffe/layers/contrastive_loss_layer.cu +++ b/src/caffe/layers/contrastive_loss_layer.cu @@ -10,7 +10,7 @@ namespace caffe { template void ContrastiveLossLayer::Forward_gpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { const int count = bottom[0]->count(); caffe_gpu_sub( count, @@ -41,7 +41,7 @@ void ContrastiveLossLayer::Forward_gpu( } } loss = loss / static_cast(bottom[0]->num()) / Dtype(2); - (*top)[0]->mutable_cpu_data()[0] = loss; + top[0]->mutable_cpu_data()[0] = loss; } template @@ -65,22 +65,22 @@ __global__ void CLLForward(const int count, const int channels, template void ContrastiveLossLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { for (int i = 0; i < 2; ++i) { if (propagate_down[i]) { - const int count = (*bottom)[0]->count(); - const int channels = (*bottom)[0]->channels(); + const int count = bottom[0]->count(); + const int channels = bottom[0]->channels(); Dtype margin = this->layer_param_.contrastive_loss_param().margin(); const Dtype sign = (i == 0) ? 1 : -1; const Dtype alpha = sign * top[0]->cpu_diff()[0] / - static_cast((*bottom)[0]->num()); + static_cast(bottom[0]->num()); // NOLINT_NEXT_LINE(whitespace/operators) CLLForward<<>>( count, channels, margin, alpha, - (*bottom)[2]->gpu_data(), // pair similarity 0 or 1 + bottom[2]->gpu_data(), // pair similarity 0 or 1 diff_.gpu_data(), // the cached eltwise difference between a and b dist_sq_.gpu_data(), // the cached square distance between a and b - (*bottom)[i]->mutable_gpu_diff()); + bottom[i]->mutable_gpu_diff()); CUDA_POST_KERNEL_CHECK; } } diff --git a/src/caffe/layers/conv_layer.cpp b/src/caffe/layers/conv_layer.cpp index 58918fd4baf..8c08c100bd5 100644 --- a/src/caffe/layers/conv_layer.cpp +++ b/src/caffe/layers/conv_layer.cpp @@ -10,7 +10,7 @@ namespace caffe { template void ConvolutionLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // Configure the kernel size, padding, stride, and inputs. ConvolutionParameter conv_param = this->layer_param_.convolution_param(); CHECK(!conv_param.has_kernel_size() != @@ -89,7 +89,7 @@ void ConvolutionLayer::LayerSetUp(const vector*>& bottom, template void ConvolutionLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { num_ = bottom[0]->num(); height_ = bottom[0]->height(); width_ = bottom[0]->width(); @@ -109,8 +109,8 @@ void ConvolutionLayer::Reshape(const vector*>& bottom, height_out_ = (height_ + 2 * pad_h_ - kernel_h_) / stride_h_ + 1; width_out_ = (width_ + 2 * pad_w_ - kernel_w_) / stride_w_ + 1; - for (int top_id = 0; top_id < top->size(); ++top_id) { - (*top)[top_id]->Reshape(num_, num_output_, height_out_, width_out_); + for (int top_id = 0; top_id < top.size(); ++top_id) { + top[top_id]->Reshape(num_, num_output_, height_out_, width_out_); } // Prepare the matrix multiplication computation. // Each input will be convolved as a single GEMM. @@ -121,8 +121,8 @@ void ConvolutionLayer::Reshape(const vector*>& bottom, // overly large memory usage. col_buffer_.Reshape( 1, channels_ * kernel_h_ * kernel_w_, height_out_, width_out_); - for (int top_id = 0; top_id < top->size(); ++top_id) { - (*top)[top_id]->Reshape(num_, num_output_, height_out_, width_out_); + for (int top_id = 0; top_id < top.size(); ++top_id) { + top[top_id]->Reshape(num_, num_output_, height_out_, width_out_); } // Set up the all ones "bias multiplier" for adding biases by BLAS if (bias_term_) { @@ -133,10 +133,10 @@ void ConvolutionLayer::Reshape(const vector*>& bottom, template void ConvolutionLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->cpu_data(); - Dtype* top_data = (*top)[i]->mutable_cpu_data(); + Dtype* top_data = top[i]->mutable_cpu_data(); Dtype* col_data = col_buffer_.mutable_cpu_data(); const Dtype* weight = this->blobs_[0]->cpu_data(); int weight_offset = M_ * K_; // number of filter parameters in a group @@ -152,14 +152,14 @@ void ConvolutionLayer::Forward_cpu(const vector*>& bottom, for (int g = 0; g < group_; ++g) { caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, (Dtype)1., weight + weight_offset * g, col_data + col_offset * g, - (Dtype)0., top_data + (*top)[i]->offset(n) + top_offset * g); + (Dtype)0., top_data + top[i]->offset(n) + top_offset * g); } // Add bias. if (bias_term_) { caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, num_output_, N_, 1, (Dtype)1., this->blobs_[1]->cpu_data(), bias_multiplier_.cpu_data(), - (Dtype)1., top_data + (*top)[i]->offset(n)); + (Dtype)1., top_data + top[i]->offset(n)); } } } @@ -167,7 +167,7 @@ void ConvolutionLayer::Forward_cpu(const vector*>& bottom, template void ConvolutionLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const Dtype* weight = NULL; Dtype* weight_diff = NULL; if (this->param_propagate_down_[0]) { @@ -201,12 +201,12 @@ void ConvolutionLayer::Backward_cpu(const vector*>& top, } Dtype* col_data = col_buffer_.mutable_cpu_data(); Dtype* col_diff = col_buffer_.mutable_cpu_diff(); - const Dtype* bottom_data = (*bottom)[i]->cpu_data(); - Dtype* bottom_diff = (*bottom)[i]->mutable_cpu_diff(); + const Dtype* bottom_data = bottom[i]->cpu_data(); + Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); for (int n = 0; n < num_; ++n) { // Since we saved memory in the forward pass by not storing all col // data, we will need to recompute them. - im2col_cpu(bottom_data + (*bottom)[i]->offset(n), channels_, height_, + im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, col_data); // gradient w.r.t. weight. Note that we will accumulate diffs. @@ -232,7 +232,7 @@ void ConvolutionLayer::Backward_cpu(const vector*>& top, // col2im back to the data col2im_cpu(col_diff, channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, bottom_diff + (*bottom)[i]->offset(n)); + stride_h_, stride_w_, bottom_diff + bottom[i]->offset(n)); } } } diff --git a/src/caffe/layers/conv_layer.cu b/src/caffe/layers/conv_layer.cu index 43f76a2368f..908f5a65855 100644 --- a/src/caffe/layers/conv_layer.cu +++ b/src/caffe/layers/conv_layer.cu @@ -11,10 +11,10 @@ namespace caffe { /// @brief refer to CPU forward -- the BLAS implementation is the same. template void ConvolutionLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->gpu_data(); - Dtype* top_data = (*top)[i]->mutable_gpu_data(); + Dtype* top_data = top[i]->mutable_gpu_data(); Dtype* col_data = col_buffer_.mutable_gpu_data(); const Dtype* weight = this->blobs_[0]->gpu_data(); int weight_offset = M_ * K_; @@ -30,14 +30,14 @@ void ConvolutionLayer::Forward_gpu(const vector*>& bottom, for (int g = 0; g < group_; ++g) { caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, (Dtype)1., weight + weight_offset * g, col_data + col_offset * g, - (Dtype)0., top_data + (*top)[i]->offset(n) + top_offset * g); + (Dtype)0., top_data + top[i]->offset(n) + top_offset * g); } // Add bias. if (bias_term_) { caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, num_output_, N_, 1, (Dtype)1., this->blobs_[1]->gpu_data(), bias_multiplier_.gpu_data(), - (Dtype)1., top_data + (*top)[i]->offset(n)); + (Dtype)1., top_data + top[i]->offset(n)); } } } @@ -46,7 +46,7 @@ void ConvolutionLayer::Forward_gpu(const vector*>& bottom, /// @brief refer to CPU backward -- the BLAS implementation is the same. template void ConvolutionLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const Dtype* weight = NULL; Dtype* weight_diff = NULL; if (this->param_propagate_down_[0]) { @@ -80,12 +80,12 @@ void ConvolutionLayer::Backward_gpu(const vector*>& top, } Dtype* col_data = col_buffer_.mutable_gpu_data(); Dtype* col_diff = col_buffer_.mutable_gpu_diff(); - const Dtype* bottom_data = (*bottom)[i]->gpu_data(); - Dtype* bottom_diff = (*bottom)[i]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[i]->gpu_data(); + Dtype* bottom_diff = bottom[i]->mutable_gpu_diff(); for (int n = 0; n < num_; ++n) { // Since we saved memory in the forward pass by not storing all col // data, we will need to recompute them. - im2col_gpu(bottom_data + (*bottom)[i]->offset(n), channels_, height_, + im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, col_data); // gradient w.r.t. weight. Note that we will accumulate diffs. @@ -111,7 +111,7 @@ void ConvolutionLayer::Backward_gpu(const vector*>& top, // col2im back to the data col2im_gpu(col_diff, channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - bottom_diff + (*bottom)[i]->offset(n)); + bottom_diff + bottom[i]->offset(n)); } } } diff --git a/src/caffe/layers/cudnn_conv_layer.cpp b/src/caffe/layers/cudnn_conv_layer.cpp index 137bbab1976..f74a3dbb02f 100644 --- a/src/caffe/layers/cudnn_conv_layer.cpp +++ b/src/caffe/layers/cudnn_conv_layer.cpp @@ -19,7 +19,7 @@ namespace caffe { */ template void CuDNNConvolutionLayer::LayerSetUp( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { ConvolutionLayer::LayerSetUp(bottom, top); // Initialize CUDA streams and cuDNN. stream_ = new cudaStream_t[this->group_ * CUDNN_STREAMS_PER_GROUP]; @@ -62,7 +62,7 @@ void CuDNNConvolutionLayer::LayerSetUp( template void CuDNNConvolutionLayer::Reshape( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { ConvolutionLayer::Reshape(bottom, top); bottom_offset_ = (this->channels_ / this->group_) * this->height_ * this->width_; diff --git a/src/caffe/layers/cudnn_conv_layer.cu b/src/caffe/layers/cudnn_conv_layer.cu index 2af13309e18..6961bbeaba5 100644 --- a/src/caffe/layers/cudnn_conv_layer.cu +++ b/src/caffe/layers/cudnn_conv_layer.cu @@ -13,10 +13,10 @@ __global__ void sync_conv_groups() { } template void CuDNNConvolutionLayer::Forward_gpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->gpu_data(); - Dtype* top_data = (*top)[i]->mutable_gpu_data(); + Dtype* top_data = top[i]->mutable_gpu_data(); const Dtype* weight = this->blobs_[0]->gpu_data(); // Forward through cuDNN in parallel over groups. @@ -48,7 +48,7 @@ void CuDNNConvolutionLayer::Forward_gpu( template void CuDNNConvolutionLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const Dtype* weight = NULL; Dtype* weight_diff = NULL; if (this->param_propagate_down_[0]) { @@ -75,7 +75,7 @@ void CuDNNConvolutionLayer::Backward_gpu(const vector*>& top, // Gradient w.r.t. weights. if (this->param_propagate_down_[0]) { - const Dtype* bottom_data = (*bottom)[i]->gpu_data(); + const Dtype* bottom_data = bottom[i]->gpu_data(); CUDNN_CHECK(cudnnConvolutionBackwardFilter(handle_[1*this->group_ + g], bottom_descs_[i], bottom_data + bottom_offset_ * g, top_descs_[i], top_diff + top_offset_ * g, @@ -86,7 +86,7 @@ void CuDNNConvolutionLayer::Backward_gpu(const vector*>& top, // Gradient w.r.t. bottom data. if (propagate_down[i]) { - Dtype* bottom_diff = (*bottom)[i]->mutable_gpu_diff(); + Dtype* bottom_diff = bottom[i]->mutable_gpu_diff(); CUDNN_CHECK(cudnnConvolutionBackwardData(handle_[2*this->group_ + g], filter_desc_, weight + weight_offset_ * g, top_descs_[i], top_diff + top_offset_ * g, diff --git a/src/caffe/layers/cudnn_pooling_layer.cpp b/src/caffe/layers/cudnn_pooling_layer.cpp index 5aea0dc886e..2af9d21be26 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cpp +++ b/src/caffe/layers/cudnn_pooling_layer.cpp @@ -11,7 +11,7 @@ namespace caffe { template void CuDNNPoolingLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { PoolingLayer::LayerSetUp(bottom, top); CUDNN_CHECK(cudnnCreate(&handle_)); @@ -24,7 +24,7 @@ void CuDNNPoolingLayer::LayerSetUp(const vector*>& bottom, template void CuDNNPoolingLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { PoolingLayer::Reshape(bottom, top); cudnn::setTensor4dDesc(&bottom_desc_, bottom[0]->num(), this->channels_, this->height_, this->width_); diff --git a/src/caffe/layers/cudnn_pooling_layer.cu b/src/caffe/layers/cudnn_pooling_layer.cu index 99c409dcc96..9d270ed25d5 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cu +++ b/src/caffe/layers/cudnn_pooling_layer.cu @@ -11,22 +11,22 @@ namespace caffe { template void CuDNNPoolingLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // Fallback to Caffe for padded pooling, max top mask. - if ((this->pad_h_ > 0 || this->pad_w_ > 0) || (*top).size() > 1) { + if ((this->pad_h_ > 0 || this->pad_w_ > 0) || top.size() > 1) { LOG(WARNING) << "Falling back to standard Caffe for padded pooling."; return PoolingLayer::Forward_gpu(bottom, top); } const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); CUDNN_CHECK(cudnnPoolingForward(handle_, pooling_desc_, bottom_desc_, bottom_data, top_desc_, top_data)); } template void CuDNNPoolingLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (!propagate_down[0]) { return; } @@ -39,8 +39,8 @@ void CuDNNPoolingLayer::Backward_gpu(const vector*>& top, const Dtype* top_diff = top[0]->gpu_diff(); const Dtype* top_data = top[0]->gpu_data(); - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); CUDNN_CHECK(cudnnPoolingBackward(handle_, pooling_desc_, top_desc_, top_data, top_desc_, top_diff, bottom_desc_, bottom_data, bottom_desc_, bottom_diff)); diff --git a/src/caffe/layers/cudnn_relu_layer.cpp b/src/caffe/layers/cudnn_relu_layer.cpp index 083868f572f..20f486f6bcf 100644 --- a/src/caffe/layers/cudnn_relu_layer.cpp +++ b/src/caffe/layers/cudnn_relu_layer.cpp @@ -9,7 +9,7 @@ namespace caffe { template void CuDNNReLULayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { ReLULayer::LayerSetUp(bottom, top); // initialize cuDNN CUDNN_CHECK(cudnnCreate(&handle_)); @@ -19,7 +19,7 @@ void CuDNNReLULayer::LayerSetUp(const vector*>& bottom, template void CuDNNReLULayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { ReLULayer::Reshape(bottom, top); const int N = bottom[0]->num(); const int K = bottom[0]->channels(); diff --git a/src/caffe/layers/cudnn_relu_layer.cu b/src/caffe/layers/cudnn_relu_layer.cu index a8519f340cc..e3900f37ab9 100644 --- a/src/caffe/layers/cudnn_relu_layer.cu +++ b/src/caffe/layers/cudnn_relu_layer.cu @@ -9,14 +9,14 @@ namespace caffe { template void CuDNNReLULayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // Fallback to standard Caffe for leaky ReLU. if (ReLULayer::layer_param_.relu_param().negative_slope() != 0) { return ReLULayer::Forward_gpu(bottom, top); } const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); CUDNN_CHECK(cudnnActivationForward(this->handle_, CUDNN_ACTIVATION_RELU, this->bottom_desc_, bottom_data, this->top_desc_, top_data)); @@ -25,7 +25,7 @@ void CuDNNReLULayer::Forward_gpu(const vector*>& bottom, template void CuDNNReLULayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (!propagate_down[0]) { return; } @@ -37,8 +37,8 @@ void CuDNNReLULayer::Backward_gpu(const vector*>& top, const Dtype* top_data = top[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); CUDNN_CHECK(cudnnActivationBackward(this->handle_, CUDNN_ACTIVATION_RELU, this->top_desc_, top_data, this->top_desc_, top_diff, diff --git a/src/caffe/layers/cudnn_sigmoid_layer.cpp b/src/caffe/layers/cudnn_sigmoid_layer.cpp index 3fe800db6f4..a94c0040a28 100644 --- a/src/caffe/layers/cudnn_sigmoid_layer.cpp +++ b/src/caffe/layers/cudnn_sigmoid_layer.cpp @@ -9,7 +9,7 @@ namespace caffe { template void CuDNNSigmoidLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { SigmoidLayer::LayerSetUp(bottom, top); // initialize cuDNN CUDNN_CHECK(cudnnCreate(&handle_)); @@ -19,7 +19,7 @@ void CuDNNSigmoidLayer::LayerSetUp(const vector*>& bottom, template void CuDNNSigmoidLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { SigmoidLayer::Reshape(bottom, top); const int N = bottom[0]->num(); const int K = bottom[0]->channels(); diff --git a/src/caffe/layers/cudnn_sigmoid_layer.cu b/src/caffe/layers/cudnn_sigmoid_layer.cu index 43019bd78ae..50bf5fcb9e0 100644 --- a/src/caffe/layers/cudnn_sigmoid_layer.cu +++ b/src/caffe/layers/cudnn_sigmoid_layer.cu @@ -9,9 +9,9 @@ namespace caffe { template void CuDNNSigmoidLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); CUDNN_CHECK(cudnnActivationForward(this->handle_, CUDNN_ACTIVATION_SIGMOID, this->bottom_desc_, bottom_data, this->top_desc_, top_data)); @@ -20,15 +20,15 @@ void CuDNNSigmoidLayer::Forward_gpu(const vector*>& bottom, template void CuDNNSigmoidLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (!propagate_down[0]) { return; } const Dtype* top_data = top[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); CUDNN_CHECK(cudnnActivationBackward(this->handle_, CUDNN_ACTIVATION_SIGMOID, this->top_desc_, top_data, this->top_desc_, top_diff, diff --git a/src/caffe/layers/cudnn_softmax_layer.cpp b/src/caffe/layers/cudnn_softmax_layer.cpp index 79ba5237ae3..1a0f406bf38 100644 --- a/src/caffe/layers/cudnn_softmax_layer.cpp +++ b/src/caffe/layers/cudnn_softmax_layer.cpp @@ -13,7 +13,7 @@ namespace caffe { template void CuDNNSoftmaxLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { SoftmaxLayer::LayerSetUp(bottom, top); // Initialize CUDNN. CUDNN_CHECK(cudnnCreate(&handle_)); @@ -23,7 +23,7 @@ void CuDNNSoftmaxLayer::LayerSetUp(const vector*>& bottom, template void CuDNNSoftmaxLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { SoftmaxLayer::Reshape(bottom, top); int N = bottom[0]->num(); int K = bottom[0]->channels(); diff --git a/src/caffe/layers/cudnn_softmax_layer.cu b/src/caffe/layers/cudnn_softmax_layer.cu index 300bdc496c8..aef66730bff 100644 --- a/src/caffe/layers/cudnn_softmax_layer.cu +++ b/src/caffe/layers/cudnn_softmax_layer.cu @@ -13,9 +13,9 @@ namespace caffe { template void CuDNNSoftmaxLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); CUDNN_CHECK(cudnnSoftmaxForward(handle_, CUDNN_SOFTMAX_ACCURATE, CUDNN_SOFTMAX_MODE_CHANNEL, bottom_desc_, bottom_data, top_desc_, top_data)); @@ -23,12 +23,12 @@ void CuDNNSoftmaxLayer::Forward_gpu(const vector*>& bottom, template void CuDNNSoftmaxLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (propagate_down[0]) { const Dtype* top_data = top[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); CUDNN_CHECK(cudnnSoftmaxBackward(handle_, CUDNN_SOFTMAX_ACCURATE, CUDNN_SOFTMAX_MODE_CHANNEL, top_desc_, top_data, top_desc_, top_diff, bottom_desc_, bottom_diff)); diff --git a/src/caffe/layers/cudnn_tanh_layer.cpp b/src/caffe/layers/cudnn_tanh_layer.cpp index 7a5c06f6596..39a3e14b3c8 100644 --- a/src/caffe/layers/cudnn_tanh_layer.cpp +++ b/src/caffe/layers/cudnn_tanh_layer.cpp @@ -9,7 +9,7 @@ namespace caffe { template void CuDNNTanHLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { TanHLayer::LayerSetUp(bottom, top); // initialize cuDNN CUDNN_CHECK(cudnnCreate(&handle_)); @@ -19,7 +19,7 @@ void CuDNNTanHLayer::LayerSetUp(const vector*>& bottom, template void CuDNNTanHLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { TanHLayer::Reshape(bottom, top); const int N = bottom[0]->num(); const int K = bottom[0]->channels(); diff --git a/src/caffe/layers/cudnn_tanh_layer.cu b/src/caffe/layers/cudnn_tanh_layer.cu index c475b08c0ee..20f887de8d0 100644 --- a/src/caffe/layers/cudnn_tanh_layer.cu +++ b/src/caffe/layers/cudnn_tanh_layer.cu @@ -9,9 +9,9 @@ namespace caffe { template void CuDNNTanHLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); CUDNN_CHECK(cudnnActivationForward(this->handle_, CUDNN_ACTIVATION_TANH, this->bottom_desc_, bottom_data, this->top_desc_, top_data)); @@ -20,15 +20,15 @@ void CuDNNTanHLayer::Forward_gpu(const vector*>& bottom, template void CuDNNTanHLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (!propagate_down[0]) { return; } const Dtype* top_data = top[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); CUDNN_CHECK(cudnnActivationBackward(this->handle_, CUDNN_ACTIVATION_TANH, this->top_desc_, top_data, this->top_desc_, top_diff, diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index d2071e2fa4f..b3b6bf3d64f 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -34,7 +34,7 @@ DataLayer::~DataLayer() { template void DataLayer::DataLayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // Initialize DB switch (this->layer_param_.data_param().backend()) { case DataParameter_DB_LEVELDB: @@ -114,23 +114,23 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // image int crop_size = this->layer_param_.transform_param().crop_size(); if (crop_size > 0) { - (*top)[0]->Reshape(this->layer_param_.data_param().batch_size(), + top[0]->Reshape(this->layer_param_.data_param().batch_size(), datum.channels(), crop_size, crop_size); this->prefetch_data_.Reshape(this->layer_param_.data_param().batch_size(), datum.channels(), crop_size, crop_size); } else { - (*top)[0]->Reshape( + top[0]->Reshape( this->layer_param_.data_param().batch_size(), datum.channels(), datum.height(), datum.width()); this->prefetch_data_.Reshape(this->layer_param_.data_param().batch_size(), datum.channels(), datum.height(), datum.width()); } - LOG(INFO) << "output data size: " << (*top)[0]->num() << "," - << (*top)[0]->channels() << "," << (*top)[0]->height() << "," - << (*top)[0]->width(); + LOG(INFO) << "output data size: " << top[0]->num() << "," + << top[0]->channels() << "," << top[0]->height() << "," + << top[0]->width(); // label if (this->output_labels_) { - (*top)[1]->Reshape(this->layer_param_.data_param().batch_size(), 1, 1, 1); + top[1]->Reshape(this->layer_param_.data_param().batch_size(), 1, 1, 1); this->prefetch_label_.Reshape(this->layer_param_.data_param().batch_size(), 1, 1, 1); } diff --git a/src/caffe/layers/dropout_layer.cpp b/src/caffe/layers/dropout_layer.cpp index 47feb1d2543..f88027c7062 100644 --- a/src/caffe/layers/dropout_layer.cpp +++ b/src/caffe/layers/dropout_layer.cpp @@ -12,7 +12,7 @@ namespace caffe { template void DropoutLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { NeuronLayer::LayerSetUp(bottom, top); threshold_ = this->layer_param_.dropout_param().dropout_ratio(); DCHECK(threshold_ > 0.); @@ -23,7 +23,7 @@ void DropoutLayer::LayerSetUp(const vector*>& bottom, template void DropoutLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { NeuronLayer::Reshape(bottom, top); // Set up the cache for random number generation rand_vec_.Reshape(bottom[0]->num(), bottom[0]->channels(), @@ -32,9 +32,9 @@ void DropoutLayer::Reshape(const vector*>& bottom, template void DropoutLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); unsigned int* mask = rand_vec_.mutable_cpu_data(); const int count = bottom[0]->count(); if (Caffe::phase() == Caffe::TRAIN) { @@ -51,13 +51,13 @@ void DropoutLayer::Forward_cpu(const vector*>& bottom, template void DropoutLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { const Dtype* top_diff = top[0]->cpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); if (Caffe::phase() == Caffe::TRAIN) { const unsigned int* mask = rand_vec_.cpu_data(); - const int count = (*bottom)[0]->count(); + const int count = bottom[0]->count(); for (int i = 0; i < count; ++i) { bottom_diff[i] = top_diff[i] * mask[i] * scale_; } diff --git a/src/caffe/layers/dropout_layer.cu b/src/caffe/layers/dropout_layer.cu index 9756c862183..fa737b86a89 100644 --- a/src/caffe/layers/dropout_layer.cu +++ b/src/caffe/layers/dropout_layer.cu @@ -22,9 +22,9 @@ __global__ void DropoutForward(const int n, const Dtype* in, template void DropoutLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); const int count = bottom[0]->count(); if (Caffe::phase() == Caffe::TRAIN) { unsigned int* mask = @@ -52,14 +52,14 @@ __global__ void DropoutBackward(const int n, const Dtype* in_diff, template void DropoutLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { const Dtype* top_diff = top[0]->gpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); if (Caffe::phase() == Caffe::TRAIN) { const unsigned int* mask = static_cast(rand_vec_.gpu_data()); - const int count = (*bottom)[0]->count(); + const int count = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) DropoutBackward<<>>( diff --git a/src/caffe/layers/dummy_data_layer.cpp b/src/caffe/layers/dummy_data_layer.cpp index 883f2528ef8..6aeba5487b8 100644 --- a/src/caffe/layers/dummy_data_layer.cpp +++ b/src/caffe/layers/dummy_data_layer.cpp @@ -8,8 +8,8 @@ namespace caffe { template void DummyDataLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { - const int num_top = top->size(); + 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 || @@ -70,7 +70,7 @@ void DummyDataLayer::LayerSetUp(const vector*>& bottom, (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); + top[i]->Reshape(num, channels, height, width); } // Run Forward once, with refill_ inverted, to fill the constant Blobs. this->Forward(bottom, top); @@ -83,11 +83,11 @@ void DummyDataLayer::LayerSetUp(const vector*>& bottom, template void DummyDataLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { - for (int i = 0; i < top->size(); ++i) { + 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]); + fillers_[filler_id]->Fill(top[i]); } } } diff --git a/src/caffe/layers/eltwise_layer.cpp b/src/caffe/layers/eltwise_layer.cpp index 569560f97d3..2830d6db195 100644 --- a/src/caffe/layers/eltwise_layer.cpp +++ b/src/caffe/layers/eltwise_layer.cpp @@ -9,7 +9,7 @@ namespace caffe { template void EltwiseLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { CHECK(this->layer_param().eltwise_param().coeff_size() == 0 || this->layer_param().eltwise_param().coeff_size() == bottom.size()) << "Eltwise Layer takes one coefficient per bottom blob."; @@ -30,7 +30,7 @@ void EltwiseLayer::LayerSetUp(const vector*>& bottom, template void EltwiseLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const int num = bottom[0]->num(); const int channels = bottom[0]->channels(); const int height = bottom[0]->height(); @@ -41,22 +41,22 @@ void EltwiseLayer::Reshape(const vector*>& bottom, CHECK_EQ(height, bottom[i]->height()); CHECK_EQ(width, bottom[i]->width()); } - (*top)[0]->Reshape(num, channels, height, width); + top[0]->Reshape(num, channels, height, width); // If max operation, we will initialize the vector index part. if (this->layer_param_.eltwise_param().operation() == - EltwiseParameter_EltwiseOp_MAX && top->size() == 1) { + EltwiseParameter_EltwiseOp_MAX && top.size() == 1) { max_idx_.Reshape(bottom[0]->num(), channels, height, width); } } template void EltwiseLayer::Forward_cpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { int* mask = NULL; const Dtype* bottom_data_a = NULL; const Dtype* bottom_data_b = NULL; - const int count = (*top)[0]->count(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const int count = top[0]->count(); + Dtype* top_data = top[0]->mutable_cpu_data(); switch (op_) { case EltwiseParameter_EltwiseOp_PROD: caffe_mul(count, bottom[0]->cpu_data(), bottom[1]->cpu_data(), top_data); @@ -106,26 +106,26 @@ void EltwiseLayer::Forward_cpu( template void EltwiseLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const int* mask = NULL; const int count = top[0]->count(); const Dtype* top_data = top[0]->cpu_data(); const Dtype* top_diff = top[0]->cpu_diff(); - for (int i = 0; i < bottom->size(); ++i) { + for (int i = 0; i < bottom.size(); ++i) { if (propagate_down[i]) { - const Dtype* bottom_data = (*bottom)[i]->cpu_data(); - Dtype* bottom_diff = (*bottom)[i]->mutable_cpu_diff(); + const Dtype* bottom_data = bottom[i]->cpu_data(); + Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); switch (op_) { case EltwiseParameter_EltwiseOp_PROD: if (stable_prod_grad_) { bool initialized = false; - for (int j = 0; j < bottom->size(); ++j) { + for (int j = 0; j < bottom.size(); ++j) { if (i == j) { continue; } if (!initialized) { - caffe_copy(count, (*bottom)[j]->cpu_data(), bottom_diff); + caffe_copy(count, bottom[j]->cpu_data(), bottom_diff); initialized = true; } else { - caffe_mul(count, (*bottom)[j]->cpu_data(), bottom_diff, + caffe_mul(count, bottom[j]->cpu_data(), bottom_diff, bottom_diff); } } diff --git a/src/caffe/layers/eltwise_layer.cu b/src/caffe/layers/eltwise_layer.cu index 16cb6cc77e3..9295cc6ad11 100644 --- a/src/caffe/layers/eltwise_layer.cu +++ b/src/caffe/layers/eltwise_layer.cu @@ -33,10 +33,10 @@ __global__ void MaxForward(const int nthreads, const Dtype* bottom_data_a, template void EltwiseLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { int* mask = NULL; - const int count = (*top)[0]->count(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const int count = top[0]->count(); + Dtype* top_data = top[0]->mutable_gpu_data(); switch (op_) { case EltwiseParameter_EltwiseOp_PROD: caffe_gpu_mul(count, bottom[0]->gpu_data(), bottom[1]->gpu_data(), @@ -82,26 +82,26 @@ __global__ void MaxBackward(const int nthreads, const Dtype* top_diff, template void EltwiseLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const int* mask = NULL; const int count = top[0]->count(); const Dtype* top_data = top[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - for (int i = 0; i < bottom->size(); ++i) { + for (int i = 0; i < bottom.size(); ++i) { if (propagate_down[i]) { - const Dtype* bottom_data = (*bottom)[i]->gpu_data(); - Dtype* bottom_diff = (*bottom)[i]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[i]->gpu_data(); + Dtype* bottom_diff = bottom[i]->mutable_gpu_diff(); switch (op_) { case EltwiseParameter_EltwiseOp_PROD: if (stable_prod_grad_) { bool initialized = false; - for (int j = 0; j < bottom->size(); ++j) { + for (int j = 0; j < bottom.size(); ++j) { if (i == j) { continue; } if (!initialized) { - caffe_copy(count, (*bottom)[j]->gpu_data(), bottom_diff); + caffe_copy(count, bottom[j]->gpu_data(), bottom_diff); initialized = true; } else { - caffe_gpu_mul(count, (*bottom)[j]->gpu_data(), bottom_diff, + caffe_gpu_mul(count, bottom[j]->gpu_data(), bottom_diff, bottom_diff); } } diff --git a/src/caffe/layers/euclidean_loss_layer.cpp b/src/caffe/layers/euclidean_loss_layer.cpp index 1b4a13d2ddc..abc8610eef6 100644 --- a/src/caffe/layers/euclidean_loss_layer.cpp +++ b/src/caffe/layers/euclidean_loss_layer.cpp @@ -9,7 +9,7 @@ namespace caffe { template void EuclideanLossLayer::Reshape( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::Reshape(bottom, top); CHECK_EQ(bottom[0]->channels(), bottom[1]->channels()); CHECK_EQ(bottom[0]->height(), bottom[1]->height()); @@ -20,7 +20,7 @@ void EuclideanLossLayer::Reshape( template void EuclideanLossLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { int count = bottom[0]->count(); caffe_sub( count, @@ -29,22 +29,22 @@ void EuclideanLossLayer::Forward_cpu(const vector*>& bottom, diff_.mutable_cpu_data()); Dtype dot = caffe_cpu_dot(count, diff_.cpu_data(), diff_.cpu_data()); Dtype loss = dot / bottom[0]->num() / Dtype(2); - (*top)[0]->mutable_cpu_data()[0] = loss; + top[0]->mutable_cpu_data()[0] = loss; } template void EuclideanLossLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { for (int i = 0; i < 2; ++i) { if (propagate_down[i]) { const Dtype sign = (i == 0) ? 1 : -1; - const Dtype alpha = sign * top[0]->cpu_diff()[0] / (*bottom)[i]->num(); + const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num(); caffe_cpu_axpby( - (*bottom)[i]->count(), // count + bottom[i]->count(), // count alpha, // alpha diff_.cpu_data(), // a Dtype(0), // beta - (*bottom)[i]->mutable_cpu_diff()); // b + bottom[i]->mutable_cpu_diff()); // b } } } diff --git a/src/caffe/layers/euclidean_loss_layer.cu b/src/caffe/layers/euclidean_loss_layer.cu index 70b1b9ee9ea..0f0c1a86f9d 100644 --- a/src/caffe/layers/euclidean_loss_layer.cu +++ b/src/caffe/layers/euclidean_loss_layer.cu @@ -9,7 +9,7 @@ namespace caffe { template void EuclideanLossLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { int count = bottom[0]->count(); caffe_gpu_sub( count, @@ -19,22 +19,22 @@ void EuclideanLossLayer::Forward_gpu(const vector*>& bottom, Dtype dot; caffe_gpu_dot(count, diff_.gpu_data(), diff_.gpu_data(), &dot); Dtype loss = dot / bottom[0]->num() / Dtype(2); - (*top)[0]->mutable_cpu_data()[0] = loss; + top[0]->mutable_cpu_data()[0] = loss; } template void EuclideanLossLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { for (int i = 0; i < 2; ++i) { if (propagate_down[i]) { const Dtype sign = (i == 0) ? 1 : -1; - const Dtype alpha = sign * top[0]->cpu_diff()[0] / (*bottom)[i]->num(); + const Dtype alpha = sign * top[0]->cpu_diff()[0] / bottom[i]->num(); caffe_gpu_axpby( - (*bottom)[i]->count(), // count + bottom[i]->count(), // count alpha, // alpha diff_.gpu_data(), // a Dtype(0), // beta - (*bottom)[i]->mutable_gpu_diff()); // b + bottom[i]->mutable_gpu_diff()); // b } } } diff --git a/src/caffe/layers/flatten_layer.cpp b/src/caffe/layers/flatten_layer.cpp index 65310cd1669..44df96d8436 100644 --- a/src/caffe/layers/flatten_layer.cpp +++ b/src/caffe/layers/flatten_layer.cpp @@ -8,25 +8,25 @@ namespace caffe { template void FlattenLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { int channels_out = bottom[0]->channels() * bottom[0]->height() * bottom[0]->width(); - (*top)[0]->Reshape(bottom[0]->num(), channels_out, 1, 1); + top[0]->Reshape(bottom[0]->num(), channels_out, 1, 1); count_ = bottom[0]->num() * channels_out; CHECK_EQ(count_, bottom[0]->count()); - CHECK_EQ(count_, (*top)[0]->count()); + CHECK_EQ(count_, top[0]->count()); } template void FlattenLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { - (*top)[0]->ShareData(*bottom[0]); + const vector*>& top) { + top[0]->ShareData(*bottom[0]); } template void FlattenLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { - (*bottom)[0]->ShareDiff(*top[0]); + const vector& propagate_down, const vector*>& bottom) { + bottom[0]->ShareDiff(*top[0]); } #ifdef CPU_ONLY diff --git a/src/caffe/layers/flatten_layer.cu b/src/caffe/layers/flatten_layer.cu index ff23f523fee..ef89bab6ff4 100644 --- a/src/caffe/layers/flatten_layer.cu +++ b/src/caffe/layers/flatten_layer.cu @@ -8,14 +8,14 @@ namespace caffe { template void FlattenLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { - (*top)[0]->ShareData(*bottom[0]); + const vector*>& top) { + top[0]->ShareData(*bottom[0]); } template void FlattenLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { - (*bottom)[0]->ShareDiff(*top[0]); + const vector& propagate_down, const vector*>& bottom) { + bottom[0]->ShareDiff(*top[0]); } INSTANTIATE_CLASS(FlattenLayer); diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index 1f2a83582f2..ff25cbb621f 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -51,7 +51,7 @@ void HDF5DataLayer::LoadHDF5FileData(const char* filename) { template void HDF5DataLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // Read the source to parse the filenames. const string& source = this->layer_param_.hdf5_data_param().source(); LOG(INFO) << "Loading filename from " << source; @@ -74,21 +74,21 @@ void HDF5DataLayer::LayerSetUp(const vector*>& bottom, // Reshape blobs. const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); - (*top)[0]->Reshape(batch_size, data_blob_.channels(), + top[0]->Reshape(batch_size, data_blob_.channels(), data_blob_.width(), data_blob_.height()); - (*top)[1]->Reshape(batch_size, label_blob_.channels(), + top[1]->Reshape(batch_size, label_blob_.channels(), label_blob_.width(), label_blob_.height()); - LOG(INFO) << "output data size: " << (*top)[0]->num() << "," - << (*top)[0]->channels() << "," << (*top)[0]->height() << "," - << (*top)[0]->width(); + LOG(INFO) << "output data size: " << top[0]->num() << "," + << top[0]->channels() << "," << top[0]->height() << "," + << top[0]->width(); } template void HDF5DataLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); - const int data_count = (*top)[0]->count() / (*top)[0]->num(); - const int label_data_count = (*top)[1]->count() / (*top)[1]->num(); + const int data_count = top[0]->count() / top[0]->num(); + const int label_data_count = top[1]->count() / top[1]->num(); for (int i = 0; i < batch_size; ++i, ++current_row_) { if (current_row_ == data_blob_.num()) { @@ -103,10 +103,10 @@ void HDF5DataLayer::Forward_cpu(const vector*>& bottom, current_row_ = 0; } caffe_copy(data_count, &data_blob_.cpu_data()[current_row_ * data_count], - &(*top)[0]->mutable_cpu_data()[i * data_count]); + &top[0]->mutable_cpu_data()[i * data_count]); caffe_copy(label_data_count, &label_blob_.cpu_data()[current_row_ * label_data_count], - &(*top)[1]->mutable_cpu_data()[i * label_data_count]); + &top[1]->mutable_cpu_data()[i * label_data_count]); } } diff --git a/src/caffe/layers/hdf5_data_layer.cu b/src/caffe/layers/hdf5_data_layer.cu index 79cc536eb28..f671ea12d76 100644 --- a/src/caffe/layers/hdf5_data_layer.cu +++ b/src/caffe/layers/hdf5_data_layer.cu @@ -18,10 +18,10 @@ namespace caffe { template void HDF5DataLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); - const int data_count = (*top)[0]->count() / (*top)[0]->num(); - const int label_data_count = (*top)[1]->count() / (*top)[1]->num(); + const int data_count = top[0]->count() / top[0]->num(); + const int label_data_count = top[1]->count() / top[1]->num(); for (int i = 0; i < batch_size; ++i, ++current_row_) { if (current_row_ == data_blob_.num()) { @@ -39,10 +39,10 @@ void HDF5DataLayer::Forward_gpu(const vector*>& bottom, } caffe_copy(data_count, &data_blob_.cpu_data()[current_row_ * data_count], - &(*top)[0]->mutable_gpu_data()[i * data_count]); + &top[0]->mutable_gpu_data()[i * data_count]); caffe_copy(label_data_count, &label_blob_.cpu_data()[current_row_ * label_data_count], - &(*top)[1]->mutable_gpu_data()[i * label_data_count]); + &top[1]->mutable_gpu_data()[i * label_data_count]); } } diff --git a/src/caffe/layers/hdf5_output_layer.cpp b/src/caffe/layers/hdf5_output_layer.cpp index 3cdbbb31a6a..b41d387a786 100644 --- a/src/caffe/layers/hdf5_output_layer.cpp +++ b/src/caffe/layers/hdf5_output_layer.cpp @@ -40,7 +40,7 @@ void HDF5OutputLayer::SaveBlobs() { template void HDF5OutputLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { CHECK_GE(bottom.size(), 2); CHECK_EQ(bottom[0]->num(), bottom[1]->num()); data_blob_.Reshape(bottom[0]->num(), bottom[0]->channels(), @@ -61,7 +61,7 @@ void HDF5OutputLayer::Forward_cpu(const vector*>& bottom, template void HDF5OutputLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { return; } diff --git a/src/caffe/layers/hdf5_output_layer.cu b/src/caffe/layers/hdf5_output_layer.cu index 0813c02a440..929c1ad8e22 100644 --- a/src/caffe/layers/hdf5_output_layer.cu +++ b/src/caffe/layers/hdf5_output_layer.cu @@ -13,7 +13,7 @@ namespace caffe { template void HDF5OutputLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { CHECK_GE(bottom.size(), 2); CHECK_EQ(bottom[0]->num(), bottom[1]->num()); data_blob_.Reshape(bottom[0]->num(), bottom[0]->channels(), @@ -34,7 +34,7 @@ void HDF5OutputLayer::Forward_gpu(const vector*>& bottom, template void HDF5OutputLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { return; } diff --git a/src/caffe/layers/hinge_loss_layer.cpp b/src/caffe/layers/hinge_loss_layer.cpp index 8022aae279c..f09916e2556 100644 --- a/src/caffe/layers/hinge_loss_layer.cpp +++ b/src/caffe/layers/hinge_loss_layer.cpp @@ -12,7 +12,7 @@ namespace caffe { template void HingeLossLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); const Dtype* label = bottom[1]->cpu_data(); @@ -30,7 +30,7 @@ void HingeLossLayer::Forward_cpu(const vector*>& bottom, Dtype(0), 1 + bottom_diff[i * dim + j]); } } - Dtype* loss = (*top)[0]->mutable_cpu_data(); + Dtype* loss = top[0]->mutable_cpu_data(); switch (this->layer_param_.hinge_loss_param().norm()) { case HingeLossParameter_Norm_L1: loss[0] = caffe_cpu_asum(count, bottom_diff) / num; @@ -45,16 +45,16 @@ void HingeLossLayer::Forward_cpu(const vector*>& bottom, template void HingeLossLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (propagate_down[1]) { LOG(FATAL) << this->type_name() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); - const Dtype* label = (*bottom)[1]->cpu_data(); - int num = (*bottom)[0]->num(); - int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + const Dtype* label = bottom[1]->cpu_data(); + int num = bottom[0]->num(); + int count = bottom[0]->count(); int dim = count / num; for (int i = 0; i < num; ++i) { diff --git a/src/caffe/layers/im2col_layer.cpp b/src/caffe/layers/im2col_layer.cpp index 870d5a9bde3..10588cebe7f 100644 --- a/src/caffe/layers/im2col_layer.cpp +++ b/src/caffe/layers/im2col_layer.cpp @@ -9,7 +9,7 @@ namespace caffe { template void Im2colLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { ConvolutionParameter conv_param = this->layer_param_.convolution_param(); CHECK(!conv_param.has_kernel_size() != !(conv_param.has_kernel_h() && conv_param.has_kernel_w())) @@ -49,11 +49,11 @@ void Im2colLayer::LayerSetUp(const vector*>& bottom, template void Im2colLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { channels_ = bottom[0]->channels(); height_ = bottom[0]->height(); width_ = bottom[0]->width(); - (*top)[0]->Reshape( + top[0]->Reshape( bottom[0]->num(), channels_ * kernel_h_ * kernel_w_, (height_ + 2 * pad_h_ - kernel_h_) / stride_h_ + 1, (width_ + 2 * pad_w_ - kernel_w_) / stride_w_ + 1); @@ -61,25 +61,25 @@ void Im2colLayer::Reshape(const vector*>& bottom, template void Im2colLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); for (int n = 0; n < bottom[0]->num(); ++n) { im2col_cpu(bottom_data + bottom[0]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, top_data + (*top)[0]->offset(n)); + stride_h_, stride_w_, top_data + top[0]->offset(n)); } } template void Im2colLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const Dtype* top_diff = top[0]->cpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); for (int n = 0; n < top[0]->num(); ++n) { col2im_cpu(top_diff + top[0]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, bottom_diff + (*bottom)[0]->offset(n)); + stride_h_, stride_w_, bottom_diff + bottom[0]->offset(n)); } } diff --git a/src/caffe/layers/im2col_layer.cu b/src/caffe/layers/im2col_layer.cu index 8df061d88e1..bad789c17fe 100644 --- a/src/caffe/layers/im2col_layer.cu +++ b/src/caffe/layers/im2col_layer.cu @@ -9,25 +9,25 @@ namespace caffe { template void Im2colLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); for (int n = 0; n < bottom[0]->num(); ++n) { im2col_gpu(bottom_data + bottom[0]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, top_data + (*top)[0]->offset(n)); + stride_h_, stride_w_, top_data + top[0]->offset(n)); } } template void Im2colLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const Dtype* top_diff = top[0]->gpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); for (int n = 0; n < top[0]->num(); ++n) { col2im_gpu(top_diff + top[0]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, bottom_diff + (*bottom)[0]->offset(n)); + stride_h_, stride_w_, bottom_diff + bottom[0]->offset(n)); } } diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index e4a575bec93..dc972f13799 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -19,7 +19,7 @@ ImageDataLayer::~ImageDataLayer() { template void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const int new_height = this->layer_param_.image_data_param().new_height(); const int new_width = this->layer_param_.image_data_param().new_width(); CHECK((new_height == 0 && new_width == 0) || @@ -61,20 +61,20 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, const int crop_size = this->layer_param_.transform_param().crop_size(); const int batch_size = this->layer_param_.image_data_param().batch_size(); if (crop_size > 0) { - (*top)[0]->Reshape(batch_size, datum.channels(), crop_size, crop_size); + top[0]->Reshape(batch_size, datum.channels(), crop_size, crop_size); this->prefetch_data_.Reshape(batch_size, datum.channels(), crop_size, crop_size); } else { - (*top)[0]->Reshape(batch_size, datum.channels(), datum.height(), + top[0]->Reshape(batch_size, datum.channels(), datum.height(), datum.width()); this->prefetch_data_.Reshape(batch_size, datum.channels(), datum.height(), datum.width()); } - LOG(INFO) << "output data size: " << (*top)[0]->num() << "," - << (*top)[0]->channels() << "," << (*top)[0]->height() << "," - << (*top)[0]->width(); + LOG(INFO) << "output data size: " << top[0]->num() << "," + << top[0]->channels() << "," << top[0]->height() << "," + << top[0]->width(); // label - (*top)[1]->Reshape(batch_size, 1, 1, 1); + top[1]->Reshape(batch_size, 1, 1, 1); this->prefetch_label_.Reshape(batch_size, 1, 1, 1); // datum size this->datum_channels_ = datum.channels(); diff --git a/src/caffe/layers/infogain_loss_layer.cpp b/src/caffe/layers/infogain_loss_layer.cpp index 894cb69811a..c4dc1b4513a 100644 --- a/src/caffe/layers/infogain_loss_layer.cpp +++ b/src/caffe/layers/infogain_loss_layer.cpp @@ -12,7 +12,7 @@ namespace caffe { template void InfogainLossLayer::LayerSetUp( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::LayerSetUp(bottom, top); if (bottom.size() < 3) { CHECK(this->layer_param_.infogain_loss_param().has_source()) @@ -26,7 +26,7 @@ void InfogainLossLayer::LayerSetUp( template void InfogainLossLayer::Reshape( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::Reshape(bottom, top); Blob* infogain = NULL; if (bottom.size() < 3) { @@ -48,7 +48,7 @@ void InfogainLossLayer::Reshape( template void InfogainLossLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); const Dtype* bottom_label = bottom[1]->cpu_data(); const Dtype* infogain_mat = NULL; @@ -67,13 +67,13 @@ void InfogainLossLayer::Forward_cpu(const vector*>& bottom, loss -= infogain_mat[label * dim + j] * log(prob); } } - (*top)[0]->mutable_cpu_data()[0] = loss / num; + top[0]->mutable_cpu_data()[0] = loss / num; } template void InfogainLossLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[1]) { LOG(FATAL) << this->type_name() << " Layer cannot backpropagate to label inputs."; @@ -83,17 +83,17 @@ void InfogainLossLayer::Backward_cpu(const vector*>& top, << " Layer cannot backpropagate to infogain inputs."; } if (propagate_down[0]) { - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); - const Dtype* bottom_label = (*bottom)[1]->cpu_data(); + const Dtype* bottom_data = bottom[0]->cpu_data(); + const Dtype* bottom_label = bottom[1]->cpu_data(); const Dtype* infogain_mat = NULL; - if (bottom->size() < 3) { + if (bottom.size() < 3) { infogain_mat = infogain_.cpu_data(); } else { - infogain_mat = (*bottom)[2]->cpu_data(); + infogain_mat = bottom[2]->cpu_data(); } - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); - int num = (*bottom)[0]->num(); - int dim = (*bottom)[0]->count() / (*bottom)[0]->num(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + int num = bottom[0]->num(); + int dim = bottom[0]->count() / bottom[0]->num(); const Dtype scale = - top[0]->cpu_diff()[0] / num; for (int i = 0; i < num; ++i) { const int label = static_cast(bottom_label[i]); diff --git a/src/caffe/layers/inner_product_layer.cpp b/src/caffe/layers/inner_product_layer.cpp index ecd05a030db..ffd872c5a70 100644 --- a/src/caffe/layers/inner_product_layer.cpp +++ b/src/caffe/layers/inner_product_layer.cpp @@ -11,7 +11,7 @@ namespace caffe { template void InnerProductLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const int num_output = this->layer_param_.inner_product_param().num_output(); bias_term_ = this->layer_param_.inner_product_param().bias_term(); N_ = num_output; @@ -44,12 +44,12 @@ void InnerProductLayer::LayerSetUp(const vector*>& bottom, template void InnerProductLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // Figure out the dimensions M_ = bottom[0]->num(); CHECK_EQ(bottom[0]->count() / bottom[0]->num(), K_) << "Input size " "incompatible with inner product parameters."; - (*top)[0]->Reshape(bottom[0]->num(), N_, 1, 1); + top[0]->Reshape(bottom[0]->num(), N_, 1, 1); // Set up the bias multiplier if (bias_term_) { bias_multiplier_.Reshape(1, 1, 1, M_); @@ -59,9 +59,9 @@ void InnerProductLayer::Reshape(const vector*>& bottom, template void InnerProductLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); const Dtype* weight = this->blobs_[0]->cpu_data(); caffe_cpu_gemm(CblasNoTrans, CblasTrans, M_, N_, K_, (Dtype)1., bottom_data, weight, (Dtype)0., top_data); @@ -75,10 +75,10 @@ void InnerProductLayer::Forward_cpu(const vector*>& bottom, template void InnerProductLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (this->param_propagate_down_[0]) { const Dtype* top_diff = top[0]->cpu_diff(); - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* bottom_data = bottom[0]->cpu_data(); // Gradient with respect to weight caffe_cpu_gemm(CblasTrans, CblasNoTrans, N_, K_, M_, (Dtype)1., top_diff, bottom_data, (Dtype)0., this->blobs_[0]->mutable_cpu_diff()); @@ -95,7 +95,7 @@ void InnerProductLayer::Backward_cpu(const vector*>& top, // Gradient with respect to bottom data caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, K_, N_, (Dtype)1., top_diff, this->blobs_[0]->cpu_data(), (Dtype)0., - (*bottom)[0]->mutable_cpu_diff()); + bottom[0]->mutable_cpu_diff()); } } diff --git a/src/caffe/layers/inner_product_layer.cu b/src/caffe/layers/inner_product_layer.cu index 3a0d4388352..2164b4d4f16 100644 --- a/src/caffe/layers/inner_product_layer.cu +++ b/src/caffe/layers/inner_product_layer.cu @@ -11,9 +11,9 @@ namespace caffe { template void InnerProductLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); const Dtype* weight = this->blobs_[0]->gpu_data(); caffe_gpu_gemm(CblasNoTrans, CblasTrans, M_, N_, K_, (Dtype)1., bottom_data, weight, (Dtype)0., top_data); @@ -27,10 +27,10 @@ void InnerProductLayer::Forward_gpu(const vector*>& bottom, template void InnerProductLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (this->param_propagate_down_[0]) { const Dtype* top_diff = top[0]->gpu_diff(); - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + const Dtype* bottom_data = bottom[0]->gpu_data(); // Gradient with respect to weight caffe_gpu_gemm(CblasTrans, CblasNoTrans, N_, K_, M_, (Dtype)1., top_diff, bottom_data, (Dtype)0., this->blobs_[0]->mutable_gpu_diff()); @@ -47,7 +47,7 @@ void InnerProductLayer::Backward_gpu(const vector*>& top, // Gradient with respect to bottom data caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, K_, N_, (Dtype)1., top_diff, this->blobs_[0]->gpu_data(), (Dtype)0., - (*bottom)[0]->mutable_gpu_diff()); + bottom[0]->mutable_gpu_diff()); } } diff --git a/src/caffe/layers/loss_layer.cpp b/src/caffe/layers/loss_layer.cpp index 9eb9dbd5c5b..a5b6d11b065 100644 --- a/src/caffe/layers/loss_layer.cpp +++ b/src/caffe/layers/loss_layer.cpp @@ -12,7 +12,7 @@ namespace caffe { template void LossLayer::LayerSetUp( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { // LossLayers have a non-zero (1) loss by default. if (this->layer_param_.loss_weight_size() == 0) { this->layer_param_.add_loss_weight(Dtype(1)); @@ -21,10 +21,10 @@ void LossLayer::LayerSetUp( template void LossLayer::Reshape( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { CHECK_EQ(bottom[0]->num(), bottom[1]->num()) << "The data and label should have the same number."; - (*top)[0]->Reshape(1, 1, 1, 1); + top[0]->Reshape(1, 1, 1, 1); } INSTANTIATE_CLASS(LossLayer); diff --git a/src/caffe/layers/lrn_layer.cpp b/src/caffe/layers/lrn_layer.cpp index d9e41e9c137..fb74b03dc88 100644 --- a/src/caffe/layers/lrn_layer.cpp +++ b/src/caffe/layers/lrn_layer.cpp @@ -8,7 +8,7 @@ namespace caffe { template void LRNLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { size_ = this->layer_param_.lrn_param().local_size(); CHECK_EQ(size_ % 2, 1) << "LRN only supports odd values for local_size"; pre_pad_ = (size_ - 1) / 2; @@ -22,7 +22,7 @@ void LRNLayer::LayerSetUp(const vector*>& bottom, split_top_vec_.push_back(&square_input_); LayerParameter split_param; split_layer_.reset(new SplitLayer(split_param)); - split_layer_->SetUp(bottom, &split_top_vec_); + split_layer_->SetUp(bottom, split_top_vec_); // Set up square_layer_ to square the inputs. square_bottom_vec_.clear(); square_top_vec_.clear(); @@ -31,7 +31,7 @@ void LRNLayer::LayerSetUp(const vector*>& bottom, LayerParameter square_param; square_param.mutable_power_param()->set_power(Dtype(2)); square_layer_.reset(new PowerLayer(square_param)); - square_layer_->SetUp(square_bottom_vec_, &square_top_vec_); + square_layer_->SetUp(square_bottom_vec_, square_top_vec_); // Set up pool_layer_ to sum over square neighborhoods of the input. pool_top_vec_.clear(); pool_top_vec_.push_back(&pool_output_); @@ -41,7 +41,7 @@ void LRNLayer::LayerSetUp(const vector*>& bottom, pool_param.mutable_pooling_param()->set_pad(pre_pad_); pool_param.mutable_pooling_param()->set_kernel_size(size_); pool_layer_.reset(new PoolingLayer(pool_param)); - pool_layer_->SetUp(square_top_vec_, &pool_top_vec_); + pool_layer_->SetUp(square_top_vec_, pool_top_vec_); // Set up power_layer_ to compute (1 + alpha_/N^2 s)^-beta_, where s is // the sum of a squared neighborhood (the output of pool_layer_). power_top_vec_.clear(); @@ -51,7 +51,7 @@ void LRNLayer::LayerSetUp(const vector*>& bottom, power_param.mutable_power_param()->set_scale(alpha_); power_param.mutable_power_param()->set_shift(Dtype(1)); power_layer_.reset(new PowerLayer(power_param)); - power_layer_->SetUp(pool_top_vec_, &power_top_vec_); + power_layer_->SetUp(pool_top_vec_, power_top_vec_); // Set up a product_layer_ to compute outputs by multiplying inputs by the // inverse demoninator computed by the power layer. product_bottom_vec_.clear(); @@ -67,21 +67,21 @@ void LRNLayer::LayerSetUp(const vector*>& bottom, template void LRNLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { num_ = bottom[0]->num(); channels_ = bottom[0]->channels(); height_ = bottom[0]->height(); width_ = bottom[0]->width(); switch (this->layer_param_.lrn_param().norm_region()) { case LRNParameter_NormRegion_ACROSS_CHANNELS: - (*top)[0]->Reshape(num_, channels_, height_, width_); + top[0]->Reshape(num_, channels_, height_, width_); scale_.Reshape(num_, channels_, height_, width_); break; case LRNParameter_NormRegion_WITHIN_CHANNEL: - split_layer_->Reshape(bottom, &split_top_vec_); - square_layer_->Reshape(square_bottom_vec_, &square_top_vec_); - pool_layer_->Reshape(square_top_vec_, &pool_top_vec_); - power_layer_->Reshape(pool_top_vec_, &power_top_vec_); + split_layer_->Reshape(bottom, split_top_vec_); + square_layer_->Reshape(square_bottom_vec_, square_top_vec_); + pool_layer_->Reshape(square_top_vec_, pool_top_vec_); + power_layer_->Reshape(pool_top_vec_, power_top_vec_); product_layer_->Reshape(product_bottom_vec_, top); break; } @@ -89,7 +89,7 @@ void LRNLayer::Reshape(const vector*>& bottom, template void LRNLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { switch (this->layer_param_.lrn_param().norm_region()) { case LRNParameter_NormRegion_ACROSS_CHANNELS: CrossChannelForward_cpu(bottom, top); @@ -104,9 +104,9 @@ void LRNLayer::Forward_cpu(const vector*>& bottom, template void LRNLayer::CrossChannelForward_cpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); Dtype* scale_data = scale_.mutable_cpu_data(); // start with the constant value for (int i = 0; i < scale_.count(); ++i) { @@ -151,17 +151,17 @@ void LRNLayer::CrossChannelForward_cpu( template void LRNLayer::WithinChannelForward( - const vector*>& bottom, vector*>* top) { - split_layer_->Forward(bottom, &split_top_vec_); - square_layer_->Forward(square_bottom_vec_, &square_top_vec_); - pool_layer_->Forward(square_top_vec_, &pool_top_vec_); - power_layer_->Forward(pool_top_vec_, &power_top_vec_); + const vector*>& bottom, const vector*>& top) { + split_layer_->Forward(bottom, split_top_vec_); + square_layer_->Forward(square_bottom_vec_, square_top_vec_); + pool_layer_->Forward(square_top_vec_, pool_top_vec_); + power_layer_->Forward(pool_top_vec_, power_top_vec_); product_layer_->Forward(product_bottom_vec_, top); } template void LRNLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { switch (this->layer_param_.lrn_param().norm_region()) { case LRNParameter_NormRegion_ACROSS_CHANNELS: CrossChannelBackward_cpu(top, propagate_down, bottom); @@ -177,12 +177,12 @@ void LRNLayer::Backward_cpu(const vector*>& top, template void LRNLayer::CrossChannelBackward_cpu( const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { const Dtype* top_diff = top[0]->cpu_diff(); const Dtype* top_data = top[0]->cpu_data(); - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* bottom_data = bottom[0]->cpu_data(); const Dtype* scale_data = scale_.cpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); Blob padded_ratio(1, channels_ + size_ - 1, height_, width_); Blob accum_ratio(1, 1, height_, width_); Dtype* padded_ratio_data = padded_ratio.mutable_cpu_data(); @@ -232,14 +232,14 @@ void LRNLayer::CrossChannelBackward_cpu( template void LRNLayer::WithinChannelBackward( const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { vector product_propagate_down(2, true); - product_layer_->Backward(top, product_propagate_down, &product_bottom_vec_); - power_layer_->Backward(power_top_vec_, propagate_down, &pool_top_vec_); - pool_layer_->Backward(pool_top_vec_, propagate_down, &square_top_vec_); + product_layer_->Backward(top, product_propagate_down, product_bottom_vec_); + power_layer_->Backward(power_top_vec_, propagate_down, pool_top_vec_); + pool_layer_->Backward(pool_top_vec_, propagate_down, square_top_vec_); square_layer_->Backward(square_top_vec_, propagate_down, - &square_bottom_vec_); + square_bottom_vec_); split_layer_->Backward(split_top_vec_, propagate_down, bottom); } } diff --git a/src/caffe/layers/lrn_layer.cu b/src/caffe/layers/lrn_layer.cu index d6cb23bf245..ee5e359ff0b 100644 --- a/src/caffe/layers/lrn_layer.cu +++ b/src/caffe/layers/lrn_layer.cu @@ -55,7 +55,7 @@ __global__ void LRNFillScale(const int nthreads, const Dtype* in, template void LRNLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { switch (this->layer_param_.lrn_param().norm_region()) { case LRNParameter_NormRegion_ACROSS_CHANNELS: CrossChannelForward_gpu(bottom, top); @@ -79,10 +79,10 @@ __global__ void LRNComputeOutput(const int nthreads, const Dtype* in, template void LRNLayer::CrossChannelForward_gpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { // First, compute scale const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); Dtype* scale_data = scale_.mutable_gpu_data(); // We will launch one kernel for each pixel location, and have the kernel // go through all the channels. @@ -102,7 +102,7 @@ void LRNLayer::CrossChannelForward_gpu( template void LRNLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { switch (this->layer_param_.lrn_param().norm_region()) { case LRNParameter_NormRegion_ACROSS_CHANNELS: CrossChannelBackward_gpu(top, propagate_down, bottom); @@ -179,14 +179,14 @@ __global__ void LRNComputeDiff(const int nthreads, const Dtype* bottom_data, template void LRNLayer::CrossChannelBackward_gpu( const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { int n_threads = num_ * height_ * width_; // NOLINT_NEXT_LINE(whitespace/operators) LRNComputeDiff<<>>( - n_threads, (*bottom)[0]->gpu_data(), top[0]->gpu_data(), + n_threads, bottom[0]->gpu_data(), top[0]->gpu_data(), scale_.gpu_data(), top[0]->gpu_diff(), num_, channels_, height_, width_, size_, -beta_, Dtype(2. * alpha_ * beta_ / size_), - (*bottom)[0]->mutable_gpu_diff()); + bottom[0]->mutable_gpu_diff()); } diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index ab631a884fb..d254da34322 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -8,7 +8,7 @@ namespace caffe { template void MemoryDataLayer::DataLayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { batch_size_ = this->layer_param_.memory_data_param().batch_size(); this->datum_channels_ = this->layer_param_.memory_data_param().channels(); this->datum_height_ = this->layer_param_.memory_data_param().height(); @@ -18,9 +18,9 @@ void MemoryDataLayer::DataLayerSetUp(const vector*>& bottom, CHECK_GT(batch_size_ * this->datum_size_, 0) << "batch_size, channels, height, and width must be specified and" " positive in memory_data_param"; - (*top)[0]->Reshape(batch_size_, this->datum_channels_, this->datum_height_, + top[0]->Reshape(batch_size_, this->datum_channels_, this->datum_height_, this->datum_width_); - (*top)[1]->Reshape(batch_size_, 1, 1, 1); + top[1]->Reshape(batch_size_, 1, 1, 1); added_data_.Reshape(batch_size_, this->datum_channels_, this->datum_height_, this->datum_width_); added_label_.Reshape(batch_size_, 1, 1, 1); @@ -66,10 +66,10 @@ void MemoryDataLayer::Reset(Dtype* data, Dtype* labels, int n) { template void MemoryDataLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { CHECK(data_) << "MemoryDataLayer needs to be initalized by calling Reset"; - (*top)[0]->set_cpu_data(data_ + pos_ * this->datum_size_); - (*top)[1]->set_cpu_data(labels_ + pos_); + top[0]->set_cpu_data(data_ + pos_ * this->datum_size_); + top[1]->set_cpu_data(labels_ + pos_); pos_ = (pos_ + batch_size_) % n_; has_new_data_ = false; } diff --git a/src/caffe/layers/multinomial_logistic_loss_layer.cpp b/src/caffe/layers/multinomial_logistic_loss_layer.cpp index c0fe1966a4d..66f9ba813aa 100644 --- a/src/caffe/layers/multinomial_logistic_loss_layer.cpp +++ b/src/caffe/layers/multinomial_logistic_loss_layer.cpp @@ -12,7 +12,7 @@ namespace caffe { template void MultinomialLogisticLossLayer::Reshape( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::Reshape(bottom, top); CHECK_EQ(bottom[1]->channels(), 1); CHECK_EQ(bottom[1]->height(), 1); @@ -21,7 +21,7 @@ void MultinomialLogisticLossLayer::Reshape( template void MultinomialLogisticLossLayer::Forward_cpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); const Dtype* bottom_label = bottom[1]->cpu_data(); int num = bottom[0]->num(); @@ -33,24 +33,24 @@ void MultinomialLogisticLossLayer::Forward_cpu( bottom_data[i * dim + label], Dtype(kLOG_THRESHOLD)); loss -= log(prob); } - (*top)[0]->mutable_cpu_data()[0] = loss / num; + top[0]->mutable_cpu_data()[0] = loss / num; } template void MultinomialLogisticLossLayer::Backward_cpu( const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[1]) { LOG(FATAL) << this->type_name() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); - const Dtype* bottom_label = (*bottom)[1]->cpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); - int num = (*bottom)[0]->num(); - int dim = (*bottom)[0]->count() / (*bottom)[0]->num(); - caffe_set((*bottom)[0]->count(), Dtype(0), bottom_diff); + const Dtype* bottom_data = bottom[0]->cpu_data(); + const Dtype* bottom_label = bottom[1]->cpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + int num = bottom[0]->num(); + int dim = bottom[0]->count() / bottom[0]->num(); + caffe_set(bottom[0]->count(), Dtype(0), bottom_diff); const Dtype scale = - top[0]->cpu_diff()[0] / num; for (int i = 0; i < num; ++i) { int label = static_cast(bottom_label[i]); diff --git a/src/caffe/layers/mvn_layer.cpp b/src/caffe/layers/mvn_layer.cpp index 6a57b3ea7fc..419f170ad7c 100644 --- a/src/caffe/layers/mvn_layer.cpp +++ b/src/caffe/layers/mvn_layer.cpp @@ -9,8 +9,8 @@ namespace caffe { template void MVNLayer::Reshape(const vector*>& bottom, - vector*>* top) { - (*top)[0]->Reshape(bottom[0]->num(), bottom[0]->channels(), + const vector*>& top) { + top[0]->Reshape(bottom[0]->num(), bottom[0]->channels(), bottom[0]->height(), bottom[0]->width()); mean_.Reshape(bottom[0]->num(), bottom[0]->channels(), 1, 1); @@ -26,9 +26,9 @@ void MVNLayer::Reshape(const vector*>& bottom, template void MVNLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); int num; if (this->layer_param_.mvn_param().across_channels()) num = bottom[0]->num(); @@ -89,19 +89,19 @@ void MVNLayer::Forward_cpu(const vector*>& bottom, template void MVNLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { const Dtype* top_diff = top[0]->cpu_diff(); const Dtype* top_data = top[0]->cpu_data(); - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); int num; if (this->layer_param_.mvn_param().across_channels()) - num = (*bottom)[0]->num(); + num = bottom[0]->num(); else - num = (*bottom)[0]->num() * (*bottom)[0]->channels(); + num = bottom[0]->num() * bottom[0]->channels(); - int dim = (*bottom)[0]->count() / num; + int dim = bottom[0]->count() / num; Dtype eps = 1e-10; if (this->layer_param_.mvn_param().normalize_variance()) { diff --git a/src/caffe/layers/mvn_layer.cu b/src/caffe/layers/mvn_layer.cu index 2c02dfe1ddc..c2a241f093f 100644 --- a/src/caffe/layers/mvn_layer.cu +++ b/src/caffe/layers/mvn_layer.cu @@ -9,9 +9,9 @@ namespace caffe { template void MVNLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); int num; if (this->layer_param_.mvn_param().across_channels()) num = bottom[0]->num(); @@ -73,19 +73,19 @@ void MVNLayer::Forward_gpu(const vector*>& bottom, template void MVNLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { const Dtype* top_diff = top[0]->gpu_diff(); const Dtype* top_data = top[0]->gpu_data(); - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); int num; if (this->layer_param_.mvn_param().across_channels()) - num = (*bottom)[0]->num(); + num = bottom[0]->num(); else - num = (*bottom)[0]->num() * (*bottom)[0]->channels(); + num = bottom[0]->num() * bottom[0]->channels(); - int dim = (*bottom)[0]->count() / num; + int dim = bottom[0]->count() / num; Dtype eps = 1e-10; diff --git a/src/caffe/layers/neuron_layer.cpp b/src/caffe/layers/neuron_layer.cpp index c28e36ea23b..ba67b43878e 100644 --- a/src/caffe/layers/neuron_layer.cpp +++ b/src/caffe/layers/neuron_layer.cpp @@ -7,8 +7,8 @@ namespace caffe { template void NeuronLayer::Reshape(const vector*>& bottom, - vector*>* top) { - (*top)[0]->ReshapeLike(*bottom[0]); + const vector*>& top) { + top[0]->ReshapeLike(*bottom[0]); } INSTANTIATE_CLASS(NeuronLayer); diff --git a/src/caffe/layers/pooling_layer.cpp b/src/caffe/layers/pooling_layer.cpp index 8e8ffad66a0..26c92c13b63 100644 --- a/src/caffe/layers/pooling_layer.cpp +++ b/src/caffe/layers/pooling_layer.cpp @@ -15,7 +15,7 @@ using std::max; template void PoolingLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { PoolingParameter pool_param = this->layer_param_.pooling_param(); CHECK(!pool_param.has_kernel_size() != !(pool_param.has_kernel_h() && pool_param.has_kernel_w())) @@ -64,7 +64,7 @@ void PoolingLayer::LayerSetUp(const vector*>& bottom, template void PoolingLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { channels_ = bottom[0]->channels(); height_ = bottom[0]->height(); width_ = bottom[0]->width(); @@ -84,14 +84,14 @@ void PoolingLayer::Reshape(const vector*>& bottom, CHECK_LT((pooled_height_ - 1) * stride_h_, height_ + pad_h_); CHECK_LT((pooled_width_ - 1) * stride_w_, width_ + pad_w_); } - (*top)[0]->Reshape(bottom[0]->num(), channels_, pooled_height_, + top[0]->Reshape(bottom[0]->num(), channels_, pooled_height_, pooled_width_); - if (top->size() > 1) { - (*top)[1]->ReshapeLike(*(*top)[0]); + if (top.size() > 1) { + top[1]->ReshapeLike(*top[0]); } // If max pooling, we will initialize the vector index part. if (this->layer_param_.pooling_param().pool() == - PoolingParameter_PoolMethod_MAX && top->size() == 1) { + PoolingParameter_PoolMethod_MAX && top.size() == 1) { max_idx_.Reshape(bottom[0]->num(), channels_, pooled_height_, pooled_width_); } @@ -107,12 +107,12 @@ void PoolingLayer::Reshape(const vector*>& bottom, // case? template void PoolingLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); - const int top_count = (*top)[0]->count(); + Dtype* top_data = top[0]->mutable_cpu_data(); + const int top_count = top[0]->count(); // We'll output the mask to top[1] if it's of size >1. - const bool use_top_mask = top->size() > 1; + const bool use_top_mask = top.size() > 1; int* mask = NULL; // suppress warnings about uninitalized variables Dtype* top_mask = NULL; // Different pooling methods. We explicitly do the switch outside the for @@ -121,7 +121,7 @@ void PoolingLayer::Forward_cpu(const vector*>& bottom, case PoolingParameter_PoolMethod_MAX: // Initialize if (use_top_mask) { - top_mask = (*top)[1]->mutable_cpu_data(); + top_mask = top[1]->mutable_cpu_data(); caffe_set(top_count, Dtype(-1), top_mask); } else { mask = max_idx_.mutable_cpu_data(); @@ -157,11 +157,11 @@ void PoolingLayer::Forward_cpu(const vector*>& bottom, } // compute offset bottom_data += bottom[0]->offset(0, 1); - top_data += (*top)[0]->offset(0, 1); + top_data += top[0]->offset(0, 1); if (use_top_mask) { - top_mask += (*top)[0]->offset(0, 1); + top_mask += top[0]->offset(0, 1); } else { - mask += (*top)[0]->offset(0, 1); + mask += top[0]->offset(0, 1); } } } @@ -195,7 +195,7 @@ void PoolingLayer::Forward_cpu(const vector*>& bottom, } // compute offset bottom_data += bottom[0]->offset(0, 1); - top_data += (*top)[0]->offset(0, 1); + top_data += top[0]->offset(0, 1); } } break; @@ -209,15 +209,15 @@ void PoolingLayer::Forward_cpu(const vector*>& bottom, template void PoolingLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (!propagate_down[0]) { return; } const Dtype* top_diff = top[0]->cpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); // Different pooling methods. We explicitly do the switch outside the for // loop to save time, although this results in more codes. - caffe_set((*bottom)[0]->count(), Dtype(0), bottom_diff); + caffe_set(bottom[0]->count(), Dtype(0), bottom_diff); // We'll output the mask to top[1] if it's of size >1. const bool use_top_mask = top.size() > 1; const int* mask = NULL; // suppress warnings about uninitialized variables @@ -240,7 +240,7 @@ void PoolingLayer::Backward_cpu(const vector*>& top, bottom_diff[bottom_index] += top_diff[index]; } } - bottom_diff += (*bottom)[0]->offset(0, 1); + bottom_diff += bottom[0]->offset(0, 1); top_diff += top[0]->offset(0, 1); if (use_top_mask) { top_mask += top[0]->offset(0, 1); @@ -274,7 +274,7 @@ void PoolingLayer::Backward_cpu(const vector*>& top, } } // offset - bottom_diff += (*bottom)[0]->offset(0, 1); + bottom_diff += bottom[0]->offset(0, 1); top_diff += top[0]->offset(0, 1); } } diff --git a/src/caffe/layers/pooling_layer.cu b/src/caffe/layers/pooling_layer.cu index e64128b87f2..aec985a7864 100644 --- a/src/caffe/layers/pooling_layer.cu +++ b/src/caffe/layers/pooling_layer.cu @@ -152,18 +152,18 @@ __global__ void StoPoolForwardTest(const int nthreads, template void PoolingLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); - int count = (*top)[0]->count(); + Dtype* top_data = top[0]->mutable_gpu_data(); + int count = top[0]->count(); // We'll output the mask to top[1] if it's of size >1. - const bool use_top_mask = top->size() > 1; + const bool use_top_mask = top.size() > 1; int* mask = NULL; Dtype* top_mask = NULL; switch (this->layer_param_.pooling_param().pool()) { case PoolingParameter_PoolMethod_MAX: if (use_top_mask) { - top_mask = (*top)[1]->mutable_gpu_data(); + top_mask = top[1]->mutable_gpu_data(); } else { mask = max_idx_.mutable_gpu_data(); } @@ -325,13 +325,13 @@ __global__ void StoPoolBackward(const int nthreads, template void PoolingLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (!propagate_down[0]) { return; } const Dtype* top_diff = top[0]->gpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); + const int count = bottom[0]->count(); caffe_gpu_set(count, Dtype(0.), bottom_diff); // We'll output the mask to top[1] if it's of size >1. const bool use_top_mask = top.size() > 1; diff --git a/src/caffe/layers/power_layer.cpp b/src/caffe/layers/power_layer.cpp index bf61955d065..04c612296aa 100644 --- a/src/caffe/layers/power_layer.cpp +++ b/src/caffe/layers/power_layer.cpp @@ -9,7 +9,7 @@ namespace caffe { template void PowerLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { NeuronLayer::LayerSetUp(bottom, top); power_ = this->layer_param_.power_param().power(); scale_ = this->layer_param_.power_param().scale(); @@ -20,8 +20,8 @@ void PowerLayer::LayerSetUp(const vector*>& bottom, // Compute y = (shift + scale * x)^power template void PowerLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const vector*>& top) { + Dtype* top_data = top[0]->mutable_cpu_data(); const int count = bottom[0]->count(); // Special case where we can ignore the input: scale or power is 0. if (diff_scale_ == Dtype(0)) { @@ -45,15 +45,15 @@ void PowerLayer::Forward_cpu(const vector*>& bottom, template void PowerLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + const int count = bottom[0]->count(); const Dtype* top_diff = top[0]->cpu_diff(); if (diff_scale_ == Dtype(0) || power_ == Dtype(1)) { caffe_set(count, diff_scale_, bottom_diff); } else { - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* bottom_data = bottom[0]->cpu_data(); // Compute dy/dx = scale * power * (shift + scale * x)^(power - 1) // = diff_scale * y / (shift + scale * x) if (power_ == Dtype(2)) { diff --git a/src/caffe/layers/power_layer.cu b/src/caffe/layers/power_layer.cu index a40bc75829d..367320a9b1f 100644 --- a/src/caffe/layers/power_layer.cu +++ b/src/caffe/layers/power_layer.cu @@ -9,8 +9,8 @@ namespace caffe { template void PowerLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const vector*>& top) { + Dtype* top_data = top[0]->mutable_gpu_data(); const int count = bottom[0]->count(); // Special case where we can ignore the input: scale or power is 0. if (diff_scale_ == Dtype(0)) { @@ -34,15 +34,15 @@ void PowerLayer::Forward_gpu(const vector*>& bottom, template void PowerLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); + const int count = bottom[0]->count(); const Dtype* top_diff = top[0]->gpu_diff(); if (diff_scale_ == Dtype(0) || power_ == Dtype(1)) { caffe_gpu_set(count, diff_scale_, bottom_diff); } else { - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + const Dtype* bottom_data = bottom[0]->gpu_data(); // Compute dy/dx = scale * power * (shift + scale * x)^(power - 1) // = diff_scale * y / (shift + scale * x) if (power_ == Dtype(2)) { diff --git a/src/caffe/layers/relu_layer.cpp b/src/caffe/layers/relu_layer.cpp index b50352f8526..7d5e6034589 100644 --- a/src/caffe/layers/relu_layer.cpp +++ b/src/caffe/layers/relu_layer.cpp @@ -8,9 +8,9 @@ namespace caffe { template void ReLULayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); const int count = bottom[0]->count(); Dtype negative_slope = this->layer_param_.relu_param().negative_slope(); for (int i = 0; i < count; ++i) { @@ -22,12 +22,12 @@ void ReLULayer::Forward_cpu(const vector*>& bottom, template void ReLULayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { - const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* bottom_data = bottom[0]->cpu_data(); const Dtype* top_diff = top[0]->cpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + const int count = bottom[0]->count(); Dtype negative_slope = this->layer_param_.relu_param().negative_slope(); for (int i = 0; i < count; ++i) { bottom_diff[i] = top_diff[i] * ((bottom_data[i] > 0) diff --git a/src/caffe/layers/relu_layer.cu b/src/caffe/layers/relu_layer.cu index def2bbcd7b9..22d5f4b5c5e 100644 --- a/src/caffe/layers/relu_layer.cu +++ b/src/caffe/layers/relu_layer.cu @@ -16,9 +16,9 @@ __global__ void ReLUForward(const int n, const Dtype* in, Dtype* out, template void ReLULayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); const int count = bottom[0]->count(); Dtype negative_slope = this->layer_param_.relu_param().negative_slope(); // NOLINT_NEXT_LINE(whitespace/operators) @@ -44,12 +44,12 @@ __global__ void ReLUBackward(const int n, const Dtype* in_diff, template void ReLULayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { - const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + const Dtype* bottom_data = bottom[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); + const int count = bottom[0]->count(); Dtype negative_slope = this->layer_param_.relu_param().negative_slope(); // NOLINT_NEXT_LINE(whitespace/operators) ReLUBackward<<>>( diff --git a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp index 6a48099ae8b..11850ac68e3 100644 --- a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp +++ b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp @@ -10,30 +10,30 @@ namespace caffe { template void SigmoidCrossEntropyLossLayer::LayerSetUp( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::LayerSetUp(bottom, top); sigmoid_bottom_vec_.clear(); sigmoid_bottom_vec_.push_back(bottom[0]); sigmoid_top_vec_.clear(); sigmoid_top_vec_.push_back(sigmoid_output_.get()); - sigmoid_layer_->SetUp(sigmoid_bottom_vec_, &sigmoid_top_vec_); + sigmoid_layer_->SetUp(sigmoid_bottom_vec_, sigmoid_top_vec_); } template void SigmoidCrossEntropyLossLayer::Reshape( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::Reshape(bottom, top); CHECK_EQ(bottom[0]->count(), bottom[1]->count()) << "SIGMOID_CROSS_ENTROPY_LOSS layer inputs must have the same count."; - sigmoid_layer_->Reshape(sigmoid_bottom_vec_, &sigmoid_top_vec_); + sigmoid_layer_->Reshape(sigmoid_bottom_vec_, sigmoid_top_vec_); } template void SigmoidCrossEntropyLossLayer::Forward_cpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { // The forward pass computes the sigmoid outputs. sigmoid_bottom_vec_[0] = bottom[0]; - sigmoid_layer_->Forward(sigmoid_bottom_vec_, &sigmoid_top_vec_); + sigmoid_layer_->Forward(sigmoid_bottom_vec_, sigmoid_top_vec_); // Compute the loss (negative log likelihood) const int count = bottom[0]->count(); const int num = bottom[0]->num(); @@ -45,24 +45,24 @@ void SigmoidCrossEntropyLossLayer::Forward_cpu( loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) - log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0))); } - (*top)[0]->mutable_cpu_data()[0] = loss / num; + top[0]->mutable_cpu_data()[0] = loss / num; } template void SigmoidCrossEntropyLossLayer::Backward_cpu( const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[1]) { LOG(FATAL) << this->type_name() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { // First, compute the diff - const int count = (*bottom)[0]->count(); - const int num = (*bottom)[0]->num(); + const int count = bottom[0]->count(); + const int num = bottom[0]->num(); const Dtype* sigmoid_output_data = sigmoid_output_->cpu_data(); - const Dtype* target = (*bottom)[1]->cpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const Dtype* target = bottom[1]->cpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); caffe_sub(count, sigmoid_output_data, target, bottom_diff); // Scale down gradient const Dtype loss_weight = top[0]->cpu_diff()[0]; diff --git a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu index 8d0fdc6fac4..175f6f86574 100644 --- a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu +++ b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu @@ -10,10 +10,10 @@ namespace caffe { template void SigmoidCrossEntropyLossLayer::Forward_gpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { // The forward pass computes the sigmoid outputs. sigmoid_bottom_vec_[0] = bottom[0]; - sigmoid_layer_->Forward(sigmoid_bottom_vec_, &sigmoid_top_vec_); + sigmoid_layer_->Forward(sigmoid_bottom_vec_, sigmoid_top_vec_); // Compute the loss (negative log likelihood) const int count = bottom[0]->count(); const int num = bottom[0]->num(); @@ -25,24 +25,24 @@ void SigmoidCrossEntropyLossLayer::Forward_gpu( loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) - log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0))); } - (*top)[0]->mutable_cpu_data()[0] = loss / num; + top[0]->mutable_cpu_data()[0] = loss / num; } template void SigmoidCrossEntropyLossLayer::Backward_gpu( const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[1]) { LOG(FATAL) << this->type_name() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { // First, compute the diff - const int count = (*bottom)[0]->count(); - const int num = (*bottom)[0]->num(); + const int count = bottom[0]->count(); + const int num = bottom[0]->num(); const Dtype* sigmoid_output_data = sigmoid_output_->gpu_data(); - const Dtype* target = (*bottom)[1]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const Dtype* target = bottom[1]->gpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); caffe_copy(count, sigmoid_output_data, bottom_diff); caffe_gpu_axpy(count, Dtype(-1), target, bottom_diff); // Scale down gradient diff --git a/src/caffe/layers/sigmoid_layer.cpp b/src/caffe/layers/sigmoid_layer.cpp index d7bba7fbfc3..48c384905bf 100644 --- a/src/caffe/layers/sigmoid_layer.cpp +++ b/src/caffe/layers/sigmoid_layer.cpp @@ -14,9 +14,9 @@ inline Dtype sigmoid(Dtype x) { template void SigmoidLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); const int count = bottom[0]->count(); for (int i = 0; i < count; ++i) { top_data[i] = sigmoid(bottom_data[i]); @@ -26,12 +26,12 @@ void SigmoidLayer::Forward_cpu(const vector*>& bottom, template void SigmoidLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { const Dtype* top_data = top[0]->cpu_data(); const Dtype* top_diff = top[0]->cpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + const int count = bottom[0]->count(); for (int i = 0; i < count; ++i) { const Dtype sigmoid_x = top_data[i]; bottom_diff[i] = top_diff[i] * sigmoid_x * (1. - sigmoid_x); diff --git a/src/caffe/layers/sigmoid_layer.cu b/src/caffe/layers/sigmoid_layer.cu index e1ebb1f6c41..6879ff7f570 100644 --- a/src/caffe/layers/sigmoid_layer.cu +++ b/src/caffe/layers/sigmoid_layer.cu @@ -16,9 +16,9 @@ __global__ void SigmoidForward(const int n, const Dtype* in, Dtype* out) { template void SigmoidLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); const int count = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) SigmoidForward<<>>( @@ -43,12 +43,12 @@ __global__ void SigmoidBackward(const int n, const Dtype* in_diff, template void SigmoidLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { const Dtype* top_data = top[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); + const int count = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) SigmoidBackward<<>>( count, top_diff, top_data, bottom_diff); diff --git a/src/caffe/layers/silence_layer.cpp b/src/caffe/layers/silence_layer.cpp index 75dbbf31f0d..0fd88580eaf 100644 --- a/src/caffe/layers/silence_layer.cpp +++ b/src/caffe/layers/silence_layer.cpp @@ -8,11 +8,11 @@ namespace caffe { template void SilenceLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { - for (int i = 0; i < bottom->size(); ++i) { + const vector& propagate_down, const vector*>& bottom) { + for (int i = 0; i < bottom.size(); ++i) { if (propagate_down[i]) { - caffe_set((*bottom)[i]->count(), Dtype(0), - (*bottom)[i]->mutable_cpu_data()); + caffe_set(bottom[i]->count(), Dtype(0), + bottom[i]->mutable_cpu_data()); } } } diff --git a/src/caffe/layers/silence_layer.cu b/src/caffe/layers/silence_layer.cu index 735abe61eaf..b350b1950bd 100644 --- a/src/caffe/layers/silence_layer.cu +++ b/src/caffe/layers/silence_layer.cu @@ -8,17 +8,17 @@ namespace caffe { template void SilenceLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // Do nothing. } template void SilenceLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { - for (int i = 0; i < bottom->size(); ++i) { + const vector& propagate_down, const vector*>& bottom) { + for (int i = 0; i < bottom.size(); ++i) { if (propagate_down[i]) { - caffe_gpu_set((*bottom)[i]->count(), Dtype(0), - (*bottom)[i]->mutable_gpu_data()); + caffe_gpu_set(bottom[i]->count(), Dtype(0), + bottom[i]->mutable_gpu_data()); } } } diff --git a/src/caffe/layers/slice_layer.cpp b/src/caffe/layers/slice_layer.cpp index ed679a9169e..17144c1a280 100644 --- a/src/caffe/layers/slice_layer.cpp +++ b/src/caffe/layers/slice_layer.cpp @@ -9,7 +9,7 @@ namespace caffe { template void SliceLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const SliceParameter& slice_param = this->layer_param_.slice_param(); slice_dim_ = slice_param.slice_dim(); CHECK_GE(slice_dim_, 0); @@ -22,18 +22,18 @@ void SliceLayer::LayerSetUp(const vector*>& bottom, template void SliceLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { count_ = 0; num_ = bottom[0]->num(); channels_ = bottom[0]->channels(); height_ = bottom[0]->height(); width_ = bottom[0]->width(); if (slice_point_.size() != 0) { - CHECK_EQ(slice_point_.size(), top->size() - 1); + CHECK_EQ(slice_point_.size(), top.size() - 1); if (slice_dim_ == 0) { - CHECK_LE(top->size(), num_); + CHECK_LE(top.size(), num_); } else { - CHECK_LE(top->size(), channels_); + CHECK_LE(top.size(), channels_); } int prev = 0; vector slices; @@ -44,32 +44,32 @@ void SliceLayer::Reshape(const vector*>& bottom, } if (slice_dim_ == 0) { slices.push_back(num_ - prev); - for (int i = 0; i < top->size(); ++i) { - (*top)[i]->Reshape(slices[i], channels_, height_, width_); - count_ += (*top)[i]->count(); + for (int i = 0; i < top.size(); ++i) { + top[i]->Reshape(slices[i], channels_, height_, width_); + count_ += top[i]->count(); } } else { slices.push_back(channels_ - prev); - for (int i = 0; i < top->size(); ++i) { - (*top)[i]->Reshape(num_, slices[i], height_, width_); - count_ += (*top)[i]->count(); + for (int i = 0; i < top.size(); ++i) { + top[i]->Reshape(num_, slices[i], height_, width_); + count_ += top[i]->count(); } } } else { if (slice_dim_ == 0) { - CHECK_EQ(num_ % top->size(), 0) - << "Number of top blobs (" << top->size() << ") " + CHECK_EQ(num_ % top.size(), 0) + << "Number of top blobs (" << top.size() << ") " << "should evenly divide input num ( " << num_ << ")"; - num_ = num_ / top->size(); + num_ = num_ / top.size(); } else { - CHECK_EQ(channels_ % top->size(), 0) - << "Number of top blobs (" << top->size() << ") " + CHECK_EQ(channels_ % top.size(), 0) + << "Number of top blobs (" << top.size() << ") " << "should evenly divide input channels ( " << channels_ << ")"; - channels_ = channels_ / top->size(); + channels_ = channels_ / top.size(); } - for (int i = 0; i < top->size(); ++i) { - (*top)[i]->Reshape(num_, channels_, height_, width_); - count_ += (*top)[i]->count(); + for (int i = 0; i < top.size(); ++i) { + top[i]->Reshape(num_, channels_, height_, width_); + count_ += top[i]->count(); } } CHECK_EQ(count_, bottom[0]->count()); @@ -77,12 +77,12 @@ void SliceLayer::Reshape(const vector*>& bottom, template void SliceLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->mutable_cpu_data(); if (slice_dim_ == 0) { int offset_num = 0; - for (int i = 0; i < top->size(); ++i) { - Blob* blob = (*top)[i]; + for (int i = 0; i < top.size(); ++i) { + Blob* blob = top[i]; Dtype* top_data = blob->mutable_cpu_data(); caffe_copy(blob->count(), bottom_data + bottom[0]->offset(offset_num), top_data); @@ -90,8 +90,8 @@ void SliceLayer::Forward_cpu(const vector*>& bottom, } } else if (slice_dim_ == 1) { int offset_channel = 0; - for (int i = 0; i < top->size(); ++i) { - Blob* blob = (*top)[i]; + for (int i = 0; i < top.size(); ++i) { + Blob* blob = top[i]; Dtype* top_data = blob->mutable_cpu_data(); const int num_elem = blob->channels() * blob->height() * blob->width(); for (int n = 0; n < num_; ++n) { @@ -105,16 +105,16 @@ void SliceLayer::Forward_cpu(const vector*>& bottom, template void SliceLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (!propagate_down[0]) { return; } - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); if (slice_dim_ == 0) { int offset_num = 0; for (int i = 0; i < top.size(); ++i) { Blob* blob = top[i]; const Dtype* top_diff = blob->cpu_diff(); caffe_copy(blob->count(), top_diff, - bottom_diff + (*bottom)[0]->offset(offset_num)); + bottom_diff + bottom[0]->offset(offset_num)); offset_num += blob->num(); } } else if (slice_dim_ == 1) { @@ -125,7 +125,7 @@ void SliceLayer::Backward_cpu(const vector*>& top, const int num_elem = blob->channels() * blob->height() * blob->width(); for (int n = 0; n < num_; ++n) { caffe_copy(num_elem, top_diff + blob->offset(n), - bottom_diff + (*bottom)[0]->offset(n, offset_channel)); + bottom_diff + bottom[0]->offset(n, offset_channel)); } offset_channel += blob->channels(); } diff --git a/src/caffe/layers/slice_layer.cu b/src/caffe/layers/slice_layer.cu index f64e5754890..657840809f6 100644 --- a/src/caffe/layers/slice_layer.cu +++ b/src/caffe/layers/slice_layer.cu @@ -8,12 +8,12 @@ namespace caffe { template void SliceLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->mutable_gpu_data(); if (slice_dim_ == 0) { int offset_num = 0; - for (int i = 0; i < top->size(); ++i) { - Blob* blob = (*top)[i]; + for (int i = 0; i < top.size(); ++i) { + Blob* blob = top[i]; Dtype* top_data = blob->mutable_gpu_data(); caffe_copy(blob->count(), bottom_data + bottom[0]->offset(offset_num), top_data); @@ -21,8 +21,8 @@ void SliceLayer::Forward_gpu(const vector*>& bottom, } } else if (slice_dim_ == 1) { int offset_channel = 0; - for (int i = 0; i < top->size(); ++i) { - Blob* blob = (*top)[i]; + for (int i = 0; i < top.size(); ++i) { + Blob* blob = top[i]; Dtype* top_data = blob->mutable_gpu_data(); const int num_elem = blob->channels() * blob->height() * blob->width(); for (int n = 0; n < num_; ++n) { @@ -36,16 +36,16 @@ void SliceLayer::Forward_gpu(const vector*>& bottom, template void SliceLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (!propagate_down[0]) { return; } - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); if (slice_dim_ == 0) { int offset_num = 0; for (int i = 0; i < top.size(); ++i) { Blob* blob = top[i]; const Dtype* top_diff = blob->gpu_diff(); caffe_copy(blob->count(), top_diff, - bottom_diff + (*bottom)[0]->offset(offset_num)); + bottom_diff + bottom[0]->offset(offset_num)); offset_num += blob->num(); } } else if (slice_dim_ == 1) { @@ -56,7 +56,7 @@ void SliceLayer::Backward_gpu(const vector*>& top, const int num_elem = blob->channels() * blob->height() * blob->width(); for (int n = 0; n < num_; ++n) { caffe_copy(num_elem, top_diff + blob->offset(n), - bottom_diff + (*bottom)[0]->offset(n, offset_channel)); + bottom_diff + bottom[0]->offset(n, offset_channel)); } offset_channel += blob->channels(); } diff --git a/src/caffe/layers/softmax_layer.cpp b/src/caffe/layers/softmax_layer.cpp index 60668a3f8ce..04e8c4f35fc 100644 --- a/src/caffe/layers/softmax_layer.cpp +++ b/src/caffe/layers/softmax_layer.cpp @@ -9,8 +9,8 @@ namespace caffe { template void SoftmaxLayer::Reshape(const vector*>& bottom, - vector*>* top) { - (*top)[0]->Reshape(bottom[0]->num(), bottom[0]->channels(), + const vector*>& top) { + top[0]->Reshape(bottom[0]->num(), bottom[0]->channels(), bottom[0]->height(), bottom[0]->width()); sum_multiplier_.Reshape(1, bottom[0]->channels(), 1, 1); Dtype* multiplier_data = sum_multiplier_.mutable_cpu_data(); @@ -22,9 +22,9 @@ void SoftmaxLayer::Reshape(const vector*>& bottom, template void SoftmaxLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); Dtype* scale_data = scale_.mutable_cpu_data(); int num = bottom[0]->num(); int channels = bottom[0]->channels(); @@ -52,8 +52,8 @@ void SoftmaxLayer::Forward_cpu(const vector*>& bottom, top_data + i * dim, sum_multiplier_.cpu_data(), 0., scale_data); // division for (int j = 0; j < channels; j++) { - caffe_div(spatial_dim, top_data + (*top)[0]->offset(i, j), scale_data, - top_data + (*top)[0]->offset(i, j)); + caffe_div(spatial_dim, top_data + top[0]->offset(i, j), scale_data, + top_data + top[0]->offset(i, j)); } } } @@ -61,10 +61,10 @@ void SoftmaxLayer::Forward_cpu(const vector*>& bottom, template void SoftmaxLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { const Dtype* top_diff = top[0]->cpu_diff(); const Dtype* top_data = top[0]->cpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); Dtype* scale_data = scale_.mutable_cpu_data(); int num = top[0]->num(); int channels = top[0]->channels(); diff --git a/src/caffe/layers/softmax_layer.cu b/src/caffe/layers/softmax_layer.cu index f97eafcedb0..8ba31d75951 100644 --- a/src/caffe/layers/softmax_layer.cu +++ b/src/caffe/layers/softmax_layer.cu @@ -87,9 +87,9 @@ __global__ void kernel_channel_dot(const int num, const int channels, template void SoftmaxLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); Dtype* scale_data = scale_.mutable_gpu_data(); int num = bottom[0]->num(); int channels = bottom[0]->channels(); @@ -126,10 +126,10 @@ void SoftmaxLayer::Forward_gpu(const vector*>& bottom, template void SoftmaxLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { const Dtype* top_diff = top[0]->gpu_diff(); const Dtype* top_data = top[0]->gpu_data(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); Dtype* scale_data = scale_.mutable_gpu_data(); int num = top[0]->num(); int channels = top[0]->channels(); diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index 55392c37ca0..651320c77f8 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -10,31 +10,31 @@ namespace caffe { template void SoftmaxWithLossLayer::LayerSetUp( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::LayerSetUp(bottom, top); softmax_bottom_vec_.clear(); softmax_bottom_vec_.push_back(bottom[0]); softmax_top_vec_.clear(); softmax_top_vec_.push_back(&prob_); - softmax_layer_->SetUp(softmax_bottom_vec_, &softmax_top_vec_); + softmax_layer_->SetUp(softmax_bottom_vec_, softmax_top_vec_); } template void SoftmaxWithLossLayer::Reshape( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { LossLayer::Reshape(bottom, top); - softmax_layer_->Reshape(softmax_bottom_vec_, &softmax_top_vec_); - if (top->size() >= 2) { + softmax_layer_->Reshape(softmax_bottom_vec_, softmax_top_vec_); + if (top.size() >= 2) { // softmax output - (*top)[1]->ReshapeLike(*bottom[0]); + top[1]->ReshapeLike(*bottom[0]); } } template void SoftmaxWithLossLayer::Forward_cpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { // The forward pass computes the softmax prob values. - softmax_layer_->Forward(softmax_bottom_vec_, &softmax_top_vec_); + softmax_layer_->Forward(softmax_bottom_vec_, softmax_top_vec_); const Dtype* prob_data = prob_.cpu_data(); const Dtype* label = bottom[1]->cpu_data(); int num = prob_.num(); @@ -48,25 +48,25 @@ void SoftmaxWithLossLayer::Forward_cpu( Dtype(FLT_MIN))); } } - (*top)[0]->mutable_cpu_data()[0] = loss / num / spatial_dim; - if (top->size() == 2) { - (*top)[1]->ShareData(prob_); + top[0]->mutable_cpu_data()[0] = loss / num / spatial_dim; + if (top.size() == 2) { + top[1]->ShareData(prob_); } } template void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[1]) { LOG(FATAL) << this->type_name() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); const Dtype* prob_data = prob_.cpu_data(); caffe_copy(prob_.count(), prob_data, bottom_diff); - const Dtype* label = (*bottom)[1]->cpu_data(); + const Dtype* label = bottom[1]->cpu_data(); int num = prob_.num(); int dim = prob_.count() / num; int spatial_dim = prob_.height() * prob_.width(); diff --git a/src/caffe/layers/softmax_loss_layer.cu b/src/caffe/layers/softmax_loss_layer.cu index 9ef8dd23615..060dc24d06e 100644 --- a/src/caffe/layers/softmax_loss_layer.cu +++ b/src/caffe/layers/softmax_loss_layer.cu @@ -10,13 +10,13 @@ namespace caffe { template void SoftmaxWithLossLayer::Forward_gpu( - const vector*>& bottom, vector*>* top) { + const vector*>& bottom, const vector*>& top) { Forward_cpu(bottom, top); } template void SoftmaxWithLossLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { // TODO(Yangqing): implement the GPU version of softmax. Backward_cpu(top, propagate_down, bottom); } diff --git a/src/caffe/layers/split_layer.cpp b/src/caffe/layers/split_layer.cpp index 40d3600ff17..ee6b5a91d3c 100644 --- a/src/caffe/layers/split_layer.cpp +++ b/src/caffe/layers/split_layer.cpp @@ -8,44 +8,44 @@ namespace caffe { template void SplitLayer::Reshape(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { count_ = bottom[0]->count(); - for (int i = 0; i < top->size(); ++i) { + for (int i = 0; i < top.size(); ++i) { // Do not allow in-place computation in the SplitLayer. Instead, share data // by reference in the forward pass, and keep separate diff allocations in // the backward pass. (Technically, it should be possible to share the diff // blob of the first split output with the input, but this seems to cause // some strange effects in practice...) - CHECK_NE((*top)[i], bottom[0]) << this->type_name() << " Layer does not " + CHECK_NE(top[i], bottom[0]) << this->type_name() << " Layer does not " "allow in-place computation."; - (*top)[i]->Reshape(bottom[0]->num(), bottom[0]->channels(), + top[i]->Reshape(bottom[0]->num(), bottom[0]->channels(), bottom[0]->height(), bottom[0]->width()); - CHECK_EQ(count_, (*top)[i]->count()); + CHECK_EQ(count_, top[i]->count()); } } template void SplitLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { - for (int i = 0; i < top->size(); ++i) { - (*top)[i]->ShareData(*bottom[0]); + const vector*>& top) { + for (int i = 0; i < top.size(); ++i) { + top[i]->ShareData(*bottom[0]); } } template void SplitLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (!propagate_down[0]) { return; } if (top.size() == 1) { - caffe_copy(count_, top[0]->cpu_diff(), (*bottom)[0]->mutable_cpu_diff()); + caffe_copy(count_, top[0]->cpu_diff(), bottom[0]->mutable_cpu_diff()); return; } caffe_add(count_, top[0]->cpu_diff(), top[1]->cpu_diff(), - (*bottom)[0]->mutable_cpu_diff()); + bottom[0]->mutable_cpu_diff()); // Add remaining top blob diffs. for (int i = 2; i < top.size(); ++i) { const Dtype* top_diff = top[i]->cpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); caffe_axpy(count_, Dtype(1.), top_diff, bottom_diff); } } diff --git a/src/caffe/layers/split_layer.cu b/src/caffe/layers/split_layer.cu index fcc0917e67d..0513b204d91 100644 --- a/src/caffe/layers/split_layer.cu +++ b/src/caffe/layers/split_layer.cu @@ -8,26 +8,26 @@ namespace caffe { template void SplitLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { - for (int i = 0; i < top->size(); ++i) { - (*top)[i]->ShareData(*bottom[0]); + const vector*>& top) { + for (int i = 0; i < top.size(); ++i) { + top[i]->ShareData(*bottom[0]); } } template void SplitLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, vector*>* bottom) { + const vector& propagate_down, const vector*>& bottom) { if (!propagate_down[0]) { return; } if (top.size() == 1) { - caffe_copy(count_, top[0]->gpu_diff(), (*bottom)[0]->mutable_gpu_diff()); + caffe_copy(count_, top[0]->gpu_diff(), bottom[0]->mutable_gpu_diff()); return; } caffe_gpu_add(count_, top[0]->gpu_diff(), top[1]->gpu_diff(), - (*bottom)[0]->mutable_gpu_diff()); + bottom[0]->mutable_gpu_diff()); // Add remaining top blob diffs. for (int i = 2; i < top.size(); ++i) { const Dtype* top_diff = top[i]->gpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); caffe_gpu_axpy(count_, Dtype(1.), top_diff, bottom_diff); } } diff --git a/src/caffe/layers/tanh_layer.cpp b/src/caffe/layers/tanh_layer.cpp index 8dae0054aed..18413d9b181 100644 --- a/src/caffe/layers/tanh_layer.cpp +++ b/src/caffe/layers/tanh_layer.cpp @@ -11,9 +11,9 @@ namespace caffe { template void TanHLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); Dtype exp2x; const int count = bottom[0]->count(); for (int i = 0; i < count; ++i) { @@ -25,12 +25,12 @@ void TanHLayer::Forward_cpu(const vector*>& bottom, template void TanHLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { const Dtype* top_data = top[0]->cpu_data(); const Dtype* top_diff = top[0]->cpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + const int count = bottom[0]->count(); Dtype tanhx; for (int i = 0; i < count; ++i) { tanhx = top_data[i]; diff --git a/src/caffe/layers/tanh_layer.cu b/src/caffe/layers/tanh_layer.cu index bdb7a94978e..a141f8e872e 100644 --- a/src/caffe/layers/tanh_layer.cu +++ b/src/caffe/layers/tanh_layer.cu @@ -19,9 +19,9 @@ __global__ void TanHForward(const int n, const Dtype* in, Dtype* out) { template void TanHLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); const int count = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) TanHForward<<>>( @@ -41,12 +41,12 @@ __global__ void TanHBackward(const int n, const Dtype* in_diff, template void TanHLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, - vector*>* bottom) { + const vector*>& bottom) { if (propagate_down[0]) { const Dtype* top_data = top[0]->gpu_data(); const Dtype* top_diff = top[0]->gpu_diff(); - Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); - const int count = (*bottom)[0]->count(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); + const int count = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) TanHBackward<<>>( count, top_diff, top_data, bottom_diff); diff --git a/src/caffe/layers/threshold_layer.cpp b/src/caffe/layers/threshold_layer.cpp index 180ea6a322b..b4b2df51bc9 100644 --- a/src/caffe/layers/threshold_layer.cpp +++ b/src/caffe/layers/threshold_layer.cpp @@ -8,16 +8,16 @@ namespace caffe { template void ThresholdLayer::LayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { NeuronLayer::LayerSetUp(bottom, top); threshold_ = this->layer_param_.threshold_param().threshold(); } template void ThresholdLayer::Forward_cpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); - Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); const int count = bottom[0]->count(); for (int i = 0; i < count; ++i) { top_data[i] = (bottom_data[i] > threshold_) ? Dtype(1) : Dtype(0); diff --git a/src/caffe/layers/threshold_layer.cu b/src/caffe/layers/threshold_layer.cu index 93430815900..7e651290897 100644 --- a/src/caffe/layers/threshold_layer.cu +++ b/src/caffe/layers/threshold_layer.cu @@ -16,9 +16,9 @@ __global__ void ThresholdForward(const int n, const Dtype threshold, template void ThresholdLayer::Forward_gpu(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { const Dtype* bottom_data = bottom[0]->gpu_data(); - Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); const int count = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) ThresholdForward<<>>( diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index a24d7de3daa..cf1f386e454 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -30,7 +30,7 @@ WindowDataLayer::~WindowDataLayer() { template void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, - vector*>* top) { + const vector*>& top) { // LayerSetUp runs through the window_file and creates two structures // that hold windows: one for foreground (object) windows and one // for background (non-object) windows. We use an overlap threshold @@ -152,20 +152,20 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, int crop_size = this->layer_param_.window_data_param().crop_size(); CHECK_GT(crop_size, 0); const int batch_size = this->layer_param_.window_data_param().batch_size(); - (*top)[0]->Reshape(batch_size, channels, crop_size, crop_size); + top[0]->Reshape(batch_size, channels, crop_size, crop_size); this->prefetch_data_.Reshape(batch_size, channels, crop_size, crop_size); - LOG(INFO) << "output data size: " << (*top)[0]->num() << "," - << (*top)[0]->channels() << "," << (*top)[0]->height() << "," - << (*top)[0]->width(); + LOG(INFO) << "output data size: " << top[0]->num() << "," + << top[0]->channels() << "," << top[0]->height() << "," + << top[0]->width(); // datum size - this->datum_channels_ = (*top)[0]->channels(); - this->datum_height_ = (*top)[0]->height(); - this->datum_width_ = (*top)[0]->width(); + this->datum_channels_ = top[0]->channels(); + this->datum_height_ = top[0]->height(); + this->datum_width_ = top[0]->width(); this->datum_size_ = - (*top)[0]->channels() * (*top)[0]->height() * (*top)[0]->width(); + top[0]->channels() * top[0]->height() * top[0]->width(); // label - (*top)[1]->Reshape(batch_size, 1, 1, 1); + top[1]->Reshape(batch_size, 1, 1, 1); this->prefetch_label_.Reshape(batch_size, 1, 1, 1); } diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 6f4a651fb10..21ab15fd31b 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -94,7 +94,7 @@ void Net::Init(const NetParameter& in_param) { } // After this layer is connected, set it up. LOG(INFO) << "Setting up " << layer_names_[layer_id]; - layers_[layer_id]->SetUp(bottom_vecs_[layer_id], &top_vecs_[layer_id]); + layers_[layer_id]->SetUp(bottom_vecs_[layer_id], top_vecs_[layer_id]); for (int top_id = 0; top_id < top_vecs_[layer_id].size(); ++top_id) { if (blob_loss_weights_.size() <= top_id_vecs_[layer_id][top_id]) { blob_loss_weights_.resize(top_id_vecs_[layer_id][top_id] + 1, Dtype(0)); @@ -504,8 +504,8 @@ Dtype Net::ForwardFromTo(int start, int end) { Dtype loss = 0; for (int i = start; i <= end; ++i) { // LOG(ERROR) << "Forwarding " << layer_names_[i]; - layers_[i]->Reshape(bottom_vecs_[i], &top_vecs_[i]); - Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], &top_vecs_[i]); + layers_[i]->Reshape(bottom_vecs_[i], top_vecs_[i]); + Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], top_vecs_[i]); loss += layer_loss; if (debug_info_) { ForwardDebugInfo(i); } } @@ -570,7 +570,7 @@ void Net::BackwardFromTo(int start, int end) { for (int i = start; i >= end; --i) { if (layer_need_backward_[i]) { layers_[i]->Backward( - top_vecs_[i], bottom_need_backward_[i], &bottom_vecs_[i]); + top_vecs_[i], bottom_need_backward_[i], bottom_vecs_[i]); if (debug_info_) { BackwardDebugInfo(i); } } } @@ -683,7 +683,7 @@ void Net::Backward() { template void Net::Reshape() { for (int i = 0; i < layers_.size(); ++i) { - layers_[i]->Reshape(bottom_vecs_[i], &top_vecs_[i]); + layers_[i]->Reshape(bottom_vecs_[i], top_vecs_[i]); } } diff --git a/src/caffe/test/test_accuracy_layer.cpp b/src/caffe/test/test_accuracy_layer.cpp index e11e3f2a981..fa59fab1e8a 100644 --- a/src/caffe/test/test_accuracy_layer.cpp +++ b/src/caffe/test/test_accuracy_layer.cpp @@ -59,7 +59,7 @@ TYPED_TEST_CASE(AccuracyLayerTest, TestDtypes); TYPED_TEST(AccuracyLayerTest, TestSetup) { LayerParameter layer_param; AccuracyLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 1); EXPECT_EQ(this->blob_top_->channels(), 1); EXPECT_EQ(this->blob_top_->height(), 1); @@ -72,7 +72,7 @@ TYPED_TEST(AccuracyLayerTest, TestSetupTopK) { layer_param.mutable_accuracy_param(); accuracy_param->set_top_k(5); AccuracyLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 1); EXPECT_EQ(this->blob_top_->channels(), 1); EXPECT_EQ(this->blob_top_->height(), 1); @@ -83,8 +83,8 @@ TYPED_TEST(AccuracyLayerTest, TestForwardCPU) { LayerParameter layer_param; Caffe::set_mode(Caffe::CPU); AccuracyLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); TypeParam max_value; int max_id; @@ -111,8 +111,8 @@ TYPED_TEST(AccuracyLayerTest, TestForwardCPUTopK) { AccuracyParameter* accuracy_param = layer_param.mutable_accuracy_param(); accuracy_param->set_top_k(this->top_k_); AccuracyLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); TypeParam current_value; int current_rank; diff --git a/src/caffe/test/test_argmax_layer.cpp b/src/caffe/test/test_argmax_layer.cpp index fb3951c3098..3487d42f21e 100644 --- a/src/caffe/test/test_argmax_layer.cpp +++ b/src/caffe/test/test_argmax_layer.cpp @@ -41,7 +41,7 @@ TYPED_TEST_CASE(ArgMaxLayerTest, TestDtypes); TYPED_TEST(ArgMaxLayerTest, TestSetup) { LayerParameter layer_param; ArgMaxLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), 1); } @@ -51,7 +51,7 @@ TYPED_TEST(ArgMaxLayerTest, TestSetupMaxVal) { ArgMaxParameter* argmax_param = layer_param.mutable_argmax_param(); argmax_param->set_out_max_val(true); ArgMaxLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), 2); } @@ -59,8 +59,8 @@ TYPED_TEST(ArgMaxLayerTest, TestSetupMaxVal) { TYPED_TEST(ArgMaxLayerTest, TestCPU) { LayerParameter layer_param; ArgMaxLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); const TypeParam* top_data = this->blob_top_->cpu_data(); @@ -84,8 +84,8 @@ TYPED_TEST(ArgMaxLayerTest, TestCPUMaxVal) { ArgMaxParameter* argmax_param = layer_param.mutable_argmax_param(); argmax_param->set_out_max_val(true); ArgMaxLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); const TypeParam* top_data = this->blob_top_->cpu_data(); @@ -110,8 +110,8 @@ TYPED_TEST(ArgMaxLayerTest, TestCPUTopK) { ArgMaxParameter* argmax_param = layer_param.mutable_argmax_param(); argmax_param->set_top_k(this->top_k_); ArgMaxLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values int max_ind; TypeParam max_val; @@ -140,8 +140,8 @@ TYPED_TEST(ArgMaxLayerTest, TestCPUMaxValTopK) { argmax_param->set_out_max_val(true); argmax_param->set_top_k(this->top_k_); ArgMaxLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values int max_ind; TypeParam max_val; diff --git a/src/caffe/test/test_concat_layer.cpp b/src/caffe/test/test_concat_layer.cpp index c60b7f744cc..f14f1d2fa4f 100644 --- a/src/caffe/test/test_concat_layer.cpp +++ b/src/caffe/test/test_concat_layer.cpp @@ -63,7 +63,7 @@ TYPED_TEST(ConcatLayerTest, TestSetupNum) { LayerParameter layer_param; layer_param.mutable_concat_param()->set_concat_dim(0); ConcatLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_1, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_1, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_0->num() + this->blob_bottom_2->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_0->channels()); @@ -75,7 +75,7 @@ TYPED_TEST(ConcatLayerTest, TestSetupChannels) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; ConcatLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_0, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_0, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_0->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_0->channels()+this->blob_bottom_1->channels()); @@ -88,8 +88,8 @@ TYPED_TEST(ConcatLayerTest, TestNum) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; ConcatLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_0, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_0, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_0, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_0, this->blob_top_vec_); for (int n = 0; n < this->blob_top_->num(); ++n) { for (int c = 0; c < this->blob_bottom_0->channels(); ++c) { for (int h = 0; h < this->blob_top_->height(); ++h) { @@ -115,8 +115,8 @@ TYPED_TEST(ConcatLayerTest, TestGradient) { LayerParameter layer_param; ConcatLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradient(&layer, &(this->blob_bottom_vec_0), - &(this->blob_top_vec_)); + checker.CheckGradient(&layer, this->blob_bottom_vec_0, + this->blob_top_vec_); } } // namespace caffe diff --git a/src/caffe/test/test_contrastive_loss_layer.cpp b/src/caffe/test/test_contrastive_loss_layer.cpp index a5bef4c9826..d269fbc26f2 100644 --- a/src/caffe/test/test_contrastive_loss_layer.cpp +++ b/src/caffe/test/test_contrastive_loss_layer.cpp @@ -62,8 +62,8 @@ TYPED_TEST(ContrastiveLossLayerTest, TestForward) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; ContrastiveLossLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // manually compute to compare const Dtype margin = layer_param.contrastive_loss_param().margin(); const int num = this->blob_bottom_data_i_->num(); @@ -90,13 +90,13 @@ TYPED_TEST(ContrastiveLossLayerTest, TestGradient) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; ContrastiveLossLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); GradientChecker checker(1e-2, 1e-2, 1701); // check the gradient for the first two bottom layers - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_), 0); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_), 1); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 1); } } // namespace caffe diff --git a/src/caffe/test/test_convolution_layer.cpp b/src/caffe/test/test_convolution_layer.cpp index a38ad3fd1a8..aef9092d8fe 100644 --- a/src/caffe/test/test_convolution_layer.cpp +++ b/src/caffe/test/test_convolution_layer.cpp @@ -157,7 +157,7 @@ TYPED_TEST(ConvolutionLayerTest, TestSetup) { this->blob_top_vec_.push_back(this->blob_top_2_); shared_ptr > layer( new ConvolutionLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 4); EXPECT_EQ(this->blob_top_->height(), 2); @@ -170,7 +170,7 @@ TYPED_TEST(ConvolutionLayerTest, TestSetup) { convolution_param->set_num_output(3); convolution_param->set_group(3); layer.reset(new ConvolutionLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 3); EXPECT_EQ(this->blob_top_->height(), 2); @@ -197,8 +197,8 @@ TYPED_TEST(ConvolutionLayerTest, TestSimpleConvolution) { convolution_param->mutable_bias_filler()->set_value(0.1); shared_ptr > layer( new ConvolutionLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Check against reference convolution. const Dtype* top_data; const Dtype* ref_top_data; @@ -233,8 +233,8 @@ TYPED_TEST(ConvolutionLayerTest, TestSimpleConvolutionGroup) { convolution_param->mutable_bias_filler()->set_value(0.1); shared_ptr > layer( new ConvolutionLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Check against reference convolution. const Dtype* top_data; const Dtype* ref_top_data; @@ -284,8 +284,8 @@ TYPED_TEST(ConvolutionLayerTest, TestSobelConvolution) { weights[i + 7] = 0; weights[i + 8] = 1; } - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Compute Sobel G_x operator as separable 3 x 1 and 1 x 3 convolutions. // (1) the [1 2 1] column filter vector*> sep_blob_bottom_vec; @@ -311,8 +311,8 @@ TYPED_TEST(ConvolutionLayerTest, TestSobelConvolution) { weights_1[i + 1] = 2; weights_1[i + 2] = 1; } - layer->SetUp(sep_blob_bottom_vec, &(sep_blob_top_vec)); - layer->Forward(sep_blob_bottom_vec, &(sep_blob_top_vec)); + layer->SetUp(sep_blob_bottom_vec, sep_blob_top_vec); + layer->Forward(sep_blob_bottom_vec, sep_blob_top_vec); // (2) the [-1 0 1] row filter blob_sep->CopyFrom(*this->blob_top_2_, false, true); sep_blob_bottom_vec.clear(); @@ -333,8 +333,8 @@ TYPED_TEST(ConvolutionLayerTest, TestSobelConvolution) { weights_2[i + 1] = 0; weights_2[i + 2] = 1; } - layer->SetUp(sep_blob_bottom_vec, &(sep_blob_top_vec)); - layer->Forward(sep_blob_bottom_vec, &(sep_blob_top_vec)); + layer->SetUp(sep_blob_bottom_vec, sep_blob_top_vec); + layer->Forward(sep_blob_bottom_vec, sep_blob_top_vec); // Test equivalence of full and separable filters. const Dtype* top_data = this->blob_top_->cpu_data(); const Dtype* sep_top_data = this->blob_top_2_->cpu_data(); @@ -357,8 +357,8 @@ TYPED_TEST(ConvolutionLayerTest, TestGradient) { convolution_param->mutable_bias_filler()->set_type("gaussian"); ConvolutionLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(ConvolutionLayerTest, TestGradientGroup) { @@ -374,8 +374,8 @@ TYPED_TEST(ConvolutionLayerTest, TestGradientGroup) { convolution_param->mutable_bias_filler()->set_type("gaussian"); ConvolutionLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } #ifdef USE_CUDNN @@ -437,7 +437,7 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSetupCuDNN) { this->blob_top_vec_.push_back(this->blob_top_2_); shared_ptr > layer( new CuDNNConvolutionLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 4); EXPECT_EQ(this->blob_top_->height(), 2); @@ -450,7 +450,7 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSetupCuDNN) { convolution_param->set_num_output(3); convolution_param->set_group(3); layer.reset(new CuDNNConvolutionLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 3); EXPECT_EQ(this->blob_top_->height(), 2); @@ -477,8 +477,8 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSimpleConvolutionCuDNN) { convolution_param->mutable_bias_filler()->set_value(0.1); shared_ptr > layer( new CuDNNConvolutionLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Check against reference convolution. const TypeParam* top_data; const TypeParam* ref_top_data; @@ -513,8 +513,8 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSimpleConvolutionGroupCuDNN) { convolution_param->mutable_bias_filler()->set_value(0.1); shared_ptr > layer( new CuDNNConvolutionLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Check against reference convolution. const TypeParam* top_data; const TypeParam* ref_top_data; @@ -564,8 +564,8 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSobelConvolutionCuDNN) { weights[i + 7] = 0; weights[i + 8] = 1; } - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Compute Sobel G_x operator as separable 3 x 1 and 1 x 3 convolutions. // (1) the [1 2 1] column filter vector*> sep_blob_bottom_vec; @@ -591,8 +591,8 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSobelConvolutionCuDNN) { weights_1[i + 1] = 2; weights_1[i + 2] = 1; } - layer->SetUp(sep_blob_bottom_vec, &(sep_blob_top_vec)); - layer->Forward(sep_blob_bottom_vec, &(sep_blob_top_vec)); + layer->SetUp(sep_blob_bottom_vec, sep_blob_top_vec); + layer->Forward(sep_blob_bottom_vec, sep_blob_top_vec); // (2) the [-1 0 1] row filter blob_sep->CopyFrom(*this->blob_top_2_, false, true); sep_blob_bottom_vec.clear(); @@ -613,8 +613,8 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSobelConvolutionCuDNN) { weights_2[i + 1] = 0; weights_2[i + 2] = 1; } - layer->SetUp(sep_blob_bottom_vec, &(sep_blob_top_vec)); - layer->Forward(sep_blob_bottom_vec, &(sep_blob_top_vec)); + layer->SetUp(sep_blob_bottom_vec, sep_blob_top_vec); + layer->Forward(sep_blob_bottom_vec, sep_blob_top_vec); // Test equivalence of full and separable filters. const TypeParam* top_data = this->blob_top_->cpu_data(); const TypeParam* sep_top_data = this->blob_top_2_->cpu_data(); @@ -637,8 +637,8 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestGradientCuDNN) { convolution_param->mutable_bias_filler()->set_type("gaussian"); CuDNNConvolutionLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(CuDNNConvolutionLayerTest, TestGradientGroupCuDNN) { @@ -654,8 +654,8 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestGradientGroupCuDNN) { convolution_param->mutable_bias_filler()->set_type("gaussian"); CuDNNConvolutionLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } #endif diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index 887124aa5bc..657ffdea68c 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -125,7 +125,7 @@ class DataLayerTest : public MultiDeviceTest { transform_param->set_scale(scale); DataLayer layer(param); - layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); EXPECT_EQ(blob_top_data_->num(), 5); EXPECT_EQ(blob_top_data_->channels(), 2); EXPECT_EQ(blob_top_data_->height(), 3); @@ -136,7 +136,7 @@ class DataLayerTest : public MultiDeviceTest { EXPECT_EQ(blob_top_label_->width(), 1); for (int iter = 0; iter < 100; ++iter) { - layer.Forward(blob_bottom_vec_, &blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); for (int i = 0; i < 5; ++i) { EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); } @@ -165,7 +165,7 @@ class DataLayerTest : public MultiDeviceTest { transform_param->set_crop_size(1); DataLayer layer(param); - layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); EXPECT_EQ(blob_top_data_->num(), 5); EXPECT_EQ(blob_top_data_->channels(), 2); EXPECT_EQ(blob_top_data_->height(), 1); @@ -176,7 +176,7 @@ class DataLayerTest : public MultiDeviceTest { EXPECT_EQ(blob_top_label_->width(), 1); for (int iter = 0; iter < 2; ++iter) { - layer.Forward(blob_bottom_vec_, &blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); for (int i = 0; i < 5; ++i) { EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); } @@ -219,9 +219,9 @@ class DataLayerTest : public MultiDeviceTest { vector > crop_sequence; { DataLayer layer1(param); - layer1.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer1.SetUp(blob_bottom_vec_, blob_top_vec_); for (int iter = 0; iter < 2; ++iter) { - layer1.Forward(blob_bottom_vec_, &blob_top_vec_); + layer1.Forward(blob_bottom_vec_, blob_top_vec_); for (int i = 0; i < 5; ++i) { EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); } @@ -240,9 +240,9 @@ class DataLayerTest : public MultiDeviceTest { // Check that the sequence is the same as the original. Caffe::set_random_seed(seed_); DataLayer layer2(param); - layer2.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer2.SetUp(blob_bottom_vec_, blob_top_vec_); for (int iter = 0; iter < 2; ++iter) { - layer2.Forward(blob_bottom_vec_, &blob_top_vec_); + layer2.Forward(blob_bottom_vec_, blob_top_vec_); for (int i = 0; i < 5; ++i) { EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); } @@ -274,9 +274,9 @@ class DataLayerTest : public MultiDeviceTest { vector > crop_sequence; { DataLayer layer1(param); - layer1.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer1.SetUp(blob_bottom_vec_, blob_top_vec_); for (int iter = 0; iter < 2; ++iter) { - layer1.Forward(blob_bottom_vec_, &blob_top_vec_); + layer1.Forward(blob_bottom_vec_, blob_top_vec_); for (int i = 0; i < 5; ++i) { EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); } @@ -295,9 +295,9 @@ class DataLayerTest : public MultiDeviceTest { // srand with 1701. Check that the sequence differs from the original. srand(seed_); DataLayer layer2(param); - layer2.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer2.SetUp(blob_bottom_vec_, blob_top_vec_); for (int iter = 0; iter < 2; ++iter) { - layer2.Forward(blob_bottom_vec_, &blob_top_vec_); + layer2.Forward(blob_bottom_vec_, blob_top_vec_); for (int i = 0; i < 5; ++i) { EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); } diff --git a/src/caffe/test/test_dummy_data_layer.cpp b/src/caffe/test/test_dummy_data_layer.cpp index 4188bb68c9e..da121fa5d99 100644 --- a/src/caffe/test/test_dummy_data_layer.cpp +++ b/src/caffe/test/test_dummy_data_layer.cpp @@ -56,7 +56,7 @@ TYPED_TEST(DummyDataLayerTest, TestOneTopConstant) { dummy_data_param->add_width(4); this->blob_top_vec_.resize(1); DummyDataLayer layer(param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_a_->num(), 5); EXPECT_EQ(this->blob_top_a_->channels(), 3); EXPECT_EQ(this->blob_top_a_->height(), 2); @@ -68,7 +68,7 @@ TYPED_TEST(DummyDataLayerTest, TestOneTopConstant) { EXPECT_EQ(0, this->blob_top_vec_[i]->cpu_data()[j]); } } - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_top_vec_.size(); ++i) { for (int j = 0; j < this->blob_top_vec_[i]->count(); ++j) { EXPECT_EQ(0, this->blob_top_vec_[i]->cpu_data()[j]); @@ -92,7 +92,7 @@ TYPED_TEST(DummyDataLayerTest, TestTwoTopConstant) { data_filler_param->set_value(7); this->blob_top_vec_.resize(2); DummyDataLayer layer(param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_a_->num(), 5); EXPECT_EQ(this->blob_top_a_->channels(), 3); EXPECT_EQ(this->blob_top_a_->height(), 2); @@ -107,7 +107,7 @@ TYPED_TEST(DummyDataLayerTest, TestTwoTopConstant) { EXPECT_EQ(7, this->blob_top_vec_[i]->cpu_data()[j]); } } - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_top_vec_.size(); ++i) { for (int j = 0; j < this->blob_top_vec_[i]->count(); ++j) { EXPECT_EQ(7, this->blob_top_vec_[i]->cpu_data()[j]); @@ -134,7 +134,7 @@ TYPED_TEST(DummyDataLayerTest, TestThreeTopConstantGaussianConstant) { FillerParameter* data_filler_param_c = dummy_data_param->add_data_filler(); data_filler_param_c->set_value(9); DummyDataLayer layer(param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_a_->num(), 5); EXPECT_EQ(this->blob_top_a_->channels(), 3); EXPECT_EQ(this->blob_top_a_->height(), 2); @@ -160,7 +160,7 @@ TYPED_TEST(DummyDataLayerTest, TestThreeTopConstantGaussianConstant) { } // Do a Forward pass to fill in Blob b with Gaussian data. - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_top_a_->count(); ++i) { EXPECT_EQ(7, this->blob_top_a_->cpu_data()[i]); } @@ -180,7 +180,7 @@ TYPED_TEST(DummyDataLayerTest, TestThreeTopConstantGaussianConstant) { // Do another Forward pass to fill in Blob b with Gaussian data again, // checking that we get different values. - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_top_a_->count(); ++i) { EXPECT_EQ(7, this->blob_top_a_->cpu_data()[i]); } diff --git a/src/caffe/test/test_eltwise_layer.cpp b/src/caffe/test/test_eltwise_layer.cpp index d5cf08229ab..be0c1347709 100644 --- a/src/caffe/test/test_eltwise_layer.cpp +++ b/src/caffe/test/test_eltwise_layer.cpp @@ -58,7 +58,7 @@ TYPED_TEST(EltwiseLayerTest, TestSetUp) { eltwise_param->set_operation(EltwiseParameter_EltwiseOp_PROD); shared_ptr > layer( new EltwiseLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 3); EXPECT_EQ(this->blob_top_->height(), 4); @@ -72,8 +72,8 @@ TYPED_TEST(EltwiseLayerTest, TestProd) { eltwise_param->set_operation(EltwiseParameter_EltwiseOp_PROD); shared_ptr > layer( new EltwiseLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* data = this->blob_top_->cpu_data(); const int count = this->blob_top_->count(); const Dtype* in_data_a = this->blob_bottom_a_->cpu_data(); @@ -91,8 +91,8 @@ TYPED_TEST(EltwiseLayerTest, TestSum) { eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); shared_ptr > layer( new EltwiseLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* data = this->blob_top_->cpu_data(); const int count = this->blob_top_->count(); const Dtype* in_data_a = this->blob_bottom_a_->cpu_data(); @@ -113,8 +113,8 @@ TYPED_TEST(EltwiseLayerTest, TestSumCoeff) { eltwise_param->add_coeff(2); shared_ptr > layer( new EltwiseLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* data = this->blob_top_->cpu_data(); const int count = this->blob_top_->count(); const Dtype* in_data_a = this->blob_bottom_a_->cpu_data(); @@ -134,8 +134,8 @@ TYPED_TEST(EltwiseLayerTest, TestStableProdGradient) { eltwise_param->set_stable_prod_grad(true); EltwiseLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(EltwiseLayerTest, TestUnstableProdGradient) { @@ -146,8 +146,8 @@ TYPED_TEST(EltwiseLayerTest, TestUnstableProdGradient) { eltwise_param->set_stable_prod_grad(false); EltwiseLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(EltwiseLayerTest, TestSumGradient) { @@ -157,8 +157,8 @@ TYPED_TEST(EltwiseLayerTest, TestSumGradient) { eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); EltwiseLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(EltwiseLayerTest, TestSumCoeffGradient) { @@ -171,8 +171,8 @@ TYPED_TEST(EltwiseLayerTest, TestSumCoeffGradient) { eltwise_param->add_coeff(2); EltwiseLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(EltwiseLayerTest, TestMax) { @@ -182,8 +182,8 @@ TYPED_TEST(EltwiseLayerTest, TestMax) { eltwise_param->set_operation(EltwiseParameter_EltwiseOp_MAX); shared_ptr > layer( new EltwiseLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* data = this->blob_top_->cpu_data(); const int count = this->blob_top_->count(); const Dtype* in_data_a = this->blob_bottom_a_->cpu_data(); @@ -202,8 +202,8 @@ TYPED_TEST(EltwiseLayerTest, TestMaxGradient) { eltwise_param->set_operation(EltwiseParameter_EltwiseOp_MAX); EltwiseLayer layer(layer_param); GradientChecker checker(1e-4, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } // namespace caffe diff --git a/src/caffe/test/test_euclidean_loss_layer.cpp b/src/caffe/test/test_euclidean_loss_layer.cpp index d7d2de7e9d4..1949742bbcb 100644 --- a/src/caffe/test/test_euclidean_loss_layer.cpp +++ b/src/caffe/test/test_euclidean_loss_layer.cpp @@ -44,18 +44,18 @@ class EuclideanLossLayerTest : public MultiDeviceTest { // equivalent to explicitly specifiying a weight of 1. LayerParameter layer_param; EuclideanLossLayer layer_weight_1(layer_param); - layer_weight_1.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer_weight_1.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype loss_weight_1 = - layer_weight_1.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer_weight_1.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Get the loss again with a different objective weight; check that it is // scaled appropriately. const Dtype kLossWeight = 3.7; layer_param.add_loss_weight(kLossWeight); EuclideanLossLayer layer_weight_2(layer_param); - layer_weight_2.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer_weight_2.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype loss_weight_2 = - layer_weight_2.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer_weight_2.Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype kErrorMargin = 1e-5; EXPECT_NEAR(loss_weight_1 * kLossWeight, loss_weight_2, kErrorMargin); // Make sure the loss is non-trivial. @@ -82,10 +82,10 @@ TYPED_TEST(EuclideanLossLayerTest, TestGradient) { const Dtype kLossWeight = 3.7; layer_param.add_loss_weight(kLossWeight); EuclideanLossLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); GradientChecker checker(1e-2, 1e-2, 1701); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } // namespace caffe diff --git a/src/caffe/test/test_flatten_layer.cpp b/src/caffe/test/test_flatten_layer.cpp index cbd01f245f2..3042d293cf7 100644 --- a/src/caffe/test/test_flatten_layer.cpp +++ b/src/caffe/test/test_flatten_layer.cpp @@ -41,7 +41,7 @@ TYPED_TEST(FlattenLayerTest, TestSetup) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; FlattenLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 3 * 6 * 5); EXPECT_EQ(this->blob_top_->height(), 1); @@ -52,8 +52,8 @@ TYPED_TEST(FlattenLayerTest, Test) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; FlattenLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int c = 0; c < 3 * 6 * 5; ++c) { EXPECT_EQ(this->blob_top_->data_at(0, c, 0, 0), this->blob_bottom_->data_at(0, c / (6 * 5), (c / 5) % 6, c % 5)); @@ -67,8 +67,8 @@ TYPED_TEST(FlattenLayerTest, TestGradient) { LayerParameter layer_param; FlattenLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } diff --git a/src/caffe/test/test_hdf5_output_layer.cpp b/src/caffe/test/test_hdf5_output_layer.cpp index eb09c8d1f3a..c8282233e5b 100644 --- a/src/caffe/test/test_hdf5_output_layer.cpp +++ b/src/caffe/test/test_hdf5_output_layer.cpp @@ -96,8 +96,8 @@ TYPED_TEST(HDF5OutputLayerTest, TestForward) { { HDF5OutputLayer layer(param); EXPECT_EQ(layer.file_name(), this->output_file_name_); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); } file_id = H5Fopen(this->output_file_name_.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); diff --git a/src/caffe/test/test_hdf5data_layer.cpp b/src/caffe/test/test_hdf5data_layer.cpp index acca75b19b1..db9068b32ed 100644 --- a/src/caffe/test/test_hdf5data_layer.cpp +++ b/src/caffe/test/test_hdf5data_layer.cpp @@ -67,7 +67,7 @@ TYPED_TEST(HDF5DataLayerTest, TestRead) { // Test that the layer setup got the correct parameters. HDF5DataLayer layer(param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_data_->num(), batch_size); EXPECT_EQ(this->blob_top_data_->channels(), num_cols); EXPECT_EQ(this->blob_top_data_->height(), height); @@ -78,12 +78,12 @@ TYPED_TEST(HDF5DataLayerTest, TestRead) { EXPECT_EQ(this->blob_top_label_->height(), 1); EXPECT_EQ(this->blob_top_label_->width(), 1); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); // Go through the data 10 times (5 batches). const int data_size = num_cols * height * width; for (int iter = 0; iter < 10; ++iter) { - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // On even iterations, we're reading the first half of the data. // On odd iterations, we're reading the second half of the data. diff --git a/src/caffe/test/test_hinge_loss_layer.cpp b/src/caffe/test/test_hinge_loss_layer.cpp index 3c11b9ac491..b6a99022905 100644 --- a/src/caffe/test/test_hinge_loss_layer.cpp +++ b/src/caffe/test/test_hinge_loss_layer.cpp @@ -57,8 +57,8 @@ TYPED_TEST(HingeLossLayerTest, TestGradientL1) { LayerParameter layer_param; HingeLossLayer layer(layer_param); GradientChecker checker(1e-2, 2e-3, 1701, 1, 0.01); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_), 0); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); } TYPED_TEST(HingeLossLayerTest, TestGradientL2) { @@ -69,8 +69,8 @@ TYPED_TEST(HingeLossLayerTest, TestGradientL2) { hinge_loss_param->set_norm(HingeLossParameter_Norm_L2); HingeLossLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2, 1701); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_), 0); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); } } // namespace caffe diff --git a/src/caffe/test/test_im2col_layer.cpp b/src/caffe/test/test_im2col_layer.cpp index 32cf6369361..f50abe103f8 100644 --- a/src/caffe/test/test_im2col_layer.cpp +++ b/src/caffe/test/test_im2col_layer.cpp @@ -44,7 +44,7 @@ TYPED_TEST(Im2colLayerTest, TestSetup) { convolution_param->set_kernel_size(3); convolution_param->set_stride(2); Im2colLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 27); EXPECT_EQ(this->blob_top_->height(), 2); @@ -59,8 +59,8 @@ TYPED_TEST(Im2colLayerTest, TestForward) { convolution_param->set_kernel_size(3); convolution_param->set_stride(2); Im2colLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // We are lazy and will only check the top left block for (int c = 0; c < 27; ++c) { EXPECT_EQ(this->blob_bottom_->data_at(0, (c / 9), (c / 3) % 3, c % 3), @@ -77,8 +77,8 @@ TYPED_TEST(Im2colLayerTest, TestGradient) { convolution_param->set_stride(2); Im2colLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } @@ -91,8 +91,8 @@ TYPED_TEST(Im2colLayerTest, TestRect) { convolution_param->set_kernel_w(3); convolution_param->set_stride(2); Im2colLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // We are lazy and will only check the top left block for (int c = 0; c < 45; ++c) { EXPECT_EQ(this->blob_top_->data_at(0, c, 0, 0), @@ -111,8 +111,8 @@ TYPED_TEST(Im2colLayerTest, TestRectGradient) { convolution_param->set_stride(2); Im2colLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } // namespace caffe diff --git a/src/caffe/test/test_image_data_layer.cpp b/src/caffe/test/test_image_data_layer.cpp index d098c765258..77523ef8c18 100644 --- a/src/caffe/test/test_image_data_layer.cpp +++ b/src/caffe/test/test_image_data_layer.cpp @@ -61,7 +61,7 @@ TYPED_TEST(ImageDataLayerTest, TestRead) { image_data_param->set_source(this->filename_.c_str()); image_data_param->set_shuffle(false); ImageDataLayer layer(param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_data_->num(), 5); EXPECT_EQ(this->blob_top_data_->channels(), 3); EXPECT_EQ(this->blob_top_data_->height(), 360); @@ -72,7 +72,7 @@ TYPED_TEST(ImageDataLayerTest, TestRead) { EXPECT_EQ(this->blob_top_label_->width(), 1); // Go through the data twice for (int iter = 0; iter < 2; ++iter) { - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < 5; ++i) { EXPECT_EQ(i, this->blob_top_label_->cpu_data()[i]); } @@ -89,7 +89,7 @@ TYPED_TEST(ImageDataLayerTest, TestResize) { image_data_param->set_new_width(256); image_data_param->set_shuffle(false); ImageDataLayer layer(param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_data_->num(), 5); EXPECT_EQ(this->blob_top_data_->channels(), 3); EXPECT_EQ(this->blob_top_data_->height(), 256); @@ -100,7 +100,7 @@ TYPED_TEST(ImageDataLayerTest, TestResize) { EXPECT_EQ(this->blob_top_label_->width(), 1); // Go through the data twice for (int iter = 0; iter < 2; ++iter) { - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < 5; ++i) { EXPECT_EQ(i, this->blob_top_label_->cpu_data()[i]); } @@ -115,7 +115,7 @@ TYPED_TEST(ImageDataLayerTest, TestShuffle) { image_data_param->set_source(this->filename_.c_str()); image_data_param->set_shuffle(true); ImageDataLayer layer(param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_data_->num(), 5); EXPECT_EQ(this->blob_top_data_->channels(), 3); EXPECT_EQ(this->blob_top_data_->height(), 360); @@ -126,7 +126,7 @@ TYPED_TEST(ImageDataLayerTest, TestShuffle) { EXPECT_EQ(this->blob_top_label_->width(), 1); // Go through the data twice for (int iter = 0; iter < 2; ++iter) { - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); map values_to_indices; int num_in_order = 0; for (int i = 0; i < 5; ++i) { diff --git a/src/caffe/test/test_infogain_loss_layer.cpp b/src/caffe/test/test_infogain_loss_layer.cpp index de2f901af31..7ec2f8073c1 100644 --- a/src/caffe/test/test_infogain_loss_layer.cpp +++ b/src/caffe/test/test_infogain_loss_layer.cpp @@ -63,8 +63,8 @@ TYPED_TEST(InfogainLossLayerTest, TestGradient) { LayerParameter layer_param; InfogainLossLayer layer(layer_param); GradientChecker checker(1e-4, 2e-2, 1701, 1, 0.01); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_), 0); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); } } // namespace caffe diff --git a/src/caffe/test/test_inner_product_layer.cpp b/src/caffe/test/test_inner_product_layer.cpp index 5f9729c4f90..c03df17383a 100644 --- a/src/caffe/test/test_inner_product_layer.cpp +++ b/src/caffe/test/test_inner_product_layer.cpp @@ -48,7 +48,7 @@ TYPED_TEST(InnerProductLayerTest, TestSetUp) { inner_product_param->set_num_output(10); shared_ptr > layer( new InnerProductLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->height(), 1); EXPECT_EQ(this->blob_top_->width(), 1); @@ -73,8 +73,8 @@ TYPED_TEST(InnerProductLayerTest, TestForward) { inner_product_param->mutable_bias_filler()->set_max(2); shared_ptr > layer( new InnerProductLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* data = this->blob_top_->cpu_data(); const int count = this->blob_top_->count(); for (int i = 0; i < count; ++i) { @@ -103,8 +103,8 @@ TYPED_TEST(InnerProductLayerTest, TestGradient) { inner_product_param->mutable_bias_filler()->set_max(2); InnerProductLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } else { LOG(ERROR) << "Skipping test due to old architecture."; } diff --git a/src/caffe/test/test_lrn_layer.cpp b/src/caffe/test/test_lrn_layer.cpp index 3bd62fd9e18..07425df9b3a 100644 --- a/src/caffe/test/test_lrn_layer.cpp +++ b/src/caffe/test/test_lrn_layer.cpp @@ -116,7 +116,7 @@ TYPED_TEST(LRNLayerTest, TestSetupAcrossChannels) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; LRNLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 7); EXPECT_EQ(this->blob_top_->height(), 3); @@ -127,8 +127,8 @@ TYPED_TEST(LRNLayerTest, TestForwardAcrossChannels) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; LRNLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); Blob top_reference; this->ReferenceLRNForward(*(this->blob_bottom_), layer_param, &top_reference); @@ -143,20 +143,20 @@ TYPED_TEST(LRNLayerTest, TestGradientAcrossChannels) { LayerParameter layer_param; LRNLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_top_->count(); ++i) { this->blob_top_->mutable_cpu_diff()[i] = 1.; } vector propagate_down(this->blob_bottom_vec_.size(), true); layer.Backward(this->blob_top_vec_, propagate_down, - &(this->blob_bottom_vec_)); + this->blob_bottom_vec_); // for (int i = 0; i < this->blob_bottom_->count(); ++i) { // std::cout << "CPU diff " << this->blob_bottom_->cpu_diff()[i] // << std::endl; // } - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(LRNLayerTest, TestSetupWithinChannel) { @@ -166,7 +166,7 @@ TYPED_TEST(LRNLayerTest, TestSetupWithinChannel) { LRNParameter_NormRegion_WITHIN_CHANNEL); layer_param.mutable_lrn_param()->set_local_size(3); LRNLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 2); EXPECT_EQ(this->blob_top_->channels(), 7); EXPECT_EQ(this->blob_top_->height(), 3); @@ -180,8 +180,8 @@ TYPED_TEST(LRNLayerTest, TestForwardWithinChannel) { LRNParameter_NormRegion_WITHIN_CHANNEL); layer_param.mutable_lrn_param()->set_local_size(3); LRNLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); Blob top_reference; this->ReferenceLRNForward(*(this->blob_bottom_), layer_param, &top_reference); @@ -199,13 +199,13 @@ TYPED_TEST(LRNLayerTest, TestGradientWithinChannel) { layer_param.mutable_lrn_param()->set_local_size(3); LRNLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_top_->count(); ++i) { this->blob_top_->mutable_cpu_diff()[i] = 1.; } - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } diff --git a/src/caffe/test/test_maxpool_dropout_layers.cpp b/src/caffe/test/test_maxpool_dropout_layers.cpp index 311c7781be5..b1f4e4eac9a 100644 --- a/src/caffe/test/test_maxpool_dropout_layers.cpp +++ b/src/caffe/test/test_maxpool_dropout_layers.cpp @@ -47,9 +47,9 @@ TYPED_TEST(MaxPoolingDropoutTest, TestSetup) { pooling_param->set_kernel_size(3); pooling_param->set_stride(2); PoolingLayer max_layer(layer_param); - max_layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + max_layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); DropoutLayer dropout_layer(layer_param); - dropout_layer.SetUp(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.SetUp(this->blob_top_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); EXPECT_EQ(this->blob_top_->height(), 3); @@ -64,8 +64,8 @@ TYPED_TEST(MaxPoolingDropoutTest, TestForward) { pooling_param->set_kernel_size(3); pooling_param->set_stride(2); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* top_data = this->blob_top_->cpu_data(); Dtype sum = 0.; for (int i = 0; i < this->blob_top_->count(); ++i) { @@ -74,8 +74,8 @@ TYPED_TEST(MaxPoolingDropoutTest, TestForward) { EXPECT_EQ(sum, this->blob_top_->count()); // Dropout in-place DropoutLayer dropout_layer(layer_param); - dropout_layer.SetUp(this->blob_top_vec_, &(this->blob_top_vec_)); - dropout_layer.Forward(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.SetUp(this->blob_top_vec_, this->blob_top_vec_); + dropout_layer.Forward(this->blob_top_vec_, this->blob_top_vec_); sum = 0.; Dtype scale = 1. / (1. - layer_param.dropout_param().dropout_ratio()); top_data = this->blob_top_->cpu_data(); @@ -94,14 +94,14 @@ TYPED_TEST(MaxPoolingDropoutTest, TestBackward) { pooling_param->set_kernel_size(3); pooling_param->set_stride(2); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_top_->count(); ++i) { this->blob_top_->mutable_cpu_diff()[i] = 1.; } vector propagate_down(this->blob_bottom_vec_.size(), true); layer.Backward(this->blob_top_vec_, propagate_down, - &(this->blob_bottom_vec_)); + this->blob_bottom_vec_); const Dtype* bottom_diff = this->blob_bottom_->cpu_diff(); Dtype sum = 0.; for (int i = 0; i < this->blob_bottom_->count(); ++i) { @@ -110,12 +110,12 @@ TYPED_TEST(MaxPoolingDropoutTest, TestBackward) { EXPECT_EQ(sum, this->blob_top_->count()); // Dropout in-place DropoutLayer dropout_layer(layer_param); - dropout_layer.SetUp(this->blob_top_vec_, &(this->blob_top_vec_)); - dropout_layer.Forward(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.SetUp(this->blob_top_vec_, this->blob_top_vec_); + dropout_layer.Forward(this->blob_top_vec_, this->blob_top_vec_); dropout_layer.Backward(this->blob_top_vec_, propagate_down, - &(this->blob_top_vec_)); + this->blob_top_vec_); layer.Backward(this->blob_top_vec_, propagate_down, - &(this->blob_bottom_vec_)); + this->blob_bottom_vec_); Dtype sum_with_dropout = 0.; bottom_diff = this->blob_bottom_->cpu_diff(); for (int i = 0; i < this->blob_bottom_->count(); ++i) { diff --git a/src/caffe/test/test_memory_data_layer.cpp b/src/caffe/test/test_memory_data_layer.cpp index 3dc00345743..497ab0d15e7 100644 --- a/src/caffe/test/test_memory_data_layer.cpp +++ b/src/caffe/test/test_memory_data_layer.cpp @@ -70,7 +70,7 @@ TYPED_TEST(MemoryDataLayerTest, TestSetup) { md_param->set_width(this->width_); shared_ptr > layer( new MemoryDataLayer(layer_param)); - layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->data_blob_->num(), this->batch_size_); EXPECT_EQ(this->data_blob_->channels(), this->channels_); EXPECT_EQ(this->data_blob_->height(), this->height_); @@ -93,12 +93,12 @@ TYPED_TEST(MemoryDataLayerTest, TestForward) { md_param->set_width(this->width_); shared_ptr > layer( new MemoryDataLayer(layer_param)); - layer->DataLayerSetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->DataLayerSetUp(this->blob_bottom_vec_, this->blob_top_vec_); layer->Reset(this->data_->mutable_cpu_data(), this->labels_->mutable_cpu_data(), this->data_->num()); for (int i = 0; i < this->batches_ * 6; ++i) { int batch_num = i % this->batches_; - layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int j = 0; j < this->data_blob_->count(); ++j) { EXPECT_EQ(this->data_blob_->cpu_data()[j], this->data_->cpu_data()[ @@ -121,7 +121,7 @@ TYPED_TEST(MemoryDataLayerTest, AddDatumVectorDefaultTransform) { memory_data_param->set_height(this->height_); memory_data_param->set_width(this->width_); MemoryDataLayer layer(param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); vector datum_vector(this->batch_size_); const size_t count = this->channels_ * this->height_ * this->width_; @@ -144,7 +144,7 @@ TYPED_TEST(MemoryDataLayerTest, AddDatumVectorDefaultTransform) { int data_index; // Go through the data 5 times for (int iter = 0; iter < 5; ++iter) { - layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* data = this->data_blob_->cpu_data(); size_t index = 0; for (int i = 0; i < this->batch_size_; ++i) { diff --git a/src/caffe/test/test_multinomial_logistic_loss_layer.cpp b/src/caffe/test/test_multinomial_logistic_loss_layer.cpp index 1fc4c42f0f4..9038017e3e2 100644 --- a/src/caffe/test/test_multinomial_logistic_loss_layer.cpp +++ b/src/caffe/test/test_multinomial_logistic_loss_layer.cpp @@ -53,10 +53,10 @@ TYPED_TEST(MultinomialLogisticLossLayerTest, TestGradientCPU) { LayerParameter layer_param; Caffe::set_mode(Caffe::CPU); MultinomialLogisticLossLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); GradientChecker checker(1e-2, 2*1e-2, 1701, 0, 0.05); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_), 0); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); } } // namespace caffe diff --git a/src/caffe/test/test_mvn_layer.cpp b/src/caffe/test/test_mvn_layer.cpp index d3d8012f09f..933b4326417 100644 --- a/src/caffe/test/test_mvn_layer.cpp +++ b/src/caffe/test/test_mvn_layer.cpp @@ -40,8 +40,8 @@ TYPED_TEST(MVNLayerTest, TestForward) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; MVNLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Test mean int num = this->blob_bottom_->num(); int channels = this->blob_bottom_->channels(); @@ -75,8 +75,8 @@ TYPED_TEST(MVNLayerTest, TestForwardMeanOnly) { LayerParameter layer_param; layer_param.ParseFromString("mvn_param{normalize_variance: false}"); MVNLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Test mean int num = this->blob_bottom_->num(); int channels = this->blob_bottom_->channels(); @@ -107,8 +107,8 @@ TYPED_TEST(MVNLayerTest, TestForwardAcrossChannels) { LayerParameter layer_param; layer_param.ParseFromString("mvn_param{across_channels: true}"); MVNLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Test mean int num = this->blob_bottom_->num(); int channels = this->blob_bottom_->channels(); @@ -142,8 +142,8 @@ TYPED_TEST(MVNLayerTest, TestGradient) { LayerParameter layer_param; MVNLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(MVNLayerTest, TestGradientMeanOnly) { @@ -152,8 +152,8 @@ TYPED_TEST(MVNLayerTest, TestGradientMeanOnly) { layer_param.ParseFromString("mvn_param{normalize_variance: false}"); MVNLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(MVNLayerTest, TestGradientAcrossChannels) { @@ -162,8 +162,8 @@ TYPED_TEST(MVNLayerTest, TestGradientAcrossChannels) { layer_param.ParseFromString("mvn_param{across_channels: true}"); MVNLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } // namespace caffe diff --git a/src/caffe/test/test_neuron_layer.cpp b/src/caffe/test/test_neuron_layer.cpp index 4c19d3f9bae..fdbb63cb3e5 100644 --- a/src/caffe/test/test_neuron_layer.cpp +++ b/src/caffe/test/test_neuron_layer.cpp @@ -44,8 +44,8 @@ class NeuronLayerTest : public MultiDeviceTest { } Caffe::set_phase(Caffe::TRAIN); DropoutLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); @@ -74,8 +74,8 @@ TYPED_TEST(NeuronLayerTest, TestAbsVal) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; AbsValLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); const int count = this->blob_bottom_->count(); @@ -89,16 +89,16 @@ TYPED_TEST(NeuronLayerTest, TestAbsGradient) { LayerParameter layer_param; AbsValLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(NeuronLayerTest, TestReLU) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; ReLULayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); @@ -113,8 +113,8 @@ TYPED_TEST(NeuronLayerTest, TestReLUGradient) { LayerParameter layer_param; ReLULayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(NeuronLayerTest, TestReLUWithNegativeSlope) { @@ -122,8 +122,8 @@ TYPED_TEST(NeuronLayerTest, TestReLUWithNegativeSlope) { LayerParameter layer_param; layer_param.ParseFromString("relu_param{negative_slope:0.01}"); ReLULayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); @@ -139,16 +139,16 @@ TYPED_TEST(NeuronLayerTest, TestReLUGradientWithNegativeSlope) { layer_param.ParseFromString("relu_param{negative_slope:0.01}"); ReLULayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(NeuronLayerTest, TestSigmoid) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; SigmoidLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); @@ -165,16 +165,16 @@ TYPED_TEST(NeuronLayerTest, TestSigmoidGradient) { LayerParameter layer_param; SigmoidLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(NeuronLayerTest, TestTanH) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; TanHLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Test exact values for (int i = 0; i < this->blob_bottom_->num(); ++i) { for (int j = 0; j < this->blob_bottom_->channels(); ++j) { @@ -197,8 +197,8 @@ TYPED_TEST(NeuronLayerTest, TestTanHGradient) { LayerParameter layer_param; TanHLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(NeuronLayerTest, TestDropoutHalf) { @@ -216,8 +216,8 @@ TYPED_TEST(NeuronLayerTest, TestDropoutTestPhase) { LayerParameter layer_param; Caffe::set_phase(Caffe::TEST); DropoutLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); @@ -234,8 +234,8 @@ TYPED_TEST(NeuronLayerTest, TestDropoutGradient) { Caffe::set_phase(Caffe::TRAIN); DropoutLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(NeuronLayerTest, TestDropoutGradientTest) { @@ -244,16 +244,16 @@ TYPED_TEST(NeuronLayerTest, TestDropoutGradientTest) { Caffe::set_phase(Caffe::TEST); DropoutLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(NeuronLayerTest, TestBNLL) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; BNLLLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); @@ -268,8 +268,8 @@ TYPED_TEST(NeuronLayerTest, TestBNLLGradient) { LayerParameter layer_param; BNLLLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } #ifdef USE_CUDNN @@ -300,8 +300,8 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestReLUCuDNN) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; CuDNNReLULayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); const TypeParam* top_data = this->blob_top_->cpu_data(); @@ -316,8 +316,8 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestReLUGradientCuDNN) { LayerParameter layer_param; CuDNNReLULayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(CuDNNNeuronLayerTest, TestReLUWithNegativeSlopeCuDNN) { @@ -325,8 +325,8 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestReLUWithNegativeSlopeCuDNN) { LayerParameter layer_param; layer_param.ParseFromString("relu_param{negative_slope:0.01}"); CuDNNReLULayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); const TypeParam* top_data = this->blob_top_->cpu_data(); @@ -342,16 +342,16 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestReLUGradientWithNegativeSlopeCuDNN) { layer_param.ParseFromString("relu_param{negative_slope:0.01}"); CuDNNReLULayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(CuDNNNeuronLayerTest, TestSigmoidCuDNN) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; CuDNNSigmoidLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); const TypeParam* top_data = this->blob_top_->cpu_data(); @@ -368,16 +368,16 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestSigmoidGradientCuDNN) { LayerParameter layer_param; CuDNNSigmoidLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } TYPED_TEST(CuDNNNeuronLayerTest, TestTanHCuDNN) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; CuDNNTanHLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Test exact values for (int i = 0; i < this->blob_bottom_->num(); ++i) { for (int j = 0; j < this->blob_bottom_->channels(); ++j) { @@ -400,8 +400,8 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestTanHGradientCuDNN) { LayerParameter layer_param; CuDNNTanHLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } #endif diff --git a/src/caffe/test/test_pooling_layer.cpp b/src/caffe/test/test_pooling_layer.cpp index ec23a682c2f..e2980331dc0 100644 --- a/src/caffe/test/test_pooling_layer.cpp +++ b/src/caffe/test/test_pooling_layer.cpp @@ -73,7 +73,7 @@ class PoolingLayerTest : public MultiDeviceTest { blob_bottom_->mutable_cpu_data()[i + 14] = 3; } PoolingLayer layer(layer_param); - layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); EXPECT_EQ(blob_top_->num(), num); EXPECT_EQ(blob_top_->channels(), channels); EXPECT_EQ(blob_top_->height(), 2); @@ -84,7 +84,7 @@ class PoolingLayerTest : public MultiDeviceTest { EXPECT_EQ(blob_top_mask_->height(), 2); EXPECT_EQ(blob_top_mask_->width(), 4); } - layer.Forward(blob_bottom_vec_, &blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); // Expected output: 2x 2 channels of: // [9 5 5 8] // [9 5 5 8] @@ -171,7 +171,7 @@ class PoolingLayerTest : public MultiDeviceTest { blob_bottom_->mutable_cpu_data()[i + 35] = 11; } PoolingLayer layer(layer_param); - layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); EXPECT_EQ(blob_top_->num(), num); EXPECT_EQ(blob_top_->channels(), channels); EXPECT_EQ(blob_top_->height(), 4); @@ -182,7 +182,7 @@ class PoolingLayerTest : public MultiDeviceTest { EXPECT_EQ(blob_top_mask_->height(), 4); EXPECT_EQ(blob_top_mask_->width(), 5); } - layer.Forward(blob_bottom_vec_, &blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); // Expected output: 2x 2 channels of: // [35 32 26 27 27] // [32 33 33 27 27] @@ -296,7 +296,7 @@ class PoolingLayerTest : public MultiDeviceTest { blob_bottom_->mutable_cpu_data()[i + 35] = 11; } PoolingLayer layer(layer_param); - layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); EXPECT_EQ(blob_top_->num(), num); EXPECT_EQ(blob_top_->channels(), channels); EXPECT_EQ(blob_top_->height(), 5); @@ -307,7 +307,7 @@ class PoolingLayerTest : public MultiDeviceTest { EXPECT_EQ(blob_top_mask_->height(), 5); EXPECT_EQ(blob_top_mask_->width(), 4); } - layer.Forward(blob_bottom_vec_, &blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); // Expected output: 2x 2 channels of: // [35 32 26 26] // [32 32 27 27] @@ -377,7 +377,7 @@ TYPED_TEST(PoolingLayerTest, TestSetup) { pooling_param->set_kernel_size(3); pooling_param->set_stride(2); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); EXPECT_EQ(this->blob_top_->height(), 3); @@ -393,7 +393,7 @@ TYPED_TEST(PoolingLayerTest, TestSetupPadded) { pooling_param->set_pad(1); pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); EXPECT_EQ(this->blob_top_->height(), 4); @@ -407,8 +407,8 @@ TYPED_TEST(PoolingLayerTest, PrintBackward) { layer_param.set_stride(2); layer_param.set_pool(LayerParameter_PoolMethod_MAX); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_bottom_->count(); ++i) { cout << "bottom data " << i << " " << this->blob_bottom_->cpu_data()[i] << endl; } @@ -419,7 +419,7 @@ TYPED_TEST(PoolingLayerTest, PrintBackward) { for (int i = 0; i < this->blob_top_->count(); ++i) { this->blob_top_->mutable_cpu_diff()[i] = i; } - layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + layer.Backward(this->blob_top_vec_, true, this->blob_bottom_vec_); for (int i = 0; i < this->blob_bottom_->count(); ++i) { cout << "bottom diff " << i << " " << this->blob_bottom_->cpu_diff()[i] << endl; } @@ -452,8 +452,8 @@ TYPED_TEST(PoolingLayerTest, TestGradientMax) { pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); PoolingLayer layer(layer_param); GradientChecker checker(1e-4, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } } @@ -481,12 +481,12 @@ TYPED_TEST(PoolingLayerTest, TestForwardMaxPadded) { this->blob_bottom_->mutable_cpu_data()[7] = 2; this->blob_bottom_->mutable_cpu_data()[8] = 1; PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 1); EXPECT_EQ(this->blob_top_->channels(), 1); EXPECT_EQ(this->blob_top_->height(), 3); EXPECT_EQ(this->blob_top_->width(), 3); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); Dtype epsilon = 1e-8; // Output: // [ 1 4 4 ] @@ -516,8 +516,8 @@ TYPED_TEST(PoolingLayerTest, TestGradientMaxTopMask) { this->blob_top_vec_.push_back(this->blob_top_mask_); PoolingLayer layer(layer_param); GradientChecker checker(1e-4, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); this->blob_top_vec_.pop_back(); } } @@ -537,12 +537,12 @@ TYPED_TEST(PoolingLayerTest, TestForwardAve) { ConstantFiller filler(filler_param); filler.Fill(this->blob_bottom_); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 1); EXPECT_EQ(this->blob_top_->channels(), 1); EXPECT_EQ(this->blob_top_->height(), 3); EXPECT_EQ(this->blob_top_->width(), 3); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); Dtype epsilon = 1e-5; EXPECT_NEAR(this->blob_top_->cpu_data()[0], 8.0 / 9, epsilon); EXPECT_NEAR(this->blob_top_->cpu_data()[1], 4.0 / 3, epsilon); @@ -567,8 +567,8 @@ TYPED_TEST(PoolingLayerTest, TestGradientAve) { pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); PoolingLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } } @@ -586,8 +586,8 @@ TYPED_TEST(PoolingLayerTest, TestGradientAvePadded) { pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); PoolingLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } } @@ -651,7 +651,7 @@ class CuDNNPoolingLayerTest : public ::testing::Test { blob_bottom_->mutable_cpu_data()[i + 14] = 3; } CuDNNPoolingLayer layer(layer_param); - layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); EXPECT_EQ(blob_top_->num(), num); EXPECT_EQ(blob_top_->channels(), channels); EXPECT_EQ(blob_top_->height(), 2); @@ -662,7 +662,7 @@ class CuDNNPoolingLayerTest : public ::testing::Test { EXPECT_EQ(blob_top_mask_->height(), 2); EXPECT_EQ(blob_top_mask_->width(), 4); } - layer.Forward(blob_bottom_vec_, &blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); // Expected output: 2x 2 channels of: // [9 5 5 8] // [9 5 5 8] @@ -749,7 +749,7 @@ class CuDNNPoolingLayerTest : public ::testing::Test { blob_bottom_->mutable_cpu_data()[i + 35] = 11; } CuDNNPoolingLayer layer(layer_param); - layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); EXPECT_EQ(blob_top_->num(), num); EXPECT_EQ(blob_top_->channels(), channels); EXPECT_EQ(blob_top_->height(), 4); @@ -760,7 +760,7 @@ class CuDNNPoolingLayerTest : public ::testing::Test { EXPECT_EQ(blob_top_mask_->height(), 4); EXPECT_EQ(blob_top_mask_->width(), 5); } - layer.Forward(blob_bottom_vec_, &blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); // Expected output: 2x 2 channels of: // [35 32 26 27 27] // [32 33 33 27 27] @@ -874,7 +874,7 @@ class CuDNNPoolingLayerTest : public ::testing::Test { blob_bottom_->mutable_cpu_data()[i + 35] = 11; } CuDNNPoolingLayer layer(layer_param); - layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); EXPECT_EQ(blob_top_->num(), num); EXPECT_EQ(blob_top_->channels(), channels); EXPECT_EQ(blob_top_->height(), 5); @@ -885,7 +885,7 @@ class CuDNNPoolingLayerTest : public ::testing::Test { EXPECT_EQ(blob_top_mask_->height(), 5); EXPECT_EQ(blob_top_mask_->width(), 4); } - layer.Forward(blob_bottom_vec_, &blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); // Expected output: 2x 2 channels of: // [35 32 26 26] // [32 32 27 27] @@ -955,7 +955,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestSetupCuDNN) { pooling_param->set_kernel_size(3); pooling_param->set_stride(2); CuDNNPoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); EXPECT_EQ(this->blob_top_->height(), 3); @@ -971,7 +971,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestSetupPaddedCuDNN) { pooling_param->set_pad(1); pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); CuDNNPoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); EXPECT_EQ(this->blob_top_->height(), 4); @@ -986,8 +986,8 @@ TYPED_TEST(CuDNNPoolingLayerTest, PrintBackwardCuDNN) { layer_param.set_stride(2); layer_param.set_pool(LayerParameter_PoolMethod_MAX); CuDNNPoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_bottom_->count(); ++i) { cout << "bottom data " << i << " " << this->blob_bottom_->cpu_data()[i] << endl; } @@ -998,7 +998,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, PrintBackwardCuDNN) { for (int i = 0; i < this->blob_top_->count(); ++i) { this->blob_top_->mutable_cpu_diff()[i] = i; } - layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + layer.Backward(this->blob_top_vec_, true, this->blob_bottom_vec_); for (int i = 0; i < this->blob_bottom_->count(); ++i) { cout << "bottom diff " << i << " " << this->blob_bottom_->cpu_diff()[i] << endl; } @@ -1033,8 +1033,8 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientMaxCuDNN) { pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); CuDNNPoolingLayer layer(layer_param); GradientChecker checker(1e-4, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } } @@ -1062,12 +1062,12 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestForwardMaxPaddedCuDNN) { this->blob_bottom_->mutable_cpu_data()[7] = 2; this->blob_bottom_->mutable_cpu_data()[8] = 1; CuDNNPoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 1); EXPECT_EQ(this->blob_top_->channels(), 1); EXPECT_EQ(this->blob_top_->height(), 3); EXPECT_EQ(this->blob_top_->width(), 3); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); TypeParam epsilon = 1e-8; // Output: // [ 1 4 4 ] @@ -1097,8 +1097,8 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientMaxTopMaskCuDNN) { this->blob_top_vec_.push_back(this->blob_top_mask_); CuDNNPoolingLayer layer(layer_param); GradientChecker checker(1e-4, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); this->blob_top_vec_.pop_back(); } } @@ -1118,12 +1118,12 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestForwardAveCuDNN) { ConstantFiller filler(filler_param); filler.Fill(this->blob_bottom_); CuDNNPoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 1); EXPECT_EQ(this->blob_top_->channels(), 1); EXPECT_EQ(this->blob_top_->height(), 3); EXPECT_EQ(this->blob_top_->width(), 3); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); TypeParam epsilon = 1e-5; EXPECT_NEAR(this->blob_top_->cpu_data()[0], 8.0 / 9, epsilon); EXPECT_NEAR(this->blob_top_->cpu_data()[1], 4.0 / 3, epsilon); @@ -1148,8 +1148,8 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientAveCuDNN) { pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); CuDNNPoolingLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } } @@ -1167,8 +1167,8 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientAvePaddedCuDNN) { pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); CuDNNPoolingLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } } } diff --git a/src/caffe/test/test_power_layer.cpp b/src/caffe/test/test_power_layer.cpp index 0c104c20b7c..0d52fa1c8e2 100644 --- a/src/caffe/test/test_power_layer.cpp +++ b/src/caffe/test/test_power_layer.cpp @@ -37,8 +37,8 @@ class PowerLayerTest : public MultiDeviceTest { layer_param.mutable_power_param()->set_scale(scale); layer_param.mutable_power_param()->set_shift(shift); PowerLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); @@ -75,8 +75,8 @@ class PowerLayerTest : public MultiDeviceTest { } } GradientChecker checker(1e-2, 1e-2, 1701, 0., 0.01); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } Blob* const blob_bottom_; diff --git a/src/caffe/test/test_sigmoid_cross_entropy_loss_layer.cpp b/src/caffe/test/test_sigmoid_cross_entropy_loss_layer.cpp index 47ccdea1538..e5737e43f6e 100644 --- a/src/caffe/test/test_sigmoid_cross_entropy_loss_layer.cpp +++ b/src/caffe/test/test_sigmoid_cross_entropy_loss_layer.cpp @@ -79,9 +79,9 @@ class SigmoidCrossEntropyLossLayerTest : public MultiDeviceTest { // Fill the targets vector targets_filler.Fill(this->blob_bottom_targets_); SigmoidCrossEntropyLossLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); Dtype layer_loss = - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); const int count = this->blob_bottom_data_->count(); const int num = this->blob_bottom_data_->num(); const Dtype* blob_bottom_data = this->blob_bottom_data_->cpu_data(); @@ -112,10 +112,10 @@ TYPED_TEST(SigmoidCrossEntropyLossLayerTest, TestGradient) { const Dtype kLossWeight = 3.7; layer_param.add_loss_weight(kLossWeight); SigmoidCrossEntropyLossLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); GradientChecker checker(1e-2, 1e-2, 1701); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_), 0); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); } diff --git a/src/caffe/test/test_slice_layer.cpp b/src/caffe/test/test_slice_layer.cpp index ee8818781f5..395be280089 100644 --- a/src/caffe/test/test_slice_layer.cpp +++ b/src/caffe/test/test_slice_layer.cpp @@ -64,7 +64,7 @@ TYPED_TEST(SliceLayerTest, TestSetupNum) { LayerParameter layer_param; layer_param.mutable_slice_param()->set_slice_dim(0); SliceLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_1_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_1_); EXPECT_EQ(this->blob_bottom_->num(), 3 * this->blob_top_0_->num()); EXPECT_EQ(this->blob_top_0_->num(), this->blob_top_1_->num()); EXPECT_EQ(this->blob_top_0_->num(), this->blob_top_2_->num()); @@ -78,7 +78,7 @@ TYPED_TEST(SliceLayerTest, TestSetupChannels) { LayerParameter layer_param; layer_param.mutable_slice_param()->add_slice_point(3); SliceLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_0_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_0_); EXPECT_EQ(this->blob_top_0_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_0_->channels(), 3); EXPECT_EQ(this->blob_top_1_->channels(), 9); @@ -93,11 +93,11 @@ TYPED_TEST(SliceLayerTest, TestSliceAcrossNum) { LayerParameter layer_param; layer_param.mutable_slice_param()->set_slice_dim(0); SliceLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_0_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_0_); const int top_num = this->blob_bottom_->num() / 2; ASSERT_EQ(top_num, this->blob_top_0_->num()); ASSERT_EQ(top_num, this->blob_top_1_->num()); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_0_)); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_0_); for (int n = 0; n < top_num; ++n) { for (int c = 0; c < this->blob_top_0_->channels(); ++c) { for (int h = 0; h < this->blob_bottom_->height(); ++h) { @@ -127,12 +127,12 @@ TYPED_TEST(SliceLayerTest, TestSliceAcrossChannels) { layer_param.mutable_slice_param()->add_slice_point(kSlicePoint0); layer_param.mutable_slice_param()->add_slice_point(kSlicePoint1); SliceLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_1_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_1_); ASSERT_EQ(kSlicePoint0, this->blob_top_0_->channels()); ASSERT_EQ(kSlicePoint1 - kSlicePoint0, this->blob_top_1_->channels()); ASSERT_EQ(this->blob_bottom_->channels() - kSlicePoint1, this->blob_top_2_->channels()); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_1_)); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_1_); for (int n = 0; n < this->blob_bottom_->num(); ++n) { for (int c = 0; c < this->blob_top_0_->channels(); ++c) { for (int h = 0; h < this->blob_bottom_->height(); ++h) { @@ -169,8 +169,8 @@ TYPED_TEST(SliceLayerTest, TestGradientAcrossNum) { layer_param.mutable_slice_param()->set_slice_dim(0); SliceLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_0_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_0_); } TYPED_TEST(SliceLayerTest, TestGradientAcrossChannels) { @@ -182,8 +182,8 @@ TYPED_TEST(SliceLayerTest, TestGradientAcrossChannels) { layer_param.mutable_slice_param()->add_slice_point(kSlicePoint); SliceLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_0_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_0_); } } // namespace caffe diff --git a/src/caffe/test/test_softmax_layer.cpp b/src/caffe/test/test_softmax_layer.cpp index 41f643f4e2a..f6674422e56 100644 --- a/src/caffe/test/test_softmax_layer.cpp +++ b/src/caffe/test/test_softmax_layer.cpp @@ -41,8 +41,8 @@ TYPED_TEST(SoftmaxLayerTest, TestForward) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; SoftmaxLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Test sum for (int i = 0; i < this->blob_bottom_->num(); ++i) { for (int k = 0; k < this->blob_bottom_->height(); ++k) { @@ -76,8 +76,8 @@ TYPED_TEST(SoftmaxLayerTest, TestGradient) { LayerParameter layer_param; SoftmaxLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } #ifdef USE_CUDNN @@ -107,8 +107,8 @@ TYPED_TEST(CuDNNSoftmaxLayerTest, TestForwardCuDNN) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; CuDNNSoftmaxLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Test sum for (int i = 0; i < this->blob_bottom_->num(); ++i) { for (int k = 0; k < this->blob_bottom_->height(); ++k) { @@ -142,8 +142,8 @@ TYPED_TEST(CuDNNSoftmaxLayerTest, TestGradientCuDNN) { LayerParameter layer_param; CuDNNSoftmaxLayer layer(layer_param); GradientChecker checker(1e-2, 1e-3); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } #endif diff --git a/src/caffe/test/test_softmax_with_loss_layer.cpp b/src/caffe/test/test_softmax_with_loss_layer.cpp index 246d64e116a..badda3b5503 100644 --- a/src/caffe/test/test_softmax_with_loss_layer.cpp +++ b/src/caffe/test/test_softmax_with_loss_layer.cpp @@ -57,8 +57,8 @@ TYPED_TEST(SoftmaxWithLossLayerTest, TestGradient) { layer_param.add_loss_weight(3); SoftmaxWithLossLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2, 1701); - checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_), 0); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); } } // namespace caffe diff --git a/src/caffe/test/test_split_layer.cpp b/src/caffe/test/test_split_layer.cpp index e9b942c5c51..38e762195a2 100644 --- a/src/caffe/test/test_split_layer.cpp +++ b/src/caffe/test/test_split_layer.cpp @@ -52,7 +52,7 @@ TYPED_TEST(SplitLayerTest, TestSetup) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; SplitLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_a_->num(), 2); EXPECT_EQ(this->blob_top_a_->channels(), 3); EXPECT_EQ(this->blob_top_a_->height(), 6); @@ -67,8 +67,8 @@ TYPED_TEST(SplitLayerTest, Test) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; SplitLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); for (int i = 0; i < this->blob_bottom_->count(); ++i) { Dtype bottom_value = this->blob_bottom_->cpu_data()[i]; EXPECT_EQ(bottom_value, this->blob_top_a_->cpu_data()[i]); @@ -81,8 +81,8 @@ TYPED_TEST(SplitLayerTest, TestGradient) { LayerParameter layer_param; SplitLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); - checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } diff --git a/src/caffe/test/test_stochastic_pooling.cpp b/src/caffe/test/test_stochastic_pooling.cpp index 4f13981bd82..ad5151007c2 100644 --- a/src/caffe/test/test_stochastic_pooling.cpp +++ b/src/caffe/test/test_stochastic_pooling.cpp @@ -53,7 +53,7 @@ TYPED_TEST(StochasticPoolingLayerTest, TestSetup) { pooling_param->set_kernel_size(3); pooling_param->set_stride(2); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); EXPECT_EQ(this->blob_top_->height(), 3); @@ -69,8 +69,8 @@ TYPED_TEST(StochasticPoolingLayerTest, TestStochasticGPU) { pooling_param->set_stride(2); pooling_param->set_pool(PoolingParameter_PoolMethod_STOCHASTIC); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Check if the output is correct - it should do random sampling const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); @@ -113,8 +113,8 @@ TYPED_TEST(StochasticPoolingLayerTest, TestStochasticGPUTestPhase) { pooling_param->set_stride(2); pooling_param->set_pool(PoolingParameter_PoolMethod_STOCHASTIC); PoolingLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Check if the output is correct - it should do random sampling const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); @@ -154,8 +154,8 @@ TYPED_TEST(StochasticPoolingLayerTest, TestGradientGPU) { GradientChecker checker(1e-4, 1e-2); // it is too expensive to call curand multiple times, so we don't do an // exhaustive gradient check. - checker.CheckGradient(&layer, &(this->blob_bottom_vec_), - &(this->blob_top_vec_)); + checker.CheckGradient(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); } diff --git a/src/caffe/test/test_threshold_layer.cpp b/src/caffe/test/test_threshold_layer.cpp index 32dfbeeac92..05ce82120e6 100644 --- a/src/caffe/test/test_threshold_layer.cpp +++ b/src/caffe/test/test_threshold_layer.cpp @@ -40,7 +40,7 @@ TYPED_TEST(ThresholdLayerTest, TestSetup) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; ThresholdLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); EXPECT_EQ(this->blob_top_->height(), this->blob_bottom_->height()); @@ -51,8 +51,8 @@ TYPED_TEST(ThresholdLayerTest, Test) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; ThresholdLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); @@ -76,8 +76,8 @@ TYPED_TEST(ThresholdLayerTest, Test2) { layer_param.mutable_threshold_param(); threshold_param->set_threshold(0.5); ThresholdLayer layer(layer_param); - layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); - layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); // Now, check values const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); diff --git a/tools/caffe.cpp b/tools/caffe.cpp index c8c8c1a6b4c..bfcd9f19cec 100644 --- a/tools/caffe.cpp +++ b/tools/caffe.cpp @@ -237,8 +237,8 @@ int time() { for (int j = 0; j < FLAGS_iterations; ++j) { // Although Reshape should be essentially free, we include it here // so that we will notice Reshape performance bugs. - layers[i]->Reshape(bottom_vecs[i], &top_vecs[i]); - layers[i]->Forward(bottom_vecs[i], &top_vecs[i]); + layers[i]->Reshape(bottom_vecs[i], top_vecs[i]); + layers[i]->Forward(bottom_vecs[i], top_vecs[i]); } LOG(INFO) << layername << "\tforward: " << timer.MilliSeconds() << " milliseconds."; @@ -252,7 +252,7 @@ int time() { timer.Start(); for (int j = 0; j < FLAGS_iterations; ++j) { layers[i]->Backward(top_vecs[i], bottom_need_backward[i], - &bottom_vecs[i]); + bottom_vecs[i]); } LOG(INFO) << layername << "\tbackward: " << timer.MilliSeconds() << " milliseconds."; From 2f45b2109b1fb6080abe035d1a8e0684cda13bb5 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 19 Sep 2014 21:32:16 -0700 Subject: [PATCH 006/798] drop out-of-date conv test comments --- src/caffe/test/test_convolution_layer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/caffe/test/test_convolution_layer.cpp b/src/caffe/test/test_convolution_layer.cpp index aef9092d8fe..c2e0a86271a 100644 --- a/src/caffe/test/test_convolution_layer.cpp +++ b/src/caffe/test/test_convolution_layer.cpp @@ -182,7 +182,6 @@ TYPED_TEST(ConvolutionLayerTest, TestSetup) { } TYPED_TEST(ConvolutionLayerTest, TestSimpleConvolution) { - // We will simply see if the convolution layer carries out averaging well. typedef typename TypeParam::Dtype Dtype; this->blob_bottom_vec_.push_back(this->blob_bottom_2_); this->blob_top_vec_.push_back(this->blob_top_2_); @@ -219,7 +218,6 @@ TYPED_TEST(ConvolutionLayerTest, TestSimpleConvolution) { } TYPED_TEST(ConvolutionLayerTest, TestSimpleConvolutionGroup) { - // We will simply see if the convolution layer carries out averaging well. typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; ConvolutionParameter* convolution_param = @@ -462,7 +460,6 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSetupCuDNN) { } TYPED_TEST(CuDNNConvolutionLayerTest, TestSimpleConvolutionCuDNN) { - // We will simply see if the convolution layer carries out averaging well. Caffe::set_mode(Caffe::GPU); this->blob_bottom_vec_.push_back(this->blob_bottom_2_); this->blob_top_vec_.push_back(this->blob_top_2_); @@ -499,7 +496,6 @@ TYPED_TEST(CuDNNConvolutionLayerTest, TestSimpleConvolutionCuDNN) { } TYPED_TEST(CuDNNConvolutionLayerTest, TestSimpleConvolutionGroupCuDNN) { - // We will simply see if the convolution layer carries out averaging well. Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; ConvolutionParameter* convolution_param = From 8109a6e56ed18e1f40b48e494a30e290019eefb4 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 19 Sep 2014 18:59:38 -0700 Subject: [PATCH 007/798] optimize 1x1 convolution for Network-in-Network style layers 1x1 convolution with stride 1 is a special case of Caffe matrix multiplication convolution for which im2col / col2im transformations are actually the identity. For this special case the memory and transformation are skipped. --- include/caffe/vision_layers.hpp | 1 + src/caffe/layers/conv_layer.cpp | 46 +++++++++++++++++------ src/caffe/layers/conv_layer.cu | 42 +++++++++++++++------ src/caffe/test/test_convolution_layer.cpp | 45 ++++++++++++++++++++++ 4 files changed, 110 insertions(+), 24 deletions(-) diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 0f1b2d9e529..fa516144d25 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -97,6 +97,7 @@ class ConvolutionLayer : public Layer { int num_output_; int height_out_, width_out_; bool bias_term_; + bool is_1x1_; /// M_ is the channel dimension of the output for a single group, which is the /// leading dimension of the filter matrix. diff --git a/src/caffe/layers/conv_layer.cpp b/src/caffe/layers/conv_layer.cpp index 8c08c100bd5..d33aa05e961 100644 --- a/src/caffe/layers/conv_layer.cpp +++ b/src/caffe/layers/conv_layer.cpp @@ -47,6 +47,10 @@ void ConvolutionLayer::LayerSetUp(const vector*>& bottom, stride_h_ = conv_param.stride_h(); stride_w_ = conv_param.stride_w(); } + // Special case: im2col is the identity for 1x1 convolution with stride 1 + // and no padding, so flag for skipping the buffer and transformation. + is_1x1_ = kernel_w_ == 1 && kernel_h_ == 1 + && stride_h_ == 1 && stride_w_ == 1 && pad_h_ == 0 && pad_w_ == 0; // Configure output channels and groups. channels_ = bottom[0]->channels(); num_output_ = this->layer_param_.convolution_param().num_output(); @@ -137,7 +141,10 @@ void ConvolutionLayer::Forward_cpu(const vector*>& bottom, for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->cpu_data(); Dtype* top_data = top[i]->mutable_cpu_data(); - Dtype* col_data = col_buffer_.mutable_cpu_data(); + Dtype* col_data = NULL; + if (!is_1x1_) { + col_data = col_buffer_.mutable_cpu_data(); + } const Dtype* weight = this->blobs_[0]->cpu_data(); int weight_offset = M_ * K_; // number of filter parameters in a group int col_offset = K_ * N_; // number of values in an input region / column @@ -145,9 +152,13 @@ void ConvolutionLayer::Forward_cpu(const vector*>& bottom, for (int n = 0; n < num_; ++n) { // im2col transformation: unroll input regions for filtering // into column matrix for multplication. - im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, - width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - col_data); + if (!is_1x1_) { + im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, + width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, + col_data); + } else { // special case for 1x1 convolution + col_data = bottom[i]->mutable_cpu_data() + bottom[i]->offset(n); + } // Take inner products for groups. for (int g = 0; g < group_; ++g) { caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, @@ -199,16 +210,25 @@ void ConvolutionLayer::Backward_cpu(const vector*>& top, if (!top_diff) { top_diff = top[i]->cpu_diff(); } - Dtype* col_data = col_buffer_.mutable_cpu_data(); - Dtype* col_diff = col_buffer_.mutable_cpu_diff(); + Dtype* col_data = NULL; + Dtype* col_diff = NULL; + if (!is_1x1_) { + col_data = col_buffer_.mutable_cpu_data(); + col_diff = col_buffer_.mutable_cpu_diff(); + } const Dtype* bottom_data = bottom[i]->cpu_data(); Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); for (int n = 0; n < num_; ++n) { // Since we saved memory in the forward pass by not storing all col // data, we will need to recompute them. - im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, - width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, col_data); + if (!is_1x1_) { + im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, + width_, kernel_h_, kernel_w_, pad_h_, pad_w_, + stride_h_, stride_w_, col_data); + } else { + col_data = bottom[i]->mutable_cpu_data() + bottom[i]->offset(n); + col_diff = bottom[i]->mutable_cpu_diff() + bottom[i]->offset(n); + } // gradient w.r.t. weight. Note that we will accumulate diffs. if (this->param_propagate_down_[0]) { for (int g = 0; g < group_; ++g) { @@ -230,9 +250,11 @@ void ConvolutionLayer::Backward_cpu(const vector*>& top, (Dtype)0., col_diff + col_offset * g); } // col2im back to the data - col2im_cpu(col_diff, channels_, height_, width_, - kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, bottom_diff + bottom[i]->offset(n)); + if (!is_1x1_) { + col2im_cpu(col_diff, channels_, height_, width_, + kernel_h_, kernel_w_, pad_h_, pad_w_, + stride_h_, stride_w_, bottom_diff + bottom[i]->offset(n)); + } } } } diff --git a/src/caffe/layers/conv_layer.cu b/src/caffe/layers/conv_layer.cu index 908f5a65855..885d90a47d3 100644 --- a/src/caffe/layers/conv_layer.cu +++ b/src/caffe/layers/conv_layer.cu @@ -15,7 +15,10 @@ void ConvolutionLayer::Forward_gpu(const vector*>& bottom, for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->gpu_data(); Dtype* top_data = top[i]->mutable_gpu_data(); - Dtype* col_data = col_buffer_.mutable_gpu_data(); + Dtype* col_data = NULL; + if (!is_1x1_) { + col_data = col_buffer_.mutable_gpu_data(); + } const Dtype* weight = this->blobs_[0]->gpu_data(); int weight_offset = M_ * K_; int col_offset = K_ * N_; @@ -23,9 +26,13 @@ void ConvolutionLayer::Forward_gpu(const vector*>& bottom, for (int n = 0; n < num_; ++n) { // im2col transformation: unroll input regions for filtering // into column matrix for multplication. - im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, - width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - col_data); + if (!is_1x1_) { + im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, + width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, + col_data); + } else { + col_data = bottom[i]->mutable_gpu_data() + bottom[i]->offset(n); + } // Take inner products for groups. for (int g = 0; g < group_; ++g) { caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, @@ -78,16 +85,25 @@ void ConvolutionLayer::Backward_gpu(const vector*>& top, if (!top_diff) { top_diff = top[i]->gpu_diff(); } - Dtype* col_data = col_buffer_.mutable_gpu_data(); - Dtype* col_diff = col_buffer_.mutable_gpu_diff(); + Dtype* col_data = NULL; + Dtype* col_diff = NULL; + if (!is_1x1_) { + col_data = col_buffer_.mutable_gpu_data(); + col_diff = col_buffer_.mutable_gpu_diff(); + } const Dtype* bottom_data = bottom[i]->gpu_data(); Dtype* bottom_diff = bottom[i]->mutable_gpu_diff(); for (int n = 0; n < num_; ++n) { // Since we saved memory in the forward pass by not storing all col // data, we will need to recompute them. - im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, - width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, col_data); + if (!is_1x1_) { + im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, + width_, kernel_h_, kernel_w_, pad_h_, pad_w_, + stride_h_, stride_w_, col_data); + } else { + col_data = bottom[i]->mutable_gpu_data() + bottom[i]->offset(n); + col_diff = bottom[i]->mutable_gpu_diff() + bottom[i]->offset(n); + } // gradient w.r.t. weight. Note that we will accumulate diffs. if (this->param_propagate_down_[0]) { for (int g = 0; g < group_; ++g) { @@ -109,9 +125,11 @@ void ConvolutionLayer::Backward_gpu(const vector*>& top, (Dtype)0., col_diff + col_offset * g); } // col2im back to the data - col2im_gpu(col_diff, channels_, height_, width_, - kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - bottom_diff + bottom[i]->offset(n)); + if (!is_1x1_) { + col2im_gpu(col_diff, channels_, height_, width_, + kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, + bottom_diff + bottom[i]->offset(n)); + } } } } diff --git a/src/caffe/test/test_convolution_layer.cpp b/src/caffe/test/test_convolution_layer.cpp index c2e0a86271a..c1fe3b58c58 100644 --- a/src/caffe/test/test_convolution_layer.cpp +++ b/src/caffe/test/test_convolution_layer.cpp @@ -217,6 +217,33 @@ TYPED_TEST(ConvolutionLayerTest, TestSimpleConvolution) { } } +TYPED_TEST(ConvolutionLayerTest, Test1x1Convolution) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(1); + convolution_param->set_stride(1); + convolution_param->set_num_output(4); + convolution_param->mutable_weight_filler()->set_type("gaussian"); + convolution_param->mutable_bias_filler()->set_type("constant"); + convolution_param->mutable_bias_filler()->set_value(0.1); + shared_ptr > layer( + new ConvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); + // Check against reference convolution. + const Dtype* top_data; + const Dtype* ref_top_data; + caffe_conv(this->blob_bottom_, convolution_param, layer->blobs(), + this->MakeReferenceTop(this->blob_top_)); + top_data = this->blob_top_->cpu_data(); + ref_top_data = this->ref_blob_top_->cpu_data(); + for (int i = 0; i < this->blob_top_->count(); ++i) { + EXPECT_NEAR(top_data[i], ref_top_data[i], 1e-4); + } +} + TYPED_TEST(ConvolutionLayerTest, TestSimpleConvolutionGroup) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; @@ -359,6 +386,24 @@ TYPED_TEST(ConvolutionLayerTest, TestGradient) { this->blob_top_vec_); } +TYPED_TEST(ConvolutionLayerTest, Test1x1Gradient) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + this->blob_bottom_vec_.push_back(this->blob_bottom_2_); + this->blob_top_vec_.push_back(this->blob_top_2_); + convolution_param->set_kernel_size(1); + convolution_param->set_stride(1); + convolution_param->set_num_output(2); + convolution_param->mutable_weight_filler()->set_type("gaussian"); + convolution_param->mutable_bias_filler()->set_type("gaussian"); + ConvolutionLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); +} + TYPED_TEST(ConvolutionLayerTest, TestGradientGroup) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; From e8ba4c83902196c44f1390f77cbe9c5fc74b711d Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 19 Sep 2014 23:12:12 -0700 Subject: [PATCH 008/798] combine col_{data,diff} into single col_buff to halve memory usage conv forward / backward only need one of the im2col data and diff at-a-time so consolidating the two saves a lazy allocation. --- src/caffe/layers/conv_layer.cpp | 33 +++++++++++++++++---------------- src/caffe/layers/conv_layer.cu | 30 +++++++++++++++--------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/caffe/layers/conv_layer.cpp b/src/caffe/layers/conv_layer.cpp index d33aa05e961..e6d6588096b 100644 --- a/src/caffe/layers/conv_layer.cpp +++ b/src/caffe/layers/conv_layer.cpp @@ -122,7 +122,8 @@ void ConvolutionLayer::Reshape(const vector*>& bottom, K_ = channels_ * kernel_h_ * kernel_w_ / group_; N_ = height_out_ * width_out_; // The im2col result buffer will only hold one image at a time to avoid - // overly large memory usage. + // overly large memory usage. In the special case of 1x1 convolution + // it goes lazily unused to save memory. col_buffer_.Reshape( 1, channels_ * kernel_h_ * kernel_w_, height_out_, width_out_); for (int top_id = 0; top_id < top.size(); ++top_id) { @@ -141,9 +142,9 @@ void ConvolutionLayer::Forward_cpu(const vector*>& bottom, for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->cpu_data(); Dtype* top_data = top[i]->mutable_cpu_data(); - Dtype* col_data = NULL; + Dtype* col_buff = NULL; if (!is_1x1_) { - col_data = col_buffer_.mutable_cpu_data(); + col_buff = col_buffer_.mutable_cpu_data(); } const Dtype* weight = this->blobs_[0]->cpu_data(); int weight_offset = M_ * K_; // number of filter parameters in a group @@ -155,14 +156,14 @@ void ConvolutionLayer::Forward_cpu(const vector*>& bottom, if (!is_1x1_) { im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - col_data); + col_buff); } else { // special case for 1x1 convolution - col_data = bottom[i]->mutable_cpu_data() + bottom[i]->offset(n); + col_buff = bottom[i]->mutable_cpu_data() + bottom[i]->offset(n); } // Take inner products for groups. for (int g = 0; g < group_; ++g) { caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, - (Dtype)1., weight + weight_offset * g, col_data + col_offset * g, + (Dtype)1., weight + weight_offset * g, col_buff + col_offset * g, (Dtype)0., top_data + top[i]->offset(n) + top_offset * g); } // Add bias. @@ -210,11 +211,9 @@ void ConvolutionLayer::Backward_cpu(const vector*>& top, if (!top_diff) { top_diff = top[i]->cpu_diff(); } - Dtype* col_data = NULL; - Dtype* col_diff = NULL; + Dtype* col_buff = NULL; if (!is_1x1_) { - col_data = col_buffer_.mutable_cpu_data(); - col_diff = col_buffer_.mutable_cpu_diff(); + col_buff = col_buffer_.mutable_cpu_data(); } const Dtype* bottom_data = bottom[i]->cpu_data(); Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); @@ -224,17 +223,16 @@ void ConvolutionLayer::Backward_cpu(const vector*>& top, if (!is_1x1_) { im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, col_data); + stride_h_, stride_w_, col_buff); } else { - col_data = bottom[i]->mutable_cpu_data() + bottom[i]->offset(n); - col_diff = bottom[i]->mutable_cpu_diff() + bottom[i]->offset(n); + col_buff = bottom[i]->mutable_cpu_data() + bottom[i]->offset(n); } // gradient w.r.t. weight. Note that we will accumulate diffs. if (this->param_propagate_down_[0]) { for (int g = 0; g < group_; ++g) { caffe_cpu_gemm(CblasNoTrans, CblasTrans, M_, K_, N_, (Dtype)1., top_diff + top[i]->offset(n) + top_offset * g, - col_data + col_offset * g, (Dtype)1., + col_buff + col_offset * g, (Dtype)1., weight_diff + weight_offset * g); } } @@ -243,15 +241,18 @@ void ConvolutionLayer::Backward_cpu(const vector*>& top, if (weight == NULL) { weight = this->blobs_[0]->cpu_data(); } + if (is_1x1_) { + col_buff = bottom[i]->mutable_cpu_diff() + bottom[i]->offset(n); + } for (int g = 0; g < group_; ++g) { caffe_cpu_gemm(CblasTrans, CblasNoTrans, K_, N_, M_, (Dtype)1., weight + weight_offset * g, top_diff + top[i]->offset(n) + top_offset * g, - (Dtype)0., col_diff + col_offset * g); + (Dtype)0., col_buff + col_offset * g); } // col2im back to the data if (!is_1x1_) { - col2im_cpu(col_diff, channels_, height_, width_, + col2im_cpu(col_buff, channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, bottom_diff + bottom[i]->offset(n)); } diff --git a/src/caffe/layers/conv_layer.cu b/src/caffe/layers/conv_layer.cu index 885d90a47d3..27d6500d6ef 100644 --- a/src/caffe/layers/conv_layer.cu +++ b/src/caffe/layers/conv_layer.cu @@ -15,9 +15,9 @@ void ConvolutionLayer::Forward_gpu(const vector*>& bottom, for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->gpu_data(); Dtype* top_data = top[i]->mutable_gpu_data(); - Dtype* col_data = NULL; + Dtype* col_buff = NULL; if (!is_1x1_) { - col_data = col_buffer_.mutable_gpu_data(); + col_buff = col_buffer_.mutable_gpu_data(); } const Dtype* weight = this->blobs_[0]->gpu_data(); int weight_offset = M_ * K_; @@ -29,14 +29,14 @@ void ConvolutionLayer::Forward_gpu(const vector*>& bottom, if (!is_1x1_) { im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - col_data); + col_buff); } else { - col_data = bottom[i]->mutable_gpu_data() + bottom[i]->offset(n); + col_buff = bottom[i]->mutable_gpu_data() + bottom[i]->offset(n); } // Take inner products for groups. for (int g = 0; g < group_; ++g) { caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, - (Dtype)1., weight + weight_offset * g, col_data + col_offset * g, + (Dtype)1., weight + weight_offset * g, col_buff + col_offset * g, (Dtype)0., top_data + top[i]->offset(n) + top_offset * g); } // Add bias. @@ -85,11 +85,9 @@ void ConvolutionLayer::Backward_gpu(const vector*>& top, if (!top_diff) { top_diff = top[i]->gpu_diff(); } - Dtype* col_data = NULL; - Dtype* col_diff = NULL; + Dtype* col_buff = NULL; if (!is_1x1_) { - col_data = col_buffer_.mutable_gpu_data(); - col_diff = col_buffer_.mutable_gpu_diff(); + col_buff = col_buffer_.mutable_gpu_data(); } const Dtype* bottom_data = bottom[i]->gpu_data(); Dtype* bottom_diff = bottom[i]->mutable_gpu_diff(); @@ -99,17 +97,16 @@ void ConvolutionLayer::Backward_gpu(const vector*>& top, if (!is_1x1_) { im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, col_data); + stride_h_, stride_w_, col_buff); } else { - col_data = bottom[i]->mutable_gpu_data() + bottom[i]->offset(n); - col_diff = bottom[i]->mutable_gpu_diff() + bottom[i]->offset(n); + col_buff = bottom[i]->mutable_gpu_data() + bottom[i]->offset(n); } // gradient w.r.t. weight. Note that we will accumulate diffs. if (this->param_propagate_down_[0]) { for (int g = 0; g < group_; ++g) { caffe_gpu_gemm(CblasNoTrans, CblasTrans, M_, K_, N_, (Dtype)1., top_diff + top[i]->offset(n) + top_offset * g, - col_data + col_offset * g, (Dtype)1., + col_buff + col_offset * g, (Dtype)1., weight_diff + weight_offset * g); } } @@ -118,15 +115,18 @@ void ConvolutionLayer::Backward_gpu(const vector*>& top, if (weight == NULL) { weight = this->blobs_[0]->gpu_data(); } + if (is_1x1_) { + col_buff = bottom[i]->mutable_gpu_diff() + bottom[i]->offset(n); + } for (int g = 0; g < group_; ++g) { caffe_gpu_gemm(CblasTrans, CblasNoTrans, K_, N_, M_, (Dtype)1., weight + weight_offset * g, top_diff + top[i]->offset(n) + top_offset * g, - (Dtype)0., col_diff + col_offset * g); + (Dtype)0., col_buff + col_offset * g); } // col2im back to the data if (!is_1x1_) { - col2im_gpu(col_diff, channels_, height_, width_, + col2im_gpu(col_buff, channels_, height_, width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, bottom_diff + bottom[i]->offset(n)); } From 2c8d946b67d5024ec56d6abc85ea53ed33df8fa4 Mon Sep 17 00:00:00 2001 From: Sergey Karayev Date: Sun, 21 Sep 2014 22:53:30 -0700 Subject: [PATCH 009/798] web demo fix, closes #1002 --- examples/web_demo/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/web_demo/app.py b/examples/web_demo/app.py index d33fc92f078..e456526fa55 100644 --- a/examples/web_demo/app.py +++ b/examples/web_demo/app.py @@ -112,7 +112,7 @@ class ImagenetClassifier(object): if not os.path.exists(val): raise Exception( "File for {} is missing. Should be at: {}".format(key, val)) - default_args['image_dim'] = 227 + default_args['image_dim'] = 256 default_args['raw_scale'] = 255. default_args['gpu_mode'] = False From 502141dd43500cd38fd78a4bc1f3262a45d95db7 Mon Sep 17 00:00:00 2001 From: Karen Simonyan Date: Thu, 18 Sep 2014 01:08:56 +0100 Subject: [PATCH 010/798] adds a parameter to the LRN layer (denoted as "k" in [Krizhevsky et al., NIPS 2012]) --- include/caffe/vision_layers.hpp | 1 + src/caffe/layers/lrn_layer.cpp | 3 ++- src/caffe/layers/lrn_layer.cu | 10 +++++----- src/caffe/proto/caffe.proto | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index fa516144d25..a3c8bc0a31f 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -246,6 +246,7 @@ class LRNLayer : public Layer { int pre_pad_; Dtype alpha_; Dtype beta_; + Dtype k_; int num_; int channels_; int height_; diff --git a/src/caffe/layers/lrn_layer.cpp b/src/caffe/layers/lrn_layer.cpp index fb74b03dc88..a09a47940d2 100644 --- a/src/caffe/layers/lrn_layer.cpp +++ b/src/caffe/layers/lrn_layer.cpp @@ -14,6 +14,7 @@ void LRNLayer::LayerSetUp(const vector*>& bottom, pre_pad_ = (size_ - 1) / 2; alpha_ = this->layer_param_.lrn_param().alpha(); beta_ = this->layer_param_.lrn_param().beta(); + k_ = this->layer_param_.lrn_param().k(); if (this->layer_param_.lrn_param().norm_region() == LRNParameter_NormRegion_WITHIN_CHANNEL) { // Set up split_layer_ to use inputs in the numerator and denominator. @@ -110,7 +111,7 @@ void LRNLayer::CrossChannelForward_cpu( Dtype* scale_data = scale_.mutable_cpu_data(); // start with the constant value for (int i = 0; i < scale_.count(); ++i) { - scale_data[i] = 1.; + scale_data[i] = k_; } Blob padded_square(1, channels_ + size_ - 1, height_, width_); Dtype* padded_square_data = padded_square.mutable_cpu_data(); diff --git a/src/caffe/layers/lrn_layer.cu b/src/caffe/layers/lrn_layer.cu index ee5e359ff0b..47b003bc4aa 100644 --- a/src/caffe/layers/lrn_layer.cu +++ b/src/caffe/layers/lrn_layer.cu @@ -10,7 +10,7 @@ template __global__ void LRNFillScale(const int nthreads, const Dtype* in, const int num, const int channels, const int height, const int width, const int size, const Dtype alpha_over_size, - Dtype* scale) { + const Dtype k, Dtype* scale) { CUDA_KERNEL_LOOP(index, nthreads) { // find out the local offset int w = index % width; @@ -33,20 +33,20 @@ __global__ void LRNFillScale(const int nthreads, const Dtype* in, // until we reach size, nothing needs to be subtracted while (head < size) { accum_scale += in[head * step] * in[head * step]; - scale[(head - post_pad) * step] = 1. + accum_scale * alpha_over_size; + scale[(head - post_pad) * step] = k + accum_scale * alpha_over_size; ++head; } // both add and subtract while (head < channels) { accum_scale += in[head * step] * in[head * step]; accum_scale -= in[(head - size) * step] * in[(head - size) * step]; - scale[(head - post_pad) * step] = 1. + accum_scale * alpha_over_size; + scale[(head - post_pad) * step] = k + accum_scale * alpha_over_size; ++head; } // subtract only while (head < channels + post_pad) { accum_scale -= in[(head - size) * step] * in[(head - size) * step]; - scale[(head - post_pad) * step] = 1. + accum_scale * alpha_over_size; + scale[(head - post_pad) * step] = k + accum_scale * alpha_over_size; ++head; } } @@ -90,7 +90,7 @@ void LRNLayer::CrossChannelForward_gpu( // NOLINT_NEXT_LINE(whitespace/operators) LRNFillScale<<>>( n_threads, bottom_data, num_, channels_, height_, width_, size_, - alpha_ / size_, scale_data); + alpha_ / size_, k_, scale_data); CUDA_POST_KERNEL_CHECK; n_threads = bottom[0]->count(); // NOLINT_NEXT_LINE(whitespace/operators) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 9395c38f3e9..b9712fa7414 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -548,6 +548,7 @@ message LRNParameter { WITHIN_CHANNEL = 1; } optional NormRegion norm_region = 4 [default = ACROSS_CHANNELS]; + optional float k = 5 [default = 1.]; } // Message that stores parameters used by MemoryDataLayer From aeb0e984a168030769c107e278d223cae5f8c0ea Mon Sep 17 00:00:00 2001 From: Karen Simonyan Date: Sun, 21 Sep 2014 17:58:41 +0100 Subject: [PATCH 011/798] added support for "k" LRN parameter to upgrade_proto --- src/caffe/proto/caffe.proto | 1 + src/caffe/util/upgrade_proto.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index b9712fa7414..01a516ee3b9 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -716,6 +716,7 @@ message V0LayerParameter { optional uint32 local_size = 13 [default = 5]; // for local response norm optional float alpha = 14 [default = 1.]; // for local response norm optional float beta = 15 [default = 0.75]; // for local response norm + optional float k = 22 [default = 1.]; // For data layers, specify the data source optional string source = 16; diff --git a/src/caffe/util/upgrade_proto.cpp b/src/caffe/util/upgrade_proto.cpp index c69c58eb340..cbd6003c948 100644 --- a/src/caffe/util/upgrade_proto.cpp +++ b/src/caffe/util/upgrade_proto.cpp @@ -285,6 +285,14 @@ bool UpgradeLayerParameter(const LayerParameter& v0_layer_connection, is_fully_compatible = false; } } + if (v0_layer_param.has_k()) { + if (type == "lrn") { + layer_param->mutable_lrn_param()->set_k(v0_layer_param.k()); + } else { + LOG(ERROR) << "Unknown parameter k for layer type " << type; + is_fully_compatible = false; + } + } if (v0_layer_param.has_source()) { if (type == "data") { layer_param->mutable_data_param()->set_source(v0_layer_param.source()); From 90584bd86fda189a1b5597bbeb7803dd5546f769 Mon Sep 17 00:00:00 2001 From: Karen Simonyan Date: Sun, 21 Sep 2014 17:59:25 +0100 Subject: [PATCH 012/798] added matcaffe_demo for the VGG models (RGB input) --- matlab/caffe/matcaffe_demo_vgg.m | 109 +++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 matlab/caffe/matcaffe_demo_vgg.m diff --git a/matlab/caffe/matcaffe_demo_vgg.m b/matlab/caffe/matcaffe_demo_vgg.m new file mode 100644 index 00000000000..698c26b9a79 --- /dev/null +++ b/matlab/caffe/matcaffe_demo_vgg.m @@ -0,0 +1,109 @@ +function [scores, maxlabel] = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) +% scores = matcaffe_demo(im, use_gpu) +% +% Demo of the matlab wrapper using the ILSVRC network. +% +% input +% im color image as uint8 HxWx3 +% use_gpu 1 to use the GPU, 0 to use the CPU +% +% output +% scores 1000-dimensional ILSVRC score vector +% +% You may need to do the following before you start matlab: +% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda-5.5/lib64 +% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 +% Or the equivalent based on where things are installed on your system +% +% Usage: +% im = imread('../../examples/images/cat.jpg'); +% scores = matcaffe_demo(im, 1); +% [score, class] = max(scores); +% Five things to be aware of: +% caffe uses row-major order +% matlab uses column-major order +% caffe uses BGR color channel order +% matlab uses RGB color channel order +% images need to have the data mean subtracted + +% Data coming in from matlab needs to be in the order +% [width, height, channels, images] +% where width is the fastest dimension. +% Here is the rough matlab for putting image data into the correct +% format: +% % convert from uint8 to single +% im = single(im); +% % reshape to a fixed size (e.g., 227x227) +% im = imresize(im, [IMAGE_DIM IMAGE_DIM], 'bilinear'); +% % permute from RGB to BGR and subtract the data mean (already in BGR) +% im = im(:,:,[3 2 1]) - data_mean; +% % flip width and height to make width the fastest dimension +% im = permute(im, [2 1 3]); + +% If you have multiple images, cat them with cat(4, ...) + +% The actual forward function. It takes in a cell array of 4-D arrays as +% input and outputs a cell array. + + +% init caffe network (spews logging info) +matcaffe_init(use_gpu, model_def_file, model_file); + +% prepare oversampled input +% input_data is Height x Width x Channel x Num +tic; +input_data = {prepare_image(im, mean_file)}; +toc; + +% do forward pass to get scores +% scores are now Width x Height x Channels x Num +tic; +scores = caffe('forward', input_data); +toc; + +scores = scores{1}; +% size(scores) +scores = squeeze(scores); +% scores = mean(scores,2); + +% [~,maxlabel] = max(scores); + +% ------------------------------------------------------------------------ +function images = prepare_image(im, mean_file) +% ------------------------------------------------------------------------ +IMAGE_DIM = 256; +CROPPED_DIM = 224; + +d = load(mean_file); +IMAGE_MEAN = d.image_mean; + +% resize to fixed input size +im = single(im); + +if size(im, 1) < size(im, 2) + im = imresize(im, [IMAGE_DIM NaN]); +else + im = imresize(im, [NaN IMAGE_DIM]); +end + +% oversample (4 corners, center, and their x-axis flips) +images = zeros(CROPPED_DIM, CROPPED_DIM, 3, 10, 'single'); + +indices_y = [0 size(im,1)-CROPPED_DIM] + 1; +indices_x = [0 size(im,2)-CROPPED_DIM] + 1; +center_y = floor(indices_y(2) / 2)+1; +center_x = floor(indices_x(2) / 2)+1; + +curr = 1; +for i = indices_y + for j = indices_x + images(:, :, :, curr) = ... + permute(im(i:i+CROPPED_DIM-1, j:j+CROPPED_DIM-1, :)-IMAGE_MEAN, [2 1 3]); + images(:, :, :, curr+5) = images(end:-1:1, :, :, curr); + curr = curr + 1; + end +end +images(:,:,:,5) = ... + permute(im(center_y:center_y+CROPPED_DIM-1,center_x:center_x+CROPPED_DIM-1,:)-IMAGE_MEAN, ... + [2 1 3]); +images(:,:,:,10) = images(end:-1:1, :, :, curr); From 536335939d2b35da7ca76509969eda90d9220278 Mon Sep 17 00:00:00 2001 From: Karen Simonyan Date: Mon, 22 Sep 2014 20:09:35 +0100 Subject: [PATCH 013/798] added comments to the Matlab demo script --- matlab/caffe/matcaffe_demo_vgg.m | 47 ++++++++------------------------ 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/matlab/caffe/matcaffe_demo_vgg.m b/matlab/caffe/matcaffe_demo_vgg.m index 698c26b9a79..3e25618164a 100644 --- a/matlab/caffe/matcaffe_demo_vgg.m +++ b/matlab/caffe/matcaffe_demo_vgg.m @@ -1,11 +1,15 @@ -function [scores, maxlabel] = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) -% scores = matcaffe_demo(im, use_gpu) +function scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) +% s = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) % -% Demo of the matlab wrapper using the ILSVRC network. +% Demo of the matlab wrapper using the VGG networks: https://gist.github.com/ksimonyan/5c9129cfb8f0359eaf67 +% described in the BMVC-2014 paper "Return of the Devil in the Details: Delving Deep into Convolutional Nets" % % input -% im color image as uint8 HxWx3 -% use_gpu 1 to use the GPU, 0 to use the CPU +% im - color image as uint8 HxWx3 +% use_gpu - 1 to use the GPU, 0 to use the CPU +% model_def_file - network configuration (.prototxt file) +% model_file - network weights (.caffemodel file) +% mean_file - mean RGB image as uint8 HxWx3 (.mat file) % % output % scores 1000-dimensional ILSVRC score vector @@ -15,36 +19,9 @@ % $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 % Or the equivalent based on where things are installed on your system % -% Usage: -% im = imread('../../examples/images/cat.jpg'); -% scores = matcaffe_demo(im, 1); -% [score, class] = max(scores); -% Five things to be aware of: -% caffe uses row-major order -% matlab uses column-major order -% caffe uses BGR color channel order -% matlab uses RGB color channel order -% images need to have the data mean subtracted - -% Data coming in from matlab needs to be in the order -% [width, height, channels, images] -% where width is the fastest dimension. -% Here is the rough matlab for putting image data into the correct -% format: -% % convert from uint8 to single -% im = single(im); -% % reshape to a fixed size (e.g., 227x227) -% im = imresize(im, [IMAGE_DIM IMAGE_DIM], 'bilinear'); -% % permute from RGB to BGR and subtract the data mean (already in BGR) -% im = im(:,:,[3 2 1]) - data_mean; -% % flip width and height to make width the fastest dimension -% im = permute(im, [2 1 3]); - -% If you have multiple images, cat them with cat(4, ...) - -% The actual forward function. It takes in a cell array of 4-D arrays as -% input and outputs a cell array. - +% NOTES +% the network is trained on RGB images and expects an RGB input +% the image crops are prepared as described in the paper (the aspect ratio is preserved) % init caffe network (spews logging info) matcaffe_init(use_gpu, model_def_file, model_file); From 5d2a9399ae03d9862c4962c770237393dbcafeb6 Mon Sep 17 00:00:00 2001 From: Karen Simonyan Date: Mon, 22 Sep 2014 20:39:37 +0100 Subject: [PATCH 014/798] added example usage to the Matlab script --- matlab/caffe/matcaffe_demo_vgg.m | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/matlab/caffe/matcaffe_demo_vgg.m b/matlab/caffe/matcaffe_demo_vgg.m index 3e25618164a..d396f50bb84 100644 --- a/matlab/caffe/matcaffe_demo_vgg.m +++ b/matlab/caffe/matcaffe_demo_vgg.m @@ -1,27 +1,36 @@ function scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) -% s = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) +% scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) % % Demo of the matlab wrapper using the VGG networks: https://gist.github.com/ksimonyan/5c9129cfb8f0359eaf67 % described in the BMVC-2014 paper "Return of the Devil in the Details: Delving Deep into Convolutional Nets" % -% input +% INPUT % im - color image as uint8 HxWx3 % use_gpu - 1 to use the GPU, 0 to use the CPU % model_def_file - network configuration (.prototxt file) % model_file - network weights (.caffemodel file) % mean_file - mean RGB image as uint8 HxWx3 (.mat file) % -% output +% OUTPUT % scores 1000-dimensional ILSVRC score vector % -% You may need to do the following before you start matlab: -% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda-5.5/lib64 -% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 -% Or the equivalent based on where things are installed on your system -% +% EXAMPLE USAGE +% model_def_file = 'zoo/VGG_CNN_F_deploy.prototxt'; +% model_file = 'zoo/VGG_CNN_F.caffemodel'; +% mean_file = 'zoo/VGG_mean.mat'; +% use_gpu = true; +% im = imread('../../examples/images/cat.jpg'); +% scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file); +% % NOTES % the network is trained on RGB images and expects an RGB input % the image crops are prepared as described in the paper (the aspect ratio is preserved) +% +% PREREQUISITES +% You may need to do the following before you start matlab: +% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda/lib64 +% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 +% Or the equivalent based on where things are installed on your system % init caffe network (spews logging info) matcaffe_init(use_gpu, model_def_file, model_file); From 60d47bf5344cde5c376cbcb354260e6366a4da1e Mon Sep 17 00:00:00 2001 From: Karen Simonyan Date: Tue, 23 Sep 2014 16:39:08 +0100 Subject: [PATCH 015/798] RGB -> BGR in the matlab demo --- matlab/caffe/matcaffe_demo_vgg.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/matlab/caffe/matcaffe_demo_vgg.m b/matlab/caffe/matcaffe_demo_vgg.m index d396f50bb84..4e5a98eb5f4 100644 --- a/matlab/caffe/matcaffe_demo_vgg.m +++ b/matlab/caffe/matcaffe_demo_vgg.m @@ -1,15 +1,14 @@ function scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) % scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) % -% Demo of the matlab wrapper using the VGG networks: https://gist.github.com/ksimonyan/5c9129cfb8f0359eaf67 -% described in the BMVC-2014 paper "Return of the Devil in the Details: Delving Deep into Convolutional Nets" +% Demo of the matlab wrapper using the networks described in the BMVC-2014 paper "Return of the Devil in the Details: Delving Deep into Convolutional Nets" % % INPUT % im - color image as uint8 HxWx3 % use_gpu - 1 to use the GPU, 0 to use the CPU % model_def_file - network configuration (.prototxt file) % model_file - network weights (.caffemodel file) -% mean_file - mean RGB image as uint8 HxWx3 (.mat file) +% mean_file - mean BGR image as uint8 HxWx3 (.mat file) % % OUTPUT % scores 1000-dimensional ILSVRC score vector @@ -23,7 +22,6 @@ % scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file); % % NOTES -% the network is trained on RGB images and expects an RGB input % the image crops are prepared as described in the paper (the aspect ratio is preserved) % % PREREQUISITES @@ -72,6 +70,9 @@ im = imresize(im, [NaN IMAGE_DIM]); end +% RGB -> BGR +im = im(:, :, [3 2 1]); + % oversample (4 corners, center, and their x-axis flips) images = zeros(CROPPED_DIM, CROPPED_DIM, 3, 10, 'single'); From 9007d96a2d6258b233fe201102f610cd2ed73586 Mon Sep 17 00:00:00 2001 From: Karen Simonyan Date: Wed, 24 Sep 2014 22:08:46 +0100 Subject: [PATCH 016/798] added a Matlab demo with mean BGR pixel subtraction instead of the mean image subtraction --- matlab/caffe/matcaffe_demo_vgg_mean_pix.m | 102 ++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 matlab/caffe/matcaffe_demo_vgg_mean_pix.m diff --git a/matlab/caffe/matcaffe_demo_vgg_mean_pix.m b/matlab/caffe/matcaffe_demo_vgg_mean_pix.m new file mode 100644 index 00000000000..5f7898a7029 --- /dev/null +++ b/matlab/caffe/matcaffe_demo_vgg_mean_pix.m @@ -0,0 +1,102 @@ +function scores = matcaffe_demo_vgg_mean_pix(im, use_gpu, model_def_file, model_file) +% scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file) +% +% Demo of the matlab wrapper based on the networks used for the "VGG" entry +% in the ILSVRC-2014 competition and described in the tech. report +% "Very Deep Convolutional Networks for Large-Scale Image Recognition" +% http://arxiv.org/abs/1409.1556/ +% +% INPUT +% im - color image as uint8 HxWx3 +% use_gpu - 1 to use the GPU, 0 to use the CPU +% model_def_file - network configuration (.prototxt file) +% model_file - network weights (.caffemodel file) +% +% OUTPUT +% scores 1000-dimensional ILSVRC score vector +% +% EXAMPLE USAGE +% model_def_file = 'zoo/deploy.prototxt'; +% model_file = 'zoo/model.caffemodel'; +% use_gpu = true; +% im = imread('../../examples/images/cat.jpg'); +% scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file); +% +% NOTES +% mean pixel subtraction is used instead of the mean image subtraction +% +% PREREQUISITES +% You may need to do the following before you start matlab: +% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda/lib64 +% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 +% Or the equivalent based on where things are installed on your system + +% init caffe network (spews logging info) +matcaffe_init(use_gpu, model_def_file, model_file); + +% mean BGR pixel +mean_pix = [103.939, 116.779, 123.68]; + +% prepare oversampled input +% input_data is Height x Width x Channel x Num +tic; +input_data = {prepare_image(im, mean_pix)}; +toc; + +% do forward pass to get scores +% scores are now Width x Height x Channels x Num +tic; +scores = caffe('forward', input_data); +toc; + +scores = scores{1}; +% size(scores) +scores = squeeze(scores); +% scores = mean(scores,2); + +% [~,maxlabel] = max(scores); + +% ------------------------------------------------------------------------ +function images = prepare_image(im, mean_pix) +% ------------------------------------------------------------------------ +IMAGE_DIM = 256; +CROPPED_DIM = 224; + +% resize to fixed input size +im = single(im); + +if size(im, 1) < size(im, 2) + im = imresize(im, [IMAGE_DIM NaN]); +else + im = imresize(im, [NaN IMAGE_DIM]); +end + +% RGB -> BGR +im = im(:, :, [3 2 1]); + +% oversample (4 corners, center, and their x-axis flips) +images = zeros(CROPPED_DIM, CROPPED_DIM, 3, 10, 'single'); + +indices_y = [0 size(im,1)-CROPPED_DIM] + 1; +indices_x = [0 size(im,2)-CROPPED_DIM] + 1; +center_y = floor(indices_y(2) / 2)+1; +center_x = floor(indices_x(2) / 2)+1; + +curr = 1; +for i = indices_y + for j = indices_x + images(:, :, :, curr) = ... + permute(im(i:i+CROPPED_DIM-1, j:j+CROPPED_DIM-1, :), [2 1 3]); + images(:, :, :, curr+5) = images(end:-1:1, :, :, curr); + curr = curr + 1; + end +end +images(:,:,:,5) = ... + permute(im(center_y:center_y+CROPPED_DIM-1,center_x:center_x+CROPPED_DIM-1,:), ... + [2 1 3]); +images(:,:,:,10) = images(end:-1:1, :, :, curr); + +% mean BGR pixel subtraction +for c = 1:3 + images(:, :, c, :) = images(:, :, c, :) - mean_pix(c); +end From 98db2dc31e5fec4ae7eb4c026348a4b69d50a670 Mon Sep 17 00:00:00 2001 From: "D.Mishkin" Date: Thu, 25 Sep 2014 17:30:48 +0300 Subject: [PATCH 017/798] Removed unnecessary "mutable" --- tools/extract_features.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 49e8f98971c..9b0288a4d5a 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -148,14 +148,14 @@ int feature_extraction_pipeline(int argc, char** argv) { ->blob_by_name(blob_names[i]); int batch_size = feature_blob->num(); int dim_features = feature_blob->count() / batch_size; - Dtype* feature_blob_data; + const Dtype* feature_blob_data; for (int n = 0; n < batch_size; ++n) { datum.set_height(dim_features); datum.set_width(1); datum.set_channels(1); datum.clear_data(); datum.clear_float_data(); - feature_blob_data = feature_blob->mutable_cpu_data() + + feature_blob_data = feature_blob->cpu_data() + feature_blob->offset(n); for (int d = 0; d < dim_features; ++d) { datum.add_float_data(feature_blob_data[d]); From f1a1426580a1279282e2d16998cb46d9755351c8 Mon Sep 17 00:00:00 2001 From: Alireza Shafaei Date: Tue, 23 Sep 2014 22:35:00 -0700 Subject: [PATCH 018/798] Random crop bugfix and abstracting random number generation inside data_transformer --- include/caffe/data_transformer.hpp | 10 +++++++++- src/caffe/data_transformer.cpp | 11 ++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 5d5134f5db5..3ca99e7b62c 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -39,7 +39,15 @@ class DataTransformer { const Dtype* mean, Dtype* transformed_data); protected: - virtual unsigned int Rand(); + /** + * @brief Generates a random integer from Uniform({0, 1, ..., n-1}). + * + * @param n + * The upperbound (exclusive) value of the random number. + * @return + * A uniformly random integer value from ({0, 1, ..., n-1}). + */ + virtual int Rand(int n); // Tranformation parameters TransformationParameter param_; diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 7150fd99c18..e52c3b6a55d 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -31,13 +31,13 @@ void DataTransformer::Transform(const int batch_item_id, int h_off, w_off; // We only do random crop when we do training. if (phase_ == Caffe::TRAIN) { - h_off = Rand() % (height - crop_size); - w_off = Rand() % (width - crop_size); + h_off = Rand(height - crop_size + 1); + w_off = Rand(width - crop_size + 1); } else { h_off = (height - crop_size) / 2; w_off = (width - crop_size) / 2; } - if (mirror && Rand() % 2) { + if (mirror && (Rand(2) == 1)) { // Copy mirrored version for (int c = 0; c < channels; ++c) { for (int h = 0; h < crop_size; ++h) { @@ -99,11 +99,12 @@ void DataTransformer::InitRand() { } template -unsigned int DataTransformer::Rand() { +int DataTransformer::Rand(int n) { CHECK(rng_); + CHECK_GT(n, 0); caffe::rng_t* rng = static_cast(rng_->generator()); - return (*rng)(); + return ((*rng)() % n); } INSTANTIATE_CLASS(DataTransformer); From 3ea823c461884c259c07c441d07c99c68cf91298 Mon Sep 17 00:00:00 2001 From: jjkjkj Date: Fri, 26 Sep 2014 12:39:49 +0300 Subject: [PATCH 019/798] Update layer_factory.cpp --- src/caffe/layer_factory.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index b78167f21eb..69c8c9ed70b 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -251,6 +251,8 @@ Layer* GetLayer(const LayerParameter& param) { return GetTanHLayer(name, param); case LayerParameter_LayerType_WINDOW_DATA: return new WindowDataLayer(param); + case LayerParameter_LayerType_THRESHOLD: + return new ThresholdLayer(param); case LayerParameter_LayerType_NONE: LOG(FATAL) << "Layer " << name << " has unspecified type."; default: From 6d80a633f43f41f2188aee9e05917b7e0dc6363c Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sat, 27 Sep 2014 20:10:13 -0700 Subject: [PATCH 020/798] cudnn pooling fallback option --- src/caffe/layer_factory.cpp | 6 +++++- src/caffe/layers/cudnn_pooling_layer.cpp | 5 ++++- src/caffe/layers/cudnn_pooling_layer.cu | 13 ------------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index b78167f21eb..19e111cbcc8 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -40,7 +40,8 @@ template ConvolutionLayer* GetConvolutionLayer(const string& name, template PoolingLayer* GetPoolingLayer(const string& name, const LayerParameter& param) { - PoolingParameter_Engine engine = param.pooling_param().engine(); + const PoolingParameter& p_param = param.pooling_param(); + const PoolingParameter_Engine& engine = p_param.engine(); if (engine == PoolingParameter_Engine_DEFAULT) { engine = PoolingParameter_Engine_CAFFE; #ifdef USE_CUDNN @@ -51,6 +52,9 @@ PoolingLayer* GetPoolingLayer(const string& name, return new PoolingLayer(param); #ifdef USE_CUDNN } else if (engine == PoolingParameter_Engine_CUDNN) { + if (p_param.pad_h() || p_param.pad_w() || param.top_size() > 1) { + return new PoolingLayer(param); + } return new CuDNNPoolingLayer(param); #endif } else { diff --git a/src/caffe/layers/cudnn_pooling_layer.cpp b/src/caffe/layers/cudnn_pooling_layer.cpp index 2af9d21be26..b61ed2a7ede 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cpp +++ b/src/caffe/layers/cudnn_pooling_layer.cpp @@ -13,7 +13,10 @@ template void CuDNNPoolingLayer::LayerSetUp(const vector*>& bottom, const vector*>& top) { PoolingLayer::LayerSetUp(bottom, top); - + // Sanity check: CUDNN currently only supports pad=0 and top.size()=1 cases. + CHECK_EQ(pad_h_, 0); + CHECK_EQ(pad_w_, 0); + CHECK_EQ(top.size(), 1); CUDNN_CHECK(cudnnCreate(&handle_)); cudnn::createTensor4dDesc(&bottom_desc_); cudnn::createTensor4dDesc(&top_desc_); diff --git a/src/caffe/layers/cudnn_pooling_layer.cu b/src/caffe/layers/cudnn_pooling_layer.cu index 9d270ed25d5..8b9e7f1bf10 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cu +++ b/src/caffe/layers/cudnn_pooling_layer.cu @@ -12,12 +12,6 @@ namespace caffe { template void CuDNNPoolingLayer::Forward_gpu(const vector*>& bottom, const vector*>& top) { - // Fallback to Caffe for padded pooling, max top mask. - if ((this->pad_h_ > 0 || this->pad_w_ > 0) || top.size() > 1) { - LOG(WARNING) << "Falling back to standard Caffe for padded pooling."; - return PoolingLayer::Forward_gpu(bottom, top); - } - const Dtype* bottom_data = bottom[0]->gpu_data(); Dtype* top_data = top[0]->mutable_gpu_data(); CUDNN_CHECK(cudnnPoolingForward(handle_, pooling_desc_, @@ -30,13 +24,6 @@ void CuDNNPoolingLayer::Backward_gpu(const vector*>& top, if (!propagate_down[0]) { return; } - - // Fallback to Caffe for padded pooling, max top mask. - if ((this->pad_h_ > 0 || this->pad_w_ > 0) || top.size() > 1) { - LOG(WARNING) << "Falling back to standard Caffe for padded pooling."; - return PoolingLayer::Backward_gpu(top, propagate_down, bottom); - } - const Dtype* top_diff = top[0]->gpu_diff(); const Dtype* top_data = top[0]->gpu_data(); const Dtype* bottom_data = bottom[0]->gpu_data(); From 560bd7ee646da7659471d142b4156a8e86e0e8b8 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sat, 27 Sep 2014 20:22:10 -0700 Subject: [PATCH 021/798] const fix --- src/caffe/layer_factory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 19e111cbcc8..3f15825bd88 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -41,7 +41,7 @@ template PoolingLayer* GetPoolingLayer(const string& name, const LayerParameter& param) { const PoolingParameter& p_param = param.pooling_param(); - const PoolingParameter_Engine& engine = p_param.engine(); + PoolingParameter_Engine engine = p_param.engine(); if (engine == PoolingParameter_Engine_DEFAULT) { engine = PoolingParameter_Engine_CAFFE; #ifdef USE_CUDNN From 7accbeeed51c76bfc94d65366b857aa1b81bd4f4 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sun, 28 Sep 2014 15:33:52 -0700 Subject: [PATCH 022/798] message --- src/caffe/layer_factory.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 3f15825bd88..9e62e9528fb 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -53,6 +53,8 @@ PoolingLayer* GetPoolingLayer(const string& name, #ifdef USE_CUDNN } else if (engine == PoolingParameter_Engine_CUDNN) { if (p_param.pad_h() || p_param.pad_w() || param.top_size() > 1) { + LOG(INFO) << "CUDNN does not support padding or multiple tops. " + << "Using Caffe's own pooling layer."; return new PoolingLayer(param); } return new CuDNNPoolingLayer(param); From d316628f8dfffb6910fe8010b9c50085ba7196a8 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Fri, 26 Sep 2014 13:58:45 -0700 Subject: [PATCH 023/798] running factory. --- Makefile | 38 +++--- include/caffe/layer.hpp | 5 +- include/caffe/layer_factory.hpp | 85 +++++++++++++ src/caffe/layer_factory.cpp | 205 ++++++++++---------------------- 4 files changed, 165 insertions(+), 168 deletions(-) create mode 100644 include/caffe/layer_factory.hpp diff --git a/Makefile b/Makefile index 5020b4109d6..243650b2ad1 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,6 @@ endif # The target shared library and static library name LIB_BUILD_DIR := $(BUILD_DIR)/lib NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so -STATIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).a ############################## # Get all source files @@ -338,7 +337,7 @@ SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo py mat py$(PROJECT) mat$(PROJECT) proto runtest \ superclean supercleanlist supercleanfiles warn everything -all: $(NAME) $(STATIC_NAME) tools examples +all: $(NAME) tools examples everything: all py$(PROJECT) mat$(PROJECT) test warn lint runtest @@ -387,16 +386,16 @@ py$(PROJECT): py py: $(PY$(PROJECT)_SO) $(PROTO_GEN_PY) -$(PY$(PROJECT)_SO): $(STATIC_NAME) $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX_SRC) +$(PY$(PROJECT)_SO): $(OBJS) $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX_SRC) $(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \ - $(STATIC_NAME) $(LINKFLAGS) $(PYTHON_LDFLAGS) + $(OBJS) $(LINKFLAGS) $(PYTHON_LDFLAGS) @ echo mat$(PROJECT): mat mat: $(MAT$(PROJECT)_SO) -$(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME) +$(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(OBJS) @ if [ -z "$(MATLAB_DIR)" ]; then \ echo "MATLAB_DIR must be specified in $(CONFIG_FILE)" \ "to build mat$(PROJECT)."; \ @@ -405,7 +404,7 @@ $(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME) $(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_SRC) \ CXX="$(CXX)" \ CXXFLAGS="\$$CXXFLAGS $(MATLAB_CXXFLAGS)" \ - CXXLIBS="\$$CXXLIBS $(STATIC_NAME) $(LDFLAGS)" -output $@ + CXXLIBS="\$$CXXLIBS $(OBJS) $(LDFLAGS)" -output $@ @ echo runtest: $(TEST_ALL_BIN) @@ -443,14 +442,10 @@ $(BUILD_DIR)/.linked: $(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK) @ mkdir -p $@ -$(NAME): $(PROTO_OBJS) $(OBJS) | $(LIB_BUILD_DIR) +$(NAME): $(OBJS) | $(LIB_BUILD_DIR) $(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) @ echo -$(STATIC_NAME): $(PROTO_OBJS) $(OBJS) | $(LIB_BUILD_DIR) - ar rcs $@ $(PROTO_OBJS) $(OBJS) - @ echo - $(TEST_BUILD_DIR)/%.o: src/$(PROJECT)/test/%.cpp $(HXX_SRCS) $(TEST_HXX_SRCS) \ | $(TEST_BUILD_DIR) $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ @@ -465,21 +460,21 @@ $(TEST_BUILD_DIR)/%.cuo: src/$(PROJECT)/test/%.cu $(HXX_SRCS) $(TEST_HXX_SRCS) \ @ cat $@.$(WARNS_EXT) @ echo -$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \ +$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(OBJS) \ | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \ + $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(OBJS) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo -$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(STATIC_NAME) \ +$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(OBJS) \ | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_NAME) \ + $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(OBJS) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo -$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.o $(GTEST_OBJ) $(STATIC_NAME) \ +$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.o $(GTEST_OBJ) $(OBJS) \ | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_NAME) \ + $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(OBJS) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo @@ -488,12 +483,12 @@ $(TOOL_BUILD_DIR)/%: $(TOOL_BUILD_DIR)/%.bin | $(TOOL_BUILD_DIR) @ $(RM) $@ @ ln -s $(abspath $<) $@ -$(TOOL_BINS): %.bin : %.o $(STATIC_NAME) - $(CXX) $< $(STATIC_NAME) -o $@ $(LINKFLAGS) $(LDFLAGS) +$(TOOL_BINS): %.bin : %.o $(OBJS) + $(CXX) $< $(OBJS) -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo -$(EXAMPLE_BINS): %.bin : %.o $(STATIC_NAME) - $(CXX) $< $(STATIC_NAME) -o $@ $(LINKFLAGS) $(LDFLAGS) +$(EXAMPLE_BINS): %.bin : %.o $(OBJS) + $(CXX) $< $(OBJS) -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo $(LAYER_BUILD_DIR)/%.o: src/$(PROJECT)/layers/%.cpp $(HXX_SRCS) \ @@ -612,6 +607,5 @@ $(DISTRIBUTE_DIR): all py $(HXX_SRCS) | $(DISTRIBUTE_SUBDIRS) cp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin # add libraries cp $(NAME) $(DISTRIBUTE_DIR)/lib - cp $(STATIC_NAME) $(DISTRIBUTE_DIR)/lib # add python - it's not the standard way, indeed... cp -r python $(DISTRIBUTE_DIR)/python diff --git a/include/caffe/layer.hpp b/include/caffe/layer.hpp index 18ff2743719..8a8330bca57 100644 --- a/include/caffe/layer.hpp +++ b/include/caffe/layer.hpp @@ -7,6 +7,7 @@ #include "caffe/blob.hpp" #include "caffe/common.hpp" +#include "caffe/layer_factory.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/device_alternate.hpp" @@ -469,10 +470,6 @@ void Layer::ToProto(LayerParameter* param, bool write_diff) { } } -// The layer factory function -template -Layer* GetLayer(const LayerParameter& param); - } // namespace caffe #endif // CAFFE_LAYER_H_ diff --git a/include/caffe/layer_factory.hpp b/include/caffe/layer_factory.hpp new file mode 100644 index 00000000000..08e3e6d3ad8 --- /dev/null +++ b/include/caffe/layer_factory.hpp @@ -0,0 +1,85 @@ +#ifndef CAFFE_LAYER_FACTORY_H_ +#define CAFFE_LAYER_FACTORY_H_ + +#include + +#include "caffe/common.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +template +class Layer; + +template +class LayerRegistry { + public: + typedef Layer* (*Creator)(const LayerParameter&); + typedef std::map CreatorRegistry; + + // Adds a creator. + static void AddCreator(const LayerParameter_LayerType& type, + Creator creator) { + CHECK_EQ(registry_.count(type), 0) + << "Layer type " << type << " already registered."; + registry_[type] = creator; + } + + // Get a layer using a LayerParameter. + static Layer* CreateLayer(const LayerParameter& param) { + LOG(INFO) << "Creating layer " << param.name(); + const LayerParameter_LayerType& type = param.type(); + CHECK_EQ(registry_.count(type), 1); + return registry_[type](param); + } + + private: + // Layer registry should never be instantiated - everything is done with its + // static variables. + LayerRegistry() {} + static CreatorRegistry registry_; +}; + +// Static variables for the templated layer factory registry. +template +typename LayerRegistry::CreatorRegistry LayerRegistry::registry_; + +template +class LayerRegisterer { + public: + LayerRegisterer(const LayerParameter_LayerType& type, + Layer* (*creator)(const LayerParameter&)) { + LOG(INFO) << "Registering layer type: " << type; + LayerRegistry::AddCreator(type, creator); + } +}; + + +#define REGISTER_LAYER_CREATOR(type, creator, classname) \ + static LayerRegisterer g_creator_f_##classname(type, creator); \ + static LayerRegisterer g_creator_d_##classname(type, creator) + +#define REGISTER_LAYER_CLASS(type, clsname) \ + template \ + Layer* Creator_##clsname(const LayerParameter& param) { \ + return new clsname(param); \ + } \ + static LayerRegisterer g_creator_f_##clsname( \ + type, Creator_##clsname); \ + static LayerRegisterer g_creator_d_##clsname( \ + type, Creator_##clsname) + +// A function to get a specific layer from the specification given in +// LayerParameter. Ideally this would be replaced by a factory pattern, +// but we will leave it this way for now. +// Yangqing's note: With LayerRegistry, we no longer need this thin wrapper any +// more. It is provided here for backward compatibility and should be removed in +// the future. +template +Layer* GetLayer(const LayerParameter& param) { + return LayerRegistry::CreateLayer(param); +} + +} // namespace caffe + +#endif // CAFFE_LAYER_FACTORY_H_ diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 566162911ef..79a732b965b 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -1,6 +1,7 @@ #include #include "caffe/layer.hpp" +#include "caffe/layer_factory.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/vision_layers.hpp" @@ -11,7 +12,7 @@ namespace caffe { // Get convolution layer according to engine. template -ConvolutionLayer* GetConvolutionLayer(const string& name, +Layer* GetConvolutionLayer( const LayerParameter& param) { ConvolutionParameter_Engine engine = param.convolution_param().engine(); if (engine == ConvolutionParameter_Engine_DEFAULT) { @@ -27,21 +28,14 @@ ConvolutionLayer* GetConvolutionLayer(const string& name, return new CuDNNConvolutionLayer(param); #endif } else { - LOG(FATAL) << "Layer " << name << " has unknown engine."; + LOG(FATAL) << "Layer " << param.name() << " has unknown engine."; } } -template ConvolutionLayer* GetConvolutionLayer(const string& name, - const LayerParameter& param); -template ConvolutionLayer* GetConvolutionLayer(const string& name, - const LayerParameter& param); - // Get pooling layer according to engine. template -PoolingLayer* GetPoolingLayer(const string& name, - const LayerParameter& param) { - const PoolingParameter& p_param = param.pooling_param(); - PoolingParameter_Engine engine = p_param.engine(); +Layer* GetPoolingLayer(const LayerParameter& param) { + PoolingParameter_Engine engine = param.pooling_param().engine(); if (engine == PoolingParameter_Engine_DEFAULT) { engine = PoolingParameter_Engine_CAFFE; #ifdef USE_CUDNN @@ -60,19 +54,13 @@ PoolingLayer* GetPoolingLayer(const string& name, return new CuDNNPoolingLayer(param); #endif } else { - LOG(FATAL) << "Layer " << name << " has unknown engine."; + LOG(FATAL) << "Layer " << param.name() << " has unknown engine."; } } -template PoolingLayer* GetPoolingLayer(const string& name, - const LayerParameter& param); -template PoolingLayer* GetPoolingLayer(const string& name, - const LayerParameter& param); - // Get relu layer according to engine. template -ReLULayer* GetReLULayer(const string& name, - const LayerParameter& param) { +Layer* GetReLULayer(const LayerParameter& param) { ReLUParameter_Engine engine = param.relu_param().engine(); if (engine == ReLUParameter_Engine_DEFAULT) { engine = ReLUParameter_Engine_CAFFE; @@ -87,19 +75,13 @@ ReLULayer* GetReLULayer(const string& name, return new CuDNNReLULayer(param); #endif } else { - LOG(FATAL) << "Layer " << name << " has unknown engine."; + LOG(FATAL) << "Layer " << param.name() << " has unknown engine."; } } -template ReLULayer* GetReLULayer(const string& name, - const LayerParameter& param); -template ReLULayer* GetReLULayer(const string& name, - const LayerParameter& param); - // Get sigmoid layer according to engine. template -SigmoidLayer* GetSigmoidLayer(const string& name, - const LayerParameter& param) { +Layer* GetSigmoidLayer(const LayerParameter& param) { SigmoidParameter_Engine engine = param.sigmoid_param().engine(); if (engine == SigmoidParameter_Engine_DEFAULT) { engine = SigmoidParameter_Engine_CAFFE; @@ -114,19 +96,13 @@ SigmoidLayer* GetSigmoidLayer(const string& name, return new CuDNNSigmoidLayer(param); #endif } else { - LOG(FATAL) << "Layer " << name << " has unknown engine."; + LOG(FATAL) << "Layer " << param.name() << " has unknown engine."; } } -template SigmoidLayer* GetSigmoidLayer(const string& name, - const LayerParameter& param); -template SigmoidLayer* GetSigmoidLayer(const string& name, - const LayerParameter& param); - // Get tanh layer according to engine. template -TanHLayer* GetTanHLayer(const string& name, - const LayerParameter& param) { +Layer* GetTanHLayer(const LayerParameter& param) { TanHParameter_Engine engine = param.tanh_param().engine(); if (engine == TanHParameter_Engine_DEFAULT) { engine = TanHParameter_Engine_CAFFE; @@ -141,19 +117,13 @@ TanHLayer* GetTanHLayer(const string& name, return new CuDNNTanHLayer(param); #endif } else { - LOG(FATAL) << "Layer " << name << " has unknown engine."; + LOG(FATAL) << "Layer " << param.name() << " has unknown engine."; } } -template TanHLayer* GetTanHLayer(const string& name, - const LayerParameter& param); -template TanHLayer* GetTanHLayer(const string& name, - const LayerParameter& param); - // Get softmax layer according to engine. template -SoftmaxLayer* GetSoftmaxLayer(const string& name, - const LayerParameter& param) { +Layer* GetSoftmaxLayer(const LayerParameter& param) { SoftmaxParameter_Engine engine = param.softmax_param().engine(); if (engine == SoftmaxParameter_Engine_DEFAULT) { engine = SoftmaxParameter_Engine_CAFFE; @@ -168,107 +138,58 @@ SoftmaxLayer* GetSoftmaxLayer(const string& name, return new CuDNNSoftmaxLayer(param); #endif } else { - LOG(FATAL) << "Layer " << name << " has unknown engine."; - } -} - -template SoftmaxLayer* GetSoftmaxLayer(const string& name, - const LayerParameter& param); -template SoftmaxLayer* GetSoftmaxLayer(const string& name, - const LayerParameter& param); - -// A function to get a specific layer from the specification given in -// LayerParameter. Ideally this would be replaced by a factory pattern, -// but we will leave it this way for now. -template -Layer* GetLayer(const LayerParameter& param) { - const string& name = param.name(); - const LayerParameter_LayerType& type = param.type(); - switch (type) { - case LayerParameter_LayerType_ACCURACY: - return new AccuracyLayer(param); - case LayerParameter_LayerType_ABSVAL: - return new AbsValLayer(param); - case LayerParameter_LayerType_ARGMAX: - return new ArgMaxLayer(param); - case LayerParameter_LayerType_BNLL: - return new BNLLLayer(param); - case LayerParameter_LayerType_CONCAT: - return new ConcatLayer(param); - case LayerParameter_LayerType_CONTRASTIVE_LOSS: - return new ContrastiveLossLayer(param); - case LayerParameter_LayerType_CONVOLUTION: - return GetConvolutionLayer(name, param); - case LayerParameter_LayerType_DATA: - return new DataLayer(param); - case LayerParameter_LayerType_DROPOUT: - return new DropoutLayer(param); - case LayerParameter_LayerType_DUMMY_DATA: - return new DummyDataLayer(param); - case LayerParameter_LayerType_EUCLIDEAN_LOSS: - return new EuclideanLossLayer(param); - case LayerParameter_LayerType_ELTWISE: - return new EltwiseLayer(param); - case LayerParameter_LayerType_FLATTEN: - return new FlattenLayer(param); - case LayerParameter_LayerType_HDF5_DATA: - return new HDF5DataLayer(param); - case LayerParameter_LayerType_HDF5_OUTPUT: - return new HDF5OutputLayer(param); - case LayerParameter_LayerType_HINGE_LOSS: - return new HingeLossLayer(param); - case LayerParameter_LayerType_IMAGE_DATA: - return new ImageDataLayer(param); - case LayerParameter_LayerType_IM2COL: - return new Im2colLayer(param); - case LayerParameter_LayerType_INFOGAIN_LOSS: - return new InfogainLossLayer(param); - case LayerParameter_LayerType_INNER_PRODUCT: - return new InnerProductLayer(param); - case LayerParameter_LayerType_LRN: - return new LRNLayer(param); - case LayerParameter_LayerType_MEMORY_DATA: - return new MemoryDataLayer(param); - case LayerParameter_LayerType_MVN: - return new MVNLayer(param); - case LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS: - return new MultinomialLogisticLossLayer(param); - case LayerParameter_LayerType_POOLING: - return GetPoolingLayer(name, param); - case LayerParameter_LayerType_POWER: - return new PowerLayer(param); - case LayerParameter_LayerType_RELU: - return GetReLULayer(name, param); - case LayerParameter_LayerType_SILENCE: - return new SilenceLayer(param); - case LayerParameter_LayerType_SIGMOID: - return GetSigmoidLayer(name, param); - case LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS: - return new SigmoidCrossEntropyLossLayer(param); - case LayerParameter_LayerType_SLICE: - return new SliceLayer(param); - case LayerParameter_LayerType_SOFTMAX: - return GetSoftmaxLayer(name, param); - case LayerParameter_LayerType_SOFTMAX_LOSS: - return new SoftmaxWithLossLayer(param); - case LayerParameter_LayerType_SPLIT: - return new SplitLayer(param); - case LayerParameter_LayerType_TANH: - return GetTanHLayer(name, param); - case LayerParameter_LayerType_WINDOW_DATA: - return new WindowDataLayer(param); - case LayerParameter_LayerType_THRESHOLD: - return new ThresholdLayer(param); - case LayerParameter_LayerType_NONE: - LOG(FATAL) << "Layer " << name << " has unspecified type."; - default: - LOG(FATAL) << "Layer " << name << " has unknown type " << type; + LOG(FATAL) << "Layer " << param.name() << " has unknown engine."; } - // just to suppress old compiler warnings. - return (Layer*)(NULL); } -template Layer* GetLayer(const LayerParameter& param); -template Layer* GetLayer(const LayerParameter& param); +// Layers that have a specific creator function. +REGISTER_LAYER_CREATOR(LayerParameter_LayerType_CONVOLUTION, + GetConvolutionLayer, ConvolutionLayer); +REGISTER_LAYER_CREATOR(LayerParameter_LayerType_POOLING, + GetPoolingLayer, PoolingLayer); +REGISTER_LAYER_CREATOR(LayerParameter_LayerType_RELU, + GetReLULayer, ReLULayer); +REGISTER_LAYER_CREATOR(LayerParameter_LayerType_SIGMOID, + GetSigmoidLayer, SigmoidLayer); +REGISTER_LAYER_CREATOR(LayerParameter_LayerType_SOFTMAX, + GetSoftmaxLayer, SoftmaxLayer); +REGISTER_LAYER_CREATOR(LayerParameter_LayerType_TANH, + GetTanHLayer, TanHLayer); +// Layers that use their constructor as their default creator. +REGISTER_LAYER_CLASS(LayerParameter_LayerType_ACCURACY, AccuracyLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_ABSVAL, AbsValLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_ARGMAX, ArgMaxLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_BNLL, BNLLLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_CONCAT, ConcatLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_CONTRASTIVE_LOSS, + ContrastiveLossLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_DATA, DataLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_DROPOUT, DropoutLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_DUMMY_DATA, DummyDataLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_EUCLIDEAN_LOSS, + EuclideanLossLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_ELTWISE, EltwiseLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_FLATTEN, FlattenLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_HDF5_DATA, HDF5DataLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_HDF5_OUTPUT, HDF5OutputLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_HINGE_LOSS, HingeLossLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_IMAGE_DATA, ImageDataLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_IM2COL, Im2colLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_INFOGAIN_LOSS, InfogainLossLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_INNER_PRODUCT, InnerProductLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_LRN, LRNLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_MEMORY_DATA, MemoryDataLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_MVN, MVNLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS, + MultinomialLogisticLossLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_POWER, PowerLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_SILENCE, SilenceLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS, + SigmoidCrossEntropyLossLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_SLICE, SliceLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_SOFTMAX_LOSS, + SoftmaxWithLossLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_SPLIT, SplitLayer); +REGISTER_LAYER_CLASS(LayerParameter_LayerType_WINDOW_DATA, WindowDataLayer); } // namespace caffe From 076980625023d99f8fa20ac32a2b19c6ae0a1ffb Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Fri, 26 Sep 2014 16:17:04 -0700 Subject: [PATCH 024/798] more docs --- include/caffe/layer_factory.hpp | 50 ++++++++++++++++++-- src/caffe/layer_factory.cpp | 84 +++++++++++++++------------------ 2 files changed, 82 insertions(+), 52 deletions(-) diff --git a/include/caffe/layer_factory.hpp b/include/caffe/layer_factory.hpp index 08e3e6d3ad8..a2c4ab56a89 100644 --- a/include/caffe/layer_factory.hpp +++ b/include/caffe/layer_factory.hpp @@ -1,3 +1,41 @@ +// This file defines a layer factory that allows one to register layers. During +// runtime, registered layers could be called by passing a LayerParameter: +// LayerRegistry::CreateLayer(param); +// +// There are two ways to register a layer. Assuming that we have a layer like: +// +// template +// class MyAwesomeLayer : public Layer { +// // your implementations +// }; +// +// and its type is defined in the protobuffer as +// +// enum LayerType { +// // other definitions +// AWESOME = 46, +// } +// +// If the layer is going to be created simply by its constructor, in your c++ +// file, add the following line: +// +// REGISTER_LAYER_CLASS(AWESOME, MyAwesomeLayer); +// +// Or, if the layer is going to be created by another creator function, in the +// format of: +// +// template +// Layer GetMyAwesomeLayer(const LayerParameter& param) { +// // your implementation +// } +// +// (for example, when your layer has multiple backends, see GetConvolutionLayer +// for a use case), then you can register the creator function instead, like +// +// REGISTER_LAYER_CREATOR(AWESOME, GetMyAwesomeLayer) +// +// Note that each layer type should only be registered once. + #ifndef CAFFE_LAYER_FACTORY_H_ #define CAFFE_LAYER_FACTORY_H_ @@ -55,9 +93,11 @@ class LayerRegisterer { }; -#define REGISTER_LAYER_CREATOR(type, creator, classname) \ - static LayerRegisterer g_creator_f_##classname(type, creator); \ - static LayerRegisterer g_creator_d_##classname(type, creator) +#define REGISTER_LAYER_CREATOR(type, creator) \ + static LayerRegisterer g_creator_f_##type( \ + LayerParameter_LayerType_##type, creator); \ + static LayerRegisterer g_creator_d_##type( \ + LayerParameter_LayerType_##type, creator) #define REGISTER_LAYER_CLASS(type, clsname) \ template \ @@ -65,9 +105,9 @@ class LayerRegisterer { return new clsname(param); \ } \ static LayerRegisterer g_creator_f_##clsname( \ - type, Creator_##clsname); \ + LayerParameter_LayerType_##type, Creator_##clsname); \ static LayerRegisterer g_creator_d_##clsname( \ - type, Creator_##clsname) + LayerParameter_LayerType_##type, Creator_##clsname) // A function to get a specific layer from the specification given in // LayerParameter. Ideally this would be replaced by a factory pattern, diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 79a732b965b..b60b3b6fdb7 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -143,53 +143,43 @@ Layer* GetSoftmaxLayer(const LayerParameter& param) { } // Layers that have a specific creator function. -REGISTER_LAYER_CREATOR(LayerParameter_LayerType_CONVOLUTION, - GetConvolutionLayer, ConvolutionLayer); -REGISTER_LAYER_CREATOR(LayerParameter_LayerType_POOLING, - GetPoolingLayer, PoolingLayer); -REGISTER_LAYER_CREATOR(LayerParameter_LayerType_RELU, - GetReLULayer, ReLULayer); -REGISTER_LAYER_CREATOR(LayerParameter_LayerType_SIGMOID, - GetSigmoidLayer, SigmoidLayer); -REGISTER_LAYER_CREATOR(LayerParameter_LayerType_SOFTMAX, - GetSoftmaxLayer, SoftmaxLayer); -REGISTER_LAYER_CREATOR(LayerParameter_LayerType_TANH, - GetTanHLayer, TanHLayer); +REGISTER_LAYER_CREATOR(CONVOLUTION, GetConvolutionLayer); +REGISTER_LAYER_CREATOR(POOLING, GetPoolingLayer); +REGISTER_LAYER_CREATOR(RELU, GetReLULayer); +REGISTER_LAYER_CREATOR(SIGMOID, GetSigmoidLayer); +REGISTER_LAYER_CREATOR(SOFTMAX, GetSoftmaxLayer); +REGISTER_LAYER_CREATOR(TANH, GetTanHLayer); + // Layers that use their constructor as their default creator. -REGISTER_LAYER_CLASS(LayerParameter_LayerType_ACCURACY, AccuracyLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_ABSVAL, AbsValLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_ARGMAX, ArgMaxLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_BNLL, BNLLLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_CONCAT, ConcatLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_CONTRASTIVE_LOSS, - ContrastiveLossLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_DATA, DataLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_DROPOUT, DropoutLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_DUMMY_DATA, DummyDataLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_EUCLIDEAN_LOSS, - EuclideanLossLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_ELTWISE, EltwiseLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_FLATTEN, FlattenLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_HDF5_DATA, HDF5DataLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_HDF5_OUTPUT, HDF5OutputLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_HINGE_LOSS, HingeLossLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_IMAGE_DATA, ImageDataLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_IM2COL, Im2colLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_INFOGAIN_LOSS, InfogainLossLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_INNER_PRODUCT, InnerProductLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_LRN, LRNLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_MEMORY_DATA, MemoryDataLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_MVN, MVNLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS, - MultinomialLogisticLossLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_POWER, PowerLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_SILENCE, SilenceLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS, - SigmoidCrossEntropyLossLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_SLICE, SliceLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_SOFTMAX_LOSS, - SoftmaxWithLossLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_SPLIT, SplitLayer); -REGISTER_LAYER_CLASS(LayerParameter_LayerType_WINDOW_DATA, WindowDataLayer); +REGISTER_LAYER_CLASS(ACCURACY, AccuracyLayer); +REGISTER_LAYER_CLASS(ABSVAL, AbsValLayer); +REGISTER_LAYER_CLASS(ARGMAX, ArgMaxLayer); +REGISTER_LAYER_CLASS(BNLL, BNLLLayer); +REGISTER_LAYER_CLASS(CONCAT, ConcatLayer); +REGISTER_LAYER_CLASS(CONTRASTIVE_LOSS, ContrastiveLossLayer); +REGISTER_LAYER_CLASS(DATA, DataLayer); +REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer); +REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer); +REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer); +REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer); +REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer); +REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer); +REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer); +REGISTER_LAYER_CLASS(HINGE_LOSS, HingeLossLayer); +REGISTER_LAYER_CLASS(IMAGE_DATA, ImageDataLayer); +REGISTER_LAYER_CLASS(IM2COL, Im2colLayer); +REGISTER_LAYER_CLASS(INFOGAIN_LOSS, InfogainLossLayer); +REGISTER_LAYER_CLASS(INNER_PRODUCT, InnerProductLayer); +REGISTER_LAYER_CLASS(LRN, LRNLayer); +REGISTER_LAYER_CLASS(MEMORY_DATA, MemoryDataLayer); +REGISTER_LAYER_CLASS(MVN, MVNLayer); +REGISTER_LAYER_CLASS(MULTINOMIAL_LOGISTIC_LOSS, MultinomialLogisticLossLayer); +REGISTER_LAYER_CLASS(POWER, PowerLayer); +REGISTER_LAYER_CLASS(SILENCE, SilenceLayer); +REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer); +REGISTER_LAYER_CLASS(SLICE, SliceLayer); +REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer); +REGISTER_LAYER_CLASS(SPLIT, SplitLayer); +REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer); } // namespace caffe From 6f15c7a8b6acbc239a9fbf8104d56d9a7301c8f5 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sat, 27 Sep 2014 12:06:10 -0700 Subject: [PATCH 025/798] Pre-lunch fun: add a dynamic library guard test. --- Makefile | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 243650b2ad1..72fca4655b6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,3 @@ -# The makefile for caffe. Pretty hacky. PROJECT := caffe CONFIG_FILE := Makefile.config @@ -17,9 +16,9 @@ else OTHER_BUILD_DIR := $(DEBUG_BUILD_DIR) endif -# The target shared library and static library name +# The target shared library name LIB_BUILD_DIR := $(BUILD_DIR)/lib -NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so +LIBRARY_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so ############################## # Get all source files @@ -127,7 +126,10 @@ TEST_CU_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \ TEST_CXX_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \ $(foreach obj,$(TEST_CXX_OBJS),$(basename $(notdir $(obj)))))) TEST_BINS := $(TEST_CXX_BINS) $(TEST_CU_BINS) +# TEST_ALL_BIN is the test binary that links caffe source objects directly. TEST_ALL_BIN := $(TEST_BIN_DIR)/test_all.testbin +# TEST_ALL_DYNINK_BIN is the test binary that links caffe as a dynamic library. +TEST_ALL_DYNLINK_BIN := $(TEST_BIN_DIR)/test_all_dynamic_link.testbin ############################## # Derive compiler warning dump locations @@ -308,6 +310,8 @@ endif INCLUDE_DIRS += $(BLAS_INCLUDE) LIBRARY_DIRS += $(BLAS_LIB) +LIBRARY_DIRS += $(LIB_BUILD_DIR) + # Complete build flags. COMMON_FLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir)) CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) @@ -337,7 +341,7 @@ SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo py mat py$(PROJECT) mat$(PROJECT) proto runtest \ superclean supercleanlist supercleanfiles warn everything -all: $(NAME) tools examples +all: $(LIBRARY_NAME) tools examples everything: all py$(PROJECT) mat$(PROJECT) test warn lint runtest @@ -376,7 +380,7 @@ $(LINT_OUTPUTS): $(LINT_OUTPUT_DIR)/%.lint.txt : % $(LINT_SCRIPT) | $(LINT_OUTPU > $@ \ || true -test: $(TEST_ALL_BIN) $(TEST_BINS) +test: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN) $(TEST_BINS) tools: $(TOOL_BINS) $(TOOL_BIN_LINKS) @@ -407,8 +411,9 @@ $(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(OBJS) CXXLIBS="\$$CXXLIBS $(OBJS) $(LDFLAGS)" -output $@ @ echo -runtest: $(TEST_ALL_BIN) - $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) +runtest: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN) + $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) && \ + $(TEST_ALL_DYNLINK_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) warn: $(EMPTY_WARN_REPORT) @@ -442,7 +447,7 @@ $(BUILD_DIR)/.linked: $(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK) @ mkdir -p $@ -$(NAME): $(OBJS) | $(LIB_BUILD_DIR) +$(LIBRARY_NAME): $(OBJS) | $(LIB_BUILD_DIR) $(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) @ echo @@ -466,6 +471,13 @@ $(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(OBJS) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo +$(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(LIBRARY_NAME) \ + | $(TEST_BIN_DIR) + $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ + -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(LIB_BUILD_DIR) + @ echo + + $(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(OBJS) \ | $(TEST_BIN_DIR) $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(OBJS) \ @@ -606,6 +618,6 @@ $(DISTRIBUTE_DIR): all py $(HXX_SRCS) | $(DISTRIBUTE_SUBDIRS) cp $(TOOL_BINS) $(DISTRIBUTE_DIR)/bin cp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin # add libraries - cp $(NAME) $(DISTRIBUTE_DIR)/lib + cp $(LIBRARY_NAME) $(DISTRIBUTE_DIR)/lib # add python - it's not the standard way, indeed... cp -r python $(DISTRIBUTE_DIR)/python From f0fdb8cf7432cf11d10f9bfce7e03e45cff9b1cf Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sat, 27 Sep 2014 13:17:33 -0700 Subject: [PATCH 026/798] Add back static library. Using -Wl,--whole-archive will allow us to preserve all symbols. --- Makefile | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 72fca4655b6..ad87e9b4ca2 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,9 @@ endif # The target shared library name LIB_BUILD_DIR := $(BUILD_DIR)/lib -LIBRARY_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so +STATIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).a +DYNAMIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so +STATIC_LINK_COMMAND := -Wl,--whole-archive $(STATIC_NAME) -Wl,--no-whole-archive ############################## # Get all source files @@ -126,7 +128,7 @@ TEST_CU_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \ TEST_CXX_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \ $(foreach obj,$(TEST_CXX_OBJS),$(basename $(notdir $(obj)))))) TEST_BINS := $(TEST_CXX_BINS) $(TEST_CU_BINS) -# TEST_ALL_BIN is the test binary that links caffe source objects directly. +# TEST_ALL_BIN is the test binary that links caffe statically. TEST_ALL_BIN := $(TEST_BIN_DIR)/test_all.testbin # TEST_ALL_DYNINK_BIN is the test binary that links caffe as a dynamic library. TEST_ALL_DYNLINK_BIN := $(TEST_BIN_DIR)/test_all_dynamic_link.testbin @@ -341,7 +343,7 @@ SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo py mat py$(PROJECT) mat$(PROJECT) proto runtest \ superclean supercleanlist supercleanfiles warn everything -all: $(LIBRARY_NAME) tools examples +all: $(STATIC_NAME) $(DYNAMIC_NAME) tools examples everything: all py$(PROJECT) mat$(PROJECT) test warn lint runtest @@ -390,16 +392,16 @@ py$(PROJECT): py py: $(PY$(PROJECT)_SO) $(PROTO_GEN_PY) -$(PY$(PROJECT)_SO): $(OBJS) $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX_SRC) +$(PY$(PROJECT)_SO): $(STATIC_NAME) $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX_SRC) $(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \ - $(OBJS) $(LINKFLAGS) $(PYTHON_LDFLAGS) + $(STATIC_LINK_COMMAND) $(LINKFLAGS) $(PYTHON_LDFLAGS) @ echo mat$(PROJECT): mat mat: $(MAT$(PROJECT)_SO) -$(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(OBJS) +$(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME) @ if [ -z "$(MATLAB_DIR)" ]; then \ echo "MATLAB_DIR must be specified in $(CONFIG_FILE)" \ "to build mat$(PROJECT)."; \ @@ -408,7 +410,7 @@ $(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(OBJS) $(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_SRC) \ CXX="$(CXX)" \ CXXFLAGS="\$$CXXFLAGS $(MATLAB_CXXFLAGS)" \ - CXXLIBS="\$$CXXLIBS $(OBJS) $(LDFLAGS)" -output $@ + CXXLIBS="\$$CXXLIBS $(STATIC_LINK_COMMAND) $(LDFLAGS)" -output $@ @ echo runtest: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN) @@ -447,10 +449,14 @@ $(BUILD_DIR)/.linked: $(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK) @ mkdir -p $@ -$(LIBRARY_NAME): $(OBJS) | $(LIB_BUILD_DIR) +$(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) $(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) @ echo +$(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) + ar rcs $@ $(OBJS) + @ echo + $(TEST_BUILD_DIR)/%.o: src/$(PROJECT)/test/%.cpp $(HXX_SRCS) $(TEST_HXX_SRCS) \ | $(TEST_BUILD_DIR) $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ @@ -465,28 +471,28 @@ $(TEST_BUILD_DIR)/%.cuo: src/$(PROJECT)/test/%.cu $(HXX_SRCS) $(TEST_HXX_SRCS) \ @ cat $@.$(WARNS_EXT) @ echo -$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(OBJS) \ +$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \ | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(OBJS) \ + $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo -$(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(LIBRARY_NAME) \ +$(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(DYNAMIC_NAME) \ | $(TEST_BIN_DIR) $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(LIB_BUILD_DIR) @ echo -$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(OBJS) \ +$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(STATIC_NAME) \ | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(OBJS) \ + $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo -$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.o $(GTEST_OBJ) $(OBJS) \ +$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.o $(GTEST_OBJ) $(STATIC_NAME) \ | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(OBJS) \ + $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo @@ -495,12 +501,12 @@ $(TOOL_BUILD_DIR)/%: $(TOOL_BUILD_DIR)/%.bin | $(TOOL_BUILD_DIR) @ $(RM) $@ @ ln -s $(abspath $<) $@ -$(TOOL_BINS): %.bin : %.o $(OBJS) - $(CXX) $< $(OBJS) -o $@ $(LINKFLAGS) $(LDFLAGS) +$(TOOL_BINS): %.bin : %.o $(STATIC_NAME) + $(CXX) $< $(STATIC_LINK_COMMAND) -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo -$(EXAMPLE_BINS): %.bin : %.o $(OBJS) - $(CXX) $< $(OBJS) -o $@ $(LINKFLAGS) $(LDFLAGS) +$(EXAMPLE_BINS): %.bin : %.o $(STATIC_NAME) + $(CXX) $< $(STATIC_LINK_COMMAND) -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo $(LAYER_BUILD_DIR)/%.o: src/$(PROJECT)/layers/%.cpp $(HXX_SRCS) \ @@ -618,6 +624,7 @@ $(DISTRIBUTE_DIR): all py $(HXX_SRCS) | $(DISTRIBUTE_SUBDIRS) cp $(TOOL_BINS) $(DISTRIBUTE_DIR)/bin cp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin # add libraries - cp $(LIBRARY_NAME) $(DISTRIBUTE_DIR)/lib + cp $(STATIC_NAME) $(DISTRIBUTE_DIR)/lib + cp $(DYNAMIC_NAME) $(DISTRIBUTE_DIR)/lib # add python - it's not the standard way, indeed... cp -r python $(DISTRIBUTE_DIR)/python From 319a95f06a469de1c6bf4ebcd4cf5ff17c6126fc Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sat, 27 Sep 2014 13:18:27 -0700 Subject: [PATCH 027/798] Mute factory registration message --- include/caffe/layer_factory.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/caffe/layer_factory.hpp b/include/caffe/layer_factory.hpp index a2c4ab56a89..24b427643d5 100644 --- a/include/caffe/layer_factory.hpp +++ b/include/caffe/layer_factory.hpp @@ -87,7 +87,7 @@ class LayerRegisterer { public: LayerRegisterer(const LayerParameter_LayerType& type, Layer* (*creator)(const LayerParameter&)) { - LOG(INFO) << "Registering layer type: " << type; + // LOG(INFO) << "Registering layer type: " << type; LayerRegistry::AddCreator(type, creator); } }; @@ -105,7 +105,7 @@ class LayerRegisterer { return new clsname(param); \ } \ static LayerRegisterer g_creator_f_##clsname( \ - LayerParameter_LayerType_##type, Creator_##clsname); \ + LayerParameter_LayerType_##type, Creator_##clsname); \ static LayerRegisterer g_creator_d_##clsname( \ LayerParameter_LayerType_##type, Creator_##clsname) From c9fb1f4a0ae92593b4e82983285921037f1db823 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sun, 28 Sep 2014 00:11:05 -0700 Subject: [PATCH 028/798] cmake. --- python/CMakeLists.txt | 3 ++- src/caffe/test/CMakeLists.txt | 10 ++++++---- tools/CMakeLists.txt | 4 +++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 8642c39367a..5024dbfea5d 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -10,6 +10,7 @@ include_directories(${Boost_INCLUDE_DIRS}) file(GLOB_RECURSE Python_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +set(CAFFE_WHOLE_LINK -Wl,--whole-archive caffe -Wl,--no-whole-archive) add_library(pycaffe SHARED ${Python_SOURCES}) target_link_libraries(pycaffe caffe ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}) @@ -17,4 +18,4 @@ target_link_libraries(pycaffe caffe ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}) install(DIRECTORY caffe DESTINATION python) install(FILES requirements.txt DESTINATION python) -install(TARGETS pycaffe DESTINATION python/caffe) \ No newline at end of file +install(TARGETS pycaffe DESTINATION python/caffe) diff --git a/src/caffe/test/CMakeLists.txt b/src/caffe/test/CMakeLists.txt index 20a1d084d6a..7b308bff168 100644 --- a/src/caffe/test/CMakeLists.txt +++ b/src/caffe/test/CMakeLists.txt @@ -47,7 +47,9 @@ include_directories( # Remove main from test sources and prepare an Object lib with main file(GLOB TEST_MAIN ${TEST_MAIN}) list(REMOVE_ITEM TEST_CPP_SOURCES ${TEST_MAIN}) -add_library(main_obj EXCLUDE_FROM_ALL OBJECT ${TEST_MAIN} ../common.cpp) +add_library(main_obj EXCLUDE_FROM_ALL OBJECT ${TEST_MAIN}) + +set(CAFFE_WHOLE_LINK -Wl,--whole-archive caffe -Wl,--no-whole-archive) # Build each test separately from *.cpp files foreach(source ${TEST_CPP_SOURCES}) @@ -58,7 +60,7 @@ foreach(source ${TEST_CPP_SOURCES}) set(TEST_OBJ_LIB $) add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_OBJ_LIB} $) - target_link_libraries(${TEST_NAME} gtest caffe) + target_link_libraries(${TEST_NAME} gtest ${CAFFE_WHOLE_LINK}) # output dir set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) @@ -75,7 +77,7 @@ foreach(source ${TEST_CU_SOURCES}) cuda_add_library(${TEST_NAME}.lib EXCLUDE_FROM_ALL ${source}) add_executable(${TEST_NAME} EXCLUDE_FROM_ALL $) - target_link_libraries(${TEST_NAME} ${TEST_NAME}.lib gtest caffe) + target_link_libraries(${TEST_NAME} ${TEST_NAME}.lib gtest ${CAFFE_WHOLE_LINK}) # output dir set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) @@ -90,7 +92,7 @@ add_executable(${ALL_TEST} EXCLUDE_FROM_ALL ${TEST_OBJ_LIBS} $ Date: Sun, 28 Sep 2014 15:46:03 -0700 Subject: [PATCH 029/798] consolidate duplicate code --- include/caffe/layer_factory.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/caffe/layer_factory.hpp b/include/caffe/layer_factory.hpp index 24b427643d5..5f44d97ca27 100644 --- a/include/caffe/layer_factory.hpp +++ b/include/caffe/layer_factory.hpp @@ -104,10 +104,7 @@ class LayerRegisterer { Layer* Creator_##clsname(const LayerParameter& param) { \ return new clsname(param); \ } \ - static LayerRegisterer g_creator_f_##clsname( \ - LayerParameter_LayerType_##type, Creator_##clsname); \ - static LayerRegisterer g_creator_d_##clsname( \ - LayerParameter_LayerType_##type, Creator_##clsname) + REGISTER_LAYER_CREATOR(type, Creator_##clsname) // A function to get a specific layer from the specification given in // LayerParameter. Ideally this would be replaced by a factory pattern, From 1dacdd819544bd491a1c7e00349ea1acae5bc66c Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sun, 28 Sep 2014 16:04:53 -0700 Subject: [PATCH 030/798] add long-ignored threshold layer --- src/caffe/layer_factory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index b60b3b6fdb7..d0bbd3f27d4 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -180,6 +180,7 @@ REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer); REGISTER_LAYER_CLASS(SLICE, SliceLayer); REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer); REGISTER_LAYER_CLASS(SPLIT, SplitLayer); +REGISTER_LAYER_CLASS(THRESHOLD, ThresholdLayer); REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer); } // namespace caffe From 57a7ae1d539ffdbf30ca13f6ab0d4214f8f2aa2d Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sun, 28 Sep 2014 18:11:35 -0700 Subject: [PATCH 031/798] add explicit declaration - does that help the flakyness? --- src/caffe/layer_factory.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index d0bbd3f27d4..f37d10511ee 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -7,6 +7,11 @@ namespace caffe { +template <> +LayerRegistry::CreatorRegistry LayerRegistry::registry_; +template <> +LayerRegistry::CreatorRegistry LayerRegistry::registry_; + // GetLayer() defines the overall layer factory. The Get*Layer() functions // define factories for layers with multiple computational engines. From 4d54cade5a6d7aca4e98eeb20984aa9925509a76 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sun, 28 Sep 2014 19:16:01 -0700 Subject: [PATCH 032/798] static initialization order fiasco --- include/caffe/layer_factory.hpp | 19 +++++++++++-------- src/caffe/layer_factory.cpp | 5 ----- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/caffe/layer_factory.hpp b/include/caffe/layer_factory.hpp index 5f44d97ca27..dd896453f41 100644 --- a/include/caffe/layer_factory.hpp +++ b/include/caffe/layer_factory.hpp @@ -55,32 +55,35 @@ class LayerRegistry { typedef Layer* (*Creator)(const LayerParameter&); typedef std::map CreatorRegistry; + static CreatorRegistry& Registry() { + static CreatorRegistry* g_registry_ = new CreatorRegistry(); + return *g_registry_; + } + // Adds a creator. static void AddCreator(const LayerParameter_LayerType& type, Creator creator) { - CHECK_EQ(registry_.count(type), 0) + CreatorRegistry& registry = Registry(); + CHECK_EQ(registry.count(type), 0) << "Layer type " << type << " already registered."; - registry_[type] = creator; + registry[type] = creator; } // Get a layer using a LayerParameter. static Layer* CreateLayer(const LayerParameter& param) { LOG(INFO) << "Creating layer " << param.name(); const LayerParameter_LayerType& type = param.type(); - CHECK_EQ(registry_.count(type), 1); - return registry_[type](param); + CreatorRegistry& registry = Registry(); + CHECK_EQ(registry.count(type), 1); + return registry[type](param); } private: // Layer registry should never be instantiated - everything is done with its // static variables. LayerRegistry() {} - static CreatorRegistry registry_; }; -// Static variables for the templated layer factory registry. -template -typename LayerRegistry::CreatorRegistry LayerRegistry::registry_; template class LayerRegisterer { diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index f37d10511ee..d0bbd3f27d4 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -7,11 +7,6 @@ namespace caffe { -template <> -LayerRegistry::CreatorRegistry LayerRegistry::registry_; -template <> -LayerRegistry::CreatorRegistry LayerRegistry::registry_; - // GetLayer() defines the overall layer factory. The Get*Layer() functions // define factories for layers with multiple computational engines. From c68f9ce858c98e94dc0aa18f07bb838af18192a0 Mon Sep 17 00:00:00 2001 From: Sergey Karayev Date: Mon, 29 Sep 2014 02:55:22 -0700 Subject: [PATCH 033/798] [examples] adding class names and deploy version of Flickr Style net --- .../finetune_flickr_style/style_names.txt | 20 ++ models/finetune_flickr_style/deploy.prototxt | 310 ++++++++++++++++++ 2 files changed, 330 insertions(+) create mode 100644 examples/finetune_flickr_style/style_names.txt create mode 100644 models/finetune_flickr_style/deploy.prototxt diff --git a/examples/finetune_flickr_style/style_names.txt b/examples/finetune_flickr_style/style_names.txt new file mode 100644 index 00000000000..73090c97821 --- /dev/null +++ b/examples/finetune_flickr_style/style_names.txt @@ -0,0 +1,20 @@ +Detailed +Pastel +Melancholy +Noir +HDR +Vintage +Long Exposure +Horror +Sunny +Bright +Hazy +Bokeh +Serene +Texture +Ethereal +Macro +Depth of Field +Geometric Composition +Minimal +Romantic diff --git a/models/finetune_flickr_style/deploy.prototxt b/models/finetune_flickr_style/deploy.prototxt new file mode 100644 index 00000000000..aa2ad961874 --- /dev/null +++ b/models/finetune_flickr_style/deploy.prototxt @@ -0,0 +1,310 @@ +name: "FlickrStyleCaffeNet" +input: "data" +input_dim: 10 +input_dim: 3 +input_dim: 227 +input_dim: 227 +layers { + name: "conv1" + type: CONVOLUTION + bottom: "data" + top: "conv1" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 11 + stride: 4 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + name: "relu1" + type: RELU + bottom: "conv1" + top: "conv1" +} +layers { + name: "pool1" + type: POOLING + bottom: "conv1" + top: "pool1" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm1" + type: LRN + bottom: "pool1" + top: "norm1" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv2" + type: CONVOLUTION + bottom: "norm1" + top: "conv2" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 2 + kernel_size: 5 + group: 2 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu2" + type: RELU + bottom: "conv2" + top: "conv2" +} +layers { + name: "pool2" + type: POOLING + bottom: "conv2" + top: "pool2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm2" + type: LRN + bottom: "pool2" + top: "norm2" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv3" + type: CONVOLUTION + bottom: "norm2" + top: "conv3" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + name: "relu3" + type: RELU + bottom: "conv3" + top: "conv3" +} +layers { + name: "conv4" + type: CONVOLUTION + bottom: "conv3" + top: "conv4" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + group: 2 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu4" + type: RELU + bottom: "conv4" + top: "conv4" +} +layers { + name: "conv5" + type: CONVOLUTION + bottom: "conv4" + top: "conv5" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + group: 2 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu5" + type: RELU + bottom: "conv5" + top: "conv5" +} +layers { + name: "pool5" + type: POOLING + bottom: "conv5" + top: "pool5" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "fc6" + type: INNER_PRODUCT + bottom: "pool5" + top: "fc6" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 4096 + weight_filler { + type: "gaussian" + std: 0.005 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu6" + type: RELU + bottom: "fc6" + top: "fc6" +} +layers { + name: "drop6" + type: DROPOUT + bottom: "fc6" + top: "fc6" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc7" + type: INNER_PRODUCT + bottom: "fc6" + top: "fc7" + # Note that blobs_lr can be set to 0 to disable any fine-tuning of this, and any other, layer + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 4096 + weight_filler { + type: "gaussian" + std: 0.005 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu7" + type: RELU + bottom: "fc7" + top: "fc7" +} +layers { + name: "drop7" + type: DROPOUT + bottom: "fc7" + top: "fc7" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc8_flickr" + type: INNER_PRODUCT + bottom: "fc7" + top: "fc8_flickr" + # blobs_lr is set to higher than for other layers, because this layer is starting from random while the others are already trained + blobs_lr: 10 + blobs_lr: 20 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 20 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + name: "prob" + type: SOFTMAX + bottom: "fc8_flickr" + top: "prob" +} From db67d52dcc3567ce636e472fa4554ce43878c84c Mon Sep 17 00:00:00 2001 From: Dmytro Mishkin Date: Mon, 29 Sep 2014 16:10:04 +0300 Subject: [PATCH 034/798] Changed linking order: -pthread -> back. Otherwise error: /usr/bin/ld: /usr/local/lib/libgflags.a(gflags.cc.o): undefined reference to symbol 'pthread_rwlock_wrlock@@GLIBC_2.2.5' /lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status --- Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 5020b4109d6..929f8d5cea6 100644 --- a/Makefile +++ b/Makefile @@ -165,12 +165,11 @@ ifneq ($(CPU_ONLY), 1) LIBRARY_DIRS += $(CUDA_LIB_DIR) LIBRARIES := cudart cublas curand endif -LIBRARIES += pthread \ - glog gflags protobuf leveldb snappy \ +LIBRARIES += glog gflags protobuf leveldb snappy \ lmdb \ boost_system \ hdf5_hl hdf5 \ - opencv_core opencv_highgui opencv_imgproc + opencv_core opencv_highgui opencv_imgproc pthread PYTHON_LIBRARIES := boost_python python2.7 WARNINGS := -Wall -Wno-sign-compare From f13461801c8912bf2029367554d229f77020bef7 Mon Sep 17 00:00:00 2001 From: Alireza Shafaei Date: Mon, 29 Sep 2014 20:24:00 -0700 Subject: [PATCH 035/798] Fixed some errors in layer_factory and cudnn_pooling --- src/caffe/layer_factory.cpp | 2 +- src/caffe/layers/cudnn_pooling_layer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 566162911ef..539ef84d03e 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -55,7 +55,7 @@ PoolingLayer* GetPoolingLayer(const string& name, if (p_param.pad_h() || p_param.pad_w() || param.top_size() > 1) { LOG(INFO) << "CUDNN does not support padding or multiple tops. " << "Using Caffe's own pooling layer."; - return new PoolingLayer(param); + return new PoolingLayer(param); } return new CuDNNPoolingLayer(param); #endif diff --git a/src/caffe/layers/cudnn_pooling_layer.cpp b/src/caffe/layers/cudnn_pooling_layer.cpp index b61ed2a7ede..4d7573c7f12 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cpp +++ b/src/caffe/layers/cudnn_pooling_layer.cpp @@ -14,8 +14,8 @@ void CuDNNPoolingLayer::LayerSetUp(const vector*>& bottom, const vector*>& top) { PoolingLayer::LayerSetUp(bottom, top); // Sanity check: CUDNN currently only supports pad=0 and top.size()=1 cases. - CHECK_EQ(pad_h_, 0); - CHECK_EQ(pad_w_, 0); + CHECK_EQ(this->pad_h_, 0); + CHECK_EQ(this->pad_w_, 0); CHECK_EQ(top.size(), 1); CUDNN_CHECK(cudnnCreate(&handle_)); cudnn::createTensor4dDesc(&bottom_desc_); From c5e404dc2988532906b08eb90b226be91b778ac0 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 29 Sep 2014 21:20:37 -0700 Subject: [PATCH 036/798] use method overrides for CuDNNPoolingLayer top blob checking --- include/caffe/vision_layers.hpp | 3 +++ src/caffe/layers/cudnn_pooling_layer.cpp | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index a3c8bc0a31f..58ac5344da4 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -338,6 +338,9 @@ class CuDNNPoolingLayer : public PoolingLayer { virtual void Reshape(const vector*>& bottom, const vector*>& top); virtual ~CuDNNPoolingLayer(); + // Currently, cuDNN does not support the extra top blob. + virtual inline int MinTopBlobs() const { return -1; } + virtual inline int ExactNumTopBlobs() const { return 1; } protected: virtual void Forward_gpu(const vector*>& bottom, diff --git a/src/caffe/layers/cudnn_pooling_layer.cpp b/src/caffe/layers/cudnn_pooling_layer.cpp index 4d7573c7f12..fc0222ac0e3 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cpp +++ b/src/caffe/layers/cudnn_pooling_layer.cpp @@ -13,10 +13,9 @@ template void CuDNNPoolingLayer::LayerSetUp(const vector*>& bottom, const vector*>& top) { PoolingLayer::LayerSetUp(bottom, top); - // Sanity check: CUDNN currently only supports pad=0 and top.size()=1 cases. + // Sanity check: CUDNN currently only supports pad == 0. CHECK_EQ(this->pad_h_, 0); CHECK_EQ(this->pad_w_, 0); - CHECK_EQ(top.size(), 1); CUDNN_CHECK(cudnnCreate(&handle_)); cudnn::createTensor4dDesc(&bottom_desc_); cudnn::createTensor4dDesc(&top_desc_); From 618b92934b4d1449c10b6611c87d56be9a4d75d2 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 29 Sep 2014 21:21:03 -0700 Subject: [PATCH 037/798] cuDNN pooling layer tests know that nonzero padding is not supported After #1172, some cuDNN pooling layer tests were failing due to use of padding. (Before #1172, these tests were actually testing PoolingLayer instead of CuDNNPoolingLayer via the fallback.) This commit disables many tests via commenting, so that they can be easily readded when cuDNN gains pooling padding support. --- src/caffe/test/test_pooling_layer.cpp | 35 +++++++++++++++++---------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/caffe/test/test_pooling_layer.cpp b/src/caffe/test/test_pooling_layer.cpp index e2980331dc0..f52073c4e6f 100644 --- a/src/caffe/test/test_pooling_layer.cpp +++ b/src/caffe/test/test_pooling_layer.cpp @@ -962,6 +962,9 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestSetupCuDNN) { EXPECT_EQ(this->blob_top_->width(), 2); } +// This test and all following cuDNN pooling tests with padding are commented +// for now, since cuDNN pooling does not currently support padding. +/* TYPED_TEST(CuDNNPoolingLayerTest, TestSetupPaddedCuDNN) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; @@ -977,6 +980,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestSetupPaddedCuDNN) { EXPECT_EQ(this->blob_top_->height(), 4); EXPECT_EQ(this->blob_top_->width(), 3); } +*/ /* TYPED_TEST(CuDNNPoolingLayerTest, PrintBackwardCuDNN) { @@ -1012,6 +1016,9 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestForwardMaxCuDNN) { this->TestForwardRectWide(); } +// Currently, cuDNN does not support a top mask, so we comment this and +// the corresponding backward test. +/* TYPED_TEST(CuDNNPoolingLayerTest, TestForwardMaxTopMaskCuDNN) { Caffe::set_mode(Caffe::GPU); this->blob_top_vec_.push_back(this->blob_top_mask_); @@ -1019,6 +1026,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestForwardMaxTopMaskCuDNN) { this->TestForwardRectHigh(); this->TestForwardRectWide(); } +*/ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientMaxCuDNN) { Caffe::set_mode(Caffe::GPU); @@ -1029,7 +1037,8 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientMaxCuDNN) { pooling_param->set_kernel_h(kernel_h); pooling_param->set_kernel_w(kernel_w); pooling_param->set_stride(2); - pooling_param->set_pad(1); + // currenty, cuDNN pooling does not support padding + pooling_param->set_pad(0); pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); CuDNNPoolingLayer layer(layer_param); GradientChecker checker(1e-4, 1e-2); @@ -1039,6 +1048,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientMaxCuDNN) { } } +/* TYPED_TEST(CuDNNPoolingLayerTest, TestForwardMaxPaddedCuDNN) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; @@ -1083,7 +1093,9 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestForwardMaxPaddedCuDNN) { EXPECT_NEAR(this->blob_top_->cpu_data()[7], 4, epsilon); EXPECT_NEAR(this->blob_top_->cpu_data()[8], 1, epsilon); } +*/ +/* TYPED_TEST(CuDNNPoolingLayerTest, TestGradientMaxTopMaskCuDNN) { Caffe::set_mode(Caffe::GPU); for (int kernel_h = 3; kernel_h <= 4; kernel_h++) { @@ -1103,6 +1115,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientMaxTopMaskCuDNN) { } } } +*/ TYPED_TEST(CuDNNPoolingLayerTest, TestForwardAveCuDNN) { Caffe::set_mode(Caffe::GPU); @@ -1110,7 +1123,9 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestForwardAveCuDNN) { PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); pooling_param->set_kernel_size(3); pooling_param->set_stride(1); - pooling_param->set_pad(1); + // Currently, cuDNN pooling does not support padding, so we use + // a simplified version of this test. + pooling_param->set_pad(0); pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); this->blob_bottom_->Reshape(1, 1, 3, 3); FillerParameter filler_param; @@ -1121,19 +1136,11 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestForwardAveCuDNN) { layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); EXPECT_EQ(this->blob_top_->num(), 1); EXPECT_EQ(this->blob_top_->channels(), 1); - EXPECT_EQ(this->blob_top_->height(), 3); - EXPECT_EQ(this->blob_top_->width(), 3); + EXPECT_EQ(this->blob_top_->height(), 1); + EXPECT_EQ(this->blob_top_->width(), 1); layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); TypeParam epsilon = 1e-5; - EXPECT_NEAR(this->blob_top_->cpu_data()[0], 8.0 / 9, epsilon); - EXPECT_NEAR(this->blob_top_->cpu_data()[1], 4.0 / 3, epsilon); - EXPECT_NEAR(this->blob_top_->cpu_data()[2], 8.0 / 9, epsilon); - EXPECT_NEAR(this->blob_top_->cpu_data()[3], 4.0 / 3, epsilon); - EXPECT_NEAR(this->blob_top_->cpu_data()[4], 2.0 , epsilon); - EXPECT_NEAR(this->blob_top_->cpu_data()[5], 4.0 / 3, epsilon); - EXPECT_NEAR(this->blob_top_->cpu_data()[6], 8.0 / 9, epsilon); - EXPECT_NEAR(this->blob_top_->cpu_data()[7], 4.0 / 3, epsilon); - EXPECT_NEAR(this->blob_top_->cpu_data()[8], 8.0 / 9, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[0], 2.0, epsilon); } TYPED_TEST(CuDNNPoolingLayerTest, TestGradientAveCuDNN) { @@ -1154,6 +1161,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientAveCuDNN) { } } +/* TYPED_TEST(CuDNNPoolingLayerTest, TestGradientAvePaddedCuDNN) { Caffe::set_mode(Caffe::GPU); for (int kernel_h = 3; kernel_h <= 4; kernel_h++) { @@ -1172,6 +1180,7 @@ TYPED_TEST(CuDNNPoolingLayerTest, TestGradientAvePaddedCuDNN) { } } } +*/ #endif From b2c26469703741007a4953a778a0b92a0d3dee57 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Tue, 30 Sep 2014 10:20:36 -0700 Subject: [PATCH 038/798] doxygen --- include/caffe/layer_factory.hpp | 78 +++++++++++++++++---------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/include/caffe/layer_factory.hpp b/include/caffe/layer_factory.hpp index dd896453f41..b86d53346d9 100644 --- a/include/caffe/layer_factory.hpp +++ b/include/caffe/layer_factory.hpp @@ -1,40 +1,44 @@ -// This file defines a layer factory that allows one to register layers. During -// runtime, registered layers could be called by passing a LayerParameter: -// LayerRegistry::CreateLayer(param); -// -// There are two ways to register a layer. Assuming that we have a layer like: -// -// template -// class MyAwesomeLayer : public Layer { -// // your implementations -// }; -// -// and its type is defined in the protobuffer as -// -// enum LayerType { -// // other definitions -// AWESOME = 46, -// } -// -// If the layer is going to be created simply by its constructor, in your c++ -// file, add the following line: -// -// REGISTER_LAYER_CLASS(AWESOME, MyAwesomeLayer); -// -// Or, if the layer is going to be created by another creator function, in the -// format of: -// -// template -// Layer GetMyAwesomeLayer(const LayerParameter& param) { -// // your implementation -// } -// -// (for example, when your layer has multiple backends, see GetConvolutionLayer -// for a use case), then you can register the creator function instead, like -// -// REGISTER_LAYER_CREATOR(AWESOME, GetMyAwesomeLayer) -// -// Note that each layer type should only be registered once. +/** + * @brief A layer factory that allows one to register layers. + * During runtime, registered layers could be called by passing a LayerParameter + * protobuffer to the CreateLayer function: + * + * LayerRegistry::CreateLayer(param); + * + * There are two ways to register a layer. Assuming that we have a layer like: + * + * template + * class MyAwesomeLayer : public Layer { + * // your implementations + * }; + * + * and its type is defined in the protobuffer as + * + * enum LayerType { + * // other definitions + * AWESOME = 46, + * } + * + * If the layer is going to be created simply by its constructor, in your c++ + * file, add the following line: + * + * REGISTER_LAYER_CLASS(AWESOME, MyAwesomeLayer); + * + * Or, if the layer is going to be created by another creator function, in the + * format of: + * + * template + * Layer GetMyAwesomeLayer(const LayerParameter& param) { + * // your implementation + * } + * + * (for example, when your layer has multiple backends, see GetConvolutionLayer + * for a use case), then you can register the creator function instead, like + * + * REGISTER_LAYER_CREATOR(AWESOME, GetMyAwesomeLayer) + * + * Note that each layer type should only be registered once. + */ #ifndef CAFFE_LAYER_FACTORY_H_ #define CAFFE_LAYER_FACTORY_H_ From 10ee219999f53ba0bfc304daf2222c2090481b02 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 30 Sep 2014 11:00:37 -0700 Subject: [PATCH 039/798] test_gradient_based_solver.cpp: removed unused typedefs --- src/caffe/test/test_gradient_based_solver.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/caffe/test/test_gradient_based_solver.cpp b/src/caffe/test/test_gradient_based_solver.cpp index 3040eb134a4..65de52aae4a 100644 --- a/src/caffe/test/test_gradient_based_solver.cpp +++ b/src/caffe/test/test_gradient_based_solver.cpp @@ -323,7 +323,6 @@ class SGDSolverTest : public GradientBasedSolverTest { TYPED_TEST_CASE(SGDSolverTest, TestDtypesAndDevices); TYPED_TEST(SGDSolverTest, TestLeastSquaresUpdate) { - typedef typename TypeParam::Dtype Dtype; this->TestLeastSquaresUpdate(); } @@ -390,7 +389,6 @@ class AdaGradSolverTest : public GradientBasedSolverTest { TYPED_TEST_CASE(AdaGradSolverTest, TestDtypesAndDevices); TYPED_TEST(AdaGradSolverTest, TestAdaGradLeastSquaresUpdate) { - typedef typename TypeParam::Dtype Dtype; this->TestLeastSquaresUpdate(); } @@ -435,7 +433,6 @@ class NesterovSolverTest : public GradientBasedSolverTest { TYPED_TEST_CASE(NesterovSolverTest, TestDtypesAndDevices); TYPED_TEST(NesterovSolverTest, TestNesterovLeastSquaresUpdate) { - typedef typename TypeParam::Dtype Dtype; this->TestLeastSquaresUpdate(); } From a7bce254c32a25f2b1260afb62493dbb4f96dc46 Mon Sep 17 00:00:00 2001 From: Chiyuan Zhang Date: Fri, 26 Sep 2014 11:21:59 -0400 Subject: [PATCH 040/798] make HDF5 layer support multiple data output --- include/caffe/data_layers.hpp | 8 +--- src/caffe/layers/hdf5_data_layer.cpp | 55 ++++++++++++++------------ src/caffe/layers/hdf5_data_layer.cu | 19 ++++----- src/caffe/test/test_hdf5data_layer.cpp | 3 ++ 4 files changed, 41 insertions(+), 44 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index b3f93cea19e..c1720b7f8ad 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -20,9 +20,6 @@ namespace caffe { -#define HDF5_DATA_DATASET_NAME "data" -#define HDF5_DATA_LABEL_NAME "label" - /** * @brief Provides base for data layers that feed blobs to the Net. * @@ -180,7 +177,7 @@ class HDF5DataLayer : public Layer { return LayerParameter_LayerType_HDF5_DATA; } virtual inline int ExactNumBottomBlobs() const { return 0; } - virtual inline int ExactNumTopBlobs() const { return 2; } + virtual inline int MinTopBlobs() const { return 1; } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -197,8 +194,7 @@ class HDF5DataLayer : public Layer { unsigned int num_files_; unsigned int current_file_; hsize_t current_row_; - Blob data_blob_; - Blob label_blob_; + std::vector > > hdf_blobs_; }; /** diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index 8fec61789e9..bf771fd093a 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -33,20 +33,27 @@ void HDF5DataLayer::LoadHDF5FileData(const char* filename) { return; } - const int MIN_DATA_DIM = 2; + int top_size = this->layer_param_.top_size(); + hdf_blobs_.resize(top_size); + + const int MIN_DATA_DIM = 1; const int MAX_DATA_DIM = 4; - hdf5_load_nd_dataset( - file_id, "data", MIN_DATA_DIM, MAX_DATA_DIM, &data_blob_); - const int MIN_LABEL_DIM = 1; - const int MAX_LABEL_DIM = 2; - hdf5_load_nd_dataset( - file_id, "label", MIN_LABEL_DIM, MAX_LABEL_DIM, &label_blob_); + for (int i = 0; i < top_size; ++i) { + hdf_blobs_[i] = shared_ptr >(new Blob()); + hdf5_load_nd_dataset(file_id, this->layer_param_.top(i).c_str(), + MIN_DATA_DIM, MAX_DATA_DIM, hdf_blobs_[i].get()); + } herr_t status = H5Fclose(file_id); CHECK_GE(status, 0) << "Failed to close HDF5 file " << filename; - CHECK_EQ(data_blob_.num(), label_blob_.num()); - LOG(INFO) << "Successully loaded " << data_blob_.num() << " rows"; + + // MinTopBlobs==1 guarantees at least one top blob + int num = hdf_blobs_[0]->num(); + for (int i = 1; i < top_size; ++i) { + CHECK_EQ(hdf_blobs_[i]->num(), num); + } + LOG(INFO) << "Successully loaded " << hdf_blobs_[0]->num() << " rows"; } template @@ -74,26 +81,21 @@ void HDF5DataLayer::LayerSetUp(const vector*>& bottom, // Reshape blobs. const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); - top[0]->Reshape(batch_size, data_blob_.channels(), - data_blob_.height(), data_blob_.width()); - top[1]->Reshape(batch_size, label_blob_.channels(), - label_blob_.height(), label_blob_.width()); - LOG(INFO) << "output data size: " << top[0]->num() << "," - << top[0]->channels() << "," << top[0]->height() << "," - << top[0]->width(); + const int top_size = this->layer_param_.top_size(); + for (int i = 0; i < top_size; ++i) { + top[i]->Reshape(batch_size, hdf_blobs_[i]->channels(), + hdf_blobs_[i]->height(), hdf_blobs_[i]->width()); + } } template void HDF5DataLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); - const int data_count = top[0]->count() / top[0]->num(); - const int label_data_count = top[1]->count() / top[1]->num(); - for (int i = 0; i < batch_size; ++i, ++current_row_) { - if (current_row_ == data_blob_.num()) { + if (current_row_ == hdf_blobs_[0]->num()) { if (num_files_ > 1) { - current_file_ += 1; + ++current_file_; if (current_file_ == num_files_) { current_file_ = 0; LOG(INFO) << "looping around to first file"; @@ -102,11 +104,12 @@ void HDF5DataLayer::Forward_cpu(const vector*>& bottom, } current_row_ = 0; } - caffe_copy(data_count, &data_blob_.cpu_data()[current_row_ * data_count], - &top[0]->mutable_cpu_data()[i * data_count]); - caffe_copy(label_data_count, - &label_blob_.cpu_data()[current_row_ * label_data_count], - &top[1]->mutable_cpu_data()[i * label_data_count]); + for (int j = 0; j < this->layer_param_.top_size(); ++j) { + int data_dim = top[j]->count() / top[j]->num(); + caffe_copy(data_dim, + &hdf_blobs_[j]->cpu_data()[current_row_ * data_dim], + &top[j]->mutable_cpu_data()[i * data_dim]); + } } } diff --git a/src/caffe/layers/hdf5_data_layer.cu b/src/caffe/layers/hdf5_data_layer.cu index f671ea12d76..02ec6733d49 100644 --- a/src/caffe/layers/hdf5_data_layer.cu +++ b/src/caffe/layers/hdf5_data_layer.cu @@ -20,29 +20,24 @@ template void HDF5DataLayer::Forward_gpu(const vector*>& bottom, const vector*>& top) { const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); - const int data_count = top[0]->count() / top[0]->num(); - const int label_data_count = top[1]->count() / top[1]->num(); - for (int i = 0; i < batch_size; ++i, ++current_row_) { - if (current_row_ == data_blob_.num()) { + if (current_row_ == hdf_blobs_[0]->num()) { if (num_files_ > 1) { current_file_ += 1; - if (current_file_ == num_files_) { current_file_ = 0; LOG(INFO) << "looping around to first file"; } - LoadHDF5FileData(hdf_filenames_[current_file_].c_str()); } current_row_ = 0; } - caffe_copy(data_count, - &data_blob_.cpu_data()[current_row_ * data_count], - &top[0]->mutable_gpu_data()[i * data_count]); - caffe_copy(label_data_count, - &label_blob_.cpu_data()[current_row_ * label_data_count], - &top[1]->mutable_gpu_data()[i * label_data_count]); + for (int j = 0; j < this->layer_param_.top_size(); ++j) { + int data_dim = top[j]->count() / top[j]->num(); + caffe_copy(data_dim, + &hdf_blobs_[j]->cpu_data()[current_row_ * data_dim], + &top[j]->mutable_gpu_data()[i * data_dim]); + } } } diff --git a/src/caffe/test/test_hdf5data_layer.cpp b/src/caffe/test/test_hdf5data_layer.cpp index 9026a91ad85..769c1323ec7 100644 --- a/src/caffe/test/test_hdf5data_layer.cpp +++ b/src/caffe/test/test_hdf5data_layer.cpp @@ -57,6 +57,9 @@ TYPED_TEST(HDF5DataLayerTest, TestRead) { // The data file we are reading has 10 rows and 8 columns, // with values from 0 to 10*8 reshaped in row-major order. LayerParameter param; + param.add_top("data"); + param.add_top("label"); + HDF5DataParameter* hdf5_data_param = param.mutable_hdf5_data_param(); int batch_size = 5; hdf5_data_param->set_batch_size(batch_size); From 7e8aefb2d76cef014f2576efcb08d79526040544 Mon Sep 17 00:00:00 2001 From: Chiyuan Zhang Date: Fri, 26 Sep 2014 16:20:48 -0400 Subject: [PATCH 041/798] added test case to cover new HDF5 behavior --- .../test/test_data/generate_sample_data.py | 9 +++++++++ src/caffe/test/test_data/sample_data.h5 | Bin 11784 -> 11824 bytes .../test/test_data/sample_data_2_gzip.h5 | Bin 10548 -> 15446 bytes src/caffe/test/test_hdf5data_layer.cpp | 16 +++++++++++++++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/caffe/test/test_data/generate_sample_data.py b/src/caffe/test/test_data/generate_sample_data.py index 2ab238611d8..e5dbc3406d8 100644 --- a/src/caffe/test/test_data/generate_sample_data.py +++ b/src/caffe/test/test_data/generate_sample_data.py @@ -20,12 +20,17 @@ label = 1 + np.arange(num_rows)[:, np.newaxis] label = label.astype('float32') +# We add an extra label2 dataset to test HDF5 layer's ability +# to handle arbitrary number of output ("top") Blobs. +label2 = label + 1 + print data print label with h5py.File(os.path.dirname(__file__) + '/sample_data.h5', 'w') as f: f['data'] = data f['label'] = label + f['label2'] = label2 with h5py.File(os.path.dirname(__file__) + '/sample_data_2_gzip.h5', 'w') as f: f.create_dataset( @@ -36,6 +41,10 @@ 'label', data=label, compression='gzip', compression_opts=1 ) + f.create_dataset( + 'label2', data=label2, + compression='gzip', compression_opts=1 + ) with open(os.path.dirname(__file__) + '/sample_data_list.txt', 'w') as f: f.write(os.path.dirname(__file__) + '/sample_data.h5\n') diff --git a/src/caffe/test/test_data/sample_data.h5 b/src/caffe/test/test_data/sample_data.h5 index 90eaaa56ec773b5de2303100a5611786c8d78766..236e66b0d122523107aac97430a3dfb5bf30ec7c 100644 GIT binary patch delta 127 zcmeB(*$^{9gVA83W;>(A#*OSuj0%%?GN}vZBqpWi7%?y~GC+XEKr_6_|x4cd>S{A2_HQ!oZL*abqr2D1(VZZ}Jyb1(?jnjn<5t N(>NBXPR`)a0009dB}f1O delta 84 zcmdlG(-AX4gOOvRW;>(6#*OSuj1rS~GO2SiGC+XC#Es^Y6`1!hJy|jN9&-dE(`0j& lz=;Pw0L6qRcd>S{KUtv~!oZNRapQN!i3dV9r*SM&1pp~c8@>Pl diff --git a/src/caffe/test/test_data/sample_data_2_gzip.h5 b/src/caffe/test/test_data/sample_data_2_gzip.h5 index ff49db4ea742f207cbea04de3027087f4994215a..a138e0367be3d4b4ce4b51dcf0d7895056018883 100644 GIT binary patch delta 170 zcmdlIbgg2722+^LM6I^TLM(C{58Ps$yn;!9QDO2xBZjB%qRfh7&hF+k8Oy6cgoFYHC51eON30Gt z3?1?ehRw>%%?twC3>zDj87f;?pKjjBvW{*Abg4oB-$glf(rlzSr?rE diff --git a/src/caffe/test/test_hdf5data_layer.cpp b/src/caffe/test/test_hdf5data_layer.cpp index 769c1323ec7..ed6fed83708 100644 --- a/src/caffe/test/test_hdf5data_layer.cpp +++ b/src/caffe/test/test_hdf5data_layer.cpp @@ -25,10 +25,12 @@ class HDF5DataLayerTest : public MultiDeviceTest { HDF5DataLayerTest() : filename(NULL), blob_top_data_(new Blob()), - blob_top_label_(new Blob()) {} + blob_top_label_(new Blob()), + blob_top_label2_(new Blob()) {} virtual void SetUp() { blob_top_vec_.push_back(blob_top_data_); blob_top_vec_.push_back(blob_top_label_); + blob_top_vec_.push_back(blob_top_label2_); // Check out generate_sample_data.py in the same directory. filename = new string( @@ -39,12 +41,14 @@ class HDF5DataLayerTest : public MultiDeviceTest { virtual ~HDF5DataLayerTest() { delete blob_top_data_; delete blob_top_label_; + delete blob_top_label2_; delete filename; } string* filename; Blob* const blob_top_data_; Blob* const blob_top_label_; + Blob* const blob_top_label2_; vector*> blob_bottom_vec_; vector*> blob_top_vec_; }; @@ -59,6 +63,7 @@ TYPED_TEST(HDF5DataLayerTest, TestRead) { LayerParameter param; param.add_top("data"); param.add_top("label"); + param.add_top("label2"); HDF5DataParameter* hdf5_data_param = param.mutable_hdf5_data_param(); int batch_size = 5; @@ -81,6 +86,11 @@ TYPED_TEST(HDF5DataLayerTest, TestRead) { EXPECT_EQ(this->blob_top_label_->height(), 1); EXPECT_EQ(this->blob_top_label_->width(), 1); + EXPECT_EQ(this->blob_top_label2_->num(), batch_size); + EXPECT_EQ(this->blob_top_label2_->channels(), 1); + EXPECT_EQ(this->blob_top_label2_->height(), 1); + EXPECT_EQ(this->blob_top_label2_->width(), 1); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); // Go through the data 10 times (5 batches). @@ -92,6 +102,7 @@ TYPED_TEST(HDF5DataLayerTest, TestRead) { // On odd iterations, we're reading the second half of the data. // NB: label is 1-indexed int label_offset = 1 + ((iter % 2 == 0) ? 0 : batch_size); + int label2_offset = 1 + label_offset; int data_offset = (iter % 2 == 0) ? 0 : batch_size * data_size; // Every two iterations we are reading the second file, @@ -103,6 +114,9 @@ TYPED_TEST(HDF5DataLayerTest, TestRead) { EXPECT_EQ( label_offset + i, this->blob_top_label_->cpu_data()[i]); + EXPECT_EQ( + label2_offset + i, + this->blob_top_label2_->cpu_data()[i]); } for (int i = 0; i < batch_size; ++i) { for (int j = 0; j < num_cols; ++j) { From 3fde283606b604a8a25becc7958c7a1268fb2249 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 30 Sep 2014 11:37:55 -0700 Subject: [PATCH 042/798] hdf5_data_layer.cpp: fix indentation --- src/caffe/layers/hdf5_data_layer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index bf771fd093a..a2c806699b8 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -40,8 +40,8 @@ void HDF5DataLayer::LoadHDF5FileData(const char* filename) { const int MAX_DATA_DIM = 4; for (int i = 0; i < top_size; ++i) { - hdf_blobs_[i] = shared_ptr >(new Blob()); - hdf5_load_nd_dataset(file_id, this->layer_param_.top(i).c_str(), + hdf_blobs_[i] = shared_ptr >(new Blob()); + hdf5_load_nd_dataset(file_id, this->layer_param_.top(i).c_str(), MIN_DATA_DIM, MAX_DATA_DIM, hdf_blobs_[i].get()); } @@ -51,7 +51,7 @@ void HDF5DataLayer::LoadHDF5FileData(const char* filename) { // MinTopBlobs==1 guarantees at least one top blob int num = hdf_blobs_[0]->num(); for (int i = 1; i < top_size; ++i) { - CHECK_EQ(hdf_blobs_[i]->num(), num); + CHECK_EQ(hdf_blobs_[i]->num(), num); } LOG(INFO) << "Successully loaded " << hdf_blobs_[0]->num() << " rows"; } From db50f0749a9ee491ecf3daad783827e4c215bf0e Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 30 Sep 2014 11:13:59 -0700 Subject: [PATCH 043/798] Cleanup HDF5DataLayer log messages. -Only use "DLOG" during Forward/Backward for less noise during training/testing -Cleanup spacing, capitalization, etc. --- src/caffe/layers/hdf5_data_layer.cpp | 14 +++++++------- src/caffe/layers/hdf5_data_layer.cu | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index a2c806699b8..d4173844667 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -26,10 +26,10 @@ HDF5DataLayer::~HDF5DataLayer() { } // Load data and label from HDF5 filename into the class property blobs. template void HDF5DataLayer::LoadHDF5FileData(const char* filename) { - LOG(INFO) << "Loading HDF5 file" << filename; + DLOG(INFO) << "Loading HDF5 file: " << filename; hid_t file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); if (file_id < 0) { - LOG(ERROR) << "Failed opening HDF5 file" << filename; + LOG(ERROR) << "Failed opening HDF5 file: " << filename; return; } @@ -46,14 +46,14 @@ void HDF5DataLayer::LoadHDF5FileData(const char* filename) { } herr_t status = H5Fclose(file_id); - CHECK_GE(status, 0) << "Failed to close HDF5 file " << filename; + CHECK_GE(status, 0) << "Failed to close HDF5 file: " << filename; // MinTopBlobs==1 guarantees at least one top blob int num = hdf_blobs_[0]->num(); for (int i = 1; i < top_size; ++i) { CHECK_EQ(hdf_blobs_[i]->num(), num); } - LOG(INFO) << "Successully loaded " << hdf_blobs_[0]->num() << " rows"; + DLOG(INFO) << "Successully loaded " << hdf_blobs_[0]->num() << " rows"; } template @@ -61,7 +61,7 @@ void HDF5DataLayer::LayerSetUp(const vector*>& bottom, const vector*>& top) { // Read the source to parse the filenames. const string& source = this->layer_param_.hdf5_data_param().source(); - LOG(INFO) << "Loading filename from " << source; + LOG(INFO) << "Loading list of HDF5 filenames from: " << source; hdf_filenames_.clear(); std::ifstream source_file(source.c_str()); if (source_file.is_open()) { @@ -73,7 +73,7 @@ void HDF5DataLayer::LayerSetUp(const vector*>& bottom, source_file.close(); num_files_ = hdf_filenames_.size(); current_file_ = 0; - LOG(INFO) << "Number of files: " << num_files_; + LOG(INFO) << "Number of HDF5 files: " << num_files_; // Load the first HDF5 file and initialize the line counter. LoadHDF5FileData(hdf_filenames_[current_file_].c_str()); @@ -98,7 +98,7 @@ void HDF5DataLayer::Forward_cpu(const vector*>& bottom, ++current_file_; if (current_file_ == num_files_) { current_file_ = 0; - LOG(INFO) << "looping around to first file"; + DLOG(INFO) << "Looping around to first file."; } LoadHDF5FileData(hdf_filenames_[current_file_].c_str()); } diff --git a/src/caffe/layers/hdf5_data_layer.cu b/src/caffe/layers/hdf5_data_layer.cu index 02ec6733d49..9f5daf230e7 100644 --- a/src/caffe/layers/hdf5_data_layer.cu +++ b/src/caffe/layers/hdf5_data_layer.cu @@ -26,7 +26,7 @@ void HDF5DataLayer::Forward_gpu(const vector*>& bottom, current_file_ += 1; if (current_file_ == num_files_) { current_file_ = 0; - LOG(INFO) << "looping around to first file"; + DLOG(INFO) << "Looping around to first file."; } LoadHDF5FileData(hdf_filenames_[current_file_].c_str()); } From fce99474e7803767dbb5ea25696e23fa8002cb50 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 30 Sep 2014 11:15:21 -0700 Subject: [PATCH 044/798] Die on failure to load HDF5 data file. --- src/caffe/layers/hdf5_data_layer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index d4173844667..601fd345f3b 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -29,8 +29,7 @@ void HDF5DataLayer::LoadHDF5FileData(const char* filename) { DLOG(INFO) << "Loading HDF5 file: " << filename; hid_t file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); if (file_id < 0) { - LOG(ERROR) << "Failed opening HDF5 file: " << filename; - return; + LOG(FATAL) << "Failed opening HDF5 file: " << filename; } int top_size = this->layer_param_.top_size(); From 7a223ec3198f3d004155e54cab4790bee19972c7 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 30 Sep 2014 12:27:09 -0700 Subject: [PATCH 045/798] HDF5DataLayer: die on failure to open source file --- src/caffe/layers/hdf5_data_layer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index 601fd345f3b..61aa293d2ac 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -68,6 +68,8 @@ void HDF5DataLayer::LayerSetUp(const vector*>& bottom, while (source_file >> line) { hdf_filenames_.push_back(line); } + } else { + LOG(FATAL) << "Failed to open source file: " << source; } source_file.close(); num_files_ = hdf_filenames_.size(); From e43c079fc33a197942d73a57250d09a26cbb2fab Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 30 Sep 2014 12:32:34 -0700 Subject: [PATCH 046/798] hdf5_load_nd_dataset_helper: check that dataset exists first --- src/caffe/util/io.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 4a22e18725d..43e5c01e36a 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -124,6 +124,9 @@ template void hdf5_load_nd_dataset_helper( hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, Blob* blob) { + // Verify that the dataset exists. + CHECK(H5LTfind_dataset(file_id, dataset_name_)) + << "Failed to find HDF5 dataset " << dataset_name_; // Verify that the number of dimensions is in the accepted range. herr_t status; int ndims; From a36cceb3bdbaeb10e1057307b9aa69037de0f031 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Sep 2014 15:28:36 -0700 Subject: [PATCH 047/798] fix cuDNN build by readding line deleted in #1167 --- src/caffe/layer_factory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 96481dd72a4..9b77ca14677 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -46,6 +46,7 @@ Layer* GetPoolingLayer(const LayerParameter& param) { return new PoolingLayer(param); #ifdef USE_CUDNN } else if (engine == PoolingParameter_Engine_CUDNN) { + PoolingParameter p_param = param.pooling_param(); if (p_param.pad_h() || p_param.pad_w() || param.top_size() > 1) { LOG(INFO) << "CUDNN does not support padding or multiple tops. " << "Using Caffe's own pooling layer."; From 4f463bdaa14c8906b03ade524aab154bec712958 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Tue, 30 Sep 2014 15:57:38 -0700 Subject: [PATCH 048/798] remove a wrong space in common.hpp --- include/caffe/common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/caffe/common.hpp b/include/caffe/common.hpp index 9c6eb4d6834..811b45e2c15 100644 --- a/include/caffe/common.hpp +++ b/include/caffe/common.hpp @@ -19,7 +19,7 @@ // gflags 2.1 issue: namespace google was changed to gflags without warning. // Luckily we will be able to use GFLAGS_GFAGS_H_ to detect if it is version -// 2.1. If yes , we will add a temporary solution to redirect the namespace. +// 2.1. If yes, we will add a temporary solution to redirect the namespace. // TODO(Yangqing): Once gflags solves the problem in a more elegant way, let's // remove the following hack. #ifndef GFLAGS_GFLAGS_H_ From a02ec65ce8f07896dfa05d52263dbe8acfbb02cd Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Tue, 30 Sep 2014 17:24:26 -0700 Subject: [PATCH 049/798] [fix] check and load weight for backward w.r.t. data fix NULL pointer when back-propagating to the data for fixed i.e. not back-propagated weights. same issue as #1048 --- src/caffe/layers/cudnn_conv_layer.cu | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/caffe/layers/cudnn_conv_layer.cu b/src/caffe/layers/cudnn_conv_layer.cu index 6961bbeaba5..cf8607e1b78 100644 --- a/src/caffe/layers/cudnn_conv_layer.cu +++ b/src/caffe/layers/cudnn_conv_layer.cu @@ -86,6 +86,9 @@ void CuDNNConvolutionLayer::Backward_gpu(const vector*>& top, // Gradient w.r.t. bottom data. if (propagate_down[i]) { + if (weight == NULL) { + weight = this->blobs_[0]->gpu_data(); + } Dtype* bottom_diff = bottom[i]->mutable_gpu_diff(); CUDNN_CHECK(cudnnConvolutionBackwardData(handle_[2*this->group_ + g], filter_desc_, weight + weight_offset_ * g, From 08ccc947f128ef88fcd24c3d5807bc7c4338efda Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Sep 2014 19:16:56 -0700 Subject: [PATCH 050/798] [pycaffe] fix comment typo --- python/caffe/_caffe.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index ba04d276351..622e887ac78 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -153,7 +153,7 @@ class PyNet { bp::dict channel_swap_; protected: - // The pointer to the internal caffe::Net instant. + // The pointer to the internal caffe::Net instance. shared_ptr > net_; // if taking input from an ndarray, we need to hold references bp::object input_data_; From 2f29ec4672dca2ab4ecafb1ec75d7c597a09cfca Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Sep 2014 16:20:27 -0700 Subject: [PATCH 051/798] [pycaffe] add converter for vectors of Nets --- python/caffe/_caffe.cpp | 3 +++ python/caffe/_caffe.hpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 5a81a42329b..ce7b726f955 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -189,6 +189,9 @@ BOOST_PYTHON_MODULE(_caffe) { .def("solve", &PySGDSolver::Solve) .def("solve", &PySGDSolver::SolveResume); + bp::class_ > >("NetVec") + .def(bp::vector_indexing_suite >, true>()); + bp::class_ > >("BlobVec") .def(bp::vector_indexing_suite >, true>()); diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index 622e887ac78..0ed0974842e 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -152,6 +152,11 @@ class PyNet { bp::dict raw_scale_; bp::dict channel_swap_; + // this is here only to satisfy boost's vector_indexing_suite + bool operator == (const PyNet &other) { + return this->net_ == other.net_; + } + protected: // The pointer to the internal caffe::Net instance. shared_ptr > net_; From 34e661b27ee0d4554b4377d3fbe5793e858f37c7 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Sep 2014 16:21:18 -0700 Subject: [PATCH 052/798] [pycaffe] expose SGDSolver.test_nets --- python/caffe/_caffe.cpp | 11 ++++++++--- python/caffe/_caffe.hpp | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index ce7b726f955..1e2dd079ad0 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -2,6 +2,7 @@ // caffe::Caffe functions so that one could easily call it from Python. // Note that for Python, we will simply use float as the data type. +#include #include // these need to be included after boost on OS X @@ -134,6 +135,9 @@ PySGDSolver::PySGDSolver(const string& param_file) { // we need to explicitly store the net wrapper, rather than constructing // it on the fly, so that it can hold references to Python objects net_.reset(new PyNet(solver_->net())); + for (int i = 0; i < solver_->test_nets().size(); ++i) { + test_nets_.push_back(boost::make_shared(solver_->test_nets()[i])); + } } void PySGDSolver::SolveResume(const string& resume_file) { @@ -185,9 +189,10 @@ BOOST_PYTHON_MODULE(_caffe) { bp::class_( "SGDSolver", bp::init()) - .add_property("net", &PySGDSolver::net) - .def("solve", &PySGDSolver::Solve) - .def("solve", &PySGDSolver::SolveResume); + .add_property("net", &PySGDSolver::net) + .add_property("test_nets", &PySGDSolver::test_nets) + .def("solve", &PySGDSolver::Solve) + .def("solve", &PySGDSolver::SolveResume); bp::class_ > >("NetVec") .def(bp::vector_indexing_suite >, true>()); diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index 0ed0974842e..bef90e1b359 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -170,11 +170,13 @@ class PySGDSolver { explicit PySGDSolver(const string& param_file); shared_ptr net() { return net_; } + vector > test_nets() { return test_nets_; } void Solve() { return solver_->Solve(); } void SolveResume(const string& resume_file); protected: shared_ptr net_; + vector > test_nets_; shared_ptr > solver_; }; From e222c5776506591715769df087c4b980a391c588 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Sep 2014 20:24:47 -0700 Subject: [PATCH 053/798] add accessor for Solver::iter_ This will be useful in code controlling the solver (from pycaffe, for example). --- include/caffe/solver.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/caffe/solver.hpp b/include/caffe/solver.hpp index 6fd159d0b98..2bad0e2fe1e 100644 --- a/include/caffe/solver.hpp +++ b/include/caffe/solver.hpp @@ -31,6 +31,7 @@ class Solver { inline const vector > >& test_nets() { return test_nets_; } + int iter() { return iter_; } protected: // PreSolve is run before any solving iteration starts, allowing one to From 5be4d7681c489d187a2c8fa3cdc746bd37d57ce2 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Sep 2014 20:26:25 -0700 Subject: [PATCH 054/798] [pycaffe] expose SGDSolver.iter --- python/caffe/_caffe.cpp | 1 + python/caffe/_caffe.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 1e2dd079ad0..5a8d99d3f22 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -191,6 +191,7 @@ BOOST_PYTHON_MODULE(_caffe) { "SGDSolver", bp::init()) .add_property("net", &PySGDSolver::net) .add_property("test_nets", &PySGDSolver::test_nets) + .add_property("iter", &PySGDSolver::iter) .def("solve", &PySGDSolver::Solve) .def("solve", &PySGDSolver::SolveResume); diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index bef90e1b359..fc7be49af1b 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -171,6 +171,7 @@ class PySGDSolver { shared_ptr net() { return net_; } vector > test_nets() { return test_nets_; } + int iter() { return solver_->iter(); } void Solve() { return solver_->Solve(); } void SolveResume(const string& resume_file); From e6ba910ed9e6270e989cb7b634b206034c39f2cd Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 1 Oct 2014 20:53:31 -0700 Subject: [PATCH 055/798] caffe.proto: do some minor cleanup (fix comments, alphabetization) --- src/caffe/proto/caffe.proto | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 1f26fd346d5..2dea5a09ee1 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -470,11 +470,6 @@ message EltwiseParameter { optional bool stable_prod_grad = 3 [default = true]; } -// Message that stores parameters used by ThresholdLayer -message ThresholdParameter { - optional float threshold = 1 [default = 0]; // Strictly Positive values -} - // Message that stores parameters used by HDF5DataLayer message HDF5DataParameter { // Specify the data source. @@ -641,7 +636,7 @@ message SliceParameter { repeated uint32 slice_point = 2; } -// Message that stores parameters used by SoftmaxLayer, SoftMaxWithLossLayer +// Message that stores parameters used by SoftmaxLayer, SoftmaxWithLossLayer message SoftmaxParameter { enum Engine { DEFAULT = 0; @@ -651,7 +646,7 @@ message SoftmaxParameter { optional Engine engine = 1 [default = DEFAULT]; } -// Message that stores parameters used by SigmoidLayer +// Message that stores parameters used by TanHLayer message TanHParameter { enum Engine { DEFAULT = 0; @@ -661,6 +656,11 @@ message TanHParameter { optional Engine engine = 1 [default = DEFAULT]; } +// Message that stores parameters used by ThresholdLayer +message ThresholdParameter { + optional float threshold = 1 [default = 0]; // Strictly positive values +} + // Message that stores parameters used by WindowDataLayer message WindowDataParameter { // Specify the data source. From 22515af9a964840a1ab7082eddf27d7733a9956f Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 2 Oct 2014 11:19:05 -0700 Subject: [PATCH 056/798] [fix] lint causing travis failures --- matlab/caffe/matcaffe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/caffe/matcaffe.cpp b/matlab/caffe/matcaffe.cpp index db8896da6ae..fc047585cfe 100644 --- a/matlab/caffe/matcaffe.cpp +++ b/matlab/caffe/matcaffe.cpp @@ -372,7 +372,7 @@ static handler_registry handlers[] = { ** matlab entry point: caffe(api_command, arg1, arg2, ...) **/ void mexFunction(MEX_ARGS) { - mexLock(); // Avoid clearing the mex file. + mexLock(); // Avoid clearing the mex file. if (nrhs == 0) { LOG(ERROR) << "No API command given"; mexErrMsgTxt("An API command is requires"); From 4b004162622963d2b857ad3adaa76f143278011d Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Thu, 2 Oct 2014 12:11:45 -0700 Subject: [PATCH 057/798] add factory header to caffe hpp --- include/caffe/caffe.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/caffe/caffe.hpp b/include/caffe/caffe.hpp index 0af9ef04c43..3c829f2f9b0 100644 --- a/include/caffe/caffe.hpp +++ b/include/caffe/caffe.hpp @@ -8,6 +8,7 @@ #include "caffe/common.hpp" #include "caffe/filler.hpp" #include "caffe/layer.hpp" +#include "caffe/layer_factory.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/solver.hpp" From ab5e86e2babf22892a241ae06a93b3f389a23db1 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Sep 2014 19:06:18 -0700 Subject: [PATCH 058/798] [pycaffe] expose Net::CopyTrainedLayersFrom as Net.copy_from This allows finetuning from Python, for example. --- python/caffe/_caffe.cpp | 1 + python/caffe/_caffe.hpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 5a81a42329b..5696f2625f6 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -147,6 +147,7 @@ BOOST_PYTHON_MODULE(_caffe) { bp::class_ >( "Net", bp::init()) .def(bp::init()) + .def("copy_from", &PyNet::CopyTrainedLayersFrom) .def("_forward", &PyNet::Forward) .def("_backward", &PyNet::Backward) .def("reshape", &PyNet::Reshape) diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index 622e887ac78..a15144ba999 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -96,6 +96,9 @@ class PyNet { inline void check_contiguous_array(PyArrayObject* arr, string name, int channels, int height, int width); + void CopyTrainedLayersFrom(const string filename) { + net_->CopyTrainedLayersFrom(filename); + } void Forward(int start, int end) { net_->ForwardFromTo(start, end); } void Backward(int start, int end) { net_->BackwardFromTo(start, end); } void Reshape() { net_->Reshape(); } From 0dfda37c7f463b19f1504a08dc026b38bdddf7c6 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 2 Oct 2014 12:50:32 -0700 Subject: [PATCH 059/798] [pycaffe] expose Net::SharedTrainedLayersWith as Net.share_with --- python/caffe/_caffe.cpp | 1 + python/caffe/_caffe.hpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 5696f2625f6..28027bed0a4 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -148,6 +148,7 @@ BOOST_PYTHON_MODULE(_caffe) { "Net", bp::init()) .def(bp::init()) .def("copy_from", &PyNet::CopyTrainedLayersFrom) + .def("share_with", &PyNet::ShareTrainedLayersWith) .def("_forward", &PyNet::Forward) .def("_backward", &PyNet::Backward) .def("reshape", &PyNet::Reshape) diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index a15144ba999..780f82e5666 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -99,6 +99,9 @@ class PyNet { void CopyTrainedLayersFrom(const string filename) { net_->CopyTrainedLayersFrom(filename); } + void ShareTrainedLayersWith(PyNet* other) { + net_->ShareTrainedLayersWith(other->net_.get()); + } void Forward(int start, int end) { net_->ForwardFromTo(start, end); } void Backward(int start, int end) { net_->BackwardFromTo(start, end); } void Reshape() { net_->Reshape(); } From 0aae4a509862f7c42b32d7653b5c068f948b462c Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 1 Oct 2014 23:11:41 -0700 Subject: [PATCH 060/798] Add caffe_gpu_exp math function --- include/caffe/util/math_functions.hpp | 3 +++ src/caffe/util/math_functions.cu | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/caffe/util/math_functions.hpp b/include/caffe/util/math_functions.hpp index 62467fb5c52..a78eb5bc978 100644 --- a/include/caffe/util/math_functions.hpp +++ b/include/caffe/util/math_functions.hpp @@ -205,6 +205,9 @@ void caffe_gpu_div(const int N, const Dtype* a, const Dtype* b, Dtype* y); template void caffe_gpu_abs(const int n, const Dtype* a, Dtype* y); +template +void caffe_gpu_exp(const int n, const Dtype* a, Dtype* y); + template void caffe_gpu_powx(const int n, const Dtype* a, const Dtype b, Dtype* y); diff --git a/src/caffe/util/math_functions.cu b/src/caffe/util/math_functions.cu index 4ae4bba6029..43e65eb9a69 100644 --- a/src/caffe/util/math_functions.cu +++ b/src/caffe/util/math_functions.cu @@ -303,6 +303,27 @@ void caffe_gpu_abs(const int N, const double* a, double* y) { } +template +__global__ void exp_kernel(const int n, const Dtype* a, Dtype* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = exp(a[index]); + } +} + +template <> +void caffe_gpu_exp(const int N, const float* a, float* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + exp_kernel<<>>( + N, a, y); +} + +template <> +void caffe_gpu_exp(const int N, const double* a, double* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + exp_kernel<<>>( + N, a, y); +} + template __global__ void powx_kernel(const int n, const Dtype* a, const Dtype alpha, Dtype* y) { From 7995a38cc14de2560de7611b1e845c4946bcd3dd Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 1 Oct 2014 23:12:06 -0700 Subject: [PATCH 061/798] Add ExpLayer to calculate y = base ^ (scale * x + shift) --- include/caffe/neuron_layers.hpp | 66 ++++++++++++++++ src/caffe/layer_factory.cpp | 1 + src/caffe/layers/exp_layer.cpp | 69 ++++++++++++++++ src/caffe/layers/exp_layer.cu | 44 +++++++++++ src/caffe/proto/caffe.proto | 16 +++- src/caffe/test/test_neuron_layer.cpp | 114 +++++++++++++++++++++++++++ 6 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 src/caffe/layers/exp_layer.cpp create mode 100644 src/caffe/layers/exp_layer.cu diff --git a/include/caffe/neuron_layers.hpp b/include/caffe/neuron_layers.hpp index 64a1fd325ad..5daeeefe7ae 100644 --- a/include/caffe/neuron_layers.hpp +++ b/include/caffe/neuron_layers.hpp @@ -212,6 +212,72 @@ class DropoutLayer : public NeuronLayer { unsigned int uint_thres_; }; +/** + * @brief Computes @f$ y = \gamma ^ {\alpha x + \beta} @f$, + * as specified by the scale @f$ \alpha @f$, shift @f$ \beta @f$, + * and base @f$ \gamma @f$. + */ +template +class ExpLayer : public NeuronLayer { + public: + /** + * @param param provides ExpParameter exp_param, + * with ExpLayer options: + * - scale (\b optional, default 1) the scale @f$ \alpha @f$ + * - shift (\b optional, default 0) the shift @f$ \beta @f$ + * - base (\b optional, default -1 for a value of @f$ e \approx 2.718 @f$) + * the base @f$ \gamma @f$ + */ + explicit ExpLayer(const LayerParameter& param) + : NeuronLayer(param) {} + virtual void LayerSetUp(const vector*>& bottom, + const vector*>& top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_EXP; + } + + protected: + /** + * @param bottom input Blob vector (length 1) + * -# @f$ (N \times C \times H \times W) @f$ + * the inputs @f$ x @f$ + * @param top output Blob vector (length 1) + * -# @f$ (N \times C \times H \times W) @f$ + * the computed outputs @f$ + * y = \gamma ^ {\alpha x + \beta} + * @f$ + */ + virtual void Forward_cpu(const vector*>& bottom, + const vector*>& top); + virtual void Forward_gpu(const vector*>& bottom, + const vector*>& top); + + /** + * @brief Computes the error gradient w.r.t. the exp inputs. + * + * @param top output Blob vector (length 1), providing the error gradient with + * respect to the outputs + * -# @f$ (N \times C \times H \times W) @f$ + * containing error gradients @f$ \frac{\partial E}{\partial y} @f$ + * with respect to computed outputs @f$ y @f$ + * @param propagate_down see Layer::Backward. + * @param bottom input Blob vector (length 1) + * -# @f$ (N \times C \times H \times W) @f$ + * the inputs @f$ x @f$; Backward fills their diff with + * gradients @f$ + * \frac{\partial E}{\partial x} = + * \frac{\partial E}{\partial y} y \alpha \log_e(gamma) + * @f$ if propagate_down[0] + */ + virtual void Backward_cpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom); + virtual void Backward_gpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom); + + Dtype inner_scale_, outer_scale_; +}; + /** * @brief Computes @f$ y = (\alpha x + \beta) ^ \gamma @f$, * as specified by the scale @f$ \alpha @f$, shift @f$ \beta @f$, diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 9b77ca14677..8815ddd021d 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -163,6 +163,7 @@ REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer); REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer); REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer); REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer); +REGISTER_LAYER_CLASS(EXP, ExpLayer); REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer); REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer); REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer); diff --git a/src/caffe/layers/exp_layer.cpp b/src/caffe/layers/exp_layer.cpp new file mode 100644 index 00000000000..25da1201c10 --- /dev/null +++ b/src/caffe/layers/exp_layer.cpp @@ -0,0 +1,69 @@ +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void ExpLayer::LayerSetUp(const vector*>& bottom, + const vector*>& top) { + NeuronLayer::LayerSetUp(bottom, top); + const Dtype base = this->layer_param_.exp_param().base(); + if (base != Dtype(-1)) { + CHECK_GT(base, 0) << "base must be strictly positive."; + } + // If base == -1, interpret the base as e and set log_base = 1 exactly. + // Otherwise, calculate its log explicitly. + const Dtype log_base = (base == Dtype(-1)) ? Dtype(1) : log(base); + CHECK(!std::isnan(log_base)) + << "NaN result: log(base) = log(" << base << ") = " << log_base; + CHECK(!std::isinf(log_base)) + << "Inf result: log(base) = log(" << base << ") = " << log_base; + const Dtype input_scale = this->layer_param_.exp_param().scale(); + const Dtype input_shift = this->layer_param_.exp_param().shift(); + inner_scale_ = log_base * input_scale; + outer_scale_ = (input_shift == Dtype(0)) ? Dtype(1) : pow(base, input_shift); +} + +template +void ExpLayer::Forward_cpu(const vector*>& bottom, + const vector*>& top) { + const int count = bottom[0]->count(); + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = top[0]->mutable_cpu_data(); + if (inner_scale_ == Dtype(1)) { + caffe_exp(count, bottom_data, top_data); + } else { + caffe_cpu_scale(count, inner_scale_, bottom_data, top_data); + caffe_exp(count, top_data, top_data); + } + if (outer_scale_ != Dtype(1)) { + caffe_scal(count, outer_scale_, top_data); + } +} + +template +void ExpLayer::Backward_cpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom) { + if (!propagate_down[0]) { return; } + const int count = bottom[0]->count(); + const Dtype* top_data = top[0]->cpu_data(); + const Dtype* top_diff = top[0]->cpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + caffe_mul(count, top_data, top_diff, bottom_diff); + if (inner_scale_ != Dtype(1)) { + caffe_scal(count, inner_scale_, bottom_diff); + } +} + +#ifdef CPU_ONLY +STUB_GPU(ExpLayer); +#endif + +INSTANTIATE_CLASS(ExpLayer); + + +} // namespace caffe diff --git a/src/caffe/layers/exp_layer.cu b/src/caffe/layers/exp_layer.cu new file mode 100644 index 00000000000..a0fd672a25a --- /dev/null +++ b/src/caffe/layers/exp_layer.cu @@ -0,0 +1,44 @@ +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void ExpLayer::Forward_gpu(const vector*>& bottom, + const vector*>& top) { + const int count = bottom[0]->count(); + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = top[0]->mutable_gpu_data(); + if (inner_scale_ == Dtype(1)) { + caffe_gpu_exp(count, bottom_data, top_data); + } else { + caffe_gpu_scale(count, inner_scale_, bottom_data, top_data); + caffe_gpu_exp(count, top_data, top_data); + } + if (outer_scale_ != Dtype(1)) { + caffe_gpu_scal(count, outer_scale_, top_data); + } +} + +template +void ExpLayer::Backward_gpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom) { + if (!propagate_down[0]) { return; } + const int count = bottom[0]->count(); + const Dtype* top_data = top[0]->gpu_data(); + const Dtype* top_diff = top[0]->gpu_diff(); + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); + caffe_gpu_mul(count, top_data, top_diff, bottom_diff); + if (inner_scale_ != Dtype(1)) { + caffe_gpu_scal(count, inner_scale_, bottom_diff); + } +} + +INSTANTIATE_CLASS(ExpLayer); + + +} // namespace caffe diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 2dea5a09ee1..6944ae847ff 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -200,7 +200,7 @@ message NetStateRule { // NOTE // Update the next available ID when you add a new LayerParameter field. // -// LayerParameter next available ID: 41 (last added: contrastive_loss_param) +// LayerParameter next available ID: 42 (last added: exp_param) message LayerParameter { repeated string bottom = 2; // the name of the bottom blobs repeated string top = 3; // the name of the top blobs @@ -221,7 +221,7 @@ message LayerParameter { // line above the enum. Update the next available ID when you add a new // LayerType. // - // LayerType next available ID: 38 (last added: CONTRASTIVE_LOSS) + // LayerType next available ID: 39 (last added: EXP) enum LayerType { // "NONE" layer type is 0th enum element so that we don't cause confusion // by defaulting to an existent LayerType (instead, should usually error if @@ -239,6 +239,7 @@ message LayerParameter { DUMMY_DATA = 32; EUCLIDEAN_LOSS = 7; ELTWISE = 25; + EXP = 38; FLATTEN = 8; HDF5_DATA = 9; HDF5_OUTPUT = 10; @@ -301,6 +302,7 @@ message LayerParameter { optional DropoutParameter dropout_param = 12; optional DummyDataParameter dummy_data_param = 26; optional EltwiseParameter eltwise_param = 24; + optional ExpParameter exp_param = 41; optional HDF5DataParameter hdf5_data_param = 13; optional HDF5OutputParameter hdf5_output_param = 14; optional HingeLossParameter hinge_loss_param = 29; @@ -470,6 +472,16 @@ message EltwiseParameter { optional bool stable_prod_grad = 3 [default = true]; } +// Message that stores parameters used by ExpLayer +message ExpParameter { + // ExpLayer computes outputs y = base ^ (shift + scale * x), for base > 0. + // Or if base is set to the default (-1), base is set to e, + // so y = exp(shift + scale * x). + optional float base = 1 [default = -1.0]; + optional float scale = 2 [default = 1.0]; + optional float shift = 3 [default = 0.0]; +} + // Message that stores parameters used by HDF5DataLayer message HDF5DataParameter { // Specify the data source. diff --git a/src/caffe/test/test_neuron_layer.cpp b/src/caffe/test/test_neuron_layer.cpp index fdbb63cb3e5..34955c3af63 100644 --- a/src/caffe/test/test_neuron_layer.cpp +++ b/src/caffe/test/test_neuron_layer.cpp @@ -66,6 +66,38 @@ class NeuronLayerTest : public MultiDeviceTest { const Dtype empirical_dropout_ratio = 1 - num_kept / Dtype(count); EXPECT_NEAR(empirical_dropout_ratio, dropout_ratio, 1.96 * std_error); } + + void TestExpForward(const float base, const float scale, const float shift) { + LayerParameter layer_param; + layer_param.mutable_exp_param()->set_base(base); + layer_param.mutable_exp_param()->set_scale(scale); + layer_param.mutable_exp_param()->set_shift(shift); + ExpLayer layer(layer_param); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); + layer.Forward(blob_bottom_vec_, blob_top_vec_); + const Dtype kDelta = 2e-4; + const Dtype* bottom_data = blob_bottom_->cpu_data(); + const Dtype* top_data = blob_top_->cpu_data(); + for (int i = 0; i < blob_bottom_->count(); ++i) { + const Dtype bottom_val = bottom_data[i]; + const Dtype top_val = top_data[i]; + if (base == -1) { + EXPECT_NEAR(top_val, exp(shift + scale * bottom_val), kDelta); + } else { + EXPECT_NEAR(top_val, pow(base, shift + scale * bottom_val), kDelta); + } + } + } + + void TestExpGradient(const float base, const float scale, const float shift) { + LayerParameter layer_param; + layer_param.mutable_exp_param()->set_base(base); + layer_param.mutable_exp_param()->set_scale(scale); + layer_param.mutable_exp_param()->set_shift(shift); + ExpLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, blob_bottom_vec_, blob_top_vec_); + } }; TYPED_TEST_CASE(NeuronLayerTest, TestDtypesAndDevices); @@ -201,6 +233,88 @@ TYPED_TEST(NeuronLayerTest, TestTanHGradient) { this->blob_top_vec_); } +TYPED_TEST(NeuronLayerTest, TestExpLayer) { + typedef typename TypeParam::Dtype Dtype; + // Test default base of "-1" -- should actually set base := e. + const Dtype kBase = -1; + const Dtype kScale = 1; + const Dtype kShift = 0; + this->TestExpForward(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpGradient) { + typedef typename TypeParam::Dtype Dtype; + // Test default base of "-1" -- should actually set base := e. + const Dtype kBase = -1; + const Dtype kScale = 1; + const Dtype kShift = 0; + this->TestExpGradient(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpLayerBase2) { + typedef typename TypeParam::Dtype Dtype; + const Dtype kBase = 2; + const Dtype kScale = 1; + const Dtype kShift = 0; + this->TestExpForward(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpGradientBase2) { + typedef typename TypeParam::Dtype Dtype; + const Dtype kBase = 2; + const Dtype kScale = 1; + const Dtype kShift = 0; + this->TestExpGradient(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpLayerBase2Shift1) { + typedef typename TypeParam::Dtype Dtype; + const Dtype kBase = 2; + const Dtype kScale = 1; + const Dtype kShift = 1; + this->TestExpForward(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpGradientBase2Shift1) { + typedef typename TypeParam::Dtype Dtype; + const Dtype kBase = 2; + const Dtype kScale = 1; + const Dtype kShift = 1; + this->TestExpGradient(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpLayerBase2Scale3) { + typedef typename TypeParam::Dtype Dtype; + const Dtype kBase = 2; + const Dtype kScale = 3; + const Dtype kShift = 0; + this->TestExpForward(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpGradientBase2Scale3) { + typedef typename TypeParam::Dtype Dtype; + const Dtype kBase = 2; + const Dtype kScale = 3; + const Dtype kShift = 0; + this->TestExpGradient(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpLayerBase2Shift1Scale3) { + typedef typename TypeParam::Dtype Dtype; + const Dtype kBase = 2; + const Dtype kScale = 3; + const Dtype kShift = 1; + this->TestExpForward(kBase, kScale, kShift); +} + +TYPED_TEST(NeuronLayerTest, TestExpGradientBase2Shift1Scale3) { + typedef typename TypeParam::Dtype Dtype; + const Dtype kBase = 2; + const Dtype kScale = 3; + const Dtype kShift = 1; + this->TestExpGradient(kBase, kScale, kShift); +} + TYPED_TEST(NeuronLayerTest, TestDropoutHalf) { const float kDropoutRatio = 0.5; this->TestDropoutForward(kDropoutRatio); From 159a422aab94d465e73b02a5d377e695c3cefc51 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 2 Oct 2014 16:20:04 -0700 Subject: [PATCH 062/798] [fix] comment typo --- src/caffe/test/test_net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caffe/test/test_net.cpp b/src/caffe/test/test_net.cpp index 9b10d100afb..d48a60ece46 100644 --- a/src/caffe/test/test_net.cpp +++ b/src/caffe/test/test_net.cpp @@ -993,7 +993,7 @@ TYPED_TEST(NetTest, TestSharedWeightsUpdate) { // Check that data blobs of shared weights share the same location in memory. EXPECT_EQ(ip1_weights->cpu_data(), ip2_weights->cpu_data()); // Check that diff blobs of shared weights are at different locations in - // locations. (The diffs should be accumulated at update time.) + // memory. (The diffs should be accumulated at update time.) EXPECT_NE(ip1_weights->cpu_diff(), ip2_weights->cpu_diff()); this->net_->Forward(bottom); this->net_->Backward(); From 4dc5bd0953aee7771487a1d8f989bbef6aecb72d Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 2 Oct 2014 17:11:38 -0700 Subject: [PATCH 063/798] save/restore shared weights unit test --- src/caffe/test/test_net.cpp | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/caffe/test/test_net.cpp b/src/caffe/test/test_net.cpp index d48a60ece46..930486dd6c5 100644 --- a/src/caffe/test/test_net.cpp +++ b/src/caffe/test/test_net.cpp @@ -1068,6 +1068,54 @@ TYPED_TEST(NetTest, TestSharedWeightsUpdate) { } } +TYPED_TEST(NetTest, TestSharedWeightsResume) { + typedef typename TypeParam::Dtype Dtype; + + // Create a net with weight sharing; Update it once. + Caffe::set_random_seed(this->seed_); + this->InitDiffDataSharedWeightsNet(); + vector*> bottom; + EXPECT_EQ(this->net_->layer_names()[1], "innerproduct1"); + EXPECT_EQ(this->net_->layer_names()[2], "innerproduct2"); + Blob* ip1_weights = this->net_->layers()[1]->blobs()[0].get(); + Blob* ip2_weights = this->net_->layers()[2]->blobs()[0].get(); + // Check that data blobs of shared weights share the same location in memory. + EXPECT_EQ(ip1_weights->cpu_data(), ip2_weights->cpu_data()); + // Check that diff blobs of shared weights are at different locations in + // memory. (The diffs should be accumulated at update time.) + EXPECT_NE(ip1_weights->cpu_diff(), ip2_weights->cpu_diff()); + this->net_->ForwardBackward(bottom); + this->net_->Update(); + Blob shared_params; + const bool kReshape = true; + const bool kCopyDiff = false; + shared_params.CopyFrom(*ip1_weights, kCopyDiff, kReshape); + const int count = ip1_weights->count(); + + // Write the net to a NetParameter, as in Solver::Snapshot. + NetParameter net_param; + this->net_->ToProto(&net_param); + + // Reinitialize the net and copy parameters from net_param, as in + // Solver::Restore. + Caffe::set_random_seed(this->seed_); + this->InitDiffDataSharedWeightsNet(); + this->net_->CopyTrainedLayersFrom(net_param); + ip1_weights = this->net_->layers()[1]->blobs()[0].get(); + ip2_weights = this->net_->layers()[2]->blobs()[0].get(); + ASSERT_FALSE(NULL == ip1_weights); + ASSERT_FALSE(NULL == ip2_weights); + EXPECT_NE(ip1_weights, ip2_weights); + // Check that data blobs of shared weights share the same location in memory. + EXPECT_EQ(ip1_weights->cpu_data(), ip2_weights->cpu_data()); + for (int i = 0; i < count; ++i) { + EXPECT_FLOAT_EQ(shared_params.cpu_data()[i], ip1_weights->cpu_data()[i]); + } + // Check that diff blobs of shared weights are at different locations in + // memory. (The diffs should be accumulated at update time.) + EXPECT_NE(ip1_weights->cpu_diff(), ip2_weights->cpu_diff()); +} + TYPED_TEST(NetTest, TestParamPropagateDown) { typedef typename TypeParam::Dtype Dtype; vector*> bottom; From 7182bfb831c3c4dc37817af7695e6247cb9eae5c Mon Sep 17 00:00:00 2001 From: Sergio Guadarrama Date: Fri, 19 Sep 2014 17:10:59 -0700 Subject: [PATCH 064/798] Move data_mean into data_transformer remove datum_* from BaseData Conflicts: src/caffe/layers/memory_data_layer.cpp --- include/caffe/data_layers.hpp | 14 ++------------ include/caffe/data_transformer.hpp | 16 ++++++++++++++-- src/caffe/data_transformer.cpp | 18 ++++++++++++++++++ src/caffe/layers/base_data_layer.cpp | 25 +------------------------ src/caffe/layers/data_layer.cpp | 8 ++------ src/caffe/layers/image_data_layer.cpp | 7 +------ src/caffe/layers/memory_data_layer.cpp | 21 +++++++++------------ src/caffe/layers/window_data_layer.cpp | 12 ++++++++++++ 8 files changed, 59 insertions(+), 62 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index c1720b7f8ad..bf06865c7d7 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -46,20 +46,9 @@ class BaseDataLayer : public Layer { virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom) {} - int datum_channels() const { return datum_channels_; } - int datum_height() const { return datum_height_; } - int datum_width() const { return datum_width_; } - int datum_size() const { return datum_size_; } - protected: TransformationParameter transform_param_; DataTransformer data_transformer_; - int datum_channels_; - int datum_height_; - int datum_width_; - int datum_size_; - Blob data_mean_; - const Dtype* mean_; Caffe::Phase phase_; bool output_labels_; }; @@ -299,7 +288,7 @@ class MemoryDataLayer : public BaseDataLayer { virtual void Forward_cpu(const vector*>& bottom, const vector*>& top); - int batch_size_; + int batch_size_, channels_, height_, width_, size_; Dtype* data_; Dtype* labels_; int n_; @@ -339,6 +328,7 @@ class WindowDataLayer : public BasePrefetchingDataLayer { enum WindowField { IMAGE_INDEX, LABEL, OVERLAP, X1, Y1, X2, Y2, NUM }; vector > fg_windows_; vector > bg_windows_; + Blob data_mean_; }; } // namespace caffe diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 3ca99e7b62c..33afa72359b 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -3,6 +3,7 @@ #include "caffe/common.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/io.hpp" namespace caffe { @@ -16,6 +17,14 @@ class DataTransformer { explicit DataTransformer(const TransformationParameter& param) : param_(param) { phase_ = Caffe::phase(); + // check if we want to have mean + if (param_.has_mean_file()) { + const string& mean_file = param.mean_file(); + LOG(INFO) << "Loading mean file from" << mean_file; + BlobProto blob_proto; + ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); + data_mean_.FromProto(blob_proto); + } } virtual ~DataTransformer() {} @@ -30,13 +39,13 @@ class DataTransformer { * writing position in the top blob's data * @param datum * Datum containing the data to be transformed. - * @param mean * @param transformed_data * This is meant to be the top blob's data. The transformed data will be * written at the appropriate place within the blob's data. */ + void Transform(const int batch_item_id, const Datum& datum, - const Dtype* mean, Dtype* transformed_data); + Dtype* transformed_data); protected: /** @@ -49,12 +58,15 @@ class DataTransformer { */ virtual int Rand(int n); + void Transform(const int batch_item_id, const Datum& datum, + const Dtype* mean, Dtype* transformed_data); // Tranformation parameters TransformationParameter param_; shared_ptr rng_; Caffe::Phase phase_; + Blob data_mean_; }; } // namespace caffe diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index e52c3b6a55d..81cb17b5cd0 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -6,6 +6,24 @@ namespace caffe { + +template +void DataTransformer::Transform(const int batch_item_id, + const Datum& datum, + Dtype* transformed_data) { + + CHECK_GT(datum.channels(), 0); + CHECK_GE(datum.height(), param_.crop_size()); + CHECK_GE(datum.height(), param_.crop_size()); + const int size = datum.channels() * datum.height() * datum.width(); + if (data_mean_.count() < size) { + data_mean_.Reshape(1, datum.channels(), datum.height(), datum.width()); + LOG(INFO) << "Transform without mean"; + } + const Dtype* mean = data_mean_.cpu_data(); + Transform(batch_item_id, datum, mean, transformed_data); +} + template void DataTransformer::Transform(const int batch_item_id, const Datum& datum, diff --git a/src/caffe/layers/base_data_layer.cpp b/src/caffe/layers/base_data_layer.cpp index 86abbae8f4c..5038d532ee1 100644 --- a/src/caffe/layers/base_data_layer.cpp +++ b/src/caffe/layers/base_data_layer.cpp @@ -21,31 +21,8 @@ void BaseDataLayer::LayerSetUp(const vector*>& bottom, } else { output_labels_ = true; } + // The subclasses should setup the size of bottom and top DataLayerSetUp(bottom, top); - // The subclasses should setup the datum channels, height and width - CHECK_GT(datum_channels_, 0); - CHECK_GT(datum_height_, 0); - CHECK_GT(datum_width_, 0); - if (transform_param_.crop_size() > 0) { - CHECK_GE(datum_height_, transform_param_.crop_size()); - CHECK_GE(datum_width_, transform_param_.crop_size()); - } - // check if we want to have mean - if (transform_param_.has_mean_file()) { - const string& mean_file = transform_param_.mean_file(); - LOG(INFO) << "Loading mean file from" << mean_file; - BlobProto blob_proto; - ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); - data_mean_.FromProto(blob_proto); - CHECK_GE(data_mean_.num(), 1); - CHECK_GE(data_mean_.channels(), datum_channels_); - CHECK_GE(data_mean_.height(), datum_height_); - CHECK_GE(data_mean_.width(), datum_width_); - } else { - // Simply initialize an all-empty mean. - data_mean_.Reshape(1, datum_channels_, datum_height_, datum_width_); - } - mean_ = data_mean_.cpu_data(); data_transformer_.InitRand(); } diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index b3b6bf3d64f..3867a87f8b0 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -134,11 +134,7 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, this->prefetch_label_.Reshape(this->layer_param_.data_param().batch_size(), 1, 1, 1); } - // datum size - this->datum_channels_ = datum.channels(); - this->datum_height_ = datum.height(); - this->datum_width_ = datum.width(); - this->datum_size_ = datum.channels() * datum.height() * datum.width(); + } // This function is used to create a thread that prefetches the data. @@ -172,7 +168,7 @@ void DataLayer::InternalThreadEntry() { } // Apply data transformations (mirror, scale, crop...) - this->data_transformer_.Transform(item_id, datum, this->mean_, top_data); + this->data_transformer_.Transform(item_id, datum, top_data); if (this->output_labels_) { top_label[item_id] = datum.label(); diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index dc972f13799..a5d46fd0c63 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -76,11 +76,6 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, // label top[1]->Reshape(batch_size, 1, 1, 1); this->prefetch_label_.Reshape(batch_size, 1, 1, 1); - // datum size - this->datum_channels_ = datum.channels(); - this->datum_height_ = datum.height(); - this->datum_width_ = datum.width(); - this->datum_size_ = datum.channels() * datum.height() * datum.width(); } template @@ -114,7 +109,7 @@ void ImageDataLayer::InternalThreadEntry() { } // Apply transformations (mirror, crop...) to the data - this->data_transformer_.Transform(item_id, datum, this->mean_, top_data); + this->data_transformer_.Transform(item_id, datum, top_data); top_label[item_id] = datum.label(); // go to the next iter diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index d254da34322..269a2679777 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -10,19 +10,16 @@ template void MemoryDataLayer::DataLayerSetUp(const vector*>& bottom, const vector*>& top) { batch_size_ = this->layer_param_.memory_data_param().batch_size(); - this->datum_channels_ = this->layer_param_.memory_data_param().channels(); - this->datum_height_ = this->layer_param_.memory_data_param().height(); - this->datum_width_ = this->layer_param_.memory_data_param().width(); - this->datum_size_ = this->datum_channels_ * this->datum_height_ * - this->datum_width_; - CHECK_GT(batch_size_ * this->datum_size_, 0) << + channels_ = this->layer_param_.memory_data_param().channels(); + height_ = this->layer_param_.memory_data_param().height(); + width_ = this->layer_param_.memory_data_param().width(); + size_ = channels_ * height_ * width_; + CHECK_GT(batch_size_ * size_, 0) << "batch_size, channels, height, and width must be specified and" " positive in memory_data_param"; - top[0]->Reshape(batch_size_, this->datum_channels_, this->datum_height_, - this->datum_width_); + top[0]->Reshape(batch_size_, channels_, height_, width_); top[1]->Reshape(batch_size_, 1, 1, 1); - added_data_.Reshape(batch_size_, this->datum_channels_, this->datum_height_, - this->datum_width_); + added_data_.Reshape(batch_size_, channels_, height_, width_); added_label_.Reshape(batch_size_, 1, 1, 1); data_ = NULL; labels_ = NULL; @@ -45,7 +42,7 @@ void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { for (int batch_item_id = 0; batch_item_id < num; ++batch_item_id) { // Apply data transformations (mirror, scale, crop...) this->data_transformer_.Transform( - batch_item_id, datum_vector[batch_item_id], this->mean_, top_data); + batch_item_id, datum_vector[batch_item_id], top_data); top_label[batch_item_id] = datum_vector[batch_item_id].label(); } // num_images == batch_size_ @@ -68,7 +65,7 @@ template void MemoryDataLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { CHECK(data_) << "MemoryDataLayer needs to be initalized by calling Reset"; - top[0]->set_cpu_data(data_ + pos_ * this->datum_size_); + top[0]->set_cpu_data(data_ + pos_ * size_); top[1]->set_cpu_data(labels_ + pos_); pos_ = (pos_ + batch_size_) % n_; has_new_data_ = false; diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 33a473d64bf..88afe829537 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -167,6 +167,18 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, // label top[1]->Reshape(batch_size, 1, 1, 1); this->prefetch_label_.Reshape(batch_size, 1, 1, 1); + + // data mean + if (this->layer_param_.window_data_param().has_mean_file()) { + const string& mean_file = + this->layer_param_.window_data_param().mean_file(); + LOG(INFO) << "Loading mean file from" << mean_file; + BlobProto blob_proto; + ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); + data_mean_.FromProto(blob_proto); + } else { + data_mean_.Reshape(1, channels, crop_size, crop_size); + } } template From e9c08e5a8c39508ecff052ef36df63bf883d2dad Mon Sep 17 00:00:00 2001 From: Sergio Guadarrama Date: Thu, 11 Sep 2014 15:19:57 -0700 Subject: [PATCH 065/798] Fixed MemoryDataLayer to make it work with pycaffe --- include/caffe/data_layers.hpp | 3 +++ include/caffe/data_transformer.hpp | 13 +------------ python/caffe/_caffe.cpp | 4 ++-- src/caffe/data_transformer.cpp | 14 +++++++++++++- src/caffe/layers/data_layer.cpp | 1 - src/caffe/layers/window_data_layer.cpp | 2 +- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index bf06865c7d7..e598a71db0a 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -283,6 +283,9 @@ class MemoryDataLayer : public BaseDataLayer { void Reset(Dtype* data, Dtype* label, int n); int batch_size() { return batch_size_; } + int channels() { return channels_; } + int height() { return height_; } + int width() { return width_; } protected: virtual void Forward_cpu(const vector*>& bottom, diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 33afa72359b..fcd101165cf 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -14,18 +14,7 @@ namespace caffe { template class DataTransformer { public: - explicit DataTransformer(const TransformationParameter& param) - : param_(param) { - phase_ = Caffe::phase(); - // check if we want to have mean - if (param_.has_mean_file()) { - const string& mean_file = param.mean_file(); - LOG(INFO) << "Loading mean file from" << mean_file; - BlobProto blob_proto; - ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); - data_mean_.FromProto(blob_proto); - } - } + explicit DataTransformer(const TransformationParameter& param); virtual ~DataTransformer() {} void InitRand(); diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 5a8d99d3f22..33e68fe40fa 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -106,8 +106,8 @@ void PyNet::set_input_arrays(bp::object data_obj, bp::object labels_obj) { reinterpret_cast(data_obj.ptr()); PyArrayObject* labels_arr = reinterpret_cast(labels_obj.ptr()); - check_contiguous_array(data_arr, "data array", md_layer->datum_channels(), - md_layer->datum_height(), md_layer->datum_width()); + check_contiguous_array(data_arr, "data array", md_layer->channels(), + md_layer->height(), md_layer->width()); check_contiguous_array(labels_arr, "labels array", 1, 1, 1); if (PyArray_DIMS(data_arr)[0] != PyArray_DIMS(labels_arr)[0]) { throw std::runtime_error("data and labels must have the same first" diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 81cb17b5cd0..553717a50da 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -6,12 +6,24 @@ namespace caffe { +template +DataTransformer::DataTransformer(const TransformationParameter& param) + : param_(param) { + phase_ = Caffe::phase(); + // check if we want to have mean + if (param_.has_mean_file()) { + const string& mean_file = param.mean_file(); + LOG(INFO) << "Loading mean file from" << mean_file; + BlobProto blob_proto; + ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); + data_mean_.FromProto(blob_proto); + } +} template void DataTransformer::Transform(const int batch_item_id, const Datum& datum, Dtype* transformed_data) { - CHECK_GT(datum.channels(), 0); CHECK_GE(datum.height(), param_.crop_size()); CHECK_GE(datum.height(), param_.crop_size()); diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 3867a87f8b0..40c48735b41 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -134,7 +134,6 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, this->prefetch_label_.Reshape(this->layer_param_.data_param().batch_size(), 1, 1, 1); } - } // This function is used to create a thread that prefetches the data. diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 88afe829537..6b70aa3cf22 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -170,7 +170,7 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, // data mean if (this->layer_param_.window_data_param().has_mean_file()) { - const string& mean_file = + const string& mean_file = this->layer_param_.window_data_param().mean_file(); LOG(INFO) << "Loading mean file from" << mean_file; BlobProto blob_proto; From 4602439900b616c590b9873f7bebdf3f9ecf716c Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 25 Sep 2014 19:58:06 -0700 Subject: [PATCH 066/798] Initial cv::Mat transformation Added cv::Mat transformation to ImageDataLayer Conflicts: src/caffe/layers/image_data_layer.cpp Added transform Datum to Blob Conflicts: src/caffe/layers/base_data_layer.cpp src/caffe/layers/base_data_layer.cu Added transform cv::Mat to Blob Added transform Vector to Blob Conflicts: src/caffe/data_transformer.cpp --- include/caffe/data_layers.hpp | 3 + include/caffe/data_transformer.hpp | 17 +- include/caffe/util/benchmark.hpp | 2 + include/caffe/util/io.hpp | 18 ++ src/caffe/data_transformer.cpp | 393 +++++++++++++++++++++---- src/caffe/layers/base_data_layer.cpp | 7 + src/caffe/layers/base_data_layer.cu | 2 + src/caffe/layers/data_layer.cpp | 17 +- src/caffe/layers/image_data_layer.cpp | 49 +-- src/caffe/layers/memory_data_layer.cpp | 12 +- src/caffe/proto/caffe.proto | 2 + src/caffe/util/benchmark.cpp | 22 ++ src/caffe/util/io.cpp | 17 ++ 13 files changed, 461 insertions(+), 100 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index e598a71db0a..e3ba2d13ccf 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -17,6 +17,7 @@ #include "caffe/internal_thread.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/benchmark.hpp" namespace caffe { @@ -51,6 +52,7 @@ class BaseDataLayer : public Layer { DataTransformer data_transformer_; Caffe::Phase phase_; bool output_labels_; + Timer timer_forward_; }; template @@ -79,6 +81,7 @@ class BasePrefetchingDataLayer : protected: Blob prefetch_data_; Blob prefetch_label_; + Blob transformed_data_; }; template diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index fcd101165cf..23594217d91 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -1,9 +1,11 @@ #ifndef CAFFE_DATA_TRANSFORMER_HPP #define CAFFE_DATA_TRANSFORMER_HPP +#include + +#include "caffe/blob.hpp" #include "caffe/common.hpp" #include "caffe/proto/caffe.pb.h" -#include "caffe/util/io.hpp" namespace caffe { @@ -33,8 +35,15 @@ class DataTransformer { * written at the appropriate place within the blob's data. */ - void Transform(const int batch_item_id, const Datum& datum, - Dtype* transformed_data); + void Transform(const Datum& datum, Dtype* transformed_data); + + void Transform(const Datum& datum, Blob* transformed_blob); + + void Transform(const vector & datum_vector, Blob* transformed_blob); + + void Transform(const cv::Mat& cv_img, Blob* transformed_blob); + + void Transform(Blob* input_blob, Blob* transformed_blob); protected: /** @@ -47,8 +56,6 @@ class DataTransformer { */ virtual int Rand(int n); - void Transform(const int batch_item_id, const Datum& datum, - const Dtype* mean, Dtype* transformed_data); // Tranformation parameters TransformationParameter param_; diff --git a/include/caffe/util/benchmark.hpp b/include/caffe/util/benchmark.hpp index f7ef8eaf3ee..6c01ac4ee18 100644 --- a/include/caffe/util/benchmark.hpp +++ b/include/caffe/util/benchmark.hpp @@ -14,6 +14,7 @@ class Timer { void Start(); void Stop(); float MilliSeconds(); + float MicroSeconds(); float Seconds(); inline bool initted() { return initted_; } @@ -33,6 +34,7 @@ class Timer { boost::posix_time::ptime start_cpu_; boost::posix_time::ptime stop_cpu_; float elapsed_milliseconds_; + float elapsed_microseconds_; }; } // namespace caffe diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 8dd338d2603..88037c86035 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -7,6 +7,7 @@ #include "google/protobuf/message.h" #include "hdf5.h" #include "hdf5_hl.h" +#include #include "caffe/blob.hpp" #include "caffe/proto/caffe.pb.h" @@ -102,6 +103,23 @@ inline bool ReadImageToDatum(const string& filename, const int label, return ReadImageToDatum(filename, label, 0, 0, datum); } +cv::Mat ReadImageToCVMat(const string& filename, + const int height, const int width, const bool is_color); + +inline cv::Mat ReadImageToCVMat(const string& filename, + const int height, const int width) { + return ReadImageToCVMat(filename, height, width, true); +} + +inline cv::Mat ReadImageToCVMat(const string& filename, + const bool is_color) { + return ReadImageToCVMat(filename, 0, 0, is_color); +} + +inline cv::Mat ReadImageToCVMat(const string& filename) { + return ReadImageToCVMat(filename, 0, 0, true); +} + leveldb::Options GetLevelDBOptions(); template diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 553717a50da..836bf3b05c4 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -1,9 +1,12 @@ #include #include "caffe/data_transformer.hpp" +#include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" +#include + namespace caffe { template @@ -21,105 +24,365 @@ DataTransformer::DataTransformer(const TransformationParameter& param) } template -void DataTransformer::Transform(const int batch_item_id, - const Datum& datum, - Dtype* transformed_data) { - CHECK_GT(datum.channels(), 0); - CHECK_GE(datum.height(), param_.crop_size()); - CHECK_GE(datum.height(), param_.crop_size()); - const int size = datum.channels() * datum.height() * datum.width(); - if (data_mean_.count() < size) { - data_mean_.Reshape(1, datum.channels(), datum.height(), datum.width()); - LOG(INFO) << "Transform without mean"; - } - const Dtype* mean = data_mean_.cpu_data(); - Transform(batch_item_id, datum, mean, transformed_data); -} - -template -void DataTransformer::Transform(const int batch_item_id, - const Datum& datum, - const Dtype* mean, +void DataTransformer::Transform(const Datum& datum, Dtype* transformed_data) { const string& data = datum.data(); - const int channels = datum.channels(); - const int height = datum.height(); - const int width = datum.width(); + const int datum_channels = datum.channels(); + const int datum_height = datum.height(); + const int datum_width = datum.width(); const int size = datum.channels() * datum.height() * datum.width(); const int crop_size = param_.crop_size(); - const bool mirror = param_.mirror(); const Dtype scale = param_.scale(); + const bool do_mirror = param_.mirror() && Rand() % 2; + const bool has_mean_file = param_.has_mean_file(); + const bool has_unit8 = data.size() > 0; + + CHECK_GT(datum_channels, 0); + CHECK_GE(datum_height, crop_size); + CHECK_GE(datum_width, crop_size); - if (mirror && crop_size == 0) { - LOG(FATAL) << "Current implementation requires mirror and crop_size to be " - << "set at the same time."; + Dtype* mean = NULL; + if (has_mean_file) { + CHECK_EQ(datum_channels, data_mean_.channels()); + CHECK_EQ(datum_height, data_mean_.height()); + CHECK_EQ(datum_width, data_mean_.width()); + mean = data_mean_.mutable_cpu_data(); } + int h_off = 0; + int w_off = 0; + Dtype datum_element; if (crop_size) { - CHECK(data.size()) << "Image cropping only support uint8 data"; - int h_off, w_off; // We only do random crop when we do training. if (phase_ == Caffe::TRAIN) { h_off = Rand(height - crop_size + 1); w_off = Rand(width - crop_size + 1); } else { - h_off = (height - crop_size) / 2; - w_off = (width - crop_size) / 2; + h_off = (datum_height - crop_size) / 2; + w_off = (datum_width - crop_size) / 2; } - if (mirror && (Rand(2) == 1)) { - // Copy mirrored version - for (int c = 0; c < channels; ++c) { - for (int h = 0; h < crop_size; ++h) { - for (int w = 0; w < crop_size; ++w) { - int data_index = (c * height + h + h_off) * width + w + w_off; - int top_index = ((batch_item_id * channels + c) * crop_size + h) - * crop_size + (crop_size - 1 - w); - Dtype datum_element = - static_cast(static_cast(data[data_index])); + + int top_index, data_index; + for (int c = 0; c < datum_channels; ++c) { + int top_index_c = c * crop_size; + int data_index_c = c * datum_height + h_off; + for (int h = 0; h < crop_size; ++h) { + int top_index_h = (top_index_c + h) * crop_size; + int data_index_h = (data_index_c + h) * datum_width + w_off; + for (int w = 0; w < crop_size; ++w) { + data_index = data_index_h + w; + if (do_mirror) { + top_index = top_index_h + (crop_size - 1 - w); + } else { + top_index = top_index_h + w; + } + if (has_unit8) { + datum_element = + static_cast(static_cast(data[data_index])); + } else { + datum_element = datum.float_data(data_index); + } + if (has_mean_file) { transformed_data[top_index] = - (datum_element - mean[data_index]) * scale; + (datum_element - mean[data_index]) * scale; + } else { + transformed_data[top_index] = datum_element * scale; } } } + } + } else { + for (int j = 0; j < size; ++j) { + if (has_unit8) { + datum_element = + static_cast(static_cast(data[j])); + } else { + datum_element = datum.float_data(j); + } + if (has_mean_file) { + transformed_data[j] = + (datum_element - mean[j]) * scale; + } else { + transformed_data[j] = datum_element * scale; + } + } + } +} + +template +void DataTransformer::Transform(const Datum& datum, + Blob* transformed_blob) { + const string& data = datum.data(); + const int datum_channels = datum.channels(); + const int datum_height = datum.height(); + const int datum_width = datum.width(); + + const int channels = transformed_blob->channels(); + const int height = transformed_blob->height(); + const int width = transformed_blob->width(); + + CHECK_EQ(datum_channels, channels); + CHECK_GE(datum_height, height); + CHECK_GE(datum_width, width); + + CHECK_EQ(transformed_blob->num(), 1) << + "transformed_blob should have num() = 1"; + + const int crop_size = param_.crop_size(); + const Dtype scale = param_.scale(); + const bool do_mirror = param_.mirror() && Rand() % 2; + const bool has_mean_file = param_.has_mean_file(); + const bool has_unit8 = data.size()>0; + + int h_off = 0; + int w_off = 0; + if (crop_size) { + CHECK_EQ(crop_size, height); + CHECK_EQ(crop_size, width); + // We only do random crop when we do training. + if (phase_ == Caffe::TRAIN) { + h_off = Rand() % (datum_height - crop_size); + w_off = Rand() % (datum_width - crop_size); } else { - // Normal copy - for (int c = 0; c < channels; ++c) { - for (int h = 0; h < crop_size; ++h) { - for (int w = 0; w < crop_size; ++w) { - int top_index = ((batch_item_id * channels + c) * crop_size + h) - * crop_size + w; - int data_index = (c * height + h + h_off) * width + w + w_off; - Dtype datum_element = - static_cast(static_cast(data[data_index])); - transformed_data[top_index] = - (datum_element - mean[data_index]) * scale; - } + h_off = (datum_height - crop_size) / 2; + w_off = (datum_width - crop_size) / 2; + } + } else { + CHECK_EQ(datum_height, height); + CHECK_EQ(datum_width, width); + } + + Dtype* transformed_data = transformed_blob->mutable_cpu_data(); + + Dtype* mean = NULL; + if (has_mean_file) { + CHECK_EQ(datum_channels, data_mean_.channels()); + CHECK_EQ(datum_height, data_mean_.height()); + CHECK_EQ(datum_width, data_mean_.width()); + mean = data_mean_.mutable_cpu_data(); + } + + Dtype datum_element; + int top_index, data_index; + for (int c = 0; c < channels; ++c) { + int top_index_c = c * height; + int data_index_c = c * datum_height + h_off; + for (int h = 0; h < height; ++h) { + int top_index_h = (top_index_c + h) * width; + int data_index_h = (data_index_c + h) * datum_width + w_off; + for (int w = 0; w < width; ++w) { + data_index = data_index_h + w; + if (do_mirror) { + top_index = top_index_h + (width - 1 - w); + } else { + top_index = top_index_h + w; + } + if (has_unit8) { + datum_element = + static_cast(static_cast(data[data_index])); + } else { + datum_element = datum.float_data(data_index); + } + if (has_mean_file) { + transformed_data[top_index] = + (datum_element - mean[data_index]) * scale; + } else { + transformed_data[top_index] = datum_element * scale; } } } + } +} + +template +void DataTransformer::Transform(const vector & datum_vector, + Blob* transformed_blob) { + const int datum_num = datum_vector.size(); + const int num = transformed_blob->num(); + const int channels = transformed_blob->channels(); + const int height = transformed_blob->height(); + const int width = transformed_blob->width(); + + CHECK_GT(datum_num, 0) << "There is no datum to add"; + CHECK_LE(datum_num, num) << + "The size of datum_vector must be smaller than transformed_blob->num()"; + Blob uni_blob(1, channels, height, width); + for (int item_id = 0; item_id < datum_num; ++item_id) { + int offset = transformed_blob->offset(item_id); + uni_blob.set_cpu_data(transformed_blob->mutable_cpu_data() + offset); + Transform(datum_vector[item_id], &uni_blob); + } +} + +template +void DataTransformer::Transform(const cv::Mat& cv_img, + Blob* transformed_blob) { + + const int img_channels = cv_img.channels(); + const int img_height = cv_img.rows; + const int img_width = cv_img.cols; + + const int channels = transformed_blob->channels(); + const int height = transformed_blob->height(); + const int width = transformed_blob->width(); + + CHECK_EQ(img_channels, channels); + CHECK_GE(img_height, height); + CHECK_GE(img_width, width); + + CHECK_EQ(transformed_blob->num(), 1) << + "transformed_blob should have num() = 1"; + + const int crop_size = param_.crop_size(); + const Dtype scale = param_.scale(); + const bool do_mirror = param_.mirror() && Rand() % 2; + const bool has_mean_file = param_.has_mean_file(); + + int h_off = 0; + int w_off = 0; + if (crop_size) { + CHECK_EQ(crop_size, height); + CHECK_EQ(crop_size, width); + // We only do random crop when we do training. + if (phase_ == Caffe::TRAIN) { + h_off = Rand() % (img_height - crop_size); + w_off = Rand() % (img_width - crop_size); + } else { + h_off = (img_height - crop_size) / 2; + w_off = (img_width - crop_size) / 2; + } } else { - // we will prefer to use data() first, and then try float_data() - if (data.size()) { - for (int j = 0; j < size; ++j) { - Dtype datum_element = - static_cast(static_cast(data[j])); - transformed_data[j + batch_item_id * size] = - (datum_element - mean[j]) * scale; + CHECK_EQ(img_height, height); + CHECK_EQ(img_width, width); + } + + Dtype* mean = NULL; + if (has_mean_file) { + CHECK_EQ(img_channels, data_mean_.channels()); + CHECK_EQ(img_height, data_mean_.height()); + CHECK_EQ(img_width, data_mean_.width()); + mean = data_mean_.mutable_cpu_data(); + } + + Dtype* transformed_data = transformed_blob->mutable_cpu_data(); + Dtype pixel; + int top_index; + for (int c = 0; c < channels; ++c) { + int top_index_c = c * height; + int mean_index_c = c * img_height + h_off; + for (int h = 0; h < height; ++h) { + int top_index_h = (top_index_c + h) * width; + int mean_index_h = (mean_index_c + h) * img_width + w_off; + for (int w = 0; w < width; ++w) { + if (do_mirror) { + top_index = top_index_h + (width - 1 - w); + } else { + top_index = top_index_h + w; + } + pixel = static_cast( + cv_img.at(h + h_off, w + w_off)[c]); + if (has_mean_file) { + int mean_index = mean_index_h + w; + transformed_data[top_index] = (pixel - mean[mean_index]) * scale; + } else { + transformed_data[top_index] = pixel * scale; + } } + } + } +} + + +template +void DataTransformer::Transform(Blob* input_blob, + Blob* transformed_blob) { + + const int input_num = input_blob->num(); + const int input_channels = input_blob->channels(); + const int input_height = input_blob->height(); + const int input_width = input_blob->width(); + + const int num = transformed_blob->num(); + const int channels = transformed_blob->channels(); + const int height = transformed_blob->height(); + const int width = transformed_blob->width(); + const int size = transformed_blob->count(); + + CHECK_LE(input_num, num); + CHECK_EQ(input_channels, channels); + CHECK_GE(input_height, height); + CHECK_GE(input_width, width); + + const int crop_size = param_.crop_size(); + const Dtype scale = param_.scale(); + const bool do_mirror = param_.mirror() && Rand() % 2; + const bool has_mean_file = param_.has_mean_file(); + + int h_off = 0; + int w_off = 0; + if (crop_size) { + CHECK_EQ(crop_size, height); + CHECK_EQ(crop_size, width); + // We only do random crop when we do training. + if (phase_ == Caffe::TRAIN) { + h_off = Rand() % (input_height - crop_size); + w_off = Rand() % (input_width - crop_size); } else { - for (int j = 0; j < size; ++j) { - transformed_data[j + batch_item_id * size] = - (datum.float_data(j) - mean[j]) * scale; + h_off = (input_height - crop_size) / 2; + w_off = (input_width - crop_size) / 2; + } + } else { + CHECK_EQ(input_height, height); + CHECK_EQ(input_width, width); + } + + Dtype* input_data = input_blob->mutable_cpu_data(); + if (has_mean_file) { + CHECK_EQ(input_channels, data_mean_.channels()); + CHECK_EQ(input_height, data_mean_.height()); + CHECK_EQ(input_width, data_mean_.width()); + for (int n = 0; n < input_num; ++n) { + int offset = input_blob->offset(n); + caffe_sub(data_mean_.count(), input_data + offset, + data_mean_.cpu_data(), input_data + offset); + } + } + + Dtype* transformed_data = transformed_blob->mutable_cpu_data(); + + for (int n = 0; n < input_num; ++n) { + int top_index_n = n * channels; + int data_index_n = n * channels; + for (int c = 0; c < channels; ++c) { + int top_index_c = (top_index_n + c) * height; + int data_index_c = (data_index_n + c) * input_height + h_off; + for (int h = 0; h < height; ++h) { + int top_index_h = (top_index_c + h) * width; + int data_index_h = (data_index_c + h) * input_width + w_off; + if (do_mirror) { + int top_index_w = top_index_h + width - 1; + for (int w = 0; w < width; ++w) { + transformed_data[top_index_w-w] = input_data[data_index_h + w]; + } + } else { + for (int w = 0; w < width; ++w) { + transformed_data[top_index_h + w] = input_data[data_index_h + w]; + } + } } } } + if (scale!=Dtype(1)) { + DLOG(INFO) << "Scale: " << scale; + caffe_scal(size, scale, transformed_data); + } } template void DataTransformer::InitRand() { - const bool needs_rand = (phase_ == Caffe::TRAIN) && - (param_.mirror() || param_.crop_size()); + const bool needs_rand = param_.mirror() || + (phase_ == Caffe::TRAIN && param_.crop_size()); if (needs_rand) { const unsigned int rng_seed = caffe_rng_rand(); rng_.reset(new Caffe::RNG(rng_seed)); diff --git a/src/caffe/layers/base_data_layer.cpp b/src/caffe/layers/base_data_layer.cpp index 5038d532ee1..d7d475229a5 100644 --- a/src/caffe/layers/base_data_layer.cpp +++ b/src/caffe/layers/base_data_layer.cpp @@ -59,16 +59,23 @@ template void BasePrefetchingDataLayer::Forward_cpu( const vector*>& bottom, const vector*>& top) { // First, join the thread + if (this->timer_forward_.has_run_at_least_once()) { + DLOG(INFO) << "Proccessing: " << this->timer_forward_.MilliSeconds() << "ms."; + } JoinPrefetchThread(); + DLOG(INFO) << "Thread joined"; // Copy the data caffe_copy(prefetch_data_.count(), prefetch_data_.cpu_data(), top[0]->mutable_cpu_data()); + DLOG(INFO) << "Prefetch copied"; if (this->output_labels_) { caffe_copy(prefetch_label_.count(), prefetch_label_.cpu_data(), top[1]->mutable_cpu_data()); } // Start a new prefetch thread + DLOG(INFO) << "CreatePrefetchThread"; CreatePrefetchThread(); + this->timer_forward_.Start(); } #ifdef CPU_ONLY diff --git a/src/caffe/layers/base_data_layer.cu b/src/caffe/layers/base_data_layer.cu index ff1510361b6..690858f09d3 100644 --- a/src/caffe/layers/base_data_layer.cu +++ b/src/caffe/layers/base_data_layer.cu @@ -7,6 +7,7 @@ namespace caffe { template void BasePrefetchingDataLayer::Forward_gpu( const vector*>& bottom, const vector*>& top) { + DLOG(INFO) << "Processing: " << this->timer_forward_.MilliSeconds() << "ms."; // First, join the thread JoinPrefetchThread(); // Copy the data @@ -18,6 +19,7 @@ void BasePrefetchingDataLayer::Forward_gpu( } // Start a new prefetch thread CreatePrefetchThread(); + this->timer_forward_.Start(); } INSTANTIATE_CLASS(BasePrefetchingDataLayer); diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 40c48735b41..b1d7ef93806 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -8,6 +8,7 @@ #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/benchmark.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -118,12 +119,15 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, datum.channels(), crop_size, crop_size); this->prefetch_data_.Reshape(this->layer_param_.data_param().batch_size(), datum.channels(), crop_size, crop_size); + this->transformed_data_.Reshape(1, datum.channels(), crop_size, crop_size); } else { top[0]->Reshape( this->layer_param_.data_param().batch_size(), datum.channels(), datum.height(), datum.width()); this->prefetch_data_.Reshape(this->layer_param_.data_param().batch_size(), datum.channels(), datum.height(), datum.width()); + this->transformed_data_.Reshape(1, datum.channels(), + datum.height(), datum.width()); } LOG(INFO) << "output data size: " << top[0]->num() << "," << top[0]->channels() << "," << top[0]->height() << "," @@ -139,10 +143,13 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // This function is used to create a thread that prefetches the data. template void DataLayer::InternalThreadEntry() { - Datum datum; + Timer batch_timer; + batch_timer.Start(); CHECK(this->prefetch_data_.count()); + CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = NULL; // suppress warnings about uninitialized variables + if (this->output_labels_) { top_label = this->prefetch_label_.mutable_cpu_data(); } @@ -150,6 +157,7 @@ void DataLayer::InternalThreadEntry() { for (int item_id = 0; item_id < batch_size; ++item_id) { // get a blob + Datum datum; switch (this->layer_param_.data_param().backend()) { case DataParameter_DB_LEVELDB: CHECK(iter_); @@ -165,10 +173,10 @@ void DataLayer::InternalThreadEntry() { default: LOG(FATAL) << "Unknown database backend"; } - // Apply data transformations (mirror, scale, crop...) - this->data_transformer_.Transform(item_id, datum, top_data); - + int offset = this->prefetch_data_.offset(item_id); + this->transformed_data_.set_cpu_data(top_data + offset); + this->data_transformer_.Transform(datum, &(this->transformed_data_)); if (this->output_labels_) { top_label[item_id] = datum.label(); } @@ -196,6 +204,7 @@ void DataLayer::InternalThreadEntry() { LOG(FATAL) << "Unknown database backend"; } } + DLOG(INFO) << "Prefetch: " << batch_timer.MilliSeconds() << " ms."; } INSTANTIATE_CLASS(DataLayer); diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index a5d46fd0c63..e167f134f97 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -22,6 +22,8 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, const vector*>& top) { const int new_height = this->layer_param_.image_data_param().new_height(); const int new_width = this->layer_param_.image_data_param().new_width(); + const bool is_color = this->layer_param_.image_data_param().is_color(); + CHECK((new_height == 0 && new_width == 0) || (new_height > 0 && new_width > 0)) << "Current implementation requires " "new_height and new_width to be set at the same time."; @@ -53,22 +55,23 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, CHECK_GT(lines_.size(), skip) << "Not enough points to skip"; lines_id_ = skip; } - // Read a data point, and use it to initialize the top blob. - Datum datum; - CHECK(ReadImageToDatum(lines_[lines_id_].first, lines_[lines_id_].second, - new_height, new_width, &datum)); + // Read an image, and use it to initialize the top blob. + cv::Mat cv_img = ReadImageToCVMat(lines_[lines_id_].first, + new_height, new_width, is_color); + const int channels = cv_img.channels(); + const int height = cv_img.rows; + const int width = cv_img.cols; // image const int crop_size = this->layer_param_.transform_param().crop_size(); const int batch_size = this->layer_param_.image_data_param().batch_size(); if (crop_size > 0) { - top[0]->Reshape(batch_size, datum.channels(), crop_size, crop_size); - this->prefetch_data_.Reshape(batch_size, datum.channels(), crop_size, - crop_size); + top[0]->Reshape(batch_size, channels, crop_size, crop_size); + this->prefetch_data_.Reshape(batch_size, channels, crop_size, crop_size); + this->transformed_data_.Reshape(1, channels, crop_size, crop_size); } else { - top[0]->Reshape(batch_size, datum.channels(), datum.height(), - datum.width()); - this->prefetch_data_.Reshape(batch_size, datum.channels(), datum.height(), - datum.width()); + top[0]->Reshape(batch_size, channels, height, width); + this->prefetch_data_.Reshape(batch_size, channels, height, width); + this->transformed_data_.Reshape(1, channels, height, width); } LOG(INFO) << "output data size: " << top[0]->num() << "," << top[0]->channels() << "," << top[0]->height() << "," @@ -88,30 +91,35 @@ void ImageDataLayer::ShuffleImages() { // This function is used to create a thread that prefetches the data. template void ImageDataLayer::InternalThreadEntry() { - Datum datum; + Timer batch_timer; + batch_timer.Start(); CHECK(this->prefetch_data_.count()); + CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = this->prefetch_label_.mutable_cpu_data(); ImageDataParameter image_data_param = this->layer_param_.image_data_param(); const int batch_size = image_data_param.batch_size(); const int new_height = image_data_param.new_height(); const int new_width = image_data_param.new_width(); + const bool is_color = image_data_param.is_color(); // datum scales const int lines_size = lines_.size(); for (int item_id = 0; item_id < batch_size; ++item_id) { // get a blob CHECK_GT(lines_size, lines_id_); - if (!ReadImageToDatum(lines_[lines_id_].first, - lines_[lines_id_].second, - new_height, new_width, &datum)) { + cv::Mat cv_img = ReadImageToCVMat(lines_[lines_id_].first, + new_height, new_width, is_color); + if (!cv_img.data) { continue; } - - // Apply transformations (mirror, crop...) to the data - this->data_transformer_.Transform(item_id, datum, top_data); - - top_label[item_id] = datum.label(); + // Apply transformations (mirror, crop...) to the image + // this->data_transformer_.Transform(item_id, cv_img, top_data); + int offset = this->prefetch_data_.offset(item_id); + this->transformed_data_.set_cpu_data(top_data + offset); + this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + + top_label[item_id] = lines_[lines_id_].second; // go to the next iter lines_id_++; if (lines_id_ >= lines_size) { @@ -123,6 +131,7 @@ void ImageDataLayer::InternalThreadEntry() { } } } + DLOG(INFO) << "Prefetch: " << batch_timer.MilliSeconds() << " ms."; } INSTANTIATE_CLASS(ImageDataLayer); diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 269a2679777..8f1c21f5424 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -37,15 +37,15 @@ void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { CHECK_LE(num, batch_size_) << "The number of added datum must be no greater than the batch size"; - Dtype* top_data = added_data_.mutable_cpu_data(); + // Apply data transformations (mirror, scale, crop...) + this->data_transformer_.Transform(datum_vector, &added_data_); + // Copy Labels Dtype* top_label = added_label_.mutable_cpu_data(); - for (int batch_item_id = 0; batch_item_id < num; ++batch_item_id) { - // Apply data transformations (mirror, scale, crop...) - this->data_transformer_.Transform( - batch_item_id, datum_vector[batch_item_id], top_data); - top_label[batch_item_id] = datum_vector[batch_item_id].label(); + for (int item_id = 0; item_id < num; ++item_id) { + top_label[item_id] = datum_vector[item_id].label(); } // num_images == batch_size_ + Dtype* top_data = added_data_.mutable_cpu_data(); Reset(top_data, top_label, batch_size_); has_new_data_ = true; } diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 6944ae847ff..8f88177944c 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -520,6 +520,8 @@ message ImageDataParameter { // It will also resize images if new_height or new_width are not zero. optional uint32 new_height = 9 [default = 0]; optional uint32 new_width = 10 [default = 0]; + // Specify if the images are color or gray + optional bool is_color = 11 [default = true]; // DEPRECATED. See TransformationParameter. For data pre-processing, we can do // simple scaling and subtracting the data mean, if provided. Note that the // mean subtraction is always carried out before scaling. diff --git a/src/caffe/util/benchmark.cpp b/src/caffe/util/benchmark.cpp index 566d06a8f5f..76829f5b36c 100644 --- a/src/caffe/util/benchmark.cpp +++ b/src/caffe/util/benchmark.cpp @@ -55,6 +55,28 @@ void Timer::Stop() { } } + +float Timer::MicroSeconds() { + if (!has_run_at_least_once()) { + LOG(WARNING) << "Timer has never been run before reading time."; + return 0; + } + if (running()) { + Stop(); + } + if (Caffe::mode() == Caffe::GPU) { +#ifndef CPU_ONLY + CUDA_CHECK(cudaEventElapsedTime(&elapsed_microseconds_, start_gpu_, + stop_gpu_)); +#else + NO_GPU; +#endif + } else { + elapsed_microseconds_ = (stop_cpu_ - start_cpu_).total_microseconds(); + } + return elapsed_microseconds_; +} + float Timer::MilliSeconds() { if (!has_run_at_least_once()) { LOG(WARNING) << "Timer has never been run before reading time."; diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 43e5c01e36a..4c32979d82f 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -66,6 +66,23 @@ void WriteProtoToBinaryFile(const Message& proto, const char* filename) { CHECK(proto.SerializeToOstream(&output)); } +cv::Mat ReadImageToCVMat(const string& filename, + const int height, const int width, const bool is_color) { + cv::Mat cv_img; + int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR : + CV_LOAD_IMAGE_GRAYSCALE); + if (height > 0 && width > 0) { + cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag); + cv::resize(cv_img_origin, cv_img, cv::Size(width, height)); + } else { + cv_img = cv::imread(filename, cv_read_flag); + } + if (!cv_img.data) { + LOG(ERROR) << "Could not open or find file " << filename; + } + return cv_img; +} + bool ReadImageToDatum(const string& filename, const int label, const int height, const int width, const bool is_color, Datum* datum) { cv::Mat cv_img; From b26e0b336c01dbccd05c0805871724d40af7ae7a Mon Sep 17 00:00:00 2001 From: Sergio Guadarrama Date: Fri, 19 Sep 2014 17:23:39 -0700 Subject: [PATCH 067/798] Remove Datum from WindowDataLayer Conflicts: src/caffe/layers/window_data_layer.cpp --- include/caffe/data_transformer.hpp | 5 ++++- include/caffe/util/io.hpp | 7 ++++--- src/caffe/data_transformer.cpp | 21 ++++++++++----------- src/caffe/layers/data_layer.cpp | 2 +- src/caffe/layers/image_data_layer.cpp | 4 ++-- src/caffe/layers/window_data_layer.cpp | 6 ------ 6 files changed, 21 insertions(+), 24 deletions(-) diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 23594217d91..25dee187e31 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -3,6 +3,8 @@ #include +#include + #include "caffe/blob.hpp" #include "caffe/common.hpp" #include "caffe/proto/caffe.pb.h" @@ -39,7 +41,8 @@ class DataTransformer { void Transform(const Datum& datum, Blob* transformed_blob); - void Transform(const vector & datum_vector, Blob* transformed_blob); + void Transform(const vector & datum_vector, + Blob* transformed_blob); void Transform(const cv::Mat& cv_img, Blob* transformed_blob); diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 88037c86035..988305e26eb 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -1,13 +1,14 @@ #ifndef CAFFE_UTIL_IO_H_ #define CAFFE_UTIL_IO_H_ +#include + #include #include #include "google/protobuf/message.h" #include "hdf5.h" #include "hdf5_hl.h" -#include #include "caffe/blob.hpp" #include "caffe/proto/caffe.pb.h" @@ -103,10 +104,10 @@ inline bool ReadImageToDatum(const string& filename, const int label, return ReadImageToDatum(filename, label, 0, 0, datum); } -cv::Mat ReadImageToCVMat(const string& filename, +cv::Mat ReadImageToCVMat(const string& filename, const int height, const int width, const bool is_color); -inline cv::Mat ReadImageToCVMat(const string& filename, +inline cv::Mat ReadImageToCVMat(const string& filename, const int height, const int width) { return ReadImageToCVMat(filename, height, width, true); } diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 836bf3b05c4..af1db3413bf 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -1,12 +1,13 @@ +#include + #include +#include #include "caffe/data_transformer.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" -#include - namespace caffe { template @@ -117,7 +118,7 @@ void DataTransformer::Transform(const Datum& datum, const int datum_channels = datum.channels(); const int datum_height = datum.height(); const int datum_width = datum.width(); - + const int channels = transformed_blob->channels(); const int height = transformed_blob->height(); const int width = transformed_blob->width(); @@ -133,7 +134,7 @@ void DataTransformer::Transform(const Datum& datum, const Dtype scale = param_.scale(); const bool do_mirror = param_.mirror() && Rand() % 2; const bool has_mean_file = param_.has_mean_file(); - const bool has_unit8 = data.size()>0; + const bool has_unit8 = data.size() > 0; int h_off = 0; int w_off = 0; @@ -154,7 +155,7 @@ void DataTransformer::Transform(const Datum& datum, } Dtype* transformed_data = transformed_blob->mutable_cpu_data(); - + Dtype* mean = NULL; if (has_mean_file) { CHECK_EQ(datum_channels, data_mean_.channels()); @@ -218,7 +219,6 @@ void DataTransformer::Transform(const vector & datum_vector, template void DataTransformer::Transform(const cv::Mat& cv_img, Blob* transformed_blob) { - const int img_channels = cv_img.channels(); const int img_height = cv_img.rows; const int img_width = cv_img.cols; @@ -238,7 +238,7 @@ void DataTransformer::Transform(const cv::Mat& cv_img, const Dtype scale = param_.scale(); const bool do_mirror = param_.mirror() && Rand() % 2; const bool has_mean_file = param_.has_mean_file(); - + int h_off = 0; int w_off = 0; if (crop_size) { @@ -297,12 +297,11 @@ void DataTransformer::Transform(const cv::Mat& cv_img, template void DataTransformer::Transform(Blob* input_blob, Blob* transformed_blob) { - const int input_num = input_blob->num(); const int input_channels = input_blob->channels(); const int input_height = input_blob->height(); const int input_width = input_blob->width(); - + const int num = transformed_blob->num(); const int channels = transformed_blob->channels(); const int height = transformed_blob->height(); @@ -346,7 +345,7 @@ void DataTransformer::Transform(Blob* input_blob, int offset = input_blob->offset(n); caffe_sub(data_mean_.count(), input_data + offset, data_mean_.cpu_data(), input_data + offset); - } + } } Dtype* transformed_data = transformed_blob->mutable_cpu_data(); @@ -373,7 +372,7 @@ void DataTransformer::Transform(Blob* input_blob, } } } - if (scale!=Dtype(1)) { + if (scale != Dtype(1)) { DLOG(INFO) << "Scale: " << scale; caffe_scal(size, scale, transformed_data); } diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index b1d7ef93806..980e4146fc9 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -176,7 +176,7 @@ void DataLayer::InternalThreadEntry() { // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); - this->data_transformer_.Transform(datum, &(this->transformed_data_)); + this->data_transformer_.Transform(datum, &(this->transformed_data_)); if (this->output_labels_) { top_label[item_id] = datum.label(); } diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index e167f134f97..d93d56dead0 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -117,8 +117,8 @@ void ImageDataLayer::InternalThreadEntry() { // this->data_transformer_.Transform(item_id, cv_img, top_data); int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); - this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); - + this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + top_label[item_id] = lines_[lines_id_].second; // go to the next iter lines_id_++; diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 6b70aa3cf22..c01b61bec9b 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -158,12 +158,6 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, LOG(INFO) << "output data size: " << top[0]->num() << "," << top[0]->channels() << "," << top[0]->height() << "," << top[0]->width(); - // datum size - this->datum_channels_ = top[0]->channels(); - this->datum_height_ = top[0]->height(); - this->datum_width_ = top[0]->width(); - this->datum_size_ = - top[0]->channels() * top[0]->height() * top[0]->width(); // label top[1]->Reshape(batch_size, 1, 1, 1); this->prefetch_label_.Reshape(batch_size, 1, 1, 1); From 28ee58eb13d7dcb7d31fb6910c025d8132ea6716 Mon Sep 17 00:00:00 2001 From: Sergio Guadarrama Date: Fri, 19 Sep 2014 08:57:00 -0700 Subject: [PATCH 068/798] Update description data_transformer.hpp --- include/caffe/data_transformer.hpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 25dee187e31..f2cbbd08586 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -27,14 +27,21 @@ class DataTransformer { * @brief Applies the transformation defined in the data layer's * transform_param block to the data. * - * @param batch_item_id - * Datum position within the batch. This is used to compute the - * writing position in the top blob's data * @param datum * Datum containing the data to be transformed. + * @param datum_vector + * A vector of Datum containing the data to be transformed. + * @param cv_img + * cv::Mat containing the data to be transformed. + * @param input_blob + * A Blob containing the data to be transformed. * @param transformed_data - * This is meant to be the top blob's data. The transformed data will be - * written at the appropriate place within the blob's data. + * This should point to the right place in memory where the + * transformed data would be written. Assumes there is enough space + * @param transformed_blob + * This is destionation blob. It can be part of top blob's data. + * The transformed data will be written at the appropriate place + * within the blob's data. */ void Transform(const Datum& datum, Dtype* transformed_data); From d1ccbe325715646e21631829975412fc9b32a344 Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 25 Sep 2014 19:58:52 -0700 Subject: [PATCH 069/798] Refactor common code Make lint happy Conflicts: src/caffe/data_transformer.cpp --- include/caffe/data_transformer.hpp | 3 +- src/caffe/data_transformer.cpp | 147 +++++++-------------------- src/caffe/layers/base_data_layer.cpp | 3 +- 3 files changed, 41 insertions(+), 112 deletions(-) diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index f2cbbd08586..4a2afdaccce 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -44,8 +44,6 @@ class DataTransformer { * within the blob's data. */ - void Transform(const Datum& datum, Dtype* transformed_data); - void Transform(const Datum& datum, Blob* transformed_blob); void Transform(const vector & datum_vector, @@ -66,6 +64,7 @@ class DataTransformer { */ virtual int Rand(int n); + void Transform(const Datum& datum, Dtype* transformed_data); // Tranformation parameters TransformationParameter param_; diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index af1db3413bf..cdb6e10c8ab 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -31,7 +31,6 @@ void DataTransformer::Transform(const Datum& datum, const int datum_channels = datum.channels(); const int datum_height = datum.height(); const int datum_width = datum.width(); - const int size = datum.channels() * datum.height() * datum.width(); const int crop_size = param_.crop_size(); const Dtype scale = param_.scale(); @@ -51,10 +50,14 @@ void DataTransformer::Transform(const Datum& datum, mean = data_mean_.mutable_cpu_data(); } + int height = datum_height; + int width = datum_width; + int h_off = 0; int w_off = 0; - Dtype datum_element; if (crop_size) { + height = crop_size; + width = crop_size; // We only do random crop when we do training. if (phase_ == Caffe::TRAIN) { h_off = Rand(height - crop_size + 1); @@ -63,49 +66,31 @@ void DataTransformer::Transform(const Datum& datum, h_off = (datum_height - crop_size) / 2; w_off = (datum_width - crop_size) / 2; } + } - int top_index, data_index; - for (int c = 0; c < datum_channels; ++c) { - int top_index_c = c * crop_size; - int data_index_c = c * datum_height + h_off; - for (int h = 0; h < crop_size; ++h) { - int top_index_h = (top_index_c + h) * crop_size; - int data_index_h = (data_index_c + h) * datum_width + w_off; - for (int w = 0; w < crop_size; ++w) { - data_index = data_index_h + w; - if (do_mirror) { - top_index = top_index_h + (crop_size - 1 - w); - } else { - top_index = top_index_h + w; - } - if (has_unit8) { - datum_element = - static_cast(static_cast(data[data_index])); - } else { - datum_element = datum.float_data(data_index); - } - if (has_mean_file) { - transformed_data[top_index] = - (datum_element - mean[data_index]) * scale; - } else { - transformed_data[top_index] = datum_element * scale; - } + Dtype datum_element; + int top_index, data_index; + for (int c = 0; c < datum_channels; ++c) { + for (int h = 0; h < height; ++h) { + for (int w = 0; w < width; ++w) { + data_index = (c * datum_height + h_off + h) * datum_width + w_off + w; + if (do_mirror) { + top_index = (c * height + h) * width + (width - 1 - w); + } else { + top_index = (c * height + h) * width + w; } - } - } - } else { - for (int j = 0; j < size; ++j) { - if (has_unit8) { + if (has_unit8) { datum_element = - static_cast(static_cast(data[j])); - } else { - datum_element = datum.float_data(j); - } - if (has_mean_file) { - transformed_data[j] = - (datum_element - mean[j]) * scale; - } else { - transformed_data[j] = datum_element * scale; + static_cast(static_cast(data[data_index])); + } else { + datum_element = datum.float_data(data_index); + } + if (has_mean_file) { + transformed_data[top_index] = + (datum_element - mean[data_index]) * scale; + } else { + transformed_data[top_index] = datum_element * scale; + } } } } @@ -114,7 +99,6 @@ void DataTransformer::Transform(const Datum& datum, template void DataTransformer::Transform(const Datum& datum, Blob* transformed_blob) { - const string& data = datum.data(); const int datum_channels = datum.channels(); const int datum_height = datum.height(); const int datum_width = datum.width(); @@ -122,78 +106,25 @@ void DataTransformer::Transform(const Datum& datum, const int channels = transformed_blob->channels(); const int height = transformed_blob->height(); const int width = transformed_blob->width(); + const int num = transformed_blob->num(); - CHECK_EQ(datum_channels, channels); - CHECK_GE(datum_height, height); - CHECK_GE(datum_width, width); - - CHECK_EQ(transformed_blob->num(), 1) << - "transformed_blob should have num() = 1"; + CHECK_EQ(channels, datum_channels); + CHECK_LE(height, datum_height); + CHECK_LE(width, datum_width); + CHECK_GE(num, 1); const int crop_size = param_.crop_size(); - const Dtype scale = param_.scale(); - const bool do_mirror = param_.mirror() && Rand() % 2; - const bool has_mean_file = param_.has_mean_file(); - const bool has_unit8 = data.size() > 0; - int h_off = 0; - int w_off = 0; if (crop_size) { CHECK_EQ(crop_size, height); CHECK_EQ(crop_size, width); - // We only do random crop when we do training. - if (phase_ == Caffe::TRAIN) { - h_off = Rand() % (datum_height - crop_size); - w_off = Rand() % (datum_width - crop_size); - } else { - h_off = (datum_height - crop_size) / 2; - w_off = (datum_width - crop_size) / 2; - } } else { CHECK_EQ(datum_height, height); CHECK_EQ(datum_width, width); } Dtype* transformed_data = transformed_blob->mutable_cpu_data(); - - Dtype* mean = NULL; - if (has_mean_file) { - CHECK_EQ(datum_channels, data_mean_.channels()); - CHECK_EQ(datum_height, data_mean_.height()); - CHECK_EQ(datum_width, data_mean_.width()); - mean = data_mean_.mutable_cpu_data(); - } - - Dtype datum_element; - int top_index, data_index; - for (int c = 0; c < channels; ++c) { - int top_index_c = c * height; - int data_index_c = c * datum_height + h_off; - for (int h = 0; h < height; ++h) { - int top_index_h = (top_index_c + h) * width; - int data_index_h = (data_index_c + h) * datum_width + w_off; - for (int w = 0; w < width; ++w) { - data_index = data_index_h + w; - if (do_mirror) { - top_index = top_index_h + (width - 1 - w); - } else { - top_index = top_index_h + w; - } - if (has_unit8) { - datum_element = - static_cast(static_cast(data[data_index])); - } else { - datum_element = datum.float_data(data_index); - } - if (has_mean_file) { - transformed_data[top_index] = - (datum_element - mean[data_index]) * scale; - } else { - transformed_data[top_index] = datum_element * scale; - } - } - } - } + Transform(datum, transformed_data); } template @@ -226,13 +157,12 @@ void DataTransformer::Transform(const cv::Mat& cv_img, const int channels = transformed_blob->channels(); const int height = transformed_blob->height(); const int width = transformed_blob->width(); + const int num = transformed_blob->num(); - CHECK_EQ(img_channels, channels); - CHECK_GE(img_height, height); - CHECK_GE(img_width, width); - - CHECK_EQ(transformed_blob->num(), 1) << - "transformed_blob should have num() = 1"; + CHECK_EQ(channels, img_channels); + CHECK_LE(height, img_height); + CHECK_LE(width, img_width); + CHECK_GE(num, 1); const int crop_size = param_.crop_size(); const Dtype scale = param_.scale(); @@ -293,7 +223,6 @@ void DataTransformer::Transform(const cv::Mat& cv_img, } } - template void DataTransformer::Transform(Blob* input_blob, Blob* transformed_blob) { diff --git a/src/caffe/layers/base_data_layer.cpp b/src/caffe/layers/base_data_layer.cpp index d7d475229a5..5ce52f05a3c 100644 --- a/src/caffe/layers/base_data_layer.cpp +++ b/src/caffe/layers/base_data_layer.cpp @@ -60,7 +60,8 @@ void BasePrefetchingDataLayer::Forward_cpu( const vector*>& bottom, const vector*>& top) { // First, join the thread if (this->timer_forward_.has_run_at_least_once()) { - DLOG(INFO) << "Proccessing: " << this->timer_forward_.MilliSeconds() << "ms."; + DLOG(INFO) << "Proccessing: " << + this->timer_forward_.MilliSeconds() << "ms."; } JoinPrefetchThread(); DLOG(INFO) << "Thread joined"; From 497eb60b79db2922241c813945543df152145cac Mon Sep 17 00:00:00 2001 From: Sergio Guadarrama Date: Mon, 22 Sep 2014 17:07:40 -0700 Subject: [PATCH 070/798] Add flag check_size=false to convert_imageset --- tools/convert_imageset.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 7e1e83d9d0c..4ab93fd0a0c 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -36,6 +36,8 @@ DEFINE_bool(shuffle, false, DEFINE_string(backend, "lmdb", "The backend for storing the result"); DEFINE_int32(resize_width, 0, "Width images are resized to"); DEFINE_int32(resize_height, 0, "Height images are resized to"); +DEFINE_bool(check_size, false, + "When this option is on, check that all the datum have the same size"); int main(int argc, char** argv) { ::google::InitGoogleLogging(argv[0]); @@ -58,6 +60,7 @@ int main(int argc, char** argv) { } bool is_color = !FLAGS_gray; + bool check_size = FLAGS_check_size; std::ifstream infile(argv[2]); std::vector > lines; string filename; @@ -131,13 +134,15 @@ int main(int argc, char** argv) { lines[line_id].second, resize_height, resize_width, is_color, &datum)) { continue; } - if (!data_size_initialized) { - data_size = datum.channels() * datum.height() * datum.width(); - data_size_initialized = true; - } else { - const string& data = datum.data(); - CHECK_EQ(data.size(), data_size) << "Incorrect data field size " - << data.size(); + if (check_size) { + if (!data_size_initialized) { + data_size = datum.channels() * datum.height() * datum.width(); + data_size_initialized = true; + } else { + const string& data = datum.data(); + CHECK_EQ(data.size(), data_size) << "Incorrect data field size " + << data.size(); + } } // sequential snprintf(key_cstr, kMaxKeyLength, "%08d_%s", line_id, From 5527e8969567fa22d2cc7c9397585e93edcfa3d1 Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 25 Sep 2014 19:59:37 -0700 Subject: [PATCH 071/798] Added test_io and faster cv::Mat processing Conflicts: src/caffe/util/io.cpp --- include/caffe/util/io.hpp | 7 +- src/caffe/test/test_io.cpp | 143 +++++++++++++++++++++++++++++++++++++ src/caffe/util/io.cpp | 48 +++++-------- 3 files changed, 166 insertions(+), 32 deletions(-) create mode 100644 src/caffe/test/test_io.cpp diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 988305e26eb..8b83534ed54 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -99,9 +99,14 @@ inline bool ReadImageToDatum(const string& filename, const int label, return ReadImageToDatum(filename, label, height, width, true, datum); } +inline bool ReadImageToDatum(const string& filename, const int label, + const bool is_color, Datum* datum) { + return ReadImageToDatum(filename, label, 0, 0, is_color, datum); +} + inline bool ReadImageToDatum(const string& filename, const int label, Datum* datum) { - return ReadImageToDatum(filename, label, 0, 0, datum); + return ReadImageToDatum(filename, label, 0, 0, true, datum); } cv::Mat ReadImageToCVMat(const string& filename, diff --git a/src/caffe/test/test_io.cpp b/src/caffe/test/test_io.cpp new file mode 100644 index 00000000000..a01b8524918 --- /dev/null +++ b/src/caffe/test/test_io.cpp @@ -0,0 +1,143 @@ +#include + +#include "gtest/gtest.h" + +#include "caffe/common.hpp" +#include "caffe/util/io.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +class IOTest : public ::testing::Test {}; + +TEST_F(IOTest, TestReadImageToDatum) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + ReadImageToDatum(filename, 0, &datum); + EXPECT_EQ(datum.channels(), 3); + EXPECT_EQ(datum.height(), 360); + EXPECT_EQ(datum.width(), 480); +} + +TEST_F(IOTest, TestReadImageToDatumContent) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + ReadImageToDatum(filename, 0, &datum); + cv::Mat cv_img = ReadImageToCVMat(filename); + EXPECT_EQ(datum.channels(), cv_img.channels()); + EXPECT_EQ(datum.height(), cv_img.rows); + EXPECT_EQ(datum.width(), cv_img.cols); + + const string& data = datum.data(); + int index = 0; + for (int c = 0; c < datum.channels(); ++c) { + for (int h = 0; h < datum.height(); ++h) { + for (int w = 0; w < datum.width(); ++w) { + EXPECT_TRUE(data[index++] == static_cast(cv_img.at(h, w)[c])); + } + } + } +} + +TEST_F(IOTest, TestReadImageToDatumContentGray) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + const bool is_color = false; + ReadImageToDatum(filename, 0, is_color, &datum); + cv::Mat cv_img = ReadImageToCVMat(filename, is_color); + EXPECT_EQ(datum.channels(), cv_img.channels()); + EXPECT_EQ(datum.height(), cv_img.rows); + EXPECT_EQ(datum.width(), cv_img.cols); + + const string& data = datum.data(); + int index = 0; + for (int h = 0; h < datum.height(); ++h) { + for (int w = 0; w < datum.width(); ++w) { + EXPECT_TRUE(data[index++] == static_cast(cv_img.at(h, w))); + } + } +} + +TEST_F(IOTest, TestReadImageToDatumResized) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + ReadImageToDatum(filename, 0, 100, 200, &datum); + EXPECT_EQ(datum.channels(), 3); + EXPECT_EQ(datum.height(), 100); + EXPECT_EQ(datum.width(), 200); +} + + +TEST_F(IOTest, TestReadImageToDatumResizedSquare) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + ReadImageToDatum(filename, 0, 256, 256, &datum); + EXPECT_EQ(datum.channels(), 3); + EXPECT_EQ(datum.height(), 256); + EXPECT_EQ(datum.width(), 256); +} + +TEST_F(IOTest, TestReadImageToDatumGray) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + const bool is_color = false; + ReadImageToDatum(filename, 0, is_color, &datum); + EXPECT_EQ(datum.channels(), 1); + EXPECT_EQ(datum.height(), 360); + EXPECT_EQ(datum.width(), 480); +} + +TEST_F(IOTest, TestReadImageToDatumResizedGray) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + const bool is_color = false; + ReadImageToDatum(filename, 0, 256, 256, is_color, &datum); + EXPECT_EQ(datum.channels(), 1); + EXPECT_EQ(datum.height(), 256); + EXPECT_EQ(datum.width(), 256); +} + +TEST_F(IOTest, TestReadImageToCVMat) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + cv::Mat cv_img = ReadImageToCVMat(filename); + EXPECT_EQ(cv_img.channels(), 3); + EXPECT_EQ(cv_img.rows, 360); + EXPECT_EQ(cv_img.cols, 480); +} + +TEST_F(IOTest, TestReadImageToCVMatResized) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + cv::Mat cv_img = ReadImageToCVMat(filename, 100, 200); + EXPECT_EQ(cv_img.channels(), 3); + EXPECT_EQ(cv_img.rows, 100); + EXPECT_EQ(cv_img.cols, 200); +} + +TEST_F(IOTest, TestReadImageToCVMatResizedSquare) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + cv::Mat cv_img = ReadImageToCVMat(filename, 256, 256); + EXPECT_EQ(cv_img.channels(), 3); + EXPECT_EQ(cv_img.rows, 256); + EXPECT_EQ(cv_img.cols, 256); +} + +TEST_F(IOTest, TestReadImageToCVMatGray) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + const bool is_color = false; + cv::Mat cv_img = ReadImageToCVMat(filename, is_color); + EXPECT_EQ(cv_img.channels(), 1); + EXPECT_EQ(cv_img.rows, 360); + EXPECT_EQ(cv_img.cols, 480); +} + +TEST_F(IOTest, TestReadImageToCVMatResizedGray) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + const bool is_color = false; + cv::Mat cv_img = ReadImageToCVMat(filename, 256, 256, is_color); + EXPECT_EQ(cv_img.channels(), 1); + EXPECT_EQ(cv_img.rows, 256); + EXPECT_EQ(cv_img.cols, 256); +} + +} // namespace caffe diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 4c32979d82f..a576a91cb4e 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -85,46 +85,32 @@ cv::Mat ReadImageToCVMat(const string& filename, bool ReadImageToDatum(const string& filename, const int label, const int height, const int width, const bool is_color, Datum* datum) { - cv::Mat cv_img; - int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR : - CV_LOAD_IMAGE_GRAYSCALE); + cv::Mat cv_img = ReadImageToCVMat(filename, height, width, is_color); - cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag); - if (!cv_img_origin.data) { - LOG(ERROR) << "Could not open or find file " << filename; - return false; - } - if (height > 0 && width > 0) { - cv::resize(cv_img_origin, cv_img, cv::Size(width, height)); - } else { - cv_img = cv_img_origin; - } - - int num_channels = (is_color ? 3 : 1); - datum->set_channels(num_channels); + CHECK(cv_img.depth() == CV_8U) << + "Image data type must be unsigned byte"; + datum->set_channels(cv_img.channels()); datum->set_height(cv_img.rows); datum->set_width(cv_img.cols); datum->set_label(label); datum->clear_data(); datum->clear_float_data(); - string* datum_string = datum->mutable_data(); - if (is_color) { - for (int c = 0; c < num_channels; ++c) { - for (int h = 0; h < cv_img.rows; ++h) { - for (int w = 0; w < cv_img.cols; ++w) { - datum_string->push_back( - static_cast(cv_img.at(h, w)[c])); - } + int datum_channels = datum->channels(); + int datum_height = datum->height(); + int datum_width = datum->width(); + int datum_size = datum_channels * datum_height * datum_width; + std::string buffer(datum_size, ' '); + for (int h = 0; h < datum_height; ++h) { + const uchar* ptr = cv_img.ptr(h); + int img_index = 0; + for (int w = 0; w < datum_width; ++w) { + for (int c = 0; c < datum_channels; ++c) { + int datum_index = (c * datum_height + h) * datum_width + w; + buffer[datum_index] = static_cast(ptr[img_index++]); } } - } else { // Faster than repeatedly testing is_color for each pixel w/i loop - for (int h = 0; h < cv_img.rows; ++h) { - for (int w = 0; w < cv_img.cols; ++w) { - datum_string->push_back( - static_cast(cv_img.at(h, w))); - } - } } + datum->set_data(buffer); return true; } From 242546fa7cfdb26805202d03129340183e7e8ddb Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 24 Sep 2014 07:36:13 -0700 Subject: [PATCH 072/798] Add CVMatToDatum --- include/caffe/util/io.hpp | 2 + src/caffe/data_transformer.cpp | 74 ++-------------------------------- src/caffe/util/io.cpp | 12 +++++- 3 files changed, 15 insertions(+), 73 deletions(-) diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 8b83534ed54..2032b1f3195 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -126,6 +126,8 @@ inline cv::Mat ReadImageToCVMat(const string& filename) { return ReadImageToCVMat(filename, 0, 0, true); } +void CVMatToDatum(const cv::Mat& cv_img, Datum* datum); + leveldb::Options GetLevelDBOptions(); template diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index cdb6e10c8ab..f001f1caea3 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -150,77 +150,9 @@ void DataTransformer::Transform(const vector & datum_vector, template void DataTransformer::Transform(const cv::Mat& cv_img, Blob* transformed_blob) { - const int img_channels = cv_img.channels(); - const int img_height = cv_img.rows; - const int img_width = cv_img.cols; - - const int channels = transformed_blob->channels(); - const int height = transformed_blob->height(); - const int width = transformed_blob->width(); - const int num = transformed_blob->num(); - - CHECK_EQ(channels, img_channels); - CHECK_LE(height, img_height); - CHECK_LE(width, img_width); - CHECK_GE(num, 1); - - const int crop_size = param_.crop_size(); - const Dtype scale = param_.scale(); - const bool do_mirror = param_.mirror() && Rand() % 2; - const bool has_mean_file = param_.has_mean_file(); - - int h_off = 0; - int w_off = 0; - if (crop_size) { - CHECK_EQ(crop_size, height); - CHECK_EQ(crop_size, width); - // We only do random crop when we do training. - if (phase_ == Caffe::TRAIN) { - h_off = Rand() % (img_height - crop_size); - w_off = Rand() % (img_width - crop_size); - } else { - h_off = (img_height - crop_size) / 2; - w_off = (img_width - crop_size) / 2; - } - } else { - CHECK_EQ(img_height, height); - CHECK_EQ(img_width, width); - } - - Dtype* mean = NULL; - if (has_mean_file) { - CHECK_EQ(img_channels, data_mean_.channels()); - CHECK_EQ(img_height, data_mean_.height()); - CHECK_EQ(img_width, data_mean_.width()); - mean = data_mean_.mutable_cpu_data(); - } - - Dtype* transformed_data = transformed_blob->mutable_cpu_data(); - Dtype pixel; - int top_index; - for (int c = 0; c < channels; ++c) { - int top_index_c = c * height; - int mean_index_c = c * img_height + h_off; - for (int h = 0; h < height; ++h) { - int top_index_h = (top_index_c + h) * width; - int mean_index_h = (mean_index_c + h) * img_width + w_off; - for (int w = 0; w < width; ++w) { - if (do_mirror) { - top_index = top_index_h + (width - 1 - w); - } else { - top_index = top_index_h + w; - } - pixel = static_cast( - cv_img.at(h + h_off, w + w_off)[c]); - if (has_mean_file) { - int mean_index = mean_index_h + w; - transformed_data[top_index] = (pixel - mean[mean_index]) * scale; - } else { - transformed_data[top_index] = pixel * scale; - } - } - } - } + Datum datum; + CVMatToDatum(cv_img, &datum); + Transform(datum, transformed_blob); } template diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index a576a91cb4e..047b14014e4 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -86,13 +86,21 @@ cv::Mat ReadImageToCVMat(const string& filename, bool ReadImageToDatum(const string& filename, const int label, const int height, const int width, const bool is_color, Datum* datum) { cv::Mat cv_img = ReadImageToCVMat(filename, height, width, is_color); + if (cv_img.data) { + CVMatToDatum(cv_img, datum); + datum->set_label(label); + return true; + } else { + return false; + } +} +void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) { CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte"; datum->set_channels(cv_img.channels()); datum->set_height(cv_img.rows); datum->set_width(cv_img.cols); - datum->set_label(label); datum->clear_data(); datum->clear_float_data(); int datum_channels = datum->channels(); @@ -111,9 +119,9 @@ bool ReadImageToDatum(const string& filename, const int label, } } datum->set_data(buffer); - return true; } + leveldb::Options GetLevelDBOptions() { // In default, we will return the leveldb option and set the max open files // in order to avoid using up the operating system's limit. From 760ffaa51475e95c9e64ec858a7d0c94fd7937ae Mon Sep 17 00:00:00 2001 From: Sergio Date: Fri, 3 Oct 2014 08:19:40 -0700 Subject: [PATCH 073/798] Added global_pooling to set the kernel size equal to the bottom size Added check for padding and stride with global_pooling --- include/caffe/vision_layers.hpp | 1 + src/caffe/layers/pooling_layer.cpp | 32 ++++++++++++++++++++++----- src/caffe/proto/caffe.proto | 3 +++ src/caffe/test/test_pooling_layer.cpp | 14 ++++++++++++ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 58ac5344da4..c803cd72449 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -319,6 +319,7 @@ class PoolingLayer : public Layer { int channels_; int height_, width_; int pooled_height_, pooled_width_; + bool global_pooling_; Blob rand_idx_; Blob max_idx_; }; diff --git a/src/caffe/layers/pooling_layer.cpp b/src/caffe/layers/pooling_layer.cpp index 26c92c13b63..2bfbb01fcec 100644 --- a/src/caffe/layers/pooling_layer.cpp +++ b/src/caffe/layers/pooling_layer.cpp @@ -17,12 +17,18 @@ template void PoolingLayer::LayerSetUp(const vector*>& bottom, const vector*>& top) { PoolingParameter pool_param = this->layer_param_.pooling_param(); - CHECK(!pool_param.has_kernel_size() != + if (pool_param.global_pooling()) { + CHECK(!(pool_param.has_kernel_size() || + pool_param.has_kernel_h() || pool_param.has_kernel_w())) + << "With Global_pooling: true Filter size cannot specified"; + } else { + CHECK(!pool_param.has_kernel_size() != !(pool_param.has_kernel_h() && pool_param.has_kernel_w())) << "Filter size is kernel_size OR kernel_h and kernel_w; not both"; - CHECK(pool_param.has_kernel_size() || + CHECK(pool_param.has_kernel_size() || (pool_param.has_kernel_h() && pool_param.has_kernel_w())) << "For non-square filters both kernel_h and kernel_w are required."; + } CHECK((!pool_param.has_pad() && pool_param.has_pad_h() && pool_param.has_pad_w()) || (!pool_param.has_pad_h() && !pool_param.has_pad_w())) @@ -31,11 +37,17 @@ void PoolingLayer::LayerSetUp(const vector*>& bottom, && pool_param.has_stride_w()) || (!pool_param.has_stride_h() && !pool_param.has_stride_w())) << "Stride is stride OR stride_h and stride_w are required."; - if (pool_param.has_kernel_size()) { - kernel_h_ = kernel_w_ = pool_param.kernel_size(); + global_pooling_ = pool_param.global_pooling(); + if (global_pooling_) { + kernel_h_ = bottom[0]->height(); + kernel_w_ = bottom[0]->width(); } else { - kernel_h_ = pool_param.kernel_h(); - kernel_w_ = pool_param.kernel_w(); + if (pool_param.has_kernel_size()) { + kernel_h_ = kernel_w_ = pool_param.kernel_size(); + } else { + kernel_h_ = pool_param.kernel_h(); + kernel_w_ = pool_param.kernel_w(); + } } CHECK_GT(kernel_h_, 0) << "Filter dimensions cannot be zero."; CHECK_GT(kernel_w_, 0) << "Filter dimensions cannot be zero."; @@ -51,6 +63,10 @@ void PoolingLayer::LayerSetUp(const vector*>& bottom, stride_h_ = pool_param.stride_h(); stride_w_ = pool_param.stride_w(); } + if (global_pooling_) { + CHECK(pad_h_ == 0 && pad_w_ == 0 && stride_h_ == 1 && stride_w_ == 1) + << "With Global_pooling: true; only pad = 0 and stride = 1"; + } if (pad_h_ != 0 || pad_w_ != 0) { CHECK(this->layer_param_.pooling_param().pool() == PoolingParameter_PoolMethod_AVE @@ -68,6 +84,10 @@ void PoolingLayer::Reshape(const vector*>& bottom, channels_ = bottom[0]->channels(); height_ = bottom[0]->height(); width_ = bottom[0]->width(); + if (global_pooling_) { + kernel_h_ = bottom[0]->height(); + kernel_w_ = bottom[0]->width(); + } pooled_height_ = static_cast(ceil(static_cast( height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1; pooled_width_ = static_cast(ceil(static_cast( diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 6944ae847ff..9374abe5b70 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -602,6 +602,9 @@ message PoolingParameter { CUDNN = 2; } optional Engine engine = 11 [default = DEFAULT]; + // If global_pooling then it will pool over the size of the bottom by doing + // kernel_h = bottom->height and kernel_w = bottom->width + optional bool global_pooling = 12 [default = false]; } // Message that stores parameters used by PowerLayer diff --git a/src/caffe/test/test_pooling_layer.cpp b/src/caffe/test/test_pooling_layer.cpp index f52073c4e6f..435caa8381e 100644 --- a/src/caffe/test/test_pooling_layer.cpp +++ b/src/caffe/test/test_pooling_layer.cpp @@ -400,6 +400,20 @@ TYPED_TEST(PoolingLayerTest, TestSetupPadded) { EXPECT_EQ(this->blob_top_->width(), 3); } +TYPED_TEST(PoolingLayerTest, TestSetupGlobalPooling) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_global_pooling(true); + pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); + EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); + EXPECT_EQ(this->blob_top_->height(), 1); + EXPECT_EQ(this->blob_top_->width(), 1); +} + /* TYPED_TEST(PoolingLayerTest, PrintBackward) { LayerParameter layer_param; From 2fcbc9d169d80c24e7acf3eedba90a94622f00ec Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Wed, 1 Oct 2014 11:50:42 -0700 Subject: [PATCH 074/798] [fix] translate g++ whole archive to force load for clang++ compilation To build with the layer registry clang++ requires `-force_load` as g++ requires `--whole-archive`. --- Makefile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b0b25150eb9..aac8205ccb0 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,6 @@ endif LIB_BUILD_DIR := $(BUILD_DIR)/lib STATIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).a DYNAMIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so -STATIC_LINK_COMMAND := -Wl,--whole-archive $(STATIC_NAME) -Wl,--no-whole-archive ############################## # Get all source files @@ -228,6 +227,7 @@ else ifeq ($(UNAME), Darwin) OSX := 1 endif +# Linux ifeq ($(LINUX), 1) CXX ?= /usr/bin/g++ GCCVERSION := $(shell $(CXX) -dumpversion | cut -f1,2 -d.) @@ -259,6 +259,15 @@ ifdef CUSTOM_CXX CXX := $(CUSTOM_CXX) endif +# Static linking +ifneq (,$(findstring clang++,$(CXX))) + STATIC_LINK_COMMAND := -Wl,-force_load $(STATIC_NAME) +else ifneq (,$(findstring g++,$(CXX))) + STATIC_LINK_COMMAND := -Wl,--whole-archive $(STATIC_NAME) -Wl,--no-whole-archive +else + $(error Cannot static link with the $(CXX) compiler.) +endif + # Debugging ifeq ($(DEBUG), 1) COMMON_FLAGS += -DDEBUG -g -O0 From 1e9681f915e157b87aa1bdc0197b001078122405 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 3 Oct 2014 13:30:21 -0700 Subject: [PATCH 075/798] [fix] set cmake static link command for clang++ and g++ globally --- CMakeLists.txt | 9 ++++++++- python/CMakeLists.txt | 1 - src/caffe/test/CMakeLists.txt | 36 +++++++++++++++++------------------ tools/CMakeLists.txt | 3 +-- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cb7d583504..6de6b102981 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,13 @@ set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -fPIC) # set global flags set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) # set debug flags set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) # set release flags +# Link Flags +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # clang++ + set(CAFFE_STATIC_LINK -Wl,-force_load $(STATIC_NAME)) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # g++ + set(CAFFE_STATIC_LINK -Wl,--whole-archive caffe -Wl,--no-whole-archive) +endif() + # Global Definitions if(CPU_ONLY) add_definitions(-DCPU_ONLY) @@ -77,7 +84,7 @@ endif() set(LINT_TARGET lint) set(LINT_SCRIPT ${CMAKE_SCRIPT_DIR}/lint.cmake) add_custom_target( - ${LINT_TARGET} + ${LINT_TARGET} COMMAND ${CMAKE_COMMAND} -P ${LINT_SCRIPT} ) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 5024dbfea5d..343c863adf5 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -10,7 +10,6 @@ include_directories(${Boost_INCLUDE_DIRS}) file(GLOB_RECURSE Python_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) -set(CAFFE_WHOLE_LINK -Wl,--whole-archive caffe -Wl,--no-whole-archive) add_library(pycaffe SHARED ${Python_SOURCES}) target_link_libraries(pycaffe caffe ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}) diff --git a/src/caffe/test/CMakeLists.txt b/src/caffe/test/CMakeLists.txt index 7b308bff168..ce0aa4c5148 100644 --- a/src/caffe/test/CMakeLists.txt +++ b/src/caffe/test/CMakeLists.txt @@ -32,12 +32,12 @@ set(IN_FILES # generator input files ${TEST_DATA_FILE} ) -foreach(in_file ${IN_FILES}) +foreach(in_file ${IN_FILES}) configure_file( ${in_file}${IN_EXT} ${in_file}${GEN_EXT} - ) -endforeach() + ) +endforeach() include_directories( ${Caffe_SOURCE_DIR} @@ -45,26 +45,24 @@ include_directories( ) # Remove main from test sources and prepare an Object lib with main -file(GLOB TEST_MAIN ${TEST_MAIN}) +file(GLOB TEST_MAIN ${TEST_MAIN}) list(REMOVE_ITEM TEST_CPP_SOURCES ${TEST_MAIN}) add_library(main_obj EXCLUDE_FROM_ALL OBJECT ${TEST_MAIN}) -set(CAFFE_WHOLE_LINK -Wl,--whole-archive caffe -Wl,--no-whole-archive) - # Build each test separately from *.cpp files foreach(source ${TEST_CPP_SOURCES}) test_name(TEST_NAME ${source}) - + # add_library(${TEST_NAME}.obj EXCLUDE_FROM_ALL OBJECT ${source}) set(TEST_OBJ_LIB $) - - add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_OBJ_LIB} $) - target_link_libraries(${TEST_NAME} gtest ${CAFFE_WHOLE_LINK}) - + + add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_OBJ_LIB} $) + target_link_libraries(${TEST_NAME} gtest ${CAFFE_STATIC_LINK}) + # output dir set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) - + # Targets and object libs set(TEST_TARGETS ${TEST_TARGETS} ${TEST_NAME}) set(TEST_OBJ_LIBS ${TEST_OBJ_LIBS} ${TEST_OBJ_LIB}) @@ -73,15 +71,15 @@ endforeach() # Build each test separately from *.cu files foreach(source ${TEST_CU_SOURCES}) test_name(TEST_NAME ${source}) - + cuda_add_library(${TEST_NAME}.lib EXCLUDE_FROM_ALL ${source}) - - add_executable(${TEST_NAME} EXCLUDE_FROM_ALL $) - target_link_libraries(${TEST_NAME} ${TEST_NAME}.lib gtest ${CAFFE_WHOLE_LINK}) - + + add_executable(${TEST_NAME} EXCLUDE_FROM_ALL $) + target_link_libraries(${TEST_NAME} ${TEST_NAME}.lib gtest ${CAFFE_STATIC_LINK}) + # output dir set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) - + # Targets and object libs set(TEST_TARGETS ${TEST_TARGETS} ${TEST_NAME}) set(TEST_CU_LIBS ${TEST_CU_LIBS} ${TEST_NAME}.lib) @@ -92,7 +90,7 @@ add_executable(${ALL_TEST} EXCLUDE_FROM_ALL ${TEST_OBJ_LIBS} $ Date: Fri, 3 Oct 2014 13:44:36 -0700 Subject: [PATCH 076/798] [fix] bend pycaffe to the whims of OS X header order To build pycaffe on OS X the boost headers need to be in this order. OS X is a bewildering platform. --- python/caffe/_caffe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 5a8d99d3f22..5af4c94cbaf 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -2,8 +2,8 @@ // caffe::Caffe functions so that one could easily call it from Python. // Note that for Python, we will simply use float as the data type. -#include #include +#include // NOLINT(build/include_alpha) // these need to be included after boost on OS X #include // NOLINT(build/include_order) From aee2efb0019b07cf9323a96e8f0fba469bead369 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 3 Oct 2014 13:53:52 -0700 Subject: [PATCH 077/798] [fix] include Python.h instead of re-ordering for pycaffe build on OS X --- python/caffe/_caffe.cpp | 4 +++- python/caffe/_caffe.hpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 5af4c94cbaf..133eb98b5d2 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -2,8 +2,10 @@ // caffe::Caffe functions so that one could easily call it from Python. // Note that for Python, we will simply use float as the data type. +#include // NOLINT(build/include_alpha) + +#include #include -#include // NOLINT(build/include_alpha) // these need to be included after boost on OS X #include // NOLINT(build/include_order) diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index fc7be49af1b..a4e0557c590 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -3,6 +3,8 @@ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include // NOLINT(build/include_alpha) + #include #include #include From 408c258ccd870c108d4a5326193c79b9e0f8c744 Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 24 Sep 2014 12:39:59 -0700 Subject: [PATCH 078/798] Add ReadImageToDatumReference to test_io --- src/caffe/data_transformer.cpp | 79 ++++++++++++++++++++++++++++-- src/caffe/test/test_io.cpp | 87 ++++++++++++++++++++++++++++++++++ src/caffe/util/io.cpp | 11 +++-- 3 files changed, 169 insertions(+), 8 deletions(-) diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index f001f1caea3..d3be1d8c696 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -150,9 +150,82 @@ void DataTransformer::Transform(const vector & datum_vector, template void DataTransformer::Transform(const cv::Mat& cv_img, Blob* transformed_blob) { - Datum datum; - CVMatToDatum(cv_img, &datum); - Transform(datum, transformed_blob); + // Datum datum; + // CVMatToDatum(cv_img, &datum); + // Transform(datum, transformed_blob); + + const int img_channels = cv_img.channels(); + const int img_height = cv_img.rows; + const int img_width = cv_img.cols; + + const int channels = transformed_blob->channels(); + const int height = transformed_blob->height(); + const int width = transformed_blob->width(); + + CHECK_EQ(img_channels, channels); + CHECK_GE(img_height, height); + CHECK_GE(img_width, width); + + CHECK_EQ(transformed_blob->num(), 1) << + "transformed_blob should have num() = 1"; + + const int crop_size = param_.crop_size(); + const Dtype scale = param_.scale(); + const bool do_mirror = param_.mirror() && Rand() % 2; + const bool has_mean_file = param_.has_mean_file(); + + int h_off = 0; + int w_off = 0; + if (crop_size) { + CHECK_EQ(crop_size, height); + CHECK_EQ(crop_size, width); + // We only do random crop when we do training. + if (phase_ == Caffe::TRAIN) { + h_off = Rand() % (img_height - crop_size); + w_off = Rand() % (img_width - crop_size); + } else { + h_off = (img_height - crop_size) / 2; + w_off = (img_width - crop_size) / 2; + } + } else { + CHECK_EQ(img_height, height); + CHECK_EQ(img_width, width); + } + + Dtype* mean = NULL; + if (has_mean_file) { + CHECK_EQ(img_channels, data_mean_.channels()); + CHECK_EQ(img_height, data_mean_.height()); + CHECK_EQ(img_width, data_mean_.width()); + mean = data_mean_.mutable_cpu_data(); + } + + Dtype* transformed_data = transformed_blob->mutable_cpu_data(); + Dtype pixel; + int top_index; + for (int c = 0; c < channels; ++c) { + int top_index_c = c * height; + int mean_index_c = c * img_height + h_off; + for (int h = 0; h < height; ++h) { + int top_index_h = (top_index_c + h) * width; + int mean_index_h = (mean_index_c + h) * img_width + w_off; + for (int w = 0; w < width; ++w) { + if (do_mirror) { + top_index = top_index_h + (width - 1 - w); + } else { + top_index = top_index_h + w; + } + pixel = static_cast( + cv_img.at(h + h_off, w + w_off)[c]); + if (has_mean_file) { + int mean_index = mean_index_h + w; + transformed_data[top_index] = (pixel - mean[mean_index]) * scale; + } else { + transformed_data[top_index] = pixel * scale; + } + } + } + } } template diff --git a/src/caffe/test/test_io.cpp b/src/caffe/test/test_io.cpp index a01b8524918..5e85af75654 100644 --- a/src/caffe/test/test_io.cpp +++ b/src/caffe/test/test_io.cpp @@ -1,3 +1,8 @@ +#include +#include +#include +#include + #include #include "gtest/gtest.h" @@ -11,6 +16,51 @@ namespace caffe { class IOTest : public ::testing::Test {}; +bool ReadImageToDatumReference(const string& filename, const int label, + const int height, const int width, const bool is_color, Datum* datum) { + cv::Mat cv_img; + int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR : + CV_LOAD_IMAGE_GRAYSCALE); + + cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag); + if (!cv_img_origin.data) { + LOG(ERROR) << "Could not open or find file " << filename; + return false; + } + if (height > 0 && width > 0) { + cv::resize(cv_img_origin, cv_img, cv::Size(width, height)); + } else { + cv_img = cv_img_origin; + } + + int num_channels = (is_color ? 3 : 1); + datum->set_channels(num_channels); + datum->set_height(cv_img.rows); + datum->set_width(cv_img.cols); + datum->set_label(label); + datum->clear_data(); + datum->clear_float_data(); + string* datum_string = datum->mutable_data(); + if (is_color) { + for (int c = 0; c < num_channels; ++c) { + for (int h = 0; h < cv_img.rows; ++h) { + for (int w = 0; w < cv_img.cols; ++w) { + datum_string->push_back( + static_cast(cv_img.at(h, w)[c])); + } + } + } + } else { // Faster than repeatedly testing is_color for each pixel w/i loop + for (int h = 0; h < cv_img.rows; ++h) { + for (int w = 0; w < cv_img.cols; ++w) { + datum_string->push_back( + static_cast(cv_img.at(h, w))); + } + } + } + return true; +} + TEST_F(IOTest, TestReadImageToDatum) { string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; Datum datum; @@ -20,6 +70,43 @@ TEST_F(IOTest, TestReadImageToDatum) { EXPECT_EQ(datum.width(), 480); } +TEST_F(IOTest, TestReadImageToDatumReference) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum, datum_ref; + ReadImageToDatum(filename, 0, 0, 0, true, &datum); + ReadImageToDatumReference(filename, 0, 0, 0, true, &datum_ref); + EXPECT_EQ(datum.channels(), datum_ref.channels()); + EXPECT_EQ(datum.height(), datum_ref.height()); + EXPECT_EQ(datum.width(), datum_ref.width()); + EXPECT_EQ(datum.data().size(), datum_ref.data().size()); + + const string& data = datum.data(); + const string& data_ref = datum.data(); + + for (int i = 0; i < datum.data().size(); ++i) { + EXPECT_TRUE(data[i] == data_ref[i]); + } +} + + +TEST_F(IOTest, TestReadImageToDatumReferenceResized) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum, datum_ref; + ReadImageToDatum(filename, 0, 100, 200, true, &datum); + ReadImageToDatumReference(filename, 0, 100, 200, true, &datum_ref); + EXPECT_EQ(datum.channels(), datum_ref.channels()); + EXPECT_EQ(datum.height(), datum_ref.height()); + EXPECT_EQ(datum.width(), datum_ref.width()); + EXPECT_EQ(datum.data().size(), datum_ref.data().size()); + + const string& data = datum.data(); + const string& data_ref = datum.data(); + + for (int i = 0; i < datum.data().size(); ++i) { + EXPECT_TRUE(data[i] == data_ref[i]); + } +} + TEST_F(IOTest, TestReadImageToDatumContent) { string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; Datum datum; diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 047b14014e4..36510d61d40 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -71,14 +71,15 @@ cv::Mat ReadImageToCVMat(const string& filename, cv::Mat cv_img; int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR : CV_LOAD_IMAGE_GRAYSCALE); + cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag); + if (!cv_img_origin.data) { + LOG(ERROR) << "Could not open or find file " << filename; + return cv_img_origin; + } if (height > 0 && width > 0) { - cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag); cv::resize(cv_img_origin, cv_img, cv::Size(width, height)); } else { - cv_img = cv::imread(filename, cv_read_flag); - } - if (!cv_img.data) { - LOG(ERROR) << "Could not open or find file " << filename; + cv_img = cv_img_origin; } return cv_img; } From 0a96030ba66e4476cc6b153863e409200989883d Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 24 Sep 2014 13:41:11 -0700 Subject: [PATCH 079/798] Added more tests to test_io for CVMatToDatum --- src/caffe/data_transformer.cpp | 79 ++-------------------------------- src/caffe/test/test_io.cpp | 48 +++++++++++++++++++++ 2 files changed, 51 insertions(+), 76 deletions(-) diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index d3be1d8c696..f001f1caea3 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -150,82 +150,9 @@ void DataTransformer::Transform(const vector & datum_vector, template void DataTransformer::Transform(const cv::Mat& cv_img, Blob* transformed_blob) { - // Datum datum; - // CVMatToDatum(cv_img, &datum); - // Transform(datum, transformed_blob); - - const int img_channels = cv_img.channels(); - const int img_height = cv_img.rows; - const int img_width = cv_img.cols; - - const int channels = transformed_blob->channels(); - const int height = transformed_blob->height(); - const int width = transformed_blob->width(); - - CHECK_EQ(img_channels, channels); - CHECK_GE(img_height, height); - CHECK_GE(img_width, width); - - CHECK_EQ(transformed_blob->num(), 1) << - "transformed_blob should have num() = 1"; - - const int crop_size = param_.crop_size(); - const Dtype scale = param_.scale(); - const bool do_mirror = param_.mirror() && Rand() % 2; - const bool has_mean_file = param_.has_mean_file(); - - int h_off = 0; - int w_off = 0; - if (crop_size) { - CHECK_EQ(crop_size, height); - CHECK_EQ(crop_size, width); - // We only do random crop when we do training. - if (phase_ == Caffe::TRAIN) { - h_off = Rand() % (img_height - crop_size); - w_off = Rand() % (img_width - crop_size); - } else { - h_off = (img_height - crop_size) / 2; - w_off = (img_width - crop_size) / 2; - } - } else { - CHECK_EQ(img_height, height); - CHECK_EQ(img_width, width); - } - - Dtype* mean = NULL; - if (has_mean_file) { - CHECK_EQ(img_channels, data_mean_.channels()); - CHECK_EQ(img_height, data_mean_.height()); - CHECK_EQ(img_width, data_mean_.width()); - mean = data_mean_.mutable_cpu_data(); - } - - Dtype* transformed_data = transformed_blob->mutable_cpu_data(); - Dtype pixel; - int top_index; - for (int c = 0; c < channels; ++c) { - int top_index_c = c * height; - int mean_index_c = c * img_height + h_off; - for (int h = 0; h < height; ++h) { - int top_index_h = (top_index_c + h) * width; - int mean_index_h = (mean_index_c + h) * img_width + w_off; - for (int w = 0; w < width; ++w) { - if (do_mirror) { - top_index = top_index_h + (width - 1 - w); - } else { - top_index = top_index_h + w; - } - pixel = static_cast( - cv_img.at(h + h_off, w + w_off)[c]); - if (has_mean_file) { - int mean_index = mean_index_h + w; - transformed_data[top_index] = (pixel - mean[mean_index]) * scale; - } else { - transformed_data[top_index] = pixel * scale; - } - } - } - } + Datum datum; + CVMatToDatum(cv_img, &datum); + Transform(datum, transformed_blob); } template diff --git a/src/caffe/test/test_io.cpp b/src/caffe/test/test_io.cpp index 5e85af75654..affbfd88f8e 100644 --- a/src/caffe/test/test_io.cpp +++ b/src/caffe/test/test_io.cpp @@ -227,4 +227,52 @@ TEST_F(IOTest, TestReadImageToCVMatResizedGray) { EXPECT_EQ(cv_img.cols, 256); } +TEST_F(IOTest, TestCVMatToDatum) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + cv::Mat cv_img = ReadImageToCVMat(filename); + Datum datum; + CVMatToDatum(cv_img, &datum); + EXPECT_EQ(datum.channels(), 3); + EXPECT_EQ(datum.height(), 360); + EXPECT_EQ(datum.width(), 480); +} + +TEST_F(IOTest, TestCVMatToDatumContent) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + cv::Mat cv_img = ReadImageToCVMat(filename); + Datum datum; + CVMatToDatum(cv_img, &datum); + Datum datum_ref; + ReadImageToDatum(filename, 0, &datum_ref); + EXPECT_EQ(datum.channels(), datum_ref.channels()); + EXPECT_EQ(datum.height(), datum_ref.height()); + EXPECT_EQ(datum.width(), datum_ref.width()); + EXPECT_EQ(datum.data().size(), datum_ref.data().size()); + + const string& data = datum.data(); + const string& data_ref = datum_ref.data(); + for (int i = 0; i < datum.data().size(); ++i) { + EXPECT_TRUE(data[i] == data_ref[i]); + } +} + +TEST_F(IOTest, TestCVMatToDatumReference) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + cv::Mat cv_img = ReadImageToCVMat(filename); + Datum datum; + CVMatToDatum(cv_img, &datum); + Datum datum_ref; + ReadImageToDatumReference(filename, 0, 0, 0, true, &datum_ref); + EXPECT_EQ(datum.channels(), datum_ref.channels()); + EXPECT_EQ(datum.height(), datum_ref.height()); + EXPECT_EQ(datum.width(), datum_ref.width()); + EXPECT_EQ(datum.data().size(), datum_ref.data().size()); + + const string& data = datum.data(); + const string& data_ref = datum_ref.data(); + for (int i = 0; i < datum.data().size(); ++i) { + EXPECT_TRUE(data[i] == data_ref[i]); + } +} + } // namespace caffe From a9572b1bbe8dca87ec3e31804fee49301e066a94 Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 24 Sep 2014 14:58:11 -0700 Subject: [PATCH 080/798] Added mean_value to specify mean channel substraction Added example of use to models/bvlc_reference_caffenet/train_val_mean_value.prototxt --- include/caffe/data_transformer.hpp | 1 + .../train_val_mean_value.prototxt | 348 ++++++++++++++++++ src/caffe/data_transformer.cpp | 44 ++- src/caffe/proto/caffe.proto | 5 + src/caffe/test/test_io.cpp | 3 +- 5 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 models/bvlc_reference_caffenet/train_val_mean_value.prototxt diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 4a2afdaccce..735f1d586c9 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -72,6 +72,7 @@ class DataTransformer { shared_ptr rng_; Caffe::Phase phase_; Blob data_mean_; + vector mean_values_; }; } // namespace caffe diff --git a/models/bvlc_reference_caffenet/train_val_mean_value.prototxt b/models/bvlc_reference_caffenet/train_val_mean_value.prototxt new file mode 100644 index 00000000000..c2fbb7118ca --- /dev/null +++ b/models/bvlc_reference_caffenet/train_val_mean_value.prototxt @@ -0,0 +1,348 @@ +name: "CaffeNet" +layers { + name: "data" + type: DATA + top: "data" + top: "label" + data_param { + source: "examples/imagenet/ilsvrc12_train_leveldb" + batch_size: 256 + } + transform_param { + crop_size: 227 + mean_value: 104 + mean_value: 117 + mean_value: 123 + mirror: true + } + include: { phase: TRAIN } +} +layers { + name: "data" + type: DATA + top: "data" + top: "label" + data_param { + source: "examples/imagenet/ilsvrc12_val_leveldb" + batch_size: 50 + } + transform_param { + crop_size: 227 + mean_value: 104 + mean_value: 117 + mean_value: 123 + mirror: false + } + include: { phase: TEST } +} +layers { + name: "conv1" + type: CONVOLUTION + bottom: "data" + top: "conv1" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 11 + stride: 4 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + name: "relu1" + type: RELU + bottom: "conv1" + top: "conv1" +} +layers { + name: "pool1" + type: POOLING + bottom: "conv1" + top: "pool1" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm1" + type: LRN + bottom: "pool1" + top: "norm1" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv2" + type: CONVOLUTION + bottom: "norm1" + top: "conv2" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 2 + kernel_size: 5 + group: 2 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu2" + type: RELU + bottom: "conv2" + top: "conv2" +} +layers { + name: "pool2" + type: POOLING + bottom: "conv2" + top: "pool2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm2" + type: LRN + bottom: "pool2" + top: "norm2" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv3" + type: CONVOLUTION + bottom: "norm2" + top: "conv3" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + name: "relu3" + type: RELU + bottom: "conv3" + top: "conv3" +} +layers { + name: "conv4" + type: CONVOLUTION + bottom: "conv3" + top: "conv4" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + group: 2 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu4" + type: RELU + bottom: "conv4" + top: "conv4" +} +layers { + name: "conv5" + type: CONVOLUTION + bottom: "conv4" + top: "conv5" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + group: 2 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu5" + type: RELU + bottom: "conv5" + top: "conv5" +} +layers { + name: "pool5" + type: POOLING + bottom: "conv5" + top: "pool5" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "fc6" + type: INNER_PRODUCT + bottom: "pool5" + top: "fc6" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 4096 + weight_filler { + type: "gaussian" + std: 0.005 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu6" + type: RELU + bottom: "fc6" + top: "fc6" +} +layers { + name: "drop6" + type: DROPOUT + bottom: "fc6" + top: "fc6" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc7" + type: INNER_PRODUCT + bottom: "fc6" + top: "fc7" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 4096 + weight_filler { + type: "gaussian" + std: 0.005 + } + bias_filler { + type: "constant" + value: 1 + } + } +} +layers { + name: "relu7" + type: RELU + bottom: "fc7" + top: "fc7" +} +layers { + name: "drop7" + type: DROPOUT + bottom: "fc7" + top: "fc7" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc8" + type: INNER_PRODUCT + bottom: "fc7" + top: "fc8" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "gaussian" + std: 0.01 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + name: "accuracy" + type: ACCURACY + bottom: "fc8" + bottom: "label" + top: "accuracy" + include: { phase: TEST } +} +layers { + name: "loss" + type: SOFTMAX_LOSS + bottom: "fc8" + bottom: "label" + top: "loss" +} diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index f001f1caea3..abc6ec2b590 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -16,12 +16,21 @@ DataTransformer::DataTransformer(const TransformationParameter& param) phase_ = Caffe::phase(); // check if we want to have mean if (param_.has_mean_file()) { + CHECK_EQ(param_.mean_value_size(), 0) << + "Cannot specify mean_file and mean_value at the same time"; const string& mean_file = param.mean_file(); LOG(INFO) << "Loading mean file from" << mean_file; BlobProto blob_proto; ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); data_mean_.FromProto(blob_proto); } + if (param_.mean_value_size() > 0) { + CHECK(param_.has_mean_file() == false) << + "Cannot specify mean_file and mean_value at the same time"; + for (int c = 0; c < param_.mean_value_size(); ++c) { + mean_values_.push_back(param_.mean_value(c)); + } + } } template @@ -37,6 +46,7 @@ void DataTransformer::Transform(const Datum& datum, const bool do_mirror = param_.mirror() && Rand() % 2; const bool has_mean_file = param_.has_mean_file(); const bool has_unit8 = data.size() > 0; + const bool has_mean_values = mean_values_.size() > 0; CHECK_GT(datum_channels, 0); CHECK_GE(datum_height, crop_size); @@ -49,6 +59,16 @@ void DataTransformer::Transform(const Datum& datum, CHECK_EQ(datum_width, data_mean_.width()); mean = data_mean_.mutable_cpu_data(); } + if (has_mean_values) { + CHECK(mean_values_.size() == 1 || mean_values_.size() == datum_channels) << + "Specify either 1 mean_value or as many as channels: " << datum_channels; + if (datum_channels > 1 && mean_values_.size() == 1) { + // Replicate the mean_value for simplicity + for (int c = 1; c < datum_channels; ++c) { + mean_values_.push_back(mean_values_[0]); + } + } + } int height = datum_height; int width = datum_width; @@ -89,7 +109,12 @@ void DataTransformer::Transform(const Datum& datum, transformed_data[top_index] = (datum_element - mean[data_index]) * scale; } else { - transformed_data[top_index] = datum_element * scale; + if (has_mean_values) { + transformed_data[top_index] = + (datum_element - mean_values_[c]) * scale; + } else { + transformed_data[top_index] = datum_element * scale; + } } } } @@ -178,6 +203,7 @@ void DataTransformer::Transform(Blob* input_blob, const Dtype scale = param_.scale(); const bool do_mirror = param_.mirror() && Rand() % 2; const bool has_mean_file = param_.has_mean_file(); + const bool has_mean_values = mean_values_.size() > 0; int h_off = 0; int w_off = 0; @@ -209,6 +235,22 @@ void DataTransformer::Transform(Blob* input_blob, } } + if (has_mean_values) { + CHECK(mean_values_.size() == 1 || mean_values_.size() == input_channels) << + "Specify either 1 mean_value or as many as channels: " << input_channels; + if (mean_values_.size() == 1) { + caffe_add_scalar(input_blob->count(), -(mean_values_[0]), input_data); + } else { + for (int n = 0; n < input_num; ++n) { + for (int c = 0; c < input_channels; ++c) { + int offset = input_blob->offset(n, c); + caffe_add_scalar(input_height * input_width, -(mean_values_[c]), + input_data + offset); + } + } + } + } + Dtype* transformed_data = transformed_blob->mutable_cpu_data(); for (int n = 0; n < input_num; ++n) { diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 8f88177944c..85418f0adaf 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -347,7 +347,12 @@ message TransformationParameter { optional bool mirror = 2 [default = false]; // Specify if we would like to randomly crop an image. optional uint32 crop_size = 3 [default = 0]; + // mean_file and mean_value cannot be specified at the same time optional string mean_file = 4; + // if specified can be repeated once (would substract it from all the channels) + // or can be repeated the same number of times as channels + // (would subtract them from the corresponding channel) + repeated float mean_value = 5; } // Message that stores parameters used by AccuracyLayer diff --git a/src/caffe/test/test_io.cpp b/src/caffe/test/test_io.cpp index affbfd88f8e..6994afda0e3 100644 --- a/src/caffe/test/test_io.cpp +++ b/src/caffe/test/test_io.cpp @@ -121,7 +121,8 @@ TEST_F(IOTest, TestReadImageToDatumContent) { for (int c = 0; c < datum.channels(); ++c) { for (int h = 0; h < datum.height(); ++h) { for (int w = 0; w < datum.width(); ++w) { - EXPECT_TRUE(data[index++] == static_cast(cv_img.at(h, w)[c])); + EXPECT_TRUE(data[index++] == + static_cast(cv_img.at(h, w)[c])); } } } From 8cd863e7cb5181cbbdfcf0dd75a78c80c56c1281 Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 25 Sep 2014 19:53:33 -0700 Subject: [PATCH 081/798] Fix OSX compilation for nvcc with opencv --- Makefile | 1 + include/caffe/data_transformer.hpp | 4 ++++ include/caffe/util/io.hpp | 4 ++++ models/bvlc_reference_caffenet/train_val.prototxt | 13 +++++++++++-- src/caffe/data_transformer.cpp | 4 ++++ 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b0b25150eb9..7dea267e4c3 100644 --- a/Makefile +++ b/Makefile @@ -252,6 +252,7 @@ ifeq ($(OSX), 1) endif # boost::thread is called boost_thread-mt to mark multithreading on OS X LIBRARIES += boost_thread-mt + NVCCFLAGS += -DOSX endif # Custom compiler diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 735f1d586c9..7e48df339e2 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -1,7 +1,9 @@ #ifndef CAFFE_DATA_TRANSFORMER_HPP #define CAFFE_DATA_TRANSFORMER_HPP +#ifndef OSX #include +#endif #include @@ -49,7 +51,9 @@ class DataTransformer { void Transform(const vector & datum_vector, Blob* transformed_blob); +#ifndef OSX void Transform(const cv::Mat& cv_img, Blob* transformed_blob); +#endif void Transform(Blob* input_blob, Blob* transformed_blob); diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 2032b1f3195..e518979a75b 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -1,7 +1,9 @@ #ifndef CAFFE_UTIL_IO_H_ #define CAFFE_UTIL_IO_H_ +#ifndef OSX #include +#endif #include #include @@ -109,6 +111,7 @@ inline bool ReadImageToDatum(const string& filename, const int label, return ReadImageToDatum(filename, label, 0, 0, true, datum); } +#ifndef OSX cv::Mat ReadImageToCVMat(const string& filename, const int height, const int width, const bool is_color); @@ -127,6 +130,7 @@ inline cv::Mat ReadImageToCVMat(const string& filename) { } void CVMatToDatum(const cv::Mat& cv_img, Datum* datum); +#endif leveldb::Options GetLevelDBOptions(); diff --git a/models/bvlc_reference_caffenet/train_val.prototxt b/models/bvlc_reference_caffenet/train_val.prototxt index 073d8aeff4a..6cfeab10e1b 100644 --- a/models/bvlc_reference_caffenet/train_val.prototxt +++ b/models/bvlc_reference_caffenet/train_val.prototxt @@ -330,11 +330,20 @@ layers { } } layers { - name: "accuracy" + name: "top-1" type: ACCURACY bottom: "fc8" bottom: "label" - top: "accuracy" + top: "top-1" + include: { phase: TEST } +} +layers { + name: "top-5" + type: ACCURACY + bottom: "fc8" + bottom: "label" + top: "top-5" + accuracy_param: { top_k: 5 } include: { phase: TEST } } layers { diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index abc6ec2b590..a195c5d2ad6 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -1,4 +1,6 @@ +#ifndef OSX #include +#endif #include #include @@ -172,6 +174,7 @@ void DataTransformer::Transform(const vector & datum_vector, } } +#ifndef OSX template void DataTransformer::Transform(const cv::Mat& cv_img, Blob* transformed_blob) { @@ -179,6 +182,7 @@ void DataTransformer::Transform(const cv::Mat& cv_img, CVMatToDatum(cv_img, &datum); Transform(datum, transformed_blob); } +#endif template void DataTransformer::Transform(Blob* input_blob, From 8a6d348bed4e25161a6146c394499f0f9ba7054d Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 25 Sep 2014 20:07:01 -0700 Subject: [PATCH 082/798] Fix calls to Rand() and test_data_layer error Remove benchmarking code, fixed data_transformer doxygen docs --- include/caffe/data_layers.hpp | 2 - include/caffe/data_transformer.hpp | 54 ++++++++++++++++++++------- src/caffe/data_transformer.cpp | 12 +++--- src/caffe/layers/base_data_layer.cpp | 5 --- src/caffe/layers/base_data_layer.cu | 2 - src/caffe/layers/data_layer.cpp | 4 -- src/caffe/layers/image_data_layer.cpp | 3 -- 7 files changed, 46 insertions(+), 36 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index e3ba2d13ccf..1ed26c17178 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -17,7 +17,6 @@ #include "caffe/internal_thread.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" -#include "caffe/util/benchmark.hpp" namespace caffe { @@ -52,7 +51,6 @@ class BaseDataLayer : public Layer { DataTransformer data_transformer_; Caffe::Phase phase_; bool output_labels_; - Timer timer_forward_; }; template diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 7e48df339e2..db2cac5e4cf 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -23,6 +23,12 @@ class DataTransformer { explicit DataTransformer(const TransformationParameter& param); virtual ~DataTransformer() {} + /** + * @brief Initialize the Random number generations if needed by the + * transformation. Currently: + * needs_rand = param_.mirror() || + * (phase_ == Caffe::TRAIN && param_.crop_size()); + */ void InitRand(); /** @@ -31,30 +37,50 @@ class DataTransformer { * * @param datum * Datum containing the data to be transformed. - * @param datum_vector - * A vector of Datum containing the data to be transformed. - * @param cv_img - * cv::Mat containing the data to be transformed. - * @param input_blob - * A Blob containing the data to be transformed. - * @param transformed_data - * This should point to the right place in memory where the - * transformed data would be written. Assumes there is enough space * @param transformed_blob - * This is destionation blob. It can be part of top blob's data. - * The transformed data will be written at the appropriate place - * within the blob's data. + * This is destination blob. It can be part of top blob's data if + * set_cpu_data() is used See data_layer.cpp for an example. */ - void Transform(const Datum& datum, Blob* transformed_blob); + /** + * @brief Applies the transformation defined in the data layer's + * transform_param block to a vector of Datum. + * + * @param datum_vector + * A vector of Datum containing the data to be transformed. + * @param transformed_blob + * This is destination blob. It can be part of top blob's data if + * set_cpu_data() is used See memory_layer.cpp for an example. + */ void Transform(const vector & datum_vector, Blob* transformed_blob); + /** + * @brief Applies the transformation defined in the data layer's + * transform_param block to a cv::Mat + * + * @param cv_img + * cv::Mat containing the data to be transformed. + * @param transformed_blob + * This is destination blob. It can be part of top blob's data if + * set_cpu_data() is used See image_data_layer.cpp for an example. + */ #ifndef OSX void Transform(const cv::Mat& cv_img, Blob* transformed_blob); #endif + /** + * @brief Applies the same transformation defined in the data layer's + * transform_param block to all the num images in a input_blob. + * + * @param input_blob + * A Blob containing the data to be transformed. It applies the same + * transformation to all the num images in the blob. + * @param transformed_blob + * This is destination blob, it will contain as many images as the + * input blob. It can be part of top blob's data. + */ void Transform(Blob* input_blob, Blob* transformed_blob); protected: @@ -63,7 +89,7 @@ class DataTransformer { * * @param n * The upperbound (exclusive) value of the random number. - * @return + * @return * A uniformly random integer value from ({0, 1, ..., n-1}). */ virtual int Rand(int n); diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index a195c5d2ad6..c7d1ecaf56f 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -45,7 +45,7 @@ void DataTransformer::Transform(const Datum& datum, const int crop_size = param_.crop_size(); const Dtype scale = param_.scale(); - const bool do_mirror = param_.mirror() && Rand() % 2; + const bool do_mirror = param_.mirror() && Rand(2); const bool has_mean_file = param_.has_mean_file(); const bool has_unit8 = data.size() > 0; const bool has_mean_values = mean_values_.size() > 0; @@ -82,8 +82,8 @@ void DataTransformer::Transform(const Datum& datum, width = crop_size; // We only do random crop when we do training. if (phase_ == Caffe::TRAIN) { - h_off = Rand(height - crop_size + 1); - w_off = Rand(width - crop_size + 1); + h_off = Rand(datum_height - crop_size + 1); + w_off = Rand(datum_width - crop_size + 1); } else { h_off = (datum_height - crop_size) / 2; w_off = (datum_width - crop_size) / 2; @@ -205,7 +205,7 @@ void DataTransformer::Transform(Blob* input_blob, const int crop_size = param_.crop_size(); const Dtype scale = param_.scale(); - const bool do_mirror = param_.mirror() && Rand() % 2; + const bool do_mirror = param_.mirror() && Rand(2); const bool has_mean_file = param_.has_mean_file(); const bool has_mean_values = mean_values_.size() > 0; @@ -216,8 +216,8 @@ void DataTransformer::Transform(Blob* input_blob, CHECK_EQ(crop_size, width); // We only do random crop when we do training. if (phase_ == Caffe::TRAIN) { - h_off = Rand() % (input_height - crop_size); - w_off = Rand() % (input_width - crop_size); + h_off = Rand(height - crop_size + 1); + w_off = Rand(width - crop_size + 1); } else { h_off = (input_height - crop_size) / 2; w_off = (input_width - crop_size) / 2; diff --git a/src/caffe/layers/base_data_layer.cpp b/src/caffe/layers/base_data_layer.cpp index 5ce52f05a3c..eb0aaf82120 100644 --- a/src/caffe/layers/base_data_layer.cpp +++ b/src/caffe/layers/base_data_layer.cpp @@ -59,10 +59,6 @@ template void BasePrefetchingDataLayer::Forward_cpu( const vector*>& bottom, const vector*>& top) { // First, join the thread - if (this->timer_forward_.has_run_at_least_once()) { - DLOG(INFO) << "Proccessing: " << - this->timer_forward_.MilliSeconds() << "ms."; - } JoinPrefetchThread(); DLOG(INFO) << "Thread joined"; // Copy the data @@ -76,7 +72,6 @@ void BasePrefetchingDataLayer::Forward_cpu( // Start a new prefetch thread DLOG(INFO) << "CreatePrefetchThread"; CreatePrefetchThread(); - this->timer_forward_.Start(); } #ifdef CPU_ONLY diff --git a/src/caffe/layers/base_data_layer.cu b/src/caffe/layers/base_data_layer.cu index 690858f09d3..ff1510361b6 100644 --- a/src/caffe/layers/base_data_layer.cu +++ b/src/caffe/layers/base_data_layer.cu @@ -7,7 +7,6 @@ namespace caffe { template void BasePrefetchingDataLayer::Forward_gpu( const vector*>& bottom, const vector*>& top) { - DLOG(INFO) << "Processing: " << this->timer_forward_.MilliSeconds() << "ms."; // First, join the thread JoinPrefetchThread(); // Copy the data @@ -19,7 +18,6 @@ void BasePrefetchingDataLayer::Forward_gpu( } // Start a new prefetch thread CreatePrefetchThread(); - this->timer_forward_.Start(); } INSTANTIATE_CLASS(BasePrefetchingDataLayer); diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 980e4146fc9..283a3a52f59 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -8,7 +8,6 @@ #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" -#include "caffe/util/benchmark.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -143,8 +142,6 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // This function is used to create a thread that prefetches the data. template void DataLayer::InternalThreadEntry() { - Timer batch_timer; - batch_timer.Start(); CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -204,7 +201,6 @@ void DataLayer::InternalThreadEntry() { LOG(FATAL) << "Unknown database backend"; } } - DLOG(INFO) << "Prefetch: " << batch_timer.MilliSeconds() << " ms."; } INSTANTIATE_CLASS(DataLayer); diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index d93d56dead0..b3e5d445ed1 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -91,8 +91,6 @@ void ImageDataLayer::ShuffleImages() { // This function is used to create a thread that prefetches the data. template void ImageDataLayer::InternalThreadEntry() { - Timer batch_timer; - batch_timer.Start(); CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -131,7 +129,6 @@ void ImageDataLayer::InternalThreadEntry() { } } } - DLOG(INFO) << "Prefetch: " << batch_timer.MilliSeconds() << " ms."; } INSTANTIATE_CLASS(ImageDataLayer); From b07a54fc36a4751c7181ba9a8a155be77cc35596 Mon Sep 17 00:00:00 2001 From: Sergio Guadarrama Date: Fri, 26 Sep 2014 16:35:21 -0700 Subject: [PATCH 083/798] Fixed crop error and add test_data_transformer Make lint happy Fix Name conventions --- include/caffe/data_transformer.hpp | 4 +- .../train_val.prototxt | 13 +- src/caffe/data_transformer.cpp | 7 +- src/caffe/layers/image_data_layer.cpp | 1 - src/caffe/layers/window_data_layer.cpp | 4 +- src/caffe/test/test_data_transformer.cpp | 360 ++++++++++++++++++ src/caffe/util/benchmark.cpp | 4 +- 7 files changed, 372 insertions(+), 21 deletions(-) create mode 100644 src/caffe/test/test_data_transformer.cpp diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index db2cac5e4cf..5f08335d4a3 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -25,9 +25,7 @@ class DataTransformer { /** * @brief Initialize the Random number generations if needed by the - * transformation. Currently: - * needs_rand = param_.mirror() || - * (phase_ == Caffe::TRAIN && param_.crop_size()); + * transformation. */ void InitRand(); diff --git a/models/bvlc_reference_caffenet/train_val.prototxt b/models/bvlc_reference_caffenet/train_val.prototxt index 6cfeab10e1b..073d8aeff4a 100644 --- a/models/bvlc_reference_caffenet/train_val.prototxt +++ b/models/bvlc_reference_caffenet/train_val.prototxt @@ -330,20 +330,11 @@ layers { } } layers { - name: "top-1" + name: "accuracy" type: ACCURACY bottom: "fc8" bottom: "label" - top: "top-1" - include: { phase: TEST } -} -layers { - name: "top-5" - type: ACCURACY - bottom: "fc8" - bottom: "label" - top: "top-5" - accuracy_param: { top_k: 5 } + top: "accuracy" include: { phase: TEST } } layers { diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index c7d1ecaf56f..78112b9b8c0 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -16,7 +16,7 @@ template DataTransformer::DataTransformer(const TransformationParameter& param) : param_(param) { phase_ = Caffe::phase(); - // check if we want to have mean + // check if we want to use mean_file if (param_.has_mean_file()) { CHECK_EQ(param_.mean_value_size(), 0) << "Cannot specify mean_file and mean_value at the same time"; @@ -26,6 +26,7 @@ DataTransformer::DataTransformer(const TransformationParameter& param) ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); data_mean_.FromProto(blob_proto); } + // check if we want to use mean_value if (param_.mean_value_size() > 0) { CHECK(param_.has_mean_file() == false) << "Cannot specify mean_file and mean_value at the same time"; @@ -216,8 +217,8 @@ void DataTransformer::Transform(Blob* input_blob, CHECK_EQ(crop_size, width); // We only do random crop when we do training. if (phase_ == Caffe::TRAIN) { - h_off = Rand(height - crop_size + 1); - w_off = Rand(width - crop_size + 1); + h_off = Rand(input_height - crop_size + 1); + w_off = Rand(input_width - crop_size + 1); } else { h_off = (input_height - crop_size) / 2; w_off = (input_width - crop_size) / 2; diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index b3e5d445ed1..19ad2dc2126 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -112,7 +112,6 @@ void ImageDataLayer::InternalThreadEntry() { continue; } // Apply transformations (mirror, crop...) to the image - // this->data_transformer_.Transform(item_id, cv_img, top_data); int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index c01b61bec9b..009bf97c612 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -163,9 +163,9 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, this->prefetch_label_.Reshape(batch_size, 1, 1, 1); // data mean - if (this->layer_param_.window_data_param().has_mean_file()) { + if (this->transform_param_.has_mean_file()) { const string& mean_file = - this->layer_param_.window_data_param().mean_file(); + this->transform_param_.mean_file(); LOG(INFO) << "Loading mean file from" << mean_file; BlobProto blob_proto; ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); diff --git a/src/caffe/test/test_data_transformer.cpp b/src/caffe/test/test_data_transformer.cpp new file mode 100644 index 00000000000..28c7241050b --- /dev/null +++ b/src/caffe/test/test_data_transformer.cpp @@ -0,0 +1,360 @@ +#include +#include + +#include "gtest/gtest.h" +#include "leveldb/db.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/data_transformer.hpp" +#include "caffe/filler.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/util/io.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +void FillDatum(const int label, const int channels, const int height, + const int width, const bool unique_pixels, Datum * datum) { + datum->set_label(label); + datum->set_channels(channels); + datum->set_height(height); + datum->set_width(width); + int size = channels * height * width; + std::string* data = datum->mutable_data(); + for (int j = 0; j < size; ++j) { + int datum = unique_pixels ? j : label; + data->push_back(static_cast(datum)); + } +} + +template +class DataTransformTest : public ::testing::Test { + protected: + DataTransformTest() + : seed_(1701), + num_iter_(10) {} + + int NumSequenceMatches(const TransformationParameter transform_param, + const Datum& datum) { + // Get crop sequence with Caffe seed 1701. + DataTransformer* transformer = + new DataTransformer(transform_param); + const int crop_size = transform_param.crop_size(); + Caffe::set_random_seed(seed_); + transformer->InitRand(); + Blob* blob = + new Blob(1, datum.channels(), datum.height(), datum.width()); + if (transform_param.crop_size() > 0) { + blob->Reshape(1, datum.channels(), crop_size, crop_size); + } + + vector > crop_sequence; + for (int iter = 0; iter < this->num_iter_; ++iter) { + vector iter_crop_sequence; + transformer->Transform(datum, blob); + for (int j = 0; j < blob->count(); ++j) { + iter_crop_sequence.push_back(blob->cpu_data()[j]); + } + crop_sequence.push_back(iter_crop_sequence); + } + // Check if the sequence differs from the previous + int num_sequence_matches = 0; + for (int iter = 0; iter < this->num_iter_; ++iter) { + vector iter_crop_sequence = crop_sequence[iter]; + transformer->Transform(datum, blob); + for (int j = 0; j < blob->count(); ++j) { + num_sequence_matches += + (crop_sequence[iter][j] == blob->cpu_data()[j]); + } + } + return num_sequence_matches; + } + + virtual ~DataTransformTest() { } + + int seed_; + int num_iter_; +}; + +TYPED_TEST_CASE(DataTransformTest, TestDtypes); + +TYPED_TEST(DataTransformTest, TestEmptyTransform) { + TransformationParameter transform_param; + const bool unique_pixels = false; // all pixels the same equal to label + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Blob* blob = new Blob(1, channels, height, width); + DataTransformer* transformer = + new DataTransformer(transform_param); + transformer->InitRand(); + transformer->Transform(datum, blob); + EXPECT_EQ(blob->num(), 1); + EXPECT_EQ(blob->channels(), datum.channels()); + EXPECT_EQ(blob->height(), datum.height()); + EXPECT_EQ(blob->width(), datum.width()); + for (int j = 0; j < blob->count(); ++j) { + EXPECT_EQ(blob->cpu_data()[j], label); + } +} + +TYPED_TEST(DataTransformTest, TestEmptyTransformUniquePixels) { + TransformationParameter transform_param; + const bool unique_pixels = true; // pixels are consecutive ints [0,size] + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Blob* blob = new Blob(1, 3, 4, 5); + DataTransformer* transformer = + new DataTransformer(transform_param); + transformer->InitRand(); + transformer->Transform(datum, blob); + EXPECT_EQ(blob->num(), 1); + EXPECT_EQ(blob->channels(), datum.channels()); + EXPECT_EQ(blob->height(), datum.height()); + EXPECT_EQ(blob->width(), datum.width()); + for (int j = 0; j < blob->count(); ++j) { + EXPECT_EQ(blob->cpu_data()[j], j); + } +} + +TYPED_TEST(DataTransformTest, TestCropSize) { + TransformationParameter transform_param; + const bool unique_pixels = false; // all pixels the same equal to label + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int crop_size = 2; + + transform_param.set_crop_size(crop_size); + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + DataTransformer* transformer = + new DataTransformer(transform_param); + transformer->InitRand(); + Blob* blob = + new Blob(1, channels, crop_size, crop_size); + for (int iter = 0; iter < this->num_iter_; ++iter) { + transformer->Transform(datum, blob); + EXPECT_EQ(blob->num(), 1); + EXPECT_EQ(blob->channels(), datum.channels()); + EXPECT_EQ(blob->height(), crop_size); + EXPECT_EQ(blob->width(), crop_size); + for (int j = 0; j < blob->count(); ++j) { + EXPECT_EQ(blob->cpu_data()[j], label); + } + } +} + +TYPED_TEST(DataTransformTest, TestCropTrain) { + TransformationParameter transform_param; + const bool unique_pixels = true; // pixels are consecutive ints [0,size] + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int crop_size = 2; + const int size = channels * crop_size * crop_size; + + transform_param.set_crop_size(crop_size); + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Caffe::set_phase(Caffe::TRAIN); + int num_matches = this->NumSequenceMatches(transform_param, datum); + EXPECT_LT(num_matches, size * this->num_iter_); +} + +TYPED_TEST(DataTransformTest, TestCropTest) { + TransformationParameter transform_param; + const bool unique_pixels = true; // pixels are consecutive ints [0,size] + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int crop_size = 2; + const int size = channels * crop_size * crop_size; + + transform_param.set_crop_size(crop_size); + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Caffe::set_phase(Caffe::TEST); + int num_matches = this->NumSequenceMatches(transform_param, datum); + EXPECT_EQ(num_matches, size * this->num_iter_); +} + +TYPED_TEST(DataTransformTest, TestMirrorTrain) { + TransformationParameter transform_param; + const bool unique_pixels = true; // pixels are consecutive ints [0,size] + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int size = channels * height * width; + + transform_param.set_mirror(true); + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Caffe::set_phase(Caffe::TRAIN); + int num_matches = this->NumSequenceMatches(transform_param, datum); + EXPECT_LT(num_matches, size * this->num_iter_); +} + +TYPED_TEST(DataTransformTest, TestMirrorTest) { + TransformationParameter transform_param; + const bool unique_pixels = true; // pixels are consecutive ints [0,size] + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int size = channels * height * width; + + transform_param.set_mirror(true); + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Caffe::set_phase(Caffe::TEST); + int num_matches = this->NumSequenceMatches(transform_param, datum); + EXPECT_LT(num_matches, size * this->num_iter_); +} + +TYPED_TEST(DataTransformTest, TestCropMirrorTrain) { + TransformationParameter transform_param; + const bool unique_pixels = true; // pixels are consecutive ints [0,size] + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int crop_size = 2; + + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + transform_param.set_crop_size(crop_size); + Caffe::set_phase(Caffe::TRAIN); + int num_matches_crop = this->NumSequenceMatches(transform_param, datum); + + transform_param.set_mirror(true); + int num_matches_crop_mirror = + this->NumSequenceMatches(transform_param, datum); + // When doing crop and mirror we expect less num_matches than just crop + EXPECT_LE(num_matches_crop_mirror, num_matches_crop); +} + +TYPED_TEST(DataTransformTest, TestCropMirrorTest) { + TransformationParameter transform_param; + const bool unique_pixels = true; // pixels are consecutive ints [0,size] + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int crop_size = 2; + + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + transform_param.set_crop_size(crop_size); + Caffe::set_phase(Caffe::TEST); + int num_matches_crop = this->NumSequenceMatches(transform_param, datum); + + transform_param.set_mirror(true); + int num_matches_crop_mirror = + this->NumSequenceMatches(transform_param, datum); + // When doing crop and mirror we expect less num_matches than just crop + EXPECT_LT(num_matches_crop_mirror, num_matches_crop); +} + + +TYPED_TEST(DataTransformTest, TestMeanValue) { + TransformationParameter transform_param; + const bool unique_pixels = false; // pixels are equal to label + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int mean_value = 2; + + transform_param.add_mean_value(mean_value); + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Blob* blob = new Blob(1, channels, height, width); + DataTransformer* transformer = + new DataTransformer(transform_param); + transformer->InitRand(); + transformer->Transform(datum, blob); + for (int j = 0; j < blob->count(); ++j) { + EXPECT_EQ(blob->cpu_data()[j], label - mean_value); + } +} + +TYPED_TEST(DataTransformTest, TestMeanValues) { + TransformationParameter transform_param; + const bool unique_pixels = false; // pixels are equal to label + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + + transform_param.add_mean_value(0); + transform_param.add_mean_value(1); + transform_param.add_mean_value(2); + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Blob* blob = new Blob(1, channels, height, width); + DataTransformer* transformer = + new DataTransformer(transform_param); + transformer->InitRand(); + transformer->Transform(datum, blob); + for (int c = 0; c < channels; ++c) { + for (int j = 0; j < height * width; ++j) { + EXPECT_EQ(blob->cpu_data()[blob->offset(0, c) + j], label - c); + } + } +} + +TYPED_TEST(DataTransformTest, TestMeanFile) { + TransformationParameter transform_param; + const bool unique_pixels = true; // pixels are consecutive ints [0,size] + const int label = 0; + const int channels = 3; + const int height = 4; + const int width = 5; + const int size = channels * height * width; + + // Create a mean file + string* mean_file = new string(); + MakeTempFilename(mean_file); + BlobProto blob_mean; + blob_mean.set_num(1); + blob_mean.set_channels(channels); + blob_mean.set_height(height); + blob_mean.set_width(width); + + for (int j = 0; j < size; ++j) { + blob_mean.add_data(j); + } + + LOG(INFO) << "Using temporary mean_file " << *mean_file; + WriteProtoToBinaryFile(blob_mean, *mean_file); + + transform_param.set_mean_file(*mean_file); + Datum datum; + FillDatum(label, channels, height, width, unique_pixels, &datum); + Blob* blob = new Blob(1, channels, height, width); + DataTransformer* transformer = + new DataTransformer(transform_param); + transformer->InitRand(); + transformer->Transform(datum, blob); + for (int j = 0; j < blob->count(); ++j) { + EXPECT_EQ(blob->cpu_data()[j], 0); + } +} + +} // namespace caffe diff --git a/src/caffe/util/benchmark.cpp b/src/caffe/util/benchmark.cpp index 76829f5b36c..2edc9a53ef0 100644 --- a/src/caffe/util/benchmark.cpp +++ b/src/caffe/util/benchmark.cpp @@ -66,8 +66,10 @@ float Timer::MicroSeconds() { } if (Caffe::mode() == Caffe::GPU) { #ifndef CPU_ONLY - CUDA_CHECK(cudaEventElapsedTime(&elapsed_microseconds_, start_gpu_, + CUDA_CHECK(cudaEventElapsedTime(&elapsed_milliseconds_, start_gpu_, stop_gpu_)); + // Cuda only measure milliseconds + elapsed_microseconds_ = elapsed_milliseconds_ / 1000; #else NO_GPU; #endif From 3115b207239b53744a600debc8b4aea146d2a79b Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 3 Oct 2014 18:02:32 -0700 Subject: [PATCH 084/798] bundle pixel mean into CaffeNet as comments --- .../train_val.prototxt | 16 + .../train_val_mean_value.prototxt | 348 ------------------ 2 files changed, 16 insertions(+), 348 deletions(-) delete mode 100644 models/bvlc_reference_caffenet/train_val_mean_value.prototxt diff --git a/models/bvlc_reference_caffenet/train_val.prototxt b/models/bvlc_reference_caffenet/train_val.prototxt index 073d8aeff4a..00fcc080261 100644 --- a/models/bvlc_reference_caffenet/train_val.prototxt +++ b/models/bvlc_reference_caffenet/train_val.prototxt @@ -14,6 +14,14 @@ layers { mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" mirror: true } +# mean pixel / channel-wise mean instead of mean image +# transform_param { +# crop_size: 227 +# mean_value: 104 +# mean_value: 117 +# mean_value: 123 +# mirror: true +# } include: { phase: TRAIN } } layers { @@ -31,6 +39,14 @@ layers { mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" mirror: false } +# mean pixel / channel-wise mean instead of mean image +# transform_param { +# crop_size: 227 +# mean_value: 104 +# mean_value: 117 +# mean_value: 123 +# mirror: true +# } include: { phase: TEST } } layers { diff --git a/models/bvlc_reference_caffenet/train_val_mean_value.prototxt b/models/bvlc_reference_caffenet/train_val_mean_value.prototxt deleted file mode 100644 index c2fbb7118ca..00000000000 --- a/models/bvlc_reference_caffenet/train_val_mean_value.prototxt +++ /dev/null @@ -1,348 +0,0 @@ -name: "CaffeNet" -layers { - name: "data" - type: DATA - top: "data" - top: "label" - data_param { - source: "examples/imagenet/ilsvrc12_train_leveldb" - batch_size: 256 - } - transform_param { - crop_size: 227 - mean_value: 104 - mean_value: 117 - mean_value: 123 - mirror: true - } - include: { phase: TRAIN } -} -layers { - name: "data" - type: DATA - top: "data" - top: "label" - data_param { - source: "examples/imagenet/ilsvrc12_val_leveldb" - batch_size: 50 - } - transform_param { - crop_size: 227 - mean_value: 104 - mean_value: 117 - mean_value: 123 - mirror: false - } - include: { phase: TEST } -} -layers { - name: "conv1" - type: CONVOLUTION - bottom: "data" - top: "conv1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 - convolution_param { - num_output: 96 - kernel_size: 11 - stride: 4 - weight_filler { - type: "gaussian" - std: 0.01 - } - bias_filler { - type: "constant" - value: 0 - } - } -} -layers { - name: "relu1" - type: RELU - bottom: "conv1" - top: "conv1" -} -layers { - name: "pool1" - type: POOLING - bottom: "conv1" - top: "pool1" - pooling_param { - pool: MAX - kernel_size: 3 - stride: 2 - } -} -layers { - name: "norm1" - type: LRN - bottom: "pool1" - top: "norm1" - lrn_param { - local_size: 5 - alpha: 0.0001 - beta: 0.75 - } -} -layers { - name: "conv2" - type: CONVOLUTION - bottom: "norm1" - top: "conv2" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 - convolution_param { - num_output: 256 - pad: 2 - kernel_size: 5 - group: 2 - weight_filler { - type: "gaussian" - std: 0.01 - } - bias_filler { - type: "constant" - value: 1 - } - } -} -layers { - name: "relu2" - type: RELU - bottom: "conv2" - top: "conv2" -} -layers { - name: "pool2" - type: POOLING - bottom: "conv2" - top: "pool2" - pooling_param { - pool: MAX - kernel_size: 3 - stride: 2 - } -} -layers { - name: "norm2" - type: LRN - bottom: "pool2" - top: "norm2" - lrn_param { - local_size: 5 - alpha: 0.0001 - beta: 0.75 - } -} -layers { - name: "conv3" - type: CONVOLUTION - bottom: "norm2" - top: "conv3" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 - convolution_param { - num_output: 384 - pad: 1 - kernel_size: 3 - weight_filler { - type: "gaussian" - std: 0.01 - } - bias_filler { - type: "constant" - value: 0 - } - } -} -layers { - name: "relu3" - type: RELU - bottom: "conv3" - top: "conv3" -} -layers { - name: "conv4" - type: CONVOLUTION - bottom: "conv3" - top: "conv4" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 - convolution_param { - num_output: 384 - pad: 1 - kernel_size: 3 - group: 2 - weight_filler { - type: "gaussian" - std: 0.01 - } - bias_filler { - type: "constant" - value: 1 - } - } -} -layers { - name: "relu4" - type: RELU - bottom: "conv4" - top: "conv4" -} -layers { - name: "conv5" - type: CONVOLUTION - bottom: "conv4" - top: "conv5" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 - convolution_param { - num_output: 256 - pad: 1 - kernel_size: 3 - group: 2 - weight_filler { - type: "gaussian" - std: 0.01 - } - bias_filler { - type: "constant" - value: 1 - } - } -} -layers { - name: "relu5" - type: RELU - bottom: "conv5" - top: "conv5" -} -layers { - name: "pool5" - type: POOLING - bottom: "conv5" - top: "pool5" - pooling_param { - pool: MAX - kernel_size: 3 - stride: 2 - } -} -layers { - name: "fc6" - type: INNER_PRODUCT - bottom: "pool5" - top: "fc6" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 - inner_product_param { - num_output: 4096 - weight_filler { - type: "gaussian" - std: 0.005 - } - bias_filler { - type: "constant" - value: 1 - } - } -} -layers { - name: "relu6" - type: RELU - bottom: "fc6" - top: "fc6" -} -layers { - name: "drop6" - type: DROPOUT - bottom: "fc6" - top: "fc6" - dropout_param { - dropout_ratio: 0.5 - } -} -layers { - name: "fc7" - type: INNER_PRODUCT - bottom: "fc6" - top: "fc7" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 - inner_product_param { - num_output: 4096 - weight_filler { - type: "gaussian" - std: 0.005 - } - bias_filler { - type: "constant" - value: 1 - } - } -} -layers { - name: "relu7" - type: RELU - bottom: "fc7" - top: "fc7" -} -layers { - name: "drop7" - type: DROPOUT - bottom: "fc7" - top: "fc7" - dropout_param { - dropout_ratio: 0.5 - } -} -layers { - name: "fc8" - type: INNER_PRODUCT - bottom: "fc7" - top: "fc8" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 - inner_product_param { - num_output: 1000 - weight_filler { - type: "gaussian" - std: 0.01 - } - bias_filler { - type: "constant" - value: 0 - } - } -} -layers { - name: "accuracy" - type: ACCURACY - bottom: "fc8" - bottom: "label" - top: "accuracy" - include: { phase: TEST } -} -layers { - name: "loss" - type: SOFTMAX_LOSS - bottom: "fc8" - bottom: "label" - top: "loss" -} From e8b48b41e0f6e1c38cf1bef144e6907ea30d6a7d Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 3 Oct 2014 18:03:02 -0700 Subject: [PATCH 085/798] uin8 spell check --- src/caffe/data_transformer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 78112b9b8c0..dffaba545b5 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -48,7 +48,7 @@ void DataTransformer::Transform(const Datum& datum, const Dtype scale = param_.scale(); const bool do_mirror = param_.mirror() && Rand(2); const bool has_mean_file = param_.has_mean_file(); - const bool has_unit8 = data.size() > 0; + const bool has_uint8 = data.size() > 0; const bool has_mean_values = mean_values_.size() > 0; CHECK_GT(datum_channels, 0); @@ -102,7 +102,7 @@ void DataTransformer::Transform(const Datum& datum, } else { top_index = (c * height + h) * width + w; } - if (has_unit8) { + if (has_uint8) { datum_element = static_cast(static_cast(data[data_index])); } else { From 1d3bbe2e7bf896379aecf8faa3fcdd5cf5bad522 Mon Sep 17 00:00:00 2001 From: Sergio Date: Sun, 5 Oct 2014 14:34:55 -0700 Subject: [PATCH 086/798] Missing param.pad condition for CUDNN pooling --- src/caffe/layer_factory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 8815ddd021d..69863543c30 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -47,7 +47,8 @@ Layer* GetPoolingLayer(const LayerParameter& param) { #ifdef USE_CUDNN } else if (engine == PoolingParameter_Engine_CUDNN) { PoolingParameter p_param = param.pooling_param(); - if (p_param.pad_h() || p_param.pad_w() || param.top_size() > 1) { + if (p_param.pad() || p_param.pad_h() || p_param.pad_w() || + param.top_size() > 1) { LOG(INFO) << "CUDNN does not support padding or multiple tops. " << "Using Caffe's own pooling layer."; return new PoolingLayer(param); From c20cf21ab430e50f0d3e8d93cd42d2e930d41dd2 Mon Sep 17 00:00:00 2001 From: Dmytro Mishkin Date: Mon, 6 Oct 2014 10:32:47 +0300 Subject: [PATCH 087/798] change -lpthread to -pthread in linking Compilation flags is already there --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 929f8d5cea6..f49ea5649a4 100644 --- a/Makefile +++ b/Makefile @@ -169,7 +169,7 @@ LIBRARIES += glog gflags protobuf leveldb snappy \ lmdb \ boost_system \ hdf5_hl hdf5 \ - opencv_core opencv_highgui opencv_imgproc pthread + opencv_core opencv_highgui opencv_imgproc PYTHON_LIBRARIES := boost_python python2.7 WARNINGS := -Wall -Wno-sign-compare @@ -314,7 +314,7 @@ CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) NVCCFLAGS += -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS) # mex may invoke an older gcc that is too liberal with -Wuninitalized MATLAB_CXXFLAGS := $(CXXFLAGS) -Wno-uninitialized -LINKFLAGS += -fPIC $(COMMON_FLAGS) $(WARNINGS) +LINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) \ $(foreach library,$(LIBRARIES),-l$(library)) PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) From 6893ea722505c889fd40c9f692d7a87eb750c752 Mon Sep 17 00:00:00 2001 From: Martin Baeuml Date: Mon, 6 Oct 2014 13:48:29 +0200 Subject: [PATCH 088/798] change linking order such that pthread comes in the back This resolves an error with the static gflags library which would other wise not link properly with an undefined reference to symbol 'pthread_rwlock_wrlock@@GLIBC_2.2.5' error under Ubuntu 14.04. --- src/caffe/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caffe/CMakeLists.txt b/src/caffe/CMakeLists.txt index 86c7c7eb4a3..0ff0412230c 100644 --- a/src/caffe/CMakeLists.txt +++ b/src/caffe/CMakeLists.txt @@ -111,13 +111,13 @@ endif() target_link_libraries(caffe proto ${BLAS_LIBRARIES} ${Boost_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} ${GFLAGS_LIBRARIES} ${GLOG_LIBRARIES} ${HDF5_LIBRARIES} ${LEVELDB_LIBS} ${LMDB_LIBRARIES} ${OpenCV_LIBS} + ${CMAKE_THREAD_LIBS_INIT} ) #set output directory From a1a48563d3cbb37ffa510d0ffae718183835e2dc Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 6 Oct 2014 13:27:10 -0700 Subject: [PATCH 089/798] use glog to provide a backtrace on crash --- src/caffe/common.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/caffe/common.cpp b/src/caffe/common.cpp index 94fdf924f44..834d5694aad 100644 --- a/src/caffe/common.cpp +++ b/src/caffe/common.cpp @@ -35,6 +35,8 @@ void GlobalInit(int* pargc, char*** pargv) { ::gflags::ParseCommandLineFlags(pargc, pargv, true); // Google logging. ::google::InitGoogleLogging(*(pargv)[0]); + // Provide a backtrace on segfault. + ::google::InstallFailureSignalHandler(); } #ifdef CPU_ONLY // CPU-only Caffe. From cf270600c588c77f0c5d0242d833fe5f615a4662 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Sat, 4 Oct 2014 10:00:59 -0700 Subject: [PATCH 090/798] SliceLayer: fix whitespace --- src/caffe/layers/slice_layer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caffe/layers/slice_layer.cpp b/src/caffe/layers/slice_layer.cpp index 17144c1a280..76522c3e456 100644 --- a/src/caffe/layers/slice_layer.cpp +++ b/src/caffe/layers/slice_layer.cpp @@ -46,13 +46,13 @@ void SliceLayer::Reshape(const vector*>& bottom, slices.push_back(num_ - prev); for (int i = 0; i < top.size(); ++i) { top[i]->Reshape(slices[i], channels_, height_, width_); - count_ += top[i]->count(); + count_ += top[i]->count(); } } else { slices.push_back(channels_ - prev); for (int i = 0; i < top.size(); ++i) { top[i]->Reshape(num_, slices[i], height_, width_); - count_ += top[i]->count(); + count_ += top[i]->count(); } } } else { From 914da95ed1059c05d39d9b6fbe0f797970aaa376 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 6 Oct 2014 16:35:33 -0700 Subject: [PATCH 091/798] correct naming in comment and message about average_loss --- src/caffe/proto/caffe.proto | 2 +- src/caffe/solver.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 751b68232cd..f0404a09b90 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -113,7 +113,7 @@ message SolverParameter { // the number of iterations between displaying info. If display = 0, no info // will be displayed. optional int32 display = 6; - // Display the cost averaged over the last average_cost iterations + // Display the loss averaged over the last average_loss iterations optional int32 average_loss = 33 [default = 1]; optional int32 max_iter = 7; // the maximum number of iterations optional string lr_policy = 8; // The learning rate decay policy. diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 221fa07e464..995df06ddc7 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -171,7 +171,7 @@ void Solver::Solve(const char* resume_file) { int average_loss = this->param_.average_loss(); - CHECK_GE(average_loss, 1) << "average_cost should be non-negative."; + CHECK_GE(average_loss, 1) << "average_loss should be non-negative."; vector losses; Dtype smoothed_loss = 0; From 84a5b8bb9aeb2b1ed965af598c63b1d3f57c2197 Mon Sep 17 00:00:00 2001 From: Martin Baeuml Date: Tue, 7 Oct 2014 10:35:00 +0200 Subject: [PATCH 092/798] [cmake] move dependency finding to root CMakeLists.txt In this way, custom include directories for the dependencies are also available for tools/ and the bindings. This is necessary for example when someone is using custom built dependencies which are not installed in the system's default directories (e.g. OpenCV includes are required in tools/ through io.hpp) --- CMakeLists.txt | 84 +++++++++++++++++++++++++++++++++++++++- src/caffe/CMakeLists.txt | 80 +------------------------------------- 2 files changed, 83 insertions(+), 81 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6de6b102981..b97eb565f45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,15 +49,95 @@ include_directories(${CMAKE_SOURCE_DIR}/src) # CMake Scripts dir set(CMAKE_SCRIPT_DIR ${CMAKE_SOURCE_DIR}/CMakeScripts) -# CMake module path for custom module finding +# CMake module path for custom module finding set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SCRIPT_DIR}) -# CUDA is required globally +### Dependencies ########################################################################## + +# Boost +find_package(Boost 1.46 COMPONENTS system thread REQUIRED) +include_directories(${Boost_INCLUDE_DIR}) +link_directories(${Boost_LIBRARY_DIRS}) + +# CUDA if(NOT CPU_ONLY) find_package(CUDA 5.5 REQUIRED) include_directories(${CUDA_INCLUDE_DIRS}) + + set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} + -gencode arch=compute_20,code=sm_20 + -gencode arch=compute_20,code=sm_21 + -gencode arch=compute_30,code=sm_30 + -gencode arch=compute_35,code=sm_35 + ) + + # https://github.com/ComputationalRadiationPhysics/picongpu/blob/master/src/picongpu/CMakeLists.txt + # work-arounds + if(Boost_VERSION EQUAL 105500) + # see https://svn.boost.org/trac/boost/ticket/9392 + message(STATUS "Boost: Applying noinline work around") + # avoid warning for CMake >= 2.8.12 + set(CUDA_NVCC_FLAGS + "${CUDA_NVCC_FLAGS} \"-DBOOST_NOINLINE=__attribute__((noinline))\" ") + endif(Boost_VERSION EQUAL 105500) +endif() + +# Threads +find_package(Threads REQUIRED) + +# Google-glog +find_package(Glog REQUIRED) +include_directories(${GLOG_INCLUDE_DIRS}) + +# Google-gflags +find_package(GFlags REQUIRED) +include_directories(${GFLAGS_INCLUDE_DIRS}) + +# BLAS +if(BLAS STREQUAL "atlas") + + find_package(Atlas REQUIRED) + include_directories(${Atlas_INCLUDE_DIR}) + set(BLAS_LIBRARIES ${Atlas_LIBRARIES}) + +elseif(BLAS STREQUAL "open") + + find_package(OpenBLAS REQUIRED) + include_directories(${OpenBLAS_INCLUDE_DIR}) + set(BLAS_LIBRARIES ${OpenBLAS_LIB}) + +elseif(BLAS STREQUAL "mkl") + + find_package(MKL REQUIRED) + include_directories(${MKL_INCLUDE_DIR}) + set(BLAS_LIBRARIES ${MKL_LIBRARIES}) + endif() +# HDF5 +find_package(HDF5 COMPONENTS HL REQUIRED) +include_directories(${HDF5_INCLUDE_DIRS}) + +# LevelDB +find_package(LevelDB REQUIRED) +include_directories(${LEVELDB_INCLUDE}) +if(LEVELDB_FOUND) + find_package(Snappy REQUIRED) + include_directories(${SNAPPY_INCLUDE_DIR}) + set(LEVELDB_LIBS + ${LEVELDB_LIBS} + ${SNAPPY_LIBS} + ) +endif() + +# LMDB +find_package(LMDB REQUIRED) +include_directories(${LMDB_INCLUDE_DIR}) + +# OpenCV +find_package(OpenCV REQUIRED core highgui imgproc) +include_directories(${OpenCV_INCLUDE_DIRS}) + ### Subdirectories ########################################################################## add_subdirectory(src/gtest) diff --git a/src/caffe/CMakeLists.txt b/src/caffe/CMakeLists.txt index 0ff0412230c..dda072688f8 100644 --- a/src/caffe/CMakeLists.txt +++ b/src/caffe/CMakeLists.txt @@ -1,65 +1,5 @@ project( CaffeSrc ) -# Threads -find_package(Threads REQUIRED) - -# Google-glog -find_package(Glog REQUIRED) -include_directories(${GLOG_INCLUDE_DIRS}) - -# Google-gflags -find_package(GFlags REQUIRED) -include_directories(${GFLAGS_INCLUDE_DIRS}) - -# BLAS -if(BLAS STREQUAL "atlas") - - find_package(Atlas REQUIRED) - include_directories(${Atlas_INCLUDE_DIR}) - set(BLAS_LIBRARIES ${Atlas_LIBRARIES}) - -elseif(BLAS STREQUAL "open") - - find_package(OpenBLAS REQUIRED) - include_directories(${OpenBLAS_INCLUDE_DIR}) - set(BLAS_LIBRARIES ${OpenBLAS_LIB}) - -elseif(BLAS STREQUAL "mkl") - - find_package(MKL REQUIRED) - include_directories(${MKL_INCLUDE_DIR}) - set(BLAS_LIBRARIES ${MKL_LIBRARIES}) - -endif() - -# HDF5 -find_package(HDF5 COMPONENTS HL REQUIRED) -include_directories(${HDF5_INCLUDE_DIRS}) - -# OpenCV -find_package(OpenCV REQUIRED core highgui imgproc) -include_directories(${OpenCV_INCLUDE_DIRS}) - -# LevelDB -find_package(LevelDB REQUIRED) -include_directories(${LEVELDB_INCLUDE}) -if(LEVELDB_FOUND) - find_package(Snappy REQUIRED) - include_directories(${SNAPPY_INCLUDE_DIR}) - set(LEVELDB_LIBS - ${LEVELDB_LIBS} - ${SNAPPY_LIBS} - ) -endif() - -# LMDB -find_package(LMDB REQUIRED) -include_directories(${LMDB_INCLUDE_DIR}) - -# Boost -find_package(Boost 1.46 COMPONENTS system thread REQUIRED) -include_directories( ${Boost_INCLUDE_DIR} ) -link_directories( ${Boost_LIBRARY_DIRS} ) add_subdirectory(proto) @@ -77,26 +17,8 @@ add_library(caffe ${CPP_SOURCES}) # both depend on proto add_dependencies(caffe proto) -# CUDA +# cuda sources if(NOT CPU_ONLY) - set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} - -gencode arch=compute_20,code=sm_20 - -gencode arch=compute_20,code=sm_21 - -gencode arch=compute_30,code=sm_30 - -gencode arch=compute_35,code=sm_35 - ) - -# https://github.com/ComputationalRadiationPhysics/picongpu/blob/master/src/picongpu/CMakeLists.txt - # work-arounds -if(Boost_VERSION EQUAL 105500) - # see https://svn.boost.org/trac/boost/ticket/9392 - message(STATUS "Boost: Applying noinline work around") - # avoid warning for CMake >= 2.8.12 - set(CUDA_NVCC_FLAGS - "${CUDA_NVCC_FLAGS} \"-DBOOST_NOINLINE=__attribute__((noinline))\" ") -endif(Boost_VERSION EQUAL 105500) - - # cuda sources file(GLOB_RECURSE CU_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cu) file(GLOB_RECURSE TEST_CU_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/test_*.cu) list(REMOVE_ITEM CU_SOURCES ${TEST_CU_SOURCES}) From b9c1eec5a6821e21d12fa67fca98558c2dd3c5f4 Mon Sep 17 00:00:00 2001 From: max argus Date: Sat, 4 Oct 2014 11:46:38 +0000 Subject: [PATCH 093/798] Fix CMake build of pycaffe - generate right shared library name - fix CMake linking with the new layer factory - find numpy Fix finding protobuf. --- CMakeScripts/FindNumPy.cmake | 103 ++++++++++++++++++++++ CMakeScripts/FindProtobuf.cmake | 152 ++++++++++++++++++++++++++++++++ python/CMakeLists.txt | 48 ++++++++-- src/caffe/proto/CMakeLists.txt | 11 ++- 4 files changed, 308 insertions(+), 6 deletions(-) create mode 100644 CMakeScripts/FindNumPy.cmake create mode 100644 CMakeScripts/FindProtobuf.cmake diff --git a/CMakeScripts/FindNumPy.cmake b/CMakeScripts/FindNumPy.cmake new file mode 100644 index 00000000000..baf21541e63 --- /dev/null +++ b/CMakeScripts/FindNumPy.cmake @@ -0,0 +1,103 @@ +# - Find the NumPy libraries +# This module finds if NumPy is installed, and sets the following variables +# indicating where it is. +# +# TODO: Update to provide the libraries and paths for linking npymath lib. +# +# NUMPY_FOUND - was NumPy found +# NUMPY_VERSION - the version of NumPy found as a string +# NUMPY_VERSION_MAJOR - the major version number of NumPy +# NUMPY_VERSION_MINOR - the minor version number of NumPy +# NUMPY_VERSION_PATCH - the patch version number of NumPy +# NUMPY_VERSION_DECIMAL - e.g. version 1.6.1 is 10601 +# NUMPY_INCLUDE_DIRS - path to the NumPy include files + +#============================================================================ +# Copyright 2012 Continuum Analytics, Inc. +# +# MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +#============================================================================ + +# Finding NumPy involves calling the Python interpreter +if(NumPy_FIND_REQUIRED) + find_package(PythonInterp REQUIRED) +else() + find_package(PythonInterp) +endif() + +if(NOT PYTHONINTERP_FOUND) + set(NUMPY_FOUND FALSE) + return() +endif() + +execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" + "import numpy as n; print(n.__version__); print(n.get_include());" + RESULT_VARIABLE _NUMPY_SEARCH_SUCCESS + OUTPUT_VARIABLE _NUMPY_VALUES_OUTPUT + ERROR_VARIABLE _NUMPY_ERROR_VALUE + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if(NOT _NUMPY_SEARCH_SUCCESS MATCHES 0) + if(NumPy_FIND_REQUIRED) + message(FATAL_ERROR + "NumPy import failure:\n${_NUMPY_ERROR_VALUE}") + endif() + set(NUMPY_FOUND FALSE) + return() +endif() + +# Convert the process output into a list +string(REGEX REPLACE ";" "\\\\;" _NUMPY_VALUES ${_NUMPY_VALUES_OUTPUT}) +string(REGEX REPLACE "\n" ";" _NUMPY_VALUES ${_NUMPY_VALUES}) +# Just in case there is unexpected output from the Python command. +list(GET _NUMPY_VALUES -2 NUMPY_VERSION) +list(GET _NUMPY_VALUES -1 NUMPY_INCLUDE_DIRS) + +string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" _VER_CHECK "${NUMPY_VERSION}") +if("${_VER_CHECK}" STREQUAL "") + # The output from Python was unexpected. Raise an error always + # here, because we found NumPy, but it appears to be corrupted somehow. + message(FATAL_ERROR + "Requested version and include path from NumPy, got instead:\n${_NUMPY_VALUES_OUTPUT}\n") + return() +endif() + +# Make sure all directory separators are '/' +string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIRS ${NUMPY_INCLUDE_DIRS}) + +# Get the major and minor version numbers +string(REGEX REPLACE "\\." ";" _NUMPY_VERSION_LIST ${NUMPY_VERSION}) +list(GET _NUMPY_VERSION_LIST 0 NUMPY_VERSION_MAJOR) +list(GET _NUMPY_VERSION_LIST 1 NUMPY_VERSION_MINOR) +list(GET _NUMPY_VERSION_LIST 2 NUMPY_VERSION_PATCH) +string(REGEX MATCH "[0-9]*" NUMPY_VERSION_PATCH ${NUMPY_VERSION_PATCH}) +math(EXPR NUMPY_VERSION_DECIMAL + "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}") + +find_package_message(NUMPY + "Found NumPy: version \"${NUMPY_VERSION}\" ${NUMPY_INCLUDE_DIRS}" + "${NUMPY_INCLUDE_DIRS}${NUMPY_VERSION}") + +set(NUMPY_FOUND TRUE) + + diff --git a/CMakeScripts/FindProtobuf.cmake b/CMakeScripts/FindProtobuf.cmake new file mode 100644 index 00000000000..0f94f498197 --- /dev/null +++ b/CMakeScripts/FindProtobuf.cmake @@ -0,0 +1,152 @@ +# Locate and configure the Google Protocol Buffers library. +# Defines the following variables: +# +# PROTOBUF_FOUND - Found the Google Protocol Buffers library +# PROTOBUF_INCLUDE_DIRS - Include directories for Google Protocol Buffers +# PROTOBUF_LIBRARIES - The protobuf library +# +# The following cache variables are also defined: +# PROTOBUF_LIBRARY - The protobuf library +# PROTOBUF_PROTOC_LIBRARY - The protoc library +# PROTOBUF_INCLUDE_DIR - The include directory for protocol buffers +# PROTOBUF_PROTOC_EXECUTABLE - The protoc compiler +# +# ==================================================================== +# Example: +# +# find_package(Protobuf REQUIRED) +# include_directories(${PROTOBUF_INCLUDE_DIRS}) +# +# include_directories(${CMAKE_CURRENT_BINARY_DIR}) +# PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS foo.proto) +# add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS}) +# target_link_libraries(bar ${PROTOBUF_LIBRARY}) +# +# NOTE: You may need to link against pthreads, depending +# on the platform. +# ==================================================================== +# +# PROTOBUF_GENERATE_CPP (public function) +# SRCS = Variable to define with autogenerated +# source files +# HDRS = Variable to define with autogenerated +# header files +# ARGN = proto files +# +# ==================================================================== + + +#============================================================================= +# Copyright 2009 Kitware, Inc. +# Copyright 2009 Philip Lowman +# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distributed this file outside of CMake, substitute the full +# License text for the above reference.) + +function(PROTOBUF_GENERATE_PYTHON SRCS) + if(NOT ARGN) + message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files") + return() + endif(NOT ARGN) + + set(${SRCS}) + foreach(FIL ${ARGN}) + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(FIL_WE ${FIL} NAME_WE) + + + list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py") + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py" + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} + ARGS --python_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} +${ABS_FIL} + DEPENDS ${ABS_FIL} + COMMENT "Running Python protocol buffer compiler on ${FIL}" + VERBATIM ) + endforeach() + + + set_source_files_properties(${${SRCS}} PROPERTIES GENERATED TRUE) + set(${SRCS} ${${SRCS}} PARENT_SCOPE) +endfunction() + + +function(PROTOBUF_GENERATE_CPP SRCS HDRS) + if(NOT ARGN) + message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files") + return() + endif(NOT ARGN) + + set(${SRCS}) + set(${HDRS}) + foreach(FIL ${ARGN}) + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(FIL_WE ${FIL} NAME_WE) + + list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc") + list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h") + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc" + "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h" + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} + ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} +${ABS_FIL} + DEPENDS ${ABS_FIL} + COMMENT "Running C++ protocol buffer compiler on ${FIL}" + VERBATIM ) + endforeach() + + set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE) + set(${SRCS} ${${SRCS}} PARENT_SCOPE) + set(${HDRS} ${${HDRS}} PARENT_SCOPE) +endfunction() + + +find_path(PROTOBUF_INCLUDE_DIR google/protobuf/service.h) + +# Google's provided vcproj files generate libraries with a "lib" +# prefix on Windows +if(WIN32) + set(PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}") + set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "") +endif() + +find_library(PROTOBUF_LIBRARY NAMES protobuf + DOC "The Google Protocol Buffers Library" +) +find_library(PROTOBUF_PROTOC_LIBRARY NAMES protoc + DOC "The Google Protocol Buffers Compiler Library" +) +find_program(PROTOBUF_PROTOC_EXECUTABLE NAMES protoc + DOC "The Google Protocol Buffers Compiler" +) + +mark_as_advanced(PROTOBUF_INCLUDE_DIR + PROTOBUF_LIBRARY + PROTOBUF_PROTOC_LIBRARY + PROTOBUF_PROTOC_EXECUTABLE) + +# Restore original find library prefixes +if(WIN32) + set(CMAKE_FIND_LIBRARY_PREFIXES "${PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES}") +endif() + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG + PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR) + +if(PROTOBUF_FOUND) + set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR}) + set(PROTOBUF_LIBRARIES ${PROTOBUF_LIBRARY}) +endif() diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 343c863adf5..6470517d213 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,20 +1,58 @@ project( Python ) # Python -find_package(PythonLibs REQUIRED) -include_directories(${PYTHON_INCLUDE_DIRS}) +find_package(PythonLibs 2.7 REQUIRED) + +# Numpy +find_package(NumPy REQUIRED) # Boost.Python find_package(Boost 1.46 COMPONENTS python REQUIRED) -include_directories(${Boost_INCLUDE_DIRS}) + + + +#In case you have both python2 and python3 installed the quickest way to +#compile pycaffe with cmake is to replace the following hardcoded paths. +#Althernativley the Find* scripts could be rewritten to support choice of +#of python version. +#if(${PYTHONLIBS_VERSION_STRING} MATCHES "^[3-9]+\\.[0-9]+(\\.[0-9]+.*)?$") +# +# set( PYTHON_INCLUDE_DIRS "/usr/include/python2.7") +# set( PYTHON_LIBRARIES "/usr/lib64/libpython2.7.so") +# set( NUMPY_INCLUDE_DIRS "/usr/lib64/python2.7/site-packages/numpy/core/include/") +# set( PYTHON_LIBRARIES "/usr/lib64/python2.7/site-packages/numpy/lib/") +# set(Boost_LIBRARIES "/usr/lib64/libboost_python-2.7-mt.so") +# +# message( "Warning: cmake found python3 by default, switching to hardcoded paths") +# +# message( "PYTHON_INCLUDE_DIRS =/usr/include/python2.7") +# message( "PYTHON_LIBRARIES =/usr/lib64/libpython2.7.so") +# message( "NUMPY_INCLUDE_DIRS =/usr/lib64/python2.7/site-packages/numpy/core/include/") +# message( "PYTHON_LIBRARIES =/usr/lib64/python2.7/site-packages/numpy/lib/") +# message( "Boost_LIBRARIES =/usr/lib64/libboost_python-2.7-mt.so") +#endif() + + +include_directories(${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS}) file(GLOB_RECURSE Python_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) add_library(pycaffe SHARED ${Python_SOURCES}) -target_link_libraries(pycaffe caffe ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}) -### Install ################################################################################# +add_dependencies(pycaffe protoPy) + +target_link_libraries(pycaffe ${CAFFE_STATIC_LINK} ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}) + +set_target_properties(pycaffe PROPERTIES PREFIX "") +set_target_properties(pycaffe PROPERTIES OUTPUT_NAME "_caffe") + +### Install ############################################################# install(DIRECTORY caffe DESTINATION python) install(FILES requirements.txt DESTINATION python) + +#This installs a library named "libpycaffe.so" install(TARGETS pycaffe DESTINATION python/caffe) + + diff --git a/src/caffe/proto/CMakeLists.txt b/src/caffe/proto/CMakeLists.txt index 186a856509b..12e7ce0a326 100644 --- a/src/caffe/proto/CMakeLists.txt +++ b/src/caffe/proto/CMakeLists.txt @@ -14,11 +14,15 @@ endif() include_directories(${PROTOBUF_INCLUDE_DIR}) file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto") PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles}) +PROTOBUF_GENERATE_PYTHON(ProtoSourcesPy ${ProtoFiles}) + +add_custom_target(protoPy DEPENDS ${ProtoSourcesPy}) add_library(proto ${ProtoSources} ${ProtoHeaders} -) + ) + target_link_libraries(proto ${PROTOBUF_LIBRARIES}) @@ -35,3 +39,8 @@ foreach(header ${ProtoHeaders}) ) endforeach(header) + +file(WRITE __init__.py) +install(PROGRAMS __init__.py DESTINATION python/caffe/proto) +install(PROGRAMS ${ProtoSourcesPy} DESTINATION python/caffe/proto) + From 44bc1552781eea958c228981a8638ddfcf80e3d9 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Thu, 9 Oct 2014 21:41:11 -0700 Subject: [PATCH 094/798] fix instantiation --- include/caffe/common.hpp | 23 +++++++++++++++++++ src/caffe/layers/absval_layer.cu | 2 +- src/caffe/layers/base_data_layer.cu | 2 +- src/caffe/layers/bnll_layer.cu | 2 +- src/caffe/layers/concat_layer.cu | 2 +- src/caffe/layers/contrastive_loss_layer.cu | 2 +- src/caffe/layers/conv_layer.cu | 2 +- src/caffe/layers/cudnn_conv_layer.cu | 2 +- src/caffe/layers/cudnn_pooling_layer.cu | 2 +- src/caffe/layers/cudnn_relu_layer.cu | 2 +- src/caffe/layers/cudnn_sigmoid_layer.cu | 2 +- src/caffe/layers/cudnn_softmax_layer.cu | 2 +- src/caffe/layers/cudnn_tanh_layer.cu | 2 +- src/caffe/layers/dropout_layer.cu | 2 +- src/caffe/layers/eltwise_layer.cu | 2 +- src/caffe/layers/euclidean_loss_layer.cu | 2 +- src/caffe/layers/exp_layer.cu | 2 +- src/caffe/layers/flatten_layer.cu | 2 +- src/caffe/layers/hdf5_data_layer.cu | 2 +- src/caffe/layers/hdf5_output_layer.cu | 2 +- src/caffe/layers/im2col_layer.cu | 2 +- src/caffe/layers/inner_product_layer.cu | 2 +- src/caffe/layers/lrn_layer.cu | 13 ++++++++++- src/caffe/layers/mvn_layer.cu | 2 +- src/caffe/layers/pooling_layer.cu | 2 +- src/caffe/layers/power_layer.cu | 2 +- src/caffe/layers/relu_layer.cu | 2 +- .../sigmoid_cross_entropy_loss_layer.cu | 2 +- src/caffe/layers/sigmoid_layer.cu | 2 +- src/caffe/layers/silence_layer.cu | 2 +- src/caffe/layers/slice_layer.cu | 2 +- src/caffe/layers/softmax_layer.cu | 2 +- src/caffe/layers/softmax_loss_layer.cu | 2 +- src/caffe/layers/split_layer.cu | 2 +- src/caffe/layers/tanh_layer.cu | 2 +- src/caffe/layers/threshold_layer.cu | 2 +- 36 files changed, 69 insertions(+), 35 deletions(-) diff --git a/include/caffe/common.hpp b/include/caffe/common.hpp index 811b45e2c15..e7776ba5d7b 100644 --- a/include/caffe/common.hpp +++ b/include/caffe/common.hpp @@ -34,9 +34,32 @@ private:\ // Instantiate a class with float and double specifications. #define INSTANTIATE_CLASS(classname) \ + char gInstantiationGuard##classname; \ template class classname; \ template class classname +#define INSTANTIATE_LAYER_GPU_FORWARD(classname) \ + template void classname::Forward_gpu( \ + const std::vector*>& bottom, \ + const std::vector*>& top); \ + template void classname::Forward_gpu( \ + const std::vector*>& bottom, \ + const std::vector*>& top); + +#define INSTANTIATE_LAYER_GPU_BACKWARD(classname) \ + template void classname::Backward_gpu( \ + const std::vector*>& top, \ + const std::vector& propagate_down, \ + const std::vector*>& bottom); \ + template void classname::Backward_gpu( \ + const std::vector*>& top, \ + const std::vector& propagate_down, \ + const std::vector*>& bottom) + +#define INSTANTIATE_LAYER_GPU_FUNCS(classname) \ + INSTANTIATE_LAYER_GPU_FORWARD(classname); \ + INSTANTIATE_LAYER_GPU_BACKWARD(classname) + // A simple macro to mark codes that are not implemented, so that when the code // is executed we will see a fatal log. #define NOT_IMPLEMENTED LOG(FATAL) << "Not Implemented Yet" diff --git a/src/caffe/layers/absval_layer.cu b/src/caffe/layers/absval_layer.cu index 48c766465fa..732d4c6252b 100644 --- a/src/caffe/layers/absval_layer.cu +++ b/src/caffe/layers/absval_layer.cu @@ -28,7 +28,7 @@ void AbsValLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(AbsValLayer); +INSTANTIATE_LAYER_GPU_FUNCS(AbsValLayer); } // namespace caffe diff --git a/src/caffe/layers/base_data_layer.cu b/src/caffe/layers/base_data_layer.cu index ff1510361b6..204a16d260a 100644 --- a/src/caffe/layers/base_data_layer.cu +++ b/src/caffe/layers/base_data_layer.cu @@ -20,6 +20,6 @@ void BasePrefetchingDataLayer::Forward_gpu( CreatePrefetchThread(); } -INSTANTIATE_CLASS(BasePrefetchingDataLayer); +INSTANTIATE_LAYER_GPU_FORWARD(BasePrefetchingDataLayer); } // namespace caffe diff --git a/src/caffe/layers/bnll_layer.cu b/src/caffe/layers/bnll_layer.cu index 3993bccd9b5..d963d0687d2 100644 --- a/src/caffe/layers/bnll_layer.cu +++ b/src/caffe/layers/bnll_layer.cu @@ -54,7 +54,7 @@ void BNLLLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(BNLLLayer); +INSTANTIATE_LAYER_GPU_FUNCS(BNLLLayer); } // namespace caffe diff --git a/src/caffe/layers/concat_layer.cu b/src/caffe/layers/concat_layer.cu index 1b4e40aa415..88fc090025f 100644 --- a/src/caffe/layers/concat_layer.cu +++ b/src/caffe/layers/concat_layer.cu @@ -71,6 +71,6 @@ void ConcatLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(ConcatLayer); +INSTANTIATE_LAYER_GPU_FUNCS(ConcatLayer); } // namespace caffe diff --git a/src/caffe/layers/contrastive_loss_layer.cu b/src/caffe/layers/contrastive_loss_layer.cu index 14b55b37173..78a55995a0a 100644 --- a/src/caffe/layers/contrastive_loss_layer.cu +++ b/src/caffe/layers/contrastive_loss_layer.cu @@ -86,6 +86,6 @@ void ContrastiveLossLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(ContrastiveLossLayer); +INSTANTIATE_LAYER_GPU_FUNCS(ContrastiveLossLayer); } // namespace caffe diff --git a/src/caffe/layers/conv_layer.cu b/src/caffe/layers/conv_layer.cu index 27d6500d6ef..af14facb523 100644 --- a/src/caffe/layers/conv_layer.cu +++ b/src/caffe/layers/conv_layer.cu @@ -137,6 +137,6 @@ void ConvolutionLayer::Backward_gpu(const vector*>& top, } -INSTANTIATE_CLASS(ConvolutionLayer); +INSTANTIATE_LAYER_GPU_FUNCS(ConvolutionLayer); } // namespace caffe diff --git a/src/caffe/layers/cudnn_conv_layer.cu b/src/caffe/layers/cudnn_conv_layer.cu index cf8607e1b78..071014e1b48 100644 --- a/src/caffe/layers/cudnn_conv_layer.cu +++ b/src/caffe/layers/cudnn_conv_layer.cu @@ -106,7 +106,7 @@ void CuDNNConvolutionLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(CuDNNConvolutionLayer); +INSTANTIATE_LAYER_GPU_FUNCS(CuDNNConvolutionLayer); } // namespace caffe #endif diff --git a/src/caffe/layers/cudnn_pooling_layer.cu b/src/caffe/layers/cudnn_pooling_layer.cu index 8b9e7f1bf10..1c113aad75f 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cu +++ b/src/caffe/layers/cudnn_pooling_layer.cu @@ -33,7 +33,7 @@ void CuDNNPoolingLayer::Backward_gpu(const vector*>& top, bottom_desc_, bottom_data, bottom_desc_, bottom_diff)); } -INSTANTIATE_CLASS(CuDNNPoolingLayer); +INSTANTIATE_LAYER_GPU_FUNCS(CuDNNPoolingLayer); } // namespace caffe #endif diff --git a/src/caffe/layers/cudnn_relu_layer.cu b/src/caffe/layers/cudnn_relu_layer.cu index e3900f37ab9..862508707a0 100644 --- a/src/caffe/layers/cudnn_relu_layer.cu +++ b/src/caffe/layers/cudnn_relu_layer.cu @@ -45,7 +45,7 @@ void CuDNNReLULayer::Backward_gpu(const vector*>& top, this->bottom_desc_, bottom_data, this->bottom_desc_, bottom_diff)); } -INSTANTIATE_CLASS(CuDNNReLULayer); +INSTANTIATE_LAYER_GPU_FUNCS(CuDNNReLULayer); } // namespace caffe #endif diff --git a/src/caffe/layers/cudnn_sigmoid_layer.cu b/src/caffe/layers/cudnn_sigmoid_layer.cu index 50bf5fcb9e0..31b094e25d4 100644 --- a/src/caffe/layers/cudnn_sigmoid_layer.cu +++ b/src/caffe/layers/cudnn_sigmoid_layer.cu @@ -35,7 +35,7 @@ void CuDNNSigmoidLayer::Backward_gpu(const vector*>& top, this->bottom_desc_, bottom_data, this->bottom_desc_, bottom_diff)); } -INSTANTIATE_CLASS(CuDNNSigmoidLayer); +INSTANTIATE_LAYER_GPU_FUNCS(CuDNNSigmoidLayer); } // namespace caffe #endif diff --git a/src/caffe/layers/cudnn_softmax_layer.cu b/src/caffe/layers/cudnn_softmax_layer.cu index aef66730bff..f328afdd831 100644 --- a/src/caffe/layers/cudnn_softmax_layer.cu +++ b/src/caffe/layers/cudnn_softmax_layer.cu @@ -35,7 +35,7 @@ void CuDNNSoftmaxLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(CuDNNSoftmaxLayer); +INSTANTIATE_LAYER_GPU_FUNCS(CuDNNSoftmaxLayer); } // namespace caffe #endif diff --git a/src/caffe/layers/cudnn_tanh_layer.cu b/src/caffe/layers/cudnn_tanh_layer.cu index 20f887de8d0..bf9ec7cfac4 100644 --- a/src/caffe/layers/cudnn_tanh_layer.cu +++ b/src/caffe/layers/cudnn_tanh_layer.cu @@ -35,7 +35,7 @@ void CuDNNTanHLayer::Backward_gpu(const vector*>& top, this->bottom_desc_, bottom_data, this->bottom_desc_, bottom_diff)); } -INSTANTIATE_CLASS(CuDNNTanHLayer); +INSTANTIATE_LAYER_GPU_FUNCS(CuDNNTanHLayer); } // namespace caffe #endif diff --git a/src/caffe/layers/dropout_layer.cu b/src/caffe/layers/dropout_layer.cu index fa737b86a89..df13d8ecb23 100644 --- a/src/caffe/layers/dropout_layer.cu +++ b/src/caffe/layers/dropout_layer.cu @@ -71,7 +71,7 @@ void DropoutLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(DropoutLayer); +INSTANTIATE_LAYER_GPU_FUNCS(DropoutLayer); } // namespace caffe diff --git a/src/caffe/layers/eltwise_layer.cu b/src/caffe/layers/eltwise_layer.cu index 9295cc6ad11..2247870d97f 100644 --- a/src/caffe/layers/eltwise_layer.cu +++ b/src/caffe/layers/eltwise_layer.cu @@ -130,6 +130,6 @@ void EltwiseLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(EltwiseLayer); +INSTANTIATE_LAYER_GPU_FUNCS(EltwiseLayer); } // namespace caffe diff --git a/src/caffe/layers/euclidean_loss_layer.cu b/src/caffe/layers/euclidean_loss_layer.cu index 0f0c1a86f9d..5b1de3ad2d9 100644 --- a/src/caffe/layers/euclidean_loss_layer.cu +++ b/src/caffe/layers/euclidean_loss_layer.cu @@ -39,6 +39,6 @@ void EuclideanLossLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(EuclideanLossLayer); +INSTANTIATE_LAYER_GPU_FUNCS(EuclideanLossLayer); } // namespace caffe diff --git a/src/caffe/layers/exp_layer.cu b/src/caffe/layers/exp_layer.cu index a0fd672a25a..2d75d8dd6c7 100644 --- a/src/caffe/layers/exp_layer.cu +++ b/src/caffe/layers/exp_layer.cu @@ -38,7 +38,7 @@ void ExpLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(ExpLayer); +INSTANTIATE_LAYER_GPU_FUNCS(ExpLayer); } // namespace caffe diff --git a/src/caffe/layers/flatten_layer.cu b/src/caffe/layers/flatten_layer.cu index ef89bab6ff4..42abdad4499 100644 --- a/src/caffe/layers/flatten_layer.cu +++ b/src/caffe/layers/flatten_layer.cu @@ -18,6 +18,6 @@ void FlattenLayer::Backward_gpu(const vector*>& top, bottom[0]->ShareDiff(*top[0]); } -INSTANTIATE_CLASS(FlattenLayer); +INSTANTIATE_LAYER_GPU_FUNCS(FlattenLayer); } // namespace caffe diff --git a/src/caffe/layers/hdf5_data_layer.cu b/src/caffe/layers/hdf5_data_layer.cu index 9f5daf230e7..02e3821d104 100644 --- a/src/caffe/layers/hdf5_data_layer.cu +++ b/src/caffe/layers/hdf5_data_layer.cu @@ -41,6 +41,6 @@ void HDF5DataLayer::Forward_gpu(const vector*>& bottom, } } -INSTANTIATE_CLASS(HDF5DataLayer); +INSTANTIATE_LAYER_GPU_FUNCS(HDF5DataLayer); } // namespace caffe diff --git a/src/caffe/layers/hdf5_output_layer.cu b/src/caffe/layers/hdf5_output_layer.cu index 929c1ad8e22..ae497c34fc2 100644 --- a/src/caffe/layers/hdf5_output_layer.cu +++ b/src/caffe/layers/hdf5_output_layer.cu @@ -38,6 +38,6 @@ void HDF5OutputLayer::Backward_gpu(const vector*>& top, return; } -INSTANTIATE_CLASS(HDF5OutputLayer); +INSTANTIATE_LAYER_GPU_FUNCS(HDF5OutputLayer); } // namespace caffe diff --git a/src/caffe/layers/im2col_layer.cu b/src/caffe/layers/im2col_layer.cu index bad789c17fe..9c338b14cb7 100644 --- a/src/caffe/layers/im2col_layer.cu +++ b/src/caffe/layers/im2col_layer.cu @@ -32,6 +32,6 @@ void Im2colLayer::Backward_gpu(const vector*>& top, } -INSTANTIATE_CLASS(Im2colLayer); +INSTANTIATE_LAYER_GPU_FUNCS(Im2colLayer); } // namespace caffe diff --git a/src/caffe/layers/inner_product_layer.cu b/src/caffe/layers/inner_product_layer.cu index 2164b4d4f16..a9e1784a205 100644 --- a/src/caffe/layers/inner_product_layer.cu +++ b/src/caffe/layers/inner_product_layer.cu @@ -51,6 +51,6 @@ void InnerProductLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(InnerProductLayer); +INSTANTIATE_LAYER_GPU_FUNCS(InnerProductLayer); } // namespace caffe diff --git a/src/caffe/layers/lrn_layer.cu b/src/caffe/layers/lrn_layer.cu index 47b003bc4aa..58c39926c72 100644 --- a/src/caffe/layers/lrn_layer.cu +++ b/src/caffe/layers/lrn_layer.cu @@ -98,6 +98,10 @@ void LRNLayer::CrossChannelForward_gpu( n_threads, bottom_data, scale_data, -beta_, top_data); CUDA_POST_KERNEL_CHECK; } +template void LRNLayer::CrossChannelForward_gpu( + const vector*>& bottom, const vector*>& top); +template void LRNLayer::CrossChannelForward_gpu( + const vector*>& bottom, const vector*>& top); template @@ -188,8 +192,15 @@ void LRNLayer::CrossChannelBackward_gpu( size_, -beta_, Dtype(2. * alpha_ * beta_ / size_), bottom[0]->mutable_gpu_diff()); } +template void LRNLayer::CrossChannelBackward_gpu( + const vector*>& top, const vector& propagate_down, + const vector*>& bottom); +template void LRNLayer::CrossChannelBackward_gpu( + const vector*>& top, const vector& propagate_down, + const vector*>& bottom); -INSTANTIATE_CLASS(LRNLayer); + +INSTANTIATE_LAYER_GPU_FUNCS(LRNLayer); } // namespace caffe diff --git a/src/caffe/layers/mvn_layer.cu b/src/caffe/layers/mvn_layer.cu index c2a241f093f..0667f50380f 100644 --- a/src/caffe/layers/mvn_layer.cu +++ b/src/caffe/layers/mvn_layer.cu @@ -139,7 +139,7 @@ void MVNLayer::Backward_gpu(const vector*>& top, } -INSTANTIATE_CLASS(MVNLayer); +INSTANTIATE_LAYER_GPU_FUNCS(MVNLayer); } // namespace caffe diff --git a/src/caffe/layers/pooling_layer.cu b/src/caffe/layers/pooling_layer.cu index aec985a7864..0d3f2183e71 100644 --- a/src/caffe/layers/pooling_layer.cu +++ b/src/caffe/layers/pooling_layer.cu @@ -373,7 +373,7 @@ void PoolingLayer::Backward_gpu(const vector*>& top, } -INSTANTIATE_CLASS(PoolingLayer); +INSTANTIATE_LAYER_GPU_FUNCS(PoolingLayer); } // namespace caffe diff --git a/src/caffe/layers/power_layer.cu b/src/caffe/layers/power_layer.cu index 367320a9b1f..90d944059b6 100644 --- a/src/caffe/layers/power_layer.cu +++ b/src/caffe/layers/power_layer.cu @@ -81,7 +81,7 @@ void PowerLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(PowerLayer); +INSTANTIATE_LAYER_GPU_FUNCS(PowerLayer); } // namespace caffe diff --git a/src/caffe/layers/relu_layer.cu b/src/caffe/layers/relu_layer.cu index 22d5f4b5c5e..b8924c855e5 100644 --- a/src/caffe/layers/relu_layer.cu +++ b/src/caffe/layers/relu_layer.cu @@ -59,7 +59,7 @@ void ReLULayer::Backward_gpu(const vector*>& top, } -INSTANTIATE_CLASS(ReLULayer); +INSTANTIATE_LAYER_GPU_FUNCS(ReLULayer); } // namespace caffe diff --git a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu index 175f6f86574..d9db4af64e6 100644 --- a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu +++ b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu @@ -51,7 +51,7 @@ void SigmoidCrossEntropyLossLayer::Backward_gpu( } } -INSTANTIATE_CLASS(SigmoidCrossEntropyLossLayer); +INSTANTIATE_LAYER_GPU_FUNCS(SigmoidCrossEntropyLossLayer); } // namespace caffe diff --git a/src/caffe/layers/sigmoid_layer.cu b/src/caffe/layers/sigmoid_layer.cu index 6879ff7f570..e1af0657ec1 100644 --- a/src/caffe/layers/sigmoid_layer.cu +++ b/src/caffe/layers/sigmoid_layer.cu @@ -56,7 +56,7 @@ void SigmoidLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(SigmoidLayer); +INSTANTIATE_LAYER_GPU_FUNCS(SigmoidLayer); } // namespace caffe diff --git a/src/caffe/layers/silence_layer.cu b/src/caffe/layers/silence_layer.cu index b350b1950bd..8d044ee7307 100644 --- a/src/caffe/layers/silence_layer.cu +++ b/src/caffe/layers/silence_layer.cu @@ -23,6 +23,6 @@ void SilenceLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(SilenceLayer); +INSTANTIATE_LAYER_GPU_FUNCS(SilenceLayer); } // namespace caffe diff --git a/src/caffe/layers/slice_layer.cu b/src/caffe/layers/slice_layer.cu index 657840809f6..b5c5e61533f 100644 --- a/src/caffe/layers/slice_layer.cu +++ b/src/caffe/layers/slice_layer.cu @@ -63,6 +63,6 @@ void SliceLayer::Backward_gpu(const vector*>& top, } // slice_dim_ is guaranteed to be 0 or 1 by SetUp. } -INSTANTIATE_CLASS(SliceLayer); +INSTANTIATE_LAYER_GPU_FUNCS(SliceLayer); } // namespace caffe diff --git a/src/caffe/layers/softmax_layer.cu b/src/caffe/layers/softmax_layer.cu index 8ba31d75951..292ad2b396a 100644 --- a/src/caffe/layers/softmax_layer.cu +++ b/src/caffe/layers/softmax_layer.cu @@ -148,7 +148,7 @@ void SoftmaxLayer::Backward_gpu(const vector*>& top, caffe_gpu_mul(top[0]->count(), bottom_diff, top_data, bottom_diff); } -INSTANTIATE_CLASS(SoftmaxLayer); +INSTANTIATE_LAYER_GPU_FUNCS(SoftmaxLayer); } // namespace caffe diff --git a/src/caffe/layers/softmax_loss_layer.cu b/src/caffe/layers/softmax_loss_layer.cu index 060dc24d06e..4cdaf51b165 100644 --- a/src/caffe/layers/softmax_loss_layer.cu +++ b/src/caffe/layers/softmax_loss_layer.cu @@ -21,7 +21,7 @@ void SoftmaxWithLossLayer::Backward_gpu(const vector*>& top, Backward_cpu(top, propagate_down, bottom); } -INSTANTIATE_CLASS(SoftmaxWithLossLayer); +INSTANTIATE_LAYER_GPU_FUNCS(SoftmaxWithLossLayer); } // namespace caffe diff --git a/src/caffe/layers/split_layer.cu b/src/caffe/layers/split_layer.cu index 0513b204d91..a4f5df26452 100644 --- a/src/caffe/layers/split_layer.cu +++ b/src/caffe/layers/split_layer.cu @@ -33,6 +33,6 @@ void SplitLayer::Backward_gpu(const vector*>& top, } -INSTANTIATE_CLASS(SplitLayer); +INSTANTIATE_LAYER_GPU_FUNCS(SplitLayer); } // namespace caffe diff --git a/src/caffe/layers/tanh_layer.cu b/src/caffe/layers/tanh_layer.cu index a141f8e872e..f1a0fc88bfd 100644 --- a/src/caffe/layers/tanh_layer.cu +++ b/src/caffe/layers/tanh_layer.cu @@ -54,7 +54,7 @@ void TanHLayer::Backward_gpu(const vector*>& top, } } -INSTANTIATE_CLASS(TanHLayer); +INSTANTIATE_LAYER_GPU_FUNCS(TanHLayer); } // namespace caffe diff --git a/src/caffe/layers/threshold_layer.cu b/src/caffe/layers/threshold_layer.cu index 7e651290897..bfa7f159460 100644 --- a/src/caffe/layers/threshold_layer.cu +++ b/src/caffe/layers/threshold_layer.cu @@ -27,7 +27,7 @@ void ThresholdLayer::Forward_gpu(const vector*>& bottom, } -INSTANTIATE_CLASS(ThresholdLayer); +INSTANTIATE_LAYER_GPU_FORWARD(ThresholdLayer); } // namespace caffe From b025da73e397b50e7f4136ad7546961d60ea934b Mon Sep 17 00:00:00 2001 From: Sergio Date: Fri, 3 Oct 2014 17:14:20 -0700 Subject: [PATCH 095/798] Added Multistep, Poly and Sigmoid learning rate decay policies Conflicts: include/caffe/solver.hpp src/caffe/proto/caffe.proto src/caffe/solver.cpp --- .../lenet/lenet_multistep_solver.prototxt | 33 +++++++++++++++++ .../lenet/lenet_stepearly_solver.prototxt | 28 ++++++++++++++ include/caffe/solver.hpp | 1 + src/caffe/proto/caffe.proto | 8 +++- src/caffe/solver.cpp | 37 ++++++++++++++++--- 5 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 examples/lenet/lenet_multistep_solver.prototxt create mode 100644 examples/lenet/lenet_stepearly_solver.prototxt diff --git a/examples/lenet/lenet_multistep_solver.prototxt b/examples/lenet/lenet_multistep_solver.prototxt new file mode 100644 index 00000000000..fadd7c904d7 --- /dev/null +++ b/examples/lenet/lenet_multistep_solver.prototxt @@ -0,0 +1,33 @@ +# The training protocol buffer definition +train_net: "lenet_train.prototxt" +# The testing protocol buffer definition +test_net: "lenet_test.prototxt" +# test_iter specifies how many forward passes the test should carry out. +# In the case of MNIST, we have test batch size 100 and 100 test iterations, +# covering the full 10,000 testing images. +test_iter: 100 +# Carry out testing every 500 training iterations. +test_interval: 500 +# The base learning rate, momentum and the weight decay of the network. +base_lr: 0.01 +momentum: 0.9 +weight_decay: 0.0005 +# The learning rate policy +lr_policy: "multistep" +gamma: 0.9 +stepvalue: 1000 +stepvalue: 2000 +stepvalue: 2500 +stepvalue: 3000 +stepvalue: 3500 +stepvalue: 4000 +# Display every 100 iterations +display: 100 +# The maximum number of iterations +max_iter: 10000 +# snapshot intermediate results +snapshot: 5000 +snapshot_prefix: "lenet" +# solver mode: 0 for CPU and 1 for GPU +solver_mode: 1 +device_id: 1 diff --git a/examples/lenet/lenet_stepearly_solver.prototxt b/examples/lenet/lenet_stepearly_solver.prototxt new file mode 100644 index 00000000000..efc6a335d8f --- /dev/null +++ b/examples/lenet/lenet_stepearly_solver.prototxt @@ -0,0 +1,28 @@ +# The training protocol buffer definition +train_net: "lenet_train.prototxt" +# The testing protocol buffer definition +test_net: "lenet_test.prototxt" +# test_iter specifies how many forward passes the test should carry out. +# In the case of MNIST, we have test batch size 100 and 100 test iterations, +# covering the full 10,000 testing images. +test_iter: 100 +# Carry out testing every 500 training iterations. +test_interval: 500 +# The base learning rate, momentum and the weight decay of the network. +base_lr: 0.01 +momentum: 0.9 +weight_decay: 0.0005 +# The learning rate policy +lr_policy: "stepearly" +gamma: 0.9 +stepearly: 1 +# Display every 100 iterations +display: 100 +# The maximum number of iterations +max_iter: 10000 +# snapshot intermediate results +snapshot: 5000 +snapshot_prefix: "lenet" +# solver mode: 0 for CPU and 1 for GPU +solver_mode: 1 +device_id: 1 diff --git a/include/caffe/solver.hpp b/include/caffe/solver.hpp index 2bad0e2fe1e..b20912606f8 100644 --- a/include/caffe/solver.hpp +++ b/include/caffe/solver.hpp @@ -57,6 +57,7 @@ class Solver { SolverParameter param_; int iter_; + int current_step_; shared_ptr > net_; vector > > test_nets_; diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index f0404a09b90..949bafecdb2 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -63,7 +63,7 @@ message NetParameter { // NOTE // Update the next available ID when you add a new SolverParameter field. // -// SolverParameter next available ID: 34 (last added: average_loss) +// SolverParameter next available ID: 35 (last added: stepvalue) message SolverParameter { ////////////////////////////////////////////////////////////////////////////// // Specifying the train and test networks @@ -124,7 +124,10 @@ message SolverParameter { // regularization types supported: L1 and L2 // controlled by weight_decay optional string regularization_type = 29 [default = "L2"]; - optional int32 stepsize = 13; // the stepsize for learning rate policy "step" + // the stepsize for learning rate policy "step" + optional int32 stepsize = 13; + // the stepsize for learning rate policy "multistep" + repeated int32 stepvalue = 34; optional int32 snapshot = 14 [default = 0]; // The snapshot interval optional string snapshot_prefix = 15; // The prefix for the snapshot. // whether to snapshot diff in the results or not. Snapshotting diff will help @@ -166,6 +169,7 @@ message SolverState { optional int32 iter = 1; // The current iteration optional string learned_net = 2; // The file that stores the learned net. repeated BlobProto history = 3; // The history for sgd solvers + optional int32 current_step = 4 [default = 0]; // The current step for learning rate } enum Phase { diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 995df06ddc7..a13bca8b44a 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -158,6 +158,7 @@ template void Solver::Solve(const char* resume_file) { Caffe::set_phase(Caffe::TRAIN); LOG(INFO) << "Solving " << net_->name(); + LOG(INFO) << "Learning Rate Policy: " << param_.lr_policy(); PreSolve(); iter_ = 0; @@ -257,7 +258,6 @@ void Solver::TestAll() { } } - template void Solver::Test(const int test_net_id) { LOG(INFO) << "Iteration " << iter_ @@ -336,6 +336,7 @@ void Solver::Snapshot() { SnapshotSolverState(&state); state.set_iter(iter_); state.set_learned_net(model_filename); + state.set_current_step(current_step_); snapshot_filename = filename + ".solverstate"; LOG(INFO) << "Snapshotting solver state to " << snapshot_filename; WriteProtoToBinaryFile(state, snapshot_filename.c_str()); @@ -351,6 +352,7 @@ void Solver::Restore(const char* state_file) { net_->CopyTrainedLayersFrom(net_param); } iter_ = state.iter(); + current_step_ = state.current_step(); RestoreSolverState(state); } @@ -361,8 +363,15 @@ void Solver::Restore(const char* state_file) { // - step: return base_lr * gamma ^ (floor(iter / step)) // - exp: return base_lr * gamma ^ iter // - inv: return base_lr * (1 + gamma * iter) ^ (- power) -// where base_lr, gamma, step and power are defined in the solver parameter -// protocol buffer, and iter is the current iteration. +// - multistep: similar to step but it allows non uniform steps defined by +// stepvalue +// - poly: the effective learning rate follows a polynomial decay, to be +// zero by the max_iter. return base_lr (1 - iter/max_iter) ^ (power) +// - sigmoid: the effective learning rate follows a sigmod decay +// return base_lr ( 1/(1 + exp(-gamma * (iter - stepsize)))) +// +// where base_lr, max_iter, gamma, step, stepvalue and power are defined +// in the solver parameter protocol buffer, and iter is the current iteration. template Dtype SGDSolver::GetLearningRate() { Dtype rate; @@ -370,22 +379,38 @@ Dtype SGDSolver::GetLearningRate() { if (lr_policy == "fixed") { rate = this->param_.base_lr(); } else if (lr_policy == "step") { - int current_step = this->iter_ / this->param_.stepsize(); + this->current_step_ = this->iter_ / this->param_.stepsize(); rate = this->param_.base_lr() * - pow(this->param_.gamma(), current_step); + pow(this->param_.gamma(), this->current_step_); } else if (lr_policy == "exp") { rate = this->param_.base_lr() * pow(this->param_.gamma(), this->iter_); } else if (lr_policy == "inv") { rate = this->param_.base_lr() * pow(Dtype(1) + this->param_.gamma() * this->iter_, - this->param_.power()); + } else if (lr_policy == "multistep") { + if (this->current_step_ < this->param_.stepvalue_size() && + this->iter_ >= this->param_.stepvalue(this->current_step_)) { + this->current_step_++; + LOG(INFO) << "MultiStep Status: Iteration " << + this->iter_ << ", step = " << this->current_step_; + } + rate = this->param_.base_lr() * + pow(this->param_.gamma(), this->current_step_); + } else if (lr_policy == "poly") { + rate = this->param_.base_lr() * pow(Dtype(1.) - + (Dtype(this->iter_) / Dtype(this->param_.max_iter())), + this->param_.power()); + } else if (lr_policy == "sigmoid") { + rate = this->param_.base_lr() * (Dtype(1.) / + (Dtype(1.) + exp(-this->param_.gamma() * (Dtype(this->iter_) - + Dtype(this->param_.stepsize()))))); } else { LOG(FATAL) << "Unknown learning rate policy: " << lr_policy; } return rate; } - template void SGDSolver::PreSolve() { // Initialize the history From 0598fe93ac7bdc3f51c413c081283fdbc918c056 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sat, 11 Oct 2014 05:01:28 +0000 Subject: [PATCH 096/798] adding missing libraries - lm and lstdc++ --- Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 5fb597c0d60..35c37af50fb 100644 --- a/Makefile +++ b/Makefile @@ -168,9 +168,7 @@ ifneq ($(CPU_ONLY), 1) LIBRARIES := cudart cublas curand endif LIBRARIES += glog gflags protobuf leveldb snappy \ - lmdb \ - boost_system \ - hdf5_hl hdf5 \ + lmdb boost_system hdf5_hl hdf5 m \ opencv_core opencv_highgui opencv_imgproc PYTHON_LIBRARIES := boost_python python2.7 WARNINGS := -Wall -Wno-sign-compare @@ -235,7 +233,8 @@ ifeq ($(LINUX), 1) WARNINGS += -Wno-uninitialized endif # boost::thread is reasonably called boost_thread (compare OS X) - LIBRARIES += boost_thread + # We will also explicitly add stdc++ to the link target. + LIBRARIES += boost_thread stdc++ endif # OS X: From 802ee6cbd2925a6db55f9c56d939a233403bd556 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 23 Sep 2014 10:47:40 -0400 Subject: [PATCH 097/798] Minor fixes. (1) cudnn.hpp uses CHECK_EQ internally, so it needs to include glog at some point. Including caffe/common.hpp. (2) I often misconfigure some layer and softmax breaks when the dimensionality is too small for the input layers. Check and fail fast. (3) CV_LOAD_IMAGE_COLOR is deprecated and has been removed in OpenCV 3.0. Replaced with cv::IMREAD_COLOR. --- include/caffe/util/cudnn.hpp | 1 + src/caffe/layers/softmax_loss_layer.cpp | 4 +++- src/caffe/layers/window_data_layer.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/caffe/util/cudnn.hpp b/include/caffe/util/cudnn.hpp index aca5bd713fc..eaed7333df8 100644 --- a/include/caffe/util/cudnn.hpp +++ b/include/caffe/util/cudnn.hpp @@ -4,6 +4,7 @@ #include +#include "caffe/common.hpp" #include "caffe/proto/caffe.pb.h" #define CUDNN_CHECK(condition) \ diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index 651320c77f8..d39429cee5d 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -43,8 +43,10 @@ void SoftmaxWithLossLayer::Forward_cpu( Dtype loss = 0; for (int i = 0; i < num; ++i) { for (int j = 0; j < spatial_dim; j++) { + const int label_value = static_cast(label[i * spatial_dim + j]); + CHECK_GT(dim, label_value * spatial_dim); loss -= log(std::max(prob_data[i * dim + - static_cast(label[i * spatial_dim + j]) * spatial_dim + j], + label_value * spatial_dim + j], Dtype(FLT_MIN))); } } diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 009bf97c612..c6d0be0f509 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -233,7 +233,7 @@ void WindowDataLayer::InternalThreadEntry() { pair > image = image_database_[window[WindowDataLayer::IMAGE_INDEX]]; - cv::Mat cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR); + cv::Mat cv_img = cv::imread(image.first, cv::IMREAD_COLOR); if (!cv_img.data) { LOG(ERROR) << "Could not open or find file " << image.first; return; From 4587b2f9043996fed36fc989c00329ec829ecae9 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 23 Sep 2014 11:29:31 -0400 Subject: [PATCH 098/798] OpenCV should be compiled using pkg-config options. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 35c37af50fb..c8226cb6872 100644 --- a/Makefile +++ b/Makefile @@ -168,8 +168,7 @@ ifneq ($(CPU_ONLY), 1) LIBRARIES := cudart cublas curand endif LIBRARIES += glog gflags protobuf leveldb snappy \ - lmdb boost_system hdf5_hl hdf5 m \ - opencv_core opencv_highgui opencv_imgproc + lmdb boost_system hdf5_hl hdf5 m PYTHON_LIBRARIES := boost_python python2.7 WARNINGS := -Wall -Wno-sign-compare @@ -330,6 +329,7 @@ NVCCFLAGS += -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS) MATLAB_CXXFLAGS := $(CXXFLAGS) -Wno-uninitialized LINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) \ + `pkg-config opencv --libs` \ $(foreach library,$(LIBRARIES),-l$(library)) PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) From 82b614b29ba48cc4be81aa41dd688dfba82a08e1 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Mon, 29 Sep 2014 12:45:25 -0400 Subject: [PATCH 099/798] Added version dependent test for IMREAD_COLOR. --- src/caffe/layers/window_data_layer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index c6d0be0f509..62ca872a32b 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -21,6 +21,10 @@ // 'source' field specifies the window_file // 'crop_size' indicates the desired warped size +#if CV_VERSION_MAJOR == 3 +const int CV_LOAD_IMAGE_COLOR = cv::IMREAD_COLOR; +#endif + namespace caffe { template @@ -233,7 +237,7 @@ void WindowDataLayer::InternalThreadEntry() { pair > image = image_database_[window[WindowDataLayer::IMAGE_INDEX]]; - cv::Mat cv_img = cv::imread(image.first, cv::IMREAD_COLOR); + cv::Mat cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR); if (!cv_img.data) { LOG(ERROR) << "Could not open or find file " << image.first; return; From 94394a059c5b0440590f561a594b84c271bc3154 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Fri, 10 Oct 2014 18:42:27 -0400 Subject: [PATCH 100/798] Fixed CMakeList to work with OpenCV 3. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b97eb565f45..d6b08470a7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,7 +135,7 @@ find_package(LMDB REQUIRED) include_directories(${LMDB_INCLUDE_DIR}) # OpenCV -find_package(OpenCV REQUIRED core highgui imgproc) +find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) ### Subdirectories ########################################################################## From 0160a0bc16055948e79dd214a61c33041994d163 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sat, 11 Oct 2014 19:35:06 +0000 Subject: [PATCH 101/798] fix flaky test EXPECT_EQ code, using EXPECT_FLOAT_NEAR per Jeff --- src/caffe/test/test_net.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/caffe/test/test_net.cpp b/src/caffe/test/test_net.cpp index 930486dd6c5..611d11bd832 100644 --- a/src/caffe/test/test_net.cpp +++ b/src/caffe/test/test_net.cpp @@ -1155,7 +1155,7 @@ TYPED_TEST(NetTest, TestParamPropagateDown) { for (int i = 0; i < num_params; ++i) { const Dtype param_asum = caffe_cpu_asum(params2[i]->count(), params2[i]->cpu_diff()); - EXPECT_EQ(param_asum, param_asums[i]); + EXPECT_FLOAT_EQ(param_asum, param_asums[i]); } // Change a subset of the learning rates to zero; check that we see zero @@ -1172,9 +1172,9 @@ TYPED_TEST(NetTest, TestParamPropagateDown) { const Dtype param_asum = caffe_cpu_asum(params3[i]->count(), params3[i]->cpu_diff()); if (i == 1 || i == 2) { - EXPECT_EQ(0, param_asum); + EXPECT_FLOAT_EQ(0, param_asum); } else { - EXPECT_EQ(param_asum, param_asums[i]); + EXPECT_FLOAT_EQ(param_asum, param_asums[i]); } } @@ -1191,9 +1191,9 @@ TYPED_TEST(NetTest, TestParamPropagateDown) { const Dtype param_asum = caffe_cpu_asum(params4[i]->count(), params4[i]->cpu_diff()); if (i == 0 || i == 3) { - EXPECT_EQ(0, param_asum); + EXPECT_FLOAT_EQ(0, param_asum); } else { - EXPECT_EQ(param_asum, param_asums[i]); + EXPECT_FLOAT_EQ(param_asum, param_asums[i]); } } } From fc5ba940744b7294846a63ee5f427b934af9cc6d Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Sat, 11 Oct 2014 19:35:40 +0000 Subject: [PATCH 102/798] fix flaky math functions, remove unnecessary instantiations. --- include/caffe/util/math_functions.hpp | 11 +++-------- src/caffe/util/math_functions.cpp | 3 --- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/include/caffe/util/math_functions.hpp b/include/caffe/util/math_functions.hpp index a78eb5bc978..12823f8da0c 100644 --- a/include/caffe/util/math_functions.hpp +++ b/include/caffe/util/math_functions.hpp @@ -108,7 +108,7 @@ Dtype caffe_cpu_asum(const int n, const Dtype* x); // the branchless, type-safe version from // http://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c template -inline char caffe_sign(Dtype val) { +inline int8_t caffe_sign(Dtype val) { return (Dtype(0) < val) - (val < Dtype(0)); } @@ -127,12 +127,6 @@ inline char caffe_sign(Dtype val) { } \ } -#define INSTANTIATE_CAFFE_CPU_UNARY_FUNC(name) \ - template <> \ - void caffe_cpu_##name(const int n, const float* x, float* y); \ - template <> \ - void caffe_cpu_##name(const int n, const double* x, double* y) - // output is 1 for the positives, 0 for zero, and -1 for the negatives DEFINE_CAFFE_CPU_UNARY_FUNC(sign, y[i] = caffe_sign(x[i])); @@ -140,7 +134,8 @@ DEFINE_CAFFE_CPU_UNARY_FUNC(sign, y[i] = caffe_sign(x[i])); // The name sngbit is meant to avoid conflicts with std::signbit in the macro. // The extra parens are needed because CUDA < 6.5 defines signbit as a macro, // and we don't want that to expand here when CUDA headers are also included. -DEFINE_CAFFE_CPU_UNARY_FUNC(sgnbit, y[i] = (std::signbit)(x[i])); +DEFINE_CAFFE_CPU_UNARY_FUNC(sgnbit, \ + y[i] = static_cast((std::signbit)(x[i]))); DEFINE_CAFFE_CPU_UNARY_FUNC(fabs, y[i] = std::fabs(x[i])); diff --git a/src/caffe/util/math_functions.cpp b/src/caffe/util/math_functions.cpp index c3afd2ffbc5..13e17be582b 100644 --- a/src/caffe/util/math_functions.cpp +++ b/src/caffe/util/math_functions.cpp @@ -370,9 +370,6 @@ double caffe_cpu_asum(const int n, const double* x) { return cblas_dasum(n, x, 1); } -INSTANTIATE_CAFFE_CPU_UNARY_FUNC(sign); -INSTANTIATE_CAFFE_CPU_UNARY_FUNC(sgnbit); - template <> void caffe_cpu_scale(const int n, const float alpha, const float *x, float* y) { From 94f00c076f973627cd552b4b0fde6dd534039f3a Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Mon, 13 Oct 2014 13:48:27 -0700 Subject: [PATCH 103/798] some namespace simplification --- include/caffe/common.hpp | 1 + src/caffe/layers/exp_layer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/caffe/common.hpp b/include/caffe/common.hpp index e7776ba5d7b..81b2e9ae101 100644 --- a/include/caffe/common.hpp +++ b/include/caffe/common.hpp @@ -74,6 +74,7 @@ using boost::shared_ptr; using std::fstream; using std::ios; using std::isnan; +using std::isinf; using std::iterator; using std::make_pair; using std::map; diff --git a/src/caffe/layers/exp_layer.cpp b/src/caffe/layers/exp_layer.cpp index 25da1201c10..2c99bfcff93 100644 --- a/src/caffe/layers/exp_layer.cpp +++ b/src/caffe/layers/exp_layer.cpp @@ -18,9 +18,9 @@ void ExpLayer::LayerSetUp(const vector*>& bottom, // If base == -1, interpret the base as e and set log_base = 1 exactly. // Otherwise, calculate its log explicitly. const Dtype log_base = (base == Dtype(-1)) ? Dtype(1) : log(base); - CHECK(!std::isnan(log_base)) + CHECK(!isnan(log_base)) << "NaN result: log(base) = log(" << base << ") = " << log_base; - CHECK(!std::isinf(log_base)) + CHECK(!isinf(log_base)) << "Inf result: log(base) = log(" << base << ") = " << log_base; const Dtype input_scale = this->layer_param_.exp_param().scale(); const Dtype input_shift = this->layer_param_.exp_param().shift(); From 2f88daba0a1187ed2828ddc58349cd71c13f11a5 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Mon, 13 Oct 2014 15:25:41 -0700 Subject: [PATCH 104/798] move registration code to corresponding cpp files. --- src/caffe/layer_factory.cpp | 93 +++++++------------ src/caffe/layers/absval_layer.cpp | 3 +- src/caffe/layers/accuracy_layer.cpp | 2 +- src/caffe/layers/argmax_layer.cpp | 1 + src/caffe/layers/bnll_layer.cpp | 3 +- src/caffe/layers/concat_layer.cpp | 2 +- src/caffe/layers/contrastive_loss_layer.cpp | 2 +- src/caffe/layers/conv_layer.cpp | 1 - src/caffe/layers/data_layer.cpp | 2 +- src/caffe/layers/dropout_layer.cpp | 3 +- src/caffe/layers/dummy_data_layer.cpp | 2 +- src/caffe/layers/eltwise_layer.cpp | 3 +- src/caffe/layers/euclidean_loss_layer.cpp | 2 +- src/caffe/layers/exp_layer.cpp | 3 +- src/caffe/layers/flatten_layer.cpp | 2 +- src/caffe/layers/hdf5_data_layer.cpp | 2 +- src/caffe/layers/hdf5_output_layer.cpp | 2 +- src/caffe/layers/hinge_loss_layer.cpp | 2 +- src/caffe/layers/im2col_layer.cpp | 2 +- src/caffe/layers/image_data_layer.cpp | 2 +- src/caffe/layers/infogain_loss_layer.cpp | 2 +- src/caffe/layers/inner_product_layer.cpp | 2 +- src/caffe/layers/lrn_layer.cpp | 3 +- src/caffe/layers/memory_data_layer.cpp | 2 +- .../multinomial_logistic_loss_layer.cpp | 2 +- src/caffe/layers/mvn_layer.cpp | 3 +- src/caffe/layers/power_layer.cpp | 3 +- .../sigmoid_cross_entropy_loss_layer.cpp | 3 +- src/caffe/layers/silence_layer.cpp | 2 +- src/caffe/layers/slice_layer.cpp | 2 +- src/caffe/layers/softmax_layer.cpp | 2 - src/caffe/layers/softmax_loss_layer.cpp | 3 +- src/caffe/layers/split_layer.cpp | 2 +- src/caffe/layers/threshold_layer.cpp | 2 +- src/caffe/layers/window_data_layer.cpp | 2 +- 35 files changed, 63 insertions(+), 106 deletions(-) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 69863543c30..5a286cd4691 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -7,9 +7,6 @@ namespace caffe { -// GetLayer() defines the overall layer factory. The Get*Layer() functions -// define factories for layers with multiple computational engines. - // Get convolution layer according to engine. template Layer* GetConvolutionLayer( @@ -32,6 +29,8 @@ Layer* GetConvolutionLayer( } } +REGISTER_LAYER_CREATOR(CONVOLUTION, GetConvolutionLayer); + // Get pooling layer according to engine. template Layer* GetPoolingLayer(const LayerParameter& param) { @@ -60,6 +59,8 @@ Layer* GetPoolingLayer(const LayerParameter& param) { } } +REGISTER_LAYER_CREATOR(POOLING, GetPoolingLayer); + // Get relu layer according to engine. template Layer* GetReLULayer(const LayerParameter& param) { @@ -81,6 +82,8 @@ Layer* GetReLULayer(const LayerParameter& param) { } } +REGISTER_LAYER_CREATOR(RELU, GetReLULayer); + // Get sigmoid layer according to engine. template Layer* GetSigmoidLayer(const LayerParameter& param) { @@ -102,26 +105,7 @@ Layer* GetSigmoidLayer(const LayerParameter& param) { } } -// Get tanh layer according to engine. -template -Layer* GetTanHLayer(const LayerParameter& param) { - TanHParameter_Engine engine = param.tanh_param().engine(); - if (engine == TanHParameter_Engine_DEFAULT) { - engine = TanHParameter_Engine_CAFFE; -#ifdef USE_CUDNN - engine = TanHParameter_Engine_CUDNN; -#endif - } - if (engine == TanHParameter_Engine_CAFFE) { - return new TanHLayer(param); -#ifdef USE_CUDNN - } else if (engine == TanHParameter_Engine_CUDNN) { - return new CuDNNTanHLayer(param); -#endif - } else { - LOG(FATAL) << "Layer " << param.name() << " has unknown engine."; - } -} +REGISTER_LAYER_CREATOR(SIGMOID, GetSigmoidLayer); // Get softmax layer according to engine. template @@ -144,46 +128,31 @@ Layer* GetSoftmaxLayer(const LayerParameter& param) { } } -// Layers that have a specific creator function. -REGISTER_LAYER_CREATOR(CONVOLUTION, GetConvolutionLayer); -REGISTER_LAYER_CREATOR(POOLING, GetPoolingLayer); -REGISTER_LAYER_CREATOR(RELU, GetReLULayer); -REGISTER_LAYER_CREATOR(SIGMOID, GetSigmoidLayer); REGISTER_LAYER_CREATOR(SOFTMAX, GetSoftmaxLayer); -REGISTER_LAYER_CREATOR(TANH, GetTanHLayer); -// Layers that use their constructor as their default creator. -REGISTER_LAYER_CLASS(ACCURACY, AccuracyLayer); -REGISTER_LAYER_CLASS(ABSVAL, AbsValLayer); -REGISTER_LAYER_CLASS(ARGMAX, ArgMaxLayer); -REGISTER_LAYER_CLASS(BNLL, BNLLLayer); -REGISTER_LAYER_CLASS(CONCAT, ConcatLayer); -REGISTER_LAYER_CLASS(CONTRASTIVE_LOSS, ContrastiveLossLayer); -REGISTER_LAYER_CLASS(DATA, DataLayer); -REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer); -REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer); -REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer); -REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer); -REGISTER_LAYER_CLASS(EXP, ExpLayer); -REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer); -REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer); -REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer); -REGISTER_LAYER_CLASS(HINGE_LOSS, HingeLossLayer); -REGISTER_LAYER_CLASS(IMAGE_DATA, ImageDataLayer); -REGISTER_LAYER_CLASS(IM2COL, Im2colLayer); -REGISTER_LAYER_CLASS(INFOGAIN_LOSS, InfogainLossLayer); -REGISTER_LAYER_CLASS(INNER_PRODUCT, InnerProductLayer); -REGISTER_LAYER_CLASS(LRN, LRNLayer); -REGISTER_LAYER_CLASS(MEMORY_DATA, MemoryDataLayer); -REGISTER_LAYER_CLASS(MVN, MVNLayer); -REGISTER_LAYER_CLASS(MULTINOMIAL_LOGISTIC_LOSS, MultinomialLogisticLossLayer); -REGISTER_LAYER_CLASS(POWER, PowerLayer); -REGISTER_LAYER_CLASS(SILENCE, SilenceLayer); -REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer); -REGISTER_LAYER_CLASS(SLICE, SliceLayer); -REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer); -REGISTER_LAYER_CLASS(SPLIT, SplitLayer); -REGISTER_LAYER_CLASS(THRESHOLD, ThresholdLayer); -REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer); +// Get tanh layer according to engine. +template +Layer* GetTanHLayer(const LayerParameter& param) { + TanHParameter_Engine engine = param.tanh_param().engine(); + if (engine == TanHParameter_Engine_DEFAULT) { + engine = TanHParameter_Engine_CAFFE; +#ifdef USE_CUDNN + engine = TanHParameter_Engine_CUDNN; +#endif + } + if (engine == TanHParameter_Engine_CAFFE) { + return new TanHLayer(param); +#ifdef USE_CUDNN + } else if (engine == TanHParameter_Engine_CUDNN) { + return new CuDNNTanHLayer(param); +#endif + } else { + LOG(FATAL) << "Layer " << param.name() << " has unknown engine."; + } +} + +REGISTER_LAYER_CREATOR(TANH, GetTanHLayer); +// Layers that use their constructor as their default creator should be +// registered in their corresponding cpp files. Do not registere them here. } // namespace caffe diff --git a/src/caffe/layers/absval_layer.cpp b/src/caffe/layers/absval_layer.cpp index 54e484b115d..70e0b583e61 100644 --- a/src/caffe/layers/absval_layer.cpp +++ b/src/caffe/layers/absval_layer.cpp @@ -41,6 +41,5 @@ STUB_GPU(AbsValLayer); #endif INSTANTIATE_CLASS(AbsValLayer); - - +REGISTER_LAYER_CLASS(ABSVAL, AbsValLayer); } // namespace caffe diff --git a/src/caffe/layers/accuracy_layer.cpp b/src/caffe/layers/accuracy_layer.cpp index 399cf2a3585..800b848f3bc 100644 --- a/src/caffe/layers/accuracy_layer.cpp +++ b/src/caffe/layers/accuracy_layer.cpp @@ -64,5 +64,5 @@ void AccuracyLayer::Forward_cpu(const vector*>& bottom, } INSTANTIATE_CLASS(AccuracyLayer); - +REGISTER_LAYER_CLASS(ACCURACY, AccuracyLayer); } // namespace caffe diff --git a/src/caffe/layers/argmax_layer.cpp b/src/caffe/layers/argmax_layer.cpp index dbe0a834aa5..15e199eb600 100644 --- a/src/caffe/layers/argmax_layer.cpp +++ b/src/caffe/layers/argmax_layer.cpp @@ -58,5 +58,6 @@ void ArgMaxLayer::Forward_cpu(const vector*>& bottom, } INSTANTIATE_CLASS(ArgMaxLayer); +REGISTER_LAYER_CLASS(ARGMAX, ArgMaxLayer); } // namespace caffe diff --git a/src/caffe/layers/bnll_layer.cpp b/src/caffe/layers/bnll_layer.cpp index bae692509e3..cb3583ae8be 100644 --- a/src/caffe/layers/bnll_layer.cpp +++ b/src/caffe/layers/bnll_layer.cpp @@ -43,6 +43,5 @@ STUB_GPU(BNLLLayer); #endif INSTANTIATE_CLASS(BNLLLayer); - - +REGISTER_LAYER_CLASS(BNLL, BNLLLayer); } // namespace caffe diff --git a/src/caffe/layers/concat_layer.cpp b/src/caffe/layers/concat_layer.cpp index f8f73564a6f..420821952b0 100644 --- a/src/caffe/layers/concat_layer.cpp +++ b/src/caffe/layers/concat_layer.cpp @@ -105,5 +105,5 @@ STUB_GPU(ConcatLayer); #endif INSTANTIATE_CLASS(ConcatLayer); - +REGISTER_LAYER_CLASS(CONCAT, ConcatLayer); } // namespace caffe diff --git a/src/caffe/layers/contrastive_loss_layer.cpp b/src/caffe/layers/contrastive_loss_layer.cpp index d716d140ea0..0d0b443b66b 100644 --- a/src/caffe/layers/contrastive_loss_layer.cpp +++ b/src/caffe/layers/contrastive_loss_layer.cpp @@ -97,5 +97,5 @@ STUB_GPU(ContrastiveLossLayer); #endif INSTANTIATE_CLASS(ContrastiveLossLayer); - +REGISTER_LAYER_CLASS(CONTRASTIVE_LOSS, ContrastiveLossLayer); } // namespace caffe diff --git a/src/caffe/layers/conv_layer.cpp b/src/caffe/layers/conv_layer.cpp index e6d6588096b..65ff9167128 100644 --- a/src/caffe/layers/conv_layer.cpp +++ b/src/caffe/layers/conv_layer.cpp @@ -267,5 +267,4 @@ STUB_GPU(ConvolutionLayer); #endif INSTANTIATE_CLASS(ConvolutionLayer); - } // namespace caffe diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 283a3a52f59..daa3289b9c2 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -204,5 +204,5 @@ void DataLayer::InternalThreadEntry() { } INSTANTIATE_CLASS(DataLayer); - +REGISTER_LAYER_CLASS(DATA, DataLayer); } // namespace caffe diff --git a/src/caffe/layers/dropout_layer.cpp b/src/caffe/layers/dropout_layer.cpp index f88027c7062..8c8936a711e 100644 --- a/src/caffe/layers/dropout_layer.cpp +++ b/src/caffe/layers/dropout_layer.cpp @@ -73,6 +73,5 @@ STUB_GPU(DropoutLayer); #endif INSTANTIATE_CLASS(DropoutLayer); - - +REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer); } // namespace caffe diff --git a/src/caffe/layers/dummy_data_layer.cpp b/src/caffe/layers/dummy_data_layer.cpp index 6aeba5487b8..15cf5a58ac6 100644 --- a/src/caffe/layers/dummy_data_layer.cpp +++ b/src/caffe/layers/dummy_data_layer.cpp @@ -93,5 +93,5 @@ void DummyDataLayer::Forward_cpu(const vector*>& bottom, } INSTANTIATE_CLASS(DummyDataLayer); - +REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer); } // namespace caffe diff --git a/src/caffe/layers/eltwise_layer.cpp b/src/caffe/layers/eltwise_layer.cpp index 2830d6db195..0c239f4ac11 100644 --- a/src/caffe/layers/eltwise_layer.cpp +++ b/src/caffe/layers/eltwise_layer.cpp @@ -163,6 +163,5 @@ STUB_GPU(EltwiseLayer); #endif INSTANTIATE_CLASS(EltwiseLayer); - - +REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer); } // namespace caffe diff --git a/src/caffe/layers/euclidean_loss_layer.cpp b/src/caffe/layers/euclidean_loss_layer.cpp index abc8610eef6..d965027f712 100644 --- a/src/caffe/layers/euclidean_loss_layer.cpp +++ b/src/caffe/layers/euclidean_loss_layer.cpp @@ -54,5 +54,5 @@ STUB_GPU(EuclideanLossLayer); #endif INSTANTIATE_CLASS(EuclideanLossLayer); - +REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer); } // namespace caffe diff --git a/src/caffe/layers/exp_layer.cpp b/src/caffe/layers/exp_layer.cpp index 2c99bfcff93..92cb5deb1e6 100644 --- a/src/caffe/layers/exp_layer.cpp +++ b/src/caffe/layers/exp_layer.cpp @@ -64,6 +64,5 @@ STUB_GPU(ExpLayer); #endif INSTANTIATE_CLASS(ExpLayer); - - +REGISTER_LAYER_CLASS(EXP, ExpLayer); } // namespace caffe diff --git a/src/caffe/layers/flatten_layer.cpp b/src/caffe/layers/flatten_layer.cpp index 44df96d8436..ec43cababca 100644 --- a/src/caffe/layers/flatten_layer.cpp +++ b/src/caffe/layers/flatten_layer.cpp @@ -34,5 +34,5 @@ STUB_GPU(FlattenLayer); #endif INSTANTIATE_CLASS(FlattenLayer); - +REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer); } // namespace caffe diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index 61aa293d2ac..f6865efe78e 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -119,5 +119,5 @@ STUB_GPU_FORWARD(HDF5DataLayer, Forward); #endif INSTANTIATE_CLASS(HDF5DataLayer); - +REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer); } // namespace caffe diff --git a/src/caffe/layers/hdf5_output_layer.cpp b/src/caffe/layers/hdf5_output_layer.cpp index b41d387a786..b8210e2ee2a 100644 --- a/src/caffe/layers/hdf5_output_layer.cpp +++ b/src/caffe/layers/hdf5_output_layer.cpp @@ -70,5 +70,5 @@ STUB_GPU(HDF5OutputLayer); #endif INSTANTIATE_CLASS(HDF5OutputLayer); - +REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer); } // namespace caffe diff --git a/src/caffe/layers/hinge_loss_layer.cpp b/src/caffe/layers/hinge_loss_layer.cpp index f09916e2556..4dfafcc8648 100644 --- a/src/caffe/layers/hinge_loss_layer.cpp +++ b/src/caffe/layers/hinge_loss_layer.cpp @@ -77,5 +77,5 @@ void HingeLossLayer::Backward_cpu(const vector*>& top, } INSTANTIATE_CLASS(HingeLossLayer); - +REGISTER_LAYER_CLASS(HINGE_LOSS, HingeLossLayer); } // namespace caffe diff --git a/src/caffe/layers/im2col_layer.cpp b/src/caffe/layers/im2col_layer.cpp index 10588cebe7f..2c4bb9029e0 100644 --- a/src/caffe/layers/im2col_layer.cpp +++ b/src/caffe/layers/im2col_layer.cpp @@ -88,5 +88,5 @@ STUB_GPU(Im2colLayer); #endif INSTANTIATE_CLASS(Im2colLayer); - +REGISTER_LAYER_CLASS(IM2COL, Im2colLayer); } // namespace caffe diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index 19ad2dc2126..2085df2760a 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -131,5 +131,5 @@ void ImageDataLayer::InternalThreadEntry() { } INSTANTIATE_CLASS(ImageDataLayer); - +REGISTER_LAYER_CLASS(IMAGE_DATA, ImageDataLayer); } // namespace caffe diff --git a/src/caffe/layers/infogain_loss_layer.cpp b/src/caffe/layers/infogain_loss_layer.cpp index c4dc1b4513a..8910431d42b 100644 --- a/src/caffe/layers/infogain_loss_layer.cpp +++ b/src/caffe/layers/infogain_loss_layer.cpp @@ -106,5 +106,5 @@ void InfogainLossLayer::Backward_cpu(const vector*>& top, } INSTANTIATE_CLASS(InfogainLossLayer); - +REGISTER_LAYER_CLASS(INFOGAIN_LOSS, InfogainLossLayer); } // namespace caffe diff --git a/src/caffe/layers/inner_product_layer.cpp b/src/caffe/layers/inner_product_layer.cpp index ffd872c5a70..ecb849ba4d8 100644 --- a/src/caffe/layers/inner_product_layer.cpp +++ b/src/caffe/layers/inner_product_layer.cpp @@ -104,5 +104,5 @@ STUB_GPU(InnerProductLayer); #endif INSTANTIATE_CLASS(InnerProductLayer); - +REGISTER_LAYER_CLASS(INNER_PRODUCT, InnerProductLayer); } // namespace caffe diff --git a/src/caffe/layers/lrn_layer.cpp b/src/caffe/layers/lrn_layer.cpp index a09a47940d2..a878cf847b3 100644 --- a/src/caffe/layers/lrn_layer.cpp +++ b/src/caffe/layers/lrn_layer.cpp @@ -252,6 +252,5 @@ STUB_GPU_BACKWARD(LRNLayer, CrossChannelBackward); #endif INSTANTIATE_CLASS(LRNLayer); - - +REGISTER_LAYER_CLASS(LRN, LRNLayer); } // namespace caffe diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 8f1c21f5424..613ca2d4c76 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -72,5 +72,5 @@ void MemoryDataLayer::Forward_cpu(const vector*>& bottom, } INSTANTIATE_CLASS(MemoryDataLayer); - +REGISTER_LAYER_CLASS(MEMORY_DATA, MemoryDataLayer); } // namespace caffe diff --git a/src/caffe/layers/multinomial_logistic_loss_layer.cpp b/src/caffe/layers/multinomial_logistic_loss_layer.cpp index 66f9ba813aa..78a1f60fca9 100644 --- a/src/caffe/layers/multinomial_logistic_loss_layer.cpp +++ b/src/caffe/layers/multinomial_logistic_loss_layer.cpp @@ -62,5 +62,5 @@ void MultinomialLogisticLossLayer::Backward_cpu( } INSTANTIATE_CLASS(MultinomialLogisticLossLayer); - +REGISTER_LAYER_CLASS(MULTINOMIAL_LOGISTIC_LOSS, MultinomialLogisticLossLayer); } // namespace caffe diff --git a/src/caffe/layers/mvn_layer.cpp b/src/caffe/layers/mvn_layer.cpp index 419f170ad7c..104ad95c7ed 100644 --- a/src/caffe/layers/mvn_layer.cpp +++ b/src/caffe/layers/mvn_layer.cpp @@ -159,6 +159,5 @@ STUB_GPU(MVNLayer); #endif INSTANTIATE_CLASS(MVNLayer); - - +REGISTER_LAYER_CLASS(MVN, MVNLayer); } // namespace caffe diff --git a/src/caffe/layers/power_layer.cpp b/src/caffe/layers/power_layer.cpp index 04c612296aa..69bd120e3dc 100644 --- a/src/caffe/layers/power_layer.cpp +++ b/src/caffe/layers/power_layer.cpp @@ -99,6 +99,5 @@ STUB_GPU(PowerLayer); #endif INSTANTIATE_CLASS(PowerLayer); - - +REGISTER_LAYER_CLASS(POWER, PowerLayer); } // namespace caffe diff --git a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp index 11850ac68e3..d1e327a54c9 100644 --- a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp +++ b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp @@ -75,6 +75,5 @@ STUB_GPU(SigmoidCrossEntropyLossLayer); #endif INSTANTIATE_CLASS(SigmoidCrossEntropyLossLayer); - - +REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer); } // namespace caffe diff --git a/src/caffe/layers/silence_layer.cpp b/src/caffe/layers/silence_layer.cpp index 0fd88580eaf..9bd20574816 100644 --- a/src/caffe/layers/silence_layer.cpp +++ b/src/caffe/layers/silence_layer.cpp @@ -22,5 +22,5 @@ STUB_GPU(SilenceLayer); #endif INSTANTIATE_CLASS(SilenceLayer); - +REGISTER_LAYER_CLASS(SILENCE, SilenceLayer); } // namespace caffe diff --git a/src/caffe/layers/slice_layer.cpp b/src/caffe/layers/slice_layer.cpp index 76522c3e456..60a5ecfa416 100644 --- a/src/caffe/layers/slice_layer.cpp +++ b/src/caffe/layers/slice_layer.cpp @@ -137,5 +137,5 @@ STUB_GPU(SliceLayer); #endif INSTANTIATE_CLASS(SliceLayer); - +REGISTER_LAYER_CLASS(SLICE, SliceLayer); } // namespace caffe diff --git a/src/caffe/layers/softmax_layer.cpp b/src/caffe/layers/softmax_layer.cpp index 04e8c4f35fc..c7b09fffd7a 100644 --- a/src/caffe/layers/softmax_layer.cpp +++ b/src/caffe/layers/softmax_layer.cpp @@ -92,6 +92,4 @@ STUB_GPU(SoftmaxLayer); #endif INSTANTIATE_CLASS(SoftmaxLayer); - - } // namespace caffe diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index d39429cee5d..35033b67c21 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -90,6 +90,5 @@ STUB_GPU(SoftmaxWithLossLayer); #endif INSTANTIATE_CLASS(SoftmaxWithLossLayer); - - +REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer); } // namespace caffe diff --git a/src/caffe/layers/split_layer.cpp b/src/caffe/layers/split_layer.cpp index ee6b5a91d3c..51ac61f4cae 100644 --- a/src/caffe/layers/split_layer.cpp +++ b/src/caffe/layers/split_layer.cpp @@ -56,5 +56,5 @@ STUB_GPU(SplitLayer); #endif INSTANTIATE_CLASS(SplitLayer); - +REGISTER_LAYER_CLASS(SPLIT, SplitLayer); } // namespace caffe diff --git a/src/caffe/layers/threshold_layer.cpp b/src/caffe/layers/threshold_layer.cpp index b4b2df51bc9..9e68c32d348 100644 --- a/src/caffe/layers/threshold_layer.cpp +++ b/src/caffe/layers/threshold_layer.cpp @@ -29,5 +29,5 @@ STUB_GPU_FORWARD(ThresholdLayer, Forward); #endif INSTANTIATE_CLASS(ThresholdLayer); - +REGISTER_LAYER_CLASS(THRESHOLD, ThresholdLayer); } // namespace caffe diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 62ca872a32b..529c3b47bd9 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -402,5 +402,5 @@ void WindowDataLayer::InternalThreadEntry() { } INSTANTIATE_CLASS(WindowDataLayer); - +REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer); } // namespace caffe From d6dbfc84db42d813747c4a4b038faa31a6b9503d Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 14 Oct 2014 11:41:40 -0700 Subject: [PATCH 105/798] Revert "OpenCV should be compiled using pkg-config options." -- breaks compilation on working systems This reverts commit 4587b2f9043996fed36fc989c00329ec829ecae9. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c8226cb6872..35c37af50fb 100644 --- a/Makefile +++ b/Makefile @@ -168,7 +168,8 @@ ifneq ($(CPU_ONLY), 1) LIBRARIES := cudart cublas curand endif LIBRARIES += glog gflags protobuf leveldb snappy \ - lmdb boost_system hdf5_hl hdf5 m + lmdb boost_system hdf5_hl hdf5 m \ + opencv_core opencv_highgui opencv_imgproc PYTHON_LIBRARIES := boost_python python2.7 WARNINGS := -Wall -Wno-sign-compare @@ -329,7 +330,6 @@ NVCCFLAGS += -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS) MATLAB_CXXFLAGS := $(CXXFLAGS) -Wno-uninitialized LINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) \ - `pkg-config opencv --libs` \ $(foreach library,$(LIBRARIES),-l$(library)) PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) From 370217bf7206150901133ac9399bcf3a87462d90 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Mon, 13 Oct 2014 16:01:07 -0700 Subject: [PATCH 106/798] some namespace cleaning. --- src/caffe/test/test_caffe_main.cpp | 3 ++- src/caffe/test/test_dummy_data_layer.cpp | 3 --- src/caffe/test/test_hdf5_output_layer.cpp | 3 --- src/caffe/test/test_hdf5data_layer.cpp | 2 -- src/caffe/test/test_upgrade_proto.cpp | 2 -- tools/compute_image_mean.cpp | 9 +++---- tools/convert_imageset.cpp | 15 ++++++------ tools/dump_network.cpp | 15 ++++++++---- tools/extract_features.cpp | 30 +++++++++++++---------- 9 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/caffe/test/test_caffe_main.cpp b/src/caffe/test/test_caffe_main.cpp index bff0c4ed20e..c8caf5ac58e 100644 --- a/src/caffe/test/test_caffe_main.cpp +++ b/src/caffe/test/test_caffe_main.cpp @@ -1,6 +1,7 @@ // The main caffe test code. Your test cpp code should include this hpp // to allow a main function to be compiled into the binary. +#include "caffe/caffe.hpp" #include "caffe/test/test_caffe_main.hpp" namespace caffe { @@ -15,7 +16,7 @@ using caffe::CAFFE_TEST_CUDA_PROP; int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - ::google::InitGoogleLogging(argv[0]); + caffe::GlobalInit(&argc, &argv); #ifndef CPU_ONLY // Before starting testing, let's first print out a few cuda defice info. int device; diff --git a/src/caffe/test/test_dummy_data_layer.cpp b/src/caffe/test/test_dummy_data_layer.cpp index da121fa5d99..99548352746 100644 --- a/src/caffe/test/test_dummy_data_layer.cpp +++ b/src/caffe/test/test_dummy_data_layer.cpp @@ -10,9 +10,6 @@ #include "caffe/test/test_caffe_main.hpp" -using std::string; -using std::stringstream; - namespace caffe { template diff --git a/src/caffe/test/test_hdf5_output_layer.cpp b/src/caffe/test/test_hdf5_output_layer.cpp index c8282233e5b..2e8f096980a 100644 --- a/src/caffe/test/test_hdf5_output_layer.cpp +++ b/src/caffe/test/test_hdf5_output_layer.cpp @@ -11,9 +11,6 @@ #include "caffe/test/test_caffe_main.hpp" -using std::string; -using std::vector; - namespace caffe { template diff --git a/src/caffe/test/test_hdf5data_layer.cpp b/src/caffe/test/test_hdf5data_layer.cpp index ed6fed83708..41a3a83dd9f 100644 --- a/src/caffe/test/test_hdf5data_layer.cpp +++ b/src/caffe/test/test_hdf5data_layer.cpp @@ -13,8 +13,6 @@ #include "caffe/test/test_caffe_main.hpp" -using std::string; - namespace caffe { template diff --git a/src/caffe/test/test_upgrade_proto.cpp b/src/caffe/test/test_upgrade_proto.cpp index f46a0e823c1..52e7f1f99f5 100644 --- a/src/caffe/test/test_upgrade_proto.cpp +++ b/src/caffe/test/test_upgrade_proto.cpp @@ -11,8 +11,6 @@ #include "caffe/test/test_caffe_main.hpp" -using std::string; - namespace caffe { class PaddingLayerUpgradeTest : public ::testing::Test { diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index 20f1ff81f1c..6adde8b1d1c 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -11,7 +11,6 @@ using caffe::Datum; using caffe::BlobProto; -using std::string; using std::max; int main(int argc, char** argv) { @@ -22,9 +21,9 @@ int main(int argc, char** argv) { return 1; } - string db_backend = "lmdb"; + std::string db_backend = "lmdb"; if (argc == 4) { - db_backend = string(argv[3]); + db_backend = std::string(argv[3]); } // leveldb @@ -94,7 +93,7 @@ int main(int argc, char** argv) { for (it->SeekToFirst(); it->Valid(); it->Next()) { // just a dummy operation datum.ParseFromString(it->value().ToString()); - const string& data = datum.data(); + const std::string& data = datum.data(); size_in_datum = std::max(datum.data().size(), datum.float_data_size()); CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " << @@ -120,7 +119,7 @@ int main(int argc, char** argv) { do { // just a dummy operation datum.ParseFromArray(mdb_value.mv_data, mdb_value.mv_size); - const string& data = datum.data(); + const std::string& data = datum.data(); size_in_datum = std::max(datum.data().size(), datum.float_data_size()); CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " << diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 4ab93fd0a0c..7c8c1dab3fb 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -27,7 +27,6 @@ using namespace caffe; // NOLINT(build/namespaces) using std::pair; -using std::string; DEFINE_bool(gray, false, "When this option is on, treat images as grayscale ones"); @@ -62,8 +61,8 @@ int main(int argc, char** argv) { bool is_color = !FLAGS_gray; bool check_size = FLAGS_check_size; std::ifstream infile(argv[2]); - std::vector > lines; - string filename; + std::vector > lines; + std::string filename; int label; while (infile >> filename >> label) { lines.push_back(std::make_pair(filename, label)); @@ -75,7 +74,7 @@ int main(int argc, char** argv) { } LOG(INFO) << "A total of " << lines.size() << " images."; - const string& db_backend = FLAGS_backend; + const std::string& db_backend = FLAGS_backend; const char* db_path = argv[3]; int resize_height = std::max(0, FLAGS_resize_height); @@ -121,7 +120,7 @@ int main(int argc, char** argv) { } // Storing to db - string root_folder(argv[1]); + std::string root_folder(argv[1]); Datum datum; int count = 0; const int kMaxKeyLength = 256; @@ -139,7 +138,7 @@ int main(int argc, char** argv) { data_size = datum.channels() * datum.height() * datum.width(); data_size_initialized = true; } else { - const string& data = datum.data(); + const std::string& data = datum.data(); CHECK_EQ(data.size(), data_size) << "Incorrect data field size " << data.size(); } @@ -147,9 +146,9 @@ int main(int argc, char** argv) { // sequential snprintf(key_cstr, kMaxKeyLength, "%08d_%s", line_id, lines[line_id].first.c_str()); - string value; + std::string value; datum.SerializeToString(&value); - string keystr(key_cstr); + std::string keystr(key_cstr); // Put in db if (db_backend == "leveldb") { // leveldb diff --git a/tools/dump_network.cpp b/tools/dump_network.cpp index 90895fdc969..9cb996ef612 100644 --- a/tools/dump_network.cpp +++ b/tools/dump_network.cpp @@ -22,7 +22,12 @@ #include "caffe/solver.hpp" #include "caffe/util/io.hpp" -using namespace caffe; // NOLINT(build/namespaces) +using boost::shared_ptr; +using caffe::Blob; +using caffe::BlobProto; +using caffe::Caffe; +using caffe::Net; +using caffe::NetParameter; int main(int argc, char** argv) { Caffe::set_mode(Caffe::GPU); @@ -37,7 +42,7 @@ int main(int argc, char** argv) { } caffe_net->CopyTrainedLayersFrom(argv[2]); - vector* > input_vec; + std::vector* > input_vec; shared_ptr > input_blob(new Blob()); if (strcmp(argv[3], "none") != 0) { BlobProto input_blob_proto; @@ -46,7 +51,7 @@ int main(int argc, char** argv) { input_vec.push_back(input_blob.get()); } - string output_prefix(argv[4]); + std::string output_prefix(argv[4]); // Run the network without training. LOG(ERROR) << "Performing Forward"; caffe_net->Forward(input_vec); @@ -62,8 +67,8 @@ int main(int argc, char** argv) { } // Now, let's dump all the layers - const vector& blob_names = caffe_net->blob_names(); - const vector > >& blobs = caffe_net->blobs(); + const std::vector& blob_names = caffe_net->blob_names(); + const std::vector > >& blobs = caffe_net->blobs(); for (int blobid = 0; blobid < caffe_net->blobs().size(); ++blobid) { // Serialize blob LOG(ERROR) << "Dumping " << blob_names[blobid]; diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 9b0288a4d5a..299b3118760 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -14,7 +14,11 @@ #include "caffe/util/io.hpp" #include "caffe/vision_layers.hpp" -using namespace caffe; // NOLINT(build/namespaces) +using boost::shared_ptr; +using caffe::Blob; +using caffe::Caffe; +using caffe::Datum; +using caffe::Net; template int feature_extraction_pipeline(int argc, char** argv); @@ -62,7 +66,7 @@ int feature_extraction_pipeline(int argc, char** argv) { Caffe::set_phase(Caffe::TEST); arg_pos = 0; // the name of the executable - string pretrained_binary_proto(argv[++arg_pos]); + std::string pretrained_binary_proto(argv[++arg_pos]); // Expected prototxt contains at least one data layer such as // the layer data_layer_name and one feature blob such as the @@ -91,17 +95,17 @@ int feature_extraction_pipeline(int argc, char** argv) { top: "fc7" } */ - string feature_extraction_proto(argv[++arg_pos]); + std::string feature_extraction_proto(argv[++arg_pos]); shared_ptr > feature_extraction_net( new Net(feature_extraction_proto)); feature_extraction_net->CopyTrainedLayersFrom(pretrained_binary_proto); - string extract_feature_blob_names(argv[++arg_pos]); - vector blob_names; + std::string extract_feature_blob_names(argv[++arg_pos]); + std::vector blob_names; boost::split(blob_names, extract_feature_blob_names, boost::is_any_of(",")); - string save_feature_leveldb_names(argv[++arg_pos]); - vector leveldb_names; + std::string save_feature_leveldb_names(argv[++arg_pos]); + std::vector leveldb_names; boost::split(leveldb_names, save_feature_leveldb_names, boost::is_any_of(",")); CHECK_EQ(blob_names.size(), leveldb_names.size()) << @@ -118,7 +122,7 @@ int feature_extraction_pipeline(int argc, char** argv) { options.error_if_exists = true; options.create_if_missing = true; options.write_buffer_size = 268435456; - vector > feature_dbs; + std::vector > feature_dbs; for (size_t i = 0; i < num_features; ++i) { LOG(INFO)<< "Opening leveldb " << leveldb_names[i]; leveldb::DB* db; @@ -134,13 +138,13 @@ int feature_extraction_pipeline(int argc, char** argv) { LOG(ERROR)<< "Extacting Features"; Datum datum; - vector > feature_batches( + std::vector > feature_batches( num_features, shared_ptr(new leveldb::WriteBatch())); const int kMaxKeyStrLength = 100; char key_str[kMaxKeyStrLength]; - vector*> input_vec; - vector image_indices(num_features, 0); + std::vector*> input_vec; + std::vector image_indices(num_features, 0); for (int batch_index = 0; batch_index < num_mini_batches; ++batch_index) { feature_extraction_net->Forward(input_vec); for (int i = 0; i < num_features; ++i) { @@ -160,10 +164,10 @@ int feature_extraction_pipeline(int argc, char** argv) { for (int d = 0; d < dim_features; ++d) { datum.add_float_data(feature_blob_data[d]); } - string value; + std::string value; datum.SerializeToString(&value); snprintf(key_str, kMaxKeyStrLength, "%d", image_indices[i]); - feature_batches[i]->Put(string(key_str), value); + feature_batches[i]->Put(std::string(key_str), value); ++image_indices[i]; if (image_indices[i] % 1000 == 0) { feature_dbs[i]->Write(leveldb::WriteOptions(), From 6ad4f951133535f8fd43a8b6d4ece85f33465aca Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 7 Oct 2014 15:37:35 -0400 Subject: [PATCH 107/798] Refactored leveldb and lmdb code. --- include/caffe/data_layers.hpp | 14 +-- include/caffe/database.hpp | 103 +++++++++++++++++ include/caffe/database_factory.hpp | 16 +++ include/caffe/leveldb_database.hpp | 52 +++++++++ include/caffe/lmdb_database.hpp | 54 +++++++++ include/caffe/util/io.hpp | 7 -- src/caffe/database_factory.cpp | 33 ++++++ src/caffe/layers/data_layer.cpp | 129 +++------------------ src/caffe/leveldb_database.cpp | 151 ++++++++++++++++++++++++ src/caffe/lmdb_database.cpp | 154 +++++++++++++++++++++++++ src/caffe/proto/caffe.proto | 6 +- src/caffe/test/test_data_layer.cpp | 93 ++++----------- src/caffe/test/test_hdf5data_layer.cpp | 2 - src/caffe/util/io.cpp | 10 -- tools/compute_image_mean.cpp | 132 +++++---------------- tools/convert_imageset.cpp | 81 ++----------- tools/extract_features.cpp | 50 ++++---- 17 files changed, 660 insertions(+), 427 deletions(-) create mode 100644 include/caffe/database.hpp create mode 100644 include/caffe/database_factory.hpp create mode 100644 include/caffe/leveldb_database.hpp create mode 100644 include/caffe/lmdb_database.hpp create mode 100644 src/caffe/database_factory.cpp create mode 100644 src/caffe/leveldb_database.cpp create mode 100644 src/caffe/lmdb_database.cpp diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index 1ed26c17178..810f2bb833d 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -7,12 +7,11 @@ #include "boost/scoped_ptr.hpp" #include "hdf5.h" -#include "leveldb/db.h" -#include "lmdb.h" #include "caffe/blob.hpp" #include "caffe/common.hpp" #include "caffe/data_transformer.hpp" +#include "caffe/database.hpp" #include "caffe/filler.hpp" #include "caffe/internal_thread.hpp" #include "caffe/layer.hpp" @@ -101,15 +100,8 @@ class DataLayer : public BasePrefetchingDataLayer { protected: virtual void InternalThreadEntry(); - // LEVELDB - shared_ptr db_; - shared_ptr iter_; - // LMDB - MDB_env* mdb_env_; - MDB_dbi mdb_dbi_; - MDB_txn* mdb_txn_; - MDB_cursor* mdb_cursor_; - MDB_val mdb_key_, mdb_value_; + shared_ptr database_; + Database::const_iterator iter_; }; /** diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp new file mode 100644 index 00000000000..4a1a25efd12 --- /dev/null +++ b/include/caffe/database.hpp @@ -0,0 +1,103 @@ +#ifndef CAFFE_DATABASE_H_ +#define CAFFE_DATABASE_H_ + +#include +#include +#include +#include + +#include "caffe/common.hpp" + +namespace caffe { + +class Database { + public: + enum Mode { + New, + ReadWrite, + ReadOnly + }; + + virtual void open(const string& filename, Mode mode) = 0; + virtual void put(const string& key, const string& value) = 0; + virtual void commit() = 0; + virtual void close() = 0; + + Database() { } + virtual ~Database() { } + + class iterator; + typedef iterator const_iterator; + + virtual const_iterator begin() const = 0; + virtual const_iterator cbegin() const = 0; + virtual const_iterator end() const = 0; + virtual const_iterator cend() const = 0; + + protected: + class DatabaseState; + + public: + class iterator : + public std::iterator > { + public: + typedef pair T; + typedef T value_type; + typedef T& reference_type; + typedef T* pointer_type; + + iterator() + : parent_(NULL) { } + + iterator(const Database* parent, shared_ptr state) + : parent_(parent), + state_(state) { } + ~iterator() { } + + bool operator==(const iterator& other) const { + return parent_->equal(state_, other.state_); + } + + bool operator!=(const iterator& other) const { + return !(*this == other); + } + + iterator& operator++() { + parent_->increment(state_); + return *this; + } + iterator operator++(int) { + iterator copy(*this); + parent_->increment(state_); + return copy; + } + + reference_type operator*() const { + return parent_->dereference(state_); + } + + pointer_type operator->() const { + return &parent_->dereference(state_); + } + + protected: + const Database* parent_; + shared_ptr state_; + }; + + protected: + class DatabaseState { + public: + virtual ~DatabaseState() { } + }; + + virtual bool equal(shared_ptr state1, + shared_ptr state2) const = 0; + virtual void increment(shared_ptr state) const = 0; + virtual pair& dereference( + shared_ptr state) const = 0; +}; + +} // namespace caffe + +#endif // CAFFE_DATABASE_H_ diff --git a/include/caffe/database_factory.hpp b/include/caffe/database_factory.hpp new file mode 100644 index 00000000000..a6e39e76188 --- /dev/null +++ b/include/caffe/database_factory.hpp @@ -0,0 +1,16 @@ +#ifndef CAFFE_DATABASE_FACTORY_H_ +#define CAFFE_DATABASE_FACTORY_H_ + +#include + +#include "caffe/common.hpp" +#include "caffe/database.hpp" + +namespace caffe { + +shared_ptr DatabaseFactory(const DataParameter_DB& type); +shared_ptr DatabaseFactory(const string& type); + +} // namespace caffe + +#endif // CAFFE_DATABASE_FACTORY_H_ diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp new file mode 100644 index 00000000000..5daf0e51e12 --- /dev/null +++ b/include/caffe/leveldb_database.hpp @@ -0,0 +1,52 @@ +#ifndef CAFFE_LEVELDB_DATABASE_H_ +#define CAFFE_LEVELDB_DATABASE_H_ + +#include +#include + +#include +#include + +#include "caffe/common.hpp" +#include "caffe/database.hpp" + +namespace caffe { + +class LeveldbDatabase : public Database { + public: + void open(const string& filename, Mode mode); + void put(const string& key, const string& value); + void commit(); + void close(); + + ~LeveldbDatabase() { this->close(); } + + protected: + class LeveldbState : public Database::DatabaseState { + public: + explicit LeveldbState(shared_ptr iter) + : Database::DatabaseState(), + iter_(iter) { } + + shared_ptr iter_; + pair kv_pair_; + }; + + bool equal(shared_ptr state1, + shared_ptr state2) const; + void increment(shared_ptr state) const; + pair& dereference(shared_ptr state) const; + + const_iterator begin() const; + const_iterator cbegin() const; + const_iterator end() const; + const_iterator cend() const; + + protected: + shared_ptr db_; + shared_ptr batch_; +}; + +} // namespace caffe + +#endif // CAFFE_LEVELDB_DATABASE_H_ diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp new file mode 100644 index 00000000000..f275cb48f5c --- /dev/null +++ b/include/caffe/lmdb_database.hpp @@ -0,0 +1,54 @@ +#ifndef CAFFE_LMDB_DATABASE_H_ +#define CAFFE_LMDB_DATABASE_H_ + +#include +#include + +#include "lmdb.h" + +#include "caffe/common.hpp" +#include "caffe/database.hpp" + +namespace caffe { + +class LmdbDatabase : public Database { + public: + LmdbDatabase() + : dbi_(0) { } + ~LmdbDatabase() { this->close(); } + + void open(const string& filename, Mode mode); + void put(const string& key, const string& value); + void commit(); + void close(); + + protected: + class LmdbState : public Database::DatabaseState { + public: + explicit LmdbState(MDB_cursor* cursor) + : Database::DatabaseState(), + cursor_(cursor) { } + + MDB_cursor* cursor_; + pair kv_pair_; + }; + + bool equal(shared_ptr state1, + shared_ptr state2) const; + void increment(shared_ptr state) const; + pair& dereference(shared_ptr state) const; + + protected: + const_iterator begin() const; + const_iterator cbegin() const; + const_iterator end() const; + const_iterator cend() const; + + MDB_env *env_ = NULL; + MDB_dbi dbi_; + MDB_txn *txn_ = NULL; +}; + +} // namespace caffe + +#endif // CAFFE_LMDB_DATABASE_H_ diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index e518979a75b..1124bef179a 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -17,11 +17,6 @@ #define HDF5_NUM_DIMS 4 -namespace leveldb { -// Forward declaration for leveldb::Options to be used in GetlevelDBOptions(). -struct Options; -} - namespace caffe { using ::google::protobuf::Message; @@ -132,8 +127,6 @@ inline cv::Mat ReadImageToCVMat(const string& filename) { void CVMatToDatum(const cv::Mat& cv_img, Datum* datum); #endif -leveldb::Options GetLevelDBOptions(); - template void hdf5_load_nd_dataset_helper( hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, diff --git a/src/caffe/database_factory.cpp b/src/caffe/database_factory.cpp new file mode 100644 index 00000000000..393635b3208 --- /dev/null +++ b/src/caffe/database_factory.cpp @@ -0,0 +1,33 @@ +#include +#include + +#include "caffe/database_factory.hpp" +#include "caffe/leveldb_database.hpp" +#include "caffe/lmdb_database.hpp" + +namespace caffe { + +shared_ptr DatabaseFactory(const DataParameter_DB& type) { + switch (type) { + case DataParameter_DB_LEVELDB: + return shared_ptr(new LeveldbDatabase()); + case DataParameter_DB_LMDB: + return shared_ptr(new LmdbDatabase()); + default: + LOG(FATAL) << "Unknown database type " << type; + } +} + +shared_ptr DatabaseFactory(const string& type) { + if ("leveldb" == type) { + return DatabaseFactory(DataParameter_DB_LEVELDB); + } else if ("lmdb" == type) { + return DatabaseFactory(DataParameter_DB_LMDB); + } else { + LOG(FATAL) << "Unknown database type " << type; + } +} + +} // namespace caffe + + diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index daa3289b9c2..b746bc8a37d 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -6,6 +5,7 @@ #include "caffe/common.hpp" #include "caffe/data_layers.hpp" +#include "caffe/database_factory.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" @@ -18,60 +18,18 @@ template DataLayer::~DataLayer() { this->JoinPrefetchThread(); // clean up the database resources - switch (this->layer_param_.data_param().backend()) { - case DataParameter_DB_LEVELDB: - break; // do nothing - case DataParameter_DB_LMDB: - mdb_cursor_close(mdb_cursor_); - mdb_close(mdb_env_, mdb_dbi_); - mdb_txn_abort(mdb_txn_); - mdb_env_close(mdb_env_); - break; - default: - LOG(FATAL) << "Unknown database backend"; - } + iter_ = database_->end(); + database_->close(); } template void DataLayer::DataLayerSetUp(const vector*>& bottom, const vector*>& top) { // Initialize DB - switch (this->layer_param_.data_param().backend()) { - case DataParameter_DB_LEVELDB: - { - leveldb::DB* db_temp; - leveldb::Options options = GetLevelDBOptions(); - options.create_if_missing = false; - LOG(INFO) << "Opening leveldb " << this->layer_param_.data_param().source(); - leveldb::Status status = leveldb::DB::Open( - options, this->layer_param_.data_param().source(), &db_temp); - CHECK(status.ok()) << "Failed to open leveldb " - << this->layer_param_.data_param().source() << std::endl - << status.ToString(); - db_.reset(db_temp); - iter_.reset(db_->NewIterator(leveldb::ReadOptions())); - iter_->SeekToFirst(); - } - break; - case DataParameter_DB_LMDB: - CHECK_EQ(mdb_env_create(&mdb_env_), MDB_SUCCESS) << "mdb_env_create failed"; - CHECK_EQ(mdb_env_set_mapsize(mdb_env_, 1099511627776), MDB_SUCCESS); // 1TB - CHECK_EQ(mdb_env_open(mdb_env_, - this->layer_param_.data_param().source().c_str(), - MDB_RDONLY|MDB_NOTLS, 0664), MDB_SUCCESS) << "mdb_env_open failed"; - CHECK_EQ(mdb_txn_begin(mdb_env_, NULL, MDB_RDONLY, &mdb_txn_), MDB_SUCCESS) - << "mdb_txn_begin failed"; - CHECK_EQ(mdb_open(mdb_txn_, NULL, 0, &mdb_dbi_), MDB_SUCCESS) - << "mdb_open failed"; - CHECK_EQ(mdb_cursor_open(mdb_txn_, mdb_dbi_, &mdb_cursor_), MDB_SUCCESS) - << "mdb_cursor_open failed"; - LOG(INFO) << "Opening lmdb " << this->layer_param_.data_param().source(); - CHECK_EQ(mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, MDB_FIRST), - MDB_SUCCESS) << "mdb_cursor_get failed"; - break; - default: - LOG(FATAL) << "Unknown database backend"; - } + database_ = DatabaseFactory(this->layer_param_.data_param().backend()); + LOG(INFO) << "Opening database " << this->layer_param_.data_param().source(); + database_->open(this->layer_param_.data_param().source(), Database::ReadOnly); + iter_ = database_->begin(); // Check if we would need to randomly skip a few data points if (this->layer_param_.data_param().rand_skip()) { @@ -79,37 +37,16 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, this->layer_param_.data_param().rand_skip(); LOG(INFO) << "Skipping first " << skip << " data points."; while (skip-- > 0) { - switch (this->layer_param_.data_param().backend()) { - case DataParameter_DB_LEVELDB: - iter_->Next(); - if (!iter_->Valid()) { - iter_->SeekToFirst(); - } - break; - case DataParameter_DB_LMDB: - if (mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, MDB_NEXT) - != MDB_SUCCESS) { - CHECK_EQ(mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, - MDB_FIRST), MDB_SUCCESS); - } - break; - default: - LOG(FATAL) << "Unknown database backend"; + LOG(INFO) << iter_->first; + if (++iter_ == database_->end()) { + iter_ = database_->begin(); } } } // Read a data point, and use it to initialize the top blob. + CHECK(iter_ != database_->end()); Datum datum; - switch (this->layer_param_.data_param().backend()) { - case DataParameter_DB_LEVELDB: - datum.ParseFromString(iter_->value().ToString()); - break; - case DataParameter_DB_LMDB: - datum.ParseFromArray(mdb_value_.mv_data, mdb_value_.mv_size); - break; - default: - LOG(FATAL) << "Unknown database backend"; - } + datum.ParseFromString(iter_->second); // image int crop_size = this->layer_param_.transform_param().crop_size(); @@ -153,23 +90,10 @@ void DataLayer::InternalThreadEntry() { const int batch_size = this->layer_param_.data_param().batch_size(); for (int item_id = 0; item_id < batch_size; ++item_id) { - // get a blob Datum datum; - switch (this->layer_param_.data_param().backend()) { - case DataParameter_DB_LEVELDB: - CHECK(iter_); - CHECK(iter_->Valid()); - datum.ParseFromString(iter_->value().ToString()); - break; - case DataParameter_DB_LMDB: - CHECK_EQ(mdb_cursor_get(mdb_cursor_, &mdb_key_, - &mdb_value_, MDB_GET_CURRENT), MDB_SUCCESS); - datum.ParseFromArray(mdb_value_.mv_data, - mdb_value_.mv_size); - break; - default: - LOG(FATAL) << "Unknown database backend"; - } + CHECK(iter_ != database_->end()); + datum.ParseFromString(iter_->second); + // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); @@ -179,26 +103,9 @@ void DataLayer::InternalThreadEntry() { } // go to the next iter - switch (this->layer_param_.data_param().backend()) { - case DataParameter_DB_LEVELDB: - iter_->Next(); - if (!iter_->Valid()) { - // We have reached the end. Restart from the first. - DLOG(INFO) << "Restarting data prefetching from start."; - iter_->SeekToFirst(); - } - break; - case DataParameter_DB_LMDB: - if (mdb_cursor_get(mdb_cursor_, &mdb_key_, - &mdb_value_, MDB_NEXT) != MDB_SUCCESS) { - // We have reached the end. Restart from the first. - DLOG(INFO) << "Restarting data prefetching from start."; - CHECK_EQ(mdb_cursor_get(mdb_cursor_, &mdb_key_, - &mdb_value_, MDB_FIRST), MDB_SUCCESS); - } - break; - default: - LOG(FATAL) << "Unknown database backend"; + ++iter_; + if (iter_ == database_->end()) { + iter_ = database_->begin(); } } } diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp new file mode 100644 index 00000000000..be7ac7f141c --- /dev/null +++ b/src/caffe/leveldb_database.cpp @@ -0,0 +1,151 @@ +#include +#include + +#include "caffe/leveldb_database.hpp" + +namespace caffe { + +void LeveldbDatabase::open(const string& filename, Mode mode) { + LOG(INFO) << "LevelDB: Open " << filename; + + leveldb::Options options; + switch (mode) { + case New: + LOG(INFO) << " mode NEW"; + options.error_if_exists = true; + options.create_if_missing = true; + break; + case ReadWrite: + LOG(INFO) << " mode RW"; + options.error_if_exists = false; + options.create_if_missing = true; + break; + case ReadOnly: + LOG(INFO) << " mode RO"; + options.error_if_exists = false; + options.create_if_missing = false; + break; + default: + LOG(FATAL) << "unknown mode " << mode; + } + options.write_buffer_size = 268435456; + options.max_open_files = 100; + + leveldb::DB* db; + + LOG(INFO) << "Opening leveldb " << filename; + leveldb::Status status = leveldb::DB::Open( + options, filename, &db); + db_.reset(db); + CHECK(status.ok()) << "Failed to open leveldb " << filename + << ". Is it already existing?"; + batch_.reset(new leveldb::WriteBatch()); +} + +void LeveldbDatabase::put(const string& key, const string& value) { + LOG(INFO) << "LevelDB: Put " << key; + + CHECK_NOTNULL(batch_.get()); + batch_->Put(key, value); +} + +void LeveldbDatabase::commit() { + LOG(INFO) << "LevelDB: Commit"; + + CHECK_NOTNULL(db_.get()); + CHECK_NOTNULL(batch_.get()); + + db_->Write(leveldb::WriteOptions(), batch_.get()); + batch_.reset(new leveldb::WriteBatch()); +} + +void LeveldbDatabase::close() { + LOG(INFO) << "LevelDB: Close"; + + if (batch_ && db_) { + this->commit(); + } + batch_.reset(); + db_.reset(); +} + +LeveldbDatabase::const_iterator LeveldbDatabase::begin() const { + CHECK_NOTNULL(db_.get()); + shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); + iter->SeekToFirst(); + if (!iter->Valid()) { + iter.reset(); + } + shared_ptr state(new LeveldbState(iter)); + return const_iterator(this, state); +} + +LeveldbDatabase::const_iterator LeveldbDatabase::end() const { + shared_ptr iter; + shared_ptr state(new LeveldbState(iter)); + return const_iterator(this, state); +} + +LeveldbDatabase::const_iterator LeveldbDatabase::cbegin() const { + return begin(); +} + +LeveldbDatabase::const_iterator LeveldbDatabase::cend() const { return end(); } + +bool LeveldbDatabase::equal(shared_ptr state1, + shared_ptr state2) const { + shared_ptr leveldb_state1 = + boost::dynamic_pointer_cast(state1); + + CHECK_NOTNULL(leveldb_state1.get()); + + shared_ptr leveldb_state2 = + boost::dynamic_pointer_cast(state2); + + CHECK_NOTNULL(leveldb_state2.get()); + + CHECK(!leveldb_state1->iter_ || leveldb_state1->iter_->Valid()); + CHECK(!leveldb_state2->iter_ || leveldb_state2->iter_->Valid()); + + // The KV store doesn't really have any sort of ordering, + // so while we can do a sequential scan over the collection, + // we can't really use subranges. + return !leveldb_state1->iter_ && !leveldb_state2->iter_; +} + +void LeveldbDatabase::increment(shared_ptr state) const { + shared_ptr leveldb_state = + boost::dynamic_pointer_cast(state); + + CHECK_NOTNULL(leveldb_state.get()); + + shared_ptr& iter = leveldb_state->iter_; + + CHECK_NOTNULL(iter.get()); + CHECK(iter->Valid()); + + iter->Next(); + if (!iter->Valid()) { + iter.reset(); + } +} + +pair& LeveldbDatabase::dereference( + shared_ptr state) const { + shared_ptr leveldb_state = + boost::dynamic_pointer_cast(state); + + CHECK_NOTNULL(leveldb_state.get()); + + shared_ptr& iter = leveldb_state->iter_; + + CHECK_NOTNULL(iter.get()); + + CHECK(iter->Valid()); + + leveldb_state->kv_pair_ = make_pair(iter->key().ToString(), + iter->value().ToString()); + return leveldb_state->kv_pair_; +} + +} // namespace caffe diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp new file mode 100644 index 00000000000..796bbc9d4ac --- /dev/null +++ b/src/caffe/lmdb_database.cpp @@ -0,0 +1,154 @@ +#include + +#include +#include + +#include "caffe/lmdb_database.hpp" + +namespace caffe { + +void LmdbDatabase::open(const string& filename, Mode mode) { + LOG(INFO) << "LMDB: Open " << filename; + + CHECK(NULL == env_); + CHECK(NULL == txn_); + CHECK_EQ(0, dbi_); + + if (mode != ReadOnly) { + CHECK_EQ(mkdir(filename.c_str(), 0744), 0) << "mkdir " << filename + << "failed"; + } + + CHECK_EQ(mdb_env_create(&env_), MDB_SUCCESS) << "mdb_env_create failed"; + CHECK_EQ(mdb_env_set_mapsize(env_, 1099511627776), MDB_SUCCESS) // 1TB + << "mdb_env_set_mapsize failed"; + + int flag1 = 0; + int flag2 = 0; + if (mode == ReadOnly) { + flag1 = MDB_RDONLY | MDB_NOTLS; + flag2 = MDB_RDONLY; + } + + CHECK_EQ(mdb_env_open(env_, filename.c_str(), flag1, 0664), MDB_SUCCESS) + << "mdb_env_open failed"; + CHECK_EQ(mdb_txn_begin(env_, NULL, flag2, &txn_), MDB_SUCCESS) + << "mdb_txn_begin failed"; + CHECK_EQ(mdb_open(txn_, NULL, 0, &dbi_), MDB_SUCCESS) << "mdb_open failed"; +} + +void LmdbDatabase::put(const string& key, const string& value) { + LOG(INFO) << "LMDB: Put " << key; + + MDB_val mdbkey, mdbdata; + mdbdata.mv_size = value.size(); + mdbdata.mv_data = const_cast(&value[0]); + mdbkey.mv_size = key.size(); + mdbkey.mv_data = const_cast(&key[0]); + + CHECK_NOTNULL(txn_); + CHECK_NE(0, dbi_); + + CHECK_EQ(mdb_put(txn_, dbi_, &mdbkey, &mdbdata, 0), MDB_SUCCESS) + << "mdb_put failed"; +} + +void LmdbDatabase::commit() { + LOG(INFO) << "LMDB: Commit"; + + CHECK_NOTNULL(txn_); + + CHECK_EQ(mdb_txn_commit(txn_), MDB_SUCCESS) << "mdb_txn_commit failed"; +} + +void LmdbDatabase::close() { + LOG(INFO) << "LMDB: Close"; + + if (env_ && dbi_ && txn_) { + this->commit(); + } + + if (env_ && dbi_) { + mdb_close(env_, dbi_); + mdb_env_close(env_); + env_ = NULL; + dbi_ = 0; + txn_ = NULL; + } +} + +LmdbDatabase::const_iterator LmdbDatabase::begin() const { + MDB_cursor* cursor; + CHECK_EQ(mdb_cursor_open(txn_, dbi_, &cursor), MDB_SUCCESS); + MDB_val key; + MDB_val val; + CHECK_EQ(mdb_cursor_get(cursor, &key, &val, MDB_FIRST), MDB_SUCCESS); + + shared_ptr state(new LmdbState(cursor)); + return const_iterator(this, state); +} + +LmdbDatabase::const_iterator LmdbDatabase::end() const { + shared_ptr state(new LmdbState(NULL)); + return const_iterator(this, state); +} + +LmdbDatabase::const_iterator LmdbDatabase::cbegin() const { return begin(); } +LmdbDatabase::const_iterator LmdbDatabase::cend() const { return end(); } + +bool LmdbDatabase::equal(shared_ptr state1, + shared_ptr state2) const { + shared_ptr lmdb_state1 = + boost::dynamic_pointer_cast(state1); + + CHECK_NOTNULL(lmdb_state1.get()); + + shared_ptr lmdb_state2 = + boost::dynamic_pointer_cast(state2); + + CHECK_NOTNULL(lmdb_state2.get()); + + // The KV store doesn't really have any sort of ordering, + // so while we can do a sequential scan over the collection, + // we can't really use subranges. + return !lmdb_state1->cursor_ && !lmdb_state2->cursor_; +} + +void LmdbDatabase::increment(shared_ptr state) const { + shared_ptr lmdb_state = + boost::dynamic_pointer_cast(state); + + CHECK_NOTNULL(lmdb_state.get()); + + MDB_cursor*& cursor = lmdb_state->cursor_; + + MDB_val key; + MDB_val val; + if (MDB_SUCCESS != mdb_cursor_get(cursor, &key, &val, MDB_NEXT)) { + mdb_cursor_close(cursor); + cursor = NULL; + } +} + +pair& LmdbDatabase::dereference( + shared_ptr state) const { + shared_ptr lmdb_state = + boost::dynamic_pointer_cast(state); + + CHECK_NOTNULL(lmdb_state.get()); + + MDB_cursor*& cursor = lmdb_state->cursor_; + + MDB_val mdb_key; + MDB_val mdb_val; + CHECK_EQ(mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT), + MDB_SUCCESS); + + lmdb_state->kv_pair_ = make_pair( + string(reinterpret_cast(mdb_key.mv_data), mdb_key.mv_size), + string(reinterpret_cast(mdb_val.mv_data), mdb_val.mv_size)); + + return lmdb_state->kv_pair_; +} + +} // namespace caffe diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index f0404a09b90..f0dba097d05 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -423,7 +423,7 @@ message DataParameter { // The rand_skip variable is for the data layer to skip a few data points // to avoid all asynchronous sgd clients to start at the same point. The skip // point would be set as rand_skip * rand(0,1). Note that rand_skip should not - // be larger than the number of keys in the leveldb. + // be larger than the number of keys in the database. optional uint32 rand_skip = 7 [default = 0]; optional DB backend = 8 [default = LEVELDB]; // DEPRECATED. See TransformationParameter. For data pre-processing, we can do @@ -518,7 +518,7 @@ message ImageDataParameter { // The rand_skip variable is for the data layer to skip a few data points // to avoid all asynchronous sgd clients to start at the same point. The skip // point would be set as rand_skip * rand(0,1). Note that rand_skip should not - // be larger than the number of keys in the leveldb. + // be larger than the number of keys in the database. optional uint32 rand_skip = 7 [default = 0]; // Whether or not ImageLayer should shuffle the list of files at every epoch. optional bool shuffle = 8 [default = false]; @@ -767,7 +767,7 @@ message V0LayerParameter { // The rand_skip variable is for the data layer to skip a few data points // to avoid all asynchronous sgd clients to start at the same point. The skip // point would be set as rand_skip * rand(0,1). Note that rand_skip should not - // be larger than the number of keys in the leveldb. + // be larger than the number of keys in the database. optional uint32 rand_skip = 53 [default = 0]; // Fields related to detection (det_*) diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index 657ffdea68c..d99b5e3a0d3 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -2,10 +2,10 @@ #include #include "gtest/gtest.h" -#include "leveldb/db.h" #include "caffe/blob.hpp" #include "caffe/common.hpp" +#include "caffe/database_factory.hpp" #include "caffe/filler.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" @@ -36,16 +36,11 @@ class DataLayerTest : public MultiDeviceTest { // Fill the LevelDB with data: if unique_pixels, each pixel is unique but // all images are the same; else each image is unique but all pixels within // an image are the same. - void FillLevelDB(const bool unique_pixels) { - backend_ = DataParameter_DB_LEVELDB; - LOG(INFO) << "Using temporary leveldb " << *filename_; - leveldb::DB* db; - leveldb::Options options; - options.error_if_exists = true; - options.create_if_missing = true; - leveldb::Status status = - leveldb::DB::Open(options, filename_->c_str(), &db); - CHECK(status.ok()); + void Fill(const bool unique_pixels, DataParameter_DB backend) { + backend_ = backend; + LOG(INFO) << "Using temporary database " << *filename_; + shared_ptr database = DatabaseFactory(backend_); + database->open(*filename_, Database::New); for (int i = 0; i < 5; ++i) { Datum datum; datum.set_label(i); @@ -59,57 +54,9 @@ class DataLayerTest : public MultiDeviceTest { } stringstream ss; ss << i; - db->Put(leveldb::WriteOptions(), ss.str(), datum.SerializeAsString()); + database->put(ss.str(), datum.SerializeAsString()); } - delete db; - } - - // Fill the LMDB with data: unique_pixels has same meaning as in FillLevelDB. - void FillLMDB(const bool unique_pixels) { - backend_ = DataParameter_DB_LMDB; - LOG(INFO) << "Using temporary lmdb " << *filename_; - CHECK_EQ(mkdir(filename_->c_str(), 0744), 0) << "mkdir " << filename_ - << "failed"; - MDB_env *env; - MDB_dbi dbi; - MDB_val mdbkey, mdbdata; - MDB_txn *txn; - CHECK_EQ(mdb_env_create(&env), MDB_SUCCESS) << "mdb_env_create failed"; - CHECK_EQ(mdb_env_set_mapsize(env, 1099511627776), MDB_SUCCESS) // 1TB - << "mdb_env_set_mapsize failed"; - CHECK_EQ(mdb_env_open(env, filename_->c_str(), 0, 0664), MDB_SUCCESS) - << "mdb_env_open failed"; - CHECK_EQ(mdb_txn_begin(env, NULL, 0, &txn), MDB_SUCCESS) - << "mdb_txn_begin failed"; - CHECK_EQ(mdb_open(txn, NULL, 0, &dbi), MDB_SUCCESS) << "mdb_open failed"; - - for (int i = 0; i < 5; ++i) { - Datum datum; - datum.set_label(i); - datum.set_channels(2); - datum.set_height(3); - datum.set_width(4); - std::string* data = datum.mutable_data(); - for (int j = 0; j < 24; ++j) { - int datum = unique_pixels ? j : i; - data->push_back(static_cast(datum)); - } - stringstream ss; - ss << i; - - string value; - datum.SerializeToString(&value); - mdbdata.mv_size = value.size(); - mdbdata.mv_data = reinterpret_cast(&value[0]); - string keystr = ss.str(); - mdbkey.mv_size = keystr.size(); - mdbkey.mv_data = reinterpret_cast(&keystr[0]); - CHECK_EQ(mdb_put(txn, dbi, &mdbkey, &mdbdata, 0), MDB_SUCCESS) - << "mdb_put failed"; - } - CHECK_EQ(mdb_txn_commit(txn), MDB_SUCCESS) << "mdb_txn_commit failed"; - mdb_close(env, dbi); - mdb_env_close(env); + database->close(); } void TestRead() { @@ -234,7 +181,7 @@ class DataLayerTest : public MultiDeviceTest { } crop_sequence.push_back(iter_crop_sequence); } - } // destroy 1st data layer and unlock the leveldb + } // destroy 1st data layer and unlock the database // Get crop sequence after reseeding Caffe with 1701. // Check that the sequence is the same as the original. @@ -289,7 +236,7 @@ class DataLayerTest : public MultiDeviceTest { } crop_sequence.push_back(iter_crop_sequence); } - } // destroy 1st data layer and unlock the leveldb + } // destroy 1st data layer and unlock the database // Get crop sequence continuing from previous Caffe RNG state; reseed // srand with 1701. Check that the sequence differs from the original. @@ -327,14 +274,14 @@ TYPED_TEST_CASE(DataLayerTest, TestDtypesAndDevices); TYPED_TEST(DataLayerTest, TestReadLevelDB) { const bool unique_pixels = false; // all pixels the same; images different - this->FillLevelDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LEVELDB); this->TestRead(); } TYPED_TEST(DataLayerTest, TestReadCropTrainLevelDB) { Caffe::set_phase(Caffe::TRAIN); const bool unique_pixels = true; // all images the same; pixels different - this->FillLevelDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LEVELDB); this->TestReadCrop(); } @@ -343,7 +290,7 @@ TYPED_TEST(DataLayerTest, TestReadCropTrainLevelDB) { TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceSeededLevelDB) { Caffe::set_phase(Caffe::TRAIN); const bool unique_pixels = true; // all images the same; pixels different - this->FillLevelDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LEVELDB); this->TestReadCropTrainSequenceSeeded(); } @@ -352,27 +299,27 @@ TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceSeededLevelDB) { TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceUnseededLevelDB) { Caffe::set_phase(Caffe::TRAIN); const bool unique_pixels = true; // all images the same; pixels different - this->FillLevelDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LEVELDB); this->TestReadCropTrainSequenceUnseeded(); } TYPED_TEST(DataLayerTest, TestReadCropTestLevelDB) { Caffe::set_phase(Caffe::TEST); const bool unique_pixels = true; // all images the same; pixels different - this->FillLevelDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LEVELDB); this->TestReadCrop(); } TYPED_TEST(DataLayerTest, TestReadLMDB) { const bool unique_pixels = false; // all pixels the same; images different - this->FillLMDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LMDB); this->TestRead(); } TYPED_TEST(DataLayerTest, TestReadCropTrainLMDB) { Caffe::set_phase(Caffe::TRAIN); const bool unique_pixels = true; // all images the same; pixels different - this->FillLMDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LMDB); this->TestReadCrop(); } @@ -381,7 +328,7 @@ TYPED_TEST(DataLayerTest, TestReadCropTrainLMDB) { TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceSeededLMDB) { Caffe::set_phase(Caffe::TRAIN); const bool unique_pixels = true; // all images the same; pixels different - this->FillLMDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LMDB); this->TestReadCropTrainSequenceSeeded(); } @@ -390,14 +337,14 @@ TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceSeededLMDB) { TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceUnseededLMDB) { Caffe::set_phase(Caffe::TRAIN); const bool unique_pixels = true; // all images the same; pixels different - this->FillLMDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LMDB); this->TestReadCropTrainSequenceUnseeded(); } TYPED_TEST(DataLayerTest, TestReadCropTestLMDB) { Caffe::set_phase(Caffe::TEST); const bool unique_pixels = true; // all images the same; pixels different - this->FillLMDB(unique_pixels); + this->Fill(unique_pixels, DataParameter_DB_LMDB); this->TestReadCrop(); } diff --git a/src/caffe/test/test_hdf5data_layer.cpp b/src/caffe/test/test_hdf5data_layer.cpp index 41a3a83dd9f..8d3b3d1e987 100644 --- a/src/caffe/test/test_hdf5data_layer.cpp +++ b/src/caffe/test/test_hdf5data_layer.cpp @@ -1,8 +1,6 @@ #include #include -#include "leveldb/db.h" - #include "gtest/gtest.h" #include "caffe/blob.hpp" diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 36510d61d40..a4a6627b277 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -122,15 +121,6 @@ void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) { datum->set_data(buffer); } - -leveldb::Options GetLevelDBOptions() { - // In default, we will return the leveldb option and set the max open files - // in order to avoid using up the operating system's limit. - leveldb::Options options; - options.max_open_files = 100; - return options; -} - // Verifies format of data stored in HDF5 file and reshapes blob accordingly. template void hdf5_load_nd_dataset_helper( diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index 6adde8b1d1c..e59bbf19f0d 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -1,14 +1,14 @@ #include -#include -#include #include #include #include +#include "caffe/database_factory.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" +using caffe::Database; using caffe::Datum; using caffe::BlobProto; using std::max; @@ -26,57 +26,16 @@ int main(int argc, char** argv) { db_backend = std::string(argv[3]); } - // leveldb - leveldb::DB* db; - leveldb::Options options; - options.create_if_missing = false; - leveldb::Iterator* it = NULL; - // lmdb - MDB_env* mdb_env; - MDB_dbi mdb_dbi; - MDB_val mdb_key, mdb_value; - MDB_txn* mdb_txn; - MDB_cursor* mdb_cursor; + caffe::shared_ptr database = caffe::DatabaseFactory(db_backend); // Open db - if (db_backend == "leveldb") { // leveldb - LOG(INFO) << "Opening leveldb " << argv[1]; - leveldb::Status status = leveldb::DB::Open( - options, argv[1], &db); - CHECK(status.ok()) << "Failed to open leveldb " << argv[1]; - leveldb::ReadOptions read_options; - read_options.fill_cache = false; - it = db->NewIterator(read_options); - it->SeekToFirst(); - } else if (db_backend == "lmdb") { // lmdb - LOG(INFO) << "Opening lmdb " << argv[1]; - CHECK_EQ(mdb_env_create(&mdb_env), MDB_SUCCESS) << "mdb_env_create failed"; - CHECK_EQ(mdb_env_set_mapsize(mdb_env, 1099511627776), MDB_SUCCESS); // 1TB - CHECK_EQ(mdb_env_open(mdb_env, argv[1], MDB_RDONLY, 0664), - MDB_SUCCESS) << "mdb_env_open failed"; - CHECK_EQ(mdb_txn_begin(mdb_env, NULL, MDB_RDONLY, &mdb_txn), MDB_SUCCESS) - << "mdb_txn_begin failed"; - CHECK_EQ(mdb_open(mdb_txn, NULL, 0, &mdb_dbi), MDB_SUCCESS) - << "mdb_open failed"; - CHECK_EQ(mdb_cursor_open(mdb_txn, mdb_dbi, &mdb_cursor), MDB_SUCCESS) - << "mdb_cursor_open failed"; - CHECK_EQ(mdb_cursor_get(mdb_cursor, &mdb_key, &mdb_value, MDB_FIRST), - MDB_SUCCESS); - } else { - LOG(FATAL) << "Unknown db backend " << db_backend; - } + database->open(argv[1], Database::ReadOnly); Datum datum; BlobProto sum_blob; int count = 0; // load first datum - if (db_backend == "leveldb") { - datum.ParseFromString(it->value().ToString()); - } else if (db_backend == "lmdb") { - datum.ParseFromArray(mdb_value.mv_data, mdb_value.mv_size); - } else { - LOG(FATAL) << "Unknown db backend " << db_backend; - } + datum.ParseFromString(database->begin()->second); sum_blob.set_num(1); sum_blob.set_channels(datum.channels()); @@ -89,59 +48,29 @@ int main(int argc, char** argv) { sum_blob.add_data(0.); } LOG(INFO) << "Starting Iteration"; - if (db_backend == "leveldb") { // leveldb - for (it->SeekToFirst(); it->Valid(); it->Next()) { - // just a dummy operation - datum.ParseFromString(it->value().ToString()); - const std::string& data = datum.data(); - size_in_datum = std::max(datum.data().size(), - datum.float_data_size()); - CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " << - size_in_datum; - if (data.size() != 0) { - for (int i = 0; i < size_in_datum; ++i) { - sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]); - } - } else { - for (int i = 0; i < size_in_datum; ++i) { - sum_blob.set_data(i, sum_blob.data(i) + - static_cast(datum.float_data(i))); - } + for (Database::const_iterator iter = database->begin(); + iter != database->end(); ++iter) { + // just a dummy operation + datum.ParseFromString(iter->second); + const std::string& data = datum.data(); + size_in_datum = std::max(datum.data().size(), + datum.float_data_size()); + CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " << + size_in_datum; + if (data.size() != 0) { + for (int i = 0; i < size_in_datum; ++i) { + sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]); } - ++count; - if (count % 10000 == 0) { - LOG(ERROR) << "Processed " << count << " files."; + } else { + for (int i = 0; i < size_in_datum; ++i) { + sum_blob.set_data(i, sum_blob.data(i) + + static_cast(datum.float_data(i))); } } - } else if (db_backend == "lmdb") { // lmdb - CHECK_EQ(mdb_cursor_get(mdb_cursor, &mdb_key, &mdb_value, MDB_FIRST), - MDB_SUCCESS); - do { - // just a dummy operation - datum.ParseFromArray(mdb_value.mv_data, mdb_value.mv_size); - const std::string& data = datum.data(); - size_in_datum = std::max(datum.data().size(), - datum.float_data_size()); - CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " << - size_in_datum; - if (data.size() != 0) { - for (int i = 0; i < size_in_datum; ++i) { - sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]); - } - } else { - for (int i = 0; i < size_in_datum; ++i) { - sum_blob.set_data(i, sum_blob.data(i) + - static_cast(datum.float_data(i))); - } - } - ++count; - if (count % 10000 == 0) { - LOG(ERROR) << "Processed " << count << " files."; - } - } while (mdb_cursor_get(mdb_cursor, &mdb_key, &mdb_value, MDB_NEXT) - == MDB_SUCCESS); - } else { - LOG(FATAL) << "Unknown db backend " << db_backend; + ++count; + if (count % 10000 == 0) { + LOG(ERROR) << "Processed " << count << " files."; + } } if (count % 10000 != 0) { @@ -155,15 +84,6 @@ int main(int argc, char** argv) { WriteProtoToBinaryFile(sum_blob, argv[2]); // Clean up - if (db_backend == "leveldb") { - delete db; - } else if (db_backend == "lmdb") { - mdb_cursor_close(mdb_cursor); - mdb_close(mdb_env, mdb_dbi); - mdb_txn_abort(mdb_txn); - mdb_env_close(mdb_env); - } else { - LOG(FATAL) << "Unknown db backend " << db_backend; - } + database->close(); return 0; } diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 7c8c1dab3fb..6f03a9d9d49 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -10,10 +10,6 @@ #include #include -#include -#include -#include -#include #include #include // NOLINT(readability/streams) @@ -21,6 +17,7 @@ #include #include +#include "caffe/database_factory.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" #include "caffe/util/rng.hpp" @@ -81,43 +78,10 @@ int main(int argc, char** argv) { int resize_width = std::max(0, FLAGS_resize_width); // Open new db - // lmdb - MDB_env *mdb_env; - MDB_dbi mdb_dbi; - MDB_val mdb_key, mdb_data; - MDB_txn *mdb_txn; - // leveldb - leveldb::DB* db; - leveldb::Options options; - options.error_if_exists = true; - options.create_if_missing = true; - options.write_buffer_size = 268435456; - leveldb::WriteBatch* batch = NULL; + shared_ptr database = DatabaseFactory(db_backend); // Open db - if (db_backend == "leveldb") { // leveldb - LOG(INFO) << "Opening leveldb " << db_path; - leveldb::Status status = leveldb::DB::Open( - options, db_path, &db); - CHECK(status.ok()) << "Failed to open leveldb " << db_path - << ". Is it already existing?"; - batch = new leveldb::WriteBatch(); - } else if (db_backend == "lmdb") { // lmdb - LOG(INFO) << "Opening lmdb " << db_path; - CHECK_EQ(mkdir(db_path, 0744), 0) - << "mkdir " << db_path << "failed"; - CHECK_EQ(mdb_env_create(&mdb_env), MDB_SUCCESS) << "mdb_env_create failed"; - CHECK_EQ(mdb_env_set_mapsize(mdb_env, 1099511627776), MDB_SUCCESS) // 1TB - << "mdb_env_set_mapsize failed"; - CHECK_EQ(mdb_env_open(mdb_env, db_path, 0, 0664), MDB_SUCCESS) - << "mdb_env_open failed"; - CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS) - << "mdb_txn_begin failed"; - CHECK_EQ(mdb_open(mdb_txn, NULL, 0, &mdb_dbi), MDB_SUCCESS) - << "mdb_open failed. Does the lmdb already exist? "; - } else { - LOG(FATAL) << "Unknown db backend " << db_backend; - } + database->open(db_path, Database::New); // Storing to db std::string root_folder(argv[1]); @@ -151,50 +115,19 @@ int main(int argc, char** argv) { std::string keystr(key_cstr); // Put in db - if (db_backend == "leveldb") { // leveldb - batch->Put(keystr, value); - } else if (db_backend == "lmdb") { // lmdb - mdb_data.mv_size = value.size(); - mdb_data.mv_data = reinterpret_cast(&value[0]); - mdb_key.mv_size = keystr.size(); - mdb_key.mv_data = reinterpret_cast(&keystr[0]); - CHECK_EQ(mdb_put(mdb_txn, mdb_dbi, &mdb_key, &mdb_data, 0), MDB_SUCCESS) - << "mdb_put failed"; - } else { - LOG(FATAL) << "Unknown db backend " << db_backend; - } + database->put(keystr, value); if (++count % 1000 == 0) { // Commit txn - if (db_backend == "leveldb") { // leveldb - db->Write(leveldb::WriteOptions(), batch); - delete batch; - batch = new leveldb::WriteBatch(); - } else if (db_backend == "lmdb") { // lmdb - CHECK_EQ(mdb_txn_commit(mdb_txn), MDB_SUCCESS) - << "mdb_txn_commit failed"; - CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS) - << "mdb_txn_begin failed"; - } else { - LOG(FATAL) << "Unknown db backend " << db_backend; - } + database->commit(); LOG(ERROR) << "Processed " << count << " files."; } } // write the last batch if (count % 1000 != 0) { - if (db_backend == "leveldb") { // leveldb - db->Write(leveldb::WriteOptions(), batch); - delete batch; - delete db; - } else if (db_backend == "lmdb") { // lmdb - CHECK_EQ(mdb_txn_commit(mdb_txn), MDB_SUCCESS) << "mdb_txn_commit failed"; - mdb_close(mdb_env, mdb_dbi); - mdb_env_close(mdb_env); - } else { - LOG(FATAL) << "Unknown db backend " << db_backend; - } + database->commit(); LOG(ERROR) << "Processed " << count << " files."; } + database->close(); return 0; } diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 299b3118760..b3ad8e60622 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -4,11 +4,10 @@ #include "boost/algorithm/string.hpp" #include "google/protobuf/text_format.h" -#include "leveldb/db.h" -#include "leveldb/write_batch.h" #include "caffe/blob.hpp" #include "caffe/common.hpp" +#include "caffe/database_factory.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" @@ -17,6 +16,8 @@ using boost::shared_ptr; using caffe::Blob; using caffe::Caffe; +using caffe::Database; +using caffe::DatabaseFactory; using caffe::Datum; using caffe::Net; @@ -38,12 +39,12 @@ int feature_extraction_pipeline(int argc, char** argv) { " extract features of the input data produced by the net.\n" "Usage: extract_features pretrained_net_param" " feature_extraction_proto_file extract_feature_blob_name1[,name2,...]" - " save_feature_leveldb_name1[,name2,...] num_mini_batches [CPU/GPU]" + " save_feature_database_name1[,name2,...] num_mini_batches [CPU/GPU]" " [DEVICE_ID=0]\n" "Note: you can extract multiple features in one pass by specifying" - " multiple feature blob names and leveldb names seperated by ','." + " multiple feature blob names and database names seperated by ','." " The names cannot contain white space characters and the number of blobs" - " and leveldbs must be equal."; + " and databases must be equal."; return 1; } int arg_pos = num_required_args; @@ -104,12 +105,12 @@ int feature_extraction_pipeline(int argc, char** argv) { std::vector blob_names; boost::split(blob_names, extract_feature_blob_names, boost::is_any_of(",")); - std::string save_feature_leveldb_names(argv[++arg_pos]); - std::vector leveldb_names; - boost::split(leveldb_names, save_feature_leveldb_names, + std::string save_feature_database_names(argv[++arg_pos]); + std::vector database_names; + boost::split(database_names, save_feature_database_names, boost::is_any_of(",")); - CHECK_EQ(blob_names.size(), leveldb_names.size()) << - " the number of blob names and leveldb names must be equal"; + CHECK_EQ(blob_names.size(), database_names.size()) << + " the number of blob names and database names must be equal"; size_t num_features = blob_names.size(); for (size_t i = 0; i < num_features; i++) { @@ -118,19 +119,12 @@ int feature_extraction_pipeline(int argc, char** argv) { << " in the network " << feature_extraction_proto; } - leveldb::Options options; - options.error_if_exists = true; - options.create_if_missing = true; - options.write_buffer_size = 268435456; - std::vector > feature_dbs; + std::vector > feature_dbs; for (size_t i = 0; i < num_features; ++i) { - LOG(INFO)<< "Opening leveldb " << leveldb_names[i]; - leveldb::DB* db; - leveldb::Status status = leveldb::DB::Open(options, - leveldb_names[i].c_str(), - &db); - CHECK(status.ok()) << "Failed to open leveldb " << leveldb_names[i]; - feature_dbs.push_back(shared_ptr(db)); + LOG(INFO)<< "Opening database " << database_names[i]; + shared_ptr database = DatabaseFactory("leveldb"); + database->open(database_names.at(i), Database::New); + feature_dbs.push_back(database); } int num_mini_batches = atoi(argv[++arg_pos]); @@ -138,9 +132,6 @@ int feature_extraction_pipeline(int argc, char** argv) { LOG(ERROR)<< "Extacting Features"; Datum datum; - std::vector > feature_batches( - num_features, - shared_ptr(new leveldb::WriteBatch())); const int kMaxKeyStrLength = 100; char key_str[kMaxKeyStrLength]; std::vector*> input_vec; @@ -167,14 +158,12 @@ int feature_extraction_pipeline(int argc, char** argv) { std::string value; datum.SerializeToString(&value); snprintf(key_str, kMaxKeyStrLength, "%d", image_indices[i]); - feature_batches[i]->Put(std::string(key_str), value); + feature_dbs.at(i)->put(std::string(key_str), value); ++image_indices[i]; if (image_indices[i] % 1000 == 0) { - feature_dbs[i]->Write(leveldb::WriteOptions(), - feature_batches[i].get()); + feature_dbs.at(i)->commit(); LOG(ERROR)<< "Extracted features of " << image_indices[i] << " query images for feature blob " << blob_names[i]; - feature_batches[i].reset(new leveldb::WriteBatch()); } } // for (int n = 0; n < batch_size; ++n) } // for (int i = 0; i < num_features; ++i) @@ -182,10 +171,11 @@ int feature_extraction_pipeline(int argc, char** argv) { // write the last batch for (int i = 0; i < num_features; ++i) { if (image_indices[i] % 1000 != 0) { - feature_dbs[i]->Write(leveldb::WriteOptions(), feature_batches[i].get()); + feature_dbs.at(i)->commit(); } LOG(ERROR)<< "Extracted features of " << image_indices[i] << " query images for feature blob " << blob_names[i]; + feature_dbs.at(i)->close(); } LOG(ERROR)<< "Successfully extracted the features!"; From 329e4481263d396b22a6e8ca6b00b19d57860ab9 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 7 Oct 2014 16:14:29 -0400 Subject: [PATCH 108/798] Some cleanup to make travis happy. --- include/caffe/database_factory.hpp | 1 + include/caffe/leveldb_database.hpp | 11 +++++------ include/caffe/lmdb_database.hpp | 19 ++++++++++--------- src/caffe/database_factory.cpp | 2 ++ src/caffe/layers/data_layer.cpp | 3 +++ 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/caffe/database_factory.hpp b/include/caffe/database_factory.hpp index a6e39e76188..91185e99b89 100644 --- a/include/caffe/database_factory.hpp +++ b/include/caffe/database_factory.hpp @@ -5,6 +5,7 @@ #include "caffe/common.hpp" #include "caffe/database.hpp" +#include "caffe/proto/caffe.pb.h" namespace caffe { diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index 5daf0e51e12..ee8c5f2eed8 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -19,6 +19,11 @@ class LeveldbDatabase : public Database { void commit(); void close(); + const_iterator begin() const; + const_iterator cbegin() const; + const_iterator end() const; + const_iterator cend() const; + ~LeveldbDatabase() { this->close(); } protected: @@ -37,12 +42,6 @@ class LeveldbDatabase : public Database { void increment(shared_ptr state) const; pair& dereference(shared_ptr state) const; - const_iterator begin() const; - const_iterator cbegin() const; - const_iterator end() const; - const_iterator cend() const; - - protected: shared_ptr db_; shared_ptr batch_; }; diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index f275cb48f5c..7387afd24d0 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -14,7 +14,9 @@ namespace caffe { class LmdbDatabase : public Database { public: LmdbDatabase() - : dbi_(0) { } + : env_(NULL), + dbi_(0), + txn_(NULL) { } ~LmdbDatabase() { this->close(); } void open(const string& filename, Mode mode); @@ -22,6 +24,11 @@ class LmdbDatabase : public Database { void commit(); void close(); + const_iterator begin() const; + const_iterator cbegin() const; + const_iterator end() const; + const_iterator cend() const; + protected: class LmdbState : public Database::DatabaseState { public: @@ -38,15 +45,9 @@ class LmdbDatabase : public Database { void increment(shared_ptr state) const; pair& dereference(shared_ptr state) const; - protected: - const_iterator begin() const; - const_iterator cbegin() const; - const_iterator end() const; - const_iterator cend() const; - - MDB_env *env_ = NULL; + MDB_env *env_; MDB_dbi dbi_; - MDB_txn *txn_ = NULL; + MDB_txn *txn_; }; } // namespace caffe diff --git a/src/caffe/database_factory.cpp b/src/caffe/database_factory.cpp index 393635b3208..062de8c02e3 100644 --- a/src/caffe/database_factory.cpp +++ b/src/caffe/database_factory.cpp @@ -15,6 +15,7 @@ shared_ptr DatabaseFactory(const DataParameter_DB& type) { return shared_ptr(new LmdbDatabase()); default: LOG(FATAL) << "Unknown database type " << type; + return shared_ptr(); } } @@ -25,6 +26,7 @@ shared_ptr DatabaseFactory(const string& type) { return DatabaseFactory(DataParameter_DB_LMDB); } else { LOG(FATAL) << "Unknown database type " << type; + return shared_ptr(); } } diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index b746bc8a37d..1d37170bdde 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -18,6 +18,9 @@ template DataLayer::~DataLayer() { this->JoinPrefetchThread(); // clean up the database resources + + // Very important to invalidate iterators before closing the database. + // TODO(kmatzen): Figure out a better design to avoid this. iter_ = database_->end(); database_->close(); } From 7e504c0612b23449aa83fd7aac8d49c56b03fd62 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 7 Oct 2014 18:03:02 -0400 Subject: [PATCH 109/798] Updated interface to make fewer string copies. --- include/caffe/database.hpp | 13 ++++-- include/caffe/leveldb_database.hpp | 6 +-- include/caffe/lmdb_database.hpp | 6 +-- include/caffe/util/io.hpp | 8 ++-- src/caffe/layers/data_layer.cpp | 5 +- src/caffe/leveldb_database.cpp | 18 +++++--- src/caffe/lmdb_database.cpp | 73 ++++++++++++++++++++---------- src/caffe/test/test_data_layer.cpp | 7 ++- tools/compute_image_mean.cpp | 6 ++- tools/convert_imageset.cpp | 11 +++-- tools/extract_features.cpp | 11 +++-- 11 files changed, 103 insertions(+), 61 deletions(-) diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index 4a1a25efd12..23036a8e075 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "caffe/common.hpp" @@ -18,8 +19,10 @@ class Database { ReadOnly }; + typedef vector buffer_t; + virtual void open(const string& filename, Mode mode) = 0; - virtual void put(const string& key, const string& value) = 0; + virtual void put(buffer_t* key, buffer_t* value) = 0; virtual void commit() = 0; virtual void close() = 0; @@ -38,10 +41,10 @@ class Database { class DatabaseState; public: - class iterator : - public std::iterator > { + class iterator : public std::iterator< + std::forward_iterator_tag, pair > { public: - typedef pair T; + typedef pair T; typedef T value_type; typedef T& reference_type; typedef T* pointer_type; @@ -94,7 +97,7 @@ class Database { virtual bool equal(shared_ptr state1, shared_ptr state2) const = 0; virtual void increment(shared_ptr state) const = 0; - virtual pair& dereference( + virtual pair& dereference( shared_ptr state) const = 0; }; diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index ee8c5f2eed8..f30273d6fe7 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -15,7 +15,7 @@ namespace caffe { class LeveldbDatabase : public Database { public: void open(const string& filename, Mode mode); - void put(const string& key, const string& value); + void put(buffer_t* key, buffer_t* value); void commit(); void close(); @@ -34,13 +34,13 @@ class LeveldbDatabase : public Database { iter_(iter) { } shared_ptr iter_; - pair kv_pair_; + pair kv_pair_; }; bool equal(shared_ptr state1, shared_ptr state2) const; void increment(shared_ptr state) const; - pair& dereference(shared_ptr state) const; + pair& dereference(shared_ptr state) const; shared_ptr db_; shared_ptr batch_; diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index 7387afd24d0..ee3806ddf36 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -20,7 +20,7 @@ class LmdbDatabase : public Database { ~LmdbDatabase() { this->close(); } void open(const string& filename, Mode mode); - void put(const string& key, const string& value); + void put(buffer_t* key, buffer_t* value); void commit(); void close(); @@ -37,13 +37,13 @@ class LmdbDatabase : public Database { cursor_(cursor) { } MDB_cursor* cursor_; - pair kv_pair_; + pair kv_pair_; }; bool equal(shared_ptr state1, shared_ptr state2) const; void increment(shared_ptr state) const; - pair& dereference(shared_ptr state) const; + pair& dereference(shared_ptr state) const; MDB_env *env_; MDB_dbi dbi_; diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 1124bef179a..b64c821a86e 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -24,27 +24,27 @@ using ::google::protobuf::Message; inline void MakeTempFilename(string* temp_filename) { temp_filename->clear(); *temp_filename = "/tmp/caffe_test.XXXXXX"; - char* temp_filename_cstr = new char[temp_filename->size()]; + char* temp_filename_cstr = new char[temp_filename->size() + 1]; // NOLINT_NEXT_LINE(runtime/printf) strcpy(temp_filename_cstr, temp_filename->c_str()); int fd = mkstemp(temp_filename_cstr); CHECK_GE(fd, 0) << "Failed to open a temporary file at: " << *temp_filename; close(fd); *temp_filename = temp_filename_cstr; - delete temp_filename_cstr; + delete[] temp_filename_cstr; } inline void MakeTempDir(string* temp_dirname) { temp_dirname->clear(); *temp_dirname = "/tmp/caffe_test.XXXXXX"; - char* temp_dirname_cstr = new char[temp_dirname->size()]; + char* temp_dirname_cstr = new char[temp_dirname->size() + 1]; // NOLINT_NEXT_LINE(runtime/printf) strcpy(temp_dirname_cstr, temp_dirname->c_str()); char* mkdtemp_result = mkdtemp(temp_dirname_cstr); CHECK(mkdtemp_result != NULL) << "Failed to create a temporary directory at: " << *temp_dirname; *temp_dirname = temp_dirname_cstr; - delete temp_dirname_cstr; + delete[] temp_dirname_cstr; } bool ReadProtoFromTextFile(const char* filename, Message* proto); diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 1d37170bdde..4d36b8ede42 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -40,7 +40,6 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, this->layer_param_.data_param().rand_skip(); LOG(INFO) << "Skipping first " << skip << " data points."; while (skip-- > 0) { - LOG(INFO) << iter_->first; if (++iter_ == database_->end()) { iter_ = database_->begin(); } @@ -49,7 +48,7 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // Read a data point, and use it to initialize the top blob. CHECK(iter_ != database_->end()); Datum datum; - datum.ParseFromString(iter_->second); + datum.ParseFromArray(iter_->second.data(), iter_->second.size()); // image int crop_size = this->layer_param_.transform_param().crop_size(); @@ -95,7 +94,7 @@ void DataLayer::InternalThreadEntry() { for (int item_id = 0; item_id < batch_size; ++item_id) { Datum datum; CHECK(iter_ != database_->end()); - datum.ParseFromString(iter_->second); + datum.ParseFromArray(iter_->second.data(), iter_->second.size()); // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index be7ac7f141c..a8fe02a3157 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -42,11 +42,15 @@ void LeveldbDatabase::open(const string& filename, Mode mode) { batch_.reset(new leveldb::WriteBatch()); } -void LeveldbDatabase::put(const string& key, const string& value) { - LOG(INFO) << "LevelDB: Put " << key; +void LeveldbDatabase::put(buffer_t* key, buffer_t* value) { + LOG(INFO) << "LevelDB: Put"; CHECK_NOTNULL(batch_.get()); - batch_->Put(key, value); + + leveldb::Slice key_slice(key->data(), key->size()); + leveldb::Slice value_slice(value->data(), value->size()); + + batch_->Put(key_slice, value_slice); } void LeveldbDatabase::commit() { @@ -130,7 +134,7 @@ void LeveldbDatabase::increment(shared_ptr state) const { } } -pair& LeveldbDatabase::dereference( +pair& LeveldbDatabase::dereference( shared_ptr state) const { shared_ptr leveldb_state = boost::dynamic_pointer_cast(state); @@ -143,8 +147,10 @@ pair& LeveldbDatabase::dereference( CHECK(iter->Valid()); - leveldb_state->kv_pair_ = make_pair(iter->key().ToString(), - iter->value().ToString()); + leveldb_state->kv_pair_ = make_pair( + buffer_t(iter->key().data(), iter->key().data() + iter->key().size()), + buffer_t(iter->value().data(), + iter->value().data() + iter->value().size())); return leveldb_state->kv_pair_; } diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index 796bbc9d4ac..7197a4775dc 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -19,9 +19,13 @@ void LmdbDatabase::open(const string& filename, Mode mode) { << "failed"; } - CHECK_EQ(mdb_env_create(&env_), MDB_SUCCESS) << "mdb_env_create failed"; - CHECK_EQ(mdb_env_set_mapsize(env_, 1099511627776), MDB_SUCCESS) // 1TB - << "mdb_env_set_mapsize failed"; + int retval; + retval = mdb_env_create(&env_); + CHECK_EQ(retval, MDB_SUCCESS) << "mdb_env_create failed " + << mdb_strerror(retval); + retval = mdb_env_set_mapsize(env_, 1099511627776); + CHECK_EQ(retval, MDB_SUCCESS) // 1TB + << "mdb_env_set_mapsize failed " << mdb_strerror(retval); int flag1 = 0; int flag2 = 0; @@ -30,27 +34,31 @@ void LmdbDatabase::open(const string& filename, Mode mode) { flag2 = MDB_RDONLY; } - CHECK_EQ(mdb_env_open(env_, filename.c_str(), flag1, 0664), MDB_SUCCESS) - << "mdb_env_open failed"; - CHECK_EQ(mdb_txn_begin(env_, NULL, flag2, &txn_), MDB_SUCCESS) - << "mdb_txn_begin failed"; - CHECK_EQ(mdb_open(txn_, NULL, 0, &dbi_), MDB_SUCCESS) << "mdb_open failed"; + retval = mdb_env_open(env_, filename.c_str(), flag1, 0664); + CHECK_EQ(retval, MDB_SUCCESS) + << "mdb_env_open failed " << mdb_strerror(retval); + retval = mdb_txn_begin(env_, NULL, flag2, &txn_); + CHECK_EQ(retval, MDB_SUCCESS) + << "mdb_txn_begin failed " << mdb_strerror(retval); + retval = mdb_open(txn_, NULL, 0, &dbi_); + CHECK_EQ(retval, MDB_SUCCESS) << "mdb_open failed" << mdb_strerror(retval); } -void LmdbDatabase::put(const string& key, const string& value) { - LOG(INFO) << "LMDB: Put " << key; +void LmdbDatabase::put(buffer_t* key, buffer_t* value) { + LOG(INFO) << "LMDB: Put"; MDB_val mdbkey, mdbdata; - mdbdata.mv_size = value.size(); - mdbdata.mv_data = const_cast(&value[0]); - mdbkey.mv_size = key.size(); - mdbkey.mv_data = const_cast(&key[0]); + mdbdata.mv_size = value->size(); + mdbdata.mv_data = value->data(); + mdbkey.mv_size = key->size(); + mdbkey.mv_data = key->data(); CHECK_NOTNULL(txn_); CHECK_NE(0, dbi_); - CHECK_EQ(mdb_put(txn_, dbi_, &mdbkey, &mdbdata, 0), MDB_SUCCESS) - << "mdb_put failed"; + int retval = mdb_put(txn_, dbi_, &mdbkey, &mdbdata, 0); + CHECK_EQ(retval, MDB_SUCCESS) + << "mdb_put failed " << mdb_strerror(retval); } void LmdbDatabase::commit() { @@ -58,7 +66,9 @@ void LmdbDatabase::commit() { CHECK_NOTNULL(txn_); - CHECK_EQ(mdb_txn_commit(txn_), MDB_SUCCESS) << "mdb_txn_commit failed"; + int retval = mdb_txn_commit(txn_); + CHECK_EQ(retval, MDB_SUCCESS) << "mdb_txn_commit failed " + << mdb_strerror(retval); } void LmdbDatabase::close() { @@ -79,10 +89,13 @@ void LmdbDatabase::close() { LmdbDatabase::const_iterator LmdbDatabase::begin() const { MDB_cursor* cursor; - CHECK_EQ(mdb_cursor_open(txn_, dbi_, &cursor), MDB_SUCCESS); + int retval; + retval = mdb_cursor_open(txn_, dbi_, &cursor); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); MDB_val key; MDB_val val; - CHECK_EQ(mdb_cursor_get(cursor, &key, &val, MDB_FIRST), MDB_SUCCESS); + retval = mdb_cursor_get(cursor, &key, &val, MDB_FIRST); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); shared_ptr state(new LmdbState(cursor)); return const_iterator(this, state); @@ -122,15 +135,20 @@ void LmdbDatabase::increment(shared_ptr state) const { MDB_cursor*& cursor = lmdb_state->cursor_; + CHECK_NOTNULL(cursor); + MDB_val key; MDB_val val; - if (MDB_SUCCESS != mdb_cursor_get(cursor, &key, &val, MDB_NEXT)) { + int retval = mdb_cursor_get(cursor, &key, &val, MDB_NEXT); + if (MDB_NOTFOUND == retval) { mdb_cursor_close(cursor); cursor = NULL; + } else { + CHECK_EQ(MDB_SUCCESS, retval) << mdb_strerror(retval); } } -pair& LmdbDatabase::dereference( +pair& LmdbDatabase::dereference( shared_ptr state) const { shared_ptr lmdb_state = boost::dynamic_pointer_cast(state); @@ -139,14 +157,19 @@ pair& LmdbDatabase::dereference( MDB_cursor*& cursor = lmdb_state->cursor_; + CHECK_NOTNULL(cursor); + MDB_val mdb_key; MDB_val mdb_val; - CHECK_EQ(mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT), - MDB_SUCCESS); + int retval = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + + char* key_data = reinterpret_cast(mdb_key.mv_data); + char* value_data = reinterpret_cast(mdb_val.mv_data); lmdb_state->kv_pair_ = make_pair( - string(reinterpret_cast(mdb_key.mv_data), mdb_key.mv_size), - string(reinterpret_cast(mdb_val.mv_data), mdb_val.mv_size)); + buffer_t(key_data, key_data + mdb_key.mv_size), + buffer_t(value_data, value_data + mdb_val.mv_size)); return lmdb_state->kv_pair_; } diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index d99b5e3a0d3..c17f7295c3c 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -54,7 +54,12 @@ class DataLayerTest : public MultiDeviceTest { } stringstream ss; ss << i; - database->put(ss.str(), datum.SerializeAsString()); + string key_str = ss.str(); + Database::buffer_t key(key_str.c_str(), key_str.c_str() + key_str.size()); + Database::buffer_t value(datum.ByteSize()); + datum.SerializeWithCachedSizesToArray( + reinterpret_cast(value.data())); + database->put(&key, &value); } database->close(); } diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index e59bbf19f0d..f981af40fdf 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -35,7 +35,8 @@ int main(int argc, char** argv) { BlobProto sum_blob; int count = 0; // load first datum - datum.ParseFromString(database->begin()->second); + const Database::buffer_t& first_blob = database->begin()->second; + datum.ParseFromArray(first_blob.data(), first_blob.size()); sum_blob.set_num(1); sum_blob.set_channels(datum.channels()); @@ -51,7 +52,8 @@ int main(int argc, char** argv) { for (Database::const_iterator iter = database->begin(); iter != database->end(); ++iter) { // just a dummy operation - datum.ParseFromString(iter->second); + const Database::buffer_t& blob = iter->second; + datum.ParseFromArray(blob.data(), blob.size()); const std::string& data = datum.data(); size_in_datum = std::max(datum.data().size(), datum.float_data_size()); diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 6f03a9d9d49..19c87e53ff0 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -108,14 +108,15 @@ int main(int argc, char** argv) { } } // sequential - snprintf(key_cstr, kMaxKeyLength, "%08d_%s", line_id, + int length = snprintf(key_cstr, kMaxKeyLength, "%08d_%s", line_id, lines[line_id].first.c_str()); - std::string value; - datum.SerializeToString(&value); - std::string keystr(key_cstr); + Database::buffer_t value(datum.ByteSize()); + datum.SerializeWithCachedSizesToArray( + reinterpret_cast(value.data())); + Database::buffer_t keystr(key_cstr, key_cstr + length); // Put in db - database->put(keystr, value); + database->put(&keystr, &value); if (++count % 1000 == 0) { // Commit txn diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index b3ad8e60622..1065d449a42 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -155,10 +155,13 @@ int feature_extraction_pipeline(int argc, char** argv) { for (int d = 0; d < dim_features; ++d) { datum.add_float_data(feature_blob_data[d]); } - std::string value; - datum.SerializeToString(&value); - snprintf(key_str, kMaxKeyStrLength, "%d", image_indices[i]); - feature_dbs.at(i)->put(std::string(key_str), value); + Database::buffer_t value(datum.ByteSize()); + datum.SerializeWithCachedSizesToArray( + reinterpret_cast(value.data())); + int length = snprintf(key_str, kMaxKeyStrLength, "%d", + image_indices[i]); + Database::buffer_t key(key_str, key_str + length); + feature_dbs.at(i)->put(&key, &value); ++image_indices[i]; if (image_indices[i] % 1000 == 0) { feature_dbs.at(i)->commit(); From edff676ea8482d48f4b7bc794288696afce782ca Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 7 Oct 2014 21:46:15 -0400 Subject: [PATCH 110/798] Don't autocommit on close for the databases. If they were read-only, then they might fail. --- examples/cifar10/convert_cifar_data.cpp | 59 ++++++++++++++----------- include/caffe/leveldb_database.hpp | 2 - include/caffe/lmdb_database.hpp | 1 - src/caffe/leveldb_database.cpp | 3 -- src/caffe/lmdb_database.cpp | 15 ++++--- tools/compute_image_mean.cpp | 4 +- 6 files changed, 43 insertions(+), 41 deletions(-) diff --git a/examples/cifar10/convert_cifar_data.cpp b/examples/cifar10/convert_cifar_data.cpp index 90ecb6d9a88..c4930878405 100644 --- a/examples/cifar10/convert_cifar_data.cpp +++ b/examples/cifar10/convert_cifar_data.cpp @@ -11,13 +11,17 @@ #include "glog/logging.h" #include "google/protobuf/text_format.h" -#include "leveldb/db.h" #include "stdint.h" +#include "caffe/database_factory.hpp" #include "caffe/proto/caffe.pb.h" using std::string; +using caffe::Database; +using caffe::DatabaseFactory; +using caffe::shared_ptr; + const int kCIFARSize = 32; const int kCIFARImageNBytes = 3072; const int kCIFARBatchSize = 10000; @@ -31,26 +35,20 @@ void read_image(std::ifstream* file, int* label, char* buffer) { return; } -void convert_dataset(const string& input_folder, const string& output_folder) { - // Leveldb options - leveldb::Options options; - options.create_if_missing = true; - options.error_if_exists = true; +void convert_dataset(const string& input_folder, const string& output_folder, + const string& db_type) { + shared_ptr train_database = DatabaseFactory(db_type); + train_database->open(output_folder + "/cifar10_train_" + db_type, + Database::New); // Data buffer int label; char str_buffer[kCIFARImageNBytes]; - string value; caffe::Datum datum; datum.set_channels(3); datum.set_height(kCIFARSize); datum.set_width(kCIFARSize); LOG(INFO) << "Writing Training data"; - leveldb::DB* train_db; - leveldb::Status status; - status = leveldb::DB::Open(options, output_folder + "/cifar10_train_leveldb", - &train_db); - CHECK(status.ok()) << "Failed to open leveldb."; for (int fileid = 0; fileid < kCIFARTrainBatches; ++fileid) { // Open files LOG(INFO) << "Training Batch " << fileid + 1; @@ -62,17 +60,22 @@ void convert_dataset(const string& input_folder, const string& output_folder) { read_image(&data_file, &label, str_buffer); datum.set_label(label); datum.set_data(str_buffer, kCIFARImageNBytes); - datum.SerializeToString(&value); - snprintf(str_buffer, kCIFARImageNBytes, "%05d", + Database::buffer_t value(datum.ByteSize()); + datum.SerializeWithCachedSizesToArray( + reinterpret_cast(value.data())); + int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", fileid * kCIFARBatchSize + itemid); - train_db->Put(leveldb::WriteOptions(), string(str_buffer), value); + Database::buffer_t key(str_buffer, str_buffer + length); + train_database->put(&key, &value); } } + train_database->commit(); + train_database->close(); LOG(INFO) << "Writing Testing data"; - leveldb::DB* test_db; - CHECK(leveldb::DB::Open(options, output_folder + "/cifar10_test_leveldb", - &test_db).ok()) << "Failed to open leveldb."; + shared_ptr test_database = DatabaseFactory(db_type); + test_database->open(output_folder + "/cifar10_test_" + db_type, + Database::New); // Open files std::ifstream data_file((input_folder + "/test_batch.bin").c_str(), std::ios::in | std::ios::binary); @@ -81,28 +84,30 @@ void convert_dataset(const string& input_folder, const string& output_folder) { read_image(&data_file, &label, str_buffer); datum.set_label(label); datum.set_data(str_buffer, kCIFARImageNBytes); - datum.SerializeToString(&value); - snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); - test_db->Put(leveldb::WriteOptions(), string(str_buffer), value); + Database::buffer_t value(datum.ByteSize()); + datum.SerializeWithCachedSizesToArray( + reinterpret_cast(value.data())); + int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); + Database::buffer_t key(str_buffer, str_buffer + length); + test_database->put(&key, &value); } - - delete train_db; - delete test_db; + test_database->commit(); + test_database->close(); } int main(int argc, char** argv) { - if (argc != 3) { + if (argc != 4) { printf("This script converts the CIFAR dataset to the leveldb format used\n" "by caffe to perform classification.\n" "Usage:\n" - " convert_cifar_data input_folder output_folder\n" + " convert_cifar_data input_folder output_folder db_type\n" "Where the input folder should contain the binary batch files.\n" "The CIFAR dataset could be downloaded at\n" " http://www.cs.toronto.edu/~kriz/cifar.html\n" "You should gunzip them after downloading.\n"); } else { google::InitGoogleLogging(argv[0]); - convert_dataset(string(argv[1]), string(argv[2])); + convert_dataset(string(argv[1]), string(argv[2]), string(argv[3])); } return 0; } diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index f30273d6fe7..dda669704bd 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -24,8 +24,6 @@ class LeveldbDatabase : public Database { const_iterator end() const; const_iterator cend() const; - ~LeveldbDatabase() { this->close(); } - protected: class LeveldbState : public Database::DatabaseState { public: diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index ee3806ddf36..96542227c9a 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -17,7 +17,6 @@ class LmdbDatabase : public Database { : env_(NULL), dbi_(0), txn_(NULL) { } - ~LmdbDatabase() { this->close(); } void open(const string& filename, Mode mode); void put(buffer_t* key, buffer_t* value); diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index a8fe02a3157..a5cdaa3b7f1 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -66,9 +66,6 @@ void LeveldbDatabase::commit() { void LeveldbDatabase::close() { LOG(INFO) << "LevelDB: Close"; - if (batch_ && db_) { - this->commit(); - } batch_.reset(); db_.reset(); } diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index 7197a4775dc..08607789bb1 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -14,9 +14,9 @@ void LmdbDatabase::open(const string& filename, Mode mode) { CHECK(NULL == txn_); CHECK_EQ(0, dbi_); - if (mode != ReadOnly) { + if (mode == New) { CHECK_EQ(mkdir(filename.c_str(), 0744), 0) << "mkdir " << filename - << "failed"; + << " failed"; } int retval; @@ -66,18 +66,19 @@ void LmdbDatabase::commit() { CHECK_NOTNULL(txn_); - int retval = mdb_txn_commit(txn_); + int retval; + retval = mdb_txn_commit(txn_); CHECK_EQ(retval, MDB_SUCCESS) << "mdb_txn_commit failed " << mdb_strerror(retval); + + retval = mdb_txn_begin(env_, NULL, 0, &txn_); + CHECK_EQ(retval, MDB_SUCCESS) + << "mdb_txn_begin failed " << mdb_strerror(retval); } void LmdbDatabase::close() { LOG(INFO) << "LMDB: Close"; - if (env_ && dbi_ && txn_) { - this->commit(); - } - if (env_ && dbi_) { mdb_close(env_, dbi_); mdb_env_close(env_); diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index f981af40fdf..11f6fb820e6 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -35,8 +35,10 @@ int main(int argc, char** argv) { BlobProto sum_blob; int count = 0; // load first datum - const Database::buffer_t& first_blob = database->begin()->second; + Database::const_iterator iter = database->begin(); + const Database::buffer_t& first_blob = iter->second; datum.ParseFromArray(first_blob.data(), first_blob.size()); + iter = database->end(); sum_blob.set_num(1); sum_blob.set_channels(datum.channels()); From c7a5d8a4fbb3c6bf17130e75305fb5dabdc273f3 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 7 Oct 2014 22:10:20 -0400 Subject: [PATCH 111/798] data layer test was relying on the autocommit on close db behavior that was recently removed. --- src/caffe/test/test_data_layer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index c17f7295c3c..98ef1b96f24 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -61,6 +61,7 @@ class DataLayerTest : public MultiDeviceTest { reinterpret_cast(value.data())); database->put(&key, &value); } + database->commit(); database->close(); } From b1150c9ad9c6091348618a714ad6d36b715b893f Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Wed, 8 Oct 2014 16:15:23 +0000 Subject: [PATCH 112/798] Updated cifar10 build script to specify db backend. --- examples/cifar10/create_cifar10.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/cifar10/create_cifar10.sh b/examples/cifar10/create_cifar10.sh index dfba7cca48a..b82fd3e3a06 100755 --- a/examples/cifar10/create_cifar10.sh +++ b/examples/cifar10/create_cifar10.sh @@ -3,16 +3,17 @@ EXAMPLE=examples/cifar10 DATA=data/cifar10 +DBTYPE=leveldb -echo "Creating leveldb..." +echo "Creating $DBTYPE..." -rm -rf $EXAMPLE/cifar10_train_leveldb $EXAMPLE/cifar10_test_leveldb +rm -rf $EXAMPLE/cifar10_train_$DBTYPE $EXAMPLE/cifar10_test_$DBTYPE -./build/examples/cifar10/convert_cifar_data.bin $DATA $EXAMPLE +./build/examples/cifar10/convert_cifar_data.bin $DATA $EXAMPLE $DBTYPE echo "Computing image mean..." -./build/tools/compute_image_mean $EXAMPLE/cifar10_train_leveldb \ - $EXAMPLE/mean.binaryproto leveldb +./build/tools/compute_image_mean $EXAMPLE/cifar10_train_$DBTYPE \ + $EXAMPLE/mean.binaryproto $DBTYPE echo "Done." From 5a559f55c38330f462c3e4258450e898deee016e Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Fri, 10 Oct 2014 19:47:50 -0400 Subject: [PATCH 113/798] Switched create_cifar10.sh output from leveldb to lmdb. --- examples/cifar10/create_cifar10.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cifar10/create_cifar10.sh b/examples/cifar10/create_cifar10.sh index b82fd3e3a06..ebfca46de87 100755 --- a/examples/cifar10/create_cifar10.sh +++ b/examples/cifar10/create_cifar10.sh @@ -3,7 +3,7 @@ EXAMPLE=examples/cifar10 DATA=data/cifar10 -DBTYPE=leveldb +DBTYPE=lmdb echo "Creating $DBTYPE..." From a1ea5ba4b2a6e1af9ef360aefd0c8ab777039a5b Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 14:15:17 -0400 Subject: [PATCH 114/798] Updated extract_features to take a leveldb/lmdb config option. --- examples/feature_extraction/readme.md | 2 +- tools/extract_features.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/feature_extraction/readme.md b/examples/feature_extraction/readme.md index c325ed482e5..6c8917e27e1 100644 --- a/examples/feature_extraction/readme.md +++ b/examples/feature_extraction/readme.md @@ -51,7 +51,7 @@ Extract Features Now everything necessary is in place. - ./build/tools/extract_features.bin models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel examples/_temp/imagenet_val.prototxt fc7 examples/_temp/features 10 + ./build/tools/extract_features.bin models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel examples/_temp/imagenet_val.prototxt fc7 examples/_temp/features 10 lmdb The name of feature blob that you extract is `fc7`, which represents the highest level feature of the reference model. We can use any other layer, as well, such as `conv5` or `pool3`. diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 1065d449a42..c4d1a39eb5b 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -32,15 +32,15 @@ int main(int argc, char** argv) { template int feature_extraction_pipeline(int argc, char** argv) { ::google::InitGoogleLogging(argv[0]); - const int num_required_args = 6; + const int num_required_args = 7; if (argc < num_required_args) { LOG(ERROR)<< "This program takes in a trained network and an input data layer, and then" " extract features of the input data produced by the net.\n" "Usage: extract_features pretrained_net_param" " feature_extraction_proto_file extract_feature_blob_name1[,name2,...]" - " save_feature_database_name1[,name2,...] num_mini_batches [CPU/GPU]" - " [DEVICE_ID=0]\n" + " save_feature_database_name1[,name2,...] num_mini_batches db_type" + " [CPU/GPU] [DEVICE_ID=0]\n" "Note: you can extract multiple features in one pass by specifying" " multiple feature blob names and database names seperated by ','." " The names cannot contain white space characters and the number of blobs" @@ -119,16 +119,16 @@ int feature_extraction_pipeline(int argc, char** argv) { << " in the network " << feature_extraction_proto; } + int num_mini_batches = atoi(argv[++arg_pos]); + std::vector > feature_dbs; for (size_t i = 0; i < num_features; ++i) { LOG(INFO)<< "Opening database " << database_names[i]; - shared_ptr database = DatabaseFactory("leveldb"); + shared_ptr database = DatabaseFactory(argv[++arg_pos]); database->open(database_names.at(i), Database::New); feature_dbs.push_back(database); } - int num_mini_batches = atoi(argv[++arg_pos]); - LOG(ERROR)<< "Extacting Features"; Datum datum; From 8fef285e536a67a6b2c72b54734335aeb3069d59 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 14:39:31 -0400 Subject: [PATCH 115/798] Updated Database interface to use custom KV type rather than std::pair. Removed two buffer copies in dereference operation for DB iterators. --- include/caffe/database.hpp | 12 ++++++++---- include/caffe/leveldb_database.hpp | 4 ++-- include/caffe/lmdb_database.hpp | 4 ++-- src/caffe/layers/data_layer.cpp | 4 ++-- src/caffe/leveldb_database.cpp | 14 +++++++++----- src/caffe/lmdb_database.cpp | 13 ++++++++----- tools/compute_image_mean.cpp | 4 ++-- 7 files changed, 33 insertions(+), 22 deletions(-) diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index 23036a8e075..953b58cfa2e 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -21,6 +21,11 @@ class Database { typedef vector buffer_t; + struct KV { + buffer_t key; + buffer_t value; + }; + virtual void open(const string& filename, Mode mode) = 0; virtual void put(buffer_t* key, buffer_t* value) = 0; virtual void commit() = 0; @@ -41,10 +46,9 @@ class Database { class DatabaseState; public: - class iterator : public std::iterator< - std::forward_iterator_tag, pair > { + class iterator : public std::iterator { public: - typedef pair T; + typedef KV T; typedef T value_type; typedef T& reference_type; typedef T* pointer_type; @@ -97,7 +101,7 @@ class Database { virtual bool equal(shared_ptr state1, shared_ptr state2) const = 0; virtual void increment(shared_ptr state) const = 0; - virtual pair& dereference( + virtual KV& dereference( shared_ptr state) const = 0; }; diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index dda669704bd..1c084cb070d 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -32,13 +32,13 @@ class LeveldbDatabase : public Database { iter_(iter) { } shared_ptr iter_; - pair kv_pair_; + KV kv_pair_; }; bool equal(shared_ptr state1, shared_ptr state2) const; void increment(shared_ptr state) const; - pair& dereference(shared_ptr state) const; + Database::KV& dereference(shared_ptr state) const; shared_ptr db_; shared_ptr batch_; diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index 96542227c9a..d72be3d4c66 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -36,13 +36,13 @@ class LmdbDatabase : public Database { cursor_(cursor) { } MDB_cursor* cursor_; - pair kv_pair_; + KV kv_pair_; }; bool equal(shared_ptr state1, shared_ptr state2) const; void increment(shared_ptr state) const; - pair& dereference(shared_ptr state) const; + Database::KV& dereference(shared_ptr state) const; MDB_env *env_; MDB_dbi dbi_; diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 4d36b8ede42..998c00c3561 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -48,7 +48,7 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // Read a data point, and use it to initialize the top blob. CHECK(iter_ != database_->end()); Datum datum; - datum.ParseFromArray(iter_->second.data(), iter_->second.size()); + datum.ParseFromArray(iter_->value.data(), iter_->value.size()); // image int crop_size = this->layer_param_.transform_param().crop_size(); @@ -94,7 +94,7 @@ void DataLayer::InternalThreadEntry() { for (int item_id = 0; item_id < batch_size; ++item_id) { Datum datum; CHECK(iter_ != database_->end()); - datum.ParseFromArray(iter_->second.data(), iter_->second.size()); + datum.ParseFromArray(iter_->value.data(), iter_->value.size()); // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index a5cdaa3b7f1..8084a6c4d8d 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -131,7 +131,7 @@ void LeveldbDatabase::increment(shared_ptr state) const { } } -pair& LeveldbDatabase::dereference( +Database::KV& LeveldbDatabase::dereference( shared_ptr state) const { shared_ptr leveldb_state = boost::dynamic_pointer_cast(state); @@ -144,10 +144,14 @@ pair& LeveldbDatabase::dereference( CHECK(iter->Valid()); - leveldb_state->kv_pair_ = make_pair( - buffer_t(iter->key().data(), iter->key().data() + iter->key().size()), - buffer_t(iter->value().data(), - iter->value().data() + iter->value().size())); + Database::buffer_t temp_key(buffer_t(iter->key().data(), + iter->key().data() + iter->key().size())); + + Database::buffer_t temp_value(buffer_t(iter->value().data(), + iter->value().data() + iter->value().size())); + + leveldb_state->kv_pair_.key.swap(temp_key); + leveldb_state->kv_pair_.value.swap(temp_value); return leveldb_state->kv_pair_; } diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index 08607789bb1..54d67d5442f 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -149,8 +149,7 @@ void LmdbDatabase::increment(shared_ptr state) const { } } -pair& LmdbDatabase::dereference( - shared_ptr state) const { +Database::KV& LmdbDatabase::dereference(shared_ptr state) const { shared_ptr lmdb_state = boost::dynamic_pointer_cast(state); @@ -168,9 +167,13 @@ pair& LmdbDatabase::dereference( char* key_data = reinterpret_cast(mdb_key.mv_data); char* value_data = reinterpret_cast(mdb_val.mv_data); - lmdb_state->kv_pair_ = make_pair( - buffer_t(key_data, key_data + mdb_key.mv_size), - buffer_t(value_data, value_data + mdb_val.mv_size)); + Database::buffer_t temp_key(key_data, key_data + mdb_key.mv_size); + + Database::buffer_t temp_value(value_data, + value_data + mdb_val.mv_size); + + lmdb_state->kv_pair_.key.swap(temp_key); + lmdb_state->kv_pair_.value.swap(temp_value); return lmdb_state->kv_pair_; } diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index 11f6fb820e6..01e16c179b6 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -36,7 +36,7 @@ int main(int argc, char** argv) { int count = 0; // load first datum Database::const_iterator iter = database->begin(); - const Database::buffer_t& first_blob = iter->second; + const Database::buffer_t& first_blob = iter->value; datum.ParseFromArray(first_blob.data(), first_blob.size()); iter = database->end(); @@ -54,7 +54,7 @@ int main(int argc, char** argv) { for (Database::const_iterator iter = database->begin(); iter != database->end(); ++iter) { // just a dummy operation - const Database::buffer_t& blob = iter->second; + const Database::buffer_t& blob = iter->value; datum.ParseFromArray(blob.data(), blob.size()); const std::string& data = datum.data(); size_in_datum = std::max(datum.data().size(), From be2df844221476a2f8ee5c1bb03258eadecac047 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 14:47:04 -0400 Subject: [PATCH 116/798] Added a couple of sanity checks to make sure the datum buffer sizes matched what we expected. --- tools/compute_image_mean.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index 01e16c179b6..aaa324a02b3 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -62,10 +62,12 @@ int main(int argc, char** argv) { CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " << size_in_datum; if (data.size() != 0) { + CHECK_EQ(data.size(), size_in_datum); for (int i = 0; i < size_in_datum; ++i) { sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]); } } else { + CHECK_EQ(datum.float_data_size(), size_in_datum); for (int i = 0; i < size_in_datum; ++i) { sum_blob.set_data(i, sum_blob.data(i) + static_cast(datum.float_data(i))); From c31e4446884262ff3c68e5d2adf7afd5050771e4 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 16:31:17 -0400 Subject: [PATCH 117/798] Added get interface to Database. Added test cases for Database. Fixed a few bugs related to ReadOnly mode in Database in order to pass test cases. --- include/caffe/database.hpp | 1 + include/caffe/leveldb_database.hpp | 2 + include/caffe/lmdb_database.hpp | 5 +- src/caffe/leveldb_database.cpp | 22 ++ src/caffe/lmdb_database.cpp | 44 ++- src/caffe/test/test_database.cpp | 590 +++++++++++++++++++++++++++++ 6 files changed, 658 insertions(+), 6 deletions(-) create mode 100644 src/caffe/test/test_database.cpp diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index 953b58cfa2e..c61ab51f06c 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -28,6 +28,7 @@ class Database { virtual void open(const string& filename, Mode mode) = 0; virtual void put(buffer_t* key, buffer_t* value) = 0; + virtual void get(buffer_t* key, buffer_t* value) = 0; virtual void commit() = 0; virtual void close() = 0; diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index 1c084cb070d..42f73f98f2a 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -16,6 +16,7 @@ class LeveldbDatabase : public Database { public: void open(const string& filename, Mode mode); void put(buffer_t* key, buffer_t* value); + void get(buffer_t* key, buffer_t* value); void commit(); void close(); @@ -42,6 +43,7 @@ class LeveldbDatabase : public Database { shared_ptr db_; shared_ptr batch_; + bool read_only_; }; } // namespace caffe diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index d72be3d4c66..4796b4dc73b 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -20,6 +20,7 @@ class LmdbDatabase : public Database { void open(const string& filename, Mode mode); void put(buffer_t* key, buffer_t* value); + void get(buffer_t* key, buffer_t* value); void commit(); void close(); @@ -44,9 +45,9 @@ class LmdbDatabase : public Database { void increment(shared_ptr state) const; Database::KV& dereference(shared_ptr state) const; - MDB_env *env_; + MDB_env* env_; MDB_dbi dbi_; - MDB_txn *txn_; + MDB_txn* txn_; }; } // namespace caffe diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index 8084a6c4d8d..d2b37e6aa15 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -14,16 +14,19 @@ void LeveldbDatabase::open(const string& filename, Mode mode) { LOG(INFO) << " mode NEW"; options.error_if_exists = true; options.create_if_missing = true; + read_only_ = false; break; case ReadWrite: LOG(INFO) << " mode RW"; options.error_if_exists = false; options.create_if_missing = true; + read_only_ = false; break; case ReadOnly: LOG(INFO) << " mode RO"; options.error_if_exists = false; options.create_if_missing = false; + read_only_ = true; break; default: LOG(FATAL) << "unknown mode " << mode; @@ -45,6 +48,8 @@ void LeveldbDatabase::open(const string& filename, Mode mode) { void LeveldbDatabase::put(buffer_t* key, buffer_t* value) { LOG(INFO) << "LevelDB: Put"; + CHECK(!read_only_); + CHECK_NOTNULL(batch_.get()); leveldb::Slice key_slice(key->data(), key->size()); @@ -53,9 +58,26 @@ void LeveldbDatabase::put(buffer_t* key, buffer_t* value) { batch_->Put(key_slice, value_slice); } +void LeveldbDatabase::get(buffer_t* key, buffer_t* value) { + LOG(INFO) << "LevelDB: Get"; + + leveldb::Slice key_slice(key->data(), key->size()); + + string value_string; + leveldb::Status status = + db_->Get(leveldb::ReadOptions(), key_slice, &value_string); + CHECK(status.ok()) << "leveldb get failed"; + + Database::buffer_t temp_value(value_string.data(), + value_string.data() + value_string.size()); + value->swap(temp_value); +} + void LeveldbDatabase::commit() { LOG(INFO) << "LevelDB: Commit"; + CHECK(!read_only_); + CHECK_NOTNULL(db_.get()); CHECK_NOTNULL(batch_.get()); diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index 54d67d5442f..952e95a62d8 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -14,12 +14,24 @@ void LmdbDatabase::open(const string& filename, Mode mode) { CHECK(NULL == txn_); CHECK_EQ(0, dbi_); - if (mode == New) { - CHECK_EQ(mkdir(filename.c_str(), 0744), 0) << "mkdir " << filename - << " failed"; + int retval; + if (mode != ReadOnly) { + retval = mkdir(filename.c_str(), 0744); + switch (mode) { + case New: + CHECK_EQ(0, retval) << "mkdir " << filename << " failed"; + break; + case ReadWrite: + if (-1 == retval) { + CHECK_EQ(EEXIST, errno) << "mkdir " << filename << " failed (" + << strerror(errno) << ")"; + } + break; + default: + LOG(FATAL) << "Invalid mode " << mode; + } } - int retval; retval = mdb_env_create(&env_); CHECK_EQ(retval, MDB_SUCCESS) << "mdb_env_create failed " << mdb_strerror(retval); @@ -61,6 +73,30 @@ void LmdbDatabase::put(buffer_t* key, buffer_t* value) { << "mdb_put failed " << mdb_strerror(retval); } +void LmdbDatabase::get(buffer_t* key, buffer_t* value) { + LOG(INFO) << "LMDB: Get"; + + MDB_val mdbkey, mdbdata; + mdbkey.mv_data = key->data(); + mdbkey.mv_size = key->size(); + + int retval; + MDB_txn* get_txn; + retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &get_txn); + CHECK_EQ(MDB_SUCCESS, retval) << "mdb_txn_begin failed " + << mdb_strerror(retval); + + retval = mdb_get(get_txn, dbi_, &mdbkey, &mdbdata); + CHECK_EQ(MDB_SUCCESS, retval) << "mdb_get failed " << mdb_strerror(retval); + + mdb_txn_abort(get_txn); + + Database::buffer_t temp_value(reinterpret_cast(mdbdata.mv_data), + reinterpret_cast(mdbdata.mv_data) + mdbdata.mv_size); + + value->swap(temp_value); +} + void LmdbDatabase::commit() { LOG(INFO) << "LMDB: Commit"; diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp new file mode 100644 index 00000000000..dce92d88b5d --- /dev/null +++ b/src/caffe/test/test_database.cpp @@ -0,0 +1,590 @@ +#include +#include + +#include "caffe/util/io.hpp" + +#include "gtest/gtest.h" + +#include "caffe/database_factory.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class DatabaseTest : public MultiDeviceTest { + typedef typename TypeParam::Dtype Dtype; + + protected: + string DBName() { + string filename; + MakeTempDir(&filename); + filename += "/db"; + return filename; + } + + Database::buffer_t TestKey() { + const char* kKey = "hello"; + Database::buffer_t key(kKey, kKey + 5); + return key; + } + + Database::buffer_t TestValue() { + const char* kValue = "world"; + Database::buffer_t value(kValue, kValue + 5); + return value; + } +}; + +TYPED_TEST_CASE(DatabaseTest, TestDtypesAndDevices); + +TYPED_TEST(DatabaseTest, TestNewDoesntExistLevelDBPasses) { + shared_ptr database = DatabaseFactory("leveldb"); + database->open(this->DBName(), Database::New); + database->close(); +} + +TYPED_TEST(DatabaseTest, TestNewExistsFailsLevelDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + database->close(); + + EXPECT_DEATH(database->open(name, Database::New), ""); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyExistsLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + database->close(); + + database->open(name, Database::ReadOnly); + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyDoesntExistFailsLevelDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + EXPECT_DEATH(database->open(name, Database::ReadOnly), ""); +} + +TYPED_TEST(DatabaseTest, TestReadWriteExistsLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + database->close(); + + database->open(name, Database::ReadWrite); + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::ReadWrite); + database->close(); +} + +TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + const int kNumExamples = 4; + for (int i = 0; i < kNumExamples; ++i) { + stringstream ss; + ss << i; + string key = ss.str(); + ss << " here be data"; + string value = ss.str(); + Database::buffer_t key_buf(key.data(), key.data() + key.size()); + Database::buffer_t val_buf(value.data(), value.data() + value.size()); + database->put(&key_buf, &val_buf); + } + database->commit(); + + int count = 0; + for (Database::const_iterator iter = database->begin(); + iter != database->end(); ++iter) { + (void)iter; + ++count; + } + + EXPECT_EQ(kNumExamples, count); +} + +TYPED_TEST(DatabaseTest, TestNewPutLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestNewCommitLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + database->commit(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestNewGetLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + Database::buffer_t new_val; + + database->get(&key, &new_val); + + EXPECT_EQ(val.size(), new_val.size()); + for (size_t i = 0; i < val.size(); ++i) { + EXPECT_EQ(val.at(i), new_val.at(i)); + } + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestNewGetNoCommitLevelDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + Database::buffer_t new_val; + + EXPECT_DEATH(database->get(&key, &new_val), ""); +} + + +TYPED_TEST(DatabaseTest, TestReadWritePutLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::ReadWrite); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadWriteCommitLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::ReadWrite); + + database->commit(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadWriteGetLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + Database::buffer_t new_val; + + database->get(&key, &new_val); + + EXPECT_EQ(val.size(), new_val.size()); + for (size_t i = 0; i < val.size(); ++i) { + EXPECT_EQ(val.at(i), new_val.at(i)); + } + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLevelDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + Database::buffer_t new_val; + + EXPECT_DEATH(database->get(&key, &new_val), ""); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyPutLevelDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + database->close(); + + database->open(name, Database::ReadOnly); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + EXPECT_DEATH(database->put(&key, &val), ""); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyCommitLevelDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + database->close(); + + database->open(name, Database::ReadOnly); + + EXPECT_DEATH(database->commit(), ""); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + database->close(); + + database->open(name, Database::ReadOnly); + + Database::buffer_t new_val; + + database->get(&key, &new_val); + + EXPECT_EQ(val.size(), new_val.size()); + for (size_t i = 0; i < val.size(); ++i) { + EXPECT_EQ(val.at(i), new_val.at(i)); + } +} + +TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLevelDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->close(); + + database->open(name, Database::ReadOnly); + + Database::buffer_t new_val; + + EXPECT_DEATH(database->get(&key, &new_val), ""); +} + +TYPED_TEST(DatabaseTest, TestNewDoesntExistLMDBPasses) { + shared_ptr database = DatabaseFactory("lmdb"); + database->open(this->DBName(), Database::New); + database->close(); +} + +TYPED_TEST(DatabaseTest, TestNewExistsFailsLMDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + database->close(); + + EXPECT_DEATH(database->open(name, Database::New), ""); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyExistsLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + database->close(); + + database->open(name, Database::ReadOnly); + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyDoesntExistFailsLMDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + EXPECT_DEATH(database->open(name, Database::ReadOnly), ""); +} + +TYPED_TEST(DatabaseTest, TestReadWriteExistsLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + database->close(); + + database->open(name, Database::ReadWrite); + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::ReadWrite); + database->close(); +} + +TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + const int kNumExamples = 4; + for (int i = 0; i < kNumExamples; ++i) { + stringstream ss; + ss << i; + string key = ss.str(); + ss << " here be data"; + string value = ss.str(); + Database::buffer_t key_buf(key.data(), key.data() + key.size()); + Database::buffer_t val_buf(value.data(), value.data() + value.size()); + database->put(&key_buf, &val_buf); + } + database->commit(); + + int count = 0; + for (Database::const_iterator iter = database->begin(); + iter != database->end(); ++iter) { + (void)iter; + ++count; + } + + EXPECT_EQ(kNumExamples, count); +} + +TYPED_TEST(DatabaseTest, TestNewPutLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestNewCommitLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + database->commit(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestNewGetLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + Database::buffer_t new_val; + + database->get(&key, &new_val); + + EXPECT_EQ(val.size(), new_val.size()); + for (size_t i = 0; i < val.size(); ++i) { + EXPECT_EQ(val.at(i), new_val.at(i)); + } + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestNewGetNoCommitLMDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + Database::buffer_t new_val; + + EXPECT_DEATH(database->get(&key, &new_val), ""); +} + +TYPED_TEST(DatabaseTest, TestReadWritePutLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::ReadWrite); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadWriteCommitLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::ReadWrite); + + database->commit(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadWriteGetLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + Database::buffer_t new_val; + + database->get(&key, &new_val); + + EXPECT_EQ(val.size(), new_val.size()); + for (size_t i = 0; i < val.size(); ++i) { + EXPECT_EQ(val.at(i), new_val.at(i)); + } + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLMDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + Database::buffer_t new_val; + + EXPECT_DEATH(database->get(&key, &new_val), ""); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyPutLMDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + database->close(); + + database->open(name, Database::ReadOnly); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + EXPECT_DEATH(database->put(&key, &val), ""); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyCommitLMDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + database->close(); + + database->open(name, Database::ReadOnly); + + EXPECT_DEATH(database->commit(), ""); +} + +TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->commit(); + + database->close(); + + database->open(name, Database::ReadOnly); + + Database::buffer_t new_val; + + database->get(&key, &new_val); + + EXPECT_EQ(val.size(), new_val.size()); + for (size_t i = 0; i < val.size(); ++i) { + EXPECT_EQ(val.at(i), new_val.at(i)); + } +} + +TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLMDBFails) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key = this->TestKey(); + Database::buffer_t val = this->TestValue(); + + database->put(&key, &val); + + database->close(); + + database->open(name, Database::ReadOnly); + + Database::buffer_t new_val; + + EXPECT_DEATH(database->get(&key, &new_val), ""); +} + +} // namespace caffe From c86ed418b9e9a89a98de9c5d339a595ac7ebc3c2 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 18:43:44 -0400 Subject: [PATCH 118/798] Added some tests for the Database iterator interface. Updated the post-increment operator so that it forks off a copy of the LevelDB or LMDB iterator/cursor when necessary. Neither of these APIs allow you to directly copy an iterator or cursor, so I create a new iterator and seek to the key that the previous one was currently on. This means the pre-increment operator can be much cheaper than the post-increment operator. --- include/caffe/database.hpp | 15 ++ include/caffe/leveldb_database.hpp | 18 ++- include/caffe/lmdb_database.hpp | 28 +++- src/caffe/leveldb_database.cpp | 4 +- src/caffe/lmdb_database.cpp | 4 +- src/caffe/test/test_database.cpp | 218 +++++++++++++++++++++++++---- 6 files changed, 256 insertions(+), 31 deletions(-) diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index c61ab51f06c..08baf2fea92 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -62,6 +62,20 @@ class Database { state_(state) { } ~iterator() { } + iterator(const iterator& other) + : parent_(other.parent_), + state_(other.state_->clone()) { } + + iterator& operator=(iterator copy) { + copy.swap(*this); + return *this; + } + + void swap(iterator& other) throw() { + std::swap(this->parent_, other.parent_); + std::swap(this->state_, other.state_); + } + bool operator==(const iterator& other) const { return parent_->equal(state_, other.state_); } @@ -97,6 +111,7 @@ class Database { class DatabaseState { public: virtual ~DatabaseState() { } + virtual shared_ptr clone() = 0; }; virtual bool equal(shared_ptr state1, diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index 42f73f98f2a..03bfd38a437 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -28,10 +28,26 @@ class LeveldbDatabase : public Database { protected: class LeveldbState : public Database::DatabaseState { public: - explicit LeveldbState(shared_ptr iter) + explicit LeveldbState(shared_ptr db, + shared_ptr iter) : Database::DatabaseState(), + db_(db), iter_(iter) { } + shared_ptr clone() { + shared_ptr new_iter; + + if (iter_.get()) { + new_iter.reset(db_->NewIterator(leveldb::ReadOptions())); + CHECK(iter_->Valid()); + new_iter->Seek(iter_->key()); + CHECK(new_iter->Valid()); + } + + return shared_ptr(new LeveldbState(db_, new_iter)); + } + + shared_ptr db_; shared_ptr iter_; KV kv_pair_; }; diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index 4796b4dc73b..7b532f8161a 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -32,11 +32,35 @@ class LmdbDatabase : public Database { protected: class LmdbState : public Database::DatabaseState { public: - explicit LmdbState(MDB_cursor* cursor) + explicit LmdbState(MDB_cursor* cursor, MDB_txn* txn, const MDB_dbi* dbi) : Database::DatabaseState(), - cursor_(cursor) { } + cursor_(cursor), + txn_(txn), + dbi_(dbi) { } + + shared_ptr clone() { + MDB_cursor* new_cursor; + + if (cursor_) { + int retval; + retval = mdb_cursor_open(txn_, *dbi_, &new_cursor); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + MDB_val key; + MDB_val val; + retval = mdb_cursor_get(cursor_, &key, &val, MDB_GET_CURRENT); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + retval = mdb_cursor_get(new_cursor, &key, &val, MDB_SET); + CHECK_EQ(MDB_SUCCESS, retval) << mdb_strerror(retval); + } else { + new_cursor = cursor_; + } + + return shared_ptr(new LmdbState(new_cursor, txn_, dbi_)); + } MDB_cursor* cursor_; + MDB_txn* txn_; + const MDB_dbi* dbi_; KV kv_pair_; }; diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index d2b37e6aa15..51d50cce5c0 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -99,13 +99,13 @@ LeveldbDatabase::const_iterator LeveldbDatabase::begin() const { if (!iter->Valid()) { iter.reset(); } - shared_ptr state(new LeveldbState(iter)); + shared_ptr state(new LeveldbState(db_, iter)); return const_iterator(this, state); } LeveldbDatabase::const_iterator LeveldbDatabase::end() const { shared_ptr iter; - shared_ptr state(new LeveldbState(iter)); + shared_ptr state(new LeveldbState(db_, iter)); return const_iterator(this, state); } diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index 952e95a62d8..a546c8c5259 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -134,12 +134,12 @@ LmdbDatabase::const_iterator LmdbDatabase::begin() const { retval = mdb_cursor_get(cursor, &key, &val, MDB_FIRST); CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - shared_ptr state(new LmdbState(cursor)); + shared_ptr state(new LmdbState(cursor, txn_, &dbi_)); return const_iterator(this, state); } LmdbDatabase::const_iterator LmdbDatabase::end() const { - shared_ptr state(new LmdbState(NULL)); + shared_ptr state(new LmdbState(NULL, txn_, &dbi_)); return const_iterator(this, state); } diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp index dce92d88b5d..5d5f4ea79c4 100644 --- a/src/caffe/test/test_database.cpp +++ b/src/caffe/test/test_database.cpp @@ -34,6 +34,32 @@ class DatabaseTest : public MultiDeviceTest { Database::buffer_t value(kValue, kValue + 5); return value; } + + Database::buffer_t TestAltKey() { + const char* kKey = "foo"; + Database::buffer_t key(kKey, kKey + 3); + return key; + } + + Database::buffer_t TestAltValue() { + const char* kValue = "bar"; + Database::buffer_t value(kValue, kValue + 3); + return value; + } + + bool BufferEq(const Database::buffer_t& buf1, + const Database::buffer_t& buf2) { + if (buf1.size() != buf2.size()) { + return false; + } + for (size_t i = 0; i < buf1.size(); ++i) { + if (buf1.at(i) != buf2.at(i)) { + return false; + } + } + + return true; + } }; TYPED_TEST_CASE(DatabaseTest, TestDtypesAndDevices); @@ -114,6 +140,87 @@ TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { EXPECT_EQ(kNumExamples, count); } +TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLevelDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key1 = this->TestAltKey(); + Database::buffer_t value1 = this->TestAltValue(); + + Database::buffer_t key2 = this->TestKey(); + Database::buffer_t value2 = this->TestValue(); + + database->put(&key1, &value1); + database->put(&key2, &value2); + database->commit(); + + Database::const_iterator iter1 = database->begin(); + + EXPECT_FALSE(database->end() == iter1); + + EXPECT_TRUE(this->BufferEq(iter1->key, key1)); + + Database::const_iterator iter2 = ++iter1; + + EXPECT_FALSE(database->end() == iter1); + EXPECT_FALSE(database->end() == iter2); + + EXPECT_TRUE(this->BufferEq(iter2->key, key2)); + + Database::const_iterator iter3 = ++iter2; + + EXPECT_TRUE(database->end() == iter3); + + iter1 = database->end(); + iter2 = database->end(); + iter3 = database->end(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLevelDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + database->open(name, Database::New); + + Database::buffer_t key1 = this->TestAltKey(); + Database::buffer_t value1 = this->TestAltValue(); + + Database::buffer_t key2 = this->TestKey(); + Database::buffer_t value2 = this->TestValue(); + + database->put(&key1, &value1); + database->put(&key2, &value2); + database->commit(); + + Database::const_iterator iter1 = database->begin(); + + EXPECT_FALSE(database->end() == iter1); + + EXPECT_TRUE(this->BufferEq(iter1->key, key1)); + + Database::const_iterator iter2 = iter1++; + + EXPECT_FALSE(database->end() == iter1); + EXPECT_FALSE(database->end() == iter2); + + EXPECT_TRUE(this->BufferEq(iter2->key, key1)); + EXPECT_TRUE(this->BufferEq(iter1->key, key2)); + + Database::const_iterator iter3 = iter1++; + + EXPECT_FALSE(database->end() == iter3); + EXPECT_TRUE(this->BufferEq(iter3->key, key2)); + EXPECT_TRUE(database->end() == iter1); + + iter1 = database->end(); + iter2 = database->end(); + iter3 = database->end(); + + database->close(); +} + TYPED_TEST(DatabaseTest, TestNewPutLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); @@ -155,10 +262,7 @@ TYPED_TEST(DatabaseTest, TestNewGetLevelDBPasses) { database->get(&key, &new_val); - EXPECT_EQ(val.size(), new_val.size()); - for (size_t i = 0; i < val.size(); ++i) { - EXPECT_EQ(val.at(i), new_val.at(i)); - } + EXPECT_TRUE(this->BufferEq(val, new_val)); database->close(); } @@ -220,10 +324,7 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetLevelDBPasses) { database->get(&key, &new_val); - EXPECT_EQ(val.size(), new_val.size()); - for (size_t i = 0; i < val.size(); ++i) { - EXPECT_EQ(val.at(i), new_val.at(i)); - } + EXPECT_TRUE(this->BufferEq(val, new_val)); database->close(); } @@ -288,10 +389,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { database->get(&key, &new_val); - EXPECT_EQ(val.size(), new_val.size()); - for (size_t i = 0; i < val.size(); ++i) { - EXPECT_EQ(val.at(i), new_val.at(i)); - } + EXPECT_TRUE(this->BufferEq(val, new_val)); } TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLevelDBFails) { @@ -389,6 +487,87 @@ TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { EXPECT_EQ(kNumExamples, count); } +TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLMDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key1 = this->TestAltKey(); + Database::buffer_t value1 = this->TestAltValue(); + + Database::buffer_t key2 = this->TestKey(); + Database::buffer_t value2 = this->TestValue(); + + database->put(&key1, &value1); + database->put(&key2, &value2); + database->commit(); + + Database::const_iterator iter1 = database->begin(); + + EXPECT_FALSE(database->end() == iter1); + + EXPECT_TRUE(this->BufferEq(iter1->key, key1)); + + Database::const_iterator iter2 = ++iter1; + + EXPECT_FALSE(database->end() == iter1); + EXPECT_FALSE(database->end() == iter2); + + EXPECT_TRUE(this->BufferEq(iter2->key, key2)); + + Database::const_iterator iter3 = ++iter2; + + EXPECT_TRUE(database->end() == iter3); + + iter1 = database->end(); + iter2 = database->end(); + iter3 = database->end(); + + database->close(); +} + +TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLMDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + database->open(name, Database::New); + + Database::buffer_t key1 = this->TestAltKey(); + Database::buffer_t value1 = this->TestAltValue(); + + Database::buffer_t key2 = this->TestKey(); + Database::buffer_t value2 = this->TestValue(); + + database->put(&key1, &value1); + database->put(&key2, &value2); + database->commit(); + + Database::const_iterator iter1 = database->begin(); + + EXPECT_FALSE(database->end() == iter1); + + EXPECT_TRUE(this->BufferEq(iter1->key, key1)); + + Database::const_iterator iter2 = iter1++; + + EXPECT_FALSE(database->end() == iter1); + EXPECT_FALSE(database->end() == iter2); + + EXPECT_TRUE(this->BufferEq(iter2->key, key1)); + EXPECT_TRUE(this->BufferEq(iter1->key, key2)); + + Database::const_iterator iter3 = iter1++; + + EXPECT_FALSE(database->end() == iter3); + EXPECT_TRUE(this->BufferEq(iter3->key, key2)); + EXPECT_TRUE(database->end() == iter1); + + iter1 = database->end(); + iter2 = database->end(); + iter3 = database->end(); + + database->close(); +} + TYPED_TEST(DatabaseTest, TestNewPutLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); @@ -430,10 +609,7 @@ TYPED_TEST(DatabaseTest, TestNewGetLMDBPasses) { database->get(&key, &new_val); - EXPECT_EQ(val.size(), new_val.size()); - for (size_t i = 0; i < val.size(); ++i) { - EXPECT_EQ(val.at(i), new_val.at(i)); - } + EXPECT_TRUE(this->BufferEq(val, new_val)); database->close(); } @@ -494,10 +670,7 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetLMDBPasses) { database->get(&key, &new_val); - EXPECT_EQ(val.size(), new_val.size()); - for (size_t i = 0; i < val.size(); ++i) { - EXPECT_EQ(val.at(i), new_val.at(i)); - } + EXPECT_TRUE(this->BufferEq(val, new_val)); database->close(); } @@ -562,10 +735,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { database->get(&key, &new_val); - EXPECT_EQ(val.size(), new_val.size()); - for (size_t i = 0; i < val.size(); ++i) { - EXPECT_EQ(val.at(i), new_val.at(i)); - } + EXPECT_TRUE(this->BufferEq(val, new_val)); } TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLMDBFails) { From 73b16e43e4376207ddc30b5772ed4a3f5dba88d9 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 20:20:31 -0400 Subject: [PATCH 119/798] Updated Database interface so that rather than CHECKing for certain conditions inside open, put, get, and commit, these functions return a bool indicating whether or not the operation was successful or a failure. This means the caller is now responsible for error checking. --- examples/cifar10/convert_cifar_data.cpp | 16 +- include/caffe/database.hpp | 8 +- include/caffe/leveldb_database.hpp | 8 +- include/caffe/lmdb_database.hpp | 8 +- src/caffe/layers/data_layer.cpp | 5 +- src/caffe/leveldb_database.cpp | 43 ++++- src/caffe/lmdb_database.cpp | 88 ++++++--- src/caffe/test/test_data_layer.cpp | 6 +- src/caffe/test/test_database.cpp | 236 ++++++++++++------------ tools/compute_image_mean.cpp | 2 +- tools/convert_imageset.cpp | 8 +- tools/extract_features.cpp | 8 +- 12 files changed, 249 insertions(+), 187 deletions(-) diff --git a/examples/cifar10/convert_cifar_data.cpp b/examples/cifar10/convert_cifar_data.cpp index c4930878405..b29e4121bf5 100644 --- a/examples/cifar10/convert_cifar_data.cpp +++ b/examples/cifar10/convert_cifar_data.cpp @@ -38,8 +38,8 @@ void read_image(std::ifstream* file, int* label, char* buffer) { void convert_dataset(const string& input_folder, const string& output_folder, const string& db_type) { shared_ptr train_database = DatabaseFactory(db_type); - train_database->open(output_folder + "/cifar10_train_" + db_type, - Database::New); + CHECK(train_database->open(output_folder + "/cifar10_train_" + db_type, + Database::New)); // Data buffer int label; char str_buffer[kCIFARImageNBytes]; @@ -66,16 +66,16 @@ void convert_dataset(const string& input_folder, const string& output_folder, int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", fileid * kCIFARBatchSize + itemid); Database::buffer_t key(str_buffer, str_buffer + length); - train_database->put(&key, &value); + CHECK(train_database->put(&key, &value)); } } - train_database->commit(); + CHECK(train_database->commit()); train_database->close(); LOG(INFO) << "Writing Testing data"; shared_ptr test_database = DatabaseFactory(db_type); - test_database->open(output_folder + "/cifar10_test_" + db_type, - Database::New); + CHECK(test_database->open(output_folder + "/cifar10_test_" + db_type, + Database::New)); // Open files std::ifstream data_file((input_folder + "/test_batch.bin").c_str(), std::ios::in | std::ios::binary); @@ -89,9 +89,9 @@ void convert_dataset(const string& input_folder, const string& output_folder, reinterpret_cast(value.data())); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); Database::buffer_t key(str_buffer, str_buffer + length); - test_database->put(&key, &value); + CHECK(test_database->put(&key, &value)); } - test_database->commit(); + CHECK(test_database->commit()); test_database->close(); } diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index 08baf2fea92..148b1ed7f38 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -26,10 +26,10 @@ class Database { buffer_t value; }; - virtual void open(const string& filename, Mode mode) = 0; - virtual void put(buffer_t* key, buffer_t* value) = 0; - virtual void get(buffer_t* key, buffer_t* value) = 0; - virtual void commit() = 0; + virtual bool open(const string& filename, Mode mode) = 0; + virtual bool put(buffer_t* key, buffer_t* value) = 0; + virtual bool get(buffer_t* key, buffer_t* value) = 0; + virtual bool commit() = 0; virtual void close() = 0; Database() { } diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index 03bfd38a437..64bfa7cebee 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -14,10 +14,10 @@ namespace caffe { class LeveldbDatabase : public Database { public: - void open(const string& filename, Mode mode); - void put(buffer_t* key, buffer_t* value); - void get(buffer_t* key, buffer_t* value); - void commit(); + bool open(const string& filename, Mode mode); + bool put(buffer_t* key, buffer_t* value); + bool get(buffer_t* key, buffer_t* value); + bool commit(); void close(); const_iterator begin() const; diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index 7b532f8161a..69e3ce0f03d 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -18,10 +18,10 @@ class LmdbDatabase : public Database { dbi_(0), txn_(NULL) { } - void open(const string& filename, Mode mode); - void put(buffer_t* key, buffer_t* value); - void get(buffer_t* key, buffer_t* value); - void commit(); + bool open(const string& filename, Mode mode); + bool put(buffer_t* key, buffer_t* value); + bool get(buffer_t* key, buffer_t* value); + bool commit(); void close(); const_iterator begin() const; diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 998c00c3561..dcba10fabec 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -30,8 +30,9 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, const vector*>& top) { // Initialize DB database_ = DatabaseFactory(this->layer_param_.data_param().backend()); - LOG(INFO) << "Opening database " << this->layer_param_.data_param().source(); - database_->open(this->layer_param_.data_param().source(), Database::ReadOnly); + const string& source = this->layer_param_.data_param().source(); + LOG(INFO) << "Opening database " << source; + CHECK(database_->open(source, Database::ReadOnly)); iter_ = database_->begin(); // Check if we would need to randomly skip a few data points diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index 51d50cce5c0..d7506edf74e 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -5,7 +5,7 @@ namespace caffe { -void LeveldbDatabase::open(const string& filename, Mode mode) { +bool LeveldbDatabase::open(const string& filename, Mode mode) { LOG(INFO) << "LevelDB: Open " << filename; leveldb::Options options; @@ -40,15 +40,24 @@ void LeveldbDatabase::open(const string& filename, Mode mode) { leveldb::Status status = leveldb::DB::Open( options, filename, &db); db_.reset(db); - CHECK(status.ok()) << "Failed to open leveldb " << filename - << ". Is it already existing?"; + + if (!status.ok()) { + LOG(ERROR) << "Failed to open leveldb " << filename + << ". Is it already existing?"; + return false; + } + batch_.reset(new leveldb::WriteBatch()); + return true; } -void LeveldbDatabase::put(buffer_t* key, buffer_t* value) { +bool LeveldbDatabase::put(buffer_t* key, buffer_t* value) { LOG(INFO) << "LevelDB: Put"; - CHECK(!read_only_); + if (read_only_) { + LOG(ERROR) << "put can not be used on a database in ReadOnly mode"; + return false; + } CHECK_NOTNULL(batch_.get()); @@ -56,9 +65,11 @@ void LeveldbDatabase::put(buffer_t* key, buffer_t* value) { leveldb::Slice value_slice(value->data(), value->size()); batch_->Put(key_slice, value_slice); + + return true; } -void LeveldbDatabase::get(buffer_t* key, buffer_t* value) { +bool LeveldbDatabase::get(buffer_t* key, buffer_t* value) { LOG(INFO) << "LevelDB: Get"; leveldb::Slice key_slice(key->data(), key->size()); @@ -66,23 +77,35 @@ void LeveldbDatabase::get(buffer_t* key, buffer_t* value) { string value_string; leveldb::Status status = db_->Get(leveldb::ReadOptions(), key_slice, &value_string); - CHECK(status.ok()) << "leveldb get failed"; + + if (!status.ok()) { + LOG(ERROR) << "leveldb get failed"; + return false; + } Database::buffer_t temp_value(value_string.data(), value_string.data() + value_string.size()); value->swap(temp_value); + + return true; } -void LeveldbDatabase::commit() { +bool LeveldbDatabase::commit() { LOG(INFO) << "LevelDB: Commit"; - CHECK(!read_only_); + if (read_only_) { + LOG(ERROR) << "commit can not be used on a database in ReadOnly mode"; + return false; + } CHECK_NOTNULL(db_.get()); CHECK_NOTNULL(batch_.get()); - db_->Write(leveldb::WriteOptions(), batch_.get()); + leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch_.get()); + batch_.reset(new leveldb::WriteBatch()); + + return status.ok(); } void LeveldbDatabase::close() { diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index a546c8c5259..d71513a55ee 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -7,7 +7,7 @@ namespace caffe { -void LmdbDatabase::open(const string& filename, Mode mode) { +bool LmdbDatabase::open(const string& filename, Mode mode) { LOG(INFO) << "LMDB: Open " << filename; CHECK(NULL == env_); @@ -19,12 +19,16 @@ void LmdbDatabase::open(const string& filename, Mode mode) { retval = mkdir(filename.c_str(), 0744); switch (mode) { case New: - CHECK_EQ(0, retval) << "mkdir " << filename << " failed"; + if (0 != retval) { + LOG(ERROR) << "mkdir " << filename << " failed"; + return false; + } break; case ReadWrite: - if (-1 == retval) { - CHECK_EQ(EEXIST, errno) << "mkdir " << filename << " failed (" + if (-1 == retval && EEXIST != errno) { + LOG(ERROR) << "mkdir " << filename << " failed (" << strerror(errno) << ")"; + return false; } break; default: @@ -33,11 +37,17 @@ void LmdbDatabase::open(const string& filename, Mode mode) { } retval = mdb_env_create(&env_); - CHECK_EQ(retval, MDB_SUCCESS) << "mdb_env_create failed " - << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_env_create failed " + << mdb_strerror(retval); + return false; + } + retval = mdb_env_set_mapsize(env_, 1099511627776); - CHECK_EQ(retval, MDB_SUCCESS) // 1TB - << "mdb_env_set_mapsize failed " << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_env_set_mapsize failed " << mdb_strerror(retval); + return false; + } int flag1 = 0; int flag2 = 0; @@ -47,16 +57,27 @@ void LmdbDatabase::open(const string& filename, Mode mode) { } retval = mdb_env_open(env_, filename.c_str(), flag1, 0664); - CHECK_EQ(retval, MDB_SUCCESS) - << "mdb_env_open failed " << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_env_open failed " << mdb_strerror(retval); + return false; + } + retval = mdb_txn_begin(env_, NULL, flag2, &txn_); - CHECK_EQ(retval, MDB_SUCCESS) - << "mdb_txn_begin failed " << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); + return false; + } + retval = mdb_open(txn_, NULL, 0, &dbi_); - CHECK_EQ(retval, MDB_SUCCESS) << "mdb_open failed" << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_open failed" << mdb_strerror(retval); + return false; + } + + return true; } -void LmdbDatabase::put(buffer_t* key, buffer_t* value) { +bool LmdbDatabase::put(buffer_t* key, buffer_t* value) { LOG(INFO) << "LMDB: Put"; MDB_val mdbkey, mdbdata; @@ -69,11 +90,15 @@ void LmdbDatabase::put(buffer_t* key, buffer_t* value) { CHECK_NE(0, dbi_); int retval = mdb_put(txn_, dbi_, &mdbkey, &mdbdata, 0); - CHECK_EQ(retval, MDB_SUCCESS) - << "mdb_put failed " << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_put failed " << mdb_strerror(retval); + return false; + } + + return true; } -void LmdbDatabase::get(buffer_t* key, buffer_t* value) { +bool LmdbDatabase::get(buffer_t* key, buffer_t* value) { LOG(INFO) << "LMDB: Get"; MDB_val mdbkey, mdbdata; @@ -83,11 +108,16 @@ void LmdbDatabase::get(buffer_t* key, buffer_t* value) { int retval; MDB_txn* get_txn; retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &get_txn); - CHECK_EQ(MDB_SUCCESS, retval) << "mdb_txn_begin failed " - << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); + return false; + } retval = mdb_get(get_txn, dbi_, &mdbkey, &mdbdata); - CHECK_EQ(MDB_SUCCESS, retval) << "mdb_get failed " << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_get failed " << mdb_strerror(retval); + return false; + } mdb_txn_abort(get_txn); @@ -95,21 +125,29 @@ void LmdbDatabase::get(buffer_t* key, buffer_t* value) { reinterpret_cast(mdbdata.mv_data) + mdbdata.mv_size); value->swap(temp_value); + + return true; } -void LmdbDatabase::commit() { +bool LmdbDatabase::commit() { LOG(INFO) << "LMDB: Commit"; CHECK_NOTNULL(txn_); int retval; retval = mdb_txn_commit(txn_); - CHECK_EQ(retval, MDB_SUCCESS) << "mdb_txn_commit failed " - << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_txn_commit failed " << mdb_strerror(retval); + return false; + } retval = mdb_txn_begin(env_, NULL, 0, &txn_); - CHECK_EQ(retval, MDB_SUCCESS) - << "mdb_txn_begin failed " << mdb_strerror(retval); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); + return false; + } + + return true; } void LmdbDatabase::close() { diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index 98ef1b96f24..cc9ad20487c 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -40,7 +40,7 @@ class DataLayerTest : public MultiDeviceTest { backend_ = backend; LOG(INFO) << "Using temporary database " << *filename_; shared_ptr database = DatabaseFactory(backend_); - database->open(*filename_, Database::New); + CHECK(database->open(*filename_, Database::New)); for (int i = 0; i < 5; ++i) { Datum datum; datum.set_label(i); @@ -59,9 +59,9 @@ class DataLayerTest : public MultiDeviceTest { Database::buffer_t value(datum.ByteSize()); datum.SerializeWithCachedSizesToArray( reinterpret_cast(value.data())); - database->put(&key, &value); + CHECK(database->put(&key, &value)); } - database->commit(); + CHECK(database->commit()); database->close(); } diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp index 5d5f4ea79c4..f65865014fa 100644 --- a/src/caffe/test/test_database.cpp +++ b/src/caffe/test/test_database.cpp @@ -66,56 +66,56 @@ TYPED_TEST_CASE(DatabaseTest, TestDtypesAndDevices); TYPED_TEST(DatabaseTest, TestNewDoesntExistLevelDBPasses) { shared_ptr database = DatabaseFactory("leveldb"); - database->open(this->DBName(), Database::New); + EXPECT_TRUE(database->open(this->DBName(), Database::New)); database->close(); } TYPED_TEST(DatabaseTest, TestNewExistsFailsLevelDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - EXPECT_DEATH(database->open(name, Database::New), ""); + EXPECT_FALSE(database->open(name, Database::New)); } TYPED_TEST(DatabaseTest, TestReadOnlyExistsLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); database->close(); } TYPED_TEST(DatabaseTest, TestReadOnlyDoesntExistFailsLevelDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_DEATH(database->open(name, Database::ReadOnly), ""); + EXPECT_FALSE(database->open(name, Database::ReadOnly)); } TYPED_TEST(DatabaseTest, TestReadWriteExistsLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - database->open(name, Database::ReadWrite); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); database->close(); } TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::ReadWrite); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); database->close(); } TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); const int kNumExamples = 4; for (int i = 0; i < kNumExamples; ++i) { @@ -126,9 +126,9 @@ TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { string value = ss.str(); Database::buffer_t key_buf(key.data(), key.data() + key.size()); Database::buffer_t val_buf(value.data(), value.data() + value.size()); - database->put(&key_buf, &val_buf); + EXPECT_TRUE(database->put(&key_buf, &val_buf)); } - database->commit(); + EXPECT_TRUE(database->commit()); int count = 0; for (Database::const_iterator iter = database->begin(); @@ -143,7 +143,7 @@ TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLevelDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key1 = this->TestAltKey(); Database::buffer_t value1 = this->TestAltValue(); @@ -151,9 +151,9 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLevelDB) { Database::buffer_t key2 = this->TestKey(); Database::buffer_t value2 = this->TestValue(); - database->put(&key1, &value1); - database->put(&key2, &value2); - database->commit(); + EXPECT_TRUE(database->put(&key1, &value1)); + EXPECT_TRUE(database->put(&key2, &value2)); + EXPECT_TRUE(database->commit()); Database::const_iterator iter1 = database->begin(); @@ -182,7 +182,7 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLevelDB) { TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLevelDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key1 = this->TestAltKey(); Database::buffer_t value1 = this->TestAltValue(); @@ -190,9 +190,9 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLevelDB) { Database::buffer_t key2 = this->TestKey(); Database::buffer_t value2 = this->TestValue(); - database->put(&key1, &value1); - database->put(&key2, &value2); - database->commit(); + EXPECT_TRUE(database->put(&key1, &value1)); + EXPECT_TRUE(database->put(&key2, &value2)); + EXPECT_TRUE(database->commit()); Database::const_iterator iter1 = database->begin(); @@ -224,14 +224,14 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLevelDB) { TYPED_TEST(DatabaseTest, TestNewPutLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); } @@ -239,9 +239,9 @@ TYPED_TEST(DatabaseTest, TestNewPutLevelDBPasses) { TYPED_TEST(DatabaseTest, TestNewCommitLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); } @@ -249,18 +249,18 @@ TYPED_TEST(DatabaseTest, TestNewCommitLevelDBPasses) { TYPED_TEST(DatabaseTest, TestNewGetLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); Database::buffer_t new_val; - database->get(&key, &new_val); + EXPECT_TRUE(database->get(&key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); @@ -270,30 +270,30 @@ TYPED_TEST(DatabaseTest, TestNewGetLevelDBPasses) { TYPED_TEST(DatabaseTest, TestNewGetNoCommitLevelDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); Database::buffer_t new_val; - EXPECT_DEATH(database->get(&key, &new_val), ""); + EXPECT_FALSE(database->get(&key, &new_val)); } TYPED_TEST(DatabaseTest, TestReadWritePutLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::ReadWrite); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); } @@ -301,9 +301,9 @@ TYPED_TEST(DatabaseTest, TestReadWritePutLevelDBPasses) { TYPED_TEST(DatabaseTest, TestReadWriteCommitLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::ReadWrite); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); } @@ -311,18 +311,18 @@ TYPED_TEST(DatabaseTest, TestReadWriteCommitLevelDBPasses) { TYPED_TEST(DatabaseTest, TestReadWriteGetLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); Database::buffer_t new_val; - database->get(&key, &new_val); + EXPECT_TRUE(database->get(&key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); @@ -332,62 +332,62 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetLevelDBPasses) { TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLevelDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); Database::buffer_t new_val; - EXPECT_DEATH(database->get(&key, &new_val), ""); + EXPECT_FALSE(database->get(&key, &new_val)); } TYPED_TEST(DatabaseTest, TestReadOnlyPutLevelDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_DEATH(database->put(&key, &val), ""); + EXPECT_FALSE(database->put(&key, &val)); } TYPED_TEST(DatabaseTest, TestReadOnlyCommitLevelDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); - EXPECT_DEATH(database->commit(), ""); + EXPECT_FALSE(database->commit()); } TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); Database::buffer_t new_val; - database->get(&key, &new_val); + EXPECT_TRUE(database->get(&key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); } @@ -395,74 +395,74 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLevelDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); Database::buffer_t new_val; - EXPECT_DEATH(database->get(&key, &new_val), ""); + EXPECT_FALSE(database->get(&key, &new_val)); } TYPED_TEST(DatabaseTest, TestNewDoesntExistLMDBPasses) { shared_ptr database = DatabaseFactory("lmdb"); - database->open(this->DBName(), Database::New); + EXPECT_TRUE(database->open(this->DBName(), Database::New)); database->close(); } TYPED_TEST(DatabaseTest, TestNewExistsFailsLMDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - EXPECT_DEATH(database->open(name, Database::New), ""); + EXPECT_FALSE(database->open(name, Database::New)); } TYPED_TEST(DatabaseTest, TestReadOnlyExistsLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); database->close(); } TYPED_TEST(DatabaseTest, TestReadOnlyDoesntExistFailsLMDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_DEATH(database->open(name, Database::ReadOnly), ""); + EXPECT_FALSE(database->open(name, Database::ReadOnly)); } TYPED_TEST(DatabaseTest, TestReadWriteExistsLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - database->open(name, Database::ReadWrite); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); database->close(); } TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::ReadWrite); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); database->close(); } TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); const int kNumExamples = 4; for (int i = 0; i < kNumExamples; ++i) { @@ -473,9 +473,9 @@ TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { string value = ss.str(); Database::buffer_t key_buf(key.data(), key.data() + key.size()); Database::buffer_t val_buf(value.data(), value.data() + value.size()); - database->put(&key_buf, &val_buf); + EXPECT_TRUE(database->put(&key_buf, &val_buf)); } - database->commit(); + EXPECT_TRUE(database->commit()); int count = 0; for (Database::const_iterator iter = database->begin(); @@ -490,7 +490,7 @@ TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLMDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key1 = this->TestAltKey(); Database::buffer_t value1 = this->TestAltValue(); @@ -498,9 +498,9 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLMDB) { Database::buffer_t key2 = this->TestKey(); Database::buffer_t value2 = this->TestValue(); - database->put(&key1, &value1); - database->put(&key2, &value2); - database->commit(); + EXPECT_TRUE(database->put(&key1, &value1)); + EXPECT_TRUE(database->put(&key2, &value2)); + EXPECT_TRUE(database->commit()); Database::const_iterator iter1 = database->begin(); @@ -529,7 +529,7 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLMDB) { TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLMDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key1 = this->TestAltKey(); Database::buffer_t value1 = this->TestAltValue(); @@ -537,9 +537,9 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLMDB) { Database::buffer_t key2 = this->TestKey(); Database::buffer_t value2 = this->TestValue(); - database->put(&key1, &value1); - database->put(&key2, &value2); - database->commit(); + EXPECT_TRUE(database->put(&key1, &value1)); + EXPECT_TRUE(database->put(&key2, &value2)); + EXPECT_TRUE(database->commit()); Database::const_iterator iter1 = database->begin(); @@ -571,14 +571,14 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLMDB) { TYPED_TEST(DatabaseTest, TestNewPutLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); } @@ -586,9 +586,9 @@ TYPED_TEST(DatabaseTest, TestNewPutLMDBPasses) { TYPED_TEST(DatabaseTest, TestNewCommitLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); } @@ -596,18 +596,18 @@ TYPED_TEST(DatabaseTest, TestNewCommitLMDBPasses) { TYPED_TEST(DatabaseTest, TestNewGetLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); Database::buffer_t new_val; - database->get(&key, &new_val); + EXPECT_TRUE(database->get(&key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); @@ -617,29 +617,29 @@ TYPED_TEST(DatabaseTest, TestNewGetLMDBPasses) { TYPED_TEST(DatabaseTest, TestNewGetNoCommitLMDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); Database::buffer_t new_val; - EXPECT_DEATH(database->get(&key, &new_val), ""); + EXPECT_FALSE(database->get(&key, &new_val)); } TYPED_TEST(DatabaseTest, TestReadWritePutLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::ReadWrite); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); } @@ -647,9 +647,9 @@ TYPED_TEST(DatabaseTest, TestReadWritePutLMDBPasses) { TYPED_TEST(DatabaseTest, TestReadWriteCommitLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::ReadWrite); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); } @@ -657,18 +657,18 @@ TYPED_TEST(DatabaseTest, TestReadWriteCommitLMDBPasses) { TYPED_TEST(DatabaseTest, TestReadWriteGetLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); Database::buffer_t new_val; - database->get(&key, &new_val); + EXPECT_TRUE(database->get(&key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); @@ -678,62 +678,62 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetLMDBPasses) { TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLMDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); Database::buffer_t new_val; - EXPECT_DEATH(database->get(&key, &new_val), ""); + EXPECT_FALSE(database->get(&key, &new_val)); } TYPED_TEST(DatabaseTest, TestReadOnlyPutLMDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_DEATH(database->put(&key, &val), ""); + EXPECT_FALSE(database->put(&key, &val)); } TYPED_TEST(DatabaseTest, TestReadOnlyCommitLMDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); - EXPECT_DEATH(database->commit(), ""); + EXPECT_FALSE(database->commit()); } TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); - database->commit(); + EXPECT_TRUE(database->commit()); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); Database::buffer_t new_val; - database->get(&key, &new_val); + EXPECT_TRUE(database->get(&key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); } @@ -741,20 +741,20 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLMDBFails) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); - database->open(name, Database::New); + EXPECT_TRUE(database->open(name, Database::New)); Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - database->put(&key, &val); + EXPECT_TRUE(database->put(&key, &val)); database->close(); - database->open(name, Database::ReadOnly); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); Database::buffer_t new_val; - EXPECT_DEATH(database->get(&key, &new_val), ""); + EXPECT_FALSE(database->get(&key, &new_val)); } } // namespace caffe diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index aaa324a02b3..b973c5277ad 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -29,7 +29,7 @@ int main(int argc, char** argv) { caffe::shared_ptr database = caffe::DatabaseFactory(db_backend); // Open db - database->open(argv[1], Database::ReadOnly); + CHECK(database->open(argv[1], Database::ReadOnly)); Datum datum; BlobProto sum_blob; diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 19c87e53ff0..3345c9c7e26 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -81,7 +81,7 @@ int main(int argc, char** argv) { shared_ptr database = DatabaseFactory(db_backend); // Open db - database->open(db_path, Database::New); + CHECK(database->open(db_path, Database::New)); // Storing to db std::string root_folder(argv[1]); @@ -116,17 +116,17 @@ int main(int argc, char** argv) { Database::buffer_t keystr(key_cstr, key_cstr + length); // Put in db - database->put(&keystr, &value); + CHECK(database->put(&keystr, &value)); if (++count % 1000 == 0) { // Commit txn - database->commit(); + CHECK(database->commit()); LOG(ERROR) << "Processed " << count << " files."; } } // write the last batch if (count % 1000 != 0) { - database->commit(); + CHECK(database->commit()); LOG(ERROR) << "Processed " << count << " files."; } database->close(); diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index c4d1a39eb5b..1560ef60a7c 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -125,7 +125,7 @@ int feature_extraction_pipeline(int argc, char** argv) { for (size_t i = 0; i < num_features; ++i) { LOG(INFO)<< "Opening database " << database_names[i]; shared_ptr database = DatabaseFactory(argv[++arg_pos]); - database->open(database_names.at(i), Database::New); + CHECK(database->open(database_names.at(i), Database::New)); feature_dbs.push_back(database); } @@ -161,10 +161,10 @@ int feature_extraction_pipeline(int argc, char** argv) { int length = snprintf(key_str, kMaxKeyStrLength, "%d", image_indices[i]); Database::buffer_t key(key_str, key_str + length); - feature_dbs.at(i)->put(&key, &value); + CHECK(feature_dbs.at(i)->put(&key, &value)); ++image_indices[i]; if (image_indices[i] % 1000 == 0) { - feature_dbs.at(i)->commit(); + CHECK(feature_dbs.at(i)->commit()); LOG(ERROR)<< "Extracted features of " << image_indices[i] << " query images for feature blob " << blob_names[i]; } @@ -174,7 +174,7 @@ int feature_extraction_pipeline(int argc, char** argv) { // write the last batch for (int i = 0; i < num_features; ++i) { if (image_indices[i] % 1000 != 0) { - feature_dbs.at(i)->commit(); + CHECK(feature_dbs.at(i)->commit()); } LOG(ERROR)<< "Extracted features of " << image_indices[i] << " query images for feature blob " << blob_names[i]; From e0b572dd1a63d5dda000ee4cc803be04e51597a1 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 20:30:29 -0400 Subject: [PATCH 120/798] Updated Database interface to take key and value by const reference for put and key by const reference for put. Additional copies are made for get and put in the LMDB implementation. --- examples/cifar10/convert_cifar_data.cpp | 4 +- include/caffe/database.hpp | 4 +- include/caffe/leveldb_database.hpp | 4 +- include/caffe/lmdb_database.hpp | 4 +- src/caffe/leveldb_database.cpp | 10 ++-- src/caffe/lmdb_database.cpp | 22 ++++--- src/caffe/test/test_data_layer.cpp | 2 +- src/caffe/test/test_database.cpp | 80 ++++++++++++------------- tools/convert_imageset.cpp | 2 +- tools/extract_features.cpp | 2 +- 10 files changed, 70 insertions(+), 64 deletions(-) diff --git a/examples/cifar10/convert_cifar_data.cpp b/examples/cifar10/convert_cifar_data.cpp index b29e4121bf5..af845eadfb6 100644 --- a/examples/cifar10/convert_cifar_data.cpp +++ b/examples/cifar10/convert_cifar_data.cpp @@ -66,7 +66,7 @@ void convert_dataset(const string& input_folder, const string& output_folder, int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", fileid * kCIFARBatchSize + itemid); Database::buffer_t key(str_buffer, str_buffer + length); - CHECK(train_database->put(&key, &value)); + CHECK(train_database->put(key, value)); } } CHECK(train_database->commit()); @@ -89,7 +89,7 @@ void convert_dataset(const string& input_folder, const string& output_folder, reinterpret_cast(value.data())); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); Database::buffer_t key(str_buffer, str_buffer + length); - CHECK(test_database->put(&key, &value)); + CHECK(test_database->put(key, value)); } CHECK(test_database->commit()); test_database->close(); diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index 148b1ed7f38..3f3970d77a7 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -27,8 +27,8 @@ class Database { }; virtual bool open(const string& filename, Mode mode) = 0; - virtual bool put(buffer_t* key, buffer_t* value) = 0; - virtual bool get(buffer_t* key, buffer_t* value) = 0; + virtual bool put(const buffer_t& key, const buffer_t& value) = 0; + virtual bool get(const buffer_t& key, buffer_t* value) = 0; virtual bool commit() = 0; virtual void close() = 0; diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index 64bfa7cebee..e2558ff477f 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -15,8 +15,8 @@ namespace caffe { class LeveldbDatabase : public Database { public: bool open(const string& filename, Mode mode); - bool put(buffer_t* key, buffer_t* value); - bool get(buffer_t* key, buffer_t* value); + bool put(const buffer_t& key, const buffer_t& value); + bool get(const buffer_t& key, buffer_t* value); bool commit(); void close(); diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index 69e3ce0f03d..4a0f3183bd5 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -19,8 +19,8 @@ class LmdbDatabase : public Database { txn_(NULL) { } bool open(const string& filename, Mode mode); - bool put(buffer_t* key, buffer_t* value); - bool get(buffer_t* key, buffer_t* value); + bool put(const buffer_t& key, const buffer_t& value); + bool get(const buffer_t& key, buffer_t* value); bool commit(); void close(); diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index d7506edf74e..c09112f668b 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -51,7 +51,7 @@ bool LeveldbDatabase::open(const string& filename, Mode mode) { return true; } -bool LeveldbDatabase::put(buffer_t* key, buffer_t* value) { +bool LeveldbDatabase::put(const buffer_t& key, const buffer_t& value) { LOG(INFO) << "LevelDB: Put"; if (read_only_) { @@ -61,18 +61,18 @@ bool LeveldbDatabase::put(buffer_t* key, buffer_t* value) { CHECK_NOTNULL(batch_.get()); - leveldb::Slice key_slice(key->data(), key->size()); - leveldb::Slice value_slice(value->data(), value->size()); + leveldb::Slice key_slice(key.data(), key.size()); + leveldb::Slice value_slice(value.data(), value.size()); batch_->Put(key_slice, value_slice); return true; } -bool LeveldbDatabase::get(buffer_t* key, buffer_t* value) { +bool LeveldbDatabase::get(const buffer_t& key, buffer_t* value) { LOG(INFO) << "LevelDB: Get"; - leveldb::Slice key_slice(key->data(), key->size()); + leveldb::Slice key_slice(key.data(), key.size()); string value_string; leveldb::Status status = diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index d71513a55ee..2cb699b4234 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -77,14 +77,18 @@ bool LmdbDatabase::open(const string& filename, Mode mode) { return true; } -bool LmdbDatabase::put(buffer_t* key, buffer_t* value) { +bool LmdbDatabase::put(const buffer_t& key, const buffer_t& value) { LOG(INFO) << "LMDB: Put"; + // MDB_val::mv_size is not const, so we need to make a local copy. + buffer_t local_key = key; + buffer_t local_value = value; + MDB_val mdbkey, mdbdata; - mdbdata.mv_size = value->size(); - mdbdata.mv_data = value->data(); - mdbkey.mv_size = key->size(); - mdbkey.mv_data = key->data(); + mdbdata.mv_size = local_value.size(); + mdbdata.mv_data = local_value.data(); + mdbkey.mv_size = local_key.size(); + mdbkey.mv_data = local_key.data(); CHECK_NOTNULL(txn_); CHECK_NE(0, dbi_); @@ -98,12 +102,14 @@ bool LmdbDatabase::put(buffer_t* key, buffer_t* value) { return true; } -bool LmdbDatabase::get(buffer_t* key, buffer_t* value) { +bool LmdbDatabase::get(const buffer_t& key, buffer_t* value) { LOG(INFO) << "LMDB: Get"; + buffer_t local_key = key; + MDB_val mdbkey, mdbdata; - mdbkey.mv_data = key->data(); - mdbkey.mv_size = key->size(); + mdbkey.mv_data = local_key.data(); + mdbkey.mv_size = local_key.size(); int retval; MDB_txn* get_txn; diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index cc9ad20487c..8ae8f2b8da8 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -59,7 +59,7 @@ class DataLayerTest : public MultiDeviceTest { Database::buffer_t value(datum.ByteSize()); datum.SerializeWithCachedSizesToArray( reinterpret_cast(value.data())); - CHECK(database->put(&key, &value)); + CHECK(database->put(key, value)); } CHECK(database->commit()); database->close(); diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp index f65865014fa..70e1d962619 100644 --- a/src/caffe/test/test_database.cpp +++ b/src/caffe/test/test_database.cpp @@ -126,7 +126,7 @@ TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { string value = ss.str(); Database::buffer_t key_buf(key.data(), key.data() + key.size()); Database::buffer_t val_buf(value.data(), value.data() + value.size()); - EXPECT_TRUE(database->put(&key_buf, &val_buf)); + EXPECT_TRUE(database->put(key_buf, val_buf)); } EXPECT_TRUE(database->commit()); @@ -151,8 +151,8 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLevelDB) { Database::buffer_t key2 = this->TestKey(); Database::buffer_t value2 = this->TestValue(); - EXPECT_TRUE(database->put(&key1, &value1)); - EXPECT_TRUE(database->put(&key2, &value2)); + EXPECT_TRUE(database->put(key1, value1)); + EXPECT_TRUE(database->put(key2, value2)); EXPECT_TRUE(database->commit()); Database::const_iterator iter1 = database->begin(); @@ -190,8 +190,8 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLevelDB) { Database::buffer_t key2 = this->TestKey(); Database::buffer_t value2 = this->TestValue(); - EXPECT_TRUE(database->put(&key1, &value1)); - EXPECT_TRUE(database->put(&key2, &value2)); + EXPECT_TRUE(database->put(key1, value1)); + EXPECT_TRUE(database->put(key2, value2)); EXPECT_TRUE(database->commit()); Database::const_iterator iter1 = database->begin(); @@ -229,7 +229,7 @@ TYPED_TEST(DatabaseTest, TestNewPutLevelDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); @@ -254,13 +254,13 @@ TYPED_TEST(DatabaseTest, TestNewGetLevelDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); Database::buffer_t new_val; - EXPECT_TRUE(database->get(&key, &new_val)); + EXPECT_TRUE(database->get(key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); @@ -275,11 +275,11 @@ TYPED_TEST(DatabaseTest, TestNewGetNoCommitLevelDBFails) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); Database::buffer_t new_val; - EXPECT_FALSE(database->get(&key, &new_val)); + EXPECT_FALSE(database->get(key, &new_val)); } @@ -291,7 +291,7 @@ TYPED_TEST(DatabaseTest, TestReadWritePutLevelDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); @@ -316,13 +316,13 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetLevelDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); Database::buffer_t new_val; - EXPECT_TRUE(database->get(&key, &new_val)); + EXPECT_TRUE(database->get(key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); @@ -337,11 +337,11 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLevelDBFails) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); Database::buffer_t new_val; - EXPECT_FALSE(database->get(&key, &new_val)); + EXPECT_FALSE(database->get(key, &new_val)); } TYPED_TEST(DatabaseTest, TestReadOnlyPutLevelDBFails) { @@ -355,7 +355,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyPutLevelDBFails) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_FALSE(database->put(&key, &val)); + EXPECT_FALSE(database->put(key, val)); } TYPED_TEST(DatabaseTest, TestReadOnlyCommitLevelDBFails) { @@ -377,7 +377,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); @@ -387,7 +387,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { Database::buffer_t new_val; - EXPECT_TRUE(database->get(&key, &new_val)); + EXPECT_TRUE(database->get(key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); } @@ -400,7 +400,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLevelDBFails) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); database->close(); @@ -408,7 +408,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLevelDBFails) { Database::buffer_t new_val; - EXPECT_FALSE(database->get(&key, &new_val)); + EXPECT_FALSE(database->get(key, &new_val)); } TYPED_TEST(DatabaseTest, TestNewDoesntExistLMDBPasses) { @@ -473,7 +473,7 @@ TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { string value = ss.str(); Database::buffer_t key_buf(key.data(), key.data() + key.size()); Database::buffer_t val_buf(value.data(), value.data() + value.size()); - EXPECT_TRUE(database->put(&key_buf, &val_buf)); + EXPECT_TRUE(database->put(key_buf, val_buf)); } EXPECT_TRUE(database->commit()); @@ -498,8 +498,8 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLMDB) { Database::buffer_t key2 = this->TestKey(); Database::buffer_t value2 = this->TestValue(); - EXPECT_TRUE(database->put(&key1, &value1)); - EXPECT_TRUE(database->put(&key2, &value2)); + EXPECT_TRUE(database->put(key1, value1)); + EXPECT_TRUE(database->put(key2, value2)); EXPECT_TRUE(database->commit()); Database::const_iterator iter1 = database->begin(); @@ -537,8 +537,8 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLMDB) { Database::buffer_t key2 = this->TestKey(); Database::buffer_t value2 = this->TestValue(); - EXPECT_TRUE(database->put(&key1, &value1)); - EXPECT_TRUE(database->put(&key2, &value2)); + EXPECT_TRUE(database->put(key1, value1)); + EXPECT_TRUE(database->put(key2, value2)); EXPECT_TRUE(database->commit()); Database::const_iterator iter1 = database->begin(); @@ -576,7 +576,7 @@ TYPED_TEST(DatabaseTest, TestNewPutLMDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); @@ -601,13 +601,13 @@ TYPED_TEST(DatabaseTest, TestNewGetLMDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); Database::buffer_t new_val; - EXPECT_TRUE(database->get(&key, &new_val)); + EXPECT_TRUE(database->get(key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); @@ -622,11 +622,11 @@ TYPED_TEST(DatabaseTest, TestNewGetNoCommitLMDBFails) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); Database::buffer_t new_val; - EXPECT_FALSE(database->get(&key, &new_val)); + EXPECT_FALSE(database->get(key, &new_val)); } TYPED_TEST(DatabaseTest, TestReadWritePutLMDBPasses) { @@ -637,7 +637,7 @@ TYPED_TEST(DatabaseTest, TestReadWritePutLMDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); @@ -662,13 +662,13 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetLMDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); Database::buffer_t new_val; - EXPECT_TRUE(database->get(&key, &new_val)); + EXPECT_TRUE(database->get(key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); @@ -683,11 +683,11 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLMDBFails) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); Database::buffer_t new_val; - EXPECT_FALSE(database->get(&key, &new_val)); + EXPECT_FALSE(database->get(key, &new_val)); } TYPED_TEST(DatabaseTest, TestReadOnlyPutLMDBFails) { @@ -701,7 +701,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyPutLMDBFails) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_FALSE(database->put(&key, &val)); + EXPECT_FALSE(database->put(key, val)); } TYPED_TEST(DatabaseTest, TestReadOnlyCommitLMDBFails) { @@ -723,7 +723,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); @@ -733,7 +733,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { Database::buffer_t new_val; - EXPECT_TRUE(database->get(&key, &new_val)); + EXPECT_TRUE(database->get(key, &new_val)); EXPECT_TRUE(this->BufferEq(val, new_val)); } @@ -746,7 +746,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLMDBFails) { Database::buffer_t key = this->TestKey(); Database::buffer_t val = this->TestValue(); - EXPECT_TRUE(database->put(&key, &val)); + EXPECT_TRUE(database->put(key, val)); database->close(); @@ -754,7 +754,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLMDBFails) { Database::buffer_t new_val; - EXPECT_FALSE(database->get(&key, &new_val)); + EXPECT_FALSE(database->get(key, &new_val)); } } // namespace caffe diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 3345c9c7e26..5ad2c0b4d5a 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -116,7 +116,7 @@ int main(int argc, char** argv) { Database::buffer_t keystr(key_cstr, key_cstr + length); // Put in db - CHECK(database->put(&keystr, &value)); + CHECK(database->put(keystr, value)); if (++count % 1000 == 0) { // Commit txn diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 1560ef60a7c..0c7660d5d49 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -161,7 +161,7 @@ int feature_extraction_pipeline(int argc, char** argv) { int length = snprintf(key_str, kMaxKeyStrLength, "%d", image_indices[i]); Database::buffer_t key(key_str, key_str + length); - CHECK(feature_dbs.at(i)->put(&key, &value)); + CHECK(feature_dbs.at(i)->put(key, value)); ++image_indices[i]; if (image_indices[i] % 1000 == 0) { CHECK(feature_dbs.at(i)->commit()); From 2200a7a4b1f7fa7ac5fac7a2463552e8fe0ca9c2 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 20:43:01 -0400 Subject: [PATCH 121/798] The LevelDB iterator/DB deallocation order bug is pretty much fixed by having each iterator hold a shared pointer to the DB. I manually specified a deconstructor for the LeveldbState to make it clear what order these two things need to be deallocated in. --- include/caffe/leveldb_database.hpp | 8 ++++++++ src/caffe/layers/data_layer.cpp | 4 ---- src/caffe/test/test_database.cpp | 16 ---------------- tools/compute_image_mean.cpp | 1 - 4 files changed, 8 insertions(+), 21 deletions(-) diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index e2558ff477f..2a610a370a4 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -34,6 +34,14 @@ class LeveldbDatabase : public Database { db_(db), iter_(iter) { } + ~LeveldbState() { + // This order is very important. + // Iterators must be destroyed before their associated DB + // is destroyed. + iter_.reset(); + db_.reset(); + } + shared_ptr clone() { shared_ptr new_iter; diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index dcba10fabec..c379d78d8f3 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -18,10 +18,6 @@ template DataLayer::~DataLayer() { this->JoinPrefetchThread(); // clean up the database resources - - // Very important to invalidate iterators before closing the database. - // TODO(kmatzen): Figure out a better design to avoid this. - iter_ = database_->end(); database_->close(); } diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp index 70e1d962619..3dd200673ff 100644 --- a/src/caffe/test/test_database.cpp +++ b/src/caffe/test/test_database.cpp @@ -172,10 +172,6 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLevelDB) { EXPECT_TRUE(database->end() == iter3); - iter1 = database->end(); - iter2 = database->end(); - iter3 = database->end(); - database->close(); } @@ -214,10 +210,6 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLevelDB) { EXPECT_TRUE(this->BufferEq(iter3->key, key2)); EXPECT_TRUE(database->end() == iter1); - iter1 = database->end(); - iter2 = database->end(); - iter3 = database->end(); - database->close(); } @@ -519,10 +511,6 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLMDB) { EXPECT_TRUE(database->end() == iter3); - iter1 = database->end(); - iter2 = database->end(); - iter3 = database->end(); - database->close(); } @@ -561,10 +549,6 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLMDB) { EXPECT_TRUE(this->BufferEq(iter3->key, key2)); EXPECT_TRUE(database->end() == iter1); - iter1 = database->end(); - iter2 = database->end(); - iter3 = database->end(); - database->close(); } diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index b973c5277ad..5f6ea6eecc5 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -38,7 +38,6 @@ int main(int argc, char** argv) { Database::const_iterator iter = database->begin(); const Database::buffer_t& first_blob = iter->value; datum.ParseFromArray(first_blob.data(), first_blob.size()); - iter = database->end(); sum_blob.set_num(1); sum_blob.set_channels(datum.channels()); From 80a99b939bfad88d918e82b41fd2c28c454abb50 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 20:54:39 -0400 Subject: [PATCH 122/798] Changed Database::buffer_t to Database::key_type and Database::value_type --- examples/cifar10/convert_cifar_data.cpp | 8 +- include/caffe/database.hpp | 11 +- include/caffe/leveldb_database.hpp | 4 +- include/caffe/lmdb_database.hpp | 4 +- src/caffe/leveldb_database.cpp | 10 +- src/caffe/lmdb_database.cpp | 16 +-- src/caffe/test/test_data_layer.cpp | 4 +- src/caffe/test/test_database.cpp | 156 ++++++++++++------------ tools/compute_image_mean.cpp | 4 +- tools/convert_imageset.cpp | 4 +- tools/extract_features.cpp | 4 +- 11 files changed, 113 insertions(+), 112 deletions(-) diff --git a/examples/cifar10/convert_cifar_data.cpp b/examples/cifar10/convert_cifar_data.cpp index af845eadfb6..46ab1558623 100644 --- a/examples/cifar10/convert_cifar_data.cpp +++ b/examples/cifar10/convert_cifar_data.cpp @@ -60,12 +60,12 @@ void convert_dataset(const string& input_folder, const string& output_folder, read_image(&data_file, &label, str_buffer); datum.set_label(label); datum.set_data(str_buffer, kCIFARImageNBytes); - Database::buffer_t value(datum.ByteSize()); + Database::value_type value(datum.ByteSize()); datum.SerializeWithCachedSizesToArray( reinterpret_cast(value.data())); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", fileid * kCIFARBatchSize + itemid); - Database::buffer_t key(str_buffer, str_buffer + length); + Database::key_type key(str_buffer, str_buffer + length); CHECK(train_database->put(key, value)); } } @@ -84,11 +84,11 @@ void convert_dataset(const string& input_folder, const string& output_folder, read_image(&data_file, &label, str_buffer); datum.set_label(label); datum.set_data(str_buffer, kCIFARImageNBytes); - Database::buffer_t value(datum.ByteSize()); + Database::value_type value(datum.ByteSize()); datum.SerializeWithCachedSizesToArray( reinterpret_cast(value.data())); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); - Database::buffer_t key(str_buffer, str_buffer + length); + Database::key_type key(str_buffer, str_buffer + length); CHECK(test_database->put(key, value)); } CHECK(test_database->commit()); diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index 3f3970d77a7..2341149ce59 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -19,16 +19,17 @@ class Database { ReadOnly }; - typedef vector buffer_t; + typedef vector key_type; + typedef vector value_type; struct KV { - buffer_t key; - buffer_t value; + key_type key; + value_type value; }; virtual bool open(const string& filename, Mode mode) = 0; - virtual bool put(const buffer_t& key, const buffer_t& value) = 0; - virtual bool get(const buffer_t& key, buffer_t* value) = 0; + virtual bool put(const key_type& key, const value_type& value) = 0; + virtual bool get(const key_type& key, value_type* value) = 0; virtual bool commit() = 0; virtual void close() = 0; diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index 2a610a370a4..9c7f70ec053 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -15,8 +15,8 @@ namespace caffe { class LeveldbDatabase : public Database { public: bool open(const string& filename, Mode mode); - bool put(const buffer_t& key, const buffer_t& value); - bool get(const buffer_t& key, buffer_t* value); + bool put(const key_type& key, const value_type& value); + bool get(const key_type& key, value_type* value); bool commit(); void close(); diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index 4a0f3183bd5..107d936da83 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -19,8 +19,8 @@ class LmdbDatabase : public Database { txn_(NULL) { } bool open(const string& filename, Mode mode); - bool put(const buffer_t& key, const buffer_t& value); - bool get(const buffer_t& key, buffer_t* value); + bool put(const key_type& key, const value_type& value); + bool get(const key_type& key, value_type* value); bool commit(); void close(); diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index c09112f668b..2061b8ea65e 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -51,7 +51,7 @@ bool LeveldbDatabase::open(const string& filename, Mode mode) { return true; } -bool LeveldbDatabase::put(const buffer_t& key, const buffer_t& value) { +bool LeveldbDatabase::put(const key_type& key, const value_type& value) { LOG(INFO) << "LevelDB: Put"; if (read_only_) { @@ -69,7 +69,7 @@ bool LeveldbDatabase::put(const buffer_t& key, const buffer_t& value) { return true; } -bool LeveldbDatabase::get(const buffer_t& key, buffer_t* value) { +bool LeveldbDatabase::get(const key_type& key, value_type* value) { LOG(INFO) << "LevelDB: Get"; leveldb::Slice key_slice(key.data(), key.size()); @@ -83,7 +83,7 @@ bool LeveldbDatabase::get(const buffer_t& key, buffer_t* value) { return false; } - Database::buffer_t temp_value(value_string.data(), + Database::value_type temp_value(value_string.data(), value_string.data() + value_string.size()); value->swap(temp_value); @@ -189,10 +189,10 @@ Database::KV& LeveldbDatabase::dereference( CHECK(iter->Valid()); - Database::buffer_t temp_key(buffer_t(iter->key().data(), + Database::key_type temp_key(key_type(iter->key().data(), iter->key().data() + iter->key().size())); - Database::buffer_t temp_value(buffer_t(iter->value().data(), + Database::value_type temp_value(value_type(iter->value().data(), iter->value().data() + iter->value().size())); leveldb_state->kv_pair_.key.swap(temp_key); diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index 2cb699b4234..eb22d15f28d 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -77,12 +77,12 @@ bool LmdbDatabase::open(const string& filename, Mode mode) { return true; } -bool LmdbDatabase::put(const buffer_t& key, const buffer_t& value) { +bool LmdbDatabase::put(const key_type& key, const value_type& value) { LOG(INFO) << "LMDB: Put"; // MDB_val::mv_size is not const, so we need to make a local copy. - buffer_t local_key = key; - buffer_t local_value = value; + key_type local_key = key; + value_type local_value = value; MDB_val mdbkey, mdbdata; mdbdata.mv_size = local_value.size(); @@ -102,10 +102,10 @@ bool LmdbDatabase::put(const buffer_t& key, const buffer_t& value) { return true; } -bool LmdbDatabase::get(const buffer_t& key, buffer_t* value) { +bool LmdbDatabase::get(const key_type& key, value_type* value) { LOG(INFO) << "LMDB: Get"; - buffer_t local_key = key; + key_type local_key = key; MDB_val mdbkey, mdbdata; mdbkey.mv_data = local_key.data(); @@ -127,7 +127,7 @@ bool LmdbDatabase::get(const buffer_t& key, buffer_t* value) { mdb_txn_abort(get_txn); - Database::buffer_t temp_value(reinterpret_cast(mdbdata.mv_data), + Database::value_type temp_value(reinterpret_cast(mdbdata.mv_data), reinterpret_cast(mdbdata.mv_data) + mdbdata.mv_size); value->swap(temp_value); @@ -247,9 +247,9 @@ Database::KV& LmdbDatabase::dereference(shared_ptr state) const { char* key_data = reinterpret_cast(mdb_key.mv_data); char* value_data = reinterpret_cast(mdb_val.mv_data); - Database::buffer_t temp_key(key_data, key_data + mdb_key.mv_size); + Database::key_type temp_key(key_data, key_data + mdb_key.mv_size); - Database::buffer_t temp_value(value_data, + Database::value_type temp_value(value_data, value_data + mdb_val.mv_size); lmdb_state->kv_pair_.key.swap(temp_key); diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index 8ae8f2b8da8..5f982063cc7 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -55,8 +55,8 @@ class DataLayerTest : public MultiDeviceTest { stringstream ss; ss << i; string key_str = ss.str(); - Database::buffer_t key(key_str.c_str(), key_str.c_str() + key_str.size()); - Database::buffer_t value(datum.ByteSize()); + Database::key_type key(key_str.c_str(), key_str.c_str() + key_str.size()); + Database::value_type value(datum.ByteSize()); datum.SerializeWithCachedSizesToArray( reinterpret_cast(value.data())); CHECK(database->put(key, value)); diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp index 3dd200673ff..ad1c786465a 100644 --- a/src/caffe/test/test_database.cpp +++ b/src/caffe/test/test_database.cpp @@ -23,32 +23,32 @@ class DatabaseTest : public MultiDeviceTest { return filename; } - Database::buffer_t TestKey() { + Database::key_type TestKey() { const char* kKey = "hello"; - Database::buffer_t key(kKey, kKey + 5); + Database::key_type key(kKey, kKey + 5); return key; } - Database::buffer_t TestValue() { + Database::value_type TestValue() { const char* kValue = "world"; - Database::buffer_t value(kValue, kValue + 5); + Database::value_type value(kValue, kValue + 5); return value; } - Database::buffer_t TestAltKey() { + Database::key_type TestAltKey() { const char* kKey = "foo"; - Database::buffer_t key(kKey, kKey + 3); + Database::key_type key(kKey, kKey + 3); return key; } - Database::buffer_t TestAltValue() { + Database::value_type TestAltValue() { const char* kValue = "bar"; - Database::buffer_t value(kValue, kValue + 3); + Database::value_type value(kValue, kValue + 3); return value; } - bool BufferEq(const Database::buffer_t& buf1, - const Database::buffer_t& buf2) { + template + bool BufferEq(const T& buf1, const T& buf2) { if (buf1.size() != buf2.size()) { return false; } @@ -124,8 +124,8 @@ TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { string key = ss.str(); ss << " here be data"; string value = ss.str(); - Database::buffer_t key_buf(key.data(), key.data() + key.size()); - Database::buffer_t val_buf(value.data(), value.data() + value.size()); + Database::key_type key_buf(key.data(), key.data() + key.size()); + Database::value_type val_buf(value.data(), value.data() + value.size()); EXPECT_TRUE(database->put(key_buf, val_buf)); } EXPECT_TRUE(database->commit()); @@ -145,11 +145,11 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLevelDB) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key1 = this->TestAltKey(); - Database::buffer_t value1 = this->TestAltValue(); + Database::key_type key1 = this->TestAltKey(); + Database::value_type value1 = this->TestAltValue(); - Database::buffer_t key2 = this->TestKey(); - Database::buffer_t value2 = this->TestValue(); + Database::key_type key2 = this->TestKey(); + Database::value_type value2 = this->TestValue(); EXPECT_TRUE(database->put(key1, value1)); EXPECT_TRUE(database->put(key2, value2)); @@ -180,11 +180,11 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLevelDB) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key1 = this->TestAltKey(); - Database::buffer_t value1 = this->TestAltValue(); + Database::key_type key1 = this->TestAltKey(); + Database::value_type value1 = this->TestAltValue(); - Database::buffer_t key2 = this->TestKey(); - Database::buffer_t value2 = this->TestValue(); + Database::key_type key2 = this->TestKey(); + Database::value_type value2 = this->TestValue(); EXPECT_TRUE(database->put(key1, value1)); EXPECT_TRUE(database->put(key2, value2)); @@ -218,8 +218,8 @@ TYPED_TEST(DatabaseTest, TestNewPutLevelDBPasses) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); @@ -243,14 +243,14 @@ TYPED_TEST(DatabaseTest, TestNewGetLevelDBPasses) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_TRUE(database->get(key, &new_val)); @@ -264,12 +264,12 @@ TYPED_TEST(DatabaseTest, TestNewGetNoCommitLevelDBFails) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_FALSE(database->get(key, &new_val)); } @@ -280,8 +280,8 @@ TYPED_TEST(DatabaseTest, TestReadWritePutLevelDBPasses) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::ReadWrite)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); @@ -305,14 +305,14 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetLevelDBPasses) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_TRUE(database->get(key, &new_val)); @@ -326,12 +326,12 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLevelDBFails) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_FALSE(database->get(key, &new_val)); } @@ -344,8 +344,8 @@ TYPED_TEST(DatabaseTest, TestReadOnlyPutLevelDBFails) { EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_FALSE(database->put(key, val)); } @@ -366,8 +366,8 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); @@ -377,7 +377,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_TRUE(database->get(key, &new_val)); @@ -389,8 +389,8 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLevelDBFails) { shared_ptr database = DatabaseFactory("leveldb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); @@ -398,7 +398,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLevelDBFails) { EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_FALSE(database->get(key, &new_val)); } @@ -463,8 +463,8 @@ TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { string key = ss.str(); ss << " here be data"; string value = ss.str(); - Database::buffer_t key_buf(key.data(), key.data() + key.size()); - Database::buffer_t val_buf(value.data(), value.data() + value.size()); + Database::key_type key_buf(key.data(), key.data() + key.size()); + Database::value_type val_buf(value.data(), value.data() + value.size()); EXPECT_TRUE(database->put(key_buf, val_buf)); } EXPECT_TRUE(database->commit()); @@ -484,11 +484,11 @@ TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLMDB) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key1 = this->TestAltKey(); - Database::buffer_t value1 = this->TestAltValue(); + Database::key_type key1 = this->TestAltKey(); + Database::value_type value1 = this->TestAltValue(); - Database::buffer_t key2 = this->TestKey(); - Database::buffer_t value2 = this->TestValue(); + Database::key_type key2 = this->TestKey(); + Database::value_type value2 = this->TestValue(); EXPECT_TRUE(database->put(key1, value1)); EXPECT_TRUE(database->put(key2, value2)); @@ -519,11 +519,11 @@ TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLMDB) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key1 = this->TestAltKey(); - Database::buffer_t value1 = this->TestAltValue(); + Database::key_type key1 = this->TestAltKey(); + Database::value_type value1 = this->TestAltValue(); - Database::buffer_t key2 = this->TestKey(); - Database::buffer_t value2 = this->TestValue(); + Database::key_type key2 = this->TestKey(); + Database::value_type value2 = this->TestValue(); EXPECT_TRUE(database->put(key1, value1)); EXPECT_TRUE(database->put(key2, value2)); @@ -557,8 +557,8 @@ TYPED_TEST(DatabaseTest, TestNewPutLMDBPasses) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); @@ -582,14 +582,14 @@ TYPED_TEST(DatabaseTest, TestNewGetLMDBPasses) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_TRUE(database->get(key, &new_val)); @@ -603,12 +603,12 @@ TYPED_TEST(DatabaseTest, TestNewGetNoCommitLMDBFails) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_FALSE(database->get(key, &new_val)); } @@ -618,8 +618,8 @@ TYPED_TEST(DatabaseTest, TestReadWritePutLMDBPasses) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::ReadWrite)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); @@ -643,14 +643,14 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetLMDBPasses) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); EXPECT_TRUE(database->commit()); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_TRUE(database->get(key, &new_val)); @@ -664,12 +664,12 @@ TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLMDBFails) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_FALSE(database->get(key, &new_val)); } @@ -682,8 +682,8 @@ TYPED_TEST(DatabaseTest, TestReadOnlyPutLMDBFails) { EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_FALSE(database->put(key, val)); } @@ -704,8 +704,8 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); @@ -715,7 +715,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_TRUE(database->get(key, &new_val)); @@ -727,8 +727,8 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLMDBFails) { shared_ptr database = DatabaseFactory("lmdb"); EXPECT_TRUE(database->open(name, Database::New)); - Database::buffer_t key = this->TestKey(); - Database::buffer_t val = this->TestValue(); + Database::key_type key = this->TestKey(); + Database::value_type val = this->TestValue(); EXPECT_TRUE(database->put(key, val)); @@ -736,7 +736,7 @@ TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLMDBFails) { EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::buffer_t new_val; + Database::value_type new_val; EXPECT_FALSE(database->get(key, &new_val)); } diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index 5f6ea6eecc5..d13c4a0f833 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -36,7 +36,7 @@ int main(int argc, char** argv) { int count = 0; // load first datum Database::const_iterator iter = database->begin(); - const Database::buffer_t& first_blob = iter->value; + const Database::value_type& first_blob = iter->value; datum.ParseFromArray(first_blob.data(), first_blob.size()); sum_blob.set_num(1); @@ -53,7 +53,7 @@ int main(int argc, char** argv) { for (Database::const_iterator iter = database->begin(); iter != database->end(); ++iter) { // just a dummy operation - const Database::buffer_t& blob = iter->value; + const Database::value_type& blob = iter->value; datum.ParseFromArray(blob.data(), blob.size()); const std::string& data = datum.data(); size_in_datum = std::max(datum.data().size(), diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 5ad2c0b4d5a..1cdca7e015a 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -110,10 +110,10 @@ int main(int argc, char** argv) { // sequential int length = snprintf(key_cstr, kMaxKeyLength, "%08d_%s", line_id, lines[line_id].first.c_str()); - Database::buffer_t value(datum.ByteSize()); + Database::value_type value(datum.ByteSize()); datum.SerializeWithCachedSizesToArray( reinterpret_cast(value.data())); - Database::buffer_t keystr(key_cstr, key_cstr + length); + Database::key_type keystr(key_cstr, key_cstr + length); // Put in db CHECK(database->put(keystr, value)); diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 0c7660d5d49..1340192cbe4 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -155,12 +155,12 @@ int feature_extraction_pipeline(int argc, char** argv) { for (int d = 0; d < dim_features; ++d) { datum.add_float_data(feature_blob_data[d]); } - Database::buffer_t value(datum.ByteSize()); + Database::value_type value(datum.ByteSize()); datum.SerializeWithCachedSizesToArray( reinterpret_cast(value.data())); int length = snprintf(key_str, kMaxKeyStrLength, "%d", image_indices[i]); - Database::buffer_t key(key_str, key_str + length); + Database::key_type key(key_str, key_str + length); CHECK(feature_dbs.at(i)->put(key, value)); ++image_indices[i]; if (image_indices[i] % 1000 == 0) { From 08e2cdedbbe4d7178597d6dc1479eccfcce3b0d5 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 21:36:59 -0400 Subject: [PATCH 123/798] Added function to Database interface to retrieve keys. Exposed a bug with LMDB iterators. Fix the bug and updated how invalid iterators are represented. --- include/caffe/database.hpp | 11 ++-- include/caffe/leveldb_database.hpp | 5 +- include/caffe/lmdb_database.hpp | 5 +- src/caffe/leveldb_database.cpp | 35 ++++++---- src/caffe/lmdb_database.cpp | 44 +++++++++---- src/caffe/test/test_database.cpp | 101 +++++++++++++++++++++++++++++ 6 files changed, 169 insertions(+), 32 deletions(-) diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index 2341149ce59..8469e84a1dd 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -33,6 +33,8 @@ class Database { virtual bool commit() = 0; virtual void close() = 0; + virtual void keys(vector* keys) = 0; + Database() { } virtual ~Database() { } @@ -65,7 +67,8 @@ class Database { iterator(const iterator& other) : parent_(other.parent_), - state_(other.state_->clone()) { } + state_(other.state_ ? other.state_->clone() + : shared_ptr()) { } iterator& operator=(iterator copy) { copy.swap(*this); @@ -86,12 +89,12 @@ class Database { } iterator& operator++() { - parent_->increment(state_); + parent_->increment(&state_); return *this; } iterator operator++(int) { iterator copy(*this); - parent_->increment(state_); + parent_->increment(&state_); return copy; } @@ -117,7 +120,7 @@ class Database { virtual bool equal(shared_ptr state1, shared_ptr state2) const = 0; - virtual void increment(shared_ptr state) const = 0; + virtual void increment(shared_ptr* state) const = 0; virtual KV& dereference( shared_ptr state) const = 0; }; diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index 9c7f70ec053..48cf11e06d4 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -6,6 +6,7 @@ #include #include +#include #include "caffe/common.hpp" #include "caffe/database.hpp" @@ -20,6 +21,8 @@ class LeveldbDatabase : public Database { bool commit(); void close(); + void keys(vector* keys); + const_iterator begin() const; const_iterator cbegin() const; const_iterator end() const; @@ -62,7 +65,7 @@ class LeveldbDatabase : public Database { bool equal(shared_ptr state1, shared_ptr state2) const; - void increment(shared_ptr state) const; + void increment(shared_ptr* state) const; Database::KV& dereference(shared_ptr state) const; shared_ptr db_; diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index 107d936da83..a8ce60dada5 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "lmdb.h" @@ -24,6 +25,8 @@ class LmdbDatabase : public Database { bool commit(); void close(); + void keys(vector* keys); + const_iterator begin() const; const_iterator cbegin() const; const_iterator end() const; @@ -66,7 +69,7 @@ class LmdbDatabase : public Database { bool equal(shared_ptr state1, shared_ptr state2) const; - void increment(shared_ptr state) const; + void increment(shared_ptr* state) const; Database::KV& dereference(shared_ptr state) const; MDB_env* env_; diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index 2061b8ea65e..ad98f9e2d4f 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "caffe/leveldb_database.hpp" @@ -115,6 +116,16 @@ void LeveldbDatabase::close() { db_.reset(); } +void LeveldbDatabase::keys(vector* keys) { + LOG(INFO) << "LevelDB: Keys"; + + keys->clear(); + for (Database::const_iterator iter = begin(); iter != end(); ++iter) { + LOG(INFO) << "KEY"; + keys->push_back(iter->key); + } +} + LeveldbDatabase::const_iterator LeveldbDatabase::begin() const { CHECK_NOTNULL(db_.get()); shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); @@ -122,13 +133,16 @@ LeveldbDatabase::const_iterator LeveldbDatabase::begin() const { if (!iter->Valid()) { iter.reset(); } - shared_ptr state(new LeveldbState(db_, iter)); + + shared_ptr state; + if (iter) { + state.reset(new LeveldbState(db_, iter)); + } return const_iterator(this, state); } LeveldbDatabase::const_iterator LeveldbDatabase::end() const { - shared_ptr iter; - shared_ptr state(new LeveldbState(db_, iter)); + shared_ptr state; return const_iterator(this, state); } @@ -143,25 +157,20 @@ bool LeveldbDatabase::equal(shared_ptr state1, shared_ptr leveldb_state1 = boost::dynamic_pointer_cast(state1); - CHECK_NOTNULL(leveldb_state1.get()); - shared_ptr leveldb_state2 = boost::dynamic_pointer_cast(state2); - CHECK_NOTNULL(leveldb_state2.get()); - - CHECK(!leveldb_state1->iter_ || leveldb_state1->iter_->Valid()); - CHECK(!leveldb_state2->iter_ || leveldb_state2->iter_->Valid()); + LOG(INFO) << leveldb_state1 << " " << leveldb_state2; // The KV store doesn't really have any sort of ordering, // so while we can do a sequential scan over the collection, // we can't really use subranges. - return !leveldb_state1->iter_ && !leveldb_state2->iter_; + return !leveldb_state1 && !leveldb_state2; } -void LeveldbDatabase::increment(shared_ptr state) const { +void LeveldbDatabase::increment(shared_ptr* state) const { shared_ptr leveldb_state = - boost::dynamic_pointer_cast(state); + boost::dynamic_pointer_cast(*state); CHECK_NOTNULL(leveldb_state.get()); @@ -172,7 +181,7 @@ void LeveldbDatabase::increment(shared_ptr state) const { iter->Next(); if (!iter->Valid()) { - iter.reset(); + state->reset(); } } diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index eb22d15f28d..aabb733b635 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "caffe/lmdb_database.hpp" @@ -168,22 +169,43 @@ void LmdbDatabase::close() { } } +void LmdbDatabase::keys(vector* keys) { + LOG(INFO) << "LMDB: Keys"; + + keys->clear(); + for (Database::const_iterator iter = begin(); iter != end(); ++iter) { + keys->push_back(iter->key); + } +} + LmdbDatabase::const_iterator LmdbDatabase::begin() const { - MDB_cursor* cursor; int retval; - retval = mdb_cursor_open(txn_, dbi_, &cursor); + + MDB_txn* iter_txn; + + retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &iter_txn); + CHECK_EQ(MDB_SUCCESS, retval) << "mdb_txn_begin failed " + << mdb_strerror(retval); + + MDB_cursor* cursor; + retval = mdb_cursor_open(iter_txn, dbi_, &cursor); CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); MDB_val key; MDB_val val; retval = mdb_cursor_get(cursor, &key, &val, MDB_FIRST); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - shared_ptr state(new LmdbState(cursor, txn_, &dbi_)); + CHECK(MDB_SUCCESS == retval || MDB_NOTFOUND == retval) + << mdb_strerror(retval); + + shared_ptr state; + if (MDB_SUCCESS == retval) { + state.reset(new LmdbState(cursor, iter_txn, &dbi_)); + } return const_iterator(this, state); } LmdbDatabase::const_iterator LmdbDatabase::end() const { - shared_ptr state(new LmdbState(NULL, txn_, &dbi_)); + shared_ptr state; return const_iterator(this, state); } @@ -195,22 +217,18 @@ bool LmdbDatabase::equal(shared_ptr state1, shared_ptr lmdb_state1 = boost::dynamic_pointer_cast(state1); - CHECK_NOTNULL(lmdb_state1.get()); - shared_ptr lmdb_state2 = boost::dynamic_pointer_cast(state2); - CHECK_NOTNULL(lmdb_state2.get()); - // The KV store doesn't really have any sort of ordering, // so while we can do a sequential scan over the collection, // we can't really use subranges. - return !lmdb_state1->cursor_ && !lmdb_state2->cursor_; + return !lmdb_state1 && !lmdb_state2; } -void LmdbDatabase::increment(shared_ptr state) const { +void LmdbDatabase::increment(shared_ptr* state) const { shared_ptr lmdb_state = - boost::dynamic_pointer_cast(state); + boost::dynamic_pointer_cast(*state); CHECK_NOTNULL(lmdb_state.get()); @@ -223,7 +241,7 @@ void LmdbDatabase::increment(shared_ptr state) const { int retval = mdb_cursor_get(cursor, &key, &val, MDB_NEXT); if (MDB_NOTFOUND == retval) { mdb_cursor_close(cursor); - cursor = NULL; + state->reset(); } else { CHECK_EQ(MDB_SUCCESS, retval) << mdb_strerror(retval); } diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp index ad1c786465a..9c569106f10 100644 --- a/src/caffe/test/test_database.cpp +++ b/src/caffe/test/test_database.cpp @@ -112,6 +112,56 @@ TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistLevelDBPasses) { database->close(); } +TYPED_TEST(DatabaseTest, TestKeysLevelDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + EXPECT_TRUE(database->open(name, Database::New)); + + Database::key_type key1 = this->TestKey(); + Database::value_type value1 = this->TestValue(); + + EXPECT_TRUE(database->put(key1, value1)); + + Database::key_type key2 = this->TestAltKey(); + Database::value_type value2 = this->TestAltValue(); + + EXPECT_TRUE(database->put(key2, value2)); + + EXPECT_TRUE(database->commit()); + + vector keys; + database->keys(&keys); + + EXPECT_EQ(2, keys.size()); + + EXPECT_TRUE(this->BufferEq(keys.at(0), key1) || + this->BufferEq(keys.at(0), key2)); + EXPECT_TRUE(this->BufferEq(keys.at(1), key1) || + this->BufferEq(keys.at(2), key2)); + EXPECT_FALSE(this->BufferEq(keys.at(0), keys.at(1))); +} + +TYPED_TEST(DatabaseTest, TestKeysNoCommitLevelDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("leveldb"); + EXPECT_TRUE(database->open(name, Database::New)); + + Database::key_type key1 = this->TestKey(); + Database::value_type value1 = this->TestValue(); + + EXPECT_TRUE(database->put(key1, value1)); + + Database::key_type key2 = this->TestAltKey(); + Database::value_type value2 = this->TestAltValue(); + + EXPECT_TRUE(database->put(key2, value2)); + + vector keys; + database->keys(&keys); + + EXPECT_EQ(0, keys.size()); +} + TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("leveldb"); @@ -451,6 +501,57 @@ TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistLMDBPasses) { database->close(); } +TYPED_TEST(DatabaseTest, TestKeysLMDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + EXPECT_TRUE(database->open(name, Database::New)); + + Database::key_type key1 = this->TestKey(); + Database::value_type value1 = this->TestValue(); + + EXPECT_TRUE(database->put(key1, value1)); + + Database::key_type key2 = this->TestAltKey(); + Database::value_type value2 = this->TestAltValue(); + + EXPECT_TRUE(database->put(key2, value2)); + + EXPECT_TRUE(database->commit()); + + vector keys; + database->keys(&keys); + + EXPECT_EQ(2, keys.size()); + + EXPECT_TRUE(this->BufferEq(keys.at(0), key1) || + this->BufferEq(keys.at(0), key2)); + EXPECT_TRUE(this->BufferEq(keys.at(1), key1) || + this->BufferEq(keys.at(2), key2)); + EXPECT_FALSE(this->BufferEq(keys.at(0), keys.at(1))); +} + +TYPED_TEST(DatabaseTest, TestKeysNoCommitLMDB) { + string name = this->DBName(); + shared_ptr database = DatabaseFactory("lmdb"); + EXPECT_TRUE(database->open(name, Database::New)); + + Database::key_type key1 = this->TestKey(); + Database::value_type value1 = this->TestValue(); + + EXPECT_TRUE(database->put(key1, value1)); + + Database::key_type key2 = this->TestAltKey(); + Database::value_type value2 = this->TestAltValue(); + + EXPECT_TRUE(database->put(key2, value2)); + + vector keys; + database->keys(&keys); + + EXPECT_EQ(0, keys.size()); +} + + TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { string name = this->DBName(); shared_ptr database = DatabaseFactory("lmdb"); From 0987c72c9d11b94524e1dc91150daf273c5b2537 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sun, 12 Oct 2014 21:39:33 -0400 Subject: [PATCH 124/798] Switched some Database logging statements from LOG to DLOG. --- src/caffe/leveldb_database.cpp | 23 ++++++++++------------- src/caffe/lmdb_database.cpp | 12 ++++++------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index ad98f9e2d4f..a163abc09af 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -7,30 +7,30 @@ namespace caffe { bool LeveldbDatabase::open(const string& filename, Mode mode) { - LOG(INFO) << "LevelDB: Open " << filename; + DLOG(INFO) << "LevelDB: Open " << filename; leveldb::Options options; switch (mode) { case New: - LOG(INFO) << " mode NEW"; + DLOG(INFO) << " mode NEW"; options.error_if_exists = true; options.create_if_missing = true; read_only_ = false; break; case ReadWrite: - LOG(INFO) << " mode RW"; + DLOG(INFO) << " mode RW"; options.error_if_exists = false; options.create_if_missing = true; read_only_ = false; break; case ReadOnly: - LOG(INFO) << " mode RO"; + DLOG(INFO) << " mode RO"; options.error_if_exists = false; options.create_if_missing = false; read_only_ = true; break; default: - LOG(FATAL) << "unknown mode " << mode; + DLOG(FATAL) << "unknown mode " << mode; } options.write_buffer_size = 268435456; options.max_open_files = 100; @@ -53,7 +53,7 @@ bool LeveldbDatabase::open(const string& filename, Mode mode) { } bool LeveldbDatabase::put(const key_type& key, const value_type& value) { - LOG(INFO) << "LevelDB: Put"; + DLOG(INFO) << "LevelDB: Put"; if (read_only_) { LOG(ERROR) << "put can not be used on a database in ReadOnly mode"; @@ -71,7 +71,7 @@ bool LeveldbDatabase::put(const key_type& key, const value_type& value) { } bool LeveldbDatabase::get(const key_type& key, value_type* value) { - LOG(INFO) << "LevelDB: Get"; + DLOG(INFO) << "LevelDB: Get"; leveldb::Slice key_slice(key.data(), key.size()); @@ -92,7 +92,7 @@ bool LeveldbDatabase::get(const key_type& key, value_type* value) { } bool LeveldbDatabase::commit() { - LOG(INFO) << "LevelDB: Commit"; + DLOG(INFO) << "LevelDB: Commit"; if (read_only_) { LOG(ERROR) << "commit can not be used on a database in ReadOnly mode"; @@ -110,18 +110,17 @@ bool LeveldbDatabase::commit() { } void LeveldbDatabase::close() { - LOG(INFO) << "LevelDB: Close"; + DLOG(INFO) << "LevelDB: Close"; batch_.reset(); db_.reset(); } void LeveldbDatabase::keys(vector* keys) { - LOG(INFO) << "LevelDB: Keys"; + DLOG(INFO) << "LevelDB: Keys"; keys->clear(); for (Database::const_iterator iter = begin(); iter != end(); ++iter) { - LOG(INFO) << "KEY"; keys->push_back(iter->key); } } @@ -160,8 +159,6 @@ bool LeveldbDatabase::equal(shared_ptr state1, shared_ptr leveldb_state2 = boost::dynamic_pointer_cast(state2); - LOG(INFO) << leveldb_state1 << " " << leveldb_state2; - // The KV store doesn't really have any sort of ordering, // so while we can do a sequential scan over the collection, // we can't really use subranges. diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index aabb733b635..de94391ae7d 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -9,7 +9,7 @@ namespace caffe { bool LmdbDatabase::open(const string& filename, Mode mode) { - LOG(INFO) << "LMDB: Open " << filename; + DLOG(INFO) << "LMDB: Open " << filename; CHECK(NULL == env_); CHECK(NULL == txn_); @@ -79,7 +79,7 @@ bool LmdbDatabase::open(const string& filename, Mode mode) { } bool LmdbDatabase::put(const key_type& key, const value_type& value) { - LOG(INFO) << "LMDB: Put"; + DLOG(INFO) << "LMDB: Put"; // MDB_val::mv_size is not const, so we need to make a local copy. key_type local_key = key; @@ -104,7 +104,7 @@ bool LmdbDatabase::put(const key_type& key, const value_type& value) { } bool LmdbDatabase::get(const key_type& key, value_type* value) { - LOG(INFO) << "LMDB: Get"; + DLOG(INFO) << "LMDB: Get"; key_type local_key = key; @@ -137,7 +137,7 @@ bool LmdbDatabase::get(const key_type& key, value_type* value) { } bool LmdbDatabase::commit() { - LOG(INFO) << "LMDB: Commit"; + DLOG(INFO) << "LMDB: Commit"; CHECK_NOTNULL(txn_); @@ -158,7 +158,7 @@ bool LmdbDatabase::commit() { } void LmdbDatabase::close() { - LOG(INFO) << "LMDB: Close"; + DLOG(INFO) << "LMDB: Close"; if (env_ && dbi_) { mdb_close(env_, dbi_); @@ -170,7 +170,7 @@ void LmdbDatabase::close() { } void LmdbDatabase::keys(vector* keys) { - LOG(INFO) << "LMDB: Keys"; + DLOG(INFO) << "LMDB: Keys"; keys->clear(); for (Database::const_iterator iter = begin(); iter != end(); ++iter) { From 08b971feae8551ca5c7ce31a938a1f232ee56af2 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Mon, 13 Oct 2014 13:16:04 -0400 Subject: [PATCH 125/798] Templated the key and value types for the Database interface. The Database is now responsible for serialization. Refactored the tests so that they reuse the same code for each value type and backend configuration. --- examples/cifar10/convert_cifar_data.cpp | 25 +- include/caffe/data_layers.hpp | 4 +- include/caffe/database.hpp | 116 ++- include/caffe/database_factory.hpp | 7 +- include/caffe/leveldb_database.hpp | 23 +- include/caffe/lmdb_database.hpp | 23 +- src/caffe/database_factory.cpp | 31 +- src/caffe/layers/data_layer.cpp | 11 +- src/caffe/leveldb_database.cpp | 95 ++- src/caffe/lmdb_database.cpp | 113 +-- src/caffe/test/test_data_layer.cpp | 12 +- src/caffe/test/test_database.cpp | 901 +++++++++--------------- tools/compute_image_mean.cpp | 16 +- tools/convert_imageset.cpp | 11 +- tools/extract_features.cpp | 14 +- 15 files changed, 689 insertions(+), 713 deletions(-) diff --git a/examples/cifar10/convert_cifar_data.cpp b/examples/cifar10/convert_cifar_data.cpp index 46ab1558623..f86f3936a35 100644 --- a/examples/cifar10/convert_cifar_data.cpp +++ b/examples/cifar10/convert_cifar_data.cpp @@ -20,6 +20,7 @@ using std::string; using caffe::Database; using caffe::DatabaseFactory; +using caffe::Datum; using caffe::shared_ptr; const int kCIFARSize = 32; @@ -37,13 +38,14 @@ void read_image(std::ifstream* file, int* label, char* buffer) { void convert_dataset(const string& input_folder, const string& output_folder, const string& db_type) { - shared_ptr train_database = DatabaseFactory(db_type); + shared_ptr > train_database = + DatabaseFactory(db_type); CHECK(train_database->open(output_folder + "/cifar10_train_" + db_type, - Database::New)); + Database::New)); // Data buffer int label; char str_buffer[kCIFARImageNBytes]; - caffe::Datum datum; + Datum datum; datum.set_channels(3); datum.set_height(kCIFARSize); datum.set_width(kCIFARSize); @@ -60,22 +62,19 @@ void convert_dataset(const string& input_folder, const string& output_folder, read_image(&data_file, &label, str_buffer); datum.set_label(label); datum.set_data(str_buffer, kCIFARImageNBytes); - Database::value_type value(datum.ByteSize()); - datum.SerializeWithCachedSizesToArray( - reinterpret_cast(value.data())); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", fileid * kCIFARBatchSize + itemid); - Database::key_type key(str_buffer, str_buffer + length); - CHECK(train_database->put(key, value)); + CHECK(train_database->put(string(str_buffer, length), datum)); } } CHECK(train_database->commit()); train_database->close(); LOG(INFO) << "Writing Testing data"; - shared_ptr test_database = DatabaseFactory(db_type); + shared_ptr > test_database = + DatabaseFactory(db_type); CHECK(test_database->open(output_folder + "/cifar10_test_" + db_type, - Database::New)); + Database::New)); // Open files std::ifstream data_file((input_folder + "/test_batch.bin").c_str(), std::ios::in | std::ios::binary); @@ -84,12 +83,8 @@ void convert_dataset(const string& input_folder, const string& output_folder, read_image(&data_file, &label, str_buffer); datum.set_label(label); datum.set_data(str_buffer, kCIFARImageNBytes); - Database::value_type value(datum.ByteSize()); - datum.SerializeWithCachedSizesToArray( - reinterpret_cast(value.data())); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); - Database::key_type key(str_buffer, str_buffer + length); - CHECK(test_database->put(key, value)); + CHECK(test_database->put(string(str_buffer, length), datum)); } CHECK(test_database->commit()); test_database->close(); diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index 810f2bb833d..13ba4e6f8b3 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -100,8 +100,8 @@ class DataLayer : public BasePrefetchingDataLayer { protected: virtual void InternalThreadEntry(); - shared_ptr database_; - Database::const_iterator iter_; + shared_ptr > database_; + Database::const_iterator iter_; }; /** diff --git a/include/caffe/database.hpp b/include/caffe/database.hpp index 8469e84a1dd..711ebdd3fa0 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/database.hpp @@ -11,6 +11,83 @@ namespace caffe { +namespace database_internal { + +template +struct Coder { + static bool serialize(const T& obj, string* serialized) { + return obj.SerializeToString(serialized); + } + + static bool serialize(const T& obj, vector* serialized) { + serialized->resize(obj.ByteSize()); + return obj.SerializeWithCachedSizesToArray( + reinterpret_cast(serialized->data())); + } + + static bool deserialize(const string& serialized, T* obj) { + return obj->ParseFromString(serialized); + } + + static bool deserialize(const char* data, size_t size, T* obj) { + return obj->ParseFromArray(data, size); + } +}; + +template <> +struct Coder { + static bool serialize(string obj, string* serialized) { + *serialized = obj; + return true; + } + + static bool serialize(const string& obj, vector* serialized) { + vector temp(obj.data(), obj.data() + obj.size()); + serialized->swap(temp); + return true; + } + + static bool deserialize(const string& serialized, string* obj) { + *obj = serialized; + return true; + } + + static bool deserialize(const char* data, size_t size, string* obj) { + string temp_string(data, size); + obj->swap(temp_string); + return true; + } +}; + +template <> +struct Coder > { + static bool serialize(vector obj, string* serialized) { + string tmp(obj.data(), obj.size()); + serialized->swap(tmp); + return true; + } + + static bool serialize(const vector& obj, vector* serialized) { + *serialized = obj; + return true; + } + + static bool deserialize(const string& serialized, vector* obj) { + vector tmp(serialized.data(), serialized.data() + serialized.size()); + obj->swap(tmp); + return true; + } + + static bool deserialize(const char* data, size_t size, vector* obj) { + vector tmp(data, data + size); + obj->swap(tmp); + return true; + } +}; + +} // namespace database_internal + +template class Database { public: enum Mode { @@ -19,21 +96,21 @@ class Database { ReadOnly }; - typedef vector key_type; - typedef vector value_type; + typedef K key_type; + typedef V value_type; struct KV { - key_type key; - value_type value; + K key; + V value; }; virtual bool open(const string& filename, Mode mode) = 0; - virtual bool put(const key_type& key, const value_type& value) = 0; - virtual bool get(const key_type& key, value_type* value) = 0; + virtual bool put(const K& key, const V& value) = 0; + virtual bool get(const K& key, V* value) = 0; virtual bool commit() = 0; virtual void close() = 0; - virtual void keys(vector* keys) = 0; + virtual void keys(vector* keys) = 0; Database() { } virtual ~Database() { } @@ -123,8 +200,33 @@ class Database { virtual void increment(shared_ptr* state) const = 0; virtual KV& dereference( shared_ptr state) const = 0; + + template + static bool serialize(const T& obj, string* serialized) { + return database_internal::Coder::serialize(obj, serialized); + } + + template + static bool serialize(const T& obj, vector* serialized) { + return database_internal::Coder::serialize(obj, serialized); + } + + template + static bool deserialize(const string& serialized, T* obj) { + return database_internal::Coder::deserialize(serialized, obj); + } + + template + static bool deserialize(const char* data, size_t size, T* obj) { + return database_internal::Coder::deserialize(data, size, obj); + } }; } // namespace caffe +#define INSTANTIATE_DATABASE(type) \ + template class type; \ + template class type >; \ + template class type; + #endif // CAFFE_DATABASE_H_ diff --git a/include/caffe/database_factory.hpp b/include/caffe/database_factory.hpp index 91185e99b89..30f191e76b4 100644 --- a/include/caffe/database_factory.hpp +++ b/include/caffe/database_factory.hpp @@ -9,8 +9,11 @@ namespace caffe { -shared_ptr DatabaseFactory(const DataParameter_DB& type); -shared_ptr DatabaseFactory(const string& type); +template +shared_ptr > DatabaseFactory(const DataParameter_DB& type); + +template +shared_ptr > DatabaseFactory(const string& type); } // namespace caffe diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_database.hpp index 48cf11e06d4..cd966c440cc 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_database.hpp @@ -13,15 +13,24 @@ namespace caffe { -class LeveldbDatabase : public Database { +template +class LeveldbDatabase : public Database { public: + typedef Database Base; + typedef typename Base::key_type key_type; + typedef typename Base::value_type value_type; + typedef typename Base::DatabaseState DatabaseState; + typedef typename Base::Mode Mode; + typedef typename Base::const_iterator const_iterator; + typedef typename Base::KV KV; + bool open(const string& filename, Mode mode); - bool put(const key_type& key, const value_type& value); - bool get(const key_type& key, value_type* value); + bool put(const K& key, const V& value); + bool get(const K& key, V* value); bool commit(); void close(); - void keys(vector* keys); + void keys(vector* keys); const_iterator begin() const; const_iterator cbegin() const; @@ -29,11 +38,11 @@ class LeveldbDatabase : public Database { const_iterator cend() const; protected: - class LeveldbState : public Database::DatabaseState { + class LeveldbState : public DatabaseState { public: explicit LeveldbState(shared_ptr db, shared_ptr iter) - : Database::DatabaseState(), + : DatabaseState(), db_(db), iter_(iter) { } @@ -66,7 +75,7 @@ class LeveldbDatabase : public Database { bool equal(shared_ptr state1, shared_ptr state2) const; void increment(shared_ptr* state) const; - Database::KV& dereference(shared_ptr state) const; + KV& dereference(shared_ptr state) const; shared_ptr db_; shared_ptr batch_; diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_database.hpp index a8ce60dada5..b5a02ca46a7 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_database.hpp @@ -12,20 +12,29 @@ namespace caffe { -class LmdbDatabase : public Database { +template +class LmdbDatabase : public Database { public: + typedef Database Base; + typedef typename Base::key_type key_type; + typedef typename Base::value_type value_type; + typedef typename Base::DatabaseState DatabaseState; + typedef typename Base::Mode Mode; + typedef typename Base::const_iterator const_iterator; + typedef typename Base::KV KV; + LmdbDatabase() : env_(NULL), dbi_(0), txn_(NULL) { } bool open(const string& filename, Mode mode); - bool put(const key_type& key, const value_type& value); - bool get(const key_type& key, value_type* value); + bool put(const K& key, const V& value); + bool get(const K& key, V* value); bool commit(); void close(); - void keys(vector* keys); + void keys(vector* keys); const_iterator begin() const; const_iterator cbegin() const; @@ -33,10 +42,10 @@ class LmdbDatabase : public Database { const_iterator cend() const; protected: - class LmdbState : public Database::DatabaseState { + class LmdbState : public DatabaseState { public: explicit LmdbState(MDB_cursor* cursor, MDB_txn* txn, const MDB_dbi* dbi) - : Database::DatabaseState(), + : DatabaseState(), cursor_(cursor), txn_(txn), dbi_(dbi) { } @@ -70,7 +79,7 @@ class LmdbDatabase : public Database { bool equal(shared_ptr state1, shared_ptr state2) const; void increment(shared_ptr* state) const; - Database::KV& dereference(shared_ptr state) const; + KV& dereference(shared_ptr state) const; MDB_env* env_; MDB_dbi dbi_; diff --git a/src/caffe/database_factory.cpp b/src/caffe/database_factory.cpp index 062de8c02e3..4ccd429ef97 100644 --- a/src/caffe/database_factory.cpp +++ b/src/caffe/database_factory.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "caffe/database_factory.hpp" #include "caffe/leveldb_database.hpp" @@ -7,29 +8,43 @@ namespace caffe { -shared_ptr DatabaseFactory(const DataParameter_DB& type) { +template +shared_ptr > DatabaseFactory(const DataParameter_DB& type) { switch (type) { case DataParameter_DB_LEVELDB: - return shared_ptr(new LeveldbDatabase()); + return shared_ptr >(new LeveldbDatabase()); case DataParameter_DB_LMDB: - return shared_ptr(new LmdbDatabase()); + return shared_ptr >(new LmdbDatabase()); default: LOG(FATAL) << "Unknown database type " << type; - return shared_ptr(); + return shared_ptr >(); } } -shared_ptr DatabaseFactory(const string& type) { +template +shared_ptr > DatabaseFactory(const string& type) { if ("leveldb" == type) { - return DatabaseFactory(DataParameter_DB_LEVELDB); + return DatabaseFactory(DataParameter_DB_LEVELDB); } else if ("lmdb" == type) { - return DatabaseFactory(DataParameter_DB_LMDB); + return DatabaseFactory(DataParameter_DB_LMDB); } else { LOG(FATAL) << "Unknown database type " << type; - return shared_ptr(); + return shared_ptr >(); } } +#define REGISTER_DATABASE(key_type, value_type) \ + template shared_ptr > \ + DatabaseFactory(const string& type); \ + template shared_ptr > \ + DatabaseFactory(const DataParameter_DB& type); \ + +REGISTER_DATABASE(string, string); +REGISTER_DATABASE(string, vector); +REGISTER_DATABASE(string, Datum); + +#undef REGISTER_DATABASE + } // namespace caffe diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index c379d78d8f3..6296335276e 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -25,10 +25,11 @@ template void DataLayer::DataLayerSetUp(const vector*>& bottom, const vector*>& top) { // Initialize DB - database_ = DatabaseFactory(this->layer_param_.data_param().backend()); + database_ = DatabaseFactory( + this->layer_param_.data_param().backend()); const string& source = this->layer_param_.data_param().source(); LOG(INFO) << "Opening database " << source; - CHECK(database_->open(source, Database::ReadOnly)); + CHECK(database_->open(source, Database::ReadOnly)); iter_ = database_->begin(); // Check if we would need to randomly skip a few data points @@ -44,8 +45,7 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, } // Read a data point, and use it to initialize the top blob. CHECK(iter_ != database_->end()); - Datum datum; - datum.ParseFromArray(iter_->value.data(), iter_->value.size()); + const Datum& datum = iter_->value; // image int crop_size = this->layer_param_.transform_param().crop_size(); @@ -89,9 +89,8 @@ void DataLayer::InternalThreadEntry() { const int batch_size = this->layer_param_.data_param().batch_size(); for (int item_id = 0; item_id < batch_size; ++item_id) { - Datum datum; CHECK(iter_ != database_->end()); - datum.ParseFromArray(iter_->value.data(), iter_->value.size()); + const Datum& datum = iter_->value; // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_database.cpp index a163abc09af..267ddf07330 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_database.cpp @@ -2,28 +2,30 @@ #include #include +#include "caffe/caffe.hpp" #include "caffe/leveldb_database.hpp" namespace caffe { -bool LeveldbDatabase::open(const string& filename, Mode mode) { +template +bool LeveldbDatabase::open(const string& filename, Mode mode) { DLOG(INFO) << "LevelDB: Open " << filename; leveldb::Options options; switch (mode) { - case New: + case Base::New: DLOG(INFO) << " mode NEW"; options.error_if_exists = true; options.create_if_missing = true; read_only_ = false; break; - case ReadWrite: + case Base::ReadWrite: DLOG(INFO) << " mode RW"; options.error_if_exists = false; options.create_if_missing = true; read_only_ = false; break; - case ReadOnly: + case Base::ReadOnly: DLOG(INFO) << " mode RO"; options.error_if_exists = false; options.create_if_missing = false; @@ -52,7 +54,8 @@ bool LeveldbDatabase::open(const string& filename, Mode mode) { return true; } -bool LeveldbDatabase::put(const key_type& key, const value_type& value) { +template +bool LeveldbDatabase::put(const K& key, const V& value) { DLOG(INFO) << "LevelDB: Put"; if (read_only_) { @@ -62,36 +65,48 @@ bool LeveldbDatabase::put(const key_type& key, const value_type& value) { CHECK_NOTNULL(batch_.get()); - leveldb::Slice key_slice(key.data(), key.size()); - leveldb::Slice value_slice(value.data(), value.size()); + string serialized_key; + if (!Base::serialize(key, &serialized_key)) { + return false; + } + + string serialized_value; + if (!Base::serialize(value, &serialized_value)) { + return false; + } - batch_->Put(key_slice, value_slice); + batch_->Put(serialized_key, serialized_value); return true; } -bool LeveldbDatabase::get(const key_type& key, value_type* value) { +template +bool LeveldbDatabase::get(const K& key, V* value) { DLOG(INFO) << "LevelDB: Get"; - leveldb::Slice key_slice(key.data(), key.size()); + string serialized_key; + if (!Base::serialize(key, &serialized_key)) { + return false; + } - string value_string; + string serialized_value; leveldb::Status status = - db_->Get(leveldb::ReadOptions(), key_slice, &value_string); + db_->Get(leveldb::ReadOptions(), serialized_key, &serialized_value); if (!status.ok()) { LOG(ERROR) << "leveldb get failed"; return false; } - Database::value_type temp_value(value_string.data(), - value_string.data() + value_string.size()); - value->swap(temp_value); + if (!Base::deserialize(serialized_value, value)) { + return false; + } return true; } -bool LeveldbDatabase::commit() { +template +bool LeveldbDatabase::commit() { DLOG(INFO) << "LevelDB: Commit"; if (read_only_) { @@ -109,23 +124,27 @@ bool LeveldbDatabase::commit() { return status.ok(); } -void LeveldbDatabase::close() { +template +void LeveldbDatabase::close() { DLOG(INFO) << "LevelDB: Close"; batch_.reset(); db_.reset(); } -void LeveldbDatabase::keys(vector* keys) { +template +void LeveldbDatabase::keys(vector* keys) { DLOG(INFO) << "LevelDB: Keys"; keys->clear(); - for (Database::const_iterator iter = begin(); iter != end(); ++iter) { + for (const_iterator iter = begin(); iter != end(); ++iter) { keys->push_back(iter->key); } } -LeveldbDatabase::const_iterator LeveldbDatabase::begin() const { +template +typename LeveldbDatabase::const_iterator + LeveldbDatabase::begin() const { CHECK_NOTNULL(db_.get()); shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); iter->SeekToFirst(); @@ -140,18 +159,25 @@ LeveldbDatabase::const_iterator LeveldbDatabase::begin() const { return const_iterator(this, state); } -LeveldbDatabase::const_iterator LeveldbDatabase::end() const { +template +typename LeveldbDatabase::const_iterator + LeveldbDatabase::end() const { shared_ptr state; return const_iterator(this, state); } -LeveldbDatabase::const_iterator LeveldbDatabase::cbegin() const { +template +typename LeveldbDatabase::const_iterator + LeveldbDatabase::cbegin() const { return begin(); } -LeveldbDatabase::const_iterator LeveldbDatabase::cend() const { return end(); } +template +typename LeveldbDatabase::const_iterator + LeveldbDatabase::cend() const { return end(); } -bool LeveldbDatabase::equal(shared_ptr state1, +template +bool LeveldbDatabase::equal(shared_ptr state1, shared_ptr state2) const { shared_ptr leveldb_state1 = boost::dynamic_pointer_cast(state1); @@ -165,7 +191,8 @@ bool LeveldbDatabase::equal(shared_ptr state1, return !leveldb_state1 && !leveldb_state2; } -void LeveldbDatabase::increment(shared_ptr* state) const { +template +void LeveldbDatabase::increment(shared_ptr* state) const { shared_ptr leveldb_state = boost::dynamic_pointer_cast(*state); @@ -182,7 +209,8 @@ void LeveldbDatabase::increment(shared_ptr* state) const { } } -Database::KV& LeveldbDatabase::dereference( +template +typename Database::KV& LeveldbDatabase::dereference( shared_ptr state) const { shared_ptr leveldb_state = boost::dynamic_pointer_cast(state); @@ -195,15 +223,16 @@ Database::KV& LeveldbDatabase::dereference( CHECK(iter->Valid()); - Database::key_type temp_key(key_type(iter->key().data(), - iter->key().data() + iter->key().size())); + const leveldb::Slice& key = iter->key(); + const leveldb::Slice& value = iter->value(); + CHECK(Base::deserialize(key.data(), key.size(), + &leveldb_state->kv_pair_.key)); + CHECK(Base::deserialize(value.data(), value.size(), + &leveldb_state->kv_pair_.value)); - Database::value_type temp_value(value_type(iter->value().data(), - iter->value().data() + iter->value().size())); - - leveldb_state->kv_pair_.key.swap(temp_key); - leveldb_state->kv_pair_.value.swap(temp_value); return leveldb_state->kv_pair_; } +INSTANTIATE_DATABASE(LeveldbDatabase); + } // namespace caffe diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_database.cpp index de94391ae7d..22a08b2a580 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_database.cpp @@ -4,11 +4,13 @@ #include #include +#include "caffe/caffe.hpp" #include "caffe/lmdb_database.hpp" namespace caffe { -bool LmdbDatabase::open(const string& filename, Mode mode) { +template +bool LmdbDatabase::open(const string& filename, Mode mode) { DLOG(INFO) << "LMDB: Open " << filename; CHECK(NULL == env_); @@ -16,16 +18,16 @@ bool LmdbDatabase::open(const string& filename, Mode mode) { CHECK_EQ(0, dbi_); int retval; - if (mode != ReadOnly) { + if (mode != Base::ReadOnly) { retval = mkdir(filename.c_str(), 0744); switch (mode) { - case New: + case Base::New: if (0 != retval) { LOG(ERROR) << "mkdir " << filename << " failed"; return false; } break; - case ReadWrite: + case Base::ReadWrite: if (-1 == retval && EEXIST != errno) { LOG(ERROR) << "mkdir " << filename << " failed (" << strerror(errno) << ")"; @@ -52,7 +54,7 @@ bool LmdbDatabase::open(const string& filename, Mode mode) { int flag1 = 0; int flag2 = 0; - if (mode == ReadOnly) { + if (mode == Base::ReadOnly) { flag1 = MDB_RDONLY | MDB_NOTLS; flag2 = MDB_RDONLY; } @@ -78,18 +80,27 @@ bool LmdbDatabase::open(const string& filename, Mode mode) { return true; } -bool LmdbDatabase::put(const key_type& key, const value_type& value) { +template +bool LmdbDatabase::put(const K& key, const V& value) { DLOG(INFO) << "LMDB: Put"; - // MDB_val::mv_size is not const, so we need to make a local copy. - key_type local_key = key; - value_type local_value = value; + vector serialized_key; + if (!Base::serialize(key, &serialized_key)) { + LOG(ERROR) << "failed to serialize key"; + return false; + } + + vector serialized_value; + if (!Base::serialize(value, &serialized_value)) { + LOG(ERROR) << "failed to serialized value"; + return false; + } MDB_val mdbkey, mdbdata; - mdbdata.mv_size = local_value.size(); - mdbdata.mv_data = local_value.data(); - mdbkey.mv_size = local_key.size(); - mdbkey.mv_data = local_key.data(); + mdbdata.mv_size = serialized_value.size(); + mdbdata.mv_data = serialized_value.data(); + mdbkey.mv_size = serialized_key.size(); + mdbkey.mv_data = serialized_key.data(); CHECK_NOTNULL(txn_); CHECK_NE(0, dbi_); @@ -103,14 +114,19 @@ bool LmdbDatabase::put(const key_type& key, const value_type& value) { return true; } -bool LmdbDatabase::get(const key_type& key, value_type* value) { +template +bool LmdbDatabase::get(const K& key, V* value) { DLOG(INFO) << "LMDB: Get"; - key_type local_key = key; + vector serialized_key; + if (!Base::serialize(key, &serialized_key)) { + LOG(ERROR) << "failed to serialized key"; + return false; + } MDB_val mdbkey, mdbdata; - mdbkey.mv_data = local_key.data(); - mdbkey.mv_size = local_key.size(); + mdbkey.mv_data = serialized_key.data(); + mdbkey.mv_size = serialized_key.size(); int retval; MDB_txn* get_txn; @@ -128,15 +144,17 @@ bool LmdbDatabase::get(const key_type& key, value_type* value) { mdb_txn_abort(get_txn); - Database::value_type temp_value(reinterpret_cast(mdbdata.mv_data), - reinterpret_cast(mdbdata.mv_data) + mdbdata.mv_size); - - value->swap(temp_value); + if (!Base::deserialize(reinterpret_cast(mdbdata.mv_data), + mdbdata.mv_size, value)) { + LOG(ERROR) << "failed to deserialize value"; + return false; + } return true; } -bool LmdbDatabase::commit() { +template +bool LmdbDatabase::commit() { DLOG(INFO) << "LMDB: Commit"; CHECK_NOTNULL(txn_); @@ -157,7 +175,8 @@ bool LmdbDatabase::commit() { return true; } -void LmdbDatabase::close() { +template +void LmdbDatabase::close() { DLOG(INFO) << "LMDB: Close"; if (env_ && dbi_) { @@ -169,16 +188,19 @@ void LmdbDatabase::close() { } } -void LmdbDatabase::keys(vector* keys) { +template +void LmdbDatabase::keys(vector* keys) { DLOG(INFO) << "LMDB: Keys"; keys->clear(); - for (Database::const_iterator iter = begin(); iter != end(); ++iter) { + for (const_iterator iter = begin(); iter != end(); ++iter) { keys->push_back(iter->key); } } -LmdbDatabase::const_iterator LmdbDatabase::begin() const { +template +typename LmdbDatabase::const_iterator + LmdbDatabase::begin() const { int retval; MDB_txn* iter_txn; @@ -204,15 +226,23 @@ LmdbDatabase::const_iterator LmdbDatabase::begin() const { return const_iterator(this, state); } -LmdbDatabase::const_iterator LmdbDatabase::end() const { +template +typename LmdbDatabase::const_iterator + LmdbDatabase::end() const { shared_ptr state; return const_iterator(this, state); } -LmdbDatabase::const_iterator LmdbDatabase::cbegin() const { return begin(); } -LmdbDatabase::const_iterator LmdbDatabase::cend() const { return end(); } +template +typename LmdbDatabase::const_iterator + LmdbDatabase::cbegin() const { return begin(); } -bool LmdbDatabase::equal(shared_ptr state1, +template +typename LmdbDatabase::const_iterator + LmdbDatabase::cend() const { return end(); } + +template +bool LmdbDatabase::equal(shared_ptr state1, shared_ptr state2) const { shared_ptr lmdb_state1 = boost::dynamic_pointer_cast(state1); @@ -226,7 +256,8 @@ bool LmdbDatabase::equal(shared_ptr state1, return !lmdb_state1 && !lmdb_state2; } -void LmdbDatabase::increment(shared_ptr* state) const { +template +void LmdbDatabase::increment(shared_ptr* state) const { shared_ptr lmdb_state = boost::dynamic_pointer_cast(*state); @@ -247,7 +278,9 @@ void LmdbDatabase::increment(shared_ptr* state) const { } } -Database::KV& LmdbDatabase::dereference(shared_ptr state) const { +template +typename Database::KV& LmdbDatabase::dereference( + shared_ptr state) const { shared_ptr lmdb_state = boost::dynamic_pointer_cast(state); @@ -262,18 +295,14 @@ Database::KV& LmdbDatabase::dereference(shared_ptr state) const { int retval = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT); CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - char* key_data = reinterpret_cast(mdb_key.mv_data); - char* value_data = reinterpret_cast(mdb_val.mv_data); - - Database::key_type temp_key(key_data, key_data + mdb_key.mv_size); - - Database::value_type temp_value(value_data, - value_data + mdb_val.mv_size); - - lmdb_state->kv_pair_.key.swap(temp_key); - lmdb_state->kv_pair_.value.swap(temp_value); + CHECK(Base::deserialize(reinterpret_cast(mdb_key.mv_data), + mdb_key.mv_size, &lmdb_state->kv_pair_.key)); + CHECK(Base::deserialize(reinterpret_cast(mdb_val.mv_data), + mdb_val.mv_size, &lmdb_state->kv_pair_.value)); return lmdb_state->kv_pair_; } +INSTANTIATE_DATABASE(LmdbDatabase); + } // namespace caffe diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index 5f982063cc7..1c3ec1fc576 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -39,8 +39,9 @@ class DataLayerTest : public MultiDeviceTest { void Fill(const bool unique_pixels, DataParameter_DB backend) { backend_ = backend; LOG(INFO) << "Using temporary database " << *filename_; - shared_ptr database = DatabaseFactory(backend_); - CHECK(database->open(*filename_, Database::New)); + shared_ptr > database = + DatabaseFactory(backend_); + CHECK(database->open(*filename_, Database::New)); for (int i = 0; i < 5; ++i) { Datum datum; datum.set_label(i); @@ -54,12 +55,7 @@ class DataLayerTest : public MultiDeviceTest { } stringstream ss; ss << i; - string key_str = ss.str(); - Database::key_type key(key_str.c_str(), key_str.c_str() + key_str.size()); - Database::value_type value(datum.ByteSize()); - datum.SerializeWithCachedSizesToArray( - reinterpret_cast(value.data())); - CHECK(database->put(key, value)); + CHECK(database->put(ss.str(), datum)); } CHECK(database->commit()); database->close(); diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp index 9c569106f10..9a7d6dec8c7 100644 --- a/src/caffe/test/test_database.cpp +++ b/src/caffe/test/test_database.cpp @@ -11,551 +11,303 @@ namespace caffe { -template -class DatabaseTest : public MultiDeviceTest { - typedef typename TypeParam::Dtype Dtype; - - protected: - string DBName() { - string filename; - MakeTempDir(&filename); - filename += "/db"; - return filename; - } - - Database::key_type TestKey() { - const char* kKey = "hello"; - Database::key_type key(kKey, kKey + 5); - return key; - } - - Database::value_type TestValue() { - const char* kValue = "world"; - Database::value_type value(kValue, kValue + 5); - return value; - } - - Database::key_type TestAltKey() { - const char* kKey = "foo"; - Database::key_type key(kKey, kKey + 3); - return key; - } - - Database::value_type TestAltValue() { - const char* kValue = "bar"; - Database::value_type value(kValue, kValue + 3); - return value; - } - - template - bool BufferEq(const T& buf1, const T& buf2) { - if (buf1.size() != buf2.size()) { - return false; - } - for (size_t i = 0; i < buf1.size(); ++i) { - if (buf1.at(i) != buf2.at(i)) { - return false; - } - } +namespace DatabaseTest_internal { - return true; - } +template +struct TestData { + static T TestValue(); + static T TestAltValue(); + static bool equals(const T& a, const T& b); }; -TYPED_TEST_CASE(DatabaseTest, TestDtypesAndDevices); - -TYPED_TEST(DatabaseTest, TestNewDoesntExistLevelDBPasses) { - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(this->DBName(), Database::New)); - database->close(); +template <> +string TestData::TestValue() { + return "world"; } -TYPED_TEST(DatabaseTest, TestNewExistsFailsLevelDB) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_FALSE(database->open(name, Database::New)); +template <> +string TestData::TestAltValue() { + return "bar"; } -TYPED_TEST(DatabaseTest, TestReadOnlyExistsLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - database->close(); +template <> +bool TestData::equals(const string& a, const string& b) { + return a == b; } -TYPED_TEST(DatabaseTest, TestReadOnlyDoesntExistFailsLevelDB) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_FALSE(database->open(name, Database::ReadOnly)); -} - -TYPED_TEST(DatabaseTest, TestReadWriteExistsLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadWrite)); - database->close(); +template <> +vector TestData >::TestValue() { + string str = "world"; + vector val(str.data(), str.data() + str.size()); + return val; } -TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); - database->close(); +template <> +vector TestData >::TestAltValue() { + string str = "bar"; + vector val(str.data(), str.data() + str.size()); + return val; } -TYPED_TEST(DatabaseTest, TestKeysLevelDB) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key1 = this->TestKey(); - Database::value_type value1 = this->TestValue(); - - EXPECT_TRUE(database->put(key1, value1)); - - Database::key_type key2 = this->TestAltKey(); - Database::value_type value2 = this->TestAltValue(); - - EXPECT_TRUE(database->put(key2, value2)); - - EXPECT_TRUE(database->commit()); - - vector keys; - database->keys(&keys); - - EXPECT_EQ(2, keys.size()); - - EXPECT_TRUE(this->BufferEq(keys.at(0), key1) || - this->BufferEq(keys.at(0), key2)); - EXPECT_TRUE(this->BufferEq(keys.at(1), key1) || - this->BufferEq(keys.at(2), key2)); - EXPECT_FALSE(this->BufferEq(keys.at(0), keys.at(1))); -} - -TYPED_TEST(DatabaseTest, TestKeysNoCommitLevelDB) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key1 = this->TestKey(); - Database::value_type value1 = this->TestValue(); - - EXPECT_TRUE(database->put(key1, value1)); - - Database::key_type key2 = this->TestAltKey(); - Database::value_type value2 = this->TestAltValue(); - - EXPECT_TRUE(database->put(key2, value2)); - - vector keys; - database->keys(&keys); - - EXPECT_EQ(0, keys.size()); -} - -TYPED_TEST(DatabaseTest, TestIteratorsLevelDB) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - const int kNumExamples = 4; - for (int i = 0; i < kNumExamples; ++i) { - stringstream ss; - ss << i; - string key = ss.str(); - ss << " here be data"; - string value = ss.str(); - Database::key_type key_buf(key.data(), key.data() + key.size()); - Database::value_type val_buf(value.data(), value.data() + value.size()); - EXPECT_TRUE(database->put(key_buf, val_buf)); +template <> +bool TestData >::equals(const vector& a, + const vector& b) { + if (a.size() != b.size()) { + return false; } - EXPECT_TRUE(database->commit()); - - int count = 0; - for (Database::const_iterator iter = database->begin(); - iter != database->end(); ++iter) { - (void)iter; - ++count; + for (size_t i = 0; i < a.size(); ++i) { + if (a.at(i) != b.at(i)) { + return false; + } } - EXPECT_EQ(kNumExamples, count); + return true; } -TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLevelDB) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key1 = this->TestAltKey(); - Database::value_type value1 = this->TestAltValue(); - - Database::key_type key2 = this->TestKey(); - Database::value_type value2 = this->TestValue(); - - EXPECT_TRUE(database->put(key1, value1)); - EXPECT_TRUE(database->put(key2, value2)); - EXPECT_TRUE(database->commit()); - - Database::const_iterator iter1 = database->begin(); - - EXPECT_FALSE(database->end() == iter1); - - EXPECT_TRUE(this->BufferEq(iter1->key, key1)); - - Database::const_iterator iter2 = ++iter1; - - EXPECT_FALSE(database->end() == iter1); - EXPECT_FALSE(database->end() == iter2); - - EXPECT_TRUE(this->BufferEq(iter2->key, key2)); - - Database::const_iterator iter3 = ++iter2; - - EXPECT_TRUE(database->end() == iter3); - - database->close(); +template <> +Datum TestData::TestValue() { + Datum datum; + datum.set_channels(3); + datum.set_height(32); + datum.set_width(32); + datum.set_data(string(32 * 32 * 3 * 4, ' ')); + datum.set_label(0); + return datum; } -TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLevelDB) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key1 = this->TestAltKey(); - Database::value_type value1 = this->TestAltValue(); - - Database::key_type key2 = this->TestKey(); - Database::value_type value2 = this->TestValue(); - - EXPECT_TRUE(database->put(key1, value1)); - EXPECT_TRUE(database->put(key2, value2)); - EXPECT_TRUE(database->commit()); - - Database::const_iterator iter1 = database->begin(); - - EXPECT_FALSE(database->end() == iter1); - - EXPECT_TRUE(this->BufferEq(iter1->key, key1)); - - Database::const_iterator iter2 = iter1++; - - EXPECT_FALSE(database->end() == iter1); - EXPECT_FALSE(database->end() == iter2); - - EXPECT_TRUE(this->BufferEq(iter2->key, key1)); - EXPECT_TRUE(this->BufferEq(iter1->key, key2)); - - Database::const_iterator iter3 = iter1++; - - EXPECT_FALSE(database->end() == iter3); - EXPECT_TRUE(this->BufferEq(iter3->key, key2)); - EXPECT_TRUE(database->end() == iter1); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestNewPutLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); - - EXPECT_TRUE(database->put(key, val)); - - EXPECT_TRUE(database->commit()); - - database->close(); +template <> +Datum TestData::TestAltValue() { + Datum datum; + datum.set_channels(1); + datum.set_height(64); + datum.set_width(64); + datum.set_data(string(64 * 64 * 1 * 4, ' ')); + datum.set_label(1); + return datum; } -TYPED_TEST(DatabaseTest, TestNewCommitLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); +template <> +bool TestData::equals(const Datum& a, const Datum& b) { + string serialized_a; + a.SerializeToString(&serialized_a); - EXPECT_TRUE(database->commit()); + string serialized_b; + b.SerializeToString(&serialized_b); - database->close(); + return serialized_a == serialized_b; } -TYPED_TEST(DatabaseTest, TestNewGetLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); - - EXPECT_TRUE(database->put(key, val)); - - EXPECT_TRUE(database->commit()); - - Database::value_type new_val; - - EXPECT_TRUE(database->get(key, &new_val)); - - EXPECT_TRUE(this->BufferEq(val, new_val)); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestNewGetNoCommitLevelDBFails) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); - - EXPECT_TRUE(database->put(key, val)); +} // namespace DatabaseTest_internal - Database::value_type new_val; - - EXPECT_FALSE(database->get(key, &new_val)); -} +#define UNPACK_TYPES \ + typedef typename TypeParam::value_type value_type; \ + const DataParameter_DB backend = TypeParam::backend; +template +class DatabaseTest : public ::testing::Test { + protected: + typedef typename TypeParam::value_type value_type; -TYPED_TEST(DatabaseTest, TestReadWritePutLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); + string DBName() { + string filename; + MakeTempDir(&filename); + filename += "/db"; + return filename; + } - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string TestKey() { + return "hello"; + } - EXPECT_TRUE(database->put(key, val)); + value_type TestValue() { + return DatabaseTest_internal::TestData::TestValue(); + } - EXPECT_TRUE(database->commit()); + string TestAltKey() { + return "foo"; + } - database->close(); -} + value_type TestAltValue() { + return DatabaseTest_internal::TestData::TestAltValue(); + } -TYPED_TEST(DatabaseTest, TestReadWriteCommitLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); + template + bool equals(const T& a, const T& b) { + return DatabaseTest_internal::TestData::equals(a, b); + } +}; - EXPECT_TRUE(database->commit()); +struct StringLeveldb { + typedef string value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB StringLeveldb::backend = DataParameter_DB_LEVELDB; - database->close(); -} +struct StringLmdb { + typedef string value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB StringLmdb::backend = DataParameter_DB_LEVELDB; -TYPED_TEST(DatabaseTest, TestReadWriteGetLevelDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); +struct VectorLeveldb { + typedef vector value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB VectorLeveldb::backend = DataParameter_DB_LEVELDB; - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); +struct VectorLmdb { + typedef vector value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB VectorLmdb::backend = DataParameter_DB_LEVELDB; - EXPECT_TRUE(database->put(key, val)); +struct DatumLeveldb { + typedef Datum value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB DatumLeveldb::backend = DataParameter_DB_LEVELDB; - EXPECT_TRUE(database->commit()); +struct DatumLmdb { + typedef Datum value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB DatumLmdb::backend = DataParameter_DB_LEVELDB; - Database::value_type new_val; +typedef ::testing::Types TestTypes; - EXPECT_TRUE(database->get(key, &new_val)); +TYPED_TEST_CASE(DatabaseTest, TestTypes); - EXPECT_TRUE(this->BufferEq(val, new_val)); +TYPED_TEST(DatabaseTest, TestNewDoesntExistPasses) { + UNPACK_TYPES; + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(this->DBName(), + Database::New)); database->close(); } -TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLevelDBFails) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); - - EXPECT_TRUE(database->put(key, val)); - - Database::value_type new_val; - - EXPECT_FALSE(database->get(key, &new_val)); -} +TYPED_TEST(DatabaseTest, TestNewExistsFails) { + UNPACK_TYPES; -TYPED_TEST(DatabaseTest, TestReadOnlyPutLevelDBFails) { string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); - - EXPECT_FALSE(database->put(key, val)); + EXPECT_FALSE(database->open(name, Database::New)); } -TYPED_TEST(DatabaseTest, TestReadOnlyCommitLevelDBFails) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - - EXPECT_FALSE(database->commit()); -} +TYPED_TEST(DatabaseTest, TestReadOnlyExistsPasses) { + UNPACK_TYPES; -TYPED_TEST(DatabaseTest, TestReadOnlyGetLevelDBPasses) { string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); - - EXPECT_TRUE(database->put(key, val)); - - EXPECT_TRUE(database->commit()); - + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - - Database::value_type new_val; - - EXPECT_TRUE(database->get(key, &new_val)); - - EXPECT_TRUE(this->BufferEq(val, new_val)); -} - -TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLevelDBFails) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("leveldb"); - EXPECT_TRUE(database->open(name, Database::New)); - - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); - - EXPECT_TRUE(database->put(key, val)); - + EXPECT_TRUE(database->open(name, Database::ReadOnly)); database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - - Database::value_type new_val; - - EXPECT_FALSE(database->get(key, &new_val)); } -TYPED_TEST(DatabaseTest, TestNewDoesntExistLMDBPasses) { - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(this->DBName(), Database::New)); - database->close(); -} +TYPED_TEST(DatabaseTest, TestReadOnlyDoesntExistFails) { + UNPACK_TYPES; -TYPED_TEST(DatabaseTest, TestNewExistsFailsLMDB) { string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_FALSE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_FALSE(database->open(name, Database::ReadOnly)); } -TYPED_TEST(DatabaseTest, TestReadOnlyExistsLMDBPasses) { +TYPED_TEST(DatabaseTest, TestReadWriteExistsPasses) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - EXPECT_TRUE(database->open(name, Database::ReadOnly)); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); database->close(); } -TYPED_TEST(DatabaseTest, TestReadOnlyDoesntExistFailsLMDB) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_FALSE(database->open(name, Database::ReadOnly)); -} +TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistPasses) { + UNPACK_TYPES; -TYPED_TEST(DatabaseTest, TestReadWriteExistsLMDBPasses) { string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadWrite)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); database->close(); } -TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistLMDBPasses) { - string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); - database->close(); -} +TYPED_TEST(DatabaseTest, TestKeys) { + UNPACK_TYPES; -TYPED_TEST(DatabaseTest, TestKeysLMDB) { string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key1 = this->TestKey(); - Database::value_type value1 = this->TestValue(); + string key1 = this->TestKey(); + value_type value1 = this->TestValue(); EXPECT_TRUE(database->put(key1, value1)); - Database::key_type key2 = this->TestAltKey(); - Database::value_type value2 = this->TestAltValue(); + string key2 = this->TestAltKey(); + value_type value2 = this->TestAltValue(); EXPECT_TRUE(database->put(key2, value2)); EXPECT_TRUE(database->commit()); - vector keys; + vector keys; database->keys(&keys); EXPECT_EQ(2, keys.size()); - EXPECT_TRUE(this->BufferEq(keys.at(0), key1) || - this->BufferEq(keys.at(0), key2)); - EXPECT_TRUE(this->BufferEq(keys.at(1), key1) || - this->BufferEq(keys.at(2), key2)); - EXPECT_FALSE(this->BufferEq(keys.at(0), keys.at(1))); + EXPECT_TRUE(this->equals(keys.at(0), key1) || + this->equals(keys.at(0), key2)); + EXPECT_TRUE(this->equals(keys.at(1), key1) || + this->equals(keys.at(2), key2)); + EXPECT_FALSE(this->equals(keys.at(0), keys.at(1))); } -TYPED_TEST(DatabaseTest, TestKeysNoCommitLMDB) { +TYPED_TEST(DatabaseTest, TestKeysNoCommit) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key1 = this->TestKey(); - Database::value_type value1 = this->TestValue(); + string key1 = this->TestKey(); + value_type value1 = this->TestValue(); EXPECT_TRUE(database->put(key1, value1)); - Database::key_type key2 = this->TestAltKey(); - Database::value_type value2 = this->TestAltValue(); + string key2 = this->TestAltKey(); + value_type value2 = this->TestAltValue(); EXPECT_TRUE(database->put(key2, value2)); - vector keys; + vector keys; database->keys(&keys); EXPECT_EQ(0, keys.size()); } +TYPED_TEST(DatabaseTest, TestIterators) { + UNPACK_TYPES; -TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); const int kNumExamples = 4; for (int i = 0; i < kNumExamples; ++i) { @@ -563,16 +315,14 @@ TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { ss << i; string key = ss.str(); ss << " here be data"; - string value = ss.str(); - Database::key_type key_buf(key.data(), key.data() + key.size()); - Database::value_type val_buf(value.data(), value.data() + value.size()); - EXPECT_TRUE(database->put(key_buf, val_buf)); + value_type value = this->TestValue(); + EXPECT_TRUE(database->put(key, value)); } EXPECT_TRUE(database->commit()); int count = 0; - for (Database::const_iterator iter = database->begin(); - iter != database->end(); ++iter) { + typedef typename Database::const_iterator Iter; + for (Iter iter = database->begin(); iter != database->end(); ++iter) { (void)iter; ++count; } @@ -580,266 +330,313 @@ TYPED_TEST(DatabaseTest, TestIteratorsLMDB) { EXPECT_EQ(kNumExamples, count); } -TYPED_TEST(DatabaseTest, TestIteratorsPreIncrementLMDB) { +TYPED_TEST(DatabaseTest, TestIteratorsPreIncrement) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key1 = this->TestAltKey(); - Database::value_type value1 = this->TestAltValue(); + string key1 = this->TestAltKey(); + value_type value1 = this->TestAltValue(); - Database::key_type key2 = this->TestKey(); - Database::value_type value2 = this->TestValue(); + string key2 = this->TestKey(); + value_type value2 = this->TestValue(); EXPECT_TRUE(database->put(key1, value1)); EXPECT_TRUE(database->put(key2, value2)); EXPECT_TRUE(database->commit()); - Database::const_iterator iter1 = database->begin(); + typename Database::const_iterator iter1 = + database->begin(); EXPECT_FALSE(database->end() == iter1); - EXPECT_TRUE(this->BufferEq(iter1->key, key1)); + EXPECT_TRUE(this->equals(iter1->key, key1)); - Database::const_iterator iter2 = ++iter1; + typename Database::const_iterator iter2 = ++iter1; EXPECT_FALSE(database->end() == iter1); EXPECT_FALSE(database->end() == iter2); - EXPECT_TRUE(this->BufferEq(iter2->key, key2)); + EXPECT_TRUE(this->equals(iter2->key, key2)); - Database::const_iterator iter3 = ++iter2; + typename Database::const_iterator iter3 = ++iter2; EXPECT_TRUE(database->end() == iter3); database->close(); } -TYPED_TEST(DatabaseTest, TestIteratorsPostIncrementLMDB) { +TYPED_TEST(DatabaseTest, TestIteratorsPostIncrement) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key1 = this->TestAltKey(); - Database::value_type value1 = this->TestAltValue(); + string key1 = this->TestAltKey(); + value_type value1 = this->TestAltValue(); - Database::key_type key2 = this->TestKey(); - Database::value_type value2 = this->TestValue(); + string key2 = this->TestKey(); + value_type value2 = this->TestValue(); EXPECT_TRUE(database->put(key1, value1)); EXPECT_TRUE(database->put(key2, value2)); EXPECT_TRUE(database->commit()); - Database::const_iterator iter1 = database->begin(); + typename Database::const_iterator iter1 = + database->begin(); EXPECT_FALSE(database->end() == iter1); - EXPECT_TRUE(this->BufferEq(iter1->key, key1)); + EXPECT_TRUE(this->equals(iter1->key, key1)); - Database::const_iterator iter2 = iter1++; + typename Database::const_iterator iter2 = iter1++; EXPECT_FALSE(database->end() == iter1); EXPECT_FALSE(database->end() == iter2); - EXPECT_TRUE(this->BufferEq(iter2->key, key1)); - EXPECT_TRUE(this->BufferEq(iter1->key, key2)); + EXPECT_TRUE(this->equals(iter2->key, key1)); + EXPECT_TRUE(this->equals(iter1->key, key2)); - Database::const_iterator iter3 = iter1++; + typename Database::const_iterator iter3 = iter1++; EXPECT_FALSE(database->end() == iter3); - EXPECT_TRUE(this->BufferEq(iter3->key, key2)); + EXPECT_TRUE(this->equals(iter3->key, key2)); EXPECT_TRUE(database->end() == iter1); database->close(); } -TYPED_TEST(DatabaseTest, TestNewPutLMDBPasses) { +TYPED_TEST(DatabaseTest, TestNewPutPasses) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, val)); + EXPECT_TRUE(database->put(key, value)); EXPECT_TRUE(database->commit()); database->close(); } -TYPED_TEST(DatabaseTest, TestNewCommitLMDBPasses) { +TYPED_TEST(DatabaseTest, TestNewCommitPasses) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); EXPECT_TRUE(database->commit()); database->close(); } -TYPED_TEST(DatabaseTest, TestNewGetLMDBPasses) { +TYPED_TEST(DatabaseTest, TestNewGetPasses) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, val)); + EXPECT_TRUE(database->put(key, value)); EXPECT_TRUE(database->commit()); - Database::value_type new_val; + value_type new_value; - EXPECT_TRUE(database->get(key, &new_val)); + EXPECT_TRUE(database->get(key, &new_value)); - EXPECT_TRUE(this->BufferEq(val, new_val)); + EXPECT_TRUE(this->equals(value, new_value)); database->close(); } -TYPED_TEST(DatabaseTest, TestNewGetNoCommitLMDBFails) { +TYPED_TEST(DatabaseTest, TestNewGetNoCommitFails) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, val)); + EXPECT_TRUE(database->put(key, value)); - Database::value_type new_val; + value_type new_value; - EXPECT_FALSE(database->get(key, &new_val)); + EXPECT_FALSE(database->get(key, &new_value)); } -TYPED_TEST(DatabaseTest, TestReadWritePutLMDBPasses) { + +TYPED_TEST(DatabaseTest, TestReadWritePutPasses) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, val)); + EXPECT_TRUE(database->put(key, value)); EXPECT_TRUE(database->commit()); database->close(); } -TYPED_TEST(DatabaseTest, TestReadWriteCommitLMDBPasses) { +TYPED_TEST(DatabaseTest, TestReadWriteCommitPasses) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::ReadWrite)); EXPECT_TRUE(database->commit()); database->close(); } -TYPED_TEST(DatabaseTest, TestReadWriteGetLMDBPasses) { +TYPED_TEST(DatabaseTest, TestReadWriteGetPasses) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, val)); + EXPECT_TRUE(database->put(key, value)); EXPECT_TRUE(database->commit()); - Database::value_type new_val; + value_type new_value; - EXPECT_TRUE(database->get(key, &new_val)); + EXPECT_TRUE(database->get(key, &new_value)); - EXPECT_TRUE(this->BufferEq(val, new_val)); + EXPECT_TRUE(this->equals(value, new_value)); database->close(); } -TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitLMDBFails) { +TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitFails) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, val)); + EXPECT_TRUE(database->put(key, value)); - Database::value_type new_val; + value_type new_value; - EXPECT_FALSE(database->get(key, &new_val)); + EXPECT_FALSE(database->get(key, &new_value)); } -TYPED_TEST(DatabaseTest, TestReadOnlyPutLMDBFails) { +TYPED_TEST(DatabaseTest, TestReadOnlyPutFails) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - EXPECT_TRUE(database->open(name, Database::ReadOnly)); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_FALSE(database->put(key, val)); + EXPECT_FALSE(database->put(key, value)); } -TYPED_TEST(DatabaseTest, TestReadOnlyCommitLMDBFails) { +TYPED_TEST(DatabaseTest, TestReadOnlyCommitFails) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); database->close(); - EXPECT_TRUE(database->open(name, Database::ReadOnly)); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); EXPECT_FALSE(database->commit()); } -TYPED_TEST(DatabaseTest, TestReadOnlyGetLMDBPasses) { +TYPED_TEST(DatabaseTest, TestReadOnlyGetPasses) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, val)); + EXPECT_TRUE(database->put(key, value)); EXPECT_TRUE(database->commit()); database->close(); - EXPECT_TRUE(database->open(name, Database::ReadOnly)); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::value_type new_val; + value_type new_value; - EXPECT_TRUE(database->get(key, &new_val)); + EXPECT_TRUE(database->get(key, &new_value)); - EXPECT_TRUE(this->BufferEq(val, new_val)); + EXPECT_TRUE(this->equals(value, new_value)); } -TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitLMDBFails) { +TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitFails) { + UNPACK_TYPES; + string name = this->DBName(); - shared_ptr database = DatabaseFactory("lmdb"); - EXPECT_TRUE(database->open(name, Database::New)); + shared_ptr > database = + DatabaseFactory(backend); + EXPECT_TRUE(database->open(name, Database::New)); - Database::key_type key = this->TestKey(); - Database::value_type val = this->TestValue(); + string key = this->TestKey(); + value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, val)); + EXPECT_TRUE(database->put(key, value)); database->close(); - EXPECT_TRUE(database->open(name, Database::ReadOnly)); + EXPECT_TRUE(database->open(name, Database::ReadOnly)); - Database::value_type new_val; + value_type new_value; - EXPECT_FALSE(database->get(key, &new_val)); + EXPECT_FALSE(database->get(key, &new_value)); } +#undef UNPACK_TYPES + } // namespace caffe diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index d13c4a0f833..f1a79679091 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -26,18 +26,17 @@ int main(int argc, char** argv) { db_backend = std::string(argv[3]); } - caffe::shared_ptr database = caffe::DatabaseFactory(db_backend); + caffe::shared_ptr > database = + caffe::DatabaseFactory(db_backend); // Open db - CHECK(database->open(argv[1], Database::ReadOnly)); + CHECK(database->open(argv[1], Database::ReadOnly)); - Datum datum; BlobProto sum_blob; int count = 0; // load first datum - Database::const_iterator iter = database->begin(); - const Database::value_type& first_blob = iter->value; - datum.ParseFromArray(first_blob.data(), first_blob.size()); + Database::const_iterator iter = database->begin(); + const Datum& datum = iter->value; sum_blob.set_num(1); sum_blob.set_channels(datum.channels()); @@ -50,11 +49,10 @@ int main(int argc, char** argv) { sum_blob.add_data(0.); } LOG(INFO) << "Starting Iteration"; - for (Database::const_iterator iter = database->begin(); + for (Database::const_iterator iter = database->begin(); iter != database->end(); ++iter) { // just a dummy operation - const Database::value_type& blob = iter->value; - datum.ParseFromArray(blob.data(), blob.size()); + const Datum& datum = iter->value; const std::string& data = datum.data(); size_in_datum = std::max(datum.data().size(), datum.float_data_size()); diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 1cdca7e015a..2ba3e3c7250 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -78,10 +78,11 @@ int main(int argc, char** argv) { int resize_width = std::max(0, FLAGS_resize_width); // Open new db - shared_ptr database = DatabaseFactory(db_backend); + shared_ptr > database = + DatabaseFactory(db_backend); // Open db - CHECK(database->open(db_path, Database::New)); + CHECK(database->open(db_path, Database::New)); // Storing to db std::string root_folder(argv[1]); @@ -110,13 +111,9 @@ int main(int argc, char** argv) { // sequential int length = snprintf(key_cstr, kMaxKeyLength, "%08d_%s", line_id, lines[line_id].first.c_str()); - Database::value_type value(datum.ByteSize()); - datum.SerializeWithCachedSizesToArray( - reinterpret_cast(value.data())); - Database::key_type keystr(key_cstr, key_cstr + length); // Put in db - CHECK(database->put(keystr, value)); + CHECK(database->put(string(key_cstr, length), datum)); if (++count % 1000 == 0) { // Commit txn diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 1340192cbe4..47565a83025 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -121,11 +121,13 @@ int feature_extraction_pipeline(int argc, char** argv) { int num_mini_batches = atoi(argv[++arg_pos]); - std::vector > feature_dbs; + std::vector > > feature_dbs; for (size_t i = 0; i < num_features; ++i) { LOG(INFO)<< "Opening database " << database_names[i]; - shared_ptr database = DatabaseFactory(argv[++arg_pos]); - CHECK(database->open(database_names.at(i), Database::New)); + shared_ptr > database = + DatabaseFactory(argv[++arg_pos]); + CHECK(database->open(database_names.at(i), + Database::New)); feature_dbs.push_back(database); } @@ -155,13 +157,9 @@ int feature_extraction_pipeline(int argc, char** argv) { for (int d = 0; d < dim_features; ++d) { datum.add_float_data(feature_blob_data[d]); } - Database::value_type value(datum.ByteSize()); - datum.SerializeWithCachedSizesToArray( - reinterpret_cast(value.data())); int length = snprintf(key_str, kMaxKeyStrLength, "%d", image_indices[i]); - Database::key_type key(key_str, key_str + length); - CHECK(feature_dbs.at(i)->put(key, value)); + CHECK(feature_dbs.at(i)->put(std::string(key_str, length), datum)); ++image_indices[i]; if (image_indices[i] % 1000 == 0) { CHECK(feature_dbs.at(i)->commit()); From d275f77332e1e4a1457a520ee3deaf4d126ddfdf Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Mon, 13 Oct 2014 14:54:48 -0400 Subject: [PATCH 126/798] Renamed Database interface to Dataset. --- examples/cifar10/convert_cifar_data.cpp | 34 +- include/caffe/data_layers.hpp | 6 +- include/caffe/database_factory.hpp | 20 - include/caffe/{database.hpp => dataset.hpp} | 50 +- include/caffe/dataset_factory.hpp | 20 + ...veldb_database.hpp => leveldb_dataset.hpp} | 30 +- .../{lmdb_database.hpp => lmdb_dataset.hpp} | 32 +- src/caffe/database_factory.cpp | 50 -- src/caffe/dataset_factory.cpp | 50 ++ src/caffe/layers/data_layer.cpp | 26 +- ...veldb_database.cpp => leveldb_dataset.cpp} | 50 +- .../{lmdb_database.cpp => lmdb_dataset.cpp} | 46 +- src/caffe/test/test_data_layer.cpp | 20 +- src/caffe/test/test_database.cpp | 642 ------------------ src/caffe/test/test_dataset.cpp | 642 ++++++++++++++++++ tools/compute_image_mean.cpp | 18 +- tools/convert_imageset.cpp | 16 +- tools/extract_features.cpp | 35 +- 18 files changed, 893 insertions(+), 894 deletions(-) delete mode 100644 include/caffe/database_factory.hpp rename include/caffe/{database.hpp => dataset.hpp} (81%) create mode 100644 include/caffe/dataset_factory.hpp rename include/caffe/{leveldb_database.hpp => leveldb_dataset.hpp} (70%) rename include/caffe/{lmdb_database.hpp => lmdb_dataset.hpp} (71%) delete mode 100644 src/caffe/database_factory.cpp create mode 100644 src/caffe/dataset_factory.cpp rename src/caffe/{leveldb_database.cpp => leveldb_dataset.cpp} (78%) rename src/caffe/{lmdb_database.cpp => lmdb_dataset.cpp} (85%) delete mode 100644 src/caffe/test/test_database.cpp create mode 100644 src/caffe/test/test_dataset.cpp diff --git a/examples/cifar10/convert_cifar_data.cpp b/examples/cifar10/convert_cifar_data.cpp index f86f3936a35..9eecc74c989 100644 --- a/examples/cifar10/convert_cifar_data.cpp +++ b/examples/cifar10/convert_cifar_data.cpp @@ -13,13 +13,13 @@ #include "google/protobuf/text_format.h" #include "stdint.h" -#include "caffe/database_factory.hpp" +#include "caffe/dataset_factory.hpp" #include "caffe/proto/caffe.pb.h" using std::string; -using caffe::Database; -using caffe::DatabaseFactory; +using caffe::Dataset; +using caffe::DatasetFactory; using caffe::Datum; using caffe::shared_ptr; @@ -38,10 +38,10 @@ void read_image(std::ifstream* file, int* label, char* buffer) { void convert_dataset(const string& input_folder, const string& output_folder, const string& db_type) { - shared_ptr > train_database = - DatabaseFactory(db_type); - CHECK(train_database->open(output_folder + "/cifar10_train_" + db_type, - Database::New)); + shared_ptr > train_dataset = + DatasetFactory(db_type); + CHECK(train_dataset->open(output_folder + "/cifar10_train_" + db_type, + Dataset::New)); // Data buffer int label; char str_buffer[kCIFARImageNBytes]; @@ -64,17 +64,17 @@ void convert_dataset(const string& input_folder, const string& output_folder, datum.set_data(str_buffer, kCIFARImageNBytes); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", fileid * kCIFARBatchSize + itemid); - CHECK(train_database->put(string(str_buffer, length), datum)); + CHECK(train_dataset->put(string(str_buffer, length), datum)); } } - CHECK(train_database->commit()); - train_database->close(); + CHECK(train_dataset->commit()); + train_dataset->close(); LOG(INFO) << "Writing Testing data"; - shared_ptr > test_database = - DatabaseFactory(db_type); - CHECK(test_database->open(output_folder + "/cifar10_test_" + db_type, - Database::New)); + shared_ptr > test_dataset = + DatasetFactory(db_type); + CHECK(test_dataset->open(output_folder + "/cifar10_test_" + db_type, + Dataset::New)); // Open files std::ifstream data_file((input_folder + "/test_batch.bin").c_str(), std::ios::in | std::ios::binary); @@ -84,10 +84,10 @@ void convert_dataset(const string& input_folder, const string& output_folder, datum.set_label(label); datum.set_data(str_buffer, kCIFARImageNBytes); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); - CHECK(test_database->put(string(str_buffer, length), datum)); + CHECK(test_dataset->put(string(str_buffer, length), datum)); } - CHECK(test_database->commit()); - test_database->close(); + CHECK(test_dataset->commit()); + test_dataset->close(); } int main(int argc, char** argv) { diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index 13ba4e6f8b3..a2ea854e5ff 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -11,7 +11,7 @@ #include "caffe/blob.hpp" #include "caffe/common.hpp" #include "caffe/data_transformer.hpp" -#include "caffe/database.hpp" +#include "caffe/dataset.hpp" #include "caffe/filler.hpp" #include "caffe/internal_thread.hpp" #include "caffe/layer.hpp" @@ -100,8 +100,8 @@ class DataLayer : public BasePrefetchingDataLayer { protected: virtual void InternalThreadEntry(); - shared_ptr > database_; - Database::const_iterator iter_; + shared_ptr > dataset_; + Dataset::const_iterator iter_; }; /** diff --git a/include/caffe/database_factory.hpp b/include/caffe/database_factory.hpp deleted file mode 100644 index 30f191e76b4..00000000000 --- a/include/caffe/database_factory.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CAFFE_DATABASE_FACTORY_H_ -#define CAFFE_DATABASE_FACTORY_H_ - -#include - -#include "caffe/common.hpp" -#include "caffe/database.hpp" -#include "caffe/proto/caffe.pb.h" - -namespace caffe { - -template -shared_ptr > DatabaseFactory(const DataParameter_DB& type); - -template -shared_ptr > DatabaseFactory(const string& type); - -} // namespace caffe - -#endif // CAFFE_DATABASE_FACTORY_H_ diff --git a/include/caffe/database.hpp b/include/caffe/dataset.hpp similarity index 81% rename from include/caffe/database.hpp rename to include/caffe/dataset.hpp index 711ebdd3fa0..1f07aa9d18d 100644 --- a/include/caffe/database.hpp +++ b/include/caffe/dataset.hpp @@ -1,5 +1,5 @@ -#ifndef CAFFE_DATABASE_H_ -#define CAFFE_DATABASE_H_ +#ifndef CAFFE_DATASET_H_ +#define CAFFE_DATASET_H_ #include #include @@ -11,7 +11,7 @@ namespace caffe { -namespace database_internal { +namespace dataset_internal { template struct Coder { @@ -85,10 +85,10 @@ struct Coder > { } }; -} // namespace database_internal +} // namespace dataset_internal template -class Database { +class Dataset { public: enum Mode { New, @@ -112,8 +112,8 @@ class Database { virtual void keys(vector* keys) = 0; - Database() { } - virtual ~Database() { } + Dataset() { } + virtual ~Dataset() { } class iterator; typedef iterator const_iterator; @@ -124,7 +124,7 @@ class Database { virtual const_iterator cend() const = 0; protected: - class DatabaseState; + class DatasetState; public: class iterator : public std::iterator { @@ -137,7 +137,7 @@ class Database { iterator() : parent_(NULL) { } - iterator(const Database* parent, shared_ptr state) + iterator(const Dataset* parent, shared_ptr state) : parent_(parent), state_(state) { } ~iterator() { } @@ -145,7 +145,7 @@ class Database { iterator(const iterator& other) : parent_(other.parent_), state_(other.state_ ? other.state_->clone() - : shared_ptr()) { } + : shared_ptr()) { } iterator& operator=(iterator copy) { copy.swap(*this); @@ -184,49 +184,49 @@ class Database { } protected: - const Database* parent_; - shared_ptr state_; + const Dataset* parent_; + shared_ptr state_; }; protected: - class DatabaseState { + class DatasetState { public: - virtual ~DatabaseState() { } - virtual shared_ptr clone() = 0; + virtual ~DatasetState() { } + virtual shared_ptr clone() = 0; }; - virtual bool equal(shared_ptr state1, - shared_ptr state2) const = 0; - virtual void increment(shared_ptr* state) const = 0; + virtual bool equal(shared_ptr state1, + shared_ptr state2) const = 0; + virtual void increment(shared_ptr* state) const = 0; virtual KV& dereference( - shared_ptr state) const = 0; + shared_ptr state) const = 0; template static bool serialize(const T& obj, string* serialized) { - return database_internal::Coder::serialize(obj, serialized); + return dataset_internal::Coder::serialize(obj, serialized); } template static bool serialize(const T& obj, vector* serialized) { - return database_internal::Coder::serialize(obj, serialized); + return dataset_internal::Coder::serialize(obj, serialized); } template static bool deserialize(const string& serialized, T* obj) { - return database_internal::Coder::deserialize(serialized, obj); + return dataset_internal::Coder::deserialize(serialized, obj); } template static bool deserialize(const char* data, size_t size, T* obj) { - return database_internal::Coder::deserialize(data, size, obj); + return dataset_internal::Coder::deserialize(data, size, obj); } }; } // namespace caffe -#define INSTANTIATE_DATABASE(type) \ +#define INSTANTIATE_DATASET(type) \ template class type; \ template class type >; \ template class type; -#endif // CAFFE_DATABASE_H_ +#endif // CAFFE_DATASET_H_ diff --git a/include/caffe/dataset_factory.hpp b/include/caffe/dataset_factory.hpp new file mode 100644 index 00000000000..57db49bf524 --- /dev/null +++ b/include/caffe/dataset_factory.hpp @@ -0,0 +1,20 @@ +#ifndef CAFFE_DATASET_FACTORY_H_ +#define CAFFE_DATASET_FACTORY_H_ + +#include + +#include "caffe/common.hpp" +#include "caffe/dataset.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +template +shared_ptr > DatasetFactory(const DataParameter_DB& type); + +template +shared_ptr > DatasetFactory(const string& type); + +} // namespace caffe + +#endif // CAFFE_DATASET_FACTORY_H_ diff --git a/include/caffe/leveldb_database.hpp b/include/caffe/leveldb_dataset.hpp similarity index 70% rename from include/caffe/leveldb_database.hpp rename to include/caffe/leveldb_dataset.hpp index cd966c440cc..eb354d95db3 100644 --- a/include/caffe/leveldb_database.hpp +++ b/include/caffe/leveldb_dataset.hpp @@ -1,5 +1,5 @@ -#ifndef CAFFE_LEVELDB_DATABASE_H_ -#define CAFFE_LEVELDB_DATABASE_H_ +#ifndef CAFFE_LEVELDB_DATASET_H_ +#define CAFFE_LEVELDB_DATASET_H_ #include #include @@ -9,17 +9,17 @@ #include #include "caffe/common.hpp" -#include "caffe/database.hpp" +#include "caffe/dataset.hpp" namespace caffe { template -class LeveldbDatabase : public Database { +class LeveldbDataset : public Dataset { public: - typedef Database Base; + typedef Dataset Base; typedef typename Base::key_type key_type; typedef typename Base::value_type value_type; - typedef typename Base::DatabaseState DatabaseState; + typedef typename Base::DatasetState DatasetState; typedef typename Base::Mode Mode; typedef typename Base::const_iterator const_iterator; typedef typename Base::KV KV; @@ -38,11 +38,11 @@ class LeveldbDatabase : public Database { const_iterator cend() const; protected: - class LeveldbState : public DatabaseState { + class LeveldbState : public DatasetState { public: explicit LeveldbState(shared_ptr db, shared_ptr iter) - : DatabaseState(), + : DatasetState(), db_(db), iter_(iter) { } @@ -54,7 +54,7 @@ class LeveldbDatabase : public Database { db_.reset(); } - shared_ptr clone() { + shared_ptr clone() { shared_ptr new_iter; if (iter_.get()) { @@ -64,7 +64,7 @@ class LeveldbDatabase : public Database { CHECK(new_iter->Valid()); } - return shared_ptr(new LeveldbState(db_, new_iter)); + return shared_ptr(new LeveldbState(db_, new_iter)); } shared_ptr db_; @@ -72,10 +72,10 @@ class LeveldbDatabase : public Database { KV kv_pair_; }; - bool equal(shared_ptr state1, - shared_ptr state2) const; - void increment(shared_ptr* state) const; - KV& dereference(shared_ptr state) const; + bool equal(shared_ptr state1, + shared_ptr state2) const; + void increment(shared_ptr* state) const; + KV& dereference(shared_ptr state) const; shared_ptr db_; shared_ptr batch_; @@ -84,4 +84,4 @@ class LeveldbDatabase : public Database { } // namespace caffe -#endif // CAFFE_LEVELDB_DATABASE_H_ +#endif // CAFFE_LEVELDB_DATASET_H_ diff --git a/include/caffe/lmdb_database.hpp b/include/caffe/lmdb_dataset.hpp similarity index 71% rename from include/caffe/lmdb_database.hpp rename to include/caffe/lmdb_dataset.hpp index b5a02ca46a7..57da5dea829 100644 --- a/include/caffe/lmdb_database.hpp +++ b/include/caffe/lmdb_dataset.hpp @@ -1,5 +1,5 @@ -#ifndef CAFFE_LMDB_DATABASE_H_ -#define CAFFE_LMDB_DATABASE_H_ +#ifndef CAFFE_LMDB_DATASET_H_ +#define CAFFE_LMDB_DATASET_H_ #include #include @@ -8,22 +8,22 @@ #include "lmdb.h" #include "caffe/common.hpp" -#include "caffe/database.hpp" +#include "caffe/dataset.hpp" namespace caffe { template -class LmdbDatabase : public Database { +class LmdbDataset : public Dataset { public: - typedef Database Base; + typedef Dataset Base; typedef typename Base::key_type key_type; typedef typename Base::value_type value_type; - typedef typename Base::DatabaseState DatabaseState; + typedef typename Base::DatasetState DatasetState; typedef typename Base::Mode Mode; typedef typename Base::const_iterator const_iterator; typedef typename Base::KV KV; - LmdbDatabase() + LmdbDataset() : env_(NULL), dbi_(0), txn_(NULL) { } @@ -42,15 +42,15 @@ class LmdbDatabase : public Database { const_iterator cend() const; protected: - class LmdbState : public DatabaseState { + class LmdbState : public DatasetState { public: explicit LmdbState(MDB_cursor* cursor, MDB_txn* txn, const MDB_dbi* dbi) - : DatabaseState(), + : DatasetState(), cursor_(cursor), txn_(txn), dbi_(dbi) { } - shared_ptr clone() { + shared_ptr clone() { MDB_cursor* new_cursor; if (cursor_) { @@ -67,7 +67,7 @@ class LmdbDatabase : public Database { new_cursor = cursor_; } - return shared_ptr(new LmdbState(new_cursor, txn_, dbi_)); + return shared_ptr(new LmdbState(new_cursor, txn_, dbi_)); } MDB_cursor* cursor_; @@ -76,10 +76,10 @@ class LmdbDatabase : public Database { KV kv_pair_; }; - bool equal(shared_ptr state1, - shared_ptr state2) const; - void increment(shared_ptr* state) const; - KV& dereference(shared_ptr state) const; + bool equal(shared_ptr state1, + shared_ptr state2) const; + void increment(shared_ptr* state) const; + KV& dereference(shared_ptr state) const; MDB_env* env_; MDB_dbi dbi_; @@ -88,4 +88,4 @@ class LmdbDatabase : public Database { } // namespace caffe -#endif // CAFFE_LMDB_DATABASE_H_ +#endif // CAFFE_LMDB_DATASET_H_ diff --git a/src/caffe/database_factory.cpp b/src/caffe/database_factory.cpp deleted file mode 100644 index 4ccd429ef97..00000000000 --- a/src/caffe/database_factory.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include - -#include "caffe/database_factory.hpp" -#include "caffe/leveldb_database.hpp" -#include "caffe/lmdb_database.hpp" - -namespace caffe { - -template -shared_ptr > DatabaseFactory(const DataParameter_DB& type) { - switch (type) { - case DataParameter_DB_LEVELDB: - return shared_ptr >(new LeveldbDatabase()); - case DataParameter_DB_LMDB: - return shared_ptr >(new LmdbDatabase()); - default: - LOG(FATAL) << "Unknown database type " << type; - return shared_ptr >(); - } -} - -template -shared_ptr > DatabaseFactory(const string& type) { - if ("leveldb" == type) { - return DatabaseFactory(DataParameter_DB_LEVELDB); - } else if ("lmdb" == type) { - return DatabaseFactory(DataParameter_DB_LMDB); - } else { - LOG(FATAL) << "Unknown database type " << type; - return shared_ptr >(); - } -} - -#define REGISTER_DATABASE(key_type, value_type) \ - template shared_ptr > \ - DatabaseFactory(const string& type); \ - template shared_ptr > \ - DatabaseFactory(const DataParameter_DB& type); \ - -REGISTER_DATABASE(string, string); -REGISTER_DATABASE(string, vector); -REGISTER_DATABASE(string, Datum); - -#undef REGISTER_DATABASE - -} // namespace caffe - - diff --git a/src/caffe/dataset_factory.cpp b/src/caffe/dataset_factory.cpp new file mode 100644 index 00000000000..3313de3c408 --- /dev/null +++ b/src/caffe/dataset_factory.cpp @@ -0,0 +1,50 @@ +#include +#include +#include + +#include "caffe/dataset_factory.hpp" +#include "caffe/leveldb_dataset.hpp" +#include "caffe/lmdb_dataset.hpp" + +namespace caffe { + +template +shared_ptr > DatasetFactory(const DataParameter_DB& type) { + switch (type) { + case DataParameter_DB_LEVELDB: + return shared_ptr >(new LeveldbDataset()); + case DataParameter_DB_LMDB: + return shared_ptr >(new LmdbDataset()); + default: + LOG(FATAL) << "Unknown dataset type " << type; + return shared_ptr >(); + } +} + +template +shared_ptr > DatasetFactory(const string& type) { + if ("leveldb" == type) { + return DatasetFactory(DataParameter_DB_LEVELDB); + } else if ("lmdb" == type) { + return DatasetFactory(DataParameter_DB_LMDB); + } else { + LOG(FATAL) << "Unknown dataset type " << type; + return shared_ptr >(); + } +} + +#define REGISTER_DATASET(key_type, value_type) \ + template shared_ptr > \ + DatasetFactory(const string& type); \ + template shared_ptr > \ + DatasetFactory(const DataParameter_DB& type); \ + +REGISTER_DATASET(string, string); +REGISTER_DATASET(string, vector); +REGISTER_DATASET(string, Datum); + +#undef REGISTER_DATASET + +} // namespace caffe + + diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 6296335276e..fcf9bb20a57 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -5,7 +5,7 @@ #include "caffe/common.hpp" #include "caffe/data_layers.hpp" -#include "caffe/database_factory.hpp" +#include "caffe/dataset_factory.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" @@ -17,20 +17,20 @@ namespace caffe { template DataLayer::~DataLayer() { this->JoinPrefetchThread(); - // clean up the database resources - database_->close(); + // clean up the dataset resources + dataset_->close(); } template void DataLayer::DataLayerSetUp(const vector*>& bottom, const vector*>& top) { // Initialize DB - database_ = DatabaseFactory( + dataset_ = DatasetFactory( this->layer_param_.data_param().backend()); const string& source = this->layer_param_.data_param().source(); - LOG(INFO) << "Opening database " << source; - CHECK(database_->open(source, Database::ReadOnly)); - iter_ = database_->begin(); + LOG(INFO) << "Opening dataset " << source; + CHECK(dataset_->open(source, Dataset::ReadOnly)); + iter_ = dataset_->begin(); // Check if we would need to randomly skip a few data points if (this->layer_param_.data_param().rand_skip()) { @@ -38,13 +38,13 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, this->layer_param_.data_param().rand_skip(); LOG(INFO) << "Skipping first " << skip << " data points."; while (skip-- > 0) { - if (++iter_ == database_->end()) { - iter_ = database_->begin(); + if (++iter_ == dataset_->end()) { + iter_ = dataset_->begin(); } } } // Read a data point, and use it to initialize the top blob. - CHECK(iter_ != database_->end()); + CHECK(iter_ != dataset_->end()); const Datum& datum = iter_->value; // image @@ -89,7 +89,7 @@ void DataLayer::InternalThreadEntry() { const int batch_size = this->layer_param_.data_param().batch_size(); for (int item_id = 0; item_id < batch_size; ++item_id) { - CHECK(iter_ != database_->end()); + CHECK(iter_ != dataset_->end()); const Datum& datum = iter_->value; // Apply data transformations (mirror, scale, crop...) @@ -102,8 +102,8 @@ void DataLayer::InternalThreadEntry() { // go to the next iter ++iter_; - if (iter_ == database_->end()) { - iter_ = database_->begin(); + if (iter_ == dataset_->end()) { + iter_ = dataset_->begin(); } } } diff --git a/src/caffe/leveldb_database.cpp b/src/caffe/leveldb_dataset.cpp similarity index 78% rename from src/caffe/leveldb_database.cpp rename to src/caffe/leveldb_dataset.cpp index 267ddf07330..41c71e44557 100644 --- a/src/caffe/leveldb_database.cpp +++ b/src/caffe/leveldb_dataset.cpp @@ -3,12 +3,12 @@ #include #include "caffe/caffe.hpp" -#include "caffe/leveldb_database.hpp" +#include "caffe/leveldb_dataset.hpp" namespace caffe { template -bool LeveldbDatabase::open(const string& filename, Mode mode) { +bool LeveldbDataset::open(const string& filename, Mode mode) { DLOG(INFO) << "LevelDB: Open " << filename; leveldb::Options options; @@ -55,11 +55,11 @@ bool LeveldbDatabase::open(const string& filename, Mode mode) { } template -bool LeveldbDatabase::put(const K& key, const V& value) { +bool LeveldbDataset::put(const K& key, const V& value) { DLOG(INFO) << "LevelDB: Put"; if (read_only_) { - LOG(ERROR) << "put can not be used on a database in ReadOnly mode"; + LOG(ERROR) << "put can not be used on a dataset in ReadOnly mode"; return false; } @@ -81,7 +81,7 @@ bool LeveldbDatabase::put(const K& key, const V& value) { } template -bool LeveldbDatabase::get(const K& key, V* value) { +bool LeveldbDataset::get(const K& key, V* value) { DLOG(INFO) << "LevelDB: Get"; string serialized_key; @@ -106,11 +106,11 @@ bool LeveldbDatabase::get(const K& key, V* value) { } template -bool LeveldbDatabase::commit() { +bool LeveldbDataset::commit() { DLOG(INFO) << "LevelDB: Commit"; if (read_only_) { - LOG(ERROR) << "commit can not be used on a database in ReadOnly mode"; + LOG(ERROR) << "commit can not be used on a dataset in ReadOnly mode"; return false; } @@ -125,7 +125,7 @@ bool LeveldbDatabase::commit() { } template -void LeveldbDatabase::close() { +void LeveldbDataset::close() { DLOG(INFO) << "LevelDB: Close"; batch_.reset(); @@ -133,7 +133,7 @@ void LeveldbDatabase::close() { } template -void LeveldbDatabase::keys(vector* keys) { +void LeveldbDataset::keys(vector* keys) { DLOG(INFO) << "LevelDB: Keys"; keys->clear(); @@ -143,8 +143,8 @@ void LeveldbDatabase::keys(vector* keys) { } template -typename LeveldbDatabase::const_iterator - LeveldbDatabase::begin() const { +typename LeveldbDataset::const_iterator + LeveldbDataset::begin() const { CHECK_NOTNULL(db_.get()); shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); iter->SeekToFirst(); @@ -152,7 +152,7 @@ typename LeveldbDatabase::const_iterator iter.reset(); } - shared_ptr state; + shared_ptr state; if (iter) { state.reset(new LeveldbState(db_, iter)); } @@ -160,25 +160,25 @@ typename LeveldbDatabase::const_iterator } template -typename LeveldbDatabase::const_iterator - LeveldbDatabase::end() const { - shared_ptr state; +typename LeveldbDataset::const_iterator + LeveldbDataset::end() const { + shared_ptr state; return const_iterator(this, state); } template -typename LeveldbDatabase::const_iterator - LeveldbDatabase::cbegin() const { +typename LeveldbDataset::const_iterator + LeveldbDataset::cbegin() const { return begin(); } template -typename LeveldbDatabase::const_iterator - LeveldbDatabase::cend() const { return end(); } +typename LeveldbDataset::const_iterator + LeveldbDataset::cend() const { return end(); } template -bool LeveldbDatabase::equal(shared_ptr state1, - shared_ptr state2) const { +bool LeveldbDataset::equal(shared_ptr state1, + shared_ptr state2) const { shared_ptr leveldb_state1 = boost::dynamic_pointer_cast(state1); @@ -192,7 +192,7 @@ bool LeveldbDatabase::equal(shared_ptr state1, } template -void LeveldbDatabase::increment(shared_ptr* state) const { +void LeveldbDataset::increment(shared_ptr* state) const { shared_ptr leveldb_state = boost::dynamic_pointer_cast(*state); @@ -210,8 +210,8 @@ void LeveldbDatabase::increment(shared_ptr* state) const { } template -typename Database::KV& LeveldbDatabase::dereference( - shared_ptr state) const { +typename Dataset::KV& LeveldbDataset::dereference( + shared_ptr state) const { shared_ptr leveldb_state = boost::dynamic_pointer_cast(state); @@ -233,6 +233,6 @@ typename Database::KV& LeveldbDatabase::dereference( return leveldb_state->kv_pair_; } -INSTANTIATE_DATABASE(LeveldbDatabase); +INSTANTIATE_DATASET(LeveldbDataset); } // namespace caffe diff --git a/src/caffe/lmdb_database.cpp b/src/caffe/lmdb_dataset.cpp similarity index 85% rename from src/caffe/lmdb_database.cpp rename to src/caffe/lmdb_dataset.cpp index 22a08b2a580..d2b6fcd1c85 100644 --- a/src/caffe/lmdb_database.cpp +++ b/src/caffe/lmdb_dataset.cpp @@ -5,12 +5,12 @@ #include #include "caffe/caffe.hpp" -#include "caffe/lmdb_database.hpp" +#include "caffe/lmdb_dataset.hpp" namespace caffe { template -bool LmdbDatabase::open(const string& filename, Mode mode) { +bool LmdbDataset::open(const string& filename, Mode mode) { DLOG(INFO) << "LMDB: Open " << filename; CHECK(NULL == env_); @@ -81,7 +81,7 @@ bool LmdbDatabase::open(const string& filename, Mode mode) { } template -bool LmdbDatabase::put(const K& key, const V& value) { +bool LmdbDataset::put(const K& key, const V& value) { DLOG(INFO) << "LMDB: Put"; vector serialized_key; @@ -115,7 +115,7 @@ bool LmdbDatabase::put(const K& key, const V& value) { } template -bool LmdbDatabase::get(const K& key, V* value) { +bool LmdbDataset::get(const K& key, V* value) { DLOG(INFO) << "LMDB: Get"; vector serialized_key; @@ -154,7 +154,7 @@ bool LmdbDatabase::get(const K& key, V* value) { } template -bool LmdbDatabase::commit() { +bool LmdbDataset::commit() { DLOG(INFO) << "LMDB: Commit"; CHECK_NOTNULL(txn_); @@ -176,7 +176,7 @@ bool LmdbDatabase::commit() { } template -void LmdbDatabase::close() { +void LmdbDataset::close() { DLOG(INFO) << "LMDB: Close"; if (env_ && dbi_) { @@ -189,7 +189,7 @@ void LmdbDatabase::close() { } template -void LmdbDatabase::keys(vector* keys) { +void LmdbDataset::keys(vector* keys) { DLOG(INFO) << "LMDB: Keys"; keys->clear(); @@ -199,8 +199,8 @@ void LmdbDatabase::keys(vector* keys) { } template -typename LmdbDatabase::const_iterator - LmdbDatabase::begin() const { +typename LmdbDataset::const_iterator + LmdbDataset::begin() const { int retval; MDB_txn* iter_txn; @@ -219,7 +219,7 @@ typename LmdbDatabase::const_iterator CHECK(MDB_SUCCESS == retval || MDB_NOTFOUND == retval) << mdb_strerror(retval); - shared_ptr state; + shared_ptr state; if (MDB_SUCCESS == retval) { state.reset(new LmdbState(cursor, iter_txn, &dbi_)); } @@ -227,23 +227,23 @@ typename LmdbDatabase::const_iterator } template -typename LmdbDatabase::const_iterator - LmdbDatabase::end() const { - shared_ptr state; +typename LmdbDataset::const_iterator + LmdbDataset::end() const { + shared_ptr state; return const_iterator(this, state); } template -typename LmdbDatabase::const_iterator - LmdbDatabase::cbegin() const { return begin(); } +typename LmdbDataset::const_iterator + LmdbDataset::cbegin() const { return begin(); } template -typename LmdbDatabase::const_iterator - LmdbDatabase::cend() const { return end(); } +typename LmdbDataset::const_iterator + LmdbDataset::cend() const { return end(); } template -bool LmdbDatabase::equal(shared_ptr state1, - shared_ptr state2) const { +bool LmdbDataset::equal(shared_ptr state1, + shared_ptr state2) const { shared_ptr lmdb_state1 = boost::dynamic_pointer_cast(state1); @@ -257,7 +257,7 @@ bool LmdbDatabase::equal(shared_ptr state1, } template -void LmdbDatabase::increment(shared_ptr* state) const { +void LmdbDataset::increment(shared_ptr* state) const { shared_ptr lmdb_state = boost::dynamic_pointer_cast(*state); @@ -279,8 +279,8 @@ void LmdbDatabase::increment(shared_ptr* state) const { } template -typename Database::KV& LmdbDatabase::dereference( - shared_ptr state) const { +typename Dataset::KV& LmdbDataset::dereference( + shared_ptr state) const { shared_ptr lmdb_state = boost::dynamic_pointer_cast(state); @@ -303,6 +303,6 @@ typename Database::KV& LmdbDatabase::dereference( return lmdb_state->kv_pair_; } -INSTANTIATE_DATABASE(LmdbDatabase); +INSTANTIATE_DATASET(LmdbDataset); } // namespace caffe diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index 1c3ec1fc576..32f5d41e2f2 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -5,7 +5,7 @@ #include "caffe/blob.hpp" #include "caffe/common.hpp" -#include "caffe/database_factory.hpp" +#include "caffe/dataset_factory.hpp" #include "caffe/filler.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" @@ -38,10 +38,10 @@ class DataLayerTest : public MultiDeviceTest { // an image are the same. void Fill(const bool unique_pixels, DataParameter_DB backend) { backend_ = backend; - LOG(INFO) << "Using temporary database " << *filename_; - shared_ptr > database = - DatabaseFactory(backend_); - CHECK(database->open(*filename_, Database::New)); + LOG(INFO) << "Using temporary dataset " << *filename_; + shared_ptr > dataset = + DatasetFactory(backend_); + CHECK(dataset->open(*filename_, Dataset::New)); for (int i = 0; i < 5; ++i) { Datum datum; datum.set_label(i); @@ -55,10 +55,10 @@ class DataLayerTest : public MultiDeviceTest { } stringstream ss; ss << i; - CHECK(database->put(ss.str(), datum)); + CHECK(dataset->put(ss.str(), datum)); } - CHECK(database->commit()); - database->close(); + CHECK(dataset->commit()); + dataset->close(); } void TestRead() { @@ -183,7 +183,7 @@ class DataLayerTest : public MultiDeviceTest { } crop_sequence.push_back(iter_crop_sequence); } - } // destroy 1st data layer and unlock the database + } // destroy 1st data layer and unlock the dataset // Get crop sequence after reseeding Caffe with 1701. // Check that the sequence is the same as the original. @@ -238,7 +238,7 @@ class DataLayerTest : public MultiDeviceTest { } crop_sequence.push_back(iter_crop_sequence); } - } // destroy 1st data layer and unlock the database + } // destroy 1st data layer and unlock the dataset // Get crop sequence continuing from previous Caffe RNG state; reseed // srand with 1701. Check that the sequence differs from the original. diff --git a/src/caffe/test/test_database.cpp b/src/caffe/test/test_database.cpp deleted file mode 100644 index 9a7d6dec8c7..00000000000 --- a/src/caffe/test/test_database.cpp +++ /dev/null @@ -1,642 +0,0 @@ -#include -#include - -#include "caffe/util/io.hpp" - -#include "gtest/gtest.h" - -#include "caffe/database_factory.hpp" - -#include "caffe/test/test_caffe_main.hpp" - -namespace caffe { - -namespace DatabaseTest_internal { - -template -struct TestData { - static T TestValue(); - static T TestAltValue(); - static bool equals(const T& a, const T& b); -}; - -template <> -string TestData::TestValue() { - return "world"; -} - -template <> -string TestData::TestAltValue() { - return "bar"; -} - -template <> -bool TestData::equals(const string& a, const string& b) { - return a == b; -} - -template <> -vector TestData >::TestValue() { - string str = "world"; - vector val(str.data(), str.data() + str.size()); - return val; -} - -template <> -vector TestData >::TestAltValue() { - string str = "bar"; - vector val(str.data(), str.data() + str.size()); - return val; -} - -template <> -bool TestData >::equals(const vector& a, - const vector& b) { - if (a.size() != b.size()) { - return false; - } - for (size_t i = 0; i < a.size(); ++i) { - if (a.at(i) != b.at(i)) { - return false; - } - } - - return true; -} - -template <> -Datum TestData::TestValue() { - Datum datum; - datum.set_channels(3); - datum.set_height(32); - datum.set_width(32); - datum.set_data(string(32 * 32 * 3 * 4, ' ')); - datum.set_label(0); - return datum; -} - -template <> -Datum TestData::TestAltValue() { - Datum datum; - datum.set_channels(1); - datum.set_height(64); - datum.set_width(64); - datum.set_data(string(64 * 64 * 1 * 4, ' ')); - datum.set_label(1); - return datum; -} - -template <> -bool TestData::equals(const Datum& a, const Datum& b) { - string serialized_a; - a.SerializeToString(&serialized_a); - - string serialized_b; - b.SerializeToString(&serialized_b); - - return serialized_a == serialized_b; -} - -} // namespace DatabaseTest_internal - -#define UNPACK_TYPES \ - typedef typename TypeParam::value_type value_type; \ - const DataParameter_DB backend = TypeParam::backend; - -template -class DatabaseTest : public ::testing::Test { - protected: - typedef typename TypeParam::value_type value_type; - - string DBName() { - string filename; - MakeTempDir(&filename); - filename += "/db"; - return filename; - } - - string TestKey() { - return "hello"; - } - - value_type TestValue() { - return DatabaseTest_internal::TestData::TestValue(); - } - - string TestAltKey() { - return "foo"; - } - - value_type TestAltValue() { - return DatabaseTest_internal::TestData::TestAltValue(); - } - - template - bool equals(const T& a, const T& b) { - return DatabaseTest_internal::TestData::equals(a, b); - } -}; - -struct StringLeveldb { - typedef string value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB StringLeveldb::backend = DataParameter_DB_LEVELDB; - -struct StringLmdb { - typedef string value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB StringLmdb::backend = DataParameter_DB_LEVELDB; - -struct VectorLeveldb { - typedef vector value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB VectorLeveldb::backend = DataParameter_DB_LEVELDB; - -struct VectorLmdb { - typedef vector value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB VectorLmdb::backend = DataParameter_DB_LEVELDB; - -struct DatumLeveldb { - typedef Datum value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB DatumLeveldb::backend = DataParameter_DB_LEVELDB; - -struct DatumLmdb { - typedef Datum value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB DatumLmdb::backend = DataParameter_DB_LEVELDB; - -typedef ::testing::Types TestTypes; - -TYPED_TEST_CASE(DatabaseTest, TestTypes); - -TYPED_TEST(DatabaseTest, TestNewDoesntExistPasses) { - UNPACK_TYPES; - - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(this->DBName(), - Database::New)); - database->close(); -} - -TYPED_TEST(DatabaseTest, TestNewExistsFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_FALSE(database->open(name, Database::New)); -} - -TYPED_TEST(DatabaseTest, TestReadOnlyExistsPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - database->close(); -} - -TYPED_TEST(DatabaseTest, TestReadOnlyDoesntExistFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_FALSE(database->open(name, Database::ReadOnly)); -} - -TYPED_TEST(DatabaseTest, TestReadWriteExistsPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadWrite)); - database->close(); -} - -TYPED_TEST(DatabaseTest, TestReadWriteDoesntExistPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); - database->close(); -} - -TYPED_TEST(DatabaseTest, TestKeys) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key1 = this->TestKey(); - value_type value1 = this->TestValue(); - - EXPECT_TRUE(database->put(key1, value1)); - - string key2 = this->TestAltKey(); - value_type value2 = this->TestAltValue(); - - EXPECT_TRUE(database->put(key2, value2)); - - EXPECT_TRUE(database->commit()); - - vector keys; - database->keys(&keys); - - EXPECT_EQ(2, keys.size()); - - EXPECT_TRUE(this->equals(keys.at(0), key1) || - this->equals(keys.at(0), key2)); - EXPECT_TRUE(this->equals(keys.at(1), key1) || - this->equals(keys.at(2), key2)); - EXPECT_FALSE(this->equals(keys.at(0), keys.at(1))); -} - -TYPED_TEST(DatabaseTest, TestKeysNoCommit) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key1 = this->TestKey(); - value_type value1 = this->TestValue(); - - EXPECT_TRUE(database->put(key1, value1)); - - string key2 = this->TestAltKey(); - value_type value2 = this->TestAltValue(); - - EXPECT_TRUE(database->put(key2, value2)); - - vector keys; - database->keys(&keys); - - EXPECT_EQ(0, keys.size()); -} - -TYPED_TEST(DatabaseTest, TestIterators) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - const int kNumExamples = 4; - for (int i = 0; i < kNumExamples; ++i) { - stringstream ss; - ss << i; - string key = ss.str(); - ss << " here be data"; - value_type value = this->TestValue(); - EXPECT_TRUE(database->put(key, value)); - } - EXPECT_TRUE(database->commit()); - - int count = 0; - typedef typename Database::const_iterator Iter; - for (Iter iter = database->begin(); iter != database->end(); ++iter) { - (void)iter; - ++count; - } - - EXPECT_EQ(kNumExamples, count); -} - -TYPED_TEST(DatabaseTest, TestIteratorsPreIncrement) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key1 = this->TestAltKey(); - value_type value1 = this->TestAltValue(); - - string key2 = this->TestKey(); - value_type value2 = this->TestValue(); - - EXPECT_TRUE(database->put(key1, value1)); - EXPECT_TRUE(database->put(key2, value2)); - EXPECT_TRUE(database->commit()); - - typename Database::const_iterator iter1 = - database->begin(); - - EXPECT_FALSE(database->end() == iter1); - - EXPECT_TRUE(this->equals(iter1->key, key1)); - - typename Database::const_iterator iter2 = ++iter1; - - EXPECT_FALSE(database->end() == iter1); - EXPECT_FALSE(database->end() == iter2); - - EXPECT_TRUE(this->equals(iter2->key, key2)); - - typename Database::const_iterator iter3 = ++iter2; - - EXPECT_TRUE(database->end() == iter3); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestIteratorsPostIncrement) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key1 = this->TestAltKey(); - value_type value1 = this->TestAltValue(); - - string key2 = this->TestKey(); - value_type value2 = this->TestValue(); - - EXPECT_TRUE(database->put(key1, value1)); - EXPECT_TRUE(database->put(key2, value2)); - EXPECT_TRUE(database->commit()); - - typename Database::const_iterator iter1 = - database->begin(); - - EXPECT_FALSE(database->end() == iter1); - - EXPECT_TRUE(this->equals(iter1->key, key1)); - - typename Database::const_iterator iter2 = iter1++; - - EXPECT_FALSE(database->end() == iter1); - EXPECT_FALSE(database->end() == iter2); - - EXPECT_TRUE(this->equals(iter2->key, key1)); - EXPECT_TRUE(this->equals(iter1->key, key2)); - - typename Database::const_iterator iter3 = iter1++; - - EXPECT_FALSE(database->end() == iter3); - EXPECT_TRUE(this->equals(iter3->key, key2)); - EXPECT_TRUE(database->end() == iter1); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestNewPutPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(database->put(key, value)); - - EXPECT_TRUE(database->commit()); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestNewCommitPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - EXPECT_TRUE(database->commit()); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestNewGetPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(database->put(key, value)); - - EXPECT_TRUE(database->commit()); - - value_type new_value; - - EXPECT_TRUE(database->get(key, &new_value)); - - EXPECT_TRUE(this->equals(value, new_value)); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestNewGetNoCommitFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(database->put(key, value)); - - value_type new_value; - - EXPECT_FALSE(database->get(key, &new_value)); -} - - -TYPED_TEST(DatabaseTest, TestReadWritePutPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(database->put(key, value)); - - EXPECT_TRUE(database->commit()); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestReadWriteCommitPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::ReadWrite)); - - EXPECT_TRUE(database->commit()); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestReadWriteGetPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(database->put(key, value)); - - EXPECT_TRUE(database->commit()); - - value_type new_value; - - EXPECT_TRUE(database->get(key, &new_value)); - - EXPECT_TRUE(this->equals(value, new_value)); - - database->close(); -} - -TYPED_TEST(DatabaseTest, TestReadWriteGetNoCommitFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(database->put(key, value)); - - value_type new_value; - - EXPECT_FALSE(database->get(key, &new_value)); -} - -TYPED_TEST(DatabaseTest, TestReadOnlyPutFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_FALSE(database->put(key, value)); -} - -TYPED_TEST(DatabaseTest, TestReadOnlyCommitFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - - EXPECT_FALSE(database->commit()); -} - -TYPED_TEST(DatabaseTest, TestReadOnlyGetPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(database->put(key, value)); - - EXPECT_TRUE(database->commit()); - - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - - value_type new_value; - - EXPECT_TRUE(database->get(key, &new_value)); - - EXPECT_TRUE(this->equals(value, new_value)); -} - -TYPED_TEST(DatabaseTest, TestReadOnlyGetNoCommitFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > database = - DatabaseFactory(backend); - EXPECT_TRUE(database->open(name, Database::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(database->put(key, value)); - - database->close(); - - EXPECT_TRUE(database->open(name, Database::ReadOnly)); - - value_type new_value; - - EXPECT_FALSE(database->get(key, &new_value)); -} - -#undef UNPACK_TYPES - -} // namespace caffe diff --git a/src/caffe/test/test_dataset.cpp b/src/caffe/test/test_dataset.cpp new file mode 100644 index 00000000000..bb6cf4ce616 --- /dev/null +++ b/src/caffe/test/test_dataset.cpp @@ -0,0 +1,642 @@ +#include +#include + +#include "caffe/util/io.hpp" + +#include "gtest/gtest.h" + +#include "caffe/dataset_factory.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +namespace DatasetTest_internal { + +template +struct TestData { + static T TestValue(); + static T TestAltValue(); + static bool equals(const T& a, const T& b); +}; + +template <> +string TestData::TestValue() { + return "world"; +} + +template <> +string TestData::TestAltValue() { + return "bar"; +} + +template <> +bool TestData::equals(const string& a, const string& b) { + return a == b; +} + +template <> +vector TestData >::TestValue() { + string str = "world"; + vector val(str.data(), str.data() + str.size()); + return val; +} + +template <> +vector TestData >::TestAltValue() { + string str = "bar"; + vector val(str.data(), str.data() + str.size()); + return val; +} + +template <> +bool TestData >::equals(const vector& a, + const vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (a.at(i) != b.at(i)) { + return false; + } + } + + return true; +} + +template <> +Datum TestData::TestValue() { + Datum datum; + datum.set_channels(3); + datum.set_height(32); + datum.set_width(32); + datum.set_data(string(32 * 32 * 3 * 4, ' ')); + datum.set_label(0); + return datum; +} + +template <> +Datum TestData::TestAltValue() { + Datum datum; + datum.set_channels(1); + datum.set_height(64); + datum.set_width(64); + datum.set_data(string(64 * 64 * 1 * 4, ' ')); + datum.set_label(1); + return datum; +} + +template <> +bool TestData::equals(const Datum& a, const Datum& b) { + string serialized_a; + a.SerializeToString(&serialized_a); + + string serialized_b; + b.SerializeToString(&serialized_b); + + return serialized_a == serialized_b; +} + +} // namespace DatasetTest_internal + +#define UNPACK_TYPES \ + typedef typename TypeParam::value_type value_type; \ + const DataParameter_DB backend = TypeParam::backend; + +template +class DatasetTest : public ::testing::Test { + protected: + typedef typename TypeParam::value_type value_type; + + string DBName() { + string filename; + MakeTempDir(&filename); + filename += "/db"; + return filename; + } + + string TestKey() { + return "hello"; + } + + value_type TestValue() { + return DatasetTest_internal::TestData::TestValue(); + } + + string TestAltKey() { + return "foo"; + } + + value_type TestAltValue() { + return DatasetTest_internal::TestData::TestAltValue(); + } + + template + bool equals(const T& a, const T& b) { + return DatasetTest_internal::TestData::equals(a, b); + } +}; + +struct StringLeveldb { + typedef string value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB StringLeveldb::backend = DataParameter_DB_LEVELDB; + +struct StringLmdb { + typedef string value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB StringLmdb::backend = DataParameter_DB_LEVELDB; + +struct VectorLeveldb { + typedef vector value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB VectorLeveldb::backend = DataParameter_DB_LEVELDB; + +struct VectorLmdb { + typedef vector value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB VectorLmdb::backend = DataParameter_DB_LEVELDB; + +struct DatumLeveldb { + typedef Datum value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB DatumLeveldb::backend = DataParameter_DB_LEVELDB; + +struct DatumLmdb { + typedef Datum value_type; + static const DataParameter_DB backend; +}; +const DataParameter_DB DatumLmdb::backend = DataParameter_DB_LEVELDB; + +typedef ::testing::Types TestTypes; + +TYPED_TEST_CASE(DatasetTest, TestTypes); + +TYPED_TEST(DatasetTest, TestNewDoesntExistPasses) { + UNPACK_TYPES; + + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(this->DBName(), + Dataset::New)); + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestNewExistsFails) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + dataset->close(); + + EXPECT_FALSE(dataset->open(name, Dataset::New)); +} + +TYPED_TEST(DatasetTest, TestReadOnlyExistsPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + dataset->close(); + + EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestReadOnlyDoesntExistFails) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_FALSE(dataset->open(name, Dataset::ReadOnly)); +} + +TYPED_TEST(DatasetTest, TestReadWriteExistsPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + dataset->close(); + + EXPECT_TRUE(dataset->open(name, Dataset::ReadWrite)); + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestReadWriteDoesntExistPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::ReadWrite)); + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestKeys) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key1 = this->TestKey(); + value_type value1 = this->TestValue(); + + EXPECT_TRUE(dataset->put(key1, value1)); + + string key2 = this->TestAltKey(); + value_type value2 = this->TestAltValue(); + + EXPECT_TRUE(dataset->put(key2, value2)); + + EXPECT_TRUE(dataset->commit()); + + vector keys; + dataset->keys(&keys); + + EXPECT_EQ(2, keys.size()); + + EXPECT_TRUE(this->equals(keys.at(0), key1) || + this->equals(keys.at(0), key2)); + EXPECT_TRUE(this->equals(keys.at(1), key1) || + this->equals(keys.at(2), key2)); + EXPECT_FALSE(this->equals(keys.at(0), keys.at(1))); +} + +TYPED_TEST(DatasetTest, TestKeysNoCommit) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key1 = this->TestKey(); + value_type value1 = this->TestValue(); + + EXPECT_TRUE(dataset->put(key1, value1)); + + string key2 = this->TestAltKey(); + value_type value2 = this->TestAltValue(); + + EXPECT_TRUE(dataset->put(key2, value2)); + + vector keys; + dataset->keys(&keys); + + EXPECT_EQ(0, keys.size()); +} + +TYPED_TEST(DatasetTest, TestIterators) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + const int kNumExamples = 4; + for (int i = 0; i < kNumExamples; ++i) { + stringstream ss; + ss << i; + string key = ss.str(); + ss << " here be data"; + value_type value = this->TestValue(); + EXPECT_TRUE(dataset->put(key, value)); + } + EXPECT_TRUE(dataset->commit()); + + int count = 0; + typedef typename Dataset::const_iterator Iter; + for (Iter iter = dataset->begin(); iter != dataset->end(); ++iter) { + (void)iter; + ++count; + } + + EXPECT_EQ(kNumExamples, count); +} + +TYPED_TEST(DatasetTest, TestIteratorsPreIncrement) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key1 = this->TestAltKey(); + value_type value1 = this->TestAltValue(); + + string key2 = this->TestKey(); + value_type value2 = this->TestValue(); + + EXPECT_TRUE(dataset->put(key1, value1)); + EXPECT_TRUE(dataset->put(key2, value2)); + EXPECT_TRUE(dataset->commit()); + + typename Dataset::const_iterator iter1 = + dataset->begin(); + + EXPECT_FALSE(dataset->end() == iter1); + + EXPECT_TRUE(this->equals(iter1->key, key1)); + + typename Dataset::const_iterator iter2 = ++iter1; + + EXPECT_FALSE(dataset->end() == iter1); + EXPECT_FALSE(dataset->end() == iter2); + + EXPECT_TRUE(this->equals(iter2->key, key2)); + + typename Dataset::const_iterator iter3 = ++iter2; + + EXPECT_TRUE(dataset->end() == iter3); + + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestIteratorsPostIncrement) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key1 = this->TestAltKey(); + value_type value1 = this->TestAltValue(); + + string key2 = this->TestKey(); + value_type value2 = this->TestValue(); + + EXPECT_TRUE(dataset->put(key1, value1)); + EXPECT_TRUE(dataset->put(key2, value2)); + EXPECT_TRUE(dataset->commit()); + + typename Dataset::const_iterator iter1 = + dataset->begin(); + + EXPECT_FALSE(dataset->end() == iter1); + + EXPECT_TRUE(this->equals(iter1->key, key1)); + + typename Dataset::const_iterator iter2 = iter1++; + + EXPECT_FALSE(dataset->end() == iter1); + EXPECT_FALSE(dataset->end() == iter2); + + EXPECT_TRUE(this->equals(iter2->key, key1)); + EXPECT_TRUE(this->equals(iter1->key, key2)); + + typename Dataset::const_iterator iter3 = iter1++; + + EXPECT_FALSE(dataset->end() == iter3); + EXPECT_TRUE(this->equals(iter3->key, key2)); + EXPECT_TRUE(dataset->end() == iter1); + + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestNewPutPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_TRUE(dataset->put(key, value)); + + EXPECT_TRUE(dataset->commit()); + + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestNewCommitPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + EXPECT_TRUE(dataset->commit()); + + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestNewGetPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_TRUE(dataset->put(key, value)); + + EXPECT_TRUE(dataset->commit()); + + value_type new_value; + + EXPECT_TRUE(dataset->get(key, &new_value)); + + EXPECT_TRUE(this->equals(value, new_value)); + + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestNewGetNoCommitFails) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_TRUE(dataset->put(key, value)); + + value_type new_value; + + EXPECT_FALSE(dataset->get(key, &new_value)); +} + + +TYPED_TEST(DatasetTest, TestReadWritePutPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::ReadWrite)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_TRUE(dataset->put(key, value)); + + EXPECT_TRUE(dataset->commit()); + + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestReadWriteCommitPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::ReadWrite)); + + EXPECT_TRUE(dataset->commit()); + + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestReadWriteGetPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_TRUE(dataset->put(key, value)); + + EXPECT_TRUE(dataset->commit()); + + value_type new_value; + + EXPECT_TRUE(dataset->get(key, &new_value)); + + EXPECT_TRUE(this->equals(value, new_value)); + + dataset->close(); +} + +TYPED_TEST(DatasetTest, TestReadWriteGetNoCommitFails) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_TRUE(dataset->put(key, value)); + + value_type new_value; + + EXPECT_FALSE(dataset->get(key, &new_value)); +} + +TYPED_TEST(DatasetTest, TestReadOnlyPutFails) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + dataset->close(); + + EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_FALSE(dataset->put(key, value)); +} + +TYPED_TEST(DatasetTest, TestReadOnlyCommitFails) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + dataset->close(); + + EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); + + EXPECT_FALSE(dataset->commit()); +} + +TYPED_TEST(DatasetTest, TestReadOnlyGetPasses) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_TRUE(dataset->put(key, value)); + + EXPECT_TRUE(dataset->commit()); + + dataset->close(); + + EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); + + value_type new_value; + + EXPECT_TRUE(dataset->get(key, &new_value)); + + EXPECT_TRUE(this->equals(value, new_value)); +} + +TYPED_TEST(DatasetTest, TestReadOnlyGetNoCommitFails) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + + EXPECT_TRUE(dataset->put(key, value)); + + dataset->close(); + + EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); + + value_type new_value; + + EXPECT_FALSE(dataset->get(key, &new_value)); +} + +#undef UNPACK_TYPES + +} // namespace caffe diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index f1a79679091..a720f162aa2 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -4,11 +4,11 @@ #include #include -#include "caffe/database_factory.hpp" +#include "caffe/dataset_factory.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" -using caffe::Database; +using caffe::Dataset; using caffe::Datum; using caffe::BlobProto; using std::max; @@ -26,16 +26,16 @@ int main(int argc, char** argv) { db_backend = std::string(argv[3]); } - caffe::shared_ptr > database = - caffe::DatabaseFactory(db_backend); + caffe::shared_ptr > dataset = + caffe::DatasetFactory(db_backend); // Open db - CHECK(database->open(argv[1], Database::ReadOnly)); + CHECK(dataset->open(argv[1], Dataset::ReadOnly)); BlobProto sum_blob; int count = 0; // load first datum - Database::const_iterator iter = database->begin(); + Dataset::const_iterator iter = dataset->begin(); const Datum& datum = iter->value; sum_blob.set_num(1); @@ -49,8 +49,8 @@ int main(int argc, char** argv) { sum_blob.add_data(0.); } LOG(INFO) << "Starting Iteration"; - for (Database::const_iterator iter = database->begin(); - iter != database->end(); ++iter) { + for (Dataset::const_iterator iter = dataset->begin(); + iter != dataset->end(); ++iter) { // just a dummy operation const Datum& datum = iter->value; const std::string& data = datum.data(); @@ -87,6 +87,6 @@ int main(int argc, char** argv) { WriteProtoToBinaryFile(sum_blob, argv[2]); // Clean up - database->close(); + dataset->close(); return 0; } diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 2ba3e3c7250..37efa5c13f7 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -17,7 +17,7 @@ #include #include -#include "caffe/database_factory.hpp" +#include "caffe/dataset_factory.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" #include "caffe/util/rng.hpp" @@ -78,11 +78,11 @@ int main(int argc, char** argv) { int resize_width = std::max(0, FLAGS_resize_width); // Open new db - shared_ptr > database = - DatabaseFactory(db_backend); + shared_ptr > dataset = + DatasetFactory(db_backend); // Open db - CHECK(database->open(db_path, Database::New)); + CHECK(dataset->open(db_path, Dataset::New)); // Storing to db std::string root_folder(argv[1]); @@ -113,19 +113,19 @@ int main(int argc, char** argv) { lines[line_id].first.c_str()); // Put in db - CHECK(database->put(string(key_cstr, length), datum)); + CHECK(dataset->put(string(key_cstr, length), datum)); if (++count % 1000 == 0) { // Commit txn - CHECK(database->commit()); + CHECK(dataset->commit()); LOG(ERROR) << "Processed " << count << " files."; } } // write the last batch if (count % 1000 != 0) { - CHECK(database->commit()); + CHECK(dataset->commit()); LOG(ERROR) << "Processed " << count << " files."; } - database->close(); + dataset->close(); return 0; } diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 47565a83025..ddbce1075ed 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -7,7 +7,7 @@ #include "caffe/blob.hpp" #include "caffe/common.hpp" -#include "caffe/database_factory.hpp" +#include "caffe/dataset_factory.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" @@ -16,8 +16,8 @@ using boost::shared_ptr; using caffe::Blob; using caffe::Caffe; -using caffe::Database; -using caffe::DatabaseFactory; +using caffe::Dataset; +using caffe::DatasetFactory; using caffe::Datum; using caffe::Net; @@ -39,12 +39,12 @@ int feature_extraction_pipeline(int argc, char** argv) { " extract features of the input data produced by the net.\n" "Usage: extract_features pretrained_net_param" " feature_extraction_proto_file extract_feature_blob_name1[,name2,...]" - " save_feature_database_name1[,name2,...] num_mini_batches db_type" + " save_feature_dataset_name1[,name2,...] num_mini_batches db_type" " [CPU/GPU] [DEVICE_ID=0]\n" "Note: you can extract multiple features in one pass by specifying" - " multiple feature blob names and database names seperated by ','." + " multiple feature blob names and dataset names seperated by ','." " The names cannot contain white space characters and the number of blobs" - " and databases must be equal."; + " and datasets must be equal."; return 1; } int arg_pos = num_required_args; @@ -105,12 +105,12 @@ int feature_extraction_pipeline(int argc, char** argv) { std::vector blob_names; boost::split(blob_names, extract_feature_blob_names, boost::is_any_of(",")); - std::string save_feature_database_names(argv[++arg_pos]); - std::vector database_names; - boost::split(database_names, save_feature_database_names, + std::string save_feature_dataset_names(argv[++arg_pos]); + std::vector dataset_names; + boost::split(dataset_names, save_feature_dataset_names, boost::is_any_of(",")); - CHECK_EQ(blob_names.size(), database_names.size()) << - " the number of blob names and database names must be equal"; + CHECK_EQ(blob_names.size(), dataset_names.size()) << + " the number of blob names and dataset names must be equal"; size_t num_features = blob_names.size(); for (size_t i = 0; i < num_features; i++) { @@ -121,14 +121,13 @@ int feature_extraction_pipeline(int argc, char** argv) { int num_mini_batches = atoi(argv[++arg_pos]); - std::vector > > feature_dbs; + std::vector > > feature_dbs; for (size_t i = 0; i < num_features; ++i) { - LOG(INFO)<< "Opening database " << database_names[i]; - shared_ptr > database = - DatabaseFactory(argv[++arg_pos]); - CHECK(database->open(database_names.at(i), - Database::New)); - feature_dbs.push_back(database); + LOG(INFO)<< "Opening dataset " << dataset_names[i]; + shared_ptr > dataset = + DatasetFactory(argv[++arg_pos]); + CHECK(dataset->open(dataset_names.at(i), Dataset::New)); + feature_dbs.push_back(dataset); } LOG(ERROR)<< "Extacting Features"; From 6fd72e106526e6cbdf8a8b867576816f87700681 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 14 Oct 2014 12:44:00 -0400 Subject: [PATCH 127/798] Had forgotten to set some of the Dataset test cases to LMDB backend. --- src/caffe/test/test_dataset.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/caffe/test/test_dataset.cpp b/src/caffe/test/test_dataset.cpp index bb6cf4ce616..7d0f6b3d9bb 100644 --- a/src/caffe/test/test_dataset.cpp +++ b/src/caffe/test/test_dataset.cpp @@ -147,7 +147,7 @@ struct StringLmdb { typedef string value_type; static const DataParameter_DB backend; }; -const DataParameter_DB StringLmdb::backend = DataParameter_DB_LEVELDB; +const DataParameter_DB StringLmdb::backend = DataParameter_DB_LMDB; struct VectorLeveldb { typedef vector value_type; @@ -159,7 +159,7 @@ struct VectorLmdb { typedef vector value_type; static const DataParameter_DB backend; }; -const DataParameter_DB VectorLmdb::backend = DataParameter_DB_LEVELDB; +const DataParameter_DB VectorLmdb::backend = DataParameter_DB_LMDB; struct DatumLeveldb { typedef Datum value_type; @@ -171,7 +171,7 @@ struct DatumLmdb { typedef Datum value_type; static const DataParameter_DB backend; }; -const DataParameter_DB DatumLmdb::backend = DataParameter_DB_LEVELDB; +const DataParameter_DB DatumLmdb::backend = DataParameter_DB_LMDB; typedef ::testing::Types TestTypes; From ef518dc6e02b6d837a3281cf353a52a333a5a669 Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Tue, 14 Oct 2014 14:00:29 -0400 Subject: [PATCH 128/798] Reworked the Coder interface such that a Dataset now has both user-definable KCoder and VCoder which default to a set of DefaultCoder's based on types K and V. Reworked the DefaultCoder's such that if none are available, a static assertion fails with a relevant message. --- include/caffe/dataset.hpp | 66 ++++++++++++++------------ include/caffe/leveldb_dataset.hpp | 8 ++-- include/caffe/lmdb_dataset.hpp | 8 ++-- src/caffe/leveldb_dataset.cpp | 77 ++++++++++++++++--------------- src/caffe/lmdb_dataset.cpp | 75 +++++++++++++++--------------- 5 files changed, 126 insertions(+), 108 deletions(-) diff --git a/include/caffe/dataset.hpp b/include/caffe/dataset.hpp index 1f07aa9d18d..efe3ffde582 100644 --- a/include/caffe/dataset.hpp +++ b/include/caffe/dataset.hpp @@ -1,6 +1,8 @@ #ifndef CAFFE_DATASET_H_ #define CAFFE_DATASET_H_ +#include + #include #include #include @@ -8,34 +10,58 @@ #include #include "caffe/common.hpp" +#include "caffe/proto/caffe.pb.h" namespace caffe { namespace dataset_internal { +using google::protobuf::Message; + +template +struct static_assertion {}; +template<> +struct static_assertion { + enum { + DEFAULT_CODER_NOT_AVAILABLE + }; +}; + template -struct Coder { - static bool serialize(const T& obj, string* serialized) { +struct DefaultCoder { + using static_assertion::DEFAULT_CODER_NOT_AVAILABLE; + static bool serialize(const T& obj, string* serialized); + static bool serialize(const T& obj, vector* serialized); + static bool deserialize(const string& serialized, T* obj); + static bool deserialize(const char* data, size_t size, T* obj); +}; + +template <> +struct DefaultCoder { + static bool serialize(const Message& obj, string* serialized) { return obj.SerializeToString(serialized); } - static bool serialize(const T& obj, vector* serialized) { + static bool serialize(const Message& obj, vector* serialized) { serialized->resize(obj.ByteSize()); return obj.SerializeWithCachedSizesToArray( reinterpret_cast(serialized->data())); } - static bool deserialize(const string& serialized, T* obj) { + static bool deserialize(const string& serialized, Message* obj) { return obj->ParseFromString(serialized); } - static bool deserialize(const char* data, size_t size, T* obj) { + static bool deserialize(const char* data, size_t size, Message* obj) { return obj->ParseFromArray(data, size); } }; template <> -struct Coder { +struct DefaultCoder : public DefaultCoder { }; + +template <> +struct DefaultCoder { static bool serialize(string obj, string* serialized) { *serialized = obj; return true; @@ -60,7 +86,7 @@ struct Coder { }; template <> -struct Coder > { +struct DefaultCoder > { static bool serialize(vector obj, string* serialized) { string tmp(obj.data(), obj.size()); serialized->swap(tmp); @@ -87,7 +113,9 @@ struct Coder > { } // namespace dataset_internal -template +template , + typename VCoder = dataset_internal::DefaultCoder > class Dataset { public: enum Mode { @@ -200,26 +228,6 @@ class Dataset { virtual void increment(shared_ptr* state) const = 0; virtual KV& dereference( shared_ptr state) const = 0; - - template - static bool serialize(const T& obj, string* serialized) { - return dataset_internal::Coder::serialize(obj, serialized); - } - - template - static bool serialize(const T& obj, vector* serialized) { - return dataset_internal::Coder::serialize(obj, serialized); - } - - template - static bool deserialize(const string& serialized, T* obj) { - return dataset_internal::Coder::deserialize(serialized, obj); - } - - template - static bool deserialize(const char* data, size_t size, T* obj) { - return dataset_internal::Coder::deserialize(data, size, obj); - } }; } // namespace caffe @@ -227,6 +235,6 @@ class Dataset { #define INSTANTIATE_DATASET(type) \ template class type; \ template class type >; \ - template class type; + template class type; #endif // CAFFE_DATASET_H_ diff --git a/include/caffe/leveldb_dataset.hpp b/include/caffe/leveldb_dataset.hpp index eb354d95db3..90f92d9336a 100644 --- a/include/caffe/leveldb_dataset.hpp +++ b/include/caffe/leveldb_dataset.hpp @@ -13,10 +13,12 @@ namespace caffe { -template -class LeveldbDataset : public Dataset { +template , + typename VCoder = dataset_internal::DefaultCoder > +class LeveldbDataset : public Dataset { public: - typedef Dataset Base; + typedef Dataset Base; typedef typename Base::key_type key_type; typedef typename Base::value_type value_type; typedef typename Base::DatasetState DatasetState; diff --git a/include/caffe/lmdb_dataset.hpp b/include/caffe/lmdb_dataset.hpp index 57da5dea829..8817df7cade 100644 --- a/include/caffe/lmdb_dataset.hpp +++ b/include/caffe/lmdb_dataset.hpp @@ -12,10 +12,12 @@ namespace caffe { -template -class LmdbDataset : public Dataset { +template , + typename VCoder = dataset_internal::DefaultCoder > +class LmdbDataset : public Dataset { public: - typedef Dataset Base; + typedef Dataset Base; typedef typename Base::key_type key_type; typedef typename Base::value_type value_type; typedef typename Base::DatasetState DatasetState; diff --git a/src/caffe/leveldb_dataset.cpp b/src/caffe/leveldb_dataset.cpp index 41c71e44557..af9560456d8 100644 --- a/src/caffe/leveldb_dataset.cpp +++ b/src/caffe/leveldb_dataset.cpp @@ -7,8 +7,9 @@ namespace caffe { -template -bool LeveldbDataset::open(const string& filename, Mode mode) { +template +bool LeveldbDataset::open(const string& filename, + Mode mode) { DLOG(INFO) << "LevelDB: Open " << filename; leveldb::Options options; @@ -54,8 +55,8 @@ bool LeveldbDataset::open(const string& filename, Mode mode) { return true; } -template -bool LeveldbDataset::put(const K& key, const V& value) { +template +bool LeveldbDataset::put(const K& key, const V& value) { DLOG(INFO) << "LevelDB: Put"; if (read_only_) { @@ -66,12 +67,12 @@ bool LeveldbDataset::put(const K& key, const V& value) { CHECK_NOTNULL(batch_.get()); string serialized_key; - if (!Base::serialize(key, &serialized_key)) { + if (!KCoder::serialize(key, &serialized_key)) { return false; } string serialized_value; - if (!Base::serialize(value, &serialized_value)) { + if (!VCoder::serialize(value, &serialized_value)) { return false; } @@ -80,12 +81,12 @@ bool LeveldbDataset::put(const K& key, const V& value) { return true; } -template -bool LeveldbDataset::get(const K& key, V* value) { +template +bool LeveldbDataset::get(const K& key, V* value) { DLOG(INFO) << "LevelDB: Get"; string serialized_key; - if (!Base::serialize(key, &serialized_key)) { + if (!KCoder::serialize(key, &serialized_key)) { return false; } @@ -98,15 +99,15 @@ bool LeveldbDataset::get(const K& key, V* value) { return false; } - if (!Base::deserialize(serialized_value, value)) { + if (!VCoder::deserialize(serialized_value, value)) { return false; } return true; } -template -bool LeveldbDataset::commit() { +template +bool LeveldbDataset::commit() { DLOG(INFO) << "LevelDB: Commit"; if (read_only_) { @@ -124,16 +125,16 @@ bool LeveldbDataset::commit() { return status.ok(); } -template -void LeveldbDataset::close() { +template +void LeveldbDataset::close() { DLOG(INFO) << "LevelDB: Close"; batch_.reset(); db_.reset(); } -template -void LeveldbDataset::keys(vector* keys) { +template +void LeveldbDataset::keys(vector* keys) { DLOG(INFO) << "LevelDB: Keys"; keys->clear(); @@ -142,9 +143,9 @@ void LeveldbDataset::keys(vector* keys) { } } -template -typename LeveldbDataset::const_iterator - LeveldbDataset::begin() const { +template +typename LeveldbDataset::const_iterator + LeveldbDataset::begin() const { CHECK_NOTNULL(db_.get()); shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); iter->SeekToFirst(); @@ -159,26 +160,26 @@ typename LeveldbDataset::const_iterator return const_iterator(this, state); } -template -typename LeveldbDataset::const_iterator - LeveldbDataset::end() const { +template +typename LeveldbDataset::const_iterator + LeveldbDataset::end() const { shared_ptr state; return const_iterator(this, state); } -template -typename LeveldbDataset::const_iterator - LeveldbDataset::cbegin() const { +template +typename LeveldbDataset::const_iterator + LeveldbDataset::cbegin() const { return begin(); } -template -typename LeveldbDataset::const_iterator - LeveldbDataset::cend() const { return end(); } +template +typename LeveldbDataset::const_iterator + LeveldbDataset::cend() const { return end(); } -template -bool LeveldbDataset::equal(shared_ptr state1, - shared_ptr state2) const { +template +bool LeveldbDataset::equal( + shared_ptr state1, shared_ptr state2) const { shared_ptr leveldb_state1 = boost::dynamic_pointer_cast(state1); @@ -191,8 +192,9 @@ bool LeveldbDataset::equal(shared_ptr state1, return !leveldb_state1 && !leveldb_state2; } -template -void LeveldbDataset::increment(shared_ptr* state) const { +template +void LeveldbDataset::increment( + shared_ptr* state) const { shared_ptr leveldb_state = boost::dynamic_pointer_cast(*state); @@ -209,8 +211,9 @@ void LeveldbDataset::increment(shared_ptr* state) const { } } -template -typename Dataset::KV& LeveldbDataset::dereference( +template +typename Dataset::KV& + LeveldbDataset::dereference( shared_ptr state) const { shared_ptr leveldb_state = boost::dynamic_pointer_cast(state); @@ -225,9 +228,9 @@ typename Dataset::KV& LeveldbDataset::dereference( const leveldb::Slice& key = iter->key(); const leveldb::Slice& value = iter->value(); - CHECK(Base::deserialize(key.data(), key.size(), + CHECK(KCoder::deserialize(key.data(), key.size(), &leveldb_state->kv_pair_.key)); - CHECK(Base::deserialize(value.data(), value.size(), + CHECK(VCoder::deserialize(value.data(), value.size(), &leveldb_state->kv_pair_.value)); return leveldb_state->kv_pair_; diff --git a/src/caffe/lmdb_dataset.cpp b/src/caffe/lmdb_dataset.cpp index d2b6fcd1c85..ca968432bc0 100644 --- a/src/caffe/lmdb_dataset.cpp +++ b/src/caffe/lmdb_dataset.cpp @@ -9,8 +9,9 @@ namespace caffe { -template -bool LmdbDataset::open(const string& filename, Mode mode) { +template +bool LmdbDataset::open(const string& filename, + Mode mode) { DLOG(INFO) << "LMDB: Open " << filename; CHECK(NULL == env_); @@ -80,18 +81,18 @@ bool LmdbDataset::open(const string& filename, Mode mode) { return true; } -template -bool LmdbDataset::put(const K& key, const V& value) { +template +bool LmdbDataset::put(const K& key, const V& value) { DLOG(INFO) << "LMDB: Put"; vector serialized_key; - if (!Base::serialize(key, &serialized_key)) { + if (!KCoder::serialize(key, &serialized_key)) { LOG(ERROR) << "failed to serialize key"; return false; } vector serialized_value; - if (!Base::serialize(value, &serialized_value)) { + if (!VCoder::serialize(value, &serialized_value)) { LOG(ERROR) << "failed to serialized value"; return false; } @@ -114,12 +115,12 @@ bool LmdbDataset::put(const K& key, const V& value) { return true; } -template -bool LmdbDataset::get(const K& key, V* value) { +template +bool LmdbDataset::get(const K& key, V* value) { DLOG(INFO) << "LMDB: Get"; vector serialized_key; - if (!Base::serialize(key, &serialized_key)) { + if (!KCoder::serialize(key, &serialized_key)) { LOG(ERROR) << "failed to serialized key"; return false; } @@ -144,7 +145,7 @@ bool LmdbDataset::get(const K& key, V* value) { mdb_txn_abort(get_txn); - if (!Base::deserialize(reinterpret_cast(mdbdata.mv_data), + if (!VCoder::deserialize(reinterpret_cast(mdbdata.mv_data), mdbdata.mv_size, value)) { LOG(ERROR) << "failed to deserialize value"; return false; @@ -153,8 +154,8 @@ bool LmdbDataset::get(const K& key, V* value) { return true; } -template -bool LmdbDataset::commit() { +template +bool LmdbDataset::commit() { DLOG(INFO) << "LMDB: Commit"; CHECK_NOTNULL(txn_); @@ -175,8 +176,8 @@ bool LmdbDataset::commit() { return true; } -template -void LmdbDataset::close() { +template +void LmdbDataset::close() { DLOG(INFO) << "LMDB: Close"; if (env_ && dbi_) { @@ -188,8 +189,8 @@ void LmdbDataset::close() { } } -template -void LmdbDataset::keys(vector* keys) { +template +void LmdbDataset::keys(vector* keys) { DLOG(INFO) << "LMDB: Keys"; keys->clear(); @@ -198,9 +199,9 @@ void LmdbDataset::keys(vector* keys) { } } -template -typename LmdbDataset::const_iterator - LmdbDataset::begin() const { +template +typename LmdbDataset::const_iterator + LmdbDataset::begin() const { int retval; MDB_txn* iter_txn; @@ -226,23 +227,23 @@ typename LmdbDataset::const_iterator return const_iterator(this, state); } -template -typename LmdbDataset::const_iterator - LmdbDataset::end() const { +template +typename LmdbDataset::const_iterator + LmdbDataset::end() const { shared_ptr state; return const_iterator(this, state); } -template -typename LmdbDataset::const_iterator - LmdbDataset::cbegin() const { return begin(); } +template +typename LmdbDataset::const_iterator + LmdbDataset::cbegin() const { return begin(); } -template -typename LmdbDataset::const_iterator - LmdbDataset::cend() const { return end(); } +template +typename LmdbDataset::const_iterator + LmdbDataset::cend() const { return end(); } -template -bool LmdbDataset::equal(shared_ptr state1, +template +bool LmdbDataset::equal(shared_ptr state1, shared_ptr state2) const { shared_ptr lmdb_state1 = boost::dynamic_pointer_cast(state1); @@ -256,8 +257,9 @@ bool LmdbDataset::equal(shared_ptr state1, return !lmdb_state1 && !lmdb_state2; } -template -void LmdbDataset::increment(shared_ptr* state) const { +template +void LmdbDataset::increment( + shared_ptr* state) const { shared_ptr lmdb_state = boost::dynamic_pointer_cast(*state); @@ -278,8 +280,9 @@ void LmdbDataset::increment(shared_ptr* state) const { } } -template -typename Dataset::KV& LmdbDataset::dereference( +template +typename Dataset::KV& + LmdbDataset::dereference( shared_ptr state) const { shared_ptr lmdb_state = boost::dynamic_pointer_cast(state); @@ -295,9 +298,9 @@ typename Dataset::KV& LmdbDataset::dereference( int retval = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT); CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - CHECK(Base::deserialize(reinterpret_cast(mdb_key.mv_data), + CHECK(KCoder::deserialize(reinterpret_cast(mdb_key.mv_data), mdb_key.mv_size, &lmdb_state->kv_pair_.key)); - CHECK(Base::deserialize(reinterpret_cast(mdb_val.mv_data), + CHECK(VCoder::deserialize(reinterpret_cast(mdb_val.mv_data), mdb_val.mv_size, &lmdb_state->kv_pair_.value)); return lmdb_state->kv_pair_; From 8944b7addcff7be6947c255db7ee85881d1b586d Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 14 Oct 2014 21:03:03 -0700 Subject: [PATCH 129/798] Reintroduce pkg-config with optional Makefile.config flag. --- Makefile | 9 ++++++++- Makefile.config.example | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 35c37af50fb..26d5964cacc 100644 --- a/Makefile +++ b/Makefile @@ -329,7 +329,14 @@ NVCCFLAGS += -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS) # mex may invoke an older gcc that is too liberal with -Wuninitalized MATLAB_CXXFLAGS := $(CXXFLAGS) -Wno-uninitialized LINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) -LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) \ + +USE_PKG_CONFIG ?= 0 +ifeq ($(USE_PKG_CONFIG), 1) + PKG_CONFIG := $(shell pkg-config opencv --libs) +else + PKG_CONFIG := +endif +LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) $(PKG_CONFIG) \ $(foreach library,$(LIBRARIES),-l$(library)) PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) diff --git a/Makefile.config.example b/Makefile.config.example index 5cb0b243aca..b6d95e31df8 100644 --- a/Makefile.config.example +++ b/Makefile.config.example @@ -60,6 +60,10 @@ PYTHON_LIB := /usr/lib INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib +# Uncomment to use `pkg-config` to specify OpenCV library paths. +# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.) +# USE_PKG_CONFIG := 1 + BUILD_DIR := build DISTRIBUTE_DIR := distribute From 23af87fc49d7ffaa70584458cacb1528a5fb1f77 Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 15 Oct 2014 09:45:09 -0700 Subject: [PATCH 130/798] Added first_key and last_key to dataset --- include/caffe/dataset.hpp | 2 + include/caffe/leveldb_dataset.hpp | 2 + include/caffe/lmdb_dataset.hpp | 2 + src/caffe/leveldb_dataset.cpp | 24 +++++++ src/caffe/lmdb_dataset.cpp | 64 +++++++++++++++++ src/caffe/test/test_dataset.cpp | 114 ++++++++++++++++++++++++++++++ 6 files changed, 208 insertions(+) diff --git a/include/caffe/dataset.hpp b/include/caffe/dataset.hpp index efe3ffde582..90deb3160fa 100644 --- a/include/caffe/dataset.hpp +++ b/include/caffe/dataset.hpp @@ -135,6 +135,8 @@ class Dataset { virtual bool open(const string& filename, Mode mode) = 0; virtual bool put(const K& key, const V& value) = 0; virtual bool get(const K& key, V* value) = 0; + virtual bool first_key(K* key) = 0; + virtual bool last_key(K* key) = 0; virtual bool commit() = 0; virtual void close() = 0; diff --git a/include/caffe/leveldb_dataset.hpp b/include/caffe/leveldb_dataset.hpp index 90f92d9336a..f6c57fe65af 100644 --- a/include/caffe/leveldb_dataset.hpp +++ b/include/caffe/leveldb_dataset.hpp @@ -29,6 +29,8 @@ class LeveldbDataset : public Dataset { bool open(const string& filename, Mode mode); bool put(const K& key, const V& value); bool get(const K& key, V* value); + bool first_key(K* key); + bool last_key(K* key); bool commit(); void close(); diff --git a/include/caffe/lmdb_dataset.hpp b/include/caffe/lmdb_dataset.hpp index 8817df7cade..71b322490c0 100644 --- a/include/caffe/lmdb_dataset.hpp +++ b/include/caffe/lmdb_dataset.hpp @@ -33,6 +33,8 @@ class LmdbDataset : public Dataset { bool open(const string& filename, Mode mode); bool put(const K& key, const V& value); bool get(const K& key, V* value); + bool first_key(K* key); + bool last_key(K* key); bool commit(); void close(); diff --git a/src/caffe/leveldb_dataset.cpp b/src/caffe/leveldb_dataset.cpp index af9560456d8..53df985721c 100644 --- a/src/caffe/leveldb_dataset.cpp +++ b/src/caffe/leveldb_dataset.cpp @@ -106,6 +106,30 @@ bool LeveldbDataset::get(const K& key, V* value) { return true; } +template +bool LeveldbDataset::first_key(K* key) { + DLOG(INFO) << "LevelDB: First key"; + + CHECK_NOTNULL(db_.get()); + shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); + iter->SeekToFirst(); + CHECK(iter->Valid()); + const leveldb::Slice& key_slice = iter->key(); + return KCoder::deserialize(key_slice.data(), key_slice.size(), key); +} + +template +bool LeveldbDataset::last_key(K* key) { + DLOG(INFO) << "LevelDB: Last key"; + + CHECK_NOTNULL(db_.get()); + shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); + iter->SeekToLast(); + CHECK(iter->Valid()); + const leveldb::Slice& key_slice = iter->key(); + return KCoder::deserialize(key_slice.data(), key_slice.size(), key); +} + template bool LeveldbDataset::commit() { DLOG(INFO) << "LevelDB: Commit"; diff --git a/src/caffe/lmdb_dataset.cpp b/src/caffe/lmdb_dataset.cpp index ca968432bc0..23852f0cd81 100644 --- a/src/caffe/lmdb_dataset.cpp +++ b/src/caffe/lmdb_dataset.cpp @@ -154,6 +154,70 @@ bool LmdbDataset::get(const K& key, V* value) { return true; } +template +bool LmdbDataset::first_key(K* key) { + DLOG(INFO) << "LMDB: First key"; + + int retval; + + MDB_txn* iter_txn; + + retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &iter_txn); + CHECK_EQ(MDB_SUCCESS, retval) << "mdb_txn_begin failed " + << mdb_strerror(retval); + + MDB_cursor* cursor; + retval = mdb_cursor_open(iter_txn, dbi_, &cursor); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + MDB_val mdbkey; + MDB_val mdbval; + retval = mdb_cursor_get(cursor, &mdbkey, &mdbval, MDB_FIRST); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + + mdb_cursor_close(cursor); + mdb_txn_abort(iter_txn); + + if (!KCoder::deserialize(reinterpret_cast(mdbkey.mv_data), + mdbkey.mv_size, key)) { + LOG(ERROR) << "failed to deserialize key"; + return false; + } + + return true; +} + +template +bool LmdbDataset::last_key(K* key) { + DLOG(INFO) << "LMDB: Last key"; + + int retval; + + MDB_txn* iter_txn; + + retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &iter_txn); + CHECK_EQ(MDB_SUCCESS, retval) << "mdb_txn_begin failed " + << mdb_strerror(retval); + + MDB_cursor* cursor; + retval = mdb_cursor_open(iter_txn, dbi_, &cursor); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + MDB_val mdbkey; + MDB_val mdbval; + retval = mdb_cursor_get(cursor, &mdbkey, &mdbval, MDB_LAST); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + + mdb_cursor_close(cursor); + mdb_txn_abort(iter_txn); + + if (!KCoder::deserialize(reinterpret_cast(mdbkey.mv_data), + mdbkey.mv_size, key)) { + LOG(ERROR) << "failed to deserialize key"; + return false; + } + + return true; +} + template bool LmdbDataset::commit() { DLOG(INFO) << "LMDB: Commit"; diff --git a/src/caffe/test/test_dataset.cpp b/src/caffe/test/test_dataset.cpp index 7d0f6b3d9bb..e5bd1d2c40e 100644 --- a/src/caffe/test/test_dataset.cpp +++ b/src/caffe/test/test_dataset.cpp @@ -277,6 +277,120 @@ TYPED_TEST(DatasetTest, TestKeys) { EXPECT_FALSE(this->equals(keys.at(0), keys.at(1))); } +TYPED_TEST(DatasetTest, TestFirstKey) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + value_type value = this->TestValue(); + + string key1 = "01"; + EXPECT_TRUE(dataset->put(key1, value)); + + string key2 = "02"; + EXPECT_TRUE(dataset->put(key2, value)); + + string key3 = "03"; + EXPECT_TRUE(dataset->put(key3, value)); + + EXPECT_TRUE(dataset->commit()); + + string first_key; + dataset->first_key(&first_key); + + EXPECT_TRUE(this->equals(first_key, key1)); +} + +TYPED_TEST(DatasetTest, TestLastKey) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + value_type value = this->TestValue(); + + string key1 = "01"; + EXPECT_TRUE(dataset->put(key1, value)); + + string key2 = "02"; + EXPECT_TRUE(dataset->put(key2, value)); + + string key3 = "03"; + EXPECT_TRUE(dataset->put(key3, value)); + + EXPECT_TRUE(dataset->commit()); + + string last_key; + dataset->last_key(&last_key); + + EXPECT_TRUE(this->equals(last_key, key3)); +} + +TYPED_TEST(DatasetTest, TestFirstLastKeys) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + value_type value = this->TestValue(); + + string key1 = "01"; + EXPECT_TRUE(dataset->put(key1, value)); + + string key2 = "02"; + EXPECT_TRUE(dataset->put(key2, value)); + + string key3 = "03"; + EXPECT_TRUE(dataset->put(key3, value)); + + EXPECT_TRUE(dataset->commit()); + + string first_key; + dataset->first_key(&first_key); + string last_key; + dataset->last_key(&last_key); + + EXPECT_TRUE(this->equals(first_key, key1)); + EXPECT_TRUE(this->equals(last_key, key3)); +} + +TYPED_TEST(DatasetTest, TestFirstLastKeysUnOrdered) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + value_type value = this->TestValue(); + + string key3 = "03"; + EXPECT_TRUE(dataset->put(key3, value)); + + string key1 = "01"; + EXPECT_TRUE(dataset->put(key1, value)); + + string key2 = "02"; + EXPECT_TRUE(dataset->put(key2, value)); + + EXPECT_TRUE(dataset->commit()); + + string first_key; + dataset->first_key(&first_key); + string last_key; + dataset->last_key(&last_key); + + EXPECT_TRUE(this->equals(first_key, key1)); + EXPECT_TRUE(this->equals(last_key, key3)); +} + TYPED_TEST(DatasetTest, TestKeysNoCommit) { UNPACK_TYPES; From ae88994128858ffc66095c2d927a825ed04f5ed3 Mon Sep 17 00:00:00 2001 From: Sergio Date: Mon, 6 Oct 2014 18:05:11 -0700 Subject: [PATCH 131/798] Added encoded option and check_size to convert_imageset Conflicts: tools/convert_imageset.cpp --- tools/convert_imageset.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 37efa5c13f7..c554ed389ab 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -34,6 +34,8 @@ DEFINE_int32(resize_width, 0, "Width images are resized to"); DEFINE_int32(resize_height, 0, "Height images are resized to"); DEFINE_bool(check_size, false, "When this option is on, check that all the datum have the same size"); +DEFINE_bool(encoded, false, + "When this option is on, the encoded image will be save in datum"); int main(int argc, char** argv) { ::google::InitGoogleLogging(argv[0]); @@ -55,8 +57,10 @@ int main(int argc, char** argv) { return 1; } - bool is_color = !FLAGS_gray; - bool check_size = FLAGS_check_size; + const bool is_color = !FLAGS_gray; + const bool check_size = FLAGS_check_size; + const bool encoded = FLAGS_encoded; + std::ifstream infile(argv[2]); std::vector > lines; std::string filename; @@ -74,6 +78,12 @@ int main(int argc, char** argv) { const std::string& db_backend = FLAGS_backend; const char* db_path = argv[3]; + if (encoded) { + CHECK_EQ(FLAGS_resize_height, 0) << "With encoded don't resize images"; + CHECK_EQ(FLAGS_resize_width, 0) << "With encoded don't resize images"; + CHECK(!check_size) << "With encoded cannot check_size"; + } + int resize_height = std::max(0, FLAGS_resize_height); int resize_width = std::max(0, FLAGS_resize_width); @@ -94,10 +104,15 @@ int main(int argc, char** argv) { bool data_size_initialized = false; for (int line_id = 0; line_id < lines.size(); ++line_id) { - if (!ReadImageToDatum(root_folder + lines[line_id].first, - lines[line_id].second, resize_height, resize_width, is_color, &datum)) { - continue; + bool status; + if (encoded) { + status = ReadFileToDatum(root_folder + lines[line_id].first, + lines[line_id].second, &datum); + } else { + status = ReadImageToDatum(root_folder + lines[line_id].first, + lines[line_id].second, resize_height, resize_width, is_color, &datum); } + if (status == false) continue; if (check_size) { if (!data_size_initialized) { data_size = datum.channels() * datum.height() * datum.width(); From 9fc7f36e0445883249f6ef07d460d3806d4c9ab3 Mon Sep 17 00:00:00 2001 From: Sergio Date: Mon, 6 Oct 2014 18:25:28 -0700 Subject: [PATCH 132/798] Added encoded datum to io --- include/caffe/util/io.hpp | 38 +++++++++++++++++++++++ src/caffe/proto/caffe.proto | 2 ++ src/caffe/util/io.cpp | 61 +++++++++++++++++++++++++++++++++++-- 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index b64c821a86e..63afe6298ff 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -88,6 +88,12 @@ inline void WriteProtoToBinaryFile( WriteProtoToBinaryFile(proto, filename.c_str()); } +bool ReadFileToDatum(const string& filename, const int label, Datum* datum); + +inline bool ReadFileToDatum(const string& filename, Datum* datum) { + return ReadFileToDatum(filename, -1, datum); +} + bool ReadImageToDatum(const string& filename, const int label, const int height, const int width, const bool is_color, Datum* datum); @@ -106,6 +112,21 @@ inline bool ReadImageToDatum(const string& filename, const int label, return ReadImageToDatum(filename, label, 0, 0, true, datum); } +bool DecodeDatum(const int height, const int width, const bool is_color, + Datum& datum); + +inline bool DecodeDatum(const int height, const int width, Datum& datum) { + return DecodeDatum(height, width, true, datum); +} + +inline bool DecodeDatum(const bool is_color, Datum& datum) { + return DecodeDatum(0, 0, is_color, datum); +} + +inline bool DecodeDatum(Datum& datum) { + return DecodeDatum(0, 0, true, datum); +} + #ifndef OSX cv::Mat ReadImageToCVMat(const string& filename, const int height, const int width, const bool is_color); @@ -124,6 +145,23 @@ inline cv::Mat ReadImageToCVMat(const string& filename) { return ReadImageToCVMat(filename, 0, 0, true); } +cv::Mat DecodeDatumToCVMat(const Datum& datum, + const int height, const int width, const bool is_color); + +inline cv::Mat DecodeDatumToCVMat(const Datum& datum, + const int height, const int width) { + return DecodeDatumToCVMat(datum, height, width, true); +} + +inline cv::Mat DecodeDatumToCVMat(const Datum& datum, + const bool is_color) { + return DecodeDatumToCVMat(datum, 0, 0, is_color); +} + +inline cv::Mat DecodeDatumToCVMat(const Datum& datum) { + return DecodeDatumToCVMat(datum, 0, 0, true); +} + void CVMatToDatum(const cv::Mat& cv_img, Datum* datum); #endif diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index f0dba097d05..53db6f76945 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -26,6 +26,8 @@ message Datum { optional int32 label = 5; // Optionally, the datum could also hold float data. repeated float float_data = 6; + // If true data contains an encoded image that need to be decoded + optional bool encoded = 7 [default = false]; } message FillerParameter { diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index a4a6627b277..6aa410a0feb 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -95,21 +95,76 @@ bool ReadImageToDatum(const string& filename, const int label, } } +bool ReadFileToDatum(const string& filename, const int label, + Datum* datum) { + std::streampos size; + + fstream file(filename.c_str(), ios::in|ios::binary|ios::ate); + if (file.is_open()) { + size = file.tellg(); + std::string buffer(size, ' '); + file.seekg(0, ios::beg); + file.read(&buffer[0], size); + file.close(); + datum->set_data(buffer); + datum->set_label(label); + datum->set_encoded(true); + return true; + } else { + return false; + } +} + +cv::Mat DecodeDatumToCVMat(const Datum& datum, + const int height, const int width, const bool is_color) { + cv::Mat cv_img; + CHECK(datum.encoded()) << "Datum not encoded"; + int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR : + CV_LOAD_IMAGE_GRAYSCALE); + const string& data = datum.data(); + std::vector vec_data(data.c_str(), data.c_str() + data.size()); + if (height > 0 && width > 0) { + cv::Mat cv_img_origin = cv::imdecode(cv::Mat(vec_data), cv_read_flag); + cv::resize(cv_img_origin, cv_img, cv::Size(width, height)); + } else { + cv_img = cv::imdecode(vec_data, cv_read_flag); + } + if (!cv_img.data) { + LOG(ERROR) << "Could not decode datum "; + } + return cv_img; +} + +// If Datum is encoded will decoded using DecodeDatumToCVMat and CVMatToDatum +// if height and width are set it will resize it +// If Datum is not encoded will do nothing +bool DecodeDatum(const int height, const int width, const bool is_color, + Datum& datum) { + if (datum.encoded()) { + cv::Mat cv_img = DecodeDatumToCVMat(datum, height, width, is_color); + CVMatToDatum(cv_img, &datum); + return true; + } else { + return false; + } +} + void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) { - CHECK(cv_img.depth() == CV_8U) << - "Image data type must be unsigned byte"; + CHECK(cv_img.depth() == CV_8U || cv_img.depth() == CV_8S) << + "Image data type must be unsigned or signed byte"; datum->set_channels(cv_img.channels()); datum->set_height(cv_img.rows); datum->set_width(cv_img.cols); datum->clear_data(); datum->clear_float_data(); + datum->set_encoded(false); int datum_channels = datum->channels(); int datum_height = datum->height(); int datum_width = datum->width(); int datum_size = datum_channels * datum_height * datum_width; std::string buffer(datum_size, ' '); for (int h = 0; h < datum_height; ++h) { - const uchar* ptr = cv_img.ptr(h); + const char* ptr = cv_img.ptr(h); int img_index = 0; for (int w = 0; w < datum_width; ++w) { for (int c = 0; c < datum_channels; ++c) { From 1d586ff245447062cbd1c60603c485f99024753c Mon Sep 17 00:00:00 2001 From: Sergio Date: Mon, 6 Oct 2014 23:27:40 -0700 Subject: [PATCH 133/798] Added test for encoded Datum to test_io.cpp --- include/caffe/util/io.hpp | 8 ++-- src/caffe/test/test_io.cpp | 80 ++++++++++++++++++++++++++++++++++++++ src/caffe/util/io.cpp | 8 ++-- 3 files changed, 88 insertions(+), 8 deletions(-) diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 63afe6298ff..64df0155780 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -113,17 +113,17 @@ inline bool ReadImageToDatum(const string& filename, const int label, } bool DecodeDatum(const int height, const int width, const bool is_color, - Datum& datum); + Datum* datum); -inline bool DecodeDatum(const int height, const int width, Datum& datum) { +inline bool DecodeDatum(const int height, const int width, Datum* datum) { return DecodeDatum(height, width, true, datum); } -inline bool DecodeDatum(const bool is_color, Datum& datum) { +inline bool DecodeDatum(const bool is_color, Datum* datum) { return DecodeDatum(0, 0, is_color, datum); } -inline bool DecodeDatum(Datum& datum) { +inline bool DecodeDatum(Datum* datum) { return DecodeDatum(0, 0, true, datum); } diff --git a/src/caffe/test/test_io.cpp b/src/caffe/test/test_io.cpp index 6994afda0e3..4d941fa8683 100644 --- a/src/caffe/test/test_io.cpp +++ b/src/caffe/test/test_io.cpp @@ -276,4 +276,84 @@ TEST_F(IOTest, TestCVMatToDatumReference) { } } +TEST_F(IOTest, TestReadFileToDatum) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + EXPECT_TRUE(ReadFileToDatum(filename, &datum)); + EXPECT_TRUE(datum.encoded()); + EXPECT_EQ(datum.label(), -1); + EXPECT_EQ(datum.data().size(), 140391); +} + +TEST_F(IOTest, TestDecodeDatum) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + EXPECT_TRUE(ReadFileToDatum(filename, &datum)); + EXPECT_TRUE(DecodeDatum(&datum)); + EXPECT_FALSE(DecodeDatum(&datum)); + Datum datum_ref; + ReadImageToDatumReference(filename, 0, 0, 0, true, &datum_ref); + EXPECT_EQ(datum.channels(), datum_ref.channels()); + EXPECT_EQ(datum.height(), datum_ref.height()); + EXPECT_EQ(datum.width(), datum_ref.width()); + EXPECT_EQ(datum.data().size(), datum_ref.data().size()); + + const string& data = datum.data(); + const string& data_ref = datum_ref.data(); + for (int i = 0; i < datum.data().size(); ++i) { + EXPECT_TRUE(data[i] == data_ref[i]); + } +} + +TEST_F(IOTest, TestDecodeDatumToCVMat) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + EXPECT_TRUE(ReadFileToDatum(filename, &datum)); + cv::Mat cv_img = DecodeDatumToCVMat(datum); + EXPECT_EQ(cv_img.channels(), 3); + EXPECT_EQ(cv_img.rows, 360); + EXPECT_EQ(cv_img.cols, 480); +} + +TEST_F(IOTest, TestDecodeDatumToCVMatResized) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + EXPECT_TRUE(ReadFileToDatum(filename, &datum)); + cv::Mat cv_img = DecodeDatumToCVMat(datum, 100, 200); + EXPECT_EQ(cv_img.channels(), 3); + EXPECT_EQ(cv_img.rows, 100); + EXPECT_EQ(cv_img.cols, 200); +} + +TEST_F(IOTest, TestDecodeDatumToCVMatResizedGray) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + EXPECT_TRUE(ReadFileToDatum(filename, &datum)); + const bool is_color = false; + cv::Mat cv_img = DecodeDatumToCVMat(datum, 200, 100, is_color); + EXPECT_EQ(cv_img.channels(), 1); + EXPECT_EQ(cv_img.rows, 200); + EXPECT_EQ(cv_img.cols, 100); +} + +TEST_F(IOTest, TestDecodeDatumToCVMatContent) { + string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; + Datum datum; + EXPECT_TRUE(ReadFileToDatum(filename, &datum)); + cv::Mat cv_img = DecodeDatumToCVMat(datum); + cv::Mat cv_img_ref = ReadImageToCVMat(filename); + EXPECT_EQ(cv_img_ref.channels(), cv_img.channels()); + EXPECT_EQ(cv_img_ref.rows, cv_img.rows); + EXPECT_EQ(cv_img_ref.cols, cv_img.cols); + + for (int c = 0; c < datum.channels(); ++c) { + for (int h = 0; h < datum.height(); ++h) { + for (int w = 0; w < datum.width(); ++w) { + EXPECT_TRUE(cv_img.at(h, w)[c]== + cv_img_ref.at(h, w)[c]); + } + } + } +} + } // namespace caffe diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 6aa410a0feb..06b9deb078a 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -139,10 +139,10 @@ cv::Mat DecodeDatumToCVMat(const Datum& datum, // if height and width are set it will resize it // If Datum is not encoded will do nothing bool DecodeDatum(const int height, const int width, const bool is_color, - Datum& datum) { - if (datum.encoded()) { - cv::Mat cv_img = DecodeDatumToCVMat(datum, height, width, is_color); - CVMatToDatum(cv_img, &datum); + Datum* datum) { + if (datum->encoded()) { + cv::Mat cv_img = DecodeDatumToCVMat((*datum), height, width, is_color); + CVMatToDatum(cv_img, datum); return true; } else { return false; From 917e90a2e1be366fdc478a321accd96b79cb55f5 Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 15 Oct 2014 15:35:01 -0700 Subject: [PATCH 134/798] Added timers for benchmarking --- src/caffe/layers/data_layer.cpp | 22 +++++++++++++++++++--- src/caffe/layers/image_data_layer.cpp | 13 +++++++++++++ src/caffe/layers/window_data_layer.cpp | 20 ++++++++++++++------ src/caffe/net.cpp | 7 +++++++ 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index fcf9bb20a57..330381d2771 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -8,6 +8,7 @@ #include "caffe/dataset_factory.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/benchmark.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -47,6 +48,9 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, CHECK(iter_ != dataset_->end()); const Datum& datum = iter_->value; + if (DecodeDatum(datum)) { + LOG(INFO) << "Decoding Datum"; + } // image int crop_size = this->layer_param_.transform_param().crop_size(); if (crop_size > 0) { @@ -78,6 +82,8 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // This function is used to create a thread that prefetches the data. template void DataLayer::InternalThreadEntry() { + Timer batch_timer; + batch_timer.Start(); CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -87,25 +93,35 @@ void DataLayer::InternalThreadEntry() { top_label = this->prefetch_label_.mutable_cpu_data(); } const int batch_size = this->layer_param_.data_param().batch_size(); - + float read_time = 0; + float trans_time = 0; + Timer timer; for (int item_id = 0; item_id < batch_size; ++item_id) { + timer.Start(); + // get a blob CHECK(iter_ != dataset_->end()); const Datum& datum = iter_->value; + cv::Mat cv_img = DecodeDatumToCVMat(datum); + read_time += timer.MilliSeconds(); + timer.Start(); // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); - this->data_transformer_.Transform(datum, &(this->transformed_data_)); + this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); if (this->output_labels_) { top_label[item_id] = datum.label(); } - + trans_time += timer.MilliSeconds(); // go to the next iter ++iter_; if (iter_ == dataset_->end()) { iter_ = dataset_->begin(); } } + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + DLOG(INFO) << "Read time: " << read_time << "ms."; + DLOG(INFO) << "Transform time: " << trans_time << "ms."; } INSTANTIATE_CLASS(DataLayer); diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index 2085df2760a..67493117b88 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -6,6 +6,7 @@ #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" +#include "caffe/util/benchmark.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -91,6 +92,8 @@ void ImageDataLayer::ShuffleImages() { // This function is used to create a thread that prefetches the data. template void ImageDataLayer::InternalThreadEntry() { + Timer batch_timer; + batch_timer.Start(); CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -103,18 +106,25 @@ void ImageDataLayer::InternalThreadEntry() { // datum scales const int lines_size = lines_.size(); + float read_time = 0; + float trans_time = 0; + Timer timer; for (int item_id = 0; item_id < batch_size; ++item_id) { // get a blob + timer.Start(); CHECK_GT(lines_size, lines_id_); cv::Mat cv_img = ReadImageToCVMat(lines_[lines_id_].first, new_height, new_width, is_color); if (!cv_img.data) { continue; } + read_time += timer.MilliSeconds(); + timer.Start(); // Apply transformations (mirror, crop...) to the image int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + trans_time += timer.MilliSeconds(); top_label[item_id] = lines_[lines_id_].second; // go to the next iter @@ -128,6 +138,9 @@ void ImageDataLayer::InternalThreadEntry() { } } } + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + DLOG(INFO) << "Read time: " << read_time << "ms."; + DLOG(INFO) << "Transform time: " << trans_time << "ms."; } INSTANTIATE_CLASS(ImageDataLayer); diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 529c3b47bd9..47e0fb2a123 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -13,6 +13,7 @@ #include "caffe/common.hpp" #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" +#include "caffe/util/benchmark.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -192,7 +193,8 @@ template void WindowDataLayer::InternalThreadEntry() { // At each iteration, sample N windows where N*p are foreground (object) // windows and N*(1-p) are background (non-object) windows - + Timer batch_timer; + batch_timer.Start(); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = this->prefetch_label_.mutable_cpu_data(); const Dtype scale = this->layer_param_.window_data_param().scale(); @@ -219,19 +221,20 @@ void WindowDataLayer::InternalThreadEntry() { const int num_samples[2] = { batch_size - num_fg, num_fg }; int item_id = 0; + float read_time = 0; + float trans_time = 0; + Timer timer; // sample from bg set then fg set for (int is_fg = 0; is_fg < 2; ++is_fg) { for (int dummy = 0; dummy < num_samples[is_fg]; ++dummy) { // sample a window + timer.Start(); const unsigned int rand_index = PrefetchRand(); vector window = (is_fg) ? fg_windows_[rand_index % fg_windows_.size()] : bg_windows_[rand_index % bg_windows_.size()]; - bool do_mirror = false; - if (mirror && PrefetchRand() % 2) { - do_mirror = true; - } + bool do_mirror = mirror && PrefetchRand() % 2; // load the image containing the window pair > image = @@ -242,6 +245,8 @@ void WindowDataLayer::InternalThreadEntry() { LOG(ERROR) << "Could not open or find file " << image.first; return; } + read_time += timer.MilliSeconds(); + timer.Start(); const int channels = cv_img.channels(); // crop window out of image and warp it @@ -359,7 +364,7 @@ void WindowDataLayer::InternalThreadEntry() { } } } - + trans_time += timer.MilliSeconds(); // get window label top_label[item_id] = window[WindowDataLayer::LABEL]; @@ -399,6 +404,9 @@ void WindowDataLayer::InternalThreadEntry() { item_id++; } } + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + DLOG(INFO) << "Read time: " << read_time << "ms."; + DLOG(INFO) << "Transform time: " << trans_time << "ms."; } INSTANTIATE_CLASS(WindowDataLayer); diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 21ab15fd31b..5b7152e6993 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -9,6 +9,7 @@ #include "caffe/layer.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/benchmark.hpp" #include "caffe/util/insert_splits.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" @@ -499,6 +500,8 @@ void Net::GetLearningRateAndWeightDecay() { template Dtype Net::ForwardFromTo(int start, int end) { + Timer timer; + timer.Start(); CHECK_GE(start, 0); CHECK_LT(end, layers_.size()); Dtype loss = 0; @@ -509,6 +512,7 @@ Dtype Net::ForwardFromTo(int start, int end) { loss += layer_loss; if (debug_info_) { ForwardDebugInfo(i); } } + LOG(INFO) << "Forward time: " << timer.MilliSeconds() << "ms."; return loss; } @@ -565,6 +569,8 @@ string Net::Forward(const string& input_blob_protos, Dtype* loss) { template void Net::BackwardFromTo(int start, int end) { + Timer timer; + timer.Start(); CHECK_GE(end, 0); CHECK_LT(start, layers_.size()); for (int i = start; i >= end; --i) { @@ -574,6 +580,7 @@ void Net::BackwardFromTo(int start, int end) { if (debug_info_) { BackwardDebugInfo(i); } } } + LOG(INFO) << "Backward time: " << timer.MilliSeconds() << "ms."; } template From d337b044c25abf30f94dd9fb7d25aca940eda7c0 Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 15 Oct 2014 15:35:26 -0700 Subject: [PATCH 135/798] Add fast code for transform(cv::Mat,Blob) --- src/caffe/data_transformer.cpp | 103 +++++++++++++++++++++++++++++++- src/caffe/layers/data_layer.cpp | 12 +++- 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index dffaba545b5..8f145994562 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -179,9 +179,106 @@ void DataTransformer::Transform(const vector & datum_vector, template void DataTransformer::Transform(const cv::Mat& cv_img, Blob* transformed_blob) { - Datum datum; - CVMatToDatum(cv_img, &datum); - Transform(datum, transformed_blob); + const int img_channels = cv_img.channels(); + const int img_height = cv_img.rows; + const int img_width = cv_img.cols; + + const int channels = transformed_blob->channels(); + const int height = transformed_blob->height(); + const int width = transformed_blob->width(); + const int num = transformed_blob->num(); + + CHECK_EQ(channels, img_channels); + CHECK_LE(height, img_height); + CHECK_LE(width, img_width); + CHECK_GE(num, 1); + + CHECK(cv_img.depth() == CV_8U || cv_img.depth() == CV_8S) << + "Image data type must be unsigned or signed byte"; + + const int crop_size = param_.crop_size(); + const Dtype scale = param_.scale(); + const bool do_mirror = param_.mirror() && Rand(2); + const bool has_mean_file = param_.has_mean_file(); + const bool has_mean_values = mean_values_.size() > 0; + + CHECK_GT(img_channels, 0); + CHECK_GE(img_height, crop_size); + CHECK_GE(img_width, crop_size); + + Dtype* mean = NULL; + if (has_mean_file) { + CHECK_EQ(img_channels, data_mean_.channels()); + CHECK_EQ(img_height, data_mean_.height()); + CHECK_EQ(img_width, data_mean_.width()); + mean = data_mean_.mutable_cpu_data(); + } + if (has_mean_values) { + CHECK(mean_values_.size() == 1 || mean_values_.size() == img_channels) << + "Specify either 1 mean_value or as many as channels: " << img_channels; + if (img_channels > 1 && mean_values_.size() == 1) { + // Replicate the mean_value for simplicity + for (int c = 1; c < img_channels; ++c) { + mean_values_.push_back(mean_values_[0]); + } + } + } + + int h_off = 0; + int w_off = 0; + cv::Mat cv_cropped_img = cv_img; + if (crop_size) { + CHECK_EQ(crop_size, height); + CHECK_EQ(crop_size, width); + // We only do random crop when we do training. + if (phase_ == Caffe::TRAIN) { + h_off = Rand(img_height - crop_size + 1); + w_off = Rand(img_width - crop_size + 1); + } else { + h_off = (img_height - crop_size) / 2; + w_off = (img_width - crop_size) / 2; + } + cv::Rect roi(h_off, w_off, crop_size, crop_size); + cv_cropped_img = cv_img(roi); + } else { + CHECK_EQ(img_height, height); + CHECK_EQ(img_width, width); + } + + // if (do_mirror) { + // cv::flip(cv_cropped_img, cv_cropped_img, 1); + // } + CHECK(cv_cropped_img.data); + + Dtype* transformed_data = transformed_blob->mutable_cpu_data(); + int top_index; + for (int h = 0; h < height; ++h) { + const char* ptr = cv_cropped_img.ptr(h); + int img_index = 0; + for (int w = 0; w < width; ++w) { + for (int c = 0; c < img_channels; ++c) { + if (do_mirror) { + top_index = (c * height + h) * width + (width - 1 - w); + } else { + top_index = (c * height + h) * width + w; + } + // int top_index = (c * height + h) * width + w; + Dtype pixel = static_cast(ptr[img_index++]); + if (has_mean_file) { + int mean_index = (c * img_height + h_off + h) * img_width + w_off + w; + transformed_data[top_index] = + (pixel - mean[mean_index]) * scale; + } else { + if (has_mean_values) { + transformed_data[top_index] = + (pixel - mean_values_[c]) * scale; + } else { + transformed_data[top_index] = pixel * scale; + } + } + } + } + } } #endif diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 330381d2771..95c54279661 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -101,14 +101,22 @@ void DataLayer::InternalThreadEntry() { // get a blob CHECK(iter_ != dataset_->end()); const Datum& datum = iter_->value; - cv::Mat cv_img = DecodeDatumToCVMat(datum); + cv::Mat cv_img; + if (datum.encoded()) { + cv_img = DecodeDatumToCVMat(datum); + } read_time += timer.MilliSeconds(); timer.Start(); // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); - this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + if (datum.encoded()) { + this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + } else { + this->data_transformer_.Transform(datum, &(this->transformed_data_)); + } + if (this->output_labels_) { top_label[item_id] = datum.label(); } From e9d6e5a0b22a9f4768b8c04c9031ee8adb822ece Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 7 Oct 2014 11:19:16 -0700 Subject: [PATCH 136/798] Add root_folder to ImageDataLayer --- Makefile | 6 ++++++ include/caffe/net.hpp | 10 +++++++++ src/caffe/data_transformer.cpp | 12 ++++------- src/caffe/layers/data_layer.cpp | 25 ++++++++++++++------- src/caffe/layers/image_data_layer.cpp | 30 +++++++++++++++++++------- src/caffe/layers/window_data_layer.cpp | 24 +++++++++++++++------ src/caffe/net.cpp | 10 +++++++++ src/caffe/proto/caffe.proto | 1 + src/caffe/util/io.cpp | 5 ++--- 9 files changed, 90 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 26d5964cacc..393fe18a70d 100644 --- a/Makefile +++ b/Makefile @@ -281,6 +281,12 @@ ifeq ($(USE_CUDNN), 1) COMMON_FLAGS += -DUSE_CUDNN endif +TIMING ?= 0 +# Timing Flag +ifneq ($(TIMING), 0) + COMMON_FLAGS += -DTIMING +endif + # CPU-only configuration ifeq ($(CPU_ONLY), 1) OBJS := $(PROTO_OBJS) $(CXX_OBJS) diff --git a/include/caffe/net.hpp b/include/caffe/net.hpp index 1d06dc45533..879f474674d 100644 --- a/include/caffe/net.hpp +++ b/include/caffe/net.hpp @@ -11,6 +11,9 @@ #include "caffe/common.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" +#ifdef TIMING +#include "caffe/util/benchmark.hpp" +#endif namespace caffe { @@ -76,9 +79,16 @@ class Net { void Reshape(); Dtype ForwardBackward(const vector* > & bottom) { + #ifdef TIMING + Timer timer; + timer.Start(); + #endif Dtype loss; Forward(bottom, &loss); Backward(); + #ifdef TIMING + LOG(INFO) << "ForwardBackward Time: " << timer.MilliSeconds() << "ms."; + #endif return loss; } diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 8f145994562..023396ce5e6 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -193,8 +193,7 @@ void DataTransformer::Transform(const cv::Mat& cv_img, CHECK_LE(width, img_width); CHECK_GE(num, 1); - CHECK(cv_img.depth() == CV_8U || cv_img.depth() == CV_8S) << - "Image data type must be unsigned or signed byte"; + CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte"; const int crop_size = param_.crop_size(); const Dtype scale = param_.scale(); @@ -238,22 +237,19 @@ void DataTransformer::Transform(const cv::Mat& cv_img, h_off = (img_height - crop_size) / 2; w_off = (img_width - crop_size) / 2; } - cv::Rect roi(h_off, w_off, crop_size, crop_size); + cv::Rect roi(w_off, h_off, crop_size, crop_size); cv_cropped_img = cv_img(roi); } else { CHECK_EQ(img_height, height); CHECK_EQ(img_width, width); } - - // if (do_mirror) { - // cv::flip(cv_cropped_img, cv_cropped_img, 1); - // } + CHECK(cv_cropped_img.data); Dtype* transformed_data = transformed_blob->mutable_cpu_data(); int top_index; for (int h = 0; h < height; ++h) { - const char* ptr = cv_cropped_img.ptr(h); + const uchar* ptr = cv_cropped_img.ptr(h); int img_index = 0; for (int w = 0; w < width; ++w) { for (int c = 0; c < img_channels; ++c) { diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 95c54279661..95604e5a1ac 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -8,7 +8,9 @@ #include "caffe/dataset_factory.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" +#ifdef TIMING #include "caffe/util/benchmark.hpp" +#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -82,8 +84,13 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // This function is used to create a thread that prefetches the data. template void DataLayer::InternalThreadEntry() { + #ifdef TIMING Timer batch_timer; batch_timer.Start(); + float read_time = 0; + float trans_time = 0; + Timer timer; + #endif CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -93,9 +100,6 @@ void DataLayer::InternalThreadEntry() { top_label = this->prefetch_label_.mutable_cpu_data(); } const int batch_size = this->layer_param_.data_param().batch_size(); - float read_time = 0; - float trans_time = 0; - Timer timer; for (int item_id = 0; item_id < batch_size; ++item_id) { timer.Start(); // get a blob @@ -105,31 +109,36 @@ void DataLayer::InternalThreadEntry() { if (datum.encoded()) { cv_img = DecodeDatumToCVMat(datum); } + #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); + #endif // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); if (datum.encoded()) { - this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); } else { this->data_transformer_.Transform(datum, &(this->transformed_data_)); } - if (this->output_labels_) { top_label[item_id] = datum.label(); } + #ifdef TIMING trans_time += timer.MilliSeconds(); + #endif // go to the next iter ++iter_; if (iter_ == dataset_->end()) { iter_ = dataset_->begin(); } } - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + #ifdef TIMING + LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + LOG(INFO) << "Read time: " << read_time << "ms."; + LOG(INFO) << "Transform time: " << trans_time << "ms."; + #endif } INSTANTIATE_CLASS(DataLayer); diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index 67493117b88..0abcd888b67 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -6,7 +6,9 @@ #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" +#ifdef TIMING #include "caffe/util/benchmark.hpp" +#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -24,6 +26,7 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, const int new_height = this->layer_param_.image_data_param().new_height(); const int new_width = this->layer_param_.image_data_param().new_width(); const bool is_color = this->layer_param_.image_data_param().is_color(); + string root_folder = this->layer_param_.image_data_param().root_folder(); CHECK((new_height == 0 && new_width == 0) || (new_height > 0 && new_width > 0)) << "Current implementation requires " @@ -57,7 +60,7 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, lines_id_ = skip; } // Read an image, and use it to initialize the top blob. - cv::Mat cv_img = ReadImageToCVMat(lines_[lines_id_].first, + cv::Mat cv_img = ReadImageToCVMat(root_folder + lines_[lines_id_].first, new_height, new_width, is_color); const int channels = cv_img.channels(); const int height = cv_img.rows; @@ -92,8 +95,13 @@ void ImageDataLayer::ShuffleImages() { // This function is used to create a thread that prefetches the data. template void ImageDataLayer::InternalThreadEntry() { + #ifdef TIMING Timer batch_timer; batch_timer.Start(); + float read_time = 0; + float trans_time = 0; + Timer timer; + #endif CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -103,28 +111,32 @@ void ImageDataLayer::InternalThreadEntry() { const int new_height = image_data_param.new_height(); const int new_width = image_data_param.new_width(); const bool is_color = image_data_param.is_color(); + string root_folder = image_data_param.root_folder(); // datum scales const int lines_size = lines_.size(); - float read_time = 0; - float trans_time = 0; - Timer timer; for (int item_id = 0; item_id < batch_size; ++item_id) { // get a blob + #ifdef TIMING timer.Start(); + #endif CHECK_GT(lines_size, lines_id_); - cv::Mat cv_img = ReadImageToCVMat(lines_[lines_id_].first, + cv::Mat cv_img = ReadImageToCVMat(root_folder + lines_[lines_id_].first, new_height, new_width, is_color); if (!cv_img.data) { continue; } + #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); + #endif // Apply transformations (mirror, crop...) to the image int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + #ifdef TIMING trans_time += timer.MilliSeconds(); + #endif top_label[item_id] = lines_[lines_id_].second; // go to the next iter @@ -138,9 +150,11 @@ void ImageDataLayer::InternalThreadEntry() { } } } - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + #ifdef TIMING + LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + LOG(INFO) << "Read time: " << read_time << "ms."; + LOG(INFO) << "Transform time: " << trans_time << "ms."; + #endif } INSTANTIATE_CLASS(ImageDataLayer); diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 47e0fb2a123..8e65615507b 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -13,7 +13,9 @@ #include "caffe/common.hpp" #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" +#ifdef TIMING #include "caffe/util/benchmark.hpp" +#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -193,8 +195,13 @@ template void WindowDataLayer::InternalThreadEntry() { // At each iteration, sample N windows where N*p are foreground (object) // windows and N*(1-p) are background (non-object) windows + #ifdef TIMING Timer batch_timer; batch_timer.Start(); + float read_time = 0; + float trans_time = 0; + Timer timer; + #endif Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = this->prefetch_label_.mutable_cpu_data(); const Dtype scale = this->layer_param_.window_data_param().scale(); @@ -221,14 +228,13 @@ void WindowDataLayer::InternalThreadEntry() { const int num_samples[2] = { batch_size - num_fg, num_fg }; int item_id = 0; - float read_time = 0; - float trans_time = 0; - Timer timer; // sample from bg set then fg set for (int is_fg = 0; is_fg < 2; ++is_fg) { for (int dummy = 0; dummy < num_samples[is_fg]; ++dummy) { // sample a window + #ifdef TIMING timer.Start(); + #endif const unsigned int rand_index = PrefetchRand(); vector window = (is_fg) ? fg_windows_[rand_index % fg_windows_.size()] : @@ -245,8 +251,10 @@ void WindowDataLayer::InternalThreadEntry() { LOG(ERROR) << "Could not open or find file " << image.first; return; } + #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); + #endif const int channels = cv_img.channels(); // crop window out of image and warp it @@ -364,7 +372,9 @@ void WindowDataLayer::InternalThreadEntry() { } } } + #ifdef TIMING trans_time += timer.MilliSeconds(); + #endif // get window label top_label[item_id] = window[WindowDataLayer::LABEL]; @@ -404,9 +414,11 @@ void WindowDataLayer::InternalThreadEntry() { item_id++; } } - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + #ifdef TIMING + LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + LOG(INFO) << "Read time: " << read_time << "ms."; + LOG(INFO) << "Transform time: " << trans_time << "ms."; + #endif } INSTANTIATE_CLASS(WindowDataLayer); diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 5b7152e6993..c0e56920c83 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -9,7 +9,9 @@ #include "caffe/layer.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" +#ifdef TIMING #include "caffe/util/benchmark.hpp" +#endif #include "caffe/util/insert_splits.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" @@ -500,8 +502,10 @@ void Net::GetLearningRateAndWeightDecay() { template Dtype Net::ForwardFromTo(int start, int end) { + #ifdef TIMING Timer timer; timer.Start(); + #endif CHECK_GE(start, 0); CHECK_LT(end, layers_.size()); Dtype loss = 0; @@ -512,7 +516,9 @@ Dtype Net::ForwardFromTo(int start, int end) { loss += layer_loss; if (debug_info_) { ForwardDebugInfo(i); } } + #ifdef TIMING LOG(INFO) << "Forward time: " << timer.MilliSeconds() << "ms."; + #endif return loss; } @@ -569,8 +575,10 @@ string Net::Forward(const string& input_blob_protos, Dtype* loss) { template void Net::BackwardFromTo(int start, int end) { + #ifdef TIMING Timer timer; timer.Start(); + #endif CHECK_GE(end, 0); CHECK_LT(start, layers_.size()); for (int i = start; i >= end; --i) { @@ -580,7 +588,9 @@ void Net::BackwardFromTo(int start, int end) { if (debug_info_) { BackwardDebugInfo(i); } } } + #ifdef TIMING LOG(INFO) << "Backward time: " << timer.MilliSeconds() << "ms."; + #endif } template diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 53db6f76945..b602d0e4c7b 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -540,6 +540,7 @@ message ImageDataParameter { // DEPRECATED. See TransformationParameter. Specify if we want to randomly mirror // data. optional bool mirror = 6 [default = false]; + optional string root_folder = 12 [default = ""]; } // Message that stores parameters InfogainLossLayer diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 06b9deb078a..b136bc8a120 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -150,8 +150,7 @@ bool DecodeDatum(const int height, const int width, const bool is_color, } void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) { - CHECK(cv_img.depth() == CV_8U || cv_img.depth() == CV_8S) << - "Image data type must be unsigned or signed byte"; + CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte"; datum->set_channels(cv_img.channels()); datum->set_height(cv_img.rows); datum->set_width(cv_img.cols); @@ -164,7 +163,7 @@ void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) { int datum_size = datum_channels * datum_height * datum_width; std::string buffer(datum_size, ' '); for (int h = 0; h < datum_height; ++h) { - const char* ptr = cv_img.ptr(h); + const uchar* ptr = cv_img.ptr(h); int img_index = 0; for (int w = 0; w < datum_width; ++w) { for (int c = 0; c < datum_channels; ++c) { From 3744598ed39d26d6219cd0369dd6923e2c747c99 Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 7 Oct 2014 14:14:50 -0700 Subject: [PATCH 137/798] Speed up WindowDataLayer and add mean_values --- include/caffe/data_layers.hpp | 3 ++ src/caffe/layers/window_data_layer.cpp | 65 ++++++++++++++++++-------- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index a2ea854e5ff..c4903ce0891 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -325,6 +325,9 @@ class WindowDataLayer : public BasePrefetchingDataLayer { vector > fg_windows_; vector > bg_windows_; Blob data_mean_; + vector mean_values_; + bool has_mean_file_; + bool has_mean_values_; }; } // namespace caffe diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 8e65615507b..fc0ffc886bb 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -170,15 +170,30 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, this->prefetch_label_.Reshape(batch_size, 1, 1, 1); // data mean - if (this->transform_param_.has_mean_file()) { + has_mean_file_ = this->transform_param_.has_mean_file(); + has_mean_values_ = this->transform_param_.mean_value_size() > 0; + if (has_mean_file_) { const string& mean_file = this->transform_param_.mean_file(); LOG(INFO) << "Loading mean file from" << mean_file; BlobProto blob_proto; ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); data_mean_.FromProto(blob_proto); - } else { - data_mean_.Reshape(1, channels, crop_size, crop_size); + } + if (has_mean_values_) { + CHECK(has_mean_file_ == false) << + "Cannot specify mean_file and mean_value at the same time"; + for (int c = 0; c < this->transform_param_.mean_value_size(); ++c) { + mean_values_.push_back(this->transform_param_.mean_value(c)); + } + CHECK(mean_values_.size() == 1 || mean_values_.size() == channels) << + "Specify either 1 mean_value or as many as channels: " << channels; + if (channels > 1 && mean_values_.size() == 1) { + // Replicate the mean_value for simplicity + for (int c = 1; c < channels; ++c) { + mean_values_.push_back(mean_values_[0]); + } + } } } @@ -211,10 +226,14 @@ void WindowDataLayer::InternalThreadEntry() { const bool mirror = this->transform_param_.mirror(); const float fg_fraction = this->layer_param_.window_data_param().fg_fraction(); - const Dtype* mean = this->data_mean_.cpu_data(); - const int mean_off = (this->data_mean_.width() - crop_size) / 2; - const int mean_width = this->data_mean_.width(); - const int mean_height = this->data_mean_.height(); + Dtype* mean = NULL; + int mean_off, mean_width, mean_height; + if (this->has_mean_file_) { + mean = this->data_mean_.mutable_cpu_data(); + mean_off = (this->data_mean_.width() - crop_size) / 2; + mean_width = this->data_mean_.width(); + mean_height = this->data_mean_.height(); + } cv::Size cv_crop_size(crop_size, crop_size); const string& crop_mode = this->layer_param_.window_data_param().crop_mode(); @@ -357,18 +376,26 @@ void WindowDataLayer::InternalThreadEntry() { } // copy the warped window into top_data - for (int c = 0; c < channels; ++c) { - for (int h = 0; h < cv_cropped_img.rows; ++h) { - for (int w = 0; w < cv_cropped_img.cols; ++w) { - Dtype pixel = - static_cast(cv_cropped_img.at(h, w)[c]); - - top_data[((item_id * channels + c) * crop_size + h + pad_h) - * crop_size + w + pad_w] - = (pixel - - mean[(c * mean_height + h + mean_off + pad_h) - * mean_width + w + mean_off + pad_w]) - * scale; + for (int h = 0; h < cv_cropped_img.rows; ++h) { + const uchar* ptr = cv_cropped_img.ptr(h); + int img_index = 0; + for (int w = 0; w < cv_cropped_img.cols; ++w) { + for (int c = 0; c < channels; ++c) { + int top_index = ((item_id * channels + c) * crop_size + h + pad_h) + * crop_size + w + pad_w; + // int top_index = (c * height + h) * width + w; + Dtype pixel = static_cast(ptr[img_index++]); + if (this->has_mean_file_) { + int mean_index = (c * mean_height + h + mean_off + pad_h) + * mean_width + w + mean_off + pad_w; + top_data[top_index] = (pixel - mean[mean_index]) * scale; + } else { + if (this->has_mean_values_) { + top_data[top_index] = (pixel - this->mean_values_[c]) * scale; + } else { + top_data[top_index] = pixel * scale; + } + } } } } From 14f548d8e45573044ba20cdf52eeaccef2217ff5 Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 7 Oct 2014 17:19:15 -0700 Subject: [PATCH 138/798] Added cache_images to WindowDataLayer Added root_folder to WindowDataLayer to locate images --- include/caffe/data_layers.hpp | 2 ++ src/caffe/layers/window_data_layer.cpp | 38 ++++++++++++++++++++++---- src/caffe/proto/caffe.proto | 4 +++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index c4903ce0891..34b9b30aa3e 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -328,6 +328,8 @@ class WindowDataLayer : public BasePrefetchingDataLayer { vector mean_values_; bool has_mean_file_; bool has_mean_values_; + bool cache_images_; + vector > image_database_cache_; }; } // namespace caffe diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index fc0ffc886bb..8f75557d694 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -59,7 +59,14 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, << " background (non-object) overlap threshold: " << this->layer_param_.window_data_param().bg_threshold() << std::endl << " foreground sampling fraction: " - << this->layer_param_.window_data_param().fg_fraction(); + << this->layer_param_.window_data_param().fg_fraction() << std::endl + << " cache_images: " + << this->layer_param_.window_data_param().cache_images() << std::endl + << " root_folder: " + << this->layer_param_.window_data_param().root_folder(); + + cache_images_ = this->layer_param_.window_data_param().cache_images(); + string root_folder = this->layer_param_.window_data_param().root_folder(); const bool prefetch_needs_rand = this->transform_param_.mirror() || @@ -88,12 +95,21 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, // read image path string image_path; infile >> image_path; + image_path = root_folder + image_path; // read image dimensions vector image_size(3); infile >> image_size[0] >> image_size[1] >> image_size[2]; channels = image_size[0]; image_database_.push_back(std::make_pair(image_path, image_size)); + if (cache_images_) { + Datum datum; + if (!ReadFileToDatum(image_path, &datum)) { + LOG(ERROR) << "Could not open or find file " << image_path; + return; + } + image_database_cache_.push_back(std::make_pair(image_path, datum)); + } // read each box int num_windows; infile >> num_windows; @@ -227,7 +243,9 @@ void WindowDataLayer::InternalThreadEntry() { const float fg_fraction = this->layer_param_.window_data_param().fg_fraction(); Dtype* mean = NULL; - int mean_off, mean_width, mean_height; + int mean_off = 0; + int mean_width = 0; + int mean_height = 0; if (this->has_mean_file_) { mean = this->data_mean_.mutable_cpu_data(); mean_off = (this->data_mean_.width() - crop_size) / 2; @@ -265,10 +283,17 @@ void WindowDataLayer::InternalThreadEntry() { pair > image = image_database_[window[WindowDataLayer::IMAGE_INDEX]]; - cv::Mat cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR); - if (!cv_img.data) { - LOG(ERROR) << "Could not open or find file " << image.first; - return; + cv::Mat cv_img; + if (this->cache_images_) { + pair image_cached = + image_database_cache_[window[WindowDataLayer::IMAGE_INDEX]]; + cv_img = DecodeDatumToCVMat(image_cached.second); + } else { + cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR); + if (!cv_img.data) { + LOG(ERROR) << "Could not open or find file " << image.first; + return; + } } #ifdef TIMING read_time += timer.MilliSeconds(); @@ -442,6 +467,7 @@ void WindowDataLayer::InternalThreadEntry() { } } #ifdef TIMING + batch_timer.Stop(); LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; LOG(INFO) << "Read time: " << read_time << "ms."; LOG(INFO) << "Transform time: " << trans_time << "ms."; diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index b602d0e4c7b..03d955fa7ac 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -714,6 +714,10 @@ message WindowDataParameter { // warp: cropped window is warped to a fixed size and aspect ratio // square: the tightest square around the window is cropped optional string crop_mode = 11 [default = "warp"]; + // cache_images: will load all images in memory for faster access + optional bool cache_images = 12 [default = false]; + // append root_folder to locate images + optional string root_folder = 13 [default = ""]; } // DEPRECATED: V0LayerParameter is the old way of specifying layer parameters From d6b71e58237968679cea44418b869721a5ea9654 Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 15 Oct 2014 15:36:16 -0700 Subject: [PATCH 139/798] Change caffe time to do forward/backward and accumulate time per layer --- Makefile | 6 ---- src/caffe/layers/data_layer.cpp | 18 +++------- src/caffe/layers/image_data_layer.cpp | 19 +++------- src/caffe/layers/window_data_layer.cpp | 18 ++-------- src/caffe/net.cpp | 17 --------- tools/caffe.cpp | 49 ++++++++++++++++---------- 6 files changed, 42 insertions(+), 85 deletions(-) diff --git a/Makefile b/Makefile index 393fe18a70d..26d5964cacc 100644 --- a/Makefile +++ b/Makefile @@ -281,12 +281,6 @@ ifeq ($(USE_CUDNN), 1) COMMON_FLAGS += -DUSE_CUDNN endif -TIMING ?= 0 -# Timing Flag -ifneq ($(TIMING), 0) - COMMON_FLAGS += -DTIMING -endif - # CPU-only configuration ifeq ($(CPU_ONLY), 1) OBJS := $(PROTO_OBJS) $(CXX_OBJS) diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 95604e5a1ac..7ddd4662e73 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -8,9 +8,7 @@ #include "caffe/dataset_factory.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" -#ifdef TIMING #include "caffe/util/benchmark.hpp" -#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -84,13 +82,11 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // This function is used to create a thread that prefetches the data. template void DataLayer::InternalThreadEntry() { - #ifdef TIMING Timer batch_timer; batch_timer.Start(); float read_time = 0; float trans_time = 0; Timer timer; - #endif CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -105,14 +101,13 @@ void DataLayer::InternalThreadEntry() { // get a blob CHECK(iter_ != dataset_->end()); const Datum& datum = iter_->value; + cv::Mat cv_img; if (datum.encoded()) { cv_img = DecodeDatumToCVMat(datum); } - #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); - #endif // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); @@ -125,20 +120,17 @@ void DataLayer::InternalThreadEntry() { if (this->output_labels_) { top_label[item_id] = datum.label(); } - #ifdef TIMING trans_time += timer.MilliSeconds(); - #endif // go to the next iter ++iter_; if (iter_ == dataset_->end()) { iter_ = dataset_->begin(); } } - #ifdef TIMING - LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - LOG(INFO) << "Read time: " << read_time << "ms."; - LOG(INFO) << "Transform time: " << trans_time << "ms."; - #endif + batch_timer.Stop(); + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + DLOG(INFO) << "Read time: " << read_time << "ms."; + DLOG(INFO) << "Transform time: " << trans_time << "ms."; } INSTANTIATE_CLASS(DataLayer); diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index 0abcd888b67..e0778e5989f 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -6,9 +6,7 @@ #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" -#ifdef TIMING #include "caffe/util/benchmark.hpp" -#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -95,13 +93,11 @@ void ImageDataLayer::ShuffleImages() { // This function is used to create a thread that prefetches the data. template void ImageDataLayer::InternalThreadEntry() { - #ifdef TIMING Timer batch_timer; batch_timer.Start(); float read_time = 0; float trans_time = 0; Timer timer; - #endif CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -117,26 +113,20 @@ void ImageDataLayer::InternalThreadEntry() { const int lines_size = lines_.size(); for (int item_id = 0; item_id < batch_size; ++item_id) { // get a blob - #ifdef TIMING timer.Start(); - #endif CHECK_GT(lines_size, lines_id_); cv::Mat cv_img = ReadImageToCVMat(root_folder + lines_[lines_id_].first, new_height, new_width, is_color); if (!cv_img.data) { continue; } - #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); - #endif // Apply transformations (mirror, crop...) to the image int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); - #ifdef TIMING trans_time += timer.MilliSeconds(); - #endif top_label[item_id] = lines_[lines_id_].second; // go to the next iter @@ -150,11 +140,10 @@ void ImageDataLayer::InternalThreadEntry() { } } } - #ifdef TIMING - LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - LOG(INFO) << "Read time: " << read_time << "ms."; - LOG(INFO) << "Transform time: " << trans_time << "ms."; - #endif + batch_timer.Stop(); + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + DLOG(INFO) << "Read time: " << read_time << "ms."; + DLOG(INFO) << "Transform time: " << trans_time << "ms."; } INSTANTIATE_CLASS(ImageDataLayer); diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 8f75557d694..14e8caad6c9 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -13,9 +13,7 @@ #include "caffe/common.hpp" #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" -#ifdef TIMING #include "caffe/util/benchmark.hpp" -#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -226,13 +224,11 @@ template void WindowDataLayer::InternalThreadEntry() { // At each iteration, sample N windows where N*p are foreground (object) // windows and N*(1-p) are background (non-object) windows - #ifdef TIMING Timer batch_timer; batch_timer.Start(); float read_time = 0; float trans_time = 0; Timer timer; - #endif Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = this->prefetch_label_.mutable_cpu_data(); const Dtype scale = this->layer_param_.window_data_param().scale(); @@ -269,9 +265,7 @@ void WindowDataLayer::InternalThreadEntry() { for (int is_fg = 0; is_fg < 2; ++is_fg) { for (int dummy = 0; dummy < num_samples[is_fg]; ++dummy) { // sample a window - #ifdef TIMING timer.Start(); - #endif const unsigned int rand_index = PrefetchRand(); vector window = (is_fg) ? fg_windows_[rand_index % fg_windows_.size()] : @@ -295,10 +289,8 @@ void WindowDataLayer::InternalThreadEntry() { return; } } - #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); - #endif const int channels = cv_img.channels(); // crop window out of image and warp it @@ -424,9 +416,7 @@ void WindowDataLayer::InternalThreadEntry() { } } } - #ifdef TIMING trans_time += timer.MilliSeconds(); - #endif // get window label top_label[item_id] = window[WindowDataLayer::LABEL]; @@ -466,12 +456,10 @@ void WindowDataLayer::InternalThreadEntry() { item_id++; } } - #ifdef TIMING batch_timer.Stop(); - LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - LOG(INFO) << "Read time: " << read_time << "ms."; - LOG(INFO) << "Transform time: " << trans_time << "ms."; - #endif + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + DLOG(INFO) << "Read time: " << read_time << "ms."; + DLOG(INFO) << "Transform time: " << trans_time << "ms."; } INSTANTIATE_CLASS(WindowDataLayer); diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index c0e56920c83..21ab15fd31b 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -9,9 +9,6 @@ #include "caffe/layer.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" -#ifdef TIMING -#include "caffe/util/benchmark.hpp" -#endif #include "caffe/util/insert_splits.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" @@ -502,10 +499,6 @@ void Net::GetLearningRateAndWeightDecay() { template Dtype Net::ForwardFromTo(int start, int end) { - #ifdef TIMING - Timer timer; - timer.Start(); - #endif CHECK_GE(start, 0); CHECK_LT(end, layers_.size()); Dtype loss = 0; @@ -516,9 +509,6 @@ Dtype Net::ForwardFromTo(int start, int end) { loss += layer_loss; if (debug_info_) { ForwardDebugInfo(i); } } - #ifdef TIMING - LOG(INFO) << "Forward time: " << timer.MilliSeconds() << "ms."; - #endif return loss; } @@ -575,10 +565,6 @@ string Net::Forward(const string& input_blob_protos, Dtype* loss) { template void Net::BackwardFromTo(int start, int end) { - #ifdef TIMING - Timer timer; - timer.Start(); - #endif CHECK_GE(end, 0); CHECK_LT(start, layers_.size()); for (int i = start; i >= end; --i) { @@ -588,9 +574,6 @@ void Net::BackwardFromTo(int start, int end) { if (debug_info_) { BackwardDebugInfo(i); } } } - #ifdef TIMING - LOG(INFO) << "Backward time: " << timer.MilliSeconds() << "ms."; - #endif } template diff --git a/tools/caffe.cpp b/tools/caffe.cpp index bfcd9f19cec..1c842a078c2 100644 --- a/tools/caffe.cpp +++ b/tools/caffe.cpp @@ -229,35 +229,46 @@ int time() { Timer total_timer; total_timer.Start(); Timer forward_timer; - forward_timer.Start(); + Timer backward_timer; Timer timer; - for (int i = 0; i < layers.size(); ++i) { - const caffe::string& layername = layers[i]->layer_param().name(); - timer.Start(); - for (int j = 0; j < FLAGS_iterations; ++j) { + std::vector forward_time_per_layer(layers.size(), 0.0); + std::vector backward_time_per_layer(layers.size(), 0.0); + float forward_time = 0.0; + float backward_time = 0.0; + for (int j = 0; j < FLAGS_iterations; ++j) { + Timer iter_timer; + iter_timer.Start(); + forward_timer.Start(); + for (int i = 0; i < layers.size(); ++i) { + timer.Start(); // Although Reshape should be essentially free, we include it here // so that we will notice Reshape performance bugs. layers[i]->Reshape(bottom_vecs[i], top_vecs[i]); layers[i]->Forward(bottom_vecs[i], top_vecs[i]); + forward_time_per_layer[i] += timer.MilliSeconds(); } - LOG(INFO) << layername << "\tforward: " << timer.MilliSeconds() << - " milliseconds."; - } - LOG(INFO) << "Forward pass: " << forward_timer.MilliSeconds() << - " milliseconds."; - Timer backward_timer; - backward_timer.Start(); - for (int i = layers.size() - 1; i >= 0; --i) { - const caffe::string& layername = layers[i]->layer_param().name(); - timer.Start(); - for (int j = 0; j < FLAGS_iterations; ++j) { + forward_time += forward_timer.MilliSeconds(); + backward_timer.Start(); + for (int i = layers.size() - 1; i >= 0; --i) { + timer.Start(); layers[i]->Backward(top_vecs[i], bottom_need_backward[i], bottom_vecs[i]); + backward_time_per_layer[i] += timer.MilliSeconds(); } - LOG(INFO) << layername << "\tbackward: " - << timer.MilliSeconds() << " milliseconds."; + backward_time += backward_timer.MilliSeconds(); + LOG(INFO) << "Iteration: " << j + 1 << " forward-backward time: " + << iter_timer.MilliSeconds() << " milliseconds."; } - LOG(INFO) << "Backward pass: " << backward_timer.MilliSeconds() << + for (int i = 0; i < layers.size(); ++i) { + const caffe::string& layername = layers[i]->layer_param().name(); + LOG(INFO) << std::setfill(' ') << std::setw(10) << layername << + "\tforward: " << forward_time_per_layer[i] << " milliseconds."; + LOG(INFO) << std::setfill(' ') << std::setw(10) << layername << + "\tbackward: " << backward_time_per_layer[i] << " milliseconds."; + } + LOG(INFO) << "Forward pass: " << forward_time << + " milliseconds."; + LOG(INFO) << "Backward pass: " << backward_time << " milliseconds."; LOG(INFO) << "Total Time: " << total_timer.MilliSeconds() << " milliseconds."; From 65688bed17b3bc162fd5a0db9c97de11c9131258 Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 15 Oct 2014 15:36:42 -0700 Subject: [PATCH 140/798] Upgrade compute_image_mean to use gflags, accept list_of_images, and print mean_values --- examples/cifar10/create_cifar10.sh | 4 +- src/caffe/layers/data_layer.cpp | 4 +- tools/compute_image_mean.cpp | 59 ++++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/examples/cifar10/create_cifar10.sh b/examples/cifar10/create_cifar10.sh index ebfca46de87..a42725cb610 100755 --- a/examples/cifar10/create_cifar10.sh +++ b/examples/cifar10/create_cifar10.sh @@ -13,7 +13,7 @@ rm -rf $EXAMPLE/cifar10_train_$DBTYPE $EXAMPLE/cifar10_test_$DBTYPE echo "Computing image mean..." -./build/tools/compute_image_mean $EXAMPLE/cifar10_train_$DBTYPE \ - $EXAMPLE/mean.binaryproto $DBTYPE +./build/tools/compute_image_mean -backend=$DBTYPE \ + $EXAMPLE/cifar10_train_$DBTYPE $EXAMPLE/mean.binaryproto echo "Done." diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 7ddd4662e73..05f2e298ee7 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -46,9 +46,9 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, } // Read a data point, and use it to initialize the top blob. CHECK(iter_ != dataset_->end()); - const Datum& datum = iter_->value; + Datum datum = iter_->value; - if (DecodeDatum(datum)) { + if (DecodeDatum(&datum)) { LOG(INFO) << "Decoding Datum"; } // image diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index a720f162aa2..4c2c658bbb0 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -12,19 +13,31 @@ using caffe::Dataset; using caffe::Datum; using caffe::BlobProto; using std::max; +using std::pair; + + +DEFINE_string(backend, "lmdb", "The backend for containing the images"); int main(int argc, char** argv) { ::google::InitGoogleLogging(argv[0]); - if (argc < 3 || argc > 4) { - LOG(ERROR) << "Usage: compute_image_mean input_db output_file" - << " db_backend[leveldb or lmdb]"; + +#ifndef GFLAGS_GFLAGS_H_ + namespace gflags = google; +#endif + + gflags::SetUsageMessage("Compute the mean_image of a set of images given by" + " a leveldb/lmdb or a list of images\n" + "Usage:\n" + " compute_image_mean [FLAGS] INPUT_DB [OUTPUT_FILE]\n"); + + gflags::ParseCommandLineFlags(&argc, &argv, true); + + if (argc < 2 || argc > 3) { + gflags::ShowUsageWithFlagsRestrict(argv[0], "tools/compute_image_mean"); return 1; } - std::string db_backend = "lmdb"; - if (argc == 4) { - db_backend = std::string(argv[3]); - } + std::string db_backend = FLAGS_backend; caffe::shared_ptr > dataset = caffe::DatasetFactory(db_backend); @@ -36,7 +49,11 @@ int main(int argc, char** argv) { int count = 0; // load first datum Dataset::const_iterator iter = dataset->begin(); - const Datum& datum = iter->value; + Datum datum = iter->value; + + if (DecodeDatum(&datum)) { + LOG(INFO) << "Decoding Datum"; + } sum_blob.set_num(1); sum_blob.set_channels(datum.channels()); @@ -51,8 +68,9 @@ int main(int argc, char** argv) { LOG(INFO) << "Starting Iteration"; for (Dataset::const_iterator iter = dataset->begin(); iter != dataset->end(); ++iter) { - // just a dummy operation - const Datum& datum = iter->value; + Datum datum = iter->value; + DecodeDatum(&datum); + const std::string& data = datum.data(); size_in_datum = std::max(datum.data().size(), datum.float_data_size()); @@ -72,20 +90,31 @@ int main(int argc, char** argv) { } ++count; if (count % 10000 == 0) { - LOG(ERROR) << "Processed " << count << " files."; + LOG(INFO) << "Processed " << count << " files."; } } if (count % 10000 != 0) { - LOG(ERROR) << "Processed " << count << " files."; + LOG(INFO) << "Processed " << count << " files."; } for (int i = 0; i < sum_blob.data_size(); ++i) { sum_blob.set_data(i, sum_blob.data(i) / count); } // Write to disk - LOG(INFO) << "Write to " << argv[2]; - WriteProtoToBinaryFile(sum_blob, argv[2]); - + if (argc == 3) { + LOG(INFO) << "Write to " << argv[2]; + WriteProtoToBinaryFile(sum_blob, argv[2]); + } + const int channels = sum_blob.channels(); + const int dim = sum_blob.height() * sum_blob.width(); + std::vector mean_values(channels, 0.0); + LOG(INFO) << "Number of channels: " << channels; + for (int c = 0; c < channels; ++c) { + for (int i = 0; i < dim; ++i) { + mean_values[c] += sum_blob.data(dim * c + i); + } + LOG(INFO) << "mean_value channel [" << c << "]:" << mean_values[c] / dim; + } // Clean up dataset->close(); return 0; From 8867a54599f1d35b36bb29ee6fea94d6f635d675 Mon Sep 17 00:00:00 2001 From: Sergio Date: Sun, 12 Oct 2014 23:16:59 -0700 Subject: [PATCH 141/798] Added CPUTimer Make timing more precise using double and microseconds --- include/caffe/util/benchmark.hpp | 20 ++++++++--- src/caffe/layers/data_layer.cpp | 18 +++++----- src/caffe/layers/image_data_layer.cpp | 18 +++++----- src/caffe/layers/window_data_layer.cpp | 18 +++++----- src/caffe/util/benchmark.cpp | 49 +++++++++++++++++++++++++- tools/caffe.cpp | 39 +++++++++++--------- tools/compute_image_mean.cpp | 2 ++ 7 files changed, 114 insertions(+), 50 deletions(-) diff --git a/include/caffe/util/benchmark.hpp b/include/caffe/util/benchmark.hpp index 6c01ac4ee18..d63582776ee 100644 --- a/include/caffe/util/benchmark.hpp +++ b/include/caffe/util/benchmark.hpp @@ -11,11 +11,11 @@ class Timer { public: Timer(); virtual ~Timer(); - void Start(); - void Stop(); - float MilliSeconds(); - float MicroSeconds(); - float Seconds(); + virtual void Start(); + virtual void Stop(); + virtual float MilliSeconds(); + virtual float MicroSeconds(); + virtual float Seconds(); inline bool initted() { return initted_; } inline bool running() { return running_; } @@ -37,6 +37,16 @@ class Timer { float elapsed_microseconds_; }; +class CPUTimer : public Timer { + public: + explicit CPUTimer(); + virtual ~CPUTimer() {} + virtual void Start(); + virtual void Stop(); + virtual float MilliSeconds(); + virtual float MicroSeconds(); +}; + } // namespace caffe #endif // CAFFE_UTIL_BENCHMARK_H_ diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 05f2e298ee7..5d6f05802ce 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -82,11 +82,11 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // This function is used to create a thread that prefetches the data. template void DataLayer::InternalThreadEntry() { - Timer batch_timer; + CPUTimer batch_timer; batch_timer.Start(); - float read_time = 0; - float trans_time = 0; - Timer timer; + double read_time = 0; + double trans_time = 0; + CPUTimer timer; CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -106,7 +106,7 @@ void DataLayer::InternalThreadEntry() { if (datum.encoded()) { cv_img = DecodeDatumToCVMat(datum); } - read_time += timer.MilliSeconds(); + read_time += timer.MicroSeconds(); timer.Start(); // Apply data transformations (mirror, scale, crop...) @@ -120,7 +120,7 @@ void DataLayer::InternalThreadEntry() { if (this->output_labels_) { top_label[item_id] = datum.label(); } - trans_time += timer.MilliSeconds(); + trans_time += timer.MicroSeconds(); // go to the next iter ++iter_; if (iter_ == dataset_->end()) { @@ -128,9 +128,9 @@ void DataLayer::InternalThreadEntry() { } } batch_timer.Stop(); - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << " ms."; + DLOG(INFO) << " Read time: " << read_time / 1000 << " ms."; + DLOG(INFO) << "Transform time: " << trans_time / 1000 << " ms."; } INSTANTIATE_CLASS(DataLayer); diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index e0778e5989f..50997a23bf9 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -93,11 +93,11 @@ void ImageDataLayer::ShuffleImages() { // This function is used to create a thread that prefetches the data. template void ImageDataLayer::InternalThreadEntry() { - Timer batch_timer; + CPUTimer batch_timer; batch_timer.Start(); - float read_time = 0; - float trans_time = 0; - Timer timer; + double read_time = 0; + double trans_time = 0; + CPUTimer timer; CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -120,13 +120,13 @@ void ImageDataLayer::InternalThreadEntry() { if (!cv_img.data) { continue; } - read_time += timer.MilliSeconds(); + read_time += timer.MicroSeconds(); timer.Start(); // Apply transformations (mirror, crop...) to the image int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); - trans_time += timer.MilliSeconds(); + trans_time += timer.MicroSeconds(); top_label[item_id] = lines_[lines_id_].second; // go to the next iter @@ -141,9 +141,9 @@ void ImageDataLayer::InternalThreadEntry() { } } batch_timer.Stop(); - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << " ms."; + DLOG(INFO) << " Read time: " << read_time / 1000 << " ms."; + DLOG(INFO) << "Transform time: " << trans_time / 1000 << " ms."; } INSTANTIATE_CLASS(ImageDataLayer); diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 14e8caad6c9..6287b385dc5 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -224,11 +224,11 @@ template void WindowDataLayer::InternalThreadEntry() { // At each iteration, sample N windows where N*p are foreground (object) // windows and N*(1-p) are background (non-object) windows - Timer batch_timer; + CPUTimer batch_timer; batch_timer.Start(); - float read_time = 0; - float trans_time = 0; - Timer timer; + double read_time = 0; + double trans_time = 0; + CPUTimer timer; Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = this->prefetch_label_.mutable_cpu_data(); const Dtype scale = this->layer_param_.window_data_param().scale(); @@ -289,7 +289,7 @@ void WindowDataLayer::InternalThreadEntry() { return; } } - read_time += timer.MilliSeconds(); + read_time += timer.MicroSeconds(); timer.Start(); const int channels = cv_img.channels(); @@ -416,7 +416,7 @@ void WindowDataLayer::InternalThreadEntry() { } } } - trans_time += timer.MilliSeconds(); + trans_time += timer.MicroSeconds(); // get window label top_label[item_id] = window[WindowDataLayer::LABEL]; @@ -457,9 +457,9 @@ void WindowDataLayer::InternalThreadEntry() { } } batch_timer.Stop(); - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << " ms."; + DLOG(INFO) << " Read time: " << read_time / 1000 << " ms."; + DLOG(INFO) << "Transform time: " << trans_time / 1000 << " ms."; } INSTANTIATE_CLASS(WindowDataLayer); diff --git a/src/caffe/util/benchmark.cpp b/src/caffe/util/benchmark.cpp index 2edc9a53ef0..1d269c351c1 100644 --- a/src/caffe/util/benchmark.cpp +++ b/src/caffe/util/benchmark.cpp @@ -69,7 +69,7 @@ float Timer::MicroSeconds() { CUDA_CHECK(cudaEventElapsedTime(&elapsed_milliseconds_, start_gpu_, stop_gpu_)); // Cuda only measure milliseconds - elapsed_microseconds_ = elapsed_milliseconds_ / 1000; + elapsed_microseconds_ = elapsed_milliseconds_ * 1000; #else NO_GPU; #endif @@ -118,4 +118,51 @@ void Timer::Init() { } } +CPUTimer::CPUTimer() { + this->initted_ = true; + this->running_ = false; + this->has_run_at_least_once_ = false; +} + +void CPUTimer::Start() { + if (!running()) { + this->start_cpu_ = boost::posix_time::microsec_clock::local_time(); + this->running_ = true; + this->has_run_at_least_once_ = true; + } +} + +void CPUTimer::Stop() { + if (running()) { + this->stop_cpu_ = boost::posix_time::microsec_clock::local_time(); + this->running_ = false; + } +} + +float CPUTimer::MilliSeconds() { + if (!has_run_at_least_once()) { + LOG(WARNING) << "Timer has never been run before reading time."; + return 0; + } + if (running()) { + Stop(); + } + this->elapsed_milliseconds_ = (this->stop_cpu_ - + this->start_cpu_).total_milliseconds(); + return this->elapsed_milliseconds_; +} + +float CPUTimer::MicroSeconds() { + if (!has_run_at_least_once()) { + LOG(WARNING) << "Timer has never been run before reading time."; + return 0; + } + if (running()) { + Stop(); + } + this->elapsed_microseconds_ = (this->stop_cpu_ - + this->start_cpu_).total_microseconds(); + return this->elapsed_microseconds_; +} + } // namespace caffe diff --git a/tools/caffe.cpp b/tools/caffe.cpp index 1c842a078c2..9f9d975dfba 100644 --- a/tools/caffe.cpp +++ b/tools/caffe.cpp @@ -231,10 +231,10 @@ int time() { Timer forward_timer; Timer backward_timer; Timer timer; - std::vector forward_time_per_layer(layers.size(), 0.0); - std::vector backward_time_per_layer(layers.size(), 0.0); - float forward_time = 0.0; - float backward_time = 0.0; + std::vector forward_time_per_layer(layers.size(), 0.0); + std::vector backward_time_per_layer(layers.size(), 0.0); + double forward_time = 0.0; + double backward_time = 0.0; for (int j = 0; j < FLAGS_iterations; ++j) { Timer iter_timer; iter_timer.Start(); @@ -245,33 +245,38 @@ int time() { // so that we will notice Reshape performance bugs. layers[i]->Reshape(bottom_vecs[i], top_vecs[i]); layers[i]->Forward(bottom_vecs[i], top_vecs[i]); - forward_time_per_layer[i] += timer.MilliSeconds(); + forward_time_per_layer[i] += timer.MicroSeconds(); } - forward_time += forward_timer.MilliSeconds(); + forward_time += forward_timer.MicroSeconds(); backward_timer.Start(); for (int i = layers.size() - 1; i >= 0; --i) { timer.Start(); layers[i]->Backward(top_vecs[i], bottom_need_backward[i], bottom_vecs[i]); - backward_time_per_layer[i] += timer.MilliSeconds(); + backward_time_per_layer[i] += timer.MicroSeconds(); } - backward_time += backward_timer.MilliSeconds(); + backward_time += backward_timer.MicroSeconds(); LOG(INFO) << "Iteration: " << j + 1 << " forward-backward time: " - << iter_timer.MilliSeconds() << " milliseconds."; + << iter_timer.MilliSeconds() << " ms."; } + LOG(INFO) << "Average time per layer: "; for (int i = 0; i < layers.size(); ++i) { const caffe::string& layername = layers[i]->layer_param().name(); LOG(INFO) << std::setfill(' ') << std::setw(10) << layername << - "\tforward: " << forward_time_per_layer[i] << " milliseconds."; + "\tforward: " << forward_time_per_layer[i] / 1000 / + FLAGS_iterations << " ms."; LOG(INFO) << std::setfill(' ') << std::setw(10) << layername << - "\tbackward: " << backward_time_per_layer[i] << " milliseconds."; + "\tbackward: " << backward_time_per_layer[i] / 1000 / + FLAGS_iterations << " ms."; } - LOG(INFO) << "Forward pass: " << forward_time << - " milliseconds."; - LOG(INFO) << "Backward pass: " << backward_time << - " milliseconds."; - LOG(INFO) << "Total Time: " << total_timer.MilliSeconds() << - " milliseconds."; + total_timer.Stop(); + LOG(INFO) << "Average Forward pass: " << forward_time / 1000 / + FLAGS_iterations << " ms."; + LOG(INFO) << "Average Backward pass: " << backward_time / 1000 / + FLAGS_iterations << " ms."; + LOG(INFO) << "Average Forward-Backward: " << total_timer.MilliSeconds() / + FLAGS_iterations << " ms."; + LOG(INFO) << "Total Time: " << total_timer.MilliSeconds() << " ms."; LOG(INFO) << "*** Benchmark ends ***"; return 0; } diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index 4c2c658bbb0..358f57e38d6 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include "caffe/dataset_factory.hpp" #include "caffe/proto/caffe.pb.h" From a1f83100858121fd094df625ed40af8c5afb42e5 Mon Sep 17 00:00:00 2001 From: Sergio Date: Fri, 3 Oct 2014 17:14:20 -0700 Subject: [PATCH 142/798] Adapt lenet_multistep_solver.prototxt to current solvers --- .../lenet_multistep_solver.prototxt | 13 +++++-------- examples/mnist/readme.md | 3 +++ 2 files changed, 8 insertions(+), 8 deletions(-) rename examples/{lenet => mnist}/lenet_multistep_solver.prototxt (74%) diff --git a/examples/lenet/lenet_multistep_solver.prototxt b/examples/mnist/lenet_multistep_solver.prototxt similarity index 74% rename from examples/lenet/lenet_multistep_solver.prototxt rename to examples/mnist/lenet_multistep_solver.prototxt index fadd7c904d7..7ee9fb60e67 100644 --- a/examples/lenet/lenet_multistep_solver.prototxt +++ b/examples/mnist/lenet_multistep_solver.prototxt @@ -1,7 +1,5 @@ -# The training protocol buffer definition -train_net: "lenet_train.prototxt" -# The testing protocol buffer definition -test_net: "lenet_test.prototxt" +# The train/test net protocol buffer definition +net: "examples/mnist/lenet_train_test.prototxt" # test_iter specifies how many forward passes the test should carry out. # In the case of MNIST, we have test batch size 100 and 100 test iterations, # covering the full 10,000 testing images. @@ -27,7 +25,6 @@ display: 100 max_iter: 10000 # snapshot intermediate results snapshot: 5000 -snapshot_prefix: "lenet" -# solver mode: 0 for CPU and 1 for GPU -solver_mode: 1 -device_id: 1 +snapshot_prefix: "examples/mnist/lenet_multistep" +# solver mode: CPU or GPU +solver_mode: GPU diff --git a/examples/mnist/readme.md b/examples/mnist/readme.md index 44e0091f420..1f8a869630d 100644 --- a/examples/mnist/readme.md +++ b/examples/mnist/readme.md @@ -283,3 +283,6 @@ You just did! All the training was carried out on the GPU. In fact, if you would and you will be using CPU for training. Isn't that easy? MNIST is a small dataset, so training with GPU does not really introduce too much benefit due to communication overheads. On larger datasets with more complex models, such as ImageNet, the computation speed difference will be more significant. + +### How to reduce the learning rate a fixed steps? +Look at lenet_multistep_solver.prototxt From d7da420b4ce2b07dad7fca42535a576cff43ce96 Mon Sep 17 00:00:00 2001 From: Craig Quiter Date: Wed, 15 Oct 2014 21:26:01 -0700 Subject: [PATCH 143/798] Sometimes anaconda is installed in root. Helps fix #489. --- Makefile.config.example | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile.config.example b/Makefile.config.example index b6d95e31df8..e11db51395d 100644 --- a/Makefile.config.example +++ b/Makefile.config.example @@ -48,13 +48,15 @@ BLAS := atlas PYTHON_INCLUDE := /usr/include/python2.7 \ /usr/lib/python2.7/dist-packages/numpy/core/include # Anaconda Python distribution is quite popular. Include path: -# PYTHON_INCLUDE := $(HOME)/anaconda/include \ - # $(HOME)/anaconda/include/python2.7 \ - # $(HOME)/anaconda/lib/python2.7/site-packages/numpy/core/include +# Verify anaconda location, sometimes it's in root. +# ANACONDA_HOME := $(HOME)/anaconda +# PYTHON_INCLUDE := $(ANACONDA_HOME)/include \ + # $(ANACONDA_HOME)/include/python2.7 \ + # $(ANACONDA_HOME)/lib/python2.7/site-packages/numpy/core/include \ # We need to be able to find libpythonX.X.so or .dylib. PYTHON_LIB := /usr/lib -# PYTHON_LIB := $(HOME)/anaconda/lib +# PYTHON_LIB := $(ANACONDA_HOME)/lib # Whatever else you find you need goes here. INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include From 3d95ed3ae19f6cadcd3400c75970fdbeb10ad4c5 Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 16 Oct 2014 11:17:24 -0700 Subject: [PATCH 144/798] Fix init current_step --- examples/mnist/lenet_multistep_solver.prototxt | 11 +++++------ src/caffe/solver.cpp | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/mnist/lenet_multistep_solver.prototxt b/examples/mnist/lenet_multistep_solver.prototxt index 7ee9fb60e67..9b22b45ba6b 100644 --- a/examples/mnist/lenet_multistep_solver.prototxt +++ b/examples/mnist/lenet_multistep_solver.prototxt @@ -13,12 +13,11 @@ weight_decay: 0.0005 # The learning rate policy lr_policy: "multistep" gamma: 0.9 -stepvalue: 1000 -stepvalue: 2000 -stepvalue: 2500 -stepvalue: 3000 -stepvalue: 3500 -stepvalue: 4000 +stepvalue: 5000 +stepvalue: 7000 +stepvalue: 8000 +stepvalue: 9000 +stepvalue: 9500 # Display every 100 iterations display: 100 # The maximum number of iterations diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index a13bca8b44a..5b8f0795306 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -162,6 +162,7 @@ void Solver::Solve(const char* resume_file) { PreSolve(); iter_ = 0; + current_step_ = 0; if (resume_file) { LOG(INFO) << "Restoring previous solver status from " << resume_file; Restore(resume_file); From e41ddbd3d70eff49a7bab430bb085d3b89647b4d Mon Sep 17 00:00:00 2001 From: Kevin James Matzen Date: Sat, 18 Oct 2014 02:51:29 -0400 Subject: [PATCH 145/798] LMDB doesn't support many concurrent read-only transactions, so this preallocates one read-only transaction and reuses it. It's very important that iterations are considered invalid after a commit has been performed. --- include/caffe/dataset.hpp | 1 - include/caffe/leveldb_dataset.hpp | 11 ++--- include/caffe/lmdb_dataset.hpp | 30 ++++++------ src/caffe/lmdb_dataset.cpp | 77 ++++++++++++++----------------- src/caffe/test/test_dataset.cpp | 38 +++++++++++++++ 5 files changed, 92 insertions(+), 65 deletions(-) diff --git a/include/caffe/dataset.hpp b/include/caffe/dataset.hpp index 90deb3160fa..1dd8458cd74 100644 --- a/include/caffe/dataset.hpp +++ b/include/caffe/dataset.hpp @@ -170,7 +170,6 @@ class Dataset { iterator(const Dataset* parent, shared_ptr state) : parent_(parent), state_(state) { } - ~iterator() { } iterator(const iterator& other) : parent_(other.parent_), diff --git a/include/caffe/leveldb_dataset.hpp b/include/caffe/leveldb_dataset.hpp index f6c57fe65af..d58c181bb2b 100644 --- a/include/caffe/leveldb_dataset.hpp +++ b/include/caffe/leveldb_dataset.hpp @@ -61,12 +61,11 @@ class LeveldbDataset : public Dataset { shared_ptr clone() { shared_ptr new_iter; - if (iter_.get()) { - new_iter.reset(db_->NewIterator(leveldb::ReadOptions())); - CHECK(iter_->Valid()); - new_iter->Seek(iter_->key()); - CHECK(new_iter->Valid()); - } + CHECK(iter_.get()); + new_iter.reset(db_->NewIterator(leveldb::ReadOptions())); + CHECK(iter_->Valid()); + new_iter->Seek(iter_->key()); + CHECK(new_iter->Valid()); return shared_ptr(new LeveldbState(db_, new_iter)); } diff --git a/include/caffe/lmdb_dataset.hpp b/include/caffe/lmdb_dataset.hpp index 71b322490c0..ac1e5ee25dd 100644 --- a/include/caffe/lmdb_dataset.hpp +++ b/include/caffe/lmdb_dataset.hpp @@ -28,7 +28,8 @@ class LmdbDataset : public Dataset { LmdbDataset() : env_(NULL), dbi_(0), - txn_(NULL) { } + write_txn_(NULL), + read_txn_(NULL) { } bool open(const string& filename, Mode mode); bool put(const K& key, const V& value); @@ -55,21 +56,19 @@ class LmdbDataset : public Dataset { dbi_(dbi) { } shared_ptr clone() { + CHECK(cursor_); + MDB_cursor* new_cursor; + int retval; - if (cursor_) { - int retval; - retval = mdb_cursor_open(txn_, *dbi_, &new_cursor); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - MDB_val key; - MDB_val val; - retval = mdb_cursor_get(cursor_, &key, &val, MDB_GET_CURRENT); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - retval = mdb_cursor_get(new_cursor, &key, &val, MDB_SET); - CHECK_EQ(MDB_SUCCESS, retval) << mdb_strerror(retval); - } else { - new_cursor = cursor_; - } + retval = mdb_cursor_open(txn_, *dbi_, &new_cursor); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + MDB_val key; + MDB_val val; + retval = mdb_cursor_get(cursor_, &key, &val, MDB_GET_CURRENT); + CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); + retval = mdb_cursor_get(new_cursor, &key, &val, MDB_SET); + CHECK_EQ(MDB_SUCCESS, retval) << mdb_strerror(retval); return shared_ptr(new LmdbState(new_cursor, txn_, dbi_)); } @@ -87,7 +86,8 @@ class LmdbDataset : public Dataset { MDB_env* env_; MDB_dbi dbi_; - MDB_txn* txn_; + MDB_txn* write_txn_; + MDB_txn* read_txn_; }; } // namespace caffe diff --git a/src/caffe/lmdb_dataset.cpp b/src/caffe/lmdb_dataset.cpp index 23852f0cd81..8f8e68e901e 100644 --- a/src/caffe/lmdb_dataset.cpp +++ b/src/caffe/lmdb_dataset.cpp @@ -15,7 +15,8 @@ bool LmdbDataset::open(const string& filename, DLOG(INFO) << "LMDB: Open " << filename; CHECK(NULL == env_); - CHECK(NULL == txn_); + CHECK(NULL == write_txn_); + CHECK(NULL == read_txn_); CHECK_EQ(0, dbi_); int retval; @@ -66,13 +67,19 @@ bool LmdbDataset::open(const string& filename, return false; } - retval = mdb_txn_begin(env_, NULL, flag2, &txn_); + retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &read_txn_); if (MDB_SUCCESS != retval) { LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); return false; } - retval = mdb_open(txn_, NULL, 0, &dbi_); + retval = mdb_txn_begin(env_, NULL, flag2, &write_txn_); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); + return false; + } + + retval = mdb_open(write_txn_, NULL, 0, &dbi_); if (MDB_SUCCESS != retval) { LOG(ERROR) << "mdb_open failed" << mdb_strerror(retval); return false; @@ -103,10 +110,10 @@ bool LmdbDataset::put(const K& key, const V& value) { mdbkey.mv_size = serialized_key.size(); mdbkey.mv_data = serialized_key.data(); - CHECK_NOTNULL(txn_); + CHECK_NOTNULL(write_txn_); CHECK_NE(0, dbi_); - int retval = mdb_put(txn_, dbi_, &mdbkey, &mdbdata, 0); + int retval = mdb_put(write_txn_, dbi_, &mdbkey, &mdbdata, 0); if (MDB_SUCCESS != retval) { LOG(ERROR) << "mdb_put failed " << mdb_strerror(retval); return false; @@ -130,21 +137,12 @@ bool LmdbDataset::get(const K& key, V* value) { mdbkey.mv_size = serialized_key.size(); int retval; - MDB_txn* get_txn; - retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &get_txn); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); - return false; - } - - retval = mdb_get(get_txn, dbi_, &mdbkey, &mdbdata); + retval = mdb_get(read_txn_, dbi_, &mdbkey, &mdbdata); if (MDB_SUCCESS != retval) { LOG(ERROR) << "mdb_get failed " << mdb_strerror(retval); return false; } - mdb_txn_abort(get_txn); - if (!VCoder::deserialize(reinterpret_cast(mdbdata.mv_data), mdbdata.mv_size, value)) { LOG(ERROR) << "failed to deserialize value"; @@ -160,14 +158,8 @@ bool LmdbDataset::first_key(K* key) { int retval; - MDB_txn* iter_txn; - - retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &iter_txn); - CHECK_EQ(MDB_SUCCESS, retval) << "mdb_txn_begin failed " - << mdb_strerror(retval); - MDB_cursor* cursor; - retval = mdb_cursor_open(iter_txn, dbi_, &cursor); + retval = mdb_cursor_open(read_txn_, dbi_, &cursor); CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); MDB_val mdbkey; MDB_val mdbval; @@ -175,7 +167,6 @@ bool LmdbDataset::first_key(K* key) { CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); mdb_cursor_close(cursor); - mdb_txn_abort(iter_txn); if (!KCoder::deserialize(reinterpret_cast(mdbkey.mv_data), mdbkey.mv_size, key)) { @@ -192,14 +183,8 @@ bool LmdbDataset::last_key(K* key) { int retval; - MDB_txn* iter_txn; - - retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &iter_txn); - CHECK_EQ(MDB_SUCCESS, retval) << "mdb_txn_begin failed " - << mdb_strerror(retval); - MDB_cursor* cursor; - retval = mdb_cursor_open(iter_txn, dbi_, &cursor); + retval = mdb_cursor_open(read_txn_, dbi_, &cursor); CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); MDB_val mdbkey; MDB_val mdbval; @@ -207,7 +192,6 @@ bool LmdbDataset::last_key(K* key) { CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); mdb_cursor_close(cursor); - mdb_txn_abort(iter_txn); if (!KCoder::deserialize(reinterpret_cast(mdbkey.mv_data), mdbkey.mv_size, key)) { @@ -222,16 +206,24 @@ template bool LmdbDataset::commit() { DLOG(INFO) << "LMDB: Commit"; - CHECK_NOTNULL(txn_); + CHECK_NOTNULL(write_txn_); int retval; - retval = mdb_txn_commit(txn_); + retval = mdb_txn_commit(write_txn_); if (MDB_SUCCESS != retval) { LOG(ERROR) << "mdb_txn_commit failed " << mdb_strerror(retval); return false; } - retval = mdb_txn_begin(env_, NULL, 0, &txn_); + mdb_txn_abort(read_txn_); + + retval = mdb_txn_begin(env_, NULL, 0, &write_txn_); + if (MDB_SUCCESS != retval) { + LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); + return false; + } + + retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &read_txn_); if (MDB_SUCCESS != retval) { LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); return false; @@ -245,11 +237,14 @@ void LmdbDataset::close() { DLOG(INFO) << "LMDB: Close"; if (env_ && dbi_) { + mdb_txn_abort(write_txn_); + mdb_txn_abort(read_txn_); mdb_close(env_, dbi_); mdb_env_close(env_); env_ = NULL; dbi_ = 0; - txn_ = NULL; + write_txn_ = NULL; + read_txn_ = NULL; } } @@ -268,14 +263,8 @@ typename LmdbDataset::const_iterator LmdbDataset::begin() const { int retval; - MDB_txn* iter_txn; - - retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &iter_txn); - CHECK_EQ(MDB_SUCCESS, retval) << "mdb_txn_begin failed " - << mdb_strerror(retval); - MDB_cursor* cursor; - retval = mdb_cursor_open(iter_txn, dbi_, &cursor); + retval = mdb_cursor_open(read_txn_, dbi_, &cursor); CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); MDB_val key; MDB_val val; @@ -286,7 +275,9 @@ typename LmdbDataset::const_iterator shared_ptr state; if (MDB_SUCCESS == retval) { - state.reset(new LmdbState(cursor, iter_txn, &dbi_)); + state.reset(new LmdbState(cursor, read_txn_, &dbi_)); + } else { + mdb_cursor_close(cursor); } return const_iterator(this, state); } diff --git a/src/caffe/test/test_dataset.cpp b/src/caffe/test/test_dataset.cpp index e5bd1d2c40e..6645ca228d2 100644 --- a/src/caffe/test/test_dataset.cpp +++ b/src/caffe/test/test_dataset.cpp @@ -751,6 +751,44 @@ TYPED_TEST(DatasetTest, TestReadOnlyGetNoCommitFails) { EXPECT_FALSE(dataset->get(key, &new_value)); } +TYPED_TEST(DatasetTest, TestCreateManyItersShortScope) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + EXPECT_TRUE(dataset->put(key, value)); + EXPECT_TRUE(dataset->commit()); + + for (int i = 0; i < 1000; ++i) { + typename Dataset::const_iterator iter = + dataset->begin(); + } +} + +TYPED_TEST(DatasetTest, TestCreateManyItersLongScope) { + UNPACK_TYPES; + + string name = this->DBName(); + shared_ptr > dataset = + DatasetFactory(backend); + EXPECT_TRUE(dataset->open(name, Dataset::New)); + + string key = this->TestKey(); + value_type value = this->TestValue(); + EXPECT_TRUE(dataset->put(key, value)); + EXPECT_TRUE(dataset->commit()); + + vector::const_iterator> iters; + for (int i = 0; i < 1000; ++i) { + iters.push_back(dataset->begin()); + } +} + #undef UNPACK_TYPES } // namespace caffe From a723be04acf250a08b5a6f0fbb7e3fde7de429be Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 18 Oct 2014 07:59:53 -0700 Subject: [PATCH 146/798] Remove TIMING from ForwardBackward --- include/caffe/net.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/caffe/net.hpp b/include/caffe/net.hpp index 879f474674d..1d06dc45533 100644 --- a/include/caffe/net.hpp +++ b/include/caffe/net.hpp @@ -11,9 +11,6 @@ #include "caffe/common.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" -#ifdef TIMING -#include "caffe/util/benchmark.hpp" -#endif namespace caffe { @@ -79,16 +76,9 @@ class Net { void Reshape(); Dtype ForwardBackward(const vector* > & bottom) { - #ifdef TIMING - Timer timer; - timer.Start(); - #endif Dtype loss; Forward(bottom, &loss); Backward(); - #ifdef TIMING - LOG(INFO) << "ForwardBackward Time: " << timer.MilliSeconds() << "ms."; - #endif return loss; } From 60554bc4d238f224ba7b4745715a9ae323cf3c4b Mon Sep 17 00:00:00 2001 From: Jack Culpepper Date: Sun, 19 Oct 2014 08:31:29 -0700 Subject: [PATCH 147/798] define gradient at zero to be zero --- src/caffe/layers/absval_layer.cpp | 3 +-- src/caffe/layers/absval_layer.cu | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/caffe/layers/absval_layer.cpp b/src/caffe/layers/absval_layer.cpp index 54e484b115d..c347d460c0c 100644 --- a/src/caffe/layers/absval_layer.cpp +++ b/src/caffe/layers/absval_layer.cpp @@ -26,12 +26,11 @@ template void AbsValLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom) { const int count = top[0]->count(); - const Dtype* top_data = top[0]->cpu_data(); const Dtype* top_diff = top[0]->cpu_diff(); if (propagate_down[0]) { const Dtype* bottom_data = bottom[0]->cpu_data(); Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); - caffe_div(count, top_data, bottom_data, bottom_diff); + caffe_cpu_sign(count, bottom_data, bottom_diff); caffe_mul(count, bottom_diff, top_diff, bottom_diff); } } diff --git a/src/caffe/layers/absval_layer.cu b/src/caffe/layers/absval_layer.cu index 732d4c6252b..91f3c77fe9a 100644 --- a/src/caffe/layers/absval_layer.cu +++ b/src/caffe/layers/absval_layer.cu @@ -23,7 +23,7 @@ void AbsValLayer::Backward_gpu(const vector*>& top, if (propagate_down[0]) { const Dtype* bottom_data = bottom[0]->gpu_data(); Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); - caffe_gpu_div(count, top_data, bottom_data, bottom_diff); + caffe_gpu_sign(count, bottom_data, bottom_diff); caffe_gpu_mul(count, bottom_diff, top_diff, bottom_diff); } } From c211fd01ed62c8279ffc810e4f4d1ab2f0b93366 Mon Sep 17 00:00:00 2001 From: Maksim Lapin Date: Tue, 7 Oct 2014 21:48:26 +0200 Subject: [PATCH 148/798] include opencv only in .cpp --- Makefile | 1 - include/caffe/common.hpp | 3 +++ include/caffe/data_transformer.hpp | 6 ----- include/caffe/util/io.hpp | 39 ++++++++------------------- src/caffe/data_transformer.cpp | 4 --- src/caffe/layers/data_layer.cpp | 2 ++ src/caffe/layers/image_data_layer.cpp | 2 ++ src/caffe/util/io.cpp | 28 +++++++++++++++++++ 8 files changed, 46 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 26d5964cacc..dcd7b2457b7 100644 --- a/Makefile +++ b/Makefile @@ -250,7 +250,6 @@ ifeq ($(OSX), 1) endif # boost::thread is called boost_thread-mt to mark multithreading on OS X LIBRARIES += boost_thread-mt - NVCCFLAGS += -DOSX endif # Custom compiler diff --git a/include/caffe/common.hpp b/include/caffe/common.hpp index 81b2e9ae101..5fc4ed3a3e1 100644 --- a/include/caffe/common.hpp +++ b/include/caffe/common.hpp @@ -64,6 +64,9 @@ private:\ // is executed we will see a fatal log. #define NOT_IMPLEMENTED LOG(FATAL) << "Not Implemented Yet" +// See PR #1236 +namespace cv {class Mat;} + namespace caffe { // We will use the boost shared_ptr instead of the new C++11 one mainly diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 5f08335d4a3..70e74368ca7 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -1,10 +1,6 @@ #ifndef CAFFE_DATA_TRANSFORMER_HPP #define CAFFE_DATA_TRANSFORMER_HPP -#ifndef OSX -#include -#endif - #include #include "caffe/blob.hpp" @@ -64,9 +60,7 @@ class DataTransformer { * This is destination blob. It can be part of top blob's data if * set_cpu_data() is used See image_data_layer.cpp for an example. */ -#ifndef OSX void Transform(const cv::Mat& cv_img, Blob* transformed_blob); -#endif /** * @brief Applies the same transformation defined in the data layer's diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 64df0155780..9c0b4872af6 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -1,10 +1,6 @@ #ifndef CAFFE_UTIL_IO_H_ #define CAFFE_UTIL_IO_H_ -#ifndef OSX -#include -#endif - #include #include @@ -13,6 +9,7 @@ #include "hdf5_hl.h" #include "caffe/blob.hpp" +#include "caffe/common.hpp" #include "caffe/proto/caffe.pb.h" #define HDF5_NUM_DIMS 4 @@ -127,43 +124,29 @@ inline bool DecodeDatum(Datum* datum) { return DecodeDatum(0, 0, true, datum); } -#ifndef OSX cv::Mat ReadImageToCVMat(const string& filename, const int height, const int width, const bool is_color); -inline cv::Mat ReadImageToCVMat(const string& filename, - const int height, const int width) { - return ReadImageToCVMat(filename, height, width, true); -} +cv::Mat ReadImageToCVMat(const string& filename, + const int height, const int width); -inline cv::Mat ReadImageToCVMat(const string& filename, - const bool is_color) { - return ReadImageToCVMat(filename, 0, 0, is_color); -} +cv::Mat ReadImageToCVMat(const string& filename, + const bool is_color); -inline cv::Mat ReadImageToCVMat(const string& filename) { - return ReadImageToCVMat(filename, 0, 0, true); -} +cv::Mat ReadImageToCVMat(const string& filename); cv::Mat DecodeDatumToCVMat(const Datum& datum, const int height, const int width, const bool is_color); -inline cv::Mat DecodeDatumToCVMat(const Datum& datum, - const int height, const int width) { - return DecodeDatumToCVMat(datum, height, width, true); -} +cv::Mat DecodeDatumToCVMat(const Datum& datum, + const int height, const int width); -inline cv::Mat DecodeDatumToCVMat(const Datum& datum, - const bool is_color) { - return DecodeDatumToCVMat(datum, 0, 0, is_color); -} +cv::Mat DecodeDatumToCVMat(const Datum& datum, + const bool is_color); -inline cv::Mat DecodeDatumToCVMat(const Datum& datum) { - return DecodeDatumToCVMat(datum, 0, 0, true); -} +cv::Mat DecodeDatumToCVMat(const Datum& datum); void CVMatToDatum(const cv::Mat& cv_img, Datum* datum); -#endif template void hdf5_load_nd_dataset_helper( diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 023396ce5e6..209dc0349ad 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -1,6 +1,4 @@ -#ifndef OSX #include -#endif #include #include @@ -175,7 +173,6 @@ void DataTransformer::Transform(const vector & datum_vector, } } -#ifndef OSX template void DataTransformer::Transform(const cv::Mat& cv_img, Blob* transformed_blob) { @@ -276,7 +273,6 @@ void DataTransformer::Transform(const cv::Mat& cv_img, } } } -#endif template void DataTransformer::Transform(Blob* input_blob, diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 5d6f05802ce..a5030899cee 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -1,3 +1,5 @@ +#include + #include #include diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index 50997a23bf9..ef6a342c30a 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -1,3 +1,5 @@ +#include + #include // NOLINT(readability/streams) #include // NOLINT(readability/streams) #include diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index b136bc8a120..ffdaeb12c4a 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -83,6 +83,20 @@ cv::Mat ReadImageToCVMat(const string& filename, return cv_img; } +cv::Mat ReadImageToCVMat(const string& filename, + const int height, const int width) { + return ReadImageToCVMat(filename, height, width, true); +} + +cv::Mat ReadImageToCVMat(const string& filename, + const bool is_color) { + return ReadImageToCVMat(filename, 0, 0, is_color); +} + +cv::Mat ReadImageToCVMat(const string& filename) { + return ReadImageToCVMat(filename, 0, 0, true); +} + bool ReadImageToDatum(const string& filename, const int label, const int height, const int width, const bool is_color, Datum* datum) { cv::Mat cv_img = ReadImageToCVMat(filename, height, width, is_color); @@ -135,6 +149,20 @@ cv::Mat DecodeDatumToCVMat(const Datum& datum, return cv_img; } +cv::Mat DecodeDatumToCVMat(const Datum& datum, + const int height, const int width) { + return DecodeDatumToCVMat(datum, height, width, true); +} + +cv::Mat DecodeDatumToCVMat(const Datum& datum, + const bool is_color) { + return DecodeDatumToCVMat(datum, 0, 0, is_color); +} + +cv::Mat DecodeDatumToCVMat(const Datum& datum) { + return DecodeDatumToCVMat(datum, 0, 0, true); +} + // If Datum is encoded will decoded using DecodeDatumToCVMat and CVMatToDatum // if height and width are set it will resize it // If Datum is not encoded will do nothing From 293347196a81f68046b30984448cc4883d6c5aa5 Mon Sep 17 00:00:00 2001 From: Ryota Tomioka Date: Mon, 20 Oct 2014 09:35:20 -0500 Subject: [PATCH 149/798] Fixed a memory leak issue in InternalThread (and removed caffe::Thread calss). --- include/caffe/internal_thread.hpp | 19 +++---------------- include/caffe/util/thread.hpp | 25 ------------------------- src/caffe/internal_thread.cpp | 8 +------- 3 files changed, 4 insertions(+), 48 deletions(-) delete mode 100644 include/caffe/util/thread.hpp diff --git a/include/caffe/internal_thread.hpp b/include/caffe/internal_thread.hpp index 6a106e6eefa..9c24585b2cd 100644 --- a/include/caffe/internal_thread.hpp +++ b/include/caffe/internal_thread.hpp @@ -1,24 +1,11 @@ #ifndef CAFFE_INTERNAL_THREAD_HPP_ #define CAFFE_INTERNAL_THREAD_HPP_ +#include #include "caffe/common.hpp" namespace caffe { -/** - * A minimal wrapper for boost::thread to force host compilation for boost - * Defined in caffe/util/thread.hpp - */ -class Thread { - public: - template - Thread(Callable func, A1 a1); - void join(); - bool joinable(); - private: - void* thread_; -}; - /** * Virtual class encapsulate boost::thread for use in base class * The child class will acquire the ability to run a single thread, @@ -26,7 +13,7 @@ class Thread { */ class InternalThread { public: - InternalThread() : thread_(NULL) {} + InternalThread() : thread_() {} virtual ~InternalThread(); /** Returns true if the thread was successfully started. **/ @@ -42,7 +29,7 @@ class InternalThread { with the code you want your thread to run. */ virtual void InternalThreadEntry() {} - caffe::Thread* thread_; + shared_ptr thread_; }; } // namespace caffe diff --git a/include/caffe/util/thread.hpp b/include/caffe/util/thread.hpp deleted file mode 100644 index 7251402cf1a..00000000000 --- a/include/caffe/util/thread.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef CAFFE_THREAD_CPP_HPP_ -#define CAFFE_THREAD_CPP_HPP_ - -#include -#include "caffe/common.hpp" -#include "caffe/internal_thread.hpp" - -namespace caffe { - -template -Thread::Thread(Callable func, A1 a1) { - this->thread_ = new boost::thread(func, a1); -} - -void Thread::join() { - static_cast(this->thread_)->join(); -} - -bool Thread::joinable() { - return static_cast(this->thread_)->joinable(); -} - -} // namespace caffe - -#endif diff --git a/src/caffe/internal_thread.cpp b/src/caffe/internal_thread.cpp index d7b6ae206cf..62a4c1faee2 100644 --- a/src/caffe/internal_thread.cpp +++ b/src/caffe/internal_thread.cpp @@ -1,14 +1,9 @@ #include "caffe/internal_thread.hpp" -#include "caffe/util/thread.hpp" - namespace caffe { InternalThread::~InternalThread() { WaitForInternalThreadToExit(); - if (thread_ != NULL) { - delete thread_; - } } bool InternalThread::StartInternalThread() { @@ -16,8 +11,7 @@ bool InternalThread::StartInternalThread() { return false; } try { - thread_ = new caffe::Thread - (&InternalThread::InternalThreadEntry, this); + thread_.reset(new boost::thread(&InternalThread::InternalThreadEntry, this)); } catch (...) { return false; } From ab94bea9ab54c1fea8c6d45d260c5973a388d745 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Mon, 20 Oct 2014 15:16:55 -0700 Subject: [PATCH 150/798] Update data_transformer.hpp Minor grammar fix in comments. --- include/caffe/data_transformer.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 5f08335d4a3..84ebba28125 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -37,7 +37,7 @@ class DataTransformer { * Datum containing the data to be transformed. * @param transformed_blob * This is destination blob. It can be part of top blob's data if - * set_cpu_data() is used See data_layer.cpp for an example. + * set_cpu_data() is used. See data_layer.cpp for an example. */ void Transform(const Datum& datum, Blob* transformed_blob); @@ -49,7 +49,7 @@ class DataTransformer { * A vector of Datum containing the data to be transformed. * @param transformed_blob * This is destination blob. It can be part of top blob's data if - * set_cpu_data() is used See memory_layer.cpp for an example. + * set_cpu_data() is used. See memory_layer.cpp for an example. */ void Transform(const vector & datum_vector, Blob* transformed_blob); @@ -62,7 +62,7 @@ class DataTransformer { * cv::Mat containing the data to be transformed. * @param transformed_blob * This is destination blob. It can be part of top blob's data if - * set_cpu_data() is used See image_data_layer.cpp for an example. + * set_cpu_data() is used. See image_data_layer.cpp for an example. */ #ifndef OSX void Transform(const cv::Mat& cv_img, Blob* transformed_blob); From 85477b75f7411efa3bf97c2c2cfec403205b7ce6 Mon Sep 17 00:00:00 2001 From: Ryota Tomioka Date: Tue, 21 Oct 2014 10:52:38 -0500 Subject: [PATCH 151/798] Forward declare boost::thread instead of including boost/thread.hpp in internal_thread.hpp. --- include/caffe/internal_thread.hpp | 11 ++++++++--- src/caffe/internal_thread.cpp | 6 ++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/caffe/internal_thread.hpp b/include/caffe/internal_thread.hpp index 9c24585b2cd..fec22a47c86 100644 --- a/include/caffe/internal_thread.hpp +++ b/include/caffe/internal_thread.hpp @@ -1,9 +1,14 @@ #ifndef CAFFE_INTERNAL_THREAD_HPP_ #define CAFFE_INTERNAL_THREAD_HPP_ -#include #include "caffe/common.hpp" +/** + Forward declare boost::thread instead of including boost/thread.hpp + to avoid a boost/NVCC issues (#1009, #1010) on OSX. + */ +namespace boost { class thread; } + namespace caffe { /** @@ -22,7 +27,7 @@ class InternalThread { /** Will not return until the internal thread has exited. */ bool WaitForInternalThreadToExit(); - bool is_started() const { return thread_ != NULL && thread_->joinable(); } + bool is_started() const; protected: /* Implement this method in your subclass @@ -34,4 +39,4 @@ class InternalThread { } // namespace caffe -#endif +#endif // CAFFE_INTERNAL_THREAD_HPP_ diff --git a/src/caffe/internal_thread.cpp b/src/caffe/internal_thread.cpp index 62a4c1faee2..58772e36c23 100644 --- a/src/caffe/internal_thread.cpp +++ b/src/caffe/internal_thread.cpp @@ -1,3 +1,4 @@ +#include #include "caffe/internal_thread.hpp" namespace caffe { @@ -6,6 +7,11 @@ InternalThread::~InternalThread() { WaitForInternalThreadToExit(); } +bool InternalThread::is_started() const { + return thread_.get() != NULL && thread_->joinable(); +} + + bool InternalThread::StartInternalThread() { if (!WaitForInternalThreadToExit()) { return false; From ce980cea21096f9961f2021b2992f2a46e93e552 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Tue, 21 Oct 2014 10:17:11 -0700 Subject: [PATCH 152/798] groom ignore - re-group general and Caffe ignores - ignore OS X files and Eclipse .settings as suggested by @cypof --- .gitignore | 56 +++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index fa279f9071b..c27c7a6a5f6 100644 --- a/.gitignore +++ b/.gitignore @@ -26,21 +26,26 @@ # Compiled MATLAB *.mex* -# build, distribute, and bins -build -.build_debug/* -.build_release/* -distribute/* -*.testbin -*.bin -python/caffe/proto/ +# IPython notebook checkpoints +.ipynb_checkpoints + +# CMake generated files +*.gen.cmake # Editor temporaries *.swp *~ -# IPython notebook checkpoints -.ipynb_checkpoints +# Sublime Text settings +*.sublime-workspace +*.sublime-project + +# Eclipse Project settings +*.*project +.settings + +# OSX dir files +.DS_Store ## Caffe @@ -58,13 +63,14 @@ models/* *leveldb *lmdb -# LevelDB files -*.sst -*.ldb -LOCK -LOG* -CURRENT -MANIFEST-* +# build, distribute, and bins (+ python proto bindings) +build +.build_debug/* +.build_release/* +distribute/* +*.testbin +*.bin +python/caffe/proto/ # Generated documentation docs/_site @@ -73,12 +79,10 @@ _site doxygen docs/dev -# Sublime Text settings -*.sublime-workspace -*.sublime-project - -# Eclipse Project settings -*.*project - -# CMake generated files -*.gen.cmake +# LevelDB files +*.sst +*.ldb +LOCK +LOG* +CURRENT +MANIFEST-* From 6d183710c2fbeb7b227cb0444d318f476cd18fd3 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Tue, 21 Oct 2014 10:19:56 -0700 Subject: [PATCH 153/798] make release, debug build dirs configurable in Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 26d5964cacc..1e70c2d5c6e 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,8 @@ CONFIG_FILE := Makefile.config include $(CONFIG_FILE) BUILD_DIR_LINK := $(BUILD_DIR) -RELEASE_BUILD_DIR := .$(BUILD_DIR)_release -DEBUG_BUILD_DIR := .$(BUILD_DIR)_debug +RELEASE_BUILD_DIR ?= .$(BUILD_DIR)_release +DEBUG_BUILD_DIR ?= .$(BUILD_DIR)_debug DEBUG ?= 0 ifeq ($(DEBUG), 1) From 1ca3b01610d8431497671fbb5ab98a83777f909d Mon Sep 17 00:00:00 2001 From: Martin Baeuml Date: Wed, 22 Oct 2014 10:19:44 +0200 Subject: [PATCH 154/798] Minor whitespace fix in logging message in HDF5 output layer --- src/caffe/layers/hdf5_output_layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caffe/layers/hdf5_output_layer.cpp b/src/caffe/layers/hdf5_output_layer.cpp index b8210e2ee2a..4a72a18aa12 100644 --- a/src/caffe/layers/hdf5_output_layer.cpp +++ b/src/caffe/layers/hdf5_output_layer.cpp @@ -30,7 +30,7 @@ HDF5OutputLayer::~HDF5OutputLayer() { template void HDF5OutputLayer::SaveBlobs() { // TODO: no limit on the number of blobs - LOG(INFO) << "Saving HDF5 file" << file_name_; + LOG(INFO) << "Saving HDF5 file " << file_name_; CHECK_EQ(data_blob_.num(), label_blob_.num()) << "data blob and label blob must have the same batch size"; hdf5_save_nd_dataset(file_id_, HDF5_DATA_DATASET_NAME, data_blob_); From 0b6c663d9bcc7a77a4f63e7a5bb98ec18e18041f Mon Sep 17 00:00:00 2001 From: Rohit Date: Fri, 31 Oct 2014 21:43:44 -0400 Subject: [PATCH 155/798] documentation bug --- examples/cifar10/readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/cifar10/readme.md b/examples/cifar10/readme.md index a329b49c5ea..4a95cee9e8f 100644 --- a/examples/cifar10/readme.md +++ b/examples/cifar10/readme.md @@ -24,8 +24,8 @@ You will first need to download and convert the data format from the [CIFAR-10 w cd $CAFFE_ROOT/data/cifar10 ./get_cifar10.sh - cd $CAFFE_ROOT/examples/cifar10 - ./create_cifar10.sh + cd $CAFFE_ROOT + ./examples/cifar10/create_cifar10.sh If it complains that `wget` or `gunzip` are not installed, you need to install them respectively. After running the script there should be the dataset, `./cifar10-leveldb`, and the data set image mean `./mean.binaryproto`. @@ -39,8 +39,8 @@ Training and Testing the "Quick" Model Training the model is simple after you have written the network definition protobuf and solver protobuf files (refer to [MNIST Tutorial](../examples/mnist.html)). Simply run `train_quick.sh`, or the following command directly: - cd $CAFFE_ROOT/examples/cifar10 - ./train_quick.sh + cd $CAFFE_ROOT + ./examples/cifar10/train_quick.sh `train_quick.sh` is a simple script, so have a look inside. The main tool for training is `caffe` with the `train` action, and the solver protobuf text file as its argument. From f7625e3632fd18ef0ebeafbe9c807990582618dc Mon Sep 17 00:00:00 2001 From: Daniel Golden Date: Wed, 5 Nov 2014 13:36:00 -0800 Subject: [PATCH 156/798] Prevent Matlab on OS X from crashing on error Replace CHECK() and LOG(FATAL) with LOG(ERROR) and mexErrMsgTxt A failed CHECK() or LOG(FATAL) causes Matlab to crash on OS X 10.9 with Matlab 2014a. --- matlab/caffe/matcaffe.cpp | 71 +++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/matlab/caffe/matcaffe.cpp b/matlab/caffe/matcaffe.cpp index fc047585cfe..3de0f02e1eb 100644 --- a/matlab/caffe/matcaffe.cpp +++ b/matlab/caffe/matcaffe.cpp @@ -3,6 +3,7 @@ // caffe::Caffe functions so that one could easily call it from matlab. // Note that for matlab, we will simply use float as the data type. +#include #include #include @@ -12,6 +13,12 @@ #define MEX_ARGS int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs +// Log and throw a Mex error +inline void mex_error(const std::string &msg) { + LOG(ERROR) << msg; + mexErrMsgTxt(msg.c_str()); +} + using namespace caffe; // NOLINT(build/namespaces) // The pointer to the internal caffe::Net instance @@ -46,14 +53,22 @@ static int init_key = -2; static mxArray* do_forward(const mxArray* const bottom) { vector*>& input_blobs = net_->input_blobs(); - CHECK_EQ(static_cast(mxGetDimensions(bottom)[0]), - input_blobs.size()); + if (static_cast(mxGetDimensions(bottom)[0]) != + input_blobs.size()) { + mex_error("Invalid input size"); + } for (unsigned int i = 0; i < input_blobs.size(); ++i) { const mxArray* const elem = mxGetCell(bottom, i); - CHECK(mxIsSingle(elem)) - << "MatCaffe require single-precision float point data"; - CHECK_EQ(mxGetNumberOfElements(elem), input_blobs[i]->count()) - << "MatCaffe input size does not match the input size of the network"; + if (!mxIsSingle(elem)) { + mex_error("MatCaffe require single-precision float point data"); + } + if (mxGetNumberOfElements(elem) != input_blobs[i]->count()) { + std::string error_msg; + error_msg += "MatCaffe input size does not match the input size "; + error_msg += "of the network"; + mex_error(error_msg); + } + const float* const data_ptr = reinterpret_cast(mxGetPr(elem)); switch (Caffe::mode()) { @@ -66,7 +81,7 @@ static mxArray* do_forward(const mxArray* const bottom) { input_blobs[i]->mutable_gpu_data()); break; default: - LOG(FATAL) << "Unknown Caffe mode."; + mex_error("Unknown Caffe mode"); } // switch (Caffe::mode()) } const vector*>& output_blobs = net_->ForwardPrefilled(); @@ -89,7 +104,7 @@ static mxArray* do_forward(const mxArray* const bottom) { data_ptr); break; default: - LOG(FATAL) << "Unknown Caffe mode."; + mex_error("Unknown Caffe mode"); } // switch (Caffe::mode()) } @@ -99,8 +114,10 @@ static mxArray* do_forward(const mxArray* const bottom) { static mxArray* do_backward(const mxArray* const top_diff) { vector*>& output_blobs = net_->output_blobs(); vector*>& input_blobs = net_->input_blobs(); - CHECK_EQ(static_cast(mxGetDimensions(top_diff)[0]), - output_blobs.size()); + if (static_cast(mxGetDimensions(top_diff)[0]) != + output_blobs.size()) { + mex_error("Invalid input size"); + } // First, copy the output diff for (unsigned int i = 0; i < output_blobs.size(); ++i) { const mxArray* const elem = mxGetCell(top_diff, i); @@ -116,7 +133,7 @@ static mxArray* do_backward(const mxArray* const top_diff) { output_blobs[i]->mutable_gpu_diff()); break; default: - LOG(FATAL) << "Unknown Caffe mode."; + mex_error("Unknown Caffe mode"); } // switch (Caffe::mode()) } // LOG(INFO) << "Start"; @@ -139,7 +156,7 @@ static mxArray* do_backward(const mxArray* const top_diff) { caffe_copy(input_blobs[i]->count(), input_blobs[i]->gpu_diff(), data_ptr); break; default: - LOG(FATAL) << "Unknown Caffe mode."; + mex_error("Unknown Caffe mode"); } // switch (Caffe::mode()) } @@ -216,7 +233,7 @@ static mxArray* do_get_weights() { weights_ptr); break; default: - LOG(FATAL) << "Unknown caffe mode: " << Caffe::mode(); + mex_error("Unknown Caffe mode"); } } } @@ -247,8 +264,9 @@ static void set_phase_test(MEX_ARGS) { static void set_device(MEX_ARGS) { if (nrhs != 1) { - LOG(ERROR) << "Only given " << nrhs << " arguments"; - mexErrMsgTxt("Wrong number of arguments"); + ostringstream error_msg; + error_msg << "Expected 1 argument, got " << nrhs; + mex_error(error_msg.str()); } int device_id = static_cast(mxGetScalar(prhs[0])); @@ -261,8 +279,9 @@ static void get_init_key(MEX_ARGS) { static void init(MEX_ARGS) { if (nrhs != 2) { - LOG(ERROR) << "Only given " << nrhs << " arguments"; - mexErrMsgTxt("Wrong number of arguments"); + ostringstream error_msg; + error_msg << "Expected 2 arguments, got " << nrhs; + mex_error(error_msg.str()); } char* param_file = mxArrayToString(prhs[0]); @@ -291,8 +310,9 @@ static void reset(MEX_ARGS) { static void forward(MEX_ARGS) { if (nrhs != 1) { - LOG(ERROR) << "Only given " << nrhs << " arguments"; - mexErrMsgTxt("Wrong number of arguments"); + ostringstream error_msg; + error_msg << "Expected 1 argument, got " << nrhs; + mex_error(error_msg.str()); } plhs[0] = do_forward(prhs[0]); @@ -300,8 +320,9 @@ static void forward(MEX_ARGS) { static void backward(MEX_ARGS) { if (nrhs != 1) { - LOG(ERROR) << "Only given " << nrhs << " arguments"; - mexErrMsgTxt("Wrong number of arguments"); + ostringstream error_msg; + error_msg << "Expected 1 argument, got " << nrhs; + mex_error(error_msg.str()); } plhs[0] = do_backward(prhs[0]); @@ -374,8 +395,7 @@ static handler_registry handlers[] = { void mexFunction(MEX_ARGS) { mexLock(); // Avoid clearing the mex file. if (nrhs == 0) { - LOG(ERROR) << "No API command given"; - mexErrMsgTxt("An API command is requires"); + mex_error("No API command given"); return; } @@ -391,8 +411,9 @@ void mexFunction(MEX_ARGS) { } } if (!dispatched) { - LOG(ERROR) << "Unknown command `" << cmd << "'"; - mexErrMsgTxt("API command not recognized"); + ostringstream error_msg; + error_msg << "Unknown command '" << cmd << "'"; + mex_error(error_msg.str()); } mxFree(cmd); } From f29d4bd75423e4d9c91d7a26e092ab687ab87e97 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Fri, 7 Nov 2014 17:17:49 -0800 Subject: [PATCH 157/798] clean incorrect relu test code --- src/caffe/test/test_neuron_layer.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/caffe/test/test_neuron_layer.cpp b/src/caffe/test/test_neuron_layer.cpp index 34955c3af63..89db53a6979 100644 --- a/src/caffe/test/test_neuron_layer.cpp +++ b/src/caffe/test/test_neuron_layer.cpp @@ -1,6 +1,7 @@ #include #include +#include "google/protobuf/text_format.h" #include "gtest/gtest.h" #include "caffe/blob.hpp" @@ -152,7 +153,8 @@ TYPED_TEST(NeuronLayerTest, TestReLUGradient) { TYPED_TEST(NeuronLayerTest, TestReLUWithNegativeSlope) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; - layer_param.ParseFromString("relu_param{negative_slope:0.01}"); + CHECK(google::protobuf::TextFormat::ParseFromString( + "relu_param { negative_slope: 0.01 }", &layer_param)); ReLULayer layer(layer_param); layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); @@ -160,15 +162,19 @@ TYPED_TEST(NeuronLayerTest, TestReLUWithNegativeSlope) { const Dtype* bottom_data = this->blob_bottom_->cpu_data(); const Dtype* top_data = this->blob_top_->cpu_data(); for (int i = 0; i < this->blob_bottom_->count(); ++i) { - EXPECT_GE(top_data[i], 0.); - EXPECT_TRUE(top_data[i] == 0 || top_data[i] == bottom_data[i]); + if (top_data[i] >= 0) { + EXPECT_FLOAT_EQ(top_data[i], bottom_data[i]); + } else { + EXPECT_FLOAT_EQ(top_data[i], bottom_data[i] * 0.01); + } } } TYPED_TEST(NeuronLayerTest, TestReLUGradientWithNegativeSlope) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; - layer_param.ParseFromString("relu_param{negative_slope:0.01}"); + CHECK(google::protobuf::TextFormat::ParseFromString( + "relu_param { negative_slope: 0.01 }", &layer_param)); ReLULayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, @@ -437,7 +443,8 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestReLUGradientCuDNN) { TYPED_TEST(CuDNNNeuronLayerTest, TestReLUWithNegativeSlopeCuDNN) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; - layer_param.ParseFromString("relu_param{negative_slope:0.01}"); + CHECK(google::protobuf::TextFormat::ParseFromString( + "relu_param { negative_slope: 0.01 }", &layer_param)); CuDNNReLULayer layer(layer_param); layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); @@ -453,7 +460,8 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestReLUWithNegativeSlopeCuDNN) { TYPED_TEST(CuDNNNeuronLayerTest, TestReLUGradientWithNegativeSlopeCuDNN) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; - layer_param.ParseFromString("relu_param{negative_slope:0.01}"); + CHECK(google::protobuf::TextFormat::ParseFromString( + "relu_param { negative_slope: 0.01 }", &layer_param)); CuDNNReLULayer layer(layer_param); GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, From 9ff22ec5283182198c2db6a4c1b5a5a9dceb1ead Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Fri, 7 Nov 2014 17:42:43 -0800 Subject: [PATCH 158/798] relax benchmark milliseconds threshold --- src/caffe/test/test_benchmark.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/caffe/test/test_benchmark.cpp b/src/caffe/test/test_benchmark.cpp index dbbee08d667..43aaa639b3c 100644 --- a/src/caffe/test/test_benchmark.cpp +++ b/src/caffe/test/test_benchmark.cpp @@ -9,6 +9,8 @@ namespace caffe { +const float kMillisecondsThreshold = 30; + template class BenchmarkTest : public MultiDeviceTest {}; @@ -63,8 +65,8 @@ TYPED_TEST(BenchmarkTest, TestTimerMilliSeconds) { EXPECT_FALSE(timer.has_run_at_least_once()); timer.Start(); usleep(300 * 1000); - EXPECT_GE(timer.MilliSeconds(), 290); - EXPECT_LE(timer.MilliSeconds(), 310); + EXPECT_GE(timer.MilliSeconds(), 300 - kMillisecondsThreshold); + EXPECT_LE(timer.MilliSeconds(), 300 + kMillisecondsThreshold); EXPECT_TRUE(timer.initted()); EXPECT_FALSE(timer.running()); EXPECT_TRUE(timer.has_run_at_least_once()); @@ -78,8 +80,8 @@ TYPED_TEST(BenchmarkTest, TestTimerSeconds) { EXPECT_FALSE(timer.has_run_at_least_once()); timer.Start(); usleep(300 * 1000); - EXPECT_GE(timer.Seconds(), 0.290); - EXPECT_LE(timer.Seconds(), 0.310); + EXPECT_GE(timer.Seconds(), 0.3 - kMillisecondsThreshold / 1000.); + EXPECT_LE(timer.Seconds(), 0.3 + kMillisecondsThreshold / 1000.); EXPECT_TRUE(timer.initted()); EXPECT_FALSE(timer.running()); EXPECT_TRUE(timer.has_run_at_least_once()); From 1fe4b81a4147d42b4a7042bb82b06f7b41fd2d99 Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Thu, 13 Nov 2014 22:05:42 -0800 Subject: [PATCH 159/798] fix relu cudnn test bug --- src/caffe/test/test_neuron_layer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/caffe/test/test_neuron_layer.cpp b/src/caffe/test/test_neuron_layer.cpp index 89db53a6979..b19a5abdcdf 100644 --- a/src/caffe/test/test_neuron_layer.cpp +++ b/src/caffe/test/test_neuron_layer.cpp @@ -452,8 +452,11 @@ TYPED_TEST(CuDNNNeuronLayerTest, TestReLUWithNegativeSlopeCuDNN) { const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); const TypeParam* top_data = this->blob_top_->cpu_data(); for (int i = 0; i < this->blob_bottom_->count(); ++i) { - EXPECT_GE(top_data[i], 0.); - EXPECT_TRUE(top_data[i] == 0 || top_data[i] == bottom_data[i]); + if (top_data[i] >= 0) { + EXPECT_FLOAT_EQ(top_data[i], bottom_data[i]); + } else { + EXPECT_FLOAT_EQ(top_data[i], bottom_data[i] * 0.01); + } } } From 51a09de81d10714d0d1a03e4eab028e994cb82e1 Mon Sep 17 00:00:00 2001 From: Pavel Campr Date: Fri, 14 Nov 2014 08:31:34 +0100 Subject: [PATCH 160/798] fixed filename in build_docs.sh --- scripts/build_docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_docs.sh b/scripts/build_docs.sh index f8ace0ead43..0e28bd71631 100755 --- a/scripts/build_docs.sh +++ b/scripts/build_docs.sh @@ -3,7 +3,7 @@ PORT=${1:-4000} -echo "usage: build.sh [port]" +echo "usage: build_docs.sh [port]" # Find the docs dir, no matter where the script is called ROOT_DIR="$( cd "$(dirname "$0")"/.. ; pwd -P )" From 8271e6bd0cccd8aa8b878c1b9cafdd965a09ec9b Mon Sep 17 00:00:00 2001 From: Michele Pratusevich Date: Tue, 18 Nov 2014 17:47:13 -0500 Subject: [PATCH 161/798] Update python requirements.txt You need pyyaml to run the download scripts for getting the BVLC model references. --- python/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/python/requirements.txt b/python/requirements.txt index 4c35dcb0b6f..908373bf452 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -13,3 +13,4 @@ pandas>=0.12.0 python-dateutil>=1.4,<2 protobuf>=2.5.0 python-gflags>=2.0 +pyyaml>=3.10 From dbb6a2054651cbd0a5058d45a27575b9de41b5a5 Mon Sep 17 00:00:00 2001 From: Sean Bell Date: Wed, 19 Nov 2014 17:25:08 -0500 Subject: [PATCH 162/798] fixed tanh to not return NaN for input values outside the range [-40, 40] --- src/caffe/layers/tanh_layer.cpp | 4 +- src/caffe/layers/tanh_layer.cu | 3 +- src/caffe/test/test_tanh_layer.cpp | 102 +++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 src/caffe/test/test_tanh_layer.cpp diff --git a/src/caffe/layers/tanh_layer.cpp b/src/caffe/layers/tanh_layer.cpp index 18413d9b181..ee5ed773c74 100644 --- a/src/caffe/layers/tanh_layer.cpp +++ b/src/caffe/layers/tanh_layer.cpp @@ -14,11 +14,9 @@ void TanHLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { const Dtype* bottom_data = bottom[0]->cpu_data(); Dtype* top_data = top[0]->mutable_cpu_data(); - Dtype exp2x; const int count = bottom[0]->count(); for (int i = 0; i < count; ++i) { - exp2x = exp(2 * bottom_data[i]); - top_data[i] = (exp2x - Dtype(1)) / (exp2x + Dtype(1)); + top_data[i] = tanh(bottom_data[i]); } } diff --git a/src/caffe/layers/tanh_layer.cu b/src/caffe/layers/tanh_layer.cu index f1a0fc88bfd..ccd6e63ee7c 100644 --- a/src/caffe/layers/tanh_layer.cu +++ b/src/caffe/layers/tanh_layer.cu @@ -12,8 +12,7 @@ namespace caffe { template __global__ void TanHForward(const int n, const Dtype* in, Dtype* out) { CUDA_KERNEL_LOOP(index, n) { - Dtype exp2x = exp(2 * in[index]); - out[index] = (exp2x - Dtype(1)) / (exp2x + Dtype(1)); + out[index] = tanh(in[index]); } } diff --git a/src/caffe/test/test_tanh_layer.cpp b/src/caffe/test/test_tanh_layer.cpp new file mode 100644 index 00000000000..9a93e08e805 --- /dev/null +++ b/src/caffe/test/test_tanh_layer.cpp @@ -0,0 +1,102 @@ +#include +#include + +#include "gtest/gtest.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/common_layers.hpp" + +#include "caffe/test/test_caffe_main.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +namespace caffe { + +double tanh_naive(double x) { + if (x < -40) { + // avoid negative overflow + return -1; + } else if (x > 40) { + // avoid positive overflow + return 1; + } else { + // exact expression for tanh, which is unstable for large x + double exp2x = exp(2 * x); + return (exp2x - 1.0) / (exp2x + 1.0); + } +} + +template +class TanHLayerTest : public MultiDeviceTest { + typedef typename TypeParam::Dtype Dtype; + + protected: + TanHLayerTest() + : blob_bottom_(new Blob(2, 3, 4, 5)), + blob_top_(new Blob()) { + Caffe::set_random_seed(1701); + FillerParameter filler_param; + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~TanHLayerTest() { delete blob_bottom_; delete blob_top_; } + + void TestForward(Dtype filler_std) { + FillerParameter filler_param; + filler_param.set_std(filler_std); + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + + LayerParameter layer_param; + TanHLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); + // Now, check values + const Dtype* bottom_data = this->blob_bottom_->cpu_data(); + const Dtype* top_data = this->blob_top_->cpu_data(); + const Dtype min_precision = 1e-5; + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + Dtype expected_value = tanh_naive(bottom_data[i]); + Dtype precision = std::max( + Dtype(std::abs(expected_value * Dtype(1e-4))), min_precision); + EXPECT_NEAR(expected_value, top_data[i], precision); + } + } + + void TestBackward(Dtype filler_std) { + FillerParameter filler_param; + filler_param.set_std(filler_std); + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + + LayerParameter layer_param; + TanHLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2, 1701); + checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); + } + + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +TYPED_TEST_CASE(TanHLayerTest, TestDtypesAndDevices); + +TYPED_TEST(TanHLayerTest, TestTanH) { + this->TestForward(1.0); +} + +TYPED_TEST(TanHLayerTest, TestTanHOverflow) { + // this will fail if tanh overflow is not properly handled + this->TestForward(10000.0); +} + +TYPED_TEST(TanHLayerTest, TestTanHGradient) { + this->TestBackward(1.0); +} + +} // namespace caffe From cb3eb31753cdd9ee2f9aa0f71c53bf2000ea5cfd Mon Sep 17 00:00:00 2001 From: Sean Bell Date: Wed, 19 Nov 2014 23:21:53 -0500 Subject: [PATCH 163/798] Fixed header order to satisfy linter --- src/caffe/test/test_tanh_layer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/caffe/test/test_tanh_layer.cpp b/src/caffe/test/test_tanh_layer.cpp index 9a93e08e805..5dc92832fc8 100644 --- a/src/caffe/test/test_tanh_layer.cpp +++ b/src/caffe/test/test_tanh_layer.cpp @@ -5,9 +5,8 @@ #include "caffe/blob.hpp" #include "caffe/common.hpp" -#include "caffe/filler.hpp" -#include "caffe/vision_layers.hpp" #include "caffe/common_layers.hpp" +#include "caffe/filler.hpp" #include "caffe/test/test_caffe_main.hpp" #include "caffe/test/test_gradient_check_util.hpp" From 9443c4417527d8a07f60410a52dc87d75f7304f5 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sat, 22 Nov 2014 11:59:07 -0800 Subject: [PATCH 164/798] in SoftmaxLossLayer, check label >= 0 in addition to upper bound --- src/caffe/layers/softmax_loss_layer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index 35033b67c21..c4358731753 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -44,6 +44,7 @@ void SoftmaxWithLossLayer::Forward_cpu( for (int i = 0; i < num; ++i) { for (int j = 0; j < spatial_dim; j++) { const int label_value = static_cast(label[i * spatial_dim + j]); + CHECK_GE(label_value, 0); CHECK_GT(dim, label_value * spatial_dim); loss -= log(std::max(prob_data[i * dim + label_value * spatial_dim + j], From 33eb36e4034a0db92af8b08dc0a9217d46ba531b Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 23 Nov 2014 17:58:24 -0800 Subject: [PATCH 165/798] use DCHECK in SoftmaxLossLayer so that bounds checking has no perf penalty without DEBUG --- src/caffe/layers/softmax_loss_layer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index c4358731753..82c62f6a1bd 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -44,8 +44,8 @@ void SoftmaxWithLossLayer::Forward_cpu( for (int i = 0; i < num; ++i) { for (int j = 0; j < spatial_dim; j++) { const int label_value = static_cast(label[i * spatial_dim + j]); - CHECK_GE(label_value, 0); - CHECK_GT(dim, label_value * spatial_dim); + DCHECK_GE(label_value, 0); + DCHECK_GT(dim, label_value * spatial_dim); loss -= log(std::max(prob_data[i * dim + label_value * spatial_dim + j], Dtype(FLT_MIN))); From 8009436671ec01823fe465283b111141ef28e8f4 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 30 Nov 2014 21:34:29 -0800 Subject: [PATCH 166/798] remove redundant code in ConvolutionLayer::Reshape --- src/caffe/layers/conv_layer.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/caffe/layers/conv_layer.cpp b/src/caffe/layers/conv_layer.cpp index 65ff9167128..0a032025bfb 100644 --- a/src/caffe/layers/conv_layer.cpp +++ b/src/caffe/layers/conv_layer.cpp @@ -126,9 +126,6 @@ void ConvolutionLayer::Reshape(const vector*>& bottom, // it goes lazily unused to save memory. col_buffer_.Reshape( 1, channels_ * kernel_h_ * kernel_w_, height_out_, width_out_); - for (int top_id = 0; top_id < top.size(); ++top_id) { - top[top_id]->Reshape(num_, num_output_, height_out_, width_out_); - } // Set up the all ones "bias multiplier" for adding biases by BLAS if (bias_term_) { bias_multiplier_.Reshape(1, 1, 1, N_); From 873a860ade3a4124bb5a9b34becf0858197a11f8 Mon Sep 17 00:00:00 2001 From: Daniel Golden Date: Tue, 2 Dec 2014 11:20:58 -0800 Subject: [PATCH 167/798] Better instructions for updating Homebrew after modifying formulae Previous instructions glossed over how to deal with OpenCV-related update problems --- docs/installation.md | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 207e17d1539..c667cd8ce01 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -208,28 +208,39 @@ If you're not using Anaconda, include `hdf5` in the list above. Aborting Error: Failure while executing: git pull -q origin refs/heads/master:refs/remotes/origin/master -One solution is to commit your changes to a separate Homebrew branch, run `brew update`, and rebase your changes onto the updated master, as follows: +One solution is to commit your changes to a separate Homebrew branch, run `brew update`, and rebase your changes onto the updated master. You'll have to do this both for the main Homebrew repository in `/usr/local/` and the Homebrew science repository that contains OpenCV in `/usr/local/Library/Taps/homebrew/homebrew-science`, as follows: cd /usr/local git checkout -b caffe git add . git commit -m "Update Caffe dependencies to use libstdc++" + cd /usr/local/Library/Taps/homebrew/homebrew-science + git checkout -b caffe + git add . + git commit -m "Update Caffe dependencies" + +Then, whenever you want to update homebrew, switch back to the master branches, do the update, rebase the caffe branches onto master and fix any conflicts: + + # Switch batch to homebrew master branches + cd /usr/local + git checkout master + cd /usr/local/Library/Taps/homebrew/homebrew-science git checkout master + + # Update homebrew; hopefully this works without errors! brew update + + # Switch back to the caffe branches with the forumlae that you modified earlier + cd /usr/local git rebase master caffe - # Resolve any merge conflicts here - git checkout caffe - -At this point, you should be running the latest Homebrew packages and your Caffe-related modifications will remain in place. You may still get the following error: - - $ brew update - error: Your local changes to the following files would be overwritten by merge: - opencv.rb - Please, commit your changes or stash them before you can merge. - Aborting - Error: Failed to update tap: homebrew/science + # Fix any merge conflicts and commit to caffe branch + cd /usr/local/Library/Taps/homebrew/homebrew-science + git rebase master caffe + # Fix any merge conflicts and commit to caffe branch + + # Done! -but non-OpenCV packages will still update as expected. +At this point, you should be running the latest Homebrew packages and your Caffe-related modifications will remain in place. #### Windows From a5b7b2d7ede8dd37f4e6bdcf87ca3e71f78633e0 Mon Sep 17 00:00:00 2001 From: Daniel Golden Date: Wed, 3 Dec 2014 14:30:14 -0800 Subject: [PATCH 168/798] Update mean file help Numpy array dimensions should be [Channels x Height x Width], NOT [Height x Width x Channels] If an image mean file is supplied with channels as the last dimension, classify.py throws errors like: ValueError: operands could not be broadcast together with shapes (3,227,227) (256,0,225) (3,227,227) --- python/classify.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/classify.py b/python/classify.py index 873b5e38f19..d435a572266 100755 --- a/python/classify.py +++ b/python/classify.py @@ -60,8 +60,8 @@ def main(argv): "--mean_file", default=os.path.join(pycaffe_dir, 'caffe/imagenet/ilsvrc_2012_mean.npy'), - help="Data set image mean of H x W x K dimensions (numpy array). " + - "Set to '' for no mean subtraction." + help="Data set image mean of [Channels x Height x Width] dimensions " + + "(numpy array). Set to '' for no mean subtraction." ) parser.add_argument( "--input_scale", From e8dee350ade66a712144aebc8b5f4a8c989d43c0 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 5 Dec 2014 08:06:40 -0800 Subject: [PATCH 169/798] compile for compute capability 5.0 --- Makefile.config.example | 9 ++++----- src/caffe/CMakeLists.txt | 4 +++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile.config.example b/Makefile.config.example index 5cb0b243aca..18798ed2d06 100644 --- a/Makefile.config.example +++ b/Makefile.config.example @@ -17,15 +17,14 @@ CUDA_DIR := /usr/local/cuda # "sudo apt-get install nvidia-cuda-toolkit" then use this instead: # CUDA_DIR := /usr -# CUDA architecture setting: going with all of them (up to CUDA 5.5 compatible). -# For the latest architecture, you need to install CUDA >= 6.0 and uncomment -# the *_50 lines below. +# CUDA architecture setting: going with all of them. +# For CUDA < 6.0, comment the *_50 lines for compatibility. CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ -gencode arch=compute_20,code=sm_21 \ -gencode arch=compute_30,code=sm_30 \ -gencode arch=compute_35,code=sm_35 \ - #-gencode arch=compute_50,code=sm_50 \ - #-gencode arch=compute_50,code=compute_50 + -gencode arch=compute_50,code=sm_50 \ + -gencode arch=compute_50,code=compute_50 # BLAS choice: # atlas for ATLAS (default) diff --git a/src/caffe/CMakeLists.txt b/src/caffe/CMakeLists.txt index 86c7c7eb4a3..dc6b5a2baac 100644 --- a/src/caffe/CMakeLists.txt +++ b/src/caffe/CMakeLists.txt @@ -84,8 +84,10 @@ if(NOT CPU_ONLY) -gencode arch=compute_20,code=sm_21 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=sm_35 + -gencode arch=compute_50,code=sm_50 + -gencode arch=compute_50,code=compute_50 ) - + # https://github.com/ComputationalRadiationPhysics/picongpu/blob/master/src/picongpu/CMakeLists.txt # work-arounds if(Boost_VERSION EQUAL 105500) From fb298ddd4ef13375c953a201422293f33da44300 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 7 Dec 2014 03:06:35 -0800 Subject: [PATCH 170/798] clarify #endif comment --- include/caffe/util/math_functions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/caffe/util/math_functions.hpp b/include/caffe/util/math_functions.hpp index 12823f8da0c..d3ecf5875fa 100644 --- a/include/caffe/util/math_functions.hpp +++ b/include/caffe/util/math_functions.hpp @@ -267,7 +267,7 @@ void caffe_gpu_##name(const int n, const double* x, double* y) { \ n, x, y); \ } -#endif // CPU_ONLY +#endif // !CPU_ONLY } // namespace caffe From 9b78bcffbb515b39228f2d483dbfd596410d5f59 Mon Sep 17 00:00:00 2001 From: Daniel Golden Date: Thu, 30 Oct 2014 15:51:14 -0700 Subject: [PATCH 171/798] Created parse_log.py, competitor to parse_log.sh --- tools/extra/extract_seconds.py | 33 ++++++-- tools/extra/parse_log.py | 140 +++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 6 deletions(-) create mode 100755 tools/extra/parse_log.py diff --git a/tools/extra/extract_seconds.py b/tools/extra/extract_seconds.py index f791afa32a2..591a51f96bd 100755 --- a/tools/extra/extract_seconds.py +++ b/tools/extra/extract_seconds.py @@ -18,18 +18,39 @@ def extract_datetime_from_line(line, year): dt = datetime.datetime(year, month, day, hour, minute, second, microsecond) return dt + +def get_log_created_year(input_file): + """Get year from log file system timestamp + """ + + log_created_time = os.path.getctime(input_file) + log_created_year = datetime.datetime.fromtimestamp(log_created_time).year + return log_created_year + + +def get_start_time(line_iterable, year): + """Find start time from group of lines + """ + + start_datetime = None + for line in line_iterable: + line = line.strip() + if line.find('Solving') != -1: + start_datetime = extract_datetime_from_line(line, year) + break + return start_datetime + + def extract_seconds(input_file, output_file): with open(input_file, 'r') as f: lines = f.readlines() - log_created_time = os.path.getctime(input_file) - log_created_year = datetime.datetime.fromtimestamp(log_created_time).year - start_time_found = False + log_created_year = get_log_created_year(input_file) + start_datetime = get_start_time(lines, log_created_year) + assert start_datetime, 'Start time not found' + out = open(output_file, 'w') for line in lines: line = line.strip() - if not start_time_found and line.find('Solving') != -1: - start_time_found = True - start_datetime = extract_datetime_from_line(line, log_created_year) if line.find('Iteration') != -1: dt = extract_datetime_from_line(line, log_created_year) elapsed_seconds = (dt - start_datetime).total_seconds() diff --git a/tools/extra/parse_log.py b/tools/extra/parse_log.py new file mode 100755 index 00000000000..dca7999f1bc --- /dev/null +++ b/tools/extra/parse_log.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python + +""" +Parse training log + +Competitor to parse_log.sh +""" + +import os +import re +import extract_seconds +import argparse + + +def get_line_type(line): + """Return either 'test' or 'train depending on line type + """ + + line_type = None + if line.find('Train') != -1: + line_type = 'train' + elif line.find('Test') != -1: + line_type = 'test' + return line_type + + +def parse_log(path_to_log): + """Parse log file + """ + + re_iteration = re.compile('Iteration (\d+)') + re_accuracy = re.compile('output #\d+: accuracy = ([\.\d]+)') + re_loss = re.compile('output #\d+: loss = ([\.\d]+)') + re_lr = re.compile('lr = ([\.\d]+)') + + # Pick out lines of interest + iteration = -1 + test_accuracy = -1 + learning_rate = float('NaN') + train_list = [] + test_list = [] + + logfile_year = extract_seconds.get_log_created_year(path_to_log) + with open(path_to_log) as f: + start_time = extract_seconds.get_start_time(f, logfile_year) + + for line in f: + iteration_match = re_iteration.search(line) + if iteration_match: + iteration = float(iteration_match.group(1)) + if iteration == -1: + # Only look for other stuff if we've found the first iteration + continue + + time = extract_seconds.extract_datetime_from_line(line, + logfile_year) + seconds = (time - start_time).total_seconds() + + lr_match = re_lr.search(line) + if lr_match: + learning_rate = float(lr_match.group(1)) + + accuracy_match = re_accuracy.search(line) + if accuracy_match: + test_accuracy = float(accuracy_match.group(1)) + + loss_match = re_loss.search(line) + if loss_match: + loss = float(loss_match.group(1)) + line_type = get_line_type(line) + assert line_type, ('Failed to determine line type for line: ' + + line) + if line_type == 'test': + # NOTE: we assume that accuracy always comes right before + # loss for test data + test_list.append((iteration, seconds, test_accuracy, loss)) + elif line_type == 'train': + train_list.append((iteration, seconds, loss, learning_rate)) + + return train_list, test_list + + +def save_csv_files(logfile_path, output_dir, train_list, test_list, + verbose=False): + """Save CSV files to output_dir + + If the input log file is, e.g., caffe.INFO, the names will be + caffe.INFO.train and caffe.INFO.test + """ + + log_basename = os.path.basename(logfile_path) + train_filename = os.path.join(output_dir, log_basename + '.train') + write_csv(train_filename, train_list, '%d,%f,%f,%f', + 'NumIters,Seconds,TrainingLoss,LearningRate', verbose) + + test_filename = os.path.join(output_dir, log_basename + '.test') + write_csv(test_filename, test_list, '%d,%f,%f,%f', + 'NumIters,Seconds,TestAccuracy,TestLoss', verbose) + + +def write_csv(output_filename, list_of_tuples, format_string, header, + verbose=False): + """Write a CSV file + """ + with open(output_filename, 'w') as f: + f.write(header + '\n') + for row in list_of_tuples: + line = format_string % row + f.write(line + '\n') + if verbose: + print 'Wrote %s' % output_filename + + +def parse_args(): + description = ('Parse a Caffe training log into two CSV files ' + 'representing training and testing information') + parser = argparse.ArgumentParser(description=description) + + parser.add_argument('logfile_path', + help='Path to log file') + + parser.add_argument('output_dir', + help='Directory in which to place output CSV files') + + parser.add_argument('--verbose', + action='store_true', + help='Print some extra info (e.g., output filenames)') + + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + train_list, test_list = parse_log(args.logfile_path) + save_csv_files(args.logfile_path, args.output_dir, train_list, test_list) + + +if __name__ == '__main__': + main() From f954c6bea18e7c69520ee4c962b9b263c18a9769 Mon Sep 17 00:00:00 2001 From: Daniel Golden Date: Fri, 31 Oct 2014 10:24:07 -0700 Subject: [PATCH 172/798] Take train loss from `Iteration N, loss = X` lines Was previously using `Train net output #M: loss = X` lines, but there may not be exactly one of those (e.g., for GoogLeNet, which has multiple loss layers); I believe that `Iteration N, loss = X` is the aggregated loss. If there's only one loss layer, these two values will be equal and it won't matter. Otherwise, we presumably want to report the aggregated loss. --- tools/extra/parse_log.py | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/tools/extra/parse_log.py b/tools/extra/parse_log.py index dca7999f1bc..41fe54dc8a0 100755 --- a/tools/extra/parse_log.py +++ b/tools/extra/parse_log.py @@ -13,7 +13,7 @@ def get_line_type(line): - """Return either 'test' or 'train depending on line type + """Return either 'test' or 'train' depending on line type """ line_type = None @@ -30,7 +30,8 @@ def parse_log(path_to_log): re_iteration = re.compile('Iteration (\d+)') re_accuracy = re.compile('output #\d+: accuracy = ([\.\d]+)') - re_loss = re.compile('output #\d+: loss = ([\.\d]+)') + re_train_loss = re.compile('Iteration \d+, loss = ([\.\d]+)') + re_output_loss = re.compile('output #\d+: loss = ([\.\d]+)') re_lr = re.compile('lr = ([\.\d]+)') # Pick out lines of interest @@ -61,21 +62,23 @@ def parse_log(path_to_log): learning_rate = float(lr_match.group(1)) accuracy_match = re_accuracy.search(line) - if accuracy_match: + if accuracy_match and get_line_type(line) == 'test': test_accuracy = float(accuracy_match.group(1)) - loss_match = re_loss.search(line) - if loss_match: - loss = float(loss_match.group(1)) - line_type = get_line_type(line) - assert line_type, ('Failed to determine line type for line: ' + - line) - if line_type == 'test': - # NOTE: we assume that accuracy always comes right before - # loss for test data - test_list.append((iteration, seconds, test_accuracy, loss)) - elif line_type == 'train': - train_list.append((iteration, seconds, loss, learning_rate)) + train_loss_match = re_train_loss.search(line) + if train_loss_match: + train_loss = float(train_loss_match.group(1)) + train_list.append((iteration, seconds, train_loss, + learning_rate)) + + output_loss_match = re_output_loss.search(line) + if output_loss_match and get_line_type(line) == 'test': + test_loss = float(output_loss_match.group(1)) + # NOTE: we assume that (1) accuracy always comes right before + # loss for test data so the test_accuracy variable is already + # correctly populated and (2) there's one and only one output + # named "accuracy" for the test net + test_list.append((iteration, seconds, test_accuracy, test_loss)) return train_list, test_list @@ -113,7 +116,7 @@ def write_csv(output_filename, list_of_tuples, format_string, header, def parse_args(): description = ('Parse a Caffe training log into two CSV files ' - 'representing training and testing information') + 'containing training and testing information') parser = argparse.ArgumentParser(description=description) parser.add_argument('logfile_path', From bae916f74b03793c323edd679eaa0e665da0ec0b Mon Sep 17 00:00:00 2001 From: Daniel Golden Date: Sun, 2 Nov 2014 21:02:07 -0800 Subject: [PATCH 173/798] Store data in lists of dicts and use csv package Output format is unchanged (except that csv.DictWriter insists on writing ints as 0.0 instead of 0) --- tools/extra/parse_log.py | 54 +++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/tools/extra/parse_log.py b/tools/extra/parse_log.py index 41fe54dc8a0..16ba077aee6 100755 --- a/tools/extra/parse_log.py +++ b/tools/extra/parse_log.py @@ -10,6 +10,7 @@ import re import extract_seconds import argparse +import csv def get_line_type(line): @@ -26,6 +27,13 @@ def get_line_type(line): def parse_log(path_to_log): """Parse log file + Returns (train_dict_list, train_dict_names, test_dict_list, test_dict_names) + + train_dict_list and test_dict_list are lists of dicts that define the table + rows + + train_dict_names and test_dict_names are ordered tuples of the column names + for the two dict_lists """ re_iteration = re.compile('Iteration (\d+)') @@ -38,8 +46,10 @@ def parse_log(path_to_log): iteration = -1 test_accuracy = -1 learning_rate = float('NaN') - train_list = [] - test_list = [] + train_dict_list = [] + test_dict_list = [] + train_dict_names = ('NumIters', 'Seconds', 'TrainingLoss', 'LearningRate') + test_dict_names = ('NumIters', 'Seconds', 'TestAccuracy', 'TestLoss') logfile_year = extract_seconds.get_log_created_year(path_to_log) with open(path_to_log) as f: @@ -68,8 +78,10 @@ def parse_log(path_to_log): train_loss_match = re_train_loss.search(line) if train_loss_match: train_loss = float(train_loss_match.group(1)) - train_list.append((iteration, seconds, train_loss, - learning_rate)) + train_dict_list.append({'NumIters': iteration, + 'Seconds': seconds, + 'TrainingLoss': train_loss, + 'LearningRate': learning_rate}) output_loss_match = re_output_loss.search(line) if output_loss_match and get_line_type(line) == 'test': @@ -78,13 +90,16 @@ def parse_log(path_to_log): # loss for test data so the test_accuracy variable is already # correctly populated and (2) there's one and only one output # named "accuracy" for the test net - test_list.append((iteration, seconds, test_accuracy, test_loss)) + test_dict_list.append({'NumIters': iteration, + 'Seconds': seconds, + 'TestAccuracy': test_accuracy, + 'TestLoss': test_loss}) - return train_list, test_list + return train_dict_list, train_dict_names, test_dict_list, test_dict_names -def save_csv_files(logfile_path, output_dir, train_list, test_list, - verbose=False): +def save_csv_files(logfile_path, output_dir, train_dict_list, train_dict_names, + test_dict_list, test_dict_names, verbose=False): """Save CSV files to output_dir If the input log file is, e.g., caffe.INFO, the names will be @@ -93,23 +108,20 @@ def save_csv_files(logfile_path, output_dir, train_list, test_list, log_basename = os.path.basename(logfile_path) train_filename = os.path.join(output_dir, log_basename + '.train') - write_csv(train_filename, train_list, '%d,%f,%f,%f', - 'NumIters,Seconds,TrainingLoss,LearningRate', verbose) + write_csv(train_filename, train_dict_list, train_dict_names, verbose) test_filename = os.path.join(output_dir, log_basename + '.test') - write_csv(test_filename, test_list, '%d,%f,%f,%f', - 'NumIters,Seconds,TestAccuracy,TestLoss', verbose) + write_csv(test_filename, test_dict_list, test_dict_names, verbose) -def write_csv(output_filename, list_of_tuples, format_string, header, - verbose=False): +def write_csv(output_filename, dict_list, header_names, verbose=False): """Write a CSV file """ + with open(output_filename, 'w') as f: - f.write(header + '\n') - for row in list_of_tuples: - line = format_string % row - f.write(line + '\n') + dict_writer = csv.DictWriter(f, header_names) + dict_writer.writeheader() + dict_writer.writerows(dict_list) if verbose: print 'Wrote %s' % output_filename @@ -135,8 +147,10 @@ def parse_args(): def main(): args = parse_args() - train_list, test_list = parse_log(args.logfile_path) - save_csv_files(args.logfile_path, args.output_dir, train_list, test_list) + train_dict_list, train_dict_names, test_dict_list, test_dict_names = \ + parse_log(args.logfile_path) + save_csv_files(args.logfile_path, args.output_dir, train_dict_list, + train_dict_names, test_dict_list, test_dict_names) if __name__ == '__main__': From 646a204c7d925d8c385b095d8a7a86563f54b706 Mon Sep 17 00:00:00 2001 From: Daniel Golden Date: Wed, 10 Dec 2014 10:39:17 -0800 Subject: [PATCH 174/798] Improvements to network drawing * Use ArgumentParser in draw_net.py to parse input arguments * Plot network horizontally (left-right) by default; yes, this confuses the names "top" and "bottom", but since everyone's monitor is wider than it is tall, you'll be able to see over 50% more of the network on your screen at once. The top-bottom functionality is available via the "--rankdir BT" command line argument to draw_net.py * Display number of outputs on edge for data, convolution and inner product layers * In node names, add newline between layer name and layer type, to save horizontal space (only if graph rank direction is left-right or right-left) * Include convolution and pooling parameters within node names * Distinct colors for convolution, pooling and inner product nodes --- python/caffe/draw.py | 123 ++++++++++++++++++++++++++++++++++++++----- python/draw_net.py | 45 +++++++++++----- 2 files changed, 142 insertions(+), 26 deletions(-) diff --git a/python/caffe/draw.py b/python/caffe/draw.py index f8631cfa09e..d95c193cc93 100644 --- a/python/caffe/draw.py +++ b/python/caffe/draw.py @@ -11,11 +11,11 @@ import pydot # Internal layer and blob styles. -LAYER_STYLE = {'shape': 'record', 'fillcolor': '#6495ED', +LAYER_STYLE_DEFAULT = {'shape': 'record', 'fillcolor': '#6495ED', 'style': 'filled'} NEURON_LAYER_STYLE = {'shape': 'record', 'fillcolor': '#90EE90', 'style': 'filled'} -BLOB_STYLE = {'shape': 'octagon', 'fillcolor': '#F0E68C', +BLOB_STYLE = {'shape': 'octagon', 'fillcolor': '#E0E0E0', 'style': 'filled'} def get_enum_name_by_value(): desc = caffe_pb2.LayerParameter.LayerType.DESCRIPTOR @@ -24,39 +24,136 @@ def get_enum_name_by_value(): d[v.number] = k return d -def get_pydot_graph(caffe_net): - pydot_graph = pydot.Dot(caffe_net.name, graph_type='digraph', rankdir="BT") + +def get_pooling_types_dict(): + """Get dictionary mapping pooling type number to type name + """ + desc = caffe_pb2.PoolingParameter.PoolMethod.DESCRIPTOR + d = {} + for k,v in desc.values_by_name.items(): + d[v.number] = k + return d + + +def determine_edge_label_by_layertype(layer, layertype): + """Define edge label based on layer type + """ + + if layertype == 'DATA': + edge_label = 'Batch ' + str(layer.data_param.batch_size) + elif layertype == 'CONVOLUTION': + edge_label = str(layer.convolution_param.num_output) + elif layertype == 'INNER_PRODUCT': + edge_label = str(layer.inner_product_param.num_output) + else: + edge_label = '""' + + return edge_label + + +def determine_node_label_by_layertype(layer, layertype, rankdir): + """Define node label based on layer type + """ + + if rankdir in ('TB', 'BT'): + # If graph orientation is vertical, horizontal space is free and + # vertical space is not; separate words with spaces + separator = ' ' + else: + # If graph orientation is horizontal, vertical space is free and + # horizontal space is not; separate words with newlines + separator = '\n' + + if layertype == 'CONVOLUTION': + # Outer double quotes needed or else colon characters don't parse + # properly + node_label = '"%s%s(%s)%skernel size: %d%sstride: %d%spad: %d"' %\ + (layer.name, + separator, + layertype, + separator, + layer.convolution_param.kernel_size, + separator, + layer.convolution_param.stride, + separator, + layer.convolution_param.pad) + elif layertype == 'POOLING': + pooling_types_dict = get_pooling_types_dict() + node_label = '"%s%s(%s %s)%skernel size: %d%sstride: %d%spad: %d"' %\ + (layer.name, + separator, + pooling_types_dict[layer.pooling_param.pool], + layertype, + separator, + layer.pooling_param.kernel_size, + separator, + layer.pooling_param.stride, + separator, + layer.pooling_param.pad) + else: + node_label = '"%s%s(%s)"' % (layer.name, separator, layertype) + return node_label + + +def choose_color_by_layertype(layertype): + """Define colors for nodes based on the layer type + """ + color = '#6495ED' # Default + if layertype == 'CONVOLUTION': + color = '#FF5050' + elif layertype == 'POOLING': + color = '#FF9900' + elif layertype == 'INNER_PRODUCT': + color = '#CC33FF' + return color + + +def get_pydot_graph(caffe_net, rankdir, label_edges=True): + pydot_graph = pydot.Dot(caffe_net.name, graph_type='digraph', rankdir=rankdir) pydot_nodes = {} pydot_edges = [] d = get_enum_name_by_value() for layer in caffe_net.layers: name = layer.name layertype = d[layer.type] + node_label = determine_node_label_by_layertype(layer, layertype, rankdir) if (len(layer.bottom) == 1 and len(layer.top) == 1 and layer.bottom[0] == layer.top[0]): # We have an in-place neuron layer. pydot_nodes[name + '_' + layertype] = pydot.Node( - '%s (%s)' % (name, layertype), **NEURON_LAYER_STYLE) + node_label, **NEURON_LAYER_STYLE) else: + layer_style = LAYER_STYLE_DEFAULT + layer_style['fillcolor'] = choose_color_by_layertype(layertype) pydot_nodes[name + '_' + layertype] = pydot.Node( - '%s (%s)' % (name, layertype), **LAYER_STYLE) + node_label, **layer_style) for bottom_blob in layer.bottom: pydot_nodes[bottom_blob + '_blob'] = pydot.Node( '%s' % (bottom_blob), **BLOB_STYLE) - pydot_edges.append((bottom_blob + '_blob', name + '_' + layertype)) + edge_label = '""' + pydot_edges.append({'src': bottom_blob + '_blob', + 'dst': name + '_' + layertype, + 'label': edge_label}) for top_blob in layer.top: pydot_nodes[top_blob + '_blob'] = pydot.Node( '%s' % (top_blob)) - pydot_edges.append((name + '_' + layertype, top_blob + '_blob')) + if label_edges: + edge_label = determine_edge_label_by_layertype(layer, layertype) + else: + edge_label = '""' + pydot_edges.append({'src': name + '_' + layertype, + 'dst': top_blob + '_blob', + 'label': edge_label}) # Now, add the nodes and edges to the graph. for node in pydot_nodes.values(): pydot_graph.add_node(node) for edge in pydot_edges: pydot_graph.add_edge( - pydot.Edge(pydot_nodes[edge[0]], pydot_nodes[edge[1]])) + pydot.Edge(pydot_nodes[edge['src']], pydot_nodes[edge['dst']], + label=edge['label'])) return pydot_graph -def draw_net(caffe_net, ext='png'): +def draw_net(caffe_net, rankdir, ext='png'): """Draws a caffe net and returns the image string encoded using the given extension. @@ -64,13 +161,13 @@ def draw_net(caffe_net, ext='png'): caffe_net: a caffe.proto.caffe_pb2.NetParameter protocol buffer. ext: the image extension. Default 'png'. """ - return get_pydot_graph(caffe_net).create(format=ext) + return get_pydot_graph(caffe_net, rankdir).create(format=ext) -def draw_net_to_file(caffe_net, filename): +def draw_net_to_file(caffe_net, filename, rankdir='LR'): """Draws a caffe net, and saves it to file using the format given as the file extension. Use '.raw' to output raw text that you can manually feed to graphviz to draw graphs. """ ext = filename[filename.rfind('.')+1:] with open(filename, 'wb') as fid: - fid.write(draw_net(caffe_net, ext)) + fid.write(draw_net(caffe_net, rankdir, ext)) diff --git a/python/draw_net.py b/python/draw_net.py index ba488294275..4457b793e86 100755 --- a/python/draw_net.py +++ b/python/draw_net.py @@ -2,24 +2,43 @@ """ Draw a graph of the net architecture. """ -import os +import argparse from google.protobuf import text_format -import caffe, caffe.draw +import caffe +import caffe.draw from caffe.proto import caffe_pb2 -def main(argv): - if len(argv) != 3: - print 'Usage: %s input_net_proto_file output_image_file' % \ - os.path.basename(sys.argv[0]) - else: - net = caffe_pb2.NetParameter() - text_format.Merge(open(sys.argv[1]).read(), net) - print 'Drawing net to %s' % sys.argv[2] - caffe.draw.draw_net_to_file(net, sys.argv[2]) +def parse_args(): + """Parse input arguments + """ + + parser = argparse.ArgumentParser(description='Draw a network graph') + + parser.add_argument('input_net_proto_file', + help='Input network prototxt file') + parser.add_argument('output_image_file', + help='Output image file') + parser.add_argument('--rankdir', + help=('One of TB (top-bottom, i.e., vertical), ' + 'RL (right-left, i.e., horizontal), or another' + 'valid dot option; see' + 'http://www.graphviz.org/doc/info/attrs.html#k:rankdir' + '(default: LR)'), + default='LR') + + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + net = caffe_pb2.NetParameter() + text_format.Merge(open(args.input_net_proto_file).read(), net) + print 'Drawing net to %s' % args.output_image_file + caffe.draw.draw_net_to_file(net, args.output_image_file, args.rankdir) if __name__ == '__main__': - import sys - main(sys.argv) + main() From 957318783d1aa3396a1b70755aac6de3639e6ab3 Mon Sep 17 00:00:00 2001 From: Jonathan Ho Date: Wed, 10 Dec 2014 18:27:56 -0800 Subject: [PATCH 175/798] Check input line count in HDF5 data layer --- src/caffe/layers/hdf5_data_layer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index f6865efe78e..706c4a18319 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -75,6 +75,8 @@ void HDF5DataLayer::LayerSetUp(const vector*>& bottom, num_files_ = hdf_filenames_.size(); current_file_ = 0; LOG(INFO) << "Number of HDF5 files: " << num_files_; + CHECK_GE(num_files_, 1) << "Must have at least 1 HDF5 filename listed in " + << source; // Load the first HDF5 file and initialize the line counter. LoadHDF5FileData(hdf_filenames_[current_file_].c_str()); From 0a56995d3df9b442d457f2187d842e3b8d5c2a45 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 16 Dec 2014 01:52:43 -0800 Subject: [PATCH 176/798] remove extra blank line --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 1e70c2d5c6e..b19555fe962 100644 --- a/Makefile +++ b/Makefile @@ -498,7 +498,6 @@ $(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(DYNAMIC_NA -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(LIB_BUILD_DIR) @ echo - $(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(STATIC_NAME) \ | $(TEST_BIN_DIR) $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ From f519338c5e38f29bb8f02d59b945cc3af73d828b Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 23 Nov 2014 22:35:46 -0800 Subject: [PATCH 177/798] consolidate build rules for object files --- Makefile | 77 ++++++++------------------------------------------------ 1 file changed, 10 insertions(+), 67 deletions(-) diff --git a/Makefile b/Makefile index b19555fe962..da8a4d81921 100644 --- a/Makefile +++ b/Makefile @@ -472,15 +472,20 @@ $(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) ar rcs $@ $(OBJS) @ echo -$(TEST_BUILD_DIR)/%.o: src/$(PROJECT)/test/%.cpp $(HXX_SRCS) $(TEST_HXX_SRCS) \ - | $(TEST_BUILD_DIR) +$(BUILD_DIR)/%.o: %.cpp $(HXX_SRCS) | $(ALL_BUILD_DIRS) $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ || (cat $@.$(WARNS_EXT); exit 1) @ cat $@.$(WARNS_EXT) @ echo -$(TEST_BUILD_DIR)/%.cuo: src/$(PROJECT)/test/%.cu $(HXX_SRCS) $(TEST_HXX_SRCS) \ - | $(TEST_BUILD_DIR) +$(PROTO_BUILD_DIR)/%.pb.o: $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_GEN_HEADER) \ + | $(PROTO_BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ + || (cat $@.$(WARNS_EXT); exit 1) + @ cat $@.$(WARNS_EXT) + @ echo + +$(BUILD_DIR)/%.cuo: %.cu $(HXX_SRCS) | $(ALL_BUILD_DIRS) $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \ || (cat $@.$(WARNS_EXT); exit 1) @ cat $@.$(WARNS_EXT) @@ -515,72 +520,10 @@ $(TOOL_BUILD_DIR)/%: $(TOOL_BUILD_DIR)/%.bin | $(TOOL_BUILD_DIR) @ $(RM) $@ @ ln -s $(abspath $<) $@ -$(TOOL_BINS): %.bin : %.o $(STATIC_NAME) +$(TOOL_BINS) $(EXAMPLE_BINS): %.bin : %.o $(STATIC_NAME) $(CXX) $< $(STATIC_LINK_COMMAND) -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo -$(EXAMPLE_BINS): %.bin : %.o $(STATIC_NAME) - $(CXX) $< $(STATIC_LINK_COMMAND) -o $@ $(LINKFLAGS) $(LDFLAGS) - @ echo - -$(LAYER_BUILD_DIR)/%.o: src/$(PROJECT)/layers/%.cpp $(HXX_SRCS) \ - | $(LAYER_BUILD_DIR) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - -$(PROTO_BUILD_DIR)/%.pb.o: $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_GEN_HEADER) \ - | $(PROTO_BUILD_DIR) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - -$(UTIL_BUILD_DIR)/%.o: src/$(PROJECT)/util/%.cpp $(HXX_SRCS) | $(UTIL_BUILD_DIR) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - -$(GTEST_OBJ): $(GTEST_SRC) | $(GTEST_BUILD_DIR) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - -$(LAYER_BUILD_DIR)/%.cuo: src/$(PROJECT)/layers/%.cu $(HXX_SRCS) \ - | $(LAYER_BUILD_DIR) - $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - -$(UTIL_BUILD_DIR)/%.cuo: src/$(PROJECT)/util/%.cu | $(UTIL_BUILD_DIR) - $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - -$(TOOL_BUILD_DIR)/%.o: tools/%.cpp $(PROTO_GEN_HEADER) | $(TOOL_BUILD_DIR) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - -$(EXAMPLE_BUILD_DIR)/%.o: examples/%.cpp $(PROTO_GEN_HEADER) \ - | $(EXAMPLE_BUILD_DIRS) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - -$(BUILD_DIR)/src/$(PROJECT)/%.o: src/$(PROJECT)/%.cpp $(HXX_SRCS) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ - || (cat $@.$(WARNS_EXT); exit 1) - @ cat $@.$(WARNS_EXT) - @ echo - proto: $(PROTO_GEN_CC) $(PROTO_GEN_HEADER) $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_BUILD_DIR)/%.pb.h : \ From 89f7019acef532064f0897ceb45d2ed37a6bd608 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 24 Nov 2014 00:10:35 -0800 Subject: [PATCH 178/798] automatic discovery of source directories --- Makefile | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index da8a4d81921..e5a4b5ee40c 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,10 @@ else OTHER_BUILD_DIR := $(DEBUG_BUILD_DIR) endif +# All of the directories containing code. +SRC_DIRS := $(shell find * -type d -exec bash -c "find {} -maxdepth 1 \ + \( -name '*.cpp' -o -name '*.proto' \) | grep -q ." \; -print) + # The target shared library name LIB_BUILD_DIR := $(BUILD_DIR)/lib STATIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).a @@ -98,9 +102,6 @@ PROTO_GEN_PY := $(foreach file,${PROTO_SRCS:.proto=_pb2.py}, \ CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o}) CU_OBJS := $(addprefix $(BUILD_DIR)/, ${CU_SRCS:.cu=.cuo}) PROTO_OBJS := ${PROTO_GEN_CC:.cc=.o} -OBJ_BUILD_DIR := $(BUILD_DIR)/src/$(PROJECT) -LAYER_BUILD_DIR := $(OBJ_BUILD_DIR)/layers -UTIL_BUILD_DIR := $(OBJ_BUILD_DIR)/util OBJS := $(PROTO_OBJS) $(CXX_OBJS) $(CU_OBJS) # tool, example, and test objects TOOL_OBJS := $(addprefix $(BUILD_DIR)/, ${TOOL_SRCS:.cpp=.o}) @@ -110,11 +111,7 @@ TEST_CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${TEST_SRCS:.cpp=.o}) TEST_CU_OBJS := $(addprefix $(BUILD_DIR)/, ${TEST_CU_SRCS:.cu=.cuo}) TEST_OBJS := $(TEST_CXX_OBJS) $(TEST_CU_OBJS) GTEST_OBJ := $(addprefix $(BUILD_DIR)/, ${GTEST_SRC:.cpp=.o}) -GTEST_BUILD_DIR := $(dir $(GTEST_OBJ)) EXAMPLE_OBJS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o}) -EXAMPLE_BUILD_DIR := $(BUILD_DIR)/examples -EXAMPLE_BUILD_DIRS := $(EXAMPLE_BUILD_DIR) -EXAMPLE_BUILD_DIRS += $(foreach obj,$(EXAMPLE_OBJS),$(dir $(obj))) # tool, example, and test bins TOOL_BINS := ${TOOL_OBJS:.o=.bin} EXAMPLE_BINS := ${EXAMPLE_OBJS:.o=.bin} @@ -183,14 +180,9 @@ ifneq ($(strip $(DISTRIBUTE_DIR)),distribute) DIST_ALIASES += distribute endif -ALL_BUILD_DIRS := $(sort \ - $(BUILD_DIR) $(LIB_BUILD_DIR) $(OBJ_BUILD_DIR) \ - $(LAYER_BUILD_DIR) $(UTIL_BUILD_DIR) $(TOOL_BUILD_DIR) \ - $(TEST_BUILD_DIR) $(TEST_BIN_DIR) $(GTEST_BUILD_DIR) \ - $(EXAMPLE_BUILD_DIRS) \ - $(LINT_OUTPUT_DIR) \ - $(PROTO_BUILD_DIR) $(PROTO_BUILD_INCLUDE_DIR) $(PY_PROTO_BUILD_DIR) \ - $(DISTRIBUTE_SUBDIRS)) +ALL_BUILD_DIRS := $(sort $(BUILD_DIR) $(addprefix $(BUILD_DIR)/, $(SRC_DIRS)) \ + $(LIB_BUILD_DIR) $(TEST_BIN_DIR) $(PY_PROTO_BUILD_DIR) $(LINT_OUTPUT_DIR) \ + $(DISTRIBUTE_SUBDIRS) $(PROTO_BUILD_INCLUDE_DIR)) ############################## # Set directory for Doxygen-generated documentation From 492f67c4084fd173f6592b69903491f7e47edbfb Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Wed, 10 Dec 2014 23:37:42 -0800 Subject: [PATCH 179/798] move cuda output from build/.../.cuo -> build/cuda/.../.o This will allow nvcc's -M dependency generation option to work harmoniously, since it assumes that output will have a .o extension. --- Makefile | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index e5a4b5ee40c..54d5636135d 100644 --- a/Makefile +++ b/Makefile @@ -100,15 +100,16 @@ PROTO_GEN_PY := $(foreach file,${PROTO_SRCS:.proto=_pb2.py}, \ # These objects will be linked into the final shared library, so we # exclude the tool, example, and test objects. CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o}) -CU_OBJS := $(addprefix $(BUILD_DIR)/, ${CU_SRCS:.cu=.cuo}) +CU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o}) PROTO_OBJS := ${PROTO_GEN_CC:.cc=.o} OBJS := $(PROTO_OBJS) $(CXX_OBJS) $(CU_OBJS) # tool, example, and test objects TOOL_OBJS := $(addprefix $(BUILD_DIR)/, ${TOOL_SRCS:.cpp=.o}) TOOL_BUILD_DIR := $(BUILD_DIR)/tools -TEST_BUILD_DIR := $(BUILD_DIR)/src/$(PROJECT)/test +TEST_CXX_BUILD_DIR := $(BUILD_DIR)/src/$(PROJECT)/test +TEST_CU_BUILD_DIR := $(BUILD_DIR)/cuda/src/$(PROJECT)/test TEST_CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${TEST_SRCS:.cpp=.o}) -TEST_CU_OBJS := $(addprefix $(BUILD_DIR)/, ${TEST_CU_SRCS:.cu=.cuo}) +TEST_CU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${TEST_CU_SRCS:.cu=.o}) TEST_OBJS := $(TEST_CXX_OBJS) $(TEST_CU_OBJS) GTEST_OBJ := $(addprefix $(BUILD_DIR)/, ${GTEST_SRC:.cpp=.o}) EXAMPLE_OBJS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o}) @@ -134,11 +135,11 @@ TEST_ALL_DYNLINK_BIN := $(TEST_BIN_DIR)/test_all_dynamic_link.testbin ############################## WARNS_EXT := warnings.txt CXX_WARNS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o.$(WARNS_EXT)}) -CU_WARNS := $(addprefix $(BUILD_DIR)/, ${CU_SRCS:.cu=.cuo.$(WARNS_EXT)}) +CU_WARNS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o.$(WARNS_EXT)}) TOOL_WARNS := $(addprefix $(BUILD_DIR)/, ${TOOL_SRCS:.cpp=.o.$(WARNS_EXT)}) EXAMPLE_WARNS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o.$(WARNS_EXT)}) TEST_WARNS := $(addprefix $(BUILD_DIR)/, ${TEST_SRCS:.cpp=.o.$(WARNS_EXT)}) -TEST_CU_WARNS := $(addprefix $(BUILD_DIR)/, ${TEST_CU_SRCS:.cu=.cuo.$(WARNS_EXT)}) +TEST_CU_WARNS := $(addprefix $(BUILD_DIR)/cuda/, ${TEST_CU_SRCS:.cu=.o.$(WARNS_EXT)}) ALL_CXX_WARNS := $(CXX_WARNS) $(TOOL_WARNS) $(EXAMPLE_WARNS) $(TEST_WARNS) ALL_CU_WARNS := $(CU_WARNS) $(TEST_CU_WARNS) ALL_WARNS := $(ALL_CXX_WARNS) $(ALL_CU_WARNS) @@ -181,6 +182,7 @@ ifneq ($(strip $(DISTRIBUTE_DIR)),distribute) endif ALL_BUILD_DIRS := $(sort $(BUILD_DIR) $(addprefix $(BUILD_DIR)/, $(SRC_DIRS)) \ + $(addprefix $(BUILD_DIR)/cuda/, $(SRC_DIRS)) \ $(LIB_BUILD_DIR) $(TEST_BIN_DIR) $(PY_PROTO_BUILD_DIR) $(LINT_OUTPUT_DIR) \ $(DISTRIBUTE_SUBDIRS) $(PROTO_BUILD_INCLUDE_DIR)) @@ -437,9 +439,7 @@ $(EMPTY_WARN_REPORT): $(ALL_WARNS) | $(BUILD_DIR) $(RM) $(NONEMPTY_WARN_REPORT); \ echo "No compiler warnings!"; -$(ALL_CXX_WARNS): %.o.$(WARNS_EXT) : %.o - -$(ALL_CU_WARNS): %.cuo.$(WARNS_EXT) : %.cuo +$(ALL_WARNS): %.o.$(WARNS_EXT) : %.o $(BUILD_DIR_LINK): $(BUILD_DIR)/.linked @@ -495,14 +495,14 @@ $(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(DYNAMIC_NA -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(LIB_BUILD_DIR) @ echo -$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.cuo $(GTEST_OBJ) $(STATIC_NAME) \ - | $(TEST_BIN_DIR) +$(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CU_BUILD_DIR)/%.o \ + $(GTEST_OBJ) $(STATIC_NAME) | $(TEST_BIN_DIR) $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo -$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.o $(GTEST_OBJ) $(STATIC_NAME) \ - | $(TEST_BIN_DIR) +$(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CXX_BUILD_DIR)/%.o \ + $(GTEST_OBJ) $(STATIC_NAME) | $(TEST_BIN_DIR) $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) @ echo From da18d318f4d99036a61fa6c3d843eb43827268b8 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 16 Dec 2014 20:18:53 -0800 Subject: [PATCH 180/798] check host malloc result --- include/caffe/syncedmem.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/caffe/syncedmem.hpp b/include/caffe/syncedmem.hpp index db8d0e80e12..2564e0716ef 100644 --- a/include/caffe/syncedmem.hpp +++ b/include/caffe/syncedmem.hpp @@ -24,6 +24,7 @@ namespace caffe { inline void CaffeMallocHost(void** ptr, size_t size) { *ptr = malloc(size); + CHECK(*ptr) << "host allocation of size " << size << " failed"; } inline void CaffeFreeHost(void* ptr) { From 8d3e46dda3783ba451942bf9708a6c1ef52ce9ff Mon Sep 17 00:00:00 2001 From: Thomas Schenker Date: Wed, 10 Dec 2014 16:16:34 +0100 Subject: [PATCH 181/798] Add CHECKs to prevent segfault for incorrect IMAGE_DATA layers. Incomplete IMAGE_DATA layers cause a segmentation fault, e.g.: layers { name: "mnist" type: IMAGE_DATA top: "data" top: "label" image_data_param { batch_size: 100 } include: { phase: TRAIN } } or layers { name: "mnist" type: IMAGE_DATA top: "data" top: "label" data_param { source: "./data/train.txt" batch_size: 100 } include: { phase: TRAIN } } Also empty image list files cause a segfault. This is fixed by adding 3 CHECK instructions. --- src/caffe/layers/image_data_layer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index e4a575bec93..b5a34ff81aa 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -27,8 +27,11 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, "new_height and new_width to be set at the same time."; // Read the file with filenames and labels const string& source = this->layer_param_.image_data_param().source(); + CHECK_GT(source.size(), 0); LOG(INFO) << "Opening file " << source; std::ifstream infile(source.c_str()); + CHECK(infile.good()) + << "Could not open image list (filename: \""+ source + "\")"; string filename; int label; while (infile >> filename >> label) { @@ -53,6 +56,8 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, CHECK_GT(lines_.size(), skip) << "Not enough points to skip"; lines_id_ = skip; } + CHECK(!lines_.empty()) + << "Image list is empty (filename: \"" + source + "\")"; // Read a data point, and use it to initialize the top blob. Datum datum; CHECK(ReadImageToDatum(lines_[lines_id_].first, lines_[lines_id_].second, From 555f4d3b7cf9d5db73b983c3757474deced0abfa Mon Sep 17 00:00:00 2001 From: Kyle Krafka Date: Sat, 20 Dec 2014 23:02:19 -0500 Subject: [PATCH 182/798] Use valid MathJax delimiters. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MathJax does not support $ as a delimiter by default, so math was not displayed properly on the “Forward and Backward” page. --- docs/tutorial/forward_backward.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/forward_backward.md b/docs/tutorial/forward_backward.md index f58b9cac19e..a645f002f61 100644 --- a/docs/tutorial/forward_backward.md +++ b/docs/tutorial/forward_backward.md @@ -15,7 +15,7 @@ This pass goes from bottom to top. Forward pass -The data $x$ is passed through an inner product layer for $g(x)$ then through a softmax for $h(g(x))$ and softmax loss to give $f_W(x)$. +The data $$x$$ is passed through an inner product layer for $$g(x)$$ then through a softmax for $$h(g(x))$$ and softmax loss to give $$f_W(x)$$. The **backward** pass computes the gradient given the loss for learning. In backward Caffe reverse-composes the gradient of each layer to compute the gradient of the whole model by automatic differentiation. @@ -24,7 +24,7 @@ This pass goes from top to bottom. Backward pass -The backward pass begins with the loss and computes the gradient with respect to the output $\frac{\partial f_W}{\partial h}$. The gradient with respect to the rest of the model is computed layer-by-layer through the chain rule. Layers with parameters, like the `INNER_PRODUCT` layer, compute the gradient with respect to their parameters $\frac{\partial f_W}{\partial W_{\text{ip}}}$ during the backward step. +The backward pass begins with the loss and computes the gradient with respect to the output $$\frac{\partial f_W}{\partial h}$$. The gradient with respect to the rest of the model is computed layer-by-layer through the chain rule. Layers with parameters, like the `INNER_PRODUCT` layer, compute the gradient with respect to their parameters $$\frac{\partial f_W}{\partial W_{\text{ip}}}$$ during the backward step. These computations follow immediately from defining the model: Caffe plans and carries out the forward and backward passes for you. From 3855ad574c89847552705cd1ceb70dd5e8687c4d Mon Sep 17 00:00:00 2001 From: Kyle Krafka Date: Sat, 20 Dec 2014 23:34:51 -0500 Subject: [PATCH 183/798] Fix minor typos in strings. --- tools/caffe.cpp | 2 +- tools/convert_imageset.cpp | 2 +- tools/extract_features.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/caffe.cpp b/tools/caffe.cpp index c8c8c1a6b4c..046b38938e4 100644 --- a/tools/caffe.cpp +++ b/tools/caffe.cpp @@ -21,7 +21,7 @@ DEFINE_int32(gpu, -1, DEFINE_string(solver, "", "The solver definition protocol buffer text file."); DEFINE_string(model, "", - "The model definition protocol buffer text file.."); + "The model definition protocol buffer text file."); DEFINE_string(snapshot, "", "Optional; the snapshot solver state to resume training."); DEFINE_string(weights, "", diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 7e1e83d9d0c..09e84d6b3ef 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -112,7 +112,7 @@ int main(int argc, char** argv) { CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS) << "mdb_txn_begin failed"; CHECK_EQ(mdb_open(mdb_txn, NULL, 0, &mdb_dbi), MDB_SUCCESS) - << "mdb_open failed. Does the lmdb already exist? "; + << "mdb_open failed. Does the lmdb already exist?"; } else { LOG(FATAL) << "Unknown db backend " << db_backend; } diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index 49e8f98971c..cb48c4796b9 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -131,7 +131,7 @@ int feature_extraction_pipeline(int argc, char** argv) { int num_mini_batches = atoi(argv[++arg_pos]); - LOG(ERROR)<< "Extacting Features"; + LOG(ERROR)<< "Extracting Features"; Datum datum; vector > feature_batches( From f15210cdc8f0e9b2e5866972ab81149ac68e96c6 Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 2 Dec 2014 13:10:57 -0800 Subject: [PATCH 184/798] Added bvlc_googlenet prototxt and weights --- models/bvlc_googlenet/deploy.prototxt | 1924 ++++++++++++++++ models/bvlc_googlenet/quick_solver.prototxt | 15 + models/bvlc_googlenet/readme.md | 33 + models/bvlc_googlenet/solver.prototxt | 16 + models/bvlc_googlenet/train_val.prototxt | 2240 +++++++++++++++++++ 5 files changed, 4228 insertions(+) create mode 100644 models/bvlc_googlenet/deploy.prototxt create mode 100644 models/bvlc_googlenet/quick_solver.prototxt create mode 100644 models/bvlc_googlenet/readme.md create mode 100644 models/bvlc_googlenet/solver.prototxt create mode 100644 models/bvlc_googlenet/train_val.prototxt diff --git a/models/bvlc_googlenet/deploy.prototxt b/models/bvlc_googlenet/deploy.prototxt new file mode 100644 index 00000000000..e31a4c9cd00 --- /dev/null +++ b/models/bvlc_googlenet/deploy.prototxt @@ -0,0 +1,1924 @@ +name: "GoogleNet" +input: "data" +input_dim: 10 +input_dim: 3 +input_dim: 224 +input_dim: 224 +layers { + bottom: "data" + top: "conv1/7x7_s2" + name: "conv1/7x7_s2" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 3 + kernel_size: 7 + stride: 2 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv1/7x7_s2" + top: "conv1/7x7_s2" + name: "conv1/relu_7x7" + type: RELU +} +layers { + bottom: "conv1/7x7_s2" + top: "pool1/3x3_s2" + name: "pool1/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool1/3x3_s2" + top: "pool1/norm1" + name: "pool1/norm1" + type: LRN + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + bottom: "pool1/norm1" + top: "conv2/3x3_reduce" + name: "conv2/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv2/3x3_reduce" + top: "conv2/3x3_reduce" + name: "conv2/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "conv2/3x3_reduce" + top: "conv2/3x3" + name: "conv2/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv2/3x3" + top: "conv2/3x3" + name: "conv2/relu_3x3" + type: RELU +} +layers { + bottom: "conv2/3x3" + top: "conv2/norm2" + name: "conv2/norm2" + type: LRN + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + bottom: "conv2/norm2" + top: "pool2/3x3_s2" + name: "pool2/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/1x1" + name: "inception_3a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/1x1" + top: "inception_3a/1x1" + name: "inception_3a/relu_1x1" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/3x3_reduce" + name: "inception_3a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3_reduce" + name: "inception_3a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3" + name: "inception_3a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/3x3" + top: "inception_3a/3x3" + name: "inception_3a/relu_3x3" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/5x5_reduce" + name: "inception_3a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5_reduce" + name: "inception_3a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5" + name: "inception_3a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/5x5" + top: "inception_3a/5x5" + name: "inception_3a/relu_5x5" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/pool" + name: "inception_3a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_3a/pool" + top: "inception_3a/pool_proj" + name: "inception_3a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/pool_proj" + top: "inception_3a/pool_proj" + name: "inception_3a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_3a/1x1" + bottom: "inception_3a/3x3" + bottom: "inception_3a/5x5" + bottom: "inception_3a/pool_proj" + top: "inception_3a/output" + name: "inception_3a/output" + type: CONCAT +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/1x1" + name: "inception_3b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/1x1" + top: "inception_3b/1x1" + name: "inception_3b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/3x3_reduce" + name: "inception_3b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3_reduce" + name: "inception_3b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3" + name: "inception_3b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/3x3" + top: "inception_3b/3x3" + name: "inception_3b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/5x5_reduce" + name: "inception_3b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5_reduce" + name: "inception_3b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5" + name: "inception_3b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/5x5" + top: "inception_3b/5x5" + name: "inception_3b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/pool" + name: "inception_3b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_3b/pool" + top: "inception_3b/pool_proj" + name: "inception_3b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/pool_proj" + top: "inception_3b/pool_proj" + name: "inception_3b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_3b/1x1" + bottom: "inception_3b/3x3" + bottom: "inception_3b/5x5" + bottom: "inception_3b/pool_proj" + top: "inception_3b/output" + name: "inception_3b/output" + type: CONCAT +} +layers { + bottom: "inception_3b/output" + top: "pool3/3x3_s2" + name: "pool3/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/1x1" + name: "inception_4a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/1x1" + top: "inception_4a/1x1" + name: "inception_4a/relu_1x1" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/3x3_reduce" + name: "inception_4a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3_reduce" + name: "inception_4a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3" + name: "inception_4a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 208 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/3x3" + top: "inception_4a/3x3" + name: "inception_4a/relu_3x3" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/5x5_reduce" + name: "inception_4a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5_reduce" + name: "inception_4a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5" + name: "inception_4a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 48 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/5x5" + top: "inception_4a/5x5" + name: "inception_4a/relu_5x5" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/pool" + name: "inception_4a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4a/pool" + top: "inception_4a/pool_proj" + name: "inception_4a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/pool_proj" + top: "inception_4a/pool_proj" + name: "inception_4a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4a/1x1" + bottom: "inception_4a/3x3" + bottom: "inception_4a/5x5" + bottom: "inception_4a/pool_proj" + top: "inception_4a/output" + name: "inception_4a/output" + type: CONCAT +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/1x1" + name: "inception_4b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/1x1" + top: "inception_4b/1x1" + name: "inception_4b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/3x3_reduce" + name: "inception_4b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3_reduce" + name: "inception_4b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3" + name: "inception_4b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 224 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/3x3" + top: "inception_4b/3x3" + name: "inception_4b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/5x5_reduce" + name: "inception_4b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5_reduce" + name: "inception_4b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5" + name: "inception_4b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/5x5" + top: "inception_4b/5x5" + name: "inception_4b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/pool" + name: "inception_4b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4b/pool" + top: "inception_4b/pool_proj" + name: "inception_4b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/pool_proj" + top: "inception_4b/pool_proj" + name: "inception_4b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4b/1x1" + bottom: "inception_4b/3x3" + bottom: "inception_4b/5x5" + bottom: "inception_4b/pool_proj" + top: "inception_4b/output" + name: "inception_4b/output" + type: CONCAT +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/1x1" + name: "inception_4c/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/1x1" + top: "inception_4c/1x1" + name: "inception_4c/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/3x3_reduce" + name: "inception_4c/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3_reduce" + name: "inception_4c/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3" + name: "inception_4c/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/3x3" + top: "inception_4c/3x3" + name: "inception_4c/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/5x5_reduce" + name: "inception_4c/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5_reduce" + name: "inception_4c/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5" + name: "inception_4c/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/5x5" + top: "inception_4c/5x5" + name: "inception_4c/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/pool" + name: "inception_4c/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4c/pool" + top: "inception_4c/pool_proj" + name: "inception_4c/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/pool_proj" + top: "inception_4c/pool_proj" + name: "inception_4c/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4c/1x1" + bottom: "inception_4c/3x3" + bottom: "inception_4c/5x5" + bottom: "inception_4c/pool_proj" + top: "inception_4c/output" + name: "inception_4c/output" + type: CONCAT +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/1x1" + name: "inception_4d/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/1x1" + top: "inception_4d/1x1" + name: "inception_4d/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/3x3_reduce" + name: "inception_4d/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 144 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3_reduce" + name: "inception_4d/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3" + name: "inception_4d/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 288 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/3x3" + top: "inception_4d/3x3" + name: "inception_4d/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/5x5_reduce" + name: "inception_4d/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5_reduce" + name: "inception_4d/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5" + name: "inception_4d/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/5x5" + top: "inception_4d/5x5" + name: "inception_4d/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/pool" + name: "inception_4d/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4d/pool" + top: "inception_4d/pool_proj" + name: "inception_4d/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/pool_proj" + top: "inception_4d/pool_proj" + name: "inception_4d/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4d/1x1" + bottom: "inception_4d/3x3" + bottom: "inception_4d/5x5" + bottom: "inception_4d/pool_proj" + top: "inception_4d/output" + name: "inception_4d/output" + type: CONCAT +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/1x1" + name: "inception_4e/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/1x1" + top: "inception_4e/1x1" + name: "inception_4e/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/3x3_reduce" + name: "inception_4e/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3_reduce" + name: "inception_4e/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3" + name: "inception_4e/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/3x3" + top: "inception_4e/3x3" + name: "inception_4e/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/5x5_reduce" + name: "inception_4e/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5_reduce" + name: "inception_4e/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5" + name: "inception_4e/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/5x5" + top: "inception_4e/5x5" + name: "inception_4e/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/pool" + name: "inception_4e/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4e/pool" + top: "inception_4e/pool_proj" + name: "inception_4e/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/pool_proj" + top: "inception_4e/pool_proj" + name: "inception_4e/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4e/1x1" + bottom: "inception_4e/3x3" + bottom: "inception_4e/5x5" + bottom: "inception_4e/pool_proj" + top: "inception_4e/output" + name: "inception_4e/output" + type: CONCAT +} +layers { + bottom: "inception_4e/output" + top: "pool4/3x3_s2" + name: "pool4/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/1x1" + name: "inception_5a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/1x1" + top: "inception_5a/1x1" + name: "inception_5a/relu_1x1" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/3x3_reduce" + name: "inception_5a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3_reduce" + name: "inception_5a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3" + name: "inception_5a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/3x3" + top: "inception_5a/3x3" + name: "inception_5a/relu_3x3" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/5x5_reduce" + name: "inception_5a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5_reduce" + name: "inception_5a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5" + name: "inception_5a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/5x5" + top: "inception_5a/5x5" + name: "inception_5a/relu_5x5" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/pool" + name: "inception_5a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_5a/pool" + top: "inception_5a/pool_proj" + name: "inception_5a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/pool_proj" + top: "inception_5a/pool_proj" + name: "inception_5a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_5a/1x1" + bottom: "inception_5a/3x3" + bottom: "inception_5a/5x5" + bottom: "inception_5a/pool_proj" + top: "inception_5a/output" + name: "inception_5a/output" + type: CONCAT +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/1x1" + name: "inception_5b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/1x1" + top: "inception_5b/1x1" + name: "inception_5b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/3x3_reduce" + name: "inception_5b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3_reduce" + name: "inception_5b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3" + name: "inception_5b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/3x3" + top: "inception_5b/3x3" + name: "inception_5b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/5x5_reduce" + name: "inception_5b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 48 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5_reduce" + name: "inception_5b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5" + name: "inception_5b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/5x5" + top: "inception_5b/5x5" + name: "inception_5b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/pool" + name: "inception_5b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_5b/pool" + top: "inception_5b/pool_proj" + name: "inception_5b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/pool_proj" + top: "inception_5b/pool_proj" + name: "inception_5b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_5b/1x1" + bottom: "inception_5b/3x3" + bottom: "inception_5b/5x5" + bottom: "inception_5b/pool_proj" + top: "inception_5b/output" + name: "inception_5b/output" + type: CONCAT +} +layers { + bottom: "inception_5b/output" + top: "pool5/7x7_s1" + name: "pool5/7x7_s1" + type: POOLING + pooling_param { + pool: AVE + kernel_size: 7 + stride: 1 + } +} +layers { + bottom: "pool5/7x7_s1" + top: "pool5/7x7_s1" + name: "pool5/drop_7x7_s1" + type: DROPOUT + dropout_param { + dropout_ratio: 0.4 + } +} +layers { + bottom: "pool5/7x7_s1" + top: "loss3/classifier" + name: "loss3/classifier" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + name: "prob" + type: SOFTMAX + bottom: "loss3/classifier" + top: "prob" +} \ No newline at end of file diff --git a/models/bvlc_googlenet/quick_solver.prototxt b/models/bvlc_googlenet/quick_solver.prototxt new file mode 100644 index 00000000000..5d2f7ee70b9 --- /dev/null +++ b/models/bvlc_googlenet/quick_solver.prototxt @@ -0,0 +1,15 @@ +net: "models/bvlc_googlenet/train_val.prototxt" +test_iter: 1000 +test_interval: 4000 +test_initialization: false +display: 40 +average_loss: 40 +base_lr: 0.01 +lr_policy: "poly" +power: 0.5 +max_iter: 2400000 +momentum: 0.9 +weight_decay: 0.0002 +snapshot: 40000 +snapshot_prefix: "models/bvlc_googlenet/bvlc_googlenet_quick" +solver_mode: GPU diff --git a/models/bvlc_googlenet/readme.md b/models/bvlc_googlenet/readme.md new file mode 100644 index 00000000000..27022d3384a --- /dev/null +++ b/models/bvlc_googlenet/readme.md @@ -0,0 +1,33 @@ +--- +name: BVLC GoogleNet Model +caffemodel: bvlc_googlenet.caffemodel +caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel +license: non-commercial +sha1: 405fc5acd08a3bb12de8ee5e23a96bec22f08204 +caffe_commit: bc614d1bd91896e3faceaf40b23b72dab47d44f5 +--- + +This model is a replication of the model described in the [GoogleNet](http://arxiv.org/abs/1409.4842) publication. We would like to thank Christian Szegedy for all his help in the replication of GoogleNet model. + +Differences: +- not training with the relighting data-augmentation; +- not training with the scale or aspect-ratio data-augmentation; +- uses "xavier" to initialize the weights instead of "gaussian"; +- quick_solver.prototxt uses a different learning rate decay policy than the original solver.prototxt, that allows a much faster training (60 epochs vs 250 epochs); + +The bundled model is the iteration 2,400,000 snapshot (60 epochs) using quick_solver.prototxt + +This bundled model obtains a top-1 accuracy 68.7% (31.3% error) and a top-5 accuracy 88.9% (11.1% error) on the validation set, using just the center crop. +(Using the average of 10 crops, (4 + 1 center) * 2 mirror, should obtain a bit higher accuracy.) + +Timings for bvlc_googlenet with cuDNN using batch_size:128 on a K40c: + - Average Forward pass: 562.841 ms. + - Average Backward pass: 1123.84 ms. + - Average Forward-Backward: 1688.8 ms. + + +## License + +The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: +"Researcher shall use the Database only for non-commercial research and educational purposes." +Accordingly, this model is distributed under a non-commercial license. diff --git a/models/bvlc_googlenet/solver.prototxt b/models/bvlc_googlenet/solver.prototxt new file mode 100644 index 00000000000..d7d1788173c --- /dev/null +++ b/models/bvlc_googlenet/solver.prototxt @@ -0,0 +1,16 @@ +net: "models/bvlc_googlenet/train_val.prototxt" +test_iter: 1000 +test_interval: 4000 +test_initialization: false +display: 40 +average_loss: 40 +base_lr: 0.01 +lr_policy: "step" +stepsize: 320000 +gamma: 0.96 +max_iter: 10000000 +momentum: 0.9 +weight_decay: 0.0002 +snapshot: 40000 +snapshot_prefix: "models/bvlc_googlenet/bvlc_googlenet" +solver_mode: GPU diff --git a/models/bvlc_googlenet/train_val.prototxt b/models/bvlc_googlenet/train_val.prototxt new file mode 100644 index 00000000000..cd8f38abdc8 --- /dev/null +++ b/models/bvlc_googlenet/train_val.prototxt @@ -0,0 +1,2240 @@ +name: "GoogleNet" +layers { + top: "data" + top: "label" + name: "data" + type: DATA + data_param { + source: "examples/imagenet/ilsvrc12_train_lmdb" + batch_size: 32 + backend: LMDB + } + include { + phase: TRAIN + } + transform_param { + mirror: true + crop_size: 224 + mean_value: 104 + mean_value: 117 + mean_value: 123 + } +} +layers { + top: "data" + top: "label" + name: "data" + type: DATA + data_param { + source: "examples/imagenet/ilsvrc12_val_lmdb" + batch_size: 50 + backend: LMDB + } + include { + phase: TEST + } + transform_param { + mirror: false + crop_size: 224 + mean_value: 104 + mean_value: 117 + mean_value: 123 + } +} +layers { + bottom: "data" + top: "conv1/7x7_s2" + name: "conv1/7x7_s2" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 3 + kernel_size: 7 + stride: 2 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv1/7x7_s2" + top: "conv1/7x7_s2" + name: "conv1/relu_7x7" + type: RELU +} +layers { + bottom: "conv1/7x7_s2" + top: "pool1/3x3_s2" + name: "pool1/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool1/3x3_s2" + top: "pool1/norm1" + name: "pool1/norm1" + type: LRN + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + bottom: "pool1/norm1" + top: "conv2/3x3_reduce" + name: "conv2/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv2/3x3_reduce" + top: "conv2/3x3_reduce" + name: "conv2/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "conv2/3x3_reduce" + top: "conv2/3x3" + name: "conv2/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv2/3x3" + top: "conv2/3x3" + name: "conv2/relu_3x3" + type: RELU +} +layers { + bottom: "conv2/3x3" + top: "conv2/norm2" + name: "conv2/norm2" + type: LRN + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + bottom: "conv2/norm2" + top: "pool2/3x3_s2" + name: "pool2/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/1x1" + name: "inception_3a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/1x1" + top: "inception_3a/1x1" + name: "inception_3a/relu_1x1" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/3x3_reduce" + name: "inception_3a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3_reduce" + name: "inception_3a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3" + name: "inception_3a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/3x3" + top: "inception_3a/3x3" + name: "inception_3a/relu_3x3" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/5x5_reduce" + name: "inception_3a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5_reduce" + name: "inception_3a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5" + name: "inception_3a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/5x5" + top: "inception_3a/5x5" + name: "inception_3a/relu_5x5" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/pool" + name: "inception_3a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_3a/pool" + top: "inception_3a/pool_proj" + name: "inception_3a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/pool_proj" + top: "inception_3a/pool_proj" + name: "inception_3a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_3a/1x1" + bottom: "inception_3a/3x3" + bottom: "inception_3a/5x5" + bottom: "inception_3a/pool_proj" + top: "inception_3a/output" + name: "inception_3a/output" + type: CONCAT +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/1x1" + name: "inception_3b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/1x1" + top: "inception_3b/1x1" + name: "inception_3b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/3x3_reduce" + name: "inception_3b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3_reduce" + name: "inception_3b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3" + name: "inception_3b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/3x3" + top: "inception_3b/3x3" + name: "inception_3b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/5x5_reduce" + name: "inception_3b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5_reduce" + name: "inception_3b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5" + name: "inception_3b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/5x5" + top: "inception_3b/5x5" + name: "inception_3b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/pool" + name: "inception_3b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_3b/pool" + top: "inception_3b/pool_proj" + name: "inception_3b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/pool_proj" + top: "inception_3b/pool_proj" + name: "inception_3b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_3b/1x1" + bottom: "inception_3b/3x3" + bottom: "inception_3b/5x5" + bottom: "inception_3b/pool_proj" + top: "inception_3b/output" + name: "inception_3b/output" + type: CONCAT +} +layers { + bottom: "inception_3b/output" + top: "pool3/3x3_s2" + name: "pool3/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/1x1" + name: "inception_4a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/1x1" + top: "inception_4a/1x1" + name: "inception_4a/relu_1x1" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/3x3_reduce" + name: "inception_4a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3_reduce" + name: "inception_4a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3" + name: "inception_4a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 208 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/3x3" + top: "inception_4a/3x3" + name: "inception_4a/relu_3x3" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/5x5_reduce" + name: "inception_4a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5_reduce" + name: "inception_4a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5" + name: "inception_4a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 48 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/5x5" + top: "inception_4a/5x5" + name: "inception_4a/relu_5x5" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/pool" + name: "inception_4a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4a/pool" + top: "inception_4a/pool_proj" + name: "inception_4a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/pool_proj" + top: "inception_4a/pool_proj" + name: "inception_4a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4a/1x1" + bottom: "inception_4a/3x3" + bottom: "inception_4a/5x5" + bottom: "inception_4a/pool_proj" + top: "inception_4a/output" + name: "inception_4a/output" + type: CONCAT +} +layers { + bottom: "inception_4a/output" + top: "loss1/ave_pool" + name: "loss1/ave_pool" + type: POOLING + pooling_param { + pool: AVE + kernel_size: 5 + stride: 3 + } +} +layers { + bottom: "loss1/ave_pool" + top: "loss1/conv" + name: "loss1/conv" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.08 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "loss1/conv" + top: "loss1/conv" + name: "loss1/relu_conv" + type: RELU +} +layers { + bottom: "loss1/conv" + top: "loss1/fc" + name: "loss1/fc" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1024 + weight_filler { + type: "xavier" + std: 0.02 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "loss1/fc" + top: "loss1/fc" + name: "loss1/relu_fc" + type: RELU +} +layers { + bottom: "loss1/fc" + top: "loss1/fc" + name: "loss1/drop_fc" + type: DROPOUT + dropout_param { + dropout_ratio: 0.7 + } +} +layers { + bottom: "loss1/fc" + top: "loss1/classifier" + name: "loss1/classifier" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + std: 0.0009765625 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + bottom: "loss1/classifier" + bottom: "label" + top: "loss1/loss1" + name: "loss1/loss" + type: SOFTMAX_LOSS + loss_weight: 0.3 +} +layers { + bottom: "loss1/classifier" + bottom: "label" + top: "loss1/top-1" + name: "loss1/top-1" + type: ACCURACY + include { + phase: TEST + } +} +layers { + bottom: "loss1/classifier" + bottom: "label" + top: "loss1/top-5" + name: "loss1/top-5" + type: ACCURACY + accuracy_param { + top_k: 5 + } + include { + phase: TEST + } +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/1x1" + name: "inception_4b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/1x1" + top: "inception_4b/1x1" + name: "inception_4b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/3x3_reduce" + name: "inception_4b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3_reduce" + name: "inception_4b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3" + name: "inception_4b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 224 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/3x3" + top: "inception_4b/3x3" + name: "inception_4b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/5x5_reduce" + name: "inception_4b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5_reduce" + name: "inception_4b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5" + name: "inception_4b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/5x5" + top: "inception_4b/5x5" + name: "inception_4b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/pool" + name: "inception_4b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4b/pool" + top: "inception_4b/pool_proj" + name: "inception_4b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/pool_proj" + top: "inception_4b/pool_proj" + name: "inception_4b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4b/1x1" + bottom: "inception_4b/3x3" + bottom: "inception_4b/5x5" + bottom: "inception_4b/pool_proj" + top: "inception_4b/output" + name: "inception_4b/output" + type: CONCAT +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/1x1" + name: "inception_4c/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/1x1" + top: "inception_4c/1x1" + name: "inception_4c/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/3x3_reduce" + name: "inception_4c/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3_reduce" + name: "inception_4c/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3" + name: "inception_4c/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/3x3" + top: "inception_4c/3x3" + name: "inception_4c/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/5x5_reduce" + name: "inception_4c/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5_reduce" + name: "inception_4c/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5" + name: "inception_4c/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/5x5" + top: "inception_4c/5x5" + name: "inception_4c/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/pool" + name: "inception_4c/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4c/pool" + top: "inception_4c/pool_proj" + name: "inception_4c/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/pool_proj" + top: "inception_4c/pool_proj" + name: "inception_4c/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4c/1x1" + bottom: "inception_4c/3x3" + bottom: "inception_4c/5x5" + bottom: "inception_4c/pool_proj" + top: "inception_4c/output" + name: "inception_4c/output" + type: CONCAT +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/1x1" + name: "inception_4d/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/1x1" + top: "inception_4d/1x1" + name: "inception_4d/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/3x3_reduce" + name: "inception_4d/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 144 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3_reduce" + name: "inception_4d/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3" + name: "inception_4d/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 288 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/3x3" + top: "inception_4d/3x3" + name: "inception_4d/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/5x5_reduce" + name: "inception_4d/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5_reduce" + name: "inception_4d/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5" + name: "inception_4d/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/5x5" + top: "inception_4d/5x5" + name: "inception_4d/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/pool" + name: "inception_4d/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4d/pool" + top: "inception_4d/pool_proj" + name: "inception_4d/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/pool_proj" + top: "inception_4d/pool_proj" + name: "inception_4d/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4d/1x1" + bottom: "inception_4d/3x3" + bottom: "inception_4d/5x5" + bottom: "inception_4d/pool_proj" + top: "inception_4d/output" + name: "inception_4d/output" + type: CONCAT +} +layers { + bottom: "inception_4d/output" + top: "loss2/ave_pool" + name: "loss2/ave_pool" + type: POOLING + pooling_param { + pool: AVE + kernel_size: 5 + stride: 3 + } +} +layers { + bottom: "loss2/ave_pool" + top: "loss2/conv" + name: "loss2/conv" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.08 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "loss2/conv" + top: "loss2/conv" + name: "loss2/relu_conv" + type: RELU +} +layers { + bottom: "loss2/conv" + top: "loss2/fc" + name: "loss2/fc" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1024 + weight_filler { + type: "xavier" + std: 0.02 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "loss2/fc" + top: "loss2/fc" + name: "loss2/relu_fc" + type: RELU +} +layers { + bottom: "loss2/fc" + top: "loss2/fc" + name: "loss2/drop_fc" + type: DROPOUT + dropout_param { + dropout_ratio: 0.7 + } +} +layers { + bottom: "loss2/fc" + top: "loss2/classifier" + name: "loss2/classifier" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + std: 0.0009765625 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + bottom: "loss2/classifier" + bottom: "label" + top: "loss2/loss1" + name: "loss2/loss" + type: SOFTMAX_LOSS + loss_weight: 0.3 +} +layers { + bottom: "loss2/classifier" + bottom: "label" + top: "loss2/top-1" + name: "loss2/top-1" + type: ACCURACY + include { + phase: TEST + } +} +layers { + bottom: "loss2/classifier" + bottom: "label" + top: "loss2/top-5" + name: "loss2/top-5" + type: ACCURACY + accuracy_param { + top_k: 5 + } + include { + phase: TEST + } +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/1x1" + name: "inception_4e/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/1x1" + top: "inception_4e/1x1" + name: "inception_4e/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/3x3_reduce" + name: "inception_4e/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3_reduce" + name: "inception_4e/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3" + name: "inception_4e/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/3x3" + top: "inception_4e/3x3" + name: "inception_4e/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/5x5_reduce" + name: "inception_4e/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5_reduce" + name: "inception_4e/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5" + name: "inception_4e/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/5x5" + top: "inception_4e/5x5" + name: "inception_4e/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/pool" + name: "inception_4e/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4e/pool" + top: "inception_4e/pool_proj" + name: "inception_4e/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/pool_proj" + top: "inception_4e/pool_proj" + name: "inception_4e/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4e/1x1" + bottom: "inception_4e/3x3" + bottom: "inception_4e/5x5" + bottom: "inception_4e/pool_proj" + top: "inception_4e/output" + name: "inception_4e/output" + type: CONCAT +} +layers { + bottom: "inception_4e/output" + top: "pool4/3x3_s2" + name: "pool4/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/1x1" + name: "inception_5a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/1x1" + top: "inception_5a/1x1" + name: "inception_5a/relu_1x1" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/3x3_reduce" + name: "inception_5a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3_reduce" + name: "inception_5a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3" + name: "inception_5a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/3x3" + top: "inception_5a/3x3" + name: "inception_5a/relu_3x3" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/5x5_reduce" + name: "inception_5a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5_reduce" + name: "inception_5a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5" + name: "inception_5a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/5x5" + top: "inception_5a/5x5" + name: "inception_5a/relu_5x5" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/pool" + name: "inception_5a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_5a/pool" + top: "inception_5a/pool_proj" + name: "inception_5a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/pool_proj" + top: "inception_5a/pool_proj" + name: "inception_5a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_5a/1x1" + bottom: "inception_5a/3x3" + bottom: "inception_5a/5x5" + bottom: "inception_5a/pool_proj" + top: "inception_5a/output" + name: "inception_5a/output" + type: CONCAT +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/1x1" + name: "inception_5b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/1x1" + top: "inception_5b/1x1" + name: "inception_5b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/3x3_reduce" + name: "inception_5b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3_reduce" + name: "inception_5b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3" + name: "inception_5b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/3x3" + top: "inception_5b/3x3" + name: "inception_5b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/5x5_reduce" + name: "inception_5b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 48 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5_reduce" + name: "inception_5b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5" + name: "inception_5b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/5x5" + top: "inception_5b/5x5" + name: "inception_5b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/pool" + name: "inception_5b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_5b/pool" + top: "inception_5b/pool_proj" + name: "inception_5b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/pool_proj" + top: "inception_5b/pool_proj" + name: "inception_5b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_5b/1x1" + bottom: "inception_5b/3x3" + bottom: "inception_5b/5x5" + bottom: "inception_5b/pool_proj" + top: "inception_5b/output" + name: "inception_5b/output" + type: CONCAT +} +layers { + bottom: "inception_5b/output" + top: "pool5/7x7_s1" + name: "pool5/7x7_s1" + type: POOLING + pooling_param { + pool: AVE + kernel_size: 7 + stride: 1 + } +} +layers { + bottom: "pool5/7x7_s1" + top: "pool5/7x7_s1" + name: "pool5/drop_7x7_s1" + type: DROPOUT + dropout_param { + dropout_ratio: 0.4 + } +} +layers { + bottom: "pool5/7x7_s1" + top: "loss3/classifier" + name: "loss3/classifier" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + bottom: "loss3/classifier" + bottom: "label" + top: "loss3/loss3" + name: "loss3/loss3" + type: SOFTMAX_LOSS + loss_weight: 1 +} +layers { + bottom: "loss3/classifier" + bottom: "label" + top: "loss3/top-1" + name: "loss3/top-1" + type: ACCURACY + include { + phase: TEST + } +} +layers { + bottom: "loss3/classifier" + bottom: "label" + top: "loss3/top-5" + name: "loss3/top-5" + type: ACCURACY + accuracy_param { + top_k: 5 + } + include { + phase: TEST + } +} From f347355207601a602cc1081ea10f969f995138e9 Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 20 Dec 2014 23:24:32 -0800 Subject: [PATCH 185/798] Added credits for training bvlc models --- models/bvlc_alexnet/readme.md | 2 ++ models/bvlc_googlenet/readme.md | 2 ++ models/bvlc_reference_caffenet/readme.md | 2 ++ models/bvlc_reference_rcnn_ilsvrc13/readme.md | 2 ++ models/finetune_flickr_style/readme.md | 2 ++ 5 files changed, 10 insertions(+) diff --git a/models/bvlc_alexnet/readme.md b/models/bvlc_alexnet/readme.md index 20c393ff26b..c25fd4f8018 100644 --- a/models/bvlc_alexnet/readme.md +++ b/models/bvlc_alexnet/readme.md @@ -18,6 +18,8 @@ The best validation performance during training was iteration 358,000 with valid This model obtains a top-1 accuracy 57.1% and a top-5 accuracy 80.2% on the validation set, using just the center crop. (Using the average of 10 crops, (4 + 1 center) * 2 mirror, should obtain a bit higher accuracy.) +This model was trained by Evan Shelhamer @shelhamer + ## License The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: diff --git a/models/bvlc_googlenet/readme.md b/models/bvlc_googlenet/readme.md index 27022d3384a..8a3bbec4f8b 100644 --- a/models/bvlc_googlenet/readme.md +++ b/models/bvlc_googlenet/readme.md @@ -5,6 +5,7 @@ caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel license: non-commercial sha1: 405fc5acd08a3bb12de8ee5e23a96bec22f08204 caffe_commit: bc614d1bd91896e3faceaf40b23b72dab47d44f5 +gist_id: 866e2aa1fd707b89b913 --- This model is a replication of the model described in the [GoogleNet](http://arxiv.org/abs/1409.4842) publication. We would like to thank Christian Szegedy for all his help in the replication of GoogleNet model. @@ -25,6 +26,7 @@ Timings for bvlc_googlenet with cuDNN using batch_size:128 on a K40c: - Average Backward pass: 1123.84 ms. - Average Forward-Backward: 1688.8 ms. +This model was trained by Sergio Guadarrama @sguada ## License diff --git a/models/bvlc_reference_caffenet/readme.md b/models/bvlc_reference_caffenet/readme.md index d1c6269ae73..b867e7386a3 100644 --- a/models/bvlc_reference_caffenet/readme.md +++ b/models/bvlc_reference_caffenet/readme.md @@ -18,6 +18,8 @@ The best validation performance during training was iteration 313,000 with valid This model obtains a top-1 accuracy 57.4% and a top-5 accuracy 80.4% on the validation set, using just the center crop. (Using the average of 10 crops, (4 + 1 center) * 2 mirror, should obtain a bit higher accuracy still.) +This model was trained by Jeff Donahue @jeffdonahue + ## License The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: diff --git a/models/bvlc_reference_rcnn_ilsvrc13/readme.md b/models/bvlc_reference_rcnn_ilsvrc13/readme.md index fb8f26d15df..5d4bc5afe32 100644 --- a/models/bvlc_reference_rcnn_ilsvrc13/readme.md +++ b/models/bvlc_reference_rcnn_ilsvrc13/readme.md @@ -13,6 +13,8 @@ Try the [detection example](http://nbviewer.ipython.org/github/BVLC/caffe/blob/m *N.B. For research purposes, make use of the official R-CNN package and not this example.* +This model was trained by Ross Girshick @rbgirshick + ## License The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: diff --git a/models/finetune_flickr_style/readme.md b/models/finetune_flickr_style/readme.md index d2a8a95f669..aac7f7c96e8 100644 --- a/models/finetune_flickr_style/readme.md +++ b/models/finetune_flickr_style/readme.md @@ -15,6 +15,8 @@ The final performance: I1017 07:36:17.370730 31333 solver.cpp:247] Iteration 100000, Testing net (#0) I1017 07:36:34.248730 31333 solver.cpp:298] Test net output #0: accuracy = 0.3916 +This model was trained by Sergey Karayev @sergeyk + ## License The Flickr Style dataset contains only URLs to images. From 396a7bd06838118b26fac7510b1cf28fbec1cd1e Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 20 Dec 2014 23:28:19 -0800 Subject: [PATCH 186/798] Added credits and bvlc_googlenet to model_zoo.md --- docs/model_zoo.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/model_zoo.md b/docs/model_zoo.md index 330850cbbd6..358bbb7fc91 100644 --- a/docs/model_zoo.md +++ b/docs/model_zoo.md @@ -15,9 +15,10 @@ To lower the friction of sharing these models, we introduce the model zoo framew First of all, we provide some trained models out of the box. Each one of these can be downloaded by running `scripts/download_model_binary.py ` where `` is specified below: -- **BVLC Reference CaffeNet** in `models/bvlc_reference_caffenet`: AlexNet trained on ILSVRC 2012, with a minor variation from the version as described in the NIPS 2012 paper. -- **BVLC AlexNet** in `models/bvlc_alexnet`: AlexNet trained on ILSVRC 2012, almost exactly as described in NIPS 2012. -- **BVLC Reference R-CNN ILSVRC-2013** in `models/bvlc_reference_rcnn_ilsvrc13`: pure Caffe implementation of [R-CNN](https://github.com/rbgirshick/rcnn). +- **BVLC Reference CaffeNet** in `models/bvlc_reference_caffenet`: AlexNet trained on ILSVRC 2012, with a minor variation from the version as described in the NIPS 2012 paper. (Trained by Jeff Donahue @jeffdonahue) +- **BVLC AlexNet** in `models/bvlc_alexnet`: AlexNet trained on ILSVRC 2012, almost exactly as described in NIPS 2012. (Trained by Evan Shelhamer @shelhamer) +- **BVLC Reference R-CNN ILSVRC-2013** in `models/bvlc_reference_rcnn_ilsvrc13`: pure Caffe implementation of [R-CNN](https://github.com/rbgirshick/rcnn). (Trained by Ross Girshick @rbgirshick) +- **BVLC GoogleNet** in `models/bvlc_googlenet`: GoogleNet trained on ILSVRC 2012, almost exactly as described in [GoogleNet](http://arxiv.org/abs/1409.4842). (Trained by Sergio Guadarrama @sguada) User-provided models are posted to a public-editable [wiki page](https://github.com/BVLC/caffe/wiki/Model-Zoo). From 9e756bfd10bf6f3196905b8e721d9fb5abde2ad2 Mon Sep 17 00:00:00 2001 From: qipeng Date: Tue, 16 Sep 2014 19:59:53 -0700 Subject: [PATCH 187/798] Display averaged loss over the last several iterations --- src/caffe/proto/caffe.proto | 4 +++- src/caffe/solver.cpp | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 9395c38f3e9..a789aeefa25 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -63,7 +63,7 @@ message NetParameter { // NOTE // Update the next available ID when you add a new SolverParameter field. // -// SolverParameter next available ID: 33 (last added: test_initialization) +// SolverParameter next available ID: 34 (last added: average_loss) message SolverParameter { ////////////////////////////////////////////////////////////////////////////// // Specifying the train and test networks @@ -113,6 +113,8 @@ message SolverParameter { // the number of iterations between displaying info. If display = 0, no info // will be displayed. optional int32 display = 6; + // Display the cost averaged over the last average_cost iterations + optional int32 average_loss = 33 [default = 1]; optional int32 max_iter = 7; // the maximum number of iterations optional string lr_policy = 8; // The learning rate decay policy. optional float gamma = 9; // The parameter to compute the learning rate. diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index ba262920a9a..5c34e487cb6 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -169,6 +169,13 @@ void Solver::Solve(const char* resume_file) { // resume_file above. const int start_iter = iter_; + int average_loss = this->param_.average_loss(); + + CHECK_GE(average_loss, 1) << "average_cost should be non-negative."; + + vector losses; + Dtype smoothed_loss = 0; + // For a network that is trained by the solver, no bottom or top vecs // should be given, and we will just provide dummy vecs. vector*> bottom_vec; @@ -187,8 +194,17 @@ void Solver::Solve(const char* resume_file) { const bool display = param_.display() && iter_ % param_.display() == 0; net_->set_debug_info(display && param_.debug_info()); Dtype loss = net_->ForwardBackward(bottom_vec); + if (losses.size() < average_loss) { + losses.push_back(loss); + int size = losses.size(); + smoothed_loss = (smoothed_loss * (size - 1) + loss) / size; + } else { + int idx = (iter_ - start_iter) % average_loss; + smoothed_loss += (loss - losses[idx]) / average_loss; + losses[idx] = loss; + } if (display) { - LOG(INFO) << "Iteration " << iter_ << ", loss = " << loss; + LOG(INFO) << "Iteration " << iter_ << ", loss = " << smoothed_loss; const vector*>& result = net_->output_blobs(); int score_index = 0; for (int j = 0; j < result.size(); ++j) { From 18749f8982e11eca91e1d97bc4317c6d64f9dca7 Mon Sep 17 00:00:00 2001 From: Sergio Date: Fri, 3 Oct 2014 17:14:20 -0700 Subject: [PATCH 188/798] Added Multistep, Poly and Sigmoid learning rate decay policies Conflicts: include/caffe/solver.hpp src/caffe/proto/caffe.proto src/caffe/solver.cpp --- .../lenet/lenet_multistep_solver.prototxt | 33 +++++++++++++++++ .../lenet/lenet_stepearly_solver.prototxt | 28 ++++++++++++++ include/caffe/solver.hpp | 1 + src/caffe/proto/caffe.proto | 8 +++- src/caffe/solver.cpp | 37 ++++++++++++++++--- 5 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 examples/lenet/lenet_multistep_solver.prototxt create mode 100644 examples/lenet/lenet_stepearly_solver.prototxt diff --git a/examples/lenet/lenet_multistep_solver.prototxt b/examples/lenet/lenet_multistep_solver.prototxt new file mode 100644 index 00000000000..fadd7c904d7 --- /dev/null +++ b/examples/lenet/lenet_multistep_solver.prototxt @@ -0,0 +1,33 @@ +# The training protocol buffer definition +train_net: "lenet_train.prototxt" +# The testing protocol buffer definition +test_net: "lenet_test.prototxt" +# test_iter specifies how many forward passes the test should carry out. +# In the case of MNIST, we have test batch size 100 and 100 test iterations, +# covering the full 10,000 testing images. +test_iter: 100 +# Carry out testing every 500 training iterations. +test_interval: 500 +# The base learning rate, momentum and the weight decay of the network. +base_lr: 0.01 +momentum: 0.9 +weight_decay: 0.0005 +# The learning rate policy +lr_policy: "multistep" +gamma: 0.9 +stepvalue: 1000 +stepvalue: 2000 +stepvalue: 2500 +stepvalue: 3000 +stepvalue: 3500 +stepvalue: 4000 +# Display every 100 iterations +display: 100 +# The maximum number of iterations +max_iter: 10000 +# snapshot intermediate results +snapshot: 5000 +snapshot_prefix: "lenet" +# solver mode: 0 for CPU and 1 for GPU +solver_mode: 1 +device_id: 1 diff --git a/examples/lenet/lenet_stepearly_solver.prototxt b/examples/lenet/lenet_stepearly_solver.prototxt new file mode 100644 index 00000000000..efc6a335d8f --- /dev/null +++ b/examples/lenet/lenet_stepearly_solver.prototxt @@ -0,0 +1,28 @@ +# The training protocol buffer definition +train_net: "lenet_train.prototxt" +# The testing protocol buffer definition +test_net: "lenet_test.prototxt" +# test_iter specifies how many forward passes the test should carry out. +# In the case of MNIST, we have test batch size 100 and 100 test iterations, +# covering the full 10,000 testing images. +test_iter: 100 +# Carry out testing every 500 training iterations. +test_interval: 500 +# The base learning rate, momentum and the weight decay of the network. +base_lr: 0.01 +momentum: 0.9 +weight_decay: 0.0005 +# The learning rate policy +lr_policy: "stepearly" +gamma: 0.9 +stepearly: 1 +# Display every 100 iterations +display: 100 +# The maximum number of iterations +max_iter: 10000 +# snapshot intermediate results +snapshot: 5000 +snapshot_prefix: "lenet" +# solver mode: 0 for CPU and 1 for GPU +solver_mode: 1 +device_id: 1 diff --git a/include/caffe/solver.hpp b/include/caffe/solver.hpp index 6fd159d0b98..51aebb323c5 100644 --- a/include/caffe/solver.hpp +++ b/include/caffe/solver.hpp @@ -56,6 +56,7 @@ class Solver { SolverParameter param_; int iter_; + int current_step_; shared_ptr > net_; vector > > test_nets_; diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index a789aeefa25..88f670fd497 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -63,7 +63,7 @@ message NetParameter { // NOTE // Update the next available ID when you add a new SolverParameter field. // -// SolverParameter next available ID: 34 (last added: average_loss) +// SolverParameter next available ID: 35 (last added: stepvalue) message SolverParameter { ////////////////////////////////////////////////////////////////////////////// // Specifying the train and test networks @@ -124,7 +124,10 @@ message SolverParameter { // regularization types supported: L1 and L2 // controlled by weight_decay optional string regularization_type = 29 [default = "L2"]; - optional int32 stepsize = 13; // the stepsize for learning rate policy "step" + // the stepsize for learning rate policy "step" + optional int32 stepsize = 13; + // the stepsize for learning rate policy "multistep" + repeated int32 stepvalue = 34; optional int32 snapshot = 14 [default = 0]; // The snapshot interval optional string snapshot_prefix = 15; // The prefix for the snapshot. // whether to snapshot diff in the results or not. Snapshotting diff will help @@ -166,6 +169,7 @@ message SolverState { optional int32 iter = 1; // The current iteration optional string learned_net = 2; // The file that stores the learned net. repeated BlobProto history = 3; // The history for sgd solvers + optional int32 current_step = 4 [default = 0]; // The current step for learning rate } enum Phase { diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 5c34e487cb6..886c3cc6edc 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -158,6 +158,7 @@ template void Solver::Solve(const char* resume_file) { Caffe::set_phase(Caffe::TRAIN); LOG(INFO) << "Solving " << net_->name(); + LOG(INFO) << "Learning Rate Policy: " << param_.lr_policy(); PreSolve(); iter_ = 0; @@ -257,7 +258,6 @@ void Solver::TestAll() { } } - template void Solver::Test(const int test_net_id) { LOG(INFO) << "Iteration " << iter_ @@ -336,6 +336,7 @@ void Solver::Snapshot() { SnapshotSolverState(&state); state.set_iter(iter_); state.set_learned_net(model_filename); + state.set_current_step(current_step_); snapshot_filename = filename + ".solverstate"; LOG(INFO) << "Snapshotting solver state to " << snapshot_filename; WriteProtoToBinaryFile(state, snapshot_filename.c_str()); @@ -351,6 +352,7 @@ void Solver::Restore(const char* state_file) { net_->CopyTrainedLayersFrom(net_param); } iter_ = state.iter(); + current_step_ = state.current_step(); RestoreSolverState(state); } @@ -361,8 +363,15 @@ void Solver::Restore(const char* state_file) { // - step: return base_lr * gamma ^ (floor(iter / step)) // - exp: return base_lr * gamma ^ iter // - inv: return base_lr * (1 + gamma * iter) ^ (- power) -// where base_lr, gamma, step and power are defined in the solver parameter -// protocol buffer, and iter is the current iteration. +// - multistep: similar to step but it allows non uniform steps defined by +// stepvalue +// - poly: the effective learning rate follows a polynomial decay, to be +// zero by the max_iter. return base_lr (1 - iter/max_iter) ^ (power) +// - sigmoid: the effective learning rate follows a sigmod decay +// return base_lr ( 1/(1 + exp(-gamma * (iter - stepsize)))) +// +// where base_lr, max_iter, gamma, step, stepvalue and power are defined +// in the solver parameter protocol buffer, and iter is the current iteration. template Dtype SGDSolver::GetLearningRate() { Dtype rate; @@ -370,22 +379,38 @@ Dtype SGDSolver::GetLearningRate() { if (lr_policy == "fixed") { rate = this->param_.base_lr(); } else if (lr_policy == "step") { - int current_step = this->iter_ / this->param_.stepsize(); + this->current_step_ = this->iter_ / this->param_.stepsize(); rate = this->param_.base_lr() * - pow(this->param_.gamma(), current_step); + pow(this->param_.gamma(), this->current_step_); } else if (lr_policy == "exp") { rate = this->param_.base_lr() * pow(this->param_.gamma(), this->iter_); } else if (lr_policy == "inv") { rate = this->param_.base_lr() * pow(Dtype(1) + this->param_.gamma() * this->iter_, - this->param_.power()); + } else if (lr_policy == "multistep") { + if (this->current_step_ < this->param_.stepvalue_size() && + this->iter_ >= this->param_.stepvalue(this->current_step_)) { + this->current_step_++; + LOG(INFO) << "MultiStep Status: Iteration " << + this->iter_ << ", step = " << this->current_step_; + } + rate = this->param_.base_lr() * + pow(this->param_.gamma(), this->current_step_); + } else if (lr_policy == "poly") { + rate = this->param_.base_lr() * pow(Dtype(1.) - + (Dtype(this->iter_) / Dtype(this->param_.max_iter())), + this->param_.power()); + } else if (lr_policy == "sigmoid") { + rate = this->param_.base_lr() * (Dtype(1.) / + (Dtype(1.) + exp(-this->param_.gamma() * (Dtype(this->iter_) - + Dtype(this->param_.stepsize()))))); } else { LOG(FATAL) << "Unknown learning rate policy: " << lr_policy; } return rate; } - template void SGDSolver::PreSolve() { // Initialize the history From 899dfde6f545faa73c0ffe5732ae641b10dfbc09 Mon Sep 17 00:00:00 2001 From: Sergio Date: Fri, 3 Oct 2014 17:14:20 -0700 Subject: [PATCH 189/798] Adapt lenet_multistep_solver.prototxt to current solvers --- .../lenet_multistep_solver.prototxt | 13 +++++-------- examples/mnist/readme.md | 3 +++ 2 files changed, 8 insertions(+), 8 deletions(-) rename examples/{lenet => mnist}/lenet_multistep_solver.prototxt (74%) diff --git a/examples/lenet/lenet_multistep_solver.prototxt b/examples/mnist/lenet_multistep_solver.prototxt similarity index 74% rename from examples/lenet/lenet_multistep_solver.prototxt rename to examples/mnist/lenet_multistep_solver.prototxt index fadd7c904d7..7ee9fb60e67 100644 --- a/examples/lenet/lenet_multistep_solver.prototxt +++ b/examples/mnist/lenet_multistep_solver.prototxt @@ -1,7 +1,5 @@ -# The training protocol buffer definition -train_net: "lenet_train.prototxt" -# The testing protocol buffer definition -test_net: "lenet_test.prototxt" +# The train/test net protocol buffer definition +net: "examples/mnist/lenet_train_test.prototxt" # test_iter specifies how many forward passes the test should carry out. # In the case of MNIST, we have test batch size 100 and 100 test iterations, # covering the full 10,000 testing images. @@ -27,7 +25,6 @@ display: 100 max_iter: 10000 # snapshot intermediate results snapshot: 5000 -snapshot_prefix: "lenet" -# solver mode: 0 for CPU and 1 for GPU -solver_mode: 1 -device_id: 1 +snapshot_prefix: "examples/mnist/lenet_multistep" +# solver mode: CPU or GPU +solver_mode: GPU diff --git a/examples/mnist/readme.md b/examples/mnist/readme.md index 33ed371b4a1..ef7f5da67d5 100644 --- a/examples/mnist/readme.md +++ b/examples/mnist/readme.md @@ -282,3 +282,6 @@ You just did! All the training was carried out on the GPU. In fact, if you would and you will be using CPU for training. Isn't that easy? MNIST is a small dataset, so training with GPU does not really introduce too much benefit due to communication overheads. On larger datasets with more complex models, such as ImageNet, the computation speed difference will be more significant. + +### How to reduce the learning rate a fixed steps? +Look at lenet_multistep_solver.prototxt From cb3dbee20a46e822c2e4306b03f4b127c1db1f5c Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 16 Oct 2014 11:17:24 -0700 Subject: [PATCH 190/798] Fix init current_step --- examples/mnist/lenet_multistep_solver.prototxt | 11 +++++------ src/caffe/solver.cpp | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/mnist/lenet_multistep_solver.prototxt b/examples/mnist/lenet_multistep_solver.prototxt index 7ee9fb60e67..9b22b45ba6b 100644 --- a/examples/mnist/lenet_multistep_solver.prototxt +++ b/examples/mnist/lenet_multistep_solver.prototxt @@ -13,12 +13,11 @@ weight_decay: 0.0005 # The learning rate policy lr_policy: "multistep" gamma: 0.9 -stepvalue: 1000 -stepvalue: 2000 -stepvalue: 2500 -stepvalue: 3000 -stepvalue: 3500 -stepvalue: 4000 +stepvalue: 5000 +stepvalue: 7000 +stepvalue: 8000 +stepvalue: 9000 +stepvalue: 9500 # Display every 100 iterations display: 100 # The maximum number of iterations diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 886c3cc6edc..0fd8d0f89dc 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -162,6 +162,7 @@ void Solver::Solve(const char* resume_file) { PreSolve(); iter_ = 0; + current_step_ = 0; if (resume_file) { LOG(INFO) << "Restoring previous solver status from " << resume_file; Restore(resume_file); From 4ba6efc7ac939be59e5ff121c0289885a9a4263d Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 2 Dec 2014 13:10:57 -0800 Subject: [PATCH 191/798] Added bvlc_googlenet prototxt and weights --- models/bvlc_googlenet/deploy.prototxt | 1924 ++++++++++++++++ models/bvlc_googlenet/quick_solver.prototxt | 15 + models/bvlc_googlenet/readme.md | 33 + models/bvlc_googlenet/solver.prototxt | 16 + models/bvlc_googlenet/train_val.prototxt | 2242 +++++++++++++++++++ 5 files changed, 4230 insertions(+) create mode 100644 models/bvlc_googlenet/deploy.prototxt create mode 100644 models/bvlc_googlenet/quick_solver.prototxt create mode 100644 models/bvlc_googlenet/readme.md create mode 100644 models/bvlc_googlenet/solver.prototxt create mode 100644 models/bvlc_googlenet/train_val.prototxt diff --git a/models/bvlc_googlenet/deploy.prototxt b/models/bvlc_googlenet/deploy.prototxt new file mode 100644 index 00000000000..e31a4c9cd00 --- /dev/null +++ b/models/bvlc_googlenet/deploy.prototxt @@ -0,0 +1,1924 @@ +name: "GoogleNet" +input: "data" +input_dim: 10 +input_dim: 3 +input_dim: 224 +input_dim: 224 +layers { + bottom: "data" + top: "conv1/7x7_s2" + name: "conv1/7x7_s2" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 3 + kernel_size: 7 + stride: 2 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv1/7x7_s2" + top: "conv1/7x7_s2" + name: "conv1/relu_7x7" + type: RELU +} +layers { + bottom: "conv1/7x7_s2" + top: "pool1/3x3_s2" + name: "pool1/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool1/3x3_s2" + top: "pool1/norm1" + name: "pool1/norm1" + type: LRN + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + bottom: "pool1/norm1" + top: "conv2/3x3_reduce" + name: "conv2/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv2/3x3_reduce" + top: "conv2/3x3_reduce" + name: "conv2/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "conv2/3x3_reduce" + top: "conv2/3x3" + name: "conv2/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv2/3x3" + top: "conv2/3x3" + name: "conv2/relu_3x3" + type: RELU +} +layers { + bottom: "conv2/3x3" + top: "conv2/norm2" + name: "conv2/norm2" + type: LRN + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + bottom: "conv2/norm2" + top: "pool2/3x3_s2" + name: "pool2/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/1x1" + name: "inception_3a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/1x1" + top: "inception_3a/1x1" + name: "inception_3a/relu_1x1" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/3x3_reduce" + name: "inception_3a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3_reduce" + name: "inception_3a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3" + name: "inception_3a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/3x3" + top: "inception_3a/3x3" + name: "inception_3a/relu_3x3" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/5x5_reduce" + name: "inception_3a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5_reduce" + name: "inception_3a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5" + name: "inception_3a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/5x5" + top: "inception_3a/5x5" + name: "inception_3a/relu_5x5" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/pool" + name: "inception_3a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_3a/pool" + top: "inception_3a/pool_proj" + name: "inception_3a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/pool_proj" + top: "inception_3a/pool_proj" + name: "inception_3a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_3a/1x1" + bottom: "inception_3a/3x3" + bottom: "inception_3a/5x5" + bottom: "inception_3a/pool_proj" + top: "inception_3a/output" + name: "inception_3a/output" + type: CONCAT +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/1x1" + name: "inception_3b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/1x1" + top: "inception_3b/1x1" + name: "inception_3b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/3x3_reduce" + name: "inception_3b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3_reduce" + name: "inception_3b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3" + name: "inception_3b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/3x3" + top: "inception_3b/3x3" + name: "inception_3b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/5x5_reduce" + name: "inception_3b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5_reduce" + name: "inception_3b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5" + name: "inception_3b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/5x5" + top: "inception_3b/5x5" + name: "inception_3b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/pool" + name: "inception_3b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_3b/pool" + top: "inception_3b/pool_proj" + name: "inception_3b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/pool_proj" + top: "inception_3b/pool_proj" + name: "inception_3b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_3b/1x1" + bottom: "inception_3b/3x3" + bottom: "inception_3b/5x5" + bottom: "inception_3b/pool_proj" + top: "inception_3b/output" + name: "inception_3b/output" + type: CONCAT +} +layers { + bottom: "inception_3b/output" + top: "pool3/3x3_s2" + name: "pool3/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/1x1" + name: "inception_4a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/1x1" + top: "inception_4a/1x1" + name: "inception_4a/relu_1x1" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/3x3_reduce" + name: "inception_4a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3_reduce" + name: "inception_4a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3" + name: "inception_4a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 208 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/3x3" + top: "inception_4a/3x3" + name: "inception_4a/relu_3x3" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/5x5_reduce" + name: "inception_4a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5_reduce" + name: "inception_4a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5" + name: "inception_4a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 48 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/5x5" + top: "inception_4a/5x5" + name: "inception_4a/relu_5x5" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/pool" + name: "inception_4a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4a/pool" + top: "inception_4a/pool_proj" + name: "inception_4a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/pool_proj" + top: "inception_4a/pool_proj" + name: "inception_4a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4a/1x1" + bottom: "inception_4a/3x3" + bottom: "inception_4a/5x5" + bottom: "inception_4a/pool_proj" + top: "inception_4a/output" + name: "inception_4a/output" + type: CONCAT +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/1x1" + name: "inception_4b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/1x1" + top: "inception_4b/1x1" + name: "inception_4b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/3x3_reduce" + name: "inception_4b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3_reduce" + name: "inception_4b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3" + name: "inception_4b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 224 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/3x3" + top: "inception_4b/3x3" + name: "inception_4b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/5x5_reduce" + name: "inception_4b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5_reduce" + name: "inception_4b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5" + name: "inception_4b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/5x5" + top: "inception_4b/5x5" + name: "inception_4b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/pool" + name: "inception_4b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4b/pool" + top: "inception_4b/pool_proj" + name: "inception_4b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/pool_proj" + top: "inception_4b/pool_proj" + name: "inception_4b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4b/1x1" + bottom: "inception_4b/3x3" + bottom: "inception_4b/5x5" + bottom: "inception_4b/pool_proj" + top: "inception_4b/output" + name: "inception_4b/output" + type: CONCAT +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/1x1" + name: "inception_4c/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/1x1" + top: "inception_4c/1x1" + name: "inception_4c/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/3x3_reduce" + name: "inception_4c/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3_reduce" + name: "inception_4c/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3" + name: "inception_4c/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/3x3" + top: "inception_4c/3x3" + name: "inception_4c/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/5x5_reduce" + name: "inception_4c/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5_reduce" + name: "inception_4c/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5" + name: "inception_4c/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/5x5" + top: "inception_4c/5x5" + name: "inception_4c/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/pool" + name: "inception_4c/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4c/pool" + top: "inception_4c/pool_proj" + name: "inception_4c/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/pool_proj" + top: "inception_4c/pool_proj" + name: "inception_4c/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4c/1x1" + bottom: "inception_4c/3x3" + bottom: "inception_4c/5x5" + bottom: "inception_4c/pool_proj" + top: "inception_4c/output" + name: "inception_4c/output" + type: CONCAT +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/1x1" + name: "inception_4d/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/1x1" + top: "inception_4d/1x1" + name: "inception_4d/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/3x3_reduce" + name: "inception_4d/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 144 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3_reduce" + name: "inception_4d/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3" + name: "inception_4d/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 288 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/3x3" + top: "inception_4d/3x3" + name: "inception_4d/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/5x5_reduce" + name: "inception_4d/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5_reduce" + name: "inception_4d/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5" + name: "inception_4d/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/5x5" + top: "inception_4d/5x5" + name: "inception_4d/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/pool" + name: "inception_4d/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4d/pool" + top: "inception_4d/pool_proj" + name: "inception_4d/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/pool_proj" + top: "inception_4d/pool_proj" + name: "inception_4d/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4d/1x1" + bottom: "inception_4d/3x3" + bottom: "inception_4d/5x5" + bottom: "inception_4d/pool_proj" + top: "inception_4d/output" + name: "inception_4d/output" + type: CONCAT +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/1x1" + name: "inception_4e/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/1x1" + top: "inception_4e/1x1" + name: "inception_4e/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/3x3_reduce" + name: "inception_4e/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3_reduce" + name: "inception_4e/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3" + name: "inception_4e/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/3x3" + top: "inception_4e/3x3" + name: "inception_4e/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/5x5_reduce" + name: "inception_4e/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5_reduce" + name: "inception_4e/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5" + name: "inception_4e/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/5x5" + top: "inception_4e/5x5" + name: "inception_4e/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/pool" + name: "inception_4e/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4e/pool" + top: "inception_4e/pool_proj" + name: "inception_4e/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/pool_proj" + top: "inception_4e/pool_proj" + name: "inception_4e/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4e/1x1" + bottom: "inception_4e/3x3" + bottom: "inception_4e/5x5" + bottom: "inception_4e/pool_proj" + top: "inception_4e/output" + name: "inception_4e/output" + type: CONCAT +} +layers { + bottom: "inception_4e/output" + top: "pool4/3x3_s2" + name: "pool4/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/1x1" + name: "inception_5a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/1x1" + top: "inception_5a/1x1" + name: "inception_5a/relu_1x1" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/3x3_reduce" + name: "inception_5a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3_reduce" + name: "inception_5a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3" + name: "inception_5a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/3x3" + top: "inception_5a/3x3" + name: "inception_5a/relu_3x3" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/5x5_reduce" + name: "inception_5a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5_reduce" + name: "inception_5a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5" + name: "inception_5a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/5x5" + top: "inception_5a/5x5" + name: "inception_5a/relu_5x5" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/pool" + name: "inception_5a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_5a/pool" + top: "inception_5a/pool_proj" + name: "inception_5a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/pool_proj" + top: "inception_5a/pool_proj" + name: "inception_5a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_5a/1x1" + bottom: "inception_5a/3x3" + bottom: "inception_5a/5x5" + bottom: "inception_5a/pool_proj" + top: "inception_5a/output" + name: "inception_5a/output" + type: CONCAT +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/1x1" + name: "inception_5b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/1x1" + top: "inception_5b/1x1" + name: "inception_5b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/3x3_reduce" + name: "inception_5b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3_reduce" + name: "inception_5b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3" + name: "inception_5b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/3x3" + top: "inception_5b/3x3" + name: "inception_5b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/5x5_reduce" + name: "inception_5b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 48 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5_reduce" + name: "inception_5b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5" + name: "inception_5b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/5x5" + top: "inception_5b/5x5" + name: "inception_5b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/pool" + name: "inception_5b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_5b/pool" + top: "inception_5b/pool_proj" + name: "inception_5b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/pool_proj" + top: "inception_5b/pool_proj" + name: "inception_5b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_5b/1x1" + bottom: "inception_5b/3x3" + bottom: "inception_5b/5x5" + bottom: "inception_5b/pool_proj" + top: "inception_5b/output" + name: "inception_5b/output" + type: CONCAT +} +layers { + bottom: "inception_5b/output" + top: "pool5/7x7_s1" + name: "pool5/7x7_s1" + type: POOLING + pooling_param { + pool: AVE + kernel_size: 7 + stride: 1 + } +} +layers { + bottom: "pool5/7x7_s1" + top: "pool5/7x7_s1" + name: "pool5/drop_7x7_s1" + type: DROPOUT + dropout_param { + dropout_ratio: 0.4 + } +} +layers { + bottom: "pool5/7x7_s1" + top: "loss3/classifier" + name: "loss3/classifier" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + name: "prob" + type: SOFTMAX + bottom: "loss3/classifier" + top: "prob" +} \ No newline at end of file diff --git a/models/bvlc_googlenet/quick_solver.prototxt b/models/bvlc_googlenet/quick_solver.prototxt new file mode 100644 index 00000000000..5d2f7ee70b9 --- /dev/null +++ b/models/bvlc_googlenet/quick_solver.prototxt @@ -0,0 +1,15 @@ +net: "models/bvlc_googlenet/train_val.prototxt" +test_iter: 1000 +test_interval: 4000 +test_initialization: false +display: 40 +average_loss: 40 +base_lr: 0.01 +lr_policy: "poly" +power: 0.5 +max_iter: 2400000 +momentum: 0.9 +weight_decay: 0.0002 +snapshot: 40000 +snapshot_prefix: "models/bvlc_googlenet/bvlc_googlenet_quick" +solver_mode: GPU diff --git a/models/bvlc_googlenet/readme.md b/models/bvlc_googlenet/readme.md new file mode 100644 index 00000000000..27022d3384a --- /dev/null +++ b/models/bvlc_googlenet/readme.md @@ -0,0 +1,33 @@ +--- +name: BVLC GoogleNet Model +caffemodel: bvlc_googlenet.caffemodel +caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel +license: non-commercial +sha1: 405fc5acd08a3bb12de8ee5e23a96bec22f08204 +caffe_commit: bc614d1bd91896e3faceaf40b23b72dab47d44f5 +--- + +This model is a replication of the model described in the [GoogleNet](http://arxiv.org/abs/1409.4842) publication. We would like to thank Christian Szegedy for all his help in the replication of GoogleNet model. + +Differences: +- not training with the relighting data-augmentation; +- not training with the scale or aspect-ratio data-augmentation; +- uses "xavier" to initialize the weights instead of "gaussian"; +- quick_solver.prototxt uses a different learning rate decay policy than the original solver.prototxt, that allows a much faster training (60 epochs vs 250 epochs); + +The bundled model is the iteration 2,400,000 snapshot (60 epochs) using quick_solver.prototxt + +This bundled model obtains a top-1 accuracy 68.7% (31.3% error) and a top-5 accuracy 88.9% (11.1% error) on the validation set, using just the center crop. +(Using the average of 10 crops, (4 + 1 center) * 2 mirror, should obtain a bit higher accuracy.) + +Timings for bvlc_googlenet with cuDNN using batch_size:128 on a K40c: + - Average Forward pass: 562.841 ms. + - Average Backward pass: 1123.84 ms. + - Average Forward-Backward: 1688.8 ms. + + +## License + +The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: +"Researcher shall use the Database only for non-commercial research and educational purposes." +Accordingly, this model is distributed under a non-commercial license. diff --git a/models/bvlc_googlenet/solver.prototxt b/models/bvlc_googlenet/solver.prototxt new file mode 100644 index 00000000000..d7d1788173c --- /dev/null +++ b/models/bvlc_googlenet/solver.prototxt @@ -0,0 +1,16 @@ +net: "models/bvlc_googlenet/train_val.prototxt" +test_iter: 1000 +test_interval: 4000 +test_initialization: false +display: 40 +average_loss: 40 +base_lr: 0.01 +lr_policy: "step" +stepsize: 320000 +gamma: 0.96 +max_iter: 10000000 +momentum: 0.9 +weight_decay: 0.0002 +snapshot: 40000 +snapshot_prefix: "models/bvlc_googlenet/bvlc_googlenet" +solver_mode: GPU diff --git a/models/bvlc_googlenet/train_val.prototxt b/models/bvlc_googlenet/train_val.prototxt new file mode 100644 index 00000000000..156d05fd254 --- /dev/null +++ b/models/bvlc_googlenet/train_val.prototxt @@ -0,0 +1,2242 @@ +name: "GoogleNet" +layers { + top: "data" + top: "label" + name: "data" + type: DATA + data_param { + source: "examples/imagenet/ilsvrc12_train_lmdb" + batch_size: 32 + backend: LMDB + } + include { + phase: TRAIN + } + transform_param { + mirror: true + crop_size: 224 + mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" + # mean_value: 104 + # mean_value: 117 + # mean_value: 123 + } +} +layers { + top: "data" + top: "label" + name: "data" + type: DATA + data_param { + source: "examples/imagenet/ilsvrc12_val_lmdb" + batch_size: 50 + backend: LMDB + } + include { + phase: TEST + } + transform_param { + mirror: false + crop_size: 224 + mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" + # mean_value: 104 + # mean_value: 117 + # mean_value: 123 + } +} +layers { + bottom: "data" + top: "conv1/7x7_s2" + name: "conv1/7x7_s2" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 3 + kernel_size: 7 + stride: 2 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv1/7x7_s2" + top: "conv1/7x7_s2" + name: "conv1/relu_7x7" + type: RELU +} +layers { + bottom: "conv1/7x7_s2" + top: "pool1/3x3_s2" + name: "pool1/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool1/3x3_s2" + top: "pool1/norm1" + name: "pool1/norm1" + type: LRN + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + bottom: "pool1/norm1" + top: "conv2/3x3_reduce" + name: "conv2/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv2/3x3_reduce" + top: "conv2/3x3_reduce" + name: "conv2/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "conv2/3x3_reduce" + top: "conv2/3x3" + name: "conv2/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "conv2/3x3" + top: "conv2/3x3" + name: "conv2/relu_3x3" + type: RELU +} +layers { + bottom: "conv2/3x3" + top: "conv2/norm2" + name: "conv2/norm2" + type: LRN + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + bottom: "conv2/norm2" + top: "pool2/3x3_s2" + name: "pool2/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/1x1" + name: "inception_3a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/1x1" + top: "inception_3a/1x1" + name: "inception_3a/relu_1x1" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/3x3_reduce" + name: "inception_3a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3_reduce" + name: "inception_3a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3" + name: "inception_3a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/3x3" + top: "inception_3a/3x3" + name: "inception_3a/relu_3x3" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/5x5_reduce" + name: "inception_3a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5_reduce" + name: "inception_3a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5" + name: "inception_3a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/5x5" + top: "inception_3a/5x5" + name: "inception_3a/relu_5x5" + type: RELU +} +layers { + bottom: "pool2/3x3_s2" + top: "inception_3a/pool" + name: "inception_3a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_3a/pool" + top: "inception_3a/pool_proj" + name: "inception_3a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3a/pool_proj" + top: "inception_3a/pool_proj" + name: "inception_3a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_3a/1x1" + bottom: "inception_3a/3x3" + bottom: "inception_3a/5x5" + bottom: "inception_3a/pool_proj" + top: "inception_3a/output" + name: "inception_3a/output" + type: CONCAT +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/1x1" + name: "inception_3b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/1x1" + top: "inception_3b/1x1" + name: "inception_3b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/3x3_reduce" + name: "inception_3b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3_reduce" + name: "inception_3b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3" + name: "inception_3b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/3x3" + top: "inception_3b/3x3" + name: "inception_3b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/5x5_reduce" + name: "inception_3b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5_reduce" + name: "inception_3b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5" + name: "inception_3b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/5x5" + top: "inception_3b/5x5" + name: "inception_3b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_3a/output" + top: "inception_3b/pool" + name: "inception_3b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_3b/pool" + top: "inception_3b/pool_proj" + name: "inception_3b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_3b/pool_proj" + top: "inception_3b/pool_proj" + name: "inception_3b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_3b/1x1" + bottom: "inception_3b/3x3" + bottom: "inception_3b/5x5" + bottom: "inception_3b/pool_proj" + top: "inception_3b/output" + name: "inception_3b/output" + type: CONCAT +} +layers { + bottom: "inception_3b/output" + top: "pool3/3x3_s2" + name: "pool3/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/1x1" + name: "inception_4a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/1x1" + top: "inception_4a/1x1" + name: "inception_4a/relu_1x1" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/3x3_reduce" + name: "inception_4a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3_reduce" + name: "inception_4a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3" + name: "inception_4a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 208 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/3x3" + top: "inception_4a/3x3" + name: "inception_4a/relu_3x3" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/5x5_reduce" + name: "inception_4a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5_reduce" + name: "inception_4a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5" + name: "inception_4a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 48 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/5x5" + top: "inception_4a/5x5" + name: "inception_4a/relu_5x5" + type: RELU +} +layers { + bottom: "pool3/3x3_s2" + top: "inception_4a/pool" + name: "inception_4a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4a/pool" + top: "inception_4a/pool_proj" + name: "inception_4a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4a/pool_proj" + top: "inception_4a/pool_proj" + name: "inception_4a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4a/1x1" + bottom: "inception_4a/3x3" + bottom: "inception_4a/5x5" + bottom: "inception_4a/pool_proj" + top: "inception_4a/output" + name: "inception_4a/output" + type: CONCAT +} +layers { + bottom: "inception_4a/output" + top: "loss1/ave_pool" + name: "loss1/ave_pool" + type: POOLING + pooling_param { + pool: AVE + kernel_size: 5 + stride: 3 + } +} +layers { + bottom: "loss1/ave_pool" + top: "loss1/conv" + name: "loss1/conv" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.08 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "loss1/conv" + top: "loss1/conv" + name: "loss1/relu_conv" + type: RELU +} +layers { + bottom: "loss1/conv" + top: "loss1/fc" + name: "loss1/fc" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1024 + weight_filler { + type: "xavier" + std: 0.02 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "loss1/fc" + top: "loss1/fc" + name: "loss1/relu_fc" + type: RELU +} +layers { + bottom: "loss1/fc" + top: "loss1/fc" + name: "loss1/drop_fc" + type: DROPOUT + dropout_param { + dropout_ratio: 0.7 + } +} +layers { + bottom: "loss1/fc" + top: "loss1/classifier" + name: "loss1/classifier" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + std: 0.0009765625 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + bottom: "loss1/classifier" + bottom: "label" + top: "loss1/loss1" + name: "loss1/loss" + type: SOFTMAX_LOSS + loss_weight: 0.3 +} +layers { + bottom: "loss1/classifier" + bottom: "label" + top: "loss1/top-1" + name: "loss1/top-1" + type: ACCURACY + include { + phase: TEST + } +} +layers { + bottom: "loss1/classifier" + bottom: "label" + top: "loss1/top-5" + name: "loss1/top-5" + type: ACCURACY + accuracy_param { + top_k: 5 + } + include { + phase: TEST + } +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/1x1" + name: "inception_4b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/1x1" + top: "inception_4b/1x1" + name: "inception_4b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/3x3_reduce" + name: "inception_4b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3_reduce" + name: "inception_4b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3" + name: "inception_4b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 224 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/3x3" + top: "inception_4b/3x3" + name: "inception_4b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/5x5_reduce" + name: "inception_4b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5_reduce" + name: "inception_4b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5" + name: "inception_4b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/5x5" + top: "inception_4b/5x5" + name: "inception_4b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4a/output" + top: "inception_4b/pool" + name: "inception_4b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4b/pool" + top: "inception_4b/pool_proj" + name: "inception_4b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4b/pool_proj" + top: "inception_4b/pool_proj" + name: "inception_4b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4b/1x1" + bottom: "inception_4b/3x3" + bottom: "inception_4b/5x5" + bottom: "inception_4b/pool_proj" + top: "inception_4b/output" + name: "inception_4b/output" + type: CONCAT +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/1x1" + name: "inception_4c/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/1x1" + top: "inception_4c/1x1" + name: "inception_4c/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/3x3_reduce" + name: "inception_4c/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3_reduce" + name: "inception_4c/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3" + name: "inception_4c/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/3x3" + top: "inception_4c/3x3" + name: "inception_4c/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/5x5_reduce" + name: "inception_4c/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5_reduce" + name: "inception_4c/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5" + name: "inception_4c/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/5x5" + top: "inception_4c/5x5" + name: "inception_4c/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4b/output" + top: "inception_4c/pool" + name: "inception_4c/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4c/pool" + top: "inception_4c/pool_proj" + name: "inception_4c/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4c/pool_proj" + top: "inception_4c/pool_proj" + name: "inception_4c/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4c/1x1" + bottom: "inception_4c/3x3" + bottom: "inception_4c/5x5" + bottom: "inception_4c/pool_proj" + top: "inception_4c/output" + name: "inception_4c/output" + type: CONCAT +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/1x1" + name: "inception_4d/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/1x1" + top: "inception_4d/1x1" + name: "inception_4d/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/3x3_reduce" + name: "inception_4d/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 144 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3_reduce" + name: "inception_4d/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3" + name: "inception_4d/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 288 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/3x3" + top: "inception_4d/3x3" + name: "inception_4d/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/5x5_reduce" + name: "inception_4d/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5_reduce" + name: "inception_4d/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5" + name: "inception_4d/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/5x5" + top: "inception_4d/5x5" + name: "inception_4d/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4c/output" + top: "inception_4d/pool" + name: "inception_4d/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4d/pool" + top: "inception_4d/pool_proj" + name: "inception_4d/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4d/pool_proj" + top: "inception_4d/pool_proj" + name: "inception_4d/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4d/1x1" + bottom: "inception_4d/3x3" + bottom: "inception_4d/5x5" + bottom: "inception_4d/pool_proj" + top: "inception_4d/output" + name: "inception_4d/output" + type: CONCAT +} +layers { + bottom: "inception_4d/output" + top: "loss2/ave_pool" + name: "loss2/ave_pool" + type: POOLING + pooling_param { + pool: AVE + kernel_size: 5 + stride: 3 + } +} +layers { + bottom: "loss2/ave_pool" + top: "loss2/conv" + name: "loss2/conv" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.08 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "loss2/conv" + top: "loss2/conv" + name: "loss2/relu_conv" + type: RELU +} +layers { + bottom: "loss2/conv" + top: "loss2/fc" + name: "loss2/fc" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1024 + weight_filler { + type: "xavier" + std: 0.02 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "loss2/fc" + top: "loss2/fc" + name: "loss2/relu_fc" + type: RELU +} +layers { + bottom: "loss2/fc" + top: "loss2/fc" + name: "loss2/drop_fc" + type: DROPOUT + dropout_param { + dropout_ratio: 0.7 + } +} +layers { + bottom: "loss2/fc" + top: "loss2/classifier" + name: "loss2/classifier" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + std: 0.0009765625 + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + bottom: "loss2/classifier" + bottom: "label" + top: "loss2/loss1" + name: "loss2/loss" + type: SOFTMAX_LOSS + loss_weight: 0.3 +} +layers { + bottom: "loss2/classifier" + bottom: "label" + top: "loss2/top-1" + name: "loss2/top-1" + type: ACCURACY + include { + phase: TEST + } +} +layers { + bottom: "loss2/classifier" + bottom: "label" + top: "loss2/top-5" + name: "loss2/top-5" + type: ACCURACY + accuracy_param { + top_k: 5 + } + include { + phase: TEST + } +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/1x1" + name: "inception_4e/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/1x1" + top: "inception_4e/1x1" + name: "inception_4e/relu_1x1" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/3x3_reduce" + name: "inception_4e/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3_reduce" + name: "inception_4e/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3" + name: "inception_4e/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/3x3" + top: "inception_4e/3x3" + name: "inception_4e/relu_3x3" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/5x5_reduce" + name: "inception_4e/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5_reduce" + name: "inception_4e/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5" + name: "inception_4e/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/5x5" + top: "inception_4e/5x5" + name: "inception_4e/relu_5x5" + type: RELU +} +layers { + bottom: "inception_4d/output" + top: "inception_4e/pool" + name: "inception_4e/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_4e/pool" + top: "inception_4e/pool_proj" + name: "inception_4e/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_4e/pool_proj" + top: "inception_4e/pool_proj" + name: "inception_4e/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_4e/1x1" + bottom: "inception_4e/3x3" + bottom: "inception_4e/5x5" + bottom: "inception_4e/pool_proj" + top: "inception_4e/output" + name: "inception_4e/output" + type: CONCAT +} +layers { + bottom: "inception_4e/output" + top: "pool4/3x3_s2" + name: "pool4/3x3_s2" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/1x1" + name: "inception_5a/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/1x1" + top: "inception_5a/1x1" + name: "inception_5a/relu_1x1" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/3x3_reduce" + name: "inception_5a/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3_reduce" + name: "inception_5a/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3" + name: "inception_5a/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/3x3" + top: "inception_5a/3x3" + name: "inception_5a/relu_3x3" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/5x5_reduce" + name: "inception_5a/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5_reduce" + name: "inception_5a/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5" + name: "inception_5a/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/5x5" + top: "inception_5a/5x5" + name: "inception_5a/relu_5x5" + type: RELU +} +layers { + bottom: "pool4/3x3_s2" + top: "inception_5a/pool" + name: "inception_5a/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_5a/pool" + top: "inception_5a/pool_proj" + name: "inception_5a/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5a/pool_proj" + top: "inception_5a/pool_proj" + name: "inception_5a/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_5a/1x1" + bottom: "inception_5a/3x3" + bottom: "inception_5a/5x5" + bottom: "inception_5a/pool_proj" + top: "inception_5a/output" + name: "inception_5a/output" + type: CONCAT +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/1x1" + name: "inception_5b/1x1" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/1x1" + top: "inception_5b/1x1" + name: "inception_5b/relu_1x1" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/3x3_reduce" + name: "inception_5b/3x3_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3_reduce" + name: "inception_5b/relu_3x3_reduce" + type: RELU +} +layers { + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3" + name: "inception_5b/3x3" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/3x3" + top: "inception_5b/3x3" + name: "inception_5b/relu_3x3" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/5x5_reduce" + name: "inception_5b/5x5_reduce" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 48 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5_reduce" + name: "inception_5b/relu_5x5_reduce" + type: RELU +} +layers { + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5" + name: "inception_5b/5x5" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/5x5" + top: "inception_5b/5x5" + name: "inception_5b/relu_5x5" + type: RELU +} +layers { + bottom: "inception_5a/output" + top: "inception_5b/pool" + name: "inception_5b/pool" + type: POOLING + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layers { + bottom: "inception_5b/pool" + top: "inception_5b/pool_proj" + name: "inception_5b/pool_proj" + type: CONVOLUTION + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layers { + bottom: "inception_5b/pool_proj" + top: "inception_5b/pool_proj" + name: "inception_5b/relu_pool_proj" + type: RELU +} +layers { + bottom: "inception_5b/1x1" + bottom: "inception_5b/3x3" + bottom: "inception_5b/5x5" + bottom: "inception_5b/pool_proj" + top: "inception_5b/output" + name: "inception_5b/output" + type: CONCAT +} +layers { + bottom: "inception_5b/output" + top: "pool5/7x7_s1" + name: "pool5/7x7_s1" + type: POOLING + pooling_param { + pool: AVE + kernel_size: 7 + stride: 1 + } +} +layers { + bottom: "pool5/7x7_s1" + top: "pool5/7x7_s1" + name: "pool5/drop_7x7_s1" + type: DROPOUT + dropout_param { + dropout_ratio: 0.4 + } +} +layers { + bottom: "pool5/7x7_s1" + top: "loss3/classifier" + name: "loss3/classifier" + type: INNER_PRODUCT + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layers { + bottom: "loss3/classifier" + bottom: "label" + top: "loss3/loss3" + name: "loss3/loss3" + type: SOFTMAX_LOSS + loss_weight: 1 +} +layers { + bottom: "loss3/classifier" + bottom: "label" + top: "loss3/top-1" + name: "loss3/top-1" + type: ACCURACY + include { + phase: TEST + } +} +layers { + bottom: "loss3/classifier" + bottom: "label" + top: "loss3/top-5" + name: "loss3/top-5" + type: ACCURACY + accuracy_param { + top_k: 5 + } + include { + phase: TEST + } +} From b99e6cdcaf10196b901cfa870d9ca5f7d9d886bf Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 20 Dec 2014 23:24:32 -0800 Subject: [PATCH 192/798] Added credits for training bvlc models --- models/bvlc_alexnet/readme.md | 2 ++ models/bvlc_googlenet/readme.md | 2 ++ models/bvlc_reference_caffenet/readme.md | 2 ++ models/bvlc_reference_rcnn_ilsvrc13/readme.md | 2 ++ models/finetune_flickr_style/readme.md | 2 ++ 5 files changed, 10 insertions(+) diff --git a/models/bvlc_alexnet/readme.md b/models/bvlc_alexnet/readme.md index 20c393ff26b..c25fd4f8018 100644 --- a/models/bvlc_alexnet/readme.md +++ b/models/bvlc_alexnet/readme.md @@ -18,6 +18,8 @@ The best validation performance during training was iteration 358,000 with valid This model obtains a top-1 accuracy 57.1% and a top-5 accuracy 80.2% on the validation set, using just the center crop. (Using the average of 10 crops, (4 + 1 center) * 2 mirror, should obtain a bit higher accuracy.) +This model was trained by Evan Shelhamer @shelhamer + ## License The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: diff --git a/models/bvlc_googlenet/readme.md b/models/bvlc_googlenet/readme.md index 27022d3384a..8a3bbec4f8b 100644 --- a/models/bvlc_googlenet/readme.md +++ b/models/bvlc_googlenet/readme.md @@ -5,6 +5,7 @@ caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel license: non-commercial sha1: 405fc5acd08a3bb12de8ee5e23a96bec22f08204 caffe_commit: bc614d1bd91896e3faceaf40b23b72dab47d44f5 +gist_id: 866e2aa1fd707b89b913 --- This model is a replication of the model described in the [GoogleNet](http://arxiv.org/abs/1409.4842) publication. We would like to thank Christian Szegedy for all his help in the replication of GoogleNet model. @@ -25,6 +26,7 @@ Timings for bvlc_googlenet with cuDNN using batch_size:128 on a K40c: - Average Backward pass: 1123.84 ms. - Average Forward-Backward: 1688.8 ms. +This model was trained by Sergio Guadarrama @sguada ## License diff --git a/models/bvlc_reference_caffenet/readme.md b/models/bvlc_reference_caffenet/readme.md index d1c6269ae73..b867e7386a3 100644 --- a/models/bvlc_reference_caffenet/readme.md +++ b/models/bvlc_reference_caffenet/readme.md @@ -18,6 +18,8 @@ The best validation performance during training was iteration 313,000 with valid This model obtains a top-1 accuracy 57.4% and a top-5 accuracy 80.4% on the validation set, using just the center crop. (Using the average of 10 crops, (4 + 1 center) * 2 mirror, should obtain a bit higher accuracy still.) +This model was trained by Jeff Donahue @jeffdonahue + ## License The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: diff --git a/models/bvlc_reference_rcnn_ilsvrc13/readme.md b/models/bvlc_reference_rcnn_ilsvrc13/readme.md index fb8f26d15df..5d4bc5afe32 100644 --- a/models/bvlc_reference_rcnn_ilsvrc13/readme.md +++ b/models/bvlc_reference_rcnn_ilsvrc13/readme.md @@ -13,6 +13,8 @@ Try the [detection example](http://nbviewer.ipython.org/github/BVLC/caffe/blob/m *N.B. For research purposes, make use of the official R-CNN package and not this example.* +This model was trained by Ross Girshick @rbgirshick + ## License The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: diff --git a/models/finetune_flickr_style/readme.md b/models/finetune_flickr_style/readme.md index d2a8a95f669..aac7f7c96e8 100644 --- a/models/finetune_flickr_style/readme.md +++ b/models/finetune_flickr_style/readme.md @@ -15,6 +15,8 @@ The final performance: I1017 07:36:17.370730 31333 solver.cpp:247] Iteration 100000, Testing net (#0) I1017 07:36:34.248730 31333 solver.cpp:298] Test net output #0: accuracy = 0.3916 +This model was trained by Sergey Karayev @sergeyk + ## License The Flickr Style dataset contains only URLs to images. From 43357d089484efdad843f79b4efcd83c7b74ed6e Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 20 Dec 2014 23:28:19 -0800 Subject: [PATCH 193/798] Added credits and bvlc_googlenet to model_zoo.md --- docs/model_zoo.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/model_zoo.md b/docs/model_zoo.md index 330850cbbd6..358bbb7fc91 100644 --- a/docs/model_zoo.md +++ b/docs/model_zoo.md @@ -15,9 +15,10 @@ To lower the friction of sharing these models, we introduce the model zoo framew First of all, we provide some trained models out of the box. Each one of these can be downloaded by running `scripts/download_model_binary.py ` where `` is specified below: -- **BVLC Reference CaffeNet** in `models/bvlc_reference_caffenet`: AlexNet trained on ILSVRC 2012, with a minor variation from the version as described in the NIPS 2012 paper. -- **BVLC AlexNet** in `models/bvlc_alexnet`: AlexNet trained on ILSVRC 2012, almost exactly as described in NIPS 2012. -- **BVLC Reference R-CNN ILSVRC-2013** in `models/bvlc_reference_rcnn_ilsvrc13`: pure Caffe implementation of [R-CNN](https://github.com/rbgirshick/rcnn). +- **BVLC Reference CaffeNet** in `models/bvlc_reference_caffenet`: AlexNet trained on ILSVRC 2012, with a minor variation from the version as described in the NIPS 2012 paper. (Trained by Jeff Donahue @jeffdonahue) +- **BVLC AlexNet** in `models/bvlc_alexnet`: AlexNet trained on ILSVRC 2012, almost exactly as described in NIPS 2012. (Trained by Evan Shelhamer @shelhamer) +- **BVLC Reference R-CNN ILSVRC-2013** in `models/bvlc_reference_rcnn_ilsvrc13`: pure Caffe implementation of [R-CNN](https://github.com/rbgirshick/rcnn). (Trained by Ross Girshick @rbgirshick) +- **BVLC GoogleNet** in `models/bvlc_googlenet`: GoogleNet trained on ILSVRC 2012, almost exactly as described in [GoogleNet](http://arxiv.org/abs/1409.4842). (Trained by Sergio Guadarrama @sguada) User-provided models are posted to a public-editable [wiki page](https://github.com/BVLC/caffe/wiki/Model-Zoo). From d00c465a69541a1b82d6171d44f266b419c62b43 Mon Sep 17 00:00:00 2001 From: Sergio Date: Sun, 21 Dec 2014 14:03:49 -0800 Subject: [PATCH 194/798] Warning of fallback only the first time for cudnn_pooling_layer --- src/caffe/layers/cudnn_pooling_layer.cu | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/caffe/layers/cudnn_pooling_layer.cu b/src/caffe/layers/cudnn_pooling_layer.cu index 99c409dcc96..7cdc0afadcb 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cu +++ b/src/caffe/layers/cudnn_pooling_layer.cu @@ -14,7 +14,8 @@ void CuDNNPoolingLayer::Forward_gpu(const vector*>& bottom, vector*>* top) { // Fallback to Caffe for padded pooling, max top mask. if ((this->pad_h_ > 0 || this->pad_w_ > 0) || (*top).size() > 1) { - LOG(WARNING) << "Falling back to standard Caffe for padded pooling."; + LOG_FIRST_N(WARNING, 1) + << "Falling back to standard Caffe for padded pooling."; return PoolingLayer::Forward_gpu(bottom, top); } @@ -33,7 +34,8 @@ void CuDNNPoolingLayer::Backward_gpu(const vector*>& top, // Fallback to Caffe for padded pooling, max top mask. if ((this->pad_h_ > 0 || this->pad_w_ > 0) || top.size() > 1) { - LOG(WARNING) << "Falling back to standard Caffe for padded pooling."; + LOG_FIRST_N(WARNING, 1) + << "Falling back to standard Caffe for padded pooling."; return PoolingLayer::Backward_gpu(top, propagate_down, bottom); } From b00445630bef5db71dc4e9346b8da62cb4c2e2b5 Mon Sep 17 00:00:00 2001 From: "Peihao.Huang" Date: Tue, 23 Dec 2014 11:18:51 +0800 Subject: [PATCH 195/798] switch cifar10 example to lmdb --- examples/cifar10/cifar10_full_train_test.prototxt | 6 ++++-- examples/cifar10/cifar10_quick_train_test.prototxt | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/cifar10/cifar10_full_train_test.prototxt b/examples/cifar10/cifar10_full_train_test.prototxt index 8fde19f046e..38cc04f4a68 100644 --- a/examples/cifar10/cifar10_full_train_test.prototxt +++ b/examples/cifar10/cifar10_full_train_test.prototxt @@ -5,8 +5,9 @@ layers { top: "data" top: "label" data_param { - source: "examples/cifar10/cifar10_train_leveldb" + source: "examples/cifar10/cifar10_train_lmdb" batch_size: 100 + backend: LMDB } transform_param { mean_file: "examples/cifar10/mean.binaryproto" @@ -19,8 +20,9 @@ layers { top: "data" top: "label" data_param { - source: "examples/cifar10/cifar10_test_leveldb" + source: "examples/cifar10/cifar10_test_lmdb" batch_size: 100 + backend: LMDB } transform_param { mean_file: "examples/cifar10/mean.binaryproto" diff --git a/examples/cifar10/cifar10_quick_train_test.prototxt b/examples/cifar10/cifar10_quick_train_test.prototxt index 409cfe809f4..074bb0011e3 100644 --- a/examples/cifar10/cifar10_quick_train_test.prototxt +++ b/examples/cifar10/cifar10_quick_train_test.prototxt @@ -5,8 +5,9 @@ layers { top: "data" top: "label" data_param { - source: "examples/cifar10/cifar10_train_leveldb" + source: "examples/cifar10/cifar10_train_lmdb" batch_size: 100 + backend: LMDB } transform_param { mean_file: "examples/cifar10/mean.binaryproto" @@ -19,8 +20,9 @@ layers { top: "data" top: "label" data_param { - source: "examples/cifar10/cifar10_test_leveldb" + source: "examples/cifar10/cifar10_test_lmdb" batch_size: 100 + backend: LMDB } transform_param { mean_file: "examples/cifar10/mean.binaryproto" From 0d21a1f8826a04c18058449c0bd1a3c64b939c44 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sat, 27 Dec 2014 01:47:59 -0800 Subject: [PATCH 196/798] update use of GetLayer -> LayerRegistry::CreateLayer --- src/caffe/net.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 21ab15fd31b..e4492cfd6e3 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -62,7 +62,8 @@ void Net::Init(const NetParameter& in_param) { bottom_need_backward_.resize(param.layers_size()); for (int layer_id = 0; layer_id < param.layers_size(); ++layer_id) { const LayerParameter& layer_param = param.layers(layer_id); - layers_.push_back(shared_ptr >(GetLayer(layer_param))); + layers_.push_back(shared_ptr >( + LayerRegistry::CreateLayer(layer_param))); layer_names_.push_back(layer_param.name()); LOG(INFO) << "Creating Layer " << layer_param.name(); bool need_backward = false; From fba2471ab7e94fc6c6ae5984d58f643716dcec91 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 24 Nov 2014 13:37:06 -0800 Subject: [PATCH 197/798] automatic dependency generation --- Makefile | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 54d5636135d..75619c01da0 100644 --- a/Makefile +++ b/Makefile @@ -30,8 +30,6 @@ DYNAMIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so ############################## # CXX_SRCS are the source files excluding the test ones. CXX_SRCS := $(shell find src/$(PROJECT) ! -name "test_*.cpp" -name "*.cpp") -# HXX_SRCS are the header files -HXX_SRCS := $(shell find include/$(PROJECT) ! -name "test_*.hpp" -name "*.hpp") # CU_SRCS are the cuda source files CU_SRCS := $(shell find src/$(PROJECT) ! -name "test_*.cu" -name "*.cu") # TEST_SRCS are the test source files @@ -40,8 +38,6 @@ TEST_SRCS := $(shell find src/$(PROJECT) -name "test_*.cpp") TEST_SRCS := $(filter-out $(TEST_MAIN_SRC), $(TEST_SRCS)) TEST_CU_SRCS := $(shell find src/$(PROJECT) -name "test_*.cu") GTEST_SRC := src/gtest/gtest-all.cpp -# TEST_HXX_SRCS are the test header files -TEST_HXX_SRCS := $(shell find include/$(PROJECT) -name "test_*.hpp") # TOOL_SRCS are the source files for the tool binaries TOOL_SRCS := $(shell find tools -name "*.cpp") # EXAMPLE_SRCS are the source files for the example binaries @@ -90,7 +86,6 @@ PROTO_GEN_HEADER_SRCS := $(addprefix $(PROTO_BUILD_DIR)/, \ $(notdir ${PROTO_SRCS:.proto=.pb.h})) PROTO_GEN_HEADER := $(addprefix $(PROTO_BUILD_INCLUDE_DIR)/, \ $(notdir ${PROTO_SRCS:.proto=.pb.h})) -HXX_SRCS += $(PROTO_GEN_HEADER) PROTO_GEN_CC := $(addprefix $(BUILD_DIR)/, ${PROTO_SRCS:.proto=.pb.cc}) PY_PROTO_BUILD_DIR := python/$(PROJECT)/proto PY_PROTO_INIT := python/$(PROJECT)/proto/__init__.py @@ -113,6 +108,9 @@ TEST_CU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${TEST_CU_SRCS:.cu=.o}) TEST_OBJS := $(TEST_CXX_OBJS) $(TEST_CU_OBJS) GTEST_OBJ := $(addprefix $(BUILD_DIR)/, ${GTEST_SRC:.cpp=.o}) EXAMPLE_OBJS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o}) +# Output files for automatic dependency generation +DEPS := ${CXX_OBJS:.o=.d} ${CU_OBJS:.o=.d} ${TEST_CXX_OBJS:.o=.d} \ + ${TEST_CU_OBJS:.o=.d} # tool, example, and test bins TOOL_BINS := ${TOOL_OBJS:.o=.bin} EXAMPLE_BINS := ${EXAMPLE_OBJS:.o=.bin} @@ -316,6 +314,9 @@ LIBRARY_DIRS += $(BLAS_LIB) LIBRARY_DIRS += $(LIB_BUILD_DIR) +# Automatic dependency generation (nvcc is handled separately) +CXXFLAGS += -MMD -MP + # Complete build flags. COMMON_FLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir)) CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) @@ -464,7 +465,7 @@ $(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) ar rcs $@ $(OBJS) @ echo -$(BUILD_DIR)/%.o: %.cpp $(HXX_SRCS) | $(ALL_BUILD_DIRS) +$(BUILD_DIR)/%.o: %.cpp | $(ALL_BUILD_DIRS) $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ || (cat $@.$(WARNS_EXT); exit 1) @ cat $@.$(WARNS_EXT) @@ -477,7 +478,9 @@ $(PROTO_BUILD_DIR)/%.pb.o: $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_GEN_HEADER) \ @ cat $@.$(WARNS_EXT) @ echo -$(BUILD_DIR)/%.cuo: %.cu $(HXX_SRCS) | $(ALL_BUILD_DIRS) +$(BUILD_DIR)/cuda/%.o: %.cu | $(ALL_BUILD_DIRS) + $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -M $< -o ${@:.o=.d} \ + -odir $(@D) $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \ || (cat $@.$(WARNS_EXT); exit 1) @ cat $@.$(WARNS_EXT) @@ -564,7 +567,7 @@ superclean: clean supercleanfiles $(DIST_ALIASES): $(DISTRIBUTE_DIR) -$(DISTRIBUTE_DIR): all py $(HXX_SRCS) | $(DISTRIBUTE_SUBDIRS) +$(DISTRIBUTE_DIR): all py | $(DISTRIBUTE_SUBDIRS) # add include cp -r include $(DISTRIBUTE_DIR)/ mkdir -p $(DISTRIBUTE_DIR)/include/caffe/proto @@ -577,3 +580,5 @@ $(DISTRIBUTE_DIR): all py $(HXX_SRCS) | $(DISTRIBUTE_SUBDIRS) cp $(DYNAMIC_NAME) $(DISTRIBUTE_DIR)/lib # add python - it's not the standard way, indeed... cp -r python $(DISTRIBUTE_DIR)/python + +-include $(DEPS) From b0f45a90029797d13e31e024605a1baa478bc7bd Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 11 Dec 2014 14:45:38 -0800 Subject: [PATCH 198/798] pretty the build with the Q variable Unset Q (in the environment) to see full commands, or edit in Makefile.config. --- Makefile | 60 ++++++++++++++++++++--------------------- Makefile.config.example | 3 +++ 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 75619c01da0..ea97392d8ef 100644 --- a/Makefile +++ b/Makefile @@ -402,10 +402,10 @@ py$(PROJECT): py py: $(PY$(PROJECT)_SO) $(PROTO_GEN_PY) -$(PY$(PROJECT)_SO): $(STATIC_NAME) $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX_SRC) - $(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \ +$(PY$(PROJECT)_SO): $(PY$(PROJECT)_SRC) $(STATIC_NAME) $(PY$(PROJECT)_HXX_SRC) + @ echo CXX $< + $(Q)$(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \ $(STATIC_LINK_COMMAND) $(LINKFLAGS) $(PYTHON_LDFLAGS) - @ echo mat$(PROJECT): mat @@ -417,11 +417,11 @@ $(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME) "to build mat$(PROJECT)."; \ exit 1; \ fi - $(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_SRC) \ + @ echo MEX $< + $(Q)$(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_SRC) \ CXX="$(CXX)" \ CXXFLAGS="\$$CXXFLAGS $(MATLAB_CXXFLAGS)" \ CXXLIBS="\$$CXXLIBS $(STATIC_LINK_COMMAND) $(LDFLAGS)" -output $@ - @ echo runtest: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN) $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) && \ @@ -458,57 +458,57 @@ $(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK) @ mkdir -p $@ $(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) - $(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) - @ echo + @ echo LD $< + $(Q)$(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) $(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) - ar rcs $@ $(OBJS) - @ echo + @ echo AR $< + $(Q)ar rcs $@ $(OBJS) $(BUILD_DIR)/%.o: %.cpp | $(ALL_BUILD_DIRS) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ + @ echo CXX $< + $(Q)$(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ || (cat $@.$(WARNS_EXT); exit 1) @ cat $@.$(WARNS_EXT) - @ echo $(PROTO_BUILD_DIR)/%.pb.o: $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_GEN_HEADER) \ | $(PROTO_BUILD_DIR) - $(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ + @ echo CXX $< + $(Q)$(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \ || (cat $@.$(WARNS_EXT); exit 1) @ cat $@.$(WARNS_EXT) - @ echo $(BUILD_DIR)/cuda/%.o: %.cu | $(ALL_BUILD_DIRS) - $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -M $< -o ${@:.o=.d} \ + @ echo NVCC $< + $(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -M $< -o ${@:.o=.d} \ -odir $(@D) - $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \ + $(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \ || (cat $@.$(WARNS_EXT); exit 1) @ cat $@.$(WARNS_EXT) - @ echo $(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \ | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ + @ echo CXX/LD -o $@ $< + $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) - @ echo $(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(DYNAMIC_NAME) \ | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ + @ echo CXX/LD -o $@ $< + $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(LIB_BUILD_DIR) - @ echo $(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CU_BUILD_DIR)/%.o \ $(GTEST_OBJ) $(STATIC_NAME) | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ + @ echo LD $< + $(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) - @ echo $(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CXX_BUILD_DIR)/%.o \ $(GTEST_OBJ) $(STATIC_NAME) | $(TEST_BIN_DIR) - $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ + @ echo LD $< + $(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) - @ echo # Target for extension-less symlinks to tool binaries with extension '*.bin'. $(TOOL_BUILD_DIR)/%: $(TOOL_BUILD_DIR)/%.bin | $(TOOL_BUILD_DIR) @@ -516,20 +516,20 @@ $(TOOL_BUILD_DIR)/%: $(TOOL_BUILD_DIR)/%.bin | $(TOOL_BUILD_DIR) @ ln -s $(abspath $<) $@ $(TOOL_BINS) $(EXAMPLE_BINS): %.bin : %.o $(STATIC_NAME) - $(CXX) $< $(STATIC_LINK_COMMAND) -o $@ $(LINKFLAGS) $(LDFLAGS) - @ echo + @ echo LD $< + $(Q)$(CXX) $< $(STATIC_LINK_COMMAND) -o $@ $(LINKFLAGS) $(LDFLAGS) proto: $(PROTO_GEN_CC) $(PROTO_GEN_HEADER) $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_BUILD_DIR)/%.pb.h : \ $(PROTO_SRC_DIR)/%.proto | $(PROTO_BUILD_DIR) - protoc --proto_path=$(PROTO_SRC_DIR) --cpp_out=$(PROTO_BUILD_DIR) $< - @ echo + @ echo PROTOC $< + $(Q)protoc --proto_path=$(PROTO_SRC_DIR) --cpp_out=$(PROTO_BUILD_DIR) $< $(PY_PROTO_BUILD_DIR)/%_pb2.py : $(PROTO_SRC_DIR)/%.proto \ $(PY_PROTO_INIT) | $(PY_PROTO_BUILD_DIR) - protoc --proto_path=$(PROTO_SRC_DIR) --python_out=$(PY_PROTO_BUILD_DIR) $< - @ echo + @ echo PROTOC \(python\) $< + $(Q)protoc --proto_path=$(PROTO_SRC_DIR) --python_out=$(PY_PROTO_BUILD_DIR) $< $(PY_PROTO_INIT): | $(PY_PROTO_BUILD_DIR) touch $(PY_PROTO_INIT) diff --git a/Makefile.config.example b/Makefile.config.example index e11db51395d..0c996038a7c 100644 --- a/Makefile.config.example +++ b/Makefile.config.example @@ -74,3 +74,6 @@ DISTRIBUTE_DIR := distribute # The ID of the GPU that 'make runtest' will use to run unit tests. TEST_GPUID := 0 + +# enable pretty build (comment to see full commands) +Q ?= @ From b91d0ab112720b3354314b58914d7c1054695251 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 28 Dec 2014 18:03:45 -0800 Subject: [PATCH 199/798] remove unused GetLayer function (replaced by LayerRegistry::CreateLayer) --- include/caffe/layer_factory.hpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/include/caffe/layer_factory.hpp b/include/caffe/layer_factory.hpp index b86d53346d9..c1fd6aa0d43 100644 --- a/include/caffe/layer_factory.hpp +++ b/include/caffe/layer_factory.hpp @@ -113,17 +113,6 @@ class LayerRegisterer { } \ REGISTER_LAYER_CREATOR(type, Creator_##clsname) -// A function to get a specific layer from the specification given in -// LayerParameter. Ideally this would be replaced by a factory pattern, -// but we will leave it this way for now. -// Yangqing's note: With LayerRegistry, we no longer need this thin wrapper any -// more. It is provided here for backward compatibility and should be removed in -// the future. -template -Layer* GetLayer(const LayerParameter& param) { - return LayerRegistry::CreateLayer(param); -} - } // namespace caffe #endif // CAFFE_LAYER_FACTORY_H_ From ace55bbe1b9b97004d53ff29ea172c3df1142f25 Mon Sep 17 00:00:00 2001 From: Daniel Golden Date: Tue, 2 Dec 2014 11:20:58 -0800 Subject: [PATCH 200/798] Better instructions for updating Homebrew after modifying formulae Previous instructions glossed over how to deal with OpenCV-related update problems --- docs/installation.md | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 207e17d1539..c667cd8ce01 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -208,28 +208,39 @@ If you're not using Anaconda, include `hdf5` in the list above. Aborting Error: Failure while executing: git pull -q origin refs/heads/master:refs/remotes/origin/master -One solution is to commit your changes to a separate Homebrew branch, run `brew update`, and rebase your changes onto the updated master, as follows: +One solution is to commit your changes to a separate Homebrew branch, run `brew update`, and rebase your changes onto the updated master. You'll have to do this both for the main Homebrew repository in `/usr/local/` and the Homebrew science repository that contains OpenCV in `/usr/local/Library/Taps/homebrew/homebrew-science`, as follows: cd /usr/local git checkout -b caffe git add . git commit -m "Update Caffe dependencies to use libstdc++" + cd /usr/local/Library/Taps/homebrew/homebrew-science + git checkout -b caffe + git add . + git commit -m "Update Caffe dependencies" + +Then, whenever you want to update homebrew, switch back to the master branches, do the update, rebase the caffe branches onto master and fix any conflicts: + + # Switch batch to homebrew master branches + cd /usr/local + git checkout master + cd /usr/local/Library/Taps/homebrew/homebrew-science git checkout master + + # Update homebrew; hopefully this works without errors! brew update + + # Switch back to the caffe branches with the forumlae that you modified earlier + cd /usr/local git rebase master caffe - # Resolve any merge conflicts here - git checkout caffe - -At this point, you should be running the latest Homebrew packages and your Caffe-related modifications will remain in place. You may still get the following error: - - $ brew update - error: Your local changes to the following files would be overwritten by merge: - opencv.rb - Please, commit your changes or stash them before you can merge. - Aborting - Error: Failed to update tap: homebrew/science + # Fix any merge conflicts and commit to caffe branch + cd /usr/local/Library/Taps/homebrew/homebrew-science + git rebase master caffe + # Fix any merge conflicts and commit to caffe branch + + # Done! -but non-OpenCV packages will still update as expected. +At this point, you should be running the latest Homebrew packages and your Caffe-related modifications will remain in place. #### Windows From 150da0ebcfe96b236d68b5938d510dd18647bb26 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 28 Dec 2014 20:57:37 -0800 Subject: [PATCH 201/798] [scripts] fix find warnings in upload_model_to_gist.sh --- scripts/upload_model_to_gist.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upload_model_to_gist.sh b/scripts/upload_model_to_gist.sh index 2dfbabd72a3..3c4fd64e3fc 100755 --- a/scripts/upload_model_to_gist.sh +++ b/scripts/upload_model_to_gist.sh @@ -7,7 +7,7 @@ if [ ! -f $DIRNAME/readme.md ]; then echo " /readme.md must exist" fi cd $DIRNAME -FILES=`find . -type f -maxdepth 1 ! -name "*.caffemodel*" | xargs echo` +FILES=`find . -maxdepth 1 -type f ! -name "*.caffemodel*" | xargs echo` # Check for gist tool. gist -v >/dev/null 2>&1 || { echo >&2 "I require 'gist' but it's not installed. Do 'gem install gist'."; exit 1; } From e348fdd73d67ff4615cb860886e9af21ed9d3d18 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Mon, 29 Dec 2014 15:13:59 -0500 Subject: [PATCH 202/798] [docs] groom model zoo intro + list --- docs/model_zoo.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/model_zoo.md b/docs/model_zoo.md index 358bbb7fc91..97025483c58 100644 --- a/docs/model_zoo.md +++ b/docs/model_zoo.md @@ -3,8 +3,10 @@ title: Model Zoo --- # Caffe Model Zoo -Lots of people have used Caffe to train models of different architectures and applied to different problems, ranging from simple regression to AlexNet-alikes to Siamese networks for image similarity to speech applications. -To lower the friction of sharing these models, we introduce the model zoo framework: +Lots of researchers and engineers have made Caffe models for different tasks with all kinds of architectures and data. +These models are learned and applied for problems ranging from simple regression, to large-scale visual classification, to Siamese networks for image similarity, to speech and robotics applications. + +To help share these models, we introduce the model zoo framework: - A standard format for packaging Caffe model info. - Tools to upload/download model info to/from Github Gists, and to download trained `.caffemodel` binaries. @@ -15,10 +17,10 @@ To lower the friction of sharing these models, we introduce the model zoo framew First of all, we provide some trained models out of the box. Each one of these can be downloaded by running `scripts/download_model_binary.py ` where `` is specified below: -- **BVLC Reference CaffeNet** in `models/bvlc_reference_caffenet`: AlexNet trained on ILSVRC 2012, with a minor variation from the version as described in the NIPS 2012 paper. (Trained by Jeff Donahue @jeffdonahue) -- **BVLC AlexNet** in `models/bvlc_alexnet`: AlexNet trained on ILSVRC 2012, almost exactly as described in NIPS 2012. (Trained by Evan Shelhamer @shelhamer) -- **BVLC Reference R-CNN ILSVRC-2013** in `models/bvlc_reference_rcnn_ilsvrc13`: pure Caffe implementation of [R-CNN](https://github.com/rbgirshick/rcnn). (Trained by Ross Girshick @rbgirshick) -- **BVLC GoogleNet** in `models/bvlc_googlenet`: GoogleNet trained on ILSVRC 2012, almost exactly as described in [GoogleNet](http://arxiv.org/abs/1409.4842). (Trained by Sergio Guadarrama @sguada) +- **BVLC Reference CaffeNet** in `models/bvlc_reference_caffenet`: AlexNet trained on ILSVRC 2012, with a minor variation from the version as described in [ImageNet classification with deep convolutional neural networks](http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks) by Krizhevsky et al. in NIPS 2012. (Trained by Jeff Donahue @jeffdonahue) +- **BVLC AlexNet** in `models/bvlc_alexnet`: AlexNet trained on ILSVRC 2012, almost exactly as described in [ImageNet classification with deep convolutional neural networks](http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks) by Krizhevsky et al. in NIPS 2012. (Trained by Evan Shelhamer @shelhamer) +- **BVLC Reference R-CNN ILSVRC-2013** in `models/bvlc_reference_rcnn_ilsvrc13`: pure Caffe implementation of [R-CNN](https://github.com/rbgirshick/rcnn) as described by Girshick et al. in CVPR 2014. (Trained by Ross Girshick @rbgirshick) +- **BVLC GoogLeNet** in `models/bvlc_googlenet`: GoogLeNet trained on ILSVRC 2012, almost exactly as described in [Going Deeper with Convolutions](http://arxiv.org/abs/1409.4842) by Szegedy et al. in ILSVRC 2014. (Trained by Sergio Guadarrama @sguada) User-provided models are posted to a public-editable [wiki page](https://github.com/BVLC/caffe/wiki/Model-Zoo). @@ -36,11 +38,11 @@ A caffe model is distributed as a directory containing: - License information. - [optional] Other helpful scripts. -## Hosting model info +### Hosting model info Github Gist is a good format for model info distribution because it can contain multiple files, is versionable, and has in-browser syntax highlighting and markdown rendering. -- `scripts/upload_model_to_gist.sh `: uploads non-binary files in the model directory as a Github Gist and prints the Gist ID. If `gist_id` is already part of the `/readme.md` frontmatter, then updates existing Gist. +`scripts/upload_model_to_gist.sh ` uploads non-binary files in the model directory as a Github Gist and prints the Gist ID. If `gist_id` is already part of the `/readme.md` frontmatter, then updates existing Gist. Try doing `scripts/upload_model_to_gist.sh models/bvlc_alexnet` to test the uploading (don't forget to delete the uploaded gist afterward). @@ -52,4 +54,4 @@ It is up to the user where to host the `.caffemodel` file. We host our BVLC-provided models on our own server. Dropbox also works fine (tip: make sure that `?dl=1` is appended to the end of the URL). -- `scripts/download_model_binary.py `: downloads the `.caffemodel` from the URL specified in the `/readme.md` frontmatter and confirms SHA1. +`scripts/download_model_binary.py ` downloads the `.caffemodel` from the URL specified in the `/readme.md` frontmatter and confirms SHA1. From 6b842060a46fae212abd1b6b783730a2fc709c7f Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Mon, 29 Dec 2014 16:23:18 -0500 Subject: [PATCH 203/798] [docs] open release of BVLC models for unrestricted use See BVLC model license details on the model zoo page. --- docs/model_zoo.md | 17 +++++++++++++++-- examples/classification.ipynb | 2 +- models/bvlc_alexnet/readme.md | 4 +--- models/bvlc_googlenet/readme.md | 4 +--- models/bvlc_reference_caffenet/readme.md | 4 +--- models/bvlc_reference_rcnn_ilsvrc13/readme.md | 4 +--- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/model_zoo.md b/docs/model_zoo.md index 97025483c58..06dc0a49ec7 100644 --- a/docs/model_zoo.md +++ b/docs/model_zoo.md @@ -14,7 +14,9 @@ To help share these models, we introduce the model zoo framework: ## Where to get trained models -First of all, we provide some trained models out of the box. +First of all, we bundle BVLC-trained models for unrestricted, out of the box use. +
+See the [BVLC model license](#bvlc-model-license) for details. Each one of these can be downloaded by running `scripts/download_model_binary.py ` where `` is specified below: - **BVLC Reference CaffeNet** in `models/bvlc_reference_caffenet`: AlexNet trained on ILSVRC 2012, with a minor variation from the version as described in [ImageNet classification with deep convolutional neural networks](http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks) by Krizhevsky et al. in NIPS 2012. (Trained by Jeff Donahue @jeffdonahue) @@ -22,7 +24,9 @@ Each one of these can be downloaded by running `scripts/download_model_binary.py - **BVLC Reference R-CNN ILSVRC-2013** in `models/bvlc_reference_rcnn_ilsvrc13`: pure Caffe implementation of [R-CNN](https://github.com/rbgirshick/rcnn) as described by Girshick et al. in CVPR 2014. (Trained by Ross Girshick @rbgirshick) - **BVLC GoogLeNet** in `models/bvlc_googlenet`: GoogLeNet trained on ILSVRC 2012, almost exactly as described in [Going Deeper with Convolutions](http://arxiv.org/abs/1409.4842) by Szegedy et al. in ILSVRC 2014. (Trained by Sergio Guadarrama @sguada) -User-provided models are posted to a public-editable [wiki page](https://github.com/BVLC/caffe/wiki/Model-Zoo). +**Community models** made by Caffe users are posted to a publicly editable [wiki page](https://github.com/BVLC/caffe/wiki/Model-Zoo). +These models are subject to conditions of their respective authors such as citation and license. +Thank you for sharing your models! ## Model info format @@ -55,3 +59,12 @@ We host our BVLC-provided models on our own server. Dropbox also works fine (tip: make sure that `?dl=1` is appended to the end of the URL). `scripts/download_model_binary.py ` downloads the `.caffemodel` from the URL specified in the `/readme.md` frontmatter and confirms SHA1. + +## BVLC model license + +The Caffe models bundled by the BVLC are released for unrestricted use. + +These models are trained on data from the [ImageNet project](http://www.image-net.org/) and training data includes internet photos that may be subject to copyright. + +Our present understanding as researchers is that there is no restriction placed on the open release of these learned model weights, since none of the original images are distributed in whole or in part. +To the extent that the interpretation arises that weights are derivative works of the original copyright holder and they assert such a copyright, UC Berkeley makes no representations as to what use is allowed other than to consider our present release in the spirit of fair use in the academic mission of the university to disseminate knowledge and tools as broadly as possible without restriction. diff --git a/examples/classification.ipynb b/examples/classification.ipynb index fb44da8958f..1e2126fe652 100644 --- a/examples/classification.ipynb +++ b/examples/classification.ipynb @@ -19,7 +19,7 @@ "\n", "Caffe provides a general Python interface for models with `caffe.Net` in `python/caffe/pycaffe.py`, but to make off-the-shelf classification easy we provide a `caffe.Classifier` class and `classify.py` script. Both Python and MATLAB wrappers are provided. However, the Python wrapper has more features so we will describe it here. For MATLAB, refer to `matlab/caffe/matcaffe_demo.m`.\n", "\n", - "Before we begin, you must compile Caffe and install the python wrapper by setting your `PYTHONPATH`. If you haven't yet done so, please refer to the [installation instructions](installation.html). This example uses our pre-trained CaffeNet model, an ILSVRC12 image classifier. You can download it by running `./scripts/download_model_binary.py models/bvlc_reference_caffenet`. Note that this pre-trained model is licensed for academic research / non-commercial use only.\n", + "Before we begin, you must compile Caffe and install the python wrapper by setting your `PYTHONPATH`. If you haven't yet done so, please refer to the [installation instructions](installation.html). This example uses our pre-trained CaffeNet model, an ILSVRC12 image classifier. You can download it by running `./scripts/download_model_binary.py models/bvlc_reference_caffenet`.\n", "\n", "Ready? Let's start." ] diff --git a/models/bvlc_alexnet/readme.md b/models/bvlc_alexnet/readme.md index c25fd4f8018..97b66bec8c2 100644 --- a/models/bvlc_alexnet/readme.md +++ b/models/bvlc_alexnet/readme.md @@ -22,6 +22,4 @@ This model was trained by Evan Shelhamer @shelhamer ## License -The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: -"Researcher shall use the Database only for non-commercial research and educational purposes." -Accordingly, this model is distributed under a non-commercial license. +This model is released for unrestricted use. diff --git a/models/bvlc_googlenet/readme.md b/models/bvlc_googlenet/readme.md index 8a3bbec4f8b..19f6b881f5c 100644 --- a/models/bvlc_googlenet/readme.md +++ b/models/bvlc_googlenet/readme.md @@ -30,6 +30,4 @@ This model was trained by Sergio Guadarrama @sguada ## License -The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: -"Researcher shall use the Database only for non-commercial research and educational purposes." -Accordingly, this model is distributed under a non-commercial license. +This model is released for unrestricted use. diff --git a/models/bvlc_reference_caffenet/readme.md b/models/bvlc_reference_caffenet/readme.md index b867e7386a3..b6b6103429a 100644 --- a/models/bvlc_reference_caffenet/readme.md +++ b/models/bvlc_reference_caffenet/readme.md @@ -22,6 +22,4 @@ This model was trained by Jeff Donahue @jeffdonahue ## License -The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: -"Researcher shall use the Database only for non-commercial research and educational purposes." -Accordingly, this model is distributed under a non-commercial license. +This model is released for unrestricted use. diff --git a/models/bvlc_reference_rcnn_ilsvrc13/readme.md b/models/bvlc_reference_rcnn_ilsvrc13/readme.md index 5d4bc5afe32..01996ee4d4a 100644 --- a/models/bvlc_reference_rcnn_ilsvrc13/readme.md +++ b/models/bvlc_reference_rcnn_ilsvrc13/readme.md @@ -17,6 +17,4 @@ This model was trained by Ross Girshick @rbgirshick ## License -The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: -"Researcher shall use the Database only for non-commercial research and educational purposes." -Accordingly, this model is distributed under a non-commercial license. +This model is released for unrestricted use. From d8a415efd099980dc0d86f1739c5b0298a46a14e Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 29 Dec 2014 17:36:08 -0800 Subject: [PATCH 204/798] move softmax loss GPU todo comment to header file There's no need to have GPU stubs just for a comment, and the absence of a GPU-specific implementation is made more obvious by the nonexistence of the .cu file. --- include/caffe/loss_layers.hpp | 5 +---- src/caffe/layers/softmax_loss_layer.cu | 27 -------------------------- 2 files changed, 1 insertion(+), 31 deletions(-) delete mode 100644 src/caffe/layers/softmax_loss_layer.cu diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 9fe58cd97bc..13b108afd2d 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -718,8 +718,7 @@ class SoftmaxWithLossLayer : public LossLayer { /// @copydoc SoftmaxWithLossLayer virtual void Forward_cpu(const vector*>& bottom, const vector*>& top); - virtual void Forward_gpu(const vector*>& bottom, - const vector*>& top); + // TODO(Yangqing): implement the GPU version of softmax. /** * @brief Computes the softmax loss error gradient w.r.t. the predictions. @@ -750,8 +749,6 @@ class SoftmaxWithLossLayer : public LossLayer { */ virtual void Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); - virtual void Backward_gpu(const vector*>& top, - const vector& propagate_down, const vector*>& bottom); /// The internal SoftmaxLayer used to map predictions to a distribution. shared_ptr > softmax_layer_; diff --git a/src/caffe/layers/softmax_loss_layer.cu b/src/caffe/layers/softmax_loss_layer.cu deleted file mode 100644 index 4cdaf51b165..00000000000 --- a/src/caffe/layers/softmax_loss_layer.cu +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include - -#include "caffe/layer.hpp" -#include "caffe/util/math_functions.hpp" -#include "caffe/vision_layers.hpp" - -namespace caffe { - -template -void SoftmaxWithLossLayer::Forward_gpu( - const vector*>& bottom, const vector*>& top) { - Forward_cpu(bottom, top); -} - -template -void SoftmaxWithLossLayer::Backward_gpu(const vector*>& top, - const vector& propagate_down, const vector*>& bottom) { - // TODO(Yangqing): implement the GPU version of softmax. - Backward_cpu(top, propagate_down, bottom); -} - -INSTANTIATE_LAYER_GPU_FUNCS(SoftmaxWithLossLayer); - - -} // namespace caffe From 11add5bca9f31dc08329aa220d8674b7832c513d Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 29 Dec 2014 17:59:07 -0800 Subject: [PATCH 205/798] remove SoftmaxLossLayer CPU_ONLY stubs, since there is no GPU version --- src/caffe/layers/softmax_loss_layer.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index 82c62f6a1bd..db8dd8bb626 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -85,11 +85,7 @@ void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, } } - -#ifdef CPU_ONLY -STUB_GPU(SoftmaxWithLossLayer); -#endif - INSTANTIATE_CLASS(SoftmaxWithLossLayer); REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer); + } // namespace caffe From 03f87a90a3ebb66a9a2e80e3864b004aa1da87d8 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 30 Dec 2014 01:31:46 -0800 Subject: [PATCH 206/798] only build matcaffe as part of 'make everything' if MATLAB_DIR is set --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ea97392d8ef..6361305a991 100644 --- a/Makefile +++ b/Makefile @@ -346,6 +346,13 @@ PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) # default behavior of 'find'. SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo +# Set the sub-targets of the 'everything' target. +EVERYTHING_TARGETS := all py$(PROJECT) test warn lint runtest +# Only build matcaffe as part of "everything" if MATLAB_DIR is specified. +ifneq ($(MATLAB_DIR),) + EVERYTHING_TARGETS += mat$(PROJECT) +endif + ############################## # Define build targets ############################## @@ -355,7 +362,7 @@ SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo all: $(STATIC_NAME) $(DYNAMIC_NAME) tools examples -everything: all py$(PROJECT) mat$(PROJECT) test warn lint runtest +everything: $(EVERYTHING_TARGETS) linecount: cloc --read-lang-def=$(PROJECT).cloc \ From dc1557d01c0bd43f6bc3f2d567343165c97f52e5 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 30 Dec 2014 01:33:05 -0800 Subject: [PATCH 207/798] don't do runtest as part of 'make everything' --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6361305a991..46bf7280919 100644 --- a/Makefile +++ b/Makefile @@ -347,7 +347,7 @@ PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo # Set the sub-targets of the 'everything' target. -EVERYTHING_TARGETS := all py$(PROJECT) test warn lint runtest +EVERYTHING_TARGETS := all py$(PROJECT) test warn lint # Only build matcaffe as part of "everything" if MATLAB_DIR is specified. ifneq ($(MATLAB_DIR),) EVERYTHING_TARGETS += mat$(PROJECT) From 2237540de0b0ba4ec7e457cd8efe05320ace48fe Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Dec 2014 12:52:53 -0800 Subject: [PATCH 208/798] [tests] don't use Gaussian labels in NetTest's TinyNet Previously, labels were being nonsensically filled with a zero-mean Gaussian. Now they are just set to constant zero. Note that this is not necessary for TrickyNet, neither forward nor backward are ever called. --- src/caffe/test/test_net.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/caffe/test/test_net.cpp b/src/caffe/test/test_net.cpp index 611d11bd832..319958fee49 100644 --- a/src/caffe/test/test_net.cpp +++ b/src/caffe/test/test_net.cpp @@ -75,6 +75,10 @@ class NetTest : public MultiDeviceTest { " type: 'gaussian' " " std: 0.01 " " } " + " data_filler { " + " type: 'constant' " + " value: 0 " + " } " " } " " top: 'data' " " top: 'label' " From 2326bed7a63ed08b8bc240a55d34e58e8794565e Mon Sep 17 00:00:00 2001 From: Sean Bell Date: Tue, 30 Dec 2014 20:06:31 -0500 Subject: [PATCH 209/798] fixed resize_image for the case of constant images --- python/caffe/io.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/python/caffe/io.py b/python/caffe/io.py index aabcfddbbeb..a8354021b05 100644 --- a/python/caffe/io.py +++ b/python/caffe/io.py @@ -43,11 +43,17 @@ def resize_image(im, new_dims, interp_order=1): im: resized ndarray with shape (new_dims[0], new_dims[1], K) """ if im.shape[-1] == 1 or im.shape[-1] == 3: - # skimage is fast but only understands {1,3} channel images in [0, 1]. im_min, im_max = im.min(), im.max() - im_std = (im - im_min) / (im_max - im_min) - resized_std = resize(im_std, new_dims, order=interp_order) - resized_im = resized_std * (im_max - im_min) + im_min + if im_max > im_min: + # skimage is fast but only understands {1,3} channel images in [0, 1]. + im_std = (im - im_min) / (im_max - im_min) + resized_std = resize(im_std, new_dims, order=interp_order) + resized_im = resized_std * (im_max - im_min) + im_min + else: + # the image is a constant -- avoid divide by 0 + ret = np.empty((new_dims[0], new_dims[1], im.shape[-1]), dtype=np.float32) + ret.fill(im_min) + return ret else: # ndimage interpolates anything but more slowly. scale = tuple(np.array(new_dims) / np.array(im.shape[:2])) From 5843b52558491b636bebcc5cf4ba706b074a717b Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 29 Dec 2014 17:05:47 -0800 Subject: [PATCH 210/798] add missing value support to SoftmaxLossLayer --- include/caffe/loss_layers.hpp | 4 ++++ src/caffe/layers/softmax_loss_layer.cpp | 28 ++++++++++++++++++++----- src/caffe/proto/caffe.proto | 11 +++++++++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 13b108afd2d..3e4414ae6c1 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -758,6 +758,10 @@ class SoftmaxWithLossLayer : public LossLayer { vector*> softmax_bottom_vec_; /// top vector holder used in call to the underlying SoftmaxLayer::Forward vector*> softmax_top_vec_; + /// Whether to ignore instances with a certain label. + bool has_ignore_label_; + /// The label indicating that an instance should be ignored. + int ignore_label_; }; } // namespace caffe diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index db8dd8bb626..bc511cf603b 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -17,6 +17,12 @@ void SoftmaxWithLossLayer::LayerSetUp( softmax_top_vec_.clear(); softmax_top_vec_.push_back(&prob_); softmax_layer_->SetUp(softmax_bottom_vec_, softmax_top_vec_); + + has_ignore_label_ = + this->layer_param_.loss_param().has_ignore_label(); + if (has_ignore_label_) { + ignore_label_ = this->layer_param_.loss_param().ignore_label(); + } } template @@ -40,15 +46,19 @@ void SoftmaxWithLossLayer::Forward_cpu( int num = prob_.num(); int dim = prob_.count() / num; int spatial_dim = prob_.height() * prob_.width(); + int count = 0; Dtype loss = 0; for (int i = 0; i < num; ++i) { for (int j = 0; j < spatial_dim; j++) { const int label_value = static_cast(label[i * spatial_dim + j]); + if (has_ignore_label_ && label_value == ignore_label_) { + continue; + } DCHECK_GE(label_value, 0); - DCHECK_GT(dim, label_value * spatial_dim); - loss -= log(std::max(prob_data[i * dim + - label_value * spatial_dim + j], + DCHECK_LT(label_value, prob_.channels()); + loss -= log(std::max(prob_data[i * dim + label_value * spatial_dim + j], Dtype(FLT_MIN))); + ++count; } } top[0]->mutable_cpu_data()[0] = loss / num / spatial_dim; @@ -73,10 +83,18 @@ void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, int num = prob_.num(); int dim = prob_.count() / num; int spatial_dim = prob_.height() * prob_.width(); + int count = 0; for (int i = 0; i < num; ++i) { for (int j = 0; j < spatial_dim; ++j) { - bottom_diff[i * dim + static_cast(label[i * spatial_dim + j]) - * spatial_dim + j] -= 1; + const int label_value = static_cast(label[i * spatial_dim + j]); + if (has_ignore_label_ && label_value == ignore_label_) { + for (int c = 0; c < bottom[0]->channels(); ++c) { + bottom_diff[i * dim + c * spatial_dim + j] = 0; + } + } else { + bottom_diff[i * dim + label_value * spatial_dim + j] -= 1; + ++count; + } } } // Scale gradient diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 8086ad66579..cfd5cca2518 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -206,7 +206,7 @@ message NetStateRule { // NOTE // Update the next available ID when you add a new LayerParameter field. // -// LayerParameter next available ID: 42 (last added: exp_param) +// LayerParameter next available ID: 43 (last added: loss_param) message LayerParameter { repeated string bottom = 2; // the name of the bottom blobs repeated string top = 3; // the name of the top blobs @@ -331,6 +331,9 @@ message LayerParameter { // Parameters for data pre-processing. optional TransformationParameter transform_param = 36; + // Parameters shared by loss layers. + optional LossParameter loss_param = 42; + // Note: certain layers may have more than one computational engine // for their implementation. These layers include an Engine type and // engine parameter for selecting the implementation. @@ -361,6 +364,12 @@ message TransformationParameter { repeated float mean_value = 5; } +// Message that stores parameters shared by loss layers +message LossParameter { + // If specified, ignore instances with the given label. + optional int32 ignore_label = 1; +} + // Message that stores parameters used by AccuracyLayer message AccuracyParameter { // When computing accuracy, count as correct by comparing the true label to From 34321e4ecf26494ded5a05221010ccc9ea99c144 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 29 Dec 2014 17:08:21 -0800 Subject: [PATCH 211/798] add spatial normalization option to SoftmaxLossLayer With missing values (and batches of varying spatial dimension), normalizing each batch across instances can inappropriately give different instances different weights, so we give the option of simply normalizing by the batch size instead. --- include/caffe/loss_layers.hpp | 3 +++ src/caffe/layers/softmax_loss_layer.cpp | 13 +++++++++++-- src/caffe/proto/caffe.proto | 3 +++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 3e4414ae6c1..321f7068273 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -762,6 +762,9 @@ class SoftmaxWithLossLayer : public LossLayer { bool has_ignore_label_; /// The label indicating that an instance should be ignored. int ignore_label_; + /// Whether to normalize the loss by the total number of values present + /// (otherwise just by the batch size). + bool normalize_; }; } // namespace caffe diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index bc511cf603b..74893af7820 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -23,6 +23,7 @@ void SoftmaxWithLossLayer::LayerSetUp( if (has_ignore_label_) { ignore_label_ = this->layer_param_.loss_param().ignore_label(); } + normalize_ = this->layer_param_.loss_param().normalize(); } template @@ -61,7 +62,11 @@ void SoftmaxWithLossLayer::Forward_cpu( ++count; } } - top[0]->mutable_cpu_data()[0] = loss / num / spatial_dim; + if (normalize_) { + top[0]->mutable_cpu_data()[0] = loss / count; + } else { + top[0]->mutable_cpu_data()[0] = loss / num; + } if (top.size() == 2) { top[1]->ShareData(prob_); } @@ -99,7 +104,11 @@ void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, } // Scale gradient const Dtype loss_weight = top[0]->cpu_diff()[0]; - caffe_scal(prob_.count(), loss_weight / num / spatial_dim, bottom_diff); + if (normalize_) { + caffe_scal(prob_.count(), loss_weight / count, bottom_diff); + } else { + caffe_scal(prob_.count(), loss_weight / num, bottom_diff); + } } } diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index cfd5cca2518..2bfd7b36fa3 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -368,6 +368,9 @@ message TransformationParameter { message LossParameter { // If specified, ignore instances with the given label. optional int32 ignore_label = 1; + // If true, normalize each batch across all instances (including spatial + // dimesions, but not ignored instances); else, divide by batch size only. + optional bool normalize = 2 [default = true]; } // Message that stores parameters used by AccuracyLayer From c7f63da671d7dc6345d645b89d3641bcd8b7cc27 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 30 Dec 2014 12:31:53 -0800 Subject: [PATCH 212/798] clean up formatting in SoftmaxLossLayer --- src/caffe/layers/softmax_loss_layer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index 74893af7820..55eb0918ad2 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -74,8 +74,7 @@ void SoftmaxWithLossLayer::Forward_cpu( template void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, - const vector& propagate_down, - const vector*>& bottom) { + const vector& propagate_down, const vector*>& bottom) { if (propagate_down[1]) { LOG(FATAL) << this->type_name() << " Layer cannot backpropagate to label inputs."; From 55d7ffde2907459f021dc72f56c36a61235e187a Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 29 Sep 2014 16:47:06 -0700 Subject: [PATCH 213/798] break out Step from Solver --- include/caffe/solver.hpp | 10 +++--- src/caffe/solver.cpp | 73 +++++++++++++++++++++------------------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/include/caffe/solver.hpp b/include/caffe/solver.hpp index b20912606f8..fde66208207 100644 --- a/include/caffe/solver.hpp +++ b/include/caffe/solver.hpp @@ -26,6 +26,7 @@ class Solver { // in a non-zero iter number to resume training for a pre-trained net. virtual void Solve(const char* resume_file = NULL); inline void Solve(const string resume_file) { Solve(resume_file.c_str()); } + void Step(int iters); virtual ~Solver() {} inline shared_ptr > net() { return net_; } inline const vector > >& test_nets() { @@ -34,9 +35,6 @@ class Solver { int iter() { return iter_; } protected: - // PreSolve is run before any solving iteration starts, allowing one to - // put up some scaffold. - virtual void PreSolve() {} // Get the update value for the current iteration. virtual void ComputeUpdateValue() = 0; // The Solver::Snapshot function implements the basic snapshotting utility @@ -73,14 +71,14 @@ template class SGDSolver : public Solver { public: explicit SGDSolver(const SolverParameter& param) - : Solver(param) {} + : Solver(param) { PreSolve(); } explicit SGDSolver(const string& param_file) - : Solver(param_file) {} + : Solver(param_file) { PreSolve(); } const vector > >& history() { return history_; } protected: - virtual void PreSolve(); + void PreSolve(); Dtype GetLearningRate(); virtual void ComputeUpdateValue(); virtual void SnapshotSolverState(SolverState * state); diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 7f5d3d20f35..ab9c00eed8f 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -32,6 +32,7 @@ void Solver::Init(const SolverParameter& param) { LOG(INFO) << "Initializing solver from parameters: " << std::endl << param.DebugString(); param_ = param; + CHECK_GE(param_.average_loss(), 1) << "average_loss should be non-negative."; if (param_.random_seed() >= 0) { Caffe::set_random_seed(param_.random_seed()); } @@ -39,6 +40,8 @@ void Solver::Init(const SolverParameter& param) { InitTrainNet(); InitTestNets(); LOG(INFO) << "Solver scaffolding done."; + iter_ = 0; + current_step_ = 0; } template @@ -155,39 +158,15 @@ void Solver::InitTestNets() { } template -void Solver::Solve(const char* resume_file) { - Caffe::set_phase(Caffe::TRAIN); - LOG(INFO) << "Solving " << net_->name(); - LOG(INFO) << "Learning Rate Policy: " << param_.lr_policy(); - PreSolve(); - - iter_ = 0; - current_step_ = 0; - if (resume_file) { - LOG(INFO) << "Restoring previous solver status from " << resume_file; - Restore(resume_file); - } - // Remember the initial iter_ value; will be non-zero if we loaded from a - // resume_file above. +void Solver::Step(int iters) { + vector*> bottom_vec; const int start_iter = iter_; - + const int stop_iter = iter_ + iters; int average_loss = this->param_.average_loss(); - - CHECK_GE(average_loss, 1) << "average_loss should be non-negative."; - vector losses; Dtype smoothed_loss = 0; - // For a network that is trained by the solver, no bottom or top vecs - // should be given, and we will just provide dummy vecs. - vector*> bottom_vec; - for (; iter_ < param_.max_iter(); ++iter_) { - // Save a snapshot if needed. - if (param_.snapshot() && iter_ > start_iter && - iter_ % param_.snapshot() == 0) { - Snapshot(); - } - + for (; iter_ < stop_iter; ++iter_) { if (param_.test_interval() && iter_ % param_.test_interval() == 0 && (iter_ > 0 || param_.test_initialization())) { TestAll(); @@ -227,13 +206,36 @@ void Solver::Solve(const char* resume_file) { } } } - ComputeUpdateValue(); net_->Update(); + + // Save a snapshot if needed. + if (param_.snapshot() && (iter_ + 1) % param_.snapshot() == 0) { + Snapshot(); + } + } +} + +template +void Solver::Solve(const char* resume_file) { + Caffe::set_phase(Caffe::TRAIN); + LOG(INFO) << "Solving " << net_->name(); + LOG(INFO) << "Learning Rate Policy: " << param_.lr_policy(); + + if (resume_file) { + LOG(INFO) << "Restoring previous solver status from " << resume_file; + Restore(resume_file); + } + + // For a network that is trained by the solver, no bottom or top vecs + // should be given, and we will just provide dummy vecs. + Step(param_.max_iter() - iter_); + // If we haven't already, save a snapshot after optimization, unless + // overridden by setting snapshot_after_train := false + if (param_.snapshot_after_train() + && (!param_.snapshot() || iter_ % param_.snapshot() != 0)) { + Snapshot(); } - // Always save a snapshot after optimization, unless overridden by setting - // snapshot_after_train := false. - if (param_.snapshot_after_train()) { Snapshot(); } // After the optimization is done, run an additional train and test pass to // display the train and test loss/outputs if appropriate (based on the // display and test_interval settings, respectively). Unlike in the rest of @@ -242,7 +244,7 @@ void Solver::Solve(const char* resume_file) { // display the loss, which is computed in the forward pass. if (param_.display() && iter_ % param_.display() == 0) { Dtype loss; - net_->Forward(bottom_vec, &loss); + net_->ForwardPrefilled(&loss); LOG(INFO) << "Iteration " << iter_ << ", loss = " << loss; } if (param_.test_interval() && iter_ % param_.test_interval() == 0) { @@ -328,14 +330,15 @@ void Solver::Snapshot() { string model_filename, snapshot_filename; const int kBufferSize = 20; char iter_str_buffer[kBufferSize]; - snprintf(iter_str_buffer, kBufferSize, "_iter_%d", iter_); + // Add one to iter_ to get the number of iterations that have completed. + snprintf(iter_str_buffer, kBufferSize, "_iter_%d", iter_ + 1); filename += iter_str_buffer; model_filename = filename + ".caffemodel"; LOG(INFO) << "Snapshotting to " << model_filename; WriteProtoToBinaryFile(net_param, model_filename.c_str()); SolverState state; SnapshotSolverState(&state); - state.set_iter(iter_); + state.set_iter(iter_ + 1); state.set_learned_net(model_filename); state.set_current_step(current_step_); snapshot_filename = filename + ".solverstate"; From 10c23643bbf71628faad26c5ffbdc249b2c3fe37 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 29 Sep 2014 16:49:49 -0700 Subject: [PATCH 214/798] [pycaffe] expose SGDSolver.step --- python/caffe/_caffe.cpp | 3 ++- python/caffe/_caffe.hpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index f03dae3dce6..156b5187d58 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -197,7 +197,8 @@ BOOST_PYTHON_MODULE(_caffe) { .add_property("test_nets", &PySGDSolver::test_nets) .add_property("iter", &PySGDSolver::iter) .def("solve", &PySGDSolver::Solve) - .def("solve", &PySGDSolver::SolveResume); + .def("solve", &PySGDSolver::SolveResume) + .def("step", &PySGDSolver::Step); bp::class_ > >("NetVec") .def(bp::vector_indexing_suite >, true>()); diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index bf1b7d168f8..a5cef74ad66 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -181,6 +181,7 @@ class PySGDSolver { vector > test_nets() { return test_nets_; } int iter() { return solver_->iter(); } void Solve() { return solver_->Solve(); } + void Step(int iters) { solver_->Step(iters); } void SolveResume(const string& resume_file); protected: From 9e9c21082d0ee038d1c789148521997bfd7b72fa Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 20 Nov 2014 20:36:56 -0800 Subject: [PATCH 215/798] add "make pytest" for running Python tests --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 46bf7280919..d3bddea7bea 100644 --- a/Makefile +++ b/Makefile @@ -434,6 +434,9 @@ runtest: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN) $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) && \ $(TEST_ALL_DYNLINK_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) +pytest: py + cd python; python -m unittest discover -s caffe/test + warn: $(EMPTY_WARN_REPORT) $(EMPTY_WARN_REPORT): $(ALL_WARNS) | $(BUILD_DIR) From b26eaf78097d07575a4de7e89b2f91811ad587f2 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 25 Nov 2014 11:07:52 -0800 Subject: [PATCH 216/798] [travis] remove unneeded Makefile.config sed hacking Make allows variable redefinition, so sed brittleness can be avoided. --- scripts/travis/travis_setup_makefile_config.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/travis/travis_setup_makefile_config.sh b/scripts/travis/travis_setup_makefile_config.sh index a309bb3d6fe..5e4cd3ad7d5 100755 --- a/scripts/travis/travis_setup_makefile_config.sh +++ b/scripts/travis/travis_setup_makefile_config.sh @@ -5,9 +5,7 @@ set -e mv Makefile.config.example Makefile.config if $WITH_CUDA; then - # Remove default gencode set; only generate compute_50. - sed -i 's/-gencode arch=.*\\//' Makefile.config - sed -i 's/CUDA_ARCH :=//' Makefile.config + # Only generate compute_50. GENCODE="-gencode arch=compute_50,code=sm_50" GENCODE="$GENCODE -gencode arch=compute_50,code=compute_50" echo "CUDA_ARCH := $GENCODE" >> Makefile.config From 0c2a1bcf4feb84de91c7d56f231f100cf8ad0b4f Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 20 Nov 2014 20:40:56 -0800 Subject: [PATCH 217/798] [travis] run pytest --- .travis.yml | 3 ++- scripts/travis/travis_build_and_test.sh | 1 + scripts/travis/travis_install.sh | 11 +++++++++++ scripts/travis/travis_setup_makefile_config.sh | 10 ++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3deb45a2f0c..955aa8c3ba2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,8 @@ install: - sudo -E $SCRIPTS/travis_install.sh before_script: - - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib + - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/cuda/lib64 + - export PATH=/home/travis/miniconda/bin:$PATH - if ! $WITH_CMAKE; then $SCRIPTS/travis_setup_makefile_config.sh; fi script: $SCRIPTS/travis_build_and_test.sh diff --git a/scripts/travis/travis_build_and_test.sh b/scripts/travis/travis_build_and_test.sh index dec4d097c17..53c6c341101 100755 --- a/scripts/travis/travis_build_and_test.sh +++ b/scripts/travis/travis_build_and_test.sh @@ -26,6 +26,7 @@ else $MAKE all $MAKE test $MAKE pycaffe + $MAKE pytest $MAKE warn if ! $WITH_CUDA; then $MAKE lint diff --git a/scripts/travis/travis_install.sh b/scripts/travis/travis_install.sh index e17f253ecdc..82f386cf029 100755 --- a/scripts/travis/travis_install.sh +++ b/scripts/travis/travis_install.sh @@ -57,3 +57,14 @@ $MAKE $MAKE install popd rm -f $LMDB_FILE + +# Install the Python runtime dependencies via miniconda (this is much faster +# than using pip for everything). +wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh +chmod +x miniconda.sh +./miniconda.sh -b +export PATH=/home/travis/miniconda/bin:$PATH +conda update --yes conda +conda install --yes numpy scipy matplotlib scikit-image pip +pip install protobuf +rm /home/travis/miniconda/lib/libm.* diff --git a/scripts/travis/travis_setup_makefile_config.sh b/scripts/travis/travis_setup_makefile_config.sh index 5e4cd3ad7d5..e8d85f9be78 100755 --- a/scripts/travis/travis_setup_makefile_config.sh +++ b/scripts/travis/travis_setup_makefile_config.sh @@ -10,3 +10,13 @@ if $WITH_CUDA; then GENCODE="$GENCODE -gencode arch=compute_50,code=compute_50" echo "CUDA_ARCH := $GENCODE" >> Makefile.config fi + +cat << 'EOF' >> Makefile.config +ANACONDA_HOME := $(HOME)/miniconda +PYTHON_INCLUDE := $(ANACONDA_HOME)/include \ + $(ANACONDA_HOME)/include/python2.7 \ + $(ANACONDA_HOME)/lib/python2.7/site-packages/numpy/core/include +PYTHON_LIB := $(ANACONDA_HOME)/lib +INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include +LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib +EOF From 3f6a85c23c8c3a016f6360baf9614b6720e5c1f4 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Mon, 24 Nov 2014 18:53:14 -0800 Subject: [PATCH 218/798] [pycaffe] basic, partial testing of Net and SGDSolver --- python/caffe/test/test_net.py | 77 ++++++++++++++++++++++++++++++++ python/caffe/test/test_solver.py | 49 ++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 python/caffe/test/test_net.py create mode 100644 python/caffe/test/test_solver.py diff --git a/python/caffe/test/test_net.py b/python/caffe/test/test_net.py new file mode 100644 index 00000000000..f0e9deef19c --- /dev/null +++ b/python/caffe/test/test_net.py @@ -0,0 +1,77 @@ +import unittest +import tempfile +import os +import numpy as np + +import caffe + +def simple_net_file(num_output): + """Make a simple net prototxt, based on test_net.cpp, returning the name + of the (temporary) file.""" + + f = tempfile.NamedTemporaryFile(delete=False) + f.write("""name: 'testnet' force_backward: true + layers { type: DUMMY_DATA name: 'data' top: 'data' top: 'label' + dummy_data_param { num: 5 channels: 2 height: 3 width: 4 + num: 5 channels: 1 height: 1 width: 1 + data_filler { type: 'gaussian' std: 1 } + data_filler { type: 'constant' } } } + layers { type: CONVOLUTION name: 'conv' bottom: 'data' top: 'conv' + convolution_param { num_output: 11 kernel_size: 2 pad: 3 + weight_filler { type: 'gaussian' std: 1 } + bias_filler { type: 'constant' value: 2 } } + weight_decay: 1 weight_decay: 0 } + layers { type: INNER_PRODUCT name: 'ip' bottom: 'conv' top: 'ip' + inner_product_param { num_output: """ + str(num_output) + """ + weight_filler { type: 'gaussian' std: 2.5 } + bias_filler { type: 'constant' value: -3 } } } + layers { type: SOFTMAX_LOSS name: 'loss' bottom: 'ip' bottom: 'label' + top: 'loss' }""") + f.close() + return f.name + +class TestNet(unittest.TestCase): + def setUp(self): + self.num_output = 13 + net_file = simple_net_file(self.num_output) + self.net = caffe.Net(net_file) + # fill in valid labels + self.net.blobs['label'].data[...] = \ + np.random.randint(self.num_output, + size=self.net.blobs['label'].data.shape) + os.remove(net_file) + + def test_memory(self): + """Check that holding onto blob data beyond the life of a Net is OK""" + + params = sum(map(list, self.net.params.itervalues()), []) + blobs = self.net.blobs.values() + del self.net + + # now sum everything (forcing all memory to be read) + total = 0 + for p in params: + total += p.data.sum() + p.diff.sum() + for bl in blobs: + total += bl.data.sum() + bl.diff.sum() + + def test_forward_backward(self): + self.net.forward() + self.net.backward() + + def test_inputs_outputs(self): + self.assertEqual(self.net.inputs, []) + self.assertEqual(self.net.outputs, ['loss']) + + def test_save_and_read(self): + f = tempfile.NamedTemporaryFile(delete=False) + f.close() + self.net.save(f.name) + net_file = simple_net_file(self.num_output) + net2 = caffe.Net(net_file, f.name) + os.remove(net_file) + os.remove(f.name) + for name in self.net.params: + for i in range(len(self.net.params[name])): + self.assertEqual(abs(self.net.params[name][i].data + - net2.params[name][i].data).sum(), 0) diff --git a/python/caffe/test/test_solver.py b/python/caffe/test/test_solver.py new file mode 100644 index 00000000000..b78c91f9978 --- /dev/null +++ b/python/caffe/test/test_solver.py @@ -0,0 +1,49 @@ +import unittest +import tempfile +import os +import numpy as np + +import caffe +from test_net import simple_net_file + +class TestSolver(unittest.TestCase): + def setUp(self): + self.num_output = 13 + net_f = simple_net_file(self.num_output) + f = tempfile.NamedTemporaryFile(delete=False) + f.write("""net: '""" + net_f + """' + test_iter: 10 test_interval: 10 base_lr: 0.01 momentum: 0.9 + weight_decay: 0.0005 lr_policy: 'inv' gamma: 0.0001 power: 0.75 + display: 100 max_iter: 100 snapshot_after_train: false""") + f.close() + self.solver = caffe.SGDSolver(f.name) + self.solver.net.set_mode_cpu() + # fill in valid labels + self.solver.net.blobs['label'].data[...] = \ + np.random.randint(self.num_output, + size=self.solver.net.blobs['label'].data.shape) + self.solver.test_nets[0].blobs['label'].data[...] = \ + np.random.randint(self.num_output, + size=self.solver.test_nets[0].blobs['label'].data.shape) + os.remove(f.name) + os.remove(net_f) + + def test_solve(self): + self.assertEqual(self.solver.iter, 0) + self.solver.solve() + self.assertEqual(self.solver.iter, 100) + + def test_net_memory(self): + """Check that nets survive after the solver is destroyed.""" + + nets = [self.solver.net] + list(self.solver.test_nets) + self.assertEqual(len(nets), 2) + del self.solver + + total = 0 + for net in nets: + for ps in net.params.itervalues(): + for p in ps: + total += p.data.sum() + p.diff.sum() + for bl in net.blobs.itervalues(): + total += bl.data.sum() + bl.diff.sum() From 7e465f288a4a7fc2d74b2a0a145f98a03891dcb8 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Wed, 7 Jan 2015 23:00:27 -0500 Subject: [PATCH 219/798] BVLC models are for unrestricted use (follow-up to #1650) --- models/bvlc_alexnet/readme.md | 2 +- models/bvlc_googlenet/readme.md | 2 +- models/bvlc_reference_caffenet/readme.md | 2 +- models/bvlc_reference_rcnn_ilsvrc13/readme.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/models/bvlc_alexnet/readme.md b/models/bvlc_alexnet/readme.md index 97b66bec8c2..008d690f7f4 100644 --- a/models/bvlc_alexnet/readme.md +++ b/models/bvlc_alexnet/readme.md @@ -2,7 +2,7 @@ name: BVLC AlexNet Model caffemodel: bvlc_alexnet.caffemodel caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_alexnet.caffemodel -license: non-commercial +license: unrestricted sha1: 9116a64c0fbe4459d18f4bb6b56d647b63920377 caffe_commit: 709dc15af4a06bebda027c1eb2b3f3e3375d5077 --- diff --git a/models/bvlc_googlenet/readme.md b/models/bvlc_googlenet/readme.md index 19f6b881f5c..2e22dfcf59a 100644 --- a/models/bvlc_googlenet/readme.md +++ b/models/bvlc_googlenet/readme.md @@ -2,7 +2,7 @@ name: BVLC GoogleNet Model caffemodel: bvlc_googlenet.caffemodel caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel -license: non-commercial +license: unrestricted sha1: 405fc5acd08a3bb12de8ee5e23a96bec22f08204 caffe_commit: bc614d1bd91896e3faceaf40b23b72dab47d44f5 gist_id: 866e2aa1fd707b89b913 diff --git a/models/bvlc_reference_caffenet/readme.md b/models/bvlc_reference_caffenet/readme.md index b6b6103429a..671e47a5056 100644 --- a/models/bvlc_reference_caffenet/readme.md +++ b/models/bvlc_reference_caffenet/readme.md @@ -2,7 +2,7 @@ name: BVLC CaffeNet Model caffemodel: bvlc_reference_caffenet.caffemodel caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_reference_caffenet.caffemodel -license: non-commercial +license: unrestricted sha1: 4c8d77deb20ea792f84eb5e6d0a11ca0a8660a46 caffe_commit: 709dc15af4a06bebda027c1eb2b3f3e3375d5077 --- diff --git a/models/bvlc_reference_rcnn_ilsvrc13/readme.md b/models/bvlc_reference_rcnn_ilsvrc13/readme.md index 01996ee4d4a..9a11a24d8f8 100644 --- a/models/bvlc_reference_rcnn_ilsvrc13/readme.md +++ b/models/bvlc_reference_rcnn_ilsvrc13/readme.md @@ -2,7 +2,7 @@ name: BVLC Reference RCNN ILSVRC13 Model caffemodel: bvlc_reference_rcnn_ilsvrc13.caffemodel caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_reference_rcnn_ilsvrc13.caffemodel -license: non-commercial +license: unrestricted sha1: bdd8abb885819cba5e2fe1eb36235f2319477e64 caffe_commit: a7e397abbda52c0b90323c23ab95bdeabee90a98 --- From 2377b68dcc3c20685ec388097dbe9e9c6b3b0e92 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 6 Jan 2015 20:25:53 -0800 Subject: [PATCH 220/798] improve const-ness of Net --- include/caffe/net.hpp | 72 ++++++++++++++++++++++++++++--------------- src/caffe/net.cpp | 16 +++++----- src/caffe/solver.cpp | 23 ++++++++------ tools/caffe.cpp | 4 +-- 4 files changed, 70 insertions(+), 45 deletions(-) diff --git a/include/caffe/net.hpp b/include/caffe/net.hpp index 1d06dc45533..bbb220eb00d 100644 --- a/include/caffe/net.hpp +++ b/include/caffe/net.hpp @@ -89,7 +89,7 @@ class Net { * @brief For an already initialized net, implicitly copies (i.e., using no * additional memory) the pre-trained layers from another Net. */ - void ShareTrainedLayersWith(Net* other); + void ShareTrainedLayersWith(const Net* other); // For an already initialized net, CopyTrainedLayersFrom() copies the already // trained layers from another net parameter instance. /** @@ -99,51 +99,73 @@ class Net { void CopyTrainedLayersFrom(const NetParameter& param); void CopyTrainedLayersFrom(const string trained_filename); /// @brief Writes the net to a proto. - void ToProto(NetParameter* param, bool write_diff = false); + void ToProto(NetParameter* param, bool write_diff = false) const; /// @brief returns the network name. - inline const string& name() { return name_; } + inline const string& name() const { return name_; } /// @brief returns the layer names - inline const vector& layer_names() { return layer_names_; } + inline const vector& layer_names() const { return layer_names_; } /// @brief returns the blob names - inline const vector& blob_names() { return blob_names_; } + inline const vector& blob_names() const { return blob_names_; } /// @brief returns the blobs - inline const vector > >& blobs() { return blobs_; } + inline const vector > >& blobs() const { + return blobs_; + } /// @brief returns the layers - inline const vector > >& layers() { return layers_; } + inline const vector > >& layers() const { + return layers_; + } /** * @brief returns the bottom vecs for each layer -- usually you won't * need this unless you do per-layer checks such as gradients. */ - inline vector*> >& bottom_vecs() { return bottom_vecs_; } + inline const vector*> >& bottom_vecs() const { + return bottom_vecs_; + } /** * @brief returns the top vecs for each layer -- usually you won't * need this unless you do per-layer checks such as gradients. */ - inline vector*> >& top_vecs() { return top_vecs_; } - inline vector >& bottom_need_backward() { + inline const vector*> >& top_vecs() const { + return top_vecs_; + } + inline const vector >& bottom_need_backward() const { return bottom_need_backward_; } - inline vector& blob_loss_weights() { + inline const vector& blob_loss_weights() const { return blob_loss_weights_; } /// @brief returns the parameters - inline vector > >& params() { return params_; } + inline const vector > >& params() const { + return params_; + } /// @brief returns the parameter learning rate multipliers - inline vector& params_lr() { return params_lr_; } - inline vector& params_weight_decay() { return params_weight_decay_; } - const map& param_names_index() { return param_names_index_; } + inline const vector& params_lr() const { return params_lr_; } + inline const vector& params_weight_decay() const { + return params_weight_decay_; + } + const map& param_names_index() const { + return param_names_index_; + } /// @brief Input and output blob numbers - inline int num_inputs() { return net_input_blobs_.size(); } - inline int num_outputs() { return net_output_blobs_.size(); } - inline vector*>& input_blobs() { return net_input_blobs_; } - inline vector*>& output_blobs() { return net_output_blobs_; } - inline vector& input_blob_indices() { return net_input_blob_indices_; } - inline vector& output_blob_indices() { return net_output_blob_indices_; } - bool has_blob(const string& blob_name); - const shared_ptr > blob_by_name(const string& blob_name); - bool has_layer(const string& layer_name); - const shared_ptr > layer_by_name(const string& layer_name); + inline int num_inputs() const { return net_input_blobs_.size(); } + inline int num_outputs() const { return net_output_blobs_.size(); } + inline const vector*>& input_blobs() const { + return net_input_blobs_; + } + inline const vector*>& output_blobs() const { + return net_output_blobs_; + } + inline const vector& input_blob_indices() const { + return net_input_blob_indices_; + } + inline const vector& output_blob_indices() const { + return net_output_blob_indices_; + } + bool has_blob(const string& blob_name) const; + const shared_ptr > blob_by_name(const string& blob_name) const; + bool has_layer(const string& layer_name) const; + const shared_ptr > layer_by_name(const string& layer_name) const; void set_debug_info(const bool value) { debug_info_ = value; } diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index e4492cfd6e3..47fc8446064 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -636,7 +636,7 @@ void Net::UpdateDebugInfo(const int param_id) { } template -void Net::ShareTrainedLayersWith(Net* other) { +void Net::ShareTrainedLayersWith(const Net* other) { int num_source_layers = other->layers().size(); for (int i = 0; i < num_source_layers; ++i) { Layer* source_layer = other->layers()[i].get(); @@ -726,7 +726,7 @@ void Net::CopyTrainedLayersFrom(const string trained_filename) { } template -void Net::ToProto(NetParameter* param, bool write_diff) { +void Net::ToProto(NetParameter* param, bool write_diff) const { param->Clear(); param->set_name(name_); // Add bottom and top @@ -785,16 +785,16 @@ void Net::Update() { } template -bool Net::has_blob(const string& blob_name) { +bool Net::has_blob(const string& blob_name) const { return blob_names_index_.find(blob_name) != blob_names_index_.end(); } template const shared_ptr > Net::blob_by_name( - const string& blob_name) { + const string& blob_name) const { shared_ptr > blob_ptr; if (has_blob(blob_name)) { - blob_ptr = blobs_[blob_names_index_[blob_name]]; + blob_ptr = blobs_[blob_names_index_.find(blob_name)->second]; } else { blob_ptr.reset((Blob*)(NULL)); LOG(WARNING) << "Unknown blob name " << blob_name; @@ -803,16 +803,16 @@ const shared_ptr > Net::blob_by_name( } template -bool Net::has_layer(const string& layer_name) { +bool Net::has_layer(const string& layer_name) const { return layer_names_index_.find(layer_name) != layer_names_index_.end(); } template const shared_ptr > Net::layer_by_name( - const string& layer_name) { + const string& layer_name) const { shared_ptr > layer_ptr; if (has_layer(layer_name)) { - layer_ptr = layers_[layer_names_index_[layer_name]]; + layer_ptr = layers_[layer_names_index_.find(layer_name)->second]; } else { layer_ptr.reset((Layer*)(NULL)); LOG(WARNING) << "Unknown layer name " << layer_name; diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index ab9c00eed8f..3fa0e2d14b7 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -418,7 +418,7 @@ Dtype SGDSolver::GetLearningRate() { template void SGDSolver::PreSolve() { // Initialize the history - vector > >& net_params = this->net_->params(); + const vector > >& net_params = this->net_->params(); history_.clear(); update_.clear(); temp_.clear(); @@ -439,9 +439,10 @@ void SGDSolver::PreSolve() { template void SGDSolver::ComputeUpdateValue() { - vector > >& net_params = this->net_->params(); - vector& net_params_lr = this->net_->params_lr(); - vector& net_params_weight_decay = this->net_->params_weight_decay(); + const vector > >& net_params = this->net_->params(); + const vector& net_params_lr = this->net_->params_lr(); + const vector& net_params_weight_decay = + this->net_->params_weight_decay(); // get the learning rate Dtype rate = GetLearningRate(); if (this->param_.display() && this->iter_ % this->param_.display() == 0) { @@ -552,9 +553,10 @@ void SGDSolver::RestoreSolverState(const SolverState& state) { template void NesterovSolver::ComputeUpdateValue() { - vector > >& net_params = this->net_->params(); - vector& net_params_lr = this->net_->params_lr(); - vector& net_params_weight_decay = this->net_->params_weight_decay(); + const vector > >& net_params = this->net_->params(); + const vector& net_params_lr = this->net_->params_lr(); + const vector& net_params_weight_decay = + this->net_->params_weight_decay(); // get the learning rate Dtype rate = this->GetLearningRate(); if (this->param_.display() && this->iter_ % this->param_.display() == 0) { @@ -667,9 +669,10 @@ void NesterovSolver::ComputeUpdateValue() { template void AdaGradSolver::ComputeUpdateValue() { - vector > >& net_params = this->net_->params(); - vector& net_params_lr = this->net_->params_lr(); - vector& net_params_weight_decay = this->net_->params_weight_decay(); + const vector > >& net_params = this->net_->params(); + const vector& net_params_lr = this->net_->params_lr(); + const vector& net_params_weight_decay = + this->net_->params_weight_decay(); // get the learning rate Dtype rate = this->GetLearningRate(); Dtype delta = this->param_.delta(); diff --git a/tools/caffe.cpp b/tools/caffe.cpp index 9f9d975dfba..ad54bc3b9eb 100644 --- a/tools/caffe.cpp +++ b/tools/caffe.cpp @@ -220,8 +220,8 @@ int time() { caffe_net.Backward(); const vector > >& layers = caffe_net.layers(); - vector*> >& bottom_vecs = caffe_net.bottom_vecs(); - vector*> >& top_vecs = caffe_net.top_vecs(); + const vector*> >& bottom_vecs = caffe_net.bottom_vecs(); + const vector*> >& top_vecs = caffe_net.top_vecs(); const vector >& bottom_need_backward = caffe_net.bottom_need_backward(); LOG(INFO) << "*** Benchmark begins ***"; From 25e37489294cabcc023b3583ad72d8753317e069 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sat, 10 Jan 2015 01:16:12 -0800 Subject: [PATCH 221/798] fix typo in layer_factory.cpp --- src/caffe/layer_factory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 5a286cd4691..80694834a33 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -154,5 +154,5 @@ Layer* GetTanHLayer(const LayerParameter& param) { REGISTER_LAYER_CREATOR(TANH, GetTanHLayer); // Layers that use their constructor as their default creator should be -// registered in their corresponding cpp files. Do not registere them here. +// registered in their corresponding cpp files. Do not register them here. } // namespace caffe From 9cdf40df6d0214bd50c21eee362f2c3e13df8dc7 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sat, 10 Jan 2015 01:18:39 -0800 Subject: [PATCH 222/798] [build] more meaningful messages for link commands --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 46bf7280919..f6178162f34 100644 --- a/Makefile +++ b/Makefile @@ -465,11 +465,11 @@ $(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK) @ mkdir -p $@ $(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) - @ echo LD $< + @ echo LD -o $@ $(Q)$(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) $(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) - @ echo AR $< + @ echo AR -o $@ $(Q)ar rcs $@ $(OBJS) $(BUILD_DIR)/%.o: %.cpp | $(ALL_BUILD_DIRS) From 3c5048c27e0579ca43e10186a0102b908b591a69 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sat, 10 Jan 2015 01:42:23 -0800 Subject: [PATCH 223/798] [build] specify RPATH using $ORIGIN Currently, when dynamically linking against libcaffe (right now, only done for tests), RPATH is specified relative to the caffe source root. This commit fixes RPATH using the special $ORIGIN variable to be relative to the executable itself, so that there is no dependence on the working directory. --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 46bf7280919..c5f6addbfa0 100644 --- a/Makefile +++ b/Makefile @@ -334,6 +334,7 @@ endif LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) $(PKG_CONFIG) \ $(foreach library,$(LIBRARIES),-l$(library)) PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) +DYNAMIC_LDFLAGS := -l$(PROJECT) -Wl,-rpath,\$$ORIGIN/../lib # 'superclean' target recursively* deletes all files ending with an extension # in $(SUPERCLEAN_EXTS) below. This may be useful if you've built older @@ -503,7 +504,7 @@ $(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(DYNAMIC_NA | $(TEST_BIN_DIR) @ echo CXX/LD -o $@ $< $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ - -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(LIB_BUILD_DIR) + -o $@ $(LINKFLAGS) $(LDFLAGS) $(DYNAMIC_LDFLAGS) $(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CU_BUILD_DIR)/%.o \ $(GTEST_OBJ) $(STATIC_NAME) | $(TEST_BIN_DIR) From 8d2aebc2f4440e7d83b3031398d97230426e4196 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 21 Dec 2014 19:20:36 -0800 Subject: [PATCH 224/798] add BaseConvolutionLayer This provides a common place for code used by ConvolutionLayer and DeconvolutionLayer, simplifying the implementations of both. --- include/caffe/vision_layers.hpp | 87 ++++++++ src/caffe/layers/base_conv_layer.cpp | 289 +++++++++++++++++++++++++++ 2 files changed, 376 insertions(+) create mode 100644 src/caffe/layers/base_conv_layer.cpp diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index c803cd72449..e1bb7abf07c 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -16,6 +16,93 @@ namespace caffe { +template +class BaseConvolutionLayer : public Layer { + public: + explicit BaseConvolutionLayer(const LayerParameter& param) + : Layer(param) {} + virtual void LayerSetUp(const vector*>& bottom, + const vector*>& top); + virtual void Reshape(const vector*>& bottom, + const vector*>& top); + + virtual inline int MinBottomBlobs() const { return 1; } + virtual inline int MinTopBlobs() const { return 1; } + virtual inline bool EqualNumBottomTopBlobs() const { return true; } + + protected: + // Helper functions that abstract away the column buffer and gemm arguments. + // The last argument in forward_cpu_gemm is so that we can skip the im2col if + // we just called weight_cpu_gemm with the same input. + void forward_cpu_gemm(const Dtype* input, const Dtype* weights, + Dtype* output, bool skip_im2col = false); + void forward_cpu_bias(Dtype* output, const Dtype* bias); + void backward_cpu_gemm(const Dtype* input, const Dtype* weights, + Dtype* output); + void weight_cpu_gemm(const Dtype* input, const Dtype* output, Dtype* + weights); + void backward_cpu_bias(Dtype* bias, const Dtype* input); + + void forward_gpu_gemm(const Dtype* col_input, const Dtype* weights, + Dtype* output, bool skip_im2col = false); + void forward_gpu_bias(Dtype* output, const Dtype* bias); + void backward_gpu_gemm(const Dtype* input, const Dtype* weights, + Dtype* col_output); + void weight_gpu_gemm(const Dtype* col_input, const Dtype* output, Dtype* + weights); + void backward_gpu_bias(Dtype* bias, const Dtype* input); + + // reverse_dimensions should return true iff we are implementing deconv, so + // that conv helpers know which dimensions are which. + virtual bool reverse_dimensions() = 0; + // Compute height_out_ and width_out_ from other parameters. + virtual void compute_output_shape() = 0; + + int kernel_h_, kernel_w_; + int stride_h_, stride_w_; + int num_; + int channels_; + int pad_h_, pad_w_; + int height_, width_; + int group_; + int num_output_; + int height_out_, width_out_; + bool bias_term_; + bool is_1x1_; + + private: + // wrap im2col/col2im so we don't have to remember the (long) argument lists + inline void conv_im2col_cpu(const Dtype* data, Dtype* col_buff) { + im2col_cpu(data, conv_in_channels_, conv_in_height_, conv_in_width_, + kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, col_buff); + } + inline void conv_col2im_cpu(const Dtype* col_buff, Dtype* data) { + col2im_cpu(col_buff, conv_in_channels_, conv_in_height_, conv_in_width_, + kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, data); + } + inline void conv_im2col_gpu(const Dtype* data, Dtype* col_buff) { + im2col_gpu(data, conv_in_channels_, conv_in_height_, conv_in_width_, + kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, col_buff); + } + inline void conv_col2im_gpu(const Dtype* col_buff, Dtype* data) { + col2im_gpu(col_buff, conv_in_channels_, conv_in_height_, conv_in_width_, + kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, data); + } + + int conv_out_channels_; + int conv_in_channels_; + int conv_out_spatial_dim_; + int conv_in_height_; + int conv_in_width_; + int kernel_dim_; + int weight_offset_; + int col_offset_; + int output_offset_; + + Blob col_buffer_; + Blob bias_multiplier_; +}; + /** * @brief Convolves the input image with a bank of learned filters, * and (optionally) adds biases. diff --git a/src/caffe/layers/base_conv_layer.cpp b/src/caffe/layers/base_conv_layer.cpp new file mode 100644 index 00000000000..a44867a0cf3 --- /dev/null +++ b/src/caffe/layers/base_conv_layer.cpp @@ -0,0 +1,289 @@ +#include + +#include "caffe/filler.hpp" +#include "caffe/layer.hpp" +#include "caffe/util/im2col.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void BaseConvolutionLayer::LayerSetUp(const vector*>& bottom, + const vector*>& top) { + // Configure the kernel size, padding, stride, and inputs. + ConvolutionParameter conv_param = this->layer_param_.convolution_param(); + CHECK(!conv_param.has_kernel_size() != + !(conv_param.has_kernel_h() && conv_param.has_kernel_w())) + << "Filter size is kernel_size OR kernel_h and kernel_w; not both"; + CHECK(conv_param.has_kernel_size() || + (conv_param.has_kernel_h() && conv_param.has_kernel_w())) + << "For non-square filters both kernel_h and kernel_w are required."; + CHECK((!conv_param.has_pad() && conv_param.has_pad_h() + && conv_param.has_pad_w()) + || (!conv_param.has_pad_h() && !conv_param.has_pad_w())) + << "pad is pad OR pad_h and pad_w are required."; + CHECK((!conv_param.has_stride() && conv_param.has_stride_h() + && conv_param.has_stride_w()) + || (!conv_param.has_stride_h() && !conv_param.has_stride_w())) + << "Stride is stride OR stride_h and stride_w are required."; + if (conv_param.has_kernel_size()) { + kernel_h_ = kernel_w_ = conv_param.kernel_size(); + } else { + kernel_h_ = conv_param.kernel_h(); + kernel_w_ = conv_param.kernel_w(); + } + CHECK_GT(kernel_h_, 0) << "Filter dimensions cannot be zero."; + CHECK_GT(kernel_w_, 0) << "Filter dimensions cannot be zero."; + if (!conv_param.has_pad_h()) { + pad_h_ = pad_w_ = conv_param.pad(); + } else { + pad_h_ = conv_param.pad_h(); + pad_w_ = conv_param.pad_w(); + } + if (!conv_param.has_stride_h()) { + stride_h_ = stride_w_ = conv_param.stride(); + } else { + stride_h_ = conv_param.stride_h(); + stride_w_ = conv_param.stride_w(); + } + // Special case: im2col is the identity for 1x1 convolution with stride 1 + // and no padding, so flag for skipping the buffer and transformation. + is_1x1_ = kernel_w_ == 1 && kernel_h_ == 1 + && stride_h_ == 1 && stride_w_ == 1 && pad_h_ == 0 && pad_w_ == 0; + // Configure output channels and groups. + channels_ = bottom[0]->channels(); + num_output_ = this->layer_param_.convolution_param().num_output(); + CHECK_GT(num_output_, 0); + group_ = this->layer_param_.convolution_param().group(); + CHECK_EQ(channels_ % group_, 0); + CHECK_EQ(num_output_ % group_, 0) + << "Number of output should be multiples of group."; + if (reverse_dimensions()) { + conv_out_channels_ = channels_; + conv_in_channels_ = num_output_; + } else { + conv_out_channels_ = num_output_; + conv_in_channels_ = channels_; + } + // Handle the parameters: weights and biases. + // - blobs_[0] holds the filter weights + // - blobs_[1] holds the biases (optional) + bias_term_ = this->layer_param_.convolution_param().bias_term(); + if (this->blobs_.size() > 0) { + LOG(INFO) << "Skipping parameter initialization"; + } else { + if (bias_term_) { + this->blobs_.resize(2); + } else { + this->blobs_.resize(1); + } + // Initialize and fill the weights: + // output channels x input channels per-group x kernel height x kernel width + this->blobs_[0].reset(new Blob( + conv_out_channels_, conv_in_channels_ / group_, kernel_h_, kernel_w_)); + shared_ptr > weight_filler(GetFiller( + this->layer_param_.convolution_param().weight_filler())); + weight_filler->Fill(this->blobs_[0].get()); + // If necessary, initialize and fill the biases: + // 1 x 1 x 1 x output channels + if (bias_term_) { + this->blobs_[1].reset(new Blob(1, 1, 1, num_output_)); + shared_ptr > bias_filler(GetFiller( + this->layer_param_.convolution_param().bias_filler())); + bias_filler->Fill(this->blobs_[1].get()); + } + } + // Propagate gradients to the parameters (as directed by backward pass). + this->param_propagate_down_.resize(this->blobs_.size(), true); +} + +template +void BaseConvolutionLayer::Reshape(const vector*>& bottom, + const vector*>& top) { + num_ = bottom[0]->num(); + height_ = bottom[0]->height(); + width_ = bottom[0]->width(); + CHECK_EQ(bottom[0]->channels(), channels_) << "Input size incompatible with" + " convolution kernel."; + // TODO: generalize to handle inputs of different shapes. + for (int bottom_id = 1; bottom_id < bottom.size(); ++bottom_id) { + CHECK_EQ(num_, bottom[bottom_id]->num()) << "Inputs must have same num."; + CHECK_EQ(channels_, bottom[bottom_id]->channels()) + << "Inputs must have same channels."; + CHECK_EQ(height_, bottom[bottom_id]->height()) + << "Inputs must have same height."; + CHECK_EQ(width_, bottom[bottom_id]->width()) + << "Inputs must have same width."; + } + // Shape the tops. + compute_output_shape(); + for (int top_id = 0; top_id < top.size(); ++top_id) { + top[top_id]->Reshape(num_, num_output_, height_out_, width_out_); + } + if (reverse_dimensions()) { + conv_in_height_ = height_out_; + conv_in_width_ = width_out_; + conv_out_spatial_dim_ = height_ * width_; + } else { + conv_in_height_ = height_; + conv_in_width_ = width_; + conv_out_spatial_dim_ = height_out_ * width_out_; + } + kernel_dim_ = conv_in_channels_ * kernel_h_ * kernel_w_; + weight_offset_ = conv_out_channels_ * kernel_dim_ / group_ / group_; + col_offset_ = kernel_dim_ * conv_out_spatial_dim_ / group_; + output_offset_ = conv_out_channels_ * conv_out_spatial_dim_ / group_; + // The im2col result buffer will only hold one image at a time to avoid + // overly large memory usage. In the special case of 1x1 convolution + // it goes lazily unused to save memory. + if (reverse_dimensions()) { + col_buffer_.Reshape(1, kernel_dim_, height_, width_); + } else { + col_buffer_.Reshape(1, kernel_dim_, height_out_, width_out_); + } + // Set up the all ones "bias multiplier" for adding biases by BLAS + if (bias_term_) { + bias_multiplier_.Reshape(1, 1, 1, height_out_ * width_out_); + caffe_set(bias_multiplier_.count(), Dtype(1), + bias_multiplier_.mutable_cpu_data()); + } +} + +template +void BaseConvolutionLayer::forward_cpu_gemm(const Dtype* input, + const Dtype* weights, Dtype* output, bool skip_im2col) { + const Dtype* col_buff = input; + if (!is_1x1_) { + if (!skip_im2col) { + conv_im2col_cpu(input, col_buffer_.mutable_cpu_data()); + } + col_buff = col_buffer_.cpu_data(); + } + for (int g = 0; g < group_; ++g) { + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, conv_out_channels_ / + group_, conv_out_spatial_dim_, kernel_dim_ / group_, + (Dtype)1., weights + weight_offset_ * g, col_buff + col_offset_ * g, + (Dtype)0., output + output_offset_ * g); + } +} + +template +void BaseConvolutionLayer::forward_cpu_bias(Dtype* output, + const Dtype* bias) { + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, num_output_, + height_out_ * width_out_, 1, (Dtype)1., bias, bias_multiplier_.cpu_data(), + (Dtype)1., output); +} + +template +void BaseConvolutionLayer::backward_cpu_gemm(const Dtype* output, + const Dtype* weights, Dtype* input) { + Dtype* col_buff = col_buffer_.mutable_cpu_data(); + if (is_1x1_) { + col_buff = input; + } + for (int g = 0; g < group_; ++g) { + caffe_cpu_gemm(CblasTrans, CblasNoTrans, kernel_dim_ / group_, + conv_out_spatial_dim_, conv_out_channels_ / group_, + (Dtype)1., weights + weight_offset_ * g, output + output_offset_ * g, + (Dtype)0., col_buff + col_offset_ * g); + } + if (!is_1x1_) { + conv_col2im_cpu(col_buff, input); + } +} + +template +void BaseConvolutionLayer::weight_cpu_gemm(const Dtype* input, + const Dtype* output, Dtype* weights) { + const Dtype* col_buff = input; + if (!is_1x1_) { + conv_im2col_cpu(input, col_buffer_.mutable_cpu_data()); + col_buff = col_buffer_.cpu_data(); + } + for (int g = 0; g < group_; ++g) { + caffe_cpu_gemm(CblasNoTrans, CblasTrans, conv_out_channels_ / group_, + kernel_dim_ / group_, conv_out_spatial_dim_, + (Dtype)1., output + output_offset_ * g, col_buff + col_offset_ * g, + (Dtype)1., weights + weight_offset_ * g); + } +} + +template +void BaseConvolutionLayer::backward_cpu_bias(Dtype* bias, + const Dtype* input) { + caffe_cpu_gemv(CblasNoTrans, num_output_, height_out_ * width_out_, 1., + input, bias_multiplier_.cpu_data(), 1., bias); +} + +template +void BaseConvolutionLayer::forward_gpu_gemm(const Dtype* input, + const Dtype* weights, Dtype* output, bool skip_im2col) { + const Dtype* col_buff = input; + if (!is_1x1_) { + if (!skip_im2col) { + conv_im2col_gpu(input, col_buffer_.mutable_gpu_data()); + } + col_buff = col_buffer_.gpu_data(); + } + for (int g = 0; g < group_; ++g) { + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, conv_out_channels_ / + group_, conv_out_spatial_dim_, kernel_dim_ / group_, + (Dtype)1., weights + weight_offset_ * g, col_buff + col_offset_ * g, + (Dtype)0., output + output_offset_ * g); + } +} + +template +void BaseConvolutionLayer::forward_gpu_bias(Dtype* output, + const Dtype* bias) { + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, num_output_, + height_out_ * width_out_, 1, (Dtype)1., bias, bias_multiplier_.gpu_data(), + (Dtype)1., output); +} + +template +void BaseConvolutionLayer::backward_gpu_gemm(const Dtype* output, + const Dtype* weights, Dtype* input) { + Dtype* col_buff = col_buffer_.mutable_gpu_data(); + if (is_1x1_) { + col_buff = input; + } + for (int g = 0; g < group_; ++g) { + caffe_gpu_gemm(CblasTrans, CblasNoTrans, kernel_dim_ / group_, + conv_out_spatial_dim_, conv_out_channels_ / group_, + (Dtype)1., weights + weight_offset_ * g, output + output_offset_ * g, + (Dtype)0., col_buff + col_offset_ * g); + } + if (!is_1x1_) { + conv_col2im_gpu(col_buff, input); + } +} + +template +void BaseConvolutionLayer::weight_gpu_gemm(const Dtype* input, + const Dtype* output, Dtype* weights) { + const Dtype* col_buff = input; + if (!is_1x1_) { + conv_im2col_gpu(input, col_buffer_.mutable_gpu_data()); + col_buff = col_buffer_.gpu_data(); + } + for (int g = 0; g < group_; ++g) { + caffe_gpu_gemm(CblasNoTrans, CblasTrans, conv_out_channels_ / group_, + kernel_dim_ / group_, conv_out_spatial_dim_, + (Dtype)1., output + output_offset_ * g, col_buff + col_offset_ * g, + (Dtype)1., weights + weight_offset_ * g); + } +} + +template +void BaseConvolutionLayer::backward_gpu_bias(Dtype* bias, + const Dtype* input) { + caffe_gpu_gemv(CblasNoTrans, num_output_, height_out_ * width_out_, 1., + input, bias_multiplier_.gpu_data(), 1., bias); +} + +INSTANTIATE_CLASS(BaseConvolutionLayer); + +} // namespace caffe From a0e9db1347c325ff007166e79d1ca693e2e5de18 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 21 Dec 2014 23:33:35 -0800 Subject: [PATCH 225/798] add CPU_ONLY ifdef guards to BaseConvolutionLayer --- include/caffe/vision_layers.hpp | 4 ++++ src/caffe/layers/base_conv_layer.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index e1bb7abf07c..4cf7e8b0428 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -43,6 +43,7 @@ class BaseConvolutionLayer : public Layer { weights); void backward_cpu_bias(Dtype* bias, const Dtype* input); +#ifndef CPU_ONLY void forward_gpu_gemm(const Dtype* col_input, const Dtype* weights, Dtype* output, bool skip_im2col = false); void forward_gpu_bias(Dtype* output, const Dtype* bias); @@ -51,6 +52,7 @@ class BaseConvolutionLayer : public Layer { void weight_gpu_gemm(const Dtype* col_input, const Dtype* output, Dtype* weights); void backward_gpu_bias(Dtype* bias, const Dtype* input); +#endif // reverse_dimensions should return true iff we are implementing deconv, so // that conv helpers know which dimensions are which. @@ -80,6 +82,7 @@ class BaseConvolutionLayer : public Layer { col2im_cpu(col_buff, conv_in_channels_, conv_in_height_, conv_in_width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, data); } +#ifndef CPU_ONLY inline void conv_im2col_gpu(const Dtype* data, Dtype* col_buff) { im2col_gpu(data, conv_in_channels_, conv_in_height_, conv_in_width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, col_buff); @@ -88,6 +91,7 @@ class BaseConvolutionLayer : public Layer { col2im_gpu(col_buff, conv_in_channels_, conv_in_height_, conv_in_width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, data); } +#endif int conv_out_channels_; int conv_in_channels_; diff --git a/src/caffe/layers/base_conv_layer.cpp b/src/caffe/layers/base_conv_layer.cpp index a44867a0cf3..dccd5170c11 100644 --- a/src/caffe/layers/base_conv_layer.cpp +++ b/src/caffe/layers/base_conv_layer.cpp @@ -217,6 +217,8 @@ void BaseConvolutionLayer::backward_cpu_bias(Dtype* bias, input, bias_multiplier_.cpu_data(), 1., bias); } +#ifndef CPU_ONLY + template void BaseConvolutionLayer::forward_gpu_gemm(const Dtype* input, const Dtype* weights, Dtype* output, bool skip_im2col) { @@ -284,6 +286,8 @@ void BaseConvolutionLayer::backward_gpu_bias(Dtype* bias, input, bias_multiplier_.gpu_data(), 1., bias); } +#endif // !CPU_ONLY + INSTANTIATE_CLASS(BaseConvolutionLayer); } // namespace caffe From e3e2f2d3139880f77355e6837e72ad6c2848b448 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 21 Dec 2014 19:42:29 -0800 Subject: [PATCH 226/798] rewrite ConvolutionLayer to use BaseConvolutionLayer helpers --- include/caffe/vision_layers.hpp | 36 +---- src/caffe/layers/conv_layer.cpp | 243 ++++---------------------------- src/caffe/layers/conv_layer.cu | 117 +++------------ 3 files changed, 56 insertions(+), 340 deletions(-) diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 4cf7e8b0428..4d93e6c10fc 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -124,7 +124,7 @@ class BaseConvolutionLayer : public Layer { * the output channel N' columns of the output matrix. */ template -class ConvolutionLayer : public Layer { +class ConvolutionLayer : public BaseConvolutionLayer { public: /** * @param param provides ConvolutionParameter convolution_param, @@ -155,18 +155,10 @@ class ConvolutionLayer : public Layer { * kernels + stream parallelism) engines. */ explicit ConvolutionLayer(const LayerParameter& param) - : Layer(param) {} - virtual void LayerSetUp(const vector*>& bottom, - const vector*>& top); - virtual void Reshape(const vector*>& bottom, - const vector*>& top); - + : BaseConvolutionLayer(param) {} virtual inline LayerParameter_LayerType type() const { return LayerParameter_LayerType_CONVOLUTION; } - virtual inline int MinBottomBlobs() const { return 1; } - virtual inline int MinTopBlobs() const { return 1; } - virtual inline bool EqualNumBottomTopBlobs() const { return true; } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -177,30 +169,10 @@ class ConvolutionLayer : public Layer { const vector& propagate_down, const vector*>& bottom); virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + virtual inline bool reverse_dimensions() { return false; } + virtual void compute_output_shape(); - int kernel_h_, kernel_w_; - int stride_h_, stride_w_; - int num_; - int channels_; - int pad_h_, pad_w_; - int height_, width_; - int group_; - int num_output_; - int height_out_, width_out_; - bool bias_term_; - bool is_1x1_; - /// M_ is the channel dimension of the output for a single group, which is the - /// leading dimension of the filter matrix. - int M_; - /// K_ is the dimension of an unrolled input for a single group, which is the - /// leading dimension of the data matrix. - int K_; - /// N_ is the spatial dimension of the output, the H x W, which are the last - /// dimensions of the data and filter matrices. - int N_; - Blob col_buffer_; - Blob bias_multiplier_; }; #ifdef USE_CUDNN diff --git a/src/caffe/layers/conv_layer.cpp b/src/caffe/layers/conv_layer.cpp index 0a032025bfb..9fd2fc6a15f 100644 --- a/src/caffe/layers/conv_layer.cpp +++ b/src/caffe/layers/conv_layer.cpp @@ -9,166 +9,26 @@ namespace caffe { template -void ConvolutionLayer::LayerSetUp(const vector*>& bottom, - const vector*>& top) { - // Configure the kernel size, padding, stride, and inputs. - ConvolutionParameter conv_param = this->layer_param_.convolution_param(); - CHECK(!conv_param.has_kernel_size() != - !(conv_param.has_kernel_h() && conv_param.has_kernel_w())) - << "Filter size is kernel_size OR kernel_h and kernel_w; not both"; - CHECK(conv_param.has_kernel_size() || - (conv_param.has_kernel_h() && conv_param.has_kernel_w())) - << "For non-square filters both kernel_h and kernel_w are required."; - CHECK((!conv_param.has_pad() && conv_param.has_pad_h() - && conv_param.has_pad_w()) - || (!conv_param.has_pad_h() && !conv_param.has_pad_w())) - << "pad is pad OR pad_h and pad_w are required."; - CHECK((!conv_param.has_stride() && conv_param.has_stride_h() - && conv_param.has_stride_w()) - || (!conv_param.has_stride_h() && !conv_param.has_stride_w())) - << "Stride is stride OR stride_h and stride_w are required."; - if (conv_param.has_kernel_size()) { - kernel_h_ = kernel_w_ = conv_param.kernel_size(); - } else { - kernel_h_ = conv_param.kernel_h(); - kernel_w_ = conv_param.kernel_w(); - } - CHECK_GT(kernel_h_, 0) << "Filter dimensions cannot be zero."; - CHECK_GT(kernel_w_, 0) << "Filter dimensions cannot be zero."; - if (!conv_param.has_pad_h()) { - pad_h_ = pad_w_ = conv_param.pad(); - } else { - pad_h_ = conv_param.pad_h(); - pad_w_ = conv_param.pad_w(); - } - if (!conv_param.has_stride_h()) { - stride_h_ = stride_w_ = conv_param.stride(); - } else { - stride_h_ = conv_param.stride_h(); - stride_w_ = conv_param.stride_w(); - } - // Special case: im2col is the identity for 1x1 convolution with stride 1 - // and no padding, so flag for skipping the buffer and transformation. - is_1x1_ = kernel_w_ == 1 && kernel_h_ == 1 - && stride_h_ == 1 && stride_w_ == 1 && pad_h_ == 0 && pad_w_ == 0; - // Configure output channels and groups. - channels_ = bottom[0]->channels(); - num_output_ = this->layer_param_.convolution_param().num_output(); - CHECK_GT(num_output_, 0); - group_ = this->layer_param_.convolution_param().group(); - CHECK_EQ(channels_ % group_, 0); - CHECK_EQ(num_output_ % group_, 0) - << "Number of output should be multiples of group."; - // Handle the parameters: weights and biases. - // - blobs_[0] holds the filter weights - // - blobs_[1] holds the biases (optional) - bias_term_ = this->layer_param_.convolution_param().bias_term(); - if (this->blobs_.size() > 0) { - LOG(INFO) << "Skipping parameter initialization"; - } else { - if (bias_term_) { - this->blobs_.resize(2); - } else { - this->blobs_.resize(1); - } - // Initialize and fill the weights: - // output channels x input channels per-group x kernel height x kernel width - this->blobs_[0].reset(new Blob( - num_output_, channels_ / group_, kernel_h_, kernel_w_)); - shared_ptr > weight_filler(GetFiller( - this->layer_param_.convolution_param().weight_filler())); - weight_filler->Fill(this->blobs_[0].get()); - // If necessary, initialize and fill the biases: - // 1 x 1 x 1 x output channels - if (bias_term_) { - this->blobs_[1].reset(new Blob(1, 1, 1, num_output_)); - shared_ptr > bias_filler(GetFiller( - this->layer_param_.convolution_param().bias_filler())); - bias_filler->Fill(this->blobs_[1].get()); - } - } - // Propagate gradients to the parameters (as directed by backward pass). - this->param_propagate_down_.resize(this->blobs_.size(), true); -} - -template -void ConvolutionLayer::Reshape(const vector*>& bottom, - const vector*>& top) { - num_ = bottom[0]->num(); - height_ = bottom[0]->height(); - width_ = bottom[0]->width(); - CHECK_EQ(bottom[0]->channels(), channels_) << "Input size incompatible with" - " convolution kernel."; - // TODO: generalize to handle inputs of different shapes. - for (int bottom_id = 1; bottom_id < bottom.size(); ++bottom_id) { - CHECK_EQ(num_, bottom[bottom_id]->num()) << "Inputs must have same num."; - CHECK_EQ(channels_, bottom[bottom_id]->channels()) - << "Inputs must have same channels."; - CHECK_EQ(height_, bottom[bottom_id]->height()) - << "Inputs must have same height."; - CHECK_EQ(width_, bottom[bottom_id]->width()) - << "Inputs must have same width."; - } - // Shape the tops. - height_out_ = - (height_ + 2 * pad_h_ - kernel_h_) / stride_h_ + 1; - width_out_ = (width_ + 2 * pad_w_ - kernel_w_) / stride_w_ + 1; - for (int top_id = 0; top_id < top.size(); ++top_id) { - top[top_id]->Reshape(num_, num_output_, height_out_, width_out_); - } - // Prepare the matrix multiplication computation. - // Each input will be convolved as a single GEMM. - M_ = num_output_ / group_; - K_ = channels_ * kernel_h_ * kernel_w_ / group_; - N_ = height_out_ * width_out_; - // The im2col result buffer will only hold one image at a time to avoid - // overly large memory usage. In the special case of 1x1 convolution - // it goes lazily unused to save memory. - col_buffer_.Reshape( - 1, channels_ * kernel_h_ * kernel_w_, height_out_, width_out_); - // Set up the all ones "bias multiplier" for adding biases by BLAS - if (bias_term_) { - bias_multiplier_.Reshape(1, 1, 1, N_); - caffe_set(N_, Dtype(1), bias_multiplier_.mutable_cpu_data()); - } +void ConvolutionLayer::compute_output_shape() { + this->height_out_ = (this->height_ + 2 * this->pad_h_ - this->kernel_h_) + / this->stride_h_ + 1; + this->width_out_ = (this->width_ + 2 * this->pad_w_ - this->kernel_w_) + / this->stride_w_ + 1; } template void ConvolutionLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { + const Dtype* weight = this->blobs_[0]->cpu_data(); for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->cpu_data(); Dtype* top_data = top[i]->mutable_cpu_data(); - Dtype* col_buff = NULL; - if (!is_1x1_) { - col_buff = col_buffer_.mutable_cpu_data(); - } - const Dtype* weight = this->blobs_[0]->cpu_data(); - int weight_offset = M_ * K_; // number of filter parameters in a group - int col_offset = K_ * N_; // number of values in an input region / column - int top_offset = M_ * N_; // number of values in an output region / column - for (int n = 0; n < num_; ++n) { - // im2col transformation: unroll input regions for filtering - // into column matrix for multplication. - if (!is_1x1_) { - im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, - width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - col_buff); - } else { // special case for 1x1 convolution - col_buff = bottom[i]->mutable_cpu_data() + bottom[i]->offset(n); - } - // Take inner products for groups. - for (int g = 0; g < group_; ++g) { - caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, - (Dtype)1., weight + weight_offset * g, col_buff + col_offset * g, - (Dtype)0., top_data + top[i]->offset(n) + top_offset * g); - } - // Add bias. - if (bias_term_) { - caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, num_output_, - N_, 1, (Dtype)1., this->blobs_[1]->cpu_data(), - bias_multiplier_.cpu_data(), - (Dtype)1., top_data + top[i]->offset(n)); + for (int n = 0; n < this->num_; ++n) { + this->forward_cpu_gemm(bottom_data + bottom[i]->offset(n), weight, + top_data + top[i]->offset(n)); + if (this->bias_term_) { + const Dtype* bias = this->blobs_[1]->cpu_data(); + this->forward_cpu_bias(top_data + top[i]->offset(n), bias); } } } @@ -177,82 +37,37 @@ void ConvolutionLayer::Forward_cpu(const vector*>& bottom, template void ConvolutionLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom) { - const Dtype* weight = NULL; - Dtype* weight_diff = NULL; + const Dtype* weight = this->blobs_[0]->cpu_data(); + Dtype* weight_diff = this->blobs_[0]->mutable_cpu_diff(); if (this->param_propagate_down_[0]) { - weight = this->blobs_[0]->cpu_data(); - weight_diff = this->blobs_[0]->mutable_cpu_diff(); caffe_set(this->blobs_[0]->count(), Dtype(0), weight_diff); } - Dtype* bias_diff = NULL; - if (bias_term_ && this->param_propagate_down_[1]) { - bias_diff = this->blobs_[1]->mutable_cpu_diff(); - caffe_set(this->blobs_[1]->count(), Dtype(0), bias_diff); + if (this->bias_term_ && this->param_propagate_down_[1]) { + caffe_set(this->blobs_[1]->count(), Dtype(0), + this->blobs_[1]->mutable_cpu_diff()); } - const int weight_offset = M_ * K_; - const int col_offset = K_ * N_; - const int top_offset = M_ * N_; for (int i = 0; i < top.size(); ++i) { - const Dtype* top_diff = NULL; + const Dtype* top_diff = top[i]->cpu_diff(); + const Dtype* bottom_data = bottom[i]->cpu_data(); + Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); // Bias gradient, if necessary. - if (bias_term_ && this->param_propagate_down_[1]) { - top_diff = top[i]->cpu_diff(); - for (int n = 0; n < num_; ++n) { - caffe_cpu_gemv(CblasNoTrans, num_output_, N_, - 1., top_diff + top[0]->offset(n), - bias_multiplier_.cpu_data(), 1., - bias_diff); + if (this->bias_term_ && this->param_propagate_down_[1]) { + Dtype* bias_diff = this->blobs_[1]->mutable_cpu_diff(); + for (int n = 0; n < this->num_; ++n) { + this->backward_cpu_bias(bias_diff, top_diff + top[i]->offset(n)); } } if (this->param_propagate_down_[0] || propagate_down[i]) { - if (!top_diff) { - top_diff = top[i]->cpu_diff(); - } - Dtype* col_buff = NULL; - if (!is_1x1_) { - col_buff = col_buffer_.mutable_cpu_data(); - } - const Dtype* bottom_data = bottom[i]->cpu_data(); - Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); - for (int n = 0; n < num_; ++n) { - // Since we saved memory in the forward pass by not storing all col - // data, we will need to recompute them. - if (!is_1x1_) { - im2col_cpu(bottom_data + bottom[i]->offset(n), channels_, height_, - width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, col_buff); - } else { - col_buff = bottom[i]->mutable_cpu_data() + bottom[i]->offset(n); - } + for (int n = 0; n < this->num_; ++n) { // gradient w.r.t. weight. Note that we will accumulate diffs. if (this->param_propagate_down_[0]) { - for (int g = 0; g < group_; ++g) { - caffe_cpu_gemm(CblasNoTrans, CblasTrans, M_, K_, N_, - (Dtype)1., top_diff + top[i]->offset(n) + top_offset * g, - col_buff + col_offset * g, (Dtype)1., - weight_diff + weight_offset * g); - } + this->weight_cpu_gemm(bottom_data + bottom[i]->offset(n), + top_diff + top[i]->offset(n), weight_diff); } // gradient w.r.t. bottom data, if necessary. if (propagate_down[i]) { - if (weight == NULL) { - weight = this->blobs_[0]->cpu_data(); - } - if (is_1x1_) { - col_buff = bottom[i]->mutable_cpu_diff() + bottom[i]->offset(n); - } - for (int g = 0; g < group_; ++g) { - caffe_cpu_gemm(CblasTrans, CblasNoTrans, K_, N_, M_, - (Dtype)1., weight + weight_offset * g, - top_diff + top[i]->offset(n) + top_offset * g, - (Dtype)0., col_buff + col_offset * g); - } - // col2im back to the data - if (!is_1x1_) { - col2im_cpu(col_buff, channels_, height_, width_, - kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, bottom_diff + bottom[i]->offset(n)); - } + this->backward_cpu_gemm(top_diff + top[i]->offset(n), weight, + bottom_diff + bottom[i]->offset(n)); } } } diff --git a/src/caffe/layers/conv_layer.cu b/src/caffe/layers/conv_layer.cu index af14facb523..3902fdf3930 100644 --- a/src/caffe/layers/conv_layer.cu +++ b/src/caffe/layers/conv_layer.cu @@ -8,135 +8,64 @@ namespace caffe { -/// @brief refer to CPU forward -- the BLAS implementation is the same. template void ConvolutionLayer::Forward_gpu(const vector*>& bottom, const vector*>& top) { + const Dtype* weight = this->blobs_[0]->gpu_data(); for (int i = 0; i < bottom.size(); ++i) { const Dtype* bottom_data = bottom[i]->gpu_data(); Dtype* top_data = top[i]->mutable_gpu_data(); - Dtype* col_buff = NULL; - if (!is_1x1_) { - col_buff = col_buffer_.mutable_gpu_data(); - } - const Dtype* weight = this->blobs_[0]->gpu_data(); - int weight_offset = M_ * K_; - int col_offset = K_ * N_; - int top_offset = M_ * N_; - for (int n = 0; n < num_; ++n) { - // im2col transformation: unroll input regions for filtering - // into column matrix for multplication. - if (!is_1x1_) { - im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, - width_, kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - col_buff); - } else { - col_buff = bottom[i]->mutable_gpu_data() + bottom[i]->offset(n); - } - // Take inner products for groups. - for (int g = 0; g < group_; ++g) { - caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, - (Dtype)1., weight + weight_offset * g, col_buff + col_offset * g, - (Dtype)0., top_data + top[i]->offset(n) + top_offset * g); - } - // Add bias. - if (bias_term_) { - caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, num_output_, - N_, 1, (Dtype)1., this->blobs_[1]->gpu_data(), - bias_multiplier_.gpu_data(), - (Dtype)1., top_data + top[i]->offset(n)); + for (int n = 0; n < this->num_; ++n) { + this->forward_gpu_gemm(bottom_data + bottom[i]->offset(n), weight, + top_data + top[i]->offset(n)); + if (this->bias_term_) { + const Dtype* bias = this->blobs_[1]->gpu_data(); + this->forward_gpu_bias(top_data + top[i]->offset(n), bias); } } } } -/// @brief refer to CPU backward -- the BLAS implementation is the same. template void ConvolutionLayer::Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom) { - const Dtype* weight = NULL; - Dtype* weight_diff = NULL; + const Dtype* weight = this->blobs_[0]->gpu_data(); + Dtype* weight_diff = this->blobs_[0]->mutable_gpu_diff(); if (this->param_propagate_down_[0]) { - weight = this->blobs_[0]->gpu_data(); - weight_diff = this->blobs_[0]->mutable_gpu_diff(); caffe_gpu_set(this->blobs_[0]->count(), Dtype(0), weight_diff); } - Dtype* bias_diff = NULL; - if (bias_term_ && this->param_propagate_down_[1]) { - bias_diff = this->blobs_[1]->mutable_gpu_diff(); - caffe_gpu_set(this->blobs_[1]->count(), Dtype(0), bias_diff); + if (this->bias_term_ && this->param_propagate_down_[1]) { + caffe_gpu_set(this->blobs_[1]->count(), Dtype(0), + this->blobs_[1]->mutable_gpu_diff()); } - const int weight_offset = M_ * K_; - const int col_offset = K_ * N_; - const int top_offset = M_ * N_; for (int i = 0; i < top.size(); ++i) { - const Dtype* top_diff = NULL; + const Dtype* top_diff = top[i]->gpu_diff(); // Bias gradient, if necessary. - if (bias_term_ && this->param_propagate_down_[1]) { - top_diff = top[i]->gpu_diff(); - for (int n = 0; n < num_; ++n) { - caffe_gpu_gemv(CblasNoTrans, num_output_, N_, - 1., top_diff + top[0]->offset(n), - bias_multiplier_.gpu_data(), 1., - bias_diff); + if (this->bias_term_ && this->param_propagate_down_[1]) { + Dtype* bias_diff = this->blobs_[1]->mutable_gpu_diff(); + for (int n = 0; n < this->num_; ++n) { + this->backward_gpu_bias(bias_diff, top_diff + top[i]->offset(n)); } } if (this->param_propagate_down_[0] || propagate_down[i]) { - if (!top_diff) { - top_diff = top[i]->gpu_diff(); - } - Dtype* col_buff = NULL; - if (!is_1x1_) { - col_buff = col_buffer_.mutable_gpu_data(); - } const Dtype* bottom_data = bottom[i]->gpu_data(); Dtype* bottom_diff = bottom[i]->mutable_gpu_diff(); - for (int n = 0; n < num_; ++n) { - // Since we saved memory in the forward pass by not storing all col - // data, we will need to recompute them. - if (!is_1x1_) { - im2col_gpu(bottom_data + bottom[i]->offset(n), channels_, height_, - width_, kernel_h_, kernel_w_, pad_h_, pad_w_, - stride_h_, stride_w_, col_buff); - } else { - col_buff = bottom[i]->mutable_gpu_data() + bottom[i]->offset(n); - } + for (int n = 0; n < this->num_; ++n) { // gradient w.r.t. weight. Note that we will accumulate diffs. if (this->param_propagate_down_[0]) { - for (int g = 0; g < group_; ++g) { - caffe_gpu_gemm(CblasNoTrans, CblasTrans, M_, K_, N_, - (Dtype)1., top_diff + top[i]->offset(n) + top_offset * g, - col_buff + col_offset * g, (Dtype)1., - weight_diff + weight_offset * g); - } + this->weight_gpu_gemm(bottom_data + bottom[i]->offset(n), + top_diff + top[i]->offset(n), weight_diff); } - // gradient w.r.t. bottom data, if necessary + // gradient w.r.t. bottom data, if necessary. if (propagate_down[i]) { - if (weight == NULL) { - weight = this->blobs_[0]->gpu_data(); - } - if (is_1x1_) { - col_buff = bottom[i]->mutable_gpu_diff() + bottom[i]->offset(n); - } - for (int g = 0; g < group_; ++g) { - caffe_gpu_gemm(CblasTrans, CblasNoTrans, K_, N_, M_, - (Dtype)1., weight + weight_offset * g, - top_diff + top[i]->offset(n) + top_offset * g, - (Dtype)0., col_buff + col_offset * g); - } - // col2im back to the data - if (!is_1x1_) { - col2im_gpu(col_buff, channels_, height_, width_, - kernel_h_, kernel_w_, pad_h_, pad_w_, stride_h_, stride_w_, - bottom_diff + bottom[i]->offset(n)); - } + this->backward_gpu_gemm(top_diff + top[i]->offset(n), weight, + bottom_diff + bottom[i]->offset(n)); } } } } } - INSTANTIATE_LAYER_GPU_FUNCS(ConvolutionLayer); } // namespace caffe From 3617352124ab97154d37534e4ba30d7a2b9b6d2f Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Sun, 21 Dec 2014 19:43:36 -0800 Subject: [PATCH 227/798] add DeconvolutionLayer, using BaseConvolutionLayer --- include/caffe/vision_layers.hpp | 20 ++++++++ src/caffe/layers/deconv_layer.cpp | 85 +++++++++++++++++++++++++++++++ src/caffe/layers/deconv_layer.cu | 71 ++++++++++++++++++++++++++ src/caffe/proto/caffe.proto | 3 +- 4 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 src/caffe/layers/deconv_layer.cpp create mode 100644 src/caffe/layers/deconv_layer.cu diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 4d93e6c10fc..646378dea9f 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -171,8 +171,28 @@ class ConvolutionLayer : public BaseConvolutionLayer { const vector& propagate_down, const vector*>& bottom); virtual inline bool reverse_dimensions() { return false; } virtual void compute_output_shape(); +}; +template +class DeconvolutionLayer : public BaseConvolutionLayer { + public: + explicit DeconvolutionLayer(const LayerParameter& param) + : BaseConvolutionLayer(param) {} + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_DECONVOLUTION; + } + protected: + virtual void Forward_cpu(const vector*>& bottom, + const vector*>& top); + virtual void Forward_gpu(const vector*>& bottom, + const vector*>& top); + virtual void Backward_cpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom); + virtual void Backward_gpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom); + virtual inline bool reverse_dimensions() { return true; } + virtual void compute_output_shape(); }; #ifdef USE_CUDNN diff --git a/src/caffe/layers/deconv_layer.cpp b/src/caffe/layers/deconv_layer.cpp new file mode 100644 index 00000000000..59114f017bf --- /dev/null +++ b/src/caffe/layers/deconv_layer.cpp @@ -0,0 +1,85 @@ +#include + +#include "caffe/filler.hpp" +#include "caffe/layer.hpp" +#include "caffe/util/im2col.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void DeconvolutionLayer::compute_output_shape() { + this->height_out_ = this->stride_h_ * (this->height_ - 1) + this->kernel_h_ + - 2 * this->pad_h_; + this->width_out_ = this->stride_w_ * (this->width_ - 1) + this->kernel_w_ + - 2 * this->pad_w_; +} + +template +void DeconvolutionLayer::Forward_cpu(const vector*>& bottom, + const vector*>& top) { + const Dtype* weight = this->blobs_[0]->cpu_data(); + for (int i = 0; i < bottom.size(); ++i) { + const Dtype* bottom_data = bottom[i]->cpu_data(); + Dtype* top_data = top[i]->mutable_cpu_data(); + for (int n = 0; n < this->num_; ++n) { + this->backward_cpu_gemm(bottom_data + bottom[i]->offset(n), weight, + top_data + top[i]->offset(n)); + if (this->bias_term_) { + const Dtype* bias = this->blobs_[1]->cpu_data(); + this->forward_cpu_bias(top_data + top[i]->offset(n), bias); + } + } + } +} + +template +void DeconvolutionLayer::Backward_cpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom) { + const Dtype* weight = this->blobs_[0]->cpu_data(); + Dtype* weight_diff = this->blobs_[0]->mutable_cpu_diff(); + if (this->param_propagate_down_[0]) { + caffe_set(this->blobs_[0]->count(), Dtype(0), weight_diff); + } + if (this->bias_term_ && this->param_propagate_down_[1]) { + caffe_set(this->blobs_[1]->count(), Dtype(0), + this->blobs_[1]->mutable_cpu_diff()); + } + for (int i = 0; i < top.size(); ++i) { + const Dtype* top_diff = top[i]->cpu_diff(); + const Dtype* bottom_data = bottom[i]->cpu_data(); + Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); + // Bias gradient, if necessary. + if (this->bias_term_ && this->param_propagate_down_[1]) { + Dtype* bias_diff = this->blobs_[1]->mutable_cpu_diff(); + for (int n = 0; n < this->num_; ++n) { + this->backward_cpu_bias(bias_diff, top_diff + top[i]->offset(n)); + } + } + if (this->param_propagate_down_[0] || propagate_down[i]) { + for (int n = 0; n < this->num_; ++n) { + // Gradient w.r.t. weight. Note that we will accumulate diffs. + if (this->param_propagate_down_[0]) { + this->weight_cpu_gemm(top_diff + top[i]->offset(n), + bottom_data + bottom[i]->offset(n), weight_diff); + } + // Gradient w.r.t. bottom data, if necessary, reusing the column buffer + // we might have just computed above. + if (propagate_down[i]) { + this->forward_cpu_gemm(top_diff + top[i]->offset(n), weight, + bottom_diff + bottom[i]->offset(n), + this->param_propagate_down_[0]); + } + } + } + } +} + +#ifdef CPU_ONLY +STUB_GPU(DeconvolutionLayer); +#endif + +INSTANTIATE_CLASS(DeconvolutionLayer); +REGISTER_LAYER_CLASS(DECONVOLUTION, DeconvolutionLayer); +} // namespace caffe diff --git a/src/caffe/layers/deconv_layer.cu b/src/caffe/layers/deconv_layer.cu new file mode 100644 index 00000000000..9198dd64c72 --- /dev/null +++ b/src/caffe/layers/deconv_layer.cu @@ -0,0 +1,71 @@ +#include + +#include "caffe/filler.hpp" +#include "caffe/layer.hpp" +#include "caffe/util/im2col.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void DeconvolutionLayer::Forward_gpu(const vector*>& bottom, + const vector*>& top) { + const Dtype* weight = this->blobs_[0]->gpu_data(); + for (int i = 0; i < bottom.size(); ++i) { + const Dtype* bottom_data = bottom[i]->gpu_data(); + Dtype* top_data = top[i]->mutable_gpu_data(); + for (int n = 0; n < this->num_; ++n) { + this->backward_gpu_gemm(bottom_data + bottom[i]->offset(n), weight, + top_data + top[i]->offset(n)); + if (this->bias_term_) { + const Dtype* bias = this->blobs_[1]->gpu_data(); + this->forward_gpu_bias(top_data + top[i]->offset(n), bias); + } + } + } +} + +template +void DeconvolutionLayer::Backward_gpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom) { + const Dtype* weight = this->blobs_[0]->gpu_data(); + Dtype* weight_diff = this->blobs_[0]->mutable_gpu_diff(); + if (this->param_propagate_down_[0]) { + caffe_gpu_set(this->blobs_[0]->count(), Dtype(0), weight_diff); + } + if (this->bias_term_ && this->param_propagate_down_[1]) { + caffe_gpu_set(this->blobs_[1]->count(), Dtype(0), + this->blobs_[1]->mutable_gpu_diff()); + } + for (int i = 0; i < top.size(); ++i) { + const Dtype* top_diff = top[i]->gpu_diff(); + const Dtype* bottom_data = bottom[i]->gpu_data(); + Dtype* bottom_diff = bottom[i]->mutable_gpu_diff(); + // Bias gradient, if necessary. + if (this->bias_term_ && this->param_propagate_down_[1]) { + Dtype* bias_diff = this->blobs_[1]->mutable_gpu_diff(); + for (int n = 0; n < this->num_; ++n) { + this->backward_gpu_bias(bias_diff, top_diff + top[i]->offset(n)); + } + } + if (this->param_propagate_down_[0] || propagate_down[i]) { + for (int n = 0; n < this->num_; ++n) { + // gradient w.r.t. weight. Note that we will accumulate diffs. + if (this->param_propagate_down_[0]) { + this->weight_gpu_gemm(top_diff + top[i]->offset(n), + bottom_data + bottom[i]->offset(n), weight_diff); + } + // gradient w.r.t. bottom data, if necessary. + if (propagate_down[i]) { + this->forward_gpu_gemm(top_diff + top[i]->offset(n), weight, + bottom_diff + bottom[i]->offset(n)); + } + } + } + } +} + +INSTANTIATE_LAYER_GPU_FUNCS(DeconvolutionLayer); + +} // namespace caffe diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 8086ad66579..e83eefa1622 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -227,7 +227,7 @@ message LayerParameter { // line above the enum. Update the next available ID when you add a new // LayerType. // - // LayerType next available ID: 39 (last added: EXP) + // LayerType next available ID: 40 (last added: DECONVOLUTION) enum LayerType { // "NONE" layer type is 0th enum element so that we don't cause confusion // by defaulting to an existent LayerType (instead, should usually error if @@ -241,6 +241,7 @@ message LayerParameter { CONTRASTIVE_LOSS = 37; CONVOLUTION = 4; DATA = 5; + DECONVOLUTION = 39; DROPOUT = 6; DUMMY_DATA = 32; EUCLIDEAN_LOSS = 7; From f2057680c7f633ec0d9d63d865d09fe1b958ebee Mon Sep 17 00:00:00 2001 From: Pannous Date: Wed, 14 Jan 2015 18:43:49 +0100 Subject: [PATCH 228/798] Message: Please ask usage questions and how to model different tasks on the caffe-users mailing list --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0e3c833e8fb..9a9b3ee36eb 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,7 @@ Caffe is a deep learning framework developed with cleanliness, readability, and speed in mind.
Consult the [project website](http://caffe.berkeleyvision.org) for all documentation. + + +Please ask usage questions and how to model different tasks on the [caffe-users mailing list](https://groups.google.com/forum/#!forum/caffe-users). + From 4041e4d0117e46bb213a6017e9e34806a8ccb286 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Wed, 14 Jan 2015 17:56:23 -0800 Subject: [PATCH 229/798] set mode, phase, device in pycaffe; fix #1700 Attach mode, phase, and device setters to caffe module itself so that these can be set before making nets. This is needed to properly initialize layers with the right device and phase configuration. Update examples to new usage. --- examples/classification.ipynb | 54 +++++++++++------------------ examples/filter_visualization.ipynb | 9 ++--- examples/net_surgery.ipynb | 7 ++-- python/caffe/__init__.py | 2 ++ python/caffe/_caffe.cpp | 12 ++++--- python/caffe/_caffe.hpp | 13 ++++--- python/caffe/classifier.py | 6 ++-- python/caffe/detector.py | 6 ++-- python/caffe/pycaffe.py | 2 ++ 9 files changed, 52 insertions(+), 59 deletions(-) diff --git a/examples/classification.ipynb b/examples/classification.ipynb index 1e2126fe652..6b6c5488d36 100644 --- a/examples/classification.ipynb +++ b/examples/classification.ipynb @@ -3,7 +3,8 @@ "description": "Use the pre-trained ImageNet model to classify images with the Python interface.", "example_name": "ImageNet classification", "include_in_docs": true, - "priority": 1 + "priority": 1, + "signature": "sha256:2caae2c1fe3e282b8f836d380a45622351c91db18a1591e4f2fa67faba9ab72c" }, "nbformat": 3, "nbformat_minor": 0, @@ -54,13 +55,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Loading a network is easy. `caffe.Classifier` takes care of everything. Note the arguments for configuring input preprocessing: mean subtraction switched on by giving a mean array, input channel swapping takes care of mapping RGB into the reference ImageNet model's BGR order, and raw scaling multiplies the feature scale from the input [0,1] to the ImageNet model's [0,255]." + "Loading a network is easy. `caffe.Classifier` takes care of everything. Note the arguments for configuring input preprocessing: mean subtraction switched on by giving a mean array, input channel swapping takes care of mapping RGB into the reference ImageNet model's BGR order, and raw scaling multiplies the feature scale from the input [0,1] to the ImageNet model's [0,255].\n", + "\n", + "We will set the phase to test since we are doing testing, and will first use CPU for the computation." ] }, { "cell_type": "code", "collapsed": false, "input": [ + "caffe.set_phase_test()\n", + "caffe.set_mode_cpu()\n", "net = caffe.Classifier(MODEL_FILE, PRETRAINED,\n", " mean=np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy'),\n", " channel_swap=(2,1,0),\n", @@ -72,25 +77,6 @@ "outputs": [], "prompt_number": 2 }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will set the phase to test since we are doing testing, and will first use CPU for the computation." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "net.set_phase_test()\n", - "net.set_mode_cpu()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 3 - }, { "cell_type": "markdown", "metadata": {}, @@ -111,7 +97,7 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 4, + "prompt_number": 3, "text": [ "" ] @@ -125,7 +111,7 @@ ] } ], - "prompt_number": 4 + "prompt_number": 3 }, { "cell_type": "markdown", @@ -163,7 +149,7 @@ ] } ], - "prompt_number": 5 + "prompt_number": 4 }, { "cell_type": "markdown", @@ -205,7 +191,7 @@ ] } ], - "prompt_number": 6 + "prompt_number": 5 }, { "cell_type": "markdown", @@ -233,7 +219,7 @@ ] } ], - "prompt_number": 7 + "prompt_number": 6 }, { "cell_type": "markdown", @@ -266,7 +252,7 @@ ] } ], - "prompt_number": 8 + "prompt_number": 7 }, { "cell_type": "markdown", @@ -279,12 +265,12 @@ "cell_type": "code", "collapsed": false, "input": [ - "net.set_mode_gpu()" + "caffe.set_mode_gpu()" ], "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 9 + "prompt_number": 8 }, { "cell_type": "markdown", @@ -314,7 +300,7 @@ { "metadata": {}, "output_type": "pyout", - "prompt_number": 10, + "prompt_number": 9, "text": [ "[]" ] @@ -328,7 +314,7 @@ ] } ], - "prompt_number": 10 + "prompt_number": 9 }, { "cell_type": "markdown", @@ -355,7 +341,7 @@ ] } ], - "prompt_number": 11 + "prompt_number": 10 }, { "cell_type": "code", @@ -375,7 +361,7 @@ ] } ], - "prompt_number": 12 + "prompt_number": 11 }, { "cell_type": "markdown", @@ -404,4 +390,4 @@ "metadata": {} } ] -} +} \ No newline at end of file diff --git a/examples/filter_visualization.ipynb b/examples/filter_visualization.ipynb index 09b416fb4ca..8e068805d62 100644 --- a/examples/filter_visualization.ipynb +++ b/examples/filter_visualization.ipynb @@ -3,7 +3,8 @@ "description": "Extracting features and visualizing trained filters with an example image, viewed layer-by-layer.", "example_name": "Filter visualization", "include_in_docs": true, - "priority": 2 + "priority": 2, + "signature": "sha256:526501b358e0f60c489eaf5799e8603a75019cc65401533baa307b5603fdefa1" }, "nbformat": 3, "nbformat_minor": 0, @@ -61,10 +62,10 @@ "cell_type": "code", "collapsed": false, "input": [ + "caffe.set_phase_test()\n", + "caffe.set_mode_cpu()\n", "net = caffe.Classifier(caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt',\n", " caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel')\n", - "net.set_phase_test()\n", - "net.set_mode_cpu()\n", "# input preprocessing: 'data' is the name of the input blob == net.inputs[0]\n", "net.set_mean('data', np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy')) # ImageNet mean\n", "net.set_raw_scale('data', 255) # the reference model operates on images in [0,255] range instead of [0,1]\n", @@ -598,4 +599,4 @@ "metadata": {} } ] -} +} \ No newline at end of file diff --git a/examples/net_surgery.ipynb b/examples/net_surgery.ipynb index 64310016101..a4fb4a66065 100644 --- a/examples/net_surgery.ipynb +++ b/examples/net_surgery.ipynb @@ -4,7 +4,7 @@ "example_name": "Editing model parameters", "include_in_docs": true, "priority": 5, - "signature": "sha256:179fb20339497f5e64f6fbeb57987f27a962b7ae6d940c8fede2631aba9bffaf" + "signature": "sha256:bf84bcbd78fe007310f86d71c5969ba4205b6e06f408029860eec94821844bee" }, "nbformat": 3, "nbformat_minor": 0, @@ -279,9 +279,10 @@ "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", + "caffe.set_phase_test()\n", + "\n", "# load input and configure preprocessing\n", "im = caffe.io.load_image('images/cat.jpg')\n", - "net_full_conv.set_phase_test()\n", "net_full_conv.set_mean('data', np.load('../python/caffe/imagenet/ilsvrc_2012_mean.npy'))\n", "net_full_conv.set_channel_swap('data', (2,1,0))\n", "net_full_conv.set_raw_scale('data', 255.0)\n", @@ -352,4 +353,4 @@ "metadata": {} } ] -} +} \ No newline at end of file diff --git a/python/caffe/__init__.py b/python/caffe/__init__.py index 430bfce2ba5..8dd2464d1c4 100644 --- a/python/caffe/__init__.py +++ b/python/caffe/__init__.py @@ -1,4 +1,6 @@ from .pycaffe import Net, SGDSolver +from .pycaffe import set_mode_cpu, set_mode_gpu, set_phase_train, set_phase_test +from .pycaffe import set_device from .classifier import Classifier from .detector import Detector import io diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 5a81a42329b..2b279e8a6ce 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -142,6 +142,13 @@ void PySGDSolver::SolveResume(const string& resume_file) { } BOOST_PYTHON_MODULE(_caffe) { + // Caffe utility methods + bp::def("set_mode_cpu", &set_mode_cpu); + bp::def("set_mode_gpu", &set_mode_gpu); + bp::def("set_phase_train", &set_phase_train); + bp::def("set_phase_test", &set_phase_test); + bp::def("set_device", &Caffe::SetDevice); + // below, we prepend an underscore to methods that will be replaced // in Python bp::class_ >( @@ -150,11 +157,6 @@ BOOST_PYTHON_MODULE(_caffe) { .def("_forward", &PyNet::Forward) .def("_backward", &PyNet::Backward) .def("reshape", &PyNet::Reshape) - .def("set_mode_cpu", &PyNet::set_mode_cpu) - .def("set_mode_gpu", &PyNet::set_mode_gpu) - .def("set_phase_train", &PyNet::set_phase_train) - .def("set_phase_test", &PyNet::set_phase_test) - .def("set_device", &PyNet::set_device) .add_property("_blobs", &PyNet::blobs) .add_property("layers", &PyNet::layers) .add_property("_blob_names", &PyNet::blob_names) diff --git a/python/caffe/_caffe.hpp b/python/caffe/_caffe.hpp index ba04d276351..e2e1ca348ab 100644 --- a/python/caffe/_caffe.hpp +++ b/python/caffe/_caffe.hpp @@ -18,6 +18,12 @@ using boost::shared_ptr; namespace caffe { +// Selecting mode and phase. +void set_mode_cpu() { Caffe::set_mode(Caffe::CPU); } +void set_mode_gpu() { Caffe::set_mode(Caffe::GPU); } +void set_phase_train() { Caffe::set_phase(Caffe::TRAIN); } +void set_phase_test() { Caffe::set_phase(Caffe::TEST); } + // wrap shared_ptr in a class that we construct in C++ and pass // to Python template @@ -109,13 +115,6 @@ class PyNet { WriteProtoToBinaryFile(net_param, filename.c_str()); } - // The caffe::Caffe utility functions. - void set_mode_cpu() { Caffe::set_mode(Caffe::CPU); } - void set_mode_gpu() { Caffe::set_mode(Caffe::GPU); } - void set_phase_train() { Caffe::set_phase(Caffe::TRAIN); } - void set_phase_test() { Caffe::set_phase(Caffe::TEST); } - void set_device(int device_id) { Caffe::SetDevice(device_id); } - vector > blobs() { return vector >(net_->blobs().begin(), net_->blobs().end()); } diff --git a/python/caffe/classifier.py b/python/caffe/classifier.py index fe471ca13b1..f9a13a39865 100644 --- a/python/caffe/classifier.py +++ b/python/caffe/classifier.py @@ -24,12 +24,12 @@ def __init__(self, model_file, pretrained_file, image_dims=None, preprocessing options. """ caffe.Net.__init__(self, model_file, pretrained_file) - self.set_phase_test() + caffe.set_phase_test() if gpu: - self.set_mode_gpu() + caffe.set_mode_gpu() else: - self.set_mode_cpu() + caffe.set_mode_cpu() if mean is not None: self.set_mean(self.inputs[0], mean) diff --git a/python/caffe/detector.py b/python/caffe/detector.py index f219b6105e1..b78abd12a89 100644 --- a/python/caffe/detector.py +++ b/python/caffe/detector.py @@ -36,12 +36,12 @@ def __init__(self, model_file, pretrained_file, gpu=False, mean=None, R-CNN feature extraction. """ caffe.Net.__init__(self, model_file, pretrained_file) - self.set_phase_test() + caffe.set_phase_test() if gpu: - self.set_mode_gpu() + caffe.set_mode_gpu() else: - self.set_mode_cpu() + caffe.set_mode_cpu() if mean is not None: self.set_mean(self.inputs[0], mean) diff --git a/python/caffe/pycaffe.py b/python/caffe/pycaffe.py index 31dc1f9b001..8899309ddfd 100644 --- a/python/caffe/pycaffe.py +++ b/python/caffe/pycaffe.py @@ -8,6 +8,8 @@ import numpy as np from ._caffe import Net, SGDSolver +from ._caffe import set_mode_cpu, set_mode_gpu, set_phase_train, set_phase_test +from ._caffe import set_device import caffe.io # We directly update methods from Net here (rather than using composition or From ab839f5b2f5c93da34c2ab797ab2a64b62645976 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 15 Jan 2015 16:28:09 -0800 Subject: [PATCH 230/798] support OS X Yosemite / 10.10 - pick libstdc++ for OS X (regardless of version) - make gtest rely on its own tuple to not conflict with clang (thanks @pluskid!) - 10.10 has Accelerate while 10.9 has vecLib for BLAS (thanks @leonardt and @drdan14) --- Makefile | 21 ++++++++++++++------- docs/installation.md | 14 +++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 46bf7280919..2d82e058085 100644 --- a/Makefile +++ b/Makefile @@ -234,15 +234,15 @@ endif # libstdc++ instead of libc++ for CUDA compatibility on 10.9 ifeq ($(OSX), 1) CXX := /usr/bin/clang++ + CXXFLAGS += -stdlib=libstdc++ + LINKFLAGS += -stdlib=libstdc++ # clang throws this warning for cuda headers WARNINGS += -Wno-unneeded-internal-declaration - ifneq ($(findstring 10.9, $(shell sw_vers -productVersion)),) - CXXFLAGS += -stdlib=libstdc++ - LINKFLAGS += -stdlib=libstdc++ - endif + # gtest needs to use its own tuple to not conflict with clang + CXXFLAGS += -DGTEST_USE_OWN_TR1_TUPLE=1 # boost::thread is called boost_thread-mt to mark multithreading on OS X LIBRARIES += boost_thread-mt - NVCCFLAGS += -DOSX + NVCCFLAGS += -DOSX endif # Custom compiler @@ -304,9 +304,16 @@ else endif else ifeq ($(OSX), 1) # OS X packages atlas as the vecLib framework - BLAS_INCLUDE ?= /System/Library/Frameworks/vecLib.framework/Versions/Current/Headers/ LIBRARIES += cblas - LDFLAGS += -framework vecLib + # 10.10 has accelerate while 10.9 has veclib + XCODE_CLT_VER := $(shell pkgutil --pkg-info=com.apple.pkg.CLTools_Executables | grep -o 'version: 6') + ifneq (,$(findstring version: 6,$(XCODE_CLT_VER))) + BLAS_INCLUDE ?= /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/ + LDFLAGS += -framework Accelerate + else + BLAS_INCLUDE ?= /System/Library/Frameworks/vecLib.framework/Versions/Current/Headers/ + LDFLAGS += -framework vecLib + endif endif endif INCLUDE_DIRS += $(BLAS_INCLUDE) diff --git a/docs/installation.md b/docs/installation.md index c667cd8ce01..94068e503dc 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -5,7 +5,7 @@ title: Installation # Installation Prior to installing, it is best to read through this guide and take note of the details for your platform. -We have installed Caffe on Ubuntu 14.04, Ubuntu 12.04, OS X 10.9, and OS X 10.8. +We have installed Caffe on Ubuntu 14.04, Ubuntu 12.04, OS X 10.10, 10.9, and 10.8. - [Prerequisites](#prerequisites) - [Compilation](#compilation) @@ -156,9 +156,9 @@ Building boost from source is needed to link against your local Python (exceptio **Note** that the HDF5 dependency is provided by Anaconda Python in this case. If you're not using Anaconda, include `hdf5` in the list above. -#### 10.9-specific Instructions +#### 10.10- and 10.9-specific Instructions -In OS X 10.9, clang++ is the default C++ compiler and uses `libc++` as the standard library. +In OS X 10.9+, clang++ is the default C++ compiler and uses `libc++` as the standard library. However, NVIDIA CUDA (even version 6.0) currently links only with `libstdc++`. This makes it necessary to change the compilation settings for each of the dependencies. @@ -226,10 +226,10 @@ Then, whenever you want to update homebrew, switch back to the master branches, git checkout master cd /usr/local/Library/Taps/homebrew/homebrew-science git checkout master - + # Update homebrew; hopefully this works without errors! brew update - + # Switch back to the caffe branches with the forumlae that you modified earlier cd /usr/local git rebase master caffe @@ -237,8 +237,8 @@ Then, whenever you want to update homebrew, switch back to the master branches, cd /usr/local/Library/Taps/homebrew/homebrew-science git rebase master caffe # Fix any merge conflicts and commit to caffe branch - - # Done! + + # Done! At this point, you should be running the latest Homebrew packages and your Caffe-related modifications will remain in place. From c16493cfb2cdf57f9ee5f511826ea110686929cf Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 15 Jan 2015 20:43:24 -0800 Subject: [PATCH 231/798] lint internal thread --- include/caffe/internal_thread.hpp | 2 +- src/caffe/internal_thread.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/caffe/internal_thread.hpp b/include/caffe/internal_thread.hpp index fec22a47c86..815ca54605e 100644 --- a/include/caffe/internal_thread.hpp +++ b/include/caffe/internal_thread.hpp @@ -39,4 +39,4 @@ class InternalThread { } // namespace caffe -#endif // CAFFE_INTERNAL_THREAD_HPP_ +#endif // CAFFE_INTERNAL_THREAD_HPP_ diff --git a/src/caffe/internal_thread.cpp b/src/caffe/internal_thread.cpp index 58772e36c23..c2d19d433b4 100644 --- a/src/caffe/internal_thread.cpp +++ b/src/caffe/internal_thread.cpp @@ -17,7 +17,8 @@ bool InternalThread::StartInternalThread() { return false; } try { - thread_.reset(new boost::thread(&InternalThread::InternalThreadEntry, this)); + thread_.reset( + new boost::thread(&InternalThread::InternalThreadEntry, this)); } catch (...) { return false; } From d612f4a35cf84d9d025757b3d1cd65b96e2e5850 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 15 Jan 2015 21:47:50 -0800 Subject: [PATCH 232/798] check for enough args to convert_imageset (this might better be handled by making all args flags...) --- tools/convert_imageset.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index c554ed389ab..5d42e69c1ed 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -52,7 +52,7 @@ int main(int argc, char** argv) { " http://www.image-net.org/download-images\n"); gflags::ParseCommandLineFlags(&argc, &argv, true); - if (argc != 4) { + if (argc < 4) { gflags::ShowUsageWithFlagsRestrict(argv[0], "tools/convert_imageset"); return 1; } From 6af39c503677fad31c8c3c7ba784080090a01399 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 16 Jan 2015 13:41:34 -0800 Subject: [PATCH 233/798] [docs] OpenCV version >= 2.4 --- docs/installation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index c667cd8ce01..a42ef5b309c 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -17,7 +17,7 @@ Caffe depends on several software packages. * [CUDA](https://developer.nvidia.com/cuda-zone) library version 6.5 (recommended), 6.0, 5.5, or 5.0 and the latest driver version for CUDA 6 or 319.* for CUDA 5 (and NOT 331.*) * [BLAS](http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms) (provided via ATLAS, MKL, or OpenBLAS). -* [OpenCV](http://opencv.org/). +* [OpenCV](http://opencv.org/) (>= 2.4) * [Boost](http://www.boost.org/) (>= 1.55, although only 1.55 and 1.56 are tested) * `glog`, `gflags`, `protobuf`, `leveldb`, `snappy`, `hdf5`, `lmdb` * For the Python wrapper @@ -226,10 +226,10 @@ Then, whenever you want to update homebrew, switch back to the master branches, git checkout master cd /usr/local/Library/Taps/homebrew/homebrew-science git checkout master - + # Update homebrew; hopefully this works without errors! brew update - + # Switch back to the caffe branches with the forumlae that you modified earlier cd /usr/local git rebase master caffe @@ -237,8 +237,8 @@ Then, whenever you want to update homebrew, switch back to the master branches, cd /usr/local/Library/Taps/homebrew/homebrew-science git rebase master caffe # Fix any merge conflicts and commit to caffe branch - - # Done! + + # Done! At this point, you should be running the latest Homebrew packages and your Caffe-related modifications will remain in place. From f476e9014830a502b0b01e18b3936021f7b2fb33 Mon Sep 17 00:00:00 2001 From: Christos Nikolaou Date: Thu, 30 Oct 2014 01:05:12 +0200 Subject: [PATCH 234/798] Update interfaces.md file Proofread and update the /docs/tutorial/interfaces.md file. --- docs/tutorial/interfaces.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/tutorial/interfaces.md b/docs/tutorial/interfaces.md index 6b0ec347dfe..17430b35c57 100644 --- a/docs/tutorial/interfaces.md +++ b/docs/tutorial/interfaces.md @@ -9,7 +9,13 @@ Caffe has command line, Python, and MATLAB interfaces for day-to-day usage, inte The command line interface -- cmdcaffe -- is the `caffe` tool for model training, scoring, and diagnostics. Run `caffe` without any arguments for help. This tool and others are found in caffe/build/tools. (The following example calls require completing the LeNet / MNIST example first.) -**Training**: `caffe train` learns models from scratch, resumes learning from saved snapshots, and fine-tunes models to new data and tasks. All training requires a solver configuration through the `-solver solver.prototxt` argument. Resuming requires the `-snapshot model_iter_1000.solverstate` argument to load the solver snapshot. Fine-tuning requires the `-weights model.caffemodel` argument for the model initialization. +**Training**: `caffe train` learns models from scratch, resumes learning from saved snapshots, and fine-tunes models to new data and tasks: + +* All training requires a solver configuration through the `-solver solver.prototxt` argument. +* Resuming requires the `-snapshot model_iter_1000.solverstate` argument to load the solver snapshot. +* Fine-tuning requires the `-weights model.caffemodel` argument for the model initialization. + +For example, you can run: # train LeNet caffe train -solver examples/mnist/lenet_solver.prototxt @@ -26,17 +32,19 @@ For a full example of fine-tuning, see examples/finetuning_on_flickr_style, but **Testing**: `caffe test` scores models by running them in the test phase and reports the net output as its score. The net architecture must be properly defined to output an accuracy measure or loss as its output. The per-batch score is reported and then the grand average is reported last. # - # score the learned LeNet model on the validation set as defined in the model architeture lenet_train_test.prototxt - caffe test -model examples/mnist/lenet_train_test.prototxt -weights examples/mnist/lenet_iter_10000 -gpu 0 -iterations 100 + # score the learned LeNet model on the validation set as defined in the + # model architeture lenet_train_test.prototxt + caffe test -model examples/mnist/lenet_train_test.prototxt -weights examples/mnist/lenet_iter_10000.caffemodel -gpu 0 -iterations 100 **Benchmarking**: `caffe time` benchmarks model execution layer-by-layer through timing and synchronization. This is useful to check system performance and measure relative execution times for models. # (These example calls require you complete the LeNet / MNIST example first.) # time LeNet training on CPU for 10 iterations caffe time -model examples/mnist/lenet_train_test.prototxt -iterations 10 - # time a model architecture with the given weights on the first GPU for 10 iterations # time LeNet training on GPU for the default 50 iterations caffe time -model examples/mnist/lenet_train_test.prototxt -gpu 0 + # time a model architecture with the given weights on the first GPU for 10 iterations + caffe time -model examples/mnist/lenet_train_test.prototxt -weights examples/mnist/lenet_iter_10000.caffemodel -gpu 0 -iterations 10 **Diagnostics**: `caffe device_query` reports GPU details for reference and checking device ordinals for running on a given device in multi-GPU machines. From 1304173d85d3d382d3ae2b2aa4f6c04b2c8c75ca Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Sat, 17 Jan 2015 15:41:44 -0800 Subject: [PATCH 235/798] Make comments for sparse GaussianFiller match actual behavior (Fixes #1497 reported by @denizyuret) --- include/caffe/filler.hpp | 6 +++--- src/caffe/proto/caffe.proto | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/caffe/filler.hpp b/include/caffe/filler.hpp index 136ce958aed..eebf565b1d5 100644 --- a/include/caffe/filler.hpp +++ b/include/caffe/filler.hpp @@ -76,13 +76,13 @@ class GaussianFiller : public Filler { CHECK_GE(sparse, -1); if (sparse >= 0) { // Sparse initialization is implemented for "weight" blobs; i.e. matrices. - // These have num == channels == 1; height is number of inputs; width is + // These have num == channels == 1; width is number of inputs; height is // number of outputs. The 'sparse' variable specifies the mean number // of non-zero input weights for a given output. CHECK_EQ(blob->num(), 1); CHECK_EQ(blob->channels(), 1); - int num_inputs = blob->height(); - Dtype non_zero_probability = Dtype(sparse) / Dtype(num_inputs); + int num_outputs = blob->height(); + Dtype non_zero_probability = Dtype(sparse) / Dtype(num_outputs); rand_vec_.reset(new SyncedMemory(blob->count() * sizeof(int))); int* mask = reinterpret_cast(rand_vec_->mutable_cpu_data()); caffe_rng_bernoulli(blob->count(), non_zero_probability, mask); diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 8086ad66579..d6eec02087b 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -38,7 +38,7 @@ message FillerParameter { optional float max = 4 [default = 1]; // the max value in uniform filler optional float mean = 5 [default = 0]; // the mean value in Gaussian filler optional float std = 6 [default = 1]; // the std value in Gaussian filler - // The expected number of non-zero input weights for a given output in + // The expected number of non-zero output weights for a given input in // Gaussian filler -- the default -1 means don't perform sparsification. optional int32 sparse = 7 [default = -1]; } From c795095fd26767152e3ee6a3183cda5edd75c39b Mon Sep 17 00:00:00 2001 From: Dinesh Jayaraman Date: Sat, 17 Jan 2015 18:23:48 -0600 Subject: [PATCH 236/798] Matlab demo for Caffe-compatible HDF5 read/write --- matlab/caffe/hdf5creation/.gitignore | 2 + matlab/caffe/hdf5creation/demo.m | 64 ++++++++++++++++++++++++++ matlab/caffe/hdf5creation/store2hdf5.m | 59 ++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 matlab/caffe/hdf5creation/.gitignore create mode 100644 matlab/caffe/hdf5creation/demo.m create mode 100644 matlab/caffe/hdf5creation/store2hdf5.m diff --git a/matlab/caffe/hdf5creation/.gitignore b/matlab/caffe/hdf5creation/.gitignore new file mode 100644 index 00000000000..e2333dd1776 --- /dev/null +++ b/matlab/caffe/hdf5creation/.gitignore @@ -0,0 +1,2 @@ +*.h5 +list.txt diff --git a/matlab/caffe/hdf5creation/demo.m b/matlab/caffe/hdf5creation/demo.m new file mode 100644 index 00000000000..f554b87e5f6 --- /dev/null +++ b/matlab/caffe/hdf5creation/demo.m @@ -0,0 +1,64 @@ +%% WRITING TO HDF5 +filename='trial.h5'; + +num_total_samples=10000; +% to simulate data being read from disk / generated etc. +data_disk=rand(5,5,1,num_total_samples); +label_disk=rand(10,num_total_samples); + +chunksz=100; +created_flag=false; +totalct=0; +for batchno=1:num_total_samples/chunksz + fprintf('batch no. %d\n', batchno); + last_read=(batchno-1)*chunksz; + + % to simulate maximum data to be held in memory before dumping to hdf5 file + batchdata=data_disk(:,:,1,last_read+1:last_read+chunksz); + batchlabs=label_disk(:,last_read+1:last_read+chunksz); + + % store to hdf5 + startloc=struct('dat',[1,1,1,totalct+1], 'lab', [1,totalct+1]); + curr_dat_sz=store2hdf5(filename, batchdata, batchlabs, ~created_flag, startloc, chunksz); + created_flag=true;% flag set so that file is created only once + totalct=curr_dat_sz(end);% updated dataset size (#samples) +end + +% display structure of the stored HDF5 file +h5disp(filename); + +%% READING FROM HDF5 + +% Read data and labels for samples #1000 to 1999 +data_rd=h5read(filename, '/data', [1 1 1 1000], [5, 5, 1, 1000]); +label_rd=h5read(filename, '/label', [1 1000], [10, 1000]); +fprintf('Testing ...\n'); +try + assert(isequal(data_rd, single(data_disk(:,:,:,1000:1999))), 'Data do not match'); + assert(isequal(label_rd, single(label_disk(:,1000:1999))), 'Labels do not match'); + + fprintf('Success!\n'); +catch err + fprintf('Test failed ...\n'); + getReport(err) +end + +%delete(filename); + +% CREATE list.txt containing filename, to be used as source for HDF5_DATA_LAYER +FILE=fopen('list.txt', 'w'); +fprintf(FILE, '%s', filename); +fclose(FILE); +fprintf('HDF5 filename listed in %s \n', 'list.txt'); + +% NOTE: In net definition prototxt, use list.txt as input to HDF5_DATA as: +% layers { +% name: "data" +% type: HDF5_DATA +% top: "data" +% top: "labelvec" +% hdf5_data_param { +% source: "/path/to/list.txt" +% batch_size: 64 +% } +% } diff --git a/matlab/caffe/hdf5creation/store2hdf5.m b/matlab/caffe/hdf5creation/store2hdf5.m new file mode 100644 index 00000000000..0a0016dca40 --- /dev/null +++ b/matlab/caffe/hdf5creation/store2hdf5.m @@ -0,0 +1,59 @@ +function [curr_dat_sz, curr_lab_sz] = store2hdf5(filename, data, labels, create, startloc, chunksz) + % *data* is W*H*C*N matrix of images should be normalized (e.g. to lie between 0 and 1) beforehand + % *label* is D*N matrix of labels (D labels per sample) + % *create* [0/1] specifies whether to create file newly or to append to previously created file, useful to store information in batches when a dataset is too big to be held in memory (default: 1) + % *startloc* (point at which to start writing data). By default, + % if create=1 (create mode), startloc.data=[1 1 1 1], and startloc.lab=[1 1]; + % if create=0 (append mode), startloc.data=[1 1 1 K+1], and startloc.lab = [1 K+1]; where K is the current number of samples stored in the HDF + % chunksz (used only in create mode), specifies number of samples to be stored per chunk (see HDF5 documentation on chunking) for creating HDF5 files with unbounded maximum size - TLDR; higher chunk sizes allow faster read-write operations + + % verify that format is right + dat_dims=size(data); + lab_dims=size(labels); + num_samples=dat_dims(end); + + assert(lab_dims(end)==num_samples, 'Number of samples should be matched between data and labels'); + + if ~exist('create','var') + create=true; + end + + + if create + %fprintf('Creating dataset with %d samples\n', num_samples); + if ~exist('chunksz', 'var') + chunksz=1000; + end + if exist(filename, 'file') + fprintf('Warning: replacing existing file %s \n', filename); + delete(filename); + end + h5create(filename, '/data', [dat_dims(1:end-1) Inf], 'Datatype', 'single', 'ChunkSize', [dat_dims(1:end-1) chunksz]); % width, height, channels, number + h5create(filename, '/label', [lab_dims(1:end-1) Inf], 'Datatype', 'single', 'ChunkSize', [lab_dims(1:end-1) chunksz]); % width, height, channels, number + if ~exist('startloc','var') + startloc.dat=[ones(1,length(dat_dims)-1), 1]; + startloc.lab=[ones(1,length(lab_dims)-1), 1]; + end + else % append mode + if ~exist('startloc','var') + info=h5info(filename); + prev_dat_sz=info.Datasets(1).Dataspace.Size; + prev_lab_sz=info.Datasets(2).Dataspace.Size; + assert(prev_dat_sz(1:end-1)==dat_dims(1:end-1), 'Data dimensions must match existing dimensions in dataset'); + assert(prev_lab_sz(1:end-1)==lab_dims(1:end-1), 'Label dimensions must match existing dimensions in dataset'); + startloc.dat=[ones(1,length(dat_dims)-1), prev_dat_sz(end)+1]; + startloc.lab=[ones(1,length(lab_dims)-1), prev_lab_sz(end)+1]; + end + end + + if ~isempty(data) + h5write(filename, '/data', single(data), startloc.dat, size(data)); + h5write(filename, '/label', single(labels), startloc.lab, size(labels)); + end + + if nargout + info=h5info(filename); + curr_dat_sz=info.Datasets(1).Dataspace.Size; + curr_lab_sz=info.Datasets(2).Dataspace.Size; + end +end From 21f1b5941df6faeed8bfc1d68f6b42559e2eb417 Mon Sep 17 00:00:00 2001 From: Jason Yosinski Date: Sat, 17 Jan 2015 23:07:36 -0500 Subject: [PATCH 237/798] Updated doc to suggest boost 1.57 --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 94068e503dc..66f080eb781 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -141,7 +141,7 @@ Do `brew edit opencv` and change the lines that look like the two lines below to **NOTE**: We find that everything compiles successfully if `$LD_LIBRARY_PATH` is not set at all, and `$DYLD_FALLBACK_LIBRARY_PATH` is set to to provide CUDA, Python, and other relevant libraries (e.g. `/usr/local/cuda/lib:$HOME/anaconda/lib:/usr/local/lib:/usr/lib`). In other `ENV` settings, things may not work as expected. -**NOTE**: There is currently a conflict between boost 1.56 and CUDA in some configurations. Check the [conflict description](https://github.com/BVLC/caffe/issues/1193#issuecomment-57491906) and try downgrading to 1.55. +**NOTE**: There is currently a conflict between boost 1.56 and CUDA in some configurations. Check the [conflict description](https://github.com/BVLC/caffe/issues/1193#issuecomment-57491906) and try downgrading to 1.55 or upgrading to 1.57. #### 10.8-specific Instructions From 1856bb2d89ecbabe84cbf0a647de7a2ab6c29207 Mon Sep 17 00:00:00 2001 From: Sergio Guadarrama Date: Fri, 16 Jan 2015 13:18:50 -0800 Subject: [PATCH 238/798] add db wrappers --- include/caffe/util/db.hpp | 190 ++++++++++++++++++++++++++++++++++++++ src/caffe/util/db.cpp | 84 +++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 include/caffe/util/db.hpp create mode 100644 src/caffe/util/db.cpp diff --git a/include/caffe/util/db.hpp b/include/caffe/util/db.hpp new file mode 100644 index 00000000000..afdb8d2c4f8 --- /dev/null +++ b/include/caffe/util/db.hpp @@ -0,0 +1,190 @@ +#ifndef CAFFE_UTIL_DB_HPP +#define CAFFE_UTIL_DB_HPP + +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +#include "lmdb.h" + +#include "caffe/common.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { namespace db { + +enum Mode { READ, WRITE, NEW }; + +class Cursor { + public: + Cursor() { } + virtual ~Cursor() { } + virtual void SeekToFirst() = 0; + virtual void Next() = 0; + virtual string key() = 0; + virtual string value() = 0; + virtual bool valid() = 0; + + DISABLE_COPY_AND_ASSIGN(Cursor); +}; + +class Transaction { + public: + Transaction() { } + virtual ~Transaction() { } + virtual void Put(const string& key, const string& value) = 0; + virtual void Commit() = 0; + + DISABLE_COPY_AND_ASSIGN(Transaction); +}; + +class DB { + public: + DB() { } + virtual ~DB() { } + virtual void Open(const string& source, Mode mode) = 0; + virtual void Close() = 0; + virtual Cursor* NewCursor() = 0; + virtual Transaction* NewTransaction() = 0; + + DISABLE_COPY_AND_ASSIGN(DB); +}; + +class LevelDBCursor : public Cursor { + public: + explicit LevelDBCursor(leveldb::Iterator* iter) + : iter_(iter) { SeekToFirst(); } + ~LevelDBCursor() { delete iter_; } + virtual void SeekToFirst() { iter_->SeekToFirst(); } + virtual void Next() { iter_->Next(); } + virtual string key() { return iter_->key().ToString(); } + virtual string value() { return iter_->value().ToString(); } + virtual bool valid() { return iter_->Valid(); } + + private: + leveldb::Iterator* iter_; +}; + +class LevelDBTransaction : public Transaction { + public: + explicit LevelDBTransaction(leveldb::DB* db) : db_(db) { CHECK_NOTNULL(db_); } + virtual void Put(const string& key, const string& value) { + batch_.Put(key, value); + } + virtual void Commit() { + leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch_); + CHECK(status.ok()) << "Failed to write batch to leveldb " + << std::endl << status.ToString(); + } + + private: + leveldb::DB* db_; + leveldb::WriteBatch batch_; + + DISABLE_COPY_AND_ASSIGN(LevelDBTransaction); +}; + +class LevelDB : public DB { + public: + LevelDB() : db_(NULL) { } + virtual ~LevelDB() { Close(); } + virtual void Open(const string& source, Mode mode); + virtual void Close() { + if (db_ != NULL) { + delete db_; + db_ = NULL; + } + } + virtual LevelDBCursor* NewCursor() { + return new LevelDBCursor(db_->NewIterator(leveldb::ReadOptions())); + } + virtual LevelDBTransaction* NewTransaction() { + return new LevelDBTransaction(db_); + } + + private: + leveldb::DB* db_; +}; + +inline void MDB_CHECK(int mdb_status) { + CHECK_EQ(mdb_status, MDB_SUCCESS) << mdb_strerror(mdb_status); +} + +class LMDBCursor : public Cursor { + public: + explicit LMDBCursor(MDB_txn* mdb_txn, MDB_cursor* mdb_cursor) + : mdb_txn_(mdb_txn), mdb_cursor_(mdb_cursor), valid_(false) { + SeekToFirst(); + } + virtual ~LMDBCursor() { + mdb_cursor_close(mdb_cursor_); + mdb_txn_abort(mdb_txn_); + } + virtual void SeekToFirst() { Seek(MDB_FIRST); } + virtual void Next() { Seek(MDB_NEXT); } + virtual string key() { + return string(static_cast(mdb_key_.mv_data), mdb_key_.mv_size); + } + virtual string value() { + return string(static_cast(mdb_value_.mv_data), + mdb_value_.mv_size); + } + virtual bool valid() { return valid_; } + + private: + void Seek(MDB_cursor_op op) { + int mdb_status = mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, op); + if (mdb_status == MDB_NOTFOUND) { + valid_ = false; + } else { + MDB_CHECK(mdb_status); + valid_ = true; + } + } + + MDB_txn* mdb_txn_; + MDB_cursor* mdb_cursor_; + MDB_val mdb_key_, mdb_value_; + bool valid_; +}; + +class LMDBTransaction : public Transaction { + public: + explicit LMDBTransaction(MDB_dbi* mdb_dbi, MDB_txn* mdb_txn) + : mdb_dbi_(mdb_dbi), mdb_txn_(mdb_txn) { } + virtual void Put(const string& key, const string& value); + virtual void Commit() { MDB_CHECK(mdb_txn_commit(mdb_txn_)); } + + private: + MDB_dbi* mdb_dbi_; + MDB_txn* mdb_txn_; + + DISABLE_COPY_AND_ASSIGN(LMDBTransaction); +}; + +class LMDB : public DB { + public: + LMDB() : mdb_env_(NULL) { } + virtual ~LMDB() { Close(); } + virtual void Open(const string& source, Mode mode); + virtual void Close() { + if (mdb_env_ != NULL) { + mdb_dbi_close(mdb_env_, mdb_dbi_); + mdb_env_close(mdb_env_); + mdb_env_ = NULL; + } + } + virtual LMDBCursor* NewCursor(); + virtual LMDBTransaction* NewTransaction(); + + private: + MDB_env* mdb_env_; + MDB_dbi mdb_dbi_; +}; + +DB* GetDB(DataParameter::DB backend); +DB* GetDB(const string& backend); + +} // namespace db +} // namespace caffe + +#endif // CAFFE_UTIL_DB_HPP diff --git a/src/caffe/util/db.cpp b/src/caffe/util/db.cpp new file mode 100644 index 00000000000..7f7018107ec --- /dev/null +++ b/src/caffe/util/db.cpp @@ -0,0 +1,84 @@ +#include "caffe/util/db.hpp" + +#include +#include + +namespace caffe { namespace db { + +const size_t LMDB_MAP_SIZE = 1099511627776; // 1 TB + +void LevelDB::Open(const string& source, Mode mode) { + leveldb::Options options; + options.block_size = 65536; + options.write_buffer_size = 268435456; + options.max_open_files = 100; + options.error_if_exists = mode == NEW; + options.create_if_missing = mode != READ; + leveldb::Status status = leveldb::DB::Open(options, source, &db_); + CHECK(status.ok()) << "Failed to open leveldb " << source + << std::endl << status.ToString(); + LOG(INFO) << "Opened leveldb " << source; +} + +void LMDB::Open(const string& source, Mode mode) { + MDB_CHECK(mdb_env_create(&mdb_env_)); + MDB_CHECK(mdb_env_set_mapsize(mdb_env_, LMDB_MAP_SIZE)); + if (mode == NEW) { + CHECK_EQ(mkdir(source.c_str(), 0744), 0) << "mkdir " << source << "failed"; + } + int flags = 0; + if (mode == READ) { + flags = MDB_RDONLY | MDB_NOTLS; + } + MDB_CHECK(mdb_env_open(mdb_env_, source.c_str(), flags, 0664)); + LOG(INFO) << "Opened lmdb " << source; +} + +LMDBCursor* LMDB::NewCursor() { + MDB_txn* mdb_txn; + MDB_cursor* mdb_cursor; + MDB_CHECK(mdb_txn_begin(mdb_env_, NULL, MDB_RDONLY, &mdb_txn)); + MDB_CHECK(mdb_dbi_open(mdb_txn, NULL, 0, &mdb_dbi_)); + MDB_CHECK(mdb_cursor_open(mdb_txn, mdb_dbi_, &mdb_cursor)); + return new LMDBCursor(mdb_txn, mdb_cursor); +} + +LMDBTransaction* LMDB::NewTransaction() { + MDB_txn* mdb_txn; + MDB_CHECK(mdb_txn_begin(mdb_env_, NULL, 0, &mdb_txn)); + MDB_CHECK(mdb_dbi_open(mdb_txn, NULL, 0, &mdb_dbi_)); + return new LMDBTransaction(&mdb_dbi_, mdb_txn); +} + +void LMDBTransaction::Put(const string& key, const string& value) { + MDB_val mdb_key, mdb_value; + mdb_key.mv_data = const_cast(key.data()); + mdb_key.mv_size = key.size(); + mdb_value.mv_data = const_cast(value.data()); + mdb_value.mv_size = value.size(); + MDB_CHECK(mdb_put(mdb_txn_, *mdb_dbi_, &mdb_key, &mdb_value, 0)); +} + +DB* GetDB(DataParameter::DB backend) { + switch (backend) { + case DataParameter_DB_LEVELDB: + return new LevelDB(); + case DataParameter_DB_LMDB: + return new LMDB(); + default: + LOG(FATAL) << "Unknown database backend"; + } +} + +DB* GetDB(const string& backend) { + if (backend == "leveldb") { + return new LevelDB(); + } else if (backend == "lmdb") { + return new LMDB(); + } else { + LOG(FATAL) << "Unknown database backend"; + } +} + +} // namespace db +} // namespace caffe From 7dfe23963c69759c3bdca1f0ee8ff9866c0fb5c2 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Fri, 16 Jan 2015 13:20:15 -0800 Subject: [PATCH 239/798] use db wrappers --- examples/cifar10/convert_cifar_data.cpp | 41 ++++++++++++----------- include/caffe/data_layers.hpp | 6 ++-- src/caffe/layers/data_layer.cpp | 34 ++++++++----------- src/caffe/test/test_data_layer.cpp | 27 ++++++++------- tools/compute_image_mean.cpp | 44 +++++++++++-------------- tools/convert_imageset.cpp | 38 ++++++++++----------- tools/extract_features.cpp | 31 +++++++++-------- 7 files changed, 111 insertions(+), 110 deletions(-) diff --git a/examples/cifar10/convert_cifar_data.cpp b/examples/cifar10/convert_cifar_data.cpp index 9eecc74c989..f4c42e4d2e7 100644 --- a/examples/cifar10/convert_cifar_data.cpp +++ b/examples/cifar10/convert_cifar_data.cpp @@ -9,19 +9,18 @@ #include // NOLINT(readability/streams) #include +#include "boost/scoped_ptr.hpp" #include "glog/logging.h" #include "google/protobuf/text_format.h" #include "stdint.h" -#include "caffe/dataset_factory.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/db.hpp" -using std::string; - -using caffe::Dataset; -using caffe::DatasetFactory; using caffe::Datum; -using caffe::shared_ptr; +using boost::scoped_ptr; +using std::string; +namespace db = caffe::db; const int kCIFARSize = 32; const int kCIFARImageNBytes = 3072; @@ -38,10 +37,9 @@ void read_image(std::ifstream* file, int* label, char* buffer) { void convert_dataset(const string& input_folder, const string& output_folder, const string& db_type) { - shared_ptr > train_dataset = - DatasetFactory(db_type); - CHECK(train_dataset->open(output_folder + "/cifar10_train_" + db_type, - Dataset::New)); + scoped_ptr train_db(db::GetDB(db_type)); + train_db->Open(output_folder + "/cifar10_train_" + db_type, db::NEW); + scoped_ptr txn(train_db->NewTransaction()); // Data buffer int label; char str_buffer[kCIFARImageNBytes]; @@ -64,17 +62,18 @@ void convert_dataset(const string& input_folder, const string& output_folder, datum.set_data(str_buffer, kCIFARImageNBytes); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", fileid * kCIFARBatchSize + itemid); - CHECK(train_dataset->put(string(str_buffer, length), datum)); + string out; + CHECK(datum.SerializeToString(&out)); + txn->Put(string(str_buffer, length), out); } } - CHECK(train_dataset->commit()); - train_dataset->close(); + txn->Commit(); + train_db->Close(); LOG(INFO) << "Writing Testing data"; - shared_ptr > test_dataset = - DatasetFactory(db_type); - CHECK(test_dataset->open(output_folder + "/cifar10_test_" + db_type, - Dataset::New)); + scoped_ptr test_db(db::GetDB(db_type)); + test_db->Open(output_folder + "/cifar10_test_" + db_type, db::NEW); + txn.reset(test_db->NewTransaction()); // Open files std::ifstream data_file((input_folder + "/test_batch.bin").c_str(), std::ios::in | std::ios::binary); @@ -84,10 +83,12 @@ void convert_dataset(const string& input_folder, const string& output_folder, datum.set_label(label); datum.set_data(str_buffer, kCIFARImageNBytes); int length = snprintf(str_buffer, kCIFARImageNBytes, "%05d", itemid); - CHECK(test_dataset->put(string(str_buffer, length), datum)); + string out; + CHECK(datum.SerializeToString(&out)); + txn->Put(string(str_buffer, length), out); } - CHECK(test_dataset->commit()); - test_dataset->close(); + txn->Commit(); + test_db->Close(); } int main(int argc, char** argv) { diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index 34b9b30aa3e..e9c83856a99 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -11,11 +11,11 @@ #include "caffe/blob.hpp" #include "caffe/common.hpp" #include "caffe/data_transformer.hpp" -#include "caffe/dataset.hpp" #include "caffe/filler.hpp" #include "caffe/internal_thread.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/db.hpp" namespace caffe { @@ -100,8 +100,8 @@ class DataLayer : public BasePrefetchingDataLayer { protected: virtual void InternalThreadEntry(); - shared_ptr > dataset_; - Dataset::const_iterator iter_; + shared_ptr db_; + shared_ptr cursor_; }; /** diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index a5030899cee..96964566630 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -7,7 +7,6 @@ #include "caffe/common.hpp" #include "caffe/data_layers.hpp" -#include "caffe/dataset_factory.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/benchmark.hpp" @@ -20,35 +19,28 @@ namespace caffe { template DataLayer::~DataLayer() { this->JoinPrefetchThread(); - // clean up the dataset resources - dataset_->close(); } template void DataLayer::DataLayerSetUp(const vector*>& bottom, const vector*>& top) { // Initialize DB - dataset_ = DatasetFactory( - this->layer_param_.data_param().backend()); - const string& source = this->layer_param_.data_param().source(); - LOG(INFO) << "Opening dataset " << source; - CHECK(dataset_->open(source, Dataset::ReadOnly)); - iter_ = dataset_->begin(); + db_.reset(db::GetDB(this->layer_param_.data_param().backend())); + db_->Open(this->layer_param_.data_param().source(), db::READ); + cursor_.reset(db_->NewCursor()); - // Check if we would need to randomly skip a few data points + // Check if we should randomly skip a few data points if (this->layer_param_.data_param().rand_skip()) { unsigned int skip = caffe_rng_rand() % this->layer_param_.data_param().rand_skip(); LOG(INFO) << "Skipping first " << skip << " data points."; while (skip-- > 0) { - if (++iter_ == dataset_->end()) { - iter_ = dataset_->begin(); - } + cursor_->Next(); } } // Read a data point, and use it to initialize the top blob. - CHECK(iter_ != dataset_->end()); - Datum datum = iter_->value; + Datum datum; + datum.ParseFromString(cursor_->value()); if (DecodeDatum(&datum)) { LOG(INFO) << "Decoding Datum"; @@ -101,8 +93,8 @@ void DataLayer::InternalThreadEntry() { for (int item_id = 0; item_id < batch_size; ++item_id) { timer.Start(); // get a blob - CHECK(iter_ != dataset_->end()); - const Datum& datum = iter_->value; + Datum datum; + datum.ParseFromString(cursor_->value()); cv::Mat cv_img; if (datum.encoded()) { @@ -124,9 +116,10 @@ void DataLayer::InternalThreadEntry() { } trans_time += timer.MicroSeconds(); // go to the next iter - ++iter_; - if (iter_ == dataset_->end()) { - iter_ = dataset_->begin(); + cursor_->Next(); + if (!cursor_->valid()) { + DLOG(INFO) << "Restarting data prefetching from start."; + cursor_->SeekToFirst(); } } batch_timer.Stop(); @@ -137,4 +130,5 @@ void DataLayer::InternalThreadEntry() { INSTANTIATE_CLASS(DataLayer); REGISTER_LAYER_CLASS(DATA, DataLayer); + } // namespace caffe diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index 32f5d41e2f2..8cc31b24167 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -1,20 +1,23 @@ #include #include +#include "boost/scoped_ptr.hpp" #include "gtest/gtest.h" #include "caffe/blob.hpp" #include "caffe/common.hpp" -#include "caffe/dataset_factory.hpp" +#include "caffe/data_layers.hpp" #include "caffe/filler.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/db.hpp" #include "caffe/util/io.hpp" -#include "caffe/vision_layers.hpp" #include "caffe/test/test_caffe_main.hpp" namespace caffe { +using boost::scoped_ptr; + template class DataLayerTest : public MultiDeviceTest { typedef typename TypeParam::Dtype Dtype; @@ -33,15 +36,15 @@ class DataLayerTest : public MultiDeviceTest { blob_top_vec_.push_back(blob_top_label_); } - // Fill the LevelDB with data: if unique_pixels, each pixel is unique but + // Fill the DB with data: if unique_pixels, each pixel is unique but // all images are the same; else each image is unique but all pixels within // an image are the same. void Fill(const bool unique_pixels, DataParameter_DB backend) { backend_ = backend; LOG(INFO) << "Using temporary dataset " << *filename_; - shared_ptr > dataset = - DatasetFactory(backend_); - CHECK(dataset->open(*filename_, Dataset::New)); + scoped_ptr db(db::GetDB(backend)); + db->Open(*filename_, db::NEW); + scoped_ptr txn(db->NewTransaction()); for (int i = 0; i < 5; ++i) { Datum datum; datum.set_label(i); @@ -55,10 +58,12 @@ class DataLayerTest : public MultiDeviceTest { } stringstream ss; ss << i; - CHECK(dataset->put(ss.str(), datum)); + string out; + CHECK(datum.SerializeToString(&out)); + txn->Put(ss.str(), out); } - CHECK(dataset->commit()); - dataset->close(); + txn->Commit(); + db->Close(); } void TestRead() { @@ -183,7 +188,7 @@ class DataLayerTest : public MultiDeviceTest { } crop_sequence.push_back(iter_crop_sequence); } - } // destroy 1st data layer and unlock the dataset + } // destroy 1st data layer and unlock the db // Get crop sequence after reseeding Caffe with 1701. // Check that the sequence is the same as the original. @@ -238,7 +243,7 @@ class DataLayerTest : public MultiDeviceTest { } crop_sequence.push_back(iter_crop_sequence); } - } // destroy 1st data layer and unlock the dataset + } // destroy 1st data layer and unlock the db // Get crop sequence continuing from previous Caffe RNG state; reseed // srand with 1701. Check that the sequence differs from the original. diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index 358f57e38d6..dff63a09dca 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -1,24 +1,25 @@ -#include -#include #include - #include #include #include #include -#include "caffe/dataset_factory.hpp" +#include "boost/scoped_ptr.hpp" +#include "gflags/gflags.h" +#include "glog/logging.h" + #include "caffe/proto/caffe.pb.h" +#include "caffe/util/db.hpp" #include "caffe/util/io.hpp" -using caffe::Dataset; -using caffe::Datum; -using caffe::BlobProto; +using namespace caffe; // NOLINT(build/namespaces) + using std::max; using std::pair; +using boost::scoped_ptr; - -DEFINE_string(backend, "lmdb", "The backend for containing the images"); +DEFINE_string(backend, "lmdb", + "The backend {leveldb, lmdb} containing the images"); int main(int argc, char** argv) { ::google::InitGoogleLogging(argv[0]); @@ -28,7 +29,7 @@ int main(int argc, char** argv) { #endif gflags::SetUsageMessage("Compute the mean_image of a set of images given by" - " a leveldb/lmdb or a list of images\n" + " a leveldb/lmdb\n" "Usage:\n" " compute_image_mean [FLAGS] INPUT_DB [OUTPUT_FILE]\n"); @@ -39,19 +40,15 @@ int main(int argc, char** argv) { return 1; } - std::string db_backend = FLAGS_backend; - - caffe::shared_ptr > dataset = - caffe::DatasetFactory(db_backend); - - // Open db - CHECK(dataset->open(argv[1], Dataset::ReadOnly)); + scoped_ptr db(db::GetDB(FLAGS_backend)); + db->Open(argv[1], db::READ); + scoped_ptr cursor(db->NewCursor()); BlobProto sum_blob; int count = 0; // load first datum - Dataset::const_iterator iter = dataset->begin(); - Datum datum = iter->value; + Datum datum; + datum.ParseFromString(cursor->value()); if (DecodeDatum(&datum)) { LOG(INFO) << "Decoding Datum"; @@ -68,9 +65,9 @@ int main(int argc, char** argv) { sum_blob.add_data(0.); } LOG(INFO) << "Starting Iteration"; - for (Dataset::const_iterator iter = dataset->begin(); - iter != dataset->end(); ++iter) { - Datum datum = iter->value; + while (cursor->valid()) { + Datum datum; + datum.ParseFromString(cursor->value()); DecodeDatum(&datum); const std::string& data = datum.data(); @@ -94,6 +91,7 @@ int main(int argc, char** argv) { if (count % 10000 == 0) { LOG(INFO) << "Processed " << count << " files."; } + cursor->Next(); } if (count % 10000 != 0) { @@ -117,7 +115,5 @@ int main(int argc, char** argv) { } LOG(INFO) << "mean_value channel [" << c << "]:" << mean_values[c] / dim; } - // Clean up - dataset->close(); return 0; } diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 5d42e69c1ed..7fbf5b0514c 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -8,28 +8,31 @@ // subfolder1/file1.JPEG 7 // .... -#include -#include - #include #include // NOLINT(readability/streams) #include #include #include -#include "caffe/dataset_factory.hpp" +#include "boost/scoped_ptr.hpp" +#include "gflags/gflags.h" +#include "glog/logging.h" + #include "caffe/proto/caffe.pb.h" +#include "caffe/util/db.hpp" #include "caffe/util/io.hpp" #include "caffe/util/rng.hpp" using namespace caffe; // NOLINT(build/namespaces) using std::pair; +using boost::scoped_ptr; DEFINE_bool(gray, false, "When this option is on, treat images as grayscale ones"); DEFINE_bool(shuffle, false, "Randomly shuffle the order of images and their labels"); -DEFINE_string(backend, "lmdb", "The backend for storing the result"); +DEFINE_string(backend, "lmdb", + "The backend {lmdb, leveldb} for storing the result"); DEFINE_int32(resize_width, 0, "Width images are resized to"); DEFINE_int32(resize_height, 0, "Height images are resized to"); DEFINE_bool(check_size, false, @@ -75,9 +78,6 @@ int main(int argc, char** argv) { } LOG(INFO) << "A total of " << lines.size() << " images."; - const std::string& db_backend = FLAGS_backend; - const char* db_path = argv[3]; - if (encoded) { CHECK_EQ(FLAGS_resize_height, 0) << "With encoded don't resize images"; CHECK_EQ(FLAGS_resize_width, 0) << "With encoded don't resize images"; @@ -87,12 +87,10 @@ int main(int argc, char** argv) { int resize_height = std::max(0, FLAGS_resize_height); int resize_width = std::max(0, FLAGS_resize_width); - // Open new db - shared_ptr > dataset = - DatasetFactory(db_backend); - - // Open db - CHECK(dataset->open(db_path, Dataset::New)); + // Create new DB + scoped_ptr db(db::GetDB(FLAGS_backend)); + db->Open(argv[3], db::NEW); + scoped_ptr txn(db->NewTransaction()); // Storing to db std::string root_folder(argv[1]); @@ -128,19 +126,21 @@ int main(int argc, char** argv) { lines[line_id].first.c_str()); // Put in db - CHECK(dataset->put(string(key_cstr, length), datum)); + string out; + CHECK(datum.SerializeToString(&out)); + txn->Put(string(key_cstr, length), out); if (++count % 1000 == 0) { - // Commit txn - CHECK(dataset->commit()); + // Commit db + txn->Commit(); + txn.reset(db->NewTransaction()); LOG(ERROR) << "Processed " << count << " files."; } } // write the last batch if (count % 1000 != 0) { - CHECK(dataset->commit()); + txn->Commit(); LOG(ERROR) << "Processed " << count << " files."; } - dataset->close(); return 0; } diff --git a/tools/extract_features.cpp b/tools/extract_features.cpp index ddbce1075ed..c17b88dd048 100644 --- a/tools/extract_features.cpp +++ b/tools/extract_features.cpp @@ -7,19 +7,19 @@ #include "caffe/blob.hpp" #include "caffe/common.hpp" -#include "caffe/dataset_factory.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/db.hpp" #include "caffe/util/io.hpp" #include "caffe/vision_layers.hpp" -using boost::shared_ptr; using caffe::Blob; using caffe::Caffe; -using caffe::Dataset; -using caffe::DatasetFactory; using caffe::Datum; using caffe::Net; +using boost::shared_ptr; +using std::string; +namespace db = caffe::db; template int feature_extraction_pipeline(int argc, char** argv); @@ -121,13 +121,15 @@ int feature_extraction_pipeline(int argc, char** argv) { int num_mini_batches = atoi(argv[++arg_pos]); - std::vector > > feature_dbs; + std::vector > feature_dbs; + std::vector > txns; for (size_t i = 0; i < num_features; ++i) { LOG(INFO)<< "Opening dataset " << dataset_names[i]; - shared_ptr > dataset = - DatasetFactory(argv[++arg_pos]); - CHECK(dataset->open(dataset_names.at(i), Dataset::New)); - feature_dbs.push_back(dataset); + shared_ptr db(db::GetDB(argv[++arg_pos])); + db->Open(dataset_names.at(i), db::NEW); + feature_dbs.push_back(db); + shared_ptr txn(db->NewTransaction()); + txns.push_back(txn); } LOG(ERROR)<< "Extacting Features"; @@ -158,10 +160,13 @@ int feature_extraction_pipeline(int argc, char** argv) { } int length = snprintf(key_str, kMaxKeyStrLength, "%d", image_indices[i]); - CHECK(feature_dbs.at(i)->put(std::string(key_str, length), datum)); + string out; + CHECK(datum.SerializeToString(&out)); + txns.at(i)->Put(std::string(key_str, length), out); ++image_indices[i]; if (image_indices[i] % 1000 == 0) { - CHECK(feature_dbs.at(i)->commit()); + txns.at(i)->Commit(); + txns.at(i).reset(feature_dbs.at(i)->NewTransaction()); LOG(ERROR)<< "Extracted features of " << image_indices[i] << " query images for feature blob " << blob_names[i]; } @@ -171,11 +176,11 @@ int feature_extraction_pipeline(int argc, char** argv) { // write the last batch for (int i = 0; i < num_features; ++i) { if (image_indices[i] % 1000 != 0) { - CHECK(feature_dbs.at(i)->commit()); + txns.at(i)->Commit(); } LOG(ERROR)<< "Extracted features of " << image_indices[i] << " query images for feature blob " << blob_names[i]; - feature_dbs.at(i)->close(); + feature_dbs.at(i)->Close(); } LOG(ERROR)<< "Successfully extracted the features!"; From 88e3bc88b4ca09d51dd551b62e64e3c149cd4e0c Mon Sep 17 00:00:00 2001 From: Sergio Guadarrama Date: Fri, 16 Jan 2015 13:20:26 -0800 Subject: [PATCH 240/798] test db wrappers --- src/caffe/test/test_db.cpp | 134 +++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/caffe/test/test_db.cpp diff --git a/src/caffe/test/test_db.cpp b/src/caffe/test/test_db.cpp new file mode 100644 index 00000000000..5b2ac230a0b --- /dev/null +++ b/src/caffe/test/test_db.cpp @@ -0,0 +1,134 @@ +#include + +#include "boost/scoped_ptr.hpp" +#include "gtest/gtest.h" + +#include "caffe/common.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/util/db.hpp" +#include "caffe/util/io.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +using boost::scoped_ptr; + +template +class DBTest : public ::testing::Test { + protected: + DBTest() + : backend_(TypeParam::backend), + root_images_(string(EXAMPLES_SOURCE_DIR) + string("images/")) {} + + virtual void SetUp() { + MakeTempDir(&source_); + source_ += "/db"; + string keys[] = {"cat.jpg", "fish-bike.jpg"}; + LOG(INFO) << "Using temporary db " << source_; + scoped_ptr db(db::GetDB(TypeParam::backend)); + db->Open(this->source_, db::NEW); + scoped_ptr txn(db->NewTransaction()); + for (int i = 0; i < 2; ++i) { + Datum datum; + ReadImageToDatum(root_images_ + keys[i], i, &datum); + string out; + CHECK(datum.SerializeToString(&out)); + txn->Put(keys[i], out); + } + txn->Commit(); + } + + virtual ~DBTest() { } + + DataParameter_DB backend_; + string source_; + string root_images_; +}; + +struct TypeLevelDB { + static DataParameter_DB backend; +}; +DataParameter_DB TypeLevelDB::backend = DataParameter_DB_LEVELDB; + +struct TypeLMDB { + static DataParameter_DB backend; +}; +DataParameter_DB TypeLMDB::backend = DataParameter_DB_LMDB; + +// typedef ::testing::Types TestTypes; +typedef ::testing::Types TestTypes; + +TYPED_TEST_CASE(DBTest, TestTypes); + +TYPED_TEST(DBTest, TestGetDB) { + scoped_ptr db(db::GetDB(TypeParam::backend)); +} + +TYPED_TEST(DBTest, TestNext) { + scoped_ptr db(db::GetDB(TypeParam::backend)); + db->Open(this->source_, db::READ); + scoped_ptr cursor(db->NewCursor()); + EXPECT_TRUE(cursor->valid()); + cursor->Next(); + EXPECT_TRUE(cursor->valid()); + cursor->Next(); + EXPECT_FALSE(cursor->valid()); +} + +TYPED_TEST(DBTest, TestSeekToFirst) { + scoped_ptr db(db::GetDB(TypeParam::backend)); + db->Open(this->source_, db::READ); + scoped_ptr cursor(db->NewCursor()); + cursor->Next(); + cursor->SeekToFirst(); + EXPECT_TRUE(cursor->valid()); + string key = cursor->key(); + Datum datum; + datum.ParseFromString(cursor->value()); + EXPECT_EQ(key, "cat.jpg"); + EXPECT_EQ(datum.channels(), 3); + EXPECT_EQ(datum.height(), 360); + EXPECT_EQ(datum.width(), 480); +} + +TYPED_TEST(DBTest, TestKeyValue) { + scoped_ptr db(db::GetDB(TypeParam::backend)); + db->Open(this->source_, db::READ); + scoped_ptr cursor(db->NewCursor()); + EXPECT_TRUE(cursor->valid()); + string key = cursor->key(); + Datum datum; + datum.ParseFromString(cursor->value()); + EXPECT_EQ(key, "cat.jpg"); + EXPECT_EQ(datum.channels(), 3); + EXPECT_EQ(datum.height(), 360); + EXPECT_EQ(datum.width(), 480); + cursor->Next(); + EXPECT_TRUE(cursor->valid()); + key = cursor->key(); + datum.ParseFromString(cursor->value()); + EXPECT_EQ(key, "fish-bike.jpg"); + EXPECT_EQ(datum.channels(), 3); + EXPECT_EQ(datum.height(), 323); + EXPECT_EQ(datum.width(), 481); + cursor->Next(); + EXPECT_FALSE(cursor->valid()); +} + +TYPED_TEST(DBTest, TestWrite) { + scoped_ptr db(db::GetDB(TypeParam::backend)); + db->Open(this->source_, db::WRITE); + scoped_ptr txn(db->NewTransaction()); + Datum datum; + ReadFileToDatum(this->root_images_ + "cat.jpg", 0, &datum); + string out; + CHECK(datum.SerializeToString(&out)); + txn->Put("cat.jpg", out); + ReadFileToDatum(this->root_images_ + "fish-bike.jpg", 1, &datum); + CHECK(datum.SerializeToString(&out)); + txn->Put("fish-bike.jpg", out); + txn->Commit(); +} + +} // namespace caffe From 3b88e359f7f57a62608d42e2e6786a25eab4ecbb Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Fri, 16 Jan 2015 13:25:00 -0800 Subject: [PATCH 241/798] gut dataset wrappers --- include/caffe/dataset.hpp | 241 --------- include/caffe/dataset_factory.hpp | 20 - include/caffe/leveldb_dataset.hpp | 90 ---- include/caffe/lmdb_dataset.hpp | 95 ---- src/caffe/dataset_factory.cpp | 50 -- src/caffe/leveldb_dataset.cpp | 265 ---------- src/caffe/lmdb_dataset.cpp | 366 -------------- src/caffe/test/test_dataset.cpp | 794 ------------------------------ 8 files changed, 1921 deletions(-) delete mode 100644 include/caffe/dataset.hpp delete mode 100644 include/caffe/dataset_factory.hpp delete mode 100644 include/caffe/leveldb_dataset.hpp delete mode 100644 include/caffe/lmdb_dataset.hpp delete mode 100644 src/caffe/dataset_factory.cpp delete mode 100644 src/caffe/leveldb_dataset.cpp delete mode 100644 src/caffe/lmdb_dataset.cpp delete mode 100644 src/caffe/test/test_dataset.cpp diff --git a/include/caffe/dataset.hpp b/include/caffe/dataset.hpp deleted file mode 100644 index 1dd8458cd74..00000000000 --- a/include/caffe/dataset.hpp +++ /dev/null @@ -1,241 +0,0 @@ -#ifndef CAFFE_DATASET_H_ -#define CAFFE_DATASET_H_ - -#include - -#include -#include -#include -#include -#include - -#include "caffe/common.hpp" -#include "caffe/proto/caffe.pb.h" - -namespace caffe { - -namespace dataset_internal { - -using google::protobuf::Message; - -template -struct static_assertion {}; -template<> -struct static_assertion { - enum { - DEFAULT_CODER_NOT_AVAILABLE - }; -}; - -template -struct DefaultCoder { - using static_assertion::DEFAULT_CODER_NOT_AVAILABLE; - static bool serialize(const T& obj, string* serialized); - static bool serialize(const T& obj, vector* serialized); - static bool deserialize(const string& serialized, T* obj); - static bool deserialize(const char* data, size_t size, T* obj); -}; - -template <> -struct DefaultCoder { - static bool serialize(const Message& obj, string* serialized) { - return obj.SerializeToString(serialized); - } - - static bool serialize(const Message& obj, vector* serialized) { - serialized->resize(obj.ByteSize()); - return obj.SerializeWithCachedSizesToArray( - reinterpret_cast(serialized->data())); - } - - static bool deserialize(const string& serialized, Message* obj) { - return obj->ParseFromString(serialized); - } - - static bool deserialize(const char* data, size_t size, Message* obj) { - return obj->ParseFromArray(data, size); - } -}; - -template <> -struct DefaultCoder : public DefaultCoder { }; - -template <> -struct DefaultCoder { - static bool serialize(string obj, string* serialized) { - *serialized = obj; - return true; - } - - static bool serialize(const string& obj, vector* serialized) { - vector temp(obj.data(), obj.data() + obj.size()); - serialized->swap(temp); - return true; - } - - static bool deserialize(const string& serialized, string* obj) { - *obj = serialized; - return true; - } - - static bool deserialize(const char* data, size_t size, string* obj) { - string temp_string(data, size); - obj->swap(temp_string); - return true; - } -}; - -template <> -struct DefaultCoder > { - static bool serialize(vector obj, string* serialized) { - string tmp(obj.data(), obj.size()); - serialized->swap(tmp); - return true; - } - - static bool serialize(const vector& obj, vector* serialized) { - *serialized = obj; - return true; - } - - static bool deserialize(const string& serialized, vector* obj) { - vector tmp(serialized.data(), serialized.data() + serialized.size()); - obj->swap(tmp); - return true; - } - - static bool deserialize(const char* data, size_t size, vector* obj) { - vector tmp(data, data + size); - obj->swap(tmp); - return true; - } -}; - -} // namespace dataset_internal - -template , - typename VCoder = dataset_internal::DefaultCoder > -class Dataset { - public: - enum Mode { - New, - ReadWrite, - ReadOnly - }; - - typedef K key_type; - typedef V value_type; - - struct KV { - K key; - V value; - }; - - virtual bool open(const string& filename, Mode mode) = 0; - virtual bool put(const K& key, const V& value) = 0; - virtual bool get(const K& key, V* value) = 0; - virtual bool first_key(K* key) = 0; - virtual bool last_key(K* key) = 0; - virtual bool commit() = 0; - virtual void close() = 0; - - virtual void keys(vector* keys) = 0; - - Dataset() { } - virtual ~Dataset() { } - - class iterator; - typedef iterator const_iterator; - - virtual const_iterator begin() const = 0; - virtual const_iterator cbegin() const = 0; - virtual const_iterator end() const = 0; - virtual const_iterator cend() const = 0; - - protected: - class DatasetState; - - public: - class iterator : public std::iterator { - public: - typedef KV T; - typedef T value_type; - typedef T& reference_type; - typedef T* pointer_type; - - iterator() - : parent_(NULL) { } - - iterator(const Dataset* parent, shared_ptr state) - : parent_(parent), - state_(state) { } - - iterator(const iterator& other) - : parent_(other.parent_), - state_(other.state_ ? other.state_->clone() - : shared_ptr()) { } - - iterator& operator=(iterator copy) { - copy.swap(*this); - return *this; - } - - void swap(iterator& other) throw() { - std::swap(this->parent_, other.parent_); - std::swap(this->state_, other.state_); - } - - bool operator==(const iterator& other) const { - return parent_->equal(state_, other.state_); - } - - bool operator!=(const iterator& other) const { - return !(*this == other); - } - - iterator& operator++() { - parent_->increment(&state_); - return *this; - } - iterator operator++(int) { - iterator copy(*this); - parent_->increment(&state_); - return copy; - } - - reference_type operator*() const { - return parent_->dereference(state_); - } - - pointer_type operator->() const { - return &parent_->dereference(state_); - } - - protected: - const Dataset* parent_; - shared_ptr state_; - }; - - protected: - class DatasetState { - public: - virtual ~DatasetState() { } - virtual shared_ptr clone() = 0; - }; - - virtual bool equal(shared_ptr state1, - shared_ptr state2) const = 0; - virtual void increment(shared_ptr* state) const = 0; - virtual KV& dereference( - shared_ptr state) const = 0; -}; - -} // namespace caffe - -#define INSTANTIATE_DATASET(type) \ - template class type; \ - template class type >; \ - template class type; - -#endif // CAFFE_DATASET_H_ diff --git a/include/caffe/dataset_factory.hpp b/include/caffe/dataset_factory.hpp deleted file mode 100644 index 57db49bf524..00000000000 --- a/include/caffe/dataset_factory.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CAFFE_DATASET_FACTORY_H_ -#define CAFFE_DATASET_FACTORY_H_ - -#include - -#include "caffe/common.hpp" -#include "caffe/dataset.hpp" -#include "caffe/proto/caffe.pb.h" - -namespace caffe { - -template -shared_ptr > DatasetFactory(const DataParameter_DB& type); - -template -shared_ptr > DatasetFactory(const string& type); - -} // namespace caffe - -#endif // CAFFE_DATASET_FACTORY_H_ diff --git a/include/caffe/leveldb_dataset.hpp b/include/caffe/leveldb_dataset.hpp deleted file mode 100644 index d58c181bb2b..00000000000 --- a/include/caffe/leveldb_dataset.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef CAFFE_LEVELDB_DATASET_H_ -#define CAFFE_LEVELDB_DATASET_H_ - -#include -#include - -#include -#include -#include - -#include "caffe/common.hpp" -#include "caffe/dataset.hpp" - -namespace caffe { - -template , - typename VCoder = dataset_internal::DefaultCoder > -class LeveldbDataset : public Dataset { - public: - typedef Dataset Base; - typedef typename Base::key_type key_type; - typedef typename Base::value_type value_type; - typedef typename Base::DatasetState DatasetState; - typedef typename Base::Mode Mode; - typedef typename Base::const_iterator const_iterator; - typedef typename Base::KV KV; - - bool open(const string& filename, Mode mode); - bool put(const K& key, const V& value); - bool get(const K& key, V* value); - bool first_key(K* key); - bool last_key(K* key); - bool commit(); - void close(); - - void keys(vector* keys); - - const_iterator begin() const; - const_iterator cbegin() const; - const_iterator end() const; - const_iterator cend() const; - - protected: - class LeveldbState : public DatasetState { - public: - explicit LeveldbState(shared_ptr db, - shared_ptr iter) - : DatasetState(), - db_(db), - iter_(iter) { } - - ~LeveldbState() { - // This order is very important. - // Iterators must be destroyed before their associated DB - // is destroyed. - iter_.reset(); - db_.reset(); - } - - shared_ptr clone() { - shared_ptr new_iter; - - CHECK(iter_.get()); - new_iter.reset(db_->NewIterator(leveldb::ReadOptions())); - CHECK(iter_->Valid()); - new_iter->Seek(iter_->key()); - CHECK(new_iter->Valid()); - - return shared_ptr(new LeveldbState(db_, new_iter)); - } - - shared_ptr db_; - shared_ptr iter_; - KV kv_pair_; - }; - - bool equal(shared_ptr state1, - shared_ptr state2) const; - void increment(shared_ptr* state) const; - KV& dereference(shared_ptr state) const; - - shared_ptr db_; - shared_ptr batch_; - bool read_only_; -}; - -} // namespace caffe - -#endif // CAFFE_LEVELDB_DATASET_H_ diff --git a/include/caffe/lmdb_dataset.hpp b/include/caffe/lmdb_dataset.hpp deleted file mode 100644 index ac1e5ee25dd..00000000000 --- a/include/caffe/lmdb_dataset.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef CAFFE_LMDB_DATASET_H_ -#define CAFFE_LMDB_DATASET_H_ - -#include -#include -#include - -#include "lmdb.h" - -#include "caffe/common.hpp" -#include "caffe/dataset.hpp" - -namespace caffe { - -template , - typename VCoder = dataset_internal::DefaultCoder > -class LmdbDataset : public Dataset { - public: - typedef Dataset Base; - typedef typename Base::key_type key_type; - typedef typename Base::value_type value_type; - typedef typename Base::DatasetState DatasetState; - typedef typename Base::Mode Mode; - typedef typename Base::const_iterator const_iterator; - typedef typename Base::KV KV; - - LmdbDataset() - : env_(NULL), - dbi_(0), - write_txn_(NULL), - read_txn_(NULL) { } - - bool open(const string& filename, Mode mode); - bool put(const K& key, const V& value); - bool get(const K& key, V* value); - bool first_key(K* key); - bool last_key(K* key); - bool commit(); - void close(); - - void keys(vector* keys); - - const_iterator begin() const; - const_iterator cbegin() const; - const_iterator end() const; - const_iterator cend() const; - - protected: - class LmdbState : public DatasetState { - public: - explicit LmdbState(MDB_cursor* cursor, MDB_txn* txn, const MDB_dbi* dbi) - : DatasetState(), - cursor_(cursor), - txn_(txn), - dbi_(dbi) { } - - shared_ptr clone() { - CHECK(cursor_); - - MDB_cursor* new_cursor; - int retval; - - retval = mdb_cursor_open(txn_, *dbi_, &new_cursor); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - MDB_val key; - MDB_val val; - retval = mdb_cursor_get(cursor_, &key, &val, MDB_GET_CURRENT); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - retval = mdb_cursor_get(new_cursor, &key, &val, MDB_SET); - CHECK_EQ(MDB_SUCCESS, retval) << mdb_strerror(retval); - - return shared_ptr(new LmdbState(new_cursor, txn_, dbi_)); - } - - MDB_cursor* cursor_; - MDB_txn* txn_; - const MDB_dbi* dbi_; - KV kv_pair_; - }; - - bool equal(shared_ptr state1, - shared_ptr state2) const; - void increment(shared_ptr* state) const; - KV& dereference(shared_ptr state) const; - - MDB_env* env_; - MDB_dbi dbi_; - MDB_txn* write_txn_; - MDB_txn* read_txn_; -}; - -} // namespace caffe - -#endif // CAFFE_LMDB_DATASET_H_ diff --git a/src/caffe/dataset_factory.cpp b/src/caffe/dataset_factory.cpp deleted file mode 100644 index 3313de3c408..00000000000 --- a/src/caffe/dataset_factory.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include - -#include "caffe/dataset_factory.hpp" -#include "caffe/leveldb_dataset.hpp" -#include "caffe/lmdb_dataset.hpp" - -namespace caffe { - -template -shared_ptr > DatasetFactory(const DataParameter_DB& type) { - switch (type) { - case DataParameter_DB_LEVELDB: - return shared_ptr >(new LeveldbDataset()); - case DataParameter_DB_LMDB: - return shared_ptr >(new LmdbDataset()); - default: - LOG(FATAL) << "Unknown dataset type " << type; - return shared_ptr >(); - } -} - -template -shared_ptr > DatasetFactory(const string& type) { - if ("leveldb" == type) { - return DatasetFactory(DataParameter_DB_LEVELDB); - } else if ("lmdb" == type) { - return DatasetFactory(DataParameter_DB_LMDB); - } else { - LOG(FATAL) << "Unknown dataset type " << type; - return shared_ptr >(); - } -} - -#define REGISTER_DATASET(key_type, value_type) \ - template shared_ptr > \ - DatasetFactory(const string& type); \ - template shared_ptr > \ - DatasetFactory(const DataParameter_DB& type); \ - -REGISTER_DATASET(string, string); -REGISTER_DATASET(string, vector); -REGISTER_DATASET(string, Datum); - -#undef REGISTER_DATASET - -} // namespace caffe - - diff --git a/src/caffe/leveldb_dataset.cpp b/src/caffe/leveldb_dataset.cpp deleted file mode 100644 index 53df985721c..00000000000 --- a/src/caffe/leveldb_dataset.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include -#include -#include - -#include "caffe/caffe.hpp" -#include "caffe/leveldb_dataset.hpp" - -namespace caffe { - -template -bool LeveldbDataset::open(const string& filename, - Mode mode) { - DLOG(INFO) << "LevelDB: Open " << filename; - - leveldb::Options options; - switch (mode) { - case Base::New: - DLOG(INFO) << " mode NEW"; - options.error_if_exists = true; - options.create_if_missing = true; - read_only_ = false; - break; - case Base::ReadWrite: - DLOG(INFO) << " mode RW"; - options.error_if_exists = false; - options.create_if_missing = true; - read_only_ = false; - break; - case Base::ReadOnly: - DLOG(INFO) << " mode RO"; - options.error_if_exists = false; - options.create_if_missing = false; - read_only_ = true; - break; - default: - DLOG(FATAL) << "unknown mode " << mode; - } - options.write_buffer_size = 268435456; - options.max_open_files = 100; - - leveldb::DB* db; - - LOG(INFO) << "Opening leveldb " << filename; - leveldb::Status status = leveldb::DB::Open( - options, filename, &db); - db_.reset(db); - - if (!status.ok()) { - LOG(ERROR) << "Failed to open leveldb " << filename - << ". Is it already existing?"; - return false; - } - - batch_.reset(new leveldb::WriteBatch()); - return true; -} - -template -bool LeveldbDataset::put(const K& key, const V& value) { - DLOG(INFO) << "LevelDB: Put"; - - if (read_only_) { - LOG(ERROR) << "put can not be used on a dataset in ReadOnly mode"; - return false; - } - - CHECK_NOTNULL(batch_.get()); - - string serialized_key; - if (!KCoder::serialize(key, &serialized_key)) { - return false; - } - - string serialized_value; - if (!VCoder::serialize(value, &serialized_value)) { - return false; - } - - batch_->Put(serialized_key, serialized_value); - - return true; -} - -template -bool LeveldbDataset::get(const K& key, V* value) { - DLOG(INFO) << "LevelDB: Get"; - - string serialized_key; - if (!KCoder::serialize(key, &serialized_key)) { - return false; - } - - string serialized_value; - leveldb::Status status = - db_->Get(leveldb::ReadOptions(), serialized_key, &serialized_value); - - if (!status.ok()) { - LOG(ERROR) << "leveldb get failed"; - return false; - } - - if (!VCoder::deserialize(serialized_value, value)) { - return false; - } - - return true; -} - -template -bool LeveldbDataset::first_key(K* key) { - DLOG(INFO) << "LevelDB: First key"; - - CHECK_NOTNULL(db_.get()); - shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); - iter->SeekToFirst(); - CHECK(iter->Valid()); - const leveldb::Slice& key_slice = iter->key(); - return KCoder::deserialize(key_slice.data(), key_slice.size(), key); -} - -template -bool LeveldbDataset::last_key(K* key) { - DLOG(INFO) << "LevelDB: Last key"; - - CHECK_NOTNULL(db_.get()); - shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); - iter->SeekToLast(); - CHECK(iter->Valid()); - const leveldb::Slice& key_slice = iter->key(); - return KCoder::deserialize(key_slice.data(), key_slice.size(), key); -} - -template -bool LeveldbDataset::commit() { - DLOG(INFO) << "LevelDB: Commit"; - - if (read_only_) { - LOG(ERROR) << "commit can not be used on a dataset in ReadOnly mode"; - return false; - } - - CHECK_NOTNULL(db_.get()); - CHECK_NOTNULL(batch_.get()); - - leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch_.get()); - - batch_.reset(new leveldb::WriteBatch()); - - return status.ok(); -} - -template -void LeveldbDataset::close() { - DLOG(INFO) << "LevelDB: Close"; - - batch_.reset(); - db_.reset(); -} - -template -void LeveldbDataset::keys(vector* keys) { - DLOG(INFO) << "LevelDB: Keys"; - - keys->clear(); - for (const_iterator iter = begin(); iter != end(); ++iter) { - keys->push_back(iter->key); - } -} - -template -typename LeveldbDataset::const_iterator - LeveldbDataset::begin() const { - CHECK_NOTNULL(db_.get()); - shared_ptr iter(db_->NewIterator(leveldb::ReadOptions())); - iter->SeekToFirst(); - if (!iter->Valid()) { - iter.reset(); - } - - shared_ptr state; - if (iter) { - state.reset(new LeveldbState(db_, iter)); - } - return const_iterator(this, state); -} - -template -typename LeveldbDataset::const_iterator - LeveldbDataset::end() const { - shared_ptr state; - return const_iterator(this, state); -} - -template -typename LeveldbDataset::const_iterator - LeveldbDataset::cbegin() const { - return begin(); -} - -template -typename LeveldbDataset::const_iterator - LeveldbDataset::cend() const { return end(); } - -template -bool LeveldbDataset::equal( - shared_ptr state1, shared_ptr state2) const { - shared_ptr leveldb_state1 = - boost::dynamic_pointer_cast(state1); - - shared_ptr leveldb_state2 = - boost::dynamic_pointer_cast(state2); - - // The KV store doesn't really have any sort of ordering, - // so while we can do a sequential scan over the collection, - // we can't really use subranges. - return !leveldb_state1 && !leveldb_state2; -} - -template -void LeveldbDataset::increment( - shared_ptr* state) const { - shared_ptr leveldb_state = - boost::dynamic_pointer_cast(*state); - - CHECK_NOTNULL(leveldb_state.get()); - - shared_ptr& iter = leveldb_state->iter_; - - CHECK_NOTNULL(iter.get()); - CHECK(iter->Valid()); - - iter->Next(); - if (!iter->Valid()) { - state->reset(); - } -} - -template -typename Dataset::KV& - LeveldbDataset::dereference( - shared_ptr state) const { - shared_ptr leveldb_state = - boost::dynamic_pointer_cast(state); - - CHECK_NOTNULL(leveldb_state.get()); - - shared_ptr& iter = leveldb_state->iter_; - - CHECK_NOTNULL(iter.get()); - - CHECK(iter->Valid()); - - const leveldb::Slice& key = iter->key(); - const leveldb::Slice& value = iter->value(); - CHECK(KCoder::deserialize(key.data(), key.size(), - &leveldb_state->kv_pair_.key)); - CHECK(VCoder::deserialize(value.data(), value.size(), - &leveldb_state->kv_pair_.value)); - - return leveldb_state->kv_pair_; -} - -INSTANTIATE_DATASET(LeveldbDataset); - -} // namespace caffe diff --git a/src/caffe/lmdb_dataset.cpp b/src/caffe/lmdb_dataset.cpp deleted file mode 100644 index 8f8e68e901e..00000000000 --- a/src/caffe/lmdb_dataset.cpp +++ /dev/null @@ -1,366 +0,0 @@ -#include - -#include -#include -#include - -#include "caffe/caffe.hpp" -#include "caffe/lmdb_dataset.hpp" - -namespace caffe { - -template -bool LmdbDataset::open(const string& filename, - Mode mode) { - DLOG(INFO) << "LMDB: Open " << filename; - - CHECK(NULL == env_); - CHECK(NULL == write_txn_); - CHECK(NULL == read_txn_); - CHECK_EQ(0, dbi_); - - int retval; - if (mode != Base::ReadOnly) { - retval = mkdir(filename.c_str(), 0744); - switch (mode) { - case Base::New: - if (0 != retval) { - LOG(ERROR) << "mkdir " << filename << " failed"; - return false; - } - break; - case Base::ReadWrite: - if (-1 == retval && EEXIST != errno) { - LOG(ERROR) << "mkdir " << filename << " failed (" - << strerror(errno) << ")"; - return false; - } - break; - default: - LOG(FATAL) << "Invalid mode " << mode; - } - } - - retval = mdb_env_create(&env_); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_env_create failed " - << mdb_strerror(retval); - return false; - } - - retval = mdb_env_set_mapsize(env_, 1099511627776); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_env_set_mapsize failed " << mdb_strerror(retval); - return false; - } - - int flag1 = 0; - int flag2 = 0; - if (mode == Base::ReadOnly) { - flag1 = MDB_RDONLY | MDB_NOTLS; - flag2 = MDB_RDONLY; - } - - retval = mdb_env_open(env_, filename.c_str(), flag1, 0664); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_env_open failed " << mdb_strerror(retval); - return false; - } - - retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &read_txn_); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); - return false; - } - - retval = mdb_txn_begin(env_, NULL, flag2, &write_txn_); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); - return false; - } - - retval = mdb_open(write_txn_, NULL, 0, &dbi_); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_open failed" << mdb_strerror(retval); - return false; - } - - return true; -} - -template -bool LmdbDataset::put(const K& key, const V& value) { - DLOG(INFO) << "LMDB: Put"; - - vector serialized_key; - if (!KCoder::serialize(key, &serialized_key)) { - LOG(ERROR) << "failed to serialize key"; - return false; - } - - vector serialized_value; - if (!VCoder::serialize(value, &serialized_value)) { - LOG(ERROR) << "failed to serialized value"; - return false; - } - - MDB_val mdbkey, mdbdata; - mdbdata.mv_size = serialized_value.size(); - mdbdata.mv_data = serialized_value.data(); - mdbkey.mv_size = serialized_key.size(); - mdbkey.mv_data = serialized_key.data(); - - CHECK_NOTNULL(write_txn_); - CHECK_NE(0, dbi_); - - int retval = mdb_put(write_txn_, dbi_, &mdbkey, &mdbdata, 0); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_put failed " << mdb_strerror(retval); - return false; - } - - return true; -} - -template -bool LmdbDataset::get(const K& key, V* value) { - DLOG(INFO) << "LMDB: Get"; - - vector serialized_key; - if (!KCoder::serialize(key, &serialized_key)) { - LOG(ERROR) << "failed to serialized key"; - return false; - } - - MDB_val mdbkey, mdbdata; - mdbkey.mv_data = serialized_key.data(); - mdbkey.mv_size = serialized_key.size(); - - int retval; - retval = mdb_get(read_txn_, dbi_, &mdbkey, &mdbdata); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_get failed " << mdb_strerror(retval); - return false; - } - - if (!VCoder::deserialize(reinterpret_cast(mdbdata.mv_data), - mdbdata.mv_size, value)) { - LOG(ERROR) << "failed to deserialize value"; - return false; - } - - return true; -} - -template -bool LmdbDataset::first_key(K* key) { - DLOG(INFO) << "LMDB: First key"; - - int retval; - - MDB_cursor* cursor; - retval = mdb_cursor_open(read_txn_, dbi_, &cursor); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - MDB_val mdbkey; - MDB_val mdbval; - retval = mdb_cursor_get(cursor, &mdbkey, &mdbval, MDB_FIRST); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - - mdb_cursor_close(cursor); - - if (!KCoder::deserialize(reinterpret_cast(mdbkey.mv_data), - mdbkey.mv_size, key)) { - LOG(ERROR) << "failed to deserialize key"; - return false; - } - - return true; -} - -template -bool LmdbDataset::last_key(K* key) { - DLOG(INFO) << "LMDB: Last key"; - - int retval; - - MDB_cursor* cursor; - retval = mdb_cursor_open(read_txn_, dbi_, &cursor); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - MDB_val mdbkey; - MDB_val mdbval; - retval = mdb_cursor_get(cursor, &mdbkey, &mdbval, MDB_LAST); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - - mdb_cursor_close(cursor); - - if (!KCoder::deserialize(reinterpret_cast(mdbkey.mv_data), - mdbkey.mv_size, key)) { - LOG(ERROR) << "failed to deserialize key"; - return false; - } - - return true; -} - -template -bool LmdbDataset::commit() { - DLOG(INFO) << "LMDB: Commit"; - - CHECK_NOTNULL(write_txn_); - - int retval; - retval = mdb_txn_commit(write_txn_); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_txn_commit failed " << mdb_strerror(retval); - return false; - } - - mdb_txn_abort(read_txn_); - - retval = mdb_txn_begin(env_, NULL, 0, &write_txn_); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); - return false; - } - - retval = mdb_txn_begin(env_, NULL, MDB_RDONLY, &read_txn_); - if (MDB_SUCCESS != retval) { - LOG(ERROR) << "mdb_txn_begin failed " << mdb_strerror(retval); - return false; - } - - return true; -} - -template -void LmdbDataset::close() { - DLOG(INFO) << "LMDB: Close"; - - if (env_ && dbi_) { - mdb_txn_abort(write_txn_); - mdb_txn_abort(read_txn_); - mdb_close(env_, dbi_); - mdb_env_close(env_); - env_ = NULL; - dbi_ = 0; - write_txn_ = NULL; - read_txn_ = NULL; - } -} - -template -void LmdbDataset::keys(vector* keys) { - DLOG(INFO) << "LMDB: Keys"; - - keys->clear(); - for (const_iterator iter = begin(); iter != end(); ++iter) { - keys->push_back(iter->key); - } -} - -template -typename LmdbDataset::const_iterator - LmdbDataset::begin() const { - int retval; - - MDB_cursor* cursor; - retval = mdb_cursor_open(read_txn_, dbi_, &cursor); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - MDB_val key; - MDB_val val; - retval = mdb_cursor_get(cursor, &key, &val, MDB_FIRST); - - CHECK(MDB_SUCCESS == retval || MDB_NOTFOUND == retval) - << mdb_strerror(retval); - - shared_ptr state; - if (MDB_SUCCESS == retval) { - state.reset(new LmdbState(cursor, read_txn_, &dbi_)); - } else { - mdb_cursor_close(cursor); - } - return const_iterator(this, state); -} - -template -typename LmdbDataset::const_iterator - LmdbDataset::end() const { - shared_ptr state; - return const_iterator(this, state); -} - -template -typename LmdbDataset::const_iterator - LmdbDataset::cbegin() const { return begin(); } - -template -typename LmdbDataset::const_iterator - LmdbDataset::cend() const { return end(); } - -template -bool LmdbDataset::equal(shared_ptr state1, - shared_ptr state2) const { - shared_ptr lmdb_state1 = - boost::dynamic_pointer_cast(state1); - - shared_ptr lmdb_state2 = - boost::dynamic_pointer_cast(state2); - - // The KV store doesn't really have any sort of ordering, - // so while we can do a sequential scan over the collection, - // we can't really use subranges. - return !lmdb_state1 && !lmdb_state2; -} - -template -void LmdbDataset::increment( - shared_ptr* state) const { - shared_ptr lmdb_state = - boost::dynamic_pointer_cast(*state); - - CHECK_NOTNULL(lmdb_state.get()); - - MDB_cursor*& cursor = lmdb_state->cursor_; - - CHECK_NOTNULL(cursor); - - MDB_val key; - MDB_val val; - int retval = mdb_cursor_get(cursor, &key, &val, MDB_NEXT); - if (MDB_NOTFOUND == retval) { - mdb_cursor_close(cursor); - state->reset(); - } else { - CHECK_EQ(MDB_SUCCESS, retval) << mdb_strerror(retval); - } -} - -template -typename Dataset::KV& - LmdbDataset::dereference( - shared_ptr state) const { - shared_ptr lmdb_state = - boost::dynamic_pointer_cast(state); - - CHECK_NOTNULL(lmdb_state.get()); - - MDB_cursor*& cursor = lmdb_state->cursor_; - - CHECK_NOTNULL(cursor); - - MDB_val mdb_key; - MDB_val mdb_val; - int retval = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT); - CHECK_EQ(retval, MDB_SUCCESS) << mdb_strerror(retval); - - CHECK(KCoder::deserialize(reinterpret_cast(mdb_key.mv_data), - mdb_key.mv_size, &lmdb_state->kv_pair_.key)); - CHECK(VCoder::deserialize(reinterpret_cast(mdb_val.mv_data), - mdb_val.mv_size, &lmdb_state->kv_pair_.value)); - - return lmdb_state->kv_pair_; -} - -INSTANTIATE_DATASET(LmdbDataset); - -} // namespace caffe diff --git a/src/caffe/test/test_dataset.cpp b/src/caffe/test/test_dataset.cpp deleted file mode 100644 index 6645ca228d2..00000000000 --- a/src/caffe/test/test_dataset.cpp +++ /dev/null @@ -1,794 +0,0 @@ -#include -#include - -#include "caffe/util/io.hpp" - -#include "gtest/gtest.h" - -#include "caffe/dataset_factory.hpp" - -#include "caffe/test/test_caffe_main.hpp" - -namespace caffe { - -namespace DatasetTest_internal { - -template -struct TestData { - static T TestValue(); - static T TestAltValue(); - static bool equals(const T& a, const T& b); -}; - -template <> -string TestData::TestValue() { - return "world"; -} - -template <> -string TestData::TestAltValue() { - return "bar"; -} - -template <> -bool TestData::equals(const string& a, const string& b) { - return a == b; -} - -template <> -vector TestData >::TestValue() { - string str = "world"; - vector val(str.data(), str.data() + str.size()); - return val; -} - -template <> -vector TestData >::TestAltValue() { - string str = "bar"; - vector val(str.data(), str.data() + str.size()); - return val; -} - -template <> -bool TestData >::equals(const vector& a, - const vector& b) { - if (a.size() != b.size()) { - return false; - } - for (size_t i = 0; i < a.size(); ++i) { - if (a.at(i) != b.at(i)) { - return false; - } - } - - return true; -} - -template <> -Datum TestData::TestValue() { - Datum datum; - datum.set_channels(3); - datum.set_height(32); - datum.set_width(32); - datum.set_data(string(32 * 32 * 3 * 4, ' ')); - datum.set_label(0); - return datum; -} - -template <> -Datum TestData::TestAltValue() { - Datum datum; - datum.set_channels(1); - datum.set_height(64); - datum.set_width(64); - datum.set_data(string(64 * 64 * 1 * 4, ' ')); - datum.set_label(1); - return datum; -} - -template <> -bool TestData::equals(const Datum& a, const Datum& b) { - string serialized_a; - a.SerializeToString(&serialized_a); - - string serialized_b; - b.SerializeToString(&serialized_b); - - return serialized_a == serialized_b; -} - -} // namespace DatasetTest_internal - -#define UNPACK_TYPES \ - typedef typename TypeParam::value_type value_type; \ - const DataParameter_DB backend = TypeParam::backend; - -template -class DatasetTest : public ::testing::Test { - protected: - typedef typename TypeParam::value_type value_type; - - string DBName() { - string filename; - MakeTempDir(&filename); - filename += "/db"; - return filename; - } - - string TestKey() { - return "hello"; - } - - value_type TestValue() { - return DatasetTest_internal::TestData::TestValue(); - } - - string TestAltKey() { - return "foo"; - } - - value_type TestAltValue() { - return DatasetTest_internal::TestData::TestAltValue(); - } - - template - bool equals(const T& a, const T& b) { - return DatasetTest_internal::TestData::equals(a, b); - } -}; - -struct StringLeveldb { - typedef string value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB StringLeveldb::backend = DataParameter_DB_LEVELDB; - -struct StringLmdb { - typedef string value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB StringLmdb::backend = DataParameter_DB_LMDB; - -struct VectorLeveldb { - typedef vector value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB VectorLeveldb::backend = DataParameter_DB_LEVELDB; - -struct VectorLmdb { - typedef vector value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB VectorLmdb::backend = DataParameter_DB_LMDB; - -struct DatumLeveldb { - typedef Datum value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB DatumLeveldb::backend = DataParameter_DB_LEVELDB; - -struct DatumLmdb { - typedef Datum value_type; - static const DataParameter_DB backend; -}; -const DataParameter_DB DatumLmdb::backend = DataParameter_DB_LMDB; - -typedef ::testing::Types TestTypes; - -TYPED_TEST_CASE(DatasetTest, TestTypes); - -TYPED_TEST(DatasetTest, TestNewDoesntExistPasses) { - UNPACK_TYPES; - - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(this->DBName(), - Dataset::New)); - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestNewExistsFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - dataset->close(); - - EXPECT_FALSE(dataset->open(name, Dataset::New)); -} - -TYPED_TEST(DatasetTest, TestReadOnlyExistsPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - dataset->close(); - - EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestReadOnlyDoesntExistFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_FALSE(dataset->open(name, Dataset::ReadOnly)); -} - -TYPED_TEST(DatasetTest, TestReadWriteExistsPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - dataset->close(); - - EXPECT_TRUE(dataset->open(name, Dataset::ReadWrite)); - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestReadWriteDoesntExistPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::ReadWrite)); - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestKeys) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key1 = this->TestKey(); - value_type value1 = this->TestValue(); - - EXPECT_TRUE(dataset->put(key1, value1)); - - string key2 = this->TestAltKey(); - value_type value2 = this->TestAltValue(); - - EXPECT_TRUE(dataset->put(key2, value2)); - - EXPECT_TRUE(dataset->commit()); - - vector keys; - dataset->keys(&keys); - - EXPECT_EQ(2, keys.size()); - - EXPECT_TRUE(this->equals(keys.at(0), key1) || - this->equals(keys.at(0), key2)); - EXPECT_TRUE(this->equals(keys.at(1), key1) || - this->equals(keys.at(2), key2)); - EXPECT_FALSE(this->equals(keys.at(0), keys.at(1))); -} - -TYPED_TEST(DatasetTest, TestFirstKey) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - value_type value = this->TestValue(); - - string key1 = "01"; - EXPECT_TRUE(dataset->put(key1, value)); - - string key2 = "02"; - EXPECT_TRUE(dataset->put(key2, value)); - - string key3 = "03"; - EXPECT_TRUE(dataset->put(key3, value)); - - EXPECT_TRUE(dataset->commit()); - - string first_key; - dataset->first_key(&first_key); - - EXPECT_TRUE(this->equals(first_key, key1)); -} - -TYPED_TEST(DatasetTest, TestLastKey) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - value_type value = this->TestValue(); - - string key1 = "01"; - EXPECT_TRUE(dataset->put(key1, value)); - - string key2 = "02"; - EXPECT_TRUE(dataset->put(key2, value)); - - string key3 = "03"; - EXPECT_TRUE(dataset->put(key3, value)); - - EXPECT_TRUE(dataset->commit()); - - string last_key; - dataset->last_key(&last_key); - - EXPECT_TRUE(this->equals(last_key, key3)); -} - -TYPED_TEST(DatasetTest, TestFirstLastKeys) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - value_type value = this->TestValue(); - - string key1 = "01"; - EXPECT_TRUE(dataset->put(key1, value)); - - string key2 = "02"; - EXPECT_TRUE(dataset->put(key2, value)); - - string key3 = "03"; - EXPECT_TRUE(dataset->put(key3, value)); - - EXPECT_TRUE(dataset->commit()); - - string first_key; - dataset->first_key(&first_key); - string last_key; - dataset->last_key(&last_key); - - EXPECT_TRUE(this->equals(first_key, key1)); - EXPECT_TRUE(this->equals(last_key, key3)); -} - -TYPED_TEST(DatasetTest, TestFirstLastKeysUnOrdered) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - value_type value = this->TestValue(); - - string key3 = "03"; - EXPECT_TRUE(dataset->put(key3, value)); - - string key1 = "01"; - EXPECT_TRUE(dataset->put(key1, value)); - - string key2 = "02"; - EXPECT_TRUE(dataset->put(key2, value)); - - EXPECT_TRUE(dataset->commit()); - - string first_key; - dataset->first_key(&first_key); - string last_key; - dataset->last_key(&last_key); - - EXPECT_TRUE(this->equals(first_key, key1)); - EXPECT_TRUE(this->equals(last_key, key3)); -} - -TYPED_TEST(DatasetTest, TestKeysNoCommit) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key1 = this->TestKey(); - value_type value1 = this->TestValue(); - - EXPECT_TRUE(dataset->put(key1, value1)); - - string key2 = this->TestAltKey(); - value_type value2 = this->TestAltValue(); - - EXPECT_TRUE(dataset->put(key2, value2)); - - vector keys; - dataset->keys(&keys); - - EXPECT_EQ(0, keys.size()); -} - -TYPED_TEST(DatasetTest, TestIterators) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - const int kNumExamples = 4; - for (int i = 0; i < kNumExamples; ++i) { - stringstream ss; - ss << i; - string key = ss.str(); - ss << " here be data"; - value_type value = this->TestValue(); - EXPECT_TRUE(dataset->put(key, value)); - } - EXPECT_TRUE(dataset->commit()); - - int count = 0; - typedef typename Dataset::const_iterator Iter; - for (Iter iter = dataset->begin(); iter != dataset->end(); ++iter) { - (void)iter; - ++count; - } - - EXPECT_EQ(kNumExamples, count); -} - -TYPED_TEST(DatasetTest, TestIteratorsPreIncrement) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key1 = this->TestAltKey(); - value_type value1 = this->TestAltValue(); - - string key2 = this->TestKey(); - value_type value2 = this->TestValue(); - - EXPECT_TRUE(dataset->put(key1, value1)); - EXPECT_TRUE(dataset->put(key2, value2)); - EXPECT_TRUE(dataset->commit()); - - typename Dataset::const_iterator iter1 = - dataset->begin(); - - EXPECT_FALSE(dataset->end() == iter1); - - EXPECT_TRUE(this->equals(iter1->key, key1)); - - typename Dataset::const_iterator iter2 = ++iter1; - - EXPECT_FALSE(dataset->end() == iter1); - EXPECT_FALSE(dataset->end() == iter2); - - EXPECT_TRUE(this->equals(iter2->key, key2)); - - typename Dataset::const_iterator iter3 = ++iter2; - - EXPECT_TRUE(dataset->end() == iter3); - - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestIteratorsPostIncrement) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key1 = this->TestAltKey(); - value_type value1 = this->TestAltValue(); - - string key2 = this->TestKey(); - value_type value2 = this->TestValue(); - - EXPECT_TRUE(dataset->put(key1, value1)); - EXPECT_TRUE(dataset->put(key2, value2)); - EXPECT_TRUE(dataset->commit()); - - typename Dataset::const_iterator iter1 = - dataset->begin(); - - EXPECT_FALSE(dataset->end() == iter1); - - EXPECT_TRUE(this->equals(iter1->key, key1)); - - typename Dataset::const_iterator iter2 = iter1++; - - EXPECT_FALSE(dataset->end() == iter1); - EXPECT_FALSE(dataset->end() == iter2); - - EXPECT_TRUE(this->equals(iter2->key, key1)); - EXPECT_TRUE(this->equals(iter1->key, key2)); - - typename Dataset::const_iterator iter3 = iter1++; - - EXPECT_FALSE(dataset->end() == iter3); - EXPECT_TRUE(this->equals(iter3->key, key2)); - EXPECT_TRUE(dataset->end() == iter1); - - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestNewPutPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(dataset->put(key, value)); - - EXPECT_TRUE(dataset->commit()); - - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestNewCommitPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - EXPECT_TRUE(dataset->commit()); - - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestNewGetPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(dataset->put(key, value)); - - EXPECT_TRUE(dataset->commit()); - - value_type new_value; - - EXPECT_TRUE(dataset->get(key, &new_value)); - - EXPECT_TRUE(this->equals(value, new_value)); - - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestNewGetNoCommitFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(dataset->put(key, value)); - - value_type new_value; - - EXPECT_FALSE(dataset->get(key, &new_value)); -} - - -TYPED_TEST(DatasetTest, TestReadWritePutPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::ReadWrite)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(dataset->put(key, value)); - - EXPECT_TRUE(dataset->commit()); - - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestReadWriteCommitPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::ReadWrite)); - - EXPECT_TRUE(dataset->commit()); - - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestReadWriteGetPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(dataset->put(key, value)); - - EXPECT_TRUE(dataset->commit()); - - value_type new_value; - - EXPECT_TRUE(dataset->get(key, &new_value)); - - EXPECT_TRUE(this->equals(value, new_value)); - - dataset->close(); -} - -TYPED_TEST(DatasetTest, TestReadWriteGetNoCommitFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(dataset->put(key, value)); - - value_type new_value; - - EXPECT_FALSE(dataset->get(key, &new_value)); -} - -TYPED_TEST(DatasetTest, TestReadOnlyPutFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - dataset->close(); - - EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_FALSE(dataset->put(key, value)); -} - -TYPED_TEST(DatasetTest, TestReadOnlyCommitFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - dataset->close(); - - EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); - - EXPECT_FALSE(dataset->commit()); -} - -TYPED_TEST(DatasetTest, TestReadOnlyGetPasses) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(dataset->put(key, value)); - - EXPECT_TRUE(dataset->commit()); - - dataset->close(); - - EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); - - value_type new_value; - - EXPECT_TRUE(dataset->get(key, &new_value)); - - EXPECT_TRUE(this->equals(value, new_value)); -} - -TYPED_TEST(DatasetTest, TestReadOnlyGetNoCommitFails) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - - EXPECT_TRUE(dataset->put(key, value)); - - dataset->close(); - - EXPECT_TRUE(dataset->open(name, Dataset::ReadOnly)); - - value_type new_value; - - EXPECT_FALSE(dataset->get(key, &new_value)); -} - -TYPED_TEST(DatasetTest, TestCreateManyItersShortScope) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - EXPECT_TRUE(dataset->put(key, value)); - EXPECT_TRUE(dataset->commit()); - - for (int i = 0; i < 1000; ++i) { - typename Dataset::const_iterator iter = - dataset->begin(); - } -} - -TYPED_TEST(DatasetTest, TestCreateManyItersLongScope) { - UNPACK_TYPES; - - string name = this->DBName(); - shared_ptr > dataset = - DatasetFactory(backend); - EXPECT_TRUE(dataset->open(name, Dataset::New)); - - string key = this->TestKey(); - value_type value = this->TestValue(); - EXPECT_TRUE(dataset->put(key, value)); - EXPECT_TRUE(dataset->commit()); - - vector::const_iterator> iters; - for (int i = 0; i < 1000; ++i) { - iters.push_back(dataset->begin()); - } -} - -#undef UNPACK_TYPES - -} // namespace caffe From 60f26d647ceccea5d0ab0bf85b35b492886bf451 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 16 Oct 2014 13:24:39 -0700 Subject: [PATCH 242/798] SetTotalBytesLimit to the max (2 GB minus 1 byte) --- src/caffe/util/io.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index ffdaeb12c4a..6fa6e68010e 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -17,6 +17,8 @@ #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" +const int kProtoReadBytesLimit = INT_MAX; // Max size of 2 GB minus 1 byte. + namespace caffe { using google::protobuf::io::FileInputStream; @@ -50,7 +52,7 @@ bool ReadProtoFromBinaryFile(const char* filename, Message* proto) { CHECK_NE(fd, -1) << "File not found: " << filename; ZeroCopyInputStream* raw_input = new FileInputStream(fd); CodedInputStream* coded_input = new CodedInputStream(raw_input); - coded_input->SetTotalBytesLimit(1073741824, 536870912); + coded_input->SetTotalBytesLimit(kProtoReadBytesLimit, 536870912); bool success = proto->ParseFromCodedStream(coded_input); From a0ada4fc9e0075d8ba57f128a111fd5e214266c8 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Sat, 1 Nov 2014 21:22:11 -0700 Subject: [PATCH 243/798] Unroll kernels in SoftmaxLayer...from terrible performance to mediocre performance. --- src/caffe/layers/softmax_layer.cu | 48 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/caffe/layers/softmax_layer.cu b/src/caffe/layers/softmax_layer.cu index 292ad2b396a..6b8871a0b20 100644 --- a/src/caffe/layers/softmax_layer.cu +++ b/src/caffe/layers/softmax_layer.cu @@ -25,14 +25,13 @@ __global__ void kernel_channel_max(const int num, const int channels, } template -__global__ void kernel_channel_subtract(const int num, const int channels, - const int spatial_dim, Dtype* data, const Dtype* channel_max) { - CUDA_KERNEL_LOOP(index, num * spatial_dim) { - int n = index / spatial_dim; +__global__ void kernel_channel_subtract(const int count, + const int num, const int channels, + const int spatial_dim, const Dtype* channel_max, Dtype* data) { + CUDA_KERNEL_LOOP(index, count) { + int n = index / channels / spatial_dim; int s = index % spatial_dim; - for (int c = 0; c < channels; ++c) { - data[(n * channels + c) * spatial_dim + s] -= channel_max[index]; - } + data[index] -= channel_max[n * spatial_dim + s]; } } @@ -58,14 +57,13 @@ __global__ void kernel_channel_sum(const int num, const int channels, } template -__global__ void kernel_channel_div(const int num, const int channels, - const int spatial_dim, Dtype* data, const Dtype* channel_sum) { - CUDA_KERNEL_LOOP(index, num * spatial_dim) { - int n = index / spatial_dim; +__global__ void kernel_channel_div(const int count, + const int num, const int channels, + const int spatial_dim, const Dtype* channel_sum, Dtype* data) { + CUDA_KERNEL_LOOP(index, count) { + int n = index / channels / spatial_dim; int s = index % spatial_dim; - for (int c = 0; c < channels; ++c) { - data[(n * channels + c) * spatial_dim + s] /= channel_sum[index]; - } + data[index] /= channel_sum[n * spatial_dim + s]; } } @@ -91,10 +89,11 @@ void SoftmaxLayer::Forward_gpu(const vector*>& bottom, const Dtype* bottom_data = bottom[0]->gpu_data(); Dtype* top_data = top[0]->mutable_gpu_data(); Dtype* scale_data = scale_.mutable_gpu_data(); + int count = bottom[0]->count(); int num = bottom[0]->num(); int channels = bottom[0]->channels(); int spatial_dim = bottom[0]->height() * bottom[0]->width(); - caffe_copy(bottom[0]->count(), bottom_data, top_data); + caffe_copy(count, bottom_data, top_data); // We need to subtract the max to avoid numerical issues, compute the exp, // and then normalize. // compute max @@ -104,9 +103,9 @@ void SoftmaxLayer::Forward_gpu(const vector*>& bottom, scale_data); // subtract // NOLINT_NEXT_LINE(whitespace/operators) - kernel_channel_subtract<<>>(num, channels, spatial_dim, top_data, - scale_data); + kernel_channel_subtract<<>>(count, num, channels, spatial_dim, + scale_data, top_data); // exponentiate // NOLINT_NEXT_LINE(whitespace/operators) kernel_exp<<::Forward_gpu(const vector*>& bottom, scale_data); // divide // NOLINT_NEXT_LINE(whitespace/operators) - kernel_channel_div<<>>(num, channels, spatial_dim, top_data, - scale_data); + kernel_channel_div<<>>(count, num, channels, spatial_dim, + scale_data, top_data); } template @@ -131,6 +130,7 @@ void SoftmaxLayer::Backward_gpu(const vector*>& top, const Dtype* top_data = top[0]->gpu_data(); Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); Dtype* scale_data = scale_.mutable_gpu_data(); + int count = top[0]->count(); int num = top[0]->num(); int channels = top[0]->channels(); int spatial_dim = top[0]->height() * top[0]->width(); @@ -141,9 +141,9 @@ void SoftmaxLayer::Backward_gpu(const vector*>& top, CAFFE_CUDA_NUM_THREADS>>>(num, channels, spatial_dim, top_diff, top_data, scale_data); // NOLINT_NEXT_LINE(whitespace/operators) - kernel_channel_subtract<<>>(num, channels, spatial_dim, bottom_diff, - scale_data); + kernel_channel_subtract<<>>(count, num, channels, spatial_dim, + scale_data, bottom_diff); // elementwise multiplication caffe_gpu_mul(top[0]->count(), bottom_diff, top_data, bottom_diff); } From 89a92b9d7a4b1ecdef69fe5e52f73b362f0ce913 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Sat, 1 Nov 2014 21:37:05 -0700 Subject: [PATCH 244/798] SoftmaxWithLossLayer: use CreateLayer so that a CuDNNSoftmaxLayer is created if available --- include/caffe/loss_layers.hpp | 5 ++--- src/caffe/layers/softmax_loss_layer.cpp | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 13b108afd2d..435013646a9 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -697,8 +697,7 @@ template class SoftmaxWithLossLayer : public LossLayer { public: explicit SoftmaxWithLossLayer(const LayerParameter& param) - : LossLayer(param), - softmax_layer_(new SoftmaxLayer(param)) {} + : LossLayer(param) {} virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); virtual void Reshape(const vector*>& bottom, @@ -751,7 +750,7 @@ class SoftmaxWithLossLayer : public LossLayer { const vector& propagate_down, const vector*>& bottom); /// The internal SoftmaxLayer used to map predictions to a distribution. - shared_ptr > softmax_layer_; + shared_ptr > softmax_layer_; /// prob stores the output probability predictions from the SoftmaxLayer. Blob prob_; /// bottom vector holder used in call to the underlying SoftmaxLayer::Forward diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index db8dd8bb626..dfc41d2da15 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -3,6 +3,7 @@ #include #include "caffe/layer.hpp" +#include "caffe/layer_factory.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/vision_layers.hpp" @@ -12,6 +13,9 @@ template void SoftmaxWithLossLayer::LayerSetUp( const vector*>& bottom, const vector*>& top) { LossLayer::LayerSetUp(bottom, top); + LayerParameter softmax_param(this->layer_param_); + softmax_param.set_type(LayerParameter_LayerType_SOFTMAX); + softmax_layer_.reset(LayerRegistry::CreateLayer(softmax_param)); softmax_bottom_vec_.clear(); softmax_bottom_vec_.push_back(bottom[0]); softmax_top_vec_.clear(); From daa4c5bd7bf02c21e82b1522ca44b2b6049010b5 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Sun, 2 Nov 2014 01:56:19 -0800 Subject: [PATCH 245/798] hdf5_save_nd_dataset takes a const string& (instead of const string) --- include/caffe/util/io.hpp | 10 +++++----- src/caffe/util/io.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index 9c0b4872af6..a01f917abf5 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -150,17 +150,17 @@ void CVMatToDatum(const cv::Mat& cv_img, Datum* datum); template void hdf5_load_nd_dataset_helper( - hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, - Blob* blob); + hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, + Blob* blob); template void hdf5_load_nd_dataset( - hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, - Blob* blob); + hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, + Blob* blob); template void hdf5_save_nd_dataset( - const hid_t file_id, const string dataset_name, const Blob& blob); + const hid_t file_id, const string& dataset_name, const Blob& blob); } // namespace caffe diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 6fa6e68010e..f738e053e86 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -256,7 +256,7 @@ void hdf5_load_nd_dataset(hid_t file_id, const char* dataset_name_, template <> void hdf5_save_nd_dataset( - const hid_t file_id, const string dataset_name, const Blob& blob) { + const hid_t file_id, const string& dataset_name, const Blob& blob) { hsize_t dims[HDF5_NUM_DIMS]; dims[0] = blob.num(); dims[1] = blob.channels(); @@ -269,7 +269,7 @@ void hdf5_save_nd_dataset( template <> void hdf5_save_nd_dataset( - const hid_t file_id, const string dataset_name, const Blob& blob) { + const hid_t file_id, const string& dataset_name, const Blob& blob) { hsize_t dims[HDF5_NUM_DIMS]; dims[0] = blob.num(); dims[1] = blob.channels(); From f4b386537e21ffa6fe128fd8ffd465b5eddc6dee Mon Sep 17 00:00:00 2001 From: Xianjie Chen Date: Thu, 22 Jan 2015 19:27:24 -0800 Subject: [PATCH 246/798] fix bugs by adding const --- matlab/caffe/matcaffe.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/matlab/caffe/matcaffe.cpp b/matlab/caffe/matcaffe.cpp index 3de0f02e1eb..0ab0b00eb23 100644 --- a/matlab/caffe/matcaffe.cpp +++ b/matlab/caffe/matcaffe.cpp @@ -52,7 +52,7 @@ static int init_key = -2; // input and outputs a cell array. static mxArray* do_forward(const mxArray* const bottom) { - vector*>& input_blobs = net_->input_blobs(); + const vector*>& input_blobs = net_->input_blobs(); if (static_cast(mxGetDimensions(bottom)[0]) != input_blobs.size()) { mex_error("Invalid input size"); @@ -112,8 +112,8 @@ static mxArray* do_forward(const mxArray* const bottom) { } static mxArray* do_backward(const mxArray* const top_diff) { - vector*>& output_blobs = net_->output_blobs(); - vector*>& input_blobs = net_->input_blobs(); + const vector*>& output_blobs = net_->output_blobs(); + const vector*>& input_blobs = net_->input_blobs(); if (static_cast(mxGetDimensions(top_diff)[0]) != output_blobs.size()) { mex_error("Invalid input size"); From c44bfb38fb207ff7d5814356c199651b2c18ab88 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 22 Jan 2015 19:54:57 -0800 Subject: [PATCH 247/798] [fix] align pytest for solver with #1728 --- python/caffe/test/test_solver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/caffe/test/test_solver.py b/python/caffe/test/test_solver.py index b78c91f9978..832b75c3219 100644 --- a/python/caffe/test/test_solver.py +++ b/python/caffe/test/test_solver.py @@ -17,7 +17,7 @@ def setUp(self): display: 100 max_iter: 100 snapshot_after_train: false""") f.close() self.solver = caffe.SGDSolver(f.name) - self.solver.net.set_mode_cpu() + caffe.set_mode_cpu() # fill in valid labels self.solver.net.blobs['label'].data[...] = \ np.random.randint(self.num_output, From 47d7cb7b20a7fc4563423ae669c5237e20670206 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 23 Jan 2015 22:46:53 -0800 Subject: [PATCH 248/798] drop dump_network tool Nets are better serialized as a single binaryproto or saved however desired through the Python and MATLAB interfaces. --- tools/dump_network.cpp | 82 ------------------------------------------ 1 file changed, 82 deletions(-) delete mode 100644 tools/dump_network.cpp diff --git a/tools/dump_network.cpp b/tools/dump_network.cpp deleted file mode 100644 index 9cb996ef612..00000000000 --- a/tools/dump_network.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// This program takes in a trained network and an input blob, and then dumps -// all the intermediate blobs produced by the net to individual binary -// files stored in protobuffer binary formats. -// Usage: -// dump_network input_net_param trained_net_param -// input_blob output_prefix 0/1 -// if input_net_param is 'none', we will directly load the network from -// trained_net_param. If the last argv is 1, we will do a forward-backward pass -// before dumping everyting, and also dump the who network. - -#include -#include - -#include "fcntl.h" -#include "google/protobuf/text_format.h" - -#include "caffe/blob.hpp" -#include "caffe/common.hpp" -#include "caffe/filler.hpp" -#include "caffe/net.hpp" -#include "caffe/proto/caffe.pb.h" -#include "caffe/solver.hpp" -#include "caffe/util/io.hpp" - -using boost::shared_ptr; -using caffe::Blob; -using caffe::BlobProto; -using caffe::Caffe; -using caffe::Net; -using caffe::NetParameter; - -int main(int argc, char** argv) { - Caffe::set_mode(Caffe::GPU); - Caffe::set_phase(Caffe::TEST); - - shared_ptr > caffe_net; - if (strcmp(argv[1], "none") == 0) { - // We directly load the net param from trained file - caffe_net.reset(new Net(argv[2])); - } else { - caffe_net.reset(new Net(argv[1])); - } - caffe_net->CopyTrainedLayersFrom(argv[2]); - - std::vector* > input_vec; - shared_ptr > input_blob(new Blob()); - if (strcmp(argv[3], "none") != 0) { - BlobProto input_blob_proto; - ReadProtoFromBinaryFile(argv[3], &input_blob_proto); - input_blob->FromProto(input_blob_proto); - input_vec.push_back(input_blob.get()); - } - - std::string output_prefix(argv[4]); - // Run the network without training. - LOG(ERROR) << "Performing Forward"; - caffe_net->Forward(input_vec); - if (argc > 5 && strcmp(argv[5], "1") == 0) { - LOG(ERROR) << "Performing Backward"; - Caffe::set_phase(Caffe::TRAIN); - caffe_net->Backward(); - // Dump the network - NetParameter output_net_param; - caffe_net->ToProto(&output_net_param, true); - WriteProtoToBinaryFile(output_net_param, - output_prefix + output_net_param.name()); - } - // Now, let's dump all the layers - - const std::vector& blob_names = caffe_net->blob_names(); - const std::vector > >& blobs = caffe_net->blobs(); - for (int blobid = 0; blobid < caffe_net->blobs().size(); ++blobid) { - // Serialize blob - LOG(ERROR) << "Dumping " << blob_names[blobid]; - BlobProto output_blob_proto; - blobs[blobid]->ToProto(&output_blob_proto); - WriteProtoToBinaryFile(output_blob_proto, - output_prefix + blob_names[blobid]); - } - - return 0; -} From 2f869e7426e47d5123ee399704ff386bfdee8387 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Sat, 24 Jan 2015 18:27:15 -0800 Subject: [PATCH 249/798] clarify draw_net.py usage: net prototxt, not caffemodel --- python/draw_net.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/draw_net.py b/python/draw_net.py index ba488294275..abf701572a2 100755 --- a/python/draw_net.py +++ b/python/draw_net.py @@ -11,7 +11,7 @@ def main(argv): if len(argv) != 3: - print 'Usage: %s input_net_proto_file output_image_file' % \ + print 'Usage: %s input_net_prototxt output_image_file' % \ os.path.basename(sys.argv[0]) else: net = caffe_pb2.NetParameter() From 61c63f6d1ed4cd6a3c4b4d9229497fc89c5ef662 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Sat, 24 Jan 2015 18:28:46 -0800 Subject: [PATCH 250/798] [docs] ask install + hardware questions on caffe-users --- docs/installation.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index a42ef5b309c..16e319b4392 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -11,6 +11,8 @@ We have installed Caffe on Ubuntu 14.04, Ubuntu 12.04, OS X 10.9, and OS X 10.8. - [Compilation](#compilation) - [Hardware questions](#hardware_questions) +Ask installation questions on the [caffe-users](https://groups.google.com/forum/#!forum/caffe-users) mailing list. + ## Prerequisites Caffe depends on several software packages. @@ -299,4 +301,4 @@ As a workaround, if you are using Ubuntu 12.04 you can try the following steps t Once installed, check your times against our [reference performance numbers](performance_hardware.html) to make sure everything is configured properly. -Refer to the project's issue tracker for [hardware/compatibility](https://github.com/BVLC/caffe/issues?labels=hardware%2Fcompatibility&page=1&state=open). +Ask hardware questions on the [caffe-users](https://groups.google.com/forum/#!forum/caffe-users) mailing list. From d33fffbd229ad29e06fa294356c4526ea2e82987 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Sun, 25 Jan 2015 16:04:51 -0800 Subject: [PATCH 251/798] [example] lenet early stopping -> mnist examples --- examples/{lenet => mnist}/lenet_stepearly_solver.prototxt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{lenet => mnist}/lenet_stepearly_solver.prototxt (100%) diff --git a/examples/lenet/lenet_stepearly_solver.prototxt b/examples/mnist/lenet_stepearly_solver.prototxt similarity index 100% rename from examples/lenet/lenet_stepearly_solver.prototxt rename to examples/mnist/lenet_stepearly_solver.prototxt From 47e8831ac09c82fb210e8d032a2f770499619540 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Sun, 25 Jan 2015 20:37:52 -0800 Subject: [PATCH 252/798] [pycaffe] de-dupe imports --- python/caffe/__init__.py | 4 ++-- python/caffe/pycaffe.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/python/caffe/__init__.py b/python/caffe/__init__.py index 8dd2464d1c4..acdfc071032 100644 --- a/python/caffe/__init__.py +++ b/python/caffe/__init__.py @@ -1,6 +1,6 @@ from .pycaffe import Net, SGDSolver -from .pycaffe import set_mode_cpu, set_mode_gpu, set_phase_train, set_phase_test -from .pycaffe import set_device +from ._caffe import set_mode_cpu, set_mode_gpu, set_device, \ + set_phase_train, set_phase_test from .classifier import Classifier from .detector import Detector import io diff --git a/python/caffe/pycaffe.py b/python/caffe/pycaffe.py index 8899309ddfd..31dc1f9b001 100644 --- a/python/caffe/pycaffe.py +++ b/python/caffe/pycaffe.py @@ -8,8 +8,6 @@ import numpy as np from ._caffe import Net, SGDSolver -from ._caffe import set_mode_cpu, set_mode_gpu, set_phase_train, set_phase_test -from ._caffe import set_device import caffe.io # We directly update methods from Net here (rather than using composition or From 408133ce4139a95960577e8d36daa16e9dd9e03a Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 27 Jan 2015 10:45:41 -0800 Subject: [PATCH 253/798] document DeconvolutionLayer --- include/caffe/vision_layers.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 646378dea9f..fc178e4c904 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -16,6 +16,10 @@ namespace caffe { +/** + * @brief Abstract base class that factors out the BLAS code common to + * ConvolutionLayer and DeconvolutionLayer. + */ template class BaseConvolutionLayer : public Layer { public: @@ -173,6 +177,20 @@ class ConvolutionLayer : public BaseConvolutionLayer { virtual void compute_output_shape(); }; +/** + * @brief Convolve the input with a bank of learned filters, and (optionally) + * add biases, treating filters and convolution parameters in the + * opposite sense as ConvolutionLayer. + * + * ConvolutionLayer computes each output value by dotting an input window with + * a filter; DeconvolutionLayer multiplies each input value by a filter + * elementwise, and sums over the resulting output windows. In other words, + * DeconvolutionLayer is ConvolutionLayer with the forward and backward passes + * reversed. DeconvolutionLayer reuses ConvolutionParameter for its + * parameters, but they take the opposite sense as in ConvolutionLayer (so + * padding is removed from the output rather than added to the input, and + * stride results in upsampling rather than downsampling). + */ template class DeconvolutionLayer : public BaseConvolutionLayer { public: From 25c2e3fdc7a27ec00893bd0335ac42e53ff2c7aa Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 27 Jan 2015 12:24:39 -0800 Subject: [PATCH 254/798] [test] simple test for DeconvolutionLayer --- src/caffe/test/test_deconvolution_layer.cpp | 158 ++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 src/caffe/test/test_deconvolution_layer.cpp diff --git a/src/caffe/test/test_deconvolution_layer.cpp b/src/caffe/test/test_deconvolution_layer.cpp new file mode 100644 index 00000000000..fc63d5efbe3 --- /dev/null +++ b/src/caffe/test/test_deconvolution_layer.cpp @@ -0,0 +1,158 @@ +#include +#include + +#include "gtest/gtest.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" + +#include "caffe/test/test_caffe_main.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +namespace caffe { + +// Since ConvolutionLayerTest checks the shared conv/deconv code in detail, +// we'll just do a simple forward test and a gradient check. +template +class DeconvolutionLayerTest : public MultiDeviceTest { + typedef typename TypeParam::Dtype Dtype; + + protected: + DeconvolutionLayerTest() + : blob_bottom_(new Blob(2, 3, 6, 4)), + blob_bottom_2_(new Blob(2, 3, 6, 4)), + blob_top_(new Blob()), + blob_top_2_(new Blob()) {} + virtual void SetUp() { + // fill the values + FillerParameter filler_param; + filler_param.set_value(1.); + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + filler.Fill(this->blob_bottom_2_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + + virtual ~DeconvolutionLayerTest() { + delete blob_bottom_; + delete blob_bottom_2_; + delete blob_top_; + delete blob_top_2_; + } + + Blob* const blob_bottom_; + Blob* const blob_bottom_2_; + Blob* const blob_top_; + Blob* const blob_top_2_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +TYPED_TEST_CASE(DeconvolutionLayerTest, TestDtypesAndDevices); + +TYPED_TEST(DeconvolutionLayerTest, TestSetup) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(4); + this->blob_bottom_vec_.push_back(this->blob_bottom_2_); + this->blob_top_vec_.push_back(this->blob_top_2_); + shared_ptr > layer( + new DeconvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 4); + EXPECT_EQ(this->blob_top_->height(), 13); + EXPECT_EQ(this->blob_top_->width(), 9); + EXPECT_EQ(this->blob_top_2_->num(), 2); + EXPECT_EQ(this->blob_top_2_->channels(), 4); + EXPECT_EQ(this->blob_top_2_->height(), 13); + EXPECT_EQ(this->blob_top_2_->width(), 9); + // setting group should not change the shape + convolution_param->set_num_output(3); + convolution_param->set_group(3); + layer.reset(new DeconvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 3); + EXPECT_EQ(this->blob_top_->height(), 13); + EXPECT_EQ(this->blob_top_->width(), 9); + EXPECT_EQ(this->blob_top_2_->num(), 2); + EXPECT_EQ(this->blob_top_2_->channels(), 3); + EXPECT_EQ(this->blob_top_2_->height(), 13); + EXPECT_EQ(this->blob_top_2_->width(), 9); +} + +TYPED_TEST(DeconvolutionLayerTest, TestSimpleDeconvolution) { + typedef typename TypeParam::Dtype Dtype; + this->blob_bottom_vec_.push_back(this->blob_bottom_2_); + this->blob_top_vec_.push_back(this->blob_top_2_); + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(4); + convolution_param->mutable_weight_filler()->set_type("constant"); + convolution_param->mutable_weight_filler()->set_value(1); + convolution_param->mutable_bias_filler()->set_type("constant"); + convolution_param->mutable_bias_filler()->set_value(0.1); + shared_ptr > layer( + new DeconvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + // constant-fill the bottom blobs + FillerParameter filler_param; + filler_param.set_value(1.); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + filler.Fill(this->blob_bottom_2_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); + // simply check that accumulation works with overlapping filters + const Dtype* top_data = this->blob_top_->cpu_data(); + for (int n = 0; n < this->blob_top_->num(); ++n) { + for (int c = 0; c < this->blob_top_->channels(); ++c) { + for (int h = 0; h < this->blob_top_->height(); ++h) { + for (int w = 0; w < this->blob_top_->width(); ++w) { + Dtype expected = 3.1; + bool h_overlap = h % 2 == 0 && h > 0 + && h < this->blob_top_->height() - 1; + bool w_overlap = w % 2 == 0 && w > 0 + && w < this->blob_top_->width() - 1; + if (h_overlap && w_overlap) { + expected += 9; + } else if (h_overlap || w_overlap) { + expected += 3; + } + EXPECT_NEAR(top_data[this->blob_top_->offset(n, c, h, w)], + expected, 1e-4); + } + } + } + } +} + +TYPED_TEST(DeconvolutionLayerTest, TestGradient) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + this->blob_bottom_vec_.push_back(this->blob_bottom_2_); + this->blob_top_vec_.push_back(this->blob_top_2_); + convolution_param->set_kernel_size(2); + convolution_param->set_stride(1); + convolution_param->set_num_output(1); + convolution_param->mutable_weight_filler()->set_type("gaussian"); + convolution_param->mutable_bias_filler()->set_type("gaussian"); + DeconvolutionLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_); +} + +} // namespace caffe From 41b754c4e2154f40952d123599f9fa04eda0c3e3 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 27 Jan 2015 13:09:32 -0800 Subject: [PATCH 255/798] document the loss_param options to SoftmaxWithLossLayer --- include/caffe/loss_layers.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 321f7068273..ca91579d51c 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -696,6 +696,14 @@ template class SoftmaxLayer; template class SoftmaxWithLossLayer : public LossLayer { public: + /** + * @param param provides LossParameter loss_param, with options: + * - ignore_label (optional) + * Specify a label value that should be ignored when computing the loss. + * - normalize (optional, default true) + * If true, the loss is normalized by the number of (nonignored) labels + * present; otherwise the loss is simply summed over spatial locations. + */ explicit SoftmaxWithLossLayer(const LayerParameter& param) : LossLayer(param), softmax_layer_(new SoftmaxLayer(param)) {} From f1eada76b40729d379669480b6db60eb7e01f6ce Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Tue, 27 Jan 2015 13:27:48 -0800 Subject: [PATCH 256/798] [test] gradient checks for softmax ignore_label and normalize: false --- .../test/test_softmax_with_loss_layer.cpp | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/caffe/test/test_softmax_with_loss_layer.cpp b/src/caffe/test/test_softmax_with_loss_layer.cpp index badda3b5503..1498d5c5ce1 100644 --- a/src/caffe/test/test_softmax_with_loss_layer.cpp +++ b/src/caffe/test/test_softmax_with_loss_layer.cpp @@ -3,6 +3,7 @@ #include #include +#include "boost/scoped_ptr.hpp" #include "gtest/gtest.h" #include "caffe/blob.hpp" @@ -13,6 +14,8 @@ #include "caffe/test/test_caffe_main.hpp" #include "caffe/test/test_gradient_check_util.hpp" +using boost::scoped_ptr; + namespace caffe { template @@ -50,7 +53,6 @@ class SoftmaxWithLossLayerTest : public MultiDeviceTest { TYPED_TEST_CASE(SoftmaxWithLossLayerTest, TestDtypesAndDevices); - TYPED_TEST(SoftmaxWithLossLayerTest, TestGradient) { typedef typename TypeParam::Dtype Dtype; LayerParameter layer_param; @@ -61,4 +63,48 @@ TYPED_TEST(SoftmaxWithLossLayerTest, TestGradient) { this->blob_top_vec_, 0); } +TYPED_TEST(SoftmaxWithLossLayerTest, TestForwardIgnoreLabel) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter layer_param; + layer_param.mutable_loss_param()->set_normalize(false); + // First, compute the loss with all labels + scoped_ptr > layer( + new SoftmaxWithLossLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); + Dtype full_loss = this->blob_top_loss_->cpu_data()[0]; + // Now, accumulate the loss, ignoring each label in {0, ..., 4} in turn. + Dtype accum_loss = 0; + for (int label = 0; label < 5; ++label) { + layer_param.mutable_loss_param()->set_ignore_label(label); + layer.reset(new SoftmaxWithLossLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + layer->Forward(this->blob_bottom_vec_, this->blob_top_vec_); + accum_loss += this->blob_top_loss_->cpu_data()[0]; + } + // Check that each label was included all but once. + EXPECT_NEAR(4 * full_loss, accum_loss, 1e-4); +} + +TYPED_TEST(SoftmaxWithLossLayerTest, TestGradientIgnoreLabel) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter layer_param; + // labels are in {0, ..., 4}, so we'll ignore about a fifth of them + layer_param.mutable_loss_param()->set_ignore_label(0); + SoftmaxWithLossLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2, 1701); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); +} + +TYPED_TEST(SoftmaxWithLossLayerTest, TestGradientUnnormalized) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter layer_param; + layer_param.mutable_loss_param()->set_normalize(false); + SoftmaxWithLossLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2, 1701); + checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_, + this->blob_top_vec_, 0); +} + } // namespace caffe From 4cc8195d82f13391545b90c9c61baaca39b6df84 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 29 Jan 2015 09:26:12 -0800 Subject: [PATCH 257/798] [docs] send API link to class list --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index ccc8f750eef..bf1d9c3c78b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -46,7 +46,7 @@ Tested on Ubuntu, Red Hat, OS X. BVLC suggests a standard distribution format for Caffe models, and provides trained models. * [Developing & Contributing](/development.html)
Guidelines for development and contributing to Caffe. -* [API Documentation](/doxygen/)
+* [API Documentation](/doxygen/annotated.html)
Developer documentation automagically generated from code comments. ### Examples From 1f7c3dea034ef19acd1addf5aa8f4c2b94bc358c Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 29 Jan 2015 10:53:44 -0800 Subject: [PATCH 258/798] [docs] add check mode hint to CPU-only mode error --- include/caffe/util/device_alternate.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/caffe/util/device_alternate.hpp b/include/caffe/util/device_alternate.hpp index 3df28a49ac3..1a33b947991 100644 --- a/include/caffe/util/device_alternate.hpp +++ b/include/caffe/util/device_alternate.hpp @@ -7,7 +7,7 @@ // Stub out GPU calls as unavailable. -#define NO_GPU LOG(FATAL) << "CPU-only Mode: cannot make GPU call." +#define NO_GPU LOG(FATAL) << "Cannot make GPU call in CPU-only mode: check mode setting." #define STUB_GPU(classname) \ template \ From 2a43133ce73678d633d68be4907a26a044e84176 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 24 Sep 2014 15:52:14 -0700 Subject: [PATCH 259/798] Enhancements for debug_info to display more information. Now displays for: -net inputs -test nets -params in ForwardDebugInfo --- include/caffe/net.hpp | 3 +++ src/caffe/net.cpp | 26 ++++++++++++++++++++++++++ src/caffe/solver.cpp | 1 + 3 files changed, 30 insertions(+) diff --git a/include/caffe/net.hpp b/include/caffe/net.hpp index bbb220eb00d..2709d87ec4e 100644 --- a/include/caffe/net.hpp +++ b/include/caffe/net.hpp @@ -194,6 +194,8 @@ class Net { void AppendParam(const NetParameter& param, const int layer_id, const int param_id); + /// @brief Helper for displaying debug info in Forward about input Blobs. + void InputDebugInfo(const int layer_id); /// @brief Helper for displaying debug info in Forward. void ForwardDebugInfo(const int layer_id); /// @brief Helper for displaying debug info in Backward. @@ -226,6 +228,7 @@ class Net { /// Vector of weight in the loss (or objective) function of each net blob, /// indexed by blob_id. vector blob_loss_weights_; + vector > param_id_vecs_; vector param_owners_; vector param_display_names_; vector > param_layer_indices_; diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 47fc8446064..692351fb7d2 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -58,6 +58,7 @@ void Net::Init(const NetParameter& in_param) { bottom_vecs_.resize(param.layers_size()); top_vecs_.resize(param.layers_size()); bottom_id_vecs_.resize(param.layers_size()); + param_id_vecs_.resize(param.layers_size()); top_id_vecs_.resize(param.layers_size()); bottom_need_backward_.resize(param.layers_size()); for (int layer_id = 0; layer_id < param.layers_size(); ++layer_id) { @@ -416,6 +417,7 @@ void Net::AppendParam(const NetParameter& param, const int layer_id, } const int net_param_id = params_.size(); params_.push_back(layers_[layer_id]->blobs()[param_id]); + param_id_vecs_[layer_id].push_back(net_param_id); param_layer_indices_.push_back(make_pair(layer_id, param_id)); if (!param_size || !param_name.size() || (param_name.size() && param_names_index_.find(param_name) == param_names_index_.end())) { @@ -503,6 +505,11 @@ Dtype Net::ForwardFromTo(int start, int end) { CHECK_GE(start, 0); CHECK_LT(end, layers_.size()); Dtype loss = 0; + if (debug_info_) { + for (int i = 0; i < net_input_blobs_.size(); ++i) { + InputDebugInfo(i); + } + } for (int i = start; i <= end; ++i) { // LOG(ERROR) << "Forwarding " << layer_names_[i]; layers_[i]->Reshape(bottom_vecs_[i], top_vecs_[i]); @@ -577,6 +584,15 @@ void Net::BackwardFromTo(int start, int end) { } } +template +void Net::InputDebugInfo(const int input_id) { + const Blob& blob = *net_input_blobs_[input_id]; + const string& blob_name = blob_names_[net_input_blob_indices_[input_id]]; + const Dtype data_abs_val_mean = blob.asum_data() / blob.count(); + LOG(INFO) << " [Forward] " + << "Input " << blob_name << " data: " << data_abs_val_mean; +} + template void Net::ForwardDebugInfo(const int layer_id) { for (int top_id = 0; top_id < top_vecs_[layer_id].size(); ++top_id) { @@ -587,6 +603,16 @@ void Net::ForwardDebugInfo(const int layer_id) { << "Layer " << layer_names_[layer_id] << ", top blob " << blob_name << " data: " << data_abs_val_mean; } + for (int param_id = 0; param_id < layers_[layer_id]->blobs().size(); + ++param_id) { + const Blob& blob = *layers_[layer_id]->blobs()[param_id]; + const int net_param_id = param_id_vecs_[layer_id][param_id]; + const string& blob_name = param_display_names_[net_param_id]; + const Dtype data_abs_val_mean = blob.asum_data() / blob.count(); + LOG(INFO) << " [Forward] " + << "Layer " << layer_names_[layer_id] << ", param blob " << blob_name + << " data: " << data_abs_val_mean; + } } template diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 3fa0e2d14b7..100cb357749 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -154,6 +154,7 @@ void Solver::InitTestNets() { LOG(INFO) << "Creating test net (#" << i << ") specified by " << sources[i]; test_nets_[i].reset(new Net(net_params[i])); + test_nets_[i]->set_debug_info(param_.debug_info()); } } From cfaadf61a5f082ee396354b51aa7fd8dda745750 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 6 Oct 2014 23:08:38 -0700 Subject: [PATCH 260/798] Blob: add sumsq_{data,diff} methods --- include/caffe/blob.hpp | 4 +++ src/caffe/blob.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/include/caffe/blob.hpp b/include/caffe/blob.hpp index ef10aea53f0..d425e3857e3 100644 --- a/include/caffe/blob.hpp +++ b/include/caffe/blob.hpp @@ -106,6 +106,10 @@ class Blob { Dtype asum_data() const; /// @brief Compute the sum of absolute values (L1 norm) of the diff. Dtype asum_diff() const; + /// @brief Compute the sum of squares (L2 norm squared) of the data. + Dtype sumsq_data() const; + /// @brief Compute the sum of squares (L2 norm squared) of the diff. + Dtype sumsq_diff() const; /** * @brief Set the data_ shared_ptr to point to the SyncedMemory holding the diff --git a/src/caffe/blob.cpp b/src/caffe/blob.cpp index cfffc379eb1..3b72ce0c8d0 100644 --- a/src/caffe/blob.cpp +++ b/src/caffe/blob.cpp @@ -205,6 +205,80 @@ Dtype Blob::asum_diff() const { return 0; } +template <> unsigned int Blob::sumsq_data() const { + NOT_IMPLEMENTED; + return 0; +} + +template <> int Blob::sumsq_data() const { + NOT_IMPLEMENTED; + return 0; +} + +template +Dtype Blob::sumsq_data() const { + Dtype sumsq; + const Dtype* data; + if (!data_) { return 0; } + switch (data_->head()) { + case SyncedMemory::HEAD_AT_CPU: + data = cpu_data(); + sumsq = caffe_cpu_dot(count_, data, data); + break; + case SyncedMemory::HEAD_AT_GPU: + case SyncedMemory::SYNCED: +#ifndef CPU_ONLY + data = gpu_data(); + caffe_gpu_dot(count_, data, data, &sumsq); +#else + NO_GPU; +#endif + break; + case SyncedMemory::UNINITIALIZED: + return 0; + default: + LOG(FATAL) << "Unknown SyncedMemory head state: " << data_->head(); + } + return sumsq; +} + +template <> unsigned int Blob::sumsq_diff() const { + NOT_IMPLEMENTED; + return 0; +} + +template <> int Blob::sumsq_diff() const { + NOT_IMPLEMENTED; + return 0; +} + +template +Dtype Blob::sumsq_diff() const { + Dtype sumsq; + const Dtype* diff; + if (!diff_) { return 0; } + switch (diff_->head()) { + case SyncedMemory::HEAD_AT_CPU: + diff = cpu_diff(); + sumsq = caffe_cpu_dot(count_, diff, diff); + break; + case SyncedMemory::HEAD_AT_GPU: + case SyncedMemory::SYNCED: +#ifndef CPU_ONLY + diff = gpu_diff(); + caffe_gpu_dot(count_, diff, diff, &sumsq); + break; +#else + NO_GPU; +#endif + case SyncedMemory::UNINITIALIZED: + return 0; + default: + LOG(FATAL) << "Unknown SyncedMemory head state: " << data_->head(); + } + return sumsq; +} + template void Blob::CopyFrom(const Blob& source, bool copy_diff, bool reshape) { if (num_ != source.num() || channels_ != source.channels() || From 705abfa69f242c4345372e06e3686c3887890dd3 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 29 Jan 2015 19:07:12 -0800 Subject: [PATCH 261/798] Add BlobMathTest with unit tests for sumsq and asum --- src/caffe/test/test_blob.cpp | 113 +++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/src/caffe/test/test_blob.cpp b/src/caffe/test/test_blob.cpp index adf7a4d38e9..c619ad19f11 100644 --- a/src/caffe/test/test_blob.cpp +++ b/src/caffe/test/test_blob.cpp @@ -54,4 +54,117 @@ TYPED_TEST(BlobSimpleTest, TestReshape) { EXPECT_EQ(this->blob_->count(), 120); } +template +class BlobMathTest : public MultiDeviceTest { + typedef typename TypeParam::Dtype Dtype; + protected: + BlobMathTest() + : blob_(new Blob(2, 3, 4, 5)) {} + virtual ~BlobMathTest() { delete blob_; } + Blob* const blob_; +}; + +TYPED_TEST_CASE(BlobMathTest, TestDtypesAndDevices); + +TYPED_TEST(BlobMathTest, TestSumOfSquares) { + typedef typename TypeParam::Dtype Dtype; + + // Uninitialized Blob should have sum of squares == 0. + EXPECT_EQ(0, this->blob_->sumsq_data()); + EXPECT_EQ(0, this->blob_->sumsq_diff()); + FillerParameter filler_param; + filler_param.set_min(-3); + filler_param.set_max(3); + UniformFiller filler(filler_param); + filler.Fill(this->blob_); + Dtype expected_sumsq = 0; + const Dtype* data = this->blob_->cpu_data(); + for (int i = 0; i < this->blob_->count(); ++i) { + expected_sumsq += data[i] * data[i]; + } + // Do a mutable access on the current device, + // so that the sumsq computation is done on that device. + // (Otherwise, this would only check the CPU sumsq implementation.) + switch (TypeParam::device) { + case Caffe::CPU: + this->blob_->mutable_cpu_data(); + break; + case Caffe::GPU: + this->blob_->mutable_gpu_data(); + break; + default: + LOG(FATAL) << "Unknown device: " << TypeParam::device; + } + EXPECT_FLOAT_EQ(expected_sumsq, this->blob_->sumsq_data()); + EXPECT_EQ(0, this->blob_->sumsq_diff()); + + // Check sumsq_diff too. + const Dtype kDiffScaleFactor = 7; + caffe_cpu_scale(this->blob_->count(), kDiffScaleFactor, data, + this->blob_->mutable_cpu_diff()); + switch (TypeParam::device) { + case Caffe::CPU: + this->blob_->mutable_cpu_diff(); + break; + case Caffe::GPU: + this->blob_->mutable_gpu_diff(); + break; + default: + LOG(FATAL) << "Unknown device: " << TypeParam::device; + } + EXPECT_FLOAT_EQ(expected_sumsq, this->blob_->sumsq_data()); + EXPECT_FLOAT_EQ(expected_sumsq * kDiffScaleFactor * kDiffScaleFactor, + this->blob_->sumsq_diff()); +} + +TYPED_TEST(BlobMathTest, TestAsum) { + typedef typename TypeParam::Dtype Dtype; + + // Uninitialized Blob should have sum of squares == 0. + EXPECT_EQ(0, this->blob_->asum_data()); + EXPECT_EQ(0, this->blob_->asum_diff()); + FillerParameter filler_param; + filler_param.set_min(-3); + filler_param.set_max(3); + UniformFiller filler(filler_param); + filler.Fill(this->blob_); + Dtype expected_asum = 0; + const Dtype* data = this->blob_->cpu_data(); + for (int i = 0; i < this->blob_->count(); ++i) { + expected_asum += std::fabs(data[i]); + } + // Do a mutable access on the current device, + // so that the asum computation is done on that device. + // (Otherwise, this would only check the CPU asum implementation.) + switch (TypeParam::device) { + case Caffe::CPU: + this->blob_->mutable_cpu_data(); + break; + case Caffe::GPU: + this->blob_->mutable_gpu_data(); + break; + default: + LOG(FATAL) << "Unknown device: " << TypeParam::device; + } + EXPECT_FLOAT_EQ(expected_asum, this->blob_->asum_data()); + EXPECT_EQ(0, this->blob_->asum_diff()); + + // Check asum_diff too. + const Dtype kDiffScaleFactor = 7; + caffe_cpu_scale(this->blob_->count(), kDiffScaleFactor, data, + this->blob_->mutable_cpu_diff()); + switch (TypeParam::device) { + case Caffe::CPU: + this->blob_->mutable_cpu_diff(); + break; + case Caffe::GPU: + this->blob_->mutable_gpu_diff(); + break; + default: + LOG(FATAL) << "Unknown device: " << TypeParam::device; + } + EXPECT_FLOAT_EQ(expected_asum, this->blob_->asum_data()); + EXPECT_FLOAT_EQ(expected_asum * kDiffScaleFactor, this->blob_->asum_diff()); +} + } // namespace caffe From 91ce7c0603fad74a391eab1e7a7cc3cfedda909c Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 6 Oct 2014 23:46:05 -0700 Subject: [PATCH 262/798] debug_info: print param (and gradient) stats for whole Net after Backward --- src/caffe/net.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 692351fb7d2..e827a067ea1 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -705,6 +705,21 @@ void Net::BackwardTo(int end) { template void Net::Backward() { BackwardFromTo(layers_.size() - 1, 0); + if (debug_info_) { + Dtype asum_data = 0, asum_diff = 0, sumsq_data = 0, sumsq_diff = 0; + for (int i = 0; i < params_.size(); ++i) { + if (param_owners_[i] >= 0) { continue; } + asum_data += params_[i]->asum_data(); + asum_diff += params_[i]->asum_diff(); + sumsq_data += params_[i]->sumsq_data(); + sumsq_diff += params_[i]->sumsq_diff(); + } + const Dtype l2norm_data = std::sqrt(sumsq_data); + const Dtype l2norm_diff = std::sqrt(sumsq_diff); + LOG(ERROR) << " [Backward] All net params (data, diff): " + << "L1 norm = (" << asum_data << ", " << asum_diff << "); " + << "L2 norm = (" << l2norm_data << ", " << l2norm_diff << ")"; + } } template From 3519d05283424730f300742d52f617c190313824 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 19 Jan 2015 11:52:04 -0800 Subject: [PATCH 263/798] debug_info in NetParameter so it can be enabled outside training --- src/caffe/net.cpp | 3 +-- src/caffe/proto/caffe.proto | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index e827a067ea1..4350e056085 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -218,10 +218,9 @@ void Net::Init(const NetParameter& in_param) { layer_names_index_[layer_names_[layer_id]] = layer_id; } GetLearningRateAndWeightDecay(); + debug_info_ = param.debug_info(); LOG(INFO) << "Network initialization done."; LOG(INFO) << "Memory required for data: " << memory_used_ * sizeof(Dtype); - // Don't display debug info by default. - debug_info_ = false; } template diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index d6eec02087b..d65ef787a4c 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -60,6 +60,10 @@ message NetParameter { // Some layers may be included/excluded depending on this state and the states // specified in the layers' include and exclude fields. optional NetState state = 6; + + // Print debugging information about results while running Net::Forward, + // Net::Backward, and Net::Update. + optional bool debug_info = 7 [default = false]; } // NOTE From 8b9647223346a2528804cb5bc8943f2065846d7d Mon Sep 17 00:00:00 2001 From: Andre Ambrosio Boechat Date: Fri, 30 Jan 2015 13:57:31 -0200 Subject: [PATCH 264/798] Brief explanation of SLICE layer's attributes * A sample code was added. * `slice_dim` and `slice_point` attributes were explained. --- docs/tutorial/layers.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/tutorial/layers.md b/docs/tutorial/layers.md index 5f8f519cdc4..34bb48050e8 100644 --- a/docs/tutorial/layers.md +++ b/docs/tutorial/layers.md @@ -451,6 +451,26 @@ The `CONCAT` layer is a utility layer that concatenates its multiple input blobs The `SLICE` layer is a utility layer that slices an input layer to multiple output layers along a given dimension (currently num or channel only) with given slice indices. +* Sample + + layers { + name: "slicer_label" + type: SLICE + bottom: "label" + ## Example of label with a shape N x 3 x 1 x 1 + top: "label1" + top: "label2" + top: "label3" + slice_param { + slice_dim: 1 + slice_point: 1 + slice_point: 2 + } + } + +`slice_dim` indicates the target dimension and can assume only two values: 0 for num or 1 for channel; `slice_point` indicates indexes in the selected dimension (the number of indexes must be equal to the number of top blobs minus one). + + #### Elementwise Operations `ELTWISE` From 75d0e16be912a8dd23eddd8756ee0d278c66d6ab Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 30 Jan 2015 11:25:31 -0800 Subject: [PATCH 265/798] lint 1f7c3de --- include/caffe/util/device_alternate.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/caffe/util/device_alternate.hpp b/include/caffe/util/device_alternate.hpp index 1a33b947991..4d731e26199 100644 --- a/include/caffe/util/device_alternate.hpp +++ b/include/caffe/util/device_alternate.hpp @@ -7,7 +7,7 @@ // Stub out GPU calls as unavailable. -#define NO_GPU LOG(FATAL) << "Cannot make GPU call in CPU-only mode: check mode setting." +#define NO_GPU LOG(FATAL) << "Cannot use GPU in CPU-only Caffe: check mode." #define STUB_GPU(classname) \ template \ From 33348217a7546ad63a6549f3469b2c49e09f4d31 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Mon, 2 Feb 2015 09:45:51 -0800 Subject: [PATCH 266/798] fix GoogLeNet license overwritten by back-merge (see #1650) --- models/bvlc_googlenet/readme.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/models/bvlc_googlenet/readme.md b/models/bvlc_googlenet/readme.md index 8a3bbec4f8b..2e22dfcf59a 100644 --- a/models/bvlc_googlenet/readme.md +++ b/models/bvlc_googlenet/readme.md @@ -2,7 +2,7 @@ name: BVLC GoogleNet Model caffemodel: bvlc_googlenet.caffemodel caffemodel_url: http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel -license: non-commercial +license: unrestricted sha1: 405fc5acd08a3bb12de8ee5e23a96bec22f08204 caffe_commit: bc614d1bd91896e3faceaf40b23b72dab47d44f5 gist_id: 866e2aa1fd707b89b913 @@ -30,6 +30,4 @@ This model was trained by Sergio Guadarrama @sguada ## License -The data used to train this model comes from the ImageNet project, which distributes its database to researchers who agree to a following term of access: -"Researcher shall use the Database only for non-commercial research and educational purposes." -Accordingly, this model is distributed under a non-commercial license. +This model is released for unrestricted use. From 53924a76b66faad2831205c3694e640eccb15fb5 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 2 Feb 2015 12:38:43 -0800 Subject: [PATCH 267/798] add space after "Loading mean file from" --- matlab/caffe/matcaffe.cpp | 2 +- src/caffe/data_transformer.cpp | 2 +- src/caffe/layers/window_data_layer.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/matlab/caffe/matcaffe.cpp b/matlab/caffe/matcaffe.cpp index 0ab0b00eb23..fd8397e7ff2 100644 --- a/matlab/caffe/matcaffe.cpp +++ b/matlab/caffe/matcaffe.cpp @@ -343,7 +343,7 @@ static void read_mean(MEX_ARGS) { } const string& mean_file = mxArrayToString(prhs[0]); Blob data_mean; - LOG(INFO) << "Loading mean file from" << mean_file; + LOG(INFO) << "Loading mean file from: " << mean_file; BlobProto blob_proto; bool result = ReadProtoFromBinaryFile(mean_file.c_str(), &blob_proto); if (!result) { diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 209dc0349ad..3d2c78f8ec2 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -19,7 +19,7 @@ DataTransformer::DataTransformer(const TransformationParameter& param) CHECK_EQ(param_.mean_value_size(), 0) << "Cannot specify mean_file and mean_value at the same time"; const string& mean_file = param.mean_file(); - LOG(INFO) << "Loading mean file from" << mean_file; + LOG(INFO) << "Loading mean file from: " << mean_file; BlobProto blob_proto; ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); data_mean_.FromProto(blob_proto); diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 6287b385dc5..83372e074f5 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -189,7 +189,7 @@ void WindowDataLayer::DataLayerSetUp(const vector*>& bottom, if (has_mean_file_) { const string& mean_file = this->transform_param_.mean_file(); - LOG(INFO) << "Loading mean file from" << mean_file; + LOG(INFO) << "Loading mean file from: " << mean_file; BlobProto blob_proto; ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); data_mean_.FromProto(blob_proto); From b6f9dc8f864ebb9cd63398da4de83493e81b5b54 Mon Sep 17 00:00:00 2001 From: Pannous Date: Fri, 30 Jan 2015 13:38:48 +0100 Subject: [PATCH 268/798] fixed small bug: output label_file -> label_filename --- examples/siamese/convert_mnist_siamese_data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/siamese/convert_mnist_siamese_data.cpp b/examples/siamese/convert_mnist_siamese_data.cpp index 400d15a2705..71c56a0ae61 100644 --- a/examples/siamese/convert_mnist_siamese_data.cpp +++ b/examples/siamese/convert_mnist_siamese_data.cpp @@ -36,7 +36,7 @@ void convert_dataset(const char* image_filename, const char* label_filename, std::ifstream image_file(image_filename, std::ios::in | std::ios::binary); std::ifstream label_file(label_filename, std::ios::in | std::ios::binary); CHECK(image_file) << "Unable to open file " << image_filename; - CHECK(label_file) << "Unable to open file " << label_file; + CHECK(label_file) << "Unable to open file " << label_filename; // Read the magic and the meta data uint32_t magic; uint32_t num_items; From 648aed72acf1c506009ddb33d8cace40b75e176e Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Wed, 4 Feb 2015 10:15:21 -0800 Subject: [PATCH 269/798] fix Nesterov typo found by @bamos --- docs/tutorial/solver.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/solver.md b/docs/tutorial/solver.md index 8884ea0e1e8..17f793ef778 100644 --- a/docs/tutorial/solver.md +++ b/docs/tutorial/solver.md @@ -6,7 +6,7 @@ title: Solver / Model Optimization The solver orchestrates model optimization by coordinating the network's forward inference and backward gradients to form parameter updates that attempt to improve the loss. The responsibilities of learning are divided between the Solver for overseeing the optimization and generating parameter updates and the Net for yielding loss and gradients. -The Caffe solvers are Stochastic Gradient Descent (SGD), Adaptive Gradient (ADAGRAD), and Nesterov's Accelerated Gradient (NAG). +The Caffe solvers are Stochastic Gradient Descent (SGD), Adaptive Gradient (ADAGRAD), and Nesterov's Accelerated Gradient (NESTEROV). The solver @@ -126,7 +126,7 @@ Note that in practice, for weights $$ W \in \mathcal{R}^d $$, AdaGrad implementa ### NAG -**Nesterov's accelerated gradient** (`solver_type: NAG`) was proposed by Nesterov [1] as an "optimal" method of convex optimization, achieving a convergence rate of $$ \mathcal{O}(1/t^2) $$ rather than the $$ \mathcal{O}(1/t) $$. +**Nesterov's accelerated gradient** (`solver_type: NESTEROV`) was proposed by Nesterov [1] as an "optimal" method of convex optimization, achieving a convergence rate of $$ \mathcal{O}(1/t^2) $$ rather than the $$ \mathcal{O}(1/t) $$. Though the required assumptions to achieve the $$ \mathcal{O}(1/t^2) $$ convergence typically will not hold for deep networks trained with Caffe (e.g., due to non-smoothness and non-convexity), in practice NAG can be a very effective method for optimizing certain types of deep learning architectures, as demonstrated for deep MNIST autoencoders by Sutskever et al. [2]. The weight update formulas look very similar to the SGD updates given above: From 3b13846486875be2911716bcd1947dca71a97817 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 7 Jan 2015 20:41:09 -0800 Subject: [PATCH 270/798] Layer type is a string --- include/caffe/common_layers.hpp | 40 +-- include/caffe/data_layers.hpp | 28 +- include/caffe/layer.hpp | 27 +- include/caffe/layer_factory.hpp | 52 ++-- include/caffe/loss_layers.hpp | 34 +-- include/caffe/neuron_layers.hpp | 39 +-- include/caffe/util/upgrade_proto.hpp | 2 +- include/caffe/vision_layers.hpp | 22 +- src/caffe/layer_factory.cpp | 12 +- src/caffe/layers/absval_layer.cpp | 5 +- src/caffe/layers/accuracy_layer.cpp | 3 +- src/caffe/layers/argmax_layer.cpp | 2 +- src/caffe/layers/bnll_layer.cpp | 3 +- src/caffe/layers/concat_layer.cpp | 3 +- src/caffe/layers/contrastive_loss_layer.cpp | 3 +- src/caffe/layers/conv_layer.cpp | 1 + src/caffe/layers/data_layer.cpp | 2 +- src/caffe/layers/deconv_layer.cpp | 3 +- src/caffe/layers/dropout_layer.cpp | 3 +- src/caffe/layers/dummy_data_layer.cpp | 3 +- src/caffe/layers/eltwise_layer.cpp | 3 +- src/caffe/layers/euclidean_loss_layer.cpp | 3 +- src/caffe/layers/exp_layer.cpp | 3 +- src/caffe/layers/flatten_layer.cpp | 3 +- src/caffe/layers/hdf5_data_layer.cpp | 3 +- src/caffe/layers/hdf5_output_layer.cpp | 3 +- src/caffe/layers/hinge_loss_layer.cpp | 5 +- src/caffe/layers/im2col_layer.cpp | 3 +- src/caffe/layers/image_data_layer.cpp | 3 +- src/caffe/layers/infogain_loss_layer.cpp | 6 +- src/caffe/layers/inner_product_layer.cpp | 3 +- src/caffe/layers/lrn_layer.cpp | 3 +- src/caffe/layers/memory_data_layer.cpp | 3 +- .../multinomial_logistic_loss_layer.cpp | 5 +- src/caffe/layers/mvn_layer.cpp | 3 +- src/caffe/layers/pooling_layer.cpp | 1 - src/caffe/layers/power_layer.cpp | 3 +- src/caffe/layers/relu_layer.cpp | 1 - .../sigmoid_cross_entropy_loss_layer.cpp | 5 +- .../sigmoid_cross_entropy_loss_layer.cu | 2 +- src/caffe/layers/silence_layer.cpp | 3 +- src/caffe/layers/slice_layer.cpp | 3 +- src/caffe/layers/softmax_layer.cpp | 1 + src/caffe/layers/softmax_loss_layer.cpp | 6 +- src/caffe/layers/split_layer.cpp | 5 +- src/caffe/layers/threshold_layer.cpp | 3 +- src/caffe/layers/window_data_layer.cpp | 3 +- src/caffe/proto/caffe.proto | 54 +--- src/caffe/test/test_gradient_based_solver.cpp | 6 +- src/caffe/test/test_net.cpp | 258 +++++++++--------- src/caffe/test/test_protobuf.cpp | 2 +- src/caffe/test/test_solver.cpp | 8 +- src/caffe/test/test_split_layer.cpp | 194 ++++++------- src/caffe/test/test_upgrade_proto.cpp | 106 +++---- src/caffe/util/insert_splits.cpp | 2 +- src/caffe/util/upgrade_proto.cpp | 74 ++--- 56 files changed, 487 insertions(+), 592 deletions(-) diff --git a/include/caffe/common_layers.hpp b/include/caffe/common_layers.hpp index 9718b825b14..3a5ccd2180e 100644 --- a/include/caffe/common_layers.hpp +++ b/include/caffe/common_layers.hpp @@ -43,9 +43,7 @@ class ArgMaxLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_ARGMAX; - } + virtual inline const char* type() const { return "ArgMax"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -86,9 +84,7 @@ class ConcatLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_CONCAT; - } + virtual inline const char* type() const { return "Concat"; } virtual inline int MinBottomBlobs() const { return 2; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -166,9 +162,7 @@ class EltwiseLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_ELTWISE; - } + virtual inline const char* type() const { return "Eltwise"; } virtual inline int MinBottomBlobs() const { return 2; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -207,9 +201,7 @@ class FlattenLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_FLATTEN; - } + virtual inline const char* type() const { return "Flatten"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -260,9 +252,7 @@ class InnerProductLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_INNER_PRODUCT; - } + virtual inline const char* type() const { return "InnerProduct"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -296,9 +286,7 @@ class MVNLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_MVN; - } + virtual inline const char* type() const { return "MVN"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -330,9 +318,7 @@ class SilenceLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_SILENCE; - } + virtual inline const char* type() const { return "Silence"; } virtual inline int MinBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 0; } @@ -362,9 +348,7 @@ class SoftmaxLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_SOFTMAX; - } + virtual inline const char* type() const { return "Softmax"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -426,9 +410,7 @@ class SplitLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_SPLIT; - } + virtual inline const char* type() const { return "Split"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int MinTopBlobs() const { return 1; } @@ -461,9 +443,7 @@ class SliceLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_SLICE; - } + virtual inline const char* type() const { return "Slice"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int MinTopBlobs() const { return 2; } diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index e9c83856a99..e55a0bbbd7b 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -90,9 +90,7 @@ class DataLayer : public BasePrefetchingDataLayer { virtual void DataLayerSetUp(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_DATA; - } + virtual inline const char* type() const { return "Data"; } virtual inline int ExactNumBottomBlobs() const { return 0; } virtual inline int MinTopBlobs() const { return 1; } virtual inline int MaxTopBlobs() const { return 2; } @@ -120,9 +118,7 @@ class DummyDataLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_DUMMY_DATA; - } + virtual inline const char* type() const { return "DummyData"; } virtual inline int ExactNumBottomBlobs() const { return 0; } virtual inline int MinTopBlobs() const { return 1; } @@ -155,9 +151,7 @@ class HDF5DataLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_HDF5_DATA; - } + virtual inline const char* type() const { return "HDF5Data"; } virtual inline int ExactNumBottomBlobs() const { return 0; } virtual inline int MinTopBlobs() const { return 1; } @@ -195,9 +189,7 @@ class HDF5OutputLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_HDF5_OUTPUT; - } + virtual inline const char* type() const { return "HDF5Output"; } // TODO: no limit on the number of blobs virtual inline int ExactNumBottomBlobs() const { return 2; } virtual inline int ExactNumTopBlobs() const { return 0; } @@ -235,9 +227,7 @@ class ImageDataLayer : public BasePrefetchingDataLayer { virtual void DataLayerSetUp(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_IMAGE_DATA; - } + virtual inline const char* type() const { return "ImageData"; } virtual inline int ExactNumBottomBlobs() const { return 0; } virtual inline int ExactNumTopBlobs() const { return 2; } @@ -263,9 +253,7 @@ class MemoryDataLayer : public BaseDataLayer { virtual void DataLayerSetUp(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_MEMORY_DATA; - } + virtual inline const char* type() const { return "MemoryData"; } virtual inline int ExactNumBottomBlobs() const { return 0; } virtual inline int ExactNumTopBlobs() const { return 2; } @@ -309,9 +297,7 @@ class WindowDataLayer : public BasePrefetchingDataLayer { virtual void DataLayerSetUp(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_WINDOW_DATA; - } + virtual inline const char* type() const { return "WindowData"; } virtual inline int ExactNumBottomBlobs() const { return 0; } virtual inline int ExactNumTopBlobs() const { return 2; } diff --git a/include/caffe/layer.hpp b/include/caffe/layer.hpp index 8a8330bca57..c6461c19964 100644 --- a/include/caffe/layer.hpp +++ b/include/caffe/layer.hpp @@ -179,18 +179,9 @@ class Layer { } /** - * @brief Returns the layer type as an enum value. + * @brief Returns the layer type. */ - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_NONE; - } - - /** - * @brief Returns the layer type name. - */ - virtual inline const string& type_name() const { - return LayerParameter_LayerType_Name(type()); - } + virtual inline const char* type() const { return ""; } /** * @brief Returns the exact number of bottom blobs required by the layer, @@ -347,37 +338,37 @@ class Layer { const vector*>& top) { if (ExactNumBottomBlobs() >= 0) { CHECK_EQ(ExactNumBottomBlobs(), bottom.size()) - << type_name() << " Layer takes " << ExactNumBottomBlobs() + << type() << " Layer takes " << ExactNumBottomBlobs() << " bottom blob(s) as input."; } if (MinBottomBlobs() >= 0) { CHECK_LE(MinBottomBlobs(), bottom.size()) - << type_name() << " Layer takes at least " << MinBottomBlobs() + << type() << " Layer takes at least " << MinBottomBlobs() << " bottom blob(s) as input."; } if (MaxBottomBlobs() >= 0) { CHECK_GE(MaxBottomBlobs(), bottom.size()) - << type_name() << " Layer takes at most " << MaxBottomBlobs() + << type() << " Layer takes at most " << MaxBottomBlobs() << " bottom blob(s) as input."; } if (ExactNumTopBlobs() >= 0) { CHECK_EQ(ExactNumTopBlobs(), top.size()) - << type_name() << " Layer produces " << ExactNumTopBlobs() + << type() << " Layer produces " << ExactNumTopBlobs() << " top blob(s) as output."; } if (MinTopBlobs() >= 0) { CHECK_LE(MinTopBlobs(), top.size()) - << type_name() << " Layer produces at least " << MinTopBlobs() + << type() << " Layer produces at least " << MinTopBlobs() << " top blob(s) as output."; } if (MaxTopBlobs() >= 0) { CHECK_GE(MaxTopBlobs(), top.size()) - << type_name() << " Layer produces at most " << MaxTopBlobs() + << type() << " Layer produces at most " << MaxTopBlobs() << " top blob(s) as output."; } if (EqualNumBottomTopBlobs()) { CHECK_EQ(bottom.size(), top.size()) - << type_name() << " Layer produces one top blob as output for each " + << type() << " Layer produces one top blob as output for each " << "bottom blob input."; } } diff --git a/include/caffe/layer_factory.hpp b/include/caffe/layer_factory.hpp index c1fd6aa0d43..ede5d1fae3f 100644 --- a/include/caffe/layer_factory.hpp +++ b/include/caffe/layer_factory.hpp @@ -12,17 +12,13 @@ * // your implementations * }; * - * and its type is defined in the protobuffer as - * - * enum LayerType { - * // other definitions - * AWESOME = 46, - * } + * and its type is its C++ class name, but without the "Layer" at the end + * ("MyAwesomeLayer" -> "MyAwesome"). * * If the layer is going to be created simply by its constructor, in your c++ * file, add the following line: * - * REGISTER_LAYER_CLASS(AWESOME, MyAwesomeLayer); + * REGISTER_LAYER_CLASS(MyAwesome); * * Or, if the layer is going to be created by another creator function, in the * format of: @@ -35,7 +31,7 @@ * (for example, when your layer has multiple backends, see GetConvolutionLayer * for a use case), then you can register the creator function instead, like * - * REGISTER_LAYER_CREATOR(AWESOME, GetMyAwesomeLayer) + * REGISTER_LAYER_CREATOR(MyAwesome, GetMyAwesomeLayer) * * Note that each layer type should only be registered once. */ @@ -44,6 +40,7 @@ #define CAFFE_LAYER_FACTORY_H_ #include +#include #include "caffe/common.hpp" #include "caffe/proto/caffe.pb.h" @@ -57,7 +54,7 @@ template class LayerRegistry { public: typedef Layer* (*Creator)(const LayerParameter&); - typedef std::map CreatorRegistry; + typedef std::map CreatorRegistry; static CreatorRegistry& Registry() { static CreatorRegistry* g_registry_ = new CreatorRegistry(); @@ -65,8 +62,7 @@ class LayerRegistry { } // Adds a creator. - static void AddCreator(const LayerParameter_LayerType& type, - Creator creator) { + static void AddCreator(const string& type, Creator creator) { CreatorRegistry& registry = Registry(); CHECK_EQ(registry.count(type), 0) << "Layer type " << type << " already registered."; @@ -76,9 +72,10 @@ class LayerRegistry { // Get a layer using a LayerParameter. static Layer* CreateLayer(const LayerParameter& param) { LOG(INFO) << "Creating layer " << param.name(); - const LayerParameter_LayerType& type = param.type(); + const string& type = param.type(); CreatorRegistry& registry = Registry(); - CHECK_EQ(registry.count(type), 1); + CHECK_EQ(registry.count(type), 1) << "Unknown layer type: " << type + << " (known types: " << LayerTypeList() << ")"; return registry[type](param); } @@ -86,13 +83,26 @@ class LayerRegistry { // Layer registry should never be instantiated - everything is done with its // static variables. LayerRegistry() {} + + static string LayerTypeList() { + CreatorRegistry& registry = Registry(); + string layer_types; + for (typename CreatorRegistry::iterator iter = registry.begin(); + iter != registry.end(); ++iter) { + if (iter != registry.begin()) { + layer_types += ", "; + } + layer_types += iter->first; + } + return layer_types; + } }; template class LayerRegisterer { public: - LayerRegisterer(const LayerParameter_LayerType& type, + LayerRegisterer(const string& type, Layer* (*creator)(const LayerParameter&)) { // LOG(INFO) << "Registering layer type: " << type; LayerRegistry::AddCreator(type, creator); @@ -101,17 +111,15 @@ class LayerRegisterer { #define REGISTER_LAYER_CREATOR(type, creator) \ - static LayerRegisterer g_creator_f_##type( \ - LayerParameter_LayerType_##type, creator); \ - static LayerRegisterer g_creator_d_##type( \ - LayerParameter_LayerType_##type, creator) + static LayerRegisterer g_creator_f_##type(#type, creator); \ + static LayerRegisterer g_creator_d_##type(#type, creator) \ -#define REGISTER_LAYER_CLASS(type, clsname) \ +#define REGISTER_LAYER_CLASS(type) \ template \ - Layer* Creator_##clsname(const LayerParameter& param) { \ - return new clsname(param); \ + Layer* Creator_##type##Layer(const LayerParameter& param) { \ + return new type##Layer(param); \ } \ - REGISTER_LAYER_CREATOR(type, Creator_##clsname) + REGISTER_LAYER_CREATOR(type, Creator_##type##Layer) } // namespace caffe diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 600a13b8867..f14b9716a4a 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -37,10 +37,7 @@ class AccuracyLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_ACCURACY; - } - + virtual inline const char* type() const { return "Accuracy"; } virtual inline int ExactNumBottomBlobs() const { return 2; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -154,9 +151,7 @@ class ContrastiveLossLayer : public LossLayer { const vector*>& top); virtual inline int ExactNumBottomBlobs() const { return 3; } - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_CONTRASTIVE_LOSS; - } + virtual inline const char* type() const { return "ContrastiveLoss"; } /** * Unlike most loss layers, in the ContrastiveLossLayer we can backpropagate * to the first two inputs. @@ -242,10 +237,7 @@ class EuclideanLossLayer : public LossLayer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_EUCLIDEAN_LOSS; - } - + virtual inline const char* type() const { return "EuclideanLoss"; } /** * Unlike most loss layers, in the EuclideanLossLayer we can backpropagate * to both inputs -- override to return true and always allow force_backward. @@ -351,9 +343,7 @@ class HingeLossLayer : public LossLayer { explicit HingeLossLayer(const LayerParameter& param) : LossLayer(param) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_HINGE_LOSS; - } + virtual inline const char* type() const { return "HingeLoss"; } protected: /// @copydoc HingeLossLayer @@ -440,9 +430,7 @@ class InfogainLossLayer : public LossLayer { virtual inline int MinBottomBlobs() const { return 2; } virtual inline int MaxBottomBlobs() const { return 3; } - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_INFOGAIN_LOSS; - } + virtual inline const char* type() const { return "InfogainLoss"; } protected: /// @copydoc InfogainLossLayer @@ -524,9 +512,7 @@ class MultinomialLogisticLossLayer : public LossLayer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS; - } + virtual inline const char* type() const { return "MultinomialLogisticLoss"; } protected: /// @copydoc MultinomialLogisticLossLayer @@ -606,9 +592,7 @@ class SigmoidCrossEntropyLossLayer : public LossLayer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS; - } + virtual inline const char* type() const { return "SigmoidCrossEntropyLoss"; } protected: /// @copydoc SigmoidCrossEntropyLossLayer @@ -711,9 +695,7 @@ class SoftmaxWithLossLayer : public LossLayer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_SOFTMAX_LOSS; - } + virtual inline const char* type() const { return "SoftmaxWithLoss"; } virtual inline int ExactNumBottomBlobs() const { return -1; } virtual inline int MinBottomBlobs() const { return 2; } virtual inline int MaxBottomBlobs() const { return 3; } diff --git a/include/caffe/neuron_layers.hpp b/include/caffe/neuron_layers.hpp index 5daeeefe7ae..b65d98435bc 100644 --- a/include/caffe/neuron_layers.hpp +++ b/include/caffe/neuron_layers.hpp @@ -29,9 +29,6 @@ class NeuronLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_NONE; - } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } }; @@ -54,9 +51,7 @@ class AbsValLayer : public NeuronLayer { virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_ABSVAL; - } + virtual inline const char* type() const { return "AbsVal"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -113,9 +108,7 @@ class BNLLLayer : public NeuronLayer { explicit BNLLLayer(const LayerParameter& param) : NeuronLayer(param) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_BNLL; - } + virtual inline const char* type() const { return "BNLL"; } protected: /// @copydoc BNLLLayer @@ -173,9 +166,7 @@ class DropoutLayer : public NeuronLayer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_DROPOUT; - } + virtual inline const char* type() const { return "Dropout"; } protected: /** @@ -233,9 +224,7 @@ class ExpLayer : public NeuronLayer { virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_EXP; - } + virtual inline const char* type() const { return "Exp"; } protected: /** @@ -298,9 +287,7 @@ class PowerLayer : public NeuronLayer { virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_POWER; - } + virtual inline const char* type() const { return "Power"; } protected: /** @@ -369,9 +356,7 @@ class ReLULayer : public NeuronLayer { explicit ReLULayer(const LayerParameter& param) : NeuronLayer(param) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_RELU; - } + virtual inline const char* type() const { return "ReLU"; } protected: /** @@ -465,9 +450,7 @@ class SigmoidLayer : public NeuronLayer { explicit SigmoidLayer(const LayerParameter& param) : NeuronLayer(param) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_SIGMOID; - } + virtual inline const char* type() const { return "Sigmoid"; } protected: /** @@ -549,9 +532,7 @@ class TanHLayer : public NeuronLayer { explicit TanHLayer(const LayerParameter& param) : NeuronLayer(param) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_TANH; - } + virtual inline const char* type() const { return "TanH"; } protected: /** @@ -639,9 +620,7 @@ class ThresholdLayer : public NeuronLayer { virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_THRESHOLD; - } + virtual inline const char* type() const { return "Threshold"; } protected: /** diff --git a/include/caffe/util/upgrade_proto.hpp b/include/caffe/util/upgrade_proto.hpp index 45483685133..0627afe694c 100644 --- a/include/caffe/util/upgrade_proto.hpp +++ b/include/caffe/util/upgrade_proto.hpp @@ -27,7 +27,7 @@ void UpgradeV0PaddingLayers(const NetParameter& param, bool UpgradeLayerParameter(const LayerParameter& v0_layer_connection, LayerParameter* layer_param); -LayerParameter_LayerType UpgradeV0LayerType(const string& type); +const char* UpgradeV0LayerType(const string& type); // Return true iff any layer contains deprecated data transformation parameters. bool NetNeedsDataUpgrade(const NetParameter& net_param); diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index fc178e4c904..38e369c4092 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -160,9 +160,8 @@ class ConvolutionLayer : public BaseConvolutionLayer { */ explicit ConvolutionLayer(const LayerParameter& param) : BaseConvolutionLayer(param) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_CONVOLUTION; - } + + virtual inline const char* type() const { return "Convolution"; } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -196,9 +195,8 @@ class DeconvolutionLayer : public BaseConvolutionLayer { public: explicit DeconvolutionLayer(const LayerParameter& param) : BaseConvolutionLayer(param) {} - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_DECONVOLUTION; - } + + virtual inline const char* type() const { return "Deconvolution"; } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -272,9 +270,7 @@ class Im2colLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_IM2COL; - } + virtual inline const char* type() const { return "Im2col"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -314,9 +310,7 @@ class LRNLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_LRN; - } + virtual inline const char* type() const { return "LRN"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } @@ -392,9 +386,7 @@ class PoolingLayer : public Layer { virtual void Reshape(const vector*>& bottom, const vector*>& top); - virtual inline LayerParameter_LayerType type() const { - return LayerParameter_LayerType_POOLING; - } + virtual inline const char* type() const { return "Pooling"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int MinTopBlobs() const { return 1; } // MAX POOL layers can output an extra top blob for the mask; diff --git a/src/caffe/layer_factory.cpp b/src/caffe/layer_factory.cpp index 80694834a33..c3fd1f30ff2 100644 --- a/src/caffe/layer_factory.cpp +++ b/src/caffe/layer_factory.cpp @@ -29,7 +29,7 @@ Layer* GetConvolutionLayer( } } -REGISTER_LAYER_CREATOR(CONVOLUTION, GetConvolutionLayer); +REGISTER_LAYER_CREATOR(Convolution, GetConvolutionLayer); // Get pooling layer according to engine. template @@ -59,7 +59,7 @@ Layer* GetPoolingLayer(const LayerParameter& param) { } } -REGISTER_LAYER_CREATOR(POOLING, GetPoolingLayer); +REGISTER_LAYER_CREATOR(Pooling, GetPoolingLayer); // Get relu layer according to engine. template @@ -82,7 +82,7 @@ Layer* GetReLULayer(const LayerParameter& param) { } } -REGISTER_LAYER_CREATOR(RELU, GetReLULayer); +REGISTER_LAYER_CREATOR(ReLU, GetReLULayer); // Get sigmoid layer according to engine. template @@ -105,7 +105,7 @@ Layer* GetSigmoidLayer(const LayerParameter& param) { } } -REGISTER_LAYER_CREATOR(SIGMOID, GetSigmoidLayer); +REGISTER_LAYER_CREATOR(Sigmoid, GetSigmoidLayer); // Get softmax layer according to engine. template @@ -128,7 +128,7 @@ Layer* GetSoftmaxLayer(const LayerParameter& param) { } } -REGISTER_LAYER_CREATOR(SOFTMAX, GetSoftmaxLayer); +REGISTER_LAYER_CREATOR(Softmax, GetSoftmaxLayer); // Get tanh layer according to engine. template @@ -151,7 +151,7 @@ Layer* GetTanHLayer(const LayerParameter& param) { } } -REGISTER_LAYER_CREATOR(TANH, GetTanHLayer); +REGISTER_LAYER_CREATOR(TanH, GetTanHLayer); // Layers that use their constructor as their default creator should be // registered in their corresponding cpp files. Do not register them here. diff --git a/src/caffe/layers/absval_layer.cpp b/src/caffe/layers/absval_layer.cpp index 0d054ee5665..5ce28c9e2b4 100644 --- a/src/caffe/layers/absval_layer.cpp +++ b/src/caffe/layers/absval_layer.cpp @@ -10,7 +10,7 @@ template void AbsValLayer::LayerSetUp(const vector*>& bottom, const vector*>& top) { NeuronLayer::LayerSetUp(bottom, top); - CHECK_NE(top[0], bottom[0]) << this->type_name() << " Layer does not " + CHECK_NE(top[0], bottom[0]) << this->type() << " Layer does not " "allow in-place computation."; } @@ -40,5 +40,6 @@ STUB_GPU(AbsValLayer); #endif INSTANTIATE_CLASS(AbsValLayer); -REGISTER_LAYER_CLASS(ABSVAL, AbsValLayer); +REGISTER_LAYER_CLASS(AbsVal); + } // namespace caffe diff --git a/src/caffe/layers/accuracy_layer.cpp b/src/caffe/layers/accuracy_layer.cpp index 800b848f3bc..3e8df34c0d6 100644 --- a/src/caffe/layers/accuracy_layer.cpp +++ b/src/caffe/layers/accuracy_layer.cpp @@ -64,5 +64,6 @@ void AccuracyLayer::Forward_cpu(const vector*>& bottom, } INSTANTIATE_CLASS(AccuracyLayer); -REGISTER_LAYER_CLASS(ACCURACY, AccuracyLayer); +REGISTER_LAYER_CLASS(Accuracy); + } // namespace caffe diff --git a/src/caffe/layers/argmax_layer.cpp b/src/caffe/layers/argmax_layer.cpp index 15e199eb600..c4040cdcaaa 100644 --- a/src/caffe/layers/argmax_layer.cpp +++ b/src/caffe/layers/argmax_layer.cpp @@ -58,6 +58,6 @@ void ArgMaxLayer::Forward_cpu(const vector*>& bottom, } INSTANTIATE_CLASS(ArgMaxLayer); -REGISTER_LAYER_CLASS(ARGMAX, ArgMaxLayer); +REGISTER_LAYER_CLASS(ArgMax); } // namespace caffe diff --git a/src/caffe/layers/bnll_layer.cpp b/src/caffe/layers/bnll_layer.cpp index cb3583ae8be..9ba0ea9a715 100644 --- a/src/caffe/layers/bnll_layer.cpp +++ b/src/caffe/layers/bnll_layer.cpp @@ -43,5 +43,6 @@ STUB_GPU(BNLLLayer); #endif INSTANTIATE_CLASS(BNLLLayer); -REGISTER_LAYER_CLASS(BNLL, BNLLLayer); +REGISTER_LAYER_CLASS(BNLL); + } // namespace caffe diff --git a/src/caffe/layers/concat_layer.cpp b/src/caffe/layers/concat_layer.cpp index 420821952b0..fc88433c42b 100644 --- a/src/caffe/layers/concat_layer.cpp +++ b/src/caffe/layers/concat_layer.cpp @@ -105,5 +105,6 @@ STUB_GPU(ConcatLayer); #endif INSTANTIATE_CLASS(ConcatLayer); -REGISTER_LAYER_CLASS(CONCAT, ConcatLayer); +REGISTER_LAYER_CLASS(Concat); + } // namespace caffe diff --git a/src/caffe/layers/contrastive_loss_layer.cpp b/src/caffe/layers/contrastive_loss_layer.cpp index 0d0b443b66b..0692c11c257 100644 --- a/src/caffe/layers/contrastive_loss_layer.cpp +++ b/src/caffe/layers/contrastive_loss_layer.cpp @@ -97,5 +97,6 @@ STUB_GPU(ContrastiveLossLayer); #endif INSTANTIATE_CLASS(ContrastiveLossLayer); -REGISTER_LAYER_CLASS(CONTRASTIVE_LOSS, ContrastiveLossLayer); +REGISTER_LAYER_CLASS(ContrastiveLoss); + } // namespace caffe diff --git a/src/caffe/layers/conv_layer.cpp b/src/caffe/layers/conv_layer.cpp index 9fd2fc6a15f..c0c9f6f3371 100644 --- a/src/caffe/layers/conv_layer.cpp +++ b/src/caffe/layers/conv_layer.cpp @@ -79,4 +79,5 @@ STUB_GPU(ConvolutionLayer); #endif INSTANTIATE_CLASS(ConvolutionLayer); + } // namespace caffe diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 96964566630..227db201759 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -129,6 +129,6 @@ void DataLayer::InternalThreadEntry() { } INSTANTIATE_CLASS(DataLayer); -REGISTER_LAYER_CLASS(DATA, DataLayer); +REGISTER_LAYER_CLASS(Data); } // namespace caffe diff --git a/src/caffe/layers/deconv_layer.cpp b/src/caffe/layers/deconv_layer.cpp index 59114f017bf..e6d65ab526b 100644 --- a/src/caffe/layers/deconv_layer.cpp +++ b/src/caffe/layers/deconv_layer.cpp @@ -81,5 +81,6 @@ STUB_GPU(DeconvolutionLayer); #endif INSTANTIATE_CLASS(DeconvolutionLayer); -REGISTER_LAYER_CLASS(DECONVOLUTION, DeconvolutionLayer); +REGISTER_LAYER_CLASS(Deconvolution); + } // namespace caffe diff --git a/src/caffe/layers/dropout_layer.cpp b/src/caffe/layers/dropout_layer.cpp index 8c8936a711e..5f81cc1c692 100644 --- a/src/caffe/layers/dropout_layer.cpp +++ b/src/caffe/layers/dropout_layer.cpp @@ -73,5 +73,6 @@ STUB_GPU(DropoutLayer); #endif INSTANTIATE_CLASS(DropoutLayer); -REGISTER_LAYER_CLASS(DROPOUT, DropoutLayer); +REGISTER_LAYER_CLASS(Dropout); + } // namespace caffe diff --git a/src/caffe/layers/dummy_data_layer.cpp b/src/caffe/layers/dummy_data_layer.cpp index 15cf5a58ac6..d254eb1f961 100644 --- a/src/caffe/layers/dummy_data_layer.cpp +++ b/src/caffe/layers/dummy_data_layer.cpp @@ -93,5 +93,6 @@ void DummyDataLayer::Forward_cpu(const vector*>& bottom, } INSTANTIATE_CLASS(DummyDataLayer); -REGISTER_LAYER_CLASS(DUMMY_DATA, DummyDataLayer); +REGISTER_LAYER_CLASS(DummyData); + } // namespace caffe diff --git a/src/caffe/layers/eltwise_layer.cpp b/src/caffe/layers/eltwise_layer.cpp index 0c239f4ac11..bbc34449588 100644 --- a/src/caffe/layers/eltwise_layer.cpp +++ b/src/caffe/layers/eltwise_layer.cpp @@ -163,5 +163,6 @@ STUB_GPU(EltwiseLayer); #endif INSTANTIATE_CLASS(EltwiseLayer); -REGISTER_LAYER_CLASS(ELTWISE, EltwiseLayer); +REGISTER_LAYER_CLASS(Eltwise); + } // namespace caffe diff --git a/src/caffe/layers/euclidean_loss_layer.cpp b/src/caffe/layers/euclidean_loss_layer.cpp index d965027f712..b539d3487f5 100644 --- a/src/caffe/layers/euclidean_loss_layer.cpp +++ b/src/caffe/layers/euclidean_loss_layer.cpp @@ -54,5 +54,6 @@ STUB_GPU(EuclideanLossLayer); #endif INSTANTIATE_CLASS(EuclideanLossLayer); -REGISTER_LAYER_CLASS(EUCLIDEAN_LOSS, EuclideanLossLayer); +REGISTER_LAYER_CLASS(EuclideanLoss); + } // namespace caffe diff --git a/src/caffe/layers/exp_layer.cpp b/src/caffe/layers/exp_layer.cpp index 92cb5deb1e6..c7e7c60cfad 100644 --- a/src/caffe/layers/exp_layer.cpp +++ b/src/caffe/layers/exp_layer.cpp @@ -64,5 +64,6 @@ STUB_GPU(ExpLayer); #endif INSTANTIATE_CLASS(ExpLayer); -REGISTER_LAYER_CLASS(EXP, ExpLayer); +REGISTER_LAYER_CLASS(Exp); + } // namespace caffe diff --git a/src/caffe/layers/flatten_layer.cpp b/src/caffe/layers/flatten_layer.cpp index ec43cababca..eb7b42bc10b 100644 --- a/src/caffe/layers/flatten_layer.cpp +++ b/src/caffe/layers/flatten_layer.cpp @@ -34,5 +34,6 @@ STUB_GPU(FlattenLayer); #endif INSTANTIATE_CLASS(FlattenLayer); -REGISTER_LAYER_CLASS(FLATTEN, FlattenLayer); +REGISTER_LAYER_CLASS(Flatten); + } // namespace caffe diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index 706c4a18319..77555211082 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -121,5 +121,6 @@ STUB_GPU_FORWARD(HDF5DataLayer, Forward); #endif INSTANTIATE_CLASS(HDF5DataLayer); -REGISTER_LAYER_CLASS(HDF5_DATA, HDF5DataLayer); +REGISTER_LAYER_CLASS(HDF5Data); + } // namespace caffe diff --git a/src/caffe/layers/hdf5_output_layer.cpp b/src/caffe/layers/hdf5_output_layer.cpp index 4a72a18aa12..d2fdeffc53f 100644 --- a/src/caffe/layers/hdf5_output_layer.cpp +++ b/src/caffe/layers/hdf5_output_layer.cpp @@ -70,5 +70,6 @@ STUB_GPU(HDF5OutputLayer); #endif INSTANTIATE_CLASS(HDF5OutputLayer); -REGISTER_LAYER_CLASS(HDF5_OUTPUT, HDF5OutputLayer); +REGISTER_LAYER_CLASS(HDF5Output); + } // namespace caffe diff --git a/src/caffe/layers/hinge_loss_layer.cpp b/src/caffe/layers/hinge_loss_layer.cpp index 4dfafcc8648..a2fb2a18309 100644 --- a/src/caffe/layers/hinge_loss_layer.cpp +++ b/src/caffe/layers/hinge_loss_layer.cpp @@ -47,7 +47,7 @@ template void HingeLossLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom) { if (propagate_down[1]) { - LOG(FATAL) << this->type_name() + LOG(FATAL) << this->type() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { @@ -77,5 +77,6 @@ void HingeLossLayer::Backward_cpu(const vector*>& top, } INSTANTIATE_CLASS(HingeLossLayer); -REGISTER_LAYER_CLASS(HINGE_LOSS, HingeLossLayer); +REGISTER_LAYER_CLASS(HingeLoss); + } // namespace caffe diff --git a/src/caffe/layers/im2col_layer.cpp b/src/caffe/layers/im2col_layer.cpp index 2c4bb9029e0..112226116c8 100644 --- a/src/caffe/layers/im2col_layer.cpp +++ b/src/caffe/layers/im2col_layer.cpp @@ -88,5 +88,6 @@ STUB_GPU(Im2colLayer); #endif INSTANTIATE_CLASS(Im2colLayer); -REGISTER_LAYER_CLASS(IM2COL, Im2colLayer); +REGISTER_LAYER_CLASS(Im2col); + } // namespace caffe diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index ef6a342c30a..b96be6ad72d 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -149,5 +149,6 @@ void ImageDataLayer::InternalThreadEntry() { } INSTANTIATE_CLASS(ImageDataLayer); -REGISTER_LAYER_CLASS(IMAGE_DATA, ImageDataLayer); +REGISTER_LAYER_CLASS(ImageData); + } // namespace caffe diff --git a/src/caffe/layers/infogain_loss_layer.cpp b/src/caffe/layers/infogain_loss_layer.cpp index 8910431d42b..a1e0b40de0e 100644 --- a/src/caffe/layers/infogain_loss_layer.cpp +++ b/src/caffe/layers/infogain_loss_layer.cpp @@ -75,11 +75,11 @@ void InfogainLossLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom) { if (propagate_down[1]) { - LOG(FATAL) << this->type_name() + LOG(FATAL) << this->type() << " Layer cannot backpropagate to label inputs."; } if (propagate_down.size() > 2 && propagate_down[2]) { - LOG(FATAL) << this->type_name() + LOG(FATAL) << this->type() << " Layer cannot backpropagate to infogain inputs."; } if (propagate_down[0]) { @@ -106,5 +106,5 @@ void InfogainLossLayer::Backward_cpu(const vector*>& top, } INSTANTIATE_CLASS(InfogainLossLayer); -REGISTER_LAYER_CLASS(INFOGAIN_LOSS, InfogainLossLayer); +REGISTER_LAYER_CLASS(InfogainLoss); } // namespace caffe diff --git a/src/caffe/layers/inner_product_layer.cpp b/src/caffe/layers/inner_product_layer.cpp index ecb849ba4d8..b1ec6cb25c0 100644 --- a/src/caffe/layers/inner_product_layer.cpp +++ b/src/caffe/layers/inner_product_layer.cpp @@ -104,5 +104,6 @@ STUB_GPU(InnerProductLayer); #endif INSTANTIATE_CLASS(InnerProductLayer); -REGISTER_LAYER_CLASS(INNER_PRODUCT, InnerProductLayer); +REGISTER_LAYER_CLASS(InnerProduct); + } // namespace caffe diff --git a/src/caffe/layers/lrn_layer.cpp b/src/caffe/layers/lrn_layer.cpp index a878cf847b3..5e3e7c429ef 100644 --- a/src/caffe/layers/lrn_layer.cpp +++ b/src/caffe/layers/lrn_layer.cpp @@ -252,5 +252,6 @@ STUB_GPU_BACKWARD(LRNLayer, CrossChannelBackward); #endif INSTANTIATE_CLASS(LRNLayer); -REGISTER_LAYER_CLASS(LRN, LRNLayer); +REGISTER_LAYER_CLASS(LRN); + } // namespace caffe diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 613ca2d4c76..3272b66ac55 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -72,5 +72,6 @@ void MemoryDataLayer::Forward_cpu(const vector*>& bottom, } INSTANTIATE_CLASS(MemoryDataLayer); -REGISTER_LAYER_CLASS(MEMORY_DATA, MemoryDataLayer); +REGISTER_LAYER_CLASS(MemoryData); + } // namespace caffe diff --git a/src/caffe/layers/multinomial_logistic_loss_layer.cpp b/src/caffe/layers/multinomial_logistic_loss_layer.cpp index 78a1f60fca9..4267a594a0f 100644 --- a/src/caffe/layers/multinomial_logistic_loss_layer.cpp +++ b/src/caffe/layers/multinomial_logistic_loss_layer.cpp @@ -41,7 +41,7 @@ void MultinomialLogisticLossLayer::Backward_cpu( const vector*>& top, const vector& propagate_down, const vector*>& bottom) { if (propagate_down[1]) { - LOG(FATAL) << this->type_name() + LOG(FATAL) << this->type() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { @@ -62,5 +62,6 @@ void MultinomialLogisticLossLayer::Backward_cpu( } INSTANTIATE_CLASS(MultinomialLogisticLossLayer); -REGISTER_LAYER_CLASS(MULTINOMIAL_LOGISTIC_LOSS, MultinomialLogisticLossLayer); +REGISTER_LAYER_CLASS(MultinomialLogisticLoss); + } // namespace caffe diff --git a/src/caffe/layers/mvn_layer.cpp b/src/caffe/layers/mvn_layer.cpp index 104ad95c7ed..b74d7b4f300 100644 --- a/src/caffe/layers/mvn_layer.cpp +++ b/src/caffe/layers/mvn_layer.cpp @@ -159,5 +159,6 @@ STUB_GPU(MVNLayer); #endif INSTANTIATE_CLASS(MVNLayer); -REGISTER_LAYER_CLASS(MVN, MVNLayer); +REGISTER_LAYER_CLASS(MVN); + } // namespace caffe diff --git a/src/caffe/layers/pooling_layer.cpp b/src/caffe/layers/pooling_layer.cpp index 2bfbb01fcec..6f4c69c861e 100644 --- a/src/caffe/layers/pooling_layer.cpp +++ b/src/caffe/layers/pooling_layer.cpp @@ -314,5 +314,4 @@ STUB_GPU(PoolingLayer); INSTANTIATE_CLASS(PoolingLayer); - } // namespace caffe diff --git a/src/caffe/layers/power_layer.cpp b/src/caffe/layers/power_layer.cpp index 69bd120e3dc..4fe34c49f32 100644 --- a/src/caffe/layers/power_layer.cpp +++ b/src/caffe/layers/power_layer.cpp @@ -99,5 +99,6 @@ STUB_GPU(PowerLayer); #endif INSTANTIATE_CLASS(PowerLayer); -REGISTER_LAYER_CLASS(POWER, PowerLayer); +REGISTER_LAYER_CLASS(Power); + } // namespace caffe diff --git a/src/caffe/layers/relu_layer.cpp b/src/caffe/layers/relu_layer.cpp index 7d5e6034589..cc00319a578 100644 --- a/src/caffe/layers/relu_layer.cpp +++ b/src/caffe/layers/relu_layer.cpp @@ -43,5 +43,4 @@ STUB_GPU(ReLULayer); INSTANTIATE_CLASS(ReLULayer); - } // namespace caffe diff --git a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp index d1e327a54c9..077d949981c 100644 --- a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp +++ b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp @@ -53,7 +53,7 @@ void SigmoidCrossEntropyLossLayer::Backward_cpu( const vector*>& top, const vector& propagate_down, const vector*>& bottom) { if (propagate_down[1]) { - LOG(FATAL) << this->type_name() + LOG(FATAL) << this->type() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { @@ -75,5 +75,6 @@ STUB_GPU(SigmoidCrossEntropyLossLayer); #endif INSTANTIATE_CLASS(SigmoidCrossEntropyLossLayer); -REGISTER_LAYER_CLASS(SIGMOID_CROSS_ENTROPY_LOSS, SigmoidCrossEntropyLossLayer); +REGISTER_LAYER_CLASS(SigmoidCrossEntropyLoss); + } // namespace caffe diff --git a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu index d9db4af64e6..08f7f492297 100644 --- a/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu +++ b/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu @@ -33,7 +33,7 @@ void SigmoidCrossEntropyLossLayer::Backward_gpu( const vector*>& top, const vector& propagate_down, const vector*>& bottom) { if (propagate_down[1]) { - LOG(FATAL) << this->type_name() + LOG(FATAL) << this->type() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { diff --git a/src/caffe/layers/silence_layer.cpp b/src/caffe/layers/silence_layer.cpp index 9bd20574816..4abf9eff4a2 100644 --- a/src/caffe/layers/silence_layer.cpp +++ b/src/caffe/layers/silence_layer.cpp @@ -22,5 +22,6 @@ STUB_GPU(SilenceLayer); #endif INSTANTIATE_CLASS(SilenceLayer); -REGISTER_LAYER_CLASS(SILENCE, SilenceLayer); +REGISTER_LAYER_CLASS(Silence); + } // namespace caffe diff --git a/src/caffe/layers/slice_layer.cpp b/src/caffe/layers/slice_layer.cpp index 60a5ecfa416..46c3acd6513 100644 --- a/src/caffe/layers/slice_layer.cpp +++ b/src/caffe/layers/slice_layer.cpp @@ -137,5 +137,6 @@ STUB_GPU(SliceLayer); #endif INSTANTIATE_CLASS(SliceLayer); -REGISTER_LAYER_CLASS(SLICE, SliceLayer); +REGISTER_LAYER_CLASS(Slice); + } // namespace caffe diff --git a/src/caffe/layers/softmax_layer.cpp b/src/caffe/layers/softmax_layer.cpp index c7b09fffd7a..25142fdec53 100644 --- a/src/caffe/layers/softmax_layer.cpp +++ b/src/caffe/layers/softmax_layer.cpp @@ -92,4 +92,5 @@ STUB_GPU(SoftmaxLayer); #endif INSTANTIATE_CLASS(SoftmaxLayer); + } // namespace caffe diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index 14bd383718c..bf20b6056e4 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -14,7 +14,7 @@ void SoftmaxWithLossLayer::LayerSetUp( const vector*>& bottom, const vector*>& top) { LossLayer::LayerSetUp(bottom, top); LayerParameter softmax_param(this->layer_param_); - softmax_param.set_type(LayerParameter_LayerType_SOFTMAX); + softmax_param.set_type("Softmax"); softmax_layer_.reset(LayerRegistry::CreateLayer(softmax_param)); softmax_bottom_vec_.clear(); softmax_bottom_vec_.push_back(bottom[0]); @@ -80,7 +80,7 @@ template void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom) { if (propagate_down[1]) { - LOG(FATAL) << this->type_name() + LOG(FATAL) << this->type() << " Layer cannot backpropagate to label inputs."; } if (propagate_down[0]) { @@ -116,6 +116,6 @@ void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, } INSTANTIATE_CLASS(SoftmaxWithLossLayer); -REGISTER_LAYER_CLASS(SOFTMAX_LOSS, SoftmaxWithLossLayer); +REGISTER_LAYER_CLASS(SoftmaxWithLoss); } // namespace caffe diff --git a/src/caffe/layers/split_layer.cpp b/src/caffe/layers/split_layer.cpp index 51ac61f4cae..d6929b99683 100644 --- a/src/caffe/layers/split_layer.cpp +++ b/src/caffe/layers/split_layer.cpp @@ -16,7 +16,7 @@ void SplitLayer::Reshape(const vector*>& bottom, // the backward pass. (Technically, it should be possible to share the diff // blob of the first split output with the input, but this seems to cause // some strange effects in practice...) - CHECK_NE(top[i], bottom[0]) << this->type_name() << " Layer does not " + CHECK_NE(top[i], bottom[0]) << this->type() << " Layer does not " "allow in-place computation."; top[i]->Reshape(bottom[0]->num(), bottom[0]->channels(), bottom[0]->height(), bottom[0]->width()); @@ -56,5 +56,6 @@ STUB_GPU(SplitLayer); #endif INSTANTIATE_CLASS(SplitLayer); -REGISTER_LAYER_CLASS(SPLIT, SplitLayer); +REGISTER_LAYER_CLASS(Split); + } // namespace caffe diff --git a/src/caffe/layers/threshold_layer.cpp b/src/caffe/layers/threshold_layer.cpp index 9e68c32d348..2365e7b9c72 100644 --- a/src/caffe/layers/threshold_layer.cpp +++ b/src/caffe/layers/threshold_layer.cpp @@ -29,5 +29,6 @@ STUB_GPU_FORWARD(ThresholdLayer, Forward); #endif INSTANTIATE_CLASS(ThresholdLayer); -REGISTER_LAYER_CLASS(THRESHOLD, ThresholdLayer); +REGISTER_LAYER_CLASS(Threshold); + } // namespace caffe diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 83372e074f5..23ec83d166b 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -463,5 +463,6 @@ void WindowDataLayer::InternalThreadEntry() { } INSTANTIATE_CLASS(WindowDataLayer); -REGISTER_LAYER_CLASS(WINDOW_DATA, WindowDataLayer); +REGISTER_LAYER_CLASS(WindowData); + } // namespace caffe diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index dd2c1471c29..1fea3445415 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -225,59 +225,7 @@ message LayerParameter { repeated NetStateRule include = 32; repeated NetStateRule exclude = 33; - // NOTE - // Add new LayerTypes to the enum below in lexicographical order (other than - // starting with NONE), starting with the next available ID in the comment - // line above the enum. Update the next available ID when you add a new - // LayerType. - // - // LayerType next available ID: 40 (last added: DECONVOLUTION) - enum LayerType { - // "NONE" layer type is 0th enum element so that we don't cause confusion - // by defaulting to an existent LayerType (instead, should usually error if - // the type is unspecified). - NONE = 0; - ABSVAL = 35; - ACCURACY = 1; - ARGMAX = 30; - BNLL = 2; - CONCAT = 3; - CONTRASTIVE_LOSS = 37; - CONVOLUTION = 4; - DATA = 5; - DECONVOLUTION = 39; - DROPOUT = 6; - DUMMY_DATA = 32; - EUCLIDEAN_LOSS = 7; - ELTWISE = 25; - EXP = 38; - FLATTEN = 8; - HDF5_DATA = 9; - HDF5_OUTPUT = 10; - HINGE_LOSS = 28; - IM2COL = 11; - IMAGE_DATA = 12; - INFOGAIN_LOSS = 13; - INNER_PRODUCT = 14; - LRN = 15; - MEMORY_DATA = 29; - MULTINOMIAL_LOGISTIC_LOSS = 16; - MVN = 34; - POOLING = 17; - POWER = 26; - RELU = 18; - SIGMOID = 19; - SIGMOID_CROSS_ENTROPY_LOSS = 27; - SILENCE = 36; - SOFTMAX = 20; - SOFTMAX_LOSS = 21; - SPLIT = 22; - SLICE = 33; - TANH = 23; - WINDOW_DATA = 24; - THRESHOLD = 31; - } - optional LayerType type = 5; // the layer type from the enum above + optional string type = 5; // the layer type from the enum above // The blobs containing the numeric parameters of the layer repeated BlobProto blobs = 6; diff --git a/src/caffe/test/test_gradient_based_solver.cpp b/src/caffe/test/test_gradient_based_solver.cpp index 65de52aae4a..1d8192aebbc 100644 --- a/src/caffe/test/test_gradient_based_solver.cpp +++ b/src/caffe/test/test_gradient_based_solver.cpp @@ -66,7 +66,7 @@ class GradientBasedSolverTest : public MultiDeviceTest { " name: 'TestNetwork' " " layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: " << num_ << " " " channels: " << channels_ << " " @@ -85,7 +85,7 @@ class GradientBasedSolverTest : public MultiDeviceTest { " } " " layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 1 " " weight_filler { " @@ -102,7 +102,7 @@ class GradientBasedSolverTest : public MultiDeviceTest { " } " " layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod' " " bottom: 'targets' " " } " diff --git a/src/caffe/test/test_net.cpp b/src/caffe/test/test_net.cpp index 319958fee49..a4e14f914c5 100644 --- a/src/caffe/test/test_net.cpp +++ b/src/caffe/test/test_net.cpp @@ -61,7 +61,7 @@ class NetTest : public MultiDeviceTest { "name: 'TinyTestNetwork' " "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 5 " " channels: 2 " @@ -85,7 +85,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 1000 " " weight_filler { " @@ -106,7 +106,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerproduct' " " bottom: 'label' " " top: 'top_loss' " @@ -115,7 +115,7 @@ class NetTest : public MultiDeviceTest { proto += "layers: { " " name: 'loss' " - " type: ACCURACY " + " type: 'Accuracy' " " bottom: 'innerproduct' " " bottom: 'label' " " top: 'accuracy' " @@ -132,7 +132,7 @@ class NetTest : public MultiDeviceTest { "name: 'TinyTestEuclidLossNetwork' " "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 5 " " channels: 2 " @@ -152,7 +152,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 1 " " weight_filler { " @@ -173,7 +173,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerproduct' " " bottom: 'label' " "} "; @@ -192,7 +192,7 @@ class NetTest : public MultiDeviceTest { "name: 'TrickyTestNetwork' " "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 5 " " channels: 2 " @@ -212,7 +212,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 1000 " " weight_filler { " @@ -233,7 +233,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 1 " " weight_filler { " @@ -254,7 +254,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + + " type: 'SoftmaxWithLoss' " + loss_weight_stream.str() + " bottom: 'transformed_data' " " bottom: 'transformed_label' " @@ -262,8 +262,8 @@ class NetTest : public MultiDeviceTest { InitNetFromProtoString(proto); } - // loss_weight is the loss weight for the EUCLIDEAN_LOSS layer output. - // midnet_loss_weight is the loss weight for the first INNER_PRODUCT layer + // loss_weight is the loss weight for the 'EuclideanLoss' layer output. + // midnet_loss_weight is the loss weight for the first 'InnerProduct' layer // output. Should both default to 0.0 if unspecified (i.e., if NULL is // passed to this function). virtual void InitUnsharedWeightsNet(const Dtype* loss_weight = NULL, @@ -279,7 +279,7 @@ class NetTest : public MultiDeviceTest { proto << "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 5 " " channels: 2 " @@ -294,7 +294,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: " << bias_term << @@ -322,7 +322,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: " << bias_term << @@ -346,7 +346,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS "; + " type: 'EuclideanLoss' "; if (loss_weight) { proto << " loss_weight: " << *loss_weight << " "; } @@ -362,7 +362,7 @@ class NetTest : public MultiDeviceTest { "name: 'SharedWeightsNetwork' " "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 5 " " channels: 2 " @@ -377,7 +377,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -392,7 +392,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -407,7 +407,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerproduct1' " " bottom: 'innerproduct2' " "} "; @@ -419,7 +419,7 @@ class NetTest : public MultiDeviceTest { "name: 'DiffDataUnsharedWeightsNetwork' " "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 10 " " channels: 10 " @@ -439,7 +439,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -454,7 +454,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -469,7 +469,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'data2' " " bottom: 'innerproduct2' " "} "; @@ -481,7 +481,7 @@ class NetTest : public MultiDeviceTest { "name: 'DiffDataSharedWeightsNetwork' " "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 10 " " channels: 10 " @@ -501,7 +501,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -516,7 +516,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'innerproduct2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -531,7 +531,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'data2' " " bottom: 'innerproduct2' " "} "; @@ -548,7 +548,7 @@ class NetTest : public MultiDeviceTest { "input_dim: 100 " "layers: { " " name: 'conv1' " - " type: CONVOLUTION " + " type: 'Convolution' " " bottom: 'data' " " top: 'conv1' " " convolution_param { " @@ -567,13 +567,13 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'relu1' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv1' " " top: 'conv1' " "} " "layers: { " " name: 'pool1' " - " type: POOLING " + " type: 'Pooling' " " bottom: 'conv1' " " top: 'pool1' " " pooling_param { " @@ -584,7 +584,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'norm1' " - " type: LRN " + " type: 'LRN' " " bottom: 'pool1' " " top: 'norm1' " " lrn_param { " @@ -593,7 +593,7 @@ class NetTest : public MultiDeviceTest { "} " "layers: { " " name: 'softmax' " - " type: SOFTMAX " + " type: 'Softmax' " " bottom: 'norm1' " " top: 'softmax' " "} "; @@ -702,7 +702,7 @@ TYPED_TEST(NetTest, TestBottomNeedBackwardTricky) { TYPED_TEST(NetTest, TestLossWeight) { typedef typename TypeParam::Dtype Dtype; // First, compute the loss and gradients with no loss_weight specified. - // In this case, the loss weight for the EUCLIDEAN_LOSS layer should default + // In this case, the loss weight for the 'EuclideanLoss' layer should default // to 1. vector*> bottom; Caffe::set_random_seed(this->seed_); @@ -796,8 +796,8 @@ TYPED_TEST(NetTest, TestComboLossWeight) { const bool kForceBackward = true; const Dtype kErrorMargin = 1e-4; - // Get the loss and gradients with EUCLIDEAN_LOSS weight 1, - // INNER_PRODUCT weight 1. + // Get the loss and gradients with 'EuclideanLoss' weight 1, + // 'InnerProduct' weight 1. loss_weight = 1; midnet_loss_weight = 1; Caffe::set_random_seed(this->seed_); @@ -925,7 +925,7 @@ TYPED_TEST(NetTest, TestBackwardWithAccuracyLayer) { this->InitTinyNet(kForceBackward, kAccuracyLayer); EXPECT_TRUE(this->net_->has_blob("accuracy")); vector*> bottom; - // Test that we can do Backward even though we have an ACCURACY layer. + // Test that we can do Backward even though we have an 'Accuracy' layer. this->net_->ForwardBackward(bottom); } @@ -1263,19 +1263,19 @@ TEST_F(FilterNetTest, TestNoFilter) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1287,7 +1287,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "name: 'LeNet' " "layers { " " name: 'mnist' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " " data_param { " @@ -1301,7 +1301,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'mnist' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " " data_param { " @@ -1315,7 +1315,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'conv1' " - " type: CONVOLUTION " + " type: 'Convolution' " " bottom: 'data' " " top: 'conv1' " " blobs_lr: 1 " @@ -1334,7 +1334,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'ip1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'conv1' " " top: 'ip1' " " blobs_lr: 1 " @@ -1351,7 +1351,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'accuracy' " - " type: ACCURACY " + " type: 'Accuracy' " " bottom: 'ip1' " " bottom: 'label' " " top: 'accuracy' " @@ -1359,7 +1359,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'ip2' " " bottom: 'label' " " top: 'loss' " @@ -1370,7 +1370,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "name: 'LeNet' " "layers { " " name: 'mnist' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " " data_param { " @@ -1384,7 +1384,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'conv1' " - " type: CONVOLUTION " + " type: 'Convolution' " " bottom: 'data' " " top: 'conv1' " " blobs_lr: 1 " @@ -1403,7 +1403,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'ip1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'conv1' " " top: 'ip1' " " blobs_lr: 1 " @@ -1420,7 +1420,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'ip2' " " bottom: 'label' " " top: 'loss' " @@ -1429,7 +1429,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "name: 'LeNet' " "layers { " " name: 'mnist' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " " data_param { " @@ -1443,7 +1443,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'conv1' " - " type: CONVOLUTION " + " type: 'Convolution' " " bottom: 'data' " " top: 'conv1' " " blobs_lr: 1 " @@ -1462,7 +1462,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'ip1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'conv1' " " top: 'ip1' " " blobs_lr: 1 " @@ -1479,7 +1479,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'accuracy' " - " type: ACCURACY " + " type: 'Accuracy' " " bottom: 'ip1' " " bottom: 'label' " " top: 'accuracy' " @@ -1487,7 +1487,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} " "layers { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'ip2' " " bottom: 'label' " " top: 'loss' " @@ -1519,20 +1519,20 @@ TEST_F(FilterNetTest, TestFilterOutByStage) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " " include: { stage: 'mystage' } " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1540,13 +1540,13 @@ TEST_F(FilterNetTest, TestFilterOutByStage) { "name: 'TestNetwork' " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1558,20 +1558,20 @@ TEST_F(FilterNetTest, TestFilterOutByStage2) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'mystage' } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1579,13 +1579,13 @@ TEST_F(FilterNetTest, TestFilterOutByStage2) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1598,20 +1598,20 @@ TEST_F(FilterNetTest, TestFilterInByStage) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'mystage' } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1623,20 +1623,20 @@ TEST_F(FilterNetTest, TestFilterInByStage2) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " exclude: { stage: 'mystage' } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1649,20 +1649,20 @@ TEST_F(FilterNetTest, TestFilterOutByMultipleStage) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'mystage' stage: 'myotherstage' } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { stage: 'mystage' } " @@ -1672,13 +1672,13 @@ TEST_F(FilterNetTest, TestFilterOutByMultipleStage) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { stage: 'mystage' } " @@ -1692,13 +1692,13 @@ TEST_F(FilterNetTest, TestFilterInByMultipleStage) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'myotherstage' } " @@ -1706,7 +1706,7 @@ TEST_F(FilterNetTest, TestFilterInByMultipleStage) { "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { stage: 'mystage' } " @@ -1720,20 +1720,20 @@ TEST_F(FilterNetTest, TestFilterInByMultipleStage2) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'mystage' stage: 'myotherstage' } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { stage: 'mystage' } " @@ -1747,20 +1747,20 @@ TEST_F(FilterNetTest, TestFilterInByNotStage) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { not_stage: 'myotherstage' } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { not_stage: 'myotherstage' } " @@ -1774,20 +1774,20 @@ TEST_F(FilterNetTest, TestFilterOutByNotStage) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { not_stage: 'mystage' } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { not_stage: 'mystage' } " @@ -1797,7 +1797,7 @@ TEST_F(FilterNetTest, TestFilterOutByNotStage) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} "; @@ -1809,20 +1809,20 @@ TEST_F(FilterNetTest, TestFilterOutByMinLevel) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 3 } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1830,13 +1830,13 @@ TEST_F(FilterNetTest, TestFilterOutByMinLevel) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1848,20 +1848,20 @@ TEST_F(FilterNetTest, TestFilterOutByMaxLevel) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { max_level: -3 } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1869,13 +1869,13 @@ TEST_F(FilterNetTest, TestFilterOutByMaxLevel) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1887,20 +1887,20 @@ TEST_F(FilterNetTest, TestFilterInByMinLevel) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 0 } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1913,20 +1913,20 @@ TEST_F(FilterNetTest, TestFilterInByMinLevel2) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 3 } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1938,20 +1938,20 @@ TEST_F(FilterNetTest, TestFilterInByMaxLevel) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { max_level: 0 } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1964,20 +1964,20 @@ TEST_F(FilterNetTest, TestFilterInByMaxLevel2) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { max_level: -3 } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -1989,20 +1989,20 @@ TEST_F(FilterNetTest, TestFilterInOutByIncludeMultiRule) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 2 phase: TRAIN } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { min_level: 2 phase: TEST } " @@ -2016,13 +2016,13 @@ TEST_F(FilterNetTest, TestFilterInOutByIncludeMultiRule) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 2 phase: TRAIN } " @@ -2032,13 +2032,13 @@ TEST_F(FilterNetTest, TestFilterInOutByIncludeMultiRule) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { min_level: 2 phase: TEST } " @@ -2052,13 +2052,13 @@ TEST_F(FilterNetTest, TestFilterInByIncludeMultiRule) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 2 phase: TRAIN } " @@ -2066,7 +2066,7 @@ TEST_F(FilterNetTest, TestFilterInByIncludeMultiRule) { "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { min_level: 2 phase: TEST } " @@ -2085,20 +2085,20 @@ TEST_F(FilterNetTest, TestFilterInOutByExcludeMultiRule) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " exclude: { min_level: 2 phase: TRAIN } " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " exclude: { min_level: 2 phase: TEST } " @@ -2112,13 +2112,13 @@ TEST_F(FilterNetTest, TestFilterInOutByExcludeMultiRule) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " exclude: { min_level: 2 phase: TEST } " @@ -2128,13 +2128,13 @@ TEST_F(FilterNetTest, TestFilterInOutByExcludeMultiRule) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " exclude: { min_level: 2 phase: TRAIN } " diff --git a/src/caffe/test/test_protobuf.cpp b/src/caffe/test/test_protobuf.cpp index 0c502d6dd36..01de461afdf 100644 --- a/src/caffe/test/test_protobuf.cpp +++ b/src/caffe/test/test_protobuf.cpp @@ -16,7 +16,7 @@ class ProtoTest : public ::testing::Test {}; TEST_F(ProtoTest, TestSerialization) { LayerParameter param; param.set_name("test"); - param.set_type(LayerParameter_LayerType_NONE); + param.set_type("Test"); std::cout << "Printing in binary format." << std::endl; std::cout << param.SerializeAsString() << std::endl; std::cout << "Printing in text format." << std::endl; diff --git a/src/caffe/test/test_solver.cpp b/src/caffe/test/test_solver.cpp index a7dbf77fd95..d3f646c5bb6 100644 --- a/src/caffe/test/test_solver.cpp +++ b/src/caffe/test/test_solver.cpp @@ -53,7 +53,7 @@ TYPED_TEST(SolverTest, TestInitTrainTestNets) { " name: 'TestNetwork' " " layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 5 " " channels: 3 " @@ -69,7 +69,7 @@ TYPED_TEST(SolverTest, TestInitTrainTestNets) { " } " " layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " } " @@ -78,7 +78,7 @@ TYPED_TEST(SolverTest, TestInitTrainTestNets) { " } " " layers: { " " name: 'accuracy' " - " type: ACCURACY " + " type: 'Accuracy' " " bottom: 'innerprod' " " bottom: 'label' " " top: 'accuracy' " @@ -86,7 +86,7 @@ TYPED_TEST(SolverTest, TestInitTrainTestNets) { " } " " layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " " include: { phase: TRAIN } " diff --git a/src/caffe/test/test_split_layer.cpp b/src/caffe/test/test_split_layer.cpp index 38e762195a2..584d0a4ab9c 100644 --- a/src/caffe/test/test_split_layer.cpp +++ b/src/caffe/test/test_split_layer.cpp @@ -116,19 +116,19 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertion1) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -140,32 +140,32 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertion2) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'data_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'data' " " top: 'data_split_0' " " top: 'data_split_1' " "} " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_split_0' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_split_1' " " top: 'innerprod2' " "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod2' " "} "; @@ -177,7 +177,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "name: 'CaffeNet' " "layers { " " name: 'data' " - " type: DATA " + " type: 'Data' " " data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -192,7 +192,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'conv1' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 96 " " kernel_size: 11 " @@ -215,13 +215,13 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'relu1' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv1' " " top: 'conv1' " "} " "layers { " " name: 'pool1' " - " type: POOLING " + " type: 'Pooling' " " pooling_param { " " pool: MAX " " kernel_size: 3 " @@ -232,7 +232,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'norm1' " - " type: LRN " + " type: 'LRN' " " lrn_param { " " local_size: 5 " " alpha: 0.0001 " @@ -243,7 +243,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'conv2' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 256 " " group: 2 " @@ -267,13 +267,13 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'relu2' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv2' " " top: 'conv2' " "} " "layers { " " name: 'pool2' " - " type: POOLING " + " type: 'Pooling' " " pooling_param { " " pool: MAX " " kernel_size: 3 " @@ -284,7 +284,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'norm2' " - " type: LRN " + " type: 'LRN' " " lrn_param { " " local_size: 5 " " alpha: 0.0001 " @@ -295,7 +295,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'conv3' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 384 " " kernel_size: 3 " @@ -318,13 +318,13 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'relu3' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv3' " " top: 'conv3' " "} " "layers { " " name: 'conv4' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 384 " " group: 2 " @@ -348,13 +348,13 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'relu4' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv4' " " top: 'conv4' " "} " "layers { " " name: 'conv5' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 256 " " group: 2 " @@ -378,13 +378,13 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'relu5' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv5' " " top: 'conv5' " "} " "layers { " " name: 'pool5' " - " type: POOLING " + " type: 'Pooling' " " pooling_param { " " kernel_size: 3 " " pool: MAX " @@ -395,7 +395,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'fc6' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 4096 " " weight_filler { " @@ -416,13 +416,13 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'relu6' " - " type: RELU " + " type: 'ReLU' " " bottom: 'fc6' " " top: 'fc6' " "} " "layers { " " name: 'drop6' " - " type: DROPOUT " + " type: 'Dropout' " " dropout_param { " " dropout_ratio: 0.5 " " } " @@ -431,7 +431,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'fc7' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 4096 " " weight_filler { " @@ -452,13 +452,13 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'relu7' " - " type: RELU " + " type: 'ReLU' " " bottom: 'fc7' " " top: 'fc7' " "} " "layers { " " name: 'drop7' " - " type: DROPOUT " + " type: 'Dropout' " " dropout_param { " " dropout_ratio: 0.5 " " } " @@ -467,7 +467,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'fc8' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 1000 " " weight_filler { " @@ -488,7 +488,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { "} " "layers { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'fc8' " " bottom: 'label' " "} "; @@ -500,25 +500,25 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionWithInPlace) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " "layers: { " " name: 'relu' " - " type: RELU " + " type: 'ReLU' " " bottom: 'innerprod' " " top: 'innerprod' " "} " "layers: { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " " bottom: 'label' " "} "; @@ -531,7 +531,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "force_backward: true " "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 5 " " channels: 2 " @@ -546,7 +546,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "} " "layers: { " " name: 'innerproduct1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -562,7 +562,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "} " "layers: { " " name: 'innerproduct2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -577,7 +577,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerproduct1' " " bottom: 'innerproduct2' " "} "; @@ -586,7 +586,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "force_backward: true " "layers: { " " name: 'data' " - " type: DUMMY_DATA " + " type: 'DummyData' " " dummy_data_param { " " num: 5 " " channels: 2 " @@ -601,14 +601,14 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "} " "layers: { " " name: 'data_data_0_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'data' " " top: 'data_data_0_split_0' " " top: 'data_data_0_split_1' " "} " "layers: { " " name: 'innerproduct1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -623,7 +623,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "} " "layers: { " " name: 'innerproduct1_innerproduct1_0_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'innerproduct1' " " top: 'innerproduct1_innerproduct1_0_split_0' " " top: 'innerproduct1_innerproduct1_0_split_1' " @@ -632,7 +632,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "} " "layers: { " " name: 'innerproduct2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: false " @@ -647,7 +647,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerproduct1_innerproduct1_0_split_1' " " bottom: 'innerproduct2' " "} "; @@ -659,37 +659,37 @@ TEST_F(SplitLayerInsertionTest, TestInsertion) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod2' " "} " "layers: { " " name: 'innerprod3' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod3' " "} " "layers: { " " name: 'loss1' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod2' " "} " "layers: { " " name: 'loss2' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod2' " " bottom: 'innerprod3' " "} "; @@ -697,13 +697,13 @@ TEST_F(SplitLayerInsertionTest, TestInsertion) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'data_data_0_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'data' " " top: 'data_data_0_split_0' " " top: 'data_data_0_split_1' " @@ -711,38 +711,38 @@ TEST_F(SplitLayerInsertionTest, TestInsertion) { "} " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_data_0_split_0' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_data_0_split_1' " " top: 'innerprod2' " "} " "layers: { " " name: 'innerprod2_innerprod2_0_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'innerprod2' " " top: 'innerprod2_innerprod2_0_split_0' " " top: 'innerprod2_innerprod2_0_split_1' " "} " "layers: { " " name: 'innerprod3' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_data_0_split_2' " " top: 'innerprod3' " "} " "layers: { " " name: 'loss1' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod2_innerprod2_0_split_0' " "} " "layers: { " " name: 'loss2' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod2_innerprod2_0_split_1' " " bottom: 'innerprod3' " "} "; @@ -754,43 +754,43 @@ TEST_F(SplitLayerInsertionTest, TestInsertionTwoTop) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'label' " " top: 'innerprod2' " "} " "layers: { " " name: 'innerprod3' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod3' " "} " "layers: { " " name: 'innerprod4' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'label' " " top: 'innerprod4' " "} " "layers: { " " name: 'loss1' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod3' " "} " "layers: { " " name: 'loss2' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod2' " " bottom: 'innerprod4' " "} "; @@ -798,57 +798,57 @@ TEST_F(SplitLayerInsertionTest, TestInsertionTwoTop) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'data_data_0_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'data' " " top: 'data_data_0_split_0' " " top: 'data_data_0_split_1' " "} " "layers: { " " name: 'label_data_1_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'label' " " top: 'label_data_1_split_0' " " top: 'label_data_1_split_1' " "} " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_data_0_split_0' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'label_data_1_split_0' " " top: 'innerprod2' " "} " "layers: { " " name: 'innerprod3' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_data_0_split_1' " " top: 'innerprod3' " "} " "layers: { " " name: 'innerprod4' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'label_data_1_split_1' " " top: 'innerprod4' " "} " "layers: { " " name: 'loss1' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod3' " "} " "layers: { " " name: 'loss2' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod2' " " bottom: 'innerprod4' " "} "; @@ -865,19 +865,19 @@ TEST_F(SplitLayerInsertionTest, TestInputInsertion) { "input_dim: 227 " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod2' " "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod2' " "} "; @@ -890,26 +890,26 @@ TEST_F(SplitLayerInsertionTest, TestInputInsertion) { "input_dim: 227 " "layers: { " " name: 'data_input_0_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'data' " " top: 'data_input_0_split_0' " " top: 'data_input_0_split_1' " "} " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_input_0_split_0' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_input_0_split_1' " " top: 'innerprod2' " "} " "layers: { " " name: 'loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod2' " "} "; @@ -921,37 +921,37 @@ TEST_F(SplitLayerInsertionTest, TestWithInPlace) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod1' " "} " "layers: { " " name: 'relu1' " - " type: RELU " + " type: 'ReLU' " " bottom: 'innerprod1' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'innerprod1' " " top: 'innerprod2' " "} " "layers: { " " name: 'loss1' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'label' " "} " "layers: { " " name: 'loss2' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod2' " " bottom: 'data' " "} "; @@ -959,51 +959,51 @@ TEST_F(SplitLayerInsertionTest, TestWithInPlace) { "name: 'TestNetwork' " "layers: { " " name: 'data' " - " type: DATA " + " type: 'Data' " " top: 'data' " " top: 'label' " "} " "layers: { " " name: 'data_data_0_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'data' " " top: 'data_data_0_split_0' " " top: 'data_data_0_split_1' " "} " "layers: { " " name: 'innerprod1' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'data_data_0_split_0' " " top: 'innerprod1' " "} " "layers: { " " name: 'relu1' " - " type: RELU " + " type: 'ReLU' " " bottom: 'innerprod1' " " top: 'innerprod1' " "} " "layers: { " " name: 'innerprod1_relu1_0_split' " - " type: SPLIT " + " type: 'Split' " " bottom: 'innerprod1' " " top: 'innerprod1_relu1_0_split_0' " " top: 'innerprod1_relu1_0_split_1' " "} " "layers: { " " name: 'innerprod2' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " bottom: 'innerprod1_relu1_0_split_0' " " top: 'innerprod2' " "} " "layers: { " " name: 'loss1' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod1_relu1_0_split_1' " " bottom: 'label' " "} " "layers: { " " name: 'loss2' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " " bottom: 'innerprod2' " " bottom: 'data_data_0_split_1' " "} "; diff --git a/src/caffe/test/test_upgrade_proto.cpp b/src/caffe/test/test_upgrade_proto.cpp index 52e7f1f99f5..e520b85f291 100644 --- a/src/caffe/test/test_upgrade_proto.cpp +++ b/src/caffe/test/test_upgrade_proto.cpp @@ -1184,7 +1184,7 @@ TEST_F(V0UpgradeTest, TestSimple) { "name: 'CaffeNet' " "layers { " " name: 'data' " - " type: DATA " + " type: 'Data' " " data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -1199,7 +1199,7 @@ TEST_F(V0UpgradeTest, TestSimple) { "} " "layers { " " name: 'conv1' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 96 " " kernel_size: 11 " @@ -1223,7 +1223,7 @@ TEST_F(V0UpgradeTest, TestSimple) { "} " "layers { " " name: 'fc8' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 1000 " " weight_filler { " @@ -1244,7 +1244,7 @@ TEST_F(V0UpgradeTest, TestSimple) { "} " "layers { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'fc8' " " bottom: 'label' " "} "; @@ -1520,7 +1520,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "input_dim: 32 " "layers { " " name: 'data' " - " type: DATA " + " type: 'Data' " " data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -1537,7 +1537,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'images' " - " type: IMAGE_DATA " + " type: 'ImageData' " " image_data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-images' " " batch_size: 256 " @@ -1557,7 +1557,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'window_data' " - " type: WINDOW_DATA " + " type: 'WindowData' " " window_data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -1577,7 +1577,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'hdf5data' " - " type: HDF5_DATA " + " type: 'HDF5Data' " " hdf5_data_param { " " source: '/my/hdf5/data' " " batch_size: 256 " @@ -1586,7 +1586,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'conv1' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 96 " " bias_term: false " @@ -1611,7 +1611,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'pool1ave' " - " type: POOLING " + " type: 'Pooling' " " pooling_param { " " pool: AVE " " kernel_size: 3 " @@ -1622,7 +1622,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'pool1stoch' " - " type: POOLING " + " type: 'Pooling' " " pooling_param { " " pool: STOCHASTIC " " kernel_size: 4 " @@ -1633,7 +1633,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'concat' " - " type: CONCAT " + " type: 'Concat' " " concat_param { " " concat_dim: 2 " " } " @@ -1643,7 +1643,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'norm1' " - " type: LRN " + " type: 'LRN' " " lrn_param { " " local_size: 5 " " alpha: 0.0001 " @@ -1654,7 +1654,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'fc6' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 4096 " " bias_term: false " @@ -1676,13 +1676,13 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'relu6' " - " type: RELU " + " type: 'ReLU' " " bottom: 'fc6' " " top: 'fc6' " "} " "layers { " " name: 'drop6' " - " type: DROPOUT " + " type: 'Dropout' " " dropout_param { " " dropout_ratio: 0.2 " " } " @@ -1691,7 +1691,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'loss' " - " type: INFOGAIN_LOSS " + " type: 'InfogainLoss' " " infogain_loss_param { " " source: '/my/infogain/matrix' " " } " @@ -1700,54 +1700,54 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'accuracy' " - " type: ACCURACY " + " type: 'Accuracy' " "} " "layers { " " name: 'bnll' " - " type: BNLL " + " type: 'BNLL' " "} " "layers { " " name: 'euclidean_loss' " - " type: EUCLIDEAN_LOSS " + " type: 'EuclideanLoss' " "} " "layers { " " name: 'flatten' " - " type: FLATTEN " + " type: 'Flatten' " "} " "layers { " " name: 'hdf5_output' " - " type: HDF5_OUTPUT " + " type: 'HDF5Output' " " hdf5_output_param { " " file_name: '/my/hdf5/output/file' " " } " "} " "layers { " " name: 'im2col' " - " type: IM2COL " + " type: 'Im2Col' " "} " "layers { " " name: 'images' " - " type: IMAGE_DATA " + " type: 'ImageData' " "} " "layers { " " name: 'multinomial_logistic_loss' " - " type: MULTINOMIAL_LOGISTIC_LOSS " + " type: 'MultinomialLogisticLoss' " "} " "layers { " " name: 'sigmoid' " - " type: SIGMOID " + " type: 'Sigmoid' " "} " "layers { " " name: 'softmax' " - " type: SOFTMAX " + " type: 'Softmax' " "} " "layers { " " name: 'split' " - " type: SPLIT " + " type: 'Split' " "} " "layers { " " name: 'tanh' " - " type: TANH " + " type: 'TanH' " "} "; this->RunV0UpgradeTest(input_proto, expected_output_proto); } @@ -2122,7 +2122,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "name: 'CaffeNet' " "layers { " " name: 'data' " - " type: DATA " + " type: 'Data' " " data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -2137,7 +2137,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'conv1' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 96 " " kernel_size: 11 " @@ -2160,13 +2160,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu1' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv1' " " top: 'conv1' " "} " "layers { " " name: 'pool1' " - " type: POOLING " + " type: 'Pooling' " " pooling_param { " " pool: MAX " " kernel_size: 3 " @@ -2177,7 +2177,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'norm1' " - " type: LRN " + " type: 'LRN' " " lrn_param { " " local_size: 5 " " alpha: 0.0001 " @@ -2188,7 +2188,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'conv2' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 256 " " group: 2 " @@ -2212,13 +2212,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu2' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv2' " " top: 'conv2' " "} " "layers { " " name: 'pool2' " - " type: POOLING " + " type: 'Pooling' " " pooling_param { " " pool: MAX " " kernel_size: 3 " @@ -2229,7 +2229,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'norm2' " - " type: LRN " + " type: 'LRN' " " lrn_param { " " local_size: 5 " " alpha: 0.0001 " @@ -2240,7 +2240,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'conv3' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 384 " " kernel_size: 3 " @@ -2263,13 +2263,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu3' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv3' " " top: 'conv3' " "} " "layers { " " name: 'conv4' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 384 " " group: 2 " @@ -2293,13 +2293,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu4' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv4' " " top: 'conv4' " "} " "layers { " " name: 'conv5' " - " type: CONVOLUTION " + " type: 'Convolution' " " convolution_param { " " num_output: 256 " " group: 2 " @@ -2323,13 +2323,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu5' " - " type: RELU " + " type: 'ReLU' " " bottom: 'conv5' " " top: 'conv5' " "} " "layers { " " name: 'pool5' " - " type: POOLING " + " type: 'Pooling' " " pooling_param { " " kernel_size: 3 " " pool: MAX " @@ -2340,7 +2340,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'fc6' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 4096 " " weight_filler { " @@ -2361,13 +2361,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu6' " - " type: RELU " + " type: 'ReLU' " " bottom: 'fc6' " " top: 'fc6' " "} " "layers { " " name: 'drop6' " - " type: DROPOUT " + " type: 'Dropout' " " dropout_param { " " dropout_ratio: 0.5 " " } " @@ -2376,7 +2376,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'fc7' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 4096 " " weight_filler { " @@ -2397,13 +2397,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu7' " - " type: RELU " + " type: 'ReLU' " " bottom: 'fc7' " " top: 'fc7' " "} " "layers { " " name: 'drop7' " - " type: DROPOUT " + " type: 'Dropout' " " dropout_param { " " dropout_ratio: 0.5 " " } " @@ -2412,7 +2412,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'fc8' " - " type: INNER_PRODUCT " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 1000 " " weight_filler { " @@ -2433,7 +2433,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'loss' " - " type: SOFTMAX_LOSS " + " type: 'SoftmaxWithLoss' " " bottom: 'fc8' " " bottom: 'label' " "} "; diff --git a/src/caffe/util/insert_splits.cpp b/src/caffe/util/insert_splits.cpp index f20efdae8c6..8a0ad53ed2b 100644 --- a/src/caffe/util/insert_splits.cpp +++ b/src/caffe/util/insert_splits.cpp @@ -111,7 +111,7 @@ void ConfigureSplitLayer(const string& layer_name, const string& blob_name, split_layer_param->Clear(); split_layer_param->add_bottom(blob_name); split_layer_param->set_name(SplitLayerName(layer_name, blob_name, blob_idx)); - split_layer_param->set_type(LayerParameter_LayerType_SPLIT); + split_layer_param->set_type("Split"); for (int k = 0; k < split_count; ++k) { split_layer_param->add_top( SplitBlobName(layer_name, blob_name, blob_idx, k)); diff --git a/src/caffe/util/upgrade_proto.cpp b/src/caffe/util/upgrade_proto.cpp index cbd6003c948..31e7d4db298 100644 --- a/src/caffe/util/upgrade_proto.cpp +++ b/src/caffe/util/upgrade_proto.cpp @@ -459,78 +459,78 @@ bool UpgradeLayerParameter(const LayerParameter& v0_layer_connection, return is_fully_compatible; } -LayerParameter_LayerType UpgradeV0LayerType(const string& type) { +const char* UpgradeV0LayerType(const string& type) { if (type == "accuracy") { - return LayerParameter_LayerType_ACCURACY; + return "Accuracy"; } else if (type == "bnll") { - return LayerParameter_LayerType_BNLL; + return "BNLL"; } else if (type == "concat") { - return LayerParameter_LayerType_CONCAT; + return "Concat"; } else if (type == "conv") { - return LayerParameter_LayerType_CONVOLUTION; + return "Convolution"; } else if (type == "data") { - return LayerParameter_LayerType_DATA; + return "Data"; } else if (type == "dropout") { - return LayerParameter_LayerType_DROPOUT; + return "Dropout"; } else if (type == "euclidean_loss") { - return LayerParameter_LayerType_EUCLIDEAN_LOSS; + return "EuclideanLoss"; } else if (type == "flatten") { - return LayerParameter_LayerType_FLATTEN; + return "Flatten"; } else if (type == "hdf5_data") { - return LayerParameter_LayerType_HDF5_DATA; + return "HDF5Data"; } else if (type == "hdf5_output") { - return LayerParameter_LayerType_HDF5_OUTPUT; + return "HDF5Output"; } else if (type == "im2col") { - return LayerParameter_LayerType_IM2COL; + return "Im2Col"; } else if (type == "images") { - return LayerParameter_LayerType_IMAGE_DATA; + return "ImageData"; } else if (type == "infogain_loss") { - return LayerParameter_LayerType_INFOGAIN_LOSS; + return "InfogainLoss"; } else if (type == "innerproduct") { - return LayerParameter_LayerType_INNER_PRODUCT; + return "InnerProduct"; } else if (type == "lrn") { - return LayerParameter_LayerType_LRN; + return "LRN"; } else if (type == "multinomial_logistic_loss") { - return LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS; + return "MultinomialLogisticLoss"; } else if (type == "pool") { - return LayerParameter_LayerType_POOLING; + return "Pooling"; } else if (type == "relu") { - return LayerParameter_LayerType_RELU; + return "ReLU"; } else if (type == "sigmoid") { - return LayerParameter_LayerType_SIGMOID; + return "Sigmoid"; } else if (type == "softmax") { - return LayerParameter_LayerType_SOFTMAX; + return "Softmax"; } else if (type == "softmax_loss") { - return LayerParameter_LayerType_SOFTMAX_LOSS; + return "SoftmaxWithLoss"; } else if (type == "split") { - return LayerParameter_LayerType_SPLIT; + return "Split"; } else if (type == "tanh") { - return LayerParameter_LayerType_TANH; + return "TanH"; } else if (type == "window_data") { - return LayerParameter_LayerType_WINDOW_DATA; + return "WindowData"; } else { - LOG(FATAL) << "Unknown layer name: " << type; - return LayerParameter_LayerType_NONE; + LOG(FATAL) << "Unknown layer type: " << type; + return ""; } } bool NetNeedsDataUpgrade(const NetParameter& net_param) { for (int i = 0; i < net_param.layers_size(); ++i) { - if (net_param.layers(i).type() == LayerParameter_LayerType_DATA) { + if (net_param.layers(i).type() == "Data") { DataParameter layer_param = net_param.layers(i).data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } if (layer_param.has_crop_size()) { return true; } if (layer_param.has_mirror()) { return true; } } - if (net_param.layers(i).type() == LayerParameter_LayerType_IMAGE_DATA) { + if (net_param.layers(i).type() == "ImageData") { ImageDataParameter layer_param = net_param.layers(i).image_data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } if (layer_param.has_crop_size()) { return true; } if (layer_param.has_mirror()) { return true; } } - if (net_param.layers(i).type() == LayerParameter_LayerType_WINDOW_DATA) { + if (net_param.layers(i).type() == "WindowData") { WindowDataParameter layer_param = net_param.layers(i).window_data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } @@ -541,11 +541,11 @@ bool NetNeedsDataUpgrade(const NetParameter& net_param) { return false; } -#define CONVERT_LAYER_TRANSFORM_PARAM(TYPE, Name, param_name) \ +#define CONVERT_LAYER_TRANSFORM_PARAM(TYPE_NAME, PARAM_NAME) \ do { \ - if (net_param->layers(i).type() == LayerParameter_LayerType_##TYPE) { \ - Name##Parameter* layer_param = \ - net_param->mutable_layers(i)->mutable_##param_name##_param(); \ + if (net_param->layers(i).type() == #TYPE_NAME) { \ + TYPE_NAME##Parameter* layer_param = \ + net_param->mutable_layers(i)->mutable_##PARAM_NAME##_param(); \ TransformationParameter* transform_param = \ net_param->mutable_layers(i)->mutable_transform_param(); \ if (layer_param->has_scale()) { \ @@ -569,9 +569,9 @@ bool NetNeedsDataUpgrade(const NetParameter& net_param) { void UpgradeNetDataTransformation(NetParameter* net_param) { for (int i = 0; i < net_param->layers_size(); ++i) { - CONVERT_LAYER_TRANSFORM_PARAM(DATA, Data, data); - CONVERT_LAYER_TRANSFORM_PARAM(IMAGE_DATA, ImageData, image_data); - CONVERT_LAYER_TRANSFORM_PARAM(WINDOW_DATA, WindowData, window_data); + CONVERT_LAYER_TRANSFORM_PARAM(Data, data); + CONVERT_LAYER_TRANSFORM_PARAM(ImageData, image_data); + CONVERT_LAYER_TRANSFORM_PARAM(WindowData, window_data); } } From 794cd7fbca367c27ab4303c2f6e05683eed3c117 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 12 Jan 2015 14:27:06 -0800 Subject: [PATCH 271/798] DataLayer and HDF5OutputLayer can be constructed and destroyed without errors --- include/caffe/data_layers.hpp | 6 ++++-- src/caffe/layers/hdf5_output_layer.cpp | 14 ++++++++------ src/caffe/test/test_hdf5_output_layer.cpp | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index e55a0bbbd7b..cdf2d18bb60 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -181,10 +181,11 @@ class HDF5DataLayer : public Layer { template class HDF5OutputLayer : public Layer { public: - explicit HDF5OutputLayer(const LayerParameter& param); + explicit HDF5OutputLayer(const LayerParameter& param) + : Layer(param), file_opened_(false) {} virtual ~HDF5OutputLayer(); virtual void LayerSetUp(const vector*>& bottom, - const vector*>& top) {} + const vector*>& top); // Data layers have no bottoms, so reshaping is trivial. virtual void Reshape(const vector*>& bottom, const vector*>& top) {} @@ -207,6 +208,7 @@ class HDF5OutputLayer : public Layer { const vector& propagate_down, const vector*>& bottom); virtual void SaveBlobs(); + bool file_opened_; std::string file_name_; hid_t file_id_; Blob data_blob_; diff --git a/src/caffe/layers/hdf5_output_layer.cpp b/src/caffe/layers/hdf5_output_layer.cpp index d2fdeffc53f..f63375c3dc6 100644 --- a/src/caffe/layers/hdf5_output_layer.cpp +++ b/src/caffe/layers/hdf5_output_layer.cpp @@ -12,19 +12,21 @@ namespace caffe { template -HDF5OutputLayer::HDF5OutputLayer(const LayerParameter& param) - : Layer(param), - file_name_(param.hdf5_output_param().file_name()) { - /* create a HDF5 file */ +void HDF5OutputLayer::LayerSetUp(const vector*>& bottom, + const vector*>& top) { + file_name_ = this->layer_param_.hdf5_output_param().file_name(); file_id_ = H5Fcreate(file_name_.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK_GE(file_id_, 0) << "Failed to open HDF5 file" << file_name_; + file_opened_ = true; } template HDF5OutputLayer::~HDF5OutputLayer() { - herr_t status = H5Fclose(file_id_); - CHECK_GE(status, 0) << "Failed to close HDF5 file " << file_name_; + if (file_opened_) { + herr_t status = H5Fclose(file_id_); + CHECK_GE(status, 0) << "Failed to close HDF5 file " << file_name_; + } } template diff --git a/src/caffe/test/test_hdf5_output_layer.cpp b/src/caffe/test/test_hdf5_output_layer.cpp index 2e8f096980a..a23034f284a 100644 --- a/src/caffe/test/test_hdf5_output_layer.cpp +++ b/src/caffe/test/test_hdf5_output_layer.cpp @@ -92,8 +92,8 @@ TYPED_TEST(HDF5OutputLayerTest, TestForward) { // the output hdf5 file is closed. { HDF5OutputLayer layer(param); - EXPECT_EQ(layer.file_name(), this->output_file_name_); layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + EXPECT_EQ(layer.file_name(), this->output_file_name_); layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); } file_id = H5Fopen(this->output_file_name_.c_str(), H5F_ACC_RDONLY, From c7b04c697bf923d13d139a8b162c5dd7d888396c Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 12 Jan 2015 13:42:51 -0800 Subject: [PATCH 272/798] Add unit test for LayerRegistry::CreateLayer --- src/caffe/test/test_layer_factory.cpp | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/caffe/test/test_layer_factory.cpp diff --git a/src/caffe/test/test_layer_factory.cpp b/src/caffe/test/test_layer_factory.cpp new file mode 100644 index 00000000000..3ad635a792a --- /dev/null +++ b/src/caffe/test/test_layer_factory.cpp @@ -0,0 +1,33 @@ +#include +#include + +#include "gtest/gtest.h" + +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/layer_factory.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class LayerFactoryTest : public MultiDeviceTest {}; + +TYPED_TEST_CASE(LayerFactoryTest, TestDtypesAndDevices); + +TYPED_TEST(LayerFactoryTest, TestCreateLayer) { + typedef typename TypeParam::Dtype Dtype; + typename LayerRegistry::CreatorRegistry& registry = + LayerRegistry::Registry(); + shared_ptr > layer; + LayerParameter layer_param; + for (typename LayerRegistry::CreatorRegistry::iterator iter = + registry.begin(); iter != registry.end(); ++iter) { + layer_param.set_type(iter->first); + layer.reset(LayerRegistry::CreateLayer(layer_param)); + EXPECT_EQ(iter->first, layer->type()); + } +} + +} // namespace caffe From af37eac80f01694a4845607bfcede595f50f893f Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 12 Jan 2015 17:02:15 -0800 Subject: [PATCH 273/798] 'layers' -> 'layer' --- src/caffe/net.cpp | 34 ++++++++-------- src/caffe/proto/caffe.proto | 8 +++- src/caffe/proto/caffe_pretty_print.proto | 2 +- src/caffe/util/insert_splits.cpp | 20 ++++----- src/caffe/util/upgrade_proto.cpp | 52 ++++++++++++------------ 5 files changed, 61 insertions(+), 55 deletions(-) diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 4350e056085..db9ac7ddbb3 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -55,14 +55,14 @@ void Net::Init(const NetParameter& in_param) { } DLOG(INFO) << "Memory required for data: " << memory_used_ * sizeof(Dtype); // For each layer, set up their input and output - bottom_vecs_.resize(param.layers_size()); - top_vecs_.resize(param.layers_size()); - bottom_id_vecs_.resize(param.layers_size()); - param_id_vecs_.resize(param.layers_size()); - top_id_vecs_.resize(param.layers_size()); - bottom_need_backward_.resize(param.layers_size()); - for (int layer_id = 0; layer_id < param.layers_size(); ++layer_id) { - const LayerParameter& layer_param = param.layers(layer_id); + bottom_vecs_.resize(param.layer_size()); + top_vecs_.resize(param.layer_size()); + bottom_id_vecs_.resize(param.layer_size()); + param_id_vecs_.resize(param.layer_size()); + top_id_vecs_.resize(param.layer_size()); + bottom_need_backward_.resize(param.layer_size()); + for (int layer_id = 0; layer_id < param.layer_size(); ++layer_id) { + const LayerParameter& layer_param = param.layer(layer_id); layers_.push_back(shared_ptr >( LayerRegistry::CreateLayer(layer_param))); layer_names_.push_back(layer_param.name()); @@ -242,9 +242,9 @@ void Net::FilterNet(const NetParameter& param, } } param_filtered->CopyFrom(param); - param_filtered->clear_layers(); - for (int i = 0; i < param.layers_size(); ++i) { - const LayerParameter& layer_param = param.layers(i); + param_filtered->clear_layer(); + for (int i = 0; i < param.layer_size(); ++i) { + const LayerParameter& layer_param = param.layer(i); const string& layer_name = layer_param.name(); CHECK(layer_param.include_size() == 0 || layer_param.exclude_size() == 0) << "Specify either include rules or exclude rules; not both."; @@ -262,7 +262,7 @@ void Net::FilterNet(const NetParameter& param, } } if (layer_included) { - param_filtered->add_layers()->CopyFrom(layer_param); + param_filtered->add_layer()->CopyFrom(layer_param); } } } @@ -335,7 +335,7 @@ void Net::AppendTop(const NetParameter& param, const int layer_id, const int top_id, set* available_blobs, map* blob_name_to_idx) { shared_ptr layer_param((layer_id >= 0) ? - (new LayerParameter(param.layers(layer_id))) : NULL); + (new LayerParameter(param.layer(layer_id))) : NULL); const string& blob_name = layer_param ? (layer_param->top_size() > top_id ? layer_param->top(top_id) : "(automatic)") : param.input(top_id); @@ -385,7 +385,7 @@ template int Net::AppendBottom(const NetParameter& param, const int layer_id, const int bottom_id, set* available_blobs, map* blob_name_to_idx) { - const LayerParameter& layer_param = param.layers(layer_id); + const LayerParameter& layer_param = param.layer(layer_id); const string& blob_name = layer_param.bottom(bottom_id); if (available_blobs->find(blob_name) == available_blobs->end()) { LOG(FATAL) << "Unknown blob input " << blob_name @@ -730,9 +730,9 @@ void Net::Reshape() { template void Net::CopyTrainedLayersFrom(const NetParameter& param) { - int num_source_layers = param.layers_size(); + int num_source_layers = param.layer_size(); for (int i = 0; i < num_source_layers; ++i) { - const LayerParameter& source_layer = param.layers(i); + const LayerParameter& source_layer = param.layer(i); const string& source_layer_name = source_layer.name(); int target_layer_id = 0; while (target_layer_id != layer_names_.size() && @@ -775,7 +775,7 @@ void Net::ToProto(NetParameter* param, bool write_diff) const { } DLOG(INFO) << "Serializing " << layers_.size() << " layers"; for (int i = 0; i < layers_.size(); ++i) { - LayerParameter* layer_param = param->add_layers(); + LayerParameter* layer_param = param->add_layer(); for (int j = 0; j < bottom_id_vecs_[i].size(); ++j) { layer_param->add_bottom(blob_names_[bottom_id_vecs_[i][j]]); } diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 1fea3445415..c62e7271c0f 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -45,7 +45,6 @@ message FillerParameter { message NetParameter { optional string name = 1; // consider giving the network a name - repeated LayerParameter layers = 2; // a bunch of layers. // The input blobs to the network. repeated string input = 3; // The dim of the input blobs. For each input blob there should be four @@ -64,6 +63,13 @@ message NetParameter { // Print debugging information about results while running Net::Forward, // Net::Backward, and Net::Update. optional bool debug_info = 7 [default = false]; + + // The layers that make up the net. Each of their configurations, including + // connectivity and behavior, is specified as a LayerParameter. + repeated LayerParameter layer = 100; // ID 100 so layers are printed last. + + // DEPRECATED: use 'layer' instead. + // repeated LayerParameter layers = 2; // a bunch of layers. } // NOTE diff --git a/src/caffe/proto/caffe_pretty_print.proto b/src/caffe/proto/caffe_pretty_print.proto index 6f0a5f6b8df..056541f75f1 100644 --- a/src/caffe/proto/caffe_pretty_print.proto +++ b/src/caffe/proto/caffe_pretty_print.proto @@ -14,5 +14,5 @@ message NetParameterPrettyPrint { optional bool force_backward = 2 [default = false]; repeated string input = 3; repeated int32 input_dim = 4; - repeated LayerParameter layers = 5; + repeated LayerParameter layer = 5; } diff --git a/src/caffe/util/insert_splits.cpp b/src/caffe/util/insert_splits.cpp index 8a0ad53ed2b..416f80ab3c2 100644 --- a/src/caffe/util/insert_splits.cpp +++ b/src/caffe/util/insert_splits.cpp @@ -12,7 +12,7 @@ namespace caffe { void InsertSplits(const NetParameter& param, NetParameter* param_split) { // Initialize by copying from the input NetParameter. param_split->CopyFrom(param); - param_split->clear_layers(); + param_split->clear_layer(); map > blob_name_to_last_top_idx; map, pair > bottom_idx_to_source_top_idx; map, int> top_idx_to_bottom_count; @@ -25,8 +25,8 @@ void InsertSplits(const NetParameter& param, NetParameter* param_split) { const string& blob_name = param.input(i); blob_name_to_last_top_idx[blob_name] = make_pair(-1, i); } - for (int i = 0; i < param.layers_size(); ++i) { - const LayerParameter& layer_param = param.layers(i); + for (int i = 0; i < param.layer_size(); ++i) { + const LayerParameter& layer_param = param.layer(i); layer_idx_to_layer_name[i] = layer_param.name(); for (int j = 0; j < layer_param.bottom_size(); ++j) { const string& blob_name = layer_param.bottom(j); @@ -56,22 +56,22 @@ void InsertSplits(const NetParameter& param, NetParameter* param_split) { } } } - // Create split layer for any input blobs used by other layers as bottom + // Create split layer for any input blobs used by other layer as bottom // blobs more than once. for (int i = 0; i < param.input_size(); ++i) { const int split_count = top_idx_to_bottom_count[make_pair(-1, i)]; if (split_count > 1) { const string& layer_name = layer_idx_to_layer_name[-1]; const string& blob_name = param.input(i); - LayerParameter* split_layer_param = param_split->add_layers(); + LayerParameter* split_layer_param = param_split->add_layer(); const float kZeroLossWeight = 0; ConfigureSplitLayer(layer_name, blob_name, i, split_count, kZeroLossWeight, split_layer_param); } } - for (int i = 0; i < param.layers_size(); ++i) { - LayerParameter* layer_param = param_split->add_layers(); - layer_param->CopyFrom(param.layers(i)); + for (int i = 0; i < param.layer_size(); ++i) { + LayerParameter* layer_param = param_split->add_layer(); + layer_param->CopyFrom(param.layer(i)); // Replace any shared bottom blobs with split layer outputs. for (int j = 0; j < layer_param->bottom_size(); ++j) { const pair& top_idx = @@ -84,7 +84,7 @@ void InsertSplits(const NetParameter& param, NetParameter* param_split) { blob_name, top_idx.second, top_idx_to_bottom_split_idx[top_idx]++)); } } - // Create split layer for any top blobs used by other layers as bottom + // Create split layer for any top blobs used by other layer as bottom // blobs more than once. for (int j = 0; j < layer_param->top_size(); ++j) { const pair& top_idx = make_pair(i, j); @@ -92,7 +92,7 @@ void InsertSplits(const NetParameter& param, NetParameter* param_split) { if (split_count > 1) { const string& layer_name = layer_idx_to_layer_name[i]; const string& blob_name = layer_param->top(j); - LayerParameter* split_layer_param = param_split->add_layers(); + LayerParameter* split_layer_param = param_split->add_layer(); const float loss_weight = top_idx_to_loss_weight[top_idx]; ConfigureSplitLayer(layer_name, blob_name, j, split_count, loss_weight, split_layer_param); diff --git a/src/caffe/util/upgrade_proto.cpp b/src/caffe/util/upgrade_proto.cpp index 31e7d4db298..352d08e90e3 100644 --- a/src/caffe/util/upgrade_proto.cpp +++ b/src/caffe/util/upgrade_proto.cpp @@ -13,8 +13,8 @@ namespace caffe { bool NetNeedsUpgrade(const NetParameter& net_param) { - for (int i = 0; i < net_param.layers_size(); ++i) { - if (net_param.layers(i).has_layer()) { + for (int i = 0; i < net_param.layer_size(); ++i) { + if (net_param.layer(i).has_layer()) { return true; } } @@ -32,9 +32,9 @@ bool UpgradeV0Net(const NetParameter& v0_net_param_padding_layers, if (v0_net_param.has_name()) { net_param->set_name(v0_net_param.name()); } - for (int i = 0; i < v0_net_param.layers_size(); ++i) { - is_fully_compatible &= UpgradeLayerParameter(v0_net_param.layers(i), - net_param->add_layers()); + for (int i = 0; i < v0_net_param.layer_size(); ++i) { + is_fully_compatible &= UpgradeLayerParameter(v0_net_param.layer(i), + net_param->add_layer()); } for (int i = 0; i < v0_net_param.input_size(); ++i) { net_param->add_input(v0_net_param.input(i)); @@ -53,19 +53,19 @@ void UpgradeV0PaddingLayers(const NetParameter& param, // Copy everything other than the layers from the original param. param_upgraded_pad->Clear(); param_upgraded_pad->CopyFrom(param); - param_upgraded_pad->clear_layers(); + param_upgraded_pad->clear_layer(); // Figure out which layer each bottom blob comes from. map blob_name_to_last_top_idx; for (int i = 0; i < param.input_size(); ++i) { const string& blob_name = param.input(i); blob_name_to_last_top_idx[blob_name] = -1; } - for (int i = 0; i < param.layers_size(); ++i) { - const LayerParameter& layer_connection = param.layers(i); + for (int i = 0; i < param.layer_size(); ++i) { + const LayerParameter& layer_connection = param.layer(i); const V0LayerParameter& layer_param = layer_connection.layer(); // Add the layer to the new net, unless it's a padding layer. if (layer_param.type() != "padding") { - param_upgraded_pad->add_layers()->CopyFrom(layer_connection); + param_upgraded_pad->add_layer()->CopyFrom(layer_connection); } for (int j = 0; j < layer_connection.bottom_size(); ++j) { const string& blob_name = layer_connection.bottom(j); @@ -77,7 +77,7 @@ void UpgradeV0PaddingLayers(const NetParameter& param, if (top_idx == -1) { continue; } - LayerParameter source_layer = param.layers(top_idx); + LayerParameter source_layer = param.layer(top_idx); if (source_layer.layer().type() == "padding") { // This layer has a padding layer as input -- check that it is a conv // layer or a pooling layer and takes only one input. Also check that @@ -93,10 +93,10 @@ void UpgradeV0PaddingLayers(const NetParameter& param, << "Padding Layer takes a single blob as input."; CHECK_EQ(source_layer.top_size(), 1) << "Padding Layer produces a single blob as output."; - int layer_index = param_upgraded_pad->layers_size() - 1; - param_upgraded_pad->mutable_layers(layer_index)->mutable_layer() + int layer_index = param_upgraded_pad->layer_size() - 1; + param_upgraded_pad->mutable_layer(layer_index)->mutable_layer() ->set_pad(source_layer.layer().pad()); - param_upgraded_pad->mutable_layers(layer_index) + param_upgraded_pad->mutable_layer(layer_index) ->set_bottom(j, source_layer.bottom(0)); } } @@ -515,23 +515,23 @@ const char* UpgradeV0LayerType(const string& type) { } bool NetNeedsDataUpgrade(const NetParameter& net_param) { - for (int i = 0; i < net_param.layers_size(); ++i) { - if (net_param.layers(i).type() == "Data") { - DataParameter layer_param = net_param.layers(i).data_param(); + for (int i = 0; i < net_param.layer_size(); ++i) { + if (net_param.layer(i).type() == "Data") { + DataParameter layer_param = net_param.layer(i).data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } if (layer_param.has_crop_size()) { return true; } if (layer_param.has_mirror()) { return true; } } - if (net_param.layers(i).type() == "ImageData") { - ImageDataParameter layer_param = net_param.layers(i).image_data_param(); + if (net_param.layer(i).type() == "ImageData") { + ImageDataParameter layer_param = net_param.layer(i).image_data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } if (layer_param.has_crop_size()) { return true; } if (layer_param.has_mirror()) { return true; } } - if (net_param.layers(i).type() == "WindowData") { - WindowDataParameter layer_param = net_param.layers(i).window_data_param(); + if (net_param.layer(i).type() == "WindowData") { + WindowDataParameter layer_param = net_param.layer(i).window_data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } if (layer_param.has_crop_size()) { return true; } @@ -543,11 +543,11 @@ bool NetNeedsDataUpgrade(const NetParameter& net_param) { #define CONVERT_LAYER_TRANSFORM_PARAM(TYPE_NAME, PARAM_NAME) \ do { \ - if (net_param->layers(i).type() == #TYPE_NAME) { \ + if (net_param->layer(i).type() == #TYPE_NAME) { \ TYPE_NAME##Parameter* layer_param = \ - net_param->mutable_layers(i)->mutable_##PARAM_NAME##_param(); \ + net_param->mutable_layer(i)->mutable_##PARAM_NAME##_param(); \ TransformationParameter* transform_param = \ - net_param->mutable_layers(i)->mutable_transform_param(); \ + net_param->mutable_layer(i)->mutable_transform_param(); \ if (layer_param->has_scale()) { \ transform_param->set_scale(layer_param->scale()); \ layer_param->clear_scale(); \ @@ -568,7 +568,7 @@ bool NetNeedsDataUpgrade(const NetParameter& net_param) { } while (0) void UpgradeNetDataTransformation(NetParameter* net_param) { - for (int i = 0; i < net_param->layers_size(); ++i) { + for (int i = 0; i < net_param->layer_size(); ++i) { CONVERT_LAYER_TRANSFORM_PARAM(Data, data); CONVERT_LAYER_TRANSFORM_PARAM(ImageData, image_data); CONVERT_LAYER_TRANSFORM_PARAM(WindowData, window_data); @@ -590,8 +590,8 @@ void NetParameterToPrettyPrint(const NetParameter& param, for (int i = 0; i < param.input_dim_size(); ++i) { pretty_param->add_input_dim(param.input_dim(i)); } - for (int i = 0; i < param.layers_size(); ++i) { - pretty_param->add_layers()->CopyFrom(param.layers(i)); + for (int i = 0; i < param.layer_size(); ++i) { + pretty_param->add_layer()->CopyFrom(param.layer(i)); } } From bb5ba1b7e025d4bb2a0fc3caedbe17e288b266c4 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 14 Jan 2015 15:07:20 -0800 Subject: [PATCH 274/798] restore upgrade_proto --- include/caffe/util/upgrade_proto.hpp | 6 +- src/caffe/proto/caffe.proto | 98 ++++++++++++++++++++-- src/caffe/util/upgrade_proto.cpp | 118 +++++++++++++-------------- 3 files changed, 154 insertions(+), 68 deletions(-) diff --git a/include/caffe/util/upgrade_proto.hpp b/include/caffe/util/upgrade_proto.hpp index 0627afe694c..e89756ed055 100644 --- a/include/caffe/util/upgrade_proto.hpp +++ b/include/caffe/util/upgrade_proto.hpp @@ -24,10 +24,10 @@ void UpgradeV0PaddingLayers(const NetParameter& param, NetParameter* param_upgraded_pad); // Upgrade a single V0LayerConnection to the new LayerParameter format. -bool UpgradeLayerParameter(const LayerParameter& v0_layer_connection, - LayerParameter* layer_param); +bool UpgradeLayerParameter(const V1LayerParameter& v0_layer_connection, + V1LayerParameter* layer_param); -const char* UpgradeV0LayerType(const string& type); +V1LayerParameter_LayerType UpgradeV0LayerType(const string& type); // Return true iff any layer contains deprecated data transformation parameters. bool NetNeedsDataUpgrade(const NetParameter& net_param); diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index c62e7271c0f..d81acf309f4 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -69,7 +69,7 @@ message NetParameter { repeated LayerParameter layer = 100; // ID 100 so layers are printed last. // DEPRECATED: use 'layer' instead. - // repeated LayerParameter layers = 2; // a bunch of layers. + repeated V1LayerParameter layers = 2; } // NOTE @@ -297,11 +297,6 @@ message LayerParameter { // for their implementation. These layers include an Engine type and // engine parameter for selecting the implementation. // The default for the engine is set by the ENGINE switch at compile-time. - - // DEPRECATED: The layer parameters specified as a V0LayerParameter. - // This should never be used by any code except to upgrade to the new - // LayerParameter specification. - optional V0LayerParameter layer = 1; } // Message that stores parameters used to apply transformation @@ -695,6 +690,97 @@ message WindowDataParameter { optional string root_folder = 13 [default = ""]; } +// DEPRECATED: use LayerParameter. +message V1LayerParameter { + repeated string bottom = 2; + repeated string top = 3; + optional string name = 4; + repeated NetStateRule include = 32; + repeated NetStateRule exclude = 33; + enum LayerType { + NONE = 0; + ABSVAL = 35; + ACCURACY = 1; + ARGMAX = 30; + BNLL = 2; + CONCAT = 3; + CONTRASTIVE_LOSS = 37; + CONVOLUTION = 4; + DATA = 5; + DROPOUT = 6; + DUMMY_DATA = 32; + EUCLIDEAN_LOSS = 7; + ELTWISE = 25; + EXP = 38; + FLATTEN = 8; + HDF5_DATA = 9; + HDF5_OUTPUT = 10; + HINGE_LOSS = 28; + IM2COL = 11; + IMAGE_DATA = 12; + INFOGAIN_LOSS = 13; + INNER_PRODUCT = 14; + LRN = 15; + MEMORY_DATA = 29; + MULTINOMIAL_LOGISTIC_LOSS = 16; + MVN = 34; + POOLING = 17; + POWER = 26; + RELU = 18; + SIGMOID = 19; + SIGMOID_CROSS_ENTROPY_LOSS = 27; + SILENCE = 36; + SOFTMAX = 20; + SOFTMAX_LOSS = 21; + SPLIT = 22; + SLICE = 33; + TANH = 23; + WINDOW_DATA = 24; + THRESHOLD = 31; + } + optional LayerType type = 5; + repeated BlobProto blobs = 6; + repeated string param = 1001; + repeated DimCheckMode blob_share_mode = 1002; + enum DimCheckMode { + STRICT = 0; + PERMISSIVE = 1; + } + repeated float blobs_lr = 7; + repeated float weight_decay = 8; + repeated float loss_weight = 35; + optional AccuracyParameter accuracy_param = 27; + optional ArgMaxParameter argmax_param = 23; + optional ConcatParameter concat_param = 9; + optional ContrastiveLossParameter contrastive_loss_param = 40; + optional ConvolutionParameter convolution_param = 10; + optional DataParameter data_param = 11; + optional DropoutParameter dropout_param = 12; + optional DummyDataParameter dummy_data_param = 26; + optional EltwiseParameter eltwise_param = 24; + optional ExpParameter exp_param = 41; + optional HDF5DataParameter hdf5_data_param = 13; + optional HDF5OutputParameter hdf5_output_param = 14; + optional HingeLossParameter hinge_loss_param = 29; + optional ImageDataParameter image_data_param = 15; + optional InfogainLossParameter infogain_loss_param = 16; + optional InnerProductParameter inner_product_param = 17; + optional LRNParameter lrn_param = 18; + optional MemoryDataParameter memory_data_param = 22; + optional MVNParameter mvn_param = 34; + optional PoolingParameter pooling_param = 19; + optional PowerParameter power_param = 21; + optional ReLUParameter relu_param = 30; + optional SigmoidParameter sigmoid_param = 38; + optional SoftmaxParameter softmax_param = 39; + optional SliceParameter slice_param = 31; + optional TanHParameter tanh_param = 37; + optional ThresholdParameter threshold_param = 25; + optional WindowDataParameter window_data_param = 20; + optional TransformationParameter transform_param = 36; + optional V0LayerParameter layer = 1; +} + // DEPRECATED: V0LayerParameter is the old way of specifying layer parameters // in Caffe. We keep this message type around for legacy support. message V0LayerParameter { diff --git a/src/caffe/util/upgrade_proto.cpp b/src/caffe/util/upgrade_proto.cpp index 352d08e90e3..16583b0f0ca 100644 --- a/src/caffe/util/upgrade_proto.cpp +++ b/src/caffe/util/upgrade_proto.cpp @@ -13,8 +13,8 @@ namespace caffe { bool NetNeedsUpgrade(const NetParameter& net_param) { - for (int i = 0; i < net_param.layer_size(); ++i) { - if (net_param.layer(i).has_layer()) { + for (int i = 0; i < net_param.layers_size(); ++i) { + if (net_param.layers(i).has_layer()) { return true; } } @@ -32,9 +32,9 @@ bool UpgradeV0Net(const NetParameter& v0_net_param_padding_layers, if (v0_net_param.has_name()) { net_param->set_name(v0_net_param.name()); } - for (int i = 0; i < v0_net_param.layer_size(); ++i) { - is_fully_compatible &= UpgradeLayerParameter(v0_net_param.layer(i), - net_param->add_layer()); + for (int i = 0; i < v0_net_param.layers_size(); ++i) { + is_fully_compatible &= UpgradeLayerParameter(v0_net_param.layers(i), + net_param->add_layers()); } for (int i = 0; i < v0_net_param.input_size(); ++i) { net_param->add_input(v0_net_param.input(i)); @@ -53,19 +53,19 @@ void UpgradeV0PaddingLayers(const NetParameter& param, // Copy everything other than the layers from the original param. param_upgraded_pad->Clear(); param_upgraded_pad->CopyFrom(param); - param_upgraded_pad->clear_layer(); + param_upgraded_pad->clear_layers(); // Figure out which layer each bottom blob comes from. map blob_name_to_last_top_idx; for (int i = 0; i < param.input_size(); ++i) { const string& blob_name = param.input(i); blob_name_to_last_top_idx[blob_name] = -1; } - for (int i = 0; i < param.layer_size(); ++i) { - const LayerParameter& layer_connection = param.layer(i); + for (int i = 0; i < param.layers_size(); ++i) { + const V1LayerParameter& layer_connection = param.layers(i); const V0LayerParameter& layer_param = layer_connection.layer(); // Add the layer to the new net, unless it's a padding layer. if (layer_param.type() != "padding") { - param_upgraded_pad->add_layer()->CopyFrom(layer_connection); + param_upgraded_pad->add_layers()->CopyFrom(layer_connection); } for (int j = 0; j < layer_connection.bottom_size(); ++j) { const string& blob_name = layer_connection.bottom(j); @@ -77,7 +77,7 @@ void UpgradeV0PaddingLayers(const NetParameter& param, if (top_idx == -1) { continue; } - LayerParameter source_layer = param.layer(top_idx); + const V1LayerParameter& source_layer = param.layers(top_idx); if (source_layer.layer().type() == "padding") { // This layer has a padding layer as input -- check that it is a conv // layer or a pooling layer and takes only one input. Also check that @@ -93,10 +93,10 @@ void UpgradeV0PaddingLayers(const NetParameter& param, << "Padding Layer takes a single blob as input."; CHECK_EQ(source_layer.top_size(), 1) << "Padding Layer produces a single blob as output."; - int layer_index = param_upgraded_pad->layer_size() - 1; - param_upgraded_pad->mutable_layer(layer_index)->mutable_layer() + int layer_index = param_upgraded_pad->layers_size() - 1; + param_upgraded_pad->mutable_layers(layer_index)->mutable_layer() ->set_pad(source_layer.layer().pad()); - param_upgraded_pad->mutable_layer(layer_index) + param_upgraded_pad->mutable_layers(layer_index) ->set_bottom(j, source_layer.bottom(0)); } } @@ -107,8 +107,8 @@ void UpgradeV0PaddingLayers(const NetParameter& param, } } -bool UpgradeLayerParameter(const LayerParameter& v0_layer_connection, - LayerParameter* layer_param) { +bool UpgradeLayerParameter(const V1LayerParameter& v0_layer_connection, + V1LayerParameter* layer_param) { bool is_fully_compatible = true; layer_param->Clear(); for (int i = 0; i < v0_layer_connection.bottom_size(); ++i) { @@ -459,79 +459,79 @@ bool UpgradeLayerParameter(const LayerParameter& v0_layer_connection, return is_fully_compatible; } -const char* UpgradeV0LayerType(const string& type) { +V1LayerParameter_LayerType UpgradeV0LayerType(const string& type) { if (type == "accuracy") { - return "Accuracy"; + return V1LayerParameter_LayerType_ACCURACY; } else if (type == "bnll") { - return "BNLL"; + return V1LayerParameter_LayerType_BNLL; } else if (type == "concat") { - return "Concat"; + return V1LayerParameter_LayerType_CONCAT; } else if (type == "conv") { - return "Convolution"; + return V1LayerParameter_LayerType_CONVOLUTION; } else if (type == "data") { - return "Data"; + return V1LayerParameter_LayerType_DATA; } else if (type == "dropout") { - return "Dropout"; + return V1LayerParameter_LayerType_DROPOUT; } else if (type == "euclidean_loss") { - return "EuclideanLoss"; + return V1LayerParameter_LayerType_EUCLIDEAN_LOSS; } else if (type == "flatten") { - return "Flatten"; + return V1LayerParameter_LayerType_FLATTEN; } else if (type == "hdf5_data") { - return "HDF5Data"; + return V1LayerParameter_LayerType_HDF5_DATA; } else if (type == "hdf5_output") { - return "HDF5Output"; + return V1LayerParameter_LayerType_HDF5_OUTPUT; } else if (type == "im2col") { - return "Im2Col"; + return V1LayerParameter_LayerType_IM2COL; } else if (type == "images") { - return "ImageData"; + return V1LayerParameter_LayerType_IMAGE_DATA; } else if (type == "infogain_loss") { - return "InfogainLoss"; + return V1LayerParameter_LayerType_INFOGAIN_LOSS; } else if (type == "innerproduct") { - return "InnerProduct"; + return V1LayerParameter_LayerType_INNER_PRODUCT; } else if (type == "lrn") { - return "LRN"; + return V1LayerParameter_LayerType_LRN; } else if (type == "multinomial_logistic_loss") { - return "MultinomialLogisticLoss"; + return V1LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS; } else if (type == "pool") { - return "Pooling"; + return V1LayerParameter_LayerType_POOLING; } else if (type == "relu") { - return "ReLU"; + return V1LayerParameter_LayerType_RELU; } else if (type == "sigmoid") { - return "Sigmoid"; + return V1LayerParameter_LayerType_SIGMOID; } else if (type == "softmax") { - return "Softmax"; + return V1LayerParameter_LayerType_SOFTMAX; } else if (type == "softmax_loss") { - return "SoftmaxWithLoss"; + return V1LayerParameter_LayerType_SOFTMAX_LOSS; } else if (type == "split") { - return "Split"; + return V1LayerParameter_LayerType_SPLIT; } else if (type == "tanh") { - return "TanH"; + return V1LayerParameter_LayerType_TANH; } else if (type == "window_data") { - return "WindowData"; + return V1LayerParameter_LayerType_WINDOW_DATA; } else { - LOG(FATAL) << "Unknown layer type: " << type; - return ""; + LOG(FATAL) << "Unknown layer name: " << type; + return V1LayerParameter_LayerType_NONE; } } bool NetNeedsDataUpgrade(const NetParameter& net_param) { - for (int i = 0; i < net_param.layer_size(); ++i) { - if (net_param.layer(i).type() == "Data") { - DataParameter layer_param = net_param.layer(i).data_param(); + for (int i = 0; i < net_param.layers_size(); ++i) { + if (net_param.layers(i).type() == V1LayerParameter_LayerType_DATA) { + DataParameter layer_param = net_param.layers(i).data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } if (layer_param.has_crop_size()) { return true; } if (layer_param.has_mirror()) { return true; } } - if (net_param.layer(i).type() == "ImageData") { - ImageDataParameter layer_param = net_param.layer(i).image_data_param(); + if (net_param.layers(i).type() == V1LayerParameter_LayerType_IMAGE_DATA) { + ImageDataParameter layer_param = net_param.layers(i).image_data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } if (layer_param.has_crop_size()) { return true; } if (layer_param.has_mirror()) { return true; } } - if (net_param.layer(i).type() == "WindowData") { - WindowDataParameter layer_param = net_param.layer(i).window_data_param(); + if (net_param.layers(i).type() == V1LayerParameter_LayerType_WINDOW_DATA) { + WindowDataParameter layer_param = net_param.layers(i).window_data_param(); if (layer_param.has_scale()) { return true; } if (layer_param.has_mean_file()) { return true; } if (layer_param.has_crop_size()) { return true; } @@ -541,13 +541,13 @@ bool NetNeedsDataUpgrade(const NetParameter& net_param) { return false; } -#define CONVERT_LAYER_TRANSFORM_PARAM(TYPE_NAME, PARAM_NAME) \ +#define CONVERT_LAYER_TRANSFORM_PARAM(TYPE, Name, param_name) \ do { \ - if (net_param->layer(i).type() == #TYPE_NAME) { \ - TYPE_NAME##Parameter* layer_param = \ - net_param->mutable_layer(i)->mutable_##PARAM_NAME##_param(); \ + if (net_param->layers(i).type() == V1LayerParameter_LayerType_##TYPE) { \ + Name##Parameter* layer_param = \ + net_param->mutable_layers(i)->mutable_##param_name##_param(); \ TransformationParameter* transform_param = \ - net_param->mutable_layer(i)->mutable_transform_param(); \ + net_param->mutable_layers(i)->mutable_transform_param(); \ if (layer_param->has_scale()) { \ transform_param->set_scale(layer_param->scale()); \ layer_param->clear_scale(); \ @@ -568,10 +568,10 @@ bool NetNeedsDataUpgrade(const NetParameter& net_param) { } while (0) void UpgradeNetDataTransformation(NetParameter* net_param) { - for (int i = 0; i < net_param->layer_size(); ++i) { - CONVERT_LAYER_TRANSFORM_PARAM(Data, data); - CONVERT_LAYER_TRANSFORM_PARAM(ImageData, image_data); - CONVERT_LAYER_TRANSFORM_PARAM(WindowData, window_data); + for (int i = 0; i < net_param->layers_size(); ++i) { + CONVERT_LAYER_TRANSFORM_PARAM(DATA, Data, data); + CONVERT_LAYER_TRANSFORM_PARAM(IMAGE_DATA, ImageData, image_data); + CONVERT_LAYER_TRANSFORM_PARAM(WINDOW_DATA, WindowData, window_data); } } @@ -590,7 +590,7 @@ void NetParameterToPrettyPrint(const NetParameter& param, for (int i = 0; i < param.input_dim_size(); ++i) { pretty_param->add_input_dim(param.input_dim(i)); } - for (int i = 0; i < param.layer_size(); ++i) { + for (int i = 0; i < param.layers_size(); ++i) { pretty_param->add_layer()->CopyFrom(param.layer(i)); } } From 2e6a82c8445e588dbc72dabe7126830682a3c3e3 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 14 Jan 2015 16:55:14 -0800 Subject: [PATCH 275/798] automagic upgrade for v1->v2 --- include/caffe/util/upgrade_proto.hpp | 25 ++- src/caffe/net.cpp | 13 +- src/caffe/proto/caffe.proto | 105 ++++----- src/caffe/util/upgrade_proto.cpp | 317 ++++++++++++++++++++++++++- tools/upgrade_net_proto_binary.cpp | 13 +- tools/upgrade_net_proto_text.cpp | 15 +- 6 files changed, 410 insertions(+), 78 deletions(-) diff --git a/include/caffe/util/upgrade_proto.hpp b/include/caffe/util/upgrade_proto.hpp index e89756ed055..0df3a8987f9 100644 --- a/include/caffe/util/upgrade_proto.hpp +++ b/include/caffe/util/upgrade_proto.hpp @@ -8,9 +8,12 @@ namespace caffe { +// Return true iff the net is not the current version. +bool NetNeedsUpgrade(const NetParameter& net_param); + // Return true iff any layer contains parameters specified using // deprecated V0LayerParameter. -bool NetNeedsUpgrade(const NetParameter& net_param); +bool NetNeedsV0ToV1Upgrade(const NetParameter& net_param); // Perform all necessary transformations to upgrade a V0NetParameter into a // NetParameter (including upgrading padding layers and LayerParameters). @@ -23,9 +26,9 @@ bool UpgradeV0Net(const NetParameter& v0_net_param, NetParameter* net_param); void UpgradeV0PaddingLayers(const NetParameter& param, NetParameter* param_upgraded_pad); -// Upgrade a single V0LayerConnection to the new LayerParameter format. -bool UpgradeLayerParameter(const V1LayerParameter& v0_layer_connection, - V1LayerParameter* layer_param); +// Upgrade a single V0LayerConnection to the V1LayerParameter format. +bool UpgradeV0LayerParameter(const V1LayerParameter& v0_layer_connection, + V1LayerParameter* layer_param); V1LayerParameter_LayerType UpgradeV0LayerType(const string& type); @@ -36,13 +39,25 @@ bool NetNeedsDataUpgrade(const NetParameter& net_param); // into a TransformationParameter. void UpgradeNetDataTransformation(NetParameter* net_param); +// Return true iff the Net contains any layers specified as V1LayerParameters. +bool NetNeedsV1ToV2Upgrade(const NetParameter& net_param); + +// Perform all necessary transformations to upgrade a NetParameter with +// deprecated V1LayerParameters. +bool UpgradeV1Net(const NetParameter& v1_net_param, NetParameter* net_param); + +bool UpgradeV1LayerParameter(const V1LayerParameter& v1_layer_param, + LayerParameter* layer_param); + +const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type); + // Convert a NetParameter to NetParameterPrettyPrint used for dumping to // proto text files. void NetParameterToPrettyPrint(const NetParameter& param, NetParameterPrettyPrint* pretty_param); // Check for deprecations and upgrade the NetParameter as needed. -void UpgradeNetAsNeeded(NetParameter* param); +bool UpgradeNetAsNeeded(const string& param_file, NetParameter* param); // Read parameters from a file into a NetParameter proto message. void ReadNetParamsFromTextFileOrDie(const string& param_file, diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index db9ac7ddbb3..4461fa88e75 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -138,9 +138,10 @@ void Net::Init(const NetParameter& in_param) { CHECK(param_size == num_param_blobs || param_size == 0) << "Incorrect param size: should be either 0 or the same as " "the number of the layer's parameter blobs: " << num_param_blobs; - const int blob_share_mode_size = layer_param.blob_share_mode_size(); - CHECK(blob_share_mode_size == num_param_blobs || blob_share_mode_size == 0) - << "Incorrect blob_share_mode size: should be either 0 or the same as " + const int param_share_mode_size = layer_param.param_share_mode_size(); + CHECK(param_share_mode_size == num_param_blobs || + param_share_mode_size == 0) + << "Incorrect param_share_mode size: should be either 0 or the same as " "the number of the layer's parameter blobs: " << num_param_blobs; for (int param_id = 0; param_id < num_param_blobs; ++param_id) { AppendParam(param, layer_id, param_id); @@ -441,9 +442,9 @@ void Net::AppendParam(const NetParameter& param, const int layer_id, Blob* this_blob = layers_[layer_id]->blobs()[param_id].get(); Blob* owner_blob = layers_[owner_layer_id]->blobs()[owner_param_id].get(); - const int blob_share_mode_size = layer_param.blob_share_mode_size(); - if (blob_share_mode_size > param_id && - (layer_param.blob_share_mode(param_id) == + const int param_share_mode_size = layer_param.param_share_mode_size(); + if (param_share_mode_size > param_id && + (layer_param.param_share_mode(param_id) == LayerParameter_DimCheckMode_PERMISSIVE)) { // Permissive dimension checking -- only check counts are the same. CHECK_EQ(this_blob->count(), owner_blob->count()) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index d81acf309f4..1178efe53a8 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -218,77 +218,80 @@ message NetStateRule { // // LayerParameter next available ID: 43 (last added: loss_param) message LayerParameter { - repeated string bottom = 2; // the name of the bottom blobs - repeated string top = 3; // the name of the top blobs - optional string name = 4; // the layer name - - // Rules controlling whether and when a layer is included in the network, - // based on the current NetState. You may specify a non-zero number of rules - // to include OR exclude, but not both. If no include or exclude rules are - // specified, the layer is always included. If the current NetState meets - // ANY (i.e., one or more) of the specified rules, the layer is - // included/excluded. - repeated NetStateRule include = 32; - repeated NetStateRule exclude = 33; + optional string name = 1; // the layer name + optional string type = 2; // the layer type + repeated string bottom = 3; // the name of each bottom blob + repeated string top = 4; // the name of each top blob - optional string type = 5; // the layer type from the enum above + // The amount of weight to assign each top blob in the objective. + // Each layer assigns a default value, usually of either 0 or 1, + // to each top blob. + repeated float loss_weight = 5; // The blobs containing the numeric parameters of the layer repeated BlobProto blobs = 6; + // The names of the parameter blobs -- useful for sharing parameters among // layers (but never required). - repeated string param = 1001; + repeated string param = 7; + // Whether to require shared weights to have the same shape, or just the same // count -- defaults to STRICT if unspecified. - repeated DimCheckMode blob_share_mode = 1002; + repeated DimCheckMode param_share_mode = 8; enum DimCheckMode { // STRICT (default) requires that num, channels, height, width each match. STRICT = 0; // PERMISSIVE requires only the count (num*channels*height*width) to match. PERMISSIVE = 1; } + // The ratio that is multiplied on the global learning rate. If you want to // set the learning ratio for one blob, you need to set it for all blobs. - repeated float blobs_lr = 7; - // The weight decay that is multiplied on the global weight decay. - repeated float weight_decay = 8; + repeated float blobs_lr = 9; - // The amount of weight to assign each top blob in the objective. - // Each layer assigns a default value, usually of either 0 or 1, - // to each top blob. - repeated float loss_weight = 35; + // The weight decay that is multiplied on the global weight decay. + repeated float weight_decay = 10; - optional AccuracyParameter accuracy_param = 27; - optional ArgMaxParameter argmax_param = 23; - optional ConcatParameter concat_param = 9; - optional ContrastiveLossParameter contrastive_loss_param = 40; - optional ConvolutionParameter convolution_param = 10; - optional DataParameter data_param = 11; - optional DropoutParameter dropout_param = 12; - optional DummyDataParameter dummy_data_param = 26; - optional EltwiseParameter eltwise_param = 24; - optional ExpParameter exp_param = 41; - optional HDF5DataParameter hdf5_data_param = 13; - optional HDF5OutputParameter hdf5_output_param = 14; - optional HingeLossParameter hinge_loss_param = 29; - optional ImageDataParameter image_data_param = 15; - optional InfogainLossParameter infogain_loss_param = 16; - optional InnerProductParameter inner_product_param = 17; - optional LRNParameter lrn_param = 18; - optional MemoryDataParameter memory_data_param = 22; - optional MVNParameter mvn_param = 34; - optional PoolingParameter pooling_param = 19; - optional PowerParameter power_param = 21; - optional ReLUParameter relu_param = 30; - optional SigmoidParameter sigmoid_param = 38; - optional SoftmaxParameter softmax_param = 39; - optional SliceParameter slice_param = 31; - optional TanHParameter tanh_param = 37; - optional ThresholdParameter threshold_param = 25; - optional WindowDataParameter window_data_param = 20; + // Rules controlling whether and when a layer is included in the network, + // based on the current NetState. You may specify a non-zero number of rules + // to include OR exclude, but not both. If no include or exclude rules are + // specified, the layer is always included. If the current NetState meets + // ANY (i.e., one or more) of the specified rules, the layer is + // included/excluded. + repeated NetStateRule include = 11; + repeated NetStateRule exclude = 12; // Parameters for data pre-processing. - optional TransformationParameter transform_param = 36; + optional TransformationParameter transform_param = 13; + + optional AccuracyParameter accuracy_param = 14; + optional ArgMaxParameter argmax_param = 15; + optional ConcatParameter concat_param = 16; + optional ContrastiveLossParameter contrastive_loss_param = 17; + optional ConvolutionParameter convolution_param = 18; + optional DataParameter data_param = 19; + optional DropoutParameter dropout_param = 20; + optional DummyDataParameter dummy_data_param = 21; + optional EltwiseParameter eltwise_param = 22; + optional ExpParameter exp_param = 23; + optional HDF5DataParameter hdf5_data_param = 24; + optional HDF5OutputParameter hdf5_output_param = 25; + optional HingeLossParameter hinge_loss_param = 26; + optional ImageDataParameter image_data_param = 27; + optional InfogainLossParameter infogain_loss_param = 28; + optional InnerProductParameter inner_product_param = 29; + optional LRNParameter lrn_param = 30; + optional MemoryDataParameter memory_data_param = 31; + optional MVNParameter mvn_param = 32; + optional PoolingParameter pooling_param = 33; + optional PowerParameter power_param = 34; + optional ReLUParameter relu_param = 35; + optional SigmoidParameter sigmoid_param = 36; + optional SoftmaxParameter softmax_param = 37; + optional SliceParameter slice_param = 38; + optional TanHParameter tanh_param = 39; + optional ThresholdParameter threshold_param = 40; + optional WindowDataParameter window_data_param = 41; // Parameters shared by loss layers. optional LossParameter loss_param = 42; diff --git a/src/caffe/util/upgrade_proto.cpp b/src/caffe/util/upgrade_proto.cpp index 16583b0f0ca..575d7a73fee 100644 --- a/src/caffe/util/upgrade_proto.cpp +++ b/src/caffe/util/upgrade_proto.cpp @@ -13,6 +13,10 @@ namespace caffe { bool NetNeedsUpgrade(const NetParameter& net_param) { + return NetNeedsV0ToV1Upgrade(net_param) || NetNeedsV1ToV2Upgrade(net_param); +} + +bool NetNeedsV0ToV1Upgrade(const NetParameter& net_param) { for (int i = 0; i < net_param.layers_size(); ++i) { if (net_param.layers(i).has_layer()) { return true; @@ -21,6 +25,10 @@ bool NetNeedsUpgrade(const NetParameter& net_param) { return false; } +bool NetNeedsV1ToV2Upgrade(const NetParameter& net_param) { + return net_param.layers_size() > 0; +} + bool UpgradeV0Net(const NetParameter& v0_net_param_padding_layers, NetParameter* net_param) { // First upgrade padding layers to padded conv layers. @@ -33,8 +41,8 @@ bool UpgradeV0Net(const NetParameter& v0_net_param_padding_layers, net_param->set_name(v0_net_param.name()); } for (int i = 0; i < v0_net_param.layers_size(); ++i) { - is_fully_compatible &= UpgradeLayerParameter(v0_net_param.layers(i), - net_param->add_layers()); + is_fully_compatible &= UpgradeV0LayerParameter(v0_net_param.layers(i), + net_param->add_layers()); } for (int i = 0; i < v0_net_param.input_size(); ++i) { net_param->add_input(v0_net_param.input(i)); @@ -107,8 +115,8 @@ void UpgradeV0PaddingLayers(const NetParameter& param, } } -bool UpgradeLayerParameter(const V1LayerParameter& v0_layer_connection, - V1LayerParameter* layer_param) { +bool UpgradeV0LayerParameter(const V1LayerParameter& v0_layer_connection, + V1LayerParameter* layer_param) { bool is_fully_compatible = true; layer_param->Clear(); for (int i = 0; i < v0_layer_connection.bottom_size(); ++i) { @@ -590,19 +598,21 @@ void NetParameterToPrettyPrint(const NetParameter& param, for (int i = 0; i < param.input_dim_size(); ++i) { pretty_param->add_input_dim(param.input_dim(i)); } - for (int i = 0; i < param.layers_size(); ++i) { + for (int i = 0; i < param.layer_size(); ++i) { pretty_param->add_layer()->CopyFrom(param.layer(i)); } } -void UpgradeNetAsNeeded(const string& param_file, NetParameter* param) { - if (NetNeedsUpgrade(*param)) { +bool UpgradeNetAsNeeded(const string& param_file, NetParameter* param) { + bool success = true; + if (NetNeedsV0ToV1Upgrade(*param)) { // NetParameter was specified using the old style (V0LayerParameter); try to // upgrade it. LOG(ERROR) << "Attempting to upgrade input file specified using deprecated " << "V0LayerParameter: " << param_file; NetParameter original_param(*param); if (!UpgradeV0Net(original_param, param)) { + success = false; LOG(ERROR) << "Warning: had one or more problems upgrading " << "V0NetParameter to NetParameter (see above); continuing anyway."; } else { @@ -624,6 +634,299 @@ void UpgradeNetAsNeeded(const string& param_file, NetParameter* param) { LOG(ERROR) << "Note that future Caffe releases will only support " << "transform_param messages for transformation fields."; } + if (NetNeedsV1ToV2Upgrade(*param)) { + LOG(ERROR) << "Attempting to upgrade input file specified using deprecated " + << "V1LayerParameter: " << param_file; + NetParameter original_param(*param); + if (!UpgradeV1Net(original_param, param)) { + success = false; + LOG(ERROR) << "Warning: had one or more problems upgrading " + << "V1LayerParameter (see above); continuing anyway."; + } else { + LOG(INFO) << "Successfully upgraded file specified using deprecated " + << "V1LayerParameter"; + } + } + return success; +} + +bool UpgradeV1Net(const NetParameter& v1_net_param, NetParameter* net_param) { + bool is_fully_compatible = true; + if (v1_net_param.layer_size() > 0) { + LOG(ERROR) << "Input NetParameter to be upgraded already specifies 'layer' " + << "fields; these will be ignored for the upgrade."; + is_fully_compatible = false; + } + net_param->CopyFrom(v1_net_param); + net_param->clear_layers(); + for (int i = 0; i < v1_net_param.layers_size(); ++i) { + if (!UpgradeV1LayerParameter(v1_net_param.layers(i), + net_param->add_layer())) { + LOG(ERROR) << "Upgrade of input layer " << i << " failed."; + is_fully_compatible = false; + } + } + return is_fully_compatible; +} + +bool UpgradeV1LayerParameter(const V1LayerParameter& v1_layer_param, + LayerParameter* layer_param) { + layer_param->Clear(); + bool is_fully_compatible = true; + for (int i = 0; i < v1_layer_param.bottom_size(); ++i) { + layer_param->add_bottom(v1_layer_param.bottom(i)); + } + for (int i = 0; i < v1_layer_param.top_size(); ++i) { + layer_param->add_top(v1_layer_param.top(i)); + } + if (v1_layer_param.has_name()) { + layer_param->set_name(v1_layer_param.name()); + } + for (int i = 0; i < v1_layer_param.include_size(); ++i) { + layer_param->add_include()->CopyFrom(v1_layer_param.include(i)); + } + for (int i = 0; i < v1_layer_param.exclude_size(); ++i) { + layer_param->add_exclude()->CopyFrom(v1_layer_param.exclude(i)); + } + if (v1_layer_param.has_type()) { + layer_param->set_type(UpgradeV1LayerType(v1_layer_param.type())); + } + for (int i = 0; i < v1_layer_param.blobs_size(); ++i) { + layer_param->add_blobs()->CopyFrom(v1_layer_param.blobs(i)); + } + for (int i = 0; i < v1_layer_param.param_size(); ++i) { + layer_param->add_param(v1_layer_param.param(i)); + } + for (int i = 0; i < v1_layer_param.blob_share_mode_size(); ++i) { + switch (v1_layer_param.blob_share_mode(i)) { + case V1LayerParameter_DimCheckMode_STRICT: + layer_param->add_param_share_mode(LayerParameter_DimCheckMode_STRICT); + break; + case V1LayerParameter_DimCheckMode_PERMISSIVE: + layer_param->add_param_share_mode(LayerParameter_DimCheckMode_PERMISSIVE); + break; + default: + LOG(FATAL) << "Unknown blob_share_mode: " + << v1_layer_param.blob_share_mode(i); + break; + } + } + for (int i = 0; i < v1_layer_param.blobs_lr_size(); ++i) { + layer_param->add_blobs_lr(v1_layer_param.blobs_lr(i)); + } + for (int i = 0; i < v1_layer_param.weight_decay_size(); ++i) { + layer_param->add_weight_decay(v1_layer_param.weight_decay(i)); + } + for (int i = 0; i < v1_layer_param.loss_weight_size(); ++i) { + layer_param->add_loss_weight(v1_layer_param.loss_weight(i)); + } + if (v1_layer_param.has_accuracy_param()) { + layer_param->mutable_accuracy_param()->CopyFrom( + v1_layer_param.accuracy_param()); + } + if (v1_layer_param.has_argmax_param()) { + layer_param->mutable_argmax_param()->CopyFrom( + v1_layer_param.argmax_param()); + } + if (v1_layer_param.has_concat_param()) { + layer_param->mutable_concat_param()->CopyFrom( + v1_layer_param.concat_param()); + } + if (v1_layer_param.has_contrastive_loss_param()) { + layer_param->mutable_contrastive_loss_param()->CopyFrom( + v1_layer_param.contrastive_loss_param()); + } + if (v1_layer_param.has_convolution_param()) { + layer_param->mutable_convolution_param()->CopyFrom( + v1_layer_param.convolution_param()); + } + if (v1_layer_param.has_data_param()) { + layer_param->mutable_data_param()->CopyFrom( + v1_layer_param.data_param()); + } + if (v1_layer_param.has_dropout_param()) { + layer_param->mutable_dropout_param()->CopyFrom( + v1_layer_param.dropout_param()); + } + if (v1_layer_param.has_dummy_data_param()) { + layer_param->mutable_dummy_data_param()->CopyFrom( + v1_layer_param.dummy_data_param()); + } + if (v1_layer_param.has_eltwise_param()) { + layer_param->mutable_eltwise_param()->CopyFrom( + v1_layer_param.eltwise_param()); + } + if (v1_layer_param.has_exp_param()) { + layer_param->mutable_exp_param()->CopyFrom( + v1_layer_param.exp_param()); + } + if (v1_layer_param.has_hdf5_data_param()) { + layer_param->mutable_hdf5_data_param()->CopyFrom( + v1_layer_param.hdf5_data_param()); + } + if (v1_layer_param.has_hdf5_output_param()) { + layer_param->mutable_hdf5_output_param()->CopyFrom( + v1_layer_param.hdf5_output_param()); + } + if (v1_layer_param.has_hinge_loss_param()) { + layer_param->mutable_hinge_loss_param()->CopyFrom( + v1_layer_param.hinge_loss_param()); + } + if (v1_layer_param.has_image_data_param()) { + layer_param->mutable_image_data_param()->CopyFrom( + v1_layer_param.image_data_param()); + } + if (v1_layer_param.has_infogain_loss_param()) { + layer_param->mutable_infogain_loss_param()->CopyFrom( + v1_layer_param.infogain_loss_param()); + } + if (v1_layer_param.has_inner_product_param()) { + layer_param->mutable_inner_product_param()->CopyFrom( + v1_layer_param.inner_product_param()); + } + if (v1_layer_param.has_lrn_param()) { + layer_param->mutable_lrn_param()->CopyFrom( + v1_layer_param.lrn_param()); + } + if (v1_layer_param.has_memory_data_param()) { + layer_param->mutable_memory_data_param()->CopyFrom( + v1_layer_param.memory_data_param()); + } + if (v1_layer_param.has_mvn_param()) { + layer_param->mutable_mvn_param()->CopyFrom( + v1_layer_param.mvn_param()); + } + if (v1_layer_param.has_pooling_param()) { + layer_param->mutable_pooling_param()->CopyFrom( + v1_layer_param.pooling_param()); + } + if (v1_layer_param.has_power_param()) { + layer_param->mutable_power_param()->CopyFrom( + v1_layer_param.power_param()); + } + if (v1_layer_param.has_relu_param()) { + layer_param->mutable_relu_param()->CopyFrom( + v1_layer_param.relu_param()); + } + if (v1_layer_param.has_sigmoid_param()) { + layer_param->mutable_sigmoid_param()->CopyFrom( + v1_layer_param.sigmoid_param()); + } + if (v1_layer_param.has_softmax_param()) { + layer_param->mutable_softmax_param()->CopyFrom( + v1_layer_param.softmax_param()); + } + if (v1_layer_param.has_slice_param()) { + layer_param->mutable_slice_param()->CopyFrom( + v1_layer_param.slice_param()); + } + if (v1_layer_param.has_tanh_param()) { + layer_param->mutable_tanh_param()->CopyFrom( + v1_layer_param.tanh_param()); + } + if (v1_layer_param.has_threshold_param()) { + layer_param->mutable_threshold_param()->CopyFrom( + v1_layer_param.threshold_param()); + } + if (v1_layer_param.has_window_data_param()) { + layer_param->mutable_window_data_param()->CopyFrom( + v1_layer_param.window_data_param()); + } + if (v1_layer_param.has_transform_param()) { + layer_param->mutable_transform_param()->CopyFrom( + v1_layer_param.transform_param()); + } + if (v1_layer_param.has_layer()) { + LOG(ERROR) << "Input NetParameter has V0 layer -- ignoring."; + is_fully_compatible = false; + } + return is_fully_compatible; +} + +const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type) { + switch (type) { + case V1LayerParameter_LayerType_NONE: + return ""; + case V1LayerParameter_LayerType_ABSVAL: + return "AbsVal"; + case V1LayerParameter_LayerType_ACCURACY: + return "Accuracy"; + case V1LayerParameter_LayerType_ARGMAX: + return "ArgMax"; + case V1LayerParameter_LayerType_BNLL: + return "BNLL"; + case V1LayerParameter_LayerType_CONCAT: + return "Concat"; + case V1LayerParameter_LayerType_CONTRASTIVE_LOSS: + return "ContrastiveLoss"; + case V1LayerParameter_LayerType_CONVOLUTION: + return "Convolution"; + case V1LayerParameter_LayerType_DATA: + return "Data"; + case V1LayerParameter_LayerType_DROPOUT: + return "Dropout"; + case V1LayerParameter_LayerType_DUMMY_DATA: + return "DummyData"; + case V1LayerParameter_LayerType_EUCLIDEAN_LOSS: + return "EuclideanLoss"; + case V1LayerParameter_LayerType_ELTWISE: + return "Eltwise"; + case V1LayerParameter_LayerType_EXP: + return "Exp"; + case V1LayerParameter_LayerType_FLATTEN: + return "Flatten"; + case V1LayerParameter_LayerType_HDF5_DATA: + return "HDF5Data"; + case V1LayerParameter_LayerType_HDF5_OUTPUT: + return "HDF5Output"; + case V1LayerParameter_LayerType_HINGE_LOSS: + return "HingeLoss"; + case V1LayerParameter_LayerType_IM2COL: + return "Im2col"; + case V1LayerParameter_LayerType_IMAGE_DATA: + return "ImageData"; + case V1LayerParameter_LayerType_INFOGAIN_LOSS: + return "InfogainLoss"; + case V1LayerParameter_LayerType_INNER_PRODUCT: + return "InnerProduct"; + case V1LayerParameter_LayerType_LRN: + return "LRN"; + case V1LayerParameter_LayerType_MEMORY_DATA: + return "MemoryData"; + case V1LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS: + return "MultinomialLogisticLoss"; + case V1LayerParameter_LayerType_MVN: + return "MVN"; + case V1LayerParameter_LayerType_POOLING: + return "Pooling"; + case V1LayerParameter_LayerType_POWER: + return "Power"; + case V1LayerParameter_LayerType_RELU: + return "ReLU"; + case V1LayerParameter_LayerType_SIGMOID: + return "Sigmoid"; + case V1LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS: + return "SigmoidCrossEntropyLoss"; + case V1LayerParameter_LayerType_SILENCE: + return "Silence"; + case V1LayerParameter_LayerType_SOFTMAX: + return "Softmax"; + case V1LayerParameter_LayerType_SOFTMAX_LOSS: + return "SoftmaxWithLoss"; + case V1LayerParameter_LayerType_SPLIT: + return "Split"; + case V1LayerParameter_LayerType_SLICE: + return "Slice"; + case V1LayerParameter_LayerType_TANH: + return "TanH"; + case V1LayerParameter_LayerType_WINDOW_DATA: + return "WindowData"; + case V1LayerParameter_LayerType_THRESHOLD: + return "Threshold"; + default: + LOG(FATAL) << "Unknown V1LayerParameter layer type: " << type; + return ""; + } } void ReadNetParamsFromTextFileOrDie(const string& param_file, diff --git a/tools/upgrade_net_proto_binary.cpp b/tools/upgrade_net_proto_binary.cpp index d7a62e32441..8a0dd7af743 100644 --- a/tools/upgrade_net_proto_binary.cpp +++ b/tools/upgrade_net_proto_binary.cpp @@ -5,6 +5,7 @@ #include #include // NOLINT(readability/streams) #include // NOLINT(readability/streams) +#include #include "caffe/caffe.hpp" #include "caffe/util/io.hpp" @@ -23,16 +24,20 @@ int main(int argc, char** argv) { } NetParameter net_param; - if (!ReadProtoFromBinaryFile(argv[1], &net_param)) { + string input_filename(argv[1]); + if (!ReadProtoFromBinaryFile(input_filename, &net_param)) { LOG(ERROR) << "Failed to parse input binary file as NetParameter: " - << argv[1]; + << input_filename; return 2; } bool need_upgrade = NetNeedsUpgrade(net_param); bool success = true; if (need_upgrade) { - NetParameter v0_net_param(net_param); - success = UpgradeV0Net(v0_net_param, &net_param); + success = UpgradeNetAsNeeded(input_filename, &net_param); + if (!success) { + LOG(ERROR) << "Encountered error(s) while upgrading prototxt; " + << "see details above."; + } } else { LOG(ERROR) << "File already in V1 proto format: " << argv[1]; } diff --git a/tools/upgrade_net_proto_text.cpp b/tools/upgrade_net_proto_text.cpp index 2f290fc5e14..0fe420a6d36 100644 --- a/tools/upgrade_net_proto_text.cpp +++ b/tools/upgrade_net_proto_text.cpp @@ -5,6 +5,7 @@ #include #include // NOLINT(readability/streams) #include // NOLINT(readability/streams) +#include #include "caffe/caffe.hpp" #include "caffe/util/io.hpp" @@ -23,19 +24,23 @@ int main(int argc, char** argv) { } NetParameter net_param; - if (!ReadProtoFromTextFile(argv[1], &net_param)) { + string input_filename(argv[1]); + if (!ReadProtoFromTextFile(input_filename, &net_param)) { LOG(ERROR) << "Failed to parse input text file as NetParameter: " - << argv[1]; + << input_filename; return 2; } bool need_upgrade = NetNeedsUpgrade(net_param); bool need_data_upgrade = NetNeedsDataUpgrade(net_param); bool success = true; if (need_upgrade) { - NetParameter v0_net_param(net_param); - success = UpgradeV0Net(v0_net_param, &net_param); + success = UpgradeNetAsNeeded(input_filename, &net_param); + if (!success) { + LOG(ERROR) << "Encountered error(s) while upgrading prototxt; " + << "see details above."; + } } else { - LOG(ERROR) << "File already in V1 proto format: " << argv[1]; + LOG(ERROR) << "File already in latest proto format: " << input_filename; } if (need_data_upgrade) { From cb08ffd9a3506e1c058ba5959ce05021b5f72338 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 14 Jan 2015 18:31:23 -0800 Subject: [PATCH 276/798] restore test_upgrade_proto to dev version --- src/caffe/test/test_upgrade_proto.cpp | 106 +++++++++++++------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/src/caffe/test/test_upgrade_proto.cpp b/src/caffe/test/test_upgrade_proto.cpp index e520b85f291..52e7f1f99f5 100644 --- a/src/caffe/test/test_upgrade_proto.cpp +++ b/src/caffe/test/test_upgrade_proto.cpp @@ -1184,7 +1184,7 @@ TEST_F(V0UpgradeTest, TestSimple) { "name: 'CaffeNet' " "layers { " " name: 'data' " - " type: 'Data' " + " type: DATA " " data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -1199,7 +1199,7 @@ TEST_F(V0UpgradeTest, TestSimple) { "} " "layers { " " name: 'conv1' " - " type: 'Convolution' " + " type: CONVOLUTION " " convolution_param { " " num_output: 96 " " kernel_size: 11 " @@ -1223,7 +1223,7 @@ TEST_F(V0UpgradeTest, TestSimple) { "} " "layers { " " name: 'fc8' " - " type: 'InnerProduct' " + " type: INNER_PRODUCT " " inner_product_param { " " num_output: 1000 " " weight_filler { " @@ -1244,7 +1244,7 @@ TEST_F(V0UpgradeTest, TestSimple) { "} " "layers { " " name: 'loss' " - " type: 'SoftmaxWithLoss' " + " type: SOFTMAX_LOSS " " bottom: 'fc8' " " bottom: 'label' " "} "; @@ -1520,7 +1520,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "input_dim: 32 " "layers { " " name: 'data' " - " type: 'Data' " + " type: DATA " " data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -1537,7 +1537,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'images' " - " type: 'ImageData' " + " type: IMAGE_DATA " " image_data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-images' " " batch_size: 256 " @@ -1557,7 +1557,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'window_data' " - " type: 'WindowData' " + " type: WINDOW_DATA " " window_data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -1577,7 +1577,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'hdf5data' " - " type: 'HDF5Data' " + " type: HDF5_DATA " " hdf5_data_param { " " source: '/my/hdf5/data' " " batch_size: 256 " @@ -1586,7 +1586,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'conv1' " - " type: 'Convolution' " + " type: CONVOLUTION " " convolution_param { " " num_output: 96 " " bias_term: false " @@ -1611,7 +1611,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'pool1ave' " - " type: 'Pooling' " + " type: POOLING " " pooling_param { " " pool: AVE " " kernel_size: 3 " @@ -1622,7 +1622,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'pool1stoch' " - " type: 'Pooling' " + " type: POOLING " " pooling_param { " " pool: STOCHASTIC " " kernel_size: 4 " @@ -1633,7 +1633,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'concat' " - " type: 'Concat' " + " type: CONCAT " " concat_param { " " concat_dim: 2 " " } " @@ -1643,7 +1643,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'norm1' " - " type: 'LRN' " + " type: LRN " " lrn_param { " " local_size: 5 " " alpha: 0.0001 " @@ -1654,7 +1654,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'fc6' " - " type: 'InnerProduct' " + " type: INNER_PRODUCT " " inner_product_param { " " num_output: 4096 " " bias_term: false " @@ -1676,13 +1676,13 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'relu6' " - " type: 'ReLU' " + " type: RELU " " bottom: 'fc6' " " top: 'fc6' " "} " "layers { " " name: 'drop6' " - " type: 'Dropout' " + " type: DROPOUT " " dropout_param { " " dropout_ratio: 0.2 " " } " @@ -1691,7 +1691,7 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'loss' " - " type: 'InfogainLoss' " + " type: INFOGAIN_LOSS " " infogain_loss_param { " " source: '/my/infogain/matrix' " " } " @@ -1700,54 +1700,54 @@ TEST_F(V0UpgradeTest, TestAllParams) { "} " "layers { " " name: 'accuracy' " - " type: 'Accuracy' " + " type: ACCURACY " "} " "layers { " " name: 'bnll' " - " type: 'BNLL' " + " type: BNLL " "} " "layers { " " name: 'euclidean_loss' " - " type: 'EuclideanLoss' " + " type: EUCLIDEAN_LOSS " "} " "layers { " " name: 'flatten' " - " type: 'Flatten' " + " type: FLATTEN " "} " "layers { " " name: 'hdf5_output' " - " type: 'HDF5Output' " + " type: HDF5_OUTPUT " " hdf5_output_param { " " file_name: '/my/hdf5/output/file' " " } " "} " "layers { " " name: 'im2col' " - " type: 'Im2Col' " + " type: IM2COL " "} " "layers { " " name: 'images' " - " type: 'ImageData' " + " type: IMAGE_DATA " "} " "layers { " " name: 'multinomial_logistic_loss' " - " type: 'MultinomialLogisticLoss' " + " type: MULTINOMIAL_LOGISTIC_LOSS " "} " "layers { " " name: 'sigmoid' " - " type: 'Sigmoid' " + " type: SIGMOID " "} " "layers { " " name: 'softmax' " - " type: 'Softmax' " + " type: SOFTMAX " "} " "layers { " " name: 'split' " - " type: 'Split' " + " type: SPLIT " "} " "layers { " " name: 'tanh' " - " type: 'TanH' " + " type: TANH " "} "; this->RunV0UpgradeTest(input_proto, expected_output_proto); } @@ -2122,7 +2122,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "name: 'CaffeNet' " "layers { " " name: 'data' " - " type: 'Data' " + " type: DATA " " data_param { " " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " " batch_size: 256 " @@ -2137,7 +2137,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'conv1' " - " type: 'Convolution' " + " type: CONVOLUTION " " convolution_param { " " num_output: 96 " " kernel_size: 11 " @@ -2160,13 +2160,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu1' " - " type: 'ReLU' " + " type: RELU " " bottom: 'conv1' " " top: 'conv1' " "} " "layers { " " name: 'pool1' " - " type: 'Pooling' " + " type: POOLING " " pooling_param { " " pool: MAX " " kernel_size: 3 " @@ -2177,7 +2177,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'norm1' " - " type: 'LRN' " + " type: LRN " " lrn_param { " " local_size: 5 " " alpha: 0.0001 " @@ -2188,7 +2188,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'conv2' " - " type: 'Convolution' " + " type: CONVOLUTION " " convolution_param { " " num_output: 256 " " group: 2 " @@ -2212,13 +2212,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu2' " - " type: 'ReLU' " + " type: RELU " " bottom: 'conv2' " " top: 'conv2' " "} " "layers { " " name: 'pool2' " - " type: 'Pooling' " + " type: POOLING " " pooling_param { " " pool: MAX " " kernel_size: 3 " @@ -2229,7 +2229,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'norm2' " - " type: 'LRN' " + " type: LRN " " lrn_param { " " local_size: 5 " " alpha: 0.0001 " @@ -2240,7 +2240,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'conv3' " - " type: 'Convolution' " + " type: CONVOLUTION " " convolution_param { " " num_output: 384 " " kernel_size: 3 " @@ -2263,13 +2263,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu3' " - " type: 'ReLU' " + " type: RELU " " bottom: 'conv3' " " top: 'conv3' " "} " "layers { " " name: 'conv4' " - " type: 'Convolution' " + " type: CONVOLUTION " " convolution_param { " " num_output: 384 " " group: 2 " @@ -2293,13 +2293,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu4' " - " type: 'ReLU' " + " type: RELU " " bottom: 'conv4' " " top: 'conv4' " "} " "layers { " " name: 'conv5' " - " type: 'Convolution' " + " type: CONVOLUTION " " convolution_param { " " num_output: 256 " " group: 2 " @@ -2323,13 +2323,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu5' " - " type: 'ReLU' " + " type: RELU " " bottom: 'conv5' " " top: 'conv5' " "} " "layers { " " name: 'pool5' " - " type: 'Pooling' " + " type: POOLING " " pooling_param { " " kernel_size: 3 " " pool: MAX " @@ -2340,7 +2340,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'fc6' " - " type: 'InnerProduct' " + " type: INNER_PRODUCT " " inner_product_param { " " num_output: 4096 " " weight_filler { " @@ -2361,13 +2361,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu6' " - " type: 'ReLU' " + " type: RELU " " bottom: 'fc6' " " top: 'fc6' " "} " "layers { " " name: 'drop6' " - " type: 'Dropout' " + " type: DROPOUT " " dropout_param { " " dropout_ratio: 0.5 " " } " @@ -2376,7 +2376,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'fc7' " - " type: 'InnerProduct' " + " type: INNER_PRODUCT " " inner_product_param { " " num_output: 4096 " " weight_filler { " @@ -2397,13 +2397,13 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'relu7' " - " type: 'ReLU' " + " type: RELU " " bottom: 'fc7' " " top: 'fc7' " "} " "layers { " " name: 'drop7' " - " type: 'Dropout' " + " type: DROPOUT " " dropout_param { " " dropout_ratio: 0.5 " " } " @@ -2412,7 +2412,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'fc8' " - " type: 'InnerProduct' " + " type: INNER_PRODUCT " " inner_product_param { " " num_output: 1000 " " weight_filler { " @@ -2433,7 +2433,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { "} " "layers { " " name: 'loss' " - " type: 'SoftmaxWithLoss' " + " type: SOFTMAX_LOSS " " bottom: 'fc8' " " bottom: 'label' " "} "; From 522d4644a2f54ce9bbc691e94d6ff93ab73d4868 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 14 Jan 2015 18:46:21 -0800 Subject: [PATCH 277/798] add v1 to v2 upgrade tests --- src/caffe/test/test_upgrade_proto.cpp | 432 +++++++++++++++++++++++++- 1 file changed, 420 insertions(+), 12 deletions(-) diff --git a/src/caffe/test/test_upgrade_proto.cpp b/src/caffe/test/test_upgrade_proto.cpp index 52e7f1f99f5..3a135a67174 100644 --- a/src/caffe/test/test_upgrade_proto.cpp +++ b/src/caffe/test/test_upgrade_proto.cpp @@ -1083,7 +1083,7 @@ TEST_F(PaddingLayerUpgradeTest, TestImageNet) { this->RunPaddingUpgradeTest(input_proto, expected_output_proto); } -class V0UpgradeTest : public ::testing::Test { +class NetUpgradeTest : public ::testing::Test { protected: void RunV0UpgradeTest( const string& input_param_string, const string& output_param_string) { @@ -1101,10 +1101,27 @@ class V0UpgradeTest : public ::testing::Test { EXPECT_EQ(expected_output_param.DebugString(), actual_output_param.DebugString()); } + + void RunV1UpgradeTest( + const string& input_param_string, const string& output_param_string) { + // Test that UpgradeV0Net called on the NetParameter proto specified by + // input_param_string results in the NetParameter proto specified by + // output_param_string. + NetParameter input_param; + CHECK(google::protobuf::TextFormat::ParseFromString( + input_param_string, &input_param)); + NetParameter expected_output_param; + CHECK(google::protobuf::TextFormat::ParseFromString( + output_param_string, &expected_output_param)); + NetParameter actual_output_param; + UpgradeV1Net(input_param, &actual_output_param); + EXPECT_EQ(expected_output_param.DebugString(), + actual_output_param.DebugString()); + } }; -TEST_F(V0UpgradeTest, TestSimple) { - const string& input_proto = +TEST_F(NetUpgradeTest, TestSimple) { + const string& v0_proto = "name: 'CaffeNet' " "layers { " " layer { " @@ -1180,7 +1197,7 @@ TEST_F(V0UpgradeTest, TestSimple) { " bottom: 'fc8' " " bottom: 'label' " "} "; - const string& expected_output_proto = + const string& expected_v1_proto = "name: 'CaffeNet' " "layers { " " name: 'data' " @@ -1248,11 +1265,81 @@ TEST_F(V0UpgradeTest, TestSimple) { " bottom: 'fc8' " " bottom: 'label' " "} "; - this->RunV0UpgradeTest(input_proto, expected_output_proto); + this->RunV0UpgradeTest(v0_proto, expected_v1_proto); + + const string& expected_v2_proto = + "name: 'CaffeNet' " + "layer { " + " name: 'data' " + " type: 'Data' " + " data_param { " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " batch_size: 256 " + " } " + " transform_param { " + " crop_size: 227 " + " mirror: true " + " mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layer { " + " name: 'conv1' " + " type: 'Convolution' " + " convolution_param { " + " num_output: 96 " + " kernel_size: 11 " + " stride: 4 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layer { " + " name: 'fc8' " + " type: 'InnerProduct' " + " inner_product_param { " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'conv1' " + " top: 'fc8' " + "} " + "layer { " + " name: 'loss' " + " type: 'SoftmaxWithLoss' " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + this->RunV1UpgradeTest(expected_v1_proto, expected_v2_proto); } // Test any layer or parameter upgrades not covered by other tests. -TEST_F(V0UpgradeTest, TestAllParams) { +TEST_F(NetUpgradeTest, TestAllParams) { const string& input_proto = "name: 'CaffeNet' " "input: 'input_data' " @@ -1752,8 +1839,8 @@ TEST_F(V0UpgradeTest, TestAllParams) { this->RunV0UpgradeTest(input_proto, expected_output_proto); } -TEST_F(V0UpgradeTest, TestImageNet) { - const string& input_proto = +TEST_F(NetUpgradeTest, TestImageNet) { + const string& v0_proto = "name: 'CaffeNet' " "layers { " " layer { " @@ -2118,7 +2205,7 @@ TEST_F(V0UpgradeTest, TestImageNet) { " bottom: 'fc8' " " bottom: 'label' " "} "; - const string& expected_output_proto = + const string& expected_v1_proto = "name: 'CaffeNet' " "layers { " " name: 'data' " @@ -2437,7 +2524,328 @@ TEST_F(V0UpgradeTest, TestImageNet) { " bottom: 'fc8' " " bottom: 'label' " "} "; - this->RunV0UpgradeTest(input_proto, expected_output_proto); -} + this->RunV0UpgradeTest(v0_proto, expected_v1_proto); + + const string& expected_v2_proto = + "name: 'CaffeNet' " + "layer { " + " name: 'data' " + " type: 'Data' " + " data_param { " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " batch_size: 256 " + " } " + " transform_param { " + " crop_size: 227 " + " mirror: true " + " mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layer { " + " name: 'conv1' " + " type: 'Convolution' " + " convolution_param { " + " num_output: 96 " + " kernel_size: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layer { " + " name: 'relu1' " + " type: 'ReLU' " + " bottom: 'conv1' " + " top: 'conv1' " + "} " + "layer { " + " name: 'pool1' " + " type: 'Pooling' " + " pooling_param { " + " pool: MAX " + " kernel_size: 3 " + " stride: 2 " + " } " + " bottom: 'conv1' " + " top: 'pool1' " + "} " + "layer { " + " name: 'norm1' " + " type: 'LRN' " + " lrn_param { " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool1' " + " top: 'norm1' " + "} " + "layer { " + " name: 'conv2' " + " type: 'Convolution' " + " convolution_param { " + " num_output: 256 " + " group: 2 " + " kernel_size: 5 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'norm1' " + " top: 'conv2' " + "} " + "layer { " + " name: 'relu2' " + " type: 'ReLU' " + " bottom: 'conv2' " + " top: 'conv2' " + "} " + "layer { " + " name: 'pool2' " + " type: 'Pooling' " + " pooling_param { " + " pool: MAX " + " kernel_size: 3 " + " stride: 2 " + " } " + " bottom: 'conv2' " + " top: 'pool2' " + "} " + "layer { " + " name: 'norm2' " + " type: 'LRN' " + " lrn_param { " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool2' " + " top: 'norm2' " + "} " + "layer { " + " name: 'conv3' " + " type: 'Convolution' " + " convolution_param { " + " num_output: 384 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'norm2' " + " top: 'conv3' " + "} " + "layer { " + " name: 'relu3' " + " type: 'ReLU' " + " bottom: 'conv3' " + " top: 'conv3' " + "} " + "layer { " + " name: 'conv4' " + " type: 'Convolution' " + " convolution_param { " + " num_output: 384 " + " group: 2 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'conv3' " + " top: 'conv4' " + "} " + "layer { " + " name: 'relu4' " + " type: 'ReLU' " + " bottom: 'conv4' " + " top: 'conv4' " + "} " + "layer { " + " name: 'conv5' " + " type: 'Convolution' " + " convolution_param { " + " num_output: 256 " + " group: 2 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'conv4' " + " top: 'conv5' " + "} " + "layer { " + " name: 'relu5' " + " type: 'ReLU' " + " bottom: 'conv5' " + " top: 'conv5' " + "} " + "layer { " + " name: 'pool5' " + " type: 'Pooling' " + " pooling_param { " + " kernel_size: 3 " + " pool: MAX " + " stride: 2 " + " } " + " bottom: 'conv5' " + " top: 'pool5' " + "} " + "layer { " + " name: 'fc6' " + " type: 'InnerProduct' " + " inner_product_param { " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'pool5' " + " top: 'fc6' " + "} " + "layer { " + " name: 'relu6' " + " type: 'ReLU' " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layer { " + " name: 'drop6' " + " type: 'Dropout' " + " dropout_param { " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layer { " + " name: 'fc7' " + " type: 'InnerProduct' " + " inner_product_param { " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'fc6' " + " top: 'fc7' " + "} " + "layer { " + " name: 'relu7' " + " type: 'ReLU' " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layer { " + " name: 'drop7' " + " type: 'Dropout' " + " dropout_param { " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layer { " + " name: 'fc8' " + " type: 'InnerProduct' " + " inner_product_param { " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'fc7' " + " top: 'fc8' " + "} " + "layer { " + " name: 'loss' " + " type: 'SoftmaxWithLoss' " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + this->RunV1UpgradeTest(expected_v1_proto, expected_v2_proto); +} // NOLINT(readability/fn_size) -} // namespace caffe +} // NOLINT(readability/fn_size) // namespace caffe From e64bf225b492d61f357cc52a7269ba5e7db0f00b Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 14 Jan 2015 19:00:58 -0800 Subject: [PATCH 278/798] add test that all V1 layer type enum values upgrade to valid V2 string types --- src/caffe/test/test_upgrade_proto.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/caffe/test/test_upgrade_proto.cpp b/src/caffe/test/test_upgrade_proto.cpp index 3a135a67174..8cff961f9e8 100644 --- a/src/caffe/test/test_upgrade_proto.cpp +++ b/src/caffe/test/test_upgrade_proto.cpp @@ -7,6 +7,7 @@ #include "caffe/blob.hpp" #include "caffe/common.hpp" +#include "caffe/layer.hpp" #include "caffe/util/upgrade_proto.hpp" #include "caffe/test/test_caffe_main.hpp" @@ -2848,4 +2849,21 @@ TEST_F(NetUpgradeTest, TestImageNet) { this->RunV1UpgradeTest(expected_v1_proto, expected_v2_proto); } // NOLINT(readability/fn_size) +TEST_F(NetUpgradeTest, TestUpgradeV1LayerType) { + LayerParameter layer_param; + shared_ptr > layer; + for (int i = 0; i < V1LayerParameter_LayerType_LayerType_ARRAYSIZE; ++i) { + ASSERT_TRUE(V1LayerParameter_LayerType_IsValid(i)); + V1LayerParameter_LayerType v1_type = V1LayerParameter_LayerType(i); + string v2_layer_type(UpgradeV1LayerType(v1_type)); + if (v2_layer_type == "") { + EXPECT_EQ(V1LayerParameter_LayerType_NONE, v1_type); + continue; // Empty string isn't actually a valid layer type. + } + layer_param.set_type(v2_layer_type); + layer.reset(LayerRegistry::CreateLayer(layer_param)); + EXPECT_EQ(v2_layer_type, layer->type()); + } +} + } // NOLINT(readability/fn_size) // namespace caffe From 78b02e5fd3a43912556796bf29f118e0dea7b45e Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Wed, 14 Jan 2015 20:17:26 -0800 Subject: [PATCH 279/798] add message ParamSpec to replace param name, blobs_lr, weight_decay, ... --- src/caffe/net.cpp | 82 ++-- src/caffe/proto/caffe.proto | 52 ++- src/caffe/test/test_gradient_based_solver.cpp | 6 +- src/caffe/test/test_net.cpp | 380 ++++++++++-------- src/caffe/test/test_solver.cpp | 8 +- src/caffe/test/test_split_layer.cpp | 298 ++++++++------ src/caffe/test/test_upgrade_proto.cpp | 120 ++++-- src/caffe/util/upgrade_proto.cpp | 18 +- 8 files changed, 526 insertions(+), 438 deletions(-) diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 4461fa88e75..b3e11943c1b 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -113,36 +113,19 @@ void Net::Init(const NetParameter& in_param) { memory_used_ += top_vecs_[layer_id][top_id]->count(); } DLOG(INFO) << "Memory required for data: " << memory_used_ * sizeof(Dtype); - const int blobs_lr_size = layer_param.blobs_lr_size(); + const int param_size = layer_param.param_size(); const int num_param_blobs = layers_[layer_id]->blobs().size(); - CHECK(blobs_lr_size == num_param_blobs || blobs_lr_size == 0) - << "Incorrect blobs lr size: should be either 0 " - << "or the same as the number of the layer's parameter blobs."; - if (blobs_lr_size) { - // Check if this layer needs backward operation itself - for (int param_id = 0; param_id < blobs_lr_size; ++param_id) { - const bool param_need_backward = layer_param.blobs_lr(param_id) > 0; - need_backward |= param_need_backward; - layers_[layer_id]->set_param_propagate_down(param_id, - param_need_backward); - } - } else if (layers_[layer_id]->blobs().size()) { - // catch: if a layer param does not specify blobs_lr, we should assume the - // learning rate to be 1. Thus we will need to perform backward. - need_backward = true; - for (int param_id = 0; param_id < blobs_lr_size; ++param_id) { - layers_[layer_id]->set_param_propagate_down(param_id, true); - } + CHECK_LE(param_size, num_param_blobs) + << "Too many params specified for layer " << layer_param.name(); + ParamSpec default_param_spec; + for (int param_id = 0; param_id < num_param_blobs; ++param_id) { + const ParamSpec* param_spec = (param_id < param_size) ? + &layer_param.param(param_id) : &default_param_spec; + const bool param_need_backward = param_spec->lr_mult() > 0; + need_backward |= param_need_backward; + layers_[layer_id]->set_param_propagate_down(param_id, + param_need_backward); } - const int param_size = layer_param.param_size(); - CHECK(param_size == num_param_blobs || param_size == 0) - << "Incorrect param size: should be either 0 or the same as " - "the number of the layer's parameter blobs: " << num_param_blobs; - const int param_share_mode_size = layer_param.param_share_mode_size(); - CHECK(param_share_mode_size == num_param_blobs || - param_share_mode_size == 0) - << "Incorrect param_share_mode size: should be either 0 or the same as " - "the number of the layer's parameter blobs: " << num_param_blobs; for (int param_id = 0; param_id < num_param_blobs; ++param_id) { AppendParam(param, layer_id, param_id); } @@ -407,7 +390,8 @@ void Net::AppendParam(const NetParameter& param, const int layer_id, const int param_id) { const LayerParameter& layer_param = layers_[layer_id]->layer_param(); const int param_size = layer_param.param_size(); - string param_name = param_size ? layer_param.param(param_id) : ""; + string param_name = + (param_size > param_id) ? layer_param.param(param_id).name() : ""; if (param_name.size()) { param_display_names_.push_back(param_name); } else { @@ -442,10 +426,9 @@ void Net::AppendParam(const NetParameter& param, const int layer_id, Blob* this_blob = layers_[layer_id]->blobs()[param_id].get(); Blob* owner_blob = layers_[owner_layer_id]->blobs()[owner_param_id].get(); - const int param_share_mode_size = layer_param.param_share_mode_size(); - if (param_share_mode_size > param_id && - (layer_param.param_share_mode(param_id) == - LayerParameter_DimCheckMode_PERMISSIVE)) { + const int param_size = layer_param.param_size(); + if (param_size > param_id && (layer_param.param(param_id).share_mode() == + ParamSpec_DimCheckMode_PERMISSIVE)) { // Permissive dimension checking -- only check counts are the same. CHECK_EQ(this_blob->count(), owner_blob->count()) << "Shared parameter blobs must have the same count."; @@ -468,34 +451,15 @@ void Net::AppendParam(const NetParameter& param, const int layer_id, template void Net::GetLearningRateAndWeightDecay() { LOG(INFO) << "Collecting Learning Rate and Weight Decay."; + ParamSpec default_param_spec; for (int i = 0; i < layers_.size(); ++i) { vector > >& layer_blobs = layers_[i]->blobs(); - // push the learning rate mutlipliers - if (layers_[i]->layer_param().blobs_lr_size()) { - CHECK_EQ(layers_[i]->layer_param().blobs_lr_size(), layer_blobs.size()); - for (int j = 0; j < layer_blobs.size(); ++j) { - float local_lr = layers_[i]->layer_param().blobs_lr(j); - CHECK_GE(local_lr, 0.); - params_lr_.push_back(local_lr); - } - } else { - for (int j = 0; j < layer_blobs.size(); ++j) { - params_lr_.push_back(1.); - } - } - // push the weight decay multipliers - if (layers_[i]->layer_param().weight_decay_size()) { - CHECK_EQ(layers_[i]->layer_param().weight_decay_size(), - layer_blobs.size()); - for (int j = 0; j < layer_blobs.size(); ++j) { - float local_decay = layers_[i]->layer_param().weight_decay(j); - CHECK_GE(local_decay, 0.); - params_weight_decay_.push_back(local_decay); - } - } else { - for (int j = 0; j < layer_blobs.size(); ++j) { - params_weight_decay_.push_back(1.); - } + for (int j = 0; j < layer_blobs.size(); ++j) { + const ParamSpec* param_spec = + (layers_[i]->layer_param().param_size() > j) ? + &layers_[i]->layer_param().param(j) : &default_param_spec; + params_lr_.push_back(param_spec->lr_mult()); + params_weight_decay_.push_back(param_spec->decay_mult()); } } } diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 1178efe53a8..453bf7ff285 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -213,6 +213,31 @@ message NetStateRule { repeated string not_stage = 5; } +// Specifies training parameters (multipliers on global learning constants, +// and the name and other settings used for weight sharing). +message ParamSpec { + // The names of the parameter blobs -- useful for sharing parameters among + // layers, but never required otherwise. To share a parameter between two + // layers, give it a (non-empty) name. + optional string name = 1; + + // Whether to require shared weights to have the same shape, or just the same + // count -- defaults to STRICT if unspecified. + optional DimCheckMode share_mode = 2; + enum DimCheckMode { + // STRICT (default) requires that num, channels, height, width each match. + STRICT = 0; + // PERMISSIVE requires only the count (num*channels*height*width) to match. + PERMISSIVE = 1; + } + + // The multiplier on the global learning rate for this parameter. + optional float lr_mult = 3 [default = 1.0]; + + // The multiplier on the global weight decay for this parameter. + optional float decay_mult = 4 [default = 1.0]; +} + // NOTE // Update the next available ID when you add a new LayerParameter field. // @@ -228,29 +253,12 @@ message LayerParameter { // to each top blob. repeated float loss_weight = 5; - // The blobs containing the numeric parameters of the layer - repeated BlobProto blobs = 6; + // Specifies training parameters (multipliers on global learning constants, + // and the name and other settings used for weight sharing). + repeated ParamSpec param = 6; - // The names of the parameter blobs -- useful for sharing parameters among - // layers (but never required). - repeated string param = 7; - - // Whether to require shared weights to have the same shape, or just the same - // count -- defaults to STRICT if unspecified. - repeated DimCheckMode param_share_mode = 8; - enum DimCheckMode { - // STRICT (default) requires that num, channels, height, width each match. - STRICT = 0; - // PERMISSIVE requires only the count (num*channels*height*width) to match. - PERMISSIVE = 1; - } - - // The ratio that is multiplied on the global learning rate. If you want to - // set the learning ratio for one blob, you need to set it for all blobs. - repeated float blobs_lr = 9; - - // The weight decay that is multiplied on the global weight decay. - repeated float weight_decay = 10; + // The blobs containing the numeric parameters of the layer. + repeated BlobProto blobs = 7; // Rules controlling whether and when a layer is included in the network, // based on the current NetState. You may specify a non-zero number of rules diff --git a/src/caffe/test/test_gradient_based_solver.cpp b/src/caffe/test/test_gradient_based_solver.cpp index 1d8192aebbc..eb2569c04f2 100644 --- a/src/caffe/test/test_gradient_based_solver.cpp +++ b/src/caffe/test/test_gradient_based_solver.cpp @@ -64,7 +64,7 @@ class GradientBasedSolverTest : public MultiDeviceTest { "lr_policy: 'fixed' " "net_param { " " name: 'TestNetwork' " - " layers: { " + " layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -83,7 +83,7 @@ class GradientBasedSolverTest : public MultiDeviceTest { " top: 'data' " " top: 'targets' " " } " - " layers: { " + " layer { " " name: 'innerprod' " " type: 'InnerProduct' " " inner_product_param { " @@ -100,7 +100,7 @@ class GradientBasedSolverTest : public MultiDeviceTest { " bottom: 'data' " " top: 'innerprod' " " } " - " layers: { " + " layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'innerprod' " diff --git a/src/caffe/test/test_net.cpp b/src/caffe/test/test_net.cpp index a4e14f914c5..bc0dae331b3 100644 --- a/src/caffe/test/test_net.cpp +++ b/src/caffe/test/test_net.cpp @@ -59,7 +59,7 @@ class NetTest : public MultiDeviceTest { const bool accuracy_layer = false) { string proto = "name: 'TinyTestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -83,7 +83,7 @@ class NetTest : public MultiDeviceTest { " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerproduct' " " type: 'InnerProduct' " " inner_product_param { " @@ -97,14 +97,18 @@ class NetTest : public MultiDeviceTest { " value: 0 " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'data' " " top: 'innerproduct' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerproduct' " @@ -113,7 +117,7 @@ class NetTest : public MultiDeviceTest { "} "; if (accuracy_layer) { proto += - "layers: { " + "layer { " " name: 'loss' " " type: 'Accuracy' " " bottom: 'innerproduct' " @@ -130,7 +134,7 @@ class NetTest : public MultiDeviceTest { virtual void InitTinyNetEuclidean(const bool force_backward = false) { string proto = "name: 'TinyTestEuclidLossNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -150,7 +154,7 @@ class NetTest : public MultiDeviceTest { " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerproduct' " " type: 'InnerProduct' " " inner_product_param { " @@ -164,14 +168,18 @@ class NetTest : public MultiDeviceTest { " value: 0 " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'data' " " top: 'innerproduct' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'innerproduct' " @@ -190,7 +198,7 @@ class NetTest : public MultiDeviceTest { } const string& proto = "name: 'TrickyTestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -210,7 +218,7 @@ class NetTest : public MultiDeviceTest { " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerproduct' " " type: 'InnerProduct' " " inner_product_param { " @@ -224,14 +232,18 @@ class NetTest : public MultiDeviceTest { " value: 0 " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'data' " " top: 'transformed_data' " "} " - "layers: { " + "layer { " " name: 'innerproduct' " " type: 'InnerProduct' " " inner_product_param { " @@ -245,14 +257,18 @@ class NetTest : public MultiDeviceTest { " value: 0 " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'label' " " top: 'transformed_label' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " + loss_weight_stream.str() + @@ -277,7 +293,7 @@ class NetTest : public MultiDeviceTest { proto << "force_backward: true "; } proto << - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -292,9 +308,9 @@ class NetTest : public MultiDeviceTest { " } " " top: 'data' " "} " - "layers: { " + "layer { " " name: 'innerproduct1' " - " type: 'InnerProduct' " + " type: 'InnerProduct' " " inner_product_param { " " num_output: 10 " " bias_term: " << bias_term << @@ -303,14 +319,12 @@ class NetTest : public MultiDeviceTest { " std: 10 " " } " " } " - " param: 'unsharedweights1' "; + " param { " + " name: 'unsharedweights1' " + " lr_mult: " << blobs_lr_w1 << + " } "; if (bias_term) { - proto << " param: '' "; - } - proto << - " blobs_lr: " << blobs_lr_w1; - if (bias_term) { - proto << " blobs_lr: " << blobs_lr_b1; + proto << " param { lr_mult: " << blobs_lr_b1 << " } "; } proto << " bottom: 'data' " @@ -320,7 +334,7 @@ class NetTest : public MultiDeviceTest { } proto << "} " - "layers: { " + "layer { " " name: 'innerproduct2' " " type: 'InnerProduct' " " inner_product_param { " @@ -331,20 +345,18 @@ class NetTest : public MultiDeviceTest { " std: 10 " " } " " } " - " param: 'unsharedweights2' "; + " param { " + " name: 'unsharedweights2' " + " lr_mult: " << blobs_lr_w2 << + " } "; if (bias_term) { - proto << " param: '' "; + proto << " param { lr_mult: " << blobs_lr_b2 << " } "; } proto << " bottom: 'data' " - " blobs_lr: " << blobs_lr_w2; - if (bias_term) { - proto << " blobs_lr: " << blobs_lr_b2; - } - proto << " top: 'innerproduct2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' "; if (loss_weight) { @@ -360,7 +372,7 @@ class NetTest : public MultiDeviceTest { virtual void InitSharedWeightsNet() { const string& proto = "name: 'SharedWeightsNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -375,7 +387,7 @@ class NetTest : public MultiDeviceTest { " } " " top: 'data' " "} " - "layers: { " + "layer { " " name: 'innerproduct1' " " type: 'InnerProduct' " " inner_product_param { " @@ -386,11 +398,11 @@ class NetTest : public MultiDeviceTest { " std: 10 " " } " " } " - " param: 'sharedweights' " + " param { name: 'sharedweights' } " " bottom: 'data' " " top: 'innerproduct1' " "} " - "layers: { " + "layer { " " name: 'innerproduct2' " " type: 'InnerProduct' " " inner_product_param { " @@ -401,11 +413,11 @@ class NetTest : public MultiDeviceTest { " std: 10 " " } " " } " - " param: 'sharedweights' " + " param { name: 'sharedweights' } " " bottom: 'data' " " top: 'innerproduct2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'innerproduct1' " @@ -417,7 +429,7 @@ class NetTest : public MultiDeviceTest { virtual void InitDiffDataUnsharedWeightsNet() { const string& proto = "name: 'DiffDataUnsharedWeightsNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -437,7 +449,7 @@ class NetTest : public MultiDeviceTest { " top: 'data1' " " top: 'data2' " "} " - "layers: { " + "layer { " " name: 'innerproduct1' " " type: 'InnerProduct' " " inner_product_param { " @@ -448,11 +460,11 @@ class NetTest : public MultiDeviceTest { " value: 0.5 " " } " " } " - " param: 'unsharedweights1' " + " param { name: 'unsharedweights1' } " " bottom: 'data1' " " top: 'innerproduct1' " "} " - "layers: { " + "layer { " " name: 'innerproduct2' " " type: 'InnerProduct' " " inner_product_param { " @@ -463,11 +475,11 @@ class NetTest : public MultiDeviceTest { " value: 0.5 " " } " " } " - " param: 'unsharedweights2' " + " param { name: 'unsharedweights2' } " " bottom: 'innerproduct1' " " top: 'innerproduct2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'data2' " @@ -479,7 +491,7 @@ class NetTest : public MultiDeviceTest { virtual void InitDiffDataSharedWeightsNet() { const string& proto = "name: 'DiffDataSharedWeightsNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -499,7 +511,7 @@ class NetTest : public MultiDeviceTest { " top: 'data1' " " top: 'data2' " "} " - "layers: { " + "layer { " " name: 'innerproduct1' " " type: 'InnerProduct' " " inner_product_param { " @@ -510,11 +522,11 @@ class NetTest : public MultiDeviceTest { " value: 0.5 " " } " " } " - " param: 'sharedweights' " + " param { name: 'sharedweights' } " " bottom: 'data1' " " top: 'innerproduct1' " "} " - "layers: { " + "layer { " " name: 'innerproduct2' " " type: 'InnerProduct' " " inner_product_param { " @@ -525,11 +537,11 @@ class NetTest : public MultiDeviceTest { " value: 0.5 " " } " " } " - " param: 'sharedweights' " + " param { name: 'sharedweights' } " " bottom: 'innerproduct1' " " top: 'innerproduct2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'data2' " @@ -546,7 +558,7 @@ class NetTest : public MultiDeviceTest { "input_dim: 3 " "input_dim: 100 " "input_dim: 100 " - "layers: { " + "layer { " " name: 'conv1' " " type: 'Convolution' " " bottom: 'data' " @@ -565,13 +577,13 @@ class NetTest : public MultiDeviceTest { " } " " } " "} " - "layers: { " + "layer { " " name: 'relu1' " " type: 'ReLU' " " bottom: 'conv1' " " top: 'conv1' " "} " - "layers: { " + "layer { " " name: 'pool1' " " type: 'Pooling' " " bottom: 'conv1' " @@ -582,7 +594,7 @@ class NetTest : public MultiDeviceTest { " stride: 2 " " } " "} " - "layers: { " + "layer { " " name: 'norm1' " " type: 'LRN' " " bottom: 'pool1' " @@ -591,7 +603,7 @@ class NetTest : public MultiDeviceTest { " local_size: 3 " " } " "} " - "layers: { " + "layer { " " name: 'softmax' " " type: 'Softmax' " " bottom: 'norm1' " @@ -1261,19 +1273,19 @@ class FilterNetTest : public ::testing::Test { TEST_F(FilterNetTest, TestNoFilter) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1285,7 +1297,7 @@ TEST_F(FilterNetTest, TestNoFilter) { TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { const string& input_proto = "name: 'LeNet' " - "layers { " + "layer { " " name: 'mnist' " " type: 'Data' " " top: 'data' " @@ -1299,7 +1311,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " include: { phase: TRAIN } " "} " - "layers { " + "layer { " " name: 'mnist' " " type: 'Data' " " top: 'data' " @@ -1313,13 +1325,17 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " include: { phase: TEST } " "} " - "layers { " + "layer { " " name: 'conv1' " " type: 'Convolution' " " bottom: 'data' " " top: 'conv1' " - " blobs_lr: 1 " - " blobs_lr: 2 " + " param { " + " lr_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " } " " convolution_param { " " num_output: 20 " " kernel_size: 5 " @@ -1332,13 +1348,17 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " } " "} " - "layers { " + "layer { " " name: 'ip1' " " type: 'InnerProduct' " " bottom: 'conv1' " " top: 'ip1' " - " blobs_lr: 1 " - " blobs_lr: 2 " + " param { " + " lr_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " } " " inner_product_param { " " num_output: 10 " " weight_filler { " @@ -1349,7 +1369,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " } " "} " - "layers { " + "layer { " " name: 'accuracy' " " type: 'Accuracy' " " bottom: 'ip1' " @@ -1357,7 +1377,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " top: 'accuracy' " " include: { phase: TEST } " "} " - "layers { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'ip2' " @@ -1368,7 +1388,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { const string input_proto_test = "state: { phase: TEST } " + input_proto; const string output_proto_train = "name: 'LeNet' " - "layers { " + "layer { " " name: 'mnist' " " type: 'Data' " " top: 'data' " @@ -1382,13 +1402,17 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " include: { phase: TRAIN } " "} " - "layers { " + "layer { " " name: 'conv1' " " type: 'Convolution' " " bottom: 'data' " " top: 'conv1' " - " blobs_lr: 1 " - " blobs_lr: 2 " + " param { " + " lr_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " } " " convolution_param { " " num_output: 20 " " kernel_size: 5 " @@ -1401,13 +1425,17 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " } " "} " - "layers { " + "layer { " " name: 'ip1' " " type: 'InnerProduct' " " bottom: 'conv1' " " top: 'ip1' " - " blobs_lr: 1 " - " blobs_lr: 2 " + " param { " + " lr_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " } " " inner_product_param { " " num_output: 10 " " weight_filler { " @@ -1418,7 +1446,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " } " "} " - "layers { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'ip2' " @@ -1427,7 +1455,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { "} "; const string& output_proto_test = "name: 'LeNet' " - "layers { " + "layer { " " name: 'mnist' " " type: 'Data' " " top: 'data' " @@ -1441,13 +1469,17 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " include: { phase: TEST } " "} " - "layers { " + "layer { " " name: 'conv1' " " type: 'Convolution' " " bottom: 'data' " " top: 'conv1' " - " blobs_lr: 1 " - " blobs_lr: 2 " + " param { " + " lr_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " } " " convolution_param { " " num_output: 20 " " kernel_size: 5 " @@ -1460,13 +1492,17 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " } " "} " - "layers { " + "layer { " " name: 'ip1' " " type: 'InnerProduct' " " bottom: 'conv1' " " top: 'ip1' " - " blobs_lr: 1 " - " blobs_lr: 2 " + " param { " + " lr_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " } " " inner_product_param { " " num_output: 10 " " weight_filler { " @@ -1477,7 +1513,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " } " " } " "} " - "layers { " + "layer { " " name: 'accuracy' " " type: 'Accuracy' " " bottom: 'ip1' " @@ -1485,7 +1521,7 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { " top: 'accuracy' " " include: { phase: TEST } " "} " - "layers { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'ip2' " @@ -1517,20 +1553,20 @@ TEST_F(FilterNetTest, TestFilterLeNetTrainTest) { TEST_F(FilterNetTest, TestFilterOutByStage) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " " include: { stage: 'mystage' } " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1538,13 +1574,13 @@ TEST_F(FilterNetTest, TestFilterOutByStage) { "} "; const string& output_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1556,20 +1592,20 @@ TEST_F(FilterNetTest, TestFilterOutByStage) { TEST_F(FilterNetTest, TestFilterOutByStage2) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'mystage' } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1577,13 +1613,13 @@ TEST_F(FilterNetTest, TestFilterOutByStage2) { "} "; const string& output_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1596,20 +1632,20 @@ TEST_F(FilterNetTest, TestFilterInByStage) { const string& input_proto = "state: { stage: 'mystage' } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'mystage' } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1621,20 +1657,20 @@ TEST_F(FilterNetTest, TestFilterInByStage) { TEST_F(FilterNetTest, TestFilterInByStage2) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " exclude: { stage: 'mystage' } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1647,20 +1683,20 @@ TEST_F(FilterNetTest, TestFilterOutByMultipleStage) { const string& input_proto = "state: { stage: 'mystage' } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'mystage' stage: 'myotherstage' } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1670,13 +1706,13 @@ TEST_F(FilterNetTest, TestFilterOutByMultipleStage) { const string& output_proto = "state: { stage: 'mystage' } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1690,13 +1726,13 @@ TEST_F(FilterNetTest, TestFilterInByMultipleStage) { const string& input_proto = "state: { stage: 'mystage' } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " @@ -1704,7 +1740,7 @@ TEST_F(FilterNetTest, TestFilterInByMultipleStage) { " include: { stage: 'myotherstage' } " " include: { stage: 'mystage' } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1718,20 +1754,20 @@ TEST_F(FilterNetTest, TestFilterInByMultipleStage2) { const string& input_proto = "state: { stage: 'mystage' stage: 'myotherstage' } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { stage: 'mystage' stage: 'myotherstage' } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1745,20 +1781,20 @@ TEST_F(FilterNetTest, TestFilterInByNotStage) { const string& input_proto = "state: { stage: 'mystage' } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { not_stage: 'myotherstage' } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1772,20 +1808,20 @@ TEST_F(FilterNetTest, TestFilterOutByNotStage) { const string& input_proto = "state: { stage: 'mystage' } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { not_stage: 'mystage' } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1795,7 +1831,7 @@ TEST_F(FilterNetTest, TestFilterOutByNotStage) { const string& output_proto = "state: { stage: 'mystage' } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " @@ -1807,20 +1843,20 @@ TEST_F(FilterNetTest, TestFilterOutByNotStage) { TEST_F(FilterNetTest, TestFilterOutByMinLevel) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 3 } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1828,13 +1864,13 @@ TEST_F(FilterNetTest, TestFilterOutByMinLevel) { "} "; const string& output_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1846,20 +1882,20 @@ TEST_F(FilterNetTest, TestFilterOutByMinLevel) { TEST_F(FilterNetTest, TestFilterOutByMaxLevel) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { max_level: -3 } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1867,13 +1903,13 @@ TEST_F(FilterNetTest, TestFilterOutByMaxLevel) { "} "; const string& output_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1885,20 +1921,20 @@ TEST_F(FilterNetTest, TestFilterOutByMaxLevel) { TEST_F(FilterNetTest, TestFilterInByMinLevel) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 0 } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1911,20 +1947,20 @@ TEST_F(FilterNetTest, TestFilterInByMinLevel2) { const string& input_proto = "state: { level: 7 } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 3 } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1936,20 +1972,20 @@ TEST_F(FilterNetTest, TestFilterInByMinLevel2) { TEST_F(FilterNetTest, TestFilterInByMaxLevel) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { max_level: 0 } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1962,20 +1998,20 @@ TEST_F(FilterNetTest, TestFilterInByMaxLevel2) { const string& input_proto = "state: { level: -7 } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { max_level: -3 } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -1987,20 +2023,20 @@ TEST_F(FilterNetTest, TestFilterInByMaxLevel2) { TEST_F(FilterNetTest, TestFilterInOutByIncludeMultiRule) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " include: { min_level: 2 phase: TRAIN } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -2014,13 +2050,13 @@ TEST_F(FilterNetTest, TestFilterInOutByIncludeMultiRule) { const string& output_proto_train = "state: { level: 4 phase: TRAIN } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " @@ -2030,13 +2066,13 @@ TEST_F(FilterNetTest, TestFilterInOutByIncludeMultiRule) { const string& output_proto_test = "state: { level: 4 phase: TEST } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -2050,13 +2086,13 @@ TEST_F(FilterNetTest, TestFilterInOutByIncludeMultiRule) { TEST_F(FilterNetTest, TestFilterInByIncludeMultiRule) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " @@ -2064,7 +2100,7 @@ TEST_F(FilterNetTest, TestFilterInByIncludeMultiRule) { " include: { min_level: 2 phase: TRAIN } " " include: { phase: TEST } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -2083,20 +2119,20 @@ TEST_F(FilterNetTest, TestFilterInByIncludeMultiRule) { TEST_F(FilterNetTest, TestFilterInOutByExcludeMultiRule) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " " exclude: { min_level: 2 phase: TRAIN } " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -2110,13 +2146,13 @@ TEST_F(FilterNetTest, TestFilterInOutByExcludeMultiRule) { const string& output_proto_train = "state: { level: 4 phase: TRAIN } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -2126,13 +2162,13 @@ TEST_F(FilterNetTest, TestFilterInOutByExcludeMultiRule) { const string& output_proto_test = "state: { level: 4 phase: TEST } " "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " diff --git a/src/caffe/test/test_solver.cpp b/src/caffe/test/test_solver.cpp index d3f646c5bb6..1c2c9bbb740 100644 --- a/src/caffe/test/test_solver.cpp +++ b/src/caffe/test/test_solver.cpp @@ -51,7 +51,7 @@ TYPED_TEST(SolverTest, TestInitTrainTestNets) { "test_state: {}" "net_param { " " name: 'TestNetwork' " - " layers: { " + " layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -67,7 +67,7 @@ TYPED_TEST(SolverTest, TestInitTrainTestNets) { " top: 'data' " " top: 'label' " " } " - " layers: { " + " layer { " " name: 'innerprod' " " type: 'InnerProduct' " " inner_product_param { " @@ -76,7 +76,7 @@ TYPED_TEST(SolverTest, TestInitTrainTestNets) { " bottom: 'data' " " top: 'innerprod' " " } " - " layers: { " + " layer { " " name: 'accuracy' " " type: 'Accuracy' " " bottom: 'innerprod' " @@ -84,7 +84,7 @@ TYPED_TEST(SolverTest, TestInitTrainTestNets) { " top: 'accuracy' " " exclude: { phase: TRAIN } " " } " - " layers: { " + " layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " diff --git a/src/caffe/test/test_split_layer.cpp b/src/caffe/test/test_split_layer.cpp index 584d0a4ab9c..be5204bfc3e 100644 --- a/src/caffe/test/test_split_layer.cpp +++ b/src/caffe/test/test_split_layer.cpp @@ -114,19 +114,19 @@ class SplitLayerInsertionTest : public ::testing::Test { TEST_F(SplitLayerInsertionTest, TestNoInsertion1) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -138,32 +138,32 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertion1) { TEST_F(SplitLayerInsertionTest, TestNoInsertion2) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'data_split' " " type: 'Split' " " bottom: 'data' " " top: 'data_split_0' " " top: 'data_split_1' " "} " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data_split_0' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'data_split_1' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'innerprod1' " @@ -175,7 +175,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertion2) { TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { const string& input_proto = "name: 'CaffeNet' " - "layers { " + "layer { " " name: 'data' " " type: 'Data' " " data_param { " @@ -190,7 +190,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " top: 'data' " " top: 'label' " "} " - "layers { " + "layer { " " name: 'conv1' " " type: 'Convolution' " " convolution_param { " @@ -206,20 +206,24 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " value: 0. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'data' " " top: 'conv1' " "} " - "layers { " + "layer { " " name: 'relu1' " " type: 'ReLU' " " bottom: 'conv1' " " top: 'conv1' " "} " - "layers { " + "layer { " " name: 'pool1' " " type: 'Pooling' " " pooling_param { " @@ -230,7 +234,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " bottom: 'conv1' " " top: 'pool1' " "} " - "layers { " + "layer { " " name: 'norm1' " " type: 'LRN' " " lrn_param { " @@ -241,7 +245,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " bottom: 'pool1' " " top: 'norm1' " "} " - "layers { " + "layer { " " name: 'conv2' " " type: 'Convolution' " " convolution_param { " @@ -258,20 +262,24 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'norm1' " " top: 'conv2' " "} " - "layers { " + "layer { " " name: 'relu2' " " type: 'ReLU' " " bottom: 'conv2' " " top: 'conv2' " "} " - "layers { " + "layer { " " name: 'pool2' " " type: 'Pooling' " " pooling_param { " @@ -282,7 +290,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " bottom: 'conv2' " " top: 'pool2' " "} " - "layers { " + "layer { " " name: 'norm2' " " type: 'LRN' " " lrn_param { " @@ -293,7 +301,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " bottom: 'pool2' " " top: 'norm2' " "} " - "layers { " + "layer { " " name: 'conv3' " " type: 'Convolution' " " convolution_param { " @@ -309,20 +317,24 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " value: 0. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'norm2' " " top: 'conv3' " "} " - "layers { " + "layer { " " name: 'relu3' " " type: 'ReLU' " " bottom: 'conv3' " " top: 'conv3' " "} " - "layers { " + "layer { " " name: 'conv4' " " type: 'Convolution' " " convolution_param { " @@ -339,20 +351,24 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'conv3' " " top: 'conv4' " "} " - "layers { " + "layer { " " name: 'relu4' " " type: 'ReLU' " " bottom: 'conv4' " " top: 'conv4' " "} " - "layers { " + "layer { " " name: 'conv5' " " type: 'Convolution' " " convolution_param { " @@ -369,20 +385,24 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'conv4' " " top: 'conv5' " "} " - "layers { " + "layer { " " name: 'relu5' " " type: 'ReLU' " " bottom: 'conv5' " " top: 'conv5' " "} " - "layers { " + "layer { " " name: 'pool5' " " type: 'Pooling' " " pooling_param { " @@ -393,7 +413,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " bottom: 'conv5' " " top: 'pool5' " "} " - "layers { " + "layer { " " name: 'fc6' " " type: 'InnerProduct' " " inner_product_param { " @@ -407,20 +427,24 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'pool5' " " top: 'fc6' " "} " - "layers { " + "layer { " " name: 'relu6' " " type: 'ReLU' " " bottom: 'fc6' " " top: 'fc6' " "} " - "layers { " + "layer { " " name: 'drop6' " " type: 'Dropout' " " dropout_param { " @@ -429,7 +453,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " bottom: 'fc6' " " top: 'fc6' " "} " - "layers { " + "layer { " " name: 'fc7' " " type: 'InnerProduct' " " inner_product_param { " @@ -443,20 +467,24 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'fc6' " " top: 'fc7' " "} " - "layers { " + "layer { " " name: 'relu7' " " type: 'ReLU' " " bottom: 'fc7' " " top: 'fc7' " "} " - "layers { " + "layer { " " name: 'drop7' " " type: 'Dropout' " " dropout_param { " @@ -465,7 +493,7 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " bottom: 'fc7' " " top: 'fc7' " "} " - "layers { " + "layer { " " name: 'fc8' " " type: 'InnerProduct' " " inner_product_param { " @@ -479,14 +507,18 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { " value: 0 " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'fc7' " " top: 'fc8' " "} " - "layers { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'fc8' " @@ -498,25 +530,25 @@ TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { TEST_F(SplitLayerInsertionTest, TestNoInsertionWithInPlace) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod' " "} " - "layers: { " + "layer { " " name: 'relu' " " type: 'ReLU' " " bottom: 'innerprod' " " top: 'innerprod' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'SoftmaxWithLoss' " " bottom: 'innerprod' " @@ -529,7 +561,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { const string& input_proto = "name: 'UnsharedWeightsNetwork' " "force_backward: true " - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -544,7 +576,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { " } " " top: 'data' " "} " - "layers: { " + "layer { " " name: 'innerproduct1' " " type: 'InnerProduct' " " inner_product_param { " @@ -555,12 +587,12 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { " std: 10 " " } " " } " - " param: 'unsharedweights1' " + " param { name: 'unsharedweights1' } " " bottom: 'data' " " top: 'innerproduct1' " " loss_weight: 2.5 " "} " - "layers: { " + "layer { " " name: 'innerproduct2' " " type: 'InnerProduct' " " inner_product_param { " @@ -571,11 +603,11 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { " std: 10 " " } " " } " - " param: 'unsharedweights2' " + " param { name: 'unsharedweights2' } " " bottom: 'data' " " top: 'innerproduct2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'innerproduct1' " @@ -584,7 +616,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { const string& expected_output_proto = "name: 'UnsharedWeightsNetwork' " "force_backward: true " - "layers: { " + "layer { " " name: 'data' " " type: 'DummyData' " " dummy_data_param { " @@ -599,14 +631,14 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { " } " " top: 'data' " "} " - "layers: { " + "layer { " " name: 'data_data_0_split' " " type: 'Split' " " bottom: 'data' " " top: 'data_data_0_split_0' " " top: 'data_data_0_split_1' " "} " - "layers: { " + "layer { " " name: 'innerproduct1' " " type: 'InnerProduct' " " inner_product_param { " @@ -617,11 +649,11 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { " std: 10 " " } " " } " - " param: 'unsharedweights1' " + " param { name: 'unsharedweights1' } " " bottom: 'data_data_0_split_0' " " top: 'innerproduct1' " "} " - "layers: { " + "layer { " " name: 'innerproduct1_innerproduct1_0_split' " " type: 'Split' " " bottom: 'innerproduct1' " @@ -630,7 +662,7 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { " loss_weight: 2.5 " " loss_weight: 0 " "} " - "layers: { " + "layer { " " name: 'innerproduct2' " " type: 'InnerProduct' " " inner_product_param { " @@ -641,11 +673,11 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { " std: 10 " " } " " } " - " param: 'unsharedweights2' " + " param { name: 'unsharedweights2' } " " bottom: 'data_data_0_split_1' " " top: 'innerproduct2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'innerproduct1_innerproduct1_0_split_1' " @@ -657,37 +689,37 @@ TEST_F(SplitLayerInsertionTest, TestLossInsertion) { TEST_F(SplitLayerInsertionTest, TestInsertion) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'innerprod3' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod3' " "} " - "layers: { " + "layer { " " name: 'loss1' " " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'loss2' " " type: 'EuclideanLoss' " " bottom: 'innerprod2' " @@ -695,13 +727,13 @@ TEST_F(SplitLayerInsertionTest, TestInsertion) { "} "; const string& expected_output_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'data_data_0_split' " " type: 'Split' " " bottom: 'data' " @@ -709,38 +741,38 @@ TEST_F(SplitLayerInsertionTest, TestInsertion) { " top: 'data_data_0_split_1' " " top: 'data_data_0_split_2' " "} " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data_data_0_split_0' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'data_data_0_split_1' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'innerprod2_innerprod2_0_split' " " type: 'Split' " " bottom: 'innerprod2' " " top: 'innerprod2_innerprod2_0_split_0' " " top: 'innerprod2_innerprod2_0_split_1' " "} " - "layers: { " + "layer { " " name: 'innerprod3' " " type: 'InnerProduct' " " bottom: 'data_data_0_split_2' " " top: 'innerprod3' " "} " - "layers: { " + "layer { " " name: 'loss1' " " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod2_innerprod2_0_split_0' " "} " - "layers: { " + "layer { " " name: 'loss2' " " type: 'EuclideanLoss' " " bottom: 'innerprod2_innerprod2_0_split_1' " @@ -752,43 +784,43 @@ TEST_F(SplitLayerInsertionTest, TestInsertion) { TEST_F(SplitLayerInsertionTest, TestInsertionTwoTop) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'label' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'innerprod3' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod3' " "} " - "layers: { " + "layer { " " name: 'innerprod4' " " type: 'InnerProduct' " " bottom: 'label' " " top: 'innerprod4' " "} " - "layers: { " + "layer { " " name: 'loss1' " " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod3' " "} " - "layers: { " + "layer { " " name: 'loss2' " " type: 'EuclideanLoss' " " bottom: 'innerprod2' " @@ -796,57 +828,57 @@ TEST_F(SplitLayerInsertionTest, TestInsertionTwoTop) { "} "; const string& expected_output_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'data_data_0_split' " " type: 'Split' " " bottom: 'data' " " top: 'data_data_0_split_0' " " top: 'data_data_0_split_1' " "} " - "layers: { " + "layer { " " name: 'label_data_1_split' " " type: 'Split' " " bottom: 'label' " " top: 'label_data_1_split_0' " " top: 'label_data_1_split_1' " "} " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data_data_0_split_0' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'label_data_1_split_0' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'innerprod3' " " type: 'InnerProduct' " " bottom: 'data_data_0_split_1' " " top: 'innerprod3' " "} " - "layers: { " + "layer { " " name: 'innerprod4' " " type: 'InnerProduct' " " bottom: 'label_data_1_split_1' " " top: 'innerprod4' " "} " - "layers: { " + "layer { " " name: 'loss1' " " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'innerprod3' " "} " - "layers: { " + "layer { " " name: 'loss2' " " type: 'EuclideanLoss' " " bottom: 'innerprod2' " @@ -863,19 +895,19 @@ TEST_F(SplitLayerInsertionTest, TestInputInsertion) { "input_dim: 3 " "input_dim: 227 " "input_dim: 227 " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'innerprod1' " @@ -888,26 +920,26 @@ TEST_F(SplitLayerInsertionTest, TestInputInsertion) { "input_dim: 3 " "input_dim: 227 " "input_dim: 227 " - "layers: { " + "layer { " " name: 'data_input_0_split' " " type: 'Split' " " bottom: 'data' " " top: 'data_input_0_split_0' " " top: 'data_input_0_split_1' " "} " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data_input_0_split_0' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'data_input_0_split_1' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'loss' " " type: 'EuclideanLoss' " " bottom: 'innerprod1' " @@ -919,37 +951,37 @@ TEST_F(SplitLayerInsertionTest, TestInputInsertion) { TEST_F(SplitLayerInsertionTest, TestWithInPlace) { const string& input_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'relu1' " " type: 'ReLU' " " bottom: 'innerprod1' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'innerprod1' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'loss1' " " type: 'EuclideanLoss' " " bottom: 'innerprod1' " " bottom: 'label' " "} " - "layers: { " + "layer { " " name: 'loss2' " " type: 'EuclideanLoss' " " bottom: 'innerprod2' " @@ -957,51 +989,51 @@ TEST_F(SplitLayerInsertionTest, TestWithInPlace) { "} "; const string& expected_output_proto = "name: 'TestNetwork' " - "layers: { " + "layer { " " name: 'data' " " type: 'Data' " " top: 'data' " " top: 'label' " "} " - "layers: { " + "layer { " " name: 'data_data_0_split' " " type: 'Split' " " bottom: 'data' " " top: 'data_data_0_split_0' " " top: 'data_data_0_split_1' " "} " - "layers: { " + "layer { " " name: 'innerprod1' " " type: 'InnerProduct' " " bottom: 'data_data_0_split_0' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'relu1' " " type: 'ReLU' " " bottom: 'innerprod1' " " top: 'innerprod1' " "} " - "layers: { " + "layer { " " name: 'innerprod1_relu1_0_split' " " type: 'Split' " " bottom: 'innerprod1' " " top: 'innerprod1_relu1_0_split_0' " " top: 'innerprod1_relu1_0_split_1' " "} " - "layers: { " + "layer { " " name: 'innerprod2' " " type: 'InnerProduct' " " bottom: 'innerprod1_relu1_0_split_0' " " top: 'innerprod2' " "} " - "layers: { " + "layer { " " name: 'loss1' " " type: 'EuclideanLoss' " " bottom: 'innerprod1_relu1_0_split_1' " " bottom: 'label' " "} " - "layers: { " + "layer { " " name: 'loss2' " " type: 'EuclideanLoss' " " bottom: 'innerprod2' " diff --git a/src/caffe/test/test_upgrade_proto.cpp b/src/caffe/test/test_upgrade_proto.cpp index 8cff961f9e8..7094055d4c8 100644 --- a/src/caffe/test/test_upgrade_proto.cpp +++ b/src/caffe/test/test_upgrade_proto.cpp @@ -1302,10 +1302,14 @@ TEST_F(NetUpgradeTest, TestSimple) { " value: 0. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'data' " " top: 'conv1' " "} " @@ -1323,10 +1327,14 @@ TEST_F(NetUpgradeTest, TestSimple) { " value: 0 " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'conv1' " " top: 'fc8' " "} " @@ -2560,10 +2568,14 @@ TEST_F(NetUpgradeTest, TestImageNet) { " value: 0. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'data' " " top: 'conv1' " "} " @@ -2612,10 +2624,14 @@ TEST_F(NetUpgradeTest, TestImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'norm1' " " top: 'conv2' " "} " @@ -2663,10 +2679,14 @@ TEST_F(NetUpgradeTest, TestImageNet) { " value: 0. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'norm2' " " top: 'conv3' " "} " @@ -2693,10 +2713,14 @@ TEST_F(NetUpgradeTest, TestImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'conv3' " " top: 'conv4' " "} " @@ -2723,10 +2747,14 @@ TEST_F(NetUpgradeTest, TestImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'conv4' " " top: 'conv5' " "} " @@ -2761,10 +2789,14 @@ TEST_F(NetUpgradeTest, TestImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'pool5' " " top: 'fc6' " "} " @@ -2797,10 +2829,14 @@ TEST_F(NetUpgradeTest, TestImageNet) { " value: 1. " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'fc6' " " top: 'fc7' " "} " @@ -2833,10 +2869,14 @@ TEST_F(NetUpgradeTest, TestImageNet) { " value: 0 " " } " " } " - " blobs_lr: 1. " - " blobs_lr: 2. " - " weight_decay: 1. " - " weight_decay: 0. " + " param { " + " lr_mult: 1 " + " decay_mult: 1 " + " } " + " param { " + " lr_mult: 2 " + " decay_mult: 0 " + " } " " bottom: 'fc7' " " top: 'fc8' " "} " diff --git a/src/caffe/util/upgrade_proto.cpp b/src/caffe/util/upgrade_proto.cpp index 575d7a73fee..6b401b537e0 100644 --- a/src/caffe/util/upgrade_proto.cpp +++ b/src/caffe/util/upgrade_proto.cpp @@ -659,6 +659,7 @@ bool UpgradeV1Net(const NetParameter& v1_net_param, NetParameter* net_param) { } net_param->CopyFrom(v1_net_param); net_param->clear_layers(); + net_param->clear_layer(); for (int i = 0; i < v1_net_param.layers_size(); ++i) { if (!UpgradeV1LayerParameter(v1_net_param.layers(i), net_param->add_layer())) { @@ -695,27 +696,34 @@ bool UpgradeV1LayerParameter(const V1LayerParameter& v1_layer_param, layer_param->add_blobs()->CopyFrom(v1_layer_param.blobs(i)); } for (int i = 0; i < v1_layer_param.param_size(); ++i) { - layer_param->add_param(v1_layer_param.param(i)); + while (layer_param->param_size() <= i) { layer_param->add_param(); } + layer_param->mutable_param(i)->set_name(v1_layer_param.param(i)); } + ParamSpec_DimCheckMode mode; for (int i = 0; i < v1_layer_param.blob_share_mode_size(); ++i) { + while (layer_param->param_size() <= i) { layer_param->add_param(); } switch (v1_layer_param.blob_share_mode(i)) { case V1LayerParameter_DimCheckMode_STRICT: - layer_param->add_param_share_mode(LayerParameter_DimCheckMode_STRICT); + mode = ParamSpec_DimCheckMode_STRICT; break; case V1LayerParameter_DimCheckMode_PERMISSIVE: - layer_param->add_param_share_mode(LayerParameter_DimCheckMode_PERMISSIVE); + mode = ParamSpec_DimCheckMode_PERMISSIVE; break; default: LOG(FATAL) << "Unknown blob_share_mode: " << v1_layer_param.blob_share_mode(i); break; } + layer_param->mutable_param(i)->set_share_mode(mode); } for (int i = 0; i < v1_layer_param.blobs_lr_size(); ++i) { - layer_param->add_blobs_lr(v1_layer_param.blobs_lr(i)); + while (layer_param->param_size() <= i) { layer_param->add_param(); } + layer_param->mutable_param(i)->set_lr_mult(v1_layer_param.blobs_lr(i)); } for (int i = 0; i < v1_layer_param.weight_decay_size(); ++i) { - layer_param->add_weight_decay(v1_layer_param.weight_decay(i)); + while (layer_param->param_size() <= i) { layer_param->add_param(); } + layer_param->mutable_param(i)->set_decay_mult( + v1_layer_param.weight_decay(i)); } for (int i = 0; i < v1_layer_param.loss_weight_size(); ++i) { layer_param->add_loss_weight(v1_layer_param.loss_weight(i)); From 62d1d3add909c86bf26e85203faa1ed64c88c597 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 15 Jan 2015 00:13:23 -0800 Subject: [PATCH 280/798] get rid of NetParameterPrettyPrint as layer is now after inputs (whoohoo) --- include/caffe/util/upgrade_proto.hpp | 6 ------ src/caffe/proto/caffe_pretty_print.proto | 18 ------------------ src/caffe/util/upgrade_proto.cpp | 20 -------------------- tools/upgrade_net_proto_text.cpp | 7 +------ 4 files changed, 1 insertion(+), 50 deletions(-) delete mode 100644 src/caffe/proto/caffe_pretty_print.proto diff --git a/include/caffe/util/upgrade_proto.hpp b/include/caffe/util/upgrade_proto.hpp index 0df3a8987f9..c1f21a0d4d8 100644 --- a/include/caffe/util/upgrade_proto.hpp +++ b/include/caffe/util/upgrade_proto.hpp @@ -4,7 +4,6 @@ #include #include "caffe/proto/caffe.pb.h" -#include "caffe/proto/caffe_pretty_print.pb.h" namespace caffe { @@ -51,11 +50,6 @@ bool UpgradeV1LayerParameter(const V1LayerParameter& v1_layer_param, const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type); -// Convert a NetParameter to NetParameterPrettyPrint used for dumping to -// proto text files. -void NetParameterToPrettyPrint(const NetParameter& param, - NetParameterPrettyPrint* pretty_param); - // Check for deprecations and upgrade the NetParameter as needed. bool UpgradeNetAsNeeded(const string& param_file, NetParameter* param); diff --git a/src/caffe/proto/caffe_pretty_print.proto b/src/caffe/proto/caffe_pretty_print.proto deleted file mode 100644 index 056541f75f1..00000000000 --- a/src/caffe/proto/caffe_pretty_print.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto2"; - -package caffe; - -import "caffe.proto"; - -// A near-duplicate of NetParameter with fields re-numbered to beautify -// automatic prototext dumps. The main practical purpose is to print inputs -// before layers, because having inputs at the end looks weird. -// NetParameterPrettyPrint should never be used in code except for conversion -// FROM NetParameter and subsequent dumping to proto text file. -message NetParameterPrettyPrint { - optional string name = 1; - optional bool force_backward = 2 [default = false]; - repeated string input = 3; - repeated int32 input_dim = 4; - repeated LayerParameter layer = 5; -} diff --git a/src/caffe/util/upgrade_proto.cpp b/src/caffe/util/upgrade_proto.cpp index 6b401b537e0..258d7d3ee7d 100644 --- a/src/caffe/util/upgrade_proto.cpp +++ b/src/caffe/util/upgrade_proto.cpp @@ -583,26 +583,6 @@ void UpgradeNetDataTransformation(NetParameter* net_param) { } } -void NetParameterToPrettyPrint(const NetParameter& param, - NetParameterPrettyPrint* pretty_param) { - pretty_param->Clear(); - if (param.has_name()) { - pretty_param->set_name(param.name()); - } - if (param.has_force_backward()) { - pretty_param->set_force_backward(param.force_backward()); - } - for (int i = 0; i < param.input_size(); ++i) { - pretty_param->add_input(param.input(i)); - } - for (int i = 0; i < param.input_dim_size(); ++i) { - pretty_param->add_input_dim(param.input_dim(i)); - } - for (int i = 0; i < param.layer_size(); ++i) { - pretty_param->add_layer()->CopyFrom(param.layer(i)); - } -} - bool UpgradeNetAsNeeded(const string& param_file, NetParameter* param) { bool success = true; if (NetNeedsV0ToV1Upgrade(*param)) { diff --git a/tools/upgrade_net_proto_text.cpp b/tools/upgrade_net_proto_text.cpp index 0fe420a6d36..9200431bc27 100644 --- a/tools/upgrade_net_proto_text.cpp +++ b/tools/upgrade_net_proto_text.cpp @@ -47,13 +47,8 @@ int main(int argc, char** argv) { UpgradeNetDataTransformation(&net_param); } - // Convert to a NetParameterPrettyPrint to print fields in desired - // order. - NetParameterPrettyPrint net_param_pretty; - NetParameterToPrettyPrint(net_param, &net_param_pretty); - // Save new format prototxt. - WriteProtoToTextFile(net_param_pretty, argv[2]); + WriteProtoToTextFile(net_param, argv[2]); LOG(ERROR) << "Wrote upgraded NetParameter text proto to " << argv[2]; return !success; From 11a4c1655842a625a8fbb93f8c8ccd3629321a3f Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 15 Jan 2015 01:43:23 -0800 Subject: [PATCH 281/798] start layer parameter field IDs at 100 (always want them printed at the end, and want to allow more fields to be added in the future, so reserve fields 10-99 for that purpose) --- src/caffe/proto/caffe.proto | 69 +++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 453bf7ff285..81fd2517dbf 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -241,7 +241,7 @@ message ParamSpec { // NOTE // Update the next available ID when you add a new LayerParameter field. // -// LayerParameter next available ID: 43 (last added: loss_param) +// LayerParameter next available layer-specific ID: 129 (last added: window_data_param) message LayerParameter { optional string name = 1; // the layer name optional string type = 2; // the layer type @@ -266,48 +266,49 @@ message LayerParameter { // specified, the layer is always included. If the current NetState meets // ANY (i.e., one or more) of the specified rules, the layer is // included/excluded. - repeated NetStateRule include = 11; - repeated NetStateRule exclude = 12; + repeated NetStateRule include = 8; + repeated NetStateRule exclude = 9; // Parameters for data pre-processing. - optional TransformationParameter transform_param = 13; - - optional AccuracyParameter accuracy_param = 14; - optional ArgMaxParameter argmax_param = 15; - optional ConcatParameter concat_param = 16; - optional ContrastiveLossParameter contrastive_loss_param = 17; - optional ConvolutionParameter convolution_param = 18; - optional DataParameter data_param = 19; - optional DropoutParameter dropout_param = 20; - optional DummyDataParameter dummy_data_param = 21; - optional EltwiseParameter eltwise_param = 22; - optional ExpParameter exp_param = 23; - optional HDF5DataParameter hdf5_data_param = 24; - optional HDF5OutputParameter hdf5_output_param = 25; - optional HingeLossParameter hinge_loss_param = 26; - optional ImageDataParameter image_data_param = 27; - optional InfogainLossParameter infogain_loss_param = 28; - optional InnerProductParameter inner_product_param = 29; - optional LRNParameter lrn_param = 30; - optional MemoryDataParameter memory_data_param = 31; - optional MVNParameter mvn_param = 32; - optional PoolingParameter pooling_param = 33; - optional PowerParameter power_param = 34; - optional ReLUParameter relu_param = 35; - optional SigmoidParameter sigmoid_param = 36; - optional SoftmaxParameter softmax_param = 37; - optional SliceParameter slice_param = 38; - optional TanHParameter tanh_param = 39; - optional ThresholdParameter threshold_param = 40; - optional WindowDataParameter window_data_param = 41; + optional TransformationParameter transform_param = 100; // Parameters shared by loss layers. - optional LossParameter loss_param = 42; + optional LossParameter loss_param = 101; + // Layer type-specific parameters. + // // Note: certain layers may have more than one computational engine // for their implementation. These layers include an Engine type and // engine parameter for selecting the implementation. // The default for the engine is set by the ENGINE switch at compile-time. + optional AccuracyParameter accuracy_param = 102; + optional ArgMaxParameter argmax_param = 103; + optional ConcatParameter concat_param = 104; + optional ContrastiveLossParameter contrastive_loss_param = 105; + optional ConvolutionParameter convolution_param = 106; + optional DataParameter data_param = 107; + optional DropoutParameter dropout_param = 108; + optional DummyDataParameter dummy_data_param = 109; + optional EltwiseParameter eltwise_param = 110; + optional ExpParameter exp_param = 111; + optional HDF5DataParameter hdf5_data_param = 112; + optional HDF5OutputParameter hdf5_output_param = 113; + optional HingeLossParameter hinge_loss_param = 114; + optional ImageDataParameter image_data_param = 115; + optional InfogainLossParameter infogain_loss_param = 116; + optional InnerProductParameter inner_product_param = 117; + optional LRNParameter lrn_param = 118; + optional MemoryDataParameter memory_data_param = 119; + optional MVNParameter mvn_param = 120; + optional PoolingParameter pooling_param = 121; + optional PowerParameter power_param = 122; + optional ReLUParameter relu_param = 123; + optional SigmoidParameter sigmoid_param = 124; + optional SoftmaxParameter softmax_param = 125; + optional SliceParameter slice_param = 126; + optional TanHParameter tanh_param = 127; + optional ThresholdParameter threshold_param = 128; + optional WindowDataParameter window_data_param = 129; } // Message that stores parameters used to apply transformation From e6c80dac40d4bb13390b56bc18294e6e91b00436 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 5 Feb 2015 15:17:24 -0800 Subject: [PATCH 282/798] Upgrade existing nets using upgrade_net_proto_text tool Restore comments afterwards --- examples/cifar10/cifar10_full.prototxt | 84 +- .../cifar10/cifar10_full_train_test.prototxt | 120 +- examples/cifar10/cifar10_quick.prototxt | 88 +- .../cifar10/cifar10_quick_train_test.prototxt | 124 +- .../feature_extraction/imagenet_val.prototxt | 114 +- .../pascal_finetune_trainval_test.prototxt | 230 ++- .../hdf5_classification/train_val.prototxt | 44 +- .../hdf5_classification/train_val2.prototxt | 64 +- .../imagenet/bvlc_caffenet_full_conv.prototxt | 92 +- examples/mnist/lenet.prototxt | 64 +- examples/mnist/lenet_train_test.prototxt | 105 +- examples/mnist/mnist_autoencoder.prototxt | 260 +-- examples/siamese/mnist_siamese.prototxt | 74 +- .../siamese/mnist_siamese_train_test.prototxt | 260 ++- models/bvlc_alexnet/deploy.prototxt | 248 ++- models/bvlc_alexnet/train_val.prototxt | 232 ++- models/bvlc_googlenet/deploy.prototxt | 1548 ++++++++------ models/bvlc_googlenet/train_val.prototxt | 1802 ++++++++++------- .../bvlc_reference_caffenet/deploy.prototxt | 92 +- .../train_val.prototxt | 232 ++- .../deploy.prototxt | 88 +- models/finetune_flickr_style/deploy.prototxt | 192 +- .../finetune_flickr_style/train_val.prototxt | 236 ++- 23 files changed, 3661 insertions(+), 2732 deletions(-) diff --git a/examples/cifar10/cifar10_full.prototxt b/examples/cifar10/cifar10_full.prototxt index 8bbd30004fd..c16f7dca49f 100644 --- a/examples/cifar10/cifar10_full.prototxt +++ b/examples/cifar10/cifar10_full.prototxt @@ -6,13 +6,17 @@ input_dim: 1 input_dim: 3 input_dim: 32 input_dim: 32 -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 32 pad: 2 @@ -20,9 +24,9 @@ layers { stride: 1 } } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -31,31 +35,35 @@ layers { stride: 2 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "pool1" top: "pool1" } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { - norm_region: WITHIN_CHANNEL local_size: 3 alpha: 5e-05 beta: 0.75 + norm_region: WITHIN_CHANNEL } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 32 pad: 2 @@ -63,15 +71,15 @@ layers { stride: 1 } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -80,21 +88,21 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { - norm_region: WITHIN_CHANNEL local_size: 3 alpha: 5e-05 beta: 0.75 + norm_region: WITHIN_CHANNEL } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" convolution_param { @@ -104,15 +112,15 @@ layers { stride: 1 } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "pool3" - type: POOLING + type: "Pooling" bottom: "conv3" top: "pool3" pooling_param { @@ -121,22 +129,26 @@ layers { stride: 2 } } -layers { +layer { name: "ip1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool3" top: "ip1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 250 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 250 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 10 } } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "ip1" top: "prob" } diff --git a/examples/cifar10/cifar10_full_train_test.prototxt b/examples/cifar10/cifar10_full_train_test.prototxt index 38cc04f4a68..d45fc61e120 100644 --- a/examples/cifar10/cifar10_full_train_test.prototxt +++ b/examples/cifar10/cifar10_full_train_test.prototxt @@ -1,41 +1,49 @@ name: "CIFAR10_full" -layers { +layer { name: "cifar" - type: DATA + type: "Data" top: "data" top: "label" + include { + phase: TRAIN + } + transform_param { + mean_file: "examples/cifar10/mean.binaryproto" + } data_param { source: "examples/cifar10/cifar10_train_lmdb" batch_size: 100 backend: LMDB } - transform_param { - mean_file: "examples/cifar10/mean.binaryproto" - } - include: { phase: TRAIN } } -layers { +layer { name: "cifar" - type: DATA + type: "Data" top: "data" top: "label" + include { + phase: TEST + } + transform_param { + mean_file: "examples/cifar10/mean.binaryproto" + } data_param { source: "examples/cifar10/cifar10_test_lmdb" batch_size: 100 backend: LMDB } - transform_param { - mean_file: "examples/cifar10/mean.binaryproto" - } - include: { phase: TEST } } -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 32 pad: 2 @@ -50,9 +58,9 @@ layers { } } } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -61,31 +69,35 @@ layers { stride: 2 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "pool1" top: "pool1" } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { - norm_region: WITHIN_CHANNEL local_size: 3 alpha: 5e-05 beta: 0.75 + norm_region: WITHIN_CHANNEL } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 32 pad: 2 @@ -100,15 +112,15 @@ layers { } } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -117,21 +129,21 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { - norm_region: WITHIN_CHANNEL local_size: 3 alpha: 5e-05 beta: 0.75 + norm_region: WITHIN_CHANNEL } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" convolution_param { @@ -148,15 +160,15 @@ layers { } } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "pool3" - type: POOLING + type: "Pooling" bottom: "conv3" top: "pool3" pooling_param { @@ -165,15 +177,19 @@ layers { stride: 2 } } -layers { +layer { name: "ip1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool3" top: "ip1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 250 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 250 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 10 weight_filler { @@ -185,17 +201,19 @@ layers { } } } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "ip1" bottom: "label" top: "accuracy" - include: { phase: TEST } + include { + phase: TEST + } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "ip1" bottom: "label" top: "loss" diff --git a/examples/cifar10/cifar10_quick.prototxt b/examples/cifar10/cifar10_quick.prototxt index 505158f7a34..1ad190e185f 100644 --- a/examples/cifar10/cifar10_quick.prototxt +++ b/examples/cifar10/cifar10_quick.prototxt @@ -4,13 +4,17 @@ input_dim: 1 input_dim: 3 input_dim: 32 input_dim: 32 -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 32 pad: 2 @@ -18,9 +22,9 @@ layers { stride: 1 } } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -29,19 +33,23 @@ layers { stride: 2 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "pool1" top: "pool1" } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "pool1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 32 pad: 2 @@ -49,15 +57,15 @@ layers { stride: 1 } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -66,13 +74,17 @@ layers { stride: 2 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "pool2" top: "conv3" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 64 pad: 2 @@ -80,15 +92,15 @@ layers { stride: 1 } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "pool3" - type: POOLING + type: "Pooling" bottom: "conv3" top: "pool3" pooling_param { @@ -97,31 +109,39 @@ layers { stride: 2 } } -layers { +layer { name: "ip1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool3" top: "ip1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 64 } } -layers { +layer { name: "ip2" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip1" top: "ip2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 10 } } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "ip2" top: "prob" } diff --git a/examples/cifar10/cifar10_quick_train_test.prototxt b/examples/cifar10/cifar10_quick_train_test.prototxt index 074bb0011e3..2317739353e 100644 --- a/examples/cifar10/cifar10_quick_train_test.prototxt +++ b/examples/cifar10/cifar10_quick_train_test.prototxt @@ -1,41 +1,49 @@ name: "CIFAR10_quick" -layers { +layer { name: "cifar" - type: DATA + type: "Data" top: "data" top: "label" + include { + phase: TRAIN + } + transform_param { + mean_file: "examples/cifar10/mean.binaryproto" + } data_param { source: "examples/cifar10/cifar10_train_lmdb" batch_size: 100 backend: LMDB } - transform_param { - mean_file: "examples/cifar10/mean.binaryproto" - } - include: { phase: TRAIN } } -layers { +layer { name: "cifar" - type: DATA + type: "Data" top: "data" top: "label" + include { + phase: TEST + } + transform_param { + mean_file: "examples/cifar10/mean.binaryproto" + } data_param { source: "examples/cifar10/cifar10_test_lmdb" batch_size: 100 backend: LMDB } - transform_param { - mean_file: "examples/cifar10/mean.binaryproto" - } - include: { phase: TEST } } -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 32 pad: 2 @@ -50,9 +58,9 @@ layers { } } } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -61,19 +69,23 @@ layers { stride: 2 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "pool1" top: "pool1" } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "pool1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 32 pad: 2 @@ -88,15 +100,15 @@ layers { } } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -105,13 +117,17 @@ layers { stride: 2 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "pool2" top: "conv3" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 64 pad: 2 @@ -126,15 +142,15 @@ layers { } } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "pool3" - type: POOLING + type: "Pooling" bottom: "conv3" top: "pool3" pooling_param { @@ -143,13 +159,17 @@ layers { stride: 2 } } -layers { +layer { name: "ip1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool3" top: "ip1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 64 weight_filler { @@ -161,13 +181,17 @@ layers { } } } -layers { +layer { name: "ip2" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip1" top: "ip2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 10 weight_filler { @@ -179,17 +203,19 @@ layers { } } } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "ip2" bottom: "label" top: "accuracy" - include: { phase: TEST } + include { + phase: TEST + } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "ip2" bottom: "label" top: "loss" diff --git a/examples/feature_extraction/imagenet_val.prototxt b/examples/feature_extraction/imagenet_val.prototxt index 83fe8c1a08d..b0a1cefa00e 100644 --- a/examples/feature_extraction/imagenet_val.prototxt +++ b/examples/feature_extraction/imagenet_val.prototxt @@ -1,24 +1,24 @@ name: "CaffeNet" -layers { +layer { name: "data" - type: IMAGE_DATA + type: "ImageData" top: "data" top: "label" + transform_param { + mirror: false + crop_size: 227 + mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" + } image_data_param { source: "examples/_temp/file_list.txt" batch_size: 50 new_height: 256 new_width: 256 } - transform_param { - crop_size: 227 - mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" - mirror: false - } } -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" convolution_param { @@ -27,15 +27,15 @@ layers { stride: 4 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -44,9 +44,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { @@ -55,9 +55,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" convolution_param { @@ -67,15 +67,15 @@ layers { group: 2 } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -84,9 +84,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { @@ -95,9 +95,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" convolution_param { @@ -106,15 +106,15 @@ layers { kernel_size: 3 } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" convolution_param { @@ -124,15 +124,15 @@ layers { group: 2 } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" convolution_param { @@ -142,15 +142,15 @@ layers { group: 2 } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -159,79 +159,79 @@ layers { stride: 2 } } -layers { +layer { name: "fc6" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool5" top: "fc6" inner_product_param { num_output: 4096 } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc6" top: "fc7" inner_product_param { num_output: 4096 } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7" top: "fc7" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc8" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc7" top: "fc8" inner_product_param { num_output: 1000 } } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "fc8" top: "prob" } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "prob" bottom: "label" top: "accuracy" } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "fc8" bottom: "label" top: "loss" diff --git a/examples/finetune_pascal_detection/pascal_finetune_trainval_test.prototxt b/examples/finetune_pascal_detection/pascal_finetune_trainval_test.prototxt index 5cd605bbf11..9dd2120acad 100644 --- a/examples/finetune_pascal_detection/pascal_finetune_trainval_test.prototxt +++ b/examples/finetune_pascal_detection/pascal_finetune_trainval_test.prototxt @@ -1,9 +1,17 @@ name: "CaffeNet" -layers { +layer { name: "data" - type: WINDOW_DATA + type: "WindowData" top: "data" top: "label" + include { + phase: TRAIN + } + transform_param { + mirror: true + crop_size: 227 + mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" + } window_data_param { source: "examples/finetune_pascal_detection/window_file_2007_trainval.txt" batch_size: 128 @@ -13,18 +21,20 @@ layers { context_pad: 16 crop_mode: "warp" } +} +layer { + name: "data" + type: "WindowData" + top: "data" + top: "label" + include { + phase: TEST + } transform_param { mirror: true crop_size: 227 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" } - include: { phase: TRAIN } -} -layers { - name: "data" - type: WINDOW_DATA - top: "data" - top: "label" window_data_param { source: "examples/finetune_pascal_detection/window_file_2007_test.txt" batch_size: 128 @@ -34,22 +44,20 @@ layers { context_pad: 16 crop_mode: "warp" } - transform_param { - mirror: true - crop_size: 227 - mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" - } - include: { phase: TEST } } -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 11 @@ -64,15 +72,15 @@ layers { } } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -81,9 +89,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { @@ -92,15 +100,19 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 2 @@ -116,15 +128,15 @@ layers { } } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -133,9 +145,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { @@ -144,15 +156,19 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -167,21 +183,25 @@ layers { } } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -197,21 +217,25 @@ layers { } } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 1 @@ -227,15 +251,15 @@ layers { } } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -244,15 +268,19 @@ layers { stride: 2 } } -layers { +layer { name: "fc6" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool5" top: "fc6" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -265,30 +293,34 @@ layers { } } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc6" top: "fc7" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -301,30 +333,34 @@ layers { } } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7" top: "fc7" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc8_pascal" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc7" top: "fc8_pascal" - blobs_lr: 10 - blobs_lr: 20 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 10 + decay_mult: 1 + } + param { + lr_mult: 20 + decay_mult: 0 + } inner_product_param { num_output: 21 weight_filler { @@ -337,17 +373,19 @@ layers { } } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "fc8_pascal" bottom: "label" } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "fc8_pascal" bottom: "label" top: "accuracy" - include { phase: TEST } + include { + phase: TEST + } } diff --git a/examples/hdf5_classification/train_val.prototxt b/examples/hdf5_classification/train_val.prototxt index b55b6644b17..b9ccc1a93ec 100644 --- a/examples/hdf5_classification/train_val.prototxt +++ b/examples/hdf5_classification/train_val.prototxt @@ -1,35 +1,43 @@ name: "LogisticRegressionNet" -layers { +layer { name: "data" - type: HDF5_DATA + type: "HDF5Data" top: "data" top: "label" + include { + phase: TRAIN + } hdf5_data_param { source: "examples/hdf5_classification/data/train.txt" batch_size: 10 } - include: { phase: TRAIN } } -layers { +layer { name: "data" - type: HDF5_DATA + type: "HDF5Data" top: "data" top: "label" + include { + phase: TEST + } hdf5_data_param { source: "examples/hdf5_classification/data/test.txt" batch_size: 10 } - include: { phase: TEST } } -layers { +layer { name: "fc1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "data" top: "fc1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 2 weight_filler { @@ -42,18 +50,20 @@ layers { } } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "fc1" bottom: "label" top: "loss" } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "fc1" bottom: "label" top: "accuracy" - include: { phase: TEST } + include { + phase: TEST + } } diff --git a/examples/hdf5_classification/train_val2.prototxt b/examples/hdf5_classification/train_val2.prototxt index b6a75650ad3..f9ef731fff9 100644 --- a/examples/hdf5_classification/train_val2.prototxt +++ b/examples/hdf5_classification/train_val2.prototxt @@ -1,35 +1,43 @@ name: "LogisticRegressionNet" -layers { +layer { name: "data" - type: HDF5_DATA + type: "HDF5Data" top: "data" top: "label" + include { + phase: TRAIN + } hdf5_data_param { source: "examples/hdf5_classification/data/train.txt" batch_size: 10 } - include: { phase: TRAIN } } -layers { +layer { name: "data" - type: HDF5_DATA + type: "HDF5Data" top: "data" top: "label" + include { + phase: TEST + } hdf5_data_param { source: "examples/hdf5_classification/data/test.txt" batch_size: 10 } - include: { phase: TEST } } -layers { +layer { name: "fc1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "data" top: "fc1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 40 weight_filler { @@ -42,21 +50,25 @@ layers { } } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "fc1" top: "fc1" } -layers { +layer { name: "fc2" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc1" top: "fc2" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 2 weight_filler { @@ -69,18 +81,20 @@ layers { } } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "fc2" bottom: "label" top: "loss" } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "fc2" bottom: "label" top: "accuracy" - include: { phase: TEST } + include { + phase: TEST + } } diff --git a/examples/imagenet/bvlc_caffenet_full_conv.prototxt b/examples/imagenet/bvlc_caffenet_full_conv.prototxt index 395b0f0162f..7b22bfa1404 100644 --- a/examples/imagenet/bvlc_caffenet_full_conv.prototxt +++ b/examples/imagenet/bvlc_caffenet_full_conv.prototxt @@ -5,9 +5,9 @@ input_dim: 1 input_dim: 3 input_dim: 451 input_dim: 451 -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" convolution_param { @@ -16,15 +16,15 @@ layers { stride: 4 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -33,9 +33,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { @@ -44,9 +44,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" convolution_param { @@ -56,15 +56,15 @@ layers { group: 2 } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -73,9 +73,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { @@ -84,9 +84,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" convolution_param { @@ -95,15 +95,15 @@ layers { kernel_size: 3 } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" convolution_param { @@ -113,15 +113,15 @@ layers { group: 2 } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" convolution_param { @@ -131,15 +131,15 @@ layers { group: 2 } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -148,9 +148,9 @@ layers { stride: 2 } } -layers { +layer { name: "fc6-conv" - type: CONVOLUTION + type: "Convolution" bottom: "pool5" top: "fc6-conv" convolution_param { @@ -158,24 +158,24 @@ layers { kernel_size: 6 } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6-conv" top: "fc6-conv" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6-conv" top: "fc6-conv" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7-conv" - type: CONVOLUTION + type: "Convolution" bottom: "fc6-conv" top: "fc7-conv" convolution_param { @@ -183,24 +183,24 @@ layers { kernel_size: 1 } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7-conv" top: "fc7-conv" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7-conv" top: "fc7-conv" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc8-conv" - type: CONVOLUTION + type: "Convolution" bottom: "fc7-conv" top: "fc8-conv" convolution_param { @@ -208,9 +208,9 @@ layers { kernel_size: 1 } } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "fc8-conv" top: "prob" } diff --git a/examples/mnist/lenet.prototxt b/examples/mnist/lenet.prototxt index 491fad1b1c0..cb42610fe1e 100644 --- a/examples/mnist/lenet.prototxt +++ b/examples/mnist/lenet.prototxt @@ -4,13 +4,17 @@ input_dim: 64 input_dim: 1 input_dim: 28 input_dim: 28 -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 20 kernel_size: 5 @@ -23,9 +27,9 @@ layers { } } } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -34,13 +38,17 @@ layers { stride: 2 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "pool1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 50 kernel_size: 5 @@ -53,9 +61,9 @@ layers { } } } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -64,13 +72,17 @@ layers { stride: 2 } } -layers { +layer { name: "ip1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool2" top: "ip1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 500 weight_filler { @@ -81,19 +93,23 @@ layers { } } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "ip1" top: "ip1" } -layers { +layer { name: "ip2" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip1" top: "ip2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 10 weight_filler { @@ -104,9 +120,9 @@ layers { } } } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "ip2" top: "prob" } diff --git a/examples/mnist/lenet_train_test.prototxt b/examples/mnist/lenet_train_test.prototxt index 2bd960b56aa..b18fc26cfd8 100644 --- a/examples/mnist/lenet_train_test.prototxt +++ b/examples/mnist/lenet_train_test.prototxt @@ -1,42 +1,49 @@ name: "LeNet" -layers { +layer { name: "mnist" - type: DATA + type: "Data" top: "data" top: "label" - data_param { - source: "examples/mnist/mnist_train_lmdb" - backend: LMDB - batch_size: 64 + include { + phase: TRAIN } transform_param { scale: 0.00390625 } - include: { phase: TRAIN } + data_param { + source: "examples/mnist/mnist_train_lmdb" + batch_size: 64 + backend: LMDB + } } -layers { +layer { name: "mnist" - type: DATA + type: "Data" top: "data" top: "label" - data_param { - source: "examples/mnist/mnist_test_lmdb" - backend: LMDB - batch_size: 100 + include { + phase: TEST } transform_param { scale: 0.00390625 } - include: { phase: TEST } + data_param { + source: "examples/mnist/mnist_test_lmdb" + batch_size: 100 + backend: LMDB + } } - -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 20 kernel_size: 5 @@ -49,9 +56,9 @@ layers { } } } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -60,13 +67,17 @@ layers { stride: 2 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "pool1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 50 kernel_size: 5 @@ -79,9 +90,9 @@ layers { } } } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -90,13 +101,17 @@ layers { stride: 2 } } -layers { +layer { name: "ip1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool2" top: "ip1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 500 weight_filler { @@ -107,19 +122,23 @@ layers { } } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "ip1" top: "ip1" } -layers { +layer { name: "ip2" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip1" top: "ip2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 10 weight_filler { @@ -130,17 +149,19 @@ layers { } } } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "ip2" bottom: "label" top: "accuracy" - include: { phase: TEST } + include { + phase: TEST + } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "ip2" bottom: "label" top: "loss" diff --git a/examples/mnist/mnist_autoencoder.prototxt b/examples/mnist/mnist_autoencoder.prototxt index 0b33781a16f..563c7c91e52 100644 --- a/examples/mnist/mnist_autoencoder.prototxt +++ b/examples/mnist/mnist_autoencoder.prototxt @@ -1,67 +1,73 @@ name: "MNISTAutoencoder" -layers { - top: "data" +layer { name: "data" - type: DATA - data_param { - source: "examples/mnist/mnist_train_lmdb" - backend: LMDB - batch_size: 100 + type: "Data" + top: "data" + include { + phase: TRAIN } transform_param { scale: 0.0039215684 } - include: { phase: TRAIN } -} -layers { - top: "data" - name: "data" - type: DATA data_param { source: "examples/mnist/mnist_train_lmdb" - backend: LMDB batch_size: 100 + backend: LMDB + } +} +layer { + name: "data" + type: "Data" + top: "data" + include { + phase: TEST + stage: "test-on-train" } transform_param { scale: 0.0039215684 } - include: { - phase: TEST - stage: 'test-on-train' + data_param { + source: "examples/mnist/mnist_train_lmdb" + batch_size: 100 + backend: LMDB } } -layers { - top: "data" +layer { name: "data" - type: DATA - data_param { - source: "examples/mnist/mnist_test_lmdb" - backend: LMDB - batch_size: 100 + type: "Data" + top: "data" + include { + phase: TEST + stage: "test-on-test" } transform_param { scale: 0.0039215684 } - include: { - phase: TEST - stage: 'test-on-test' + data_param { + source: "examples/mnist/mnist_test_lmdb" + batch_size: 100 + backend: LMDB } } -layers { +layer { + name: "flatdata" + type: "Flatten" bottom: "data" top: "flatdata" - name: "flatdata" - type: FLATTEN } -layers { +layer { + name: "encode1" + type: "InnerProduct" bottom: "data" top: "encode1" - name: "encode1" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 1 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 1 + decay_mult: 0 + } inner_product_param { num_output: 1000 weight_filler { @@ -75,21 +81,25 @@ layers { } } } -layers { +layer { + name: "encode1neuron" + type: "Sigmoid" bottom: "encode1" top: "encode1neuron" - name: "encode1neuron" - type: SIGMOID } -layers { +layer { + name: "encode2" + type: "InnerProduct" bottom: "encode1neuron" top: "encode2" - name: "encode2" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 1 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 1 + decay_mult: 0 + } inner_product_param { num_output: 500 weight_filler { @@ -103,21 +113,25 @@ layers { } } } -layers { +layer { + name: "encode2neuron" + type: "Sigmoid" bottom: "encode2" top: "encode2neuron" - name: "encode2neuron" - type: SIGMOID } -layers { +layer { + name: "encode3" + type: "InnerProduct" bottom: "encode2neuron" top: "encode3" - name: "encode3" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 1 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 1 + decay_mult: 0 + } inner_product_param { num_output: 250 weight_filler { @@ -131,21 +145,25 @@ layers { } } } -layers { +layer { + name: "encode3neuron" + type: "Sigmoid" bottom: "encode3" top: "encode3neuron" - name: "encode3neuron" - type: SIGMOID } -layers { +layer { + name: "encode4" + type: "InnerProduct" bottom: "encode3neuron" top: "encode4" - name: "encode4" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 1 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 1 + decay_mult: 0 + } inner_product_param { num_output: 30 weight_filler { @@ -159,15 +177,19 @@ layers { } } } -layers { +layer { + name: "decode4" + type: "InnerProduct" bottom: "encode4" top: "decode4" - name: "decode4" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 1 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 1 + decay_mult: 0 + } inner_product_param { num_output: 250 weight_filler { @@ -181,21 +203,25 @@ layers { } } } -layers { +layer { + name: "decode4neuron" + type: "Sigmoid" bottom: "decode4" top: "decode4neuron" - name: "decode4neuron" - type: SIGMOID } -layers { +layer { + name: "decode3" + type: "InnerProduct" bottom: "decode4neuron" top: "decode3" - name: "decode3" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 1 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 1 + decay_mult: 0 + } inner_product_param { num_output: 500 weight_filler { @@ -209,21 +235,25 @@ layers { } } } -layers { +layer { + name: "decode3neuron" + type: "Sigmoid" bottom: "decode3" top: "decode3neuron" - name: "decode3neuron" - type: SIGMOID } -layers { +layer { + name: "decode2" + type: "InnerProduct" bottom: "decode3neuron" top: "decode2" - name: "decode2" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 1 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 1 + decay_mult: 0 + } inner_product_param { num_output: 1000 weight_filler { @@ -237,21 +267,25 @@ layers { } } } -layers { +layer { + name: "decode2neuron" + type: "Sigmoid" bottom: "decode2" top: "decode2neuron" - name: "decode2neuron" - type: SIGMOID } -layers { +layer { + name: "decode1" + type: "InnerProduct" bottom: "decode2neuron" top: "decode1" - name: "decode1" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 1 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 1 + decay_mult: 0 + } inner_product_param { num_output: 784 weight_filler { @@ -265,25 +299,25 @@ layers { } } } -layers { +layer { + name: "loss" + type: "SigmoidCrossEntropyLoss" bottom: "decode1" bottom: "flatdata" top: "cross_entropy_loss" - name: "loss" - type: SIGMOID_CROSS_ENTROPY_LOSS loss_weight: 1 } -layers { +layer { + name: "decode1neuron" + type: "Sigmoid" bottom: "decode1" top: "decode1neuron" - name: "decode1neuron" - type: SIGMOID } -layers { +layer { + name: "loss" + type: "EuclideanLoss" bottom: "decode1neuron" bottom: "flatdata" top: "l2_error" - name: "loss" - type: EUCLIDEAN_LOSS loss_weight: 0 } diff --git a/examples/siamese/mnist_siamese.prototxt b/examples/siamese/mnist_siamese.prototxt index 8dd42e9c1b5..0e903f85909 100644 --- a/examples/siamese/mnist_siamese.prototxt +++ b/examples/siamese/mnist_siamese.prototxt @@ -4,23 +4,26 @@ input_dim: 10000 input_dim: 1 input_dim: 28 input_dim: 28 - -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 20 kernel_size: 5 stride: 1 } } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -29,22 +32,26 @@ layers { stride: 2 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "pool1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } convolution_param { num_output: 50 kernel_size: 5 stride: 1 } } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -53,42 +60,53 @@ layers { stride: 2 } } -layers { +layer { name: "ip1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool2" top: "ip1" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 500 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "ip1" top: "ip1" } -layers { +layer { name: "ip2" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip1" top: "ip2" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 10 } } - -layers { +layer { name: "feat" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip2" top: "feat" - blobs_lr: 1 - blobs_lr: 2 + param { + lr_mult: 1 + } + param { + lr_mult: 2 + } inner_product_param { num_output: 2 } diff --git a/examples/siamese/mnist_siamese_train_test.prototxt b/examples/siamese/mnist_siamese_train_test.prototxt index 92361c31dc7..8ff864f556f 100644 --- a/examples/siamese/mnist_siamese_train_test.prototxt +++ b/examples/siamese/mnist_siamese_train_test.prototxt @@ -1,50 +1,60 @@ name: "mnist_siamese_train_test" -layers { +layer { name: "pair_data" - type: DATA + type: "Data" top: "pair_data" top: "sim" + include { + phase: TRAIN + } + transform_param { + scale: 0.00390625 + } data_param { source: "examples/siamese/mnist_siamese_train_leveldb" - scale: 0.00390625 batch_size: 64 } - include: { phase: TRAIN } } -layers { +layer { name: "pair_data" - type: DATA + type: "Data" top: "pair_data" top: "sim" + include { + phase: TEST + } + transform_param { + scale: 0.00390625 + } data_param { source: "examples/siamese/mnist_siamese_test_leveldb" - scale: 0.00390625 batch_size: 100 } - include: { phase: TEST } } -layers { - name: "slice_pair" - type: SLICE - bottom: "pair_data" - top: "data" - top: "data_p" - slice_param { - slice_dim: 1 - slice_point: 1 - } +layer { + name: "slice_pair" + type: "Slice" + bottom: "pair_data" + top: "data" + top: "data_p" + slice_param { + slice_dim: 1 + slice_point: 1 + } } - - - - -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "conv1_w" + lr_mult: 1 + } + param { + name: "conv1_b" + lr_mult: 2 + } convolution_param { num_output: 20 kernel_size: 5 @@ -56,12 +66,10 @@ layers { type: "constant" } } - param: "conv1_w" - param: "conv1_b" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -70,13 +78,19 @@ layers { stride: 2 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "pool1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "conv2_w" + lr_mult: 1 + } + param { + name: "conv2_b" + lr_mult: 2 + } convolution_param { num_output: 50 kernel_size: 5 @@ -88,12 +102,10 @@ layers { type: "constant" } } - param: "conv2_w" - param: "conv2_b" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -102,13 +114,19 @@ layers { stride: 2 } } -layers { +layer { name: "ip1" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool2" top: "ip1" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "ip1_w" + lr_mult: 1 + } + param { + name: "ip1_b" + lr_mult: 2 + } inner_product_param { num_output: 500 weight_filler { @@ -118,22 +136,26 @@ layers { type: "constant" } } - param: "ip1_w" - param: "ip1_b" } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "ip1" top: "ip1" } -layers { +layer { name: "ip2" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip1" top: "ip2" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "ip2_w" + lr_mult: 1 + } + param { + name: "ip2_b" + lr_mult: 2 + } inner_product_param { num_output: 10 weight_filler { @@ -143,17 +165,20 @@ layers { type: "constant" } } - param: "ip2_w" - param: "ip2_b" } - -layers { +layer { name: "feat" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip2" top: "feat" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "feat_w" + lr_mult: 1 + } + param { + name: "feat_b" + lr_mult: 2 + } inner_product_param { num_output: 2 weight_filler { @@ -163,19 +188,20 @@ layers { type: "constant" } } - param: "feat_w" - param: "feat_b" } - - - -layers { +layer { name: "conv1_p" - type: CONVOLUTION + type: "Convolution" bottom: "data_p" top: "conv1_p" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "conv1_w" + lr_mult: 1 + } + param { + name: "conv1_b" + lr_mult: 2 + } convolution_param { num_output: 20 kernel_size: 5 @@ -187,12 +213,10 @@ layers { type: "constant" } } - param: "conv1_w" - param: "conv1_b" } -layers { +layer { name: "pool1_p" - type: POOLING + type: "Pooling" bottom: "conv1_p" top: "pool1_p" pooling_param { @@ -201,13 +225,19 @@ layers { stride: 2 } } -layers { +layer { name: "conv2_p" - type: CONVOLUTION + type: "Convolution" bottom: "pool1_p" top: "conv2_p" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "conv2_w" + lr_mult: 1 + } + param { + name: "conv2_b" + lr_mult: 2 + } convolution_param { num_output: 50 kernel_size: 5 @@ -219,12 +249,10 @@ layers { type: "constant" } } - param: "conv2_w" - param: "conv2_b" } -layers { +layer { name: "pool2_p" - type: POOLING + type: "Pooling" bottom: "conv2_p" top: "pool2_p" pooling_param { @@ -233,13 +261,19 @@ layers { stride: 2 } } -layers { +layer { name: "ip1_p" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool2_p" top: "ip1_p" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "ip1_w" + lr_mult: 1 + } + param { + name: "ip1_b" + lr_mult: 2 + } inner_product_param { num_output: 500 weight_filler { @@ -249,22 +283,26 @@ layers { type: "constant" } } - param: "ip1_w" - param: "ip1_b" } -layers { +layer { name: "relu1_p" - type: RELU + type: "ReLU" bottom: "ip1_p" top: "ip1_p" } -layers { +layer { name: "ip2_p" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip1_p" top: "ip2_p" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "ip2_w" + lr_mult: 1 + } + param { + name: "ip2_b" + lr_mult: 2 + } inner_product_param { num_output: 10 weight_filler { @@ -274,17 +312,20 @@ layers { type: "constant" } } - param: "ip2_w" - param: "ip2_b" } - -layers { +layer { name: "feat_p" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "ip2_p" top: "feat_p" - blobs_lr: 1 - blobs_lr: 2 + param { + name: "feat_w" + lr_mult: 1 + } + param { + name: "feat_b" + lr_mult: 2 + } inner_product_param { num_output: 2 weight_filler { @@ -294,20 +335,15 @@ layers { type: "constant" } } - param: "feat_w" - param: "feat_b" } - - - -layers { - name: "loss" - type: CONTRASTIVE_LOSS - contrastive_loss_param { - margin: 1.0 - } - bottom: "feat" - bottom: "feat_p" - bottom: "sim" - top: "loss" +layer { + name: "loss" + type: "ContrastiveLoss" + bottom: "feat" + bottom: "feat_p" + bottom: "sim" + top: "loss" + contrastive_loss_param { + margin: 1 + } } diff --git a/models/bvlc_alexnet/deploy.prototxt b/models/bvlc_alexnet/deploy.prototxt index d010753f3fc..ced055b85d0 100644 --- a/models/bvlc_alexnet/deploy.prototxt +++ b/models/bvlc_alexnet/deploy.prototxt @@ -4,241 +4,273 @@ input_dim: 10 input_dim: 3 input_dim: 227 input_dim: 227 -layers { +layer { name: "conv1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + type: "Convolution" + bottom: "data" + top: "conv1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 11 stride: 4 } - bottom: "data" - top: "conv1" } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" + bottom: "conv1" + top: "norm1" lrn_param { local_size: 5 alpha: 0.0001 beta: 0.75 } - bottom: "conv1" - top: "norm1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" + bottom: "norm1" + top: "pool1" pooling_param { pool: MAX kernel_size: 3 stride: 2 } - bottom: "norm1" - top: "pool1" } -layers { +layer { name: "conv2" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + type: "Convolution" + bottom: "pool1" + top: "conv2" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 2 kernel_size: 5 group: 2 } - bottom: "pool1" - top: "conv2" } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" + bottom: "conv2" + top: "norm2" lrn_param { local_size: 5 alpha: 0.0001 beta: 0.75 } - bottom: "conv2" - top: "norm2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" + bottom: "norm2" + top: "pool2" pooling_param { pool: MAX kernel_size: 3 stride: 2 } - bottom: "norm2" - top: "pool2" } -layers { +layer { name: "conv3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + type: "Convolution" + bottom: "pool2" + top: "conv3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 kernel_size: 3 } - bottom: "pool2" - top: "conv3" } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + type: "Convolution" + bottom: "conv3" + top: "conv4" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 kernel_size: 3 group: 2 } - bottom: "conv3" - top: "conv4" } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + type: "Convolution" + bottom: "conv4" + top: "conv5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 1 kernel_size: 3 group: 2 } - bottom: "conv4" - top: "conv5" } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" + bottom: "conv5" + top: "pool5" pooling_param { pool: MAX kernel_size: 3 stride: 2 } - bottom: "conv5" - top: "pool5" } -layers { +layer { name: "fc6" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + type: "InnerProduct" + bottom: "pool5" + top: "fc6" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 } - bottom: "pool5" - top: "fc6" } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" + bottom: "fc6" + top: "fc6" dropout_param { dropout_ratio: 0.5 } - bottom: "fc6" - top: "fc6" } -layers { +layer { name: "fc7" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + type: "InnerProduct" + bottom: "fc6" + top: "fc7" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 } - bottom: "fc6" - top: "fc7" } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" + bottom: "fc7" + top: "fc7" dropout_param { dropout_ratio: 0.5 } - bottom: "fc7" - top: "fc7" } -layers { +layer { name: "fc8" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + type: "InnerProduct" + bottom: "fc7" + top: "fc8" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1000 } - bottom: "fc7" - top: "fc8" } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "fc8" top: "prob" } diff --git a/models/bvlc_alexnet/train_val.prototxt b/models/bvlc_alexnet/train_val.prototxt index 717b6fa447c..588b4ea7cb5 100644 --- a/models/bvlc_alexnet/train_val.prototxt +++ b/models/bvlc_alexnet/train_val.prototxt @@ -1,47 +1,55 @@ name: "AlexNet" -layers { +layer { name: "data" - type: DATA + type: "Data" top: "data" top: "label" - data_param { - source: "examples/imagenet/ilsvrc12_train_lmdb" - backend: LMDB - batch_size: 256 + include { + phase: TRAIN } transform_param { + mirror: true crop_size: 227 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" - mirror: true } - include: { phase: TRAIN } + data_param { + source: "examples/imagenet/ilsvrc12_train_lmdb" + batch_size: 256 + backend: LMDB + } } -layers { +layer { name: "data" - type: DATA + type: "Data" top: "data" top: "label" - data_param { - source: "examples/imagenet/ilsvrc12_val_lmdb" - backend: LMDB - batch_size: 50 + include { + phase: TEST } transform_param { + mirror: false crop_size: 227 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" - mirror: false } - include: { phase: TEST } + data_param { + source: "examples/imagenet/ilsvrc12_val_lmdb" + batch_size: 50 + backend: LMDB + } } -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 11 @@ -56,15 +64,15 @@ layers { } } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "conv1" top: "norm1" lrn_param { @@ -73,9 +81,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "norm1" top: "pool1" pooling_param { @@ -84,15 +92,19 @@ layers { stride: 2 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "pool1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 2 @@ -108,15 +120,15 @@ layers { } } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "conv2" top: "norm2" lrn_param { @@ -125,9 +137,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "norm2" top: "pool2" pooling_param { @@ -136,15 +148,19 @@ layers { stride: 2 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "pool2" top: "conv3" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -159,21 +175,25 @@ layers { } } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -189,21 +209,25 @@ layers { } } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 1 @@ -219,15 +243,15 @@ layers { } } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -236,15 +260,19 @@ layers { stride: 2 } } -layers { +layer { name: "fc6" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool5" top: "fc6" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -257,30 +285,34 @@ layers { } } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc6" top: "fc7" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -293,30 +325,34 @@ layers { } } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7" top: "fc7" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc8" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc7" top: "fc8" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1000 weight_filler { @@ -329,17 +365,19 @@ layers { } } } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "fc8" bottom: "label" top: "accuracy" - include: { phase: TEST } + include { + phase: TEST + } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "fc8" bottom: "label" top: "loss" diff --git a/models/bvlc_googlenet/deploy.prototxt b/models/bvlc_googlenet/deploy.prototxt index e31a4c9cd00..4648bf26efc 100644 --- a/models/bvlc_googlenet/deploy.prototxt +++ b/models/bvlc_googlenet/deploy.prototxt @@ -4,15 +4,19 @@ input_dim: 10 input_dim: 3 input_dim: 224 input_dim: 224 -layers { +layer { + name: "conv1/7x7_s2" + type: "Convolution" bottom: "data" top: "conv1/7x7_s2" - name: "conv1/7x7_s2" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 pad: 3 @@ -28,43 +32,47 @@ layers { } } } -layers { +layer { + name: "conv1/relu_7x7" + type: "ReLU" bottom: "conv1/7x7_s2" top: "conv1/7x7_s2" - name: "conv1/relu_7x7" - type: RELU } -layers { +layer { + name: "pool1/3x3_s2" + type: "Pooling" bottom: "conv1/7x7_s2" top: "pool1/3x3_s2" - name: "pool1/3x3_s2" - type: POOLING pooling_param { pool: MAX kernel_size: 3 stride: 2 } } -layers { +layer { + name: "pool1/norm1" + type: "LRN" bottom: "pool1/3x3_s2" top: "pool1/norm1" - name: "pool1/norm1" - type: LRN lrn_param { local_size: 5 alpha: 0.0001 beta: 0.75 } } -layers { +layer { + name: "conv2/3x3_reduce" + type: "Convolution" bottom: "pool1/norm1" top: "conv2/3x3_reduce" - name: "conv2/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -78,21 +86,25 @@ layers { } } } -layers { +layer { + name: "conv2/relu_3x3_reduce" + type: "ReLU" bottom: "conv2/3x3_reduce" top: "conv2/3x3_reduce" - name: "conv2/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "conv2/3x3" + type: "Convolution" bottom: "conv2/3x3_reduce" top: "conv2/3x3" - name: "conv2/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 192 pad: 1 @@ -107,43 +119,47 @@ layers { } } } -layers { +layer { + name: "conv2/relu_3x3" + type: "ReLU" bottom: "conv2/3x3" top: "conv2/3x3" - name: "conv2/relu_3x3" - type: RELU } -layers { +layer { + name: "conv2/norm2" + type: "LRN" bottom: "conv2/3x3" top: "conv2/norm2" - name: "conv2/norm2" - type: LRN lrn_param { local_size: 5 alpha: 0.0001 beta: 0.75 } } -layers { +layer { + name: "pool2/3x3_s2" + type: "Pooling" bottom: "conv2/norm2" top: "pool2/3x3_s2" - name: "pool2/3x3_s2" - type: POOLING pooling_param { pool: MAX kernel_size: 3 stride: 2 } } -layers { +layer { + name: "inception_3a/1x1" + type: "Convolution" bottom: "pool2/3x3_s2" top: "inception_3a/1x1" - name: "inception_3a/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -157,21 +173,25 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_1x1" + type: "ReLU" bottom: "inception_3a/1x1" top: "inception_3a/1x1" - name: "inception_3a/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_3a/3x3_reduce" + type: "Convolution" bottom: "pool2/3x3_s2" top: "inception_3a/3x3_reduce" - name: "inception_3a/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 1 @@ -185,21 +205,25 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_3x3_reduce" + type: "ReLU" bottom: "inception_3a/3x3_reduce" top: "inception_3a/3x3_reduce" - name: "inception_3a/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_3a/3x3" + type: "Convolution" bottom: "inception_3a/3x3_reduce" top: "inception_3a/3x3" - name: "inception_3a/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 pad: 1 @@ -214,21 +238,25 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_3x3" + type: "ReLU" bottom: "inception_3a/3x3" top: "inception_3a/3x3" - name: "inception_3a/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_3a/5x5_reduce" + type: "Convolution" bottom: "pool2/3x3_s2" top: "inception_3a/5x5_reduce" - name: "inception_3a/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 16 kernel_size: 1 @@ -242,21 +270,25 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_5x5_reduce" + type: "ReLU" bottom: "inception_3a/5x5_reduce" top: "inception_3a/5x5_reduce" - name: "inception_3a/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_3a/5x5" + type: "Convolution" bottom: "inception_3a/5x5_reduce" top: "inception_3a/5x5" - name: "inception_3a/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 pad: 2 @@ -271,17 +303,17 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_5x5" + type: "ReLU" bottom: "inception_3a/5x5" top: "inception_3a/5x5" - name: "inception_3a/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_3a/pool" + type: "Pooling" bottom: "pool2/3x3_s2" top: "inception_3a/pool" - name: "inception_3a/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -289,15 +321,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_3a/pool_proj" + type: "Convolution" bottom: "inception_3a/pool" top: "inception_3a/pool_proj" - name: "inception_3a/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -311,30 +347,34 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_pool_proj" + type: "ReLU" bottom: "inception_3a/pool_proj" top: "inception_3a/pool_proj" - name: "inception_3a/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_3a/output" + type: "Concat" bottom: "inception_3a/1x1" bottom: "inception_3a/3x3" bottom: "inception_3a/5x5" bottom: "inception_3a/pool_proj" top: "inception_3a/output" - name: "inception_3a/output" - type: CONCAT } -layers { +layer { + name: "inception_3b/1x1" + type: "Convolution" bottom: "inception_3a/output" top: "inception_3b/1x1" - name: "inception_3b/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -348,21 +388,25 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_1x1" + type: "ReLU" bottom: "inception_3b/1x1" top: "inception_3b/1x1" - name: "inception_3b/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_3b/3x3_reduce" + type: "Convolution" bottom: "inception_3a/output" top: "inception_3b/3x3_reduce" - name: "inception_3b/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -376,21 +420,25 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_3x3_reduce" + type: "ReLU" bottom: "inception_3b/3x3_reduce" top: "inception_3b/3x3_reduce" - name: "inception_3b/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_3b/3x3" + type: "Convolution" bottom: "inception_3b/3x3_reduce" top: "inception_3b/3x3" - name: "inception_3b/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 192 pad: 1 @@ -405,21 +453,25 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_3x3" + type: "ReLU" bottom: "inception_3b/3x3" top: "inception_3b/3x3" - name: "inception_3b/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_3b/5x5_reduce" + type: "Convolution" bottom: "inception_3a/output" top: "inception_3b/5x5_reduce" - name: "inception_3b/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -433,21 +485,25 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_5x5_reduce" + type: "ReLU" bottom: "inception_3b/5x5_reduce" top: "inception_3b/5x5_reduce" - name: "inception_3b/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_3b/5x5" + type: "Convolution" bottom: "inception_3b/5x5_reduce" top: "inception_3b/5x5" - name: "inception_3b/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 pad: 2 @@ -462,17 +518,17 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_5x5" + type: "ReLU" bottom: "inception_3b/5x5" top: "inception_3b/5x5" - name: "inception_3b/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_3b/pool" + type: "Pooling" bottom: "inception_3a/output" top: "inception_3b/pool" - name: "inception_3b/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -480,15 +536,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_3b/pool_proj" + type: "Convolution" bottom: "inception_3b/pool" top: "inception_3b/pool_proj" - name: "inception_3b/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -502,41 +562,45 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_pool_proj" + type: "ReLU" bottom: "inception_3b/pool_proj" top: "inception_3b/pool_proj" - name: "inception_3b/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_3b/output" + type: "Concat" bottom: "inception_3b/1x1" bottom: "inception_3b/3x3" bottom: "inception_3b/5x5" bottom: "inception_3b/pool_proj" top: "inception_3b/output" - name: "inception_3b/output" - type: CONCAT } -layers { +layer { + name: "pool3/3x3_s2" + type: "Pooling" bottom: "inception_3b/output" top: "pool3/3x3_s2" - name: "pool3/3x3_s2" - type: POOLING pooling_param { pool: MAX kernel_size: 3 stride: 2 } } -layers { +layer { + name: "inception_4a/1x1" + type: "Convolution" bottom: "pool3/3x3_s2" top: "inception_4a/1x1" - name: "inception_4a/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 192 kernel_size: 1 @@ -550,21 +614,25 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_1x1" + type: "ReLU" bottom: "inception_4a/1x1" top: "inception_4a/1x1" - name: "inception_4a/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4a/3x3_reduce" + type: "Convolution" bottom: "pool3/3x3_s2" top: "inception_4a/3x3_reduce" - name: "inception_4a/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 1 @@ -578,21 +646,25 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4a/3x3_reduce" top: "inception_4a/3x3_reduce" - name: "inception_4a/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4a/3x3" + type: "Convolution" bottom: "inception_4a/3x3_reduce" top: "inception_4a/3x3" - name: "inception_4a/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 208 pad: 1 @@ -607,21 +679,25 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_3x3" + type: "ReLU" bottom: "inception_4a/3x3" top: "inception_4a/3x3" - name: "inception_4a/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4a/5x5_reduce" + type: "Convolution" bottom: "pool3/3x3_s2" top: "inception_4a/5x5_reduce" - name: "inception_4a/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 16 kernel_size: 1 @@ -635,21 +711,25 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4a/5x5_reduce" top: "inception_4a/5x5_reduce" - name: "inception_4a/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4a/5x5" + type: "Convolution" bottom: "inception_4a/5x5_reduce" top: "inception_4a/5x5" - name: "inception_4a/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 48 pad: 2 @@ -664,17 +744,17 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_5x5" + type: "ReLU" bottom: "inception_4a/5x5" top: "inception_4a/5x5" - name: "inception_4a/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4a/pool" + type: "Pooling" bottom: "pool3/3x3_s2" top: "inception_4a/pool" - name: "inception_4a/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -682,15 +762,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4a/pool_proj" + type: "Convolution" bottom: "inception_4a/pool" top: "inception_4a/pool_proj" - name: "inception_4a/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -704,30 +788,34 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_pool_proj" + type: "ReLU" bottom: "inception_4a/pool_proj" top: "inception_4a/pool_proj" - name: "inception_4a/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4a/output" + type: "Concat" bottom: "inception_4a/1x1" bottom: "inception_4a/3x3" bottom: "inception_4a/5x5" bottom: "inception_4a/pool_proj" top: "inception_4a/output" - name: "inception_4a/output" - type: CONCAT } -layers { +layer { + name: "inception_4b/1x1" + type: "Convolution" bottom: "inception_4a/output" top: "inception_4b/1x1" - name: "inception_4b/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 160 kernel_size: 1 @@ -741,21 +829,25 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_1x1" + type: "ReLU" bottom: "inception_4b/1x1" top: "inception_4b/1x1" - name: "inception_4b/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4b/3x3_reduce" + type: "Convolution" bottom: "inception_4a/output" top: "inception_4b/3x3_reduce" - name: "inception_4b/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 112 kernel_size: 1 @@ -769,21 +861,25 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4b/3x3_reduce" top: "inception_4b/3x3_reduce" - name: "inception_4b/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4b/3x3" + type: "Convolution" bottom: "inception_4b/3x3_reduce" top: "inception_4b/3x3" - name: "inception_4b/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 224 pad: 1 @@ -798,21 +894,25 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_3x3" + type: "ReLU" bottom: "inception_4b/3x3" top: "inception_4b/3x3" - name: "inception_4b/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4b/5x5_reduce" + type: "Convolution" bottom: "inception_4a/output" top: "inception_4b/5x5_reduce" - name: "inception_4b/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 24 kernel_size: 1 @@ -826,21 +926,25 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4b/5x5_reduce" top: "inception_4b/5x5_reduce" - name: "inception_4b/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4b/5x5" + type: "Convolution" bottom: "inception_4b/5x5_reduce" top: "inception_4b/5x5" - name: "inception_4b/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 pad: 2 @@ -855,17 +959,17 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_5x5" + type: "ReLU" bottom: "inception_4b/5x5" top: "inception_4b/5x5" - name: "inception_4b/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4b/pool" + type: "Pooling" bottom: "inception_4a/output" top: "inception_4b/pool" - name: "inception_4b/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -873,15 +977,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4b/pool_proj" + type: "Convolution" bottom: "inception_4b/pool" top: "inception_4b/pool_proj" - name: "inception_4b/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -895,30 +1003,34 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_pool_proj" + type: "ReLU" bottom: "inception_4b/pool_proj" top: "inception_4b/pool_proj" - name: "inception_4b/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4b/output" + type: "Concat" bottom: "inception_4b/1x1" bottom: "inception_4b/3x3" bottom: "inception_4b/5x5" bottom: "inception_4b/pool_proj" top: "inception_4b/output" - name: "inception_4b/output" - type: CONCAT } -layers { +layer { + name: "inception_4c/1x1" + type: "Convolution" bottom: "inception_4b/output" top: "inception_4c/1x1" - name: "inception_4c/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -932,21 +1044,25 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_1x1" + type: "ReLU" bottom: "inception_4c/1x1" top: "inception_4c/1x1" - name: "inception_4c/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4c/3x3_reduce" + type: "Convolution" bottom: "inception_4b/output" top: "inception_4c/3x3_reduce" - name: "inception_4c/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -960,21 +1076,25 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4c/3x3_reduce" top: "inception_4c/3x3_reduce" - name: "inception_4c/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4c/3x3" + type: "Convolution" bottom: "inception_4c/3x3_reduce" top: "inception_4c/3x3" - name: "inception_4c/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 1 @@ -989,21 +1109,25 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_3x3" + type: "ReLU" bottom: "inception_4c/3x3" top: "inception_4c/3x3" - name: "inception_4c/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4c/5x5_reduce" + type: "Convolution" bottom: "inception_4b/output" top: "inception_4c/5x5_reduce" - name: "inception_4c/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 24 kernel_size: 1 @@ -1017,21 +1141,25 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4c/5x5_reduce" top: "inception_4c/5x5_reduce" - name: "inception_4c/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4c/5x5" + type: "Convolution" bottom: "inception_4c/5x5_reduce" top: "inception_4c/5x5" - name: "inception_4c/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 pad: 2 @@ -1046,17 +1174,17 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_5x5" + type: "ReLU" bottom: "inception_4c/5x5" top: "inception_4c/5x5" - name: "inception_4c/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4c/pool" + type: "Pooling" bottom: "inception_4b/output" top: "inception_4c/pool" - name: "inception_4c/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1064,15 +1192,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4c/pool_proj" + type: "Convolution" bottom: "inception_4c/pool" top: "inception_4c/pool_proj" - name: "inception_4c/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -1086,30 +1218,34 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_pool_proj" + type: "ReLU" bottom: "inception_4c/pool_proj" top: "inception_4c/pool_proj" - name: "inception_4c/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4c/output" + type: "Concat" bottom: "inception_4c/1x1" bottom: "inception_4c/3x3" bottom: "inception_4c/5x5" bottom: "inception_4c/pool_proj" top: "inception_4c/output" - name: "inception_4c/output" - type: CONCAT } -layers { +layer { + name: "inception_4d/1x1" + type: "Convolution" bottom: "inception_4c/output" top: "inception_4d/1x1" - name: "inception_4d/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 112 kernel_size: 1 @@ -1123,21 +1259,25 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_1x1" + type: "ReLU" bottom: "inception_4d/1x1" top: "inception_4d/1x1" - name: "inception_4d/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4d/3x3_reduce" + type: "Convolution" bottom: "inception_4c/output" top: "inception_4d/3x3_reduce" - name: "inception_4d/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 144 kernel_size: 1 @@ -1151,21 +1291,25 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4d/3x3_reduce" top: "inception_4d/3x3_reduce" - name: "inception_4d/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4d/3x3" + type: "Convolution" bottom: "inception_4d/3x3_reduce" top: "inception_4d/3x3" - name: "inception_4d/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 288 pad: 1 @@ -1180,21 +1324,25 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_3x3" + type: "ReLU" bottom: "inception_4d/3x3" top: "inception_4d/3x3" - name: "inception_4d/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4d/5x5_reduce" + type: "Convolution" bottom: "inception_4c/output" top: "inception_4d/5x5_reduce" - name: "inception_4d/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -1208,21 +1356,25 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4d/5x5_reduce" top: "inception_4d/5x5_reduce" - name: "inception_4d/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4d/5x5" + type: "Convolution" bottom: "inception_4d/5x5_reduce" top: "inception_4d/5x5" - name: "inception_4d/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 pad: 2 @@ -1237,17 +1389,17 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_5x5" + type: "ReLU" bottom: "inception_4d/5x5" top: "inception_4d/5x5" - name: "inception_4d/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4d/pool" + type: "Pooling" bottom: "inception_4c/output" top: "inception_4d/pool" - name: "inception_4d/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1255,15 +1407,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4d/pool_proj" + type: "Convolution" bottom: "inception_4d/pool" top: "inception_4d/pool_proj" - name: "inception_4d/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -1277,30 +1433,34 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_pool_proj" + type: "ReLU" bottom: "inception_4d/pool_proj" top: "inception_4d/pool_proj" - name: "inception_4d/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4d/output" + type: "Concat" bottom: "inception_4d/1x1" bottom: "inception_4d/3x3" bottom: "inception_4d/5x5" bottom: "inception_4d/pool_proj" top: "inception_4d/output" - name: "inception_4d/output" - type: CONCAT } -layers { +layer { + name: "inception_4e/1x1" + type: "Convolution" bottom: "inception_4d/output" top: "inception_4e/1x1" - name: "inception_4e/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 kernel_size: 1 @@ -1314,21 +1474,25 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_1x1" + type: "ReLU" bottom: "inception_4e/1x1" top: "inception_4e/1x1" - name: "inception_4e/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4e/3x3_reduce" + type: "Convolution" bottom: "inception_4d/output" top: "inception_4e/3x3_reduce" - name: "inception_4e/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 160 kernel_size: 1 @@ -1342,21 +1506,25 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4e/3x3_reduce" top: "inception_4e/3x3_reduce" - name: "inception_4e/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4e/3x3" + type: "Convolution" bottom: "inception_4e/3x3_reduce" top: "inception_4e/3x3" - name: "inception_4e/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 320 pad: 1 @@ -1371,21 +1539,25 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_3x3" + type: "ReLU" bottom: "inception_4e/3x3" top: "inception_4e/3x3" - name: "inception_4e/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4e/5x5_reduce" + type: "Convolution" bottom: "inception_4d/output" top: "inception_4e/5x5_reduce" - name: "inception_4e/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -1399,21 +1571,25 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4e/5x5_reduce" top: "inception_4e/5x5_reduce" - name: "inception_4e/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4e/5x5" + type: "Convolution" bottom: "inception_4e/5x5_reduce" top: "inception_4e/5x5" - name: "inception_4e/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 pad: 2 @@ -1428,17 +1604,17 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_5x5" + type: "ReLU" bottom: "inception_4e/5x5" top: "inception_4e/5x5" - name: "inception_4e/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4e/pool" + type: "Pooling" bottom: "inception_4d/output" top: "inception_4e/pool" - name: "inception_4e/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1446,15 +1622,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4e/pool_proj" + type: "Convolution" bottom: "inception_4e/pool" top: "inception_4e/pool_proj" - name: "inception_4e/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -1468,41 +1648,45 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_pool_proj" + type: "ReLU" bottom: "inception_4e/pool_proj" top: "inception_4e/pool_proj" - name: "inception_4e/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4e/output" + type: "Concat" bottom: "inception_4e/1x1" bottom: "inception_4e/3x3" bottom: "inception_4e/5x5" bottom: "inception_4e/pool_proj" top: "inception_4e/output" - name: "inception_4e/output" - type: CONCAT } -layers { +layer { + name: "pool4/3x3_s2" + type: "Pooling" bottom: "inception_4e/output" top: "pool4/3x3_s2" - name: "pool4/3x3_s2" - type: POOLING pooling_param { pool: MAX kernel_size: 3 stride: 2 } } -layers { +layer { + name: "inception_5a/1x1" + type: "Convolution" bottom: "pool4/3x3_s2" top: "inception_5a/1x1" - name: "inception_5a/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 kernel_size: 1 @@ -1516,21 +1700,25 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_1x1" + type: "ReLU" bottom: "inception_5a/1x1" top: "inception_5a/1x1" - name: "inception_5a/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_5a/3x3_reduce" + type: "Convolution" bottom: "pool4/3x3_s2" top: "inception_5a/3x3_reduce" - name: "inception_5a/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 160 kernel_size: 1 @@ -1544,21 +1732,25 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_3x3_reduce" + type: "ReLU" bottom: "inception_5a/3x3_reduce" top: "inception_5a/3x3_reduce" - name: "inception_5a/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_5a/3x3" + type: "Convolution" bottom: "inception_5a/3x3_reduce" top: "inception_5a/3x3" - name: "inception_5a/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 320 pad: 1 @@ -1573,21 +1765,25 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_3x3" + type: "ReLU" bottom: "inception_5a/3x3" top: "inception_5a/3x3" - name: "inception_5a/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_5a/5x5_reduce" + type: "Convolution" bottom: "pool4/3x3_s2" top: "inception_5a/5x5_reduce" - name: "inception_5a/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -1601,21 +1797,25 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_5x5_reduce" + type: "ReLU" bottom: "inception_5a/5x5_reduce" top: "inception_5a/5x5_reduce" - name: "inception_5a/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_5a/5x5" + type: "Convolution" bottom: "inception_5a/5x5_reduce" top: "inception_5a/5x5" - name: "inception_5a/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 pad: 2 @@ -1630,17 +1830,17 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_5x5" + type: "ReLU" bottom: "inception_5a/5x5" top: "inception_5a/5x5" - name: "inception_5a/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_5a/pool" + type: "Pooling" bottom: "pool4/3x3_s2" top: "inception_5a/pool" - name: "inception_5a/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1648,15 +1848,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_5a/pool_proj" + type: "Convolution" bottom: "inception_5a/pool" top: "inception_5a/pool_proj" - name: "inception_5a/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -1670,30 +1874,34 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_pool_proj" + type: "ReLU" bottom: "inception_5a/pool_proj" top: "inception_5a/pool_proj" - name: "inception_5a/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_5a/output" + type: "Concat" bottom: "inception_5a/1x1" bottom: "inception_5a/3x3" bottom: "inception_5a/5x5" bottom: "inception_5a/pool_proj" top: "inception_5a/output" - name: "inception_5a/output" - type: CONCAT } -layers { +layer { + name: "inception_5b/1x1" + type: "Convolution" bottom: "inception_5a/output" top: "inception_5b/1x1" - name: "inception_5b/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 kernel_size: 1 @@ -1707,21 +1915,25 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_1x1" + type: "ReLU" bottom: "inception_5b/1x1" top: "inception_5b/1x1" - name: "inception_5b/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_5b/3x3_reduce" + type: "Convolution" bottom: "inception_5a/output" top: "inception_5b/3x3_reduce" - name: "inception_5b/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 192 kernel_size: 1 @@ -1735,21 +1947,25 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_3x3_reduce" + type: "ReLU" bottom: "inception_5b/3x3_reduce" top: "inception_5b/3x3_reduce" - name: "inception_5b/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_5b/3x3" + type: "Convolution" bottom: "inception_5b/3x3_reduce" top: "inception_5b/3x3" - name: "inception_5b/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -1764,21 +1980,25 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_3x3" + type: "ReLU" bottom: "inception_5b/3x3" top: "inception_5b/3x3" - name: "inception_5b/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_5b/5x5_reduce" + type: "Convolution" bottom: "inception_5a/output" top: "inception_5b/5x5_reduce" - name: "inception_5b/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 48 kernel_size: 1 @@ -1792,21 +2012,25 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_5x5_reduce" + type: "ReLU" bottom: "inception_5b/5x5_reduce" top: "inception_5b/5x5_reduce" - name: "inception_5b/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_5b/5x5" + type: "Convolution" bottom: "inception_5b/5x5_reduce" top: "inception_5b/5x5" - name: "inception_5b/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 pad: 2 @@ -1821,17 +2045,17 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_5x5" + type: "ReLU" bottom: "inception_5b/5x5" top: "inception_5b/5x5" - name: "inception_5b/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_5b/pool" + type: "Pooling" bottom: "inception_5a/output" top: "inception_5b/pool" - name: "inception_5b/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1839,15 +2063,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_5b/pool_proj" + type: "Convolution" bottom: "inception_5b/pool" top: "inception_5b/pool_proj" - name: "inception_5b/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -1861,50 +2089,54 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_pool_proj" + type: "ReLU" bottom: "inception_5b/pool_proj" top: "inception_5b/pool_proj" - name: "inception_5b/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_5b/output" + type: "Concat" bottom: "inception_5b/1x1" bottom: "inception_5b/3x3" bottom: "inception_5b/5x5" bottom: "inception_5b/pool_proj" top: "inception_5b/output" - name: "inception_5b/output" - type: CONCAT } -layers { +layer { + name: "pool5/7x7_s1" + type: "Pooling" bottom: "inception_5b/output" top: "pool5/7x7_s1" - name: "pool5/7x7_s1" - type: POOLING pooling_param { pool: AVE kernel_size: 7 stride: 1 } } -layers { +layer { + name: "pool5/drop_7x7_s1" + type: "Dropout" bottom: "pool5/7x7_s1" top: "pool5/7x7_s1" - name: "pool5/drop_7x7_s1" - type: DROPOUT dropout_param { dropout_ratio: 0.4 } } -layers { +layer { + name: "loss3/classifier" + type: "InnerProduct" bottom: "pool5/7x7_s1" top: "loss3/classifier" - name: "loss3/classifier" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1000 weight_filler { @@ -1916,9 +2148,9 @@ layers { } } } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "loss3/classifier" top: "prob" -} \ No newline at end of file +} diff --git a/models/bvlc_googlenet/train_val.prototxt b/models/bvlc_googlenet/train_val.prototxt index cd8f38abdc8..79ede2b9d9c 100644 --- a/models/bvlc_googlenet/train_val.prototxt +++ b/models/bvlc_googlenet/train_val.prototxt @@ -1,14 +1,9 @@ name: "GoogleNet" -layers { +layer { + name: "data" + type: "Data" top: "data" top: "label" - name: "data" - type: DATA - data_param { - source: "examples/imagenet/ilsvrc12_train_lmdb" - batch_size: 32 - backend: LMDB - } include { phase: TRAIN } @@ -19,17 +14,17 @@ layers { mean_value: 117 mean_value: 123 } -} -layers { - top: "data" - top: "label" - name: "data" - type: DATA data_param { - source: "examples/imagenet/ilsvrc12_val_lmdb" - batch_size: 50 + source: "examples/imagenet/ilsvrc12_train_lmdb" + batch_size: 32 backend: LMDB } +} +layer { + name: "data" + type: "Data" + top: "data" + top: "label" include { phase: TEST } @@ -40,16 +35,25 @@ layers { mean_value: 117 mean_value: 123 } + data_param { + source: "examples/imagenet/ilsvrc12_val_lmdb" + batch_size: 50 + backend: LMDB + } } -layers { +layer { + name: "conv1/7x7_s2" + type: "Convolution" bottom: "data" top: "conv1/7x7_s2" - name: "conv1/7x7_s2" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 pad: 3 @@ -65,43 +69,47 @@ layers { } } } -layers { +layer { + name: "conv1/relu_7x7" + type: "ReLU" bottom: "conv1/7x7_s2" top: "conv1/7x7_s2" - name: "conv1/relu_7x7" - type: RELU } -layers { +layer { + name: "pool1/3x3_s2" + type: "Pooling" bottom: "conv1/7x7_s2" top: "pool1/3x3_s2" - name: "pool1/3x3_s2" - type: POOLING pooling_param { pool: MAX kernel_size: 3 stride: 2 } } -layers { +layer { + name: "pool1/norm1" + type: "LRN" bottom: "pool1/3x3_s2" top: "pool1/norm1" - name: "pool1/norm1" - type: LRN lrn_param { local_size: 5 alpha: 0.0001 beta: 0.75 } } -layers { +layer { + name: "conv2/3x3_reduce" + type: "Convolution" bottom: "pool1/norm1" top: "conv2/3x3_reduce" - name: "conv2/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -115,21 +123,25 @@ layers { } } } -layers { +layer { + name: "conv2/relu_3x3_reduce" + type: "ReLU" bottom: "conv2/3x3_reduce" top: "conv2/3x3_reduce" - name: "conv2/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "conv2/3x3" + type: "Convolution" bottom: "conv2/3x3_reduce" top: "conv2/3x3" - name: "conv2/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 192 pad: 1 @@ -144,43 +156,47 @@ layers { } } } -layers { +layer { + name: "conv2/relu_3x3" + type: "ReLU" bottom: "conv2/3x3" top: "conv2/3x3" - name: "conv2/relu_3x3" - type: RELU } -layers { +layer { + name: "conv2/norm2" + type: "LRN" bottom: "conv2/3x3" top: "conv2/norm2" - name: "conv2/norm2" - type: LRN lrn_param { local_size: 5 alpha: 0.0001 beta: 0.75 } } -layers { +layer { + name: "pool2/3x3_s2" + type: "Pooling" bottom: "conv2/norm2" top: "pool2/3x3_s2" - name: "pool2/3x3_s2" - type: POOLING pooling_param { pool: MAX kernel_size: 3 stride: 2 } } -layers { +layer { + name: "inception_3a/1x1" + type: "Convolution" bottom: "pool2/3x3_s2" top: "inception_3a/1x1" - name: "inception_3a/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -194,21 +210,25 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_1x1" + type: "ReLU" bottom: "inception_3a/1x1" top: "inception_3a/1x1" - name: "inception_3a/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_3a/3x3_reduce" + type: "Convolution" bottom: "pool2/3x3_s2" top: "inception_3a/3x3_reduce" - name: "inception_3a/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 1 @@ -222,21 +242,25 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_3x3_reduce" + type: "ReLU" bottom: "inception_3a/3x3_reduce" top: "inception_3a/3x3_reduce" - name: "inception_3a/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_3a/3x3" + type: "Convolution" bottom: "inception_3a/3x3_reduce" top: "inception_3a/3x3" - name: "inception_3a/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 pad: 1 @@ -251,21 +275,25 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_3x3" + type: "ReLU" bottom: "inception_3a/3x3" top: "inception_3a/3x3" - name: "inception_3a/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_3a/5x5_reduce" + type: "Convolution" bottom: "pool2/3x3_s2" top: "inception_3a/5x5_reduce" - name: "inception_3a/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 16 kernel_size: 1 @@ -279,21 +307,25 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_5x5_reduce" + type: "ReLU" bottom: "inception_3a/5x5_reduce" top: "inception_3a/5x5_reduce" - name: "inception_3a/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_3a/5x5" + type: "Convolution" bottom: "inception_3a/5x5_reduce" top: "inception_3a/5x5" - name: "inception_3a/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 pad: 2 @@ -308,17 +340,17 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_5x5" + type: "ReLU" bottom: "inception_3a/5x5" top: "inception_3a/5x5" - name: "inception_3a/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_3a/pool" + type: "Pooling" bottom: "pool2/3x3_s2" top: "inception_3a/pool" - name: "inception_3a/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -326,15 +358,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_3a/pool_proj" + type: "Convolution" bottom: "inception_3a/pool" top: "inception_3a/pool_proj" - name: "inception_3a/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -348,30 +384,34 @@ layers { } } } -layers { +layer { + name: "inception_3a/relu_pool_proj" + type: "ReLU" bottom: "inception_3a/pool_proj" top: "inception_3a/pool_proj" - name: "inception_3a/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_3a/output" + type: "Concat" bottom: "inception_3a/1x1" bottom: "inception_3a/3x3" bottom: "inception_3a/5x5" bottom: "inception_3a/pool_proj" top: "inception_3a/output" - name: "inception_3a/output" - type: CONCAT } -layers { +layer { + name: "inception_3b/1x1" + type: "Convolution" bottom: "inception_3a/output" top: "inception_3b/1x1" - name: "inception_3b/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -385,21 +425,25 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_1x1" + type: "ReLU" bottom: "inception_3b/1x1" top: "inception_3b/1x1" - name: "inception_3b/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_3b/3x3_reduce" + type: "Convolution" bottom: "inception_3a/output" top: "inception_3b/3x3_reduce" - name: "inception_3b/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -413,21 +457,25 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_3x3_reduce" + type: "ReLU" bottom: "inception_3b/3x3_reduce" top: "inception_3b/3x3_reduce" - name: "inception_3b/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_3b/3x3" + type: "Convolution" bottom: "inception_3b/3x3_reduce" top: "inception_3b/3x3" - name: "inception_3b/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 192 pad: 1 @@ -442,21 +490,25 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_3x3" + type: "ReLU" bottom: "inception_3b/3x3" top: "inception_3b/3x3" - name: "inception_3b/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_3b/5x5_reduce" + type: "Convolution" bottom: "inception_3a/output" top: "inception_3b/5x5_reduce" - name: "inception_3b/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -470,21 +522,25 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_5x5_reduce" + type: "ReLU" bottom: "inception_3b/5x5_reduce" top: "inception_3b/5x5_reduce" - name: "inception_3b/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_3b/5x5" + type: "Convolution" bottom: "inception_3b/5x5_reduce" top: "inception_3b/5x5" - name: "inception_3b/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 pad: 2 @@ -499,17 +555,17 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_5x5" + type: "ReLU" bottom: "inception_3b/5x5" top: "inception_3b/5x5" - name: "inception_3b/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_3b/pool" + type: "Pooling" bottom: "inception_3a/output" top: "inception_3b/pool" - name: "inception_3b/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -517,15 +573,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_3b/pool_proj" + type: "Convolution" bottom: "inception_3b/pool" top: "inception_3b/pool_proj" - name: "inception_3b/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -539,41 +599,45 @@ layers { } } } -layers { +layer { + name: "inception_3b/relu_pool_proj" + type: "ReLU" bottom: "inception_3b/pool_proj" top: "inception_3b/pool_proj" - name: "inception_3b/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_3b/output" + type: "Concat" bottom: "inception_3b/1x1" bottom: "inception_3b/3x3" bottom: "inception_3b/5x5" bottom: "inception_3b/pool_proj" top: "inception_3b/output" - name: "inception_3b/output" - type: CONCAT } -layers { +layer { + name: "pool3/3x3_s2" + type: "Pooling" bottom: "inception_3b/output" top: "pool3/3x3_s2" - name: "pool3/3x3_s2" - type: POOLING pooling_param { pool: MAX kernel_size: 3 stride: 2 } } -layers { +layer { + name: "inception_4a/1x1" + type: "Convolution" bottom: "pool3/3x3_s2" top: "inception_4a/1x1" - name: "inception_4a/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 192 kernel_size: 1 @@ -587,21 +651,25 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_1x1" + type: "ReLU" bottom: "inception_4a/1x1" top: "inception_4a/1x1" - name: "inception_4a/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4a/3x3_reduce" + type: "Convolution" bottom: "pool3/3x3_s2" top: "inception_4a/3x3_reduce" - name: "inception_4a/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 1 @@ -615,21 +683,25 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4a/3x3_reduce" top: "inception_4a/3x3_reduce" - name: "inception_4a/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4a/3x3" + type: "Convolution" bottom: "inception_4a/3x3_reduce" top: "inception_4a/3x3" - name: "inception_4a/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 208 pad: 1 @@ -644,21 +716,25 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_3x3" + type: "ReLU" bottom: "inception_4a/3x3" top: "inception_4a/3x3" - name: "inception_4a/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4a/5x5_reduce" + type: "Convolution" bottom: "pool3/3x3_s2" top: "inception_4a/5x5_reduce" - name: "inception_4a/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 16 kernel_size: 1 @@ -672,21 +748,25 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4a/5x5_reduce" top: "inception_4a/5x5_reduce" - name: "inception_4a/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4a/5x5" + type: "Convolution" bottom: "inception_4a/5x5_reduce" top: "inception_4a/5x5" - name: "inception_4a/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 48 pad: 2 @@ -701,17 +781,17 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_5x5" + type: "ReLU" bottom: "inception_4a/5x5" top: "inception_4a/5x5" - name: "inception_4a/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4a/pool" + type: "Pooling" bottom: "pool3/3x3_s2" top: "inception_4a/pool" - name: "inception_4a/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -719,15 +799,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4a/pool_proj" + type: "Convolution" bottom: "inception_4a/pool" top: "inception_4a/pool_proj" - name: "inception_4a/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -741,41 +825,45 @@ layers { } } } -layers { +layer { + name: "inception_4a/relu_pool_proj" + type: "ReLU" bottom: "inception_4a/pool_proj" top: "inception_4a/pool_proj" - name: "inception_4a/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4a/output" + type: "Concat" bottom: "inception_4a/1x1" bottom: "inception_4a/3x3" bottom: "inception_4a/5x5" bottom: "inception_4a/pool_proj" top: "inception_4a/output" - name: "inception_4a/output" - type: CONCAT } -layers { +layer { + name: "loss1/ave_pool" + type: "Pooling" bottom: "inception_4a/output" top: "loss1/ave_pool" - name: "loss1/ave_pool" - type: POOLING pooling_param { pool: AVE kernel_size: 5 stride: 3 } } -layers { +layer { + name: "loss1/conv" + type: "Convolution" bottom: "loss1/ave_pool" top: "loss1/conv" - name: "loss1/conv" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -789,21 +877,25 @@ layers { } } } -layers { +layer { + name: "loss1/relu_conv" + type: "ReLU" bottom: "loss1/conv" top: "loss1/conv" - name: "loss1/relu_conv" - type: RELU } -layers { +layer { + name: "loss1/fc" + type: "InnerProduct" bottom: "loss1/conv" top: "loss1/fc" - name: "loss1/fc" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1024 weight_filler { @@ -816,30 +908,34 @@ layers { } } } -layers { +layer { + name: "loss1/relu_fc" + type: "ReLU" bottom: "loss1/fc" top: "loss1/fc" - name: "loss1/relu_fc" - type: RELU } -layers { +layer { + name: "loss1/drop_fc" + type: "Dropout" bottom: "loss1/fc" top: "loss1/fc" - name: "loss1/drop_fc" - type: DROPOUT dropout_param { dropout_ratio: 0.7 } } -layers { +layer { + name: "loss1/classifier" + type: "InnerProduct" bottom: "loss1/fc" top: "loss1/classifier" - name: "loss1/classifier" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1000 weight_filler { @@ -852,46 +948,50 @@ layers { } } } -layers { +layer { + name: "loss1/loss" + type: "SoftmaxWithLoss" bottom: "loss1/classifier" bottom: "label" top: "loss1/loss1" - name: "loss1/loss" - type: SOFTMAX_LOSS loss_weight: 0.3 } -layers { +layer { + name: "loss1/top-1" + type: "Accuracy" bottom: "loss1/classifier" bottom: "label" top: "loss1/top-1" - name: "loss1/top-1" - type: ACCURACY include { phase: TEST } } -layers { +layer { + name: "loss1/top-5" + type: "Accuracy" bottom: "loss1/classifier" bottom: "label" top: "loss1/top-5" - name: "loss1/top-5" - type: ACCURACY - accuracy_param { - top_k: 5 - } include { phase: TEST } + accuracy_param { + top_k: 5 + } } -layers { +layer { + name: "inception_4b/1x1" + type: "Convolution" bottom: "inception_4a/output" top: "inception_4b/1x1" - name: "inception_4b/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 160 kernel_size: 1 @@ -905,21 +1005,25 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_1x1" + type: "ReLU" bottom: "inception_4b/1x1" top: "inception_4b/1x1" - name: "inception_4b/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4b/3x3_reduce" + type: "Convolution" bottom: "inception_4a/output" top: "inception_4b/3x3_reduce" - name: "inception_4b/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 112 kernel_size: 1 @@ -933,21 +1037,25 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4b/3x3_reduce" top: "inception_4b/3x3_reduce" - name: "inception_4b/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4b/3x3" + type: "Convolution" bottom: "inception_4b/3x3_reduce" top: "inception_4b/3x3" - name: "inception_4b/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 224 pad: 1 @@ -962,21 +1070,25 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_3x3" + type: "ReLU" bottom: "inception_4b/3x3" top: "inception_4b/3x3" - name: "inception_4b/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4b/5x5_reduce" + type: "Convolution" bottom: "inception_4a/output" top: "inception_4b/5x5_reduce" - name: "inception_4b/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 24 kernel_size: 1 @@ -990,21 +1102,25 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4b/5x5_reduce" top: "inception_4b/5x5_reduce" - name: "inception_4b/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4b/5x5" + type: "Convolution" bottom: "inception_4b/5x5_reduce" top: "inception_4b/5x5" - name: "inception_4b/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 pad: 2 @@ -1019,17 +1135,17 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_5x5" + type: "ReLU" bottom: "inception_4b/5x5" top: "inception_4b/5x5" - name: "inception_4b/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4b/pool" + type: "Pooling" bottom: "inception_4a/output" top: "inception_4b/pool" - name: "inception_4b/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1037,15 +1153,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4b/pool_proj" + type: "Convolution" bottom: "inception_4b/pool" top: "inception_4b/pool_proj" - name: "inception_4b/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -1059,30 +1179,34 @@ layers { } } } -layers { +layer { + name: "inception_4b/relu_pool_proj" + type: "ReLU" bottom: "inception_4b/pool_proj" top: "inception_4b/pool_proj" - name: "inception_4b/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4b/output" + type: "Concat" bottom: "inception_4b/1x1" bottom: "inception_4b/3x3" bottom: "inception_4b/5x5" bottom: "inception_4b/pool_proj" top: "inception_4b/output" - name: "inception_4b/output" - type: CONCAT } -layers { +layer { + name: "inception_4c/1x1" + type: "Convolution" bottom: "inception_4b/output" top: "inception_4c/1x1" - name: "inception_4c/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -1096,21 +1220,25 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_1x1" + type: "ReLU" bottom: "inception_4c/1x1" top: "inception_4c/1x1" - name: "inception_4c/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4c/3x3_reduce" + type: "Convolution" bottom: "inception_4b/output" top: "inception_4c/3x3_reduce" - name: "inception_4c/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -1124,21 +1252,25 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4c/3x3_reduce" top: "inception_4c/3x3_reduce" - name: "inception_4c/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4c/3x3" + type: "Convolution" bottom: "inception_4c/3x3_reduce" top: "inception_4c/3x3" - name: "inception_4c/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 1 @@ -1153,21 +1285,25 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_3x3" + type: "ReLU" bottom: "inception_4c/3x3" top: "inception_4c/3x3" - name: "inception_4c/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4c/5x5_reduce" + type: "Convolution" bottom: "inception_4b/output" top: "inception_4c/5x5_reduce" - name: "inception_4c/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 24 kernel_size: 1 @@ -1181,21 +1317,25 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4c/5x5_reduce" top: "inception_4c/5x5_reduce" - name: "inception_4c/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4c/5x5" + type: "Convolution" bottom: "inception_4c/5x5_reduce" top: "inception_4c/5x5" - name: "inception_4c/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 pad: 2 @@ -1210,17 +1350,17 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_5x5" + type: "ReLU" bottom: "inception_4c/5x5" top: "inception_4c/5x5" - name: "inception_4c/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4c/pool" + type: "Pooling" bottom: "inception_4b/output" top: "inception_4c/pool" - name: "inception_4c/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1228,15 +1368,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4c/pool_proj" + type: "Convolution" bottom: "inception_4c/pool" top: "inception_4c/pool_proj" - name: "inception_4c/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -1250,30 +1394,34 @@ layers { } } } -layers { +layer { + name: "inception_4c/relu_pool_proj" + type: "ReLU" bottom: "inception_4c/pool_proj" top: "inception_4c/pool_proj" - name: "inception_4c/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4c/output" + type: "Concat" bottom: "inception_4c/1x1" bottom: "inception_4c/3x3" bottom: "inception_4c/5x5" bottom: "inception_4c/pool_proj" top: "inception_4c/output" - name: "inception_4c/output" - type: CONCAT } -layers { +layer { + name: "inception_4d/1x1" + type: "Convolution" bottom: "inception_4c/output" top: "inception_4d/1x1" - name: "inception_4d/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 112 kernel_size: 1 @@ -1287,21 +1435,25 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_1x1" + type: "ReLU" bottom: "inception_4d/1x1" top: "inception_4d/1x1" - name: "inception_4d/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4d/3x3_reduce" + type: "Convolution" bottom: "inception_4c/output" top: "inception_4d/3x3_reduce" - name: "inception_4d/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 144 kernel_size: 1 @@ -1315,21 +1467,25 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4d/3x3_reduce" top: "inception_4d/3x3_reduce" - name: "inception_4d/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4d/3x3" + type: "Convolution" bottom: "inception_4d/3x3_reduce" top: "inception_4d/3x3" - name: "inception_4d/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 288 pad: 1 @@ -1344,21 +1500,25 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_3x3" + type: "ReLU" bottom: "inception_4d/3x3" top: "inception_4d/3x3" - name: "inception_4d/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4d/5x5_reduce" + type: "Convolution" bottom: "inception_4c/output" top: "inception_4d/5x5_reduce" - name: "inception_4d/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -1372,21 +1532,25 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4d/5x5_reduce" top: "inception_4d/5x5_reduce" - name: "inception_4d/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4d/5x5" + type: "Convolution" bottom: "inception_4d/5x5_reduce" top: "inception_4d/5x5" - name: "inception_4d/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 pad: 2 @@ -1401,17 +1565,17 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_5x5" + type: "ReLU" bottom: "inception_4d/5x5" top: "inception_4d/5x5" - name: "inception_4d/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4d/pool" + type: "Pooling" bottom: "inception_4c/output" top: "inception_4d/pool" - name: "inception_4d/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1419,15 +1583,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4d/pool_proj" + type: "Convolution" bottom: "inception_4d/pool" top: "inception_4d/pool_proj" - name: "inception_4d/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 64 kernel_size: 1 @@ -1441,41 +1609,45 @@ layers { } } } -layers { +layer { + name: "inception_4d/relu_pool_proj" + type: "ReLU" bottom: "inception_4d/pool_proj" top: "inception_4d/pool_proj" - name: "inception_4d/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4d/output" + type: "Concat" bottom: "inception_4d/1x1" bottom: "inception_4d/3x3" bottom: "inception_4d/5x5" bottom: "inception_4d/pool_proj" top: "inception_4d/output" - name: "inception_4d/output" - type: CONCAT } -layers { +layer { + name: "loss2/ave_pool" + type: "Pooling" bottom: "inception_4d/output" top: "loss2/ave_pool" - name: "loss2/ave_pool" - type: POOLING pooling_param { pool: AVE kernel_size: 5 stride: 3 } } -layers { +layer { + name: "loss2/conv" + type: "Convolution" bottom: "loss2/ave_pool" top: "loss2/conv" - name: "loss2/conv" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -1489,21 +1661,25 @@ layers { } } } -layers { +layer { + name: "loss2/relu_conv" + type: "ReLU" bottom: "loss2/conv" top: "loss2/conv" - name: "loss2/relu_conv" - type: RELU } -layers { +layer { + name: "loss2/fc" + type: "InnerProduct" bottom: "loss2/conv" top: "loss2/fc" - name: "loss2/fc" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1024 weight_filler { @@ -1516,30 +1692,34 @@ layers { } } } -layers { +layer { + name: "loss2/relu_fc" + type: "ReLU" bottom: "loss2/fc" top: "loss2/fc" - name: "loss2/relu_fc" - type: RELU } -layers { +layer { + name: "loss2/drop_fc" + type: "Dropout" bottom: "loss2/fc" top: "loss2/fc" - name: "loss2/drop_fc" - type: DROPOUT dropout_param { dropout_ratio: 0.7 } } -layers { +layer { + name: "loss2/classifier" + type: "InnerProduct" bottom: "loss2/fc" top: "loss2/classifier" - name: "loss2/classifier" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1000 weight_filler { @@ -1552,46 +1732,50 @@ layers { } } } -layers { +layer { + name: "loss2/loss" + type: "SoftmaxWithLoss" bottom: "loss2/classifier" bottom: "label" top: "loss2/loss1" - name: "loss2/loss" - type: SOFTMAX_LOSS loss_weight: 0.3 } -layers { +layer { + name: "loss2/top-1" + type: "Accuracy" bottom: "loss2/classifier" bottom: "label" top: "loss2/top-1" - name: "loss2/top-1" - type: ACCURACY include { phase: TEST } } -layers { +layer { + name: "loss2/top-5" + type: "Accuracy" bottom: "loss2/classifier" bottom: "label" top: "loss2/top-5" - name: "loss2/top-5" - type: ACCURACY - accuracy_param { - top_k: 5 - } include { phase: TEST } + accuracy_param { + top_k: 5 + } } -layers { +layer { + name: "inception_4e/1x1" + type: "Convolution" bottom: "inception_4d/output" top: "inception_4e/1x1" - name: "inception_4e/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 kernel_size: 1 @@ -1605,21 +1789,25 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_1x1" + type: "ReLU" bottom: "inception_4e/1x1" top: "inception_4e/1x1" - name: "inception_4e/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_4e/3x3_reduce" + type: "Convolution" bottom: "inception_4d/output" top: "inception_4e/3x3_reduce" - name: "inception_4e/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 160 kernel_size: 1 @@ -1633,21 +1821,25 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_3x3_reduce" + type: "ReLU" bottom: "inception_4e/3x3_reduce" top: "inception_4e/3x3_reduce" - name: "inception_4e/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_4e/3x3" + type: "Convolution" bottom: "inception_4e/3x3_reduce" top: "inception_4e/3x3" - name: "inception_4e/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 320 pad: 1 @@ -1662,21 +1854,25 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_3x3" + type: "ReLU" bottom: "inception_4e/3x3" top: "inception_4e/3x3" - name: "inception_4e/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_4e/5x5_reduce" + type: "Convolution" bottom: "inception_4d/output" top: "inception_4e/5x5_reduce" - name: "inception_4e/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -1690,21 +1886,25 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_5x5_reduce" + type: "ReLU" bottom: "inception_4e/5x5_reduce" top: "inception_4e/5x5_reduce" - name: "inception_4e/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_4e/5x5" + type: "Convolution" bottom: "inception_4e/5x5_reduce" top: "inception_4e/5x5" - name: "inception_4e/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 pad: 2 @@ -1719,17 +1919,17 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_5x5" + type: "ReLU" bottom: "inception_4e/5x5" top: "inception_4e/5x5" - name: "inception_4e/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_4e/pool" + type: "Pooling" bottom: "inception_4d/output" top: "inception_4e/pool" - name: "inception_4e/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1737,15 +1937,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_4e/pool_proj" + type: "Convolution" bottom: "inception_4e/pool" top: "inception_4e/pool_proj" - name: "inception_4e/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -1759,41 +1963,45 @@ layers { } } } -layers { +layer { + name: "inception_4e/relu_pool_proj" + type: "ReLU" bottom: "inception_4e/pool_proj" top: "inception_4e/pool_proj" - name: "inception_4e/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_4e/output" + type: "Concat" bottom: "inception_4e/1x1" bottom: "inception_4e/3x3" bottom: "inception_4e/5x5" bottom: "inception_4e/pool_proj" top: "inception_4e/output" - name: "inception_4e/output" - type: CONCAT } -layers { +layer { + name: "pool4/3x3_s2" + type: "Pooling" bottom: "inception_4e/output" top: "pool4/3x3_s2" - name: "pool4/3x3_s2" - type: POOLING pooling_param { pool: MAX kernel_size: 3 stride: 2 } } -layers { +layer { + name: "inception_5a/1x1" + type: "Convolution" bottom: "pool4/3x3_s2" top: "inception_5a/1x1" - name: "inception_5a/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 kernel_size: 1 @@ -1807,21 +2015,25 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_1x1" + type: "ReLU" bottom: "inception_5a/1x1" top: "inception_5a/1x1" - name: "inception_5a/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_5a/3x3_reduce" + type: "Convolution" bottom: "pool4/3x3_s2" top: "inception_5a/3x3_reduce" - name: "inception_5a/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 160 kernel_size: 1 @@ -1835,21 +2047,25 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_3x3_reduce" + type: "ReLU" bottom: "inception_5a/3x3_reduce" top: "inception_5a/3x3_reduce" - name: "inception_5a/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_5a/3x3" + type: "Convolution" bottom: "inception_5a/3x3_reduce" top: "inception_5a/3x3" - name: "inception_5a/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 320 pad: 1 @@ -1864,21 +2080,25 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_3x3" + type: "ReLU" bottom: "inception_5a/3x3" top: "inception_5a/3x3" - name: "inception_5a/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_5a/5x5_reduce" + type: "Convolution" bottom: "pool4/3x3_s2" top: "inception_5a/5x5_reduce" - name: "inception_5a/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 32 kernel_size: 1 @@ -1892,21 +2112,25 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_5x5_reduce" + type: "ReLU" bottom: "inception_5a/5x5_reduce" top: "inception_5a/5x5_reduce" - name: "inception_5a/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_5a/5x5" + type: "Convolution" bottom: "inception_5a/5x5_reduce" top: "inception_5a/5x5" - name: "inception_5a/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 pad: 2 @@ -1921,17 +2145,17 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_5x5" + type: "ReLU" bottom: "inception_5a/5x5" top: "inception_5a/5x5" - name: "inception_5a/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_5a/pool" + type: "Pooling" bottom: "pool4/3x3_s2" top: "inception_5a/pool" - name: "inception_5a/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -1939,15 +2163,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_5a/pool_proj" + type: "Convolution" bottom: "inception_5a/pool" top: "inception_5a/pool_proj" - name: "inception_5a/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -1961,30 +2189,34 @@ layers { } } } -layers { +layer { + name: "inception_5a/relu_pool_proj" + type: "ReLU" bottom: "inception_5a/pool_proj" top: "inception_5a/pool_proj" - name: "inception_5a/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_5a/output" + type: "Concat" bottom: "inception_5a/1x1" bottom: "inception_5a/3x3" bottom: "inception_5a/5x5" bottom: "inception_5a/pool_proj" top: "inception_5a/output" - name: "inception_5a/output" - type: CONCAT } -layers { +layer { + name: "inception_5b/1x1" + type: "Convolution" bottom: "inception_5a/output" top: "inception_5b/1x1" - name: "inception_5b/1x1" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 kernel_size: 1 @@ -1998,21 +2230,25 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_1x1" + type: "ReLU" bottom: "inception_5b/1x1" top: "inception_5b/1x1" - name: "inception_5b/relu_1x1" - type: RELU } -layers { +layer { + name: "inception_5b/3x3_reduce" + type: "Convolution" bottom: "inception_5a/output" top: "inception_5b/3x3_reduce" - name: "inception_5b/3x3_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 192 kernel_size: 1 @@ -2026,21 +2262,25 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_3x3_reduce" + type: "ReLU" bottom: "inception_5b/3x3_reduce" top: "inception_5b/3x3_reduce" - name: "inception_5b/relu_3x3_reduce" - type: RELU } -layers { +layer { + name: "inception_5b/3x3" + type: "Convolution" bottom: "inception_5b/3x3_reduce" top: "inception_5b/3x3" - name: "inception_5b/3x3" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -2055,21 +2295,25 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_3x3" + type: "ReLU" bottom: "inception_5b/3x3" top: "inception_5b/3x3" - name: "inception_5b/relu_3x3" - type: RELU } -layers { +layer { + name: "inception_5b/5x5_reduce" + type: "Convolution" bottom: "inception_5a/output" top: "inception_5b/5x5_reduce" - name: "inception_5b/5x5_reduce" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 48 kernel_size: 1 @@ -2083,21 +2327,25 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_5x5_reduce" + type: "ReLU" bottom: "inception_5b/5x5_reduce" top: "inception_5b/5x5_reduce" - name: "inception_5b/relu_5x5_reduce" - type: RELU } -layers { +layer { + name: "inception_5b/5x5" + type: "Convolution" bottom: "inception_5b/5x5_reduce" top: "inception_5b/5x5" - name: "inception_5b/5x5" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 pad: 2 @@ -2112,17 +2360,17 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_5x5" + type: "ReLU" bottom: "inception_5b/5x5" top: "inception_5b/5x5" - name: "inception_5b/relu_5x5" - type: RELU } -layers { +layer { + name: "inception_5b/pool" + type: "Pooling" bottom: "inception_5a/output" top: "inception_5b/pool" - name: "inception_5b/pool" - type: POOLING pooling_param { pool: MAX kernel_size: 3 @@ -2130,15 +2378,19 @@ layers { pad: 1 } } -layers { +layer { + name: "inception_5b/pool_proj" + type: "Convolution" bottom: "inception_5b/pool" top: "inception_5b/pool_proj" - name: "inception_5b/pool_proj" - type: CONVOLUTION - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 128 kernel_size: 1 @@ -2152,50 +2404,54 @@ layers { } } } -layers { +layer { + name: "inception_5b/relu_pool_proj" + type: "ReLU" bottom: "inception_5b/pool_proj" top: "inception_5b/pool_proj" - name: "inception_5b/relu_pool_proj" - type: RELU } -layers { +layer { + name: "inception_5b/output" + type: "Concat" bottom: "inception_5b/1x1" bottom: "inception_5b/3x3" bottom: "inception_5b/5x5" bottom: "inception_5b/pool_proj" top: "inception_5b/output" - name: "inception_5b/output" - type: CONCAT } -layers { +layer { + name: "pool5/7x7_s1" + type: "Pooling" bottom: "inception_5b/output" top: "pool5/7x7_s1" - name: "pool5/7x7_s1" - type: POOLING pooling_param { pool: AVE kernel_size: 7 stride: 1 } } -layers { +layer { + name: "pool5/drop_7x7_s1" + type: "Dropout" bottom: "pool5/7x7_s1" top: "pool5/7x7_s1" - name: "pool5/drop_7x7_s1" - type: DROPOUT dropout_param { dropout_ratio: 0.4 } } -layers { +layer { + name: "loss3/classifier" + type: "InnerProduct" bottom: "pool5/7x7_s1" top: "loss3/classifier" - name: "loss3/classifier" - type: INNER_PRODUCT - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1000 weight_filler { @@ -2207,34 +2463,34 @@ layers { } } } -layers { +layer { + name: "loss3/loss3" + type: "SoftmaxWithLoss" bottom: "loss3/classifier" bottom: "label" top: "loss3/loss3" - name: "loss3/loss3" - type: SOFTMAX_LOSS loss_weight: 1 } -layers { +layer { + name: "loss3/top-1" + type: "Accuracy" bottom: "loss3/classifier" bottom: "label" top: "loss3/top-1" - name: "loss3/top-1" - type: ACCURACY include { phase: TEST } } -layers { +layer { + name: "loss3/top-5" + type: "Accuracy" bottom: "loss3/classifier" bottom: "label" top: "loss3/top-5" - name: "loss3/top-5" - type: ACCURACY - accuracy_param { - top_k: 5 - } include { phase: TEST } + accuracy_param { + top_k: 5 + } } diff --git a/models/bvlc_reference_caffenet/deploy.prototxt b/models/bvlc_reference_caffenet/deploy.prototxt index 4e494f420b5..29ccf1469f7 100644 --- a/models/bvlc_reference_caffenet/deploy.prototxt +++ b/models/bvlc_reference_caffenet/deploy.prototxt @@ -4,9 +4,9 @@ input_dim: 10 input_dim: 3 input_dim: 227 input_dim: 227 -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" convolution_param { @@ -15,15 +15,15 @@ layers { stride: 4 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -32,9 +32,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { @@ -43,9 +43,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" convolution_param { @@ -55,15 +55,15 @@ layers { group: 2 } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -72,9 +72,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { @@ -83,9 +83,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" convolution_param { @@ -94,15 +94,15 @@ layers { kernel_size: 3 } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" convolution_param { @@ -112,15 +112,15 @@ layers { group: 2 } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" convolution_param { @@ -130,15 +130,15 @@ layers { group: 2 } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -147,66 +147,66 @@ layers { stride: 2 } } -layers { +layer { name: "fc6" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool5" top: "fc6" inner_product_param { num_output: 4096 } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc6" top: "fc7" inner_product_param { num_output: 4096 } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7" top: "fc7" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc8" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc7" top: "fc8" inner_product_param { num_output: 1000 } } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "fc8" top: "prob" } diff --git a/models/bvlc_reference_caffenet/train_val.prototxt b/models/bvlc_reference_caffenet/train_val.prototxt index 00fcc080261..c79472e09ab 100644 --- a/models/bvlc_reference_caffenet/train_val.prototxt +++ b/models/bvlc_reference_caffenet/train_val.prototxt @@ -1,18 +1,16 @@ name: "CaffeNet" -layers { +layer { name: "data" - type: DATA + type: "Data" top: "data" top: "label" - data_param { - source: "examples/imagenet/ilsvrc12_train_lmdb" - backend: LMDB - batch_size: 256 + include { + phase: TRAIN } transform_param { + mirror: true crop_size: 227 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" - mirror: true } # mean pixel / channel-wise mean instead of mean image # transform_param { @@ -22,22 +20,24 @@ layers { # mean_value: 123 # mirror: true # } - include: { phase: TRAIN } + data_param { + source: "examples/imagenet/ilsvrc12_train_lmdb" + batch_size: 256 + backend: LMDB + } } -layers { +layer { name: "data" - type: DATA + type: "Data" top: "data" top: "label" - data_param { - source: "examples/imagenet/ilsvrc12_val_lmdb" - backend: LMDB - batch_size: 50 + include { + phase: TEST } transform_param { + mirror: false crop_size: 227 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" - mirror: false } # mean pixel / channel-wise mean instead of mean image # transform_param { @@ -47,17 +47,25 @@ layers { # mean_value: 123 # mirror: true # } - include: { phase: TEST } + data_param { + source: "examples/imagenet/ilsvrc12_val_lmdb" + batch_size: 50 + backend: LMDB + } } -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 11 @@ -72,15 +80,15 @@ layers { } } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -89,9 +97,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { @@ -100,15 +108,19 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 2 @@ -124,15 +136,15 @@ layers { } } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -141,9 +153,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { @@ -152,15 +164,19 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -175,21 +191,25 @@ layers { } } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -205,21 +225,25 @@ layers { } } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 1 @@ -235,15 +259,15 @@ layers { } } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -252,15 +276,19 @@ layers { stride: 2 } } -layers { +layer { name: "fc6" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool5" top: "fc6" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -273,30 +301,34 @@ layers { } } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc6" top: "fc7" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -309,30 +341,34 @@ layers { } } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7" top: "fc7" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc8" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc7" top: "fc8" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 1000 weight_filler { @@ -345,17 +381,19 @@ layers { } } } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "fc8" bottom: "label" top: "accuracy" - include: { phase: TEST } + include { + phase: TEST + } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "fc8" bottom: "label" top: "loss" diff --git a/models/bvlc_reference_rcnn_ilsvrc13/deploy.prototxt b/models/bvlc_reference_rcnn_ilsvrc13/deploy.prototxt index ef75a0a5e95..ea9cf98a926 100644 --- a/models/bvlc_reference_rcnn_ilsvrc13/deploy.prototxt +++ b/models/bvlc_reference_rcnn_ilsvrc13/deploy.prototxt @@ -4,9 +4,9 @@ input_dim: 10 input_dim: 3 input_dim: 227 input_dim: 227 -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" convolution_param { @@ -15,15 +15,15 @@ layers { stride: 4 } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -32,9 +32,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { @@ -43,9 +43,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" convolution_param { @@ -55,15 +55,15 @@ layers { group: 2 } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -72,9 +72,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { @@ -83,9 +83,9 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" convolution_param { @@ -94,15 +94,15 @@ layers { kernel_size: 3 } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" convolution_param { @@ -112,15 +112,15 @@ layers { group: 2 } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" convolution_param { @@ -130,15 +130,15 @@ layers { group: 2 } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -147,48 +147,48 @@ layers { stride: 2 } } -layers { +layer { name: "fc6" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool5" top: "fc6" inner_product_param { num_output: 4096 } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc6" top: "fc7" inner_product_param { num_output: 4096 } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7" top: "fc7" dropout_param { @@ -196,9 +196,9 @@ layers { } } # R-CNN classification layer made from R-CNN ILSVRC13 SVMs. -layers { +layer { name: "fc-rcnn" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc7" top: "fc-rcnn" inner_product_param { diff --git a/models/finetune_flickr_style/deploy.prototxt b/models/finetune_flickr_style/deploy.prototxt index aa2ad961874..4a924f74927 100644 --- a/models/finetune_flickr_style/deploy.prototxt +++ b/models/finetune_flickr_style/deploy.prototxt @@ -4,15 +4,19 @@ input_dim: 10 input_dim: 3 input_dim: 227 input_dim: 227 -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 11 @@ -27,15 +31,15 @@ layers { } } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -44,9 +48,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { @@ -55,15 +59,19 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 2 @@ -79,15 +87,15 @@ layers { } } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -96,9 +104,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { @@ -107,15 +115,19 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -130,21 +142,25 @@ layers { } } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -160,21 +176,25 @@ layers { } } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 1 @@ -190,15 +210,15 @@ layers { } } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -207,15 +227,19 @@ layers { stride: 2 } } -layers { +layer { name: "fc6" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool5" top: "fc6" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -228,31 +252,35 @@ layers { } } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc6" top: "fc7" - # Note that blobs_lr can be set to 0 to disable any fine-tuning of this, and any other, layer - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + # Note that lr_mult can be set to 0 to disable any fine-tuning of this, and any other, layer + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -265,31 +293,35 @@ layers { } } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7" top: "fc7" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc8_flickr" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc7" top: "fc8_flickr" - # blobs_lr is set to higher than for other layers, because this layer is starting from random while the others are already trained - blobs_lr: 10 - blobs_lr: 20 - weight_decay: 1 - weight_decay: 0 + # lr_mult is set to higher than for other layers, because this layer is starting from random while the others are already trained + param { + lr_mult: 10 + decay_mult: 1 + } + param { + lr_mult: 20 + decay_mult: 0 + } inner_product_param { num_output: 20 weight_filler { @@ -302,9 +334,9 @@ layers { } } } -layers { +layer { name: "prob" - type: SOFTMAX + type: "Softmax" bottom: "fc8_flickr" top: "prob" } diff --git a/models/finetune_flickr_style/train_val.prototxt b/models/finetune_flickr_style/train_val.prototxt index 7155c492360..aa9c73e17ce 100644 --- a/models/finetune_flickr_style/train_val.prototxt +++ b/models/finetune_flickr_style/train_val.prototxt @@ -1,49 +1,57 @@ name: "FlickrStyleCaffeNet" -layers { +layer { name: "data" - type: IMAGE_DATA + type: "ImageData" top: "data" top: "label" + include { + phase: TRAIN + } + transform_param { + mirror: true + crop_size: 227 + mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" + } image_data_param { source: "data/flickr_style/train.txt" batch_size: 50 new_height: 256 new_width: 256 } - transform_param { - crop_size: 227 - mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" - mirror: true - } - include: { phase: TRAIN } } -layers { +layer { name: "data" - type: IMAGE_DATA + type: "ImageData" top: "data" top: "label" + include { + phase: TEST + } + transform_param { + mirror: false + crop_size: 227 + mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" + } image_data_param { source: "data/flickr_style/test.txt" batch_size: 50 new_height: 256 new_width: 256 } - transform_param { - crop_size: 227 - mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" - mirror: false - } - include: { phase: TEST } } -layers { +layer { name: "conv1" - type: CONVOLUTION + type: "Convolution" bottom: "data" top: "conv1" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 96 kernel_size: 11 @@ -58,15 +66,15 @@ layers { } } } -layers { +layer { name: "relu1" - type: RELU + type: "ReLU" bottom: "conv1" top: "conv1" } -layers { +layer { name: "pool1" - type: POOLING + type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { @@ -75,9 +83,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm1" - type: LRN + type: "LRN" bottom: "pool1" top: "norm1" lrn_param { @@ -86,15 +94,19 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv2" - type: CONVOLUTION + type: "Convolution" bottom: "norm1" top: "conv2" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 2 @@ -110,15 +122,15 @@ layers { } } } -layers { +layer { name: "relu2" - type: RELU + type: "ReLU" bottom: "conv2" top: "conv2" } -layers { +layer { name: "pool2" - type: POOLING + type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { @@ -127,9 +139,9 @@ layers { stride: 2 } } -layers { +layer { name: "norm2" - type: LRN + type: "LRN" bottom: "pool2" top: "norm2" lrn_param { @@ -138,15 +150,19 @@ layers { beta: 0.75 } } -layers { +layer { name: "conv3" - type: CONVOLUTION + type: "Convolution" bottom: "norm2" top: "conv3" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -161,21 +177,25 @@ layers { } } } -layers { +layer { name: "relu3" - type: RELU + type: "ReLU" bottom: "conv3" top: "conv3" } -layers { +layer { name: "conv4" - type: CONVOLUTION + type: "Convolution" bottom: "conv3" top: "conv4" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 384 pad: 1 @@ -191,21 +211,25 @@ layers { } } } -layers { +layer { name: "relu4" - type: RELU + type: "ReLU" bottom: "conv4" top: "conv4" } -layers { +layer { name: "conv5" - type: CONVOLUTION + type: "Convolution" bottom: "conv4" top: "conv5" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } convolution_param { num_output: 256 pad: 1 @@ -221,15 +245,15 @@ layers { } } } -layers { +layer { name: "relu5" - type: RELU + type: "ReLU" bottom: "conv5" top: "conv5" } -layers { +layer { name: "pool5" - type: POOLING + type: "Pooling" bottom: "conv5" top: "pool5" pooling_param { @@ -238,15 +262,19 @@ layers { stride: 2 } } -layers { +layer { name: "fc6" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "pool5" top: "fc6" - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -259,31 +287,35 @@ layers { } } } -layers { +layer { name: "relu6" - type: RELU + type: "ReLU" bottom: "fc6" top: "fc6" } -layers { +layer { name: "drop6" - type: DROPOUT + type: "Dropout" bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc7" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc6" top: "fc7" - # Note that blobs_lr can be set to 0 to disable any fine-tuning of this, and any other, layer - blobs_lr: 1 - blobs_lr: 2 - weight_decay: 1 - weight_decay: 0 + # Note that lr_mult can be set to 0 to disable any fine-tuning of this, and any other, layer + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } inner_product_param { num_output: 4096 weight_filler { @@ -296,31 +328,35 @@ layers { } } } -layers { +layer { name: "relu7" - type: RELU + type: "ReLU" bottom: "fc7" top: "fc7" } -layers { +layer { name: "drop7" - type: DROPOUT + type: "Dropout" bottom: "fc7" top: "fc7" dropout_param { dropout_ratio: 0.5 } } -layers { +layer { name: "fc8_flickr" - type: INNER_PRODUCT + type: "InnerProduct" bottom: "fc7" top: "fc8_flickr" - # blobs_lr is set to higher than for other layers, because this layer is starting from random while the others are already trained - blobs_lr: 10 - blobs_lr: 20 - weight_decay: 1 - weight_decay: 0 + # lr_mult is set to higher than for other layers, because this layer is starting from random while the others are already trained + param { + lr_mult: 10 + decay_mult: 1 + } + param { + lr_mult: 20 + decay_mult: 0 + } inner_product_param { num_output: 20 weight_filler { @@ -333,17 +369,19 @@ layers { } } } -layers { +layer { name: "loss" - type: SOFTMAX_LOSS + type: "SoftmaxWithLoss" bottom: "fc8_flickr" bottom: "label" } -layers { +layer { name: "accuracy" - type: ACCURACY + type: "Accuracy" bottom: "fc8_flickr" bottom: "label" top: "accuracy" - include: { phase: TEST } + include { + phase: TEST + } } From e80b60fc1e64de7aacd717f70446afdd34ba6845 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 5 Feb 2015 16:41:46 -0800 Subject: [PATCH 283/798] die on inputs to IMAGE_DATA that fail to load It's better to know than march silently on. --- src/caffe/layers/image_data_layer.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index ef6a342c30a..136694886d0 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -118,10 +118,8 @@ void ImageDataLayer::InternalThreadEntry() { timer.Start(); CHECK_GT(lines_size, lines_id_); cv::Mat cv_img = ReadImageToCVMat(root_folder + lines_[lines_id_].first, - new_height, new_width, is_color); - if (!cv_img.data) { - continue; - } + new_height, new_width, is_color); + CHECK(cv_img.data) << "Could not load " << lines_[lines_id_].first; read_time += timer.MicroSeconds(); timer.Start(); // Apply transformations (mirror, crop...) to the image From 6a226970c1b2b365a165e5a8bf9aea7606815414 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 5 Feb 2015 19:28:42 -0800 Subject: [PATCH 284/798] fix for layer-type-str: loss_param and DECONVOLUTION type should have been included in V1LayerParameter, get upgraded --- src/caffe/proto/caffe.proto | 2 ++ src/caffe/util/upgrade_proto.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 81fd2517dbf..c2a39a5cadf 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -719,6 +719,7 @@ message V1LayerParameter { CONTRASTIVE_LOSS = 37; CONVOLUTION = 4; DATA = 5; + DECONVOLUTION = 39; DROPOUT = 6; DUMMY_DATA = 32; EUCLIDEAN_LOSS = 7; @@ -790,6 +791,7 @@ message V1LayerParameter { optional ThresholdParameter threshold_param = 25; optional WindowDataParameter window_data_param = 20; optional TransformationParameter transform_param = 36; + optional LossParameter loss_param = 42; optional V0LayerParameter layer = 1; } diff --git a/src/caffe/util/upgrade_proto.cpp b/src/caffe/util/upgrade_proto.cpp index 258d7d3ee7d..38a06026adf 100644 --- a/src/caffe/util/upgrade_proto.cpp +++ b/src/caffe/util/upgrade_proto.cpp @@ -824,6 +824,10 @@ bool UpgradeV1LayerParameter(const V1LayerParameter& v1_layer_param, layer_param->mutable_transform_param()->CopyFrom( v1_layer_param.transform_param()); } + if (v1_layer_param.has_loss_param()) { + layer_param->mutable_loss_param()->CopyFrom( + v1_layer_param.loss_param()); + } if (v1_layer_param.has_layer()) { LOG(ERROR) << "Input NetParameter has V0 layer -- ignoring."; is_fully_compatible = false; @@ -849,6 +853,8 @@ const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type) { return "ContrastiveLoss"; case V1LayerParameter_LayerType_CONVOLUTION: return "Convolution"; + case V1LayerParameter_LayerType_DECONVOLUTION: + return "Deconvolution"; case V1LayerParameter_LayerType_DATA: return "Data"; case V1LayerParameter_LayerType_DROPOUT: From 33a56e08d9a2714c2492bb7999a350636ed142be Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 6 Feb 2015 00:51:25 -0800 Subject: [PATCH 285/798] build with libc++ on Yosmite with CUDA 7 --- Makefile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 53c16ea4a72..81c67efeaf4 100644 --- a/Makefile +++ b/Makefile @@ -231,15 +231,18 @@ endif # OS X: # clang++ instead of g++ -# libstdc++ instead of libc++ for CUDA compatibility on 10.9 +# libstdc++ for NVCC compatibility on OS X >= 10.9 with CUDA < 7.0 ifeq ($(OSX), 1) CXX := /usr/bin/clang++ - CXXFLAGS += -stdlib=libstdc++ - LINKFLAGS += -stdlib=libstdc++ + CUDA_VERSION := $(shell $(CUDA_DIR)/bin/nvcc -V | grep -o 'release \d' | grep -o '\d') + ifeq ($(shell echo $(CUDA_VERSION) \< 7.0 | bc), 1) + CXXFLAGS += -stdlib=libstdc++ + LINKFLAGS += -stdlib=libstdc++ + endif # clang throws this warning for cuda headers WARNINGS += -Wno-unneeded-internal-declaration # gtest needs to use its own tuple to not conflict with clang - CXXFLAGS += -DGTEST_USE_OWN_TR1_TUPLE=1 + COMMON_FLAGS += -DGTEST_USE_OWN_TR1_TUPLE=1 # boost::thread is called boost_thread-mt to mark multithreading on OS X LIBRARIES += boost_thread-mt endif From 8ec095a6af69097330306eba2dcbed96c3e4b738 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 6 Feb 2015 01:37:02 -0800 Subject: [PATCH 286/798] reduce step size in PowerLayer gradient checks: fix #1252 The gradient checker fails on certain elements of the PowerLayer checks, but only 1-3 sometimes fail out of the 120 elements tested. This is not due to any numerical issue in the PowerLayer, but the distribution of the random inputs for the checks. boost 1.56 switched the normal distribution RNG engine from Box-Muller to Ziggurat. --- src/caffe/test/test_power_layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caffe/test/test_power_layer.cpp b/src/caffe/test/test_power_layer.cpp index 0d52fa1c8e2..76c9e857f36 100644 --- a/src/caffe/test/test_power_layer.cpp +++ b/src/caffe/test/test_power_layer.cpp @@ -74,7 +74,7 @@ class PowerLayerTest : public MultiDeviceTest { } } } - GradientChecker checker(1e-2, 1e-2, 1701, 0., 0.01); + GradientChecker checker(1e-3, 1e-2, 1701, 0., 0.01); checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_, this->blob_top_vec_); } From 4c894d0b2d37c4f5e6a82a797dc8446fb1a9fc62 Mon Sep 17 00:00:00 2001 From: Sagan Bolliger Date: Fri, 6 Feb 2015 12:54:32 -0800 Subject: [PATCH 287/798] Added GPU implementation of SoftmaxWithLossLayer. --- include/caffe/loss_layers.hpp | 7 +- src/caffe/layers/softmax_loss_layer.cpp | 4 + src/caffe/layers/softmax_loss_layer.cu | 129 ++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 src/caffe/layers/softmax_loss_layer.cu diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index f14b9716a4a..09a5c24dde5 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -707,8 +707,8 @@ class SoftmaxWithLossLayer : public LossLayer { /// @copydoc SoftmaxWithLossLayer virtual void Forward_cpu(const vector*>& bottom, const vector*>& top); - // TODO(Yangqing): implement the GPU version of softmax. - + virtual void Forward_gpu(const vector*>& bottom, + const vector*>& top); /** * @brief Computes the softmax loss error gradient w.r.t. the predictions. * @@ -738,6 +738,9 @@ class SoftmaxWithLossLayer : public LossLayer { */ virtual void Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + virtual void Backward_gpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom); + /// The internal SoftmaxLayer used to map predictions to a distribution. shared_ptr > softmax_layer_; diff --git a/src/caffe/layers/softmax_loss_layer.cpp b/src/caffe/layers/softmax_loss_layer.cpp index bf20b6056e4..8f6a4ef7959 100644 --- a/src/caffe/layers/softmax_loss_layer.cpp +++ b/src/caffe/layers/softmax_loss_layer.cpp @@ -115,6 +115,10 @@ void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, } } +#ifdef CPU_ONLY +STUB_GPU(SoftmaxWithLossLayer); +#endif + INSTANTIATE_CLASS(SoftmaxWithLossLayer); REGISTER_LAYER_CLASS(SoftmaxWithLoss); diff --git a/src/caffe/layers/softmax_loss_layer.cu b/src/caffe/layers/softmax_loss_layer.cu new file mode 100644 index 00000000000..215d589ffee --- /dev/null +++ b/src/caffe/layers/softmax_loss_layer.cu @@ -0,0 +1,129 @@ +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +__global__ void SoftmaxLossForwardGPU(const int nthreads, + const Dtype* prob_data, const Dtype* label, Dtype* loss, + const int num, const int dim, const int spatial_dim, + const bool has_ignore_label_, const int ignore_label_, + Dtype* counts) { + CUDA_KERNEL_LOOP(index, nthreads) { + const int n = index / spatial_dim; + const int s = index % spatial_dim; + const int label_value = static_cast(label[n * spatial_dim + s]); + if (has_ignore_label_ && label_value == ignore_label_) { + loss[index] = 0; + counts[index] = 0; + } else { + loss[index] = -log(max(prob_data[n * dim + label_value * spatial_dim + s], + Dtype(FLT_MIN))); + counts[index] = 1; + } + } +} + +template +void SoftmaxWithLossLayer::Forward_gpu( + const vector*>& bottom, const vector*>& top) { + softmax_layer_->Forward(softmax_bottom_vec_, softmax_top_vec_); + const Dtype* prob_data = prob_.gpu_data(); + const Dtype* label = bottom[1]->gpu_data(); + const int num = prob_.num(); + const int dim = prob_.count() / num; + const int spatial_dim = prob_.height() * prob_.width(); + const int nthreads = num * spatial_dim; + // Since this memory is not used for anything until it is overwritten + // on the backward pass, we use it here to avoid having to allocate new GPU + // memory to accumulate intermediate results in the kernel. + Dtype* loss_data = bottom[0]->mutable_gpu_diff(); + // Similarly, this memory is never used elsewhere, and thus we can use it + // to avoid having to allocate additional GPU memory. + Dtype* counts = prob_.mutable_gpu_diff(); + // NOLINT_NEXT_LINE(whitespace/operators) + SoftmaxLossForwardGPU<<>>(nthreads, prob_data, label, loss_data, + num, dim, spatial_dim, has_ignore_label_, ignore_label_, counts); + Dtype loss; + caffe_gpu_asum(nthreads, loss_data, &loss); + if (normalize_) { + Dtype count; + caffe_gpu_asum(nthreads, counts, &count); + loss /= count; + } else { + loss /= num; + } + top[0]->mutable_cpu_data()[0] = loss; + if (top.size() == 2) { + top[1]->ShareData(prob_); + } +} + +template +__global__ void SoftmaxLossBackwardGPU(const int nthreads, const Dtype* top, + const Dtype* label, Dtype* bottom_diff, const int num, const int dim, + const int spatial_dim, const bool has_ignore_label_, + const int ignore_label_, Dtype* counts) { + const int channels = dim / spatial_dim; + + CUDA_KERNEL_LOOP(index, nthreads) { + const int n = index / spatial_dim; + const int s = index % spatial_dim; + const int label_value = static_cast(label[n * spatial_dim + s]); + + if (has_ignore_label_ && label_value == ignore_label_) { + for (int c = 0; c < channels; ++c) { + bottom_diff[n * dim + c * spatial_dim + s] = 0; + } + counts[index] = 0; + } else { + bottom_diff[n * dim + label_value * spatial_dim + s] -= 1; + counts[index] = 1; + } + } +} + +template +void SoftmaxWithLossLayer::Backward_gpu(const vector*>& top, + const vector& propagate_down, const vector*>& bottom) { + if (propagate_down[1]) { + LOG(FATAL) << this->type() + << " Layer cannot backpropagate to label inputs."; + } + if (propagate_down[0]) { + Dtype* bottom_diff = bottom[0]->mutable_gpu_diff(); + const Dtype* prob_data = prob_.gpu_data(); + const Dtype* top_data = top[0]->gpu_data(); + caffe_gpu_memcpy(prob_.count() * sizeof(Dtype), prob_data, bottom_diff); + const Dtype* label = bottom[1]->gpu_data(); + const int num = prob_.num(); + const int dim = prob_.count() / num; + const int spatial_dim = prob_.height() * prob_.width(); + const int nthreads = num * spatial_dim; + // Since this memory is never used for anything else, + // we use to to avoid allocating new GPU memory. + Dtype* counts = prob_.mutable_gpu_diff(); + // NOLINT_NEXT_LINE(whitespace/operators) + SoftmaxLossBackwardGPU<<>>(nthreads, top_data, label, bottom_diff, + num, dim, spatial_dim, has_ignore_label_, ignore_label_, counts); + const Dtype loss_weight = top[0]->cpu_diff()[0]; + if (normalize_) { + Dtype count; + caffe_gpu_asum(nthreads, counts, &count); + caffe_gpu_scal(prob_.count(), loss_weight / count, bottom_diff); + } else { + caffe_gpu_scal(prob_.count(), loss_weight / num, bottom_diff); + } + } +} + +INSTANTIATE_LAYER_GPU_FUNCS(SoftmaxWithLossLayer); + +} // namespace caffe From 67c727a70f1a17c0de80cf1b08ba434499583ac3 Mon Sep 17 00:00:00 2001 From: manuele Date: Fri, 7 Nov 2014 20:01:33 +0100 Subject: [PATCH 288/798] Added opencv vector to memory data layer with tests --- include/caffe/data_layers.hpp | 2 ++ include/caffe/data_transformer.hpp | 13 +++++++ src/caffe/data_transformer.cpp | 20 +++++++++++ src/caffe/layers/memory_data_layer.cpp | 24 +++++++++++++ src/caffe/test/test_memory_data_layer.cpp | 43 ++++++++++++++++++++++- 5 files changed, 101 insertions(+), 1 deletion(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index cdf2d18bb60..b5449b33034 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -260,6 +260,8 @@ class MemoryDataLayer : public BaseDataLayer { virtual inline int ExactNumTopBlobs() const { return 2; } virtual void AddDatumVector(const vector& datum_vector); + virtual void AddMatVector(const vector& mat_vector, + const vector& labels); // Reset should accept const pointers, but can't, because the memory // will be given to Blob, which is mutable diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 0cfb5dcc7a3..c5d7a229fd4 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -50,6 +50,19 @@ class DataTransformer { void Transform(const vector & datum_vector, Blob* transformed_blob); + /** + * @brief Applies the transformation defined in the data layer's + * transform_param block to a vector of Mat. + * + * @param mat_vector + * A vector of Mat containing the data to be transformed. + * @param transformed_blob + * This is destination blob. It can be part of top blob's data if + * set_cpu_data() is used. See memory_layer.cpp for an example. + */ + void Transform(const vector & mat_vector, + Blob* transformed_blob); + /** * @brief Applies the transformation defined in the data layer's * transform_param block to a cv::Mat diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 3d2c78f8ec2..3b4fd120bff 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -173,6 +173,26 @@ void DataTransformer::Transform(const vector & datum_vector, } } +template +void DataTransformer::Transform(const vector & mat_vector, + Blob* transformed_blob) { + const int mat_num = mat_vector.size(); + const int num = transformed_blob->num(); + const int channels = transformed_blob->channels(); + const int height = transformed_blob->height(); + const int width = transformed_blob->width(); + + CHECK_GT(mat_num, 0) << "There is no MAT to add"; + CHECK_LE(mat_num, num) << + "The size of mat_vector must be smaller than transformed_blob->num()"; + Blob uni_blob(1, channels, height, width); + for (int item_id = 0; item_id < mat_num; ++item_id) { + int offset = transformed_blob->offset(item_id); + uni_blob.set_cpu_data(transformed_blob->mutable_cpu_data() + offset); + Transform(mat_vector[item_id], &uni_blob); + } +} + template void DataTransformer::Transform(const cv::Mat& cv_img, Blob* transformed_blob) { diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 3272b66ac55..67990f3cb93 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -50,6 +50,30 @@ void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { has_new_data_ = true; } +template +void MemoryDataLayer::AddMatVector(const vector& mat_vector, + const vector& labels) { + CHECK(!has_new_data_) << + "Can't add Mat when earlier ones haven't been consumed" + << " by the upper layers"; + size_t num = mat_vector.size(); + CHECK_GT(num, 0) << "There is no mat to add"; + CHECK_LE(num, batch_size_) << + "The number of added mat must be no greater than the batch size"; + + // Apply data transformations (mirror, scale, crop...) + this->data_transformer_.Transform(mat_vector, &added_data_); + // Copy Labels + Dtype* top_label = added_label_.mutable_cpu_data(); + for (int item_id = 0; item_id < num; ++item_id) { + top_label[item_id] = labels[item_id]; + } + // num_images == batch_size_ + Dtype* top_data = added_data_.mutable_cpu_data(); + Reset(top_data, top_label, batch_size_); + has_new_data_ = true; +} + template void MemoryDataLayer::Reset(Dtype* data, Dtype* labels, int n) { CHECK(data); diff --git a/src/caffe/test/test_memory_data_layer.cpp b/src/caffe/test/test_memory_data_layer.cpp index 497ab0d15e7..72b2759f2c2 100644 --- a/src/caffe/test/test_memory_data_layer.cpp +++ b/src/caffe/test/test_memory_data_layer.cpp @@ -127,7 +127,6 @@ TYPED_TEST(MemoryDataLayerTest, AddDatumVectorDefaultTransform) { const size_t count = this->channels_ * this->height_ * this->width_; size_t pixel_index = 0; for (int i = 0; i < this->batch_size_; ++i) { - LOG(ERROR) << "i " << i; datum_vector[i].set_channels(this->channels_); datum_vector[i].set_height(this->height_); datum_vector[i].set_width(this->width_); @@ -164,4 +163,46 @@ TYPED_TEST(MemoryDataLayerTest, AddDatumVectorDefaultTransform) { } } +TYPED_TEST(MemoryDataLayerTest, AddMatVectorDefaultTransform) { + typedef typename TypeParam::Dtype Dtype; + + LayerParameter param; + MemoryDataParameter* memory_data_param = param.mutable_memory_data_param(); + memory_data_param->set_batch_size(this->batch_size_); + memory_data_param->set_channels(this->channels_); + memory_data_param->set_height(this->height_); + memory_data_param->set_width(this->width_); + MemoryDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + vector mat_vector(this->batch_size_); + vector label_vector(this->batch_size_); + for (int i = 0; i < this->batch_size_; ++i) { + mat_vector[i] = cv::Mat(this->height_, this->width_, CV_8UC4); + label_vector[i] = i; + cv::randu(mat_vector[i], cv::Scalar::all(0), cv::Scalar::all(255)); + } + layer.AddMatVector(mat_vector, label_vector); + int data_index; + const size_t count = this->channels_ * this->height_ * this->width_; + for (int iter = 0; iter < 5; ++iter) { + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); + const Dtype* data = this->data_blob_->cpu_data(); + for (int i = 0; i < this->batch_size_; ++i) { + EXPECT_EQ(i, this->label_blob_->cpu_data()[i]); + for (int h = 0; h < this->height_; ++h) { + const unsigned char* ptr_mat = mat_vector[i].ptr(h); + int index = 0; + for (int w = 0; w < this->width_; ++w) { + for (int c = 0; c < this->channels_; ++c) { + data_index = (i*count) + (c * this->height_ + h) * this->width_ + w; + Dtype pixel = static_cast(ptr_mat[index++]); + EXPECT_EQ(static_cast(pixel), + data[data_index]); + } + } + } + } + } +} + } // namespace caffe From cedefd77625db978623fcf00ecc32d899eed954b Mon Sep 17 00:00:00 2001 From: manuele Date: Mon, 10 Nov 2014 19:24:02 +0100 Subject: [PATCH 289/798] MemoryDataLayer now accepts dynamic batch_size --- include/caffe/data_layers.hpp | 1 + src/caffe/layers/memory_data_layer.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index b5449b33034..117b1b5bb9a 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -284,6 +284,7 @@ class MemoryDataLayer : public BaseDataLayer { Blob added_data_; Blob added_label_; bool has_new_data_; + bool needs_reshape_; }; /** diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 67990f3cb93..f36eb6f85ed 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -32,7 +32,15 @@ void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { CHECK(!has_new_data_) << "Can't add Datum when earlier ones haven't been consumed" << " by the upper layers"; + size_t num = datum_vector.size(); + if (batch_size_ != num) { + needs_reshape_ = true; + batch_size_ = num; + added_data_.Reshape(batch_size_, channels_, height_, width_); + added_label_.Reshape(batch_size_, 1, 1, 1); + } + CHECK_GT(num, 0) << "There is no datum to add"; CHECK_LE(num, batch_size_) << "The number of added datum must be no greater than the batch size"; @@ -53,10 +61,22 @@ void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { template void MemoryDataLayer::AddMatVector(const vector& mat_vector, const vector& labels) { + CHECK(!has_new_data_) << "Can't add Mat when earlier ones haven't been consumed" << " by the upper layers"; + + CHECK_EQ(mat_vector.size(), labels.size()) << + "vector of labels and vector of mats need to be of the same size"; + size_t num = mat_vector.size(); + if (batch_size_ != num) { + needs_reshape_ = true; + batch_size_ = num; + added_data_.Reshape(batch_size_, channels_, height_, width_); + added_label_.Reshape(batch_size_, 1, 1, 1); + } + CHECK_GT(num, 0) << "There is no mat to add"; CHECK_LE(num, batch_size_) << "The number of added mat must be no greater than the batch size"; @@ -89,10 +109,15 @@ template void MemoryDataLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { CHECK(data_) << "MemoryDataLayer needs to be initalized by calling Reset"; + if (needs_reshape_) { + top[0]->Reshape(batch_size_, channels_, height_, width_); + top[1]->Reshape(batch_size_, 1, 1, 1); + } top[0]->set_cpu_data(data_ + pos_ * size_); top[1]->set_cpu_data(labels_ + pos_); pos_ = (pos_ + batch_size_) % n_; has_new_data_ = false; + needs_reshape_ = false; } INSTANTIATE_CLASS(MemoryDataLayer); From eb4ca169b53e53b1b288920b2bae9db0c59b4ec2 Mon Sep 17 00:00:00 2001 From: manuele Date: Tue, 9 Dec 2014 15:12:28 +0100 Subject: [PATCH 290/798] MemoryDataLayer now correctly consumes batch_size elements --- include/caffe/data_layers.hpp | 1 + include/caffe/data_transformer.hpp | 3 +- src/caffe/data_transformer.cpp | 10 +- src/caffe/layers/memory_data_layer.cpp | 61 ++++++------ src/caffe/test/test_memory_data_layer.cpp | 114 +++++++++++++++++++--- 5 files changed, 140 insertions(+), 49 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index 117b1b5bb9a..e8c6eecf0ed 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -266,6 +266,7 @@ class MemoryDataLayer : public BaseDataLayer { // Reset should accept const pointers, but can't, because the memory // will be given to Blob, which is mutable void Reset(Dtype* data, Dtype* label, int n); + void ChangeBatchSize(int new_size); int batch_size() { return batch_size_; } int channels() { return channels_; } diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index c5d7a229fd4..95062d4529d 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -60,9 +60,10 @@ class DataTransformer { * This is destination blob. It can be part of top blob's data if * set_cpu_data() is used. See memory_layer.cpp for an example. */ +#ifndef OSX void Transform(const vector & mat_vector, Blob* transformed_blob); - +#endif /** * @brief Applies the transformation defined in the data layer's * transform_param block to a cv::Mat diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 3b4fd120bff..3e11085e928 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -163,8 +163,8 @@ void DataTransformer::Transform(const vector & datum_vector, const int width = transformed_blob->width(); CHECK_GT(datum_num, 0) << "There is no datum to add"; - CHECK_LE(datum_num, num) << - "The size of datum_vector must be smaller than transformed_blob->num()"; + CHECK_EQ(datum_num, num) << + "The size of datum_vector must be equals to transformed_blob->num()"; Blob uni_blob(1, channels, height, width); for (int item_id = 0; item_id < datum_num; ++item_id) { int offset = transformed_blob->offset(item_id); @@ -173,6 +173,7 @@ void DataTransformer::Transform(const vector & datum_vector, } } +#ifndef OSX template void DataTransformer::Transform(const vector & mat_vector, Blob* transformed_blob) { @@ -183,8 +184,8 @@ void DataTransformer::Transform(const vector & mat_vector, const int width = transformed_blob->width(); CHECK_GT(mat_num, 0) << "There is no MAT to add"; - CHECK_LE(mat_num, num) << - "The size of mat_vector must be smaller than transformed_blob->num()"; + CHECK_EQ(mat_num, num) << + "The size of mat_vector must be equals to transformed_blob->num()"; Blob uni_blob(1, channels, height, width); for (int item_id = 0; item_id < mat_num; ++item_id) { int offset = transformed_blob->offset(item_id); @@ -192,6 +193,7 @@ void DataTransformer::Transform(const vector & mat_vector, Transform(mat_vector[item_id], &uni_blob); } } +#endif template void DataTransformer::Transform(const cv::Mat& cv_img, diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index f36eb6f85ed..214f9d865bc 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -23,6 +23,7 @@ void MemoryDataLayer::DataLayerSetUp(const vector*>& bottom, added_label_.Reshape(batch_size_, 1, 1, 1); data_ = NULL; labels_ = NULL; + needs_reshape_ = false; added_data_.cpu_data(); added_label_.cpu_data(); } @@ -32,19 +33,14 @@ void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { CHECK(!has_new_data_) << "Can't add Datum when earlier ones haven't been consumed" << " by the upper layers"; - size_t num = datum_vector.size(); - if (batch_size_ != num) { - needs_reshape_ = true; - batch_size_ = num; - added_data_.Reshape(batch_size_, channels_, height_, width_); - added_label_.Reshape(batch_size_, 1, 1, 1); - } - CHECK_GT(num, 0) << "There is no datum to add"; - CHECK_LE(num, batch_size_) << - "The number of added datum must be no greater than the batch size"; - + CHECK_LE(num % batch_size_, 0) << + "The number of added datum must be multiple of the batch size"; + if (num > batch_size_) { + added_data_.Reshape(num, channels_, height_, width_); + added_label_.Reshape(num, 1, 1, 1); + } // Apply data transformations (mirror, scale, crop...) this->data_transformer_.Transform(datum_vector, &added_data_); // Copy Labels @@ -54,33 +50,24 @@ void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { } // num_images == batch_size_ Dtype* top_data = added_data_.mutable_cpu_data(); - Reset(top_data, top_label, batch_size_); + Reset(top_data, top_label, num); has_new_data_ = true; } template void MemoryDataLayer::AddMatVector(const vector& mat_vector, const vector& labels) { - + size_t num = mat_vector.size(); CHECK(!has_new_data_) << "Can't add Mat when earlier ones haven't been consumed" << " by the upper layers"; - - CHECK_EQ(mat_vector.size(), labels.size()) << - "vector of labels and vector of mats need to be of the same size"; - - size_t num = mat_vector.size(); - if (batch_size_ != num) { - needs_reshape_ = true; - batch_size_ = num; - added_data_.Reshape(batch_size_, channels_, height_, width_); - added_label_.Reshape(batch_size_, 1, 1, 1); - } - + CHECK_LE(num % batch_size_, 0) << + "The number of added datum must be multiple of the batch size"; CHECK_GT(num, 0) << "There is no mat to add"; - CHECK_LE(num, batch_size_) << - "The number of added mat must be no greater than the batch size"; - + if (num > batch_size_) { + added_data_.Reshape(num, channels_, height_, width_); + added_label_.Reshape(num, 1, 1, 1); + } // Apply data transformations (mirror, scale, crop...) this->data_transformer_.Transform(mat_vector, &added_data_); // Copy Labels @@ -90,7 +77,7 @@ void MemoryDataLayer::AddMatVector(const vector& mat_vector, } // num_images == batch_size_ Dtype* top_data = added_data_.mutable_cpu_data(); - Reset(top_data, top_label, batch_size_); + Reset(top_data, top_label, num); has_new_data_ = true; } @@ -105,6 +92,17 @@ void MemoryDataLayer::Reset(Dtype* data, Dtype* labels, int n) { pos_ = 0; } +template +void MemoryDataLayer::ChangeBatchSize(int new_size) { + CHECK(!has_new_data_) << + "Can't change batch_size before all data haven't been consumed" + << " by the upper layers"; + batch_size_ = new_size; + added_data_.Reshape(batch_size_, channels_, height_, width_); + added_label_.Reshape(batch_size_, 1, 1, 1); + needs_reshape_ = true; +} + template void MemoryDataLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { @@ -112,12 +110,13 @@ void MemoryDataLayer::Forward_cpu(const vector*>& bottom, if (needs_reshape_) { top[0]->Reshape(batch_size_, channels_, height_, width_); top[1]->Reshape(batch_size_, 1, 1, 1); + needs_reshape_ = false; } top[0]->set_cpu_data(data_ + pos_ * size_); top[1]->set_cpu_data(labels_ + pos_); pos_ = (pos_ + batch_size_) % n_; - has_new_data_ = false; - needs_reshape_ = false; + if (pos_ == 0) + has_new_data_ = false; } INSTANTIATE_CLASS(MemoryDataLayer); diff --git a/src/caffe/test/test_memory_data_layer.cpp b/src/caffe/test/test_memory_data_layer.cpp index 72b2759f2c2..bc6c9b43eda 100644 --- a/src/caffe/test/test_memory_data_layer.cpp +++ b/src/caffe/test/test_memory_data_layer.cpp @@ -122,11 +122,13 @@ TYPED_TEST(MemoryDataLayerTest, AddDatumVectorDefaultTransform) { memory_data_param->set_width(this->width_); MemoryDataLayer layer(param); layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); - - vector datum_vector(this->batch_size_); + // We add batch_size*num_iter items, then for each iteration + // we forward batch_size elements + int num_iter = 5; + vector datum_vector(this->batch_size_ * num_iter); const size_t count = this->channels_ * this->height_ * this->width_; size_t pixel_index = 0; - for (int i = 0; i < this->batch_size_; ++i) { + for (int i = 0; i < this->batch_size_ * num_iter; ++i) { datum_vector[i].set_channels(this->channels_); datum_vector[i].set_height(this->height_); datum_vector[i].set_width(this->width_); @@ -137,18 +139,18 @@ TYPED_TEST(MemoryDataLayerTest, AddDatumVectorDefaultTransform) { } datum_vector[i].set_data(&(pixels[0]), count); } - layer.AddDatumVector(datum_vector); int data_index; // Go through the data 5 times - for (int iter = 0; iter < 5; ++iter) { + for (int iter = 0; iter < num_iter; ++iter) { + int offset = this->batch_size_ * iter; layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* data = this->data_blob_->cpu_data(); size_t index = 0; for (int i = 0; i < this->batch_size_; ++i) { - const string& data_string = datum_vector[i].data(); - EXPECT_EQ(i, this->label_blob_->cpu_data()[i]); + const string& data_string = datum_vector[offset + i].data(); + EXPECT_EQ(offset + i, this->label_blob_->cpu_data()[i]); for (int c = 0; c < this->channels_; ++c) { for (int h = 0; h < this->height_; ++h) { for (int w = 0; w < this->width_; ++w) { @@ -165,7 +167,52 @@ TYPED_TEST(MemoryDataLayerTest, AddDatumVectorDefaultTransform) { TYPED_TEST(MemoryDataLayerTest, AddMatVectorDefaultTransform) { typedef typename TypeParam::Dtype Dtype; + LayerParameter param; + MemoryDataParameter* memory_data_param = param.mutable_memory_data_param(); + memory_data_param->set_batch_size(this->batch_size_); + memory_data_param->set_channels(this->channels_); + memory_data_param->set_height(this->height_); + memory_data_param->set_width(this->width_); + MemoryDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + // We add batch_size*num_iter items, then for each iteration + // we forward batch_size elements + int num_iter = 5; + vector mat_vector(this->batch_size_ * num_iter); + vector label_vector(this->batch_size_ * num_iter); + for (int i = 0; i < this->batch_size_*num_iter; ++i) { + mat_vector[i] = cv::Mat(this->height_, this->width_, CV_8UC4); + label_vector[i] = i; + cv::randu(mat_vector[i], cv::Scalar::all(0), cv::Scalar::all(255)); + } + layer.AddMatVector(mat_vector, label_vector); + int data_index; + const size_t count = this->channels_ * this->height_ * this->width_; + for (int iter = 0; iter < num_iter; ++iter) { + int offset = this->batch_size_ * iter; + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); + const Dtype* data = this->data_blob_->cpu_data(); + for (int i = 0; i < this->batch_size_; ++i) { + EXPECT_EQ(offset + i, this->label_blob_->cpu_data()[i]); + for (int h = 0; h < this->height_; ++h) { + const unsigned char* ptr_mat = mat_vector[offset + i].ptr(h); + int index = 0; + for (int w = 0; w < this->width_; ++w) { + for (int c = 0; c < this->channels_; ++c) { + data_index = (i*count) + (c * this->height_ + h) * this->width_ + w; + Dtype pixel = static_cast(ptr_mat[index++]); + EXPECT_EQ(static_cast(pixel), + data[data_index]); + } + } + } + } + } +} + +TYPED_TEST(MemoryDataLayerTest, TestChangeBatchSize) { + typedef typename TypeParam::Dtype Dtype; LayerParameter param; MemoryDataParameter* memory_data_param = param.mutable_memory_data_param(); memory_data_param->set_batch_size(this->batch_size_); @@ -174,23 +221,64 @@ TYPED_TEST(MemoryDataLayerTest, AddMatVectorDefaultTransform) { memory_data_param->set_width(this->width_); MemoryDataLayer layer(param); layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); - vector mat_vector(this->batch_size_); - vector label_vector(this->batch_size_); - for (int i = 0; i < this->batch_size_; ++i) { + // first add data as usual + int num_iter = 5; + vector mat_vector(this->batch_size_ * num_iter); + vector label_vector(this->batch_size_ * num_iter); + for (int i = 0; i < this->batch_size_*num_iter; ++i) { mat_vector[i] = cv::Mat(this->height_, this->width_, CV_8UC4); label_vector[i] = i; cv::randu(mat_vector[i], cv::Scalar::all(0), cv::Scalar::all(255)); } layer.AddMatVector(mat_vector, label_vector); + // then consume the data int data_index; const size_t count = this->channels_ * this->height_ * this->width_; - for (int iter = 0; iter < 5; ++iter) { + for (int iter = 0; iter < num_iter; ++iter) { + int offset = this->batch_size_ * iter; layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); const Dtype* data = this->data_blob_->cpu_data(); for (int i = 0; i < this->batch_size_; ++i) { - EXPECT_EQ(i, this->label_blob_->cpu_data()[i]); + EXPECT_EQ(offset + i, this->label_blob_->cpu_data()[i]); + for (int h = 0; h < this->height_; ++h) { + const unsigned char* ptr_mat = mat_vector[offset + i].ptr(h); + int index = 0; + for (int w = 0; w < this->width_; ++w) { + for (int c = 0; c < this->channels_; ++c) { + data_index = (i*count) + (c * this->height_ + h) * this->width_ + w; + Dtype pixel = static_cast(ptr_mat[index++]); + EXPECT_EQ(static_cast(pixel), + data[data_index]); + } + } + } + } + } + // and then add new data with different batch_size + int new_batch_size = 16; + layer.ChangeBatchSize(new_batch_size); + mat_vector.clear(); + mat_vector.resize(new_batch_size * num_iter); + label_vector.clear(); + label_vector.resize(new_batch_size * num_iter); + for (int i = 0; i < new_batch_size*num_iter; ++i) { + mat_vector[i] = cv::Mat(this->height_, this->width_, CV_8UC4); + label_vector[i] = i; + cv::randu(mat_vector[i], cv::Scalar::all(0), cv::Scalar::all(255)); + } + layer.AddMatVector(mat_vector, label_vector); + + // finally consume new data and check if everything is fine + for (int iter = 0; iter < num_iter; ++iter) { + int offset = new_batch_size * iter; + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); + EXPECT_EQ(new_batch_size, this->blob_top_vec_[0]->num()); + EXPECT_EQ(new_batch_size, this->blob_top_vec_[1]->num()); + const Dtype* data = this->data_blob_->cpu_data(); + for (int i = 0; i < new_batch_size; ++i) { + EXPECT_EQ(offset + i, this->label_blob_->cpu_data()[i]); for (int h = 0; h < this->height_; ++h) { - const unsigned char* ptr_mat = mat_vector[i].ptr(h); + const unsigned char* ptr_mat = mat_vector[offset + i].ptr(h); int index = 0; for (int w = 0; w < this->width_; ++w) { for (int c = 0; c < this->channels_; ++c) { From 4901f830c3b90f77f9bd699930f2b9830cbc3b11 Mon Sep 17 00:00:00 2001 From: manuele Date: Thu, 8 Jan 2015 19:26:20 +0100 Subject: [PATCH 291/798] small fixes --- src/caffe/layers/memory_data_layer.cpp | 16 ++++++---------- src/caffe/test/test_memory_data_layer.cpp | 6 ++---- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 214f9d865bc..73b9f49115a 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -35,12 +35,10 @@ void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { << " by the upper layers"; size_t num = datum_vector.size(); CHECK_GT(num, 0) << "There is no datum to add"; - CHECK_LE(num % batch_size_, 0) << + CHECK_EQ(num % batch_size_, 0) << "The number of added datum must be multiple of the batch size"; - if (num > batch_size_) { - added_data_.Reshape(num, channels_, height_, width_); - added_label_.Reshape(num, 1, 1, 1); - } + added_data_.Reshape(num, channels_, height_, width_); + added_label_.Reshape(num, 1, 1, 1); // Apply data transformations (mirror, scale, crop...) this->data_transformer_.Transform(datum_vector, &added_data_); // Copy Labels @@ -61,13 +59,11 @@ void MemoryDataLayer::AddMatVector(const vector& mat_vector, CHECK(!has_new_data_) << "Can't add Mat when earlier ones haven't been consumed" << " by the upper layers"; - CHECK_LE(num % batch_size_, 0) << + CHECK_EQ(num % batch_size_, 0) << "The number of added datum must be multiple of the batch size"; CHECK_GT(num, 0) << "There is no mat to add"; - if (num > batch_size_) { - added_data_.Reshape(num, channels_, height_, width_); - added_label_.Reshape(num, 1, 1, 1); - } + added_data_.Reshape(num, channels_, height_, width_); + added_label_.Reshape(num, 1, 1, 1); // Apply data transformations (mirror, scale, crop...) this->data_transformer_.Transform(mat_vector, &added_data_); // Copy Labels diff --git a/src/caffe/test/test_memory_data_layer.cpp b/src/caffe/test/test_memory_data_layer.cpp index bc6c9b43eda..d4d57102516 100644 --- a/src/caffe/test/test_memory_data_layer.cpp +++ b/src/caffe/test/test_memory_data_layer.cpp @@ -247,8 +247,7 @@ TYPED_TEST(MemoryDataLayerTest, TestChangeBatchSize) { for (int c = 0; c < this->channels_; ++c) { data_index = (i*count) + (c * this->height_ + h) * this->width_ + w; Dtype pixel = static_cast(ptr_mat[index++]); - EXPECT_EQ(static_cast(pixel), - data[data_index]); + EXPECT_EQ(static_cast(pixel), data[data_index]); } } } @@ -284,8 +283,7 @@ TYPED_TEST(MemoryDataLayerTest, TestChangeBatchSize) { for (int c = 0; c < this->channels_; ++c) { data_index = (i*count) + (c * this->height_ + h) * this->width_ + w; Dtype pixel = static_cast(ptr_mat[index++]); - EXPECT_EQ(static_cast(pixel), - data[data_index]); + EXPECT_EQ(static_cast(pixel), data[data_index]); } } } From abe0fa2602ca1c185eff0580f4f317d970421631 Mon Sep 17 00:00:00 2001 From: manuele Date: Mon, 12 Jan 2015 12:22:49 +0100 Subject: [PATCH 292/798] removed needs_reshape_ and ChangeBatchSize is now set_batch_size --- include/caffe/data_layers.hpp | 3 +-- src/caffe/layers/memory_data_layer.cpp | 11 +++-------- src/caffe/test/test_memory_data_layer.cpp | 4 ++-- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index e8c6eecf0ed..1542af7c327 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -266,7 +266,7 @@ class MemoryDataLayer : public BaseDataLayer { // Reset should accept const pointers, but can't, because the memory // will be given to Blob, which is mutable void Reset(Dtype* data, Dtype* label, int n); - void ChangeBatchSize(int new_size); + void set_batch_size(int new_size); int batch_size() { return batch_size_; } int channels() { return channels_; } @@ -285,7 +285,6 @@ class MemoryDataLayer : public BaseDataLayer { Blob added_data_; Blob added_label_; bool has_new_data_; - bool needs_reshape_; }; /** diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 73b9f49115a..1669db393e0 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -23,7 +23,6 @@ void MemoryDataLayer::DataLayerSetUp(const vector*>& bottom, added_label_.Reshape(batch_size_, 1, 1, 1); data_ = NULL; labels_ = NULL; - needs_reshape_ = false; added_data_.cpu_data(); added_label_.cpu_data(); } @@ -89,25 +88,21 @@ void MemoryDataLayer::Reset(Dtype* data, Dtype* labels, int n) { } template -void MemoryDataLayer::ChangeBatchSize(int new_size) { +void MemoryDataLayer::set_batch_size(int new_size) { CHECK(!has_new_data_) << "Can't change batch_size before all data haven't been consumed" << " by the upper layers"; batch_size_ = new_size; added_data_.Reshape(batch_size_, channels_, height_, width_); added_label_.Reshape(batch_size_, 1, 1, 1); - needs_reshape_ = true; } template void MemoryDataLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { CHECK(data_) << "MemoryDataLayer needs to be initalized by calling Reset"; - if (needs_reshape_) { - top[0]->Reshape(batch_size_, channels_, height_, width_); - top[1]->Reshape(batch_size_, 1, 1, 1); - needs_reshape_ = false; - } + top[0]->Reshape(batch_size_, channels_, height_, width_); + top[1]->Reshape(batch_size_, 1, 1, 1); top[0]->set_cpu_data(data_ + pos_ * size_); top[1]->set_cpu_data(labels_ + pos_); pos_ = (pos_ + batch_size_) % n_; diff --git a/src/caffe/test/test_memory_data_layer.cpp b/src/caffe/test/test_memory_data_layer.cpp index d4d57102516..6a7bf045d23 100644 --- a/src/caffe/test/test_memory_data_layer.cpp +++ b/src/caffe/test/test_memory_data_layer.cpp @@ -211,7 +211,7 @@ TYPED_TEST(MemoryDataLayerTest, AddMatVectorDefaultTransform) { } } -TYPED_TEST(MemoryDataLayerTest, TestChangeBatchSize) { +TYPED_TEST(MemoryDataLayerTest, TestSetBatchSize) { typedef typename TypeParam::Dtype Dtype; LayerParameter param; MemoryDataParameter* memory_data_param = param.mutable_memory_data_param(); @@ -255,7 +255,7 @@ TYPED_TEST(MemoryDataLayerTest, TestChangeBatchSize) { } // and then add new data with different batch_size int new_batch_size = 16; - layer.ChangeBatchSize(new_batch_size); + layer.set_batch_size(new_batch_size); mat_vector.clear(); mat_vector.resize(new_batch_size * num_iter); label_vector.clear(); From a2fbea3c5ae1b2e9f1fec77c8450c10c33d5b29b Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 6 Feb 2015 21:37:54 -0800 Subject: [PATCH 293/798] groom #1416 - keep current `DataTransformer` check so that datums can be transformed into a blob incrementally - standardize check messages - include opencv where needed, drop unneeded OS X guards TODO these tests need to be de-duped --- include/caffe/data_transformer.hpp | 4 +--- src/caffe/data_transformer.cpp | 6 ++---- src/caffe/layers/memory_data_layer.cpp | 19 +++++++++---------- src/caffe/test/test_memory_data_layer.cpp | 2 ++ 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/include/caffe/data_transformer.hpp b/include/caffe/data_transformer.hpp index 95062d4529d..60696c96dcc 100644 --- a/include/caffe/data_transformer.hpp +++ b/include/caffe/data_transformer.hpp @@ -60,10 +60,8 @@ class DataTransformer { * This is destination blob. It can be part of top blob's data if * set_cpu_data() is used. See memory_layer.cpp for an example. */ -#ifndef OSX void Transform(const vector & mat_vector, Blob* transformed_blob); -#endif /** * @brief Applies the transformation defined in the data layer's * transform_param block to a cv::Mat @@ -92,7 +90,7 @@ class DataTransformer { protected: /** * @brief Generates a random integer from Uniform({0, 1, ..., n-1}). - * + * * @param n * The upperbound (exclusive) value of the random number. * @return diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 3e11085e928..c0ad72ee67d 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -163,8 +163,8 @@ void DataTransformer::Transform(const vector & datum_vector, const int width = transformed_blob->width(); CHECK_GT(datum_num, 0) << "There is no datum to add"; - CHECK_EQ(datum_num, num) << - "The size of datum_vector must be equals to transformed_blob->num()"; + CHECK_LE(datum_num, num) << + "The size of datum_vector must be no greater than transformed_blob->num()"; Blob uni_blob(1, channels, height, width); for (int item_id = 0; item_id < datum_num; ++item_id) { int offset = transformed_blob->offset(item_id); @@ -173,7 +173,6 @@ void DataTransformer::Transform(const vector & datum_vector, } } -#ifndef OSX template void DataTransformer::Transform(const vector & mat_vector, Blob* transformed_blob) { @@ -193,7 +192,6 @@ void DataTransformer::Transform(const vector & mat_vector, Transform(mat_vector[item_id], &uni_blob); } } -#endif template void DataTransformer::Transform(const cv::Mat& cv_img, diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 1669db393e0..7cb5eafab02 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -1,3 +1,5 @@ +#include + #include #include "caffe/data_layers.hpp" @@ -30,12 +32,11 @@ void MemoryDataLayer::DataLayerSetUp(const vector*>& bottom, template void MemoryDataLayer::AddDatumVector(const vector& datum_vector) { CHECK(!has_new_data_) << - "Can't add Datum when earlier ones haven't been consumed" - << " by the upper layers"; + "Can't add data until current data has been consumed."; size_t num = datum_vector.size(); - CHECK_GT(num, 0) << "There is no datum to add"; + CHECK_GT(num, 0) << "There is no datum to add."; CHECK_EQ(num % batch_size_, 0) << - "The number of added datum must be multiple of the batch size"; + "The added data must be a multiple of the batch size."; added_data_.Reshape(num, channels_, height_, width_); added_label_.Reshape(num, 1, 1, 1); // Apply data transformations (mirror, scale, crop...) @@ -56,11 +57,10 @@ void MemoryDataLayer::AddMatVector(const vector& mat_vector, const vector& labels) { size_t num = mat_vector.size(); CHECK(!has_new_data_) << - "Can't add Mat when earlier ones haven't been consumed" - << " by the upper layers"; - CHECK_EQ(num % batch_size_, 0) << - "The number of added datum must be multiple of the batch size"; + "Can't add mat until current data has been consumed."; CHECK_GT(num, 0) << "There is no mat to add"; + CHECK_EQ(num % batch_size_, 0) << + "The added data must be a multiple of the batch size."; added_data_.Reshape(num, channels_, height_, width_); added_label_.Reshape(num, 1, 1, 1); // Apply data transformations (mirror, scale, crop...) @@ -90,8 +90,7 @@ void MemoryDataLayer::Reset(Dtype* data, Dtype* labels, int n) { template void MemoryDataLayer::set_batch_size(int new_size) { CHECK(!has_new_data_) << - "Can't change batch_size before all data haven't been consumed" - << " by the upper layers"; + "Can't change batch_size until current data has been consumed."; batch_size_ = new_size; added_data_.Reshape(batch_size_, channels_, height_, width_); added_label_.Reshape(batch_size_, 1, 1, 1); diff --git a/src/caffe/test/test_memory_data_layer.cpp b/src/caffe/test/test_memory_data_layer.cpp index 6a7bf045d23..a79033f59f1 100644 --- a/src/caffe/test/test_memory_data_layer.cpp +++ b/src/caffe/test/test_memory_data_layer.cpp @@ -1,3 +1,5 @@ +#include + #include #include From d12101edb4dcd2cdb38a2b7f7dbc011ff8887d02 Mon Sep 17 00:00:00 2001 From: Dmitry Ulyanov Date: Fri, 6 Feb 2015 10:56:47 +0300 Subject: [PATCH 294/798] Allow using arrays with n_ * size_ > 2^31 uint64_t size_t --- include/caffe/data_layers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/caffe/data_layers.hpp b/include/caffe/data_layers.hpp index 1542af7c327..e0d5a8aca46 100644 --- a/include/caffe/data_layers.hpp +++ b/include/caffe/data_layers.hpp @@ -281,7 +281,7 @@ class MemoryDataLayer : public BaseDataLayer { Dtype* data_; Dtype* labels_; int n_; - int pos_; + size_t pos_; Blob added_data_; Blob added_label_; bool has_new_data_; From 56846e6dc2336c3856c98447dd89c20fc66d7faa Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 6 Feb 2015 23:12:33 -0800 Subject: [PATCH 295/798] HDF5_DATA + MEMORY_DATA refuse loudly to transform These layers are meant for generic inputs so they do not do transformations. As `transform_param` was pulled out of data layers' proto definitions for reuse, these layers silently ignored transformation parameters until now instead of signalling their refusal. --- src/caffe/layers/hdf5_data_layer.cpp | 3 +++ src/caffe/layers/memory_data_layer.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/caffe/layers/hdf5_data_layer.cpp b/src/caffe/layers/hdf5_data_layer.cpp index 77555211082..3d856ec3001 100644 --- a/src/caffe/layers/hdf5_data_layer.cpp +++ b/src/caffe/layers/hdf5_data_layer.cpp @@ -58,6 +58,9 @@ void HDF5DataLayer::LoadHDF5FileData(const char* filename) { template void HDF5DataLayer::LayerSetUp(const vector*>& bottom, const vector*>& top) { + // Refuse transformation parameters since HDF5 is totally generic. + CHECK(!this->layer_param_.has_transform_param()) << + this->type() << " does not transform data."; // Read the source to parse the filenames. const string& source = this->layer_param_.hdf5_data_param().source(); LOG(INFO) << "Loading list of HDF5 filenames from: " << source; diff --git a/src/caffe/layers/memory_data_layer.cpp b/src/caffe/layers/memory_data_layer.cpp index 7cb5eafab02..6f584de32d0 100644 --- a/src/caffe/layers/memory_data_layer.cpp +++ b/src/caffe/layers/memory_data_layer.cpp @@ -81,6 +81,9 @@ void MemoryDataLayer::Reset(Dtype* data, Dtype* labels, int n) { CHECK(data); CHECK(labels); CHECK_EQ(n % batch_size_, 0) << "n must be a multiple of batch size"; + // Refuse transformation parameters since a memory array is totally generic. + CHECK(!this->layer_param_.has_transform_param()) << + this->type() << " does not transform data."; data_ = data; labels_ = labels; n_ = n; From 8821c28aa9af399454584e90c9addce75e38b6d2 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 9 Feb 2015 18:08:50 -0800 Subject: [PATCH 296/798] Fixes for CuDNN layers: only destroy handles if setup --- include/caffe/common_layers.hpp | 3 ++- include/caffe/neuron_layers.hpp | 9 ++++++--- include/caffe/vision_layers.hpp | 6 ++++-- src/caffe/layers/cudnn_conv_layer.cpp | 5 +++++ src/caffe/layers/cudnn_pooling_layer.cpp | 4 ++++ src/caffe/layers/cudnn_relu_layer.cpp | 4 ++++ src/caffe/layers/cudnn_sigmoid_layer.cpp | 4 ++++ src/caffe/layers/cudnn_softmax_layer.cpp | 4 ++++ src/caffe/layers/cudnn_tanh_layer.cpp | 4 ++++ 9 files changed, 37 insertions(+), 6 deletions(-) diff --git a/include/caffe/common_layers.hpp b/include/caffe/common_layers.hpp index 3a5ccd2180e..c67822c3738 100644 --- a/include/caffe/common_layers.hpp +++ b/include/caffe/common_layers.hpp @@ -377,7 +377,7 @@ template class CuDNNSoftmaxLayer : public SoftmaxLayer { public: explicit CuDNNSoftmaxLayer(const LayerParameter& param) - : SoftmaxLayer(param) {} + : SoftmaxLayer(param), handles_setup_(false) {} virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); virtual void Reshape(const vector*>& bottom, @@ -390,6 +390,7 @@ class CuDNNSoftmaxLayer : public SoftmaxLayer { virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + bool handles_setup_; cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_; cudnnTensor4dDescriptor_t top_desc_; diff --git a/include/caffe/neuron_layers.hpp b/include/caffe/neuron_layers.hpp index b65d98435bc..46c84171b9c 100644 --- a/include/caffe/neuron_layers.hpp +++ b/include/caffe/neuron_layers.hpp @@ -417,7 +417,7 @@ template class CuDNNReLULayer : public ReLULayer { public: explicit CuDNNReLULayer(const LayerParameter& param) - : ReLULayer(param) {} + : ReLULayer(param), handles_setup_(false) {} virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); virtual void Reshape(const vector*>& bottom, @@ -430,6 +430,7 @@ class CuDNNReLULayer : public ReLULayer { virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + bool handles_setup_; cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_; cudnnTensor4dDescriptor_t top_desc_; @@ -499,7 +500,7 @@ template class CuDNNSigmoidLayer : public SigmoidLayer { public: explicit CuDNNSigmoidLayer(const LayerParameter& param) - : SigmoidLayer(param) {} + : SigmoidLayer(param), handles_setup_(false) {} virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); virtual void Reshape(const vector*>& bottom, @@ -512,6 +513,7 @@ class CuDNNSigmoidLayer : public SigmoidLayer { virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + bool handles_setup_; cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_; cudnnTensor4dDescriptor_t top_desc_; @@ -583,7 +585,7 @@ template class CuDNNTanHLayer : public TanHLayer { public: explicit CuDNNTanHLayer(const LayerParameter& param) - : TanHLayer(param) {} + : TanHLayer(param), handles_setup_(false) {} virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); virtual void Reshape(const vector*>& bottom, @@ -596,6 +598,7 @@ class CuDNNTanHLayer : public TanHLayer { virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + bool handles_setup_; cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_; cudnnTensor4dDescriptor_t top_desc_; diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 38e369c4092..6cb507a5780 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -230,7 +230,7 @@ template class CuDNNConvolutionLayer : public ConvolutionLayer { public: explicit CuDNNConvolutionLayer(const LayerParameter& param) - : ConvolutionLayer(param) {} + : ConvolutionLayer(param), handles_setup_(false) {} virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); virtual void Reshape(const vector*>& bottom, @@ -243,6 +243,7 @@ class CuDNNConvolutionLayer : public ConvolutionLayer { virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + bool handles_setup_; cudnnHandle_t* handle_; cudaStream_t* stream_; vector bottom_descs_, top_descs_; @@ -426,7 +427,7 @@ template class CuDNNPoolingLayer : public PoolingLayer { public: explicit CuDNNPoolingLayer(const LayerParameter& param) - : PoolingLayer(param) {} + : PoolingLayer(param), handles_setup_(false) {} virtual void LayerSetUp(const vector*>& bottom, const vector*>& top); virtual void Reshape(const vector*>& bottom, @@ -442,6 +443,7 @@ class CuDNNPoolingLayer : public PoolingLayer { virtual void Backward_gpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + bool handles_setup_; cudnnHandle_t handle_; cudnnTensor4dDescriptor_t bottom_desc_, top_desc_; cudnnPoolingDescriptor_t pooling_desc_; diff --git a/src/caffe/layers/cudnn_conv_layer.cpp b/src/caffe/layers/cudnn_conv_layer.cpp index f74a3dbb02f..4a69ca20d0a 100644 --- a/src/caffe/layers/cudnn_conv_layer.cpp +++ b/src/caffe/layers/cudnn_conv_layer.cpp @@ -58,6 +58,8 @@ void CuDNNConvolutionLayer::LayerSetUp( if (this->bias_term_) { cudnn::createTensor4dDesc(&bias_desc_); } + + handles_setup_ = true; } template @@ -98,6 +100,9 @@ void CuDNNConvolutionLayer::Reshape( template CuDNNConvolutionLayer::~CuDNNConvolutionLayer() { + // Check that handles have been setup before destroying. + if (!handles_setup_) { return; } + for (int i = 0; i < bottom_descs_.size(); i++) { cudnnDestroyTensor4dDescriptor(bottom_descs_[i]); cudnnDestroyTensor4dDescriptor(top_descs_[i]); diff --git a/src/caffe/layers/cudnn_pooling_layer.cpp b/src/caffe/layers/cudnn_pooling_layer.cpp index fc0222ac0e3..dd90195637b 100644 --- a/src/caffe/layers/cudnn_pooling_layer.cpp +++ b/src/caffe/layers/cudnn_pooling_layer.cpp @@ -22,6 +22,7 @@ void CuDNNPoolingLayer::LayerSetUp(const vector*>& bottom, cudnn::createPoolingDesc(&pooling_desc_, this->layer_param_.pooling_param().pool(), &mode_, this->kernel_h_, this->kernel_w_, this->stride_h_, this->stride_w_); + handles_setup_ = true; } template @@ -36,6 +37,9 @@ void CuDNNPoolingLayer::Reshape(const vector*>& bottom, template CuDNNPoolingLayer::~CuDNNPoolingLayer() { + // Check that handles have been setup before destroying. + if (!handles_setup_) { return; } + cudnnDestroyTensor4dDescriptor(bottom_desc_); cudnnDestroyTensor4dDescriptor(top_desc_); cudnnDestroyPoolingDescriptor(pooling_desc_); diff --git a/src/caffe/layers/cudnn_relu_layer.cpp b/src/caffe/layers/cudnn_relu_layer.cpp index 20f486f6bcf..0b8a6bc3248 100644 --- a/src/caffe/layers/cudnn_relu_layer.cpp +++ b/src/caffe/layers/cudnn_relu_layer.cpp @@ -15,6 +15,7 @@ void CuDNNReLULayer::LayerSetUp(const vector*>& bottom, CUDNN_CHECK(cudnnCreate(&handle_)); cudnn::createTensor4dDesc(&bottom_desc_); cudnn::createTensor4dDesc(&top_desc_); + handles_setup_ = true; } template @@ -31,6 +32,9 @@ void CuDNNReLULayer::Reshape(const vector*>& bottom, template CuDNNReLULayer::~CuDNNReLULayer() { + // Check that handles have been setup before destroying. + if (!handles_setup_) { return; } + cudnnDestroyTensor4dDescriptor(this->bottom_desc_); cudnnDestroyTensor4dDescriptor(this->top_desc_); cudnnDestroy(this->handle_); diff --git a/src/caffe/layers/cudnn_sigmoid_layer.cpp b/src/caffe/layers/cudnn_sigmoid_layer.cpp index a94c0040a28..67bd9c373b0 100644 --- a/src/caffe/layers/cudnn_sigmoid_layer.cpp +++ b/src/caffe/layers/cudnn_sigmoid_layer.cpp @@ -15,6 +15,7 @@ void CuDNNSigmoidLayer::LayerSetUp(const vector*>& bottom, CUDNN_CHECK(cudnnCreate(&handle_)); cudnn::createTensor4dDesc(&bottom_desc_); cudnn::createTensor4dDesc(&top_desc_); + handles_setup_ = true; } template @@ -31,6 +32,9 @@ void CuDNNSigmoidLayer::Reshape(const vector*>& bottom, template CuDNNSigmoidLayer::~CuDNNSigmoidLayer() { + // Check that handles have been setup before destroying. + if (!handles_setup_) { return; } + cudnnDestroyTensor4dDescriptor(this->bottom_desc_); cudnnDestroyTensor4dDescriptor(this->top_desc_); cudnnDestroy(this->handle_); diff --git a/src/caffe/layers/cudnn_softmax_layer.cpp b/src/caffe/layers/cudnn_softmax_layer.cpp index 1a0f406bf38..83a5b69a626 100644 --- a/src/caffe/layers/cudnn_softmax_layer.cpp +++ b/src/caffe/layers/cudnn_softmax_layer.cpp @@ -19,6 +19,7 @@ void CuDNNSoftmaxLayer::LayerSetUp(const vector*>& bottom, CUDNN_CHECK(cudnnCreate(&handle_)); cudnn::createTensor4dDesc(&bottom_desc_); cudnn::createTensor4dDesc(&top_desc_); + handles_setup_ = true; } template @@ -35,6 +36,9 @@ void CuDNNSoftmaxLayer::Reshape(const vector*>& bottom, template CuDNNSoftmaxLayer::~CuDNNSoftmaxLayer() { + // Check that handles have been setup before destroying. + if (!handles_setup_) { return; } + cudnnDestroyTensor4dDescriptor(bottom_desc_); cudnnDestroyTensor4dDescriptor(top_desc_); cudnnDestroy(handle_); diff --git a/src/caffe/layers/cudnn_tanh_layer.cpp b/src/caffe/layers/cudnn_tanh_layer.cpp index 39a3e14b3c8..b1d2b86384e 100644 --- a/src/caffe/layers/cudnn_tanh_layer.cpp +++ b/src/caffe/layers/cudnn_tanh_layer.cpp @@ -15,6 +15,7 @@ void CuDNNTanHLayer::LayerSetUp(const vector*>& bottom, CUDNN_CHECK(cudnnCreate(&handle_)); cudnn::createTensor4dDesc(&bottom_desc_); cudnn::createTensor4dDesc(&top_desc_); + handles_setup_ = true; } template @@ -31,6 +32,9 @@ void CuDNNTanHLayer::Reshape(const vector*>& bottom, template CuDNNTanHLayer::~CuDNNTanHLayer() { + // Check that handles have been setup before destroying. + if (!handles_setup_) { return; } + cudnnDestroyTensor4dDescriptor(this->bottom_desc_); cudnnDestroyTensor4dDescriptor(this->top_desc_); cudnnDestroy(this->handle_); From 852a3c5355ba5cb7f48781f72f0e4baabf0afbea Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Thu, 5 Feb 2015 14:04:35 -0800 Subject: [PATCH 297/798] SoftmaxWithLossLayer fix: takes exactly 2 bottom blobs (inherited from LossLayer) --- include/caffe/loss_layers.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 09a5c24dde5..ea52f56e0f3 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -696,9 +696,6 @@ class SoftmaxWithLossLayer : public LossLayer { const vector*>& top); virtual inline const char* type() const { return "SoftmaxWithLoss"; } - virtual inline int ExactNumBottomBlobs() const { return -1; } - virtual inline int MinBottomBlobs() const { return 2; } - virtual inline int MaxBottomBlobs() const { return 3; } virtual inline int ExactNumTopBlobs() const { return -1; } virtual inline int MinTopBlobs() const { return 1; } virtual inline int MaxTopBlobs() const { return 2; } From c15d1846969ab8338561489194d787676733caa7 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 6 Oct 2014 23:45:43 -0700 Subject: [PATCH 298/798] Blob: add scale_{data,diff} methods and tests --- include/caffe/blob.hpp | 5 +++ src/caffe/blob.cpp | 66 ++++++++++++++++++++++++++++++++++++ src/caffe/test/test_blob.cpp | 60 +++++++++++++++++++++++++++++++- 3 files changed, 130 insertions(+), 1 deletion(-) diff --git a/include/caffe/blob.hpp b/include/caffe/blob.hpp index d425e3857e3..42e4420408c 100644 --- a/include/caffe/blob.hpp +++ b/include/caffe/blob.hpp @@ -111,6 +111,11 @@ class Blob { /// @brief Compute the sum of squares (L2 norm squared) of the diff. Dtype sumsq_diff() const; + /// @brief Scale the blob data by a constant factor. + void scale_data(Dtype scale_factor); + /// @brief Scale the blob diff by a constant factor. + void scale_diff(Dtype scale_factor); + /** * @brief Set the data_ shared_ptr to point to the SyncedMemory holding the * data_ of Blob other -- useful in Layer&s which simply perform a copy diff --git a/src/caffe/blob.cpp b/src/caffe/blob.cpp index 3b72ce0c8d0..fbc1361a19d 100644 --- a/src/caffe/blob.cpp +++ b/src/caffe/blob.cpp @@ -279,6 +279,72 @@ Dtype Blob::sumsq_diff() const { return sumsq; } +template <> void Blob::scale_data(unsigned int scale_factor) { + NOT_IMPLEMENTED; +} + +template <> void Blob::scale_data(int scale_factor) { + NOT_IMPLEMENTED; +} + +template +void Blob::scale_data(Dtype scale_factor) { + Dtype* data; + if (!data_) { return; } + switch (data_->head()) { + case SyncedMemory::HEAD_AT_CPU: + data = mutable_cpu_data(); + caffe_scal(count_, scale_factor, data); + return; + case SyncedMemory::HEAD_AT_GPU: + case SyncedMemory::SYNCED: +#ifndef CPU_ONLY + data = mutable_gpu_data(); + caffe_gpu_scal(count_, scale_factor, data); + return; +#else + NO_GPU; +#endif + case SyncedMemory::UNINITIALIZED: + return; + default: + LOG(FATAL) << "Unknown SyncedMemory head state: " << data_->head(); + } +} + +template <> void Blob::scale_diff(unsigned int scale_factor) { + NOT_IMPLEMENTED; +} + +template <> void Blob::scale_diff(int scale_factor) { + NOT_IMPLEMENTED; +} + +template +void Blob::scale_diff(Dtype scale_factor) { + Dtype* diff; + if (!diff_) { return; } + switch (diff_->head()) { + case SyncedMemory::HEAD_AT_CPU: + diff = mutable_cpu_diff(); + caffe_scal(count_, scale_factor, diff); + return; + case SyncedMemory::HEAD_AT_GPU: + case SyncedMemory::SYNCED: +#ifndef CPU_ONLY + diff = mutable_gpu_diff(); + caffe_gpu_scal(count_, scale_factor, diff); + return; +#else + NO_GPU; +#endif + case SyncedMemory::UNINITIALIZED: + return; + default: + LOG(FATAL) << "Unknown SyncedMemory head state: " << diff_->head(); + } +} + template void Blob::CopyFrom(const Blob& source, bool copy_diff, bool reshape) { if (num_ != source.num() || channels_ != source.channels() || diff --git a/src/caffe/test/test_blob.cpp b/src/caffe/test/test_blob.cpp index c619ad19f11..84d84e8f444 100644 --- a/src/caffe/test/test_blob.cpp +++ b/src/caffe/test/test_blob.cpp @@ -120,7 +120,7 @@ TYPED_TEST(BlobMathTest, TestSumOfSquares) { TYPED_TEST(BlobMathTest, TestAsum) { typedef typename TypeParam::Dtype Dtype; - // Uninitialized Blob should have sum of squares == 0. + // Uninitialized Blob should have asum == 0. EXPECT_EQ(0, this->blob_->asum_data()); EXPECT_EQ(0, this->blob_->asum_diff()); FillerParameter filler_param; @@ -167,4 +167,62 @@ TYPED_TEST(BlobMathTest, TestAsum) { EXPECT_FLOAT_EQ(expected_asum * kDiffScaleFactor, this->blob_->asum_diff()); } +TYPED_TEST(BlobMathTest, TestScaleData) { + typedef typename TypeParam::Dtype Dtype; + + EXPECT_EQ(0, this->blob_->asum_data()); + EXPECT_EQ(0, this->blob_->asum_diff()); + FillerParameter filler_param; + filler_param.set_min(-3); + filler_param.set_max(3); + UniformFiller filler(filler_param); + filler.Fill(this->blob_); + const Dtype asum_before_scale = this->blob_->asum_data(); + // Do a mutable access on the current device, + // so that the asum computation is done on that device. + // (Otherwise, this would only check the CPU asum implementation.) + switch (TypeParam::device) { + case Caffe::CPU: + this->blob_->mutable_cpu_data(); + break; + case Caffe::GPU: + this->blob_->mutable_gpu_data(); + break; + default: + LOG(FATAL) << "Unknown device: " << TypeParam::device; + } + const Dtype kDataScaleFactor = 3; + this->blob_->scale_data(kDataScaleFactor); + EXPECT_FLOAT_EQ(asum_before_scale * kDataScaleFactor, + this->blob_->asum_data()); + EXPECT_EQ(0, this->blob_->asum_diff()); + + // Check scale_diff too. + const Dtype kDataToDiffScaleFactor = 7; + const Dtype* data = this->blob_->cpu_data(); + caffe_cpu_scale(this->blob_->count(), kDataToDiffScaleFactor, data, + this->blob_->mutable_cpu_diff()); + EXPECT_FLOAT_EQ(asum_before_scale * kDataScaleFactor, + this->blob_->asum_data()); + const Dtype diff_asum_before_scale = this->blob_->asum_diff(); + EXPECT_FLOAT_EQ(asum_before_scale * kDataScaleFactor * kDataToDiffScaleFactor, + diff_asum_before_scale); + switch (TypeParam::device) { + case Caffe::CPU: + this->blob_->mutable_cpu_diff(); + break; + case Caffe::GPU: + this->blob_->mutable_gpu_diff(); + break; + default: + LOG(FATAL) << "Unknown device: " << TypeParam::device; + } + const Dtype kDiffScaleFactor = 3; + this->blob_->scale_diff(kDiffScaleFactor); + EXPECT_FLOAT_EQ(asum_before_scale * kDataScaleFactor, + this->blob_->asum_data()); + EXPECT_FLOAT_EQ(diff_asum_before_scale * kDiffScaleFactor, + this->blob_->asum_diff()); +} + } // namespace caffe From e2358512dd36548c0080b0f381477418134b480f Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 19 Jan 2015 14:49:39 -0800 Subject: [PATCH 299/798] add Net::param_owners accessor for param sharing info --- include/caffe/net.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/caffe/net.hpp b/include/caffe/net.hpp index 2709d87ec4e..23da5dbbf2d 100644 --- a/include/caffe/net.hpp +++ b/include/caffe/net.hpp @@ -147,6 +147,7 @@ class Net { const map& param_names_index() const { return param_names_index_; } + inline const vector& param_owners() const { return param_owners_; } /// @brief Input and output blob numbers inline int num_inputs() const { return net_input_blobs_.size(); } inline int num_outputs() const { return net_output_blobs_.size(); } From f38ddef614b386ec9074e5e9b64e96704cb3124f Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Mon, 6 Oct 2014 23:46:48 -0700 Subject: [PATCH 300/798] Add gradient clipping -- limit L2 norm of parameter gradients --- include/caffe/solver.hpp | 1 + src/caffe/proto/caffe.proto | 7 ++++++- src/caffe/solver.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/include/caffe/solver.hpp b/include/caffe/solver.hpp index fde66208207..2510de748de 100644 --- a/include/caffe/solver.hpp +++ b/include/caffe/solver.hpp @@ -81,6 +81,7 @@ class SGDSolver : public Solver { void PreSolve(); Dtype GetLearningRate(); virtual void ComputeUpdateValue(); + virtual void ClipGradients(); virtual void SnapshotSolverState(SolverState * state); virtual void RestoreSolverState(const SolverState& state); // history maintains the historical momentum data. diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index c2a39a5cadf..8d937420eba 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -75,7 +75,7 @@ message NetParameter { // NOTE // Update the next available ID when you add a new SolverParameter field. // -// SolverParameter next available ID: 35 (last added: stepvalue) +// SolverParameter next available ID: 36 (last added: clip_gradients) message SolverParameter { ////////////////////////////////////////////////////////////////////////////// // Specifying the train and test networks @@ -140,6 +140,11 @@ message SolverParameter { optional int32 stepsize = 13; // the stepsize for learning rate policy "multistep" repeated int32 stepvalue = 34; + + // Set clip_gradients to >= 0 to clip parameter gradients to that L2 norm, + // whenever their actual L2 norm is larger. + optional float clip_gradients = 35 [default = -1]; + optional int32 snapshot = 14 [default = 0]; // The snapshot interval optional string snapshot_prefix = 15; // The prefix for the snapshot. // whether to snapshot diff in the results or not. Snapshotting diff will help diff --git a/src/caffe/solver.cpp b/src/caffe/solver.cpp index 100cb357749..9866d7cbc56 100644 --- a/src/caffe/solver.cpp +++ b/src/caffe/solver.cpp @@ -437,6 +437,30 @@ void SGDSolver::PreSolve() { } } +template +void SGDSolver::ClipGradients() { + const Dtype clip_gradients = this->param_.clip_gradients(); + if (clip_gradients < 0) { return; } + const vector > >& net_params = this->net_->params(); + Dtype sumsq_diff = 0; + for (int i = 0; i < net_params.size(); ++i) { + if (this->net_->param_owners()[i] < 0) { + sumsq_diff += net_params[i]->sumsq_diff(); + } + } + const Dtype l2norm_diff = std::sqrt(sumsq_diff); + if (l2norm_diff > clip_gradients) { + Dtype scale_factor = clip_gradients / l2norm_diff; + LOG(INFO) << "Gradient clipping: scaling down gradients (L2 norm " + << l2norm_diff << " > " << clip_gradients << ") " + << "by scale factor " << scale_factor; + for (int i = 0; i < net_params.size(); ++i) { + if (this->net_->param_owners()[i] < 0) { + net_params[i]->scale_diff(scale_factor); + } + } + } +} template void SGDSolver::ComputeUpdateValue() { @@ -449,6 +473,7 @@ void SGDSolver::ComputeUpdateValue() { if (this->param_.display() && this->iter_ % this->param_.display() == 0) { LOG(INFO) << "Iteration " << this->iter_ << ", lr = " << rate; } + ClipGradients(); Dtype momentum = this->param_.momentum(); Dtype weight_decay = this->param_.weight_decay(); string regularization_type = this->param_.regularization_type(); @@ -563,6 +588,7 @@ void NesterovSolver::ComputeUpdateValue() { if (this->param_.display() && this->iter_ % this->param_.display() == 0) { LOG(INFO) << "Iteration " << this->iter_ << ", lr = " << rate; } + SGDSolver::ClipGradients(); Dtype momentum = this->param_.momentum(); Dtype weight_decay = this->param_.weight_decay(); string regularization_type = this->param_.regularization_type(); @@ -680,6 +706,7 @@ void AdaGradSolver::ComputeUpdateValue() { if (this->param_.display() && this->iter_ % this->param_.display() == 0) { LOG(INFO) << "Iteration " << this->iter_ << ", lr = " << rate; } + SGDSolver::ClipGradients(); Dtype weight_decay = this->param_.weight_decay(); string regularization_type = this->param_.regularization_type(); switch (Caffe::mode()) { From 6a309c17fc386192df4780d85c92e3b36c2ce948 Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Sun, 15 Feb 2015 17:05:10 -0800 Subject: [PATCH 301/798] BlobMathTest: fixes for numerical precision issues --- src/caffe/test/test_blob.cpp | 53 +++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/caffe/test/test_blob.cpp b/src/caffe/test/test_blob.cpp index 84d84e8f444..e0678061173 100644 --- a/src/caffe/test/test_blob.cpp +++ b/src/caffe/test/test_blob.cpp @@ -59,9 +59,12 @@ class BlobMathTest : public MultiDeviceTest { typedef typename TypeParam::Dtype Dtype; protected: BlobMathTest() - : blob_(new Blob(2, 3, 4, 5)) {} + : blob_(new Blob(2, 3, 4, 5)), + epsilon_(1e-6) {} + virtual ~BlobMathTest() { delete blob_; } Blob* const blob_; + Dtype epsilon_; }; TYPED_TEST_CASE(BlobMathTest, TestDtypesAndDevices); @@ -95,7 +98,8 @@ TYPED_TEST(BlobMathTest, TestSumOfSquares) { default: LOG(FATAL) << "Unknown device: " << TypeParam::device; } - EXPECT_FLOAT_EQ(expected_sumsq, this->blob_->sumsq_data()); + EXPECT_NEAR(expected_sumsq, this->blob_->sumsq_data(), + this->epsilon_ * expected_sumsq); EXPECT_EQ(0, this->blob_->sumsq_diff()); // Check sumsq_diff too. @@ -112,9 +116,12 @@ TYPED_TEST(BlobMathTest, TestSumOfSquares) { default: LOG(FATAL) << "Unknown device: " << TypeParam::device; } - EXPECT_FLOAT_EQ(expected_sumsq, this->blob_->sumsq_data()); - EXPECT_FLOAT_EQ(expected_sumsq * kDiffScaleFactor * kDiffScaleFactor, - this->blob_->sumsq_diff()); + EXPECT_NEAR(expected_sumsq, this->blob_->sumsq_data(), + this->epsilon_ * expected_sumsq); + const Dtype expected_sumsq_diff = + expected_sumsq * kDiffScaleFactor * kDiffScaleFactor; + EXPECT_NEAR(expected_sumsq_diff, this->blob_->sumsq_diff(), + this->epsilon_ * expected_sumsq_diff); } TYPED_TEST(BlobMathTest, TestAsum) { @@ -146,7 +153,8 @@ TYPED_TEST(BlobMathTest, TestAsum) { default: LOG(FATAL) << "Unknown device: " << TypeParam::device; } - EXPECT_FLOAT_EQ(expected_asum, this->blob_->asum_data()); + EXPECT_NEAR(expected_asum, this->blob_->asum_data(), + this->epsilon_ * expected_asum); EXPECT_EQ(0, this->blob_->asum_diff()); // Check asum_diff too. @@ -163,8 +171,11 @@ TYPED_TEST(BlobMathTest, TestAsum) { default: LOG(FATAL) << "Unknown device: " << TypeParam::device; } - EXPECT_FLOAT_EQ(expected_asum, this->blob_->asum_data()); - EXPECT_FLOAT_EQ(expected_asum * kDiffScaleFactor, this->blob_->asum_diff()); + EXPECT_NEAR(expected_asum, this->blob_->asum_data(), + this->epsilon_ * expected_asum); + const Dtype expected_diff_asum = expected_asum * kDiffScaleFactor; + EXPECT_NEAR(expected_diff_asum, this->blob_->asum_diff(), + this->epsilon_ * expected_diff_asum); } TYPED_TEST(BlobMathTest, TestScaleData) { @@ -193,8 +204,8 @@ TYPED_TEST(BlobMathTest, TestScaleData) { } const Dtype kDataScaleFactor = 3; this->blob_->scale_data(kDataScaleFactor); - EXPECT_FLOAT_EQ(asum_before_scale * kDataScaleFactor, - this->blob_->asum_data()); + EXPECT_NEAR(asum_before_scale * kDataScaleFactor, this->blob_->asum_data(), + this->epsilon_ * asum_before_scale * kDataScaleFactor); EXPECT_EQ(0, this->blob_->asum_diff()); // Check scale_diff too. @@ -202,11 +213,13 @@ TYPED_TEST(BlobMathTest, TestScaleData) { const Dtype* data = this->blob_->cpu_data(); caffe_cpu_scale(this->blob_->count(), kDataToDiffScaleFactor, data, this->blob_->mutable_cpu_diff()); - EXPECT_FLOAT_EQ(asum_before_scale * kDataScaleFactor, - this->blob_->asum_data()); - const Dtype diff_asum_before_scale = this->blob_->asum_diff(); - EXPECT_FLOAT_EQ(asum_before_scale * kDataScaleFactor * kDataToDiffScaleFactor, - diff_asum_before_scale); + const Dtype expected_asum_before_scale = asum_before_scale * kDataScaleFactor; + EXPECT_NEAR(expected_asum_before_scale, this->blob_->asum_data(), + this->epsilon_ * expected_asum_before_scale); + const Dtype expected_diff_asum_before_scale = + asum_before_scale * kDataScaleFactor * kDataToDiffScaleFactor; + EXPECT_NEAR(expected_diff_asum_before_scale, this->blob_->asum_diff(), + this->epsilon_ * expected_diff_asum_before_scale); switch (TypeParam::device) { case Caffe::CPU: this->blob_->mutable_cpu_diff(); @@ -219,10 +232,12 @@ TYPED_TEST(BlobMathTest, TestScaleData) { } const Dtype kDiffScaleFactor = 3; this->blob_->scale_diff(kDiffScaleFactor); - EXPECT_FLOAT_EQ(asum_before_scale * kDataScaleFactor, - this->blob_->asum_data()); - EXPECT_FLOAT_EQ(diff_asum_before_scale * kDiffScaleFactor, - this->blob_->asum_diff()); + EXPECT_NEAR(asum_before_scale * kDataScaleFactor, this->blob_->asum_data(), + this->epsilon_ * asum_before_scale * kDataScaleFactor); + const Dtype expected_diff_asum = + expected_diff_asum_before_scale * kDiffScaleFactor; + EXPECT_NEAR(expected_diff_asum, this->blob_->asum_diff(), + this->epsilon_ * expected_diff_asum); } } // namespace caffe From 1344d1bc51f781b593a52fa71ecd59a23dc031fe Mon Sep 17 00:00:00 2001 From: James Steven Supancic III Date: Thu, 12 Feb 2015 13:57:25 -0800 Subject: [PATCH 302/798] Fix Draw Net Problem #1709 Introduced by Layer type is a string #1694 --- python/caffe/draw.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/python/caffe/draw.py b/python/caffe/draw.py index d95c193cc93..1871e7a08d7 100644 --- a/python/caffe/draw.py +++ b/python/caffe/draw.py @@ -17,13 +17,6 @@ 'style': 'filled'} BLOB_STYLE = {'shape': 'octagon', 'fillcolor': '#E0E0E0', 'style': 'filled'} -def get_enum_name_by_value(): - desc = caffe_pb2.LayerParameter.LayerType.DESCRIPTOR - d = {} - for k,v in desc.values_by_name.items(): - d[v.number] = k - return d - def get_pooling_types_dict(): """Get dictionary mapping pooling type number to type name @@ -112,10 +105,9 @@ def get_pydot_graph(caffe_net, rankdir, label_edges=True): pydot_graph = pydot.Dot(caffe_net.name, graph_type='digraph', rankdir=rankdir) pydot_nodes = {} pydot_edges = [] - d = get_enum_name_by_value() - for layer in caffe_net.layers: + for layer in caffe_net.layer: name = layer.name - layertype = d[layer.type] + layertype = layer.type node_label = determine_node_label_by_layertype(layer, layertype, rankdir) if (len(layer.bottom) == 1 and len(layer.top) == 1 and layer.bottom[0] == layer.top[0]): From 1e0d49a39d1e38c8de2a4c24ab0bff3a71da21ff Mon Sep 17 00:00:00 2001 From: Brandon Amos Date: Mon, 16 Feb 2015 15:09:24 -0500 Subject: [PATCH 303/798] Correct 'epochs' to 'iterations' See https://github.com/BVLC/caffe/blob/master/models/bvlc_reference_caffenet/solver.prototxt --- examples/imagenet/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/imagenet/readme.md b/examples/imagenet/readme.md index 41384f9475b..c2dd62ec963 100644 --- a/examples/imagenet/readme.md +++ b/examples/imagenet/readme.md @@ -67,7 +67,7 @@ We will also lay out a protocol buffer for running the solver. Let's make a few * We will run in batches of 256, and run a total of 450,000 iterations (about 90 epochs). * For every 1,000 iterations, we test the learned net on the validation data. * We set the initial learning rate to 0.01, and decrease it every 100,000 iterations (about 20 epochs). -* Information will be displayed every 20 epochs. +* Information will be displayed every 20 iterations. * The network will be trained with momentum 0.9 and a weight decay of 0.0005. * For every 10,000 iterations, we will take a snapshot of the current status. From 02c99fb9c7386242a9480378195539232ad7f18f Mon Sep 17 00:00:00 2001 From: Takuya Narihira Date: Mon, 16 Feb 2015 16:06:03 -0800 Subject: [PATCH 304/798] Fix `draw` to support new protobuf format --- python/caffe/draw.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/caffe/draw.py b/python/caffe/draw.py index 1871e7a08d7..6a4dbd47351 100644 --- a/python/caffe/draw.py +++ b/python/caffe/draw.py @@ -32,11 +32,11 @@ def determine_edge_label_by_layertype(layer, layertype): """Define edge label based on layer type """ - if layertype == 'DATA': + if layertype == 'Data': edge_label = 'Batch ' + str(layer.data_param.batch_size) - elif layertype == 'CONVOLUTION': + elif layertype == 'Convolution': edge_label = str(layer.convolution_param.num_output) - elif layertype == 'INNER_PRODUCT': + elif layertype == 'InnerProduct': edge_label = str(layer.inner_product_param.num_output) else: edge_label = '""' @@ -57,7 +57,7 @@ def determine_node_label_by_layertype(layer, layertype, rankdir): # horizontal space is not; separate words with newlines separator = '\n' - if layertype == 'CONVOLUTION': + if layertype == 'Convolution': # Outer double quotes needed or else colon characters don't parse # properly node_label = '"%s%s(%s)%skernel size: %d%sstride: %d%spad: %d"' %\ @@ -70,7 +70,7 @@ def determine_node_label_by_layertype(layer, layertype, rankdir): layer.convolution_param.stride, separator, layer.convolution_param.pad) - elif layertype == 'POOLING': + elif layertype == 'Pooling': pooling_types_dict = get_pooling_types_dict() node_label = '"%s%s(%s %s)%skernel size: %d%sstride: %d%spad: %d"' %\ (layer.name, @@ -92,11 +92,11 @@ def choose_color_by_layertype(layertype): """Define colors for nodes based on the layer type """ color = '#6495ED' # Default - if layertype == 'CONVOLUTION': + if layertype == 'Convolution': color = '#FF5050' - elif layertype == 'POOLING': + elif layertype == 'Pooling': color = '#FF9900' - elif layertype == 'INNER_PRODUCT': + elif layertype == 'InnerProduct': color = '#CC33FF' return color From 82551adbf8c77a06fa7e8b2508e1fb24ff1b5b31 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 16 Oct 2014 22:52:30 -0700 Subject: [PATCH 305/798] reshape DATA + IMAGE_DATA for inputs of varying dimension To feed inputs of varying dimension, the `DATA` and `IMAGE_DATA` layer reshapes its prefetch and top blobs when the batch size is 1. The `BasePrefetchingDataLayer` always reshapes on forward. --- src/caffe/layers/base_data_layer.cpp | 3 +++ src/caffe/layers/base_data_layer.cu | 3 +++ src/caffe/layers/data_layer.cpp | 16 ++++++++++++++-- src/caffe/layers/image_data_layer.cpp | 20 ++++++++++++++++---- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/caffe/layers/base_data_layer.cpp b/src/caffe/layers/base_data_layer.cpp index eb0aaf82120..c3b9bc421ba 100644 --- a/src/caffe/layers/base_data_layer.cpp +++ b/src/caffe/layers/base_data_layer.cpp @@ -61,6 +61,9 @@ void BasePrefetchingDataLayer::Forward_cpu( // First, join the thread JoinPrefetchThread(); DLOG(INFO) << "Thread joined"; + // Reshape to loaded data. + top[0]->Reshape(this->prefetch_data_.num(), this->prefetch_data_.channels(), + this->prefetch_data_.height(), this->prefetch_data_.width()); // Copy the data caffe_copy(prefetch_data_.count(), prefetch_data_.cpu_data(), top[0]->mutable_cpu_data()); diff --git a/src/caffe/layers/base_data_layer.cu b/src/caffe/layers/base_data_layer.cu index 204a16d260a..775f6c47f7e 100644 --- a/src/caffe/layers/base_data_layer.cu +++ b/src/caffe/layers/base_data_layer.cu @@ -9,6 +9,9 @@ void BasePrefetchingDataLayer::Forward_gpu( const vector*>& bottom, const vector*>& top) { // First, join the thread JoinPrefetchThread(); + // Reshape to loaded data. + top[0]->Reshape(this->prefetch_data_.num(), this->prefetch_data_.channels(), + this->prefetch_data_.height(), this->prefetch_data_.width()); // Copy the data caffe_copy(prefetch_data_.count(), prefetch_data_.cpu_data(), top[0]->mutable_gpu_data()); diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 227db201759..98ce26e9f0a 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -49,7 +49,7 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, int crop_size = this->layer_param_.transform_param().crop_size(); if (crop_size > 0) { top[0]->Reshape(this->layer_param_.data_param().batch_size(), - datum.channels(), crop_size, crop_size); + datum.channels(), crop_size, crop_size); this->prefetch_data_.Reshape(this->layer_param_.data_param().batch_size(), datum.channels(), crop_size, crop_size); this->transformed_data_.Reshape(1, datum.channels(), crop_size, crop_size); @@ -83,13 +83,25 @@ void DataLayer::InternalThreadEntry() { CPUTimer timer; CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); + + // Reshape on single input batches for inputs of varying dimension. + const int batch_size = this->layer_param_.data_param().batch_size(); + const int crop_size = this->layer_param_.transform_param().crop_size(); + if (batch_size == 1 && crop_size == 0) { + Datum datum; + datum.ParseFromString(cursor_->value()); + this->prefetch_data_.Reshape(1, datum.channels(), + datum.height(), datum.width()); + this->transformed_data_.Reshape(1, datum.channels(), + datum.height(), datum.width()); + } + Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = NULL; // suppress warnings about uninitialized variables if (this->output_labels_) { top_label = this->prefetch_label_.mutable_cpu_data(); } - const int batch_size = this->layer_param_.data_param().batch_size(); for (int item_id = 0; item_id < batch_size; ++item_id) { timer.Start(); // get a blob diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index bd4b8a033c2..e98ff85a0ea 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -102,15 +102,27 @@ void ImageDataLayer::InternalThreadEntry() { CPUTimer timer; CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); - Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); - Dtype* top_label = this->prefetch_label_.mutable_cpu_data(); ImageDataParameter image_data_param = this->layer_param_.image_data_param(); const int batch_size = image_data_param.batch_size(); const int new_height = image_data_param.new_height(); const int new_width = image_data_param.new_width(); + const int crop_size = this->layer_param_.transform_param().crop_size(); const bool is_color = image_data_param.is_color(); string root_folder = image_data_param.root_folder(); + // Reshape on single input batches for inputs of varying dimension. + if (batch_size == 1 && crop_size == 0 && new_height == 0 && new_width == 0) { + cv::Mat cv_img = ReadImageToCVMat(root_folder + lines_[lines_id_].first, + 0, 0, is_color); + this->prefetch_data_.Reshape(1, cv_img.channels(), + cv_img.rows, cv_img.cols); + this->transformed_data_.Reshape(1, cv_img.channels(), + cv_img.rows, cv_img.cols); + } + + Dtype* prefetch_data = this->prefetch_data_.mutable_cpu_data(); + Dtype* prefetch_label = this->prefetch_label_.mutable_cpu_data(); + // datum scales const int lines_size = lines_.size(); for (int item_id = 0; item_id < batch_size; ++item_id) { @@ -124,11 +136,11 @@ void ImageDataLayer::InternalThreadEntry() { timer.Start(); // Apply transformations (mirror, crop...) to the image int offset = this->prefetch_data_.offset(item_id); - this->transformed_data_.set_cpu_data(top_data + offset); + this->transformed_data_.set_cpu_data(prefetch_data + offset); this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); trans_time += timer.MicroSeconds(); - top_label[item_id] = lines_[lines_id_].second; + prefetch_label[item_id] = lines_[lines_id_].second; // go to the next iter lines_id_++; if (lines_id_ >= lines_size) { From d3b20106c02ea17d198740a6e790d4f7901a3548 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Thu, 5 Feb 2015 16:31:52 -0800 Subject: [PATCH 306/798] test reshaping DATA and IMAGE_DATA --- src/caffe/test/test_data_layer.cpp | 72 ++++++++++++++++++++++++ src/caffe/test/test_image_data_layer.cpp | 39 ++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/caffe/test/test_data_layer.cpp b/src/caffe/test/test_data_layer.cpp index 8cc31b24167..adc99dd71c9 100644 --- a/src/caffe/test/test_data_layer.cpp +++ b/src/caffe/test/test_data_layer.cpp @@ -103,6 +103,70 @@ class DataLayerTest : public MultiDeviceTest { } } + void TestReshape(DataParameter_DB backend) { + const int num_inputs = 5; + // Save data of varying shapes. + LOG(INFO) << "Using temporary dataset " << *filename_; + scoped_ptr db(db::GetDB(backend)); + db->Open(*filename_, db::NEW); + scoped_ptr txn(db->NewTransaction()); + for (int i = 0; i < num_inputs; ++i) { + Datum datum; + datum.set_label(i); + datum.set_channels(2); + datum.set_height(i % 2 + 1); + datum.set_width(i % 4 + 1); + std::string* data = datum.mutable_data(); + const int data_size = datum.channels() * datum.height() * datum.width(); + for (int j = 0; j < data_size; ++j) { + data->push_back(static_cast(j)); + } + stringstream ss; + ss << i; + string out; + CHECK(datum.SerializeToString(&out)); + txn->Put(ss.str(), out); + } + txn->Commit(); + db->Close(); + + // Load and check data of various shapes. + LayerParameter param; + DataParameter* data_param = param.mutable_data_param(); + data_param->set_batch_size(1); + data_param->set_source(filename_->c_str()); + data_param->set_backend(backend); + + DataLayer layer(param); + layer.SetUp(blob_bottom_vec_, blob_top_vec_); + EXPECT_EQ(blob_top_data_->num(), 1); + EXPECT_EQ(blob_top_data_->channels(), 2); + EXPECT_EQ(blob_top_label_->num(), 1); + EXPECT_EQ(blob_top_label_->channels(), 1); + EXPECT_EQ(blob_top_label_->height(), 1); + EXPECT_EQ(blob_top_label_->width(), 1); + + for (int iter = 0; iter < num_inputs; ++iter) { + layer.Forward(blob_bottom_vec_, blob_top_vec_); + EXPECT_EQ(blob_top_data_->height(), iter % 2 + 1); + EXPECT_EQ(blob_top_data_->width(), iter % 4 + 1); + EXPECT_EQ(iter, blob_top_label_->cpu_data()[0]); + const int channels = blob_top_data_->channels(); + const int height = blob_top_data_->height(); + const int width = blob_top_data_->width(); + for (int c = 0; c < channels; ++c) { + for (int h = 0; h < height; ++h) { + for (int w = 0; w < width; ++w) { + const int idx = (c * height + h) * width + w; + EXPECT_EQ(idx, static_cast(blob_top_data_->cpu_data()[idx])) + << "debug: iter " << iter << " c " << c + << " h " << h << " w " << w; + } + } + } + } + } + void TestReadCrop() { const Dtype scale = 3; LayerParameter param; @@ -285,6 +349,10 @@ TYPED_TEST(DataLayerTest, TestReadLevelDB) { this->TestRead(); } +TYPED_TEST(DataLayerTest, TestReshapeLevelDB) { + this->TestReshape(DataParameter_DB_LEVELDB); +} + TYPED_TEST(DataLayerTest, TestReadCropTrainLevelDB) { Caffe::set_phase(Caffe::TRAIN); const bool unique_pixels = true; // all images the same; pixels different @@ -323,6 +391,10 @@ TYPED_TEST(DataLayerTest, TestReadLMDB) { this->TestRead(); } +TYPED_TEST(DataLayerTest, TestReshapeLMDB) { + this->TestReshape(DataParameter_DB_LMDB); +} + TYPED_TEST(DataLayerTest, TestReadCropTrainLMDB) { Caffe::set_phase(Caffe::TRAIN); const bool unique_pixels = true; // all images the same; pixels different diff --git a/src/caffe/test/test_image_data_layer.cpp b/src/caffe/test/test_image_data_layer.cpp index 77523ef8c18..931a5ebf137 100644 --- a/src/caffe/test/test_image_data_layer.cpp +++ b/src/caffe/test/test_image_data_layer.cpp @@ -25,17 +25,24 @@ class ImageDataLayerTest : public MultiDeviceTest { blob_top_data_(new Blob()), blob_top_label_(new Blob()) {} virtual void SetUp() { - MakeTempFilename(&filename_); blob_top_vec_.push_back(blob_top_data_); blob_top_vec_.push_back(blob_top_label_); Caffe::set_random_seed(seed_); - // Create a Vector of files with labels + // Create test input file. + MakeTempFilename(&filename_); std::ofstream outfile(filename_.c_str(), std::ofstream::out); LOG(INFO) << "Using temporary file " << filename_; for (int i = 0; i < 5; ++i) { outfile << EXAMPLES_SOURCE_DIR "images/cat.jpg " << i; } outfile.close(); + // Create test input file for images of distinct sizes. + MakeTempFilename(&filename_reshape_); + std::ofstream reshapefile(filename_reshape_.c_str(), std::ofstream::out); + LOG(INFO) << "Using temporary file " << filename_reshape_; + reshapefile << EXAMPLES_SOURCE_DIR "images/cat.jpg " << 0; + reshapefile << EXAMPLES_SOURCE_DIR "images/fish-bike.jpg " << 1; + reshapefile.close(); } virtual ~ImageDataLayerTest() { @@ -45,6 +52,7 @@ class ImageDataLayerTest : public MultiDeviceTest { int seed_; string filename_; + string filename_reshape_; Blob* const blob_top_data_; Blob* const blob_top_label_; vector*> blob_bottom_vec_; @@ -107,6 +115,33 @@ TYPED_TEST(ImageDataLayerTest, TestResize) { } } +TYPED_TEST(ImageDataLayerTest, TestReshape) { + typedef typename TypeParam::Dtype Dtype; + LayerParameter param; + ImageDataParameter* image_data_param = param.mutable_image_data_param(); + image_data_param->set_batch_size(1); + image_data_param->set_source(this->filename_reshape_.c_str()); + image_data_param->set_shuffle(false); + ImageDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_); + EXPECT_EQ(this->blob_top_label_->num(), 1); + EXPECT_EQ(this->blob_top_label_->channels(), 1); + EXPECT_EQ(this->blob_top_label_->height(), 1); + EXPECT_EQ(this->blob_top_label_->width(), 1); + // cat.jpg + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), 1); + EXPECT_EQ(this->blob_top_data_->channels(), 3); + EXPECT_EQ(this->blob_top_data_->height(), 360); + EXPECT_EQ(this->blob_top_data_->width(), 480); + // fish-bike.jpg + layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), 1); + EXPECT_EQ(this->blob_top_data_->channels(), 3); + EXPECT_EQ(this->blob_top_data_->height(), 323); + EXPECT_EQ(this->blob_top_data_->width(), 481); +} + TYPED_TEST(ImageDataLayerTest, TestShuffle) { typedef typename TypeParam::Dtype Dtype; LayerParameter param; From 52465873d08cfd58a4c84ee8b239908814de4f39 Mon Sep 17 00:00:00 2001 From: philkr Date: Mon, 16 Feb 2015 11:42:22 -0800 Subject: [PATCH 307/798] Cleaning up the encoded flag. Allowing any image (cropped or gray scale) to be encoded. Allowing for a change in encoded (jpg -> png vice versa) and cleaning up some unused functions. --- include/caffe/util/io.hpp | 36 ++++++---------- src/caffe/layers/data_layer.cpp | 4 +- src/caffe/layers/window_data_layer.cpp | 2 +- src/caffe/test/test_io.cpp | 31 +++---------- src/caffe/util/io.cpp | 60 +++++++++++++------------- tools/compute_image_mean.cpp | 4 +- tools/convert_imageset.cpp | 30 +++++++------ 7 files changed, 72 insertions(+), 95 deletions(-) diff --git a/include/caffe/util/io.hpp b/include/caffe/util/io.hpp index a01f917abf5..9d7540d62cc 100644 --- a/include/caffe/util/io.hpp +++ b/include/caffe/util/io.hpp @@ -92,7 +92,14 @@ inline bool ReadFileToDatum(const string& filename, Datum* datum) { } bool ReadImageToDatum(const string& filename, const int label, - const int height, const int width, const bool is_color, Datum* datum); + const int height, const int width, const bool is_color, + const std::string & encoding, Datum* datum); + +inline bool ReadImageToDatum(const string& filename, const int label, + const int height, const int width, const bool is_color, Datum* datum) { + return ReadImageToDatum(filename, label, height, width, is_color, + "", datum); +} inline bool ReadImageToDatum(const string& filename, const int label, const int height, const int width, Datum* datum) { @@ -109,20 +116,12 @@ inline bool ReadImageToDatum(const string& filename, const int label, return ReadImageToDatum(filename, label, 0, 0, true, datum); } -bool DecodeDatum(const int height, const int width, const bool is_color, - Datum* datum); - -inline bool DecodeDatum(const int height, const int width, Datum* datum) { - return DecodeDatum(height, width, true, datum); -} - -inline bool DecodeDatum(const bool is_color, Datum* datum) { - return DecodeDatum(0, 0, is_color, datum); +inline bool ReadImageToDatum(const string& filename, const int label, + const std::string & encoding, Datum* datum) { + return ReadImageToDatum(filename, label, 0, 0, true, encoding, datum); } -inline bool DecodeDatum(Datum* datum) { - return DecodeDatum(0, 0, true, datum); -} +bool DecodeDatumNative(Datum* datum); cv::Mat ReadImageToCVMat(const string& filename, const int height, const int width, const bool is_color); @@ -135,16 +134,7 @@ cv::Mat ReadImageToCVMat(const string& filename, cv::Mat ReadImageToCVMat(const string& filename); -cv::Mat DecodeDatumToCVMat(const Datum& datum, - const int height, const int width, const bool is_color); - -cv::Mat DecodeDatumToCVMat(const Datum& datum, - const int height, const int width); - -cv::Mat DecodeDatumToCVMat(const Datum& datum, - const bool is_color); - -cv::Mat DecodeDatumToCVMat(const Datum& datum); +cv::Mat DecodeDatumToCVMatNative(const Datum& datum); void CVMatToDatum(const cv::Mat& cv_img, Datum* datum); diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 227db201759..891d03911c2 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -42,7 +42,7 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, Datum datum; datum.ParseFromString(cursor_->value()); - if (DecodeDatum(&datum)) { + if (DecodeDatumNative(&datum)) { LOG(INFO) << "Decoding Datum"; } // image @@ -98,7 +98,7 @@ void DataLayer::InternalThreadEntry() { cv::Mat cv_img; if (datum.encoded()) { - cv_img = DecodeDatumToCVMat(datum); + cv_img = DecodeDatumToCVMatNative(datum); } read_time += timer.MicroSeconds(); timer.Start(); diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 23ec83d166b..cceb4ffb1b5 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -281,7 +281,7 @@ void WindowDataLayer::InternalThreadEntry() { if (this->cache_images_) { pair image_cached = image_database_cache_[window[WindowDataLayer::IMAGE_INDEX]]; - cv_img = DecodeDatumToCVMat(image_cached.second); + cv_img = DecodeDatumToCVMatNative(image_cached.second); } else { cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR); if (!cv_img.data) { diff --git a/src/caffe/test/test_io.cpp b/src/caffe/test/test_io.cpp index 4d941fa8683..6b135efcf6e 100644 --- a/src/caffe/test/test_io.cpp +++ b/src/caffe/test/test_io.cpp @@ -289,8 +289,8 @@ TEST_F(IOTest, TestDecodeDatum) { string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; Datum datum; EXPECT_TRUE(ReadFileToDatum(filename, &datum)); - EXPECT_TRUE(DecodeDatum(&datum)); - EXPECT_FALSE(DecodeDatum(&datum)); + EXPECT_TRUE(DecodeDatumNative(&datum)); + EXPECT_FALSE(DecodeDatumNative(&datum)); Datum datum_ref; ReadImageToDatumReference(filename, 0, 0, 0, true, &datum_ref); EXPECT_EQ(datum.channels(), datum_ref.channels()); @@ -309,38 +309,17 @@ TEST_F(IOTest, TestDecodeDatumToCVMat) { string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; Datum datum; EXPECT_TRUE(ReadFileToDatum(filename, &datum)); - cv::Mat cv_img = DecodeDatumToCVMat(datum); + cv::Mat cv_img = DecodeDatumToCVMatNative(datum); EXPECT_EQ(cv_img.channels(), 3); EXPECT_EQ(cv_img.rows, 360); EXPECT_EQ(cv_img.cols, 480); } -TEST_F(IOTest, TestDecodeDatumToCVMatResized) { - string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; - Datum datum; - EXPECT_TRUE(ReadFileToDatum(filename, &datum)); - cv::Mat cv_img = DecodeDatumToCVMat(datum, 100, 200); - EXPECT_EQ(cv_img.channels(), 3); - EXPECT_EQ(cv_img.rows, 100); - EXPECT_EQ(cv_img.cols, 200); -} - -TEST_F(IOTest, TestDecodeDatumToCVMatResizedGray) { - string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; - Datum datum; - EXPECT_TRUE(ReadFileToDatum(filename, &datum)); - const bool is_color = false; - cv::Mat cv_img = DecodeDatumToCVMat(datum, 200, 100, is_color); - EXPECT_EQ(cv_img.channels(), 1); - EXPECT_EQ(cv_img.rows, 200); - EXPECT_EQ(cv_img.cols, 100); -} - TEST_F(IOTest, TestDecodeDatumToCVMatContent) { string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; Datum datum; - EXPECT_TRUE(ReadFileToDatum(filename, &datum)); - cv::Mat cv_img = DecodeDatumToCVMat(datum); + EXPECT_TRUE(ReadImageToDatum(filename, 0, std::string("jpg"), &datum)); + cv::Mat cv_img = DecodeDatumToCVMatNative(datum); cv::Mat cv_img_ref = ReadImageToCVMat(filename); EXPECT_EQ(cv_img_ref.channels(), cv_img.channels()); EXPECT_EQ(cv_img_ref.rows, cv_img.rows); diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index f738e053e86..65531687b63 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -98,11 +98,36 @@ cv::Mat ReadImageToCVMat(const string& filename, cv::Mat ReadImageToCVMat(const string& filename) { return ReadImageToCVMat(filename, 0, 0, true); } - +// Do the file extension and encoding match? +static bool matchExt(const std::string & fn, + std::string en) { + size_t p = fn.rfind('.'); + std::string ext = p != fn.npos ? fn.substr(p) : fn; + std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); + std::transform(en.begin(), en.end(), en.begin(), ::tolower); + if ( ext == en ) + return true; + if ( en == "jpg" && ext == "jpeg" ) + return true; + return false; +} bool ReadImageToDatum(const string& filename, const int label, - const int height, const int width, const bool is_color, Datum* datum) { + const int height, const int width, const bool is_color, + const std::string & encoding, Datum* datum) { cv::Mat cv_img = ReadImageToCVMat(filename, height, width, is_color); if (cv_img.data) { + if (encoding.size()) { + if ( (cv_img.channels() == 3) == is_color && !height && !width && + matchExt(filename, encoding) ) + return ReadFileToDatum(filename, label, datum); + std::vector buf; + cv::imencode("."+encoding, cv_img, buf); + datum->set_data(std::string(reinterpret_cast(&buf[0]), + buf.size())); + datum->set_label(label); + datum->set_encoded(true); + return true; + } CVMatToDatum(cv_img, datum); datum->set_label(label); return true; @@ -131,47 +156,24 @@ bool ReadFileToDatum(const string& filename, const int label, } } -cv::Mat DecodeDatumToCVMat(const Datum& datum, - const int height, const int width, const bool is_color) { +cv::Mat DecodeDatumToCVMatNative(const Datum& datum) { cv::Mat cv_img; CHECK(datum.encoded()) << "Datum not encoded"; - int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR : - CV_LOAD_IMAGE_GRAYSCALE); const string& data = datum.data(); std::vector vec_data(data.c_str(), data.c_str() + data.size()); - if (height > 0 && width > 0) { - cv::Mat cv_img_origin = cv::imdecode(cv::Mat(vec_data), cv_read_flag); - cv::resize(cv_img_origin, cv_img, cv::Size(width, height)); - } else { - cv_img = cv::imdecode(vec_data, cv_read_flag); - } + cv_img = cv::imdecode(vec_data, -1); if (!cv_img.data) { LOG(ERROR) << "Could not decode datum "; } return cv_img; } -cv::Mat DecodeDatumToCVMat(const Datum& datum, - const int height, const int width) { - return DecodeDatumToCVMat(datum, height, width, true); -} - -cv::Mat DecodeDatumToCVMat(const Datum& datum, - const bool is_color) { - return DecodeDatumToCVMat(datum, 0, 0, is_color); -} - -cv::Mat DecodeDatumToCVMat(const Datum& datum) { - return DecodeDatumToCVMat(datum, 0, 0, true); -} - // If Datum is encoded will decoded using DecodeDatumToCVMat and CVMatToDatum // if height and width are set it will resize it // If Datum is not encoded will do nothing -bool DecodeDatum(const int height, const int width, const bool is_color, - Datum* datum) { +bool DecodeDatumNative(Datum* datum) { if (datum->encoded()) { - cv::Mat cv_img = DecodeDatumToCVMat((*datum), height, width, is_color); + cv::Mat cv_img = DecodeDatumToCVMatNative((*datum)); CVMatToDatum(cv_img, datum); return true; } else { diff --git a/tools/compute_image_mean.cpp b/tools/compute_image_mean.cpp index dff63a09dca..b1fc7cae38f 100644 --- a/tools/compute_image_mean.cpp +++ b/tools/compute_image_mean.cpp @@ -50,7 +50,7 @@ int main(int argc, char** argv) { Datum datum; datum.ParseFromString(cursor->value()); - if (DecodeDatum(&datum)) { + if (DecodeDatumNative(&datum)) { LOG(INFO) << "Decoding Datum"; } @@ -68,7 +68,7 @@ int main(int argc, char** argv) { while (cursor->valid()) { Datum datum; datum.ParseFromString(cursor->value()); - DecodeDatum(&datum); + DecodeDatumNative(&datum); const std::string& data = datum.data(); size_in_datum = std::max(datum.data().size(), diff --git a/tools/convert_imageset.cpp b/tools/convert_imageset.cpp index 7fbf5b0514c..816a91f971b 100644 --- a/tools/convert_imageset.cpp +++ b/tools/convert_imageset.cpp @@ -39,6 +39,8 @@ DEFINE_bool(check_size, false, "When this option is on, check that all the datum have the same size"); DEFINE_bool(encoded, false, "When this option is on, the encoded image will be save in datum"); +DEFINE_string(encode_type, "", + "Optional: What type should we encode the image as ('png','jpg',...)."); int main(int argc, char** argv) { ::google::InitGoogleLogging(argv[0]); @@ -63,6 +65,7 @@ int main(int argc, char** argv) { const bool is_color = !FLAGS_gray; const bool check_size = FLAGS_check_size; const bool encoded = FLAGS_encoded; + const string encode_type = FLAGS_encode_type; std::ifstream infile(argv[2]); std::vector > lines; @@ -78,11 +81,8 @@ int main(int argc, char** argv) { } LOG(INFO) << "A total of " << lines.size() << " images."; - if (encoded) { - CHECK_EQ(FLAGS_resize_height, 0) << "With encoded don't resize images"; - CHECK_EQ(FLAGS_resize_width, 0) << "With encoded don't resize images"; - CHECK(!check_size) << "With encoded cannot check_size"; - } + if (encode_type.size() && !encoded) + LOG(INFO) << "encode_type specified, assuming encoded=true."; int resize_height = std::max(0, FLAGS_resize_height); int resize_width = std::max(0, FLAGS_resize_width); @@ -98,18 +98,24 @@ int main(int argc, char** argv) { int count = 0; const int kMaxKeyLength = 256; char key_cstr[kMaxKeyLength]; - int data_size; + int data_size = 0; bool data_size_initialized = false; for (int line_id = 0; line_id < lines.size(); ++line_id) { bool status; - if (encoded) { - status = ReadFileToDatum(root_folder + lines[line_id].first, - lines[line_id].second, &datum); - } else { - status = ReadImageToDatum(root_folder + lines[line_id].first, - lines[line_id].second, resize_height, resize_width, is_color, &datum); + std::string enc = encode_type; + if (encoded && !enc.size()) { + // Guess the encoding type from the file name + string fn = lines[line_id].first; + size_t p = fn.rfind('.'); + if ( p == fn.npos ) + LOG(WARNING) << "Failed to guess the encoding of '" << fn << "'"; + enc = fn.substr(p); + std::transform(enc.begin(), enc.end(), enc.begin(), ::tolower); } + status = ReadImageToDatum(root_folder + lines[line_id].first, + lines[line_id].second, resize_height, resize_width, is_color, + enc, &datum); if (status == false) continue; if (check_size) { if (!data_size_initialized) { From 32bf5c7ad804ad683aa5ea9382209e9284451e5f Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 20 Dec 2014 18:22:47 +0300 Subject: [PATCH 308/798] ignore qtcreator files --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index c27c7a6a5f6..58adc5cb106 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,9 @@ *.*project .settings +# QtCreator files +*.user + # OSX dir files .DS_Store @@ -71,6 +74,8 @@ distribute/* *.testbin *.bin python/caffe/proto/ +cmake_build +.cmake_build # Generated documentation docs/_site From 9358247014eb8322160c7feaad46091412d75d3f Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Wed, 17 Dec 2014 12:09:14 +0300 Subject: [PATCH 309/798] improve CMake build --- .gitignore | 3 - CMakeLists.txt | 199 +++------- CMakeScripts/FindLMDB.cmake | 28 -- CMakeScripts/FindLevelDB.cmake | 37 -- CMakeScripts/FindNumPy.cmake | 103 ----- CMakeScripts/FindProtobuf.cmake | 152 -------- CMakeScripts/FindSnappy.cmake | 33 -- cmake/ConfigGen.cmake | 86 +++++ cmake/Cuda.cmake | 243 ++++++++++++ cmake/Dependencies.cmake | 124 ++++++ cmake/Misc.cmake | 47 +++ .../Modules}/FindAtlas.cmake | 25 +- .../Modules}/FindGFlags.cmake | 6 +- .../Modules}/FindGlog.cmake | 14 +- .../Modules}/FindLAPACK.cmake | 0 cmake/Modules/FindLMDB.cmake | 28 ++ cmake/Modules/FindLevelDB.cmake | 44 +++ {CMakeScripts => cmake/Modules}/FindMKL.cmake | 0 cmake/Modules/FindMatlabMex.cmake | 48 +++ cmake/Modules/FindNumPy.cmake | 58 +++ .../Modules}/FindOpenBLAS.cmake | 0 cmake/Modules/FindSnappy.cmake | 28 ++ cmake/Modules/FindvecLib.cmake | 34 ++ cmake/ProtoBuf.cmake | 90 +++++ cmake/Summary.cmake | 166 ++++++++ cmake/Targets.cmake | 170 ++++++++ cmake/Templates/CaffeConfig.cmake.in | 58 +++ cmake/Templates/CaffeConfigVersion.cmake.in | 11 + cmake/Templates/caffe_config.h.in | 32 ++ cmake/Utils.cmake | 365 ++++++++++++++++++ {CMakeScripts => cmake}/lint.cmake | 0 docs/CMakeLists.txt | 106 +++++ examples/CMakeLists.txt | 41 +- include/caffe/test/test_caffe_main.hpp | 2 +- matlab/CMakeLists.txt | 73 +++- python/CMakeLists.txt | 77 ++-- src/caffe/CMakeLists.txt | 75 ++-- src/caffe/proto/CMakeLists.txt | 46 --- src/caffe/test/CMakeLists.txt | 135 ++----- src/caffe/test/cmake_test_defines.hpp.in | 4 - .../test/test_data/sample_data_list.txt.in | 2 - src/gtest/CMakeLists.txt | 9 +- tools/CMakeLists.txt | 47 ++- 43 files changed, 2017 insertions(+), 832 deletions(-) delete mode 100644 CMakeScripts/FindLMDB.cmake delete mode 100644 CMakeScripts/FindLevelDB.cmake delete mode 100644 CMakeScripts/FindNumPy.cmake delete mode 100644 CMakeScripts/FindProtobuf.cmake delete mode 100644 CMakeScripts/FindSnappy.cmake create mode 100644 cmake/ConfigGen.cmake create mode 100644 cmake/Cuda.cmake create mode 100644 cmake/Dependencies.cmake create mode 100644 cmake/Misc.cmake rename {CMakeScripts => cmake/Modules}/FindAtlas.cmake (63%) rename {CMakeScripts => cmake/Modules}/FindGFlags.cmake (79%) rename {CMakeScripts => cmake/Modules}/FindGlog.cmake (70%) rename {CMakeScripts => cmake/Modules}/FindLAPACK.cmake (100%) create mode 100644 cmake/Modules/FindLMDB.cmake create mode 100644 cmake/Modules/FindLevelDB.cmake rename {CMakeScripts => cmake/Modules}/FindMKL.cmake (100%) create mode 100644 cmake/Modules/FindMatlabMex.cmake create mode 100644 cmake/Modules/FindNumPy.cmake rename {CMakeScripts => cmake/Modules}/FindOpenBLAS.cmake (100%) create mode 100644 cmake/Modules/FindSnappy.cmake create mode 100644 cmake/Modules/FindvecLib.cmake create mode 100644 cmake/ProtoBuf.cmake create mode 100644 cmake/Summary.cmake create mode 100644 cmake/Targets.cmake create mode 100644 cmake/Templates/CaffeConfig.cmake.in create mode 100644 cmake/Templates/CaffeConfigVersion.cmake.in create mode 100644 cmake/Templates/caffe_config.h.in create mode 100644 cmake/Utils.cmake rename {CMakeScripts => cmake}/lint.cmake (100%) create mode 100644 docs/CMakeLists.txt delete mode 100644 src/caffe/proto/CMakeLists.txt delete mode 100644 src/caffe/test/cmake_test_defines.hpp.in delete mode 100644 src/caffe/test/test_data/sample_data_list.txt.in diff --git a/.gitignore b/.gitignore index 58adc5cb106..73bba6cb364 100644 --- a/.gitignore +++ b/.gitignore @@ -29,9 +29,6 @@ # IPython notebook checkpoints .ipynb_checkpoints -# CMake generated files -*.gen.cmake - # Editor temporaries *.swp *~ diff --git a/CMakeLists.txt b/CMakeLists.txt index d6b08470a7f..d3d50da218b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,177 +1,64 @@ cmake_minimum_required(VERSION 2.8.8) -project( Caffe ) -### Build Options ########################################################################## +# ---[ Caffe project +project(Caffe C CXX) -option(CPU_ONLY "Build Caffe without GPU support" OFF) -option(BUILD_PYTHON "Build Python wrapper" OFF) -option(BUILD_MATLAB "Build Matlab wrapper" OFF) -option(BUILD_EXAMPLES "Build examples" ON) -option(BUILD_SHARED_LIBS "Build SHARED libs if ON and STATIC otherwise" OFF) +# ---[ Using cmake scripts and modules +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) -if(NOT BLAS) - set(BLAS atlas) -endif() +include(cmake/Utils.cmake) +include(cmake/Targets.cmake) +include(cmake/Misc.cmake) +include(cmake/Summary.cmake) +include(cmake/ConfigGen.cmake) -if(NOT CUDA_TEST_DEVICE) - set(CUDA_TEST_DEVICE -1) -endif() +# ---[ Options +caffe_option(CPU_ONLY "Build Caffe wihtout CUDA support" OFF) # TODO: rename to USE_CUDA +caffe_option(USE_CUDNN "Build Caffe with cuDNN libary support" ON IF NOT CPU_ONLY) +caffe_option(BUILD_SHARED_LIBS "Build shared libraries" ON) +caffe_option(BUILD_python "Build Python wrapper" ON) +caffe_option(BUILD_matlab "Build Matlab wrapper" OFF IF UNIX OR APPLE) +caffe_option(BUILD_docs "Build documentation" ON IF UNIX OR APPLE) -# Install Prefix -if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set (CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Default install path" FORCE ) -endif() +# ---[ Dependencies +include(cmake/Dependencies.cmake) -### Configuration ########################################################################### -# Compiler Flags -set(CMAKE_CXX_COMPILER_FLAGS ${CMAKE_CXX_COMPILER_FLAGS} -Wall) -set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -fPIC) # set global flags -set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) # set debug flags -set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) # set release flags - -# Link Flags -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # clang++ - set(CAFFE_STATIC_LINK -Wl,-force_load $(STATIC_NAME)) -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # g++ - set(CAFFE_STATIC_LINK -Wl,--whole-archive caffe -Wl,--no-whole-archive) +# ---[ Flags +if(UNIX OR APLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall") endif() -# Global Definitions -if(CPU_ONLY) - add_definitions(-DCPU_ONLY) -endif() - -# Include Directories -set(${PROJECT_NAME}_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include) -include_directories(${${PROJECT_NAME}_INCLUDE_DIRS}) -include_directories(${CMAKE_SOURCE_DIR}/src) - -# CMake Scripts dir -set(CMAKE_SCRIPT_DIR ${CMAKE_SOURCE_DIR}/CMakeScripts) - -# CMake module path for custom module finding -set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SCRIPT_DIR}) - -### Dependencies ########################################################################## - -# Boost -find_package(Boost 1.46 COMPONENTS system thread REQUIRED) -include_directories(${Boost_INCLUDE_DIR}) -link_directories(${Boost_LIBRARY_DIRS}) - -# CUDA -if(NOT CPU_ONLY) - find_package(CUDA 5.5 REQUIRED) - include_directories(${CUDA_INCLUDE_DIRS}) - - set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} - -gencode arch=compute_20,code=sm_20 - -gencode arch=compute_20,code=sm_21 - -gencode arch=compute_30,code=sm_30 - -gencode arch=compute_35,code=sm_35 - ) - - # https://github.com/ComputationalRadiationPhysics/picongpu/blob/master/src/picongpu/CMakeLists.txt - # work-arounds - if(Boost_VERSION EQUAL 105500) - # see https://svn.boost.org/trac/boost/ticket/9392 - message(STATUS "Boost: Applying noinline work around") - # avoid warning for CMake >= 2.8.12 - set(CUDA_NVCC_FLAGS - "${CUDA_NVCC_FLAGS} \"-DBOOST_NOINLINE=__attribute__((noinline))\" ") - endif(Boost_VERSION EQUAL 105500) +if(APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") endif() -# Threads -find_package(Threads REQUIRED) - -# Google-glog -find_package(Glog REQUIRED) -include_directories(${GLOG_INCLUDE_DIRS}) - -# Google-gflags -find_package(GFlags REQUIRED) -include_directories(${GFLAGS_INCLUDE_DIRS}) - -# BLAS -if(BLAS STREQUAL "atlas") - - find_package(Atlas REQUIRED) - include_directories(${Atlas_INCLUDE_DIR}) - set(BLAS_LIBRARIES ${Atlas_LIBRARIES}) - -elseif(BLAS STREQUAL "open") +add_definitions(-DGTEST_USE_OWN_TR1_TUPLE) - find_package(OpenBLAS REQUIRED) - include_directories(${OpenBLAS_INCLUDE_DIR}) - set(BLAS_LIBRARIES ${OpenBLAS_LIB}) +# ---[ Warnings +caffe_warnings_disable(CMAKE_CXX_FLAGS -Wno-sign-compare -Wno-uninitialized) -elseif(BLAS STREQUAL "mkl") +# ---[ Config generation +configure_file(cmake/Templates/caffe_config.h.in "${CMAKE_BINARY_DIR}/caffe_config.h") - find_package(MKL REQUIRED) - include_directories(${MKL_INCLUDE_DIR}) - set(BLAS_LIBRARIES ${MKL_LIBRARIES}) - -endif() - -# HDF5 -find_package(HDF5 COMPONENTS HL REQUIRED) -include_directories(${HDF5_INCLUDE_DIRS}) - -# LevelDB -find_package(LevelDB REQUIRED) -include_directories(${LEVELDB_INCLUDE}) -if(LEVELDB_FOUND) - find_package(Snappy REQUIRED) - include_directories(${SNAPPY_INCLUDE_DIR}) - set(LEVELDB_LIBS - ${LEVELDB_LIBS} - ${SNAPPY_LIBS} - ) -endif() - -# LMDB -find_package(LMDB REQUIRED) -include_directories(${LMDB_INCLUDE_DIR}) - -# OpenCV -find_package(OpenCV REQUIRED) -include_directories(${OpenCV_INCLUDE_DIRS}) - -### Subdirectories ########################################################################## +# ---[ Includes +set(Caffe_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include) +include_directories(${Caffe_INCLUDE_DIR} ${CMAKE_BINARY_DIR}) +include_directories(BEFORE src) # This is needed for gtest. +# ---[ Subdirectories add_subdirectory(src/gtest) add_subdirectory(src/caffe) add_subdirectory(tools) +add_subdirectory(examples) +add_subdirectory(python) +add_subdirectory(matlab) +add_subdirectory(docs) -if(BUILD_EXAMPLES) - message(STATUS "Examples enabled") - add_subdirectory(examples) -endif() - -if(BUILD_PYTHON) - message(STATUS "Python enabled") - add_subdirectory(python) -endif() - -if(BUILD_MATLAB) - message(STATUS "Matlab enabled") - add_subdirectory(matlab) -endif() - -### Lint Target Setup ########################################################################## - -set(LINT_TARGET lint) -set(LINT_SCRIPT ${CMAKE_SCRIPT_DIR}/lint.cmake) -add_custom_target( - ${LINT_TARGET} - COMMAND ${CMAKE_COMMAND} -P ${LINT_SCRIPT} -) - -### Install ################################################################################# - -# Install Includes -file(GLOB folders ${${PROJECT_NAME}_INCLUDE_DIRS}/*) -install(DIRECTORY ${folders} DESTINATION include) +# ---[ Linter target +add_custom_target(lint COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/lint.cmake) +# ---[ Configuration summary +caffe_print_configuration_summary() +# ---[ Export configs generation +caffe_generate_export_configs() diff --git a/CMakeScripts/FindLMDB.cmake b/CMakeScripts/FindLMDB.cmake deleted file mode 100644 index e615f542335..00000000000 --- a/CMakeScripts/FindLMDB.cmake +++ /dev/null @@ -1,28 +0,0 @@ -# Try to find the LMBD libraries and headers -# LMDB_FOUND - system has LMDB lib -# LMDB_INCLUDE_DIR - the LMDB include directory -# LMDB_LIBRARIES - Libraries needed to use LMDB - -# FindCWD based on FindGMP by: -# Copyright (c) 2006, Laurent Montel, -# -# Redistribution and use is allowed according to the terms of the BSD license. - -# Adapted from FindCWD by: -# Copyright 2013 Conrad Steenberg -# Aug 31, 2013 - -if (LMDB_INCLUDE_DIR AND LMDB_LIBRARIES) - # Already in cache, be silent - set(LMDB_FIND_QUIETLY TRUE) -endif (LMDB_INCLUDE_DIR AND LMDB_LIBRARIES) - -find_path(LMDB_INCLUDE_DIR NAMES "lmdb.h" HINTS "$ENV{LMDB_DIR}/include") -find_library(LMDB_LIBRARIES NAMES lmdb HINTS $ENV{LMDB_DIR}/lib ) -MESSAGE(STATUS "LMDB lib: " ${LMDB_LIBRARIES} ) -MESSAGE(STATUS "LMDB include: " ${LMDB_INCLUDE} ) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LMDB DEFAULT_MSG LMDB_INCLUDE_DIR LMDB_LIBRARIES) - -mark_as_advanced(LMDB_INCLUDE_DIR LMDB_LIBRARIES) diff --git a/CMakeScripts/FindLevelDB.cmake b/CMakeScripts/FindLevelDB.cmake deleted file mode 100644 index f3386f26dbf..00000000000 --- a/CMakeScripts/FindLevelDB.cmake +++ /dev/null @@ -1,37 +0,0 @@ -# - Find LevelDB -# -# LEVELDB_INCLUDE - Where to find leveldb/db.h -# LEVELDB_LIBS - List of libraries when using LevelDB. -# LEVELDB_FOUND - True if LevelDB found. - -get_filename_component(module_file_path ${CMAKE_CURRENT_LIST_FILE} PATH) - -# Look for the header file. -find_path(LEVELDB_INCLUDE NAMES leveldb/db.h PATHS $ENV{LEVELDB_ROOT}/include /opt/local/include /usr/local/include /usr/include DOC "Path in which the file leveldb/db.h is located." ) -mark_as_advanced(LEVELDB_INCLUDE) - -# Look for the library. -# Does this work on UNIX systems? (LINUX) -find_library(LEVELDB_LIBS NAMES leveldb PATHS /usr/lib $ENV{LEVELDB_ROOT}/lib DOC "Path to leveldb library." ) -mark_as_advanced(LEVELDB_LIBS) - -# Copy the results to the output variables. -if (LEVELDB_INCLUDE AND LEVELDB_LIBS) - message(STATUS "Found leveldb in ${LEVELDB_INCLUDE} ${LEVELDB_LIBS}") - set(LEVELDB_FOUND 1) - include(CheckCXXSourceCompiles) - set(CMAKE_REQUIRED_LIBRARY ${LEVELDB_LIBS} pthread) - set(CMAKE_REQUIRED_INCLUDES ${LEVELDB_INCLUDE}) - else () - set(LEVELDB_FOUND 0) - endif () - - # Report the results. - if (NOT LEVELDB_FOUND) - set(LEVELDB_DIR_MESSAGE "LEVELDB was not found. Make sure LEVELDB_LIBS and LEVELDB_INCLUDE are set.") - if (LEVELDB_FIND_REQUIRED) - message(FATAL_ERROR "${LEVELDB_DIR_MESSAGE}") - elseif (NOT LEVELDB_FIND_QUIETLY) - message(STATUS "${LEVELDB_DIR_MESSAGE}") - endif () - endif () \ No newline at end of file diff --git a/CMakeScripts/FindNumPy.cmake b/CMakeScripts/FindNumPy.cmake deleted file mode 100644 index baf21541e63..00000000000 --- a/CMakeScripts/FindNumPy.cmake +++ /dev/null @@ -1,103 +0,0 @@ -# - Find the NumPy libraries -# This module finds if NumPy is installed, and sets the following variables -# indicating where it is. -# -# TODO: Update to provide the libraries and paths for linking npymath lib. -# -# NUMPY_FOUND - was NumPy found -# NUMPY_VERSION - the version of NumPy found as a string -# NUMPY_VERSION_MAJOR - the major version number of NumPy -# NUMPY_VERSION_MINOR - the minor version number of NumPy -# NUMPY_VERSION_PATCH - the patch version number of NumPy -# NUMPY_VERSION_DECIMAL - e.g. version 1.6.1 is 10601 -# NUMPY_INCLUDE_DIRS - path to the NumPy include files - -#============================================================================ -# Copyright 2012 Continuum Analytics, Inc. -# -# MIT License -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -#============================================================================ - -# Finding NumPy involves calling the Python interpreter -if(NumPy_FIND_REQUIRED) - find_package(PythonInterp REQUIRED) -else() - find_package(PythonInterp) -endif() - -if(NOT PYTHONINTERP_FOUND) - set(NUMPY_FOUND FALSE) - return() -endif() - -execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" - "import numpy as n; print(n.__version__); print(n.get_include());" - RESULT_VARIABLE _NUMPY_SEARCH_SUCCESS - OUTPUT_VARIABLE _NUMPY_VALUES_OUTPUT - ERROR_VARIABLE _NUMPY_ERROR_VALUE - OUTPUT_STRIP_TRAILING_WHITESPACE) - -if(NOT _NUMPY_SEARCH_SUCCESS MATCHES 0) - if(NumPy_FIND_REQUIRED) - message(FATAL_ERROR - "NumPy import failure:\n${_NUMPY_ERROR_VALUE}") - endif() - set(NUMPY_FOUND FALSE) - return() -endif() - -# Convert the process output into a list -string(REGEX REPLACE ";" "\\\\;" _NUMPY_VALUES ${_NUMPY_VALUES_OUTPUT}) -string(REGEX REPLACE "\n" ";" _NUMPY_VALUES ${_NUMPY_VALUES}) -# Just in case there is unexpected output from the Python command. -list(GET _NUMPY_VALUES -2 NUMPY_VERSION) -list(GET _NUMPY_VALUES -1 NUMPY_INCLUDE_DIRS) - -string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" _VER_CHECK "${NUMPY_VERSION}") -if("${_VER_CHECK}" STREQUAL "") - # The output from Python was unexpected. Raise an error always - # here, because we found NumPy, but it appears to be corrupted somehow. - message(FATAL_ERROR - "Requested version and include path from NumPy, got instead:\n${_NUMPY_VALUES_OUTPUT}\n") - return() -endif() - -# Make sure all directory separators are '/' -string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIRS ${NUMPY_INCLUDE_DIRS}) - -# Get the major and minor version numbers -string(REGEX REPLACE "\\." ";" _NUMPY_VERSION_LIST ${NUMPY_VERSION}) -list(GET _NUMPY_VERSION_LIST 0 NUMPY_VERSION_MAJOR) -list(GET _NUMPY_VERSION_LIST 1 NUMPY_VERSION_MINOR) -list(GET _NUMPY_VERSION_LIST 2 NUMPY_VERSION_PATCH) -string(REGEX MATCH "[0-9]*" NUMPY_VERSION_PATCH ${NUMPY_VERSION_PATCH}) -math(EXPR NUMPY_VERSION_DECIMAL - "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}") - -find_package_message(NUMPY - "Found NumPy: version \"${NUMPY_VERSION}\" ${NUMPY_INCLUDE_DIRS}" - "${NUMPY_INCLUDE_DIRS}${NUMPY_VERSION}") - -set(NUMPY_FOUND TRUE) - - diff --git a/CMakeScripts/FindProtobuf.cmake b/CMakeScripts/FindProtobuf.cmake deleted file mode 100644 index 0f94f498197..00000000000 --- a/CMakeScripts/FindProtobuf.cmake +++ /dev/null @@ -1,152 +0,0 @@ -# Locate and configure the Google Protocol Buffers library. -# Defines the following variables: -# -# PROTOBUF_FOUND - Found the Google Protocol Buffers library -# PROTOBUF_INCLUDE_DIRS - Include directories for Google Protocol Buffers -# PROTOBUF_LIBRARIES - The protobuf library -# -# The following cache variables are also defined: -# PROTOBUF_LIBRARY - The protobuf library -# PROTOBUF_PROTOC_LIBRARY - The protoc library -# PROTOBUF_INCLUDE_DIR - The include directory for protocol buffers -# PROTOBUF_PROTOC_EXECUTABLE - The protoc compiler -# -# ==================================================================== -# Example: -# -# find_package(Protobuf REQUIRED) -# include_directories(${PROTOBUF_INCLUDE_DIRS}) -# -# include_directories(${CMAKE_CURRENT_BINARY_DIR}) -# PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS foo.proto) -# add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS}) -# target_link_libraries(bar ${PROTOBUF_LIBRARY}) -# -# NOTE: You may need to link against pthreads, depending -# on the platform. -# ==================================================================== -# -# PROTOBUF_GENERATE_CPP (public function) -# SRCS = Variable to define with autogenerated -# source files -# HDRS = Variable to define with autogenerated -# header files -# ARGN = proto files -# -# ==================================================================== - - -#============================================================================= -# Copyright 2009 Kitware, Inc. -# Copyright 2009 Philip Lowman -# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distributed this file outside of CMake, substitute the full -# License text for the above reference.) - -function(PROTOBUF_GENERATE_PYTHON SRCS) - if(NOT ARGN) - message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files") - return() - endif(NOT ARGN) - - set(${SRCS}) - foreach(FIL ${ARGN}) - get_filename_component(ABS_FIL ${FIL} ABSOLUTE) - get_filename_component(FIL_WE ${FIL} NAME_WE) - - - list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py") - - add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py" - COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} - ARGS --python_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} -${ABS_FIL} - DEPENDS ${ABS_FIL} - COMMENT "Running Python protocol buffer compiler on ${FIL}" - VERBATIM ) - endforeach() - - - set_source_files_properties(${${SRCS}} PROPERTIES GENERATED TRUE) - set(${SRCS} ${${SRCS}} PARENT_SCOPE) -endfunction() - - -function(PROTOBUF_GENERATE_CPP SRCS HDRS) - if(NOT ARGN) - message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files") - return() - endif(NOT ARGN) - - set(${SRCS}) - set(${HDRS}) - foreach(FIL ${ARGN}) - get_filename_component(ABS_FIL ${FIL} ABSOLUTE) - get_filename_component(FIL_WE ${FIL} NAME_WE) - - list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc") - list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h") - - add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc" - "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h" - COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} - ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} -${ABS_FIL} - DEPENDS ${ABS_FIL} - COMMENT "Running C++ protocol buffer compiler on ${FIL}" - VERBATIM ) - endforeach() - - set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE) - set(${SRCS} ${${SRCS}} PARENT_SCOPE) - set(${HDRS} ${${HDRS}} PARENT_SCOPE) -endfunction() - - -find_path(PROTOBUF_INCLUDE_DIR google/protobuf/service.h) - -# Google's provided vcproj files generate libraries with a "lib" -# prefix on Windows -if(WIN32) - set(PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}") - set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "") -endif() - -find_library(PROTOBUF_LIBRARY NAMES protobuf - DOC "The Google Protocol Buffers Library" -) -find_library(PROTOBUF_PROTOC_LIBRARY NAMES protoc - DOC "The Google Protocol Buffers Compiler Library" -) -find_program(PROTOBUF_PROTOC_EXECUTABLE NAMES protoc - DOC "The Google Protocol Buffers Compiler" -) - -mark_as_advanced(PROTOBUF_INCLUDE_DIR - PROTOBUF_LIBRARY - PROTOBUF_PROTOC_LIBRARY - PROTOBUF_PROTOC_EXECUTABLE) - -# Restore original find library prefixes -if(WIN32) - set(CMAKE_FIND_LIBRARY_PREFIXES "${PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES}") -endif() - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG - PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR) - -if(PROTOBUF_FOUND) - set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR}) - set(PROTOBUF_LIBRARIES ${PROTOBUF_LIBRARY}) -endif() diff --git a/CMakeScripts/FindSnappy.cmake b/CMakeScripts/FindSnappy.cmake deleted file mode 100644 index d769b442812..00000000000 --- a/CMakeScripts/FindSnappy.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# Find the Snappy libraries -# -# The following variables are optionally searched for defaults -# Snappy_ROOT_DIR: Base directory where all Snappy components are found -# -# The following are set after configuration is done: -# Snappy_FOUND -# Snappy_INCLUDE_DIRS -# Snappy_LIBS - -find_path(SNAPPY_INCLUDE_DIR - NAMES snappy.h - HINTS ${SNAPPY_ROOT_DIR} - ${SNAPPY_ROOT_DIR}/include -) - -find_library(SNAPPY_LIBS - NAMES snappy - HINTS ${SNAPPY_ROOT_DIR} - ${SNAPPY_ROOT_DIR}/lib -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Snappy - DEFAULT_MSG - SNAPPY_LIBS - SNAPPY_INCLUDE_DIR -) - -mark_as_advanced( - SNAPPY_LIBS - SNAPPY_INCLUDE_DIR -) diff --git a/cmake/ConfigGen.cmake b/cmake/ConfigGen.cmake new file mode 100644 index 00000000000..24f23e9c494 --- /dev/null +++ b/cmake/ConfigGen.cmake @@ -0,0 +1,86 @@ + +################################################################################################ +# Helper function to fetch caffe includes which will be passed to dependent projects +# Usage: +# caffe_get_current_includes() +function(caffe_get_current_includes includes_variable) + get_property(current_includes DIRECTORY PROPERTY INCLUDE_DIRECTORIES) + caffe_convert_absolute_paths(current_includes) + + # remove at most one ${CMAKE_BINARY_DIR} include added for caffe_config.h + list(FIND current_includes ${CMAKE_BINARY_DIR} __index) + list(REMOVE_AT current_includes ${__index}) + + caffe_list_unique(current_includes) + set(${includes_variable} ${current_includes} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Helper function to get all list items that begin with given prefix +# Usage: +# caffe_get_items_with_prefix( ) +function(caffe_get_items_with_prefix prefix list_variable output_variable) + set(__result "") + foreach(__e ${${list_variable}}) + if(__e MATCHES "^${prefix}.*") + list(APPEND __result ${__e}) + endif() + endforeach() + set(${output_variable} ${__result} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Function for generation Caffe build- and install- tree export config files +# Usage: +# caffe_generate_export_configs() +function(caffe_generate_export_configs) + set(install_cmake_suffix "share/Caffe") + + # ---[ Configure build-tree CaffeConfig.cmake file ]--- + caffe_get_current_includes(Caffe_INCLUDE_DIRS) + if(NOT HAVE_CUDA) + set(HAVE_CUDA FALSE) + set(Caffe_DEFINITIONS -DCPU_ONLY) + endif() + if(NOT HAVE_CUDNN) + set(HAVE_CUDNN FALSE) + else() + set(Caffe_DEFINITIONS -DUSE_CUDNN) + endif() + + configure_file("cmake/Templates/CaffeConfig.cmake.in" "${CMAKE_BINARY_DIR}/CaffeConfig.cmake" @ONLY) + + # Add targets to the build-tree export set + export(TARGETS caffe proto FILE "${CMAKE_BINARY_DIR}/CaffeTargets.cmake") + export(PACKAGE Caffe) + + # ---[ Configure install-tree CaffeConfig.cmake file ]--- + + # remove source and build dir includes + caffe_get_items_with_prefix(${CMAKE_SOURCE_DIR} Caffe_INCLUDE_DIRS __insource) + caffe_get_items_with_prefix(${CMAKE_BINARY_DIR} Caffe_INCLUDE_DIRS __inbinary) + list(REMOVE_ITEM Caffe_INCLUDE_DIRS ${__insource} ${__inbinary}) + + # add `install` include folder + set(lines + "get_filename_component(__caffe_include \"\${Caffe_CMAKE_DIR}/../../include\" ABSOLUTE)\n" + "list(APPEND Caffe_INCLUDE_DIRS \${__caffe_include})\n" + "unset(__caffe_include)\n") + string(REPLACE ";" "" Caffe_INSTALL_INCLUDE_DIR_APPEND_COMMAND ${lines}) + + configure_file("cmake/Templates/CaffeConfig.cmake.in" "${CMAKE_BINARY_DIR}/cmake/CaffeConfig.cmake" @ONLY) + + # Install the CaffeConfig.cmake and export set to use wuth install-tree + install(FILES "${CMAKE_BINARY_DIR}/cmake/CaffeConfig.cmake" DESTINATION ${install_cmake_suffix}) + install(EXPORT CaffeTargets DESTINATION ${install_cmake_suffix}) + + # ---[ Configure and install version file ]--- + + # TODO: Lines below are commented because Caffe does't declare its version in headers. + # When the declarations are added, modify `caffe_extract_caffe_version()` macro and uncomment + + # configure_file(cmake/Templates/CaffeConfigVersion.cmake.in "${CMAKE_BINARY_DIR}/CaffeConfigVersion.cmake" @ONLY) + # install(FILES "${CMAKE_BINARY_DIR}/CaffeConfigVersion.cmake" DESTINATION ${install_cmake_suffix}) +endfunction() + + diff --git a/cmake/Cuda.cmake b/cmake/Cuda.cmake new file mode 100644 index 00000000000..42a94e5a295 --- /dev/null +++ b/cmake/Cuda.cmake @@ -0,0 +1,243 @@ +if(CPU_ONLY) + return() +endif() + +# Known NVIDIA GPU achitectures Caffe can be compiled for. +# This list will be used for CUDA_ARCH_NAME = All option +set(Caffe_known_gpu_archs "20 21(20) 30 35 50") + +################################################################################################ +# A function for automatic detection of GPUs installed (if autodetection is enabled) +# Usage: +# caffe_detect_installed_gpus(out_variable) +function(caffe_detect_installed_gpus out_variable) + if(NOT CUDA_gpu_detect_output) + set(__cufile ${CMAKE_BINARY_DIR}/detect_cuda_archs.cu) + + file(WRITE ${__cufile} "" + "#include \n" + "int main()\n" + "{\n" + " int count = 0;\n" + " if (cudaSuccess != cudaGetDeviceCount(&count)) return -1;\n" + " if (count == 0) return -1;\n" + " for (int device = 0; device < count; ++device)\n" + " {\n" + " cudaDeviceProp prop;\n" + " if (cudaSuccess == cudaGetDeviceProperties(&prop, device))\n" + " std::printf(\"%d.%d \", prop.major, prop.minor);\n" + " }\n" + " return 0;\n" + "}\n") + + execute_process(COMMAND "${CUDA_NVCC_EXECUTABLE}" "--run" "${__cufile}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/CMakeFiles/" + RESULT_VARIABLE __nvcc_res OUTPUT_VARIABLE __nvcc_out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(__nvcc_res EQUAL 0) + string(REPLACE "2.1" "2.1(2.0)" __nvcc_out "${__nvcc_out}") + set(CUDA_gpu_detect_output ${__nvcc_out} CACHE INTERNAL "Returned GPU architetures from caffe_detect_gpus tool" FORCE) + endif() + endif() + + if(NOT CUDA_gpu_detect_output) + message(STATUS "Automatic GPU detection failed. Building for all known architectures.") + set(${out_variable} ${Caffe_known_gpu_archs} PARENT_SCOPE) + else() + set(${out_variable} ${CUDA_gpu_detect_output} PARENT_SCOPE) + endif() +endfunction() + + +################################################################################################ +# Function for selecting GPU arch flags for nvcc based on CUDA_ARCH_NAME +# Usage: +# caffe_select_nvcc_arch_flags(out_variable) +function(caffe_select_nvcc_arch_flags out_variable) + # List of arch names + set(__archs_names "Fermi" "Kepler" "Maxwell" "All" "Manual") + set(__archs_name_default "All") + if(NOT CMAKE_CROSSCOMPILING) + list(APPEND __archs_names "Auto") + set(__archs_name_default "Auto") + endif() + + # set CUDA_ARCH_NAME strings (so it will be seen as dropbox in CMake-Gui) + set(CUDA_ARCH_NAME ${__archs_name_default} CACHE STRING "Select target NVIDIA GPU achitecture.") + set_property( CACHE CUDA_ARCH_NAME PROPERTY STRINGS "" ${__archs_names} ) + mark_as_advanced(CUDA_ARCH_NAME) + + # verify CUDA_ARCH_NAME value + if(NOT ";${__archs_names};" MATCHES ";${CUDA_ARCH_NAME};") + string(REPLACE ";" ", " __archs_names "${__archs_names}") + message(FATAL_ERROR "Only ${__archs_names} architeture names are supported.") + endif() + + if(${CUDA_ARCH_NAME} STREQUAL "Manual") + set(CUDA_ARCH_BIN ${Caffe_known_gpu_archs} CACHE STRING "Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported") + set(CUDA_ARCH_PTX "50" CACHE STRING "Specify 'virtual' PTX architectures to build PTX intermediate code for") + mark_as_advanced(CUDA_ARCH_BIN CUDA_ARCH_PTX) + else() + unset(CUDA_ARCH_BIN CACHE) + unset(CUDA_ARCH_PTX CACHE) + endif() + + if(${CUDA_ARCH_NAME} STREQUAL "Fermi") + set(__cuda_arch_bin "20 21(20)") + elseif(${CUDA_ARCH_NAME} STREQUAL "Kepler") + set(__cuda_arch_bin "30 35") + elseif(${CUDA_ARCH_NAME} STREQUAL "Maxwell") + set(__cuda_arch_bin "50") + elseif(${CUDA_ARCH_NAME} STREQUAL "All") + set(__cuda_arch_bin ${Caffe_known_gpu_archs}) + elseif(${CUDA_ARCH_NAME} STREQUAL "Auto") + caffe_detect_installed_gpus(__cuda_arch_bin) + else() # (${CUDA_ARCH_NAME} STREQUAL "Manual") + set(__cuda_arch_bin ${CUDA_ARCH_BIN}) + endif() + + # remove dots and convert to lists + string(REGEX REPLACE "\\." "" __cuda_arch_bin "${__cuda_arch_bin}") + string(REGEX REPLACE "\\." "" __cuda_arch_ptx "${CUDA_ARCH_PTX}") + string(REGEX MATCHALL "[0-9()]+" __cuda_arch_bin "${__cuda_arch_bin}") + string(REGEX MATCHALL "[0-9]+" __cuda_arch_ptx "${__cuda_arch_ptx}") + caffe_list_unique(__cuda_arch_bin __cuda_arch_ptx) + + set(__nvcc_flags "") + set(__nvcc_archs_readable "") + + # Tell NVCC to add binaries for the specified GPUs + foreach(__arch ${__cuda_arch_bin}) + if(__arch MATCHES "([0-9]+)\\(([0-9]+)\\)") + # User explicitly specified PTX for the concrete BIN + list(APPEND __nvcc_flags -gencode arch=compute_${CMAKE_MATCH_2},code=sm_${CMAKE_MATCH_1}) + list(APPEND __nvcc_archs_readable sm_${CMAKE_MATCH_1}) + else() + # User didn't explicitly specify PTX for the concrete BIN, we assume PTX=BIN + list(APPEND __nvcc_flags -gencode arch=compute_${__arch},code=sm_${__arch}) + list(APPEND __nvcc_archs_readable sm_${__arch}) + endif() + endforeach() + + # Tell NVCC to add PTX intermediate code for the specified architectures + foreach(__arch ${__cuda_arch_ptx}) + list(APPEND __nvcc_flags -gencode arch=compute_${__arch},code=compute_${__arch}) + list(APPEND __nvcc_archs_readable compute_${__arch}) + endforeach() + + string(REPLACE ";" " " __nvcc_archs_readable "${__nvcc_archs_readable}") + set(${out_variable} ${__nvcc_flags} PARENT_SCOPE) + set(${out_variable}_readable ${__nvcc_archs_readable} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Short command for cuda comnpilation +# Usage: +# caffe_cuda_compile( ) +macro(caffe_cuda_compile objlist_variable) + foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) + set(${var}_backup_in_cuda_compile_ "${${var}}") + + # we remove /EHa as it generates warnings under windows + string(REPLACE "/EHa" "" ${var} "${${var}}") + + endforeach() + + if(UNIX OR APPLE) + list(APPEND CUDA_NVCC_FLAGS -Xcompiler -fPIC) + endif() + + if(APPLE) + list(APPEND CUDA_NVCC_FLAGS -Xcompiler -Wno-unused-function) + endif() + + cuda_compile(cuda_objcs ${ARGN}) + + foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) + set(${var} "${${var}_backup_in_cuda_compile_}") + unset(${var}_backup_in_cuda_compile_) + endforeach() + + set(${objlist_variable} ${cuda_objcs}) +endmacro() + +################################################################################################ +# Short command for cuDNN detection. Believe it soon will be a part of CUDA toolkit distribution. +# That's why not FindcuDNN.cmake file, but just the macro +# Usage: +# detect_cuDNN() +function(detect_cuDNN) + set(CUDNN_ROOT "" CACHE PATH "CUDNN root folder") + + find_path(CUDNN_INCLUDE cudnn.h + PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDA_TOOLKIT_INCLUDE} + DOC "Path to cuDNN include directory." ) + + get_filename_component(__libpath_hist ${CUDA_CUDART_LIBRARY} PATH) + find_library(CUDNN_LIBRARY NAMES libcudnn.so # libcudnn_static.a + PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDNN_INCLUDE} ${__libpath_hist} + DOC "Path to cuDNN library.") + + if(CUDNN_INCLUDE AND CUDNN_LIBRARY) + set(HAVE_CUDNN TRUE PARENT_SCOPE) + set(CUDNN_FOUND TRUE PARENT_SCOPE) + + mark_as_advanced(CUDNN_INCLUDE CUDNN_LIBRARY CUDNN_ROOT) + message(STATUS "Found cuDNN (include: ${CUDNN_INCLUDE}, library: ${CUDNN_LIBRARY})") + endif() +endfunction() + + +################################################################################################ +### Non macro section +################################################################################################ + +find_package(CUDA 5.5 QUIET) + +if(NOT CUDA_FOUND) + return() +endif() + +set(HAVE_CUDA TRUE) +message(STATUS "CUDA detected: " ${CUDA_VERSION}) +include_directories(SYSTEM ${CUDA_INCLUDE_DIRS}) +list(APPEND Caffe_LINKER_LIBS ${CUDA_CUDART_LIBRARY} + ${CUDA_curand_LIBRARY} ${CUDA_CUBLAS_LIBRARIES}) + +# cudnn detection +if(USE_CUDNN) + detect_cuDNN() + if(HAVE_CUDNN) + add_definitions(-DUSE_CUDNN) + include_directories(SYSTEM ${CUDNN_INCLUDE}) + list(APPEND Caffe_LINKER_LIBS ${CUDNN_LIBRARY}) + endif() +endif() + +# setting nvcc arch flags +caffe_select_nvcc_arch_flags(NVCC_FLAGS_EXTRA) +list(APPEND CUDA_NVCC_FLAGS ${NVCC_FLAGS_EXTRA}) +message(STATUS "Added CUDA NVCC flags for: ${NVCC_FLAGS_EXTRA_readable}") + +# Boost 1.55 workaround, see https://svn.boost.org/trac/boost/ticket/9392 or +# https://github.com/ComputationalRadiationPhysics/picongpu/blob/master/src/picongpu/CMakeLists.txt +if(Boost_VERSION EQUAL 105500) + message(STATUS "Cuda + Boost 1.55: Applying noinline work around") + # avoid warning for CMake >= 2.8.12 + set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} \"-DBOOST_NOINLINE=__attribute__((noinline))\" ") +endif() + +# disable some nvcc diagnostic that apears in boost, glog, glags, opencv, etc. +foreach(diag cc_clobber_ignored integer_sign_change useless_using_declaration set_but_not_used) + list(APPEND CUDA_NVCC_FLAGS -Xcudafe --diag_suppress=${diag}) +endforeach() + +# setting default testing device +if(NOT CUDA_TEST_DEVICE) + set(CUDA_TEST_DEVICE -1) +endif() + +mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD) +mark_as_advanced(CUDA_SDK_ROOT_DIR CUDA_SEPARABLE_COMPILATION) + diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake new file mode 100644 index 00000000000..5de435c350d --- /dev/null +++ b/cmake/Dependencies.cmake @@ -0,0 +1,124 @@ +# This list is required for static linking and exported to CaffeConfig.cmake +set(Caffe_LINKER_LIBS "") + +# ---[ Boost +find_package(Boost 1.46 REQUIRED COMPONENTS system thread) +include_directories(SYSTEM ${Boost_INCLUDE_DIR}) +list(APPEND Caffe_LINKER_LIBS ${Boost_LIBRARIES}) + +# ---[ Threads +find_package(Threads REQUIRED) +list(APPEND Caffe_LINKER_LIBS ${CMAKE_THREAD_LIBS_INIT}) + +# ---[ Google-glog +find_package(Glog REQUIRED) +include_directories(SYSTEM ${GLOG_INCLUDE_DIRS}) +list(APPEND Caffe_LINKER_LIBS ${GLOG_LIBRARIES}) + +# ---[ Google-gflags +find_package(GFlags REQUIRED) +include_directories(SYSTEM ${GFLAGS_INCLUDE_DIRS}) +list(APPEND Caffe_LINKER_LIBS ${GFLAGS_LIBRARIES}) + +# ---[ Google-protobuf +include(cmake/ProtoBuf.cmake) + +# ---[ HDF5 +find_package(HDF5 COMPONENTS HL REQUIRED) +include_directories(SYSTEM ${HDF5_INCLUDE_DIRS}) +list(APPEND Caffe_LINKER_LIBS ${HDF5_LIBRARIES}) + +# ---[ LMDB +find_package(LMDB REQUIRED) +include_directories(SYSTEM ${LMDB_INCLUDE_DIR}) +list(APPEND Caffe_LINKER_LIBS ${LMDB_LIBRARIES}) + +# ---[ LevelDB +find_package(LevelDB REQUIRED) +include_directories(SYSTEM ${LEVELDB_INCLUDE}) +list(APPEND Caffe_LINKER_LIBS ${LevelDB_LIBRARIES}) + +# ---[ Snappy +find_package(Snappy REQUIRED) +include_directories(SYSTEM ${Snappy_INCLUDE_DIR}) +list(APPEND Caffe_LINKER_LIBS ${Snappy_LIBRARIES}) + +# ---[ CUDA +include(cmake/Cuda.cmake) +if(NOT HAVE_CUDA) + if(CPU_ONLY) + message("-- CUDA is disabled. Building without it...") + else() + message("-- CUDA is not detected by cmake. Building without it...") + endif() + + # TODO: remove this not cross platform define in future. Use caffe_config.h instead. + add_definitions(-DCPU_ONLY) +endif() + +# ---[ OpenCV +find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs) +if(NOT OpenCV_FOUND) # if not OpenCV 3.x, then imgcodecs are not found + find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc) +endif() +include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS}) +list(APPEND Caffe_LINKER_LIBS ${OpenCV_LIBS}) +message(STATUS "OpenCV found (${OpenCV_CONFIG_PATH})") + +# ---[ BLAS +if(NOT APPLE) + set(BLAS "Atlas" CACHE STRING "Selected BLAS library") + set_property(CACHE BLAS PROPERTY STRINGS "Atlas;Open;MLK") + + if(BLAS STREQUAL "Atlas" OR BLAS STREQUAL "atlas") + find_package(Atlas REQUIRED) + include_directories(SYSTEM ${Atlas_INCLUDE_DIR}) + list(APPEND Caffe_LINKER_LIBS ${Atlas_LIBRARIES}) + elseif(BLAS STREQUAL "Open" OR BLAS STREQUAL "open") + find_package(OpenBLAS REQUIRED) + include_directories(SYSTEM ${OpenBLAS_INCLUDE_DIR}) + list(APPEND Caffe_LINKER_LIBS ${OpenBLAS_LIB}) + elseif(BLAS STREQUAL "MLK" OR BLAS STREQUAL "mkl") + find_package(MKL REQUIRED) + include_directories(SYSTEM ${MKL_INCLUDE_DIR}) + list(APPEND Caffe_LINKER_LIBS ${MKL_LIBRARIES}) + endif() +elseif(APPLE) + find_package(vecLib REQUIRED) + include_directories(SYSTEM ${vecLib_INCLUDE_DIR}) + list(APPEND Caffe_LINKER_LIBS ${vecLib_LINKER_LIBS}) +endif() + +# ---[ Python +if(BUILD_python) + # disable Python 3 search + find_package(PythonInterp 2.7) + find_package(PythonLibs 2.7) + find_package(NumPy 1.7.1) + find_package(Boost 1.46 COMPONENTS python) + + if(PYTHONLIBS_FOUND AND NUMPY_FOUND AND Boost_PYTHON_FOUND) + set(HAVE_PYTHON TRUE) + endif() +endif() + +# ---[ Matlab +if(BUILD_matlab) + find_package(MatlabMex) + if(MATLABMEX_FOUND) + set(HAVE_MATLAB TRUE) + endif() + + # sudo apt-get install liboctave-dev + find_program(Octave_compiler NAMES mkoctfile DOC "Octave C++ compiler") + + if(HAVE_MATLAB AND Octave_compiler) + set(Matlab_build_mex_using "Matlab" CACHE STRING "Select Matlab or Octave if both detected") + set_property(CACHE Matlab_build_mex_using PROPERTY STRINGS "Matlab;Octave") + endif() +endif() + +# ---[ Doxygen +if(BUILD_docs) + find_package(Doxygen) +endif() diff --git a/cmake/Misc.cmake b/cmake/Misc.cmake new file mode 100644 index 00000000000..68e8a662126 --- /dev/null +++ b/cmake/Misc.cmake @@ -0,0 +1,47 @@ +# ---[ Configurations types +set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Possible configurations" FORCE) +mark_as_advanced(CMAKE_CONFIGURATION_TYPES) + +if(DEFINED CMAKE_BUILD_TYPE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES}) +endif() + +# --[ If user doesn't specify build type then assume release +if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE Release) +endif() + +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(CMAKE_COMPILER_IS_CLANGXX TRUE) +endif() + +# ---[ Solution folders +caffe_option(USE_PROJECT_FOLDERS "IDE Solution folders" (MSVC_IDE OR CMAKE_GENERATOR MATCHES Xcode) ) + +if(USE_PROJECT_FOLDERS) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") +endif() + +# ---[ Install options +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Default install path" FORCE) +endif() + +# ---[ RPATH settings +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE BOOLEAN "Use link paths for shared library rpath") +set(CMAKE_MACOSX_RPATH TRUE) + +# ---[ Funny target +if(UNIX OR APPLE) + add_custom_target(simlink_to_build COMMAND "ln" "-sf" "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/build" + COMMENT "Adding simlink: /build -> ${CMAKE_BINARY_DIR}" ) +endif() + +# ---[ Set debug postfix +set(Caffe_DEBUG_POSTFIX "-d") + +set(CAffe_POSTFIX "") +if(CMAKE_BUILD_TYPE MATCHES "Debug") + set(CAffe_POSTFIX ${Caffe_DEBUG_POSTFIX}) +endif() diff --git a/CMakeScripts/FindAtlas.cmake b/cmake/Modules/FindAtlas.cmake similarity index 63% rename from CMakeScripts/FindAtlas.cmake rename to cmake/Modules/FindAtlas.cmake index 27657a6c7d7..6e1564351c7 100644 --- a/CMakeScripts/FindAtlas.cmake +++ b/cmake/Modules/FindAtlas.cmake @@ -23,14 +23,14 @@ set(Atlas_LIB_SEARCH_PATHS $ENV{Atlas_ROOT_DIR}/lib ) -find_path(Atlas_CBLAS_INCLUDE_DIR NAMES cblas.h PATHS ${Atlas_INCLUDE_SEARCH_PATHS}) +find_path(Atlas_CBLAS_INCLUDE_DIR NAMES cblas.h PATHS ${Atlas_INCLUDE_SEARCH_PATHS}) find_path(Atlas_CLAPACK_INCLUDE_DIR NAMES clapack.h PATHS ${Atlas_INCLUDE_SEARCH_PATHS}) -find_library(Atlas_CBLAS_LIBRARY NAMES ptcblas_r ptcblas cblas_r cblas PATHS ${Atlas_LIB_SEARCH_PATHS}) -find_library(Atlas_BLAS_LIBRARY NAMES atlas_r atlas PATHS ${Atlas_LIB_SEARCH_PATHS}) -find_library(Atlas_LAPACK_LIBRARY NAMES alapack_r alapack lapack_atlas PATHS ${Atlas_LIB_SEARCH_PATHS}) -set(LOOKED_FOR +find_library(Atlas_CBLAS_LIBRARY NAMES ptcblas_r ptcblas cblas_r cblas PATHS ${Atlas_LIB_SEARCH_PATHS}) +find_library(Atlas_BLAS_LIBRARY NAMES atlas_r atlas PATHS ${Atlas_LIB_SEARCH_PATHS}) +find_library(Atlas_LAPACK_LIBRARY NAMES alapack_r alapack lapack_atlas PATHS ${Atlas_LIB_SEARCH_PATHS}) +set(LOOKED_FOR Atlas_CBLAS_INCLUDE_DIR Atlas_CLAPACK_INCLUDE_DIR @@ -43,19 +43,10 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Atlas DEFAULT_MSG ${LOOKED_FOR}) if(ATLAS_FOUND) - + set(Atlas_INCLUDE_DIR ${Atlas_CBLAS_INCLUDE_DIR} ${Atlas_CLAPACK_INCLUDE_DIR}) + set(Atlas_LIBRARIES ${Atlas_LAPACK_LIBRARY} ${Atlas_CBLAS_LIBRARY} ${Atlas_BLAS_LIBRARY}) mark_as_advanced(${LOOKED_FOR}) - set(Atlas_INCLUDE_DIR - ${Atlas_CBLAS_INCLUDE_DIR} - ${Atlas_CLAPACK_INCLUDE_DIR} - ) - - set(Atlas_LIBRARIES - ${Atlas_LAPACK_LIBRARY} - ${Atlas_CBLAS_LIBRARY} - ${Atlas_BLAS_LIBRARY} - ) - + message(STATUS "Found Atlas (include: ${Atlas_CBLAS_INCLUDE_DIR}, library: ${Atlas_BLAS_LIBRARY})") endif(ATLAS_FOUND) diff --git a/CMakeScripts/FindGFlags.cmake b/cmake/Modules/FindGFlags.cmake similarity index 79% rename from CMakeScripts/FindGFlags.cmake rename to cmake/Modules/FindGFlags.cmake index f93c57136a1..146e8455a50 100644 --- a/CMakeScripts/FindGFlags.cmake +++ b/cmake/Modules/FindGFlags.cmake @@ -38,11 +38,13 @@ else() find_library(GFLAGS_LIBRARY gflags) endif() -find_package_handle_standard_args(GFLAGS DEFAULT_MSG - GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY) +find_package_handle_standard_args(GFLAGS DEFAULT_MSG GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY) if(GFLAGS_FOUND) set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR}) set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY}) + message(STATUS "Found gflags (include: ${GFLAGS_INCLUDE_DIR}, library: ${GFLAGS_LIBRARY})") + mark_as_advanced(GFLAGS_LIBRARY_DEBUG GFLAGS_LIBRARY_RELEASE + GFLAGS_LIBRARY GFLAGS_INCLUDE_DIR GFLAGS_ROOT_DIR) endif() diff --git a/CMakeScripts/FindGlog.cmake b/cmake/Modules/FindGlog.cmake similarity index 70% rename from CMakeScripts/FindGlog.cmake rename to cmake/Modules/FindGlog.cmake index 0dc30abdbf5..56c76434897 100644 --- a/CMakeScripts/FindGlog.cmake +++ b/cmake/Modules/FindGlog.cmake @@ -34,15 +34,15 @@ if(MSVC) else() find_library(GLOG_LIBRARY glog PATHS ${GLOG_ROOT_DIR} - PATH_SUFFIXES - lib - lib64) + PATH_SUFFIXES lib lib64) endif() -find_package_handle_standard_args(GLOG DEFAULT_MSG - GLOG_INCLUDE_DIR GLOG_LIBRARY) +find_package_handle_standard_args(GLOG DEFAULT_MSG GLOG_INCLUDE_DIR GLOG_LIBRARY) if(GLOG_FOUND) - set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR}) - set(GLOG_LIBRARIES ${GLOG_LIBRARY}) + set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR}) + set(GLOG_LIBRARIES ${GLOG_LIBRARY}) + message(STATUS "Found glog (include: ${GLOG_INCLUDE_DIR}, library: ${GLOG_LIBRARY})") + mark_as_advanced(GLOG_ROOT_DIR GLOG_LIBRARY_RELEASE GLOG_LIBRARY_DEBUG + GLOG_LIBRARY GLOG_INCLUDE_DIR) endif() diff --git a/CMakeScripts/FindLAPACK.cmake b/cmake/Modules/FindLAPACK.cmake similarity index 100% rename from CMakeScripts/FindLAPACK.cmake rename to cmake/Modules/FindLAPACK.cmake diff --git a/cmake/Modules/FindLMDB.cmake b/cmake/Modules/FindLMDB.cmake new file mode 100644 index 00000000000..8a817fd6f10 --- /dev/null +++ b/cmake/Modules/FindLMDB.cmake @@ -0,0 +1,28 @@ +# Try to find the LMBD libraries and headers +# LMDB_FOUND - system has LMDB lib +# LMDB_INCLUDE_DIR - the LMDB include directory +# LMDB_LIBRARIES - Libraries needed to use LMDB + +# FindCWD based on FindGMP by: +# Copyright (c) 2006, Laurent Montel, +# +# Redistribution and use is allowed according to the terms of the BSD license. + +# Adapted from FindCWD by: +# Copyright 2013 Conrad Steenberg +# Aug 31, 2013 + +find_path(LMDB_INCLUDE_DIR NAMES lmdb.h PATHS "$ENV{LMDB_DIR}/include") +find_library(LMDB_LIBRARIES NAMES lmdb PATHS "$ENV{LMDB_DIR}/lib" ) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LMDB DEFAULT_MSG LMDB_INCLUDE_DIR LMDB_LIBRARIES) + +if(LMDB_FOUND) + message(STATUS "Found lmdb (include: ${LMDB_INCLUDE_DIR}, library: ${LMDB_LIBRARIES})") + mark_as_advanced(LMDB_INCLUDE_DIR LMDB_LIBRARIES) + + caffe_parse_header(${LMDB_INCLUDE_DIR}/lmdb.h + LMDB_VERSION_LINES MDB_VERSION_MAJOR MDB_VERSION_MINOR MDB_VERSION_PATCH) + set(LMDB_VERSION "${MDB_VERSION_MAJOR}.${MDB_VERSION_MINOR}.${MDB_VERSION_PATCH}") +endif() diff --git a/cmake/Modules/FindLevelDB.cmake b/cmake/Modules/FindLevelDB.cmake new file mode 100644 index 00000000000..97f08ac9349 --- /dev/null +++ b/cmake/Modules/FindLevelDB.cmake @@ -0,0 +1,44 @@ +# - Find LevelDB +# +# LevelDB_INCLUDES - List of LevelDB includes +# LevelDB_LIBRARIES - List of libraries when using LevelDB. +# LevelDB_FOUND - True if LevelDB found. + +# Look for the header file. +find_path(LevelDB_INCLUDE NAMES leveldb/db.h + PATHS $ENV{LEVELDB_ROOT}/include /opt/local/include /usr/local/include /usr/include + DOC "Path in which the file leveldb/db.h is located." ) + +# Look for the library. +find_library(LevelDB_LIBRARY NAMES leveldb + PATHS /usr/lib $ENV{LEVELDB_ROOT}/lib + DOC "Path to leveldb library." ) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LevelDB DEFAULT_MSG LevelDB_INCLUDE LevelDB_LIBRARY) + +if(LEVELDB_FOUND) + message(STATUS "Found LevelDB (include: ${LevelDB_INCLUDE}, library: ${LevelDB_LIBRARY})") + set(LevelDB_INCLUDES ${LevelDB_INCLUDE}) + set(LevelDB_LIBRARIES ${LevelDB_LIBRARY}) + mark_as_advanced(LevelDB_INCLUDE LevelDB_LIBRARY) + + if(EXISTS "${LevelDB_INCLUDE}/leveldb/db.h") + file(STRINGS "${LevelDB_INCLUDE}/leveldb/db.h" __version_lines + REGEX "static const int k[^V]+Version[ \t]+=[ \t]+[0-9]+;") + + foreach(__line ${__version_lines}) + if(__line MATCHES "[^k]+kMajorVersion[ \t]+=[ \t]+([0-9]+);") + set(LEVELDB_VERSION_MAJOR ${CMAKE_MATCH_1}) + elseif(__line MATCHES "[^k]+kMinorVersion[ \t]+=[ \t]+([0-9]+);") + set(LEVELDB_VERSION_MINOR ${CMAKE_MATCH_1}) + endif() + endforeach() + + if(LEVELDB_VERSION_MAJOR AND LEVELDB_VERSION_MINOR) + set(LEVELDB_VERSION "${LEVELDB_VERSION_MAJOR}.${LEVELDB_VERSION_MINOR}") + endif() + + caffe_clear_vars(__line __version_lines) + endif() +endif() diff --git a/CMakeScripts/FindMKL.cmake b/cmake/Modules/FindMKL.cmake similarity index 100% rename from CMakeScripts/FindMKL.cmake rename to cmake/Modules/FindMKL.cmake diff --git a/cmake/Modules/FindMatlabMex.cmake b/cmake/Modules/FindMatlabMex.cmake new file mode 100644 index 00000000000..28ae65e7cbb --- /dev/null +++ b/cmake/Modules/FindMatlabMex.cmake @@ -0,0 +1,48 @@ +# This module looks for MatlabMex compiler +# Defines variables: +# Matlab_DIR - Matlab root dir +# Matlab_mex - path to mex compiler +# Matlab_mexext - path to mexext + +if(MSVC) + foreach(__ver "9.30" "7.14" "7.11" "7.10" "7.9" "7.8" "7.7") + get_filename_component(__matlab_root "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${__ver};MATLABROOT]" ABSOLUTE) + if(__matlab_root) + break() + endif() + endforeach() +endif() + +if(APPLE) + foreach(__ver "R2014b" "R2014a" "R2013b" "R2013a" "R2012b" "R2012a" "R2011b" "R2011a" "R2010b" "R2010a") + if(EXISTS /Applications/MATLAB_${__ver}.app) + set(__matlab_root /Applications/MATLAB_${__ver}.app) + break() + endif() + endforeach() +endif() + +if(UNIX) + execute_process(COMMAND which matlab OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE __out RESULT_VARIABLE __res) + + if(__res MATCHES 0) # Suppress `readlink` warning if `which` returned nothing + execute_process(COMMAND which matlab COMMAND xargs readlink + COMMAND xargs dirname COMMAND xargs dirname COMMAND xargs echo -n + OUTPUT_VARIABLE __matlab_root OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() +endif() + + +find_path(Matlab_DIR NAMES bin/mex bin/mexext PATHS ${__matlab_root} + DOC "Matlab directory" NO_DEFAULT_PATH) + +find_program(Matlab_mex NAMES mex mex.bat HINTS ${Matlab_DIR} PATH_SUFFIXES bin NO_DEFAULT_PATH) +find_program(Matlab_mexext NAMES mexext mexext.bat HINTS ${Matlab_DIR} PATH_SUFFIXES bin NO_DEFAULT_PATH) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MatlabMex DEFAULT_MSG Matlab_mex Matlab_mexext) + +if(MATLABMEX_FOUND) + mark_as_advanced(Matlab_mex Matlab_mexext) +endif() diff --git a/cmake/Modules/FindNumPy.cmake b/cmake/Modules/FindNumPy.cmake new file mode 100644 index 00000000000..a671494caba --- /dev/null +++ b/cmake/Modules/FindNumPy.cmake @@ -0,0 +1,58 @@ +# - Find the NumPy libraries +# This module finds if NumPy is installed, and sets the following variables +# indicating where it is. +# +# TODO: Update to provide the libraries and paths for linking npymath lib. +# +# NUMPY_FOUND - was NumPy found +# NUMPY_VERSION - the version of NumPy found as a string +# NUMPY_VERSION_MAJOR - the major version number of NumPy +# NUMPY_VERSION_MINOR - the minor version number of NumPy +# NUMPY_VERSION_PATCH - the patch version number of NumPy +# NUMPY_VERSION_DECIMAL - e.g. version 1.6.1 is 10601 +# NUMPY_INCLUDE_DIR - path to the NumPy include files + +unset(NUMPY_VERSION) +unset(NUMPY_INCLUDE_DIR) + +if(PYTHONINTERP_FOUND) + execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" + "import numpy as n; print(n.__version__); print(n.get_include());" + RESULT_VARIABLE __result + OUTPUT_VARIABLE __output + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(__result MATCHES 0) + string(REGEX REPLACE ";" "\\\\;" __values ${__output}) + string(REGEX REPLACE "\r?\n" ";" __values ${__values}) + list(GET __values 0 NUMPY_VERSION) + list(GET __values 1 NUMPY_INCLUDE_DIR) + + string(REGEX MATCH "^([0-9])+\\.([0-9])+\\.([0-9])+" __ver_check "${NUMPY_VERSION}") + if(NOT "${__ver_check}" STREQUAL "") + set(NUMPY_VERSION_MAJOR ${CMAKE_MATCH_1}) + set(NUMPY_VERSION_MINOR ${CMAKE_MATCH_2}) + set(NUMPY_VERSION_PATCH ${CMAKE_MATCH_3}) + math(EXPR NUMPY_VERSION_DECIMAL + "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}") + string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIR ${NUMPY_INCLUDE_DIR}) + else() + unset(NUMPY_VERSION) + unset(NUMPY_INCLUDE_DIR) + message(STATUS "Requested NumPy version and include path, but got instead:\n${__output}\n") + endif() + endif() +else() + message(STATUS "To find NumPy Python interpretator is required to be found.") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(NumPy REQUIRED_VARS NUMPY_INCLUDE_DIR NUMPY_VERSION + VERSION_VAR NUMPY_VERSION) + +if(NUMPY_FOUND) + message(STATUS "NumPy ver. ${NUMPY_VERSION} found (include: ${NUMPY_INCLUDE_DIR})") +endif() + +caffe_clear_vars(__result __output __error_value __values __ver_check __error_value) + diff --git a/CMakeScripts/FindOpenBLAS.cmake b/cmake/Modules/FindOpenBLAS.cmake similarity index 100% rename from CMakeScripts/FindOpenBLAS.cmake rename to cmake/Modules/FindOpenBLAS.cmake diff --git a/cmake/Modules/FindSnappy.cmake b/cmake/Modules/FindSnappy.cmake new file mode 100644 index 00000000000..eff2a864a7b --- /dev/null +++ b/cmake/Modules/FindSnappy.cmake @@ -0,0 +1,28 @@ +# Find the Snappy libraries +# +# The following variables are optionally searched for defaults +# Snappy_ROOT_DIR: Base directory where all Snappy components are found +# +# The following are set after configuration is done: +# SNAPPY_FOUND +# Snappy_INCLUDE_DIR +# Snappy_LIBRARIES + +find_path(Snappy_INCLUDE_DIR NAMES snappy.h + PATHS ${SNAPPY_ROOT_DIR} ${SNAPPY_ROOT_DIR}/include) + +find_library(Snappy_LIBRARIES NAMES snappy + PATHS ${SNAPPY_ROOT_DIR} ${SNAPPY_ROOT_DIR}/lib) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Snappy DEFAULT_MSG Snappy_INCLUDE_DIR Snappy_LIBRARIES) + +if(SNAPPY_FOUND) + message(STATUS "Found Snappy (include: ${Snappy_INCLUDE_DIR}, library: ${Snappy_LIBRARIES})") + mark_as_advanced(Snappy_INCLUDE_DIR Snappy_LIBRARIES) + + caffe_parse_header(${Snappy_INCLUDE_DIR}/snappy-stubs-public.h + SNAPPY_VERION_LINES SNAPPY_MAJOR SNAPPY_MINOR SNAPPY_PATCHLEVEL) + set(Snappy_VERSION "${SNAPPY_MAJOR}.${SNAPPY_MINOR}.${SNAPPY_PATCHLEVEL}") +endif() + diff --git a/cmake/Modules/FindvecLib.cmake b/cmake/Modules/FindvecLib.cmake new file mode 100644 index 00000000000..9600da43647 --- /dev/null +++ b/cmake/Modules/FindvecLib.cmake @@ -0,0 +1,34 @@ +# Find the vecLib libraries as part of Accelerate.framework or as standalon framework +# +# The following are set after configuration is done: +# VECLIB_FOUND +# vecLib_INCLUDE_DIR +# vecLib_LINKER_LIBS + + +if(NOT APPLE) + return() +endif() + +set(__veclib_include_suffix "Frameworks/vecLib.framework/Versions/Current/Headers") + +find_path(vecLib_INCLUDE_DIR vecLib.h + DOC "vecLib include directory" + PATHS /System/Library/${__veclib_include_suffix} + /System/Library/Frameworks/Accelerate.framework/Versions/Current/${__veclib_include_suffix} + /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(vecLib DEFAULT_MSG vecLib_INCLUDE_DIR) + +if(VECLIB_FOUND) + if(vecLib_INCLUDE_DIR MATCHES "^/System/Library/Frameworks/vecLib.framework.*") + set(vecLib_LINKER_LIBS -lcblas "-framework vecLib") + message(STATUS "Found standalone vecLib.framework") + else() + set(vecLib_LINKER_LIBS -lcblas "-framework Accelerate") + message(STATUS "Found vecLib as part of Accelerate.framework") + endif() + + mark_as_advanced(vecLib_INCLUDE_DIR) +endif() diff --git a/cmake/ProtoBuf.cmake b/cmake/ProtoBuf.cmake new file mode 100644 index 00000000000..bb63c9ed736 --- /dev/null +++ b/cmake/ProtoBuf.cmake @@ -0,0 +1,90 @@ +# Finds Google Protocol Buffers library and compilers and extends +# the standart cmake script with version and python generation support + +find_package( Protobuf REQUIRED ) +include_directories(SYSTEM ${PROTOBUF_INCLUDE_DIR}) +list(APPEND Caffe_LINKER_LIBS ${PROTOBUF_LIBRARIES}) + +# As of Ubuntu 14.04 protoc is no longer a part of libprotobuf-dev package +# and should be installed separately as in: sudo apt-get install protobuf-compiler +if(EXISTS ${PROTOBUF_PROTOC_EXECUTABLE}) + message(STATUS "Found PROTOBUF Compiler: ${PROTOBUF_PROTOC_EXECUTABLE}") +else() + message(FATAL_ERROR "Could not find PROTOBUF Compiler") +endif() + +if(PROTOBUF_FOUND) + # fetches protobuf version + caffe_parse_header(${PROTOBUF_INCLUDE_DIR}/google/protobuf/stubs/common.h VERION_LINE GOOGLE_PROTOBUF_VERSION) + string(REGEX MATCH "([0-9])00([0-9])00([0-9])" PROTOBUF_VERSION ${GOOGLE_PROTOBUF_VERSION}) + set(PROTOBUF_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") + unset(GOOGLE_PROTOBUF_VERSION) +endif() + +# place where to generate protobuf sources +set(proto_gen_folder "${CMAKE_BINARY_DIR}/include/caffe/proto") +include_directories(SYSTEM "${CMAKE_BINARY_DIR}/include") + +set(PROTOBUF_GENERATE_CPP_APPEND_PATH TRUE) + +################################################################################################ +# Modification of standard 'protobuf_generate_cpp()' with output dir parameter and python support +# Usage: +# caffe_protobuf_generate_cpp_py( ) +function(caffe_protobuf_generate_cpp_py output_dir srcs_var hdrs_var python_var) + if(NOT ARGN) + message(SEND_ERROR "Error: caffe_protobuf_generate_cpp_py() called without any proto files") + return() + endif() + + if(PROTOBUF_GENERATE_CPP_APPEND_PATH) + # Create an include path for each file specified + foreach(fil ${ARGN}) + get_filename_component(abs_fil ${fil} ABSOLUTE) + get_filename_component(abs_path ${abs_fil} PATH) + list(FIND _protoc_include ${abs_path} _contains_already) + if(${_contains_already} EQUAL -1) + list(APPEND _protoc_include -I ${abs_path}) + endif() + endforeach() + else() + set(_protoc_include -I ${CMAKE_CURRENT_SOURCE_DIR}) + endif() + + if(DEFINED PROTOBUF_IMPORT_DIRS) + foreach(dir ${PROTOBUF_IMPORT_DIRS}) + get_filename_component(abs_path ${dir} ABSOLUTE) + list(FIND _protoc_include ${abs_path} _contains_already) + if(${_contains_already} EQUAL -1) + list(APPEND _protoc_include -I ${abs_path}) + endif() + endforeach() + endif() + + set(${srcs_var}) + set(${hdrs_var}) + set(${python_var}) + foreach(fil ${ARGN}) + get_filename_component(abs_fil ${fil} ABSOLUTE) + get_filename_component(fil_we ${fil} NAME_WE) + + list(APPEND ${srcs_var} "${output_dir}/${fil_we}.pb.cc") + list(APPEND ${hdrs_var} "${output_dir}/${fil_we}.pb.h") + list(APPEND ${python_var} "${output_dir}/${fil_we}_pb2.py") + + add_custom_command( + OUTPUT "${output_dir}/${fil_we}.pb.cc" + "${output_dir}/${fil_we}.pb.h" + "${output_dir}/${fil_we}_pb2.py" + COMMAND ${CMAKE_COMMAND} -E make_directory "${output_dir}" + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --cpp_out ${output_dir} ${_protoc_include} ${abs_fil} + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --python_out ${output_dir} ${_protoc_include} ${abs_fil} + DEPENDS ${abs_fil} + COMMENT "Running C++/Python protocol buffer compiler on ${fil}" VERBATIM ) + endforeach() + + set_source_files_properties(${${srcs_var}} ${${hdrs_var}} ${${python_var}} PROPERTIES GENERATED TRUE) + set(${srcs_var} ${${srcs_var}} PARENT_SCOPE) + set(${hdrs_var} ${${hdrs_var}} PARENT_SCOPE) + set(${python_var} ${${python_var}} PARENT_SCOPE) +endfunction() diff --git a/cmake/Summary.cmake b/cmake/Summary.cmake new file mode 100644 index 00000000000..756a738c9ab --- /dev/null +++ b/cmake/Summary.cmake @@ -0,0 +1,166 @@ +################################################################################################ +# Caffe status report function. +# Automatically align right column and selects text based on condition. +# Usage: +# caffe_status() +# caffe_status( [ ...]) +# caffe_status( THEN ELSE ) +function(caffe_status text) + set(status_cond) + set(status_then) + set(status_else) + + set(status_current_name "cond") + foreach(arg ${ARGN}) + if(arg STREQUAL "THEN") + set(status_current_name "then") + elseif(arg STREQUAL "ELSE") + set(status_current_name "else") + else() + list(APPEND status_${status_current_name} ${arg}) + endif() + endforeach() + + if(DEFINED status_cond) + set(status_placeholder_length 23) + string(RANDOM LENGTH ${status_placeholder_length} ALPHABET " " status_placeholder) + string(LENGTH "${text}" status_text_length) + if(status_text_length LESS status_placeholder_length) + string(SUBSTRING "${text}${status_placeholder}" 0 ${status_placeholder_length} status_text) + elseif(DEFINED status_then OR DEFINED status_else) + message(STATUS "${text}") + set(status_text "${status_placeholder}") + else() + set(status_text "${text}") + endif() + + if(DEFINED status_then OR DEFINED status_else) + if(${status_cond}) + string(REPLACE ";" " " status_then "${status_then}") + string(REGEX REPLACE "^[ \t]+" "" status_then "${status_then}") + message(STATUS "${status_text} ${status_then}") + else() + string(REPLACE ";" " " status_else "${status_else}") + string(REGEX REPLACE "^[ \t]+" "" status_else "${status_else}") + message(STATUS "${status_text} ${status_else}") + endif() + else() + string(REPLACE ";" " " status_cond "${status_cond}") + string(REGEX REPLACE "^[ \t]+" "" status_cond "${status_cond}") + message(STATUS "${status_text} ${status_cond}") + endif() + else() + message(STATUS "${text}") + endif() +endfunction() + + +################################################################################################ +# Function for fetching Caffe version from git and headers +# Usage: +# caffe_extract_caffe_version() +function(caffe_extract_caffe_version) + set(Caffe_GIT_VERSION "unknown") + find_package(Git) + if(GIT_FOUND) + execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + OUTPUT_VARIABLE Caffe_GIT_VERSION + RESULT_VARIABLE __git_result) + if(NOT ${__git_result} EQUAL 0) + set(Caffe_GIT_VERSION "unknown") + endif() + endif() + + set(Caffe_GIT_VERSION ${Caffe_GIT_VERSION} PARENT_SCOPE) + set(Caffe_VERSION " (Caffe doesn't declare its version in headers)" PARENT_SCOPE) + + # caffe_parse_header(${Caffe_INCLUDE_DIR}/caffe/version.hpp Caffe_VERSION_LINES CAFFE_MAJOR CAFFE_MINOR CAFFE_PATCH) + # set(Caffe_VERSION "${CAFFE_MAJOR}.${CAFFE_MINOR}.${CAFFE_PATCH}" PARENT_SCOPE) + + # or for #define Caffe_VERSION "x.x.x" + # caffe_parse_header_single_define(Caffe ${Caffe_INCLUDE_DIR}/caffe/version.hpp Caffe_VERSION) + # set(Caffe_VERSION ${Caffe_VERSION_STRING} PARENT_SCOPE) + +endfunction() + + +################################################################################################ +# Prints accumulatd caffe configuration summary +# Usage: +# caffe_print_configuration_summary() + +function(caffe_print_configuration_summary) + caffe_extract_caffe_version() + set(Caffe_VERSION ${Caffe_VERSION} PARENT_SCOPE) + + caffe_merge_flag_lists(__flags_rel CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS) + caffe_merge_flag_lists(__flags_deb CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS) + + caffe_status("") + caffe_status("******************* Caffe Configuration Summary *******************") + caffe_status("General:") + caffe_status(" Version : ${Caffe_VERSION}") + caffe_status(" Git : ${Caffe_GIT_VERSION}") + caffe_status(" System : ${CMAKE_SYSTEM_NAME}") + caffe_status(" C++ compiler : ${CMAKE_CXX_COMPILER}") + caffe_status(" Release CXX flags : ${__flags_rel}") + caffe_status(" Debug CXX flags : ${__flags_deb}") + caffe_status(" BUILD_SHARED_LIBS : ${BUILD_SHARED_LIBS}") + caffe_status(" Build type : ${CMAKE_BUILD_TYPE}") + caffe_status(" BUILD_python : ${BUILD_python}") + caffe_status(" BUILD_matlab : ${BUILD_matlab}") + caffe_status(" BUILD_docs : ${BUILD_docs}") + caffe_status(" CPU_ONLY : ${CPU_ONLY}") + caffe_status("") + caffe_status("Dependencies:") + caffe_status(" BLAS : " APPLE THEN "Yes (vecLib)" ELSE "Yes (${BLAS})") + caffe_status(" glog : Yes") + caffe_status(" gflags : Yes") + caffe_status(" protobuf : " PROTOBUF_FOUND THEN "Yes (ver. ${PROTOBUF_VERSION})" ELSE "No" ) + caffe_status(" lmdb : " LMDB_FOUND THEN "Yes (ver. ${LMDB_VERSION})" ELSE "No") + caffe_status(" Snappy : " SNAPPY_FOUND THEN "Yes (ver. ${Snappy_VERSION})" ELSE "No" ) + caffe_status(" LevelDB : " LEVELDB_FOUND THEN "Yes (ver. ${LEVELDB_VERSION})" ELSE "No") + caffe_status(" OpenCV : Yes (ver. ${OpenCV_VERSION})") + caffe_status(" CUDA : " HAVE_CUDA THEN "Yes (ver. ${CUDA_VERSION})" ELSE "No" ) + caffe_status("") + if(HAVE_CUDA) + caffe_status("NVIDIA CUDA:") + caffe_status(" Target GPU(s) : ${CUDA_ARCH_NAME}" ) + caffe_status(" GPU arch(s) : ${NVCC_FLAGS_EXTRA_readable}") + if(USE_CUDNN) + caffe_status(" cuDNN : " HAVE_CUDNN THEN "Yes" ELSE "Not found") + else() + caffe_status(" cuDNN : Disabled") + endif() + caffe_status("") + endif() + if(HAVE_PYTHON) + caffe_status("Python:") + caffe_status(" Interpreter :" PYTHON_EXECUTABLE THEN "${PYTHON_EXECUTABLE} (ver. ${PYTHON_VERSION_STRING})" ELSE "No") + caffe_status(" Libraries :" PYTHONLIBS_FOUND THEN "${PYTHON_LIBRARIES} (ver ${PYTHONLIBS_VERSION_STRING})" ELSE "No") + caffe_status(" NumPy :" NUMPY_FOUND THEN "${NUMPY_INCLUDE_DIR} (ver ${NUMPY_VERSION})" ELSE "No") + caffe_status("") + endif() + if(BUILD_matlab) + caffe_status("Matlab:") + caffe_status(" Matlab :" HAVE_MATLAB THEN "Yes (${Matlab_mex}, ${Matlab_mexext}" ELSE "No") + caffe_status(" Octave :" Octave_compiler THEN "Yes (${Octave_compiler})" ELSE "No") + if(HAVE_MATLAB AND Octave_compiler) + caffe_status(" Build mex using : ${Matlab_build_mex_using}") + endif() + caffe_status("") + endif() + if(BUILD_docs) + caffe_status("Documentaion:") + caffe_status(" Doxygen :" DOXYGEN_FOUND THEN "${DOXYGEN_EXECUTABLE} (${DOXYGEN_VERSION})" ELSE "No") + caffe_status(" config_file : ${DOXYGEN_config_file}") + + caffe_status("") + endif() + caffe_status("Install:") + caffe_status(" Install path : ${CMAKE_INSTALL_PREFIX}") + caffe_status("") +endfunction() + diff --git a/cmake/Targets.cmake b/cmake/Targets.cmake new file mode 100644 index 00000000000..84a2aaf58e9 --- /dev/null +++ b/cmake/Targets.cmake @@ -0,0 +1,170 @@ +################################################################################################ +# Defines global Caffe_LINK flag, This flag is required to prevent linker from excluding +# some objects which are not addressed directly but are registered via static constructors +if(BUILD_SHARED_LIBS) + set(Caffe_LINK caffe) +else() + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(Caffe_LINK -Wl,-force_load caffe) + elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(Caffe_LINK -Wl,--whole-archive caffe -Wl,--no-whole-archive) + endif() +endif() + +################################################################################################ +# Convenient command to setup source group for IDEs that support this feature (VS, XCode) +# Usage: +# caffe_source_group( GLOB[_RECURSE] ) +function(caffe_source_group group) + cmake_parse_arguments(CAFFE_SOURCE_GROUP "" "" "GLOB;GLOB_RECURSE" ${ARGN}) + if(CAFFE_SOURCE_GROUP_GLOB) + file(GLOB srcs1 ${CAFFE_SOURCE_GROUP_GLOB}) + source_group(${group} FILES ${srcs1}) + endif() + + if(CAFFE_SOURCE_GROUP_GLOB_RECURSE) + file(GLOB_RECURSE srcs2 ${CAFFE_SOURCE_GROUP_GLOB_RECURSE}) + source_group(${group} FILES ${srcs2}) + endif() +endfunction() + +################################################################################################ +# Collecting sources from globbing and appending to output list variable +# Usage: +# caffe_source_group( GLOB[_RECURSE] ) +function(caffe_collect_sources variable) + cmake_parse_arguments(CAFFE_COLLECT_SOURCES "" "" "GLOB;GLOB_RECURSE" ${ARGN}) + if(CAFFE_COLLECT_SOURCES_GLOB) + file(GLOB srcs1 ${CAFFE_COLLECT_SOURCES_GLOB}) + set(${variable} ${variable} ${srcs1}) + endif() + + if(CAFFE_COLLECT_SOURCES_GLOB_RECURSE) + file(GLOB_RECURSE srcs2 ${CAFFE_COLLECT_SOURCES_GLOB_RECURSE}) + set(${variable} ${variable} ${srcs2}) + endif() +endfunction() + +################################################################################################ +# Short command getting caffe sources (assuming standard Caffe code tree) +# Usage: +# caffe_pickup_caffe_sources() +function(caffe_pickup_caffe_sources root) + # put all files in source groups (visible as subfolder in many IDEs) + caffe_source_group("Include" GLOB "${root}/include/caffe/*.h*") + caffe_source_group("Include\\Util" GLOB "${root}/include/caffe/util/*.h*") + caffe_source_group("Include" GLOB "${CMAKE_BINARY_DIR}/caffe_config.h*") + caffe_source_group("Source" GLOB "${root}/src/caffe/*.cpp") + caffe_source_group("Source\\Util" GLOB "${root}/src/caffe/util/*.cpp") + caffe_source_group("Source\\Layers" GLOB "${root}/src/caffe/layers/*.cpp") + caffe_source_group("Source\\Cuda" GLOB "${root}/src/caffe/layers/*.cu") + caffe_source_group("Source\\Cuda" GLOB "${root}/src/caffe/util/*.cu") + caffe_source_group("Source\\Proto" GLOB "${root}/src/caffe/proto/*.proto") + + # source groups for test target + caffe_source_group("Include" GLOB "${root}/include/caffe/test/test_*.h*") + caffe_source_group("Source" GLOB "${root}/src/caffe/test/test_*.cpp") + caffe_source_group("Source\\Cuda" GLOB "${root}/src/caffe/test/test_*.cu") + + # collect files + file(GLOB test_hdrs ${root}/include/caffe/test/test_*.h*) + file(GLOB test_srcs ${root}/src/caffe/test/test_*.cpp) + file(GLOB_RECURSE hdrs ${root}/include/caffe/*.h*) + file(GLOB_RECURSE srcs ${root}/src/caffe/*.cpp) + list(REMOVE_ITEM hdrs ${test_hdrs}) + list(REMOVE_ITEM srcs ${test_srcs}) + + # adding headers to make the visible in some IDEs (Qt, VS, Xcode) + list(APPEND srcs ${hdrs} ${CMAKE_BINARY_DIR}/caffe_config.h) + list(APPEND test_srcs ${test_hdrs}) + + # collect cuda files + file(GLOB test_cuda ${root}/src/caffe/test/test_*.cu) + file(GLOB_RECURSE cuda ${root}/src/caffe/*.cu) + list(REMOVE_ITEM cuda ${test_cuda}) + + # add proto to make them editable in IDEs too + file(GLOB_RECURSE proto_files ${root}/src/caffe/*.proto) + list(APPEND srcs ${proto_files}) + + # convet to absolute paths + caffe_convert_absolute_paths(srcs) + caffe_convert_absolute_paths(cuda) + caffe_convert_absolute_paths(test_srcs) + caffe_convert_absolute_paths(test_cuda) + + # propogate to parent scope + set(srcs ${srcs} PARENT_SCOPE) + set(cuda ${cuda} PARENT_SCOPE) + set(test_srcs ${test_srcs} PARENT_SCOPE) + set(test_cuda ${test_cuda} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Short command for setting defeault target properties +# Usage: +# caffe_default_properties() +function(caffe_default_properties target) + set_target_properties(${target} PROPERTIES + DEBUG_POSTFIX ${Caffe_DEBUG_POSTFIX} + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") +endfunction() + +################################################################################################ +# Short command for setting runtime directory for build target +# Usage: +# caffe_set_runtime_directory( ) +function(caffe_set_runtime_directory target dir) + set_target_properties(${target} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${dir}") +endfunction() + +################################################################################################ +# Short command for setting solution folder property for target +# Usage: +# caffe_set_solution_folder( ) +function(caffe_set_solution_folder target folder) + if(USE_PROJECT_FOLDERS) + set_target_properties(${target} PROPERTIES FOLDER "${folder}") + endif() +endfunction() + +################################################################################################ +# Reads lines from input file, prepends source directory to each line and writes to output file +# Usage: +# caffe_configure_testdatafile() +function(caffe_configure_testdatafile file) + file(STRINGS ${file} __lines) + set(result "") + foreach(line ${__lines}) + set(result "${result}${CMAKE_SOURCE_DIR}/${line}\n") + endforeach() + dmsg(${result}) + file(WRITE ${file}.gen.cmake ${result}) +endfunction() + +################################################################################################ +# Filter outs all files that are not inlcuded in selected list +# Usage: +# caffe_leave_only_selected_tests( ) +function(caffe_leave_only_selected_tests file_list) + if(NOT ARGN) + return() # blank list means leave all + endif() + string(REPLACE "," ";" __selected ${ARGN}) + list(APPEND __selected caffe_main) + + set(result "") + foreach(f ${${file_list}}) + get_filename_component(name ${f} NAME_WE) + string(REGEX REPLACE "^test_" "" name ${name}) + list(FIND __selected ${name} __index) + if(NOT __index EQUAL -1) + list(APPEND result ${f}) + endif() + endforeach() + set(${file_list} ${result} PARENT_SCOPE) +endfunction() + diff --git a/cmake/Templates/CaffeConfig.cmake.in b/cmake/Templates/CaffeConfig.cmake.in new file mode 100644 index 00000000000..a4b03d961e0 --- /dev/null +++ b/cmake/Templates/CaffeConfig.cmake.in @@ -0,0 +1,58 @@ +# Config file for the Caffe package. +# +# Note: +# Caffe and this config file depends on opencv, +# so put `find_package(OpenCV)` before searching Caffe +# via `find_package(Caffe)`. All other lib/includes +# dependencies are hard coded int the file +# +# After successful configuration the following variables +# will be defined: +# +# Caffe_INCLUDE_DIRS - Caffe include directories +# Caffe_LIBRARIES - libraries to link against +# Caffe_DEFINITIONS - a list of definitions to pass to compiler +# +# Caffe_HAVE_CUDA - signals about CUDA support +# Caffe_HAVE_CUDNN - signals about cuDNN support + + +# OpenCV dependency + +if(NOT OpenCV_FOUND) + set(Caffe_OpenCV_CONFIG_PATH "@OpenCV_CONFIG_PATH@") + if(Caffe_OpenCV_CONFIG_PATH) + get_filename_component(Caffe_OpenCV_CONFIG_PATH ${Caffe_OpenCV_CONFIG_PATH} ABSOLUTE) + + if(EXISTS ${Caffe_OpenCV_CONFIG_PATH} AND NOT TARGET opencv_core) + message(STATUS "Caffe: using OpenCV config from ${Caffe_OpenCV_CONFIG_PATH}") + include(${Caffe_OpenCV_CONFIG_PATH}/OpenCVModules.cmake) + endif() + + else() + find_package(OpenCV REQUIRED) + endif() + unset(Caffe_OpenCV_CONFIG_PATH) +endif() + +# Compute paths +get_filename_component(Caffe_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +set(Caffe_INCLUDE_DIRS "@Caffe_INCLUDE_DIRS@") + +@Caffe_INSTALL_INCLUDE_DIR_APPEND_COMMAND@ + +# Our library dependencies +if(NOT TARGET caffe AND NOT caffe_BINARY_DIR) + include("${Caffe_CMAKE_DIR}/CaffeTargets.cmake") +endif() + +# List of IMPORTED libs created by CaffeTargets.cmake +set(Caffe_LIBRARIES caffe) + +# Definitions +set(Caffe_DEFINITIONS "@Caffe_DEFINITIONS@") + +# Cuda support variables +set(Caffe_CPU_ONLY @CPU_ONLY@) +set(Caffe_HAVE_CUDA @HAVE_CUDA@) +set(Caffe_HAVE_CUDNN @HAVE_CUDNN@) diff --git a/cmake/Templates/CaffeConfigVersion.cmake.in b/cmake/Templates/CaffeConfigVersion.cmake.in new file mode 100644 index 00000000000..cbfa514f1a6 --- /dev/null +++ b/cmake/Templates/CaffeConfigVersion.cmake.in @@ -0,0 +1,11 @@ +set(PACKAGE_VERSION "@Caffe_VERSION@") + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/cmake/Templates/caffe_config.h.in b/cmake/Templates/caffe_config.h.in new file mode 100644 index 00000000000..6aa22ed7b5c --- /dev/null +++ b/cmake/Templates/caffe_config.h.in @@ -0,0 +1,32 @@ +/* Sources directory */ +#define SOURCE_FOLDER "${CMAKE_SOURCE_DIR}" + +/* Binaries directory */ +#define BINARY_FOLDER "${CMAKE_BINARY_DIR}" + +/* NVIDA Cuda */ +#cmakedefine HAVE_CUDA + +/* NVIDA cuDNN */ +#cmakedefine HAVE_CUDNN +#cmakedefine USE_CUDNN + +/* NVIDA cuDNN */ +#cmakedefine CPU_ONLY + +/* Test device */ +#define CUDA_TEST_DEVICE ${CUDA_TEST_DEVICE} + +/* Temporary (TODO: remove) */ +#if 1 + #define CMAKE_SOURCE_DIR SOURCE_FOLDER "/src/" + #define EXAMPLES_SOURCE_DIR BINARY_FOLDER "/examples/" + #define CMAKE_EXT ".gen.cmake" +#else + #define CMAKE_SOURCE_DIR "src/" + #define EXAMPLES_SOURCE_DIR "examples/" + #define CMAKE_EXT "" +#endif + +/* Matlab */ +#cmakedefine HAVE_MATLAB diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake new file mode 100644 index 00000000000..048123dbe10 --- /dev/null +++ b/cmake/Utils.cmake @@ -0,0 +1,365 @@ +################################################################################################ +# Command alias for debugging messages +# Usage: +# dmgs() +function(dmsg) + message(STATUS ${ARGN}) +endfunction() + +################################################################################################ +# Removes duplicates from list(s) +# Usage: +# caffe_list_unique( [] [...]) +macro(caffe_list_unique) + foreach(__lst ${ARGN}) + if(${__lst}) + list(REMOVE_DUPLICATES ${__lst}) + endif() + endforeach() +endmacro() + +################################################################################################ +# Clears variables from lsit +# Usage: +# caffe_list_unique() +macro(caffe_clear_vars) + foreach(_var ${ARGN}) + unset(${_var}) + endforeach() +endmacro() + +################################################################################################ +# Removes duplicates from string +# Usage: +# caffe_string_unique() +function(caffe_string_unique __string) + if(${__string}) + set(__list ${${__string}}) + separate_arguments(__list) + list(REMOVE_DUPLICATES __list) + foreach(__e ${__list}) + set(__str "${__str} ${__e}") + endforeach() + set(${__string} ${__str} PARENT_SCOPE) + endif() +endfunction() + +################################################################################################ +# Prints list element per line +# Usage: +# caffe_print_list() +function(caffe_print_list) + foreach(e ${ARGN}) + message(STATUS ${e}) + endforeach() +endfunction() + +################################################################################################ +# Function merging lists of compiler flags to single string. +# Usage: +# caffe_merge_flag_lists(out_variable [] [] ...) +function(caffe_merge_flag_lists out_var) + set(__result "") + foreach(__list ${ARGN}) + foreach(__flag ${${__list}}) + string(STRIP ${__flag} __flag) + set(__result "${__result} ${__flag}") + endforeach() + endforeach() + string(STRIP ${__result} __result) + set(${out_var} ${__result} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Converts all paths in list to absolute +# Usage: +# caffe_convert_absolute_paths() +function(caffe_convert_absolute_paths variable) + set(__dlist "") + foreach(__s ${${variable}}) + get_filename_component(__abspath ${__s} ABSOLUTE) + list(APPEND __list ${__abspath}) + endforeach() + set(${variable} ${__list} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Reads set of version defines from the header file +# Usage: +# caffe_parse_header( ..) +macro(caffe_parse_header FILENAME FILE_VAR) + set(vars_regex "") + set(__parnet_scope OFF) + set(__add_cache OFF) + foreach(name ${ARGN}) + if("${name}" STREQUAL "PARENT_SCOPE") + set(__parnet_scope ON) + elseif("${name}" STREQUAL "CACHE") + set(__add_cache ON) + elseif(vars_regex) + set(vars_regex "${vars_regex}|${name}") + else() + set(vars_regex "${name}") + endif() + endforeach() + if(EXISTS "${FILENAME}") + file(STRINGS "${FILENAME}" ${FILE_VAR} REGEX "#define[ \t]+(${vars_regex})[ \t]+[0-9]+" ) + else() + unset(${FILE_VAR}) + endif() + foreach(name ${ARGN}) + if(NOT "${name}" STREQUAL "PARENT_SCOPE" AND NOT "${name}" STREQUAL "CACHE") + if(${FILE_VAR}) + if(${FILE_VAR} MATCHES ".+[ \t]${name}[ \t]+([0-9]+).*") + string(REGEX REPLACE ".+[ \t]${name}[ \t]+([0-9]+).*" "\\1" ${name} "${${FILE_VAR}}") + else() + set(${name} "") + endif() + if(__add_cache) + set(${name} ${${name}} CACHE INTERNAL "${name} parsed from ${FILENAME}" FORCE) + elseif(__parnet_scope) + set(${name} "${${name}}" PARENT_SCOPE) + endif() + else() + unset(${name} CACHE) + endif() + endif() + endforeach() +endmacro() + +################################################################################################ +# Reads single version define from the header file and parses it +# Usage: +# caffe_parse_header_single_define( ) +function(caffe_parse_header_single_define LIBNAME HDR_PATH VARNAME) + set(${LIBNAME}_H "") + if(EXISTS "${HDR_PATH}") + file(STRINGS "${HDR_PATH}" ${LIBNAME}_H REGEX "^#define[ \t]+${VARNAME}[ \t]+\"[^\"]*\".*$" LIMIT_COUNT 1) + endif() + + if(${LIBNAME}_H) + string(REGEX REPLACE "^.*[ \t]${VARNAME}[ \t]+\"([0-9]+).*$" "\\1" ${LIBNAME}_VERSION_MAJOR "${${LIBNAME}_H}") + string(REGEX REPLACE "^.*[ \t]${VARNAME}[ \t]+\"[0-9]+\\.([0-9]+).*$" "\\1" ${LIBNAME}_VERSION_MINOR "${${LIBNAME}_H}") + string(REGEX REPLACE "^.*[ \t]${VARNAME}[ \t]+\"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ${LIBNAME}_VERSION_PATCH "${${LIBNAME}_H}") + set(${LIBNAME}_VERSION_MAJOR ${${LIBNAME}_VERSION_MAJOR} ${ARGN} PARENT_SCOPE) + set(${LIBNAME}_VERSION_MINOR ${${LIBNAME}_VERSION_MINOR} ${ARGN} PARENT_SCOPE) + set(${LIBNAME}_VERSION_PATCH ${${LIBNAME}_VERSION_PATCH} ${ARGN} PARENT_SCOPE) + set(${LIBNAME}_VERSION_STRING "${${LIBNAME}_VERSION_MAJOR}.${${LIBNAME}_VERSION_MINOR}.${${LIBNAME}_VERSION_PATCH}" PARENT_SCOPE) + + # append a TWEAK version if it exists: + set(${LIBNAME}_VERSION_TWEAK "") + if("${${LIBNAME}_H}" MATCHES "^.*[ \t]${VARNAME}[ \t]+\"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$") + set(${LIBNAME}_VERSION_TWEAK "${CMAKE_MATCH_1}" ${ARGN} PARENT_SCOPE) + endif() + if(${LIBNAME}_VERSION_TWEAK) + set(${LIBNAME}_VERSION_STRING "${${LIBNAME}_VERSION_STRING}.${${LIBNAME}_VERSION_TWEAK}" ${ARGN} PARENT_SCOPE) + else() + set(${LIBNAME}_VERSION_STRING "${${LIBNAME}_VERSION_STRING}" ${ARGN} PARENT_SCOPE) + endif() + endif() +endfunction() + +######################################################################################################## +# An option that the user can select. Can accept condition to control when option is available for user. +# Usage: +# caffe_option( "doc string" [IF ]) +function(caffe_option variable description value) + set(__value ${value}) + set(__condition "") + set(__varname "__value") + foreach(arg ${ARGN}) + if(arg STREQUAL "IF" OR arg STREQUAL "if") + set(__varname "__condition") + else() + list(APPEND ${__varname} ${arg}) + endif() + endforeach() + unset(__varname) + if("${__condition}" STREQUAL "") + set(__condition 2 GREATER 1) + endif() + + if(${__condition}) + if("${__value}" MATCHES ";") + if(${__value}) + option(${variable} "${description}" ON) + else() + option(${variable} "${description}" OFF) + endif() + elseif(DEFINED ${__value}) + if(${__value}) + option(${variable} "${description}" ON) + else() + option(${variable} "${description}" OFF) + endif() + else() + option(${variable} "${description}" ${__value}) + endif() + else() + unset(${variable} CACHE) + endif() +endfunction() + +################################################################################################ +# Utility macro for comparing two lists. Used for CMake debugging purposes +# Usage: +# caffe_compare_lists( [description]) +function(caffe_compare_lists list1 list2 desc) + set(__list1 ${${list1}}) + set(__list2 ${${list2}}) + list(SORT __list1) + list(SORT __list2) + list(LENGTH __list1 __len1) + list(LENGTH __list2 __len2) + + if(NOT ${__len1} EQUAL ${__len2}) + message(FATAL_ERROR "Lists are not equal. ${__len1} != ${__len2}. ${desc}") + endif() + + foreach(__i RANGE 1 ${__len1}) + math(EXPR __index "${__i}- 1") + list(GET __list1 ${__index} __item1) + list(GET __list2 ${__index} __item2) + if(NOT ${__item1} STREQUAL ${__item2}) + message(FATAL_ERROR "Lists are not equal. Differ at element ${__index}. ${desc}") + endif() + endforeach() +endfunction() + +################################################################################################ +# Command for disabling warnings for different platforms (see below for gcc and VisualStudio) +# Usage: +# caffe_warnings_disable( -Wshadow /wd4996 ..,) +macro(caffe_warnings_disable) + set(_flag_vars "") + set(_msvc_warnings "") + set(_gxx_warnings "") + + foreach(arg ${ARGN}) + if(arg MATCHES "^CMAKE_") + list(APPEND _flag_vars ${arg}) + elseif(arg MATCHES "^/wd") + list(APPEND _msvc_warnings ${arg}) + elseif(arg MATCHES "^-W") + list(APPEND _gxx_warnings ${arg}) + endif() + endforeach() + + if(NOT _flag_vars) + set(_flag_vars CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + endif() + + if(MSVC AND _msvc_warnings) + foreach(var ${_flag_vars}) + foreach(warning ${_msvc_warnings}) + set(${var} "${${var}} ${warning}") + endforeach() + endforeach() + elseif((CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX) AND _gxx_warnings) + foreach(var ${_flag_vars}) + foreach(warning ${_gxx_warnings}) + if(NOT warning MATCHES "^-Wno-") + string(REPLACE "${warning}" "" ${var} "${${var}}") + string(REPLACE "-W" "-Wno-" warning "${warning}") + endif() + set(${var} "${${var}} ${warning}") + endforeach() + endforeach() + endif() + caffe_clear_vars(_flag_vars _msvc_warnings _gxx_warnings) +endmacro() + +################################################################################################ +# Helper function get current definitions +# Usage: +# caffe_get_current_definitions() +function(caffe_get_current_definitions definitions_var) + get_property(current_definitions DIRECTORY PROPERTY COMPILE_DEFINITIONS) + set(result "") + + foreach(d ${current_definitions}) + list(APPEND result -D${d}) + endforeach() + + caffe_list_unique(result) + set(${definitions_var} ${result} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Helper function get current includes/definitions +# Usage: +# caffe_get_current_cflags() +function(caffe_get_current_cflags cflags_var) + get_property(current_includes DIRECTORY PROPERTY INCLUDE_DIRECTORIES) + caffe_convert_absolute_paths(current_includes) + caffe_get_current_definitions(cflags) + + foreach(i ${current_includes}) + list(APPEND cflags "-I${i}") + endforeach() + + caffe_list_unique(cflags) + set(${cflags_var} ${cflags} PARENT_SCOPE) +endfunction() + +################################################################################################ +# Helper function to parse current linker libs into link directoris, libflags and osx frameworks +# Usage: +# caffe_parse_linker_libs( ) +function(caffe_parse_linker_libs Caffe_LINKER_LIBS_variable folders_var flags_var frameworks_var) + + set(__unspec "") + set(__debug "") + set(__optimized "") + set(__framework "") + set(__varname "__unspec") + + # split libs into debug, optimized, unspecified and frameworks + foreach(list_elem ${${Caffe_LINKER_LIBS_variable}}) + if(list_elem STREQUAL "debug") + set(__varname "__debug") + elseif(list_elem STREQUAL "optimized") + set(__varname "__optimized") + elseif(list_elem MATCHES "^-framework[ \t]+([^ \t].*)") + list(APPEND __framework -framework ${CMAKE_MATCH_1}) + else() + list(APPEND ${__varname} ${list_elem}) + set(__varname "__unspec") + endif() + endforeach() + + # attach debug or optimized libs to unspecified according to current configuration + if(CMAKE_BUILD_TYPE MATCHES "Debug") + set(__libs ${__unspec} ${__debug}) + else() + set(__libs ${__unspec} ${__optimized}) + endif() + + set(libflags "") + set(folders "") + + # convert linker libraries list to link flags + foreach(lib ${__libs}) + if(TARGET ${lib}) + list(APPEND folders $) + list(APPEND libflags -l${lib}) + elseif(lib MATCHES "^-l.*") + list(APPEND libflags ${lib}) + elseif(IS_ABSOLUTE ${lib}) + get_filename_component(name_we ${lib} NAME_WE) + get_filename_component(folder ${lib} PATH) + + string(REGEX MATCH "^lib(.*)" __match ${name_we}) + list(APPEND libflags -l${CMAKE_MATCH_1}) + list(APPEND folders ${folder}) + else() + message(FATAL_ERROR "Logic error. Need to update cmake script") + endif() + endforeach() + + caffe_list_unique(libflags folders) + + set(${folders_var} ${folders} PARENT_SCOPE) + set(${flags_var} ${libflags} PARENT_SCOPE) + set(${frameworks_var} ${__framework} PARENT_SCOPE) +endfunction() diff --git a/CMakeScripts/lint.cmake b/cmake/lint.cmake similarity index 100% rename from CMakeScripts/lint.cmake rename to cmake/lint.cmake diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 00000000000..927bf5bc731 --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,106 @@ +# Building docs script +# Requirements: +# sudo apt-get install doxygen texlive ruby-dev +# sudo gem install jekyll execjs therubyracer + +if(NOT BUILD_docs OR NOT DOXYGEN_FOUND) + return() +endif() + +################################################################################################# +# Gather docs from /examples/**/readme.md +function(gather_readmes_as_prebuild_cmd target gathered_dir root) + set(full_gathered_dir ${root}/${gathered_dir}) + + file(GLOB_RECURSE readmes ${root}/examples/readme.md ${root}/examples/README.md) + foreach(file ${readmes}) + # Only use file if it is to be included in docs. + file(STRINGS ${file} file_lines REGEX "include_in_docs: true") + + if(file_lines) + # Since everything is called readme.md, rename it by its dirname. + file(RELATIVE_PATH file ${root} ${file}) + get_filename_component(folder ${file} PATH) + set(new_filename ${full_gathered_dir}/${folder}.md) + + # folder value might be like /readme.md. That's why make directory. + get_filename_component(new_folder ${new_filename} PATH) + add_custom_command(TARGET ${target} PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${new_folder} + COMMAND ln -sf ${root}/${file} ${new_filename} + COMMENT "Creating simlink ${new_filename} -> ${root}/${file}" + WORKING_DIRECTORY ${root} VERBATIM) + endif() + endforeach() +endfunction() + +################################################################################################ +# Gather docs from examples/*.ipynb and add YAML front-matter. +function(gather_notebooks_as_prebuild_cmd target gathered_dir root) + set(full_gathered_dir ${root}/${gathered_dir}) + + if(NOT PYTHON_EXECUTABLE) + message(STATUS "Python interpeter is not found. Can't include *.ipynb files in docs. Skipping...") + return() + endif() + + file(GLOB_RECURSE notebooks ${root}/examples/*.ipynb) + foreach(file ${notebooks}) + file(RELATIVE_PATH file ${root} ${file}) + set(new_filename ${full_gathered_dir}/${file}) + + get_filename_component(new_folder ${new_filename} PATH) + add_custom_command(TARGET ${target} PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${new_folder} + COMMAND ${PYTHON_EXECUTABLE} scripts/copy_notebook.py ${file} ${new_filename} + COMMENT "Copying notebook ${file} to ${new_filename}" + WORKING_DIRECTORY ${root} VERBATIM) + endforeach() + + set(${outputs_var} ${outputs} PARENT_SCOPE) +endfunction() + +################################################################################################ +########################## [ Non macro part ] ################################################## + +# Gathering is done at each 'make doc' +file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/docs/gathered) + +# Doxygen config file path +set(DOXYGEN_config_file ${CMAKE_SOURCE_DIR}/.Doxyfile CACHE FILEPATH "Doxygen config file") + +# Adding docs target +add_custom_target(docs COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_config_file} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Launching doxygen..." VERBATIM) + +# Gathering examples into docs subfolder +gather_notebooks_as_prebuild_cmd(docs docs/gathered ${CMAKE_SOURCE_DIR}) +gather_readmes_as_prebuild_cmd(docs docs/gathered ${CMAKE_SOURCE_DIR}) + +# Auto detect output directory +file(STRINGS ${DOXYGEN_config_file} config_line REGEX "OUTPUT_DIRECTORY[ \t]+=[^=].*") +if(config_line) + string(REGEX MATCH "OUTPUT_DIRECTORY[ \t]+=([^=].*)" __ver_check "${config_line}") + string(STRIP ${CMAKE_MATCH_1} output_dir) + message(STATUS "Detected Doxygen OUTPUT_DIRECTORY: ${output_dir}") +else() + set(output_dir ./doxygen/) + message(STATUS "Can't find OUTPUT_DIRECTORY in doxygen config file. Try to use default: ${output_dir}") +endif() + +if(NOT IS_ABSOLUTE ${output_dir}) + set(output_dir ${CMAKE_SOURCE_DIR}/${output_dir}) + get_filename_component(output_dir ${output_dir} ABSOLUTE) +endif() + +# creates simlink in docs subfolder to code documentation built by doxygen +add_custom_command(TARGET docs POST_BUILD VERBATIM + COMMAND ln -sfn "${output_dir}/html" doxygen + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs + COMMENT "Creating simlink ${CMAKE_SOURCE_DIR}/docs/doxygen -> ${output_dir}/html") + +# for quick launch of jekyll +add_custom_target(jekyll COMMAND jekyll serve -w -s . -d _site --port=4000 + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs + COMMENT "Launching jekyll..." VERBATIM) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 055f4ef0d35..4df14afbb98 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,16 +1,31 @@ -project( Examples ) +file(GLOB_RECURSE examples_srcs "${CMAKE_SOURCE_DIR}/examples/*.cpp") -file(GLOB_RECURSE EXAMPLES_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) - -foreach(source ${EXAMPLES_SOURCES}) - # get file name - get_filename_component(name ${source} NAME_WE) +foreach(source_file ${examples_srcs}) + # get file name + get_filename_component(name ${source_file} NAME_WE) - #get folder name - get_filename_component(path ${source} PATH) - get_filename_component(folder ${path} NAME_WE) + # get folder name + get_filename_component(path ${source_file} PATH) + get_filename_component(folder ${path} NAME_WE) - add_executable(${name} ${source}) - target_link_libraries(${name} caffe) - set_target_properties(${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${folder}) -endforeach(source) + add_executable(${name} ${source_file}) + target_link_libraries(${name} ${Caffe_LINK}) + caffe_default_properties(${name}) + + # set back RUNTIME_OUTPUT_DIRECTORY + set_target_properties(${name} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/examples/${folder}") + + caffe_set_solution_folder(${name} examples) + + # install + install(TARGETS ${name} DESTINATION bin) + + if(UNIX OR APPLE) + # Funny command to make tutorials work + # TODO: remove in future as soon as naming is standartaized everywhere + set(__outname ${CMAKE_BINARY_DIR}/examples/${folder}/${name}${CAffe_POSTFIX}) + add_custom_command(TARGET ${name} POST_BUILD + COMMAND ln -sf "${__outname}" "${__outname}.bin") + endif() +endforeach() diff --git a/include/caffe/test/test_caffe_main.hpp b/include/caffe/test/test_caffe_main.hpp index 438acf2bf17..bd5f31e063f 100644 --- a/include/caffe/test/test_caffe_main.hpp +++ b/include/caffe/test/test_caffe_main.hpp @@ -15,7 +15,7 @@ using std::cout; using std::endl; #ifdef CMAKE_BUILD - #include + #include "caffe_config.h" #else #define CUDA_TEST_DEVICE -1 #define CMAKE_SOURCE_DIR "src/" diff --git a/matlab/CMakeLists.txt b/matlab/CMakeLists.txt index f6a03ee4625..40d8729ae76 100644 --- a/matlab/CMakeLists.txt +++ b/matlab/CMakeLists.txt @@ -1 +1,72 @@ -project( Matlab ) \ No newline at end of file +# Builds Matlab (or Octave) interface. In case of Matlab caffe must be +# compield as shared library. Octave can link static or shared caffe library +# To install octave run: sudo apt-get install liboctave-dev + +if(NOT BUILD_matlab) + return() +endif() + +if(HAVE_MATLAB AND Octave_compiler) + set(build_using ${Matlab_build_mex_using}) +elseif(HAVE_MATLAB AND NOT Octave_compiler) + set(build_using "Matlab") +elseif(NOT HAVE_MATLAB AND Octave_compiler) + set(build_using "Octave") +else() + return() +endif() + +if(NOT BUILD_SHARED_LIBS AND build_using MATCHES Matlab) + message(FATAL_ERROR "Matlab MEX interface (with default mex options file) can only be built if caffe is compiled as shared library. Please enable 'BUILD_SHARED_LIBS' in CMake. Aternativelly you can switch to Octave compiler.") +endif() + +# helper function to set proper mex file extention +function(caffe_fetch_and_set_proper_mexext mexfile_variable) + execute_process(COMMAND ${Matlab_mexext} OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE res OUTPUT_VARIABLE ext) + if(res MATCHES 0) + get_filename_component(folder ${${mexfile_variable}} PATH) + get_filename_component(name_we ${${mexfile_variable}} NAME_WE) + set(${mexfile_variable} ${folder}/${name_we}.${ext} PARENT_SCOPE) + endif() +endfunction() + +# global settings +file(GLOB Matlab_srcs caffe/matcaffe.cpp) +set(Matlab_caffe_mex ${CMAKE_SOURCE_DIR}/matlab/caffe/caffe.mex) + +caffe_get_current_cflags(cflags) +caffe_parse_linker_libs(Caffe_LINKER_LIBS folders libflags macos_framewoks) +set(folders $ ${folders}) + +# prepare linker flag lists +string(REPLACE ";" ";-L" link_folders "-L${folders}") +string(REPLACE ";" ":" rpath_folders "${folders}") + +if(build_using MATCHES "Matlab") + set(libflags -lcaffe${CAffe_POSTFIX} ${libflags}) # Matlab R2014a complans for -Wl,--whole-archive + + caffe_fetch_and_set_proper_mexext(Matlab_caffe_mex) + add_custom_command(OUTPUT ${Matlab_caffe_mex} COMMAND ${Matlab_mex} + ARGS -output ${Matlab_caffe_mex} ${Matlab_srcs} ${cflags} ${link_folders} ${libflags} + DEPENDS caffe COMMENT "Building Matlab interface: ${Matlab_caffe_mex}" VERBATIM) + add_custom_target(matlab ALL DEPENDS ${Matlab_caffe_mex} SOURCES ${Matlab_srcs}) + +elseif(build_using MATCHES "Octave") + + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(libflags -Wl,-force_load,$ ${libflags}) + elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(libflags -Wl,--whole-archive -lcaffe${CAffe_POSTFIX} -Wl,--no-whole-archive ${libflags}) + endif() + + add_custom_command(OUTPUT ${Matlab_caffe_mex} COMMAND ${Octave_compiler} + ARGS --mex -o ${Matlab_caffe_mex} ${Matlab_srcs} ${cflags} ${link_folders} ${libflags} -Wl,-rpath,${rpath_folders} + DEPENDS caffe COMMENT "Building Octave interface: ${Matlab_caffe_mex}" VERBATIM) + + add_custom_target(octave ALL DEPENDS ${Matlab_caffe_mex} SOURCES ${Matlab_srcs}) +endif() + +# ---[ Install +file(GLOB mfiles caffe/*.m) +install(FILES ${mfiles} ${Matlab_caffe_mex} DESTINATION matlab) + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 6470517d213..e943f691c49 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,58 +1,27 @@ -project( Python ) - -# Python -find_package(PythonLibs 2.7 REQUIRED) - -# Numpy -find_package(NumPy REQUIRED) - -# Boost.Python -find_package(Boost 1.46 COMPONENTS python REQUIRED) - - - -#In case you have both python2 and python3 installed the quickest way to -#compile pycaffe with cmake is to replace the following hardcoded paths. -#Althernativley the Find* scripts could be rewritten to support choice of -#of python version. -#if(${PYTHONLIBS_VERSION_STRING} MATCHES "^[3-9]+\\.[0-9]+(\\.[0-9]+.*)?$") -# -# set( PYTHON_INCLUDE_DIRS "/usr/include/python2.7") -# set( PYTHON_LIBRARIES "/usr/lib64/libpython2.7.so") -# set( NUMPY_INCLUDE_DIRS "/usr/lib64/python2.7/site-packages/numpy/core/include/") -# set( PYTHON_LIBRARIES "/usr/lib64/python2.7/site-packages/numpy/lib/") -# set(Boost_LIBRARIES "/usr/lib64/libboost_python-2.7-mt.so") -# -# message( "Warning: cmake found python3 by default, switching to hardcoded paths") -# -# message( "PYTHON_INCLUDE_DIRS =/usr/include/python2.7") -# message( "PYTHON_LIBRARIES =/usr/lib64/libpython2.7.so") -# message( "NUMPY_INCLUDE_DIRS =/usr/lib64/python2.7/site-packages/numpy/core/include/") -# message( "PYTHON_LIBRARIES =/usr/lib64/python2.7/site-packages/numpy/lib/") -# message( "Boost_LIBRARIES =/usr/lib64/libboost_python-2.7-mt.so") -#endif() - - -include_directories(${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} - ${Boost_INCLUDE_DIRS}) - -file(GLOB_RECURSE Python_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) - -add_library(pycaffe SHARED ${Python_SOURCES}) - -add_dependencies(pycaffe protoPy) - -target_link_libraries(pycaffe ${CAFFE_STATIC_LINK} ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}) - -set_target_properties(pycaffe PROPERTIES PREFIX "") -set_target_properties(pycaffe PROPERTIES OUTPUT_NAME "_caffe") - -### Install ############################################################# - +if(NOT HAVE_PYTHON) + message(STATUS "Python interface is disabled or not all required dependecies found. Building without it...") + return() +endif() + +include_directories(${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIR} ${Boost_INCLUDE_DIRS}) +file(GLOB_RECURSE python_srcs ${CMAKE_SOURCE_DIR}/python/*.cpp) + +add_library(pycaffe SHARED ${python_srcs}) +target_link_libraries(pycaffe ${Caffe_LINK} ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}) +set_target_properties(pycaffe PROPERTIES PREFIX "" OUTPUT_NAME "_caffe") +caffe_default_properties(pycaffe) + +if(UNIX OR APPLE) + set(__linkname "${CMAKE_SOURCE_DIR}/python/_caffe.so") + add_custom_command(TARGET pycaffe POST_BUILD + COMMAND ln -sf $ "${CMAKE_SOURCE_DIR}/python/_caffe.so" + COMMENT "Creating simlink ${__linkname} -> ${CMAKE_BINARY_DIR}/lib/_caffe${CAffe_POSTFIX}.so") +endif() + +# ---[ Install +file(GLOB files *.py requirements.txt) +install(FILES ${files} DESTINATION python) install(DIRECTORY caffe DESTINATION python) -install(FILES requirements.txt DESTINATION python) - -#This installs a library named "libpycaffe.so" install(TARGETS pycaffe DESTINATION python/caffe) diff --git a/src/caffe/CMakeLists.txt b/src/caffe/CMakeLists.txt index dda072688f8..ef74e1f004b 100644 --- a/src/caffe/CMakeLists.txt +++ b/src/caffe/CMakeLists.txt @@ -1,55 +1,36 @@ -project( CaffeSrc ) +# generate protobuf sources +file(GLOB proto_files proto/*.proto) +caffe_protobuf_generate_cpp_py(${proto_gen_folder} proto_srcs proto_hdrs proto_python ${proto_files}) +# include python files either to force generation +add_library(proto STATIC ${proto_hdrs} ${proto_srcs} ${proto_python}) +set(Caffe_LINKER_LIBS proto ${Caffe_LINKER_LIBS}) # note, crucial to prepend! +caffe_default_properties(proto) -add_subdirectory(proto) +# --[ Caffe library -# Recursively find source files -## test sources -file(GLOB_RECURSE TEST_CPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/test_*.cpp) +# creates 'test_srcs', 'srcs', 'test_cuda', 'cuda' lists +caffe_pickup_caffe_sources(${CMAKE_SOURCE_DIR}) -## all cpp sources -file(GLOB_RECURSE CPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +if(HAVE_CUDA) + caffe_cuda_compile(cuda_objs ${cuda}) + list(APPEND srcs ${cuda_objs} ${cuda}) +endif() -## remove test sources from cpp sources -list(REMOVE_ITEM CPP_SOURCES ${TEST_CPP_SOURCES}) +add_library(caffe ${srcs}) +target_link_libraries(caffe proto ${Caffe_LINKER_LIBS}) +caffe_default_properties(caffe) -add_library(caffe ${CPP_SOURCES}) -# both depend on proto -add_dependencies(caffe proto) +# ---[ Tests + add_subdirectory(test) + +# ---[ Install +install(DIRECTORY ${Caffe_INCLUDE_DIR}/caffe DESTINATION include) +install(FILES ${proto_hdrs} DESTINATION include/caffe/proto) +install(TARGETS caffe proto EXPORT CaffeTargets DESTINATION lib) + +file(WRITE ${CMAKE_BINARY_DIR}/__init__.py) +list(APPEND proto_python ${CMAKE_BINARY_DIR}/__init__.py) +install(PROGRAMS ${proto_python} DESTINATION python/caffe/proto) -# cuda sources -if(NOT CPU_ONLY) - file(GLOB_RECURSE CU_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cu) - file(GLOB_RECURSE TEST_CU_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/test_*.cu) - list(REMOVE_ITEM CU_SOURCES ${TEST_CU_SOURCES}) - cuda_add_library(caffe_cu ${CU_SOURCES}) - add_dependencies(caffe_cu proto) - target_link_libraries(caffe caffe_cu - ${CUDA_CUBLAS_LIBRARIES} - ${CUDA_curand_LIBRARY} - ) -endif() -target_link_libraries(caffe proto - ${BLAS_LIBRARIES} - ${Boost_LIBRARIES} - ${GFLAGS_LIBRARIES} - ${GLOG_LIBRARIES} - ${HDF5_LIBRARIES} - ${LEVELDB_LIBS} - ${LMDB_LIBRARIES} - ${OpenCV_LIBS} - ${CMAKE_THREAD_LIBS_INIT} -) - -#set output directory -set_target_properties(caffe PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib -) - -add_subdirectory(test) - -### Install ################################################################################# - -install(TARGETS caffe DESTINATION lib) diff --git a/src/caffe/proto/CMakeLists.txt b/src/caffe/proto/CMakeLists.txt deleted file mode 100644 index 12e7ce0a326..00000000000 --- a/src/caffe/proto/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -project( Proto ) - -# Google Protocol Buffers -find_package( Protobuf REQUIRED ) - -# As of Ubuntu 14.04 protoc is no longer a part of libprotobuf-dev package and should be installed -# separately as in: sudo apt-get install protobuf-compiler -if(PROTOBUF_PROTOC_EXECUTABLE) - message(STATUS "Found PROTOBUF Compiler: ${PROTOBUF_PROTOC_EXECUTABLE}") -else() - message(FATAL_ERROR "Could not find PROTOBUF Compiler") -endif() - -include_directories(${PROTOBUF_INCLUDE_DIR}) -file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto") -PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles}) -PROTOBUF_GENERATE_PYTHON(ProtoSourcesPy ${ProtoFiles}) - -add_custom_target(protoPy DEPENDS ${ProtoSourcesPy}) - -add_library(proto - ${ProtoSources} - ${ProtoHeaders} - ) - - -target_link_libraries(proto ${PROTOBUF_LIBRARIES}) - -# Create proto include directory -file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/include/caffe/proto) - -# Copy proto headers to include/caffe/proto/ -foreach(header ${ProtoHeaders}) - - ADD_CUSTOM_COMMAND(TARGET proto - COMMAND cmake -E copy ${header} - ${Caffe_INCLUDE_DIRS}/caffe/proto/ - DEPENDS ${header} -) - -endforeach(header) - -file(WRITE __init__.py) -install(PROGRAMS __init__.py DESTINATION python/caffe/proto) -install(PROGRAMS ${ProtoSourcesPy} DESTINATION python/caffe/proto) - diff --git a/src/caffe/test/CMakeLists.txt b/src/caffe/test/CMakeLists.txt index ce0aa4c5148..ed374e8e110 100644 --- a/src/caffe/test/CMakeLists.txt +++ b/src/caffe/test/CMakeLists.txt @@ -1,105 +1,36 @@ -# -# -# All test files' names must begin with a "test_" prefix -# -# -project( Test ) - -# Configuration -set(TEST_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) # test executables are going to be placed there -set(TEST_EXT .testbin) # test executable extension -set(ALL_TEST test${TEST_EXT}) # name of an executable comprising of all tests -set(RUN_TEST runtest) # dummy target for running tests -set(TEST_MAIN test_caffe_main.cpp) # main test file (with main function) - -# Generate config files -add_definitions(-DCMAKE_BUILD) # definition needed in order to include CMake's generated files -set(IN_EXT .in) # generator input file extension -set(GEN_EXT .gen.cmake) # generated output file extension -set(TEST_DEFINES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake_test_defines.hpp) -set(TEST_DATA_FILE ${CMAKE_CURRENT_SOURCE_DIR}/test_data/sample_data_list.txt) - -# Function prepares name of a test executable -# @output_name - output variable's name -# @filename - test_*.cpp file path -function(test_name output_name filename) - get_filename_component(name ${filename} NAME_WE) - set(${output_name} ${name}${TEST_EXT} PARENT_SCOPE) -endfunction() - -set(IN_FILES # generator input files - ${TEST_DEFINES_FILE} - ${TEST_DATA_FILE} -) - -foreach(in_file ${IN_FILES}) - configure_file( - ${in_file}${IN_EXT} - ${in_file}${GEN_EXT} - ) -endforeach() - -include_directories( - ${Caffe_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} -) - -# Remove main from test sources and prepare an Object lib with main -file(GLOB TEST_MAIN ${TEST_MAIN}) -list(REMOVE_ITEM TEST_CPP_SOURCES ${TEST_MAIN}) -add_library(main_obj EXCLUDE_FROM_ALL OBJECT ${TEST_MAIN}) - -# Build each test separately from *.cpp files -foreach(source ${TEST_CPP_SOURCES}) - test_name(TEST_NAME ${source}) - - # - add_library(${TEST_NAME}.obj EXCLUDE_FROM_ALL OBJECT ${source}) - set(TEST_OBJ_LIB $) - - add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_OBJ_LIB} $) - target_link_libraries(${TEST_NAME} gtest ${CAFFE_STATIC_LINK}) - - # output dir - set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) - - # Targets and object libs - set(TEST_TARGETS ${TEST_TARGETS} ${TEST_NAME}) - set(TEST_OBJ_LIBS ${TEST_OBJ_LIBS} ${TEST_OBJ_LIB}) -endforeach() - -# Build each test separately from *.cu files -foreach(source ${TEST_CU_SOURCES}) - test_name(TEST_NAME ${source}) - - cuda_add_library(${TEST_NAME}.lib EXCLUDE_FROM_ALL ${source}) - - add_executable(${TEST_NAME} EXCLUDE_FROM_ALL $) - target_link_libraries(${TEST_NAME} ${TEST_NAME}.lib gtest ${CAFFE_STATIC_LINK}) - - # output dir - set_target_properties(${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) - - # Targets and object libs - set(TEST_TARGETS ${TEST_TARGETS} ${TEST_NAME}) - set(TEST_CU_LIBS ${TEST_CU_LIBS} ${TEST_NAME}.lib) -endforeach() - -# Build a compound test excluded from the ALL target -add_executable(${ALL_TEST} EXCLUDE_FROM_ALL ${TEST_OBJ_LIBS} $) -if(NOT CPU_ONLY) - target_link_libraries(${ALL_TEST} ${TEST_CU_LIBS}) +# The option allows to include in build only selected test files and exclude all others +# Usage example: +# cmake -DBUILD_only_tests="common,net,blob,im2col_kernel" +set(BUILD_only_tests "" CACHE STRING "Blank or comma-separated list of test files to build without 'test_' prefix and extention") +caffe_leave_only_selected_tests(test_srcs ${BUILD_only_tests}) +caffe_leave_only_selected_tests(test_cuda ${BUILD_only_tests}) + +# For 'make runtest' target we don't need to embed test data paths to +# source files, because test target is executed in source directory +# That's why the lines below are commented. TODO: remove them + +# definition needed to include CMake generated files +#add_definitions(-DCMAKE_BUILD) + +# generates test_data/sample_data_list.txt.gen.cmake +#caffe_configure_testdatafile(test_data/sample_data_list.txt) + +set(the_target test.testbin) +set(test_args --gtest_shuffle) + +if(HAVE_CUDA) + caffe_cuda_compile(test_cuda_objs ${test_cuda}) + list(APPEND test_srcs ${test_cuda_objs} ${test_cuda}) +else() + list(APPEND test_args --gtest_filter="-*GPU*") endif() -target_link_libraries(${ALL_TEST} gtest ${CAFFE_STATIC_LINK}) -add_dependencies(${ALL_TEST} ${TEST_TARGETS}) -# Output directory -set_target_properties(${ALL_TEST} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TEST_OUTPUT_DIRECTORY}) - -# Test command -set(TEST_ARGS --gtest_shuffle) -if(CPU_ONLY) - set(TEST_ARGS ${TEST_ARGS} --gtest_filter="-*GPU*") -endif() +# ---[ Adding test target +add_executable(${the_target} EXCLUDE_FROM_ALL ${test_srcs}) +target_link_libraries(${the_target} gtest ${Caffe_LINK}) +caffe_default_properties(${the_target}) +caffe_set_runtime_directory(${the_target} "${CMAKE_BINARY_DIR}/test") -add_custom_target(${RUN_TEST} COMMAND ${ALL_TEST} ${TEST_ARGS}) +# ---[ Adding runtest +add_custom_target(runtest COMMAND ${the_target} ${test_args} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) diff --git a/src/caffe/test/cmake_test_defines.hpp.in b/src/caffe/test/cmake_test_defines.hpp.in deleted file mode 100644 index 870eaf5c26e..00000000000 --- a/src/caffe/test/cmake_test_defines.hpp.in +++ /dev/null @@ -1,4 +0,0 @@ -#define CUDA_TEST_DEVICE @CUDA_TEST_DEVICE@ -#define CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/src/" -#define EXAMPLES_SOURCE_DIR "@CMAKE_SOURCE_DIR@/examples/" -#define CMAKE_EXT ".gen.cmake" diff --git a/src/caffe/test/test_data/sample_data_list.txt.in b/src/caffe/test/test_data/sample_data_list.txt.in deleted file mode 100644 index 9860ef583ab..00000000000 --- a/src/caffe/test/test_data/sample_data_list.txt.in +++ /dev/null @@ -1,2 +0,0 @@ -@CMAKE_SOURCE_DIR@/src/caffe/test/test_data/sample_data.h5 -@CMAKE_SOURCE_DIR@/src/caffe/test/test_data/sample_data_2_gzip.h5 \ No newline at end of file diff --git a/src/gtest/CMakeLists.txt b/src/gtest/CMakeLists.txt index 82a4120ca3f..ef7ff7ed14b 100644 --- a/src/gtest/CMakeLists.txt +++ b/src/gtest/CMakeLists.txt @@ -1,6 +1,5 @@ -project(gtest CXX C) -cmake_minimum_required(VERSION 2.6.2) +add_library(gtest STATIC EXCLUDE_FROM_ALL gtest.h gtest-all.cpp) +caffe_default_properties(gtest) -add_library(gtest gtest-all.cpp) -add_library(gtest_main gtest_main.cc) -target_link_libraries(gtest_main gtest) \ No newline at end of file +#add_library(gtest_main gtest_main.cc) +#target_link_libraries(gtest_main gtest) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 110f368b2c8..4e43ba2cf25 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,20 +1,29 @@ -project( Tools ) - -# Find all source files -file(GLOB_RECURSE TOOLS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) - - -# Build each source file independently -foreach(source ${TOOLS_SOURCES}) - get_filename_component(name ${source} NAME_WE) - add_executable(${name}.bin ${source}) - set_target_properties(${name}.bin PROPERTIES OUTPUT_NAME ${name}) - target_link_libraries(${name}.bin ${CAFFE_STATIC_LINK}) - -### Install ################################################################################# - - install(TARGETS ${name}.bin DESTINATION tools) - - +# Collect source files +file(GLOB_RECURSE srcs ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) + +# Build each source file independently +foreach(source ${srcs}) + get_filename_component(name ${source} NAME_WE) + + # caffe target already exits + if(name MATCHES "caffe") + set(name ${name}.bin) + endif() + + # target + add_executable(${name} ${source}) + target_link_libraries(${name} ${Caffe_LINK}) + caffe_default_properties(${name}) + + # set back RUNTIME_OUTPUT_DIRECTORY + caffe_set_runtime_directory(${name} "${CMAKE_BINARY_DIR}/tools") + caffe_set_solution_folder(${name} tools) + + # restore output name without suffix + if(name MATCHES "caffe.bin") + set_target_properties(${name} PROPERTIES OUTPUT_NAME caffe) + endif() + + # Install + install(TARGETS ${name} DESTINATION bin) endforeach(source) - From a12dcba8c9417c5d8f8155e06bdfd6e75fd636ce Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 18 Jan 2015 22:55:26 +0300 Subject: [PATCH 310/798] opencv 3.0 compilation (replace #1714) --- cmake/lint.cmake | 4 +++- src/caffe/layers/window_data_layer.cpp | 5 +---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cmake/lint.cmake b/cmake/lint.cmake index 04df3409e84..585babb3587 100644 --- a/cmake/lint.cmake +++ b/cmake/lint.cmake @@ -1,10 +1,12 @@ -set(CMAKE_SOURCE_DIR ../) +set(CMAKE_SOURCE_DIR ..) set(LINT_COMMAND ${CMAKE_SOURCE_DIR}/scripts/cpp_lint.py) set(SRC_FILE_EXTENSIONS h hpp hu c cpp cu cc) set(EXCLUDE_FILE_EXTENSTIONS pb.h pb.cc) set(LINT_DIRS include src/caffe examples tools python matlab) +cmake_policy(SET CMP0009 NEW) # supress cmake warning + # find all files of interest foreach(ext ${SRC_FILE_EXTENSIONS}) foreach(dir ${LINT_DIRS}) diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 23ec83d166b..3e9e9765ccf 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -22,10 +23,6 @@ // 'source' field specifies the window_file // 'crop_size' indicates the desired warped size -#if CV_VERSION_MAJOR == 3 -const int CV_LOAD_IMAGE_COLOR = cv::IMREAD_COLOR; -#endif - namespace caffe { template From c0ae656c0e80e721fec89b63e2cdc390e440d625 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 18 Jan 2015 23:22:09 +0300 Subject: [PATCH 311/798] [travis] proper cmake params --- scripts/travis/travis_build_and_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/travis/travis_build_and_test.sh b/scripts/travis/travis_build_and_test.sh index 53c6c341101..8ff63f31fdd 100755 --- a/scripts/travis/travis_build_and_test.sh +++ b/scripts/travis/travis_build_and_test.sh @@ -7,7 +7,7 @@ MAKE="make --jobs=$NUM_THREADS --keep-going" if $WITH_CMAKE; then mkdir build cd build - cmake -DBUILD_PYTHON=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release -DCPU_ONLY=ON .. + cmake -DBUILD_python=ON -DCMAKE_BUILD_TYPE=Release -DCPU_ONLY=ON .. $MAKE if ! $WITH_CUDA; then $MAKE runtest From aea5dd674adbccf9927869f5e9ba9e2dfc2cbf21 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 1 Feb 2015 17:45:31 +0300 Subject: [PATCH 312/798] cmake 2.8.7. support --- CMakeLists.txt | 5 +- cmake/ConfigGen.cmake | 11 ++- cmake/Cuda.cmake | 11 +++ cmake/Dependencies.cmake | 5 +- cmake/Misc.cmake | 4 +- cmake/Modules/FindMKL.cmake | 155 ++++++++++++++++++------------------ cmake/Targets.cmake | 3 +- cmake/Utils.cmake | 16 ++++ docs/CMakeLists.txt | 6 +- matlab/CMakeLists.txt | 2 +- python/CMakeLists.txt | 9 ++- 11 files changed, 131 insertions(+), 96 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d3d50da218b..0cace5acfe3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.8) +cmake_minimum_required(VERSION 2.8.7) # ---[ Caffe project project(Caffe C CXX) @@ -28,8 +28,9 @@ if(UNIX OR APLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall") endif() -if(APPLE) +if(USE_libstdcpp) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") + message("-- Warning: forcing libstdc++ (controlled by USE_libstdcpp option in cmake)") endif() add_definitions(-DGTEST_USE_OWN_TR1_TUPLE) diff --git a/cmake/ConfigGen.cmake b/cmake/ConfigGen.cmake index 24f23e9c494..b7cf9f4cc48 100644 --- a/cmake/ConfigGen.cmake +++ b/cmake/ConfigGen.cmake @@ -38,14 +38,21 @@ function(caffe_generate_export_configs) # ---[ Configure build-tree CaffeConfig.cmake file ]--- caffe_get_current_includes(Caffe_INCLUDE_DIRS) + + set(Caffe_DEFINITIONS "") if(NOT HAVE_CUDA) set(HAVE_CUDA FALSE) - set(Caffe_DEFINITIONS -DCPU_ONLY) + list(APPEND Caffe_DEFINITIONS -DCPU_ONLY) endif() + if(NOT HAVE_CUDNN) set(HAVE_CUDNN FALSE) else() - set(Caffe_DEFINITIONS -DUSE_CUDNN) + list(APPEND DEFINITIONS -DUSE_CUDNN) + endif() + + if(BLAS STREQUAL "MKL" OR BLAS STREQUAL "mkl") + list(APPEND Caffe_DEFINITIONS -DUSE_MKL) endif() configure_file("cmake/Templates/CaffeConfig.cmake.in" "${CMAKE_BINARY_DIR}/CaffeConfig.cmake" @ONLY) diff --git a/cmake/Cuda.cmake b/cmake/Cuda.cmake index 42a94e5a295..07fa13789fa 100644 --- a/cmake/Cuda.cmake +++ b/cmake/Cuda.cmake @@ -194,6 +194,7 @@ endfunction() ################################################################################################ find_package(CUDA 5.5 QUIET) +find_cuda_helper_libs(curand) # cmake 2.8.7 compartibility which doesn't search for curand if(NOT CUDA_FOUND) return() @@ -241,3 +242,13 @@ endif() mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD) mark_as_advanced(CUDA_SDK_ROOT_DIR CUDA_SEPARABLE_COMPILATION) +# Handle clang/libc++ issue +if(APPLE) + caffe_detect_darwin_version(OSX_VERSION) + + # OSX 10.9 and higher uses clang/libc++ by default which is incompartible with old CUDA toolkits + if(OSX_VERSION VERSION_GREATER 10.8) + # enabled by default if and only if CUDA version is less than 7.0 + caffe_option(USE_libstdcpp "Use libstdc++ instead of libc++" (CUDA_VERSION VERSION_LESS 7.0)) + endif() +endif() diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index 5de435c350d..aa2dcbe1d0d 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -68,7 +68,7 @@ message(STATUS "OpenCV found (${OpenCV_CONFIG_PATH})") # ---[ BLAS if(NOT APPLE) set(BLAS "Atlas" CACHE STRING "Selected BLAS library") - set_property(CACHE BLAS PROPERTY STRINGS "Atlas;Open;MLK") + set_property(CACHE BLAS PROPERTY STRINGS "Atlas;Open;MKL") if(BLAS STREQUAL "Atlas" OR BLAS STREQUAL "atlas") find_package(Atlas REQUIRED) @@ -78,10 +78,11 @@ if(NOT APPLE) find_package(OpenBLAS REQUIRED) include_directories(SYSTEM ${OpenBLAS_INCLUDE_DIR}) list(APPEND Caffe_LINKER_LIBS ${OpenBLAS_LIB}) - elseif(BLAS STREQUAL "MLK" OR BLAS STREQUAL "mkl") + elseif(BLAS STREQUAL "MKL" OR BLAS STREQUAL "mkl") find_package(MKL REQUIRED) include_directories(SYSTEM ${MKL_INCLUDE_DIR}) list(APPEND Caffe_LINKER_LIBS ${MKL_LIBRARIES}) + add_definitions(-DUSE_MKL) endif() elseif(APPLE) find_package(vecLib REQUIRED) diff --git a/cmake/Misc.cmake b/cmake/Misc.cmake index 68e8a662126..14eaeb0ab6e 100644 --- a/cmake/Misc.cmake +++ b/cmake/Misc.cmake @@ -34,8 +34,8 @@ set(CMAKE_MACOSX_RPATH TRUE) # ---[ Funny target if(UNIX OR APPLE) - add_custom_target(simlink_to_build COMMAND "ln" "-sf" "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/build" - COMMENT "Adding simlink: /build -> ${CMAKE_BINARY_DIR}" ) + add_custom_target(symlink_to_build COMMAND "ln" "-sf" "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/build" + COMMENT "Adding symlink: /build -> ${CMAKE_BINARY_DIR}" ) endif() # ---[ Set debug postfix diff --git a/cmake/Modules/FindMKL.cmake b/cmake/Modules/FindMKL.cmake index eb2d9f8868b..d2012db579a 100644 --- a/cmake/Modules/FindMKL.cmake +++ b/cmake/Modules/FindMKL.cmake @@ -1,113 +1,110 @@ -# - Find Intel MKL # Find the MKL libraries # # Options: # -# MKL_STATAIC : use static linking -# MKL_MULTI_THREADED: use multi-threading -# MKL_SDL : Single Dynamic Library interface +# MKL_USE_SINGLE_DYNAMIC_LIBRARY : use single dynamic library interface +# MKL_USE_STATIC_LIBS : use static libraries +# MKL_MULTI_THREADED : use multi-threading # # This module defines the following variables: # -# MKL_FOUND : True if MKL_INCLUDE_DIR are found -# MKL_INCLUDE_DIR : where to find mkl.h, etc. -# MKL_INCLUDE_DIRS : set when MKL_INCLUDE_DIR found -# MKL_LIBRARIES : the library to link against. +# MKL_FOUND : True mkl is found +# MKL_INCLUDE_DIR : unclude directory +# MKL_LIBRARIES : the libraries to link against. -include(FindPackageHandleStandardArgs) +# ---[ Options +caffe_option(MKL_USE_SINGLE_DYNAMIC_LIBRARY "Use single dynamic library interface" ON) +caffe_option(MKL_USE_STATIC_LIBS "Use static libraries" OFF IF NOT MKL_USE_SINGLE_DYNAMIC_LIBRARY) +caffe_option(MKL_MULTI_THREADED "Use multi-threading" ON IF NOT MKL_USE_SINGLE_DYNAMIC_LIBRARY) +# ---[ Root folders set(INTEL_ROOT "/opt/intel" CACHE PATH "Folder contains intel libs") -set(MKL_ROOT ${INTEL_ROOT}/mkl CACHE PATH "Folder contains MKL") - -# Find include dir -find_path(MKL_INCLUDE_DIR mkl.h - PATHS ${MKL_ROOT}/include) - -# Find include directory -# There is no include folder under linux -if(WIN32) - find_path(INTEL_INCLUDE_DIR omp.h - PATHS ${INTEL_ROOT}/include) - set(MKL_INCLUDE_DIR ${MKL_INCLUDE_DIR} ${INTEL_INCLUDE_DIR}) -endif() +find_path(MKL_ROOT include/mkl.h PATHS $ENV{MKL_ROOT} ${INTEL_ROOT}/mkl + DOC "Folder contains MKL") -# Find libraries +# ---[ Find include dir +find_path(MKL_INCLUDE_DIR mkl.h PATHS ${MKL_ROOT} PATH_SUFFIXES include) +set(__looked_for MKL_INCLUDE_DIR) -# Handle suffix -set(_MKL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) +# ---[ Find libraries +if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(__path_suffixes lib lib/ia32) +else() + set(__path_suffixes lib lib/intel64) +endif() -if(WIN32) - if(MKL_STATAIC) - set(CMAKE_FIND_LIBRARY_SUFFIXES .lib) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES _dll.lib) - endif() +set(__mkl_libs "") +if(MKL_USE_SINGLE_DYNAMIC_LIBRARY) + list(APPEND __mkl_libs rt) else() - if(MKL_STATAIC) - set(CMAKE_FIND_LIBRARY_SUFFIXES .a) + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + if(WIN32) + list(APPEND __mkl_libs intel_c) else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .so) + list(APPEND __mkl_libs intel gf) endif() + else() + list(APPEND __mkl_libs intel_lp64 gf_lp64) + endif() + + if(MKL_MULTI_THREADED) + list(APPEND __mkl_libs intel_thread) + else() + list(APPEND __mkl_libs sequential) + endif() + + list(APPEND __mkl_libs core cdft_core) endif() -# MKL is composed by four layers: Interface, Threading, Computational and RTL +foreach (__lib ${__mkl_libs}) + set(__mkl_lib "mkl_${__lib}") + string(TOUPPER ${__mkl_lib} __mkl_lib_upper) -if(MKL_SDL) - find_library(MKL_LIBRARY mkl_rt - PATHS ${MKL_ROOT}/lib/ia32/) + if(MKL_USE_STATIC_LIBS) + set(__mkl_lib "lib${__mkl_lib}.a") + endif() - set(MKL_MINIMAL_LIBRARY ${MKL_LIBRARY}) -else() - ######################### Interface layer ####################### - if(WIN32) - set(MKL_INTERFACE_LIBNAME mkl_intel_c) - else() - set(MKL_INTERFACE_LIBNAME mkl_intel) - endif() + find_library(${__mkl_lib_upper}_LIBRARY + NAMES ${__mkl_lib} + PATHS ${MKL_ROOT} "${MKL_INCLUDE_DIR}/.." + PATH_SUFFIXES ${__path_suffixes} + DOC "The path to Intel(R) MKL ${__mkl_lib} library") + mark_as_advanced(${__mkl_lib_upper}_LIBRARY) - find_library(MKL_INTERFACE_LIBRARY ${MKL_INTERFACE_LIBNAME} - PATHS ${MKL_ROOT}/lib/ia32/) + list(APPEND __looked_for ${__mkl_lib_upper}_LIBRARY) + list(APPEND MKL_LIBRARIES ${${__mkl_lib_upper}_LIBRARY}) +endforeach() - ######################## Threading layer ######################## - if(MKL_MULTI_THREADED) - set(MKL_THREADING_LIBNAME mkl_intel_thread) - else() - set(MKL_THREADING_LIBNAME mkl_sequential) - endif() - find_library(MKL_THREADING_LIBRARY ${MKL_THREADING_LIBNAME} - PATHS ${MKL_ROOT}/lib/ia32/) +if(NOT MKL_USE_SINGLE_DYNAMIC_LIBRARY) + if (MKL_USE_STATIC_LIBS) + set(__iomp5_libs iomp5 libiomp5mt.lib) + else() + set(__iomp5_libs iomp5 libiomp5md.lib) + endif() - ####################### Computational layer ##################### - find_library(MKL_CORE_LIBRARY mkl_core - PATHS ${MKL_ROOT}/lib/ia32/) - find_library(MKL_FFT_LIBRARY mkl_cdft_core - PATHS ${MKL_ROOT}/lib/ia32/) - find_library(MKL_SCALAPACK_LIBRARY mkl_scalapack_core - PATHS ${MKL_ROOT}/lib/ia32/) + if(WIN32) + find_path(INTEL_INCLUDE_DIR omp.h PATHS ${INTEL_ROOT} PATH_SUFFIXES include) + list(APPEND __looked_for INTEL_INCLUDE_DIR) + endif() - ############################ RTL layer ########################## - if(WIN32) - set(MKL_RTL_LIBNAME libiomp5md) - else() - set(MKL_RTL_LIBNAME libiomp5) - endif() - find_library(MKL_RTL_LIBRARY ${MKL_RTL_LIBNAME} - PATHS ${INTEL_RTL_ROOT}/lib) + find_library(MKL_RTL_LIBRARY ${__iomp5_libs} + PATHS ${INTEL_RTL_ROOT} ${INTEL_ROOT}/compiler ${MKL_ROOT}/.. ${MKL_ROOT}/../compiler + PATH_SUFFIXES ${__path_suffixes} + DOC "Path to Path to OpenMP runtime library") - set(MKL_LIBRARY ${MKL_INTERFACE_LIBRARY} ${MKL_THREADING_LIBRARY} ${MKL_CORE_LIBRARY} ${MKL_FFT_LIBRARY} ${MKL_SCALAPACK_LIBRARY} ${MKL_RTL_LIBRARY}) - set(MKL_MINIMAL_LIBRARY ${MKL_INTERFACE_LIBRARY} ${MKL_THREADING_LIBRARY} ${MKL_CORE_LIBRARY} ${MKL_RTL_LIBRARY}) + list(APPEND __looked_for MKL_RTL_LIBRARY) + list(APPEND MKL_LIBRARIES ${MKL_RTL_LIBRARY}) endif() -set(CMAKE_FIND_LIBRARY_SUFFIXES ${_MKL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) -find_package_handle_standard_args(MKL DEFAULT_MSG - MKL_INCLUDE_DIR MKL_LIBRARY MKL_MINIMAL_LIBRARY) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MKL DEFAULT_MSG ${__looked_for}) if(MKL_FOUND) - set(MKL_INCLUDE_DIRS ${MKL_INCLUDE_DIR}) - set(MKL_LIBRARIES ${MKL_LIBRARY}) - set(MKL_MINIMAL_LIBRARIES ${MKL_LIBRARY}) + message(STATUS "Found MKL (include: ${MKL_INCLUDE_DIR}, lib: ${MKL_LIBRARIES}") endif() + +caffe_clear_vars(__looked_for __mkl_libs __path_suffixes __lib_suffix __iomp5_libs) diff --git a/cmake/Targets.cmake b/cmake/Targets.cmake index 84a2aaf58e9..3b254ad37df 100644 --- a/cmake/Targets.cmake +++ b/cmake/Targets.cmake @@ -140,8 +140,7 @@ function(caffe_configure_testdatafile file) set(result "") foreach(line ${__lines}) set(result "${result}${CMAKE_SOURCE_DIR}/${line}\n") - endforeach() - dmsg(${result}) + endforeach() file(WRITE ${file}.gen.cmake ${result}) endfunction() diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake index 048123dbe10..a56c7c300c0 100644 --- a/cmake/Utils.cmake +++ b/cmake/Utils.cmake @@ -363,3 +363,19 @@ function(caffe_parse_linker_libs Caffe_LINKER_LIBS_variable folders_var flags_va set(${flags_var} ${libflags} PARENT_SCOPE) set(${frameworks_var} ${__framework} PARENT_SCOPE) endfunction() + +################################################################################################ +# Helper function to detect Darwin version, i.e. 10.8, 10.9, 10.10, .... +# Usage: +# caffe_detect_darwin_version() +function(caffe_detect_darwin_version output_var) + if(APPLE) + execute_process(COMMAND /usr/bin/sw_vers -productVersion + RESULT_VARIABLE __sw_vers OUTPUT_VARIABLE __sw_vers_out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + + set(${output_var} ${__sw_vers_out} PARENT_SCOPE) + else() + set(${output_var} "" PARENT_SCOPE) + endif() +endfunction() diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 927bf5bc731..b1be683f907 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -28,7 +28,7 @@ function(gather_readmes_as_prebuild_cmd target gathered_dir root) add_custom_command(TARGET ${target} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${new_folder} COMMAND ln -sf ${root}/${file} ${new_filename} - COMMENT "Creating simlink ${new_filename} -> ${root}/${file}" + COMMENT "Creating symlink ${new_filename} -> ${root}/${file}" WORKING_DIRECTORY ${root} VERBATIM) endif() endforeach() @@ -94,11 +94,11 @@ if(NOT IS_ABSOLUTE ${output_dir}) get_filename_component(output_dir ${output_dir} ABSOLUTE) endif() -# creates simlink in docs subfolder to code documentation built by doxygen +# creates symlink in docs subfolder to code documentation built by doxygen add_custom_command(TARGET docs POST_BUILD VERBATIM COMMAND ln -sfn "${output_dir}/html" doxygen WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs - COMMENT "Creating simlink ${CMAKE_SOURCE_DIR}/docs/doxygen -> ${output_dir}/html") + COMMENT "Creating symlink ${CMAKE_SOURCE_DIR}/docs/doxygen -> ${output_dir}/html") # for quick launch of jekyll add_custom_target(jekyll COMMAND jekyll serve -w -s . -d _site --port=4000 diff --git a/matlab/CMakeLists.txt b/matlab/CMakeLists.txt index 40d8729ae76..51ab4fe274a 100644 --- a/matlab/CMakeLists.txt +++ b/matlab/CMakeLists.txt @@ -35,7 +35,7 @@ file(GLOB Matlab_srcs caffe/matcaffe.cpp) set(Matlab_caffe_mex ${CMAKE_SOURCE_DIR}/matlab/caffe/caffe.mex) caffe_get_current_cflags(cflags) -caffe_parse_linker_libs(Caffe_LINKER_LIBS folders libflags macos_framewoks) +caffe_parse_linker_libs(Caffe_LINKER_LIBS folders libflags macos_frameworks) set(folders $ ${folders}) # prepare linker flag lists diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index e943f691c49..ee33a9e5285 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -12,10 +12,13 @@ set_target_properties(pycaffe PROPERTIES PREFIX "" OUTPUT_NAME "_caffe") caffe_default_properties(pycaffe) if(UNIX OR APPLE) - set(__linkname "${CMAKE_SOURCE_DIR}/python/_caffe.so") + set(__linkname "${CMAKE_SOURCE_DIR}/python/caffe/_caffe.so") add_custom_command(TARGET pycaffe POST_BUILD - COMMAND ln -sf $ "${CMAKE_SOURCE_DIR}/python/_caffe.so" - COMMENT "Creating simlink ${__linkname} -> ${CMAKE_BINARY_DIR}/lib/_caffe${CAffe_POSTFIX}.so") + COMMAND ln -sf $ "${__linkname}" + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/python/caffe/proto + COMMAND touch ${CMAKE_SOURCE_DIR}/python/caffe/proto/__init__.py + COMMAND cp ${proto_gen_folder}/*.py ${CMAKE_SOURCE_DIR}/python/caffe/proto/ + COMMENT "Creating symlink ${__linkname} -> ${CMAKE_BINARY_DIR}/lib/_caffe${CAffe_POSTFIX}.so") endif() # ---[ Install From 4ba3dfbcbd2eea13a4719c197309b67fead12480 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Mon, 16 Feb 2015 21:00:04 -0800 Subject: [PATCH 313/798] [docs] note new CMake build --- docs/installation.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index c2b16a23244..73f6806c805 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -270,10 +270,10 @@ Be sure to set your MATLAB and Python paths in `Makefile.config` first! Now that you have installed Caffe, check out the [MNIST tutorial](gathered/examples/mnist.html) and the [reference ImageNet model tutorial](gathered/examples/imagenet.html). -### Compilation using CMake (beta) +### CMake Compilation -In lieu of manually editing `Makefile.config` to tell Caffe where dependencies are located, Caffe also provides a CMake-based build system (currently in "beta"). -It requires CMake version >= 2.8.8. +In lieu of manually editing `Makefile.config` to configure the build, Caffe offers an unofficial CMake build thanks to @Nerei, @akosiorek, and other members of the community. +It requires CMake version >= 2.8.7. The basic installation steps are as follows: mkdir build @@ -282,6 +282,8 @@ The basic installation steps are as follows: make all make runtest +See [PR #1667](https://github.com/BVLC/caffe/pull/1667) for details. + #### Ubuntu 12.04 Note that in Ubuntu 12.04, Aptitude will install version CMake 2.8.7 by default, which is not supported by Caffe's CMake build (requires at least 2.8.8). From 79bc8645f9790398e5ddcb706495c6aca395989a Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Mon, 16 Feb 2015 21:41:24 -0800 Subject: [PATCH 314/798] [docs] README dispatch --- README.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9a9b3ee36eb..0a60095bdf1 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,32 @@ # Caffe -Caffe is a deep learning framework developed with cleanliness, readability, and speed in mind.
-Consult the [project website](http://caffe.berkeleyvision.org) for all documentation. +Caffe is a deep learning framework made with expression, speed, and modularity in mind. +It is developed by the Berkeley Vision and Learning Center ([BVLC](http://bvlc.eecs.berkeley.edu)) and community contributors. +Check out the [project site](http://caffe.berkeleyvision.org) for all the details like -Please ask usage questions and how to model different tasks on the [caffe-users mailing list](https://groups.google.com/forum/#!forum/caffe-users). +- [DIY Deep Learning for Vision with Caffe](https://docs.google.com/presentation/d/1UeKXVgRvvxg9OUdh_UiC5G71UMscNPlvArsWER41PsU/edit#slide=id.p) +- [Tutorial Documentation](http://caffe.berkeleyvision.org/tutorial/) +- [BVLC reference models](http://caffe.berkeleyvision.org/model_zoo.html) and the [community model zoo](https://github.com/BVLC/caffe/wiki/Model-Zoo) +- [Installation instructions](http://caffe.berkeleyvision.org/installation.html) +and step-by-step examples. + +Please join the [caffe-users group](https://groups.google.com/forum/#!forum/caffe-users) to ask questions and talk about methods and models. +Framework development discussions and thorough bug reports are collected on [Issues](https://github.com/BVLC/caffe/issues). + +Happy brewing! + +## License and Citation + +Caffe is released under the [BSD 2-Clause license](https://github.com/BVLC/caffe/blob/master/LICENSE). +The BVLC reference models are released for unrestricted use. + +Please cite Caffe in your publications if it helps your research: + + @article{jia2014caffe, + Author = {Jia, Yangqing and Shelhamer, Evan and Donahue, Jeff and Karayev, Sergey and Long, Jonathan and Girshick, Ross and Guadarrama, Sergio and Darrell, Trevor}, + Journal = {arXiv preprint arXiv:1408.5093}, + Title = {Caffe: Convolutional Architecture for Fast Feature Embedding}, + Year = {2014} + } From 87b63358773902dd5217ec661386f8ef8abcf8b8 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Sat, 7 Feb 2015 00:19:54 -0800 Subject: [PATCH 315/798] dynamic linking --- Makefile | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 81c67efeaf4..0fcbb8c64cc 100644 --- a/Makefile +++ b/Makefile @@ -245,6 +245,11 @@ ifeq ($(OSX), 1) COMMON_FLAGS += -DGTEST_USE_OWN_TR1_TUPLE=1 # boost::thread is called boost_thread-mt to mark multithreading on OS X LIBRARIES += boost_thread-mt + # we need to explicitly ask for the rpath to be obeyed + DYNAMIC_FLAGS := -install_name @rpath/libcaffe.so + ORIGIN := @loader_path +else + ORIGIN := \$$ORIGIN endif # Custom compiler @@ -343,7 +348,6 @@ endif LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) $(PKG_CONFIG) \ $(foreach library,$(LIBRARIES),-l$(library)) PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) -DYNAMIC_LDFLAGS := -l$(PROJECT) -Wl,-rpath,\$$ORIGIN/../lib # 'superclean' target recursively* deletes all files ending with an extension # in $(SUPERCLEAN_EXTS) below. This may be useful if you've built older @@ -419,10 +423,11 @@ py$(PROJECT): py py: $(PY$(PROJECT)_SO) $(PROTO_GEN_PY) -$(PY$(PROJECT)_SO): $(PY$(PROJECT)_SRC) $(STATIC_NAME) $(PY$(PROJECT)_HXX_SRC) - @ echo CXX $< +$(PY$(PROJECT)_SO): $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX_SRC) | $(DYNAMIC_NAME) + @ echo CXX/LD -o $@ $< $(Q)$(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \ - $(STATIC_LINK_COMMAND) $(LINKFLAGS) $(PYTHON_LDFLAGS) + -o $@ $(LINKFLAGS) $(PYTHON_LDFLAGS) -l$(PROJECT) \ + -Wl,-rpath,$(ORIGIN)/../../build/lib mat$(PROJECT): mat @@ -479,7 +484,7 @@ $(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK) $(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) @ echo LD -o $@ - $(Q)$(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) + $(Q)$(CXX) -shared -o $@ $(OBJS) $(LINKFLAGS) $(LDFLAGS) $(DYNAMIC_FLAGS) $(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR) @ echo AR -o $@ @@ -512,32 +517,33 @@ $(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \ $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ -o $@ $(LINKFLAGS) $(LDFLAGS) -$(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(DYNAMIC_NAME) \ - | $(TEST_BIN_DIR) +$(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ + | $(DYNAMIC_NAME) $(TEST_BIN_DIR) @ echo CXX/LD -o $@ $< $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ - -o $@ $(LINKFLAGS) $(LDFLAGS) $(DYNAMIC_LDFLAGS) + -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(ORIGIN)/../lib $(TEST_CU_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CU_BUILD_DIR)/%.o \ - $(GTEST_OBJ) $(STATIC_NAME) | $(TEST_BIN_DIR) + $(GTEST_OBJ) | $(DYNAMIC_NAME) $(TEST_BIN_DIR) @ echo LD $< - $(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ - -o $@ $(LINKFLAGS) $(LDFLAGS) + $(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) \ + -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(ORIGIN)/../lib $(TEST_CXX_BINS): $(TEST_BIN_DIR)/%.testbin: $(TEST_CXX_BUILD_DIR)/%.o \ - $(GTEST_OBJ) $(STATIC_NAME) | $(TEST_BIN_DIR) + $(GTEST_OBJ) | $(DYNAMIC_NAME) $(TEST_BIN_DIR) @ echo LD $< - $(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ - -o $@ $(LINKFLAGS) $(LDFLAGS) + $(Q)$(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) \ + -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) -Wl,-rpath,$(ORIGIN)/../lib # Target for extension-less symlinks to tool binaries with extension '*.bin'. $(TOOL_BUILD_DIR)/%: $(TOOL_BUILD_DIR)/%.bin | $(TOOL_BUILD_DIR) @ $(RM) $@ @ ln -s $(abspath $<) $@ -$(TOOL_BINS) $(EXAMPLE_BINS): %.bin : %.o $(STATIC_NAME) - @ echo LD $< - $(Q)$(CXX) $< $(STATIC_LINK_COMMAND) -o $@ $(LINKFLAGS) $(LDFLAGS) +$(TOOL_BINS) $(EXAMPLE_BINS): %.bin : %.o | $(DYNAMIC_NAME) + @ echo CXX/LD -o $@ + $(Q)$(CXX) $< -o $@ $(LINKFLAGS) $(LDFLAGS) -l$(PROJECT) \ + -Wl,-rpath,$(ORIGIN)/../lib proto: $(PROTO_GEN_CC) $(PROTO_GEN_HEADER) From e4b7ceb05ddddbddb8809e22d86ac20a019959fd Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Sat, 7 Feb 2015 00:33:15 -0800 Subject: [PATCH 316/798] only dynamically link the tests No need to independently test static and dynamic linking. --- Makefile | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 0fcbb8c64cc..f94867bdf31 100644 --- a/Makefile +++ b/Makefile @@ -123,10 +123,8 @@ TEST_CU_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \ TEST_CXX_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \ $(foreach obj,$(TEST_CXX_OBJS),$(basename $(notdir $(obj)))))) TEST_BINS := $(TEST_CXX_BINS) $(TEST_CU_BINS) -# TEST_ALL_BIN is the test binary that links caffe statically. +# TEST_ALL_BIN is the test binary that links caffe dynamically. TEST_ALL_BIN := $(TEST_BIN_DIR)/test_all.testbin -# TEST_ALL_DYNINK_BIN is the test binary that links caffe as a dynamic library. -TEST_ALL_DYNLINK_BIN := $(TEST_BIN_DIR)/test_all_dynamic_link.testbin ############################## # Derive compiler warning dump locations @@ -445,9 +443,8 @@ $(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME) CXXFLAGS="\$$CXXFLAGS $(MATLAB_CXXFLAGS)" \ CXXLIBS="\$$CXXLIBS $(STATIC_LINK_COMMAND) $(LDFLAGS)" -output $@ -runtest: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN) - $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) && \ - $(TEST_ALL_DYNLINK_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) +runtest: $(TEST_ALL_BIN) + $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) pytest: py cd python; python -m unittest discover -s caffe/test @@ -511,13 +508,7 @@ $(BUILD_DIR)/cuda/%.o: %.cu | $(ALL_BUILD_DIRS) || (cat $@.$(WARNS_EXT); exit 1) @ cat $@.$(WARNS_EXT) -$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \ - | $(TEST_BIN_DIR) - @ echo CXX/LD -o $@ $< - $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_LINK_COMMAND) \ - -o $@ $(LINKFLAGS) $(LDFLAGS) - -$(TEST_ALL_DYNLINK_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ +$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ | $(DYNAMIC_NAME) $(TEST_BIN_DIR) @ echo CXX/LD -o $@ $< $(Q)$(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) \ From 3c629b1942ccd5c6ff2f37370767f662cab388c0 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Sat, 20 Sep 2014 00:16:17 -0700 Subject: [PATCH 317/798] [docs] include caffeine favicon for site --- docs/_layouts/default.html | 2 ++ docs/images/caffeine-icon.png | Bin 0 -> 954 bytes 2 files changed, 2 insertions(+) create mode 100644 docs/images/caffeine-icon.png diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index 73c6d5873d3..433b0635f43 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -11,6 +11,8 @@ Caffe {% if page contains 'title' %}| {{ page.title }}{% endif %} + + diff --git a/docs/images/caffeine-icon.png b/docs/images/caffeine-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..88b4a002bb000ad56a83d7bfb99a8b450f63fb98 GIT binary patch literal 954 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+7|R2ELR|Ol+xO|yr(?&Coj!ef{`~oK=FFKob!vNi`}XbI zA3S*Q{rmT)PoF+}_U!H3x0#ulH*eldNlCeN>(<$`XAc}W@aWN_J$v@ty?b}kq)F$` zpRcd4U$SJ$^XJdQ!ouFae_vNuw`R?njT<+9`0(M+pFcZy?)>}r@3w8*A|oRY9y~aA z?%W?ger(vV;mnyct5>gn_3G8_+qW-VxDXc?H*40c?(Xi6j*h&%yriV0#fukvdU{^F zc1=Y^#m>&|1kC%}qXS%t$>FMeH{{8#hxpP;qUj6#@>+9FAdwYAAEnD{D z#fzYzAb)@V&!0c%=jU5kSmfsBwzjrz-MTd^E9=UYD-$M6$jQmMc=4i+j!sNWOhZFM zUteEyb8}^7<)K4|K7RZ-efso>h=}#;*T=`l@7=ri@ZrPG&d#%E&)&UzcUM zc=)_|^Zx(;|0*?E9vDxxB|(0{K<Sf&HC#Zw=jUWj`fY$578H!pB)s@=xR$0 ze6YOdgXAY^7?ALw-WEwMXoHZ+p zF;5}f*Ad?y__$g}rGO`&^bURhXf2CC!Hg^ih>*_T~`m4 z@@(YVJ*&aFOQ_>y{;PP!V6_tq&$V#0rzGa{Gj5a$Wd7=LZ;jW4pFBm=j%60G9^&*1 zd=OAFwP%_Uvvjbs(DX#c@C9oERJnfiGkCiCxvX Date: Mon, 16 Feb 2015 21:47:20 -0800 Subject: [PATCH 318/798] [docs] Caffe is by the BVLC, created by Yangqing, and brewed by Evan --- docs/_layouts/default.html | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index 433b0635f43..b8efe60bc3b 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -36,8 +36,16 @@

Caffe

- Deep learning framework developed by Yangqing Jia / BVLC + Deep learning framework by the BVLC

+

+ Created by +
+ Yangqing Jia +
+ Lead Developer +
+ Evan Shelhamer