stochastic_gradient_ascent_test.cpp
Go to the documentation of this file.
1 #include <ostream>
3 #include <stan/io/dump.hpp>
7 #include <boost/math/special_functions/fpclassify.hpp>
8 #include <gtest/gtest.h>
9 #include <test/unit/util.hpp>
11 #include <boost/random/additive_combine.hpp> // L'Ecuyer RNG
12 
13 typedef boost::ecuyer1988 rng_t;
14 
15 // Mock Model
16 class mock_model: public stan::model::prob_grad {
17 public:
18 
20  stan::model::prob_grad(num_params_r),
24  log_prob_return_value(0.0) { }
25 
26  void reset() {
31  }
32 
33  template <bool propto, bool jacobian_adjust_transforms, typename T>
34  T log_prob(Eigen::Matrix<T,Eigen::Dynamic,1>& params_r,
35  std::ostream* output_stream = 0) const {
37  return log_prob_return_value;
38  }
39 
40  void transform_inits(const stan::io::var_context& context__,
41  Eigen::VectorXd& params_r__,
42  std::ostream* out) const {
44  for (int n = 0; n < params_r__.size(); n++) {
45  params_r__[n] = n;
46  }
47  }
48 
49  void get_dims(std::vector<std::vector<size_t> >& dimss__) const {
50  dimss__.resize(0);
51  std::vector<size_t> scalar_dim;
52  dimss__.push_back(scalar_dim);
53  dimss__.push_back(scalar_dim);
54  dimss__.push_back(scalar_dim);
55  }
56 
57  void constrained_param_names(std::vector<std::string>& param_names__,
58  bool include_tparams__ = true,
59  bool include_gqs__ = true) const {
60  param_names__.push_back("a");
61  param_names__.push_back("b");
62  param_names__.push_back("c");
63  }
64 
65  void get_param_names(std::vector<std::string>& names) const {
67  }
68 
69  void unconstrained_param_names(std::vector<std::string>& param_names__,
70  bool include_tparams__ = true,
71  bool include_gqs__ = true) const {
72  param_names__.clear();
73  for (size_t n = 0; n < num_params_r__; n++) {
74  std::stringstream param_name;
75  param_name << "param_" << n;
76  param_names__.push_back(param_name.str());
77  }
78  }
79 
80  template <typename RNG>
81  void write_array(RNG& base_rng__,
82  std::vector<double>& params_r__,
83  std::vector<int>& params_i__,
84  std::vector<double>& vars__,
85  bool include_tparams__ = true,
86  bool include_gqs__ = true,
87  std::ostream* pstream__ = 0) const {
89  vars__.resize(0);
90  for (size_t i = 0; i < params_r__.size(); i++)
91  vars__.push_back(params_r__[i]);
92  }
93 
94  mutable int templated_log_prob_calls;
95  mutable int transform_inits_calls;
96  mutable int write_array_calls;
97  double log_prob_return_value;
98 };
99 
100 // Mock Throwing Model throws exception
102 public:
103 
105  stan::model::prob_grad(num_params_r),
109  log_prob_return_value(0.0) { }
110 
111  void reset() {
114  write_array_calls = 0;
115  log_prob_return_value = 0.0;
116  }
117 
118  template <bool propto, bool jacobian_adjust_transforms, typename T>
119  T log_prob(Eigen::Matrix<T,Eigen::Dynamic,1>& params_r,
120  std::ostream* output_stream = 0) const {
122  throw std::domain_error("throwing within log_prob");
123  return log_prob_return_value;
124  }
125 
126  void transform_inits(const stan::io::var_context& context__,
127  Eigen::VectorXd& params_r__,
128  std::ostream* out) const {
130  for (int n = 0; n < params_r__.size(); n++) {
131  params_r__[n] = n;
132  }
133  }
134 
135  void get_dims(std::vector<std::vector<size_t> >& dimss__) const {
136  dimss__.resize(0);
137  std::vector<size_t> scalar_dim;
138  dimss__.push_back(scalar_dim);
139  dimss__.push_back(scalar_dim);
140  dimss__.push_back(scalar_dim);
141  }
142 
143  void constrained_param_names(std::vector<std::string>& param_names__,
144  bool include_tparams__ = true,
145  bool include_gqs__ = true) const {
146  param_names__.push_back("a");
147  param_names__.push_back("b");
148  param_names__.push_back("c");
149  }
150 
151  void get_param_names(std::vector<std::string>& names) const {
153  }
154 
155  void unconstrained_param_names(std::vector<std::string>& param_names__,
156  bool include_tparams__ = true,
157  bool include_gqs__ = true) const {
158  param_names__.clear();
159  for (size_t n = 0; n < num_params_r__; n++) {
160  std::stringstream param_name;
161  param_name << "param_" << n;
162  param_names__.push_back(param_name.str());
163  }
164  }
165 
166  template <typename RNG>
167  void write_array(RNG& base_rng__,
168  std::vector<double>& params_r__,
169  std::vector<int>& params_i__,
170  std::vector<double>& vars__,
171  bool include_tparams__ = true,
172  bool include_gqs__ = true,
173  std::ostream* pstream__ = 0) const {
175  vars__.resize(0);
176  for (size_t i = 0; i < params_r__.size(); i++)
177  vars__.push_back(params_r__[i]);
178  }
179 
180  mutable int templated_log_prob_calls;
181  mutable int transform_inits_calls;
182  mutable int write_array_calls;
183  double log_prob_return_value;
184 };
185 
186 class mock_rng {
187 public:
188  typedef double result_type;
189 
191  calls(0) { }
192 
193  void reset() {
194  calls = 0;
195  }
196 
197  result_type operator()() {
198  calls++;
199  return calls / 10000.0;
200  }
201 
202  static result_type max() {
203  return 1.0;
204  }
205 
206  static result_type min() {
207  return -1.0;
208  }
209 
210  int calls;
211 };
212 
213 
214 class stochastic_gradient_ascent_test : public testing::Test {
215 public:
217  model(3),
218  throwing_model(3),
219  writer(writer_output),
220  logger(logger_output, logger_output, logger_output, logger_output, logger_output) {}
221 
222  void SetUp() {
223  cont_params = Eigen::VectorXd::Zero(3);
224  model.reset();
225  rng.reset();
226  writer_output.clear();
227  logger_output.clear();
228  }
229 
231  Eigen::VectorXd cont_params;
235  std::stringstream writer_output, logger_output;
238 };
239 
240 TEST_F(stochastic_gradient_ascent_test, initialize_state_zero_negative_infinity) {
241  model.log_prob_return_value =
242  -std::numeric_limits<double>::infinity();
243 
246  mock_rng> *advi_meanfield =
248  stan::variational::normal_meanfield,
249  mock_rng>
250  (model,
251  cont_params, rng,
252  1, 100,
253  100, 1);
254 
257  mock_rng> *advi_fullrank =
259  stan::variational::normal_fullrank,
260  mock_rng>
261  (model,
262  cont_params, rng,
263  1, 100,
264  100, 1);
265 
266  stan::variational::normal_meanfield meanfield_init =
267  stan::variational::normal_meanfield(cont_params);
268  stan::variational::normal_fullrank fullrank_init =
269  stan::variational::normal_fullrank(cont_params);
270 
271  std::string error = "stan::variational::advi::calc_ELBO: "
272  "The number of dropped evaluations "
273  "has reached its maximum amount (100). "
274  "Your model may be either severely "
275  "ill-conditioned or misspecified.";
276 
277  EXPECT_THROW_MSG(advi_meanfield->stochastic_gradient_ascent(meanfield_init,
278  1.0,
279  0.01,
280  1000,
281  logger,
282  writer),
284  EXPECT_THROW_MSG(advi_fullrank->stochastic_gradient_ascent(fullrank_init,
285  1.0,
286  0.01,
287  1000,
288  logger,
289  writer),
291 
292  delete advi_meanfield;
293  delete advi_fullrank;
294 }
295 
296 TEST_F(stochastic_gradient_ascent_test, initialize_state_zero_grad_error) {
297  throwing_model.log_prob_return_value =
298  -std::numeric_limits<double>::infinity();
299 
302  mock_rng> *advi_meanfield =
303  new stan::variational::advi<mock_throwing_model,
304  stan::variational::normal_meanfield,
305  mock_rng>
306  (throwing_model,
307  cont_params, rng,
308  1, 100,
309  100, 1);
310 
311  stan::variational::advi<mock_throwing_model,
313  mock_rng> *advi_fullrank =
314  new stan::variational::advi<mock_throwing_model,
315  stan::variational::normal_fullrank,
316  mock_rng>
317  (throwing_model,
318  cont_params, rng,
319  1, 100,
320  100, 1);
321 
322  stan::variational::normal_meanfield meanfield_init =
323  stan::variational::normal_meanfield(cont_params);
324  stan::variational::normal_fullrank fullrank_init =
325  stan::variational::normal_fullrank(cont_params);
326 
327  std::string error = "stan::variational::normal_meanfield::calc_grad: "
328  "The number of dropped evaluations "
329  "has reached its maximum amount (10). "
330  "Your model may be either severely "
331  "ill-conditioned or misspecified.";
332 
333  EXPECT_THROW_MSG(advi_meanfield->stochastic_gradient_ascent(meanfield_init,
334  1.0,
335  0.01,
336  1000,
337  logger,
338  writer),
340 
341  error = "stan::variational::normal_fullrank::calc_grad: "
342  "The number of dropped evaluations "
343  "has reached its maximum amount (10). "
344  "Your model may be either severely "
345  "ill-conditioned or misspecified.";
346 
347  EXPECT_THROW_MSG(advi_fullrank->stochastic_gradient_ascent(fullrank_init,
348  1.0,
349  0.01,
350  1000,
351  logger,
352  writer),
354 
355  delete advi_meanfield;
356  delete advi_fullrank;
357 }
void get_param_names(std::vector< std::string > &names) const
void unconstrained_param_names(std::vector< std::string > &param_names__, bool include_tparams__=true, bool include_gqs__=true) const
boost::ecuyer1988 rng_t
#define EXPECT_THROW_MSG(expr, T_e, msg)
Definition: util.hpp:6
TEST_F(stochastic_gradient_ascent_test, initialize_state_zero_negative_infinity)
void get_dims(std::vector< std::vector< size_t > > &dimss__) const
void unconstrained_param_names(std::vector< std::string > &param_names__, bool include_tparams__=true, bool include_gqs__=true) const
prob_grad(size_t num_params_r)
Definition: prob_grad.hpp:23
T log_prob(Eigen::Matrix< T, Eigen::Dynamic, 1 > &params_r, std::ostream *output_stream=0) const
void constrained_param_names(std::vector< std::string > &param_names__, bool include_tparams__=true, bool include_gqs__=true) const
void write_array(RNG &base_rng__, std::vector< double > &params_r__, std::vector< int > &params_i__, std::vector< double > &vars__, bool include_tparams__=true, bool include_gqs__=true, std::ostream *pstream__=0) const
void transform_inits(const stan::io::var_context &context__, Eigen::VectorXd &params_r__, std::ostream *out) const
void domain_error(const char *function, const char *name, const T &y, const char *msg1, const char *msg2)
mock_model(size_t num_params_r)
void get_dims(std::vector< std::vector< size_t > > &dimss__) const
T log_prob(Eigen::Matrix< T, Eigen::Dynamic, 1 > &params_r, std::ostream *output_stream=0) const
void transform_inits(const stan::io::var_context &context__, Eigen::VectorXd &params_r__, std::ostream *out) const
void Zero()
static result_type max()
size_t num_params_r() const
Definition: prob_grad.hpp:36
double T
Definition: Xdiff_gwt.C:5
void get_param_names(std::vector< std::string > &names) const
static result_type min()
void constrained_param_names(std::vector< std::string > &param_names__, bool include_tparams__=true, bool include_gqs__=true) const
const XML_Char XML_Content * model
Definition: expat.h:151
void write_array(RNG &base_rng__, std::vector< double > &params_r__, std::vector< int > &params_i__, std::vector< double > &vars__, bool include_tparams__=true, bool include_gqs__=true, std::ostream *pstream__=0) const
enum BeamMode string