<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts | Experienced Sampler</title>
    <link>https://experienced-sampler.netlify.app/post/</link>
      <atom:link href="https://experienced-sampler.netlify.app/post/index.xml" rel="self" type="application/rss+xml" />
    <description>Posts</description>
    <generator>Wowchemy (https://wowchemy.com)</generator><language>en-us</language><copyright>© Joran Jongerling {2021}</copyright><lastBuildDate>Tue, 02 Nov 2021 00:00:00 +0000</lastBuildDate>
    <image>
      <url>https://experienced-sampler.netlify.app/media/icon_hua2ec155b4296a9c9791d015323e16eb5_11927_512x512_fill_lanczos_center_3.png</url>
      <title>Posts</title>
      <link>https://experienced-sampler.netlify.app/post/</link>
    </image>
    
    <item>
      <title>STAN Code for Analyzing Intensive Longitudinal Data: Part IIa - Hierarchical Autoregressive Models</title>
      <link>https://experienced-sampler.netlify.app/post/stan-hierarchical-ar/</link>
      <pubDate>Tue, 02 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://experienced-sampler.netlify.app/post/stan-hierarchical-ar/</guid>
      <description>
&lt;script src=&#34;https://experienced-sampler.netlify.app/post/stan-hierarchical-ar/index_files/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;table-of-contents&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Table of Contents&lt;/h1&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;a href=&#34;#intro&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#completemodel&#34;&gt;The Complete Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#explanation&#34;&gt;But What Does it all Mean?&lt;/a&gt;&lt;br /&gt;
1.&lt;a href=&#34;#data&#34;&gt;The Data Block and Data-generation&lt;/a&gt;&lt;br /&gt;
2.&lt;a href=&#34;#transformed&#34;&gt;The Transformed Data Block&lt;/a&gt;&lt;br /&gt;
3.&lt;a href=&#34;#parameters&#34;&gt;The Parameters Block&lt;/a&gt;&lt;br /&gt;
4.&lt;a href=&#34;#model&#34;&gt;The Model Block&lt;/a&gt;&lt;br /&gt;
5.&lt;a href=&#34;#quantities&#34;&gt;The Generated Quantities Block&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#testing&#34;&gt;Testing the Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#taf&#34;&gt;That’s all Folks!!&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction &lt;a name=&#34;intro&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Welcome to the second installment of my series in which I share (and explain) all of my intensive longitudinal data (ILD) related STAN model-code. In my previous “&lt;a href=&#34;https://experienced-sampler.netlify.app/post/stan-ar/&#34;&gt;post&lt;/a&gt;” I wrote about the first-order autoregressive (AR(1)) model, the workhorse of a lot of more advanced analyses methods for ILD. This was a nicer appetizer, at least I hope so, but we need to look at extensions of this model for you to get STAN model-code that you might actually need for your data. So let’s take a look at …. the &lt;em&gt;hierarchical&lt;/em&gt; first-order autoregressive models!&lt;/p&gt;
&lt;p&gt;This is where the fun really begins! The hierarchical AR(1) model can be fitted to ILD of &lt;em&gt;multiple&lt;/em&gt; participants, and allows for investigating between-person differences in means and/or lagged-effects. This model opens up a lot…seriously a looooot…of topics. We can use it as a jumping of point to discuss centered and non-centered parametrizations of the model (which has to do with how well/stable parameters are estimated under different conditions), individual differences in error variances, handling of missing data (one of the nice properties of hierarchical models but not done &lt;em&gt;automatically&lt;/em&gt; by STAN), including measurement error, etcetera. I’m going to go into, and provide code for, all these related topics and variants of the model. Doing so in one post would be madness however, and would severely hurt the readability (which is suffering enough already), so those topics will be coming up in future posts. That also why this post is numbered as “IIa”, this is just “chapter one part one” of our fun with the hierarchical first-order autoregressive model.&lt;/p&gt;
&lt;p&gt;This post will build on the code discussed in the previous “&lt;a href=&#34;https://experienced-sampler.netlify.app/post/stan-ar/&#34;&gt;post&lt;/a&gt;”, so be sure to check that one out if things go a bit to fast. As always the structure of this post is as follows; I give the full model code first, and then go into more chunk by chunk discussion of the model. I end with some simulations that show what the code does.&lt;/p&gt;
&lt;p&gt;All right! Let’s do this! The hierarchical first-order autoregressive models everybody!!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-complete-model-code&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The complete model code &lt;a name=&#34;completemodel&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Below is my basic STAN-code for a hierarchical AR(1) model. We can vectorize some stuff to make it a bit faster, but it runs in less than a minute on most realistic data sizes anyway, so we’ll keep it simple for now, as we did for the “basic” AR model in the previous “&lt;a href=&#34;https://experienced-sampler.netlify.app/post/stan-ar/&#34;&gt;post&lt;/a&gt;”. I did include some automatic standardization of variables (explained below) so that the specified priors can be used with data on different scales. This makes the code more broadly applicable and means you should be able to set it loose on your own data pretty much straight away (assuming for now that there are no missing data).&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
// The input data is a vector &amp;#39;y&amp;#39; of length &amp;#39;N&amp;#39;, we I individuals who we 
// measured T times for N (I*T) observations in total. We also have an indicator 
// variable that illustrates what individual (1,..., I) data belong to, and what 
// measurement occasion (1,..., T) the data was collected at. 
// Data is in long-format
data {
  int&amp;lt;lower=0&amp;gt; N;
  int&amp;lt;lower=0&amp;gt; I;
  int&amp;lt;lower=0&amp;gt; T;
  int&amp;lt;lower = 1, upper = I&amp;gt; individual[N]; 
  int&amp;lt;lower = 1, upper = T&amp;gt; time[N]; 
  vector[N] y;
}

transformed data {
  vector[N] y_std;
  real meanY;
  real sdY;

  meanY = mean(y);
  sdY = sd(y);

  y_std = (y - meanY)/sdY;
}

// The parameters accepted by the model. 
parameters {
  real alpha_hat;
  real&amp;lt;lower = 0&amp;gt; alpha_scale;
  real&amp;lt;lower=-1, upper=1&amp;gt; beta_hat;
  real&amp;lt;lower = 0&amp;gt; beta_scale;
  
  vector[I] alpha;
  vector&amp;lt;lower=-1, upper=1&amp;gt;[I] beta;
  real&amp;lt;lower=0&amp;gt; sigma;
  
  
}

// The model to be estimated. We model the output &amp;#39;y_std[n]&amp;#39; to be normally 
// distributed with mean &amp;#39;alpha[n] + beta[n] * y_c[n-1]&amp;#39; and standard deviation
// &amp;#39;sigma&amp;#39;. We use the group-mean centered values of y as predictors so that 
// alpha gives us individual means instead of intercepts.
model {
  vector[N] y_c;
   
  alpha_hat ~ normal(0, 5);
  beta_hat ~ normal(0, .5);
  
  alpha_scale ~ normal(0, 1);
  beta_scale ~ normal(0, 1);
  sigma ~ normal(0, 2);
  
  
  for(i in 1:I) {
    alpha[i] ~ normal(alpha_hat, alpha_scale);
    
    beta[i] ~ normal(beta_hat, beta_scale);
    
    }
  
  
  y_c[1] =  y_std[1] - alpha[individual[1]]; 
  
  for (n in 2:N){
  
   y_c[n] = y_std[n] - alpha[individual[n]];  
    
   if (time[n] &amp;gt; 1)
      y_std[n] ~ normal(alpha[individual[n]] + beta[individual[n]] * y_c[n-1], sigma);
  }
}

generated quantities {
  vector[I] alphas_ind;
  
  real alpha_hat_raw;
  real&amp;lt;lower = 0&amp;gt; alpha_scale_raw; 
  real&amp;lt;lower = 0&amp;gt;  sigma_raw; 
  
  alphas_ind = (sdY * alpha) + meanY;
  alpha_hat_raw = (sdY * alpha_hat) + meanY;
  alpha_scale_raw = sdY*alpha_scale;
  
  sigma_raw = sigma*sdY;
  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, you can either copy and paste the code and be off, or read on below for some explanation of the code.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;but-what-does-it-all-mean&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;But what does it all mean?! &lt;a name=&#34;explanation&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;div id=&#34;the-data-block-and-data-generation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Data Block and Data-generation &lt;a name=&#34;data&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let me just emphasize again that STAN code is very structured. For a very thorough discussion of the STAN language and block structure check out the amazing “&lt;a href=&#34;https://betanalpha.github.io/assets/case_studies/stan_intro.html#1_prologue&#34;&gt;intro&lt;/a&gt;” by Michael Betancourt. I’ll only describe the block and elements that are actually in this model. First up, the &lt;em&gt;data block&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
data {
  int&amp;lt;lower=0&amp;gt; N;
  int&amp;lt;lower=0&amp;gt; I;
  int&amp;lt;lower=0&amp;gt; T;
  int&amp;lt;lower = 1, upper = I&amp;gt; individual[N]; 
  int&amp;lt;lower = 1, upper = T&amp;gt; time[N]; 
  vector[N] y;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’ve seen the &lt;em&gt;data block&lt;/em&gt; in the previous “&lt;a href=&#34;https://experienced-sampler.netlify.app/post/stan-ar/&#34;&gt;post&lt;/a&gt;” as well. In this block you specify the variables (and their characteristics) that you specified &lt;em&gt;outside&lt;/em&gt; of STAN, and that you are using as input to your model. Here, the data are assumed to be in long-format and I specify (i) the number of total observations &lt;em&gt;N&lt;/em&gt; in your sample (i.e., the product of the number of individuals in your sample, multiplied by the number of observations per individual), (ii) the number of individuals in your sample &lt;em&gt;I&lt;/em&gt;, (iii) the number of measurements per individual &lt;em&gt;T&lt;/em&gt;, (iv) a vector that indicated which individual each line of the data belongs to (&lt;em&gt;individual&lt;/em&gt;), (v) a vector indicating what measurement occasion a line of data belongs to (&lt;em&gt;time&lt;/em&gt;), and (vi) the vector with all N observations of my outcome variable (&lt;em&gt;y&lt;/em&gt;). Note that in the &lt;em&gt;data block&lt;/em&gt; I explicitly mention that &lt;em&gt;N&lt;/em&gt;, &lt;em&gt;I&lt;/em&gt;, &lt;em&gt;T&lt;/em&gt;, &lt;em&gt;individual&lt;/em&gt;, and &lt;em&gt;time&lt;/em&gt; are integers and &lt;em&gt;y&lt;/em&gt; is a vector. As I said, the STAN model code is very structured and you have to specify the type of all your data (and parameters). I also specify a lower bound for the value of &lt;em&gt;N&lt;/em&gt;, &lt;em&gt;I&lt;/em&gt;, &lt;em&gt;T&lt;/em&gt;, &lt;em&gt;individual&lt;/em&gt;, and &lt;em&gt;time&lt;/em&gt;. The number of observations, individuals in the sample, and time points per individual can’t be smaller than 0, while each line of the data need to belong to one of our &lt;em&gt;i&lt;/em&gt; (i = 1, …, I) individual and one of their &lt;em&gt;t&lt;/em&gt; (t = 1, …, T) measurements. These bounds are to prevent me from accidentally providing weird data to the model.&lt;/p&gt;
&lt;p&gt;I you want to generate data for this model in R, you can do that with the code below. This code is a little bit more involved that the data-generation from the previous “&lt;a href=&#34;https://experienced-sampler.netlify.app/post/stan-ar/&#34;&gt;post&lt;/a&gt;”, but don’t worry! I’ll explain it all!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;I &amp;lt;- 100
t &amp;lt;- 50
N &amp;lt;- I*t
individual &amp;lt;- rep(1:I, each = t)
time &amp;lt;- rep(1:t, I)

# True values for data generation
sigma &amp;lt;- 1 # sd&amp;#39;s of Y residuals 

alpha_hat &amp;lt;- 4 
alpha_scale &amp;lt;- 1 

alphas &amp;lt;- rnorm(I,alpha_hat, alpha_scale) 


beta_hat &amp;lt;- .4 
beta_scale &amp;lt;- .1 

betaGen &amp;lt;- rnorm(I,beta_hat, beta_scale)

for(i in 1:I){
  # The while loop avoids non-stationary AR processes
  # See Hamilton  pg. 259
  while(betaGen[i] &amp;lt;= -1 | betaGen[i] &amp;gt;= 1){
    betaGen[i] &amp;lt;- rnorm(1,beta_hat, beta_scale)
  }
}

betas &amp;lt;- betaGen

# Determine first observations for everyone. The variance for this first 
# observation is different than for the subsequent ones and so it needs to be 
# samples separatelty
IndT1 &amp;lt;- match(unique(individual), individual)

# Determine variance at first measurement for everyone (depends on their 
# AR-parameter)

sigmaT1 &amp;lt;- rep(NA, I)

for(k in 1:I){
sigmaT1[k] &amp;lt;- sigma/(1-((betas[k])^2))
}

# First create storage matrices for non-centered and centered y-scores.
# We need centered values, because of we use person-cetered values as 
# predictors, alpha will be equal to individual means instead of individual 
# intercepts which are less informative.
Y &amp;lt;- rep(NA, N)
Yc &amp;lt;- rep(NA, N)


# Draw first observation for each individual first

for(l in 1:I){
  Y[IndT1[l]] &amp;lt;- rnorm(1, alphas[l], sigmaT1[l])
  Yc[IndT1[l]] &amp;lt;-  Y[IndT1[l]] - alphas[l]
}

 
# Draw subsequent observations

for(m in 1:N){
  
  # This if statement makes sure I dont try to predict a persons first 
  # observation which is impossiblethere is no measurement before the first 
  # observation and so no predictor values for that observation
  if(time[m]&amp;gt;1){
    Y[m]&amp;lt;- rnorm(1, (alphas[individual[m]] + betas[individual[m]]*Yc[m-1]), sigma)
    Yc[m] &amp;lt;-  Y[m] - alphas[individual[m]]
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Geez!….That’s a lot of generation-code isn’t it! Let’s discuss this code chunk by chunk as well, just like we are doing with the STAN-model. First, I specify my number of individuals (100), the number of measurements per individual (50), and the total number of observations (I*T). I also generate the vectors indicating which individual the line of data belongs to (individual) and to what measurement for that individual the line belongs (time).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;I &amp;lt;- 100
t &amp;lt;- 50
N &amp;lt;- I*t
individual &amp;lt;- rep(1:I, each = t)
time &amp;lt;- rep(1:t, I)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, I specify values for the model parameters. Since this is a hierarchical model we have 7 parameters in the model: (i) the residual/error variance, (ii) the population mean of y (&lt;em&gt;alpha_hat&lt;/em&gt;), (iii) the population sd of y (&lt;em&gt;alpha_scale&lt;/em&gt;), (iv) the population-average lagged effects (&lt;em&gt;beta_hat&lt;/em&gt;), (v) the population sd in the lagged-effect (&lt;em&gt;beta_scale&lt;/em&gt;), (vi) the I individual means of y (&lt;em&gt;alphas&lt;/em&gt;), and (vii) the I individual lagged effects (&lt;em&gt;betas&lt;/em&gt;). For the population values (i.e., &lt;em&gt;sigma&lt;/em&gt;, &lt;em&gt;alpha_hat&lt;/em&gt;, &lt;em&gt;alpha_scale&lt;/em&gt;, &lt;em&gt;beta_hat&lt;/em&gt;, and &lt;em&gt;beta_scale&lt;/em&gt;) we specify what values we want based on the literature. The individual means (&lt;em&gt;alphas&lt;/em&gt;) are subsequently sampled from normal-distribution based on the population-values &lt;em&gt;alpha_hat&lt;/em&gt; and &lt;em&gt;alpha_scale&lt;/em&gt;. The individual lagged effect (&lt;em&gt;betas&lt;/em&gt;) are also sample form a normal distribution using their population values (&lt;em&gt;beta_hat&lt;/em&gt; and &lt;em&gt;beta_scale&lt;/em&gt;) but for these parameters I use an intermediate outcome &lt;em&gt;betaGen&lt;/em&gt; because I need to make sure that all lagged-effects fall between -1 and 1 to ensure stationarity. To ensure this range of scores I use a &lt;em&gt;while-loop&lt;/em&gt; and only after all values fall into the intended range do I assign the values to the vector betas which will contain our true lagged-effect values.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# True values for data generation
sigma &amp;lt;- 1 # sd&amp;#39;s of Y residuals 

alpha_hat &amp;lt;- 4 
alpha_scale &amp;lt;- 1 

alphas &amp;lt;- rnorm(I,alpha_hat, alpha_scale) 


beta_hat &amp;lt;- .4 
beta_scale &amp;lt;- .1 

betaGen &amp;lt;- rnorm(I,beta_hat, beta_scale)

for(i in 1:I){
  # The while loop avoids non-stationary AR processes
  # See Hamilton  pg. 259
  while(betaGen[i] &amp;lt;= -1 | betaGen[i] &amp;gt;= 1){
    betaGen[i] &amp;lt;- rnorm(1,beta_hat, beta_scale)
  }
}

betas &amp;lt;- betaGen&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, I generate the data. This needs to be done in two steps! We need to generate the first measurement occasion for each individual separately form all other observations, because the variance of y at the first measurement occasion is different from the variance at all other time-points (a standard result from timeseries literature). I therefore create a vector indicating the data-lines containing the first observations for my I individuals (&lt;em&gt;IndT1&lt;/em&gt;) first. I then determine the variance of the first measurement for each individual (which depends on their lagged-effect values), and use those variances to draw the first observations of each individual from a normal distribution. Then I draw all successive observations for the I individuals based on a normal distribution whose mean is determined by the AR(1) model and whose sd is equal to sigma. Note that while I’m generating all observations (&lt;em&gt;Y&lt;/em&gt;), I’m also creating a vector of person-mean centered values (&lt;em&gt;Yc&lt;/em&gt;). The reason for this is that using person-mean centered values of y as the predictors in the hierarchical AR(1) model makes the alphas parameters equal to the &lt;em&gt;means&lt;/em&gt; of each individual on y (and alpha_hat and alpha_scale equal to the population mean ans the population sd in the mean), instead of individual &lt;em&gt;intercepts&lt;/em&gt; which are less easy to interpret.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Determine first observations for everyone. The variance for this first 
# observation is different than for the subsequent ones and so it needs to be 
# samples separatelty
IndT1 &amp;lt;- match(unique(individual), individual)

# Determine variance at first measurement for everyone (depends on their 
# AR-parameter)

sigmaT1 &amp;lt;- rep(NA, I)

for(k in 1:I){
sigmaT1[k] &amp;lt;- sigma/(1-((betas[k])^2))
}

# First create storage matrices for non-centered and centered y-scores.
# We need centered values, because of we use person-cetered values as 
# predictors, alpha will be equal to individual means instead of individual 
# intercepts which are less informative.
Y &amp;lt;- rep(NA, N)
Yc &amp;lt;- rep(NA, N)


# Draw first observation for each individual first

for(l in 1:I){
  Y[IndT1[l]] &amp;lt;- rnorm(1, alphas[l], sigmaT1[l])
  Yc[IndT1[l]] &amp;lt;-  Y[IndT1[l]] - alphas[l]
}

 
# Draw subsequent observations

for(m in 1:N){
  
  # This if statement makes sure I don&amp;#39;t try to predict a persons first 
  # observation which is impossible there is no measurement before the first 
  # observation and so no predictor values for that observation
  if(time[m]&amp;gt;1){
    Y[m]&amp;lt;- rnorm(1, (alphas[individual[m]] + betas[individual[m]]*Yc[m-1]), sigma)
    Yc[m] &amp;lt;-  Y[m] - alphas[individual[m]]
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-transformed-data-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Transformed Data Block &lt;a name=&#34;transformed&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ok! That takes care of the &lt;em&gt;data block&lt;/em&gt; and the data generation! On to the next block, which is a new one! The &lt;em&gt;transformed data&lt;/em&gt; block. In the &lt;em&gt;transformed data&lt;/em&gt; you can specify manipulations of your data that you want to apply before feeding the data to your model. Here I use it to standardize the data y. The reason for this is that STAN tends to run a bit quicker on standardized scales AND that by doing this I can specify priors for my parameters that can be used regardless of the actual, “raw” scale of the data. So no need to change the priors each time you use a new instrument! Instead, we specify priors that work on the standardized scale and turn every obtained scale into that standardized scale before fitting the model. When it comes to the amount of work you have to do, less is most definitely more! For the actual standardizing I specify a new vector, &lt;em&gt;y_std&lt;/em&gt;, in which I will store all the standardized values, and specify two real valued parameters in which I will store the sample mean (&lt;em&gt;meanY&lt;/em&gt;) and sample sd (&lt;em&gt;sdY&lt;/em&gt;) of our variable &lt;em&gt;y&lt;/em&gt;. Then I just apply a z-transform to all values of &lt;em&gt;y&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
transformed data {
  vector[N] y_std;
  real meanY;
  real sdY;

  meanY = mean(y);
  sdY = sd(y);

  y_std = (y - meanY)/sdY;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-parameters-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Parameters Block &lt;a name=&#34;parameters&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This bring us to a familiar block again, the &lt;em&gt;parameters block&lt;/em&gt;, in which we specify all the parameters of your model. As mentioned above when discussing the code for data generation, the hierarchical AR(1) model has 7 parameters; (i) the residual/error variance (&lt;em&gt;sigma&lt;/em&gt;), (ii) the population mean of y (&lt;em&gt;alpha_hat&lt;/em&gt;), (iii) the population sd of y (&lt;em&gt;alpha_scale&lt;/em&gt;), (iv) the population-average lagged effects (&lt;em&gt;beta_hat&lt;/em&gt;), (v) the population sd in the lagged-effect (&lt;em&gt;beta_scale&lt;/em&gt;), (vi) the I individual means of y (&lt;em&gt;alpha&lt;/em&gt;), and (vii) the I individual lagged effects (&lt;em&gt;beta&lt;/em&gt;). As for the data, you have to specify the type for your parameters, and I also specify a lower bound for my variance parameters (&lt;em&gt;sigma&lt;/em&gt;, &lt;em&gt;alpha_scale&lt;/em&gt;, and &lt;em&gt;beta_scale&lt;/em&gt;) and an upper and lower bound for my population AR-parameter (&lt;em&gt;beta_hat&lt;/em&gt;) and the individual lagged-parameters (&lt;em&gt;beta&lt;/em&gt;). This last constraint reflects that I want my model to be stationary which requires the AR-parameter to be between -1 and 1. Draws that fall outside of this range will be rejected.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
// The parameters accepted by the model. 
parameters {
  real alpha_hat;
  real&amp;lt;lower = 0&amp;gt; alpha_scale;
  real&amp;lt;lower=-1, upper=1&amp;gt; beta_hat;
  real&amp;lt;lower = 0&amp;gt; beta_scale;
  
  vector[I] alpha;
  vector&amp;lt;lower=-1, upper=1&amp;gt;[I] beta;
  real&amp;lt;lower=0&amp;gt; sigma;
  
  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-model-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Model Block &lt;a name=&#34;model&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;model block&lt;/em&gt; is up next. This is where you specify your full Bayesian model; the priors for your parameters and the observational model for your data. I’m using weakly informative normal priors for all my parameters. Remember that these priors are on the standardized-scale(!), and (see the previous “&lt;a href=&#34;https://experienced-sampler.netlify.app/post/stan-ar/&#34;&gt;post&lt;/a&gt;”) that the normal-priors on my variance parameters gets turned into a half-normal prior by STAN because I specified that I want these parameters to be larger than 0 in the &lt;em&gt;parameters block&lt;/em&gt;. I draw individual means and AR-parameters using a &lt;em&gt;for-loop&lt;/em&gt; and the population values of the means and AR-parameters.&lt;/p&gt;
&lt;p&gt;For my outcome variable &lt;em&gt;y&lt;/em&gt;, I specify the standard AR(1) model in which each observation is regressed on the immediate prior observation using the AR-parameter (&lt;em&gt;beta&lt;/em&gt;). I use a &lt;em&gt;for-loop&lt;/em&gt; to go over all &lt;em&gt;N&lt;/em&gt; lines of data starting at the second line(!!). I start at the second line because because I can’t predict the first observation (which is the first observation of the first individual in my sample) as there is no previous score to use as a predictor for this first measurement. To get valid estimates I need to make sure that individual i’s individual mean (&lt;em&gt;alpha[i]&lt;/em&gt;) and AR-parameter (&lt;em&gt;beta[i]&lt;/em&gt;) are estimated using only her/his data. For this I use the vector indicating which individual a line of data belongs to (&lt;em&gt;individual&lt;/em&gt;). Using this indicator-vector I tell my model which of the &lt;em&gt;I&lt;/em&gt; alpha and beta values should be estimated in the current iteration of the for-loop. In addition, I use the vector indicating which measurement a line of data belongs to (&lt;em&gt;time&lt;/em&gt;) to make sure that the AR(1) model is not applied to the first observation of each individual as that is impossible (as mentioned above, there is no previous observation to use as a predictor for an individuals first measurement). Finally, not the &lt;em&gt;y_c&lt;/em&gt; vector! As mentioned above, I you use person-centered y-scores as the predictor in the AR(1) model, the parameter alpha is the individual mean instead of the individual intercept. The latter is much harder to interpret and so less nice to work with. I create the &lt;em&gt;y_c&lt;/em&gt; values by subtracting individual alpha values from an individual’s &lt;em&gt;y-scores&lt;/em&gt;. For the first measurement (i.e., the first line of data) I need to do this manually, for all successive lines I can do it as part of the &lt;em&gt;for-loop&lt;/em&gt; I use to fit the AR(1) model from the second line on wards.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
// The model to be estimated. We model the output &amp;#39;y_std[n]&amp;#39; to be normally 
// distributed with mean &amp;#39;alpha[n] + beta[n] * y_c[n-1]&amp;#39; and standard deviation 
// &amp;#39;sigma&amp;#39;. We use the group-mean centered values of y as predictors so that 
// alpha gives us individual means instead of intercepts.
model {
  vector[N] y_c;
   
  alpha_hat ~ normal(0, 5);
  beta_hat ~ normal(0, .5);
  
  alpha_scale ~ normal(0, 1);
  beta_scale ~ normal(0, 1);
  sigma ~ normal(0, 2);
  
  
  for(i in 1:I) {
    alpha[i] ~ normal(alpha_hat, alpha_scale);
    
    beta[i] ~ normal(beta_hat, beta_scale);
    
    }
  
  
  y_c[1] =  y_std[1] - alpha[individual[1]]; 
  
  for (n in 2:N){
  
   y_c[n] = y_std[n] - alpha[individual[n]];  
    
   if (time[n] &amp;gt; 1)
      y_std[n] ~ normal(alpha[individual[n]] + beta[individual[n]] * y_c[n-1], sigma);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-generated-quantities-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Generated Quantities Block &lt;a name=&#34;quantities&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now, we’re almost done. There is one issue. Because I standardized my data before entering it into the model, my estimates of &lt;em&gt;alpha&lt;/em&gt;, &lt;em&gt;alpha_hat&lt;/em&gt;, &lt;em&gt;alpha_scale&lt;/em&gt;, and &lt;em&gt;sigma&lt;/em&gt; are on the standardized scale and not on the “raw” scale of the data to which you fot the model. All parameters related to the lagged-effects are fine since you use the same variable as both dependent and independent variable. To get all parameter back on the appropriate scale, we’ll use the &lt;em&gt;generated quantities&lt;/em&gt; block. You can use this block to calculate quantities in each iteration of your HMC-sampler (as opposed to the &lt;em&gt;transformed data&lt;/em&gt; whose transformations are applied once, before fitting the data). In this block we’ll transform each draw of our standardized parameters (i.e., &lt;em&gt;alpha&lt;/em&gt;, &lt;em&gt;alpha_hat&lt;/em&gt;, &lt;em&gt;alpha_scale&lt;/em&gt;, and &lt;em&gt;sigma&lt;/em&gt;) into parameters on the original scale of the data. This basically means applying an inverse z-transform to the &lt;em&gt;alpha&lt;/em&gt; and &lt;em&gt;alpha_hat&lt;/em&gt; parameters in each iteration, and multiplying the &lt;em&gt;alpha_scale&lt;/em&gt; and &lt;em&gt;sigma&lt;/em&gt; parameters with the sample sd in each iteration. In the code below I first specify a vector, &lt;em&gt;alphas_raw&lt;/em&gt;, in which I’ll store the individual means expressed on the original scale of &lt;em&gt;y&lt;/em&gt;, and three real-valued parameters in which I’ll store the values for the population mean (&lt;em&gt;alpha_hat_raw&lt;/em&gt;), population sd (&lt;em&gt;alpha_scale_raw&lt;/em&gt;), and residual variance (&lt;em&gt;sigma_raw&lt;/em&gt;) expressed on the original scale.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
generated quantities {
  vector[I] alphas_ind;
  
  real alpha_hat_raw;
  real&amp;lt;lower = 0&amp;gt; alpha_scale_raw; 
  real&amp;lt;lower = 0&amp;gt;  sigma_raw; 
  
  alphas_ind = (sdY * alpha) + meanY;
  alpha_hat_raw = (sdY * alpha_hat) + meanY;
  alpha_scale_raw = sdY*alpha_scale;
  
  sigma_raw = sigma*sdY;
  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s it for the STAN-code, let’s quickly simulate some data in R and see if the code gives accurate estimates.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;testing-the-code&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Testing the code &lt;a name=&#34;testing&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Lets load the required packages, use the data generation code described above, and fit out model using &lt;em&gt;rstan&lt;/em&gt;.
To see how well the code works we’ll look at parameter estimates of the population parameters, the correlation between the true- and estimated individual means and AR-parameters, and the average absolute difference between the true and estimated individual means and AR-parameters.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(rstan)
library(mvtnorm)
library(tidyverse)


HierAR &amp;lt;- stan_model(&amp;quot;HierarchicalAR1model.stan&amp;quot;)

I &amp;lt;- 100
t &amp;lt;- 50
N &amp;lt;- I*t
individual &amp;lt;- rep(1:I, each = t)
time &amp;lt;- rep(1:t, I)

set.seed(31121)

# True values for data generation
sigma &amp;lt;- 1 # sd&amp;#39;s of Y residuals 

alpha_hat &amp;lt;- 4 
alpha_scale &amp;lt;- 1 

alphas &amp;lt;- rnorm(I,alpha_hat, alpha_scale) 


beta_hat &amp;lt;- .4 
beta_scale &amp;lt;- .1 

betaGen &amp;lt;- rnorm(I,beta_hat, beta_scale)

for(i in 1:I){
  # The while loop avoids non-stationary AR processes
  # See Hamilton  pg. 259
  while(betaGen[i] &amp;lt;= -1 | betaGen[i] &amp;gt;= 1){
    betaGen[i] &amp;lt;- rnorm(1,beta_hat, beta_scale)
  }
}

betas &amp;lt;- betaGen

# Determine first observations for everyone. The variance for this first 
# observation is different than for the subsequent ones and so it needs to be 
# samples separatelty
IndT1 &amp;lt;- match(unique(individual), individual)

# Determine variance at first measurement for everyone (depends on their 
# AR-parameter)

sigmaT1 &amp;lt;- rep(NA, I)

for(k in 1:I){
sigmaT1[k] &amp;lt;- sigma/(1-((betas[k])^2))
}

# First create storage matrices for non-centered and centered y-scores.
# We need centered values, because of we use person-cetered values as predictors, 
# alpha will be equal to individual means instead of individual intercepts 
# which are less informative.
Y &amp;lt;- rep(NA, N)
Yc &amp;lt;- rep(NA, N)


# Draw first observation for each individual first

for(l in 1:I){
  Y[IndT1[l]] &amp;lt;- rnorm(1, alphas[l], sigmaT1[l])
  Yc[IndT1[l]] &amp;lt;-  Y[IndT1[l]] - alphas[l]
}

 
# Draw subsequent observations

for(m in 1:N){
  
  # This if statement makes sure I don&amp;#39;t try to predict a persons first 
  # observation which is impossible there is no measurement before the first 
  # observation and so no predictor values for that observation
  if(time[m]&amp;gt;1){
    Y[m]&amp;lt;- rnorm(1, (alphas[individual[m]] + betas[individual[m]]*Yc[m-1]), sigma)
    Yc[m] &amp;lt;-  Y[m] - alphas[individual[m]]
  }
}



# Data send to STAN
mod_data &amp;lt;- list(
  individual = individual,
  time = time,
  T = t,
  I = I,
  N = N,
  y = Y
)
  
# Estimate the two models
estimated_ar_model &amp;lt;- sampling(HierAR, 
                               data = mod_data, 
                               iter = 2000,
                               chains=2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## 
## SAMPLING FOR MODEL &amp;#39;HierarchicalAR1model&amp;#39; NOW (CHAIN 1).
## Chain 1: 
## Chain 1: Gradient evaluation took 0.002 seconds
## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 20 seconds.
## Chain 1: Adjust your expectations accordingly!
## Chain 1: 
## Chain 1: 
## Chain 1: Iteration:    1 / 2000 [  0%]  (Warmup)
## Chain 1: Iteration:  200 / 2000 [ 10%]  (Warmup)
## Chain 1: Iteration:  400 / 2000 [ 20%]  (Warmup)
## Chain 1: Iteration:  600 / 2000 [ 30%]  (Warmup)
## Chain 1: Iteration:  800 / 2000 [ 40%]  (Warmup)
## Chain 1: Iteration: 1000 / 2000 [ 50%]  (Warmup)
## Chain 1: Iteration: 1001 / 2000 [ 50%]  (Sampling)
## Chain 1: Iteration: 1200 / 2000 [ 60%]  (Sampling)
## Chain 1: Iteration: 1400 / 2000 [ 70%]  (Sampling)
## Chain 1: Iteration: 1600 / 2000 [ 80%]  (Sampling)
## Chain 1: Iteration: 1800 / 2000 [ 90%]  (Sampling)
## Chain 1: Iteration: 2000 / 2000 [100%]  (Sampling)
## Chain 1: 
## Chain 1:  Elapsed Time: 27.258 seconds (Warm-up)
## Chain 1:                18.613 seconds (Sampling)
## Chain 1:                45.871 seconds (Total)
## Chain 1: 
## 
## SAMPLING FOR MODEL &amp;#39;HierarchicalAR1model&amp;#39; NOW (CHAIN 2).
## Chain 2: 
## Chain 2: Gradient evaluation took 0.001 seconds
## Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 10 seconds.
## Chain 2: Adjust your expectations accordingly!
## Chain 2: 
## Chain 2: 
## Chain 2: Iteration:    1 / 2000 [  0%]  (Warmup)
## Chain 2: Iteration:  200 / 2000 [ 10%]  (Warmup)
## Chain 2: Iteration:  400 / 2000 [ 20%]  (Warmup)
## Chain 2: Iteration:  600 / 2000 [ 30%]  (Warmup)
## Chain 2: Iteration:  800 / 2000 [ 40%]  (Warmup)
## Chain 2: Iteration: 1000 / 2000 [ 50%]  (Warmup)
## Chain 2: Iteration: 1001 / 2000 [ 50%]  (Sampling)
## Chain 2: Iteration: 1200 / 2000 [ 60%]  (Sampling)
## Chain 2: Iteration: 1400 / 2000 [ 70%]  (Sampling)
## Chain 2: Iteration: 1600 / 2000 [ 80%]  (Sampling)
## Chain 2: Iteration: 1800 / 2000 [ 90%]  (Sampling)
## Chain 2: Iteration: 2000 / 2000 [100%]  (Sampling)
## Chain 2: 
## Chain 2:  Elapsed Time: 28.023 seconds (Warm-up)
## Chain 2:                18.79 seconds (Sampling)
## Chain 2:                46.813 seconds (Total)
## Chain 2:&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Check results for population parameters
print(estimated_ar_model, pars = c(&amp;quot;alpha_hat_raw&amp;quot;, &amp;quot;alpha_scale_raw&amp;quot;, &amp;quot;beta_hat&amp;quot;, &amp;quot;beta_scale&amp;quot;, &amp;quot;sigma_raw&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Inference for Stan model: HierarchicalAR1model.
## 2 chains, each with iter=2000; warmup=1000; thin=1; 
## post-warmup draws per chain=1000, total post-warmup draws=2000.
## 
##                 mean se_mean   sd 2.5%  25%  50%  75% 97.5% n_eff Rhat
## alpha_hat_raw   3.88       0 0.12 3.65 3.80 3.88 3.95  4.11  4460 1.00
## alpha_scale_raw 1.10       0 0.08 0.96 1.05 1.10 1.16  1.29  3646 1.00
## beta_hat        0.39       0 0.02 0.36 0.38 0.39 0.40  0.43  1066 1.00
## beta_scale      0.11       0 0.02 0.07 0.10 0.11 0.12  0.15   302 1.02
## sigma_raw       1.01       0 0.01 0.99 1.00 1.01 1.01  1.03  3720 1.00
## 
## Samples were drawn using NUTS(diag_e) at Thu Nov 11 09:53:36 2021.
## For each parameter, n_eff is a crude measure of effective sample size,
## and Rhat is the potential scale reduction factor on split chains (at 
## convergence, Rhat=1).&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Also check individual mean-estimates
Ind_Mean_Est &amp;lt;- summary(estimated_ar_model, pars = c(&amp;quot;alphas_ind&amp;quot;))

# Correlation
cor(Ind_Mean_Est$summary[,1], alphas)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 0.9697346&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Average absolute difference between estimated and true individual values
sqrt(mean((alphas - Ind_Mean_Est$summary[,1])^2))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 0.2602801&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Finally check individual AR-parameters
Ind_AR_Est &amp;lt;- summary(estimated_ar_model, pars = c(&amp;quot;beta&amp;quot;))

# Correlation
cor(Ind_AR_Est$summary[,1], betas)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 0.5700949&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Average absolute difference between estimated and true individual values
sqrt(mean((betas - Ind_AR_Est$summary[,1])^2))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 0.08958009&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the population values are close to their true values of 4, 1, .4, .1, and 1 for &lt;em&gt;alpha_hat_raw&lt;/em&gt;, &lt;em&gt;alpha_scale_raw&lt;/em&gt;, &lt;em&gt;beta_hat&lt;/em&gt;, &lt;em&gt;beta_scale&lt;/em&gt;, and &lt;em&gt;sigma&lt;/em&gt; respectively. The correlation between the true- and estimated individuals means is also high while the average absolute differences between the true- and estimated individual means is small given the scale of the parameter. The average absolute differences between the true- and estimated individual AR-parameters is also small given the scale of the parameter, but the correlation between the true and estimated values is on the low side. This is not a mistake in the code. With 100 individuals and only 50 observations per individual, population values are usually estimated quite well, as are individual means, but individual AR-estimates will show quite some uncertainty leading to lower correlations. So, if your goals is studying and predicting individual differences in AR-parameters, you’d do well to collect more than 50 observations per person. Simulations show that 70 - 100 observations tend to gives sufficient performance in most cases, but you should run simulations to determine your specific sample size needs in a study.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;thats-all-folks&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;That’s All Folks &lt;a name=&#34;taf&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;That’s it for this first installment on the hierarchical AR(1) model. I hope you liked it! And if you have any suggestions, comments, or questions about the code and/or the post in general, please let me know!&lt;/p&gt;
&lt;p&gt;Next up, dealing with missing data when fitting a hierarchical AR(1) model in STAN!&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>STAN Code for Analyzing Intensive Longitudinal Data: Part I - Autoregressive Models</title>
      <link>https://experienced-sampler.netlify.app/post/stan-ar/</link>
      <pubDate>Wed, 20 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://experienced-sampler.netlify.app/post/stan-ar/</guid>
      <description>
&lt;script src=&#34;https://experienced-sampler.netlify.app/post/stan-ar/index_files/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;table-of-contents&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Table of Contents&lt;/h1&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;a href=&#34;#intro&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#completemodel&#34;&gt;The Complete Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#explanation&#34;&gt;But What Does it all Mean?&lt;/a&gt;&lt;br /&gt;
1.&lt;a href=&#34;#data&#34;&gt;The Data Block and Data-generation&lt;/a&gt;&lt;br /&gt;
2.&lt;a href=&#34;#parameters&#34;&gt;The Parameters Block&lt;/a&gt;&lt;br /&gt;
3.&lt;a href=&#34;#model&#34;&gt;The Model Block&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#testing&#34;&gt;Testing the Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#taf&#34;&gt;That’s all Folks!!&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction &lt;a name=&#34;intro&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Over the years I wrote, collected, spliced together, and “stole” (but lets call it borrowed) a lot of code for analyzing intensive longitudinal data (ILD). I was always very happy to have good example code that I could change for my own needs (the “&lt;a href=&#34;https://discourse.mc-stan.org&#34;&gt;STAN-forum&lt;/a&gt;” and Michael Betancourt’s “&lt;a href=&#34;https://betanalpha.github.io/writing/&#34;&gt;case studies&lt;/a&gt;” are just two examples of priceless sources for this). In the spirit of paying it forward, I thought it would be a good idea to write a series of posts in which I share by ILD related STAN model code, including accompanying explanations of what each part of the code does and some simulations to explain/show its functioning. In this series I will share and discuss my STAN model-code, I will write a separate series with R-code for data-wrangling, visualization, etc.&lt;/p&gt;
&lt;p&gt;As this STAN-code series goes on, I’ll share all my STAN model-code, including code for multilevel Vector Autoregressive (VAR) Models (with random covariance matrices), code that can handle missing data, code for within-chain parallelization that greatly speeds up simulations, code with Cholesky decompositions that help with the stability of your code, and more. To start simple however, and to get a feel for this blogging thing I’ll start with some basic STAN-code for the humble first-order autoregressive (AR(1)) model, the workhorse of a lot of more advanced analyses methods for ILD. This model is also the model I started my journey with many years ago, so it feels like a suitable first entry.&lt;/p&gt;
&lt;p&gt;These posts will all share a similar structure in which I first give the full model code, followed with a more chunk by chunk discussion of the model and simulations that show what the code does.&lt;/p&gt;
&lt;p&gt;Alright! Almost ready to begin. I just wanted to add that this is the code that I use. My own personal little Frankensteins. There are undoubtedly ways to make the code more efficient and elegant, and if you would like to comment on the code and suggests improvements, please do! I’ll update the posts accordingly (and give full credit off course!).&lt;/p&gt;
&lt;p&gt;Now let’s get started….everyone, let me introduce the AR(1) model!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-complete-model-code&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The complete model code &lt;a name=&#34;completemodel&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Below is my basic STAN-code for the AR(1) model. We can vectorize some stuff to make it a bit faster, but this is the “no frills” version of the code, and it already runs fast enough anyway.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
// The input data is a vector &amp;#39;y&amp;#39; of length &amp;#39;N&amp;#39;.
data {
  int&amp;lt;lower=0&amp;gt; N;
  vector[N] y;
}

// The parameters accepted by the model. 
parameters {
  real alpha;
  real&amp;lt;lower=-1, upper=1&amp;gt; beta;
  real&amp;lt;lower=0&amp;gt; sigma;
}

// The model to be estimated. We model the output &amp;#39;y&amp;#39; to be normally distributed 
// with mean &amp;#39;alpha + beta * y[n-1]&amp;#39;and standard deviation &amp;#39;sigma&amp;#39;.
model {
  alpha ~ normal(0, 5);
  beta ~ normal(0, .7);
  sigma ~ normal(0, 2);
  
  
  for (n in 2:N)
    y[n] ~ normal(alpha + beta * y[n-1], sigma);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also have code that allows you to select different lags (indicated by K in the code below) for you autoregressive model. That code looks like this:&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;// The input data is a vector &amp;#39;y&amp;#39; of length &amp;#39;N&amp;#39;.
data {
  int&amp;lt;lower=0&amp;gt; K;
  int&amp;lt;lower=0&amp;gt; N;
  real y[N];
}

// The parameters accepted by the model. 
parameters {
  real alpha;
  real&amp;lt;lower=-1, upper=1&amp;gt; beta[K];
  real&amp;lt;lower=0&amp;gt; sigma;
}

// The model to be estimated. We model the output &amp;#39;y&amp;#39; to be normally distributed 
// with mean &amp;#39;mu&amp;#39;and standard deviation &amp;#39;sigma&amp;#39;.
model {
  alpha ~ normal(0, 5);
  beta ~ normal(0, .7);
  sigma ~ normal(0, 2);
  
  for (n in (K+1):N) {
    real mu = alpha;
    for (k in 1:K)
      mu += beta[k] * y[n-k];
      y[n] ~ normal(mu, sigma);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, you can either copy and paste the code and be off, or read on below for some explanation of the code.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;but-what-does-it-all-mean&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;But what does it all mean?! &lt;a name=&#34;explanation&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;div id=&#34;the-data-block-and-data-generation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Data Block and Data-generation &lt;a name=&#34;data&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;STAN code is very (veeeery) structured. This takes some getting used to, but I ended up liking it (although I still curse it from time to time). For a very thorough discussion of the STAN language and block structure check out this amazing “&lt;a href=&#34;https://betanalpha.github.io/assets/case_studies/stan_intro.html#1_prologue&#34;&gt;intro&lt;/a&gt;” by Michael Betancourt. I’ll only describe the block and elements that are actually in this model. First up, the &lt;em&gt;data block&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
// The input data is a vector &amp;#39;y&amp;#39; of length &amp;#39;N&amp;#39;.
data {
  int&amp;lt;lower=0&amp;gt; N;
  vector[N] y;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you probably guessed, the &lt;em&gt;data block&lt;/em&gt; is where you specify the variables (and their characteristics) that you specified outside of STAN, and that you are using as input to your model. Here, I specify the number of total observations N, and the vector with all N observations of my outcome variable (y). Note that in the &lt;em&gt;data block&lt;/em&gt; I explicitly mention that N is an integer and y is a vector. As I said, the STAN model code is very structured and you have to specify the type of all your data (and parameters). I also specify a lower bound for the value of N (the number of observations can’t be smaller than 0), to prevent me from accidentally providing weird data to the model. If you want to generate data for this model in R, I would do that (before calling the STAN-model) by running the code below:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N = 500

y &amp;lt;- arima.sim(list(order=c(1,0,0), ar=.5), n=N)

# If you want a mean different than 0, 5 for example, run: y &amp;lt;- y + 5  &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the model that allows you to select different lags I would also have to specify the lag (K) I want to use in my model in R before running the STAN-code. For an AR(1) model my pre-STAN data generation would look like:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N = 500

y &amp;lt;- arima.sim(list(order=c(1,0,0), ar=.5), n=N)

# If you want a mean different than 0, 5 for example, run: y &amp;lt;- y + 5  

K &amp;lt;- 1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-parameters-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Parameters Block &lt;a name=&#34;parameters&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Next is the &lt;em&gt;parameters block&lt;/em&gt;. Here you specify all the parameters of your model, here an intercept (alpha), an AR-parameter (beta), and the standard deviation of the residuals (sigma). As for the data, you have to specify the type for your parameters (here the type of all parameters is real, since they are all continuous variables). I also specify a lower bound for my standard deviation (sigma) and an upper and lower bound for my AR-parameter (beta). This last constraint reflects that I want my model to be stationary which requires the AR-parameter to be between -1 and 1. Draws that fall outside of this range will be rejected.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
// The parameters accepted by the model. 
parameters {
  real alpha;
  real&amp;lt;lower=-1, upper=1&amp;gt; beta;
  real&amp;lt;lower=0&amp;gt; sigma;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;em&gt;parameters block&lt;/em&gt; for the model in which you can choose the lag is almost the same, but now you would have to specify an AR parameter for each lag in your model (i.e., 1 parameter for an AR(1) model, 2 parameters for an AR(2) model, etc). To that end, beta is not a real valued scalar in that model but a vector containing a number of values that is equal to the lag (K).&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;parameters {
  real alpha;
  real&amp;lt;lower=-1, upper=1&amp;gt; beta[K];
  real&amp;lt;lower=0&amp;gt; sigma;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-model-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Model Block &lt;a name=&#34;model&#34;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Finally, the &lt;em&gt;model block&lt;/em&gt;. This is where you specify your full Bayesian model; the priors for your parameters and the observational model for your data. I’m using weakly informative normal priors for my intercept and AR-parameter, and a weakly informative half-normal prior for my SD. The specific values for these priors are chose based on the fact that many measures in social sciences use 5 or 7-point Likert-scales. You could also specify priors for a standardized scale and standardize your variables as part of the model, that way you don’t have to change the priors for each new data set. I’ll show this approach in an upcoming post. Note that while I say I use a half-normal prior on sigma, I actually put a normal distribution on this parameter. However, since I specified sigma should be larger than 0 in the &lt;em&gt;parameters block&lt;/em&gt;, STAN turns this into a half-normal distribution (did I already mention STAN is awesome?!). For my outcome variable y, I specify the standard AR(1) model in which each observation is regressed on the immediate prior observation using the AR-parameter (beta). Note that I can’t use the first observation on y, as there is no previous observation that I can use as a predictor for the first observation.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;
// The model to be estimated. We model the output &amp;#39;y&amp;#39; to be normally distributed 
// with mean &amp;#39;alpha + beta * y[n-1]&amp;#39;and standard deviation &amp;#39;sigma&amp;#39;.
model {
  alpha ~ normal(0, 5);
  beta ~ normal(0, .7);
  sigma ~ normal(0, 2);
  
  
  for (n in 2:N)
    y[n] ~ normal(alpha + beta * y[n-1], sigma);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the model in which you can specify the lag you want, the basics are the same but I include an additional loop so all the lags I want are fitted to the model.&lt;/p&gt;
&lt;pre class=&#34;stan&#34;&gt;&lt;code&gt;// The model to be estimated. We model the output &amp;#39;y&amp;#39; to be normally distributed 
// with mean &amp;#39;mu&amp;#39;and standard deviation &amp;#39;sigma&amp;#39;.
model {
  alpha ~ normal(0, 5);
  beta ~ normal(0, .7);
  sigma ~ normal(0, 2);
  
  for (n in (K+1):N) {
    real mu = alpha;
    
    for (k in 1:K)
      mu += beta[k] * y[n-k];
      y[n] ~ normal(mu, sigma);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Basically, I cut my observational model up into two parts. First I specify an empty model for y, that just contains the intercept alpha (this is what I do in the first line within the first for-loop). In this first for-loop I specify a new “ghost” parameter, mu, that is real valued. It’s a “ghost” parameter in the sense that it is not really a model parameter, and I only use it to conveniently add a not previously determined number of lags to my observational model (my likelihood) of y. It’s function will become apparent shortly. Also note that I have to ignore the first K observations. If I use a lag of 2, I can’t use the first two observations in my data since these don’t have two prior observations that can be used a predictors. In a separate second step I add the part of my observational model that predicts an observation using previous scores. This is what is happening in the nested for-loop. Notice that I can neatly cut a likelihood up into parts using the “+=” operator. That operator add the expression to the right of it to the likelihood that was already specified for the parameter on the left-side of the operator. This is the way my “ghost” parameter mu is used! I want to add the entire expression of the AR model to the likelihood of y, but since the number of lagged terms is not predetermined, I could not simple write out the code in the STAN-file. Instead, I add the intercept to the likelihood first (through the “ghost” parameter mu), and then add as much lagged terms to the likelihood as needed/specified by looping over the code. The “ghost” parameter mu can subsequently be specified as the mean of the normal density of y, and it will contain all relevant lagged effects as well as the intercept.&lt;/p&gt;
&lt;p&gt;Note that my model part ends with an empty line! This is because STAN always want the last line of the model code to be blank.&lt;/p&gt;
&lt;p&gt;That’s it for the STAN-code, let’s quickly simulate some data in R and see if the code gives accurate estimates.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;testing-the-code&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Testing the code &lt;a name=&#34;testing&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I tend to use &lt;em&gt;cmdstan&lt;/em&gt; as my R-interface for STAN, but below I’ll use &lt;em&gt;rstan&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Load the necessary package
library(rstan)

# Specify the data provided to the model
N = 500

K &amp;lt;- 1

y &amp;lt;- arima.sim(list(order=c(1,0,0), ar=.5), n=N)

# If you want a mean different than 0, 5 for example, run: y &amp;lt;- y + 5  

# Put the data into a list so it can be provided to STAN

# For the basic AR(1) model
mod_data &amp;lt;- list(
              N = N,
              y = y
              )
 
# For the basic AR model that allows selecting the lag
mod_data_select &amp;lt;- list(
                     N = N,
                     y = y,
                     K = 1
                     )


# Compile the STAN models discussed above

# Basic AR(1) model
Basic_AR &amp;lt;- stan_model(&amp;quot;AR1model.stan&amp;quot;)

# Basic AR model that allows setting the lag
Basic_AR_Select_Lag &amp;lt;- stan_model(&amp;quot;AR-K-model.stan&amp;quot;)


# Estimate the two models
estimated_ar_model &amp;lt;- sampling(Basic_AR, 
                            data = mod_data, 
                            iter = 2000,
                            chains=2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## 
## SAMPLING FOR MODEL &amp;#39;AR1model&amp;#39; NOW (CHAIN 1).
## Chain 1: 
## Chain 1: Gradient evaluation took 0 seconds
## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
## Chain 1: Adjust your expectations accordingly!
## Chain 1: 
## Chain 1: 
## Chain 1: Iteration:    1 / 2000 [  0%]  (Warmup)
## Chain 1: Iteration:  200 / 2000 [ 10%]  (Warmup)
## Chain 1: Iteration:  400 / 2000 [ 20%]  (Warmup)
## Chain 1: Iteration:  600 / 2000 [ 30%]  (Warmup)
## Chain 1: Iteration:  800 / 2000 [ 40%]  (Warmup)
## Chain 1: Iteration: 1000 / 2000 [ 50%]  (Warmup)
## Chain 1: Iteration: 1001 / 2000 [ 50%]  (Sampling)
## Chain 1: Iteration: 1200 / 2000 [ 60%]  (Sampling)
## Chain 1: Iteration: 1400 / 2000 [ 70%]  (Sampling)
## Chain 1: Iteration: 1600 / 2000 [ 80%]  (Sampling)
## Chain 1: Iteration: 1800 / 2000 [ 90%]  (Sampling)
## Chain 1: Iteration: 2000 / 2000 [100%]  (Sampling)
## Chain 1: 
## Chain 1:  Elapsed Time: 0.26 seconds (Warm-up)
## Chain 1:                0.263 seconds (Sampling)
## Chain 1:                0.523 seconds (Total)
## Chain 1: 
## 
## SAMPLING FOR MODEL &amp;#39;AR1model&amp;#39; NOW (CHAIN 2).
## Chain 2: 
## Chain 2: Gradient evaluation took 0 seconds
## Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
## Chain 2: Adjust your expectations accordingly!
## Chain 2: 
## Chain 2: 
## Chain 2: Iteration:    1 / 2000 [  0%]  (Warmup)
## Chain 2: Iteration:  200 / 2000 [ 10%]  (Warmup)
## Chain 2: Iteration:  400 / 2000 [ 20%]  (Warmup)
## Chain 2: Iteration:  600 / 2000 [ 30%]  (Warmup)
## Chain 2: Iteration:  800 / 2000 [ 40%]  (Warmup)
## Chain 2: Iteration: 1000 / 2000 [ 50%]  (Warmup)
## Chain 2: Iteration: 1001 / 2000 [ 50%]  (Sampling)
## Chain 2: Iteration: 1200 / 2000 [ 60%]  (Sampling)
## Chain 2: Iteration: 1400 / 2000 [ 70%]  (Sampling)
## Chain 2: Iteration: 1600 / 2000 [ 80%]  (Sampling)
## Chain 2: Iteration: 1800 / 2000 [ 90%]  (Sampling)
## Chain 2: Iteration: 2000 / 2000 [100%]  (Sampling)
## Chain 2: 
## Chain 2:  Elapsed Time: 0.256 seconds (Warm-up)
## Chain 2:                0.263 seconds (Sampling)
## Chain 2:                0.519 seconds (Total)
## Chain 2:&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;estimated_ar_select_model &amp;lt;- sampling(Basic_AR_Select_Lag, 
                               data = mod_data_select, 
                               iter = 2000,
                               chains=2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## 
## SAMPLING FOR MODEL &amp;#39;AR-K-model&amp;#39; NOW (CHAIN 1).
## Chain 1: 
## Chain 1: Gradient evaluation took 0 seconds
## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
## Chain 1: Adjust your expectations accordingly!
## Chain 1: 
## Chain 1: 
## Chain 1: Iteration:    1 / 2000 [  0%]  (Warmup)
## Chain 1: Iteration:  200 / 2000 [ 10%]  (Warmup)
## Chain 1: Iteration:  400 / 2000 [ 20%]  (Warmup)
## Chain 1: Iteration:  600 / 2000 [ 30%]  (Warmup)
## Chain 1: Iteration:  800 / 2000 [ 40%]  (Warmup)
## Chain 1: Iteration: 1000 / 2000 [ 50%]  (Warmup)
## Chain 1: Iteration: 1001 / 2000 [ 50%]  (Sampling)
## Chain 1: Iteration: 1200 / 2000 [ 60%]  (Sampling)
## Chain 1: Iteration: 1400 / 2000 [ 70%]  (Sampling)
## Chain 1: Iteration: 1600 / 2000 [ 80%]  (Sampling)
## Chain 1: Iteration: 1800 / 2000 [ 90%]  (Sampling)
## Chain 1: Iteration: 2000 / 2000 [100%]  (Sampling)
## Chain 1: 
## Chain 1:  Elapsed Time: 0.249 seconds (Warm-up)
## Chain 1:                0.263 seconds (Sampling)
## Chain 1:                0.512 seconds (Total)
## Chain 1: 
## 
## SAMPLING FOR MODEL &amp;#39;AR-K-model&amp;#39; NOW (CHAIN 2).
## Chain 2: 
## Chain 2: Gradient evaluation took 0 seconds
## Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
## Chain 2: Adjust your expectations accordingly!
## Chain 2: 
## Chain 2: 
## Chain 2: Iteration:    1 / 2000 [  0%]  (Warmup)
## Chain 2: Iteration:  200 / 2000 [ 10%]  (Warmup)
## Chain 2: Iteration:  400 / 2000 [ 20%]  (Warmup)
## Chain 2: Iteration:  600 / 2000 [ 30%]  (Warmup)
## Chain 2: Iteration:  800 / 2000 [ 40%]  (Warmup)
## Chain 2: Iteration: 1000 / 2000 [ 50%]  (Warmup)
## Chain 2: Iteration: 1001 / 2000 [ 50%]  (Sampling)
## Chain 2: Iteration: 1200 / 2000 [ 60%]  (Sampling)
## Chain 2: Iteration: 1400 / 2000 [ 70%]  (Sampling)
## Chain 2: Iteration: 1600 / 2000 [ 80%]  (Sampling)
## Chain 2: Iteration: 1800 / 2000 [ 90%]  (Sampling)
## Chain 2: Iteration: 2000 / 2000 [100%]  (Sampling)
## Chain 2: 
## Chain 2:  Elapsed Time: 0.245 seconds (Warm-up)
## Chain 2:                0.221 seconds (Sampling)
## Chain 2:                0.466 seconds (Total)
## Chain 2:&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Show Results: True alpha = 0, true beta = .5, true sigma = 1

print(estimated_ar_model)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Inference for Stan model: AR1model.
## 2 chains, each with iter=2000; warmup=1000; thin=1; 
## post-warmup draws per chain=1000, total post-warmup draws=2000.
## 
##          mean se_mean   sd    2.5%     25%     50%     75%   97.5% n_eff Rhat
## alpha    0.02    0.00 0.05   -0.07   -0.01    0.02    0.05    0.11  2076    1
## beta     0.44    0.00 0.04    0.36    0.41    0.44    0.47    0.52  1832    1
## sigma    1.02    0.00 0.03    0.96    0.99    1.02    1.04    1.08  1925    1
## lp__  -257.86    0.04 1.30 -261.34 -258.41 -257.49 -256.92 -256.43   914    1
## 
## Samples were drawn using NUTS(diag_e) at Wed Nov 10 18:38:22 2021.
## For each parameter, n_eff is a crude measure of effective sample size,
## and Rhat is the potential scale reduction factor on split chains (at 
## convergence, Rhat=1).&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;print(estimated_ar_select_model)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Inference for Stan model: AR-K-model.
## 2 chains, each with iter=2000; warmup=1000; thin=1; 
## post-warmup draws per chain=1000, total post-warmup draws=2000.
## 
##            mean se_mean   sd    2.5%     25%     50%     75%   97.5% n_eff Rhat
## alpha      0.02    0.00 0.04   -0.07   -0.01    0.02    0.05    0.11  2403    1
## beta[1]    0.44    0.00 0.04    0.36    0.42    0.44    0.47    0.52  2026    1
## sigma      1.02    0.00 0.03    0.96    0.99    1.01    1.04    1.08  1994    1
## lp__    -257.77    0.04 1.17 -260.74 -258.36 -257.47 -256.90 -256.42  1046    1
## 
## Samples were drawn using NUTS(diag_e) at Wed Nov 10 18:38:23 2021.
## For each parameter, n_eff is a crude measure of effective sample size,
## and Rhat is the potential scale reduction factor on split chains (at 
## convergence, Rhat=1).&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The true values of alpha, beta, and sigma, are 0, .5, and 1 respectively, and as you can see both models accurately estimate the parameter values.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;thats-all-folks&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;That’s All Folks &lt;a name=&#34;taf&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;That’s it for this first installment of my series of posts on STAN-code for models often used with ILD. I hope you liked it! And if you have any suggestions and/or improvements, please let me know!&lt;/p&gt;
&lt;p&gt;Next up, a multilevel AR(1) Model!&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Welcome to Wowchemy, the website builder for Hugo</title>
      <link>https://experienced-sampler.netlify.app/post/getting-started/</link>
      <pubDate>Sun, 13 Dec 2020 00:00:00 +0000</pubDate>
      <guid>https://experienced-sampler.netlify.app/post/getting-started/</guid>
      <description>&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;The Wowchemy website builder for Hugo, along with its starter templates, is designed for professional creators, educators, and teams/organizations - although it can be used to create any kind of site&lt;/li&gt;
&lt;li&gt;The template can be modified and customised to suit your needs. It&amp;rsquo;s a good platform for anyone looking to take control of their data and online identity whilst having the convenience to start off with a &lt;strong&gt;no-code solution (write in Markdown and customize with YAML parameters)&lt;/strong&gt; and having &lt;strong&gt;flexibility to later add even deeper personalization with HTML and CSS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;You can work with all your favourite tools and apps with hundreds of plugins and integrations to speed up your workflows, interact with your readers, and much more&lt;/li&gt;
&lt;/ol&gt;














&lt;figure  id=&#34;figure-the-template-is-mobile-first-with-a-responsive-design-to-ensure-that-your-site-looks-stunning-on-every-device&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img src=&#34;https://raw.githubusercontent.com/wowchemy/wowchemy-hugo-modules/master/academic.png&#34; alt=&#34;The template is mobile first with a responsive design to ensure that your site looks stunning on every device.&#34; loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      The template is mobile first with a responsive design to ensure that your site looks stunning on every device.
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&#34;get-started&#34;&gt;Get Started&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;👉 &lt;a href=&#34;https://wowchemy.com/templates/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;Create a new site&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;📚 &lt;a href=&#34;https://wowchemy.com/docs/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;Personalize your site&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;💬 &lt;a href=&#34;https://discord.gg/z8wNYzb&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chat with the &lt;strong&gt;Wowchemy community&lt;/strong&gt;&lt;/a&gt; or &lt;a href=&#34;https://discourse.gohugo.io&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;Hugo community&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;🐦 Twitter: &lt;a href=&#34;https://twitter.com/wowchemy&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;@wowchemy&lt;/a&gt; &lt;a href=&#34;https://twitter.com/GeorgeCushen&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;@GeorgeCushen&lt;/a&gt; &lt;a href=&#34;https://twitter.com/search?q=%28%23MadeWithWowchemy%20OR%20%23MadeWithAcademic%29&amp;amp;src=typed_query&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;#MadeWithWowchemy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;💡 &lt;a href=&#34;https://github.com/wowchemy/wowchemy-hugo-modules/issues&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Request a &lt;strong&gt;feature&lt;/strong&gt; or report a &lt;strong&gt;bug&lt;/strong&gt; for &lt;em&gt;Wowchemy&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;⬆️ &lt;strong&gt;Updating Wowchemy?&lt;/strong&gt; View the &lt;a href=&#34;https://wowchemy.com/docs/hugo-tutorials/update/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Update Tutorial&lt;/a&gt; and &lt;a href=&#34;https://wowchemy.com/updates/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Release Notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;crowd-funded-open-source-software&#34;&gt;Crowd-funded open-source software&lt;/h2&gt;
&lt;p&gt;To help us develop this template and software sustainably under the MIT license, we ask all individuals and businesses that use it to help support its ongoing maintenance and development via sponsorship.&lt;/p&gt;
&lt;h3 id=&#34;-click-here-to-become-a-sponsor-and-help-support-wowchemys-future-httpswowchemycomplans&#34;&gt;&lt;a href=&#34;https://wowchemy.com/plans/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;❤️ Click here to become a sponsor and help support Wowchemy&amp;rsquo;s future ❤️&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As a token of appreciation for sponsoring, you can &lt;strong&gt;unlock &lt;a href=&#34;https://wowchemy.com/plans/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;these&lt;/a&gt; awesome rewards and extra features 🦄✨&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;ecosystem&#34;&gt;Ecosystem&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/wowchemy/hugo-academic-cli&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Hugo Academic CLI&lt;/a&gt;:&lt;/strong&gt; Automatically import publications from BibTeX&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;inspiration&#34;&gt;Inspiration&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://academic-demo.netlify.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the latest &lt;strong&gt;demo&lt;/strong&gt;&lt;/a&gt; of what you&amp;rsquo;ll get in less than 10 minutes, or &lt;a href=&#34;https://wowchemy.com/user-stories/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;view the &lt;strong&gt;showcase&lt;/strong&gt;&lt;/a&gt; of personal, project, and business sites.&lt;/p&gt;
&lt;h2 id=&#34;features&#34;&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page builder&lt;/strong&gt; - Create &lt;em&gt;anything&lt;/em&gt; with &lt;a href=&#34;https://wowchemy.com/docs/page-builder/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;widgets&lt;/strong&gt;&lt;/a&gt; and &lt;a href=&#34;https://wowchemy.com/docs/content/writing-markdown-latex/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;elements&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Edit any type of content&lt;/strong&gt; - Blog posts, publications, talks, slides, projects, and more!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create content&lt;/strong&gt; in &lt;a href=&#34;https://wowchemy.com/docs/content/writing-markdown-latex/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;Markdown&lt;/strong&gt;&lt;/a&gt;, &lt;a href=&#34;https://wowchemy.com/docs/import/jupyter/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;Jupyter&lt;/strong&gt;&lt;/a&gt;, or &lt;a href=&#34;https://wowchemy.com/docs/install-locally/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;RStudio&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plugin System&lt;/strong&gt; - Fully customizable &lt;a href=&#34;https://wowchemy.com/docs/customization/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;color&lt;/strong&gt; and &lt;strong&gt;font themes&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Display Code and Math&lt;/strong&gt; - Code highlighting and &lt;a href=&#34;https://en.wikibooks.org/wiki/LaTeX/Mathematics&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;LaTeX math&lt;/a&gt; supported&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integrations&lt;/strong&gt; - &lt;a href=&#34;https://analytics.google.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Google Analytics&lt;/a&gt;, &lt;a href=&#34;https://disqus.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Disqus commenting&lt;/a&gt;, Maps, Contact Forms, and more!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Beautiful Site&lt;/strong&gt; - Simple and refreshing one page design&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Industry-Leading SEO&lt;/strong&gt; - Help get your website found on search engines and social media&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media Galleries&lt;/strong&gt; - Display your images and videos with captions in a customizable gallery&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile Friendly&lt;/strong&gt; - Look amazing on every screen with a mobile friendly version of your site&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-language&lt;/strong&gt; - 34+ language packs including English, 中文, and Português&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-user&lt;/strong&gt; - Each author gets their own profile page&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacy Pack&lt;/strong&gt; - Assists with GDPR&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stand Out&lt;/strong&gt; - Bring your site to life with animation, parallax backgrounds, and scroll effects&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One-Click Deployment&lt;/strong&gt; - No servers. No databases. Only files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;themes&#34;&gt;Themes&lt;/h2&gt;
&lt;p&gt;Wowchemy and its templates come with &lt;strong&gt;automatic day (light) and night (dark) mode&lt;/strong&gt; built-in. Alternatively, visitors can choose their preferred mode - click the moon icon in the top right of the &lt;a href=&#34;https://academic-demo.netlify.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Demo&lt;/a&gt; to see it in action! Day/night mode can also be disabled by the site admin in &lt;code&gt;params.toml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://wowchemy.com/docs/customization&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Choose a stunning &lt;strong&gt;theme&lt;/strong&gt; and &lt;strong&gt;font&lt;/strong&gt;&lt;/a&gt; for your site. Themes are fully customizable.&lt;/p&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;Copyright 2016-present &lt;a href=&#34;https://georgecushen.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;George Cushen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Released under the &lt;a href=&#34;https://github.com/wowchemy/wowchemy-hugo-modules/blob/master/LICENSE.md&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;MIT&lt;/a&gt; license.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
