ScalaStan with Existing Stan Models?

Operating System: MacOS
Interface Version: ScalaStan 0.5.8
Compiler/Toolkit: IntelliJ IDEA

@sbussmann

I’m trying to use an existing Stan model with ScalaStan but I can’t get it to work. Everything works fine if I create the data, parameters, and model in Scala, but I try to use the model from in a external .stan file, it won’t work no matter what I’ve tried. There doesn’t appear to be any examples of doing this, so I am turning to the forum for help.

Simple Scala example (Working):

case class LinearRegression(xData: Seq[Double], yData: Seq[Double]) extends ScalaStan {
  private val n = data(int(lower = 0))
  private val x: DataDeclaration[StanVector] = data(vector(n))
  private val y: DataDeclaration[StanVector] = data(vector(n))

  private val m: ParameterDeclaration[StanReal] = parameter(real())
  private val b: ParameterDeclaration[StanReal] = parameter(real())

  private val sigma: ParameterDeclaration[StanReal] = parameter(real(lower = 0))

  private val model = new Model {
    y ~ stan.normal(m * x + b, sigma)
  }

  val results = getResults()

  private def getResults[M <: CompiledModel](): StanResults = {
    val compiledModel = model.compile
      .withData(x, xData)
      .withData(y, yData)

    return compiledModel.run()
  }

}

Trying

case class LinearRegression(xData: Seq[Double], yData: Seq[Double]) extends ScalaStan {
  private val n = data(int(lower = 0))
  private val x: DataDeclaration[StanVector] = data(vector(n))
  private val y: DataDeclaration[StanVector] = data(vector(n))

  private val m: ParameterDeclaration[StanReal] = parameter(real())
  private val b: ParameterDeclaration[StanReal] = parameter(real())

  private val sigma: ParameterDeclaration[StanReal] = parameter(real(lower = 0))

  private val model = Model.loadFromFile(<path to .stan file>)

  val results = getResults()

  private def getResults[M <: CompiledModel](): StanResults = {
    val compiledModel = model.compile
      .withData(x, xData)
      .withData(y, yData)

    return compiledModel.run()
  }

}

with .stan file contents:

model {
  y ~ normal(((m) * (x)) + (b),sigma);
}

Gives the following error:

variable “y” does not exist.

According to the documentation:

To use an existing model, the data and parameters must be set up in ScalaStan, then the loadFromFile (or loadFromString) method on Model can be used to load the model.

It sounds like this would be the correct way? If I add in the data and parameters to the .stan file as:

data {
  int<lower=0> n;
  vector[n] x;
  vector[n] y;
}
parameters {
  real m;
  real b;
  real<lower=0.0> sigma;
}
model {
  y ~ normal(((m) * (x)) + (b),sigma);
}

It will get a little further but will give the following error:

Exception: variable does not exist; processing stage: data initialization; variable name=nl base type int …

If I remove “n” from both the scala file and .stan file (and hard code the vector size) it moves to not finding “x”.

Does anyone know the proper way to make this work?

You may want to tag someone at CiBO, such as @sbussmann .

Thanks bgoodri. I’ve never used Discourse before. How would I do that?

You just precede their user name with an @ symbol, a la Twitter (which I did in my previous post).

So it turns out that there was a bug recently introduced in ScalaStan where it wouldn’t pass along the data to Stan. I just opened a PR to fix it here: https://github.com/cibotech/ScalaStan/pull/72 and it should be merged soon (it’s a pretty easy fix). I also added an example to serve as an integration test so this doesn’t happen again, which also shows how to use this.

Assuming it worked correctly… you need to specify all the parameters in both the “.stan” file and in ScalaStan since ScalaStan doesn’t attempt to parse the model and figure out what’s there, so that means you need to call “withData” for “x”, “y”, and “n”.

1 Like

Awesome!

All looks good now. Thanks for the rapid fix!

1 Like