Skip to content

Bayesian_Cognitive_Modeling: extracted Stan code from R files; updated some deprecated Stan functions #233

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// #### Notes to Stan model #######################################################
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cut all of these disclaimers. This is a very simple censored model! You don't have to go deep I the User's Guide---you can just refer people to the chapter on censoring.

Did that prior come from the book? We usually only recommend hard interval constraints (here 0.25--1.0) when there are physical constraints on the model.

// ## Implementation of this model can be difficult to understand for beginners.
// ## Therefore I suggest either not trying to understand it and look on WinBUGS
// ## version or go deep into Stan manual.
// ################################################################################

// ChaSaSoon Censored Data
data {
int<lower=0> n_fails;
int<lower=0> n;
int<lower=0> z_observed;
}

parameters {
real<lower=0.25, upper=1> theta; // Uniform Prior on Rate Theta
}

model {
// Observed Data
z_observed ~ binomial(n, theta);

// Unobserved Data
target += n_fails * log(binomial_cdf(25 | n, theta)
- binomial_cdf(14 | n, theta));
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,6 @@
rm(list=ls())

library(rstan)

#### Notes to Stan model #######################################################
## Implementation of this model can be difficult to understand for beginners.
## Therefore I suggest either not trying to understand it and look on WinBUGS
## version or go deep into Stan manual.
################################################################################
model <- "
# ChaSaSoon Censored Data
data {
int<lower=0> nfails;
int<lower=0> n;
int<lower=0> z_observed;
}
parameters {
real<lower=.25,upper=1> theta; // Uniform Prior on Rate Theta
}
model {
// Observed Data
z_observed ~ binomial(n, theta);

// Unobserved Data
increment_log_prob(nfails * log(binomial_cdf(25, n, theta)
- binomial_cdf(14, n, theta)));
}"

nfails <- 949
n <- 50 # Number of questions
Expand All @@ -40,7 +16,7 @@ parameters <- c("theta")

# The following command calls Stan with specific options.
# For a detailed description type "?rstan".
samples <- stan(model_code=model,
samples <- stan(file="ChaSaSoon.stan",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you really want to go to town, converting everything to cmdstanr would be a welcome improvement. RStan just can't keep up with CRAN's demands, so it's usually 1--2 years behind the Stan releases. For instance, it's now at 2.32, which is about 1.5 years old and we're about to release 2.37.

data=data,
init=myinits, # If not specified, gives random inits
pars=parameters,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// #### Notes to Stan model #######################################################
// ## The model is not very effective.
// ## 1) Don't change seed or lower iterations. This model converges slowly so if
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just bad advice. I know it's not yours, but please just cut all this stuff out.

If the model only converges with a given seed, it's essentially broken and the model should be fixed. Fixing seeds does not guarantee the same behavior across platforms (C++ compiler version, C++ compiler options, different OSes, different hardware, etc.---they all affect floating point behavior).

// ## you change the values, you'll need to increment iterations significantly
// ## 2) Code is quite dissimilar to original WinBUGS model - using conditionals
// ## instead of step function. This will happen in further models more often.
// ## There is a difference in what functions are efficient in BUGS and Stan.
// ################################################################################

// Change Detection
data {
int n;
array[n] int t;
array[n] real c;
}

parameters {
array[2] real mu;
real<lower=0> lambda;
real<lower=0, upper=n> tau;
}

transformed parameters {
real<lower=0> sigma;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be

real<lower=0> sigma = inv_sqrt(lambda);

But overall, for new models, I'd just model sigma directly. It only looks so roundabout because it was forced to use conjugate priors in BUGS for efficiency.


sigma = inv_sqrt(lambda);
}
model {
// Group Means
mu ~ normal(0, sqrt(1000));
// Common Precision
lambda ~ gamma(0.001, 0.001);

// Which Side is Time of Change Point?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't document things that are obvious. I'd say all of this doc is useless.

Also, those priors on mu and lambda are a really bad idea---these attempts at being "uninformative" were standard in BUGS, but we've learned a lot in 30 years.

https://projecteuclid.org/journals/bayesian-analysis/volume-1/issue-3/Prior-distributions-for-variance-parameters-in-hierarchical-models-comment-on/10.1214/06-BA117A.full

So I wonder if some of these translate models are doing more harm than good. We definitely don't recommend that people follow this strategy for priors.

// Data Come From A Gaussian
for (i in 1:n) {
if ((t[i] - tau) < 0.0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for (k in 1:n) {
  c[k] ~ normal(t[k] - tau < 0 ? mu[1] : mu[2]);
}

c[i] ~ normal(mu[1], sigma);
else
c[i] ~ normal(mu[2], sigma);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,6 @@ rm(list=ls())

library(rstan)

#### Notes to Stan model #######################################################
## The model is not very effective.
## 1) Don't change seed or lower iterations. This model converges slowly so if
## you change the values, you'll need to increment iterations significantly
## 2) Code is quite dissimilar to original WinBUGS model - using conditionals
## instead of step function. This will happen in further models more often.
## There is a difference in what functions are efficient in BUGS and Stan.
################################################################################
model <- "
// Change Detection
data {
int n;
vector[n] t;
vector[n] c;
}
parameters {
vector[2] mu;
real<lower=0> lambda;
real<lower=0,upper=n> tau;
}
transformed parameters {
real<lower=0> sigma;

sigma <- inv_sqrt(lambda);
}
model {
// Group Means
mu ~ normal(0, inv_sqrt(.001));
// Common Precision
lambda ~ gamma(.001, .001);

// Which Side is Time of Change Point?
// Data Come From A Gaussian
for (i in 1:n) {
if ((t[i] - tau) < 0.0)
c[i] ~ normal(mu[1], sigma);
else
c[i] ~ normal(mu[2], sigma);
}
}"

c <- scan("changepointdata.txt")
n <- length(c)
t <- 1:n
Expand All @@ -57,7 +16,7 @@ parameters <- c("mu", "sigma", "tau")

# The following command calls Stan with specific options.
# For a detailed description type "?rstan".
samples <- stan(model_code=model,
samples <- stan(file="ChangeDetection.stan",
data=data,
init=myinits, # If not specified, gives random inits
pars=parameters,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// #### Notes to Stan model #######################################################
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is either obvious or bad advice. Please remove.

// ## 1) Multivariate normal distribution in Stan uses covariance matrix instead of
// ## precision matrix.
// ## 2) Multivariate normal distribution can be (and is) also vectorized.
// ## 3) Warnings may occur during sampling, ignore them.
// ################################################################################

// Pearson Correlation
data {
int<lower=0> n;
array[n] vector[2] x;
}

parameters {
vector[2] mu;
vector<lower=0>[2] lambda;
real<lower=-1, upper=1> r;
}

transformed parameters {
vector<lower=0>[2] sigma;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transformed parameters {
  vector<lower=0>[2] sigma = inv_sqrt(lambda);
  cov_matrix[2] T;
  T[1, 1] = square(sigma[1]);
  T[2, 2] = square(sigma[2]);
  T[1, 2] = rho * sigma[1] * sigma[2];
  T[2, 1] = T[1, 2];

cov_matrix[2] T;

// Reparameterization
sigma[1] = inv_sqrt(lambda[1]);
sigma[2] = inv_sqrt(lambda[2]);

T[1,1] = square(sigma[1]);
T[1,2] = r * sigma[1] * sigma[2];
T[2,1] = r * sigma[1] * sigma[2];
T[2,2] = square(sigma[2]);
}

model {
// Priors
mu ~ normal(0, sqrt(1000));
lambda ~ gamma(0.001, 0.001);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add a comment here that these are the original priors from the books, but not what we'd recommend.


// Data
x ~ multi_normal(mu, T);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,6 @@ rm(list=ls())

library(rstan)

#### Notes to Stan model #######################################################
## 1) Multivariate normal distribution in Stan uses covariance matrix instead of
## precision matrix.
## 2) Multivariate normal distribution can be (and is) also vectorized.
## 3) Warnings may occur during sampling, ignore them.
################################################################################
model <- "
// Pearson Correlation
data {
int<lower=0> n;
vector[2] x[n];
}
parameters {
vector[2] mu;
vector<lower=0>[2] lambda;
real<lower=-1,upper=1> r;
}
transformed parameters {
vector<lower=0>[2] sigma;
cov_matrix[2] T;

// Reparameterization
sigma[1] <- inv_sqrt(lambda[1]);
sigma[2] <- inv_sqrt(lambda[2]);
T[1,1] <- square(sigma[1]);
T[1,2] <- r * sigma[1] * sigma[2];
T[2,1] <- r * sigma[1] * sigma[2];
T[2,2] <- square(sigma[2]);
}
model {
// Priors
mu ~ normal(0, inv_sqrt(.001));
lambda ~ gamma(.001, .001);

// Data
x ~ multi_normal(mu, T);
}"

# Choose a dataset:
dataset <- 1

Expand Down Expand Up @@ -94,7 +56,7 @@ parameters <- c("r", "mu", "sigma")

# The following command calls Stan with specific options.
# For a detailed description type "?rstan".
samples <- stan(model_code=model,
samples <- stan(file="Correlation_1.stan",
data=data,
init=myinits, # If not specified, gives random inits
pars=parameters,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// #### Notes to Stan model #######################################################
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of all these useless notes.

// ## 1) All notes from previous model Correlation_1 also apply to this model.
// ## 2) If you change sigmaerror to c(0.03, 10) as suggested in excercise 5.2.2
// ## warning statements will be more frequent and posterior less smooth.
// ################################################################################

// Pearson Correlation With Uncertainty in Measurement
data {
int<lower=0> n;
array[n] vector[2] x;
vector[2] sigmaerror;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use sigma_error to make it easier to read.

}

parameters {
vector[2] mu;
vector<lower=0>[2] lambda;
real<lower=-1, upper=1> r;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can include a note that there's an implicit uniform prior on r, but I'd rename to rho to stick to the usual notation for correlation and the usual notation of Greek letters for parameters.

array[n] vector[2] y;
}

transformed parameters {
vector<lower=0>[2] sigma;
cov_matrix[2] T;

// Reparameterization
sigma[1] = inv_sqrt(lambda[1]);
sigma[2] = inv_sqrt(lambda[2]);

T[1,1] = square(sigma[1]);
T[1,2] = r * sigma[1] * sigma[2];
T[2,1] = r * sigma[1] * sigma[2];
T[2,2] = square(sigma[2]);
}

model {
// Priors
mu ~ normal(0, sqrt(1000));
lambda ~ gamma(0.001, 0.001);

// Data
y ~ multi_normal(mu, T);
for (i in 1:n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x ~ normal(y, sigma_error);

x[i] ~ normal(y[i], sigmaerror);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,6 @@ rm(list=ls())

library(rstan)

#### Notes to Stan model #######################################################
## 1) All notes from previous model Correlation_1 also apply to this model.
## 2) If you change sigmaerror to c(0.03, 10) as suggested in excercise 5.2.2
## warning statements will be more frequent and posterior less smooth.
################################################################################
model <- "
// Pearson Correlation With Uncertainty in Measurement
data {
int<lower=0> n;
vector[2] x[n];
vector[2] sigmaerror;
}
parameters {
vector[2] mu;
vector<lower=0>[2] lambda;
real<lower=-1,upper=1> r;
vector[2] y[n];
}
transformed parameters {
vector<lower=0>[2] sigma;
cov_matrix[2] T;

// Reparameterization
sigma[1] <- inv_sqrt(lambda[1]);
sigma[2] <- inv_sqrt(lambda[2]);

T[1,1] <- square(sigma[1]);
T[1,2] <- r * sigma[1] * sigma[2];
T[2,1] <- r * sigma[1] * sigma[2];
T[2,2] <- square(sigma[2]);
}
model {
// Priors
mu ~ normal(0, inv_sqrt(.001));
lambda ~ gamma(.001, .001);

// Data
y ~ multi_normal(mu, T);
for (i in 1:n)
x[i] ~ normal(y[i], sigmaerror);
}"

x <- matrix(c( .8, 102,
1.0, 98,
.5, 100,
Expand Down Expand Up @@ -72,7 +30,7 @@ parameters <- c("r", "mu", "sigma")

# The following command calls Stan with specific options.
# For a detailed description type "?rstan".
samples <- stan(model_code=model,
samples <- stan(file="Correlation_2.stan",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks---this is a huge improvement putting them in files. I'd use correlation-2.stan. File names conventionally have hyphens rather than underscores (unless we're in C++ or Python packages). But if you can, an even more informative and not so long name would be useful like meas-err.stan.

data=data,
init=myinits, # If not specified, gives random inits
pars=parameters,
Expand Down
Loading