Git Product home page Git Product logo

jags.jl's Introduction

Jags

Purpose

A package to use Jags (as an external program) from Julia. Jags.jl has been moved to JagsJulia.

For more info on Jags, please go to http://mcmc-jags.sourceforge.net.

What's new

Version 3.2.0 (unfinished)

  1. Attempting to fix issue #23.

Warning: I have seen many cases where the Jags binary simply hangs. This happens immediatiately after the line "Executing n command(s), each with m chain(s) took:".

Version 3.1.0

  1. Reactivate Github actions.

Version 3.0.3

  1. Please note that version 3.0.2 allows MCMCChains v 4.0 which can introduce breaking changes in handling of Chains. If this is a problem, please force usage of [email protected].

Version 3.0.0

  1. MCMCChains for storage and diagnostics (thanks to Chris Fisher)
  2. No longer depends on Mamba and Gadfly

Version 2.0.1 (tagged Jan 2019)

  1. Fixed issues with REQUIRE.

Version 2.0.0 (tagged Jan 2019)

  1. Thanks to Hellema Jags.jl has been updated for Julia 1.

Version 1.0.5 (tagged Jan 2018)

  1. Added an option to specify thinning by Jags. Jagsmodel() now accepts a jagsthin arguments. Default is jagsthin=1. Thanks to @hellemo. See examples Line3 and Line4.
  2. Further updates by Hellemo (e.g. to improve readdlm performance).
  3. Tested on Julia 0.6. Not yet on Julia 0.7-.

Version 1.0.2

  1. Requires Julia v"0.5.0-rc3".
  2. Updated .travis.yml to jsut test on Julia 0.5

Version 1.0.0

  1. Updated for Julia 0.5

Version 0.2.0

  1. Added badges for Julia package listing
  2. Exported JAGS_HOME in Jags.jl
  3. Updated for to also run Julia 0.4 pre-releases

Version 0.1.5

  1. Updated .travis.yml
  2. The runtests.jl script now prints package version

Version 0.1.4

  1. Allowed JAGS_HOME and JULIA_SVG_BROWSER to be set from either ~/.juliarc.jl or as an evironment variable. Updated README accordingly.

Version 0.1.3

  1. Removed upper bound on Julia in REQUIRE.

Version 0.1.2

  1. Fix for access to environment variables on Windows.

Version 0.1.1

  1. Stores Jags's input & output files in a subdirectory of the working directory.
  2. Added Bones2 example.

Version 0.1.0

The two most important features introduced in version 0.1.0 are:

  1. Using Mamba to display and diagnose simulation results. The call to jags() to sample now returns a Mamba Chains object (previously it returned a dictionary).
  2. Added the ability to specify RNGs in the initializations file for running simulations in parallel.

Version 0.0.4

  1. Added the ability to start multiple Jags scripts in parallel.

Version 0.0.3 and earlier

  1. Parsing structure for input arguments to Stan.
  2. Single process execution of a Jags simulations.
  3. Read created output files by Jags back into Julia.

Requirements

This version of the Jags.jl package assumes that:

  1. Jags is installed and the jags binary is on $PATH. The variable JAGS_HOME is currently initialized either from ~/.juliarc.jl or from an environment variable JAGS_HOME. JAGS_HOME currently only used in runtests.jl to disable attempting to run tests that need the Jags executable on $PATH.

To test and run the examples:

julia > Pkg.test("Jags")

A walk through example

As in the Jags.jl setting, the Jags program consumes and produces files in a 'tmp' subdirectory of the current directory, it is useful to control the current working directory and restore the original directory at the end of the script.

using Jags

ProjDir = dirname(@__FILE__)
cd(ProjDir)

Variable line holds the model which will be writtten to a file named $(model.name).bugs in the 'tmp' subdirectory. The value of model.name is set later on, see the call to Jagsmodel() below.

line = "
model {
  for (i in 1:n) {
        mu[i] <- alpha + beta*(x[i] - x.bar);
        y[i]   ~ dnorm(mu[i],tau);
  }
  x.bar   <- mean(x[]);
  alpha    ~ dnorm(0.0,1.0E-4);
  beta     ~ dnorm(0.0,1.0E-4);
  tau      ~ dgamma(1.0E-3,1.0E-3);
  sigma   <- 1.0/sqrt(tau);
}
"

Next, define which variables should be monitored (if => true).

monitors = (String => Bool)[
  "alpha" => true,
  "beta" => true,
  "tau" => true,
  "sigma" => true,
]

The next step is to create and initialize a Jagsmodel:

jagsmodel = Jagsmodel(
  name="line1",
  model=line,
  monitor=monitors,
  #ncommands=1, nchains=4,
  #deviance=true, dic=true, popt=true,
  pdir=ProjDir);

println("\nJagsmodel that will be used:")
jagsmodel |> display

Notice that by default a single command with 4 chains is created. It is possible to run each of the 4 chains in a separate process which has advantages. Using the Bones example as a testcase, on my machine running 1 command simulating a single chain takes 6 seconds, 4 (parallel) commands each simulating 1 chain takes about 9 seconds and a single command simulating 4 chains takes about 25 seconds. Of course this is dependent on the number of available cores and assumes the drawing of samples takes a reasonable chunk of time vs. running a command in a new shell.

Running chains in separate commands does need additional data to be passed in through the initialization data and is demonstrated in Examples/Line2. Some more details are given below.

If nchains is set to 1, this is updated in Jagsmodel() if dic and/or popt is requested. Jags needs minimally 2 chains to compute those.

The input data for the line example is in below data dictionary:

data = Dict(
  "x" => [1, 2, 3, 4, 5],
  "y" => [1, 3, 3, 3, 5],
  "n" => 5
)

println("Input observed data dictionary:")
data |> display

Next define an array of dictionaries with initial values for parameters. If the array of dictionaries has not enough elements, the elements will be recycled for chains/commands:

inits = [
  Dict("alpha" => 0,"beta" => 0,"tau" => 1),
  Dict("alpha" => 1,"beta" => 2,"tau" => 1),
  Dict("alpha" => 3,"beta" => 3,"tau" => 2),
  Dict("alpha" => 5,"beta" => 2,"tau" => 5)
]

#### Note: Multiple init sets is the best option to get independent chains.

println("\nInput initial values dictionary:")
inits |> display
println()

Run the mcmc simulation, passing in the model, the data, the initial values and the working directory. If 'inits' is a single dictionary, it needs to be passed in as '[inits]', see the Bones example.

sim = jags(jagsmodel, data, inits, ProjDir)
describe(sim)
println()

Running a Jags script, some details

Jags.jl really only consists of 2 functions, Jagsmodel() and jags().

Jagsmodel() is used to define and set up the basic structure to run a simulation. The full signature of Jagsmodel() is:

function Jagsmodel(;
  name="Noname",
  model="",
  ncommands=1,
  nchains=4,
  adapt=1000,
  nsamples=10000,
  thin=10,
  jagsthin=1,
  monitor=Dict(),
  deviance=false,
  dic=false,
  popt=false,
  updatejagsfile=true,
  pdir=pwd())

All arguments are keyword arguments and have default values, although usually at least the name and model arguments will be provided.

After a Jagsmodel has been created, the workhorse function jags() is called to run the simulation, passing in the Jagsmodel, the data and the initialization for the chains.

As Jags needs quite a few input files and produces several output files, these are all stored in a subdirectory of the working directory, typically called 'tmp'.

The full signature of jags() is:

function jags(
  model::Jagsmodel,
  data::Dict{String, Any}=Dict{String, Any}(),
  init::Array{Dict{String, Any}, 1} = Dict{String, Any}[],
  ProjDir=pwd();
  updatedatafile::Bool=true,
  updateinitfiles::Bool=true
  )

All parameters to compile and run the Jags script are implicitly passed in through the model argument.

The Line2 example shows how to run multiple Jags simulations in parallel. The most simple case, e.g. 4 commands, each with a single chain, can be initialized with an 'inits' like shown below:

inits = [
  Dict("alpha" => 0,"beta" => 0,"tau" => 1,".RNG.name" => "base::Wichmann-Hill"),
  Dict("alpha" => 1,"beta" => 2,"tau" => 1,".RNG.name" => "base::Marsaglia-Multicarry"),
  Dict("alpha" => 3,"beta" => 3,"tau" => 2,".RNG.name" => "base::Super-Duper"),
  Dict("alpha" => 5,"beta" => 2,"tau" => 5,".RNG.name" => "base::Mersenne-Twister")
]

The first entry in the 'inits' array will be passed into the first chain in the first command process, the second entry to the second process, etc. A second chain in the first command would be initialized with the second entry, etc.

To do

More features will be added as requested by users and as time permits. Please file an issue/comment/request.

Note 1: In order to support platforms other than OS X, help is needed to test on such platforms.

jags.jl's People

Contributors

github-actions[bot] avatar goedman avatar hellemo avatar juliatagbot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

jags.jl's Issues

Compat helper not updating packages

Hi Rob,

I noticed that compat helper is not generating pull requests for new packages. CSV, MCMCChains, and Documenter have newer versions. Would it be possible to allow those?

Thanks,

Chris

Chains are not independent

Hi Rob-

I noticed that the chains are not independent. Another potential issue is that the functionality of ncommands and nchains is unclear. Both appear to run n instances of the same chain, but ncommands appears to run them in parallel. Is this a bug or a problem with my setup?

Here is a simple example:

ENV["JAGS_HOME"] = "usr/bin/jags" #your path here
using Jags, StatsPlots, Random, Distributions
#cd(@__DIR__)
ProjDir = pwd()
Random.seed!(3431)

y = rand(Normal(0,1),50)

Model = "
model {
      for (i in 1:length(y)) {
            y[i] ~ dnorm(mu,sigma);
      }
      mu  ~ dnorm(0, 1/sqrt(10));
      sigma  ~ dt(0,1,1) T(0, );
  }
"

monitors = Dict(
  "mu" => true,
  "sigma" => true,
  )

jagsmodel = Jagsmodel(
  name="Gaussian",
  model=Model ,
  monitor=monitors,
  ncommands=4, nchains=1,
  #deviance=true, dic=true, popt=true,
  pdir=ProjDir
  )

println("\nJagsmodel that will be used:")
jagsmodel |> display

data = Dict{String, Any}(
  "y" => y,
)

inits = [
  Dict("mu" => 0.0,"sigma" => 1.0,
  ".RNG.name" => "base::Mersenne-Twister")
]

println("Input observed data dictionary:")
data |> display
println("\nInput initial values dictionary:")
inits |> display
println()
#######################################################################################
#                                 Estimate Parameters
#######################################################################################
sim = jags(jagsmodel, data, inits, ProjDir)
sim = sim[5001:end,:,:]
plot(sim)

problems

Hi goedman,

I found two problems:

  1. If the data[:x] = [1, 2, 3, 4, 5] (one-dimensional data) is replaced with data[:x] = eye(5) (any two-dimensional data), the data cannot be correctly written in line-data.R.
  2. If the data[:x] = [1, 2, 3, 4, NaN] contains NaN, the datum written in line-data.R is still NaN instead of NA. It seems JAGS only handle NA, right?
  3. Could I specify how many chains to run? How about warm up, update, and DIC? It would be good for me in this way to use Jagsmodel(chains = 2, warmup = 2000, update = 5000, dic = true). Hope you will consider it :)
  4. When I run the line example, it reads "could not spawn jags line.jags: no such file or directory (ENOENT)". Is that I didn't correctly set up my JAGS?

Finally, many thanks for your efforts on developing this useful package ๐Ÿ‘

Change update to n_samples

Hi Rob-

I want to propose changing the keyword argument update to n_samples so that it is clearer to the user how to set the total number of samples. Are you amenable to that?

Output Samples as MCMCChains object

Hi Rob-

I would like to use Jags.jl for MCMCBenchmarks and a few other projects. I was wondering if it would be possible to output an MCMCChain object instead of the Mamba object? If it is somewhat straightforward and similar to CmdStan, I might be able to make a PR.

Question about inits

hi, I'm trying to switch my Jags interface from R to Julia, but I'm running into a problem:

I'm trying to translate the following randomly generated inits to Julia code:
R code:
inits <- function() {
list(beta = rnorm(2, 0, 2),
lapse = rbeta(1, 3, 9),
guess = rbeta(1, 1, 1))
}

Julia code (for 4 chains, I haven't figured out how to provide a function that will generate the Dicts):
inits = [@Compat.Dict("alpha" => randn(1),
"beta" => abs(randn(1)),
"lapse" => rand(Beta(3, 20), 1),
"guess" => rand(Beta(1, 1), 1)),
@Compat.Dict("alpha" => randn(1),
"beta" => abs(randn(1)),
"lapse" => rand(Beta(3, 20), 1),
"guess" => rand(Beta(1, 1), 1)),
@Compat.Dict("alpha" => randn(1),
"beta" => abs(randn(1)),
"lapse" => rand(Beta(3, 20), 1),
"guess" => rand(Beta(1, 1), 1)),
@Compat.Dict("alpha" => randn(1),
"beta" => abs(randn(1)),
"lapse" => rand(Beta(3, 20), 1),
"guess" => rand(Beta(1, 1), 1))]
inits = map((x) -> convert(Dict{ASCIIString, Any}, x), inits)

I'm using the Distributions package to generate random numbers from a Beta distribution.
Calling sim = jags(jagsmodel, data, inits, dir) results in this:
"lapse" <- "alpha" <- "guess" <- "beta" <-

Do you have any idea what I'm doing wrong?

I've managed to get all your examples to work. Thanks very much for proving this package, by the way.

regards,
Andrew

Truncated Error Messages

Hi Rob-

I noticed that Jags.jl sometimes truncates the error messages. For example, I had a model with a vector of parameters and inadvertently supplied a single value for initialization. I recieved the following message:

RUNTIME ERROR:
Dimension mismatch in values supplied for mu

I couldn't figure out the error so I ran the model through R, which provide more information and I was able to quickly identify the problem. Here is the full error message:

Error in setParameters(init.values[[i]], i) : RUNTIME ERROR:
Dimension mismatch in values supplied for mu

Here is a MWE:

ENV["JAGS_HOME"] = "usr/bin/jags" #your path here
using Jags, StatsPlots, Random, Distributions
cd(@__DIR__)
ProjDir = pwd()
Random.seed!(3431)

y = rand(Normal(0,1),50)

Model = "
model {
      for (i in 1:length(y)) {
            y[i] ~ dnorm(mu[i],sigma);
      }
      for(i in 1:length(y)){
            mu[i]  ~ dnorm(0, 1/sqrt(10));
        }

      sigma  ~ dt(0,1,1) T(0, );
  }
"

monitors = Dict(
  "mu" => true,
  "sigma" => true,
  )

inits = [
  Dict("mu"=>.0,"sigma"=>1.0)
]


jagsmodel = Jagsmodel(
  name="Gaussian",
  model=Model ,
  monitor=monitors,
  ncommands=4, nchains=1,
  #deviance=true, dic=true, popt=true,
  pdir=ProjDir
  )

println("\nJagsmodel that will be used:")
jagsmodel |> display

data = Dict{String, Any}(
  "y" => y,
)

inits = [
  Dict("mu" => 0.0,"sigma" => 1.0,
  ".RNG.name" => "base::Mersenne-Twister")
]

println("Input observed data dictionary:")
data |> display
println("\nInput initial values dictionary:")
inits |> display
println()
#######################################################################################
#                                 Estimate Parameters
#######################################################################################
sim = jags(jagsmodel, data, inits, ProjDir)
sim = sim[5001:end,:,:]

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.