Stan  1.3
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
adaptive_hmc.hpp
Go to the documentation of this file.
1 #ifndef __STAN__MCMC__ADAPTIVE_HMC_H__
2 #define __STAN__MCMC__ADAPTIVE_HMC_H__
3 
4 #include <ctime>
5 #include <cstddef>
6 #include <iostream>
7 #include <vector>
8 
9 #include <boost/random/mersenne_twister.hpp>
10 #include <boost/random/normal_distribution.hpp>
11 #include <boost/random/uniform_01.hpp>
12 #include <boost/random/variate_generator.hpp>
13 
18 #include <stan/mcmc/hmc_base.hpp>
19 #include <stan/mcmc/util.hpp>
20 #include <stan/model/prob_grad.hpp>
21 
22 namespace stan {
23 
24  namespace mcmc {
25 
41  template <class BaseRNG = boost::mt19937>
42  class adaptive_hmc : public hmc_base<BaseRNG> {
43  private:
44 
45  unsigned int _L; // fixed number of Hamiltonian simulation steps
46 
47  public:
48 
79  const std::vector<double>& params_r,
80  const std::vector<int>& params_i,
81  int L,
82  double epsilon=-1,
83  double epsilon_pm = 0.0,
84  bool epsilon_adapt = true,
85  double delta = 0.651,
86  double gamma = 0.05,
87  BaseRNG rand_int = BaseRNG(std::time(0)))
88  : hmc_base<BaseRNG>(model,
89  params_r,
90  params_i,
91  epsilon,
92  epsilon_pm,
93  epsilon_adapt,
94  delta,
95  gamma,
96  rand_int),
97  _L(L) {
98  this->adaptation_init(1.0); // target is just epsilon
99  }
100 
101 
106  }
107 
108 
114  virtual sample next_impl() {
115  // Gibbs for discrete
116  // std::vector<double> probs;
117  // for (size_t m = 0; m < this->_model.num_params_i(); ++m) {
118  // probs.resize(0);
119  // for (int k = this->_model.param_range_i_lower(m);
120  // k < this->_model.param_range_i_upper(m);
121  // ++k)
122  // probs.push_back(this->_model.log_prob_star(m,k,this->_x,this->_z));
123  // this->_z[m] = sample_unnorm_log(probs,this->_rand_uniform_01);
124  // }
125  // HMC for continuous
126  std::vector<double> m(this->_model.num_params_r());
127  for (size_t i = 0; i < m.size(); ++i)
128  m[i] = this->_rand_unit_norm();
129  double H = -(stan::math::dot_self(m) / 2.0) + this->_logp;
130 
131  std::vector<double> g_new(this->_g);
132  std::vector<double> x_new(this->_x);
133  double logp_new = -1e100;
134  double epsilon = this->_epsilon;
135  // only vary epsilon after done adapting
136  if (!this->adapting() && this->varying_epsilon()) {
137  double low = epsilon * (1.0 - this->_epsilon_pm);
138  double high = epsilon * (1.0 + this->_epsilon_pm);
139  double range = high - low;
140  epsilon = low + (range * this->_rand_uniform_01());
141  }
142  this->_epsilon_last = epsilon;
143  for (unsigned int l = 0; l < _L; ++l)
144  logp_new = leapfrog(this->_model, this->_z, x_new, m, g_new, epsilon,
145  this->_error_msgs, this->_output_msgs);
146  this->nfevals_plus_eq(_L);
147 
148  double H_new = -(stan::math::dot_self(m) / 2.0) + logp_new;
149  double dH = H_new - H;
150  if (this->_rand_uniform_01() < exp(dH)) {
151  this->_x = x_new;
152  this->_g = g_new;
153  this->_logp = logp_new;
154  }
155 
156  // Now we just have to update epsilon, if adaptation is on.
157  double adapt_stat = stan::math::min(1, exp(dH));
158  if (adapt_stat != adapt_stat)
159  adapt_stat = 0;
160  if (this->adapting()) {
161  double adapt_g = adapt_stat - this->_delta;
162  std::vector<double> gvec(1, -adapt_g);
163  std::vector<double> result; // FIXME: update directly to _epsilon?
164  this->_da.update(gvec, result);
165  this->_epsilon = exp(result[0]);
166  }
167  std::vector<double> result;
168  this->_da.xbar(result);
169  // fprintf(stderr, "xbar = %f\n", exp(result[0]));
170  double avg_eta = 1.0 / this->n_steps();
171  this->update_mean_stat(avg_eta,adapt_stat);
172 
173  return mcmc::sample(this->_x, this->_z, this->_logp);
174  }
175 
176  virtual void write_sampler_param_names(std::ostream& o) {
177  if (this->_epsilon_adapt || this->varying_epsilon())
178  o << "stepsize__,";
179  }
180 
181  virtual void write_sampler_params(std::ostream& o) {
182  if (this->_epsilon_adapt || this->varying_epsilon())
183  o << this->_epsilon_last << ',';
184  }
185 
186  virtual void get_sampler_param_names(std::vector<std::string>& names) {
187  names.clear();
188  if (this->_epsilon_adapt || this->varying_epsilon())
189  names.push_back("stepsize__");
190  }
191 
192  virtual void get_sampler_params(std::vector<double>& values) {
193  values.clear();
194  if (this->_epsilon_adapt || this->varying_epsilon())
195  values.push_back(this->_epsilon_last);
196  }
197  };
198 
199  }
200 
201 }
202 
203 #endif

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