Skip to content

efficiency of stan code #2

Description

@spinkney

This is about twice as fast for me. Of course when you first wrote the code Stan didn't have tuples nor did it have the cholesky version of the inverse Wishart.

functions {
  matrix square_root (matrix A) {
    // assume A is SPD
    int R = rows(A);
    tuple(matrix[R, R], vector[R]) eig = eigendecompose_sym(A);
    return diag_post_multiply(eig.1, sqrt(eig.2)) * eig.1';
  }
  
  real log_norm_const(int d, real rho) {
    real num = (d - 1) * log2() + log1p(inv_sqrt(1 - square(rho)));
    real den = d * log(sqrt(1 - rho) + sqrt(1 + rho));
    return num - den;
  }
  
  real multi_expectile_lpdf (array[] vector x, vector m, matrix L, vector nu, real r) {
    int d = rows(L);
    int n = dims(x)[1];
    // real lpdf = multi_normal_cholesky_lpdf(x | m, L);
   // lpdf -= n * log_norm_const(d, r);
    
    matrix[d, d] sigma_inv = chol2inv(L);
    matrix[d, d] sigma_inv_sqrt = square_root(sigma_inv);
    real lpdf = multi_normal_prec_lpdf(x | m, sigma_inv);
    lpdf -= n * log_norm_const(d, r);
    
    real cache = 0;
    vector[d] sigma_inv_sqrt_nu = sigma_inv_sqrt * nu;
    for (i in 1:n) {
      vector[d] x_m = x[i] - m; 
      cache += dot_product(x_m, sigma_inv_sqrt_nu) * sqrt(quad_form(sigma_inv, x_m));
    }
    
    return lpdf - 0.5 * r * cache;
    
  }
}
data {
  int<lower=1> d;         // data dimension
  int<lower=0> n;         // number of observations
  array[n] vector[d] Y;         // observations
}
parameters {
  vector[d] mu;                     // mean
  real<lower=0,upper=1> rho;        // asymmetry parameter
  cholesky_factor_cov[d] L;          
  vector<lower=0>[d] diag_sigma_sq; // mu hyperprior cov mat
  vector[d] nu_tilde_raw;          // direction (tilde version)
}
transformed parameters {
  real r = sqrt(dot_self(nu_tilde_raw));
  vector[d] nu_tilde = nu_tilde_raw / r;
}
model {
  target += -0.5 * r^2 + 10 * log(r);
  mu ~ normal(0, diag_sigma_sq);
  L ~ inv_wishart_cholesky(d, diag_matrix(rep_vector(1, d)));
  diag_sigma_sq ~ inv_gamma(1, 1);
  Y ~ multi_expectile(mu, L, nu_tilde, rho);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions