Stan  1.0
probability, sampling & optimization
hmc_base.hpp
Go to the documentation of this file.
1 #ifndef __STAN__MCMC__HMC_BASE_H__
2 #define __STAN__MCMC__HMC_BASE_H__
3 
4 #include <ctime>
5 
6 #include <boost/random/normal_distribution.hpp>
7 #include <boost/random/mersenne_twister.hpp>
8 #include <boost/random/variate_generator.hpp>
9 #include <boost/random/uniform_01.hpp>
10 
13 #include <stan/model/prob_grad.hpp>
14 #include <stan/mcmc/util.hpp>
15 
16 
17 namespace stan {
18 
19  namespace mcmc {
20 
21  template <class BaseRNG = boost::mt19937>
22  class hmc_base : public adaptive_sampler {
23 
24  protected:
25 
26  // model from which to sample
27  stan::model::prob_grad& _model; // model to sample
28 
29  double _epsilon; // step size for Hamiltonian sim
30  double _epsilon_pm; // +/- around epsilon
31  double _epsilon_last; // last value of epsilon used
32  bool _epsilon_adapt; // true if adapt(ed) epsilon
33 
34  const double _delta; // target E[accept]
35  const double _gamma; // tuning param for dual avg
36  DualAverage _da; // impl of dual avg adaptation
37 
38  BaseRNG _rand_int; // base random number generator
39 
40  boost::variate_generator<BaseRNG&,
41  boost::normal_distribution<> > _rand_unit_norm;
42  // normal(0,1) RNG
43 
44  boost::uniform_01<BaseRNG&> _rand_uniform_01;
45  // uniform(0,1) RNG
46 
47  std::vector<double> _x; // most recent real params
48  std::vector<int> _z; // most recent discrete params
49  std::vector<double> _g; // most recent gradient
50  double _logp; // most recent log prob
51 
56  virtual void find_reasonable_parameters() {
57  this->_epsilon = 1.0;
58  std::vector<double> x = this->_x;
59  std::vector<double> m(this->_model.num_params_r());
60  for (size_t i = 0; i < m.size(); ++i)
61  m[i] = this->_rand_unit_norm();
62  std::vector<double> g = this->_g;
63  double lastlogp = this->_logp;
64  double logp = leapfrog(this->_model, this->_z, x, m, g, this->_epsilon);
65  double H = logp - lastlogp;
66  int direction = H > log(0.5) ? 1 : -1;
67  while (1) {
68  x = this->_x;
69  g = this->_g;
70  for (size_t i = 0; i < m.size(); ++i)
71  m[i] = this->_rand_unit_norm();
72  logp = leapfrog(this->_model, this->_z, x, m, g, this->_epsilon);
73  H = logp - lastlogp;
74  if ((direction == 1) && !(H > log(0.5)))
75  break;
76  else if ((direction == -1) && !(H < log(0.5)))
77  break;
78  else
79  this->_epsilon = ( (direction == 1)
80  ? 2.0 * this->_epsilon
81  : 0.5 * this->_epsilon );
82 
83  if (this->_epsilon > 1e300)
84  throw std::runtime_error("Posterior is improper. Please check your model.");
85  if (this->_epsilon == 0)
86  throw std::runtime_error("No acceptably small step size could be found. Perhaps the posterior is not continuous?");
87  }
88  }
89 
90  void adaptation_init(double epsilon_scale) {
91  if (this->adapting())
92  this->_da.setx0(std::vector<double>(1, log(epsilon_scale * _epsilon)));
93  }
94 
95  public:
96 
116  double epsilon=-1,
117  double epsilon_pm = 0.0,
118  bool epsilon_adapt = true,
119  double delta = 0.651,
120  double gamma = 0.05,
121  BaseRNG rand_int = BaseRNG(std::time(0)),
122  const std::vector<double>* params_r = 0,
123  const std::vector<int>* params_i = 0)
124  : adaptive_sampler(epsilon_adapt),
125  _model(model),
126  _epsilon(epsilon),
127  _epsilon_pm(epsilon_pm),
129  _epsilon_adapt(epsilon_adapt),
130  _delta(delta),
131  _gamma(gamma),
132  _da(gamma, std::vector<double>(1, 0.0)),
133  _rand_int(rand_int),
134  _rand_unit_norm(_rand_int, boost::normal_distribution<>()),
136  _x(model.num_params_r()),
137  _z(model.num_params_i()),
138  _g(model.num_params_r())
139  {
140  model.init(_x,_z);
141  if (params_r) {
142  if (params_r->size() != model.num_params_r())
143  throw std::invalid_argument("hmc_base ctor: double params must match in size");
144  _x = *params_r;
145  }
146  if (params_i) {
147  if (params_i->size() != model.num_params_i())
148  throw std::invalid_argument("hmc_base ctor: int params must match in size");
149  _z = *params_i;
150  }
151  _logp = model.grad_log_prob(_x,_z,_g);
152  if (epsilon_adapt)
154  }
155 
156  virtual ~hmc_base() { }
157 
168  virtual void set_params(const std::vector<double>& x,
169  const std::vector<int>& z) {
170  if (x.size() != this->_x.size())
171  throw std::invalid_argument("hmc_base::set_params double params must match in size");
172  if (z.size() != this->_z.size())
173  throw std::invalid_argument("hmc_base::set_params int params must match in size");
174  this->_x = x;
175  this->_z = z;
176  this->_logp = this->_model.grad_log_prob(this->_x,this->_z,this->_g);
177  }
178 
190  void set_params_r(const std::vector<double>& x) {
191  if (x.size() != this->_model.num_params_r())
192  throw std::invalid_argument("x.size() must match num model params.");
193  this->_x = x;
194  this->_logp = this->_model.grad_log_prob(this->_x,this->_z,this->_g);
195  }
196 
197 
209  void set_params_i(const std::vector<int>& z) {
210  if (z.size() != this->_model.num_params_i())
211  throw std::invalid_argument("z.size() must match num params");
212  this->_z = z;
213  this->_logp = this->_model.grad_log_prob(this->_x,this->_z,this->_g);
214  }
215 
217  return this->_epsilon_pm != 0;
218  }
219 
228  virtual void adapt_off() {
229  if (!this->adapting()) return;
231  std::vector<double> result;
232  this->_da.xbar(result);
233  this->_epsilon = exp(result[0]);
234  }
235 
241  virtual void get_parameters(std::vector<double>& params) {
242  params.assign(1, this->_epsilon);
243  }
244 
245 
246 
247 
248 
249 
250  }; // class hmc_base
251 
252  }
253 }
254 
255 
256 #endif
Implements Nesterov's dual average algorithm.
Definition: dualaverage.hpp:28
void setx0(const std::vector< double > &x0)
Set the point towards which each iterate is shrunk.
Definition: dualaverage.hpp:75
void xbar(std::vector< double > &xbar)
Get the exponentially weighted moving average of all previous iterates.
Definition: dualaverage.hpp:86
An abstract base class for adaptive samplers.
bool adapting()
Return whether or not parameter adaptation is on.
virtual void adapt_off()
Turn off parameter adaption.
boost::uniform_01< BaseRNG & > _rand_uniform_01
Definition: hmc_base.hpp:44
std::vector< double > _g
Definition: hmc_base.hpp:49
void set_params_r(const std::vector< double > &x)
Sets the model real parameters to the specified values and update gradients and log probability to ma...
Definition: hmc_base.hpp:190
const double _gamma
Definition: hmc_base.hpp:35
stan::model::prob_grad & _model
Definition: hmc_base.hpp:27
void adaptation_init(double epsilon_scale)
Definition: hmc_base.hpp:90
std::vector< double > _x
Definition: hmc_base.hpp:47
boost::variate_generator< BaseRNG &, boost::normal_distribution<> > _rand_unit_norm
Definition: hmc_base.hpp:41
hmc_base(stan::model::prob_grad &model, double epsilon=-1, double epsilon_pm=0.0, bool epsilon_adapt=true, double delta=0.651, double gamma=0.05, BaseRNG rand_int=BaseRNG(std::time(0)), const std::vector< double > *params_r=0, const std::vector< int > *params_i=0)
Construct a base HMC sampler.
Definition: hmc_base.hpp:115
std::vector< int > _z
Definition: hmc_base.hpp:48
virtual void adapt_off()
Turn off parameter adaptation.
Definition: hmc_base.hpp:228
virtual void get_parameters(std::vector< double > &params)
Write the step size into position 1 of the specified vector.
Definition: hmc_base.hpp:241
void set_params_i(const std::vector< int > &z)
Sets the model integer parameters to the specified values and update gradients and log probability to...
Definition: hmc_base.hpp:209
virtual void find_reasonable_parameters()
Search for a roughly reasonable (within a factor of 2) setting of the step size epsilon.
Definition: hmc_base.hpp:56
virtual void set_params(const std::vector< double > &x, const std::vector< int > &z)
Sets the model real and integer parameters to the specified values.
Definition: hmc_base.hpp:168
DualAverage _da
Definition: hmc_base.hpp:36
const double _delta
Definition: hmc_base.hpp:34
The prob_grad class represents densities with fixed numbers of discrete and scalar parameters and the...
Definition: prob_grad.hpp:24
virtual void init(std::vector< double > &params_r, std::vector< int > &params_i)
Definition: prob_grad.hpp:80
virtual size_t num_params_r()
Definition: prob_grad.hpp:52
virtual size_t num_params_i()
Definition: prob_grad.hpp:56
virtual double grad_log_prob(std::vector< double > &params_r, std::vector< int > &params_i, std::vector< double > &gradient, std::ostream *output_stream=0)=0
Reimplementing boost functionality.
var log(const var &a)
Return the natural log of the specified variable (cmath).
Definition: agrad.hpp:1730
var exp(const var &a)
Return the exponentiation of the specified variable (cmath).
Definition: agrad.hpp:1716
double epsilon()
Return minimum positive number representable.
double leapfrog(stan::model::prob_grad &model, std::vector< int > z, std::vector< double > &x, std::vector< double > &m, std::vector< double > &g, double epsilon, std::ostream *error_msgs=0, std::ostream *output_msgs=0)
Computes the log probability for a single leapfrog step in Hamiltonian Monte Carlo.
Definition: util.hpp:57
Probability, optimization and sampling library.
Definition: agrad.cpp:6
Template specification of functions in std for Stan.
Definition: agrad.hpp:2306

     [ Stan Home Page ] © 2011–2012, Stan Development Team.