From 7c79014a2e2cc5898bffbc59cb9aff3f10e1d57b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 14:18:25 +0000 Subject: [PATCH] release/v1.1.0rc1: updating version numbers --- cmdstanpy/_version.py | 2 +- docs/_modules/cmdstanpy/cmdstan_args.html | 42 +- docs/_modules/cmdstanpy/compiler_opts.html | 32 +- docs/_modules/cmdstanpy/model.html | 268 +++++++--- docs/_modules/cmdstanpy/stanfit.html | 6 +- docs/_modules/cmdstanpy/stanfit/gq.html | 362 +++++++++---- docs/_modules/cmdstanpy/stanfit/mcmc.html | 89 ++-- docs/_modules/cmdstanpy/stanfit/metadata.html | 18 +- docs/_modules/cmdstanpy/stanfit/mle.html | 34 +- docs/_modules/cmdstanpy/stanfit/runset.html | 42 +- docs/_modules/cmdstanpy/stanfit/vb.html | 40 +- docs/_modules/cmdstanpy/utils.html | 10 +- docs/_modules/cmdstanpy/utils/cmdstan.html | 26 +- docs/_modules/cmdstanpy/utils/json.html | 6 +- docs/_modules/index.html | 4 +- docs/_sources/changes.rst.txt | 18 + docs/_sources/community.rst.txt | 4 + docs/_sources/installation.rst.txt | 2 +- .../Run Generated Quantities.ipynb.txt | 5 +- docs/_sources/users-guide/workflow.rst.txt | 4 +- docs/_static/copybutton.css | 3 +- docs/_static/copybutton.js | 42 +- docs/_static/copybutton_funcs.js | 17 +- docs/_static/documentation_options.js | 2 +- docs/api.html | 503 ++++++++++-------- docs/changes.html | 32 +- docs/community.html | 7 +- docs/genindex.html | 15 +- docs/index.html | 5 +- docs/installation.html | 28 +- docs/internal_api.html | 194 +++---- docs/objects.inv | Bin 5111 -> 5157 bytes docs/py-modindex.html | 4 +- docs/search.html | 4 +- docs/searchindex.js | 2 +- docs/users-guide.html | 4 +- docs/users-guide/examples.html | 4 +- docs/users-guide/examples/MCMC Sampling.html | 11 +- .../Maximum Likelihood Estimation.html | 17 +- .../Maximum Likelihood Estimation.ipynb | 22 +- .../examples/Run Generated Quantities.html | 210 ++++---- .../examples/Run Generated Quantities.ipynb | 319 ++++++----- .../examples/Using External C++.html | 27 +- .../examples/VI as Sampler Inits.html | 71 +-- .../examples/VI as Sampler Inits.ipynb | 174 +++--- .../examples/Variational Inference.html | 63 +-- .../examples/Variational Inference.ipynb | 88 +-- docs/users-guide/hello_world.html | 60 +-- docs/users-guide/outputs.html | 102 ++-- docs/users-guide/overview.html | 4 +- docs/users-guide/workflow.html | 10 +- 51 files changed, 1775 insertions(+), 1283 deletions(-) diff --git a/cmdstanpy/_version.py b/cmdstanpy/_version.py index 182815cd..5a0419af 100644 --- a/cmdstanpy/_version.py +++ b/cmdstanpy/_version.py @@ -1,3 +1,3 @@ """PyPi Version""" -__version__ = '1.0.8' +__version__ = '1.1.0rc1' diff --git a/docs/_modules/cmdstanpy/cmdstan_args.html b/docs/_modules/cmdstanpy/cmdstan_args.html index 218fc744..181c99ad 100644 --- a/docs/_modules/cmdstanpy/cmdstan_args.html +++ b/docs/_modules/cmdstanpy/cmdstan_args.html @@ -5,7 +5,7 @@
-
class Method(Enum):
- """Supported CmdStan method names."""
+ """Supported CmdStan method names."""
SAMPLE = auto()
OPTIMIZE = auto()
@@ -204,7 +204,7 @@ Source code for cmdstanpy.cmdstan_args
[docs]class SamplerArgs:
- """Arguments for the NUTS adaptive sampler."""
+ """Arguments for the NUTS adaptive sampler."""
def __init__(
self,
@@ -224,7 +224,7 @@ Source code for cmdstanpy.cmdstan_args
adapt_step_size: Optional[int] = None,
fixed_param: bool = False,
) -> None:
- """Initialize object."""
+ """Initialize object."""
self.iter_warmup = iter_warmup
self.iter_sampling = iter_sampling
self.save_warmup = save_warmup
@@ -243,7 +243,7 @@ Source code for cmdstanpy.cmdstan_args
self.diagnostic_file = None
[docs] def validate(self, chains: Optional[int]) -> None:
- """
+ """
Check arguments correctness and consistency.
* adaptation and warmup args are consistent
@@ -497,7 +497,7 @@ Source code for cmdstanpy.cmdstan_args
)
[docs] def compose(self, idx: int, cmd: List[str]) -> List[str]:
- """
+ """
Compose CmdStan command for method-specific non-default arguments.
"""
cmd.append('method=sample')
@@ -547,7 +547,7 @@ Source code for cmdstanpy.cmdstan_args
[docs]class OptimizeArgs:
- """Container for arguments for the optimizer."""
+ """Container for arguments for the optimizer."""
OPTIMIZE_ALGOS = {'BFGS', 'bfgs', 'LBFGS', 'lbfgs', 'Newton', 'newton'}
@@ -580,7 +580,7 @@ Source code for cmdstanpy.cmdstan_args
[docs] def validate(
self, chains: Optional[int] = None # pylint: disable=unused-argument
) -> None:
- """
+ """
Check arguments correctness and consistency.
"""
if self.algorithm and self.algorithm not in self.OPTIMIZE_ALGOS:
@@ -678,7 +678,7 @@ Source code for cmdstanpy.cmdstan_args
# pylint: disable=unused-argument
[docs] def compose(self, idx: int, cmd: List[str]) -> List[str]:
- """compose command string for CmdStan for non-default arg values."""
+ """compose command string for CmdStan for non-default arg values."""
cmd.append('method=optimize')
if self.algorithm:
cmd.append('algorithm={}'.format(self.algorithm.lower()))
@@ -705,16 +705,16 @@ Source code for cmdstanpy.cmdstan_args
class GenerateQuantitiesArgs:
- """Arguments needed for generate_quantities method."""
+ """Arguments needed for generate_quantities method."""
def __init__(self, csv_files: List[str]) -> None:
- """Initialize object."""
+ """Initialize object."""
self.sample_csv_files = csv_files
def validate(
self, chains: Optional[int] = None # pylint: disable=unused-argument
) -> None:
- """
+ """
Check arguments correctness and consistency.
* check that sample csv files exist
@@ -726,7 +726,7 @@ Source code for cmdstanpy.cmdstan_args
)
def compose(self, idx: int, cmd: List[str]) -> List[str]:
- """
+ """
Compose CmdStan command for method-specific non-default arguments.
"""
cmd.append('method=generate_quantities')
@@ -735,7 +735,7 @@ Source code for cmdstanpy.cmdstan_args
[docs]class VariationalArgs:
- """Arguments needed for variational method."""
+ """Arguments needed for variational method."""
VARIATIONAL_ALGOS = {'meanfield', 'fullrank'}
@@ -766,7 +766,7 @@ Source code for cmdstanpy.cmdstan_args
[docs] def validate(
self, chains: Optional[int] = None # pylint: disable=unused-argument
) -> None:
- """
+ """
Check arguments correctness and consistency.
"""
if (
@@ -833,7 +833,7 @@ Source code for cmdstanpy.cmdstan_args
# pylint: disable=unused-argument
[docs] def compose(self, idx: int, cmd: List[str]) -> List[str]:
- """
+ """
Compose CmdStan command for method-specific non-default arguments.
"""
cmd.append('method=variational')
@@ -864,7 +864,7 @@ Source code for cmdstanpy.cmdstan_args
[docs]class CmdStanArgs:
- """
+ """
Container for CmdStan command line arguments.
Consists of arguments common to all methods and
and an object which contains the method-specific arguments.
@@ -887,7 +887,7 @@ Source code for cmdstanpy.cmdstan_args
save_profile: bool = False,
refresh: Optional[int] = None,
) -> None:
- """Initialize object."""
+ """Initialize object."""
self.model_name = model_name
self.model_exe = model_exe
self.chain_ids = chain_ids
@@ -912,7 +912,7 @@ Source code for cmdstanpy.cmdstan_args
self.validate()
[docs] def validate(self) -> None:
- """
+ """
Check arguments correctness and consistency.
* input files must exist
@@ -1067,7 +1067,7 @@ Source code for cmdstanpy.cmdstan_args
profile_file: Optional[str] = None,
num_chains: Optional[int] = None
) -> List[str]:
- """
+ """
Compose CmdStan command for non-default arguments.
"""
cmd: List[str] = []
diff --git a/docs/_modules/cmdstanpy/compiler_opts.html b/docs/_modules/cmdstanpy/compiler_opts.html
index a2d8fb30..7b5cc3b6 100644
--- a/docs/_modules/cmdstanpy/compiler_opts.html
+++ b/docs/_modules/cmdstanpy/compiler_opts.html
@@ -5,7 +5,7 @@
- cmdstanpy.compiler_opts — CmdStanPy 1.0.8 documentation
+ cmdstanpy.compiler_opts — CmdStanPy 1.1.0rc1 documentation
@@ -56,7 +56,7 @@
@@ -221,7 +221,7 @@ Source code for cmdstanpy.compiler_opts
[docs]class CompilerOptions:
- """
+ """
User-specified flags for stanc and C++ compiler.
Attributes:
@@ -237,7 +237,7 @@ Source code for cmdstanpy.compiler_opts
cpp_options: Optional[Dict[str, Any]] = None,
user_header: OptionalPath = None,
) -> None:
- """Initialize object."""
+ """Initialize object."""
self._stanc_options = stanc_options if stanc_options is not None else {}
self._cpp_options = cpp_options if cpp_options is not None else {}
self._user_header = str(user_header) if user_header is not None else ''
@@ -248,7 +248,7 @@ Source code for cmdstanpy.compiler_opts
)
def __eq__(self, other: Any) -> bool:
- """Overrides the default implementation"""
+ """Overrides the default implementation"""
if self.is_empty() and other is None: # equiv w/r/t compiler
return True
if not isinstance(other, CompilerOptions):
@@ -260,7 +260,7 @@ Source code for cmdstanpy.compiler_opts
)
[docs] def is_empty(self) -> bool:
- """True if no options specified."""
+ """True if no options specified."""
return (
self._stanc_options == {}
and self._cpp_options == {}
@@ -269,21 +269,21 @@ Source code for cmdstanpy.compiler_opts
@property
def stanc_options(self) -> Dict[str, Union[bool, int, str]]:
- """Stanc compiler options."""
+ """Stanc compiler options."""
return self._stanc_options
@property
def cpp_options(self) -> Dict[str, Union[bool, int]]:
- """C++ compiler options."""
+ """C++ compiler options."""
return self._cpp_options
@property
def user_header(self) -> str:
- """user header."""
+ """user header."""
return self._user_header
[docs] def validate(self) -> None:
- """
+ """
Check compiler args.
Raise ValueError if invalid options are found.
"""
@@ -292,7 +292,7 @@ Source code for cmdstanpy.compiler_opts
self.validate_user_header()
[docs] def validate_stanc_opts(self) -> None:
- """
+ """
Check stanc compiler args and consistency between stanc and C++ options.
Raise ValueError if bad config is found.
"""
@@ -365,7 +365,7 @@ Source code for cmdstanpy.compiler_opts
]
[docs] def validate_cpp_opts(self) -> None:
- """
+ """
Check cpp compiler args.
Raise ValueError if bad config is found.
"""
@@ -382,7 +382,7 @@ Source code for cmdstanpy.compiler_opts
)
[docs] def validate_user_header(self) -> None:
- """
+ """
User header exists.
Raise ValueError if bad config is found.
"""
@@ -420,7 +420,7 @@ Source code for cmdstanpy.compiler_opts
self._cpp_options['USER_HEADER'] = self._user_header
[docs] def add(self, new_opts: "CompilerOptions") -> None: # noqa: disable=Q000
- """Adds options to existing set of compiler options."""
+ """Adds options to existing set of compiler options."""
if new_opts.stanc_options is not None:
if self._stanc_options is None:
self._stanc_options = new_opts.stanc_options
@@ -437,7 +437,7 @@ Source code for cmdstanpy.compiler_opts
self._user_header = new_opts._user_header
[docs] def add_include_path(self, path: str) -> None:
- """Adds include path to existing set of compiler options."""
+ """Adds include path to existing set of compiler options."""
path = os.path.abspath(os.path.expanduser(path))
if 'include-paths' not in self._stanc_options:
self._stanc_options['include-paths'] = [path]
@@ -465,7 +465,7 @@ Source code for cmdstanpy.compiler_opts
return opts
[docs] def compose(self) -> List[str]:
- """Format makefile options as list of strings."""
+ """Format makefile options as list of strings."""
opts = ['STANCFLAGS+=' + flag for flag in self.compose_stanc()]
if self._cpp_options is not None and len(self._cpp_options) > 0:
for key, val in self._cpp_options.items():
diff --git a/docs/_modules/cmdstanpy/model.html b/docs/_modules/cmdstanpy/model.html
index 23884cdb..b968325a 100644
--- a/docs/_modules/cmdstanpy/model.html
+++ b/docs/_modules/cmdstanpy/model.html
@@ -5,7 +5,7 @@
- cmdstanpy.model — CmdStanPy 1.0.8 documentation
+ cmdstanpy.model — CmdStanPy 1.1.0rc1 documentation
@@ -56,7 +56,7 @@
@@ -177,6 +177,7 @@ Source code for cmdstanpy.model
import shutil
import subprocess
import sys
+import tempfile
import threading
from collections import OrderedDict
from concurrent.futures import ThreadPoolExecutor
@@ -184,11 +185,27 @@ Source code for cmdstanpy.model
from io import StringIO
from multiprocessing import cpu_count
from pathlib import Path
-from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Union
+from typing import (
+ Any,
+ Callable,
+ Dict,
+ Iterable,
+ List,
+ Mapping,
+ Optional,
+ TypeVar,
+ Union,
+)
+import pandas as pd
from tqdm.auto import tqdm
-from cmdstanpy import _CMDSTAN_REFRESH, _CMDSTAN_SAMPLING, _CMDSTAN_WARMUP
+from cmdstanpy import (
+ _CMDSTAN_REFRESH,
+ _CMDSTAN_SAMPLING,
+ _CMDSTAN_WARMUP,
+ _TMPDIR,
+)
from cmdstanpy.cmdstan_args import (
CmdStanArgs,
GenerateQuantitiesArgs,
@@ -220,13 +237,14 @@ Source code for cmdstanpy.model
from . import progress as progbar
OptionalPath = Union[str, os.PathLike, None]
+Fit = TypeVar('Fit', CmdStanMCMC, CmdStanMLE, CmdStanVB)
[docs]class CmdStanModel:
# overview, omitted from doc comment in order to improve Sphinx docs.
# A CmdStanModel object encapsulates the Stan program and provides
# methods for compilation and inference.
- """
+ """
The constructor method allows model instantiation given either the
Stan program source file or the compiled executable, or both.
By default, the constructor will compile the Stan program on instantiation
@@ -271,7 +289,7 @@ Source code for cmdstanpy.model
cpp_options: Optional[Dict[str, Any]] = None,
user_header: OptionalPath = None,
) -> None:
- """
+ """
Initialize object given constructor args.
:param model_name: Model name, used for output file names.
@@ -338,9 +356,14 @@ Source code for cmdstanpy.model
if not cmdstan_version_before(
2, 27
): # unknown end of version range
- model_info = self.src_info()
- if 'parameters' in model_info:
- self._fixed_param |= len(model_info['parameters']) == 0
+ try:
+ model_info = self.src_info()
+ if 'parameters' in model_info:
+ self._fixed_param |= len(model_info['parameters']) == 0
+ except ValueError as e:
+ if compile:
+ raise
+ get_logger().debug(e)
if exe_file is not None:
self._exe_file = os.path.realpath(os.path.expanduser(exe_file))
@@ -390,7 +413,7 @@ Source code for cmdstanpy.model
@property
def name(self) -> str:
- """
+ """
Model name used in output filename templates. Default is basename
of Stan program or exe file, unless specified in call to constructor
via argument ``model_name``.
@@ -399,16 +422,16 @@ Source code for cmdstanpy.model
@property
def stan_file(self) -> OptionalPath:
- """Full path to Stan program file."""
+ """Full path to Stan program file."""
return self._stan_file
@property
def exe_file(self) -> OptionalPath:
- """Full path to Stan exe file."""
+ """Full path to Stan exe file."""
return self._exe_file
[docs] def exe_info(self) -> Dict[str, str]:
- """
+ """
Run model with option 'info'. Parse output statements, which all
have form 'key = value' into a Dict.
If exe file compiled with CmdStan < 2.27, option 'info' isn't
@@ -432,38 +455,28 @@ Source code for cmdstanpy.model
return result
[docs] def src_info(self) -> Dict[str, Any]:
- """
+ """
Run stanc with option '--info'.
If stanc is older than 2.27 or if the stan
file cannot be found, returns an empty dictionary.
"""
- result: Dict[str, Any] = {}
- if self.stan_file is None:
- return result
- try:
- cmd = (
- [os.path.join(cmdstan_path(), 'bin', 'stanc' + EXTENSION)]
- # handle include-paths, allow-undefined etc
- + self._compiler_options.compose_stanc()
- + [
- '--info',
- str(self.stan_file),
- ]
- )
- proc = subprocess.run(
- cmd, capture_output=True, text=True, check=True
+ if self.stan_file is None or cmdstan_version_before(2, 27):
+ return {}
+ cmd = (
+ [os.path.join(cmdstan_path(), 'bin', 'stanc' + EXTENSION)]
+ # handle include-paths, allow-undefined etc
+ + self._compiler_options.compose_stanc()
+ + ['--info', str(self.stan_file)]
+ )
+ proc = subprocess.run(cmd, capture_output=True, text=True, check=False)
+ if proc.returncode:
+ raise ValueError(
+ f"Failed to get source info for Stan model "
+ f"'{self._stan_file}'. Console:\n{proc.stderr}"
)
- result = json.loads(proc.stdout)
- return result
- except (
- ValueError,
- RuntimeError,
- OSError,
- subprocess.CalledProcessError,
- ) as e:
- get_logger().debug(e)
- return result
+ result: Dict[str, Any] = json.loads(proc.stdout)
+ return result
[docs] def format(
self,
@@ -473,7 +486,7 @@ Source code for cmdstanpy.model
*,
backup: bool = True,
) -> None:
- """
+ """
Run stanc's auto-formatter on the model code. Either saves directly
back to the file or prints for inspection
@@ -559,21 +572,21 @@ Source code for cmdstanpy.model
@property
def stanc_options(self) -> Dict[str, Union[bool, int, str]]:
- """Options to stanc compilers."""
+ """Options to stanc compilers."""
return self._compiler_options._stanc_options
@property
def cpp_options(self) -> Dict[str, Union[bool, int]]:
- """Options to C++ compilers."""
+ """Options to C++ compilers."""
return self._compiler_options._cpp_options
@property
def user_header(self) -> str:
- """The user header file if it exists, otherwise empty"""
+ """The user header file if it exists, otherwise empty"""
return self._compiler_options._user_header
[docs] def code(self) -> Optional[str]:
- """Return Stan program as a string."""
+ """Return Stan program as a string."""
if not self._stan_file:
raise RuntimeError('Please specify source file')
@@ -595,7 +608,7 @@ Source code for cmdstanpy.model
user_header: OptionalPath = None,
override_options: bool = False,
) -> None:
- """
+ """
Compile the given Stan program file. Translates the Stan code to
C++, then calls the C++ compiler.
@@ -745,7 +758,7 @@ Source code for cmdstanpy.model
time_fmt: str = "%Y%m%d%H%M%S",
timeout: Optional[float] = None,
) -> CmdStanMLE:
- """
+ """
Run the specified CmdStan optimize algorithm to produce a
penalized maximum likelihood estimate of the model parameters.
@@ -932,7 +945,7 @@ Source code for cmdstanpy.model
*,
force_one_process_per_chain: Optional[bool] = None,
) -> CmdStanMCMC:
- """
+ """
Run or more chains of the NUTS-HMC sampler to produce a set of draws
from the posterior distribution of a model conditioned on some data.
@@ -1369,7 +1382,7 @@ Source code for cmdstanpy.model
[docs] def generate_quantities(
self,
data: Union[Mapping[str, Any], str, os.PathLike, None] = None,
- mcmc_sample: Union[CmdStanMCMC, List[str], None] = None,
+ previous_fit: Union[Fit, List[str], None] = None,
seed: Optional[int] = None,
gq_output_dir: OptionalPath = None,
sig_figs: Optional[int] = None,
@@ -1377,14 +1390,18 @@ Source code for cmdstanpy.model
refresh: Optional[int] = None,
time_fmt: str = "%Y%m%d%H%M%S",
timeout: Optional[float] = None,
- ) -> CmdStanGQ:
- """
+ *,
+ mcmc_sample: Union[CmdStanMCMC, List[str], None] = None,
+ ) -> CmdStanGQ[Fit]:
+ """
Run CmdStan's generate_quantities method which runs the generated
quantities block of a model given an existing sample.
- This function takes a :class:`CmdStanMCMC` object and the dataset used
- to generate that sample and calls to the CmdStan ``generate_quantities``
- method to generate additional quantities of interest.
+ This function takes one of the Stan fit objects
+ :class:`CmdStanMCMC`, :class:`CmdStanMLE`, or :class:`CmdStanVB`
+ and the data required for the model and calls to the CmdStan
+ ``generate_quantities`` method to generate additional quantities of
+ interest.
The :class:`CmdStanGQ` object records the command, the return code,
and the paths to the generate method output CSV and console files.
@@ -1403,9 +1420,10 @@ Source code for cmdstanpy.model
either as a dictionary with entries matching the data variables,
or as the path of a data file in JSON or Rdump format.
- :param mcmc_sample: Can be either a :class:`CmdStanMCMC` object returned
- by the :meth:`sample` method or a list of stan-csv files generated
- by fitting the model to the data using any Stan interface.
+ :param previous_fit: Can be either a :class:`CmdStanMCMC`,
+ :class:`CmdStanMLE`, or :class:`CmdStanVB` or a list of
+ stan-csv files generated by fitting the model to the data
+ using any Stan interface.
:param seed: The seed for random number generator. Must be an integer
between 0 and 2^32 - 1. If unspecified,
@@ -1439,39 +1457,64 @@ Source code for cmdstanpy.model
:return: CmdStanGQ object
"""
- if isinstance(mcmc_sample, CmdStanMCMC):
- mcmc_fit = mcmc_sample
- sample_csv_files = mcmc_sample.runset.csv_files
- elif isinstance(mcmc_sample, list):
- if len(mcmc_sample) < 1:
+ if mcmc_sample is not None:
+ if previous_fit:
+ raise ValueError(
+ "Cannot supply both 'previous_fit' and "
+ "deprecated argument 'mcmc_sample'"
+ )
+ get_logger().warning(
+ "Argument name `mcmc_sample` is deprecated, please "
+ "rename to `previous_fit`."
+ )
+
+ previous_fit = mcmc_sample # type: ignore
+
+ if isinstance(previous_fit, (CmdStanMCMC, CmdStanMLE, CmdStanVB)):
+ fit_object = previous_fit
+ fit_csv_files = previous_fit.runset.csv_files
+ elif isinstance(previous_fit, list):
+ if len(previous_fit) < 1:
raise ValueError(
'Expecting list of Stan CSV files, found empty list'
)
try:
- sample_csv_files = mcmc_sample
- sample_fit = from_csv(sample_csv_files)
- mcmc_fit = sample_fit # type: ignore
+ fit_csv_files = previous_fit
+ fit_object = from_csv(fit_csv_files) # type: ignore
except ValueError as e:
raise ValueError(
'Invalid sample from Stan CSV files, error:\n\t{}\n\t'
' while processing files\n\t{}'.format(
- repr(e), '\n\t'.join(mcmc_sample)
+ repr(e), '\n\t'.join(previous_fit)
)
) from e
else:
raise ValueError(
- 'MCMC sample must be either CmdStanMCMC object'
- ' or list of paths to sample Stan CSV files.'
- )
- chains = mcmc_fit.chains
- chain_ids = mcmc_fit.chain_ids
- if mcmc_fit.metadata.cmdstan_config['save_warmup']:
- get_logger().warning(
- 'Sample contains saved warmup draws which will be used '
- 'to generate additional quantities of interest.'
+ 'Previous fit must be either CmdStanPy fit object'
+ ' or list of paths to Stan CSV files.'
)
+ if isinstance(fit_object, CmdStanMCMC):
+ chains = fit_object.chains
+ chain_ids = fit_object.chain_ids
+ if fit_object._save_warmup:
+ get_logger().warning(
+ 'Sample contains saved warmup draws which will be used '
+ 'to generate additional quantities of interest.'
+ )
+ elif isinstance(fit_object, CmdStanMLE):
+ chains = 1
+ chain_ids = [1]
+ if fit_object._save_iterations:
+ get_logger().warning(
+ 'MLE contains saved iterations which will be used '
+ 'to generate additional quantities of interest.'
+ )
+ else: # isinstance(fit_object, CmdStanVB)
+ chains = 1
+ chain_ids = [1]
+
generate_quantities_args = GenerateQuantitiesArgs(
- csv_files=sample_csv_files
+ csv_files=fit_csv_files
)
generate_quantities_args.validate(chains)
with MaybeDictToFilePath(data, None) as (_data, _inits):
@@ -1512,7 +1555,7 @@ Source code for cmdstanpy.model
+ ' output is unclear!'
)
raise RuntimeError(msg)
- quantities = CmdStanGQ(runset=runset, mcmc_sample=mcmc_fit)
+ quantities = CmdStanGQ(runset=runset, previous_fit=fit_object)
return quantities
[docs] def variational(
@@ -1540,7 +1583,7 @@ Source code for cmdstanpy.model
time_fmt: str = "%Y%m%d%H%M%S",
timeout: Optional[float] = None,
) -> CmdStanVB:
- """
+ """
Run CmdStan's variational inference algorithm to approximate
the posterior distribution of the model conditioned on the data.
@@ -1717,6 +1760,73 @@ Source code for cmdstanpy.model
vb = CmdStanVB(runset)
return vb
+[docs] def log_prob(
+ self,
+ params: Union[Dict[str, Any], str, os.PathLike],
+ data: Union[Mapping[str, Any], str, os.PathLike, None] = None,
+ ) -> pd.DataFrame:
+ """
+ Calculate the log probability and gradient at the given parameter
+ values.
+
+ .. note:: This function is **NOT** an efficient way to evaluate the log
+ density of the model. It should be used for diagnostics ONLY.
+ Please, do not use this for other purposes such as testing new
+ sampling algorithms!
+
+ :param params: Values for all parameters in the model, specified
+ either as a dictionary with entries matching the parameter
+ variables, or as the path of a data file in JSON or Rdump format.
+
+ These should be given on the constrained (natural) scale.
+
+ :param data: Values for all data variables in the model, specified
+ either as a dictionary with entries matching the data variables,
+ or as the path of a data file in JSON or Rdump format.
+
+ :return: A pandas.DataFrame containing columns "lp_" and additional
+ columns for the gradient values. These gradients will be for the
+ unconstrained parameters of the model.
+ """
+
+ if cmdstan_version_before(2, 31, self.exe_info()):
+ raise ValueError(
+ "Method 'log_prob' not available for CmdStan versions "
+ "before 2.31"
+ )
+ with MaybeDictToFilePath(data, params) as (_data, _params):
+ cmd = [
+ str(self.exe_file),
+ "log_prob",
+ f"constrained_params={_params}",
+ ]
+ if _data is not None:
+ cmd += ["data", f"file={_data}"]
+
+ output_dir = tempfile.mkdtemp(prefix=self.name, dir=_TMPDIR)
+
+ output = os.path.join(output_dir, "output.csv")
+ cmd += ["output", f"file={output}"]
+
+ get_logger().debug("Cmd: %s", str(cmd))
+
+ proc = subprocess.run(
+ cmd, capture_output=True, check=False, text=True
+ )
+ if proc.returncode:
+ get_logger().error(
+ "'log_prob' command failed!\nstdout:%s\nstderr:%s",
+ proc.stdout,
+ proc.stderr,
+ )
+ raise RuntimeError(
+ "Method 'log_prob' failed with return code "
+ + str(proc.returncode)
+ )
+
+ result = pd.read_csv(output, comment="#")
+ return result
+
def _run_cmdstan(
self,
runset: RunSet,
@@ -1726,7 +1836,7 @@ Source code for cmdstanpy.model
progress_hook: Optional[Callable[[str, int], None]] = None,
timeout: Optional[float] = None,
) -> None:
- """
+ """
Helper function which encapsulates call to CmdStan.
Uses subprocess POpen object to run the process.
Records stdout, stderr messages, and process returncode.
@@ -1825,7 +1935,7 @@ Source code for cmdstanpy.model
chain_ids: List[int],
total: int,
) -> Optional[Callable[[str, int], None]]:
- """
+ """
Sets up tqdm callback for CmdStan sampler console msgs.
CmdStan progress messages start with "Iteration", for single chain
process, "Chain [id] Iteration" for multi-chain processing.
diff --git a/docs/_modules/cmdstanpy/stanfit.html b/docs/_modules/cmdstanpy/stanfit.html
index dc541799..d0231d45 100644
--- a/docs/_modules/cmdstanpy/stanfit.html
+++ b/docs/_modules/cmdstanpy/stanfit.html
@@ -5,7 +5,7 @@
- cmdstanpy.stanfit — CmdStanPy 1.0.8 documentation
+ cmdstanpy.stanfit — CmdStanPy 1.1.0rc1 documentation
@@ -56,7 +56,7 @@
@@ -202,7 +202,7 @@ Source code for cmdstanpy.stanfit
path: Union[str, List[str], os.PathLike, None] = None,
method: Optional[str] = None,
) -> Union[CmdStanMCMC, CmdStanMLE, CmdStanVB, None]:
- """
+ """
Instantiate a CmdStan object from a the Stan CSV files from a CmdStan run.
CSV files are specified from either a list of Stan CSV files or a single
filepath which can be either a directory name, a Stan CSV filename, or
diff --git a/docs/_modules/cmdstanpy/stanfit/gq.html b/docs/_modules/cmdstanpy/stanfit/gq.html
index 5de8cfdf..d4f3c4c4 100644
--- a/docs/_modules/cmdstanpy/stanfit/gq.html
+++ b/docs/_modules/cmdstanpy/stanfit/gq.html
@@ -5,7 +5,7 @@
- cmdstanpy.stanfit.gq — CmdStanPy 1.0.8 documentation
+ cmdstanpy.stanfit.gq — CmdStanPy 1.1.0rc1 documentation
@@ -56,7 +56,7 @@
@@ -176,12 +176,16 @@ Source code for cmdstanpy.stanfit.gq
from typing import (
Any,
Dict,
+ Generic,
Hashable,
List,
MutableMapping,
+ NoReturn,
Optional,
Tuple,
+ TypeVar,
Union,
+ overload,
)
import numpy as np
@@ -194,6 +198,7 @@ Source code for cmdstanpy.stanfit.gq
except ImportError:
XARRAY_INSTALLED = False
+
from cmdstanpy.cmdstan_args import Method
from cmdstanpy.utils import (
BaseType,
@@ -205,11 +210,15 @@ Source code for cmdstanpy.stanfit.gq
from .mcmc import CmdStanMCMC
from .metadata import InferenceMetadata
+from .mle import CmdStanMLE
from .runset import RunSet
+from .vb import CmdStanVB
+
+Fit = TypeVar('Fit', CmdStanMCMC, CmdStanMLE, CmdStanVB)
-[docs]class CmdStanGQ:
- """
+[docs]class CmdStanGQ(Generic[Fit]):
+ """
Container for outputs from CmdStan generate_quantities run.
Created by :meth:`CmdStanModel.generate_quantities`.
"""
@@ -217,16 +226,18 @@ Source code for cmdstanpy.stanfit.gq
def __init__(
self,
runset: RunSet,
- mcmc_sample: CmdStanMCMC,
+ previous_fit: Fit,
) -> None:
- """Initialize object."""
+ """Initialize object."""
if not runset.method == Method.GENERATE_QUANTITIES:
raise ValueError(
'Wrong runset method, expecting generate_quantities runset, '
'found method {}'.format(runset.method)
)
self.runset = runset
- self.mcmc_sample = mcmc_sample
+
+ self.previous_fit: Fit = previous_fit
+
self._draws: np.ndarray = np.array(())
config = self._validate_csv_files()
self._metadata = InferenceMetadata(config)
@@ -245,7 +256,7 @@ Source code for cmdstanpy.stanfit.gq
return repr
def __getattr__(self, attr: str) -> np.ndarray:
- """Synonymous with ``fit.stan_variable(attr)"""
+ """Synonymous with ``fit.stan_variable(attr)"""
if attr.startswith("_"):
raise AttributeError(f"Unknown variable name {attr}")
try:
@@ -254,8 +265,16 @@ Source code for cmdstanpy.stanfit.gq
# pylint: disable=raise-missing-from
raise AttributeError(*e.args)
+ def __getstate__(self) -> dict:
+ # This function returns the mapping of objects to serialize with pickle.
+ # See https://docs.python.org/3/library/pickle.html#object.__getstate__
+ # for details. We call _assemble_generated_quantities to ensure
+ # the data are loaded prior to serialization.
+ self._assemble_generated_quantities()
+ return self.__dict__
+
def _validate_csv_files(self) -> Dict[str, Any]:
- """
+ """
Checks that Stan CSV output files for all chains are consistent
and returns dict containing config and column names.
@@ -299,24 +318,24 @@ Source code for cmdstanpy.stanfit.gq
@property
def chains(self) -> int:
- """Number of chains."""
+ """Number of chains."""
return self.runset.chains
@property
def chain_ids(self) -> List[int]:
- """Chain ids."""
+ """Chain ids."""
return self.runset.chain_ids
@property
def column_names(self) -> Tuple[str, ...]:
- """
+ """
Names of generated quantities of interest.
"""
return self._metadata.cmdstan_config['column_names'] # type: ignore
@property
def metadata(self) -> InferenceMetadata:
- """
+ """
Returns object which contains CmdStan configuration as well as
information about the names and structure of the inference method
and model output variables.
@@ -330,7 +349,7 @@ Source code for cmdstanpy.stanfit.gq
concat_chains: bool = False,
inc_sample: bool = False,
) -> np.ndarray:
- """
+ """
Returns a numpy.ndarray over the generated quantities draws from
all chains which is stored column major so that the values
for a parameter are contiguous in memory, likewise all draws from
@@ -348,7 +367,7 @@ Source code for cmdstanpy.stanfit.gq
:param concat_chains: When ``True`` return a 2D array flattening all
all draws from all chains. Default value is ``False``.
- :param inc_sample: When ``True`` include all columns in the mcmc_sample
+ :param inc_sample: When ``True`` include all columns in the previous_fit
draws array as well, excepting columns for variables already present
in the generated quantities drawset. Default value is ``False``.
@@ -358,18 +377,32 @@ Source code for cmdstanpy.stanfit.gq
CmdStanGQ.draws_xr
CmdStanMCMC.draws
"""
- if self._draws.shape == (0,):
- self._assemble_generated_quantities()
- if (
- inc_warmup
- and not self.mcmc_sample.metadata.cmdstan_config['save_warmup']
- ):
- get_logger().warning(
- "Sample doesn't contain draws from warmup iterations,"
- ' rerun sampler with "save_warmup=True".'
- )
+ self._assemble_generated_quantities()
+ if inc_warmup:
+ if (
+ isinstance(self.previous_fit, CmdStanMCMC)
+ and not self.previous_fit._save_warmup
+ ):
+ get_logger().warning(
+ "Sample doesn't contain draws from warmup iterations,"
+ ' rerun sampler with "save_warmup=True".'
+ )
+ elif (
+ isinstance(self.previous_fit, CmdStanMLE)
+ and not self.previous_fit._save_iterations
+ ):
+ get_logger().warning(
+ "MLE doesn't contain draws from pre-convergence iterations,"
+ ' rerun optimization with "save_iterations=True".'
+ )
+ elif isinstance(self.previous_fit, CmdStanVB):
+ get_logger().warning(
+ "Variational fit doesn't make sense with argument "
+ '"inc_warmup=True"'
+ )
+
if inc_sample:
- cols_1 = self.mcmc_sample.column_names
+ cols_1 = self.previous_fit.column_names
cols_2 = self.column_names
dups = [
item
@@ -378,20 +411,15 @@ Source code for cmdstanpy.stanfit.gq
]
drop_cols: List[int] = []
for dup in dups:
- drop_cols.extend(self.mcmc_sample.metadata.stan_vars_cols[dup])
-
- start_idx = 0
- if (
- not inc_warmup
- and self.mcmc_sample.metadata.cmdstan_config['save_warmup']
- ):
- start_idx = self.mcmc_sample.num_draws_warmup
+ drop_cols.extend(self.previous_fit.metadata.stan_vars_cols[dup])
+ start_idx, _ = self._draws_start(inc_warmup)
+ previous_draws = self._previous_draws(True)
if concat_chains and inc_sample:
return flatten_chains(
np.dstack(
(
- np.delete(self.mcmc_sample.draws(), drop_cols, axis=1),
+ np.delete(previous_draws, drop_cols, axis=1),
self._draws,
)
)[start_idx:, :, :]
@@ -401,7 +429,7 @@ Source code for cmdstanpy.stanfit.gq
if inc_sample:
return np.dstack(
(
- np.delete(self.mcmc_sample.draws(), drop_cols, axis=1),
+ np.delete(previous_draws, drop_cols, axis=1),
self._draws,
)
)[start_idx:, :, :]
@@ -413,7 +441,7 @@ Source code for cmdstanpy.stanfit.gq
inc_warmup: bool = False,
inc_sample: bool = False,
) -> pd.DataFrame:
- """
+ """
Returns the generated quantities draws as a pandas DataFrame.
Flattens all chains into single column. Container variables
(array, vector, matrix) will span multiple columns, one column
@@ -437,17 +465,33 @@ Source code for cmdstanpy.stanfit.gq
vars_list = [vars]
else:
vars_list = vars
+
vars_list = list(dict.fromkeys(vars_list))
- if (
- inc_warmup
- and not self.mcmc_sample.metadata.cmdstan_config['save_warmup']
- ):
- get_logger().warning(
- 'Draws from warmup iterations not available,'
- ' must run sampler with "save_warmup=True".'
- )
- if self._draws.shape == (0,):
- self._assemble_generated_quantities()
+
+ if inc_warmup:
+ if (
+ isinstance(self.previous_fit, CmdStanMCMC)
+ and not self.previous_fit._save_warmup
+ ):
+ get_logger().warning(
+ "Sample doesn't contain draws from warmup iterations,"
+ ' rerun sampler with "save_warmup=True".'
+ )
+ elif (
+ isinstance(self.previous_fit, CmdStanMLE)
+ and not self.previous_fit._save_iterations
+ ):
+ get_logger().warning(
+ "MLE doesn't contain draws from pre-convergence iterations,"
+ ' rerun optimization with "save_iterations=True".'
+ )
+ elif isinstance(self.previous_fit, CmdStanVB):
+ get_logger().warning(
+ "Variational fit doesn't make sense with argument "
+ '"inc_warmup=True"'
+ )
+
+ self._assemble_generated_quantities()
gq_cols = []
mcmc_vars = []
@@ -458,7 +502,7 @@ Source code for cmdstanpy.stanfit.gq
gq_cols.append(self.column_names[idx])
elif (
inc_sample
- and var in self.mcmc_sample.metadata.stan_vars_cols
+ and var in self.previous_fit.metadata.stan_vars_cols
):
mcmc_vars.append(var)
else:
@@ -467,13 +511,13 @@ Source code for cmdstanpy.stanfit.gq
gq_cols = list(self.column_names)
vars_list = gq_cols
+ previous_draws_pd = self._previous_draws_pd(mcmc_vars, inc_warmup)
+
if inc_sample and mcmc_vars:
if gq_cols:
return pd.concat(
[
- self.mcmc_sample.draws_pd(
- vars=mcmc_vars, inc_warmup=inc_warmup
- ).reset_index(drop=True),
+ previous_draws_pd,
pd.DataFrame(
data=flatten_chains(
self.draws(inc_warmup=inc_warmup)
@@ -484,11 +528,9 @@ Source code for cmdstanpy.stanfit.gq
axis='columns',
)[vars_list]
else:
- return self.mcmc_sample.draws_pd(
- vars=mcmc_vars, inc_warmup=inc_warmup
- )
+ return previous_draws_pd
elif inc_sample and vars is None:
- cols_1 = self.mcmc_sample.column_names
+ cols_1 = self.previous_fit.column_names
cols_2 = self.column_names
dups = [
item
@@ -497,16 +539,13 @@ Source code for cmdstanpy.stanfit.gq
]
return pd.concat(
[
- self.mcmc_sample.draws_pd(inc_warmup=inc_warmup)
- .drop(columns=dups)
- .reset_index(drop=True),
+ previous_draws_pd.drop(columns=dups).reset_index(drop=True),
pd.DataFrame(
data=flatten_chains(self.draws(inc_warmup=inc_warmup)),
columns=self.column_names,
),
],
- axis='columns',
- ignore_index=True,
+ axis=1,
)
elif gq_cols:
return pd.DataFrame(
@@ -519,15 +558,36 @@ Source code for cmdstanpy.stanfit.gq
columns=self.column_names,
)
+ @overload
+ def draws_xr(
+ self: Union["CmdStanGQ[CmdStanMLE]", "CmdStanGQ[CmdStanVB]"],
+ vars: Union[str, List[str], None] = None,
+ inc_warmup: bool = False,
+ inc_sample: bool = False,
+ ) -> NoReturn:
+ ...
+
+ @overload
+ def draws_xr(
+ self: "CmdStanGQ[CmdStanMCMC]",
+ vars: Union[str, List[str], None] = None,
+ inc_warmup: bool = False,
+ inc_sample: bool = False,
+ ) -> "xr.Dataset":
+ ...
+
[docs] def draws_xr(
self,
vars: Union[str, List[str], None] = None,
inc_warmup: bool = False,
inc_sample: bool = False,
) -> "xr.Dataset":
- """
+ """
Returns the generated quantities draws as a xarray Dataset.
+ This method can only be called when the underlying fit was made
+ through sampling, it cannot be used on MLE or VB outputs.
+
:param vars: optional list of variable names.
:param inc_warmup: When ``True`` and the warmup draws are present in
@@ -544,6 +604,11 @@ Source code for cmdstanpy.stanfit.gq
raise RuntimeError(
'Package "xarray" is not installed, cannot produce draws array.'
)
+ if not isinstance(self.previous_fit, CmdStanMCMC):
+ raise RuntimeError(
+ 'Method "draws_xr" is only available when '
+ 'original fit is done via Sampling.'
+ )
mcmc_vars_list = []
dup_vars = []
if vars is not None:
@@ -554,7 +619,7 @@ Source code for cmdstanpy.stanfit.gq
for var in vars_list:
if var not in self.metadata.stan_vars_cols:
if inc_sample and (
- var in self.mcmc_sample.metadata.stan_vars_cols
+ var in self.previous_fit.metadata.stan_vars_cols
):
mcmc_vars_list.append(var)
dup_vars.append(var)
@@ -563,17 +628,16 @@ Source code for cmdstanpy.stanfit.gq
else:
vars_list = list(self.metadata.stan_vars_cols.keys())
if inc_sample:
- for var in self.mcmc_sample.metadata.stan_vars_cols.keys():
+ for var in self.previous_fit.metadata.stan_vars_cols.keys():
if var not in vars_list and var not in mcmc_vars_list:
mcmc_vars_list.append(var)
for var in dup_vars:
vars_list.remove(var)
- if self._draws.shape == (0,):
- self._assemble_generated_quantities()
+ self._assemble_generated_quantities()
- num_draws = self.mcmc_sample.num_draws_sampling
- sample_config = self.mcmc_sample.metadata.cmdstan_config
+ num_draws = self.previous_fit.num_draws_sampling
+ sample_config = self.previous_fit.metadata.cmdstan_config
attrs: MutableMapping[Hashable, Any] = {
"stan_version": f"{sample_config['stan_version_major']}."
f"{sample_config['stan_version_minor']}."
@@ -582,8 +646,8 @@ Source code for cmdstanpy.stanfit.gq
"num_draws_sampling": num_draws,
}
if inc_warmup and sample_config['save_warmup']:
- num_draws += self.mcmc_sample.num_draws_warmup
- attrs["num_draws_warmup"] = self.mcmc_sample.num_draws_warmup
+ num_draws += self.previous_fit.num_draws_warmup
+ attrs["num_draws_warmup"] = self.previous_fit.num_draws_warmup
data: MutableMapping[Hashable, Any] = {}
coordinates: MutableMapping[Hashable, Any] = {
@@ -606,11 +670,11 @@ Source code for cmdstanpy.stanfit.gq
build_xarray_data(
data,
var,
- self.mcmc_sample.metadata.stan_vars_dims[var],
- self.mcmc_sample.metadata.stan_vars_cols[var],
+ self.previous_fit.metadata.stan_vars_dims[var],
+ self.previous_fit.metadata.stan_vars_cols[var],
0,
- self.mcmc_sample.draws(inc_warmup=inc_warmup),
- self.mcmc_sample._metadata.stan_vars_types[var],
+ self.previous_fit.draws(inc_warmup=inc_warmup),
+ self.previous_fit._metadata.stan_vars_types[var],
)
return xr.Dataset(data, coords=coordinates, attrs=attrs).transpose(
@@ -622,7 +686,7 @@ Source code for cmdstanpy.stanfit.gq
var: str,
inc_warmup: bool = False,
) -> np.ndarray:
- """
+ """
Return a numpy.ndarray which contains the set of draws
for the named Stan program variable. Flattens the chains,
leaving the draws in chain order. The first array dimension,
@@ -663,7 +727,7 @@ Source code for cmdstanpy.stanfit.gq
CmdStanMLE.stan_variable
CmdStanVB.stan_variable
"""
- model_var_names = self.mcmc_sample.metadata.stan_vars_cols.keys()
+ model_var_names = self.previous_fit.metadata.stan_vars_cols.keys()
gq_var_names = self.metadata.stan_vars_cols.keys()
if not (var in model_var_names or var in gq_var_names):
raise ValueError(
@@ -672,39 +736,43 @@ Source code for cmdstanpy.stanfit.gq
+ ", ".join(model_var_names | gq_var_names)
)
if var not in gq_var_names:
- return self.mcmc_sample.stan_variable(var, inc_warmup=inc_warmup)
- else: # is gq variable
- if self._draws.shape == (0,):
- self._assemble_generated_quantities()
- draw1 = 0
- if (
- not inc_warmup
- and self.mcmc_sample.metadata.cmdstan_config['save_warmup']
- ):
- draw1 = self.mcmc_sample.num_draws_warmup
- num_draws = self.mcmc_sample.num_draws_sampling
- if (
- inc_warmup
- and self.mcmc_sample.metadata.cmdstan_config['save_warmup']
- ):
- num_draws += self.mcmc_sample.num_draws_warmup
- dims = [num_draws * self.chains]
- col_idxs = self._metadata.stan_vars_cols[var]
- if len(col_idxs) > 0:
- dims.extend(self._metadata.stan_vars_dims[var])
+ if isinstance(self.previous_fit, CmdStanMCMC):
+ return self.previous_fit.stan_variable(
+ var, inc_warmup=inc_warmup
+ )
+ elif isinstance(self.previous_fit, CmdStanMLE):
+ return np.atleast_1d( # type: ignore
+ np.asarray(
+ self.previous_fit.stan_variable(
+ var, inc_iterations=inc_warmup
+ )
+ )
+ )
+ else:
+ return np.atleast_1d( # type: ignore
+ np.asarray(self.previous_fit.stan_variable(var))
+ )
- draws = self._draws[draw1:, :, col_idxs]
+ # is gq variable
+ self._assemble_generated_quantities()
- if self._metadata.stan_vars_types[var] == BaseType.COMPLEX:
- draws = draws[..., ::2] + 1j * draws[..., 1::2]
- dims = dims[:-1]
+ draw1, num_draws = self._draws_start(inc_warmup)
+ dims = [num_draws * self.chains]
+ col_idxs = self._metadata.stan_vars_cols[var]
+ if len(col_idxs) > 0:
+ dims.extend(self._metadata.stan_vars_dims[var])
+ draws = self._draws[draw1:, :, col_idxs]
- draws = draws.reshape(dims, order='F')
+ if self._metadata.stan_vars_types[var] == BaseType.COMPLEX:
+ draws = draws[..., ::2] + 1j * draws[..., 1::2]
+ dims = dims[:-1]
- return draws
+ draws = draws.reshape(dims, order='F')
+
+ return draws
[docs] def stan_variables(self, inc_warmup: bool = False) -> Dict[str, np.ndarray]:
- """
+ """
Return a dictionary mapping Stan program variables names
to the corresponding numpy.ndarray containing the inferred values.
@@ -720,7 +788,7 @@ Source code for cmdstanpy.stanfit.gq
CmdStanVB.stan_variables
"""
result = {}
- sample_var_names = self.mcmc_sample.metadata.stan_vars_cols.keys()
+ sample_var_names = self.previous_fit.metadata.stan_vars_cols.keys()
gq_var_names = self.metadata.stan_vars_cols.keys()
for name in gq_var_names:
result[name] = self.stan_variable(name, inc_warmup)
@@ -730,9 +798,11 @@ Source code for cmdstanpy.stanfit.gq
return result
def _assemble_generated_quantities(self) -> None:
+ if self._draws.shape != (0,):
+ return
# use numpy loadtxt
- warmup = self.mcmc_sample.metadata.cmdstan_config['save_warmup']
- num_draws = self.mcmc_sample.draws(inc_warmup=warmup).shape[0]
+ _, num_draws = self._draws_start(inc_warmup=True)
+
gq_sample: np.ndarray = np.empty(
(num_draws, self.chains, len(self.column_names)),
dtype=float,
@@ -746,8 +816,79 @@ Source code for cmdstanpy.stanfit.gq
)
self._draws = gq_sample
+ def _draws_start(self, inc_warmup: bool) -> Tuple[int, int]:
+ draw1 = 0
+ p_fit = self.previous_fit
+ if isinstance(p_fit, CmdStanMCMC):
+ num_draws = p_fit.num_draws_sampling
+ if p_fit._save_warmup:
+ if inc_warmup:
+ num_draws += p_fit.num_draws_warmup
+ else:
+ draw1 = p_fit.num_draws_warmup
+
+ elif isinstance(p_fit, CmdStanMLE):
+ num_draws = 1
+ if p_fit._save_iterations:
+
+ opt_iters = len(p_fit.optimized_iterations_np) # type: ignore
+ if inc_warmup:
+ num_draws = opt_iters
+ else:
+ draw1 = opt_iters - 1
+ else: # CmdStanVB:
+ draw1 = 1 # skip mean
+ num_draws = p_fit.variational_sample.shape[0]
+ if inc_warmup:
+ num_draws += 1
+
+ return draw1, num_draws
+
+ def _previous_draws(self, inc_warmup: bool) -> np.ndarray:
+ """
+ Extract the draws from self.previous_fit.
+ Return is always 3-d
+ """
+ p_fit = self.previous_fit
+ if isinstance(p_fit, CmdStanMCMC):
+ return p_fit.draws(inc_warmup=inc_warmup)
+ elif isinstance(p_fit, CmdStanMLE):
+ if inc_warmup and p_fit._save_iterations:
+ return p_fit.optimized_iterations_np[:, None] # type: ignore
+
+ return np.atleast_2d(p_fit.optimized_params_np,)[ # type: ignore
+ :, None
+ ]
+ else: # CmdStanVB:
+ if inc_warmup:
+ return np.vstack(
+ [p_fit.variational_params_np, p_fit.variational_sample]
+ )[:, None]
+ return p_fit.variational_sample[:, None]
+
+ def _previous_draws_pd(
+ self, vars: List[str], inc_warmup: bool
+ ) -> pd.DataFrame:
+ if vars:
+ sel: Union[List[str], slice] = vars
+ else:
+ sel = slice(None, None)
+
+ p_fit = self.previous_fit
+ if isinstance(p_fit, CmdStanMCMC):
+ return p_fit.draws_pd(vars or None, inc_warmup=inc_warmup)
+
+ elif isinstance(p_fit, CmdStanMLE):
+
+ if inc_warmup and p_fit._save_iterations:
+ return p_fit.optimized_iterations_pd[sel] # type: ignore
+ else:
+ return p_fit.optimized_params_pd[sel]
+ else: # CmdStanVB:
+ return p_fit.variational_sample_pd[sel]
+
[docs] def save_csvfiles(self, dir: Optional[str] = None) -> None:
- """
+ """
Move output CSV files to specified directory. If files were
written to the temporary session directory, clean filename.
E.g., save 'bernoulli-201912081451-1-5nm6as7u.csv' as
@@ -760,7 +901,14 @@ Source code for cmdstanpy.stanfit.gq
stanfit.RunSet.save_csvfiles
cmdstanpy.from_csv
"""
- self.runset.save_csvfiles(dir)
+ self.runset.save_csvfiles(dir)
+
+ @property
+ def mcmc_sample(self) -> Union[CmdStanMCMC, CmdStanMLE, CmdStanVB]:
+ get_logger().warning(
+ "Property `mcmc_sample` is deprecated, use `previous_fit` instead"
+ )
+ return self.previous_fit
diff --git a/docs/_modules/cmdstanpy/stanfit/mcmc.html b/docs/_modules/cmdstanpy/stanfit/mcmc.html
index e6ce1266..7f09183e 100644
--- a/docs/_modules/cmdstanpy/stanfit/mcmc.html
+++ b/docs/_modules/cmdstanpy/stanfit/mcmc.html
@@ -5,7 +5,7 @@
- cmdstanpy.stanfit.mcmc — CmdStanPy 1.0.8 documentation
+ cmdstanpy.stanfit.mcmc — CmdStanPy 1.1.0rc1 documentation
@@ -56,7 +56,7 @@
@@ -216,7 +216,7 @@ Source code for cmdstanpy.stanfit.mcmc
[docs]class CmdStanMCMC:
- """
+ """
Container for outputs from CmdStan sampler run.
Provides methods to summarize and diagnose the model fit
and accessor methods to access the entire sample or
@@ -232,7 +232,7 @@ Source code for cmdstanpy.stanfit.mcmc
self,
runset: RunSet,
) -> None:
- """Initialize object."""
+ """Initialize object."""
if not runset.method == Method.SAMPLE:
raise ValueError(
'Wrong runset method, expecting sample runset, '
@@ -255,7 +255,7 @@ Source code for cmdstanpy.stanfit.mcmc
if sampler_args.thin is not None:
self._thin = sampler_args.thin
self._is_fixed_param = sampler_args.fixed_param
- self._save_warmup = sampler_args.save_warmup
+ self._save_warmup: bool = sampler_args.save_warmup
self._sig_figs = runset._args.sig_figs
# info from CSV values, instantiated lazily
@@ -289,7 +289,7 @@ Source code for cmdstanpy.stanfit.mcmc
return repr
def __getattr__(self, attr: str) -> np.ndarray:
- """Synonymous with ``fit.stan_variable(attr)"""
+ """Synonymous with ``fit.stan_variable(attr)"""
if attr.startswith("_"):
raise AttributeError(f"Unknown variable name {attr}")
try:
@@ -298,24 +298,32 @@ Source code for cmdstanpy.stanfit.mcmc
# pylint: disable=raise-missing-from
raise AttributeError(*e.args)
+ def __getstate__(self) -> dict:
+ # This function returns the mapping of objects to serialize with pickle.
+ # See https://docs.python.org/3/library/pickle.html#object.__getstate__
+ # for details. We call _assemble_draws to ensure posterior samples have
+ # been loaded prior to serialization.
+ self._assemble_draws()
+ return self.__dict__
+
@property
def chains(self) -> int:
- """Number of chains."""
+ """Number of chains."""
return self.runset.chains
@property
def chain_ids(self) -> List[int]:
- """Chain ids."""
+ """Chain ids."""
return self.runset.chain_ids
@property
def num_draws_warmup(self) -> int:
- """Number of warmup draws per chain, i.e., thinned warmup iterations."""
+ """Number of warmup draws per chain, i.e., thinned warmup iterations."""
return int(math.ceil((self._iter_warmup) / self._thin))
@property
def num_draws_sampling(self) -> int:
- """
+ """
Number of sampling (post-warmup) draws per chain, i.e.,
thinned sampling iterations.
"""
@@ -323,7 +331,7 @@ Source code for cmdstanpy.stanfit.mcmc
@property
def metadata(self) -> InferenceMetadata:
- """
+ """
Returns object which contains CmdStan configuration as well as
information about the names and structure of the inference method
and model output variables.
@@ -332,7 +340,7 @@ Source code for cmdstanpy.stanfit.mcmc
@property
def column_names(self) -> Tuple[str, ...]:
- """
+ """
Names of all outputs from the sampler, comprising sampler parameters
and all components of all model parameters, transformed parameters,
and quantities of interest. Corresponds to Stan CSV file header row,
@@ -342,7 +350,7 @@ Source code for cmdstanpy.stanfit.mcmc
@property
def metric_type(self) -> Optional[str]:
- """
+ """
Metric type used for adaptation, either 'diag_e' or 'dense_e', according
to CmdStan arg 'metric'.
When sampler algorithm 'fixed_param' is specified, metric_type is None.
@@ -355,7 +363,7 @@ Source code for cmdstanpy.stanfit.mcmc
@property
def metric(self) -> Optional[np.ndarray]:
- """
+ """
Metric used by sampler for each chain.
When sampler algorithm 'fixed_param' is specified, metric is None.
"""
@@ -371,7 +379,7 @@ Source code for cmdstanpy.stanfit.mcmc
@property
def step_size(self) -> Optional[np.ndarray]:
- """
+ """
Step size used by sampler for each chain.
When sampler algorithm 'fixed_param' is specified, step size is None.
"""
@@ -380,14 +388,14 @@ Source code for cmdstanpy.stanfit.mcmc
@property
def thin(self) -> int:
- """
+ """
Period between recorded iterations. (Default is 1).
"""
return self._thin
@property
def divergences(self) -> Optional[np.ndarray]:
- """
+ """
Per-chain total number of post-warmup divergent iterations.
When sampler algorithm 'fixed_param' is specified, returns None.
"""
@@ -395,7 +403,7 @@ Source code for cmdstanpy.stanfit.mcmc
@property
def max_treedepths(self) -> Optional[np.ndarray]:
- """
+ """
Per-chain total number of post-warmup iterations where the NUTS sampler
reached the maximum allowed treedepth.
When sampler algorithm 'fixed_param' is specified, returns None.
@@ -405,7 +413,7 @@ Source code for cmdstanpy.stanfit.mcmc
[docs] def draws(
self, *, inc_warmup: bool = False, concat_chains: bool = False
) -> np.ndarray:
- """
+ """
Returns a numpy.ndarray over all draws from all chains which is
stored column major so that the values for a parameter are contiguous
in memory, likewise all draws from a chain are contiguous.
@@ -428,8 +436,7 @@ Source code for cmdstanpy.stanfit.mcmc
CmdStanMCMC.draws_xr
CmdStanGQ.draws
"""
- if self._draws.shape == (0,):
- self._assemble_draws()
+ self._assemble_draws()
if inc_warmup and not self._save_warmup:
get_logger().warning(
@@ -446,7 +453,7 @@ Source code for cmdstanpy.stanfit.mcmc
return self._draws[start_idx:, :, :]
def _validate_csv_files(self) -> Dict[str, Any]:
- """
+ """
Checks that Stan CSV output files for all chains are consistent
and returns dict containing config and column names.
@@ -509,7 +516,7 @@ Source code for cmdstanpy.stanfit.mcmc
return dzero
def _check_sampler_diagnostics(self) -> None:
- """
+ """
Warn if any iterations ended in divergences or hit maxtreedepth.
"""
if np.any(self._divergences) or np.any(self._max_treedepths):
@@ -518,13 +525,13 @@ Source code for cmdstanpy.stanfit.mcmc
for i in range(self.runset._chains):
if self._divergences[i] > 0:
diagnostics.append(
- f'Chain {i + 1} had {self._divergences[i]} '
+ f'Chain {i + 1} had {self._divergences[i]} '
'divergent transitions '
f'({((self._divergences[i]/ct_iters)*100):.1f}%)'
)
if self._max_treedepths[i] > 0:
diagnostics.append(
- f'Chain {i + 1} had {self._max_treedepths[i]} '
+ f'Chain {i + 1} had {self._max_treedepths[i]} '
'iterations at max treedepth '
f'({((self._max_treedepths[i]/ct_iters)*100):.1f}%)'
)
@@ -534,7 +541,7 @@ Source code for cmdstanpy.stanfit.mcmc
get_logger().warning('\n\t'.join(diagnostics))
def _assemble_draws(self) -> None:
- """
+ """
Allocates and populates the step size, metric, and sample arrays
by parsing the validated stan_csv files.
"""
@@ -615,7 +622,7 @@ Source code for cmdstanpy.stanfit.mcmc
percentiles: Sequence[int] = (5, 50, 95),
sig_figs: int = 6,
) -> pd.DataFrame:
- """
+ """
Run cmdstan/bin/stansummary over all output CSV files, assemble
summary into DataFrame object. The first row contains statistics
for the total joint log probability `lp__`, but is omitted when the
@@ -650,7 +657,7 @@ Source code for cmdstanpy.stanfit.mcmc
)
cur_pct = pct
percentiles_str = (
- f"--percentiles= {','.join(str(x) for x in percentiles)}"
+ f"--percentiles= {','.join(str(x) for x in percentiles)}"
)
if not isinstance(sig_figs, int) or sig_figs < 1 or sig_figs > 18:
@@ -705,7 +712,7 @@ Source code for cmdstanpy.stanfit.mcmc
return summary_data[mask]
[docs] def diagnose(self) -> Optional[str]:
- """
+ """
Run cmdstan/bin/diagnose over all output CSV files,
return console output.
@@ -729,7 +736,7 @@ Source code for cmdstanpy.stanfit.mcmc
vars: Union[List[str], str, None] = None,
inc_warmup: bool = False,
) -> pd.DataFrame:
- """
+ """
Returns the sample draws as a pandas DataFrame.
Flattens all chains into single column. Container variables
(array, vector, matrix) will span multiple columns, one column
@@ -760,8 +767,7 @@ Source code for cmdstanpy.stanfit.mcmc
' must run sampler with "save_warmup=True".'
)
- if self._draws.shape == (0,):
- self._assemble_draws()
+ self._assemble_draws()
cols = []
if vars is not None:
for var in dict.fromkeys(vars_list):
@@ -786,7 +792,7 @@ Source code for cmdstanpy.stanfit.mcmc
[docs] def draws_xr(
self, vars: Union[str, List[str], None] = None, inc_warmup: bool = False
) -> "xr.Dataset":
- """
+ """
Returns the sampler draws as a xarray Dataset.
:param vars: optional list of variable names.
@@ -817,8 +823,7 @@ Source code for cmdstanpy.stanfit.mcmc
else:
vars_list = vars
- if self._draws.shape == (0,):
- self._assemble_draws()
+ self._assemble_draws()
num_draws = self.num_draws_sampling
meta = self._metadata.cmdstan_config
@@ -857,7 +862,7 @@ Source code for cmdstanpy.stanfit.mcmc
var: str,
inc_warmup: bool = False,
) -> np.ndarray:
- """
+ """
Return a numpy.ndarray which contains the set of draws
for the named Stan program variable. Flattens the chains,
leaving the draws in chain order. The first array dimension,
@@ -904,8 +909,7 @@ Source code for cmdstanpy.stanfit.mcmc
'Available variables are '
+ ", ".join(self._metadata.stan_vars_dims)
)
- if self._draws.shape == (0,):
- self._assemble_draws()
+ self._assemble_draws()
draw1 = 0
if not inc_warmup and self._save_warmup:
draw1 = self.num_draws_warmup
@@ -927,7 +931,7 @@ Source code for cmdstanpy.stanfit.mcmc
return draws
[docs] def stan_variables(self) -> Dict[str, np.ndarray]:
- """
+ """
Return a dictionary mapping Stan program variables names
to the corresponding numpy.ndarray containing the inferred values.
@@ -944,7 +948,7 @@ Source code for cmdstanpy.stanfit.mcmc
return result
[docs] def method_variables(self) -> Dict[str, np.ndarray]:
- """
+ """
Returns a dictionary of all sampler variables, i.e., all
output column names ending in `__`. Assumes that all variables
are scalar variables where column name is variable name.
@@ -952,15 +956,14 @@ Source code for cmdstanpy.stanfit.mcmc
containing per-draw diagnostic values.
"""
result = {}
- if self._draws.shape == (0,):
- self._assemble_draws()
+ self._assemble_draws()
for idxs in self.metadata.method_vars_cols.values():
for idx in idxs:
result[self.column_names[idx]] = self._draws[:, :, idx]
return result
[docs] def save_csvfiles(self, dir: Optional[str] = None) -> None:
- """
+ """
Move output CSV files to specified directory. If files were
written to the temporary session directory, clean filename.
E.g., save 'bernoulli-201912081451-1-5nm6as7u.csv' as
diff --git a/docs/_modules/cmdstanpy/stanfit/metadata.html b/docs/_modules/cmdstanpy/stanfit/metadata.html
index 5302dcc5..bdfc1980 100644
--- a/docs/_modules/cmdstanpy/stanfit/metadata.html
+++ b/docs/_modules/cmdstanpy/stanfit/metadata.html
@@ -5,7 +5,7 @@
- cmdstanpy.stanfit.metadata — CmdStanPy 1.0.8 documentation
+ cmdstanpy.stanfit.metadata — CmdStanPy 1.1.0rc1 documentation
@@ -56,7 +56,7 @@
@@ -176,14 +176,14 @@ Source code for cmdstanpy.stanfit.metadata
[docs]class InferenceMetadata:
- """
+ """
CmdStan configuration and contents of output file parsed out of
the Stan CSV file header comments and column headers.
Assumes valid CSV files.
"""
def __init__(self, config: Dict[str, Any]) -> None:
- """Initialize object from CSV headers"""
+ """Initialize object from CSV headers"""
self._cmdstan_config = config
self._method_vars_cols = parse_method_vars(names=config['column_names'])
stan_vars_dims, stan_vars_cols, stan_vars_types = parse_stan_vars(
@@ -198,7 +198,7 @@ Source code for cmdstanpy.stanfit.metadata
@property
def cmdstan_config(self) -> Dict[str, Any]:
- """
+ """
Returns a dictionary containing a set of name, value pairs
parsed out of the Stan CSV file header. These include the
command configuration and the CSV file header row information.
@@ -208,7 +208,7 @@ Source code for cmdstanpy.stanfit.metadata
@property
def method_vars_cols(self) -> Dict[str, Tuple[int, ...]]:
- """
+ """
Returns a map from a Stan inference method variable to
a tuple of column indices in inference engine's output array.
Method variable names always end in `__`, e.g. `lp__`.
@@ -218,7 +218,7 @@ Source code for cmdstanpy.stanfit.metadata
@property
def stan_vars_cols(self) -> Dict[str, Tuple[int, ...]]:
- """
+ """
Returns a map from a Stan program variable name to a
tuple of the column indices in the vector or matrix of
estimates produced by a CmdStan inference method.
@@ -228,7 +228,7 @@ Source code for cmdstanpy.stanfit.metadata
@property
def stan_vars_dims(self) -> Dict[str, Tuple[int, ...]]:
- """
+ """
Returns map from Stan program variable names to variable dimensions.
Scalar types are mapped to the empty tuple, e.g.,
program variable ``int foo`` has dimension ``()`` and
@@ -239,7 +239,7 @@ Source code for cmdstanpy.stanfit.metadata
@property
def stan_vars_types(self) -> Dict[str, BaseType]:
- """
+ """
Returns map from Stan program variable names to variable base type.
Uses deepcopy for immutability.
"""
diff --git a/docs/_modules/cmdstanpy/stanfit/mle.html b/docs/_modules/cmdstanpy/stanfit/mle.html
index b5d9b682..84fb2e39 100644
--- a/docs/_modules/cmdstanpy/stanfit/mle.html
+++ b/docs/_modules/cmdstanpy/stanfit/mle.html
@@ -5,7 +5,7 @@
- cmdstanpy.stanfit.mle — CmdStanPy 1.0.8 documentation
+ cmdstanpy.stanfit.mle — CmdStanPy 1.1.0rc1 documentation
@@ -56,7 +56,7 @@
@@ -183,13 +183,13 @@ Source code for cmdstanpy.stanfit.mle
[docs]class CmdStanMLE:
- """
+ """
Container for outputs from CmdStan optimization.
Created by :meth:`CmdStanModel.optimize`.
"""
def __init__(self, runset: RunSet) -> None:
- """Initialize object."""
+ """Initialize object."""
if not runset.method == Method.OPTIMIZE:
raise ValueError(
'Wrong runset method, expecting optimize runset, '
@@ -202,7 +202,7 @@ Source code for cmdstanpy.stanfit.mle
assert isinstance(
optimize_args, OptimizeArgs
) # make the typechecker happy
- self._save_iterations = optimize_args.save_iterations
+ self._save_iterations: bool = optimize_args.save_iterations
self._set_mle_attrs(runset.csv_files[0])
def __repr__(self) -> str:
@@ -220,7 +220,7 @@ Source code for cmdstanpy.stanfit.mle
return repr
def __getattr__(self, attr: str) -> Union[np.ndarray, float]:
- """Synonymous with ``fit.stan_variable(attr)"""
+ """Synonymous with ``fit.stan_variable(attr)"""
if attr.startswith("_"):
raise AttributeError(f"Unknown variable name {attr}")
try:
@@ -239,7 +239,7 @@ Source code for cmdstanpy.stanfit.mle
@property
def column_names(self) -> Tuple[str, ...]:
- """
+ """
Names of estimated quantities, includes joint log probability,
and all parameters, transformed parameters, and generated quantities.
"""
@@ -247,7 +247,7 @@ Source code for cmdstanpy.stanfit.mle
@property
def metadata(self) -> InferenceMetadata:
- """
+ """
Returns object which contains CmdStan configuration as well as
information about the names and structure of the inference method
and model output variables.
@@ -256,7 +256,7 @@ Source code for cmdstanpy.stanfit.mle
@property
def optimized_params_np(self) -> np.ndarray:
- """
+ """
Returns all final estimates from the optimizer as a numpy.ndarray
which contains all optimizer outputs, i.e., the value for `lp__`
as well as all Stan program variables.
@@ -269,7 +269,7 @@ Source code for cmdstanpy.stanfit.mle
@property
def optimized_iterations_np(self) -> Optional[np.ndarray]:
- """
+ """
Returns all saved iterations from the optimizer and final estimate
as a numpy.ndarray which contains all optimizer outputs, i.e.,
the value for `lp__` as well as all Stan program variables.
@@ -289,7 +289,7 @@ Source code for cmdstanpy.stanfit.mle
@property
def optimized_params_pd(self) -> pd.DataFrame:
- """
+ """
Returns all final estimates from the optimizer as a pandas.DataFrame
which contains all optimizer outputs, i.e., the value for `lp__`
as well as all Stan program variables.
@@ -302,7 +302,7 @@ Source code for cmdstanpy.stanfit.mle
@property
def optimized_iterations_pd(self) -> Optional[pd.DataFrame]:
- """
+ """
Returns all saved iterations from the optimizer and final estimate
as a pandas.DataFrame which contains all optimizer outputs, i.e.,
the value for `lp__` as well as all Stan program variables.
@@ -321,8 +321,8 @@ Source code for cmdstanpy.stanfit.mle
return pd.DataFrame(self._all_iters, columns=self.column_names)
@property
- def optimized_params_dict(self) -> Dict[str, float]:
- """
+ def optimized_params_dict(self) -> Dict[str, np.float64]:
+ """
Returns all estimates from the optimizer, including `lp__` as a
Python Dict. Only returns estimate from final iteration.
"""
@@ -339,7 +339,7 @@ Source code for cmdstanpy.stanfit.mle
inc_iterations: bool = False,
warn: bool = True,
) -> Union[np.ndarray, float]:
- """
+ """
Return a numpy.ndarray which contains the estimates for the
for the named Stan program variable where the dimensions of the
numpy.ndarray match the shape of the Stan program variable.
@@ -410,7 +410,7 @@ Source code for cmdstanpy.stanfit.mle
[docs] def stan_variables(
self, inc_iterations: bool = False
) -> Dict[str, Union[np.ndarray, float]]:
- """
+ """
Return a dictionary mapping Stan program variables names
to the corresponding numpy.ndarray containing the inferred values.
@@ -439,7 +439,7 @@ Source code for cmdstanpy.stanfit.mle