cmd_stan_rb 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +34 -0
- data/LICENSE +21 -0
- data/README.md +141 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cmd_stan_rb.gemspec +26 -0
- data/demo.ipynb +231 -0
- data/lib/cmd_stan_rb.rb +28 -0
- data/lib/cmd_stan_rb/configuration.rb +11 -0
- data/lib/cmd_stan_rb/version.rb +3 -0
- data/lib/stan.rb +5 -0
- data/lib/stan/examples.rb +23 -0
- data/lib/stan/model.rb +106 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 71cc2e69241ee94c83e321260b0f612c75c1dd9f4b3c13b1f1c71b50d2ebbeff
|
4
|
+
data.tar.gz: f5e04d315c5dfb5d0a7a3a85d950cb0704be044b0fe2d7dd630a6656cd0b2c53
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6e769bb30bb9e0c14fbe344a3576006cb7874ab592cf87989204cbb2f3f3de56499bc6e8bb5bf7e58d3dc44a2896c0d8572151eaf45f6eb382c83431044cb4e2
|
7
|
+
data.tar.gz: dd013cd4b43cdff86449f578ed0ba9027c0a926e73e992475a241aff7e5ccde10cf157e6b612d4a73ee410428748adcd3c7ad28484c0eb84c989de53a07e1fa3
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
cmd_stan_rb (0.2.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.3)
|
10
|
+
rake (12.3.3)
|
11
|
+
rspec (3.9.0)
|
12
|
+
rspec-core (~> 3.9.0)
|
13
|
+
rspec-expectations (~> 3.9.0)
|
14
|
+
rspec-mocks (~> 3.9.0)
|
15
|
+
rspec-core (3.9.1)
|
16
|
+
rspec-support (~> 3.9.1)
|
17
|
+
rspec-expectations (3.9.1)
|
18
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
+
rspec-support (~> 3.9.0)
|
20
|
+
rspec-mocks (3.9.1)
|
21
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
+
rspec-support (~> 3.9.0)
|
23
|
+
rspec-support (3.9.2)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
cmd_stan_rb!
|
30
|
+
rake (~> 12.0)
|
31
|
+
rspec (~> 3.0)
|
32
|
+
|
33
|
+
BUNDLED WITH
|
34
|
+
2.1.3
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2020 Robin Neumann
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# CmdStanRb
|
2
|
+
[![Build Status](https://travis-ci.org/neumanrq/cmd_stan_rb.svg?branch=master)](https://travis-ci.org/neumanrq/cmd_stan_rb)
|
3
|
+
|
4
|
+
Ruby interface to Stan, a library a for performing high performance statistical computations, i.e.
|
5
|
+
full Bayesian Inference.
|
6
|
+
|
7
|
+
<a href="https://mc-stan.org">
|
8
|
+
<img src="https://raw.githubusercontent.com/stan-dev/logos/master/logo.png" width=200 alt="Stan Logo"/>
|
9
|
+
</a>
|
10
|
+
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
gem install cmd_stan_rb
|
15
|
+
|
16
|
+
## Installation for IRuby notebooks
|
17
|
+
|
18
|
+
gem install cmd_stan_rb
|
19
|
+
|
20
|
+
… and then re-register your Ruby kernel by
|
21
|
+
|
22
|
+
iruby register --force
|
23
|
+
|
24
|
+
## Before you can start…
|
25
|
+
|
26
|
+
This project makes use of [CmdStan](https://github.com/stan-dev/cmdstan) to compile models
|
27
|
+
with the Stan compiler and incorporating additional tooling from the Stan ecosystem. There
|
28
|
+
are battle-tested similar projects for other Programming languages are i.e.
|
29
|
+
|
30
|
+
* [CmdStanPy](https://github.com/stan-dev/cmdstanpy)
|
31
|
+
* [CmdStanR](https://github.com/stan-dev/cmdstanr)
|
32
|
+
* [stannis](https://github.com/sakrejda/stannis])
|
33
|
+
|
34
|
+
Because of its dependency to `CmdStan`, you need to get `CmdStan` on board to
|
35
|
+
make `CmdStanRb` work. In the future I'd like to happen this automatically, but
|
36
|
+
for now you need to do this manually.
|
37
|
+
|
38
|
+
The easiest way is cloning the repository to a location of your choice:
|
39
|
+
|
40
|
+
git clone https://github.com/stan-dev/cmdstan
|
41
|
+
|
42
|
+
Then, remember the path to that directory, as we need CmdStanRb to point
|
43
|
+
to that directory by setting a config variable
|
44
|
+
|
45
|
+
## Usage
|
46
|
+
|
47
|
+
|
48
|
+
```Ruby
|
49
|
+
# Tell CmdStanRb where your CmdStan repository is located.
|
50
|
+
# If you skip this step, the default value is "vendor/cmdstan"
|
51
|
+
# as I have cloned it there for my experimentation.
|
52
|
+
CmdStanRb.configuration.cmdstan_dir = "~/path/to/cmdstan"
|
53
|
+
|
54
|
+
# Optional: Tell CmdStanRb where to store the models
|
55
|
+
CmdStanRb.configuration.model_dir = "/Users/robin/cmd_stan_rb-models"
|
56
|
+
|
57
|
+
# Prepare Stan compiler and assistent tooling
|
58
|
+
CmdStanRb.build_binaries
|
59
|
+
|
60
|
+
# Now we're ready to fit some models 👨🔬
|
61
|
+
# First, define your model. The first argument is a name,
|
62
|
+
# which is used to identify your model for re-use later.
|
63
|
+
model =
|
64
|
+
Stan::Model.new("bernoulli-test") do
|
65
|
+
# Stan code goes here as a string
|
66
|
+
%q{
|
67
|
+
data {
|
68
|
+
int<lower=0> N;
|
69
|
+
int<lower=0,upper=1> y[N];
|
70
|
+
}
|
71
|
+
|
72
|
+
parameters {
|
73
|
+
real<lower=0,upper=1> theta;
|
74
|
+
}
|
75
|
+
|
76
|
+
model {
|
77
|
+
theta ~ beta(1,1); // uniform prior on interval 0,1
|
78
|
+
y ~ bernoulli(theta);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
# Translate model
|
84
|
+
model.compile
|
85
|
+
|
86
|
+
# Specify data you've observed
|
87
|
+
model.data = {
|
88
|
+
"N" => 4,
|
89
|
+
"y" => [0,1,0,0]
|
90
|
+
}
|
91
|
+
|
92
|
+
# Run simulation to obtain samples from posterior distribution
|
93
|
+
model.fit
|
94
|
+
|
95
|
+
# Print result
|
96
|
+
puts model.show
|
97
|
+
```
|
98
|
+
|
99
|
+
The latter command shows the simulation result:
|
100
|
+
|
101
|
+
|
102
|
+
Inference for Stan model: b439_model
|
103
|
+
1 chains: each with iter=(1000); warmup=(0); thin=(1); 1000 iterations saved.
|
104
|
+
|
105
|
+
Warmup took (0.0062) seconds, 0.0062 seconds total
|
106
|
+
Sampling took (0.013) seconds, 0.013 seconds total
|
107
|
+
|
108
|
+
Mean MCSE StdDev 5% 50% 95% N_Eff N_Eff/s R_hat
|
109
|
+
lp__ -4.4 3.5e-02 0.77 -5.9 -4.1 -3.8 4.9e+02 3.7e+04 1.0e+00
|
110
|
+
accept_stat__ 0.90 4.4e-03 0.15 0.53 0.97 1.0 1.2e+03 9.2e+04 1.0e+00
|
111
|
+
stepsize__ 1.1 nan 0.00 1.1 1.1 1.1 nan nan nan
|
112
|
+
treedepth__ 1.4 1.5e-02 0.48 1.0 1.0 2.0 1.0e+03 7.6e+04 1.0e+00
|
113
|
+
n_leapfrog__ 2.3 3.2e-02 0.97 1.0 3.0 3.0 9.2e+02 6.8e+04 1.0e+00
|
114
|
+
divergent__ 0.00 nan 0.00 0.00 0.00 0.00 nan nan nan
|
115
|
+
energy__ 4.9 5.2e-02 1.1 3.9 4.6 6.8 4.3e+02 3.2e+04 1.0e+00
|
116
|
+
theta 0.34 9.3e-03 0.18 0.071 0.32 0.64 3.7e+02 2.7e+04 1.0e+00
|
117
|
+
|
118
|
+
Samples were drawn using hmc with nuts.
|
119
|
+
For each parameter, N_Eff is a crude measure of effective sample size,
|
120
|
+
and R_hat is the potential scale reduction factor on split chains (at
|
121
|
+
convergence, R_hat=1).
|
122
|
+
|
123
|
+
### Loading previously compiled models
|
124
|
+
|
125
|
+
CmdStanRb stores models in a diretory you can define by
|
126
|
+
|
127
|
+
```Ruby
|
128
|
+
CmdStanRb.configuration.model_dir = "/Users/robin/cmd_stan_rb-models"
|
129
|
+
```
|
130
|
+
|
131
|
+
If you skip this, CmdStanRb will create a folder in your home directory named `cmd_stan_rb-models` and store
|
132
|
+
the model files and the compiled model binaries there.
|
133
|
+
|
134
|
+
Having compiled a model with name `my-model-01`, you can load it again by
|
135
|
+
|
136
|
+
```Ruby
|
137
|
+
model = Stan::Model.load("my-model-01")
|
138
|
+
```
|
139
|
+
|
140
|
+
Note that once loaded, the model's data has been wiped out, so `model.data` is blank and
|
141
|
+
needs to get set again to fit again.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "cmd_stan_rb"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/cmd_stan_rb.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'lib/cmd_stan_rb/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "cmd_stan_rb"
|
5
|
+
spec.version = CmdStanRb::VERSION
|
6
|
+
spec.authors = ["Robin Neumann\n"]
|
7
|
+
spec.email = ["robin.neumann@posteo.de"]
|
8
|
+
|
9
|
+
spec.summary = %q{Ruby interface to CmdStan, the command line interface to Stan, a high performance statistical computing platform}
|
10
|
+
spec.description = %q{Stan is a state-of-the-art platform for statistical modeling and high-performance statistical computation. Thousands of users rely on Stan for statistical modeling, data analysis, and prediction in the social, biological, and physical sciences, engineering, and business. CmdStanRb offers bindings in Ruby to employ Stan, targeting easing up the integration of Stan and Bayesian Inference into Ruby-powered environments.}
|
11
|
+
spec.homepage = "https://github.com/neumanrq/cmd_stan_rb"
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
13
|
+
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
spec.metadata["source_code_uri"] = "https://github.com/neumanrq/cmd_stan_rb"
|
16
|
+
spec.metadata["changelog_uri"] = "https://github.com/neumanrq/cmd_stan_rb"
|
17
|
+
|
18
|
+
# Specify which files should be added to the gem when it is released.
|
19
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
20
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
end
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
end
|
data/demo.ipynb
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
{
|
2
|
+
"cells": [
|
3
|
+
{
|
4
|
+
"cell_type": "code",
|
5
|
+
"execution_count": 2,
|
6
|
+
"metadata": {},
|
7
|
+
"outputs": [
|
8
|
+
{
|
9
|
+
"data": {
|
10
|
+
"text/plain": [
|
11
|
+
"\"0.1.0\""
|
12
|
+
]
|
13
|
+
},
|
14
|
+
"execution_count": 2,
|
15
|
+
"metadata": {},
|
16
|
+
"output_type": "execute_result"
|
17
|
+
}
|
18
|
+
],
|
19
|
+
"source": [
|
20
|
+
"require \"cmd_stan_rb\"\n",
|
21
|
+
"CmdStanRb::VERSION"
|
22
|
+
]
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"cell_type": "code",
|
26
|
+
"execution_count": 6,
|
27
|
+
"metadata": {},
|
28
|
+
"outputs": [
|
29
|
+
{
|
30
|
+
"name": "stdout",
|
31
|
+
"output_type": "stream",
|
32
|
+
"text": [
|
33
|
+
"\n",
|
34
|
+
" data {\n",
|
35
|
+
" int<lower=0> N;\n",
|
36
|
+
" int<lower=0,upper=1> y[N];\n",
|
37
|
+
" }\n",
|
38
|
+
"\n",
|
39
|
+
" parameters {\n",
|
40
|
+
" real<lower=0,upper=1> theta;\n",
|
41
|
+
" }\n",
|
42
|
+
"\n",
|
43
|
+
" model {\n",
|
44
|
+
" theta ~ beta(1,1); // uniform prior on interval 0,1\n",
|
45
|
+
" y ~ bernoulli(theta);\n",
|
46
|
+
" }\n",
|
47
|
+
" \n"
|
48
|
+
]
|
49
|
+
}
|
50
|
+
],
|
51
|
+
"source": [
|
52
|
+
"puts CmdStanRb::Examples.bernoulli"
|
53
|
+
]
|
54
|
+
},
|
55
|
+
{
|
56
|
+
"cell_type": "markdown",
|
57
|
+
"metadata": {},
|
58
|
+
"source": [
|
59
|
+
"# Given some data and our prior knowledge. What is the value of theta?"
|
60
|
+
]
|
61
|
+
},
|
62
|
+
{
|
63
|
+
"cell_type": "code",
|
64
|
+
"execution_count": 7,
|
65
|
+
"metadata": {},
|
66
|
+
"outputs": [
|
67
|
+
{
|
68
|
+
"data": {
|
69
|
+
"text/plain": [
|
70
|
+
"#<CmdStanRb::Model:0x00007f81aaa9f050 @name=\"research-42\", @model_string=\"\\n data {\\n int<lower=0> N;\\n int<lower=0,upper=1> y[N];\\n }\\n\\n parameters {\\n real<lower=0,upper=1> theta;\\n }\\n\\n model {\\n theta ~ beta(1,1); // uniform prior on interval 0,1\\n y ~ bernoulli(theta);\\n }\\n \", @model_file=#<File:output/research-42/research-42.stan>>"
|
71
|
+
]
|
72
|
+
},
|
73
|
+
"execution_count": 7,
|
74
|
+
"metadata": {},
|
75
|
+
"output_type": "execute_result"
|
76
|
+
}
|
77
|
+
],
|
78
|
+
"source": [
|
79
|
+
"model = CmdStanRb::Model.new(\"research-42\") do \n",
|
80
|
+
" # Write Stan code here\n",
|
81
|
+
" %Q{\n",
|
82
|
+
" data {\n",
|
83
|
+
" int<lower=0> N;\n",
|
84
|
+
" int<lower=0,upper=1> y[N];\n",
|
85
|
+
" }\n",
|
86
|
+
"\n",
|
87
|
+
" parameters {\n",
|
88
|
+
" real<lower=0,upper=1> theta;\n",
|
89
|
+
" }\n",
|
90
|
+
"\n",
|
91
|
+
" model {\n",
|
92
|
+
" theta ~ beta(1,1); // uniform prior on interval 0,1\n",
|
93
|
+
" y ~ bernoulli(theta);\n",
|
94
|
+
" }\n",
|
95
|
+
" } \n",
|
96
|
+
"end"
|
97
|
+
]
|
98
|
+
},
|
99
|
+
{
|
100
|
+
"cell_type": "code",
|
101
|
+
"execution_count": 8,
|
102
|
+
"metadata": {},
|
103
|
+
"outputs": [
|
104
|
+
{
|
105
|
+
"data": {
|
106
|
+
"text/plain": [
|
107
|
+
"{:state=>:ok, :target=>\"../../output/research-42/research-42\", :working_directory=>\"/Users/robin/private_projects/cmd_stan_rb\"}"
|
108
|
+
]
|
109
|
+
},
|
110
|
+
"execution_count": 8,
|
111
|
+
"metadata": {},
|
112
|
+
"output_type": "execute_result"
|
113
|
+
}
|
114
|
+
],
|
115
|
+
"source": [
|
116
|
+
"model.compile"
|
117
|
+
]
|
118
|
+
},
|
119
|
+
{
|
120
|
+
"cell_type": "code",
|
121
|
+
"execution_count": 10,
|
122
|
+
"metadata": {},
|
123
|
+
"outputs": [
|
124
|
+
{
|
125
|
+
"data": {
|
126
|
+
"text/plain": [
|
127
|
+
"{\"N\"=>5, \"y\"=>[1, 0, 1, 1, 0]}"
|
128
|
+
]
|
129
|
+
},
|
130
|
+
"execution_count": 10,
|
131
|
+
"metadata": {},
|
132
|
+
"output_type": "execute_result"
|
133
|
+
}
|
134
|
+
],
|
135
|
+
"source": [
|
136
|
+
"model.data = { \n",
|
137
|
+
" \"N\" => 5, # We toss a coin 5 times \n",
|
138
|
+
" \"y\" => [1, 0, 1, 1, 0] # toss results\n",
|
139
|
+
"}"
|
140
|
+
]
|
141
|
+
},
|
142
|
+
{
|
143
|
+
"cell_type": "code",
|
144
|
+
"execution_count": 11,
|
145
|
+
"metadata": {},
|
146
|
+
"outputs": [
|
147
|
+
{
|
148
|
+
"name": "stdout",
|
149
|
+
"output_type": "stream",
|
150
|
+
"text": [
|
151
|
+
"/Users/robin/private_projects/cmd_stan_rb/output/research-42/research-42 sample data file=output/research-42/research-42.json\n"
|
152
|
+
]
|
153
|
+
},
|
154
|
+
{
|
155
|
+
"data": {
|
156
|
+
"text/plain": [
|
157
|
+
"{:state=>:ok, :data=>{\"N\"=>5, \"y\"=>[1, 0, 1, 1, 0]}}"
|
158
|
+
]
|
159
|
+
},
|
160
|
+
"execution_count": 11,
|
161
|
+
"metadata": {},
|
162
|
+
"output_type": "execute_result"
|
163
|
+
}
|
164
|
+
],
|
165
|
+
"source": [
|
166
|
+
"# Do the simulation magic\n",
|
167
|
+
"model.fit"
|
168
|
+
]
|
169
|
+
},
|
170
|
+
{
|
171
|
+
"cell_type": "code",
|
172
|
+
"execution_count": 12,
|
173
|
+
"metadata": {},
|
174
|
+
"outputs": [
|
175
|
+
{
|
176
|
+
"name": "stdout",
|
177
|
+
"output_type": "stream",
|
178
|
+
"text": [
|
179
|
+
"Inference for Stan model: research_42_model\n",
|
180
|
+
"1 chains: each with iter=(1000); warmup=(0); thin=(1); 1000 iterations saved.\n",
|
181
|
+
"\n",
|
182
|
+
"Warmup took (0.0058) seconds, 0.0058 seconds total\n",
|
183
|
+
"Sampling took (0.013) seconds, 0.013 seconds total\n",
|
184
|
+
"\n",
|
185
|
+
" Mean MCSE StdDev 5% 50% 95% N_Eff N_Eff/s R_hat\n",
|
186
|
+
"lp__ -5.4 4.9e-02 8.7e-01 -7.0 -5.1 -4.8 3.2e+02 2.5e+04 1.0e+00\n",
|
187
|
+
"accept_stat__ 0.91 4.0e-03 1.3e-01 0.63 0.97 1.0 1.1e+03 8.8e+04 1.0e+00\n",
|
188
|
+
"stepsize__ 1.1 nan 4.4e-15 1.1 1.1 1.1 nan nan nan\n",
|
189
|
+
"treedepth__ 1.4 1.5e-02 4.8e-01 1.0 1.0 2.0 1.0e+03 8.1e+04 1.0e+00\n",
|
190
|
+
"n_leapfrog__ 2.3 3.5e-02 9.7e-01 1.0 3.0 3.0 7.7e+02 6.0e+04 1.0e+00\n",
|
191
|
+
"divergent__ 0.00 nan 0.0e+00 0.00 0.00 0.00 nan nan nan\n",
|
192
|
+
"energy__ 5.9 6.2e-02 1.1e+00 4.8 5.5 8.1 3.3e+02 2.6e+04 1.0e+00\n",
|
193
|
+
"theta 0.57 1.1e-02 1.8e-01 0.25 0.58 0.86 2.6e+02 2.1e+04 1.0e+00\n",
|
194
|
+
"\n",
|
195
|
+
"Samples were drawn using hmc with nuts.\n",
|
196
|
+
"For each parameter, N_Eff is a crude measure of effective sample size,\n",
|
197
|
+
"and R_hat is the potential scale reduction factor on split chains (at \n",
|
198
|
+
"convergence, R_hat=1).\n",
|
199
|
+
"\n",
|
200
|
+
"\n"
|
201
|
+
]
|
202
|
+
}
|
203
|
+
],
|
204
|
+
"source": [
|
205
|
+
"puts model.show"
|
206
|
+
]
|
207
|
+
},
|
208
|
+
{
|
209
|
+
"cell_type": "code",
|
210
|
+
"execution_count": null,
|
211
|
+
"metadata": {},
|
212
|
+
"outputs": [],
|
213
|
+
"source": []
|
214
|
+
}
|
215
|
+
],
|
216
|
+
"metadata": {
|
217
|
+
"kernelspec": {
|
218
|
+
"display_name": "Ruby 2.6.5",
|
219
|
+
"language": "ruby",
|
220
|
+
"name": "ruby"
|
221
|
+
},
|
222
|
+
"language_info": {
|
223
|
+
"file_extension": ".rb",
|
224
|
+
"mimetype": "application/x-ruby",
|
225
|
+
"name": "ruby",
|
226
|
+
"version": "2.6.5"
|
227
|
+
}
|
228
|
+
},
|
229
|
+
"nbformat": 4,
|
230
|
+
"nbformat_minor": 2
|
231
|
+
}
|
data/lib/cmd_stan_rb.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "json"
|
2
|
+
require "cmd_stan_rb/version"
|
3
|
+
require "cmd_stan_rb/configuration"
|
4
|
+
require "stan"
|
5
|
+
|
6
|
+
module CmdStanRb
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_accessor :configuration
|
11
|
+
|
12
|
+
def build_binaries
|
13
|
+
system("make -C #{CmdStanRb.configuration.cmdstan_dir} build")
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
system("make -C #{CmdStanRb.configuration.cmdstan_dir} clean-all")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.configuration
|
22
|
+
@configuration ||= CmdStanRb::Configuration.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.configure
|
26
|
+
yield(configuration)
|
27
|
+
end
|
28
|
+
end
|
data/lib/stan.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Stan
|
2
|
+
module Examples
|
3
|
+
class << self
|
4
|
+
def bernoulli
|
5
|
+
%q{
|
6
|
+
data {
|
7
|
+
int<lower=0> N;
|
8
|
+
int<lower=0,upper=1> y[N];
|
9
|
+
}
|
10
|
+
|
11
|
+
parameters {
|
12
|
+
real<lower=0,upper=1> theta;
|
13
|
+
}
|
14
|
+
|
15
|
+
model {
|
16
|
+
theta ~ beta(1,1); // uniform prior on interval 0,1
|
17
|
+
y ~ bernoulli(theta);
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/stan/model.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
module Stan
|
2
|
+
class Model
|
3
|
+
class NoDataGivenError < StandardError ;; end
|
4
|
+
|
5
|
+
attr_accessor :compiled_model_path, :name, :data
|
6
|
+
attr_reader :model_string, :model_file
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def load(name)
|
10
|
+
new(name)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(name, &block)
|
15
|
+
@name = name
|
16
|
+
|
17
|
+
# I'd like to invent a convenient DSL that
|
18
|
+
# is similar to writing "direct" Stan code,
|
19
|
+
# but to do so I need to get a better understanding
|
20
|
+
# of Stan as a language/DSL itself. Until that
|
21
|
+
# I "approximate" my goal by using a block for initialization,
|
22
|
+
# where the block always needs to return the Stan model
|
23
|
+
# as a string. You can load it from a file or write in directly!
|
24
|
+
@model_string = block.call if block_given?
|
25
|
+
|
26
|
+
`mkdir -p #{model_directory}` unless Dir.exists?(model_directory)
|
27
|
+
|
28
|
+
if File.exists?(filename)
|
29
|
+
load_model_file
|
30
|
+
else
|
31
|
+
create_model_file!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Main interactions
|
36
|
+
#
|
37
|
+
#
|
38
|
+
|
39
|
+
def compile
|
40
|
+
system(commands[:compile])
|
41
|
+
{state: :ok, target: target, working_directory: working_directory}
|
42
|
+
end
|
43
|
+
|
44
|
+
def fit
|
45
|
+
raise NoDataGivenError.new("Please specify your model's data before running simulations!") if data.nil?
|
46
|
+
`chmod +x #{CmdStanRb.configuration.model_dir}/#{name}/#{name}`
|
47
|
+
`#{commands[:fit]}`
|
48
|
+
{state: :ok, data: data}
|
49
|
+
end
|
50
|
+
|
51
|
+
def show
|
52
|
+
`#{CmdStanRb.configuration.cmdstan_dir}/bin/stansummary output.csv`
|
53
|
+
end
|
54
|
+
|
55
|
+
def destroy
|
56
|
+
path = "#{CmdStanRb.configuration.model_dir}/#{name}"
|
57
|
+
`rm -rvf #{path}`
|
58
|
+
{state: :ok, destroyed_path: path}
|
59
|
+
end
|
60
|
+
|
61
|
+
def commands
|
62
|
+
{
|
63
|
+
compile: "make -C #{CmdStanRb.configuration.cmdstan_dir} #{target}",
|
64
|
+
fit: "#{CmdStanRb.configuration.model_dir}/#{name}/#{name} sample data file=#{data_file.path}"
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def load_model_file
|
71
|
+
@model_file = File.open(filename, "r")
|
72
|
+
@model_string = @model_file.read
|
73
|
+
@model_file.rewind
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_model_file!
|
77
|
+
@model_file = File.open(filename, "w")
|
78
|
+
@model_file.write(@model_string)
|
79
|
+
@model_file.rewind
|
80
|
+
end
|
81
|
+
|
82
|
+
def data_file
|
83
|
+
file = File.open("#{CmdStanRb.configuration.model_dir}/#{name}/#{name}.json", "w")
|
84
|
+
file.write(data.to_json)
|
85
|
+
file.rewind
|
86
|
+
file
|
87
|
+
end
|
88
|
+
|
89
|
+
def target
|
90
|
+
"#{CmdStanRb.configuration.model_dir}/#{name}/#{name}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def working_directory
|
94
|
+
@wd ||= `pwd`.gsub("\n", "")
|
95
|
+
end
|
96
|
+
|
97
|
+
def model_directory
|
98
|
+
"#{CmdStanRb.configuration.model_dir}/#{name}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def filename
|
102
|
+
"#{CmdStanRb.configuration.model_dir}/#{name}/#{name}.stan"
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cmd_stan_rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- 'Robin Neumann
|
8
|
+
|
9
|
+
'
|
10
|
+
autorequire:
|
11
|
+
bindir: exe
|
12
|
+
cert_chain: []
|
13
|
+
date: 2020-05-10 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
15
|
+
description: Stan is a state-of-the-art platform for statistical modeling and high-performance
|
16
|
+
statistical computation. Thousands of users rely on Stan for statistical modeling,
|
17
|
+
data analysis, and prediction in the social, biological, and physical sciences,
|
18
|
+
engineering, and business. CmdStanRb offers bindings in Ruby to employ Stan, targeting
|
19
|
+
easing up the integration of Stan and Bayesian Inference into Ruby-powered environments.
|
20
|
+
email:
|
21
|
+
- robin.neumann@posteo.de
|
22
|
+
executables: []
|
23
|
+
extensions: []
|
24
|
+
extra_rdoc_files: []
|
25
|
+
files:
|
26
|
+
- ".gitignore"
|
27
|
+
- ".rspec"
|
28
|
+
- ".travis.yml"
|
29
|
+
- CHANGELOG.md
|
30
|
+
- Gemfile
|
31
|
+
- Gemfile.lock
|
32
|
+
- LICENSE
|
33
|
+
- README.md
|
34
|
+
- Rakefile
|
35
|
+
- bin/console
|
36
|
+
- bin/setup
|
37
|
+
- cmd_stan_rb.gemspec
|
38
|
+
- demo.ipynb
|
39
|
+
- lib/cmd_stan_rb.rb
|
40
|
+
- lib/cmd_stan_rb/configuration.rb
|
41
|
+
- lib/cmd_stan_rb/version.rb
|
42
|
+
- lib/stan.rb
|
43
|
+
- lib/stan/examples.rb
|
44
|
+
- lib/stan/model.rb
|
45
|
+
homepage: https://github.com/neumanrq/cmd_stan_rb
|
46
|
+
licenses: []
|
47
|
+
metadata:
|
48
|
+
homepage_uri: https://github.com/neumanrq/cmd_stan_rb
|
49
|
+
source_code_uri: https://github.com/neumanrq/cmd_stan_rb
|
50
|
+
changelog_uri: https://github.com/neumanrq/cmd_stan_rb
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 2.3.0
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubygems_version: 3.0.3
|
67
|
+
signing_key:
|
68
|
+
specification_version: 4
|
69
|
+
summary: Ruby interface to CmdStan, the command line interface to Stan, a high performance
|
70
|
+
statistical computing platform
|
71
|
+
test_files: []
|