Exemple #1
0
 def test_stanc_exception(self):
     model_code = 'parameters {real z;} model {z ~ no_such_distribution();}'
     assertRaisesRegex = self.assertRaisesRegexp if PY2 else self.assertRaisesRegex
     with assertRaisesRegex(ValueError, 'unknown distribution'):
         stanc(model_code=model_code)
     with assertRaisesRegex(ValueError, 'unknown distribution'):
         StanModel(model_code=model_code)
Exemple #2
0
 def test_stanc_exception(self):
     model_code = 'parameters {real z;} model {z ~ no_such_distribution();}'
     assertRaisesRegex = self.assertRaisesRegexp if PY2 else self.assertRaisesRegex
     with assertRaisesRegex(ValueError, 'unknown distribution'):
         stanc(model_code=model_code)
     with assertRaisesRegex(ValueError, 'unknown distribution'):
         StanModel(model_code=model_code)
Exemple #3
0
 def test_stanc_exception(self):
     model_code = 'parameters {real z;} model {z ~ no_such_distribution();}'
     assertRaisesRegex = self.assertRaisesRegexp if PY2 else self.assertRaisesRegex
     # distribution not found error
     with assertRaisesRegex(ValueError, r'Probability function must end in _lpdf or _lpmf\. Found'):
         stanc(model_code=model_code)
     with assertRaisesRegex(ValueError, r'Probability function must end in _lpdf or _lpmf\. Found'):
         StanModel(model_code=model_code)
Exemple #4
0
 def test_stanc_exception(self):
     model_code = 'parameters {real z;} model {z ~ no_such_distribution();}'
     assertRaisesRegex = self.assertRaisesRegexp if PY2 else self.assertRaisesRegex
     # distribution not found error
     with assertRaisesRegex(
             ValueError,
             r'Probability function must end in _lpdf or _lpmf\. Found'):
         stanc(model_code=model_code)
     with assertRaisesRegex(
             ValueError,
             r'Probability function must end in _lpdf or _lpmf\. Found'):
         StanModel(model_code=model_code)
Exemple #5
0
 def test_stanc_exception_semicolon(self):
     model_code = """
     parameters {
         real z
         real y
     }
     model {
         z ~ normal(0, 1);
         y ~ normal(0, 1);}
     """
     assertRaisesRegex = self.assertRaisesRegexp if PY2 else self.assertRaisesRegex
     with assertRaisesRegex(ValueError, 'Failed to parse'):
         stanc(model_code=model_code)
     with assertRaisesRegex(ValueError, 'Failed to parse'):
         StanModel(model_code=model_code)
Exemple #6
0
 def test_stanc_exception_semicolon(self):
     model_code = """
     parameters {
         real z
         real y
     }
     model {
         z ~ normal(0, 1);
         y ~ normal(0, 1);}
     """
     assertRaisesRegex = self.assertRaisesRegexp if PY2 else self.assertRaisesRegex
     with assertRaisesRegex(ValueError, 'Parser expecting: ";"'):
         stanc(model_code=model_code)
     with assertRaisesRegex(ValueError, 'Parser expecting: ";"'):
         StanModel(model_code=model_code)
Exemple #7
0
def test_stanc():
    model_code = 'parameters {real y;} model {y ~ normal(0,1);}'
    result = stanc(model_code=model_code)
    print(result.keys())
    assert result.keys() == {"status", "model_cppname", "cppcode",
                             "model_name", "model_code"}
    assert result['cppcode'].startswith("// Code generated by Stan ")
Exemple #8
0
def build_model(stan_folder, model_name, model_code, verbose_compile):
    code_hash = hashlib.sha1(model_code.encode('utf-8')).hexdigest()
    model_filename = os.path.join(stan_folder, model_name + "_" + code_hash)
    if os.path.exists(model_filename):
        print('STAN: cached model found; loading')
        f = open(model_filename, 'rb')
        sm = pk.load(f)
        f.close()
    else:
        if not os.path.exists(stan_folder):
            os.mkdir(stan_folder)
        print('STAN: no cached model found; building')
        try:
            stanc_ret = pystan.stanc(model_code=model_code)
            stanc_ret['cppcode'] = load_modified_cpp_code(
                stan_folder, model_name, model_code)
            sm = pystan.StanModel(stanc_ret=stanc_ret, verbose=verbose_compile)
        except:
            print(
                'Compiling failed. Did you make sure to modify the weighted_[model_name]_[code_hash].cpp file to handle weighted data?'
            )
            raise

        f = open(model_filename, 'wb')
        pk.dump(sm, f)
        f.close()
    return sm
Exemple #9
0
 def test_stanc(self):
     model_code = 'parameters {real y;} model {y ~ normal(0,1);}'
     result = stanc(model_code=model_code)
     assert sorted(result.keys()) == sorted(
         {"status", "model_cppname", "cppcode", "model_name", "model_code"})
     assert result['cppcode'].startswith("// Code generated by Stan ")
     self.assertEqual(result['status'], 0)
Exemple #10
0
 def test_stanc_2_includes(self):
     model_code = 'parameters {\n#include external1.stan\n#include external2.stan\n} model {\ny ~ normal(0,1);\nz ~ normal(0,1);}'
     testdata_path = os.path.join(os.path.dirname(__file__), 'data', "")
     result = stanc(model_code=model_code, include_paths=[testdata_path])
     desired = sorted({"status", "model_cppname", "cppcode", "model_name", "model_code", "include_paths"})
     self.assertEqual(sorted(result.keys()), desired)
     self.assertEqual(result['status'], 0)
Exemple #11
0
 def test_stanc(self):
     model_code = 'parameters {real y;} model {y ~ normal(0,1);}'
     result = stanc(model_code=model_code)
     desired = sorted({"status", "model_cppname", "cppcode", "model_name", "model_code"})
     self.assertEqual(sorted(result.keys()), desired)
     self.assertTrue(result['cppcode'].startswith("// Code generated by Stan "))
     self.assertEqual(result['status'], 0)
Exemple #12
0
 def test_stanc_2_includes(self):
     model_code = 'parameters {\n#include external1.stan\n#include external2.stan\n} model {\ny ~ normal(0,1);\nz ~ normal(0,1);}'
     testdata_path = os.path.join(os.path.dirname(__file__), 'data', "")
     result = stanc(model_code=model_code, include_paths=[testdata_path])
     desired = sorted({
         "status", "model_cppname", "cppcode", "model_name", "model_code",
         "include_paths"
     })
     self.assertEqual(sorted(result.keys()), desired)
     self.assertEqual(result['status'], 0)
Exemple #13
0
 def test_stanc(self):
     model_code = 'parameters {real y;} model {y ~ normal(0,1);}'
     result = stanc(model_code=model_code)
     desired = sorted({
         "status", "model_cppname", "cppcode", "model_name", "model_code",
         "include_paths"
     })
     self.assertEqual(sorted(result.keys()), desired)
     self.assertTrue(
         result['cppcode'].startswith("// Code generated by Stan "))
     self.assertEqual(result['status'], 0)
Exemple #14
0
def get_model(model_name):
    """Get a StanModel object, checking first in local cache and recompiling
    if necessary."""
    cachefile = os.path.join(config.modelcache, '{}.pkl'.format(model_name))
    # Check if package exists, get model code.
    with _include_path() as incpth, _model_file(model_name) as modelfile:
        model_stanc = pystan.stanc(file=modelfile,
                                   include_paths=[incpth],
                                   model_name=model_name)
    # Check if cached file exists and load it
    model = None
    if os.path.isfile(cachefile):
        try:
            with open(cachefile, 'rb') as f:
                model = pickle.load(f)
        except pickle.UnpicklingError:
            os.remove(cachefile)  # Bad file, remove
    # If cache file did not exist or is from an old model, recompile and cache
    if (model is None) or (model.model_cppcode != model_stanc['cppcode']):
        model = pystan.StanModel(stanc_ret=model_stanc)
        os.makedirs(config.modelcache, exist_ok=True)
        with open(cachefile, 'wb') as f:
            pickle.dump(model, f, protocol=pickle.HIGHEST_PROTOCOL)
    return model
Exemple #15
0
    def test_stan_model_from_file(self):
        bernoulli_model_code = """
            data {
            int<lower=0> N;
            int<lower=0,upper=1> y[N];
            }
            parameters {
            real<lower=0,upper=1> theta;
            }
            model {
            for (n in 1:N)
                y[n] ~ bernoulli(theta);
            }
            """

        bernoulli_data = {'N': 10, 'y': [0, 1, 0, 0, 0, 0, 0, 0, 0, 1]}

        temp_dir = tempfile.mkdtemp()
        temp_fn = os.path.join(temp_dir, 'modelcode.stan')
        with io.open(temp_fn, 'wt') as outfile:
            outfile.write(bernoulli_model_code)

        code = stanc(file=temp_fn)['model_code']
        fit = stan(model_code=code, data=bernoulli_data)
        extr = fit.extract(permuted=True)
        assert -7.9 < np.mean(extr['lp__']) < -7.0
        assert 0.1 < np.mean(extr['theta']) < 0.4
        assert 0.01 < np.var(extr['theta']) < 0.02

        # permuted=False
        extr = fit.extract(permuted=False)
        assert extr.shape == (1000, 4, 2)
        assert 0.1 < np.mean(extr[:, 0, 0]) < 0.4

        # permuted=True
        extr = fit.extract('lp__', permuted=True)
        assert -7.9 < np.mean(extr['lp__']) < -7.0
        extr = fit.extract('theta', permuted=True)
        assert 0.1 < np.mean(extr['theta']) < 0.4
        assert 0.01 < np.var(extr['theta']) < 0.02
        extr = fit.extract('theta', permuted=False)
        assert extr['theta'].shape == (1000, 4)
        assert 0.1 < np.mean(extr['theta'][:, 0]) < 0.4

        fit = stan(file=temp_fn, data=bernoulli_data)
        extr = fit.extract(permuted=True)
        assert -7.9 < np.mean(extr['lp__']) < -7.0
        assert 0.1 < np.mean(extr['theta']) < 0.4
        assert 0.01 < np.var(extr['theta']) < 0.02

        # permuted=False
        extr = fit.extract(permuted=False)
        assert extr.shape == (1000, 4, 2)
        assert 0.1 < np.mean(extr[:, 0, 0]) < 0.4

        # permuted=True
        extr = fit.extract('lp__', permuted=True)
        assert -7.9 < np.mean(extr['lp__']) < -7.0
        extr = fit.extract('theta', permuted=True)
        assert 0.1 < np.mean(extr['theta']) < 0.4
        assert 0.01 < np.var(extr['theta']) < 0.02
        extr = fit.extract('theta', permuted=False)
        assert extr['theta'].shape == (1000, 4)
        assert 0.1 < np.mean(extr['theta'][:, 0]) < 0.4

        os.remove(temp_fn)
Exemple #16
0
 def test_utf8(self):
     model_code = 'parameters {real y;} model {y ~ normal(0,1);}'
     result = stanc(model_code=model_code)
     self.assertEqual(sorted(result.keys()), self.desired)
     self.assertTrue(result['cppcode'].startswith("// Code generated by Stan "))
     self.assertEqual(result['status'], 0)
Exemple #17
0
 def test_utf8_inprogramcode(self):
     model_code = u'parameters {real ö;\n} model {ö ~ normal(0,1);}'
     assertRaisesRegex = self.assertRaisesRegexp if PY2 else self.assertRaisesRegex
     with assertRaisesRegex(ValueError, 'Failed to parse Stan model .*'):
         stanc(model_code=model_code)
Exemple #18
0
def test_stanc_exception():
    model_code = 'parameters {real z;} model {y ~ no_such_distribution();}'
    result = stanc(model_code=model_code)
    assert result['status'] == -1
Exemple #19
0
    def test_stan_model_from_file(self):
        bernoulli_model_code = """
            data {
            int<lower=0> N;
            int<lower=0,upper=1> y[N];
            }
            parameters {
            real<lower=0,upper=1> theta;
            }
            model {
            for (n in 1:N)
                y[n] ~ bernoulli(theta);
            }
            """

        bernoulli_data = {'N': 10, 'y': [0, 1, 0, 0, 0, 0, 0, 0, 0, 1]}

        temp_dir = tempfile.mkdtemp()
        temp_fn = os.path.join(temp_dir, 'modelcode.stan')
        with io.open(temp_fn, 'wt') as outfile:
            outfile.write(bernoulli_model_code)

        code = stanc(file=temp_fn)['model_code']
        fit = stan(model_code=code, data=bernoulli_data)
        extr = fit.extract(permuted=True)
        assert -7.9 < np.mean(extr['lp__']) < -7.0
        assert 0.1 < np.mean(extr['theta']) < 0.4
        assert 0.01 < np.var(extr['theta']) < 0.02

        # permuted=False
        extr = fit.extract(permuted=False)
        assert extr.shape == (1000, 4, 2)
        assert 0.1 < np.mean(extr[:, 0, 0]) < 0.4

        # permuted=True
        extr = fit.extract('lp__', permuted=True)
        assert -7.9 < np.mean(extr['lp__']) < -7.0
        extr = fit.extract('theta', permuted=True)
        assert 0.1 < np.mean(extr['theta']) < 0.4
        assert 0.01 < np.var(extr['theta']) < 0.02
        extr = fit.extract('theta', permuted=False)
        assert extr.shape == (1000, 4, 2)
        assert 0.1 < np.mean(extr[:, 0, 0]) < 0.4

        fit = stan(file=temp_fn, data=bernoulli_data)
        extr = fit.extract(permuted=True)
        assert -7.9 < np.mean(extr['lp__']) < -7.0
        assert 0.1 < np.mean(extr['theta']) < 0.4
        assert 0.01 < np.var(extr['theta']) < 0.02

        # permuted=False
        extr = fit.extract(permuted=False)
        assert extr.shape == (1000, 4, 2)
        assert 0.1 < np.mean(extr[:, 0, 0]) < 0.4

        # permuted=True
        extr = fit.extract('lp__', permuted=True)
        assert -7.9 < np.mean(extr['lp__']) < -7.0
        extr = fit.extract('theta', permuted=True)
        assert 0.1 < np.mean(extr['theta']) < 0.4
        assert 0.01 < np.var(extr['theta']) < 0.02
        extr = fit.extract('theta', permuted=False)
        assert extr.shape == (1000, 4, 2)
        assert 0.1 < np.mean(extr[:, 0, 0]) < 0.4

        os.remove(temp_fn)
Exemple #20
0
def test_stanc_exception():
    model_code = 'parameters {real z;} model {y ~ no_such_distribution();}'
    result = stanc(model_code=model_code)
    assert result['status'] == -1
Exemple #21
0
    def stan(self, line, cell):
        '''
        Allow jupyter notebook cells to output stan code to file and compile it using
        stanc compiler in your path or pystan.stanc if no compiler is found in path.
        Output of compile is stored in "_stan_model object" or  in an <object name>
        specified in -v <object_name> (e.g %%stan -f test.stan -v test)
        %%stan
        - Saves the cell code to a string. The code string can be accessed via
        _stan_model.model_code or <object_name>.model_code
        (if you specify -v <object_name> option)
        %%stan -f <stan_file_name>
        - Saves the cell code to a file specified in <stan_file_name>. The file name
        can also be accessed in _stan_model.model_file or in
        <object_name>.model_file (if you specify -v <object_name> option)
        %%stan -v <object_name> [default: _stan_model]
          stan magic currently outputs a StanMagicOutput object in default _stan_model object.
           -v allows you to specify an alternate compile output object name, so that
           you can use specified object name instead of "_stan_model".
           This is useful if you have multiple %%stan model cells. Cuurently the output object
           exposes 3 attributes (model_name, model_code, model_file)
           [_stan_model | <object_name>].model_file -> Name of stan_file
           [_stan_model | <object_name>].model_name -> Name of stan model [None]
           [_stan_model | <object_name>].model_code -> Model code
        %%stan -f <stan_file_name> --save_only
        - Saves the cell code to a file specified in <stan_file_name>. Skips
        compile step
        %%stan -f <stan_file_name> -o <cpp_file_name>
        - Saves the cell code to a file specified in <stan_file_name> and outputs the
        compiled cpp file to the file name specified by <cpp_file_name>
        %% stan -f <stan_file_name> --allow_undefined
        - passes the --allow_undefined argument to stanc compiler
        %%stan --stanc <stanc_compiler> [default: stanc in $PATH or pystan.stanc]
        - Saves the cell code to a file specified in <stan_file_name> and compiles
        using the stan compiler specified in <stanc_compiler>.
        Optionally, if you specify --stanc pystan, it uses pystan.stanc compiler.
        If you want to use specific stanc compiler
        use this option (e.g %%stan -f binom.stan --stanc "~/cmdstan-2.16.0/bin/stanc")
        '''
        _stan_vars = {}
        __stan_code_str__ = None
        __stan_file__ = None
        __model_name__ = None

        ip = get_ipython()
        args = shlex.split(line.strip())
        options = {
            k: True if v.startswith('-') else v
            for k, v in zip(args, args[1:] + ["--"]) if k.startswith('-')
        }
        source_filename = options.get('-f', None)
        output_filename = options.get('-o', None)
        variable_name = options.get('-v', '_stan_model')
        allow_undefined = options.get('--allow_undefined', False)
        save_only = options.get('--save_only', False)

        if save_only is True:
            if source_filename is None:
                print("Need to specify stan file name (-f) for --save_only")
                return
            else:
                with open(source_filename, 'w') as f:
                    f.write(cell)
                _stan_vars['stan_file'] = source_filename
                print(
                    "File {0} saved..Skipping Compile".format(source_filename))
                return

        compiler_location = options.get('--stanc', check_program('stanc'))
        if not (isinstance(compiler_location, str)):
            print("Pls specify a location for stanccompiler or \
                   specify '--stanc pystan' to use pystan.stanc compiler")
            return
        temp_dir = tempfile.gettempdir()

        if compiler_location is None or compiler_location == 'pystan':
            print("Using pystan.stanc compiler..")
        else:
            print("Using stanc compiler: ", compiler_location)

        # We define the source and executable filenames.
        if source_filename is None:
            temp_name = str(uuid.uuid4())
            source_filename = os.path.join(temp_dir,'anon_' + \
                                temp_name + '.stan')
            output_filename = os.path.join(temp_dir,'anon_' + temp_name + \
                                 '_model.cpp')
            model_name = 'anon_' + temp_name + '_model'
            __stan_code_str__ = cell
            __stan_file__ = None
            __model_name__ = None
        else:
            __stan_file = source_filename
            model_name = source_filename.split('.')
            if len(model_name) > 1:
                model_name = '_'.join(model_name[:-1])
            else:
                model_name = ''.join(model_name)
            model_name = model_name + '_model'
            __stan_code_str__ = cell
            __stan_file__ = source_filename
            __model_name__ = model_name

        with open(source_filename, 'w') as f:
            f.write(cell)
        if compiler_location is None or compiler_location == 'pystan':
            try:
                import pystan as _pystan
                try:
                    out = _pystan.stanc(source_filename, verbose=True)
                except Exception as e:
                    print(e)
                    return
            except ImportError:
                print(
                    "Ensure stan command line (stanc) is installed and in your \
                   PATH or pystan is installed or specify compiler path using --stanc \
                   (e.g. %% stan -f model.stan --stanc ./bin/stanc")
                return

        else:
            compile_str = compiler_location

            if output_filename is not None:
                compile_str = compile_str + ' --o=' + output_filename
            else:
                compile_str = compile_str + ' --o=' + \
                                  os.path.join(temp_dir,str(uuid.uuid4()) +'.cpp')

            if allow_undefined is True:
                compile_str = compile_str + ' --allow_undefined '

            compile_str = compile_str + ' ' + source_filename

            print(compile_str)
            compile_output = ip.getoutput(compile_str)
            print('\n'.join(compile_output))

        _stan_vars[variable_name] = StanMagicOutput(__model_name__,
                                                    __stan_code_str__,
                                                    __stan_file__)
        ip.user_global_ns[variable_name] = _stan_vars[variable_name]
        print_compile_success(variable_name, __stan_file__, __model_name__,
                              __stan_code_str__)
print(" ")
print("Init:")
print(fit.get_inits()[0])
print(fit.get_inits()[1])

print(" ")
print("Adaptation:")
print(fit.get_adaptation_info()[0])
print(fit.get_adaptation_info()[1])

print(" ")
print("Chain 1, Draw 1-3")
print(list(res[:3, 0, :]))

print(" ")
print("Chain 2, Draw 1-3")
print(list(res[:3, 1, :]))

print("\n AS NUMPY")
print("Chain 1, Draw 1-3")
print(res[:3, 0, :])

print(" ")
print("Chain 2, Draw 1-3")
print(res[:3, 1, :])

print(" ")
print(" ### C++ code ###")
print(pystan.stanc("Stan-models/8schools.stan")["cppcode"])
pooled_parameters = """
parameters {
  vector[2] beta;
  real<lower=0> sigma;
} 
"""
pooled_model = """
model {
  y ~ normal(beta[1] + beta[2] * x, sigma);
}
"""
pooled_data_dict = {'N': len(log_cbo),
                    'x': final.controller,
                    'y': log_cbo}

compiled_model = pystan.stanc(model_code=pooled_data + pooled_parameters + pooled_model)
model = pystan.StanModel(stanc_ret=compiled_model)
pooled_fit = model.sampling(data=pooled_data_dict, iter=1000, chains=2)

pooled_sample = pooled_fit.extract(permuted=True)
b0, m0 = pooled_sample['beta'].T.mean(1)
# plt.scatter(final.controller, log_cbo)
import seaborn as sns
ax = sns.violinplot(final.controller, log_cbo)
xvals = np.linspace(-0.2, 1.2)
# here "0" means "not controller" which is a bit different from the original paper
ax.plot(xvals, m0*xvals+b0, 'r--')

# unpooled *change 10 to 120 in production*
unpooled_model = """data {
  int<lower=0> N;