From 4d33630096c769dd43716dd5607f151e3d5abef7 Mon Sep 17 00:00:00 2001 From: Michele Di Giorgio Date: Fri, 2 Mar 2018 09:43:54 +0000 Subject: COMPMID-987: Make beta and gamma optional in BatchNormalization Currently we have beta and gamma compulsory in Batch normalization. There are network that might not need one or both of those. Thus these should be optional with beta(offset) defaulting to zero and gamma(scale) to 1. Will also reduce some memory requirements. Change-Id: I15bf1ec14b814be2acebf1be1a4fba9c4fbd3190 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/123237 Tested-by: Jenkins Reviewed-by: Anthony Barbier --- tests/AssetsLibrary.h | 16 +++++++ tests/benchmark/CL/BatchNormalizationLayer.cpp | 24 +++++++--- .../GLES_COMPUTE/BatchNormalizationLayer.cpp | 28 +++++++---- tests/benchmark/NEON/BatchNormalizationLayer.cpp | 24 +++++++--- .../fixtures/BatchNormalizationLayerFixture.h | 6 ++- tests/validation/CL/BatchNormalizationLayer.cpp | 41 ++++++++++------ .../GLES_COMPUTE/BatchNormalizationLayer.cpp | 19 ++++++-- tests/validation/NEON/BatchNormalizationLayer.cpp | 40 ++++++++++------ .../fixtures/BatchNormalizationLayerFixture.h | 54 ++++++++++++++++++---- .../reference/BatchNormalizationLayer.cpp | 1 - 10 files changed, 191 insertions(+), 62 deletions(-) (limited to 'tests') diff --git a/tests/AssetsLibrary.h b/tests/AssetsLibrary.h index ae88824298..4bbe4c56f6 100644 --- a/tests/AssetsLibrary.h +++ b/tests/AssetsLibrary.h @@ -352,6 +352,16 @@ public: template void fill_layer_data(T &&tensor, std::string name) const; + /** Fill a tensor with a constant value + * + * @param[in, out] tensor To be filled tensor. + * @param[in] value Value to be assigned to all elements of the input tensor. + * + * @note @p value must be of the same type as the data type of @p tensor + */ + template + void fill_tensor_value(T &&tensor, D value) const; + private: // Function prototype to convert between image formats. using Converter = void (*)(const RawTensor &src, RawTensor &dst); @@ -774,6 +784,12 @@ void AssetsLibrary::fill_layer_data(T &&tensor, std::string name) const }); } } + +template +void AssetsLibrary::fill_tensor_value(T &&tensor, D value) const +{ + fill_tensor_uniform(tensor, 0, value, value); +} } // namespace test } // namespace arm_compute #endif /* __ARM_COMPUTE_TEST_TENSOR_LIBRARY_H__ */ diff --git a/tests/benchmark/CL/BatchNormalizationLayer.cpp b/tests/benchmark/CL/BatchNormalizationLayer.cpp index 82c780008b..3312319aac 100644 --- a/tests/benchmark/CL/BatchNormalizationLayer.cpp +++ b/tests/benchmark/CL/BatchNormalizationLayer.cpp @@ -51,19 +51,25 @@ using CLBatchNormalizationLayerFixture = BatchNormalizationLayerFixture - void setup(TensorShape tensor_shape, TensorShape param_shape, float epsilon, ActivationLayerInfo act_info, DataType data_type, int batches) + void setup(TensorShape tensor_shape, TensorShape param_shape, float epsilon, bool use_gamma, bool use_beta, ActivationLayerInfo act_info, DataType data_type, int batches) { // Set batched in source and destination shapes const unsigned int fixed_point_position = 4; @@ -57,7 +57,9 @@ public: gamma = create_tensor(param_shape, data_type, 1, fixed_point_position); // Create and configure function - batch_norm_layer.configure(&src, &dst, &mean, &variance, &beta, &gamma, epsilon, act_info); + TensorType *beta_ptr = use_beta ? &beta : nullptr; + TensorType *gamma_ptr = use_gamma ? &gamma : nullptr; + batch_norm_layer.configure(&src, &dst, &mean, &variance, beta_ptr, gamma_ptr, epsilon, act_info); // Allocate tensors src.allocator()->allocate(); diff --git a/tests/validation/CL/BatchNormalizationLayer.cpp b/tests/validation/CL/BatchNormalizationLayer.cpp index ef535153f2..8c143060cb 100644 --- a/tests/validation/CL/BatchNormalizationLayer.cpp +++ b/tests/validation/CL/BatchNormalizationLayer.cpp @@ -61,8 +61,11 @@ TEST_SUITE(BatchNormalizationLayer) template using CLBatchNormalizationLayerFixture = BatchNormalizationLayerValidationFixture; -DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::RandomBatchNormalizationLayerDataset(), framework::dataset::make("DataType", { DataType::QS8, DataType::QS16, DataType::F16, DataType::F32 })), - shape0, shape1, epsilon, dt) +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), + framework::dataset::make("UseGamma", { false, true }))), + framework::dataset::make("DataType", { DataType::QS8, DataType::QS16, DataType::F16, DataType::F32 })), + shape0, shape1, epsilon, use_gamma, use_beta, dt) { // Set fixed point position data type allowed const int fixed_point_position = (arm_compute::is_data_type_fixed_point(dt)) ? 3 : 0; @@ -77,7 +80,9 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::Ran // Create and Configure function CLBatchNormalizationLayer norm; - norm.configure(&src, &dst, &mean, &var, &beta, &gamma, epsilon); + CLTensor *beta_ptr = use_beta ? &beta : nullptr; + CLTensor *gamma_ptr = use_gamma ? &gamma : nullptr; + norm.configure(&src, &dst, &mean, &var, beta_ptr, gamma_ptr, epsilon); // Validate valid region const ValidRegion valid_region = shape_to_valid_region(shape0); @@ -150,7 +155,9 @@ DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip( TEST_SUITE(Float) TEST_SUITE(FP32) -FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), +FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), + framework::dataset::make("UseGamma", { false, true }))), act_infos), framework::dataset::make("DataType", DataType::F32))) { @@ -160,7 +167,9 @@ FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixture, framewor TEST_SUITE_END() TEST_SUITE(FP16) -FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), +FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), + framework::dataset::make("UseGamma", { false, true }))), framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f))), framework::dataset::make("DataType", DataType::F16))) { @@ -175,10 +184,13 @@ template using CLBatchNormalizationLayerFixedPointFixture = BatchNormalizationLayerValidationFixedPointFixture; TEST_SUITE(QS8) -FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixedPointFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), - framework::dataset::make("ActivationInfo", ActivationLayerInfo())), - framework::dataset::make("DataType", DataType::QS8)), - framework::dataset::make("FractionalBits", 1, 6))) +FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixedPointFixture, framework::DatasetMode::PRECOMMIT, + combine(combine(combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + framework::dataset::make("UseBeta", false)), + framework::dataset::make("UseGamma", false)), + framework::dataset::make("ActivationInfo", ActivationLayerInfo())), + framework::dataset::make("DataType", DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) { // Validate output validate(CLAccessor(_target), _reference, tolerance_qs8, 0); @@ -186,10 +198,13 @@ FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixedPointFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), - framework::dataset::make("ActivationInfo", ActivationLayerInfo())), - framework::dataset::make("DataType", DataType::QS16)), - framework::dataset::make("FractionalBits", 1, 14))) +FIXTURE_DATA_TEST_CASE(Random, CLBatchNormalizationLayerFixedPointFixture, framework::DatasetMode::PRECOMMIT, + combine(combine(combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + framework::dataset::make("UseBeta", false)), + framework::dataset::make("UseGamma", false)), + framework::dataset::make("ActivationInfo", ActivationLayerInfo())), + framework::dataset::make("DataType", DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) { // Validate output validate(CLAccessor(_target), _reference, tolerance_qs16, 0); diff --git a/tests/validation/GLES_COMPUTE/BatchNormalizationLayer.cpp b/tests/validation/GLES_COMPUTE/BatchNormalizationLayer.cpp index d817fc0e67..2dbb0e0fbb 100644 --- a/tests/validation/GLES_COMPUTE/BatchNormalizationLayer.cpp +++ b/tests/validation/GLES_COMPUTE/BatchNormalizationLayer.cpp @@ -59,8 +59,11 @@ TEST_SUITE(BatchNormalizationLayer) template using GCBatchNormalizationLayerFixture = BatchNormalizationLayerValidationFixture; -DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::RandomBatchNormalizationLayerDataset(), framework::dataset::make("DataType", { DataType::F32 })), - shape0, shape1, epsilon, dt) +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), + framework::dataset::make("UseGamma", { false, true }))), + framework::dataset::make("DataType", { DataType::F32 })), + shape0, shape1, epsilon, use_beta, use_gamma, dt) { // Set fixed point position data type allowed int fixed_point_position = (arm_compute::is_data_type_fixed_point(dt)) ? 3 : 0; @@ -75,7 +78,9 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::Ran // Create and Configure function GCBatchNormalizationLayer norm; - norm.configure(&src, &dst, &mean, &var, &beta, &gamma, epsilon); + GCTensor *beta_ptr = use_beta ? &beta : nullptr; + GCTensor *gamma_ptr = use_gamma ? &gamma : nullptr; + norm.configure(&src, &dst, &mean, &var, beta_ptr, gamma_ptr, epsilon); // Validate valid region const ValidRegion valid_region = shape_to_valid_region(shape0); @@ -84,7 +89,9 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::Ran TEST_SUITE(Float) TEST_SUITE(FP16) -FIXTURE_DATA_TEST_CASE(Random, GCBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), +FIXTURE_DATA_TEST_CASE(Random, GCBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), + framework::dataset::make("UseGamma", { false, true }))), act_infos), framework::dataset::make("DataType", DataType::F16))) { @@ -94,7 +101,9 @@ FIXTURE_DATA_TEST_CASE(Random, GCBatchNormalizationLayerFixture, framework TEST_SUITE_END() TEST_SUITE(FP32) -FIXTURE_DATA_TEST_CASE(Random, GCBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), +FIXTURE_DATA_TEST_CASE(Random, GCBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), + framework::dataset::make("UseGamma", { false, true }))), act_infos), framework::dataset::make("DataType", DataType::F32))) { diff --git a/tests/validation/NEON/BatchNormalizationLayer.cpp b/tests/validation/NEON/BatchNormalizationLayer.cpp index 054ed278a2..7bf1f2633e 100644 --- a/tests/validation/NEON/BatchNormalizationLayer.cpp +++ b/tests/validation/NEON/BatchNormalizationLayer.cpp @@ -63,8 +63,10 @@ TEST_SUITE(BatchNormalizationLayer) template using NEBatchNormalizationLayerFixture = BatchNormalizationLayerValidationFixture; -DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::RandomBatchNormalizationLayerDataset(), framework::dataset::make("DataType", { DataType::QS8, DataType::QS16, DataType::F32 })), - shape0, shape1, epsilon, dt) +DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), framework::dataset::make("UseGamma", { false, true }))), + framework::dataset::make("DataType", { DataType::QS8, DataType::QS16, DataType::F32 })), + shape0, shape1, epsilon, use_beta, use_gamma, dt) { // Set fixed point position data type allowed const int fixed_point_position = (arm_compute::is_data_type_fixed_point(dt)) ? 3 : 0; @@ -79,7 +81,9 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(datasets::Ran // Create and Configure function NEBatchNormalizationLayer norm; - norm.configure(&src, &dst, &mean, &var, &beta, &gamma, epsilon); + Tensor *beta_ptr = use_beta ? &beta : nullptr; + Tensor *gamma_ptr = use_gamma ? &gamma : nullptr; + norm.configure(&src, &dst, &mean, &var, beta_ptr, gamma_ptr, epsilon); // Validate valid region const ValidRegion valid_region = shape_to_valid_region(shape0); @@ -150,7 +154,9 @@ DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip( // *INDENT-ON* TEST_SUITE(Float) -FIXTURE_DATA_TEST_CASE(Random, NEBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), +FIXTURE_DATA_TEST_CASE(Random, NEBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), + framework::dataset::make("UseGamma", { false, true }))), act_infos), framework::dataset::make("DataType", DataType::F32))) { @@ -161,7 +167,9 @@ TEST_SUITE_END() #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC TEST_SUITE(Float16) -FIXTURE_DATA_TEST_CASE(Random, NEBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::RandomBatchNormalizationLayerDataset(), +FIXTURE_DATA_TEST_CASE(Random, NEBatchNormalizationLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + combine(framework::dataset::make("UseBeta", { false, true }), + framework::dataset::make("UseGamma", { false, true }))), framework::dataset::make("ActivationInfo", ActivationLayerInfo())), framework::dataset::make("DataType", DataType::F16))) { @@ -176,10 +184,13 @@ template using NEBatchNormalizationLayerFixedPointFixture = BatchNormalizationLayerValidationFixedPointFixture; TEST_SUITE(QS8) -FIXTURE_DATA_TEST_CASE(Random, NEBatchNormalizationLayerFixedPointFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), - framework::dataset::make("ActivationInfo", ActivationLayerInfo())), - framework::dataset::make("DataType", DataType::QS8)), - framework::dataset::make("FractionalBits", 1, 6))) +FIXTURE_DATA_TEST_CASE(Random, NEBatchNormalizationLayerFixedPointFixture, framework::DatasetMode::PRECOMMIT, + combine(combine(combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + framework::dataset::make("UseBeta", false)), + framework::dataset::make("UseGamma", false)), + framework::dataset::make("ActivationInfo", ActivationLayerInfo())), + framework::dataset::make("DataType", DataType::QS8)), + framework::dataset::make("FractionalBits", 1, 6))) { // Validate output validate(Accessor(_target), _reference, tolerance_qs8, 0); @@ -187,10 +198,13 @@ FIXTURE_DATA_TEST_CASE(Random, NEBatchNormalizationLayerFixedPointFixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), - framework::dataset::make("ActivationInfo", ActivationLayerInfo())), - framework::dataset::make("DataType", DataType::QS16)), - framework::dataset::make("FractionalBits", 1, 14))) +FIXTURE_DATA_TEST_CASE(Random, NEBatchNormalizationLayerFixedPointFixture, framework::DatasetMode::PRECOMMIT, + combine(combine(combine(combine(combine(datasets::RandomBatchNormalizationLayerDataset(), + framework::dataset::make("UseBeta", false)), + framework::dataset::make("UseGamma", false)), + framework::dataset::make("ActivationInfo", ActivationLayerInfo())), + framework::dataset::make("DataType", DataType::QS16)), + framework::dataset::make("FractionalBits", 1, 14))) { // Validate output validate(Accessor(_target), _reference, tolerance_qs16, 0); diff --git a/tests/validation/fixtures/BatchNormalizationLayerFixture.h b/tests/validation/fixtures/BatchNormalizationLayerFixture.h index e02c619249..4a6ac1af7f 100644 --- a/tests/validation/fixtures/BatchNormalizationLayerFixture.h +++ b/tests/validation/fixtures/BatchNormalizationLayerFixture.h @@ -45,10 +45,12 @@ class BatchNormalizationLayerValidationFixedPointFixture : public framework::Fix { public: template - void setup(TensorShape shape0, TensorShape shape1, float epsilon, ActivationLayerInfo act_info, DataType dt, int fractional_bits) + void setup(TensorShape shape0, TensorShape shape1, float epsilon, bool use_beta, bool use_gamma, ActivationLayerInfo act_info, DataType dt, int fractional_bits) { _fractional_bits = fractional_bits; _data_type = dt; + _use_beta = use_beta; + _use_gamma = use_gamma; _target = compute_target(shape0, shape1, epsilon, act_info, dt, fractional_bits); _reference = compute_reference(shape0, shape1, epsilon, act_info, dt, fractional_bits); } @@ -67,8 +69,24 @@ protected: library->fill(src_tensor, distribution, 0); library->fill(mean_tensor, distribution, 1); library->fill(var_tensor, distribution_var, 0); - library->fill(beta_tensor, distribution, 3); - library->fill(gamma_tensor, distribution, 4); + if(_use_beta) + { + library->fill(beta_tensor, distribution, 3); + } + else + { + // Fill with default value 0.f + library->fill_tensor_value(beta_tensor, 0.f); + } + if(_use_gamma) + { + library->fill(gamma_tensor, distribution, 4); + } + else + { + // Fill with default value 1.f + library->fill_tensor_value(gamma_tensor, 1.f); + } } else { @@ -80,8 +98,24 @@ protected: library->fill(src_tensor, distribution, 0); library->fill(mean_tensor, distribution, 1); library->fill(var_tensor, distribution_var, 0); - library->fill(beta_tensor, distribution, 3); - library->fill(gamma_tensor, distribution, 4); + if(_use_beta) + { + library->fill(beta_tensor, distribution, 3); + } + else + { + // Fill with default value 0 + library->fill_tensor_value(beta_tensor, static_cast(0)); + } + if(_use_gamma) + { + library->fill(gamma_tensor, distribution, 4); + } + else + { + // Fill with default value 1 + library->fill_tensor_value(gamma_tensor, static_cast(1 << (_fractional_bits))); + } } } @@ -97,7 +131,9 @@ protected: // Create and configure function FunctionType norm; - norm.configure(&src, &dst, &mean, &var, &beta, &gamma, epsilon, act_info); + TensorType *beta_ptr = _use_beta ? &beta : nullptr; + TensorType *gamma_ptr = _use_gamma ? &gamma : nullptr; + norm.configure(&src, &dst, &mean, &var, beta_ptr, gamma_ptr, epsilon, act_info); ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); @@ -149,6 +185,8 @@ protected: SimpleTensor _reference{}; int _fractional_bits{}; DataType _data_type{}; + bool _use_beta{}; + bool _use_gamma{}; }; template @@ -156,9 +194,9 @@ class BatchNormalizationLayerValidationFixture : public BatchNormalizationLayerV { public: template - void setup(TensorShape shape0, TensorShape shape1, float epsilon, ActivationLayerInfo act_info, DataType dt) + void setup(TensorShape shape0, TensorShape shape1, float epsilon, bool use_beta, bool use_gamma, ActivationLayerInfo act_info, DataType dt) { - BatchNormalizationLayerValidationFixedPointFixture::setup(shape0, shape1, epsilon, act_info, dt, 0); + BatchNormalizationLayerValidationFixedPointFixture::setup(shape0, shape1, epsilon, use_beta, use_gamma, act_info, dt, 0); } }; } // namespace validation diff --git a/tests/validation/reference/BatchNormalizationLayer.cpp b/tests/validation/reference/BatchNormalizationLayer.cpp index a9d9f0320d..c8badacc79 100644 --- a/tests/validation/reference/BatchNormalizationLayer.cpp +++ b/tests/validation/reference/BatchNormalizationLayer.cpp @@ -106,7 +106,6 @@ SimpleTensor batch_normalization_layer(const SimpleTensor &src, const Simp const float numerator = src[pos] - mean[i]; const float x_bar = numerator / denominator; result[pos] = beta[i] + x_bar * gamma[i]; - ; } } } -- cgit v1.2.1