Stan  1.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
prob_grad.hpp
Go to the documentation of this file.
1 #ifndef __STAN__MODEL__PROB_GRAD_HPP__
2 #define __STAN__MODEL__PROB_GRAD_HPP__
3 
4 #include <iomanip>
5 #include <iostream>
6 #include <limits>
7 #include <stdexcept>
8 #include <stdio.h>
9 #include <utility>
10 #include <vector>
11 
12 #include <stan/io/csv_writer.hpp>
13 
14 namespace stan {
15 
16  namespace model {
17 
24  class prob_grad {
25  protected:
27  std::vector<std::pair<int,int> > param_ranges_i__;
28 
29  public:
30 
32  : num_params_r__(num_params_r),
33  param_ranges_i__(std::vector<std::pair<int,int> >(0)) {
34  }
35 
37  std::vector<std::pair<int,int> >& param_ranges_i)
38  : num_params_r__(num_params_r),
39  param_ranges_i__(param_ranges_i) {
40  }
41 
42  virtual ~prob_grad() { }
43 
46  }
47 
48  void setparam_ranges_i__(std::vector<std::pair<int,int> > param_ranges_i) {
49  param_ranges_i__ = param_ranges_i;
50  }
51 
52  virtual size_t num_params_r() {
53  return num_params_r__;
54  }
55 
56  virtual size_t num_params_i() {
57  return param_ranges_i__.size();
58  }
59 
60  inline std::pair<int,int> param_range_i(size_t idx) {
61  return param_ranges_i__[idx];
62  }
63 
64  inline void set_param_range_i_lower(size_t idx, int low) {
65  param_ranges_i__[idx].first = low;
66  }
67 
68  inline void set_param_range_i_upper(size_t idx, int up) {
69  param_ranges_i__[idx].second = up;
70  }
71 
72  inline int param_range_i_lower(size_t idx) {
73  return param_ranges_i__[idx].first;
74  }
75 
76  inline int param_range_i_upper(size_t idx) {
77  return param_ranges_i__[idx].second;
78  }
79 
80  virtual void init(std::vector<double>& params_r,
81  std::vector<int>& params_i) {
82  for (size_t i = 0; i < num_params_r(); ++i)
83  params_r[i] = 0.0;
84  for (size_t j = 0; j < num_params_i(); ++j)
85  params_i[j] = param_range_i_lower(j);
86  }
87 
88  virtual double grad_log_prob(std::vector<double>& params_r,
89  std::vector<int>& params_i,
90  std::vector<double>& gradient,
91  std::ostream* output_stream = 0) = 0;
92 
93  virtual double log_prob(std::vector<double>& params_r,
94  std::vector<int>& params_i,
95  std::ostream* output_stream = 0) = 0;
96 
97  virtual double log_prob_star(size_t idx,
98  int val,
99  std::vector<double>& params_r,
100  std::vector<int>& params_i,
101  std::ostream* output_stream = 0) {
102  if (idx >= num_params_i()) // || idx < 0
103  throw std::runtime_error ("idx >= num_params_i()");
104  if (val >= param_range_i(idx).first) //
105  throw std::runtime_error ("val <= param_range_i(idx) lower");
106  if (val >= param_range_i(idx).second) //
107  throw std::runtime_error ("val >= param_range_i(idx) upper");
108 
109  int original_val = params_i[idx];
110  params_i[idx] = val;
111  double result = log_prob(params_r,params_i,output_stream);
112  params_i[idx] = original_val;
113  return result;
114  }
115 
116 
130  virtual void write_csv(std::vector<double>& params_r,
131  std::vector<int>& params_i,
132  std::ostream& o,
133  std::ostream* output_stream = 0) {
134  stan::io::csv_writer writer(o);
135  for (size_t i = 0; i < params_i.size(); ++i)
136  writer.write(params_i[i]);
137  for (size_t i = 0; i < params_r.size(); ++i)
138  writer.write(params_r[i]);
139  writer.newline();
140  }
141 
142 
154  void finite_diff_grad(std::vector<double>& params_r,
155  std::vector<int>& params_i,
156  std::vector<double>& grad,
157  double epsilon = 1e-6,
158  std::ostream* output_stream = 0) {
159  std::vector<double> perturbed(params_r);
160  grad_log_prob(params_r,params_i,grad,output_stream);
161  grad.resize(params_r.size());
162  for (size_t k = 0; k < params_r.size(); k++) {
163  perturbed[k] += epsilon;
164  double logp_plus = log_prob(perturbed,params_i,output_stream);
165  perturbed[k] = params_r[k] - epsilon;
166  double logp_minus = log_prob(perturbed,params_i,output_stream);
167  double gradest = (logp_plus - logp_minus) / (2*epsilon);
168  grad[k] = gradest;
169  perturbed[k] = params_r[k];
170  }
171  }
172 
189  int test_gradients(std::vector<double>& params_r,
190  std::vector<int>& params_i,
191  double epsilon = 1e-6,
192  double error = 1e-6,
193  std::ostream& o = std::cout,
194  std::ostream* output_stream = 0) {
195  std::vector<double> grad;
196  double lp = grad_log_prob(params_r,params_i,grad,output_stream);
197 
198  std::vector<double> grad_fd;
199  finite_diff_grad(params_r,params_i,grad_fd,epsilon,output_stream);
200 
201  int num_failed = 0;
202 
203  o << std::endl
204  << " Log probability=" << lp
205  << std::endl;
206 
207  o << std::endl
208  << std::setw(10) << "param idx"
209  << std::setw(16) << "value"
210  << std::setw(16) << "model"
211  << std::setw(16) << "finite diff"
212  << std::setw(16) << "error"
213  << std::endl;
214  for (size_t k = 0; k < params_r.size(); k++) {
215  o << std::setw(10) << k
216  << std::setw(16) << params_r[k]
217  << std::setw(16) << grad[k]
218  << std::setw(16) << grad_fd[k]
219  << std::setw(16) << (grad[k] - grad_fd[k])
220  << std::endl;
221  if (std::fabs(grad[k] - grad_fd[k]) > error)
222  num_failed++;
223  }
224  return num_failed;
225  }
226 
227  };
228  }
229 }
230 
231 #endif

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