Fixed uniform distribution upper bound to be inclusive
authorKai Li <kaili_kloud@163.com>
Sat, 11 Jan 2014 15:51:54 +0000 (23:51 +0800)
committerEvan Shelhamer <shelhamer@imaginarynumber.net>
Fri, 21 Mar 2014 20:52:34 +0000 (13:52 -0700)
include/caffe/util/math_functions.hpp
src/caffe/test/test_multinomial_logistic_loss_layer.cpp
src/caffe/test/test_random_number_generator.cpp [new file with mode: 0644]
src/caffe/util/math_functions.cpp

index be19204..1ff8a77 100644 (file)
@@ -87,6 +87,9 @@ template <typename Dtype>
 void caffe_powx(const int n, const Dtype* a, const Dtype b, Dtype* y);
 
 template <typename Dtype>
+Dtype caffe_nextafter(const Dtype b);
+
+template <typename Dtype>
 void caffe_vRngUniform(const int n, Dtype* r, const Dtype a, const Dtype b);
 
 template <typename Dtype>
index 5169b70..bb3e892 100644 (file)
@@ -25,6 +25,7 @@ class MultinomialLogisticLossLayerTest : public ::testing::Test {
   MultinomialLogisticLossLayerTest()
       : blob_bottom_data_(new Blob<Dtype>(10, 5, 1, 1)),
         blob_bottom_label_(new Blob<Dtype>(10, 1, 1, 1)) {
+    Caffe::set_random_seed(1701);
     // fill the values
     FillerParameter filler_param;
     PositiveUnitballFiller<Dtype> 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 (file)
index 0000000..4c3358f
--- /dev/null
@@ -0,0 +1,67 @@
+#include <cmath>
+#include <cstring>
+#include <cuda_runtime.h>
+
+#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 <typename Dtype>
+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<float, double> 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
index c3c0a69..850a408 100644 (file)
@@ -1,8 +1,10 @@
 // Copyright 2013 Yangqing Jia
 // Copyright 2014 kloudkl@github
 
+#include <limits>
 //#include <mkl.h>
 #include <eigen3/Eigen/Dense>
+#include <boost/math/special_functions/next.hpp>
 #include <boost/random.hpp>
 
 #include <cublas_v2.h>
@@ -281,6 +283,11 @@ void caffe_powx<double>(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 <typename Dtype>
+Dtype caffe_nextafter(const Dtype b) {
+  return boost::math::nextafter<Dtype, Dtype>(b, std::numeric_limits<Dtype>::max());
+}
+
 template <>
 void caffe_vRngUniform<float>(const int n, float* r,
     const float a, const float b) {
@@ -288,7 +295,8 @@ void caffe_vRngUniform<float>(const int n, float* r,
   //    n, r, a, b));
 
   // FIXME check if boundaries are handled in the same way ?
-  boost::uniform_real<float> random_distribution(a, b);
+  boost::random::uniform_real_distribution<float> random_distribution(
+      a, caffe_nextafter<float>(b));
   Caffe::random_generator_t &generator = Caffe::vsl_stream();
 
   for(int i = 0; i < n; i += 1)
@@ -304,7 +312,8 @@ void caffe_vRngUniform<double>(const int n, double* r,
   //    n, r, a, b));
 
     // FIXME check if boundaries are handled in the same way ?
-    boost::uniform_real<double> random_distribution(a, b);
+    boost::random::uniform_real_distribution<double> random_distribution(
+        a, caffe_nextafter<double>(b));
     Caffe::random_generator_t &generator = Caffe::vsl_stream();
 
     for(int i = 0; i < n; i += 1)
@@ -316,6 +325,7 @@ void caffe_vRngUniform<double>(const int n, double* r,
 template <>
 void caffe_vRngGaussian<float>(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<float>(const int n, float* r, const float a,
 template <>
 void caffe_vRngGaussian<double>(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));