From 04ca88ac15beb35cd127e7c6c2233b774e12c994 Mon Sep 17 00:00:00 2001 From: Kai Li Date: Sat, 11 Jan 2014 23:51:54 +0800 Subject: [PATCH] Fixed uniform distribution upper bound to be inclusive --- include/caffe/util/math_functions.hpp | 3 + .../test/test_multinomial_logistic_loss_layer.cpp | 1 + src/caffe/test/test_random_number_generator.cpp | 67 ++++++++++++++++++++++ src/caffe/util/math_functions.cpp | 15 ++++- 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 src/caffe/test/test_random_number_generator.cpp diff --git a/include/caffe/util/math_functions.hpp b/include/caffe/util/math_functions.hpp index be19204..1ff8a77 100644 --- a/include/caffe/util/math_functions.hpp +++ b/include/caffe/util/math_functions.hpp @@ -87,6 +87,9 @@ template void caffe_powx(const int n, const Dtype* a, const Dtype b, Dtype* y); template +Dtype caffe_nextafter(const Dtype b); + +template void caffe_vRngUniform(const int n, Dtype* r, const Dtype a, const Dtype b); template diff --git a/src/caffe/test/test_multinomial_logistic_loss_layer.cpp b/src/caffe/test/test_multinomial_logistic_loss_layer.cpp index 5169b70..bb3e892 100644 --- a/src/caffe/test/test_multinomial_logistic_loss_layer.cpp +++ b/src/caffe/test/test_multinomial_logistic_loss_layer.cpp @@ -25,6 +25,7 @@ class MultinomialLogisticLossLayerTest : public ::testing::Test { MultinomialLogisticLossLayerTest() : blob_bottom_data_(new Blob(10, 5, 1, 1)), blob_bottom_label_(new Blob(10, 1, 1, 1)) { + Caffe::set_random_seed(1701); // fill the values FillerParameter filler_param; PositiveUnitballFiller filler(filler_param); diff --git a/src/caffe/test/test_random_number_generator.cpp b/src/caffe/test/test_random_number_generator.cpp new file mode 100644 index 0000000..4c3358f --- /dev/null +++ b/src/caffe/test/test_random_number_generator.cpp @@ -0,0 +1,67 @@ +#include +#include +#include + +#include "gtest/gtest.h" +#include "caffe/common.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class RandomNumberGeneratorTest : public ::testing::Test { + public: + virtual ~RandomNumberGeneratorTest() {} + + Dtype sample_mean(const Dtype* const seqs, const size_t sample_size) + { + double sum = 0; + for (int i = 0; i < sample_size; ++i) { + sum += seqs[i]; + } + return sum / sample_size; + } + + Dtype mean_bound(const Dtype std, const size_t sample_size) + { + return std/sqrt((double)sample_size); + } +}; + + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(RandomNumberGeneratorTest, Dtypes); + +TYPED_TEST(RandomNumberGeneratorTest, TestRngGaussian) { + size_t sample_size = 10000; + SyncedMemory data_a(sample_size * sizeof(TypeParam)); + Caffe::set_random_seed(1701); + TypeParam mu = 0; + TypeParam sigma = 1; + caffe_vRngGaussian(sample_size, (TypeParam*)data_a.mutable_cpu_data(), mu, sigma); + TypeParam true_mean = mu; + TypeParam true_std = sigma; + TypeParam bound = mean_bound(true_std, sample_size); + TypeParam real_mean = sample_mean((TypeParam*)data_a.cpu_data(), sample_size); + EXPECT_NEAR(real_mean, true_mean, bound); +} + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniform) { + size_t sample_size = 10000; + SyncedMemory data_a(sample_size * sizeof(TypeParam)); + Caffe::set_random_seed(1701); + TypeParam lower = 0; + TypeParam upper = 1; + caffe_vRngUniform(sample_size, (TypeParam*)data_a.mutable_cpu_data(), lower, upper); + TypeParam true_mean = (lower + upper) / 2; + TypeParam true_std = (upper - lower) / sqrt(12); + TypeParam bound = mean_bound(true_std, sample_size); + TypeParam real_mean = sample_mean((TypeParam*)data_a.cpu_data(), sample_size); + EXPECT_NEAR(real_mean, true_mean, bound); +} + + + +} // namespace caffe diff --git a/src/caffe/util/math_functions.cpp b/src/caffe/util/math_functions.cpp index c3c0a69..850a408 100644 --- a/src/caffe/util/math_functions.cpp +++ b/src/caffe/util/math_functions.cpp @@ -1,8 +1,10 @@ // Copyright 2013 Yangqing Jia // Copyright 2014 kloudkl@github +#include //#include #include +#include #include #include @@ -281,6 +283,11 @@ void caffe_powx(const int n, const double* a, const double b, map_vector_double_t(y, n) = const_map_vector_double_t(a, n).array().pow(b); } +template +Dtype caffe_nextafter(const Dtype b) { + return boost::math::nextafter(b, std::numeric_limits::max()); +} + template <> void caffe_vRngUniform(const int n, float* r, const float a, const float b) { @@ -288,7 +295,8 @@ void caffe_vRngUniform(const int n, float* r, // n, r, a, b)); // FIXME check if boundaries are handled in the same way ? - boost::uniform_real random_distribution(a, b); + boost::random::uniform_real_distribution random_distribution( + a, caffe_nextafter(b)); Caffe::random_generator_t &generator = Caffe::vsl_stream(); for(int i = 0; i < n; i += 1) @@ -304,7 +312,8 @@ void caffe_vRngUniform(const int n, double* r, // n, r, a, b)); // FIXME check if boundaries are handled in the same way ? - boost::uniform_real random_distribution(a, b); + boost::random::uniform_real_distribution random_distribution( + a, caffe_nextafter(b)); Caffe::random_generator_t &generator = Caffe::vsl_stream(); for(int i = 0; i < n; i += 1) @@ -316,6 +325,7 @@ void caffe_vRngUniform(const int n, double* r, template <> void caffe_vRngGaussian(const int n, float* r, const float a, const float sigma) { + DCHECK(sigma > 0); //VSL_CHECK(vsRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER, // Caffe::vsl_stream(), n, r, a, sigma)); @@ -333,6 +343,7 @@ void caffe_vRngGaussian(const int n, float* r, const float a, template <> void caffe_vRngGaussian(const int n, double* r, const double a, const double sigma) { + DCHECK(sigma > 0); //VSL_CHECK(vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER, // Caffe::vsl_stream(), n, r, a, sigma)); -- 2.7.4