├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── TODO.md ├── docs ├── Makefile ├── build │ ├── .buildinfo │ ├── .doctrees │ │ ├── arima.doctree │ │ ├── arimax.doctree │ │ ├── bayes.doctree │ │ ├── classical.doctree │ │ ├── dar.doctree │ │ ├── dyn_glm.doctree │ │ ├── dyn_lin.doctree │ │ ├── egarch.doctree │ │ ├── egarchm.doctree │ │ ├── egarchmreg.doctree │ │ ├── environment.pickle │ │ ├── families.doctree │ │ ├── garch.doctree │ │ ├── gas.doctree │ │ ├── gas_llm.doctree │ │ ├── gas_llt.doctree │ │ ├── gas_rank.doctree │ │ ├── gas_reg.doctree │ │ ├── gasssm.doctree │ │ ├── gasx.doctree │ │ ├── getting_started.doctree │ │ ├── gpnar.doctree │ │ ├── index.doctree │ │ ├── llm.doctree │ │ ├── llt.doctree │ │ ├── lmegarch.doctree │ │ ├── modules.doctree │ │ ├── ngssm.doctree │ │ ├── nllm.doctree │ │ ├── nllt.doctree │ │ ├── segarch.doctree │ │ ├── segarchm.doctree │ │ ├── ssm.doctree │ │ └── var.doctree │ ├── _sources │ │ ├── arima.txt │ │ ├── arimax.txt │ │ ├── bayes.txt │ │ ├── classical.txt │ │ ├── dar.txt │ │ ├── dyn_glm.txt │ │ ├── dyn_lin.txt │ │ ├── egarch.txt │ │ ├── egarchm.txt │ │ ├── egarchmreg.txt │ │ ├── families.txt │ │ ├── garch.txt │ │ ├── gas.txt │ │ ├── gas_llm.txt │ │ ├── gas_llt.txt │ │ ├── gas_rank.txt │ │ ├── gas_reg.txt │ │ ├── gasssm.txt │ │ ├── gasx.txt │ │ ├── getting_started.txt │ │ ├── gpnar.txt │ │ ├── index.txt │ │ ├── llm.txt │ │ ├── llt.txt │ │ ├── lmegarch.txt │ │ ├── modules.txt │ │ ├── ngssm.txt │ │ ├── nllm.txt │ │ ├── nllt.txt │ │ ├── segarch.txt │ │ ├── segarchm.txt │ │ ├── ssm.txt │ │ └── var.txt │ ├── _static │ │ ├── ajax-loader.gif │ │ ├── basic.css │ │ ├── comment-bright.png │ │ ├── comment-close.png │ │ ├── comment.png │ │ ├── css │ │ │ ├── badge_only.css │ │ │ └── theme.css │ │ ├── doctools.js │ │ ├── down-pressed.png │ │ ├── down.png │ │ ├── file.png │ │ ├── fonts │ │ │ ├── Inconsolata-Bold.ttf │ │ │ ├── Inconsolata-Regular.ttf │ │ │ ├── Lato-Bold.ttf │ │ │ ├── Lato-Regular.ttf │ │ │ ├── RobotoSlab-Bold.ttf │ │ │ ├── RobotoSlab-Regular.ttf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ └── fontawesome-webfont.woff │ │ ├── jquery-1.11.1.js │ │ ├── jquery.js │ │ ├── js │ │ │ ├── modernizr.min.js │ │ │ └── theme.js │ │ ├── minus.png │ │ ├── plus.png │ │ ├── pygments.css │ │ ├── searchtools.js │ │ ├── underscore-1.3.1.js │ │ ├── underscore.js │ │ ├── up-pressed.png │ │ ├── up.png │ │ └── websupport.js │ ├── arima.html │ ├── arimax.html │ ├── bayes.html │ ├── classical.html │ ├── dar.html │ ├── dyn_glm.html │ ├── dyn_lin.html │ ├── egarch.html │ ├── egarchm.html │ ├── egarchmreg.html │ ├── families.html │ ├── garch.html │ ├── gas.html │ ├── gas_llm.html │ ├── gas_llt.html │ ├── gas_rank.html │ ├── gas_reg.html │ ├── gasssm.html │ ├── gasx.html │ ├── genindex.html │ ├── getting_started.html │ ├── gpnar.html │ ├── index.html │ ├── llm.html │ ├── llt.html │ ├── lmegarch.html │ ├── modules.html │ ├── ngssm.html │ ├── nllm.html │ ├── nllt.html │ ├── objects.inv │ ├── search.html │ ├── searchindex.js │ ├── segarch.html │ ├── segarchm.html │ ├── ssm.html │ └── var.html └── source │ ├── arima.rst │ ├── arimax.rst │ ├── bayes.rst │ ├── classical.rst │ ├── conf.py │ ├── dar.rst │ ├── dyn_glm.rst │ ├── dyn_lin.rst │ ├── egarch.rst │ ├── egarchm.rst │ ├── egarchmreg.rst │ ├── families.rst │ ├── garch.rst │ ├── gas.rst │ ├── gas_llm.rst │ ├── gas_llt.rst │ ├── gas_rank.rst │ ├── gas_reg.rst │ ├── gasssm.rst │ ├── gasx.rst │ ├── getting_started.rst │ ├── gpnar.rst │ ├── index.rst │ ├── llm.rst │ ├── llt.rst │ ├── lmegarch.rst │ ├── modules.rst │ ├── ngssm.rst │ ├── nllm.rst │ ├── nllt.rst │ ├── segarch.rst │ ├── segarchm.rst │ ├── ssm.rst │ └── var.rst ├── pyflux ├── __check_build │ ├── __init__.py │ ├── _check_build.pyx │ └── setup.py ├── __init__.py ├── arma │ ├── __init__.py │ ├── arimax.py │ ├── arma.py │ ├── arma_recursions.pyx │ ├── nn_architecture.pyx │ ├── nnar.py │ ├── nnarx.py │ ├── setup.py │ └── tests │ │ ├── __init__.py │ │ ├── test_arima_cauchy.py │ │ ├── test_arima_exponential.py │ │ ├── test_arima_inference.py │ │ ├── test_arima_laplace.py │ │ ├── test_arima_normal.py │ │ ├── test_arima_poisson.py │ │ ├── test_arima_skewt.py │ │ ├── test_arima_t.py │ │ ├── test_arimax_cauchy.py │ │ ├── test_arimax_exponential.py │ │ ├── test_arimax_inference.py │ │ ├── test_arimax_laplace.py │ │ ├── test_arimax_normal.py │ │ ├── test_arimax_poisson.py │ │ ├── test_arimax_skewt.py │ │ └── test_arimax_t.py ├── covariances.py ├── data_check.py ├── ensembles │ ├── __init__.py │ └── mixture_of_experts.py ├── families │ ├── __init__.py │ ├── cauchy.py │ ├── exponential.py │ ├── family.py │ ├── flat.py │ ├── gas_recursions.c │ ├── gas_recursions.pyx │ ├── inverse_gamma.py │ ├── inverse_wishart.py │ ├── laplace.py │ ├── normal.py │ ├── poisson.py │ ├── poisson_kalman_recursions.c │ ├── poisson_kalman_recursions.pyx │ ├── setup.py │ ├── skewt.py │ ├── t.py │ └── truncated_normal.py ├── garch │ ├── __init__.py │ ├── egarch.py │ ├── egarchm.py │ ├── egarchmreg.py │ ├── garch.py │ ├── garch_recursions.pyx │ ├── lmegarch.py │ ├── segarch.py │ ├── segarchm.py │ ├── setup.py │ └── tests │ │ ├── egarch_tests.py │ │ ├── egarchm_tests.py │ │ ├── egarchmreg_tests.py │ │ ├── garch_tests.py │ │ ├── lmegarch_tests.py │ │ ├── segarch_tests.py │ │ └── segarchm_tests.py ├── gas │ ├── __init__.py │ ├── gas.py │ ├── gas_core_recursions.pyx │ ├── gasllm.py │ ├── gasllt.py │ ├── gasrank.py │ ├── gasreg.py │ ├── gasx.py │ ├── scores.py │ ├── setup.py │ └── tests │ │ ├── __pycache__ │ │ ├── gas_llev_tests.cpython-35-PYTEST.pyc │ │ ├── gas_llev_tests_cauchy.cpython-35-PYTEST.pyc │ │ ├── gas_llev_tests_laplace.cpython-35-PYTEST.pyc │ │ ├── gas_llev_tests_normal.cpython-35-PYTEST.pyc │ │ ├── gas_llev_tests_poisson.cpython-35-PYTEST.pyc │ │ ├── gas_llev_tests_skewt.cpython-35-PYTEST.pyc │ │ ├── gas_llev_tests_t.cpython-35-PYTEST.pyc │ │ ├── gas_llt_tests.cpython-35-PYTEST.pyc │ │ ├── gas_llt_tests_cauchy.cpython-35-PYTEST.pyc │ │ ├── gas_llt_tests_normal.cpython-35-PYTEST.pyc │ │ ├── gas_llt_tests_poisson.cpython-35-PYTEST.pyc │ │ ├── gas_llt_tests_skewt.cpython-35-PYTEST.pyc │ │ ├── gas_llt_tests_t.cpython-35-PYTEST.pyc │ │ ├── gas_rank_tests.cpython-35-PYTEST.pyc │ │ ├── gas_tests.cpython-35-PYTEST.pyc │ │ ├── gas_tests_cauchy.cpython-35-PYTEST.pyc │ │ ├── gas_tests_exponential.cpython-35-PYTEST.pyc │ │ ├── gas_tests_laplace.cpython-35-PYTEST.pyc │ │ ├── gas_tests_normal.cpython-35-PYTEST.pyc │ │ ├── gas_tests_poisson.cpython-35-PYTEST.pyc │ │ ├── gas_tests_skewt.cpython-35-PYTEST.pyc │ │ ├── gas_tests_t.cpython-35-PYTEST.pyc │ │ ├── gasreg_tests_cauchy.cpython-35-PYTEST.pyc │ │ ├── gasreg_tests_laplace.cpython-35-PYTEST.pyc │ │ ├── gasreg_tests_normal.cpython-35-PYTEST.pyc │ │ ├── gasreg_tests_poisson.cpython-35-PYTEST.pyc │ │ ├── gasreg_tests_skewt.cpython-35-PYTEST.pyc │ │ ├── gasreg_tests_t.cpython-35-PYTEST.pyc │ │ ├── gasx_tests_exponential.cpython-35-PYTEST.pyc │ │ ├── gasx_tests_laplace.cpython-35-PYTEST.pyc │ │ ├── gasx_tests_normal.cpython-35-PYTEST.pyc │ │ ├── gasx_tests_poisson.cpython-35-PYTEST.pyc │ │ ├── gasx_tests_skewt.cpython-35-PYTEST.pyc │ │ └── gasx_tests_t.cpython-35-PYTEST.pyc │ │ ├── gas_llev_tests_cauchy.py │ │ ├── gas_llev_tests_laplace.py │ │ ├── gas_llev_tests_normal.py │ │ ├── gas_llev_tests_poisson.py │ │ ├── gas_llev_tests_skewt.py │ │ ├── gas_llev_tests_t.py │ │ ├── gas_llt_tests.py │ │ ├── gas_llt_tests_cauchy.py │ │ ├── gas_llt_tests_laplace.py │ │ ├── gas_llt_tests_normal.py │ │ ├── gas_llt_tests_poisson.py │ │ ├── gas_llt_tests_skewt.py │ │ ├── gas_llt_tests_t.py │ │ ├── gas_rank_tests.py │ │ ├── gas_tests_cauchy.py │ │ ├── gas_tests_exponential.py │ │ ├── gas_tests_laplace.py │ │ ├── gas_tests_normal.py │ │ ├── gas_tests_poisson.py │ │ ├── gas_tests_skewt.py │ │ ├── gas_tests_t.py │ │ ├── gasreg_tests_cauchy.py │ │ ├── gasreg_tests_laplace.py │ │ ├── gasreg_tests_normal.py │ │ ├── gasreg_tests_poisson.py │ │ ├── gasreg_tests_skewt.py │ │ ├── gasreg_tests_t.py │ │ ├── gasx_tests_cauchy.py │ │ ├── gasx_tests_exponential.py │ │ ├── gasx_tests_laplace.py │ │ ├── gasx_tests_normal.py │ │ ├── gasx_tests_poisson.py │ │ ├── gasx_tests_skewt.py │ │ └── gasx_tests_t.py ├── gpnarx │ ├── __init__.py │ ├── gpnarx.py │ ├── kernel_routines.pyx │ ├── kernels.py │ ├── setup.py │ └── tests │ │ ├── __pycache__ │ │ ├── arima_tests.cpython-35-PYTEST.pyc │ │ ├── arimax_tests.cpython-35-PYTEST.pyc │ │ └── gpnarx_tests.cpython-35-PYTEST.pyc │ │ └── gpnarx_tests.py ├── inference │ ├── __init__.py │ ├── bbvi.py │ ├── bbvi_routines.pyx │ ├── metropolis_hastings.py │ ├── metropolis_sampler.pyx │ ├── norm_post_sim.py │ ├── setup.py │ └── stoch_optim.py ├── latent_variables.py ├── output │ ├── __init__.py │ └── tableprinter.py ├── results.py ├── setup.py ├── ssm │ ├── __init__.py │ ├── dar.py │ ├── dynamic_glm.py │ ├── dynlin.py │ ├── kalman.pyx │ ├── llm.py │ ├── llt.py │ ├── local_level.py │ ├── local_trend.py │ ├── ndynlin.py │ ├── nllm.py │ ├── nllt.py │ ├── setup.py │ └── tests │ │ ├── __pycache__ │ │ └── dar_tests.cpython-35-PYTEST.pyc │ │ └── dar_tests.py ├── tests │ ├── __init__.py │ └── nhst.py ├── tsm.py └── var │ ├── __init__.py │ ├── setup.py │ ├── tests │ └── var_tests.py │ ├── var.py │ └── var_recursions.pyx ├── requirements-dev.txt ├── requirements.txt ├── setup.py └── tools └── cythonize.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *,cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # dotenv 80 | .env 81 | 82 | # virtualenv 83 | .venv/ 84 | venv/ 85 | ENV/ 86 | 87 | # Spyder project settings 88 | .spyderproject 89 | 90 | # Rope project settings 91 | .ropeproject 92 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | matrix: 4 | include: 5 | - python: 2.7 6 | - python: 3.5 7 | 8 | install: 9 | - wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh 10 | - bash miniconda.sh -b -p $HOME/miniconda 11 | - export PATH="$HOME/miniconda/bin:$PATH" 12 | - conda config --set always_yes yes --set changeps1 no 13 | - conda update conda 14 | 15 | - conda create -n pyflux python=$TRAVIS_PYTHON_VERSION pytest numpy pandas scipy patsy pytest-cov cython 16 | - source activate pyflux 17 | - conda install -c omnia numdifftools=0.9.14 18 | - python setup.py install 19 | 20 | script: 21 | - py.test -s --cov=pyflux --pyargs pyflux 22 | 23 | after_success: 24 | - coveralls -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Ross Taylor 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the copyright holder nor the names of its contributors 13 | may be used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyFlux 2 | 3 | [![Join the chat at https://gitter.im/RJT1990/pyflux](https://badges.gitter.im/RJT1990/pyflux.svg)](https://gitter.im/RJT1990/pyflux?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | [![PyPI version](https://badge.fury.io/py/pyflux.svg)](https://badge.fury.io/py/pyflux) 5 | [![Documentation Status](https://readthedocs.org/projects/pyflux/badge/?version=latest)](http://pyflux.readthedocs.io/en/latest/?badge=latest) 6 | 7 | __PyFlux__ is an open source time series library for Python. The library has a good array of modern time series models, as well as a flexible array of inference options (frequentist and Bayesian) that can be applied to these models. By combining breadth of models with breadth of inference, PyFlux allows for a probabilistic approach to time series modelling. 8 | 9 | See some examples and documentation below. PyFlux is still only alpha software; this means you use it at your own risk, that test coverage is still in need of expansion, and also that some modules are still in need of being optimized. 10 | 11 | [Click here for a getting started guide](http://pyflux.readthedocs.io/en/latest/getting_started.html). 12 | 13 | **Note From Author** : I am currently working on other projects as of now, so have paused updates for this library for the immediate future. If you'd like to help move the library forward by contributing, then do get in touch! I am planning to review at end of year and update the library as required (new version requirements, etc). 14 | 15 | ## Models 16 | 17 | - [ARIMA models](http://pyflux.readthedocs.io/en/latest/arima.html) 18 | - [ARIMAX models](http://pyflux.readthedocs.io/en/latest/arimax.html) 19 | - [Dynamic Autoregression models](http://pyflux.readthedocs.io/en/latest/docs/dar.html) 20 | - [Dynamic Paired Comparison models](http://pyflux.readthedocs.io/en/latest/gas_rank.html) 21 | - [GARCH models](http://pyflux.readthedocs.io/en/latest/garch.html) 22 | - [Beta-t-EGARCH models](http://pyflux.readthedocs.io/en/latest/egarch.html) 23 | - [EGARCH-in-mean models](http://pyflux.readthedocs.io/en/latest/egarchm.html) 24 | - [EGARCH-in-mean regression models](http://pyflux.readthedocs.io/en/latest/egarchmreg.html) 25 | - [Long Memory EGARCH models](http://pyflux.readthedocs.io/en/latest/lmegarch.html) 26 | - [Skew-t-EGARCH models](http://pyflux.readthedocs.io/en/latest/segarch.html) 27 | - [Skew-t-EGARCH-in-mean models](http://pyflux.readthedocs.io/en/latest/segarchm.html) 28 | - [GAS models](http://pyflux.readthedocs.io/en/latest/gas.html) 29 | - [GASX models](http://pyflux.readthedocs.io/en/latest/gasx.html) 30 | - [GAS State Space models](http://pyflux.readthedocs.io/en/latest/gas_llm.html) 31 | - [Gaussian State Space models](http://pyflux.readthedocs.io/en/latest/llm.html) 32 | - [Non-Gaussian State Space models](http://pyflux.readthedocs.io/en/latest/nllm.html) 33 | - [VAR models](http://pyflux.readthedocs.io/en/latest/var.html) 34 | 35 | ## Inference 36 | 37 | - [Black Box Variational Inference](http://pyflux.readthedocs.io/en/latest/bayes.html) 38 | - [Laplace Approximation](http://pyflux.readthedocs.io/en/latest/bayes.html) 39 | - [Maximum Likelihood](http://pyflux.readthedocs.io/en/latest/classical.html) and [Penalized Maximum Likelihood](http://pyflux.readthedocs.io/en/latest/bayes.html) 40 | - [Metropolis-Hastings](http://pyflux.readthedocs.io/en/latest/bayes.html) 41 | 42 | ## Installing PyFlux 43 | 44 | ```{bash} 45 | pip install pyflux 46 | ``` 47 | 48 | ## Python Version 49 | 50 | Supported on Python 2.7 and 3.5. 51 | 52 | ## Talks 53 | 54 | - [PyData San Francisco 2016](https://github.com/RJT1990/PyData2016-SanFrancisco) - August 2016 - a tour of time series (and predicting NFL games) 55 | - [PyData London Meetup](https://github.com/RJT1990/talks/blob/master/PyDataTimeSeriesTalk.ipynb) - June 2016 - an introduction to the library in its early stages 56 | 57 | ## Citation 58 | 59 | PyFlux is still alpha software so results should be treated with care, but citations are very welcome: 60 | 61 | > Ross Taylor. 2016. 62 | > _PyFlux: An open source time series library for Python_ 63 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/TODO.md -------------------------------------------------------------------------------- /docs/build/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 5593b3d6747a35c28131396c3cf791ed 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/build/.doctrees/arima.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/arima.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/arimax.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/arimax.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/bayes.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/bayes.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/classical.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/classical.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/dar.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/dar.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/dyn_glm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/dyn_glm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/dyn_lin.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/dyn_lin.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/egarch.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/egarch.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/egarchm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/egarchm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/egarchmreg.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/egarchmreg.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/build/.doctrees/families.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/families.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/garch.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/garch.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/gas.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/gas.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/gas_llm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/gas_llm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/gas_llt.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/gas_llt.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/gas_rank.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/gas_rank.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/gas_reg.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/gas_reg.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/gasssm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/gasssm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/gasx.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/gasx.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/getting_started.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/getting_started.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/gpnar.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/gpnar.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/index.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/llm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/llm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/llt.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/llt.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/lmegarch.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/lmegarch.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/modules.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/modules.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/ngssm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/ngssm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/nllm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/nllm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/nllt.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/nllt.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/segarch.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/segarch.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/segarchm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/segarchm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/ssm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/ssm.doctree -------------------------------------------------------------------------------- /docs/build/.doctrees/var.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/.doctrees/var.doctree -------------------------------------------------------------------------------- /docs/build/_sources/bayes.txt: -------------------------------------------------------------------------------- 1 | Bayesian Inference 2 | ================================== 3 | 4 | PyFlux supports Bayesian inference for all the model types on offer. 5 | 6 | Interface 7 | ---------- 8 | 9 | To view the current priors, you should print the model's latent variable object. For example: 10 | 11 | .. code-block:: python 12 | :linenos: 13 | 14 | import pyflux as pf 15 | 16 | # model = ... (specify a model) 17 | print(model.z) 18 | 19 | This will outline the current prior assumptions for each latent variable, as well as the variational approximate distribution that is assumed (if you are performing variational inference). To adjust priors, simply use the following method on your model object: 20 | 21 | .. py:function:: adjust_prior(index, prior) 22 | 23 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as :py:Class:`Normal`. 24 | 25 | Here is example usage for :py:func:`adjust_prior`: 26 | 27 | .. code-block:: python 28 | :linenos: 29 | 30 | import pyflux as pf 31 | 32 | # model = ... (specify a model) 33 | model.list_priors() 34 | model.adjust_prior(2, pf.Normal(0,1)) 35 | 36 | 37 | Methods 38 | ---------- 39 | 40 | There are a number of Bayesian inference options using the :py:func:`fit`: method. These can be chosen with the method argument. 41 | 42 | **Black-Box Variational Inference** 43 | 44 | Performs Black Box Variational Inference. Currently the fixed assumption is mean-field variational inference with normal approximate distributions. The gradient used in this implementation is the score function gradient. By default we use 24 samples for the gradient which is quite intense (other implementations use 2-8 samples). For your application, less samples may be as effective and quicker. One of the limitations of the implementation right now is BBVI here does not support using mini-batches of data. It is not clear yet how mini-batches would work with model types that have an underlying sequence of latent states - if it is shown to be effective, then this option will be included in future. 45 | 46 | .. code-block:: python 47 | :linenos: 48 | 49 | model.fit(method='BBVI', iterations='10000', optimizer='ADAM') 50 | 51 | * *batch_size* : (default : 24) number of Monte Carlo samples for the gradient 52 | * *iterations* : (default : 3000) number of iterations to run 53 | * *optimizer* : (default: RMSProp) RMSProp or ADAM (stochastic optimizers) 54 | * *map_start*: (default: True) if True, starts latent variables using a MAP/PML estimate 55 | * *mini_batch*: (default: None) if an int, then will sample mini-batches from the data of the size selected (e.g. 32). This option does not work for some model types. 56 | * *learning_rate*: (default: 0.001) the learning rate for the optimizer 57 | * *record_elbo* : (default: False) if True, will record ELBO during optimization, which can is stored as ``x.elbo_records`` for a ``BBVIResults()`` object ``x``. 58 | 59 | **Laplace Approximation** 60 | 61 | Performs a Laplace approximation on the posterior. 62 | 63 | .. code-block:: python 64 | :linenos: 65 | 66 | model.fit(method='Laplace') 67 | 68 | **Metropolis-Hastings** 69 | 70 | Performs Metropolis-Hastings MCMC. Currently uses 'one long chain' which is not ideal, but works okay for most of the models available. This method applies a warm-up period of half the number of simulations and applies thinning by removing every other sample to reduce correlation. 71 | 72 | .. code-block:: python 73 | :linenos: 74 | 75 | model.fit(method='M-H') 76 | 77 | * *map_start* : (default: True) whether to initialize starting values and the covariance matrix using MAP estimates and the Inverse Hessian 78 | * *nsims* : number of simulations for the chain 79 | 80 | **Penalized Maximum Likelihood** 81 | 82 | Provides a Maximum a posteriori (MAP) estimate. This estimate is not completely Bayesian as it is based on a 0/1 loss rather than a squared or absolute loss. It can be considered a form of modal approximation, when taken together with the Inverse Hessian matrix. 83 | 84 | .. code-block:: python 85 | :linenos: 86 | 87 | model.fit(method='PML') 88 | 89 | * *preopt_search* : (default : True) if True will use a preoptimization stage to find good starting values (if the model type has no available preoptimization method, this argument will be ignored). Turning this off will speed up optimization at the risk of obtaining an inferior solution. 90 | -------------------------------------------------------------------------------- /docs/build/_sources/classical.txt: -------------------------------------------------------------------------------- 1 | Classical Inference 2 | ================================== 3 | 4 | PyFlux supports classical methods of inference. These can be considered as point mass approximations to the full posterior. 5 | 6 | Methods 7 | ---------- 8 | 9 | There are a number of classical inference options using the :py:func:`fit`: method. These can be chosen with the method option. 10 | 11 | **Maximum Likelihood** 12 | 13 | Performs Maximum Likelihood estimation. 14 | 15 | .. code-block:: python 16 | :linenos: 17 | 18 | model.fit(method='MLE') 19 | 20 | * *preopt_search* : (default : True) if True will use a preoptimization stage to find good starting values (if the model type has no available preoptimization method, this argument will be ignored). Turning this off will speed up optimization at the risk of obtaining an inferior solution. 21 | 22 | **Ordinary Least Squares** 23 | 24 | Performs Ordinary Least Squares estimation. 25 | 26 | .. code-block:: python 27 | :linenos: 28 | 29 | model.fit(method='OLS') 30 | 31 | **Penalized Maximum Likelihood** 32 | 33 | From a frequentist perspective, PML can be viewed as a type of regularization on the coefficients. 34 | 35 | .. code-block:: python 36 | :linenos: 37 | 38 | model.fit(method='PML') 39 | 40 | * *preopt_search* : (default : True) if True will use a preoptimization stage to find good starting values (if the model type has no available preoptimization method, this argument will be ignored). Turning this off will speed up optimization at the risk of obtaining an inferior solution. -------------------------------------------------------------------------------- /docs/build/_sources/gasssm.txt: -------------------------------------------------------------------------------- 1 | GAS State Space models 2 | ================================== 3 | 4 | Example 5 | ---------- 6 | 7 | .. code-block:: python 8 | :linenos: 9 | 10 | import numpy as np 11 | import pyflux as pf 12 | import pandas as pd 13 | 14 | nile = pd.read_csv('https://vincentarelbundock.github.io/Rdatasets/csv/datasets/Nile.csv') 15 | nile.index = pd.to_datetime(nile['time'].values,format='%Y') 16 | 17 | model = pf.GASLLEV(data=nile, target='Nile', family=pf.GASt()) # local level 18 | 19 | USgrowth = pd.DataFrame(np.log(growthdata['VALUE'])) 20 | USgrowth.index = pd.to_datetime(growthdata['DATE']) 21 | USgrowth.columns = ['Logged US Real GDP'] 22 | 23 | model2 = pf.GASLLT(data=USgrowth, family=pf.GASt()) # local linear trend model 24 | 25 | Class Arguments 26 | ---------- 27 | 28 | The GAS local level (**GASLLEV**) and GAS local linear trend (**GASLLT**) models are of the following form: 29 | 30 | .. py:class:: GASLLEV(data, integ, target, family) 31 | 32 | .. py:attribute:: data 33 | 34 | pd.DataFrame or array-like : the time-series data 35 | 36 | .. py:attribute:: integ 37 | 38 | int : how many times to difference the time series (default: 0) 39 | 40 | .. py:attribute:: target 41 | 42 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 43 | 44 | .. py:attribute:: family 45 | 46 | a GAS family object; choices include GASExponential(), GASLaplace(), GASNormal(), GASPoisson(), GASSkewt(), GASt() 47 | 48 | .. py:class:: GASLLT(data, integ, target, family) 49 | 50 | .. py:attribute:: data 51 | 52 | pd.DataFrame or array-like : the time-series data 53 | 54 | .. py:attribute:: integ 55 | 56 | int : how many times to difference the time series (default: 0) 57 | 58 | .. py:attribute:: target 59 | 60 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 61 | 62 | .. py:attribute:: family 63 | 64 | a GAS family object; choices include GASExponential(), GASLaplace(), GASNormal(), GASPoisson(), GASSkewt(), GASt() 65 | 66 | Class Methods 67 | ---------- 68 | 69 | .. py:function:: adjust_prior(index, prior) 70 | 71 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as Normal(0,3). 72 | 73 | Here is example usage for :py:func:`adjust_prior`: 74 | 75 | .. code-block:: python 76 | :linenos: 77 | 78 | import pyflux as pf 79 | 80 | # model = ... (specify a model) 81 | model.list_priors() 82 | model.adjust_prior(2,pf.Normal(0,1)) 83 | 84 | .. py:function:: fit(method,**kwargs) 85 | 86 | Estimates latent variables for the model. Returns a Results object. **method** is an inference/estimation option; see Bayesian Inference and Classical Inference sections for options. If no **method** is provided then a default will be used. 87 | 88 | Optional arguments are specific to the **method** you choose - see the documentation for these methods for more detail. 89 | 90 | Here is example usage for :py:func:`fit`: 91 | 92 | .. code-block:: python 93 | :linenos: 94 | 95 | import pyflux as pf 96 | 97 | # model = ... (specify a model) 98 | model.fit("M-H",nsims=20000) 99 | 100 | .. py:function:: plot_fit(intervals,**kwargs) 101 | 102 | Graphs the fit of the model. **intervals** is a boolean; if true shows 95% C.I. intervals for the states. 103 | 104 | Optional arguments include **figsize** - the dimensions of the figure to plot - and **series_type** which has two options: *Filtered* or *Smoothed*. 105 | 106 | .. py:function:: plot_z(indices, figsize) 107 | 108 | Returns a plot of the latent variables and their associated uncertainty. **indices** is a list referring to the latent variable indices that you want ot plot. Figsize specifies how big the plot will be. 109 | 110 | .. py:function:: plot_predict(h, past_values, intervals, **kwargs) 111 | 112 | Plots predictions of the model. **h** is an int of how many steps ahead to predict. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 113 | 114 | Optional arguments include **figsize** - the dimensions of the figure to plot. 115 | 116 | .. py:function:: plot_predict_is(h, fit_once, **kwargs) 117 | 118 | Plots in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **fit_once** is a boolean specifying whether to fit the model once at the beginning of the period (True), or whether to fit after every step (False). 119 | 120 | Optional arguments include **figsize** - the dimensions of the figure to plot. 121 | 122 | .. py:function:: predict(h) 123 | 124 | Returns DataFrame of model predictions. **h** is an int of how many steps ahead to predict. 125 | 126 | .. py:function:: predict_is(h, fit_once) 127 | 128 | Returns DataFrame of in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **fit_once** is a boolean specifying whether to fit the model once at the beginning of the period (True), or whether to fit after every step (False). -------------------------------------------------------------------------------- /docs/build/_sources/gpnar.txt: -------------------------------------------------------------------------------- 1 | GP-NARX models 2 | ================================== 3 | 4 | Example 5 | ---------- 6 | 7 | .. code-block:: python 8 | :linenos: 9 | 10 | import numpy as np 11 | import pandas as pd 12 | import pyflux as pf 13 | 14 | USgrowth = #somequarterlyGDPgrowthdatahere 15 | model = pf.GPNARX(USgrowth, ar=4, kernel_type='OU') 16 | 17 | Class Arguments 18 | ---------- 19 | 20 | .. py:class:: GPNARX(data, ar, kernel_type, integ, target) 21 | 22 | .. py:attribute:: data 23 | 24 | pd.DataFrame or array-like : the time-series data 25 | 26 | .. py:attribute:: ar 27 | 28 | int : the number of autoregressive terms 29 | 30 | .. py:attribute:: kernel_type 31 | 32 | string : the type of kernel; one of ['SE','RQ','OU','Periodic','ARD'] 33 | 34 | .. py:attribute:: integ 35 | 36 | int : Specifies how many time to difference the time series. 37 | 38 | .. py:attribute:: target 39 | 40 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 41 | 42 | Class Methods 43 | ---------- 44 | 45 | .. py:function:: adjust_prior(index, prior) 46 | 47 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as Normal(0,3). 48 | 49 | Here is example usage for :py:func:`adjust_prior`: 50 | 51 | .. code-block:: python 52 | :linenos: 53 | 54 | import pyflux as pf 55 | 56 | # model = ... (specify a model) 57 | model.list_priors() 58 | model.adjust_prior(2,pf.Normal(0,1)) 59 | 60 | .. py:function:: fit(method,**kwargs) 61 | 62 | Estimates latent variables for the model. Returns a Results object. **method** is an inference/estimation option; see Bayesian Inference and Classical Inference sections for options. If no **method** is provided then a default will be used. 63 | 64 | Optional arguments are specific to the **method** you choose - see the documentation for these methods for more detail. 65 | 66 | Here is example usage for :py:func:`fit`: 67 | 68 | .. code-block:: python 69 | :linenos: 70 | 71 | import pyflux as pf 72 | 73 | # model = ... (specify a model) 74 | model.fit("M-H",nsims=20000) 75 | 76 | .. py:function:: plot_fit(**kwargs) 77 | 78 | Graphs the fit of the model. 79 | 80 | Optional arguments include **figsize** - the dimensions of the figure to plot. 81 | 82 | .. py:function:: plot_z(indices, figsize) 83 | 84 | Returns a plot of the latent variables and their associated uncertainty. **indices** is a list referring to the latent variable indices that you want ot plot. Figsize specifies how big the plot will be. 85 | 86 | .. py:function:: plot_predict(h,past_values,intervals,**kwargs) 87 | 88 | Plots predictions of the model. **h** is an int of how many steps ahead to predict. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 89 | 90 | Optional arguments include **figsize** - the dimensions of the figure to plot. 91 | 92 | .. py:function:: plot_predict_is(h, fit_once, **kwargs) 93 | 94 | Plots in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **fit_once** is a boolean specifying whether to fit the model once at the beginning of the period (True), or whether to fit after every step (False). 95 | 96 | Optional arguments include **figsize** - the dimensions of the figure to plot. 97 | 98 | .. py:function:: predict(h) 99 | 100 | Returns DataFrame of model predictions. **h** is an int of how many steps ahead to predict. 101 | 102 | .. py:function:: predict_is(h, fit_once) 103 | 104 | Returns DataFrame of in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **fit_once** is a boolean specifying whether to fit the model once at the beginning of the period (True), or whether to fit after every step (False). 105 | -------------------------------------------------------------------------------- /docs/build/_sources/modules.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_sources/modules.txt -------------------------------------------------------------------------------- /docs/build/_sources/ngssm.txt: -------------------------------------------------------------------------------- 1 | Non-Gaussian State Space models 2 | ================================== 3 | 4 | Example 5 | ---------- 6 | 7 | .. code-block:: python 8 | :linenos: 9 | 10 | import numpy as np 11 | import pyflux as pf 12 | import pandas as pd 13 | 14 | leicester = pd.read_csv('http://www.pyflux.com/notebooks/leicester_goals_scored.csv') 15 | leicester.columns= ["Time","Leicester Goals Scored"] 16 | 17 | model = pf.NLLEV.Poisson(data=leicester,target='Leicester Goals Scored') 18 | 19 | fb = DataReader('FB', 'yahoo', datetime(2015,5,1), datetime(2016,5,10)) 20 | returns = pd.DataFrame(np.diff(np.log(fb['Open'].values))) 21 | returns.index = fb.index.values[1:fb.index.values.shape[0]] 22 | returns.columns = ['Facebook Returns'] 23 | 24 | model2 = pf.NLLEV.t(data=returns,target='Close') 25 | 26 | Class Arguments 27 | ---------- 28 | 29 | The non-linear local level model (**NLLEV**) model has the options: **NLLEV.Exponential**, **NLLEV.Laplace**, **NLLEV.Poisson**, **NLLEV.t**, 30 | 31 | .. py:class:: NLLEV(data,integ,target) 32 | 33 | .. py:attribute:: data 34 | 35 | pd.DataFrame or array-like : the time-series data 36 | 37 | .. py:attribute:: integ 38 | 39 | int : how many times to difference the time series (default: 0) 40 | 41 | .. py:attribute:: target 42 | 43 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 44 | 45 | The non-linear local linear trend model (**NLLT**) model has the options: **NLLT.Exponential**, **NLLT.Laplace**, **NLLT.Poisson**, **NLLT.t**, 46 | 47 | .. py:class:: NLLT(data,integ,target) 48 | 49 | .. py:attribute:: data 50 | 51 | pd.DataFrame or array-like : the time-series data 52 | 53 | .. py:attribute:: integ 54 | 55 | int : how many times to difference the time series (default: 0) 56 | 57 | .. py:attribute:: target 58 | 59 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 60 | 61 | The non-linear dynamic regression model (**NDynLin**) model has the options: **NDynLin.Exponential**, **NDynLin.Laplace**, **NDynLin.Poisson**, **NDynLin.t**, 62 | 63 | .. py:class:: NDynLin(formula,data) 64 | 65 | .. py:attribute:: formula 66 | 67 | patsy notation string describing the regression 68 | 69 | .. py:attribute:: data 70 | 71 | pd.DataFrame or array-like : the time-series data 72 | 73 | 74 | Class Methods 75 | ---------- 76 | 77 | .. py:function:: adjust_prior(index, prior) 78 | 79 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as Normal(0,3). 80 | 81 | Here is example usage for :py:func:`adjust_prior`: 82 | 83 | .. code-block:: python 84 | :linenos: 85 | 86 | import pyflux as pf 87 | 88 | # model = ... (specify a model) 89 | model.list_priors() 90 | model.adjust_prior(2,pf.Normal(0,1)) 91 | 92 | .. py:function:: fit(method,iterations,step,**kwargs) 93 | 94 | Estimates parameters for the model using BBVI. Returns a Results object. **iterations** is the number of iterations for BBVI, and **step** is the step size for RMSProp (default : 0.001). 95 | 96 | Optional arguments include **animate** for the local level and local linear trend models: outputs an animation of stochastic optimization. 97 | 98 | Here is example usage for :py:func:`fit`: 99 | 100 | .. code-block:: python 101 | :linenos: 102 | 103 | import pyflux as pf 104 | 105 | # model = ... (specify a model) 106 | model.fit("M-H",nsims=20000) 107 | 108 | .. py:function:: plot_fit(intervals,**kwargs) 109 | 110 | Graphs the fit of the model. **intervals** is a boolean; if true shows 95% C.I. intervals for the states. 111 | 112 | Optional arguments include **figsize** - the dimensions of the figure to plot - and **series_type** which has two options: *Filtered* or *Smoothed*. 113 | 114 | .. py:function:: plot_parameters(indices, figsize) 115 | 116 | Returns a plot of the parameters and their associated uncertainty. **indices** is a list referring to the parameter indices that you want ot plot. Figsize specifies how big the plot will be. 117 | 118 | .. py:function:: plot_predict(h,past_values,intervals,**kwargs) 119 | 120 | Plots predictions of the model. **h** is an int of how many steps ahead to predict. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 121 | 122 | Optional arguments include **figsize** - the dimensions of the figure to plot. 123 | 124 | .. py:function:: plot_predict_is(h,past_values,intervals,**kwargs) 125 | 126 | Plots in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 127 | 128 | Optional arguments include **figsize** - the dimensions of the figure to plot. 129 | 130 | .. py:function:: predict(h) 131 | 132 | Returns DataFrame of model predictions. **h** is an int of how many steps ahead to predict. 133 | 134 | .. py:function:: predict_is(h) 135 | 136 | Returns DataFrame of in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. 137 | 138 | .. py:function:: simulation_smoother(data,beta,H,mu) 139 | 140 | Outputs a simulated state trajectory from a simulation smoother. Arguments are **data** : the data to simulate from - use self.data usually - and **beta** : the parameters to use, **H** is the measurement covariance matrix from an approximate Gaussian model, and **mu** is a measurement density constant from an approximate Gaussian model. -------------------------------------------------------------------------------- /docs/build/_sources/ssm.txt: -------------------------------------------------------------------------------- 1 | Gaussian State Space models 2 | ================================== 3 | 4 | Example 5 | ---------- 6 | 7 | .. code-block:: python 8 | :linenos: 9 | 10 | import numpy as np 11 | import pyflux as pf 12 | import pandas as pd 13 | 14 | nile = pd.read_csv('https://vincentarelbundock.github.io/Rdatasets/csv/datasets/Nile.csv') 15 | nile.index = pd.to_datetime(nile['time'].values,format='%Y') 16 | 17 | model = pf.LLEV(data=niles,target='Poisson') # local level 18 | 19 | USgrowth = pd.DataFrame(np.log(growthdata['VALUE'])) 20 | USgrowth.index = pd.to_datetime(growthdata['DATE']) 21 | USgrowth.columns = ['Logged US Real GDP'] 22 | 23 | model2 = pf.LLT(data=USgrowth) # local linear trend model 24 | 25 | Class Arguments 26 | ---------- 27 | 28 | The local level (**LLEV**) and local linear trend (**LLT**) models are of the following form: 29 | 30 | .. py:class:: LLEV(data,integ,target) 31 | 32 | .. py:attribute:: data 33 | 34 | pd.DataFrame or array-like : the time-series data 35 | 36 | .. py:attribute:: integ 37 | 38 | int : how many times to difference the time series (default: 0) 39 | 40 | .. py:attribute:: target 41 | 42 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 43 | 44 | .. py:class:: LLT(data,integ,target) 45 | 46 | .. py:attribute:: data 47 | 48 | pd.DataFrame or array-like : the time-series data 49 | 50 | .. py:attribute:: integ 51 | 52 | int : how many times to difference the time series (default: 0) 53 | 54 | .. py:attribute:: target 55 | 56 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 57 | 58 | The dynamic linear regression (**DynReg**) model is of the form: 59 | 60 | .. py:class:: DynReg(formula,data) 61 | 62 | .. py:attribute:: formula 63 | 64 | patsy notation string describing the regression 65 | 66 | .. py:attribute:: data 67 | 68 | pd.DataFrame or array-like : the time-series data 69 | 70 | 71 | Class Methods 72 | ---------- 73 | 74 | .. py:function:: adjust_prior(index, prior) 75 | 76 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as Normal(0,3). 77 | 78 | Here is example usage for :py:func:`adjust_prior`: 79 | 80 | .. code-block:: python 81 | :linenos: 82 | 83 | import pyflux as pf 84 | 85 | # model = ... (specify a model) 86 | model.list_priors() 87 | model.adjust_prior(2,pf.Normal(0,1)) 88 | 89 | .. py:function:: fit(method,**kwargs) 90 | 91 | Estimates parameters for the model. Returns a Results object. **method** is an inference/estimation option; see Bayesian Inference and Classical Inference sections for options. If no **method** is provided then a default will be used. 92 | 93 | Optional arguments are specific to the **method** you choose - see the documentation for these methods for more detail. 94 | 95 | Here is example usage for :py:func:`fit`: 96 | 97 | .. code-block:: python 98 | :linenos: 99 | 100 | import pyflux as pf 101 | 102 | # model = ... (specify a model) 103 | model.fit("M-H",nsims=20000) 104 | 105 | .. py:function:: plot_fit(intervals,**kwargs) 106 | 107 | Graphs the fit of the model. **intervals** is a boolean; if true shows 95% C.I. intervals for the states. 108 | 109 | Optional arguments include **figsize** - the dimensions of the figure to plot - and **series_type** which has two options: *Filtered* or *Smoothed*. 110 | 111 | .. py:function:: plot_parameters(indices, figsize) 112 | 113 | Returns a plot of the parameters and their associated uncertainty. **indices** is a list referring to the parameter indices that you want ot plot. Figsize specifies how big the plot will be. 114 | 115 | .. py:function:: plot_predict(h,past_values,intervals,**kwargs) 116 | 117 | Plots predictions of the model. **h** is an int of how many steps ahead to predict. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 118 | 119 | Optional arguments include **figsize** - the dimensions of the figure to plot. 120 | 121 | .. py:function:: plot_predict_is(h,past_values,intervals,**kwargs) 122 | 123 | Plots in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 124 | 125 | Optional arguments include **figsize** - the dimensions of the figure to plot. 126 | 127 | .. py:function:: predict(h) 128 | 129 | Returns DataFrame of model predictions. **h** is an int of how many steps ahead to predict. 130 | 131 | .. py:function:: predict_is(h) 132 | 133 | Returns DataFrame of in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. 134 | 135 | .. py:function:: simulation_smoother(data,beta) 136 | 137 | Outputs a simulated state trajectory from a simulation smoother. Arguments are **data** : the data to simulate from - use self.data usually - and **beta** : the parameters to use. 138 | -------------------------------------------------------------------------------- /docs/build/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/build/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/build/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/comment-close.png -------------------------------------------------------------------------------- /docs/build/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/comment.png -------------------------------------------------------------------------------- /docs/build/_static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}} 2 | /*# sourceMappingURL=badge_only.css.map */ 3 | -------------------------------------------------------------------------------- /docs/build/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/down-pressed.png -------------------------------------------------------------------------------- /docs/build/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/down.png -------------------------------------------------------------------------------- /docs/build/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/file.png -------------------------------------------------------------------------------- /docs/build/_static/fonts/Inconsolata-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/Inconsolata-Bold.ttf -------------------------------------------------------------------------------- /docs/build/_static/fonts/Inconsolata-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/Inconsolata-Regular.ttf -------------------------------------------------------------------------------- /docs/build/_static/fonts/Lato-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/Lato-Bold.ttf -------------------------------------------------------------------------------- /docs/build/_static/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /docs/build/_static/fonts/RobotoSlab-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/RobotoSlab-Bold.ttf -------------------------------------------------------------------------------- /docs/build/_static/fonts/RobotoSlab-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/RobotoSlab-Regular.ttf -------------------------------------------------------------------------------- /docs/build/_static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/build/_static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/build/_static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/build/_static/js/theme.js: -------------------------------------------------------------------------------- 1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o"); 77 | 78 | // Add expand links to all parents of nested ul 79 | $('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () { 80 | var link = $(this); 81 | expand = $(''); 82 | expand.on('click', function (ev) { 83 | self.toggleCurrent(link); 84 | ev.stopPropagation(); 85 | return false; 86 | }); 87 | link.prepend(expand); 88 | }); 89 | }; 90 | 91 | nav.reset = function () { 92 | // Get anchor from URL and open up nested nav 93 | var anchor = encodeURI(window.location.hash); 94 | if (anchor) { 95 | try { 96 | var link = $('.wy-menu-vertical') 97 | .find('[href="' + anchor + '"]'); 98 | $('.wy-menu-vertical li.toctree-l1 li.current') 99 | .removeClass('current'); 100 | link.closest('li.toctree-l2').addClass('current'); 101 | link.closest('li.toctree-l3').addClass('current'); 102 | link.closest('li.toctree-l4').addClass('current'); 103 | } 104 | catch (err) { 105 | console.log("Error expanding nav for anchor", err); 106 | } 107 | } 108 | }; 109 | 110 | nav.onScroll = function () { 111 | this.winScroll = false; 112 | var newWinPosition = this.win.scrollTop(), 113 | winBottom = newWinPosition + this.winHeight, 114 | navPosition = this.navBar.scrollTop(), 115 | newNavPosition = navPosition + (newWinPosition - this.winPosition); 116 | if (newWinPosition < 0 || winBottom > this.docHeight) { 117 | return; 118 | } 119 | this.navBar.scrollTop(newNavPosition); 120 | this.winPosition = newWinPosition; 121 | }; 122 | 123 | nav.onResize = function () { 124 | this.winResize = false; 125 | this.winHeight = this.win.height(); 126 | this.docHeight = $(document).height(); 127 | }; 128 | 129 | nav.hashChange = function () { 130 | this.linkScroll = true; 131 | this.win.one('hashchange', function () { 132 | this.linkScroll = false; 133 | }); 134 | }; 135 | 136 | nav.toggleCurrent = function (elem) { 137 | var parent_li = elem.closest('li'); 138 | parent_li.siblings('li.current').removeClass('current'); 139 | parent_li.siblings().find('li.current').removeClass('current'); 140 | parent_li.find('> ul li.current').removeClass('current'); 141 | parent_li.toggleClass('current'); 142 | } 143 | 144 | return nav; 145 | }; 146 | 147 | module.exports.ThemeNav = ThemeNav(); 148 | 149 | if (typeof(window) != 'undefined') { 150 | window.SphinxRtdTheme = { StickyNav: module.exports.ThemeNav }; 151 | } 152 | 153 | },{"jquery":"jquery"}]},{},["sphinx-rtd-theme"]); 154 | -------------------------------------------------------------------------------- /docs/build/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/minus.png -------------------------------------------------------------------------------- /docs/build/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/plus.png -------------------------------------------------------------------------------- /docs/build/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #333333 } /* Generic.Output */ 19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #902000 } /* Keyword.Type */ 29 | .highlight .m { color: #208050 } /* Literal.Number */ 30 | .highlight .s { color: #4070a0 } /* Literal.String */ 31 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 32 | .highlight .nb { color: #007020 } /* Name.Builtin */ 33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #60add5 } /* Name.Constant */ 35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #007020 } /* Name.Exception */ 38 | .highlight .nf { color: #06287e } /* Name.Function */ 39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 50 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 51 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 52 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 53 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 54 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 55 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 56 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 57 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 58 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 59 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 60 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 61 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 62 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 63 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 64 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 65 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/build/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/up-pressed.png -------------------------------------------------------------------------------- /docs/build/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/_static/up.png -------------------------------------------------------------------------------- /docs/build/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/build/objects.inv -------------------------------------------------------------------------------- /docs/source/bayes.rst: -------------------------------------------------------------------------------- 1 | Bayesian Inference 2 | ================================== 3 | 4 | PyFlux supports Bayesian inference for all the model types on offer. 5 | 6 | Interface 7 | ---------- 8 | 9 | To view the current priors, you should print the model's latent variable object. For example: 10 | 11 | .. code-block:: python 12 | :linenos: 13 | 14 | import pyflux as pf 15 | 16 | # model = ... (specify a model) 17 | print(model.z) 18 | 19 | This will outline the current prior assumptions for each latent variable, as well as the variational approximate distribution that is assumed (if you are performing variational inference). To adjust priors, simply use the following method on your model object: 20 | 21 | .. py:function:: adjust_prior(index, prior) 22 | 23 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as :py:Class:`Normal`. 24 | 25 | Here is example usage for :py:func:`adjust_prior`: 26 | 27 | .. code-block:: python 28 | :linenos: 29 | 30 | import pyflux as pf 31 | 32 | # model = ... (specify a model) 33 | model.list_priors() 34 | model.adjust_prior(2, pf.Normal(0,1)) 35 | 36 | 37 | Methods 38 | ---------- 39 | 40 | There are a number of Bayesian inference options using the :py:func:`fit`: method. These can be chosen with the method argument. 41 | 42 | **Black-Box Variational Inference** 43 | 44 | Performs Black Box Variational Inference. Currently the fixed assumption is mean-field variational inference with normal approximate distributions. The gradient used in this implementation is the score function gradient. By default we use 24 samples for the gradient which is quite intense (other implementations use 2-8 samples). For your application, less samples may be as effective and quicker. One of the limitations of the implementation right now is BBVI here does not support using mini-batches of data. It is not clear yet how mini-batches would work with model types that have an underlying sequence of latent states - if it is shown to be effective, then this option will be included in future. 45 | 46 | .. code-block:: python 47 | :linenos: 48 | 49 | model.fit(method='BBVI', iterations='10000', optimizer='ADAM') 50 | 51 | * *batch_size* : (default : 24) number of Monte Carlo samples for the gradient 52 | * *iterations* : (default : 3000) number of iterations to run 53 | * *optimizer* : (default: RMSProp) RMSProp or ADAM (stochastic optimizers) 54 | * *map_start*: (default: True) if True, starts latent variables using a MAP/PML estimate 55 | * *mini_batch*: (default: None) if an int, then will sample mini-batches from the data of the size selected (e.g. 32). This option does not work for some model types. 56 | * *learning_rate*: (default: 0.001) the learning rate for the optimizer 57 | * *record_elbo* : (default: False) if True, will record ELBO during optimization, which can is stored as ``x.elbo_records`` for a ``BBVIResults()`` object ``x``. 58 | 59 | **Laplace Approximation** 60 | 61 | Performs a Laplace approximation on the posterior. 62 | 63 | .. code-block:: python 64 | :linenos: 65 | 66 | model.fit(method='Laplace') 67 | 68 | **Metropolis-Hastings** 69 | 70 | Performs Metropolis-Hastings MCMC. Currently uses 'one long chain' which is not ideal, but works okay for most of the models available. This method applies a warm-up period of half the number of simulations and applies thinning by removing every other sample to reduce correlation. 71 | 72 | .. code-block:: python 73 | :linenos: 74 | 75 | model.fit(method='M-H') 76 | 77 | * *map_start* : (default: True) whether to initialize starting values and the covariance matrix using MAP estimates and the Inverse Hessian 78 | * *nsims* : number of simulations for the chain 79 | 80 | **Penalized Maximum Likelihood** 81 | 82 | Provides a Maximum a posteriori (MAP) estimate. This estimate is not completely Bayesian as it is based on a 0/1 loss rather than a squared or absolute loss. It can be considered a form of modal approximation, when taken together with the Inverse Hessian matrix. 83 | 84 | .. code-block:: python 85 | :linenos: 86 | 87 | model.fit(method='PML') 88 | 89 | * *preopt_search* : (default : True) if True will use a preoptimization stage to find good starting values (if the model type has no available preoptimization method, this argument will be ignored). Turning this off will speed up optimization at the risk of obtaining an inferior solution. 90 | -------------------------------------------------------------------------------- /docs/source/classical.rst: -------------------------------------------------------------------------------- 1 | Classical Inference 2 | ================================== 3 | 4 | PyFlux supports classical methods of inference. These can be considered as point mass approximations to the full posterior. 5 | 6 | Methods 7 | ---------- 8 | 9 | There are a number of classical inference options using the :py:func:`fit`: method. These can be chosen with the method option. 10 | 11 | **Maximum Likelihood** 12 | 13 | Performs Maximum Likelihood estimation. 14 | 15 | .. code-block:: python 16 | :linenos: 17 | 18 | model.fit(method='MLE') 19 | 20 | * *preopt_search* : (default : True) if True will use a preoptimization stage to find good starting values (if the model type has no available preoptimization method, this argument will be ignored). Turning this off will speed up optimization at the risk of obtaining an inferior solution. 21 | 22 | **Ordinary Least Squares** 23 | 24 | Performs Ordinary Least Squares estimation. 25 | 26 | .. code-block:: python 27 | :linenos: 28 | 29 | model.fit(method='OLS') 30 | 31 | **Penalized Maximum Likelihood** 32 | 33 | From a frequentist perspective, PML can be viewed as a type of regularization on the coefficients. 34 | 35 | .. code-block:: python 36 | :linenos: 37 | 38 | model.fit(method='PML') 39 | 40 | * *preopt_search* : (default : True) if True will use a preoptimization stage to find good starting values (if the model type has no available preoptimization method, this argument will be ignored). Turning this off will speed up optimization at the risk of obtaining an inferior solution. -------------------------------------------------------------------------------- /docs/source/gasssm.rst: -------------------------------------------------------------------------------- 1 | GAS State Space models 2 | ================================== 3 | 4 | Example 5 | ---------- 6 | 7 | .. code-block:: python 8 | :linenos: 9 | 10 | import numpy as np 11 | import pyflux as pf 12 | import pandas as pd 13 | 14 | nile = pd.read_csv('https://vincentarelbundock.github.io/Rdatasets/csv/datasets/Nile.csv') 15 | nile.index = pd.to_datetime(nile['time'].values,format='%Y') 16 | 17 | model = pf.GASLLEV(data=nile, target='Nile', family=pf.GASt()) # local level 18 | 19 | USgrowth = pd.DataFrame(np.log(growthdata['VALUE'])) 20 | USgrowth.index = pd.to_datetime(growthdata['DATE']) 21 | USgrowth.columns = ['Logged US Real GDP'] 22 | 23 | model2 = pf.GASLLT(data=USgrowth, family=pf.GASt()) # local linear trend model 24 | 25 | Class Arguments 26 | ---------- 27 | 28 | The GAS local level (**GASLLEV**) and GAS local linear trend (**GASLLT**) models are of the following form: 29 | 30 | .. py:class:: GASLLEV(data, integ, target, family) 31 | 32 | .. py:attribute:: data 33 | 34 | pd.DataFrame or array-like : the time-series data 35 | 36 | .. py:attribute:: integ 37 | 38 | int : how many times to difference the time series (default: 0) 39 | 40 | .. py:attribute:: target 41 | 42 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 43 | 44 | .. py:attribute:: family 45 | 46 | a GAS family object; choices include GASExponential(), GASLaplace(), GASNormal(), GASPoisson(), GASSkewt(), GASt() 47 | 48 | .. py:class:: GASLLT(data, integ, target, family) 49 | 50 | .. py:attribute:: data 51 | 52 | pd.DataFrame or array-like : the time-series data 53 | 54 | .. py:attribute:: integ 55 | 56 | int : how many times to difference the time series (default: 0) 57 | 58 | .. py:attribute:: target 59 | 60 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 61 | 62 | .. py:attribute:: family 63 | 64 | a GAS family object; choices include GASExponential(), GASLaplace(), GASNormal(), GASPoisson(), GASSkewt(), GASt() 65 | 66 | Class Methods 67 | ---------- 68 | 69 | .. py:function:: adjust_prior(index, prior) 70 | 71 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as Normal(0,3). 72 | 73 | Here is example usage for :py:func:`adjust_prior`: 74 | 75 | .. code-block:: python 76 | :linenos: 77 | 78 | import pyflux as pf 79 | 80 | # model = ... (specify a model) 81 | model.list_priors() 82 | model.adjust_prior(2,pf.Normal(0,1)) 83 | 84 | .. py:function:: fit(method,**kwargs) 85 | 86 | Estimates latent variables for the model. Returns a Results object. **method** is an inference/estimation option; see Bayesian Inference and Classical Inference sections for options. If no **method** is provided then a default will be used. 87 | 88 | Optional arguments are specific to the **method** you choose - see the documentation for these methods for more detail. 89 | 90 | Here is example usage for :py:func:`fit`: 91 | 92 | .. code-block:: python 93 | :linenos: 94 | 95 | import pyflux as pf 96 | 97 | # model = ... (specify a model) 98 | model.fit("M-H",nsims=20000) 99 | 100 | .. py:function:: plot_fit(intervals,**kwargs) 101 | 102 | Graphs the fit of the model. **intervals** is a boolean; if true shows 95% C.I. intervals for the states. 103 | 104 | Optional arguments include **figsize** - the dimensions of the figure to plot - and **series_type** which has two options: *Filtered* or *Smoothed*. 105 | 106 | .. py:function:: plot_z(indices, figsize) 107 | 108 | Returns a plot of the latent variables and their associated uncertainty. **indices** is a list referring to the latent variable indices that you want ot plot. Figsize specifies how big the plot will be. 109 | 110 | .. py:function:: plot_predict(h, past_values, intervals, **kwargs) 111 | 112 | Plots predictions of the model. **h** is an int of how many steps ahead to predict. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 113 | 114 | Optional arguments include **figsize** - the dimensions of the figure to plot. 115 | 116 | .. py:function:: plot_predict_is(h, fit_once, **kwargs) 117 | 118 | Plots in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **fit_once** is a boolean specifying whether to fit the model once at the beginning of the period (True), or whether to fit after every step (False). 119 | 120 | Optional arguments include **figsize** - the dimensions of the figure to plot. 121 | 122 | .. py:function:: predict(h) 123 | 124 | Returns DataFrame of model predictions. **h** is an int of how many steps ahead to predict. 125 | 126 | .. py:function:: predict_is(h, fit_once) 127 | 128 | Returns DataFrame of in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **fit_once** is a boolean specifying whether to fit the model once at the beginning of the period (True), or whether to fit after every step (False). -------------------------------------------------------------------------------- /docs/source/gpnar.rst: -------------------------------------------------------------------------------- 1 | GP-NARX models 2 | ================================== 3 | 4 | Example 5 | ---------- 6 | 7 | .. code-block:: python 8 | :linenos: 9 | 10 | import numpy as np 11 | import pandas as pd 12 | import pyflux as pf 13 | 14 | USgrowth = #somequarterlyGDPgrowthdatahere 15 | model = pf.GPNARX(USgrowth, ar=4, kernel_type='OU') 16 | 17 | Class Arguments 18 | ---------- 19 | 20 | .. py:class:: GPNARX(data, ar, kernel_type, integ, target) 21 | 22 | .. py:attribute:: data 23 | 24 | pd.DataFrame or array-like : the time-series data 25 | 26 | .. py:attribute:: ar 27 | 28 | int : the number of autoregressive terms 29 | 30 | .. py:attribute:: kernel_type 31 | 32 | string : the type of kernel; one of ['SE','RQ','OU','Periodic','ARD'] 33 | 34 | .. py:attribute:: integ 35 | 36 | int : Specifies how many time to difference the time series. 37 | 38 | .. py:attribute:: target 39 | 40 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 41 | 42 | Class Methods 43 | ---------- 44 | 45 | .. py:function:: adjust_prior(index, prior) 46 | 47 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as Normal(0,3). 48 | 49 | Here is example usage for :py:func:`adjust_prior`: 50 | 51 | .. code-block:: python 52 | :linenos: 53 | 54 | import pyflux as pf 55 | 56 | # model = ... (specify a model) 57 | model.list_priors() 58 | model.adjust_prior(2,pf.Normal(0,1)) 59 | 60 | .. py:function:: fit(method,**kwargs) 61 | 62 | Estimates latent variables for the model. Returns a Results object. **method** is an inference/estimation option; see Bayesian Inference and Classical Inference sections for options. If no **method** is provided then a default will be used. 63 | 64 | Optional arguments are specific to the **method** you choose - see the documentation for these methods for more detail. 65 | 66 | Here is example usage for :py:func:`fit`: 67 | 68 | .. code-block:: python 69 | :linenos: 70 | 71 | import pyflux as pf 72 | 73 | # model = ... (specify a model) 74 | model.fit("M-H",nsims=20000) 75 | 76 | .. py:function:: plot_fit(**kwargs) 77 | 78 | Graphs the fit of the model. 79 | 80 | Optional arguments include **figsize** - the dimensions of the figure to plot. 81 | 82 | .. py:function:: plot_z(indices, figsize) 83 | 84 | Returns a plot of the latent variables and their associated uncertainty. **indices** is a list referring to the latent variable indices that you want ot plot. Figsize specifies how big the plot will be. 85 | 86 | .. py:function:: plot_predict(h,past_values,intervals,**kwargs) 87 | 88 | Plots predictions of the model. **h** is an int of how many steps ahead to predict. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 89 | 90 | Optional arguments include **figsize** - the dimensions of the figure to plot. 91 | 92 | .. py:function:: plot_predict_is(h, fit_once, **kwargs) 93 | 94 | Plots in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **fit_once** is a boolean specifying whether to fit the model once at the beginning of the period (True), or whether to fit after every step (False). 95 | 96 | Optional arguments include **figsize** - the dimensions of the figure to plot. 97 | 98 | .. py:function:: predict(h) 99 | 100 | Returns DataFrame of model predictions. **h** is an int of how many steps ahead to predict. 101 | 102 | .. py:function:: predict_is(h, fit_once) 103 | 104 | Returns DataFrame of in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **fit_once** is a boolean specifying whether to fit the model once at the beginning of the period (True), or whether to fit after every step (False). 105 | -------------------------------------------------------------------------------- /docs/source/modules.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/docs/source/modules.rst -------------------------------------------------------------------------------- /docs/source/ngssm.rst: -------------------------------------------------------------------------------- 1 | Non-Gaussian State Space models 2 | ================================== 3 | 4 | Example 5 | ---------- 6 | 7 | .. code-block:: python 8 | :linenos: 9 | 10 | import numpy as np 11 | import pyflux as pf 12 | import pandas as pd 13 | 14 | leicester = pd.read_csv('http://www.pyflux.com/notebooks/leicester_goals_scored.csv') 15 | leicester.columns= ["Time","Leicester Goals Scored"] 16 | 17 | model = pf.NLLEV.Poisson(data=leicester,target='Leicester Goals Scored') 18 | 19 | fb = DataReader('FB', 'yahoo', datetime(2015,5,1), datetime(2016,5,10)) 20 | returns = pd.DataFrame(np.diff(np.log(fb['Open'].values))) 21 | returns.index = fb.index.values[1:fb.index.values.shape[0]] 22 | returns.columns = ['Facebook Returns'] 23 | 24 | model2 = pf.NLLEV.t(data=returns,target='Close') 25 | 26 | Class Arguments 27 | ---------- 28 | 29 | The non-linear local level model (**NLLEV**) model has the options: **NLLEV.Exponential**, **NLLEV.Laplace**, **NLLEV.Poisson**, **NLLEV.t**, 30 | 31 | .. py:class:: NLLEV(data,integ,target) 32 | 33 | .. py:attribute:: data 34 | 35 | pd.DataFrame or array-like : the time-series data 36 | 37 | .. py:attribute:: integ 38 | 39 | int : how many times to difference the time series (default: 0) 40 | 41 | .. py:attribute:: target 42 | 43 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 44 | 45 | The non-linear local linear trend model (**NLLT**) model has the options: **NLLT.Exponential**, **NLLT.Laplace**, **NLLT.Poisson**, **NLLT.t**, 46 | 47 | .. py:class:: NLLT(data,integ,target) 48 | 49 | .. py:attribute:: data 50 | 51 | pd.DataFrame or array-like : the time-series data 52 | 53 | .. py:attribute:: integ 54 | 55 | int : how many times to difference the time series (default: 0) 56 | 57 | .. py:attribute:: target 58 | 59 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 60 | 61 | The non-linear dynamic regression model (**NDynLin**) model has the options: **NDynLin.Exponential**, **NDynLin.Laplace**, **NDynLin.Poisson**, **NDynLin.t**, 62 | 63 | .. py:class:: NDynLin(formula,data) 64 | 65 | .. py:attribute:: formula 66 | 67 | patsy notation string describing the regression 68 | 69 | .. py:attribute:: data 70 | 71 | pd.DataFrame or array-like : the time-series data 72 | 73 | 74 | Class Methods 75 | ---------- 76 | 77 | .. py:function:: adjust_prior(index, prior) 78 | 79 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as Normal(0,3). 80 | 81 | Here is example usage for :py:func:`adjust_prior`: 82 | 83 | .. code-block:: python 84 | :linenos: 85 | 86 | import pyflux as pf 87 | 88 | # model = ... (specify a model) 89 | model.list_priors() 90 | model.adjust_prior(2,pf.Normal(0,1)) 91 | 92 | .. py:function:: fit(method,iterations,step,**kwargs) 93 | 94 | Estimates parameters for the model using BBVI. Returns a Results object. **iterations** is the number of iterations for BBVI, and **step** is the step size for RMSProp (default : 0.001). 95 | 96 | Optional arguments include **animate** for the local level and local linear trend models: outputs an animation of stochastic optimization. 97 | 98 | Here is example usage for :py:func:`fit`: 99 | 100 | .. code-block:: python 101 | :linenos: 102 | 103 | import pyflux as pf 104 | 105 | # model = ... (specify a model) 106 | model.fit("M-H",nsims=20000) 107 | 108 | .. py:function:: plot_fit(intervals,**kwargs) 109 | 110 | Graphs the fit of the model. **intervals** is a boolean; if true shows 95% C.I. intervals for the states. 111 | 112 | Optional arguments include **figsize** - the dimensions of the figure to plot - and **series_type** which has two options: *Filtered* or *Smoothed*. 113 | 114 | .. py:function:: plot_parameters(indices, figsize) 115 | 116 | Returns a plot of the parameters and their associated uncertainty. **indices** is a list referring to the parameter indices that you want ot plot. Figsize specifies how big the plot will be. 117 | 118 | .. py:function:: plot_predict(h,past_values,intervals,**kwargs) 119 | 120 | Plots predictions of the model. **h** is an int of how many steps ahead to predict. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 121 | 122 | Optional arguments include **figsize** - the dimensions of the figure to plot. 123 | 124 | .. py:function:: plot_predict_is(h,past_values,intervals,**kwargs) 125 | 126 | Plots in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 127 | 128 | Optional arguments include **figsize** - the dimensions of the figure to plot. 129 | 130 | .. py:function:: predict(h) 131 | 132 | Returns DataFrame of model predictions. **h** is an int of how many steps ahead to predict. 133 | 134 | .. py:function:: predict_is(h) 135 | 136 | Returns DataFrame of in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. 137 | 138 | .. py:function:: simulation_smoother(data,beta,H,mu) 139 | 140 | Outputs a simulated state trajectory from a simulation smoother. Arguments are **data** : the data to simulate from - use self.data usually - and **beta** : the parameters to use, **H** is the measurement covariance matrix from an approximate Gaussian model, and **mu** is a measurement density constant from an approximate Gaussian model. -------------------------------------------------------------------------------- /docs/source/ssm.rst: -------------------------------------------------------------------------------- 1 | Gaussian State Space models 2 | ================================== 3 | 4 | Example 5 | ---------- 6 | 7 | .. code-block:: python 8 | :linenos: 9 | 10 | import numpy as np 11 | import pyflux as pf 12 | import pandas as pd 13 | 14 | nile = pd.read_csv('https://vincentarelbundock.github.io/Rdatasets/csv/datasets/Nile.csv') 15 | nile.index = pd.to_datetime(nile['time'].values,format='%Y') 16 | 17 | model = pf.LLEV(data=niles,target='Poisson') # local level 18 | 19 | USgrowth = pd.DataFrame(np.log(growthdata['VALUE'])) 20 | USgrowth.index = pd.to_datetime(growthdata['DATE']) 21 | USgrowth.columns = ['Logged US Real GDP'] 22 | 23 | model2 = pf.LLT(data=USgrowth) # local linear trend model 24 | 25 | Class Arguments 26 | ---------- 27 | 28 | The local level (**LLEV**) and local linear trend (**LLT**) models are of the following form: 29 | 30 | .. py:class:: LLEV(data,integ,target) 31 | 32 | .. py:attribute:: data 33 | 34 | pd.DataFrame or array-like : the time-series data 35 | 36 | .. py:attribute:: integ 37 | 38 | int : how many times to difference the time series (default: 0) 39 | 40 | .. py:attribute:: target 41 | 42 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 43 | 44 | .. py:class:: LLT(data,integ,target) 45 | 46 | .. py:attribute:: data 47 | 48 | pd.DataFrame or array-like : the time-series data 49 | 50 | .. py:attribute:: integ 51 | 52 | int : how many times to difference the time series (default: 0) 53 | 54 | .. py:attribute:: target 55 | 56 | string (data is DataFrame) or int (data is np.array) : which column to use as the time series. If None, the first column will be chosen as the data. 57 | 58 | The dynamic linear regression (**DynReg**) model is of the form: 59 | 60 | .. py:class:: DynReg(formula,data) 61 | 62 | .. py:attribute:: formula 63 | 64 | patsy notation string describing the regression 65 | 66 | .. py:attribute:: data 67 | 68 | pd.DataFrame or array-like : the time-series data 69 | 70 | 71 | Class Methods 72 | ---------- 73 | 74 | .. py:function:: adjust_prior(index, prior) 75 | 76 | Adjusts the priors of the model. **index** can be an int or a list. **prior** is a prior object, such as Normal(0,3). 77 | 78 | Here is example usage for :py:func:`adjust_prior`: 79 | 80 | .. code-block:: python 81 | :linenos: 82 | 83 | import pyflux as pf 84 | 85 | # model = ... (specify a model) 86 | model.list_priors() 87 | model.adjust_prior(2,pf.Normal(0,1)) 88 | 89 | .. py:function:: fit(method,**kwargs) 90 | 91 | Estimates parameters for the model. Returns a Results object. **method** is an inference/estimation option; see Bayesian Inference and Classical Inference sections for options. If no **method** is provided then a default will be used. 92 | 93 | Optional arguments are specific to the **method** you choose - see the documentation for these methods for more detail. 94 | 95 | Here is example usage for :py:func:`fit`: 96 | 97 | .. code-block:: python 98 | :linenos: 99 | 100 | import pyflux as pf 101 | 102 | # model = ... (specify a model) 103 | model.fit("M-H",nsims=20000) 104 | 105 | .. py:function:: plot_fit(intervals,**kwargs) 106 | 107 | Graphs the fit of the model. **intervals** is a boolean; if true shows 95% C.I. intervals for the states. 108 | 109 | Optional arguments include **figsize** - the dimensions of the figure to plot - and **series_type** which has two options: *Filtered* or *Smoothed*. 110 | 111 | .. py:function:: plot_parameters(indices, figsize) 112 | 113 | Returns a plot of the parameters and their associated uncertainty. **indices** is a list referring to the parameter indices that you want ot plot. Figsize specifies how big the plot will be. 114 | 115 | .. py:function:: plot_predict(h,past_values,intervals,**kwargs) 116 | 117 | Plots predictions of the model. **h** is an int of how many steps ahead to predict. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 118 | 119 | Optional arguments include **figsize** - the dimensions of the figure to plot. 120 | 121 | .. py:function:: plot_predict_is(h,past_values,intervals,**kwargs) 122 | 123 | Plots in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. **past_values** is an int of how many past values of the series to plot. **intervals** is a bool on whether to include confidence/credibility intervals or not. 124 | 125 | Optional arguments include **figsize** - the dimensions of the figure to plot. 126 | 127 | .. py:function:: predict(h) 128 | 129 | Returns DataFrame of model predictions. **h** is an int of how many steps ahead to predict. 130 | 131 | .. py:function:: predict_is(h) 132 | 133 | Returns DataFrame of in-sample rolling predictions for the model. **h** is an int of how many previous steps to simulate performance on. 134 | 135 | .. py:function:: simulation_smoother(data,beta) 136 | 137 | Outputs a simulated state trajectory from a simulation smoother. Arguments are **data** : the data to simulate from - use self.data usually - and **beta** : the parameters to use. 138 | -------------------------------------------------------------------------------- /pyflux/__check_build/__init__.py: -------------------------------------------------------------------------------- 1 | """ Module to give helpful messages to the user that did not 2 | compile package properly, 3 | This code was adapted from scikit-learn's check_build utility. 4 | """ 5 | import os 6 | 7 | PACKAGE_NAME = 'pyflux' 8 | 9 | INPLACE_MSG = """ 10 | It appears that you are importing {package} from within the source tree. 11 | Please either use an inplace install or try from another location. 12 | """.format(package=PACKAGE_NAME) 13 | 14 | STANDARD_MSG = """ 15 | If you have used an installer, please check that it is suited for your 16 | Python version, your operating system and your platform. 17 | """ 18 | 19 | ERROR_TEMPLATE = """{error} 20 | ___________________________________________________________________________ 21 | Contents of {local_dir}: 22 | {contents} 23 | ___________________________________________________________________________ 24 | It seems that the {package} has not been built correctly. 25 | If you have installed {package} from source, please do not forget 26 | to build the package before using it: run `python setup.py install` 27 | in the source directory. 28 | {msg}""" 29 | 30 | 31 | def raise_build_error(e): 32 | # Raise a comprehensible error and list the contents of the 33 | # directory to help debugging on the mailing list. 34 | local_dir = os.path.split(__file__)[0] 35 | msg = STANDARD_MSG 36 | if local_dir == "pyflux/__check_build": 37 | # Picking up the local install: this will work only if the 38 | # install is an 'inplace build' 39 | msg = INPLACE_MSG 40 | dir_content = list() 41 | for i, filename in enumerate(os.listdir(local_dir)): 42 | if ((i + 1) % 3): 43 | dir_content.append(filename.ljust(26)) 44 | else: 45 | dir_content.append(filename + '\n') 46 | contents = ''.join(dir_content).strip() 47 | raise ImportError(ERROR_TEMPLATE.format(error=e, 48 | local_dir=local_dir, 49 | contents=contents, 50 | package=PACKAGE_NAME, 51 | msg=msg)) 52 | 53 | try: 54 | from ._check_build import check_build 55 | except ImportError as e: 56 | raise_build_error(e) -------------------------------------------------------------------------------- /pyflux/__check_build/_check_build.pyx: -------------------------------------------------------------------------------- 1 | # Adapted from scikit-learn __check_build script (BSD-licensed) 2 | 3 | def check_build(): 4 | return -------------------------------------------------------------------------------- /pyflux/__check_build/setup.py: -------------------------------------------------------------------------------- 1 | # Adapted from scikit-learn __check_build script (BSD-licensed) 2 | 3 | import numpy 4 | 5 | 6 | def configuration(parent_package='', top_path=None): 7 | from numpy.distutils.misc_util import Configuration 8 | config = Configuration('__check_build', parent_package, top_path) 9 | config.add_extension('_check_build', 10 | sources=['_check_build.c']) 11 | return config 12 | 13 | 14 | if __name__ == '__main__': 15 | from numpy.distutils.core import setup 16 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.4.17" 2 | 3 | # Use of SETUP built-in adapted from scikit-learn's setup utility. 4 | try: 5 | __PYFLUX_SETUP__ 6 | except NameError: 7 | __PYFLUX_SETUP__ = False 8 | 9 | if __PYFLUX_SETUP__: 10 | sys.stderr.write('Partial import of PyFlux during the build process.\n') 11 | else: 12 | from . import __check_build 13 | 14 | from .arma import * 15 | from .var import * 16 | from .ensembles import * 17 | from .families import * 18 | from .gas import * 19 | from .garch import * 20 | from .gpnarx import * 21 | from .inference import * 22 | from .ssm import * 23 | from .covariances import * 24 | from .output import * 25 | from .tests import * 26 | -------------------------------------------------------------------------------- /pyflux/arma/__init__.py: -------------------------------------------------------------------------------- 1 | from .arma import ARIMA 2 | from .arimax import ARIMAX 3 | from .nnar import NNAR -------------------------------------------------------------------------------- /pyflux/arma/arma_recursions.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | cimport cython 4 | 5 | cdef inline double double_max(double a, double b): return a if a >= b else b 6 | cdef inline double double_min(double a, double b): return a if a <= b else b 7 | 8 | @cython.boundscheck(False) 9 | @cython.wraparound(False) 10 | @cython.cdivision(True) 11 | def arima_recursion(double[:] parameters, double[:] mu, double[:] link_mu, double[:] Y, 12 | int max_lag, int Y_len, int ar_terms, int ma_terms): 13 | """ 14 | Cythonized moving average recursion for ARIMA model class 15 | """ 16 | cdef Py_ssize_t t, k 17 | 18 | for t in range(max_lag, Y_len): 19 | for k in range(0, ma_terms): 20 | mu[t] += parameters[1+ar_terms+k]*(Y[t-1-k]-link_mu[t-1-k]) 21 | 22 | return mu 23 | 24 | @cython.boundscheck(False) 25 | @cython.wraparound(False) 26 | @cython.cdivision(True) 27 | def arima_recursion_poisson(double[:] parameters, double[:] mu, double[:] link_mu, double[:] Y, 28 | int max_lag, int Y_len, int ar_terms, int ma_terms): 29 | """ 30 | Cythonized moving average recursion for ARIMA model class - Poisson 31 | """ 32 | cdef Py_ssize_t t, k 33 | 34 | for t in range(max_lag, Y_len): 35 | for k in range(0, ma_terms): 36 | mu[t] += parameters[1+ar_terms+k]*(double_min(double_max(Y[t-1-k]-link_mu[t-1-k],-1000),1000)) 37 | 38 | return mu 39 | 40 | @cython.boundscheck(False) 41 | @cython.wraparound(False) 42 | @cython.cdivision(True) 43 | def arima_recursion_normal(double[:] parameters, double[:] mu, double[:] Y, 44 | int max_lag, int Y_len, int ar_terms, int ma_terms): 45 | """ 46 | Cythonized moving average recursion for ARIMA model class - Gaussian errors 47 | """ 48 | cdef Py_ssize_t t, k 49 | 50 | for t in range(max_lag, Y_len): 51 | for k in range(0, ma_terms): 52 | mu[t] += parameters[1+ar_terms+k]*(Y[t-1-k]-mu[t-1-k]) 53 | 54 | return mu 55 | 56 | @cython.boundscheck(False) 57 | @cython.wraparound(False) 58 | @cython.cdivision(True) 59 | def arimax_recursion(double[:] parameters, double[:] mu, double[:] Y, 60 | int max_lag, int Y_len, int ar_terms, int ma_terms): 61 | """ 62 | Cythonized moving average recursion for ARIMAX model class 63 | """ 64 | cdef Py_ssize_t t, k 65 | 66 | for t in range(max_lag, Y_len): 67 | for k in range(0, ma_terms): 68 | mu[t] += parameters[ar_terms+k]*(Y[t-1-k]-mu[t-1-k]) 69 | 70 | return mu -------------------------------------------------------------------------------- /pyflux/arma/nn_architecture.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | cimport cython 4 | 5 | @cython.boundscheck(False) 6 | @cython.wraparound(False) 7 | @cython.cdivision(True) 8 | def neural_network_tanh(double[:] Y, np.ndarray[double,ndim=2,mode="c"] X, double[:] z, int units, int layers, int ar): 9 | """ 10 | Cythonized neural network 11 | """ 12 | cdef Py_ssize_t unit, layer 13 | cdef int params_used 14 | 15 | # Input layer 16 | cdef np.ndarray[double,ndim=2,mode="c"] first_layer_output = np.zeros((X.shape[1], units)) 17 | for unit in range(units): 18 | first_layer_output[:,unit] = np.tanh(np.matmul(np.transpose(X), z[unit*(ar+1):((unit+1)*(ar+1))])) 19 | 20 | params_used = ((units)*(ar+1)) 21 | 22 | hidden_layer_output = np.zeros((X.shape[1], units, layers-1)) 23 | for layer in range(1, layers): 24 | for unit in range(units): 25 | if layer == 1: 26 | hidden_layer_output[:, unit,layer-1] = np.tanh(np.matmul(first_layer_output, 27 | z[params_used+unit*(units)+((layer-1)*units**2):((params_used+(unit+1)*units)+((layer-1)*units**2))])) 28 | else: 29 | hidden_layer_output[:, unit,layer-1] = np.tanh(np.matmul(hidden_layer_output[:,:,layer-1], 30 | z[params_used+unit*(units)+((layer-1)*units**2):((params_used+(unit+1)*units)+((layer-1)*units**2))])) 31 | 32 | params_used = params_used + (layers-1)*units**2 33 | 34 | # Output layer 35 | if layers == 1: 36 | mu = np.matmul(first_layer_output, z[params_used:params_used+units]) 37 | else: 38 | mu = np.matmul(hidden_layer_output[:,:,-1], z[params_used:params_used+units]) 39 | 40 | return mu 41 | 42 | @cython.boundscheck(False) 43 | @cython.wraparound(False) 44 | @cython.cdivision(True) 45 | def neural_network_tanh_mb(double[:] Y, np.ndarray[double, ndim=2] X, double[:] z, int units, int layers, int ar): 46 | """ 47 | Cythonized neural network with minibatch 48 | """ 49 | cdef Py_ssize_t unit, layer 50 | cdef int params_used 51 | 52 | # Input layer 53 | cdef np.ndarray[double,ndim=2,mode="c"] first_layer_output = np.zeros((X.shape[1], units)) 54 | for unit in range(units): 55 | first_layer_output[:,unit] = np.tanh(np.matmul(np.transpose(X), z[unit*(ar+1):((unit+1)*(ar+1))])) 56 | 57 | params_used = ((units)*(ar+1)) 58 | 59 | hidden_layer_output = np.zeros((X.shape[1], units, layers-1)) 60 | for layer in range(1, layers): 61 | for unit in range(units): 62 | if layer == 1: 63 | hidden_layer_output[:, unit,layer-1] = np.tanh(np.matmul(first_layer_output, 64 | z[params_used+unit*(units)+((layer-1)*units**2):((params_used+(unit+1)*units)+((layer-1)*units**2))])) 65 | else: 66 | hidden_layer_output[:, unit,layer-1] = np.tanh(np.matmul(hidden_layer_output[:,:,layer-1], 67 | z[params_used+unit*(units)+((layer-1)*units**2):((params_used+(unit+1)*units)+((layer-1)*units**2))])) 68 | 69 | params_used = params_used + (layers-1)*units**2 70 | 71 | # Output layer 72 | if layers == 1: 73 | mu = np.matmul(first_layer_output, z[params_used:params_used+units]) 74 | else: 75 | mu = np.matmul(hidden_layer_output[:,:,-1], z[params_used:params_used+units]) 76 | 77 | return mu -------------------------------------------------------------------------------- /pyflux/arma/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def configuration(parent_package='', top_path=None): 5 | from numpy.distutils.misc_util import Configuration 6 | 7 | config = Configuration('arma', parent_package, top_path) 8 | 9 | config.add_extension('arma_recursions', 10 | sources=['arma_recursions.c']) 11 | config.add_extension('nn_architecture', 12 | sources=['nn_architecture.c']) 13 | 14 | config.add_subpackage('tests') 15 | 16 | return config 17 | 18 | 19 | if __name__ == '__main__': 20 | from numpy.distutils.core import setup 21 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/arma/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/arma/tests/__init__.py -------------------------------------------------------------------------------- /pyflux/arma/tests/test_arima_inference.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from pyflux.arma import ARIMA 3 | 4 | noise = np.random.normal(0,1,100) 5 | data = np.zeros(100) 6 | 7 | for i in range(1,len(data)): 8 | data[i] = 0.9*data[i-1] + noise[i] 9 | 10 | 11 | def test_bbvi(): 12 | """ 13 | Tests an ARIMA model estimated with BBVI and that the length of the latent variable 14 | list is correct, and that the estimated latent variables are not nan 15 | """ 16 | model = ARIMA(data=data, ar=1, ma=1) 17 | x = model.fit('BBVI',iterations=100, quiet_progress=True) 18 | assert(len(model.latent_variables.z_list) == 4) 19 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 20 | assert(len(lvs[np.isnan(lvs)]) == 0) 21 | 22 | def test_bbvi_mini_batch(): 23 | """ 24 | Tests an ARIMA model estimated with BBVI and that the length of the latent variable 25 | list is correct, and that the estimated latent variables are not nan 26 | """ 27 | model = ARIMA(data=data, ar=1, ma=1) 28 | x = model.fit('BBVI',iterations=100, quiet_progress=True, mini_batch=32) 29 | assert(len(model.latent_variables.z_list) == 4) 30 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 31 | assert(len(lvs[np.isnan(lvs)]) == 0) 32 | 33 | def test_bbvi_elbo(): 34 | """ 35 | Tests that the ELBO increases 36 | """ 37 | model = ARIMA(data=data, ar=1, ma=1) 38 | x = model.fit('BBVI',iterations=100, quiet_progress=True, record_elbo=True) 39 | assert(x.elbo_records[-1]>x.elbo_records[0]) 40 | 41 | def test_bbvi_mini_batch_elbo(): 42 | """ 43 | Tests that the ELBO increases 44 | """ 45 | model = ARIMA(data=data, ar=1, ma=1) 46 | x = model.fit('BBVI',iterations=100, quiet_progress=True, mini_batch=32, record_elbo=True) 47 | assert(x.elbo_records[-1]>x.elbo_records[0]) 48 | 49 | def test_mh(): 50 | """ 51 | Tests an ARIMA model estimated with Metropolis-Hastings and that the length of the 52 | latent variable list is correct, and that the estimated latent variables are not nan 53 | """ 54 | model = ARIMA(data=data, ar=1, ma=1) 55 | x = model.fit('M-H', nsims=200, quiet_progress=True) 56 | assert(len(model.latent_variables.z_list) == 4) 57 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 58 | assert(len(lvs[np.isnan(lvs)]) == 0) 59 | 60 | def test_laplace(): 61 | """ 62 | Tests an ARIMA model estimated with Laplace approximation and that the length of the 63 | latent variable list is correct, and that the estimated latent variables are not nan 64 | """ 65 | model = ARIMA(data=data, ar=1, ma=1) 66 | x = model.fit('Laplace') 67 | assert(len(model.latent_variables.z_list) == 4) 68 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 69 | assert(len(lvs[np.isnan(lvs)]) == 0) 70 | 71 | def test_pml(): 72 | """ 73 | Tests a PML model estimated with Laplace approximation and that the length of the 74 | latent variable list is correct, and that the estimated latent variables are not nan 75 | """ 76 | model = ARIMA(data=data, ar=1, ma=1) 77 | x = model.fit('PML') 78 | assert(len(model.latent_variables.z_list) == 4) 79 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 80 | assert(len(lvs[np.isnan(lvs)]) == 0) 81 | -------------------------------------------------------------------------------- /pyflux/arma/tests/test_arimax_inference.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | from pyflux.arma import ARIMAX 4 | 5 | # Set up some data to use for the tests 6 | 7 | noise = np.random.normal(0,1,100) 8 | y = np.zeros(100) 9 | x1 = np.random.normal(0,1,100) 10 | x2 = np.random.normal(0,1,100) 11 | 12 | for i in range(1,len(y)): 13 | y[i] = 0.9*y[i-1] + noise[i] + 0.1*x1[i] - 0.3*x2[i] 14 | 15 | data = pd.DataFrame([y,x1,x2]).T 16 | data.columns = ['y', 'x1', 'x2'] 17 | 18 | y_oos = np.random.normal(0,1,30) 19 | x1_oos = np.random.normal(0,1,30) 20 | x2_oos = np.random.normal(0,1,30) 21 | 22 | data_oos = pd.DataFrame([y_oos,x1_oos,x2_oos]).T 23 | data_oos.columns = ['y', 'x1', 'x2'] 24 | 25 | 26 | def test_bbvi(): 27 | """ 28 | Tests an ARIMAX model estimated with BBVI, and tests that the latent variable 29 | vector length is correct, and that value are not nan 30 | """ 31 | model = ARIMAX(formula="y ~ x1", data=data, ar=1, ma=1) 32 | x = model.fit('BBVI',iterations=100, quiet_progress=True) 33 | assert(len(model.latent_variables.z_list) == 5) 34 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 35 | assert(len(lvs[np.isnan(lvs)]) == 0) 36 | 37 | def test_bbvi_mini_batch(): 38 | """ 39 | Tests an ARIMA model estimated with BBVI and that the length of the latent variable 40 | list is correct, and that the estimated latent variables are not nan 41 | """ 42 | model = ARIMAX(formula="y ~ x1", data=data, ar=1, ma=1) 43 | x = model.fit('BBVI',iterations=100, quiet_progress=True, mini_batch=32) 44 | assert(len(model.latent_variables.z_list) == 5) 45 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 46 | assert(len(lvs[np.isnan(lvs)]) == 0) 47 | 48 | def test_bbvi_elbo(): 49 | """ 50 | Tests that the ELBO increases 51 | """ 52 | model = ARIMAX(formula="y ~ x1", data=data, ar=1, ma=1) 53 | x = model.fit('BBVI',iterations=200, record_elbo=True, quiet_progress=True) 54 | assert(x.elbo_records[-1]>x.elbo_records[0]) 55 | 56 | def test_bbvi_mini_batch_elbo(): 57 | """ 58 | Tests that the ELBO increases 59 | """ 60 | model = ARIMAX(formula="y ~ x1", data=data, ar=1, ma=1) 61 | x = model.fit('BBVI',iterations=200, mini_batch=32, record_elbo=True, quiet_progress=True) 62 | assert(x.elbo_records[-1]>x.elbo_records[0]) 63 | 64 | def test_mh(): 65 | """ 66 | Tests an ARIMAX model estimated with Metropolis-Hastings, and tests that the latent variable 67 | vector length is correct, and that value are not nan 68 | """ 69 | model = ARIMAX(formula="y ~ x1", data=data, ar=1, ma=1) 70 | x = model.fit('M-H', nsims=200, quiet_progress=True) 71 | assert(len(model.latent_variables.z_list) == 5) 72 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 73 | assert(len(lvs[np.isnan(lvs)]) == 0) 74 | 75 | def test_laplace(): 76 | """ 77 | Tests an ARIMAX model estimated with Laplace approximation, and tests that the latent variable 78 | vector length is correct, and that value are not nan 79 | """ 80 | model = ARIMAX(formula="y ~ x1", data=data, ar=1, ma=1) 81 | x = model.fit('Laplace') 82 | assert(len(model.latent_variables.z_list) == 5) 83 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 84 | assert(len(lvs[np.isnan(lvs)]) == 0) 85 | 86 | def test_pml(): 87 | """ 88 | Tests an ARIMAX model estimated with PML, and tests that the latent variable 89 | vector length is correct, and that value are not nan 90 | """ 91 | model = ARIMAX(formula="y ~ x1", data=data, ar=1, ma=1) 92 | x = model.fit('PML') 93 | assert(len(model.latent_variables.z_list) == 5) 94 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 95 | assert(len(lvs[np.isnan(lvs)]) == 0) 96 | 97 | 98 | 99 | def test_2_bbvi(): 100 | """ 101 | Tests an ARIMAX model estimated with BBVI, with multiple predictors, and 102 | tests that the latent variable vector length is correct, and that value are not nan 103 | """ 104 | model = ARIMAX(formula="y ~ x1 + x2", data=data, ar=1, ma=1) 105 | x = model.fit('BBVI',iterations=100, quiet_progress=True) 106 | assert(len(model.latent_variables.z_list) == 6) 107 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 108 | assert(len(lvs[np.isnan(lvs)]) == 0) 109 | 110 | def test_2_bbvi_mini_batch(): 111 | """ 112 | Tests an ARIMA model estimated with BBVI and that the length of the latent variable 113 | list is correct, and that the estimated latent variables are not nan 114 | """ 115 | model = ARIMAX(formula="y ~ x1 + x2", data=data, ar=1, ma=1) 116 | x = model.fit('BBVI',iterations=100, quiet_progress=True, mini_batch=32) 117 | assert(len(model.latent_variables.z_list) == 6) 118 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 119 | assert(len(lvs[np.isnan(lvs)]) == 0) 120 | 121 | def test_2_mh(): 122 | """ 123 | Tests an ARIMAX model estimated with MEtropolis-Hastings, with multiple predictors, and 124 | tests that the latent variable vector length is correct, and that value are not nan 125 | """ 126 | model = ARIMAX(formula="y ~ x1 + x2", data=data, ar=1, ma=1) 127 | x = model.fit('M-H', nsims=200, quiet_progress=True) 128 | assert(len(model.latent_variables.z_list) == 6) 129 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 130 | assert(len(lvs[np.isnan(lvs)]) == 0) 131 | 132 | def test_2_laplace(): 133 | """ 134 | Tests an ARIMAX model estimated with Laplace, with multiple predictors, and 135 | tests that the latent variable vector length is correct, and that value are not nan 136 | """ 137 | model = ARIMAX(formula="y ~ x1 + x2", data=data, ar=1, ma=1) 138 | x = model.fit('Laplace') 139 | assert(len(model.latent_variables.z_list) == 6) 140 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 141 | assert(len(lvs[np.isnan(lvs)]) == 0) 142 | 143 | def test_2_pml(): 144 | """ 145 | Tests an ARIMAX model estimated with PML, with multiple predictors, and 146 | tests that the latent variable vector length is correct, and that value are not nan 147 | """ 148 | model = ARIMAX(formula="y ~ x1 + x2", data=data, ar=1, ma=1) 149 | x = model.fit('PML') 150 | assert(len(model.latent_variables.z_list) == 6) 151 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 152 | assert(len(lvs[np.isnan(lvs)]) == 0) 153 | 154 | -------------------------------------------------------------------------------- /pyflux/covariances.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from math import sqrt 3 | 4 | # Returns sample autocovariance of two np arrays (stationarity assumed) 5 | def cov(x, lag=0): 6 | if lag >= x.shape[0]: 7 | raise ValueError("Not enough observations to compute autocovariance") 8 | else: 9 | x1 = x[lag:x.shape[0]] 10 | x2 = x[0:(x.shape[0]-lag)] 11 | return np.sum((x1-np.mean(x))*(x2-np.mean(x)))/x1.shape[0] 12 | 13 | # Returns sample autocorrelation function of an np array (stationarity assumed) 14 | def acf(x, lag=0): 15 | x1 = x[lag:x.shape[0]] 16 | return cov(x,lag=lag)/cov(x,lag=0) 17 | 18 | def acf_plot(data, max_lag=10): 19 | import matplotlib.pyplot as plt 20 | import seaborn as sns 21 | 22 | plt.figure(figsize=(15,5)) 23 | ax = plt.subplot(111) 24 | plt.bar(range(1,10), [acf(data,lag) for lag in range(1,10)]) 25 | plt.xlabel("Lag") 26 | plt.ylabel("Autocorrelation") 27 | plt.title("ACF Plot") 28 | plt.axhline(0+2/np.sqrt(len(data)), linestyle="-", color="black") 29 | plt.axhline(0-2/np.sqrt(len(data)), linestyle="-", color="black") 30 | plt.show() -------------------------------------------------------------------------------- /pyflux/data_check.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def data_check(data,target): 5 | """ Checks data type 6 | 7 | Parameters 8 | ---------- 9 | data : pd.DataFrame or np.array 10 | Field to specify the time series data that will be used. 11 | 12 | target : int or str 13 | Target column 14 | 15 | Returns 16 | ---------- 17 | transformed_data : np.array 18 | Raw data array for use in the model 19 | 20 | data_name : str 21 | Name of the data 22 | 23 | is_pandas : Boolean 24 | True if pandas data, else numpy 25 | 26 | data_index : np.array 27 | The time indices for the data 28 | """ 29 | 30 | # Check pandas or numpy 31 | if isinstance(data, pd.DataFrame) or isinstance(data, pd.core.frame.DataFrame): 32 | data_index = data.index 33 | if target is None: 34 | transformed_data = data.ix[:,0].values 35 | data_name = str(data.columns.values[0]) 36 | else: 37 | transformed_data = data[target].values 38 | data_name = str(target) 39 | is_pandas = True 40 | 41 | elif isinstance(data, np.ndarray): 42 | data_name = "Series" 43 | is_pandas = False 44 | if any(isinstance(i, np.ndarray) for i in data): 45 | if target is None: 46 | transformed_data = data[0] 47 | data_index = list(range(len(data[0]))) 48 | else: 49 | transformed_data = data[target] 50 | data_index = list(range(len(data[target]))) 51 | else: 52 | transformed_data = data 53 | data_index = list(range(len(data))) 54 | else: 55 | raise Exception("The data input is not pandas or numpy compatible!") 56 | 57 | return transformed_data, data_name, is_pandas, data_index 58 | 59 | def mv_data_check(data,check): 60 | # Check pandas or numpy 61 | 62 | if isinstance(data, pd.DataFrame): 63 | data_index = data.index 64 | transformed_data = data.values 65 | data_name = data.columns.values 66 | is_pandas = True 67 | 68 | elif isinstance(data, np.ndarray): 69 | data_name = np.asarray(range(1,len(data[0])+1)) 70 | is_pandas = False 71 | transformed_data = data 72 | data_index = list(range(len(data[0]))) 73 | 74 | else: 75 | raise Exception("The data input is not pandas or numpy compatible!") 76 | 77 | return transformed_data, data_name, is_pandas, data_index 78 | -------------------------------------------------------------------------------- /pyflux/ensembles/__init__.py: -------------------------------------------------------------------------------- 1 | from .mixture_of_experts import Aggregate -------------------------------------------------------------------------------- /pyflux/families/__init__.py: -------------------------------------------------------------------------------- 1 | from .cauchy import Cauchy 2 | from .exponential import Exponential 3 | from .flat import Flat 4 | from .inverse_gamma import InverseGamma 5 | from .inverse_wishart import InverseWishart 6 | from .laplace import Laplace 7 | from .normal import Normal 8 | from .poisson import Poisson 9 | from .skewt import Skewt 10 | from .t import t 11 | from .truncated_normal import TruncatedNormal 12 | -------------------------------------------------------------------------------- /pyflux/families/family.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class Family(object): 4 | 5 | def __init__(self, transform=None, **kwargs): 6 | """ 7 | Parameters 8 | ---------- 9 | transform : str 10 | Whether to apply a transformation - e.g. 'exp' or 'logit' 11 | """ 12 | self.transform_name = transform 13 | self.transform = self.transform_define(transform) 14 | self.itransform = self.itransform_define(transform) 15 | self.itransform_name = self.itransform_name_define(transform) 16 | 17 | @staticmethod 18 | def ilogit(x): 19 | return 1.0/(1.0+np.exp(-x)) 20 | 21 | @staticmethod 22 | def logit(x): 23 | return np.log(x) - np.log(1.0 - x) 24 | 25 | @staticmethod 26 | def transform_define(transform): 27 | """ 28 | This function links the user's choice of transformation with the associated numpy function 29 | """ 30 | if transform == 'tanh': 31 | return np.tanh 32 | elif transform == 'exp': 33 | return np.exp 34 | elif transform == 'logit': 35 | return Family.ilogit 36 | elif transform is None: 37 | return np.array 38 | else: 39 | return None 40 | 41 | @staticmethod 42 | def itransform_define(transform): 43 | """ 44 | This function links the user's choice of transformation with its inverse 45 | """ 46 | if transform == 'tanh': 47 | return np.arctanh 48 | elif transform == 'exp': 49 | return np.log 50 | elif transform == 'logit': 51 | return Family.logit 52 | elif transform is None: 53 | return np.array 54 | else: 55 | return None 56 | 57 | @staticmethod 58 | def itransform_name_define(transform): 59 | """ 60 | This function is used for model results table, displaying any transformations performed 61 | """ 62 | if transform == 'tanh': 63 | return 'arctanh' 64 | elif transform == 'exp': 65 | return 'log' 66 | elif transform == 'logit': 67 | return 'ilogit' 68 | elif transform is None: 69 | return '' 70 | else: 71 | return None 72 | -------------------------------------------------------------------------------- /pyflux/families/flat.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.stats as ss 3 | import scipy.special as sp 4 | 5 | from .family import Family 6 | 7 | 8 | class Flat(Family): 9 | """ 10 | Flat Distribution 11 | ---- 12 | This class contains methods relating to the flat prior distribution for time series. 13 | """ 14 | 15 | def __init__(self, transform=None, **kwargs): 16 | """ 17 | Parameters 18 | ---------- 19 | transform : str 20 | Whether to apply a transformation - e.g. 'exp' or 'logit' 21 | """ 22 | super(Flat, self).__init__(transform) 23 | self.covariance_prior = False 24 | 25 | def logpdf(self, mu): 26 | """ 27 | Log PDF for Flat prior 28 | 29 | Parameters 30 | ---------- 31 | mu : float 32 | Latent variable for which the prior is being formed over 33 | 34 | Returns 35 | ---------- 36 | - log(p(mu)) 37 | """ 38 | return 0.0 39 | -------------------------------------------------------------------------------- /pyflux/families/inverse_gamma.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.stats as ss 3 | import scipy.special as sp 4 | 5 | from .family import Family 6 | 7 | 8 | class InverseGamma(Family): 9 | """ 10 | Inverse Gamma Distribution 11 | ---- 12 | This class contains methods relating to the inverse gamma distribution for time series. 13 | """ 14 | 15 | def __init__(self, alpha, beta, transform=None, **kwargs): 16 | """ 17 | Parameters 18 | ---------- 19 | alpha : float 20 | Alpha parameter for the Inverse Gamma distribution 21 | 22 | beta : float 23 | Beta parameter for the Inverse Gamma distribution 24 | 25 | transform : str 26 | Whether to apply a transformation - e.g. 'exp' or 'logit' 27 | """ 28 | super(InverseGamma, self).__init__(transform) 29 | self.covariance_prior = False 30 | self.alpha = alpha 31 | self.beta = beta 32 | 33 | def logpdf(self, x): 34 | """ 35 | Log PDF for Inverse Gamma prior 36 | 37 | Parameters 38 | ---------- 39 | x : float 40 | Latent variable for which the prior is being formed over 41 | 42 | Returns 43 | ---------- 44 | - log(p(x)) 45 | """ 46 | if self.transform is not None: 47 | x = self.transform(x) 48 | return (-self.alpha-1)*np.log(x) - (self.beta/float(x)) 49 | 50 | def pdf(self, x): 51 | """ 52 | PDF for Inverse Gamma prior 53 | 54 | Parameters 55 | ---------- 56 | x : float 57 | Latent variable for which the prior is being formed over 58 | 59 | Returns 60 | ---------- 61 | - p(x) 62 | """ 63 | if self.transform is not None: 64 | x = self.transform(x) 65 | return (x**(-self.alpha-1))*np.exp(-(self.beta/float(x))) -------------------------------------------------------------------------------- /pyflux/families/inverse_wishart.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.stats as ss 3 | import scipy.special as sp 4 | 5 | from .. import inference as ifr 6 | 7 | from .family import Family 8 | 9 | from scipy.stats import invwishart 10 | 11 | 12 | class InverseWishart(Family): 13 | """ 14 | Inverse Wishart Distribution 15 | ---- 16 | This class contains methods relating to the inverse wishart distribution for time series. 17 | """ 18 | 19 | def __init__(self, v, Psi, transform=None, **kwargs): 20 | """ 21 | Parameters 22 | ---------- 23 | v : float 24 | Nu parameter for the Inverse Wishart distribution 25 | 26 | Psi : float 27 | Psi parameter for the Inverse Wishart distribution 28 | 29 | transform : str 30 | Whether to apply a transformation - e.g. 'exp' or 'logit' 31 | """ 32 | super(InverseWishart, self).__init__(transform) 33 | 34 | self.covariance_prior = True 35 | self.v = v 36 | self.Psi = Psi 37 | 38 | def logpdf(self, X): 39 | """ 40 | Log PDF for Inverse Wishart prior 41 | 42 | Parameters 43 | ---------- 44 | X : float 45 | Covariance matrix for which the prior is being formed over 46 | 47 | Returns 48 | ---------- 49 | - log(p(X)) 50 | """ 51 | return invwishart.logpdf(X, df=self.v, scale=self.Psi) 52 | 53 | def pdf(self, X): 54 | """ 55 | PDF for Inverse Wishart prior 56 | 57 | Parameters 58 | ---------- 59 | x : float 60 | Covariance matrix for which the prior is being formed over 61 | 62 | Returns 63 | ---------- 64 | - p(x) 65 | """ 66 | return invwishart.pdf(X, df=self.v, scale=self.Psi) -------------------------------------------------------------------------------- /pyflux/families/poisson_kalman_recursions.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | cimport cython 4 | 5 | # TO DO: REFACTOR AND COMBINE THESE SCRIPTS TO USE A SINGLE KALMAN FILTER/SMOOTHER SCRIPT 6 | # Main differences between these functions are whether they treat certain matrices as 7 | # constant or not 8 | 9 | def nl_univariate_KFS(y,Z,H,T,Q,R,mu): 10 | """ Kalman filtering and smoothing for univariate time series 11 | Notes 12 | ---------- 13 | y = mu + Za_t + e_t where e_t ~ N(0,H) MEASUREMENT EQUATION 14 | a_t = Ta_t-1 + Rn_t where n_t ~ N(0,Q) STATE EQUATION 15 | Parameters 16 | ---------- 17 | y : np.array 18 | The time series data 19 | Z : np.array 20 | Design matrix for state matrix a 21 | H : np.array 22 | Covariance matrix for measurement noise 23 | T : np.array 24 | Design matrix for lagged state matrix in state equation 25 | Q : np.array 26 | Covariance matrix for state evolution noise 27 | R : np.array 28 | Scale matrix for state equation covariance matrix 29 | mu : float 30 | Constant term for measurement equation 31 | Returns 32 | ---------- 33 | alpha : np.array 34 | Smoothed states 35 | V : np.array 36 | Variance of smoothed states 37 | """ 38 | 39 | # Filtering matrices 40 | a = np.zeros((T.shape[0],y.shape[0]+1)) # Initialization 41 | P = np.ones((a.shape[0],a.shape[0],y.shape[0]+1))*(10**7) # diffuse prior asumed 42 | L = np.zeros((a.shape[0],a.shape[0],y.shape[0]+1)) 43 | K = np.zeros((a.shape[0],y.shape[0])) 44 | v = np.zeros(y.shape[0]) 45 | F = np.zeros((1,1,y.shape[0])) 46 | 47 | # Smoothing matrices 48 | N = np.zeros((a.shape[0],a.shape[0],y.shape[0])) 49 | V = np.zeros((a.shape[0],a.shape[0],y.shape[0])) 50 | alpha = np.zeros((T.shape[0],y.shape[0])) 51 | r = np.zeros((T.shape[0],y.shape[0])) 52 | 53 | # FORWARDS (FILTERING) 54 | for t in range(0,y.shape[0]): 55 | v[t] = y[t] - np.dot(Z,a[:,t]) - mu[t] 56 | 57 | F[:,:,t] = np.dot(np.dot(Z,P[:,:,t]),Z.T) + H[t].ravel()[0] 58 | 59 | K[:,t] = np.dot(np.dot(T,P[:,:,t]),Z.T)/(F[:,:,t]).ravel()[0] 60 | 61 | L[:,:,t] = T - np.dot(K[:,t],Z) 62 | 63 | if t != (y.shape[0]-1): 64 | 65 | a[:,t+1] = np.dot(T,a[:,t]) + np.dot(K[:,t],v[t]) 66 | 67 | P[:,:,t+1] = np.dot(np.dot(T,P[:,:,t]),T.T) + np.dot(np.dot(R,Q),R.T) - F[:,:,t].ravel()[0]*np.dot(np.array([K[:,t]]).T,np.array([K[:,t]])) 68 | 69 | # BACKWARDS (SMOOTHING) 70 | for t in reversed(range(y.shape[0])): 71 | if t != 0: 72 | L[:,:,t] = T - np.dot(K[:,t],Z) 73 | r[:,t-1] = np.dot(Z.T,v[t])/(F[:,:,t]).ravel()[0] 74 | N[:,:,t-1] = np.dot(Z.T,Z)/(F[:,:,t]).ravel()[0] + np.dot(np.dot(L[:,:,t].T,N[:,:,t]),L[:,:,t]) 75 | alpha[:,t] = a[:,t] + np.dot(P[:,:,t],r[:,t-1]) 76 | V[:,:,t] = P[:,:,t] - np.dot(np.dot(P[:,:,t],N[:,:,t-1]),P[:,:,t]) 77 | else: 78 | alpha[:,t] = a[:,t] 79 | V[:,:,t] = P[:,:,t] 80 | 81 | return alpha, V 82 | 83 | def nld_univariate_KFS(y,Z,H,T,Q,R,mu): 84 | """ Kalman filtering and smoothing for univariate time series 85 | Notes 86 | ---------- 87 | y = mu + Za_t + e_t where e_t ~ N(0,H) MEASUREMENT EQUATION 88 | a_t = Ta_t-1 + Rn_t where n_t ~ N(0,Q) STATE EQUATION 89 | Parameters 90 | ---------- 91 | y : np.array 92 | The time series data 93 | Z : np.array 94 | Design matrix for state matrix a 95 | H : np.array 96 | Covariance matrix for measurement noise 97 | T : np.array 98 | Design matrix for lagged state matrix in state equation 99 | Q : np.array 100 | Covariance matrix for state evolution noise 101 | R : np.array 102 | Scale matrix for state equation covariance matrix 103 | mu : float 104 | Constant term for measurement equation 105 | Returns 106 | ---------- 107 | alpha : np.array 108 | Smoothed states 109 | V : np.array 110 | Variance of smoothed states 111 | """ 112 | 113 | # Filtering matrices 114 | a = np.zeros((T.shape[0],y.shape[0]+1)) # Initialization 115 | P = np.ones((a.shape[0],a.shape[0],y.shape[0]+1))*(10**7) # diffuse prior asumed 116 | L = np.zeros((a.shape[0],a.shape[0],y.shape[0]+1)) 117 | K = np.zeros((a.shape[0],y.shape[0])) 118 | v = np.zeros(y.shape[0]) 119 | F = np.zeros((1,1,y.shape[0])) 120 | 121 | # Smoothing matrices 122 | N = np.zeros((a.shape[0],a.shape[0],y.shape[0])) 123 | V = np.zeros((a.shape[0],a.shape[0],y.shape[0])) 124 | alpha = np.zeros((T.shape[0],y.shape[0])) 125 | r = np.zeros((T.shape[0],y.shape[0])) 126 | 127 | # FORWARDS (FILTERING) 128 | for t in range(0,y.shape[0]): 129 | v[t] = y[t] - np.dot(Z[t],a[:,t]) - mu[t] 130 | 131 | F[:,:,t] = np.dot(np.dot(Z[t],P[:,:,t]),Z[t].T) + H[t].ravel()[0] 132 | 133 | K[:,t] = np.dot(np.dot(T,P[:,:,t]),Z[t].T)/(F[:,:,t]).ravel()[0] 134 | 135 | L[:,:,t] = T - np.dot(K[:,t],Z[t]) 136 | 137 | if t != (y.shape[0]-1): 138 | 139 | a[:,t+1] = np.dot(T,a[:,t]) + np.dot(K[:,t],v[t]) 140 | 141 | P[:,:,t+1] = np.dot(np.dot(T,P[:,:,t]),T.T) + np.dot(np.dot(R,Q),R.T) - F[:,:,t].ravel()[0]*np.dot(np.array([K[:,t]]).T,np.array([K[:,t]])) 142 | 143 | # BACKWARDS (SMOOTHING) 144 | for t in reversed(range(y.shape[0])): 145 | if t != 0: 146 | L[:,:,t] = T - np.dot(K[:,t],Z[t]) 147 | r[:,t-1] = np.dot(Z[t].T,v[t])/(F[:,:,t]).ravel()[0] 148 | N[:,:,t-1] = np.dot(Z[t].T,Z[t])/(F[:,:,t]).ravel()[0] + np.dot(np.dot(L[:,:,t].T,N[:,:,t]),L[:,:,t]) 149 | alpha[:,t] = a[:,t] + np.dot(P[:,:,t],r[:,t-1]) 150 | V[:,:,t] = P[:,:,t] - np.dot(np.dot(P[:,:,t],N[:,:,t-1]),P[:,:,t]) 151 | else: 152 | alpha[:,t] = a[:,t] 153 | V[:,:,t] = P[:,:,t] 154 | 155 | return alpha, V 156 | -------------------------------------------------------------------------------- /pyflux/families/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def configuration(parent_package='', top_path=None): 5 | from numpy.distutils.misc_util import Configuration 6 | 7 | config = Configuration('families', parent_package, top_path) 8 | 9 | config.add_extension('gas_recursions', 10 | sources=['gas_recursions.c']) 11 | config.add_extension('poisson_kalman_recursions', 12 | sources=['poisson_kalman_recursions.c']) 13 | 14 | return config 15 | 16 | 17 | if __name__ == '__main__': 18 | from numpy.distutils.core import setup 19 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/families/truncated_normal.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.stats as ss 3 | import scipy.special as sp 4 | 5 | from .family import Family 6 | 7 | 8 | class TruncatedNormal(Family): 9 | """ 10 | TruncatedNormal Distribution 11 | ---- 12 | This class contains methods relating to the truncated normal distribution for time series. 13 | """ 14 | 15 | def __init__(self, mu=0.0, sigma=1.0, lower=None, upper=None, transform=None, **kwargs): 16 | """ 17 | Parameters 18 | ---------- 19 | mu : float 20 | Mean parameter for the Truncated Normal distribution 21 | 22 | sigma : float 23 | Standard deviation for the Truncated Normal distribution 24 | 25 | lower: float 26 | Lower truncation for the distribution 27 | 28 | upper: float 29 | Upper truncation for the distribution 30 | 31 | transform : str 32 | Whether to apply a transformation - e.g. 'exp' or 'logit' 33 | """ 34 | super(TruncatedNormal, self).__init__(transform) 35 | self.mu0 = mu 36 | self.sigma0 = sigma 37 | self.upper = upper 38 | self.lower = lower 39 | self.covariance_prior = False 40 | 41 | 42 | def logpdf(self, mu): 43 | """ 44 | Log PDF for Truncated Normal prior 45 | 46 | Parameters 47 | ---------- 48 | mu : float 49 | Latent variable for which the prior is being formed over 50 | 51 | Returns 52 | ---------- 53 | - log(p(mu)) 54 | """ 55 | if self.transform is not None: 56 | mu = self.transform(mu) 57 | if mu < self.lower and self.lower is not None: 58 | return -10.0**6 59 | elif mu > self.upper and self.upper is not None: 60 | return -10.0**6 61 | else: 62 | return -np.log(float(self.sigma0)) - (0.5*(mu-self.mu0)**2)/float(self.sigma0**2) 63 | 64 | def pdf(self, mu): 65 | """ 66 | PDF for Truncated Normal prior 67 | 68 | Parameters 69 | ---------- 70 | mu : float 71 | Latent variable for which the prior is being formed over 72 | 73 | Returns 74 | ---------- 75 | - p(mu) 76 | """ 77 | if self.transform is not None: 78 | mu = self.transform(mu) 79 | if mu < self.lower and self.lower is not None: 80 | return 0.0 81 | elif mu > self.upper and self.upper is not None: 82 | return 0.0 83 | else: 84 | return (1/float(self.sigma0))*np.exp(-(0.5*(mu-self.mu0)**2)/float(self.sigma0**2)) 85 | 86 | -------------------------------------------------------------------------------- /pyflux/garch/__init__.py: -------------------------------------------------------------------------------- 1 | from .garch import GARCH 2 | 3 | from .egarch import EGARCH 4 | from .egarchm import EGARCHM 5 | from .lmegarch import LMEGARCH 6 | from .egarchmreg import EGARCHMReg 7 | 8 | from .segarch import SEGARCH 9 | from .segarchm import SEGARCHM 10 | -------------------------------------------------------------------------------- /pyflux/garch/garch_recursions.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | cimport cython 4 | 5 | from libc.math cimport exp, abs, M_PI 6 | 7 | @cython.boundscheck(False) 8 | @cython.wraparound(False) 9 | @cython.cdivision(True) 10 | def garch_recursion(double[:] parameters, double[:] sigma2, int q_terms, int p_terms, int Y_len, int max_lag): 11 | 12 | cdef Py_ssize_t t, k 13 | 14 | if p_terms != 0: 15 | for t in range(0,Y_len): 16 | if t < max_lag: 17 | sigma2[t] = parameters[0]/(1-np.sum(parameters[(q_terms+1):(q_terms+p_terms+1)])) 18 | elif t >= max_lag: 19 | for k in range(0,p_terms): 20 | sigma2[t] += parameters[1+q_terms+k]*(sigma2[t-1-k]) 21 | 22 | return sigma2 -------------------------------------------------------------------------------- /pyflux/garch/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def configuration(parent_package='', top_path=None): 5 | from numpy.distutils.misc_util import Configuration 6 | 7 | config = Configuration('garch', parent_package, top_path) 8 | 9 | config.add_extension('garch_recursions', 10 | sources=['garch_recursions.c']) 11 | return config 12 | 13 | 14 | if __name__ == '__main__': 15 | from numpy.distutils.core import setup 16 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/gas/__init__.py: -------------------------------------------------------------------------------- 1 | from .gas import GAS 2 | from .gasx import GASX 3 | from .gasrank import GASRank 4 | from .gasllm import GASLLEV 5 | from .gasllt import GASLLT 6 | from .gasreg import GASReg 7 | 8 | from .scores import BetatScore -------------------------------------------------------------------------------- /pyflux/gas/gas_core_recursions.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.special as sp 3 | cimport numpy as np 4 | cimport cython 5 | 6 | from libc.math cimport exp, abs, M_PI 7 | 8 | cdef inline double double_max(double a, double b): return a if a >= b else b 9 | cdef inline double double_min(double a, double b): return a if a <= b else b 10 | 11 | @cython.boundscheck(False) 12 | @cython.wraparound(False) 13 | @cython.cdivision(True) 14 | def gas_recursion(double[:] parameters, double[:] theta, double[:] model_scores, double[:] Y, 15 | int ar_terms, int sc_terms, int Y_len, score_function, link, double scale, double shape, double skewness, int max_lag): 16 | 17 | cdef Py_ssize_t t 18 | 19 | for t in range(0,Y_len): 20 | if t < max_lag: 21 | theta[t] = parameters[0]/(1.0-np.sum(parameters[1:(ar_terms+1)])) 22 | else: 23 | theta[t] += np.dot(parameters[1:1+ar_terms],theta[(t-ar_terms):t][::-1]) + np.dot(parameters[1+ar_terms:1+ar_terms+sc_terms],model_scores[(t-sc_terms):t][::-1]) 24 | 25 | model_scores[t] = score_function(Y[t], link(theta[t]), scale, shape, skewness) 26 | 27 | return theta, model_scores 28 | 29 | @cython.boundscheck(False) 30 | @cython.wraparound(False) 31 | @cython.cdivision(True) 32 | def gasx_recursion(double[:] parameters, double[:] theta, double[:] model_scores, double[:] Y, 33 | int ar_terms, int sc_terms, int Y_len, score_function, link, double scale, double shape, double skewness, int max_lag): 34 | 35 | cdef Py_ssize_t t 36 | 37 | for t in range(0,Y_len): 38 | if t < max_lag: 39 | theta[t] = parameters[ar_terms+sc_terms]/(1-np.sum(parameters[:ar_terms])) 40 | else: 41 | theta[t] += np.dot(parameters[:ar_terms],theta[(t-ar_terms):t][::-1]) + np.dot(parameters[ar_terms:ar_terms+sc_terms],model_scores[(t-sc_terms):t][::-1]) 42 | 43 | model_scores[t] = score_function(Y[t], link(theta[t]), scale, shape, skewness) 44 | 45 | return theta, model_scores 46 | 47 | 48 | 49 | 50 | 51 | @cython.boundscheck(False) 52 | @cython.wraparound(False) 53 | @cython.cdivision(True) 54 | def gas_llev_recursion(double[:] parameters, double[:] theta, double[:] model_scores, double[:] Y, 55 | int Y_len, score_function, link, double scale, double shape, double skewness, int max_lag): 56 | 57 | cdef Py_ssize_t t 58 | 59 | for t in range(0,Y_len): 60 | if t < max_lag: 61 | theta[t] = 0.0 62 | else: 63 | theta[t] = theta[t-1] + parameters[0]*model_scores[t-1] 64 | 65 | model_scores[t] = score_function(Y[t], link(theta[t]), scale, shape, skewness) 66 | 67 | return theta, model_scores 68 | 69 | 70 | @cython.boundscheck(False) 71 | @cython.wraparound(False) 72 | @cython.cdivision(True) 73 | def gas_llt_recursion(double[:] parameters, double[:] theta, double[:] theta_t, double[:] model_scores, double[:] Y, 74 | int Y_len, score_function, link, double scale, double shape, double skewness, int max_lag): 75 | 76 | cdef Py_ssize_t t 77 | 78 | for t in range(0,Y_len): 79 | if t < max_lag: 80 | theta[t] = 0.0 81 | else: 82 | theta[t] = theta_t[t-1] + theta[t-1] + parameters[0]*model_scores[t-1] 83 | theta_t[t] = theta_t[t-1] + parameters[1]*model_scores[t-1] 84 | 85 | model_scores[t] = score_function(Y[t], link(theta[t]), scale, shape, skewness) 86 | 87 | return theta, model_scores 88 | 89 | 90 | @cython.boundscheck(False) 91 | @cython.wraparound(False) 92 | @cython.cdivision(True) 93 | def gas_reg_recursion(double[:] parameters, double[:] theta, np.ndarray[double,ndim=2] X, np.ndarray[double,ndim=2] coefficients, np.ndarray[double,ndim=2] model_scores, 94 | double[:] Y, int Y_len, score_function, link, double scale, double shape, double skewness): 95 | 96 | cdef Py_ssize_t t 97 | 98 | for t in range(0,Y_len): 99 | theta[t] = np.dot(X[t],coefficients[:,t]) 100 | model_scores[:,t] = score_function(X[t],Y[t],link(theta[t]),scale,shape,skewness) 101 | coefficients[:,t+1] = coefficients[:,t] + parameters[0:X.shape[1]]*model_scores[:,t] 102 | 103 | return theta, model_scores, coefficients 104 | -------------------------------------------------------------------------------- /pyflux/gas/scores.py: -------------------------------------------------------------------------------- 1 | from numpy import abs, exp, power, array, sqrt, pi 2 | from scipy.special import gamma 3 | 4 | #TODO: This file should eventually be replaced, by moving the existing functions (used for GARCH based models) 5 | # into the GARCH folder, with Cythonizations 6 | 7 | class Score(object): 8 | 9 | @staticmethod 10 | def score(y,loc,scale,shape): 11 | pass 12 | 13 | @staticmethod 14 | def adj_score(y,loc,scale,shape): 15 | pass 16 | 17 | class BetatScore(Score): 18 | 19 | def __init__(self): 20 | 21 | super(Score,self).__init__() 22 | 23 | @staticmethod 24 | def mu_score(y,loc,scale,shape): 25 | try: 26 | return (((shape+1.0)*power(y-loc,2))/float(shape*exp(scale) + power(y-loc,2))) - 1.0 27 | except: 28 | return -1.0 29 | 30 | @staticmethod 31 | def mu_adj_score(y,loc,scale,shape): 32 | try: 33 | return (((shape+1.0)*power(y-loc,2))/float(shape*exp(scale) + power(y-loc,2))) - 1.0 34 | except: 35 | return -1.0 36 | 37 | def score(self,y,loc,scale,shape): 38 | return array([self.mu_score(y,loc,scale,shape)]) 39 | 40 | def adj_score(self,y,loc,scale,shape): 41 | return array([self.mu_adj_score(y,loc,scale,shape)]) 42 | 43 | class SkewBetatScore(Score): 44 | 45 | def __init__(self): 46 | 47 | super(Score,self).__init__() 48 | 49 | @staticmethod 50 | def tv_variate_exp(df): 51 | return (sqrt(df)*gamma((df-1.0)/2.0))/(sqrt(pi)*gamma(df/2.0)) 52 | 53 | @staticmethod 54 | def mu_score(y,loc,scale,shape,skewness): 55 | try: 56 | if (y-loc)>=0: 57 | return (((shape+1.0)*power(y-loc,2))/float(power(skewness,2)*shape*exp(scale) + power(y-loc,2))) - 1.0 58 | else: 59 | return (((shape+1.0)*power(y-loc,2))/float(power(skewness,-2)*shape*exp(scale) + power(y-loc,2))) - 1.0 60 | except: 61 | return -1.0 62 | 63 | @staticmethod 64 | def mu_adj_score(y,loc,scale,shape,skewness): 65 | try: 66 | if (y-loc)>=0: 67 | return (((shape+1.0)*power(y-loc,2))/float(power(skewness,2)*shape*exp(scale) + power(y-loc,2))) - 1.0 68 | else: 69 | return (((shape+1.0)*power(y-loc,2))/float(power(skewness,-2)*shape*exp(scale) + power(y-loc,2))) - 1.0 70 | except: 71 | return -1.0 72 | 73 | def score(self,y,loc,scale,shape,skewness): 74 | return array([self.mu_score(y,loc,scale,shape,skewness)]) 75 | 76 | def adj_score(self,y,loc,scale,shape,skewness): 77 | return array([self.mu_adj_score(y,loc,scale,shape,skewness)]) -------------------------------------------------------------------------------- /pyflux/gas/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def configuration(parent_package='', top_path=None): 5 | from numpy.distutils.misc_util import Configuration 6 | 7 | config = Configuration('gas', parent_package, top_path) 8 | 9 | config.add_extension('gas_core_recursions', 10 | sources=['gas_core_recursions.c']) 11 | 12 | return config 13 | 14 | 15 | if __name__ == '__main__': 16 | from numpy.distutils.core import setup 17 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llev_tests.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llev_tests.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llev_tests_cauchy.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llev_tests_cauchy.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llev_tests_laplace.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llev_tests_laplace.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llev_tests_normal.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llev_tests_normal.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llev_tests_poisson.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llev_tests_poisson.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llev_tests_skewt.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llev_tests_skewt.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llev_tests_t.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llev_tests_t.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llt_tests.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llt_tests.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llt_tests_cauchy.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llt_tests_cauchy.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llt_tests_normal.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llt_tests_normal.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llt_tests_poisson.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llt_tests_poisson.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llt_tests_skewt.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llt_tests_skewt.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_llt_tests_t.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_llt_tests_t.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_rank_tests.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_rank_tests.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_tests.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_tests.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_tests_cauchy.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_tests_cauchy.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_tests_exponential.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_tests_exponential.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_tests_laplace.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_tests_laplace.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_tests_normal.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_tests_normal.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_tests_poisson.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_tests_poisson.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_tests_skewt.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_tests_skewt.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gas_tests_t.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gas_tests_t.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasreg_tests_cauchy.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasreg_tests_cauchy.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasreg_tests_laplace.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasreg_tests_laplace.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasreg_tests_normal.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasreg_tests_normal.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasreg_tests_poisson.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasreg_tests_poisson.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasreg_tests_skewt.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasreg_tests_skewt.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasreg_tests_t.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasreg_tests_t.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasx_tests_exponential.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasx_tests_exponential.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasx_tests_laplace.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasx_tests_laplace.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasx_tests_normal.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasx_tests_normal.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasx_tests_poisson.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasx_tests_poisson.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasx_tests_skewt.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasx_tests_skewt.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/__pycache__/gasx_tests_t.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gas/tests/__pycache__/gasx_tests_t.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gas/tests/gas_llev_tests_skewt.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pyflux as pf 3 | 4 | noise = np.random.normal(0,1,200) 5 | data = np.zeros(200) 6 | 7 | for i in range(1,len(data)): 8 | data[i] = 1.0*data[i-1] + noise[i] 9 | 10 | countdata = np.random.poisson(3,200) 11 | 12 | def test_skewt_couple_terms(): 13 | """ 14 | Tests latent variable list length is correct, and that the estimated 15 | latent variables are not nan 16 | """ 17 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 18 | x = model.fit() 19 | assert(len(model.latent_variables.z_list) == 4) 20 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 21 | assert(len(lvs[np.isnan(lvs)]) == 0) 22 | 23 | def test_skewt_couple_terms_integ(): 24 | """ 25 | Tests latent variable list length is correct, and that the estimated 26 | latent variables are not nan 27 | """ 28 | model = pf.GASLLEV(data=data, integ=1, family=pf.Skewt()) 29 | x = model.fit() 30 | assert(len(model.latent_variables.z_list) == 4) 31 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 32 | assert(len(lvs[np.isnan(lvs)]) == 0) 33 | 34 | def test_skewt_bbvi(): 35 | """ 36 | Tests an GAS model estimated with BBVI and that the length of the latent variable 37 | list is correct, and that the estimated latent variables are not nan 38 | """ 39 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 40 | x = model.fit('BBVI',iterations=100) 41 | assert(len(model.latent_variables.z_list) == 4) 42 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 43 | assert(len(lvs[np.isnan(lvs)]) == 0) 44 | 45 | def test_skewt_bbvi_mini_batch(): 46 | """ 47 | Tests an ARIMA model estimated with BBVI and that the length of the latent variable 48 | list is correct, and that the estimated latent variables are not nan 49 | """ 50 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 51 | x = model.fit('BBVI',iterations=100, mini_batch=32) 52 | assert(len(model.latent_variables.z_list) == 4) 53 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 54 | assert(len(lvs[np.isnan(lvs)]) == 0) 55 | 56 | def test_skewt_bbvi_elbo(): 57 | """ 58 | Tests that the ELBO increases 59 | """ 60 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 61 | x = model.fit('BBVI',iterations=100, record_elbo=True) 62 | assert(x.elbo_records[-1]>x.elbo_records[0]) 63 | 64 | def test_skewt_bbvi_mini_batch_elbo(): 65 | """ 66 | Tests that the ELBO increases 67 | """ 68 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 69 | x = model.fit('BBVI',iterations=100, mini_batch=32, record_elbo=True) 70 | assert(x.elbo_records[-1]>x.elbo_records[0]) 71 | 72 | def test_skewt_mh(): 73 | """ 74 | Tests an GAS model estimated with Metropolis-Hastings and that the length of the 75 | latent variable list is correct, and that the estimated latent variables are not nan 76 | """ 77 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 78 | x = model.fit('M-H',nsims=300) 79 | assert(len(model.latent_variables.z_list) == 4) 80 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 81 | assert(len(lvs[np.isnan(lvs)]) == 0) 82 | 83 | """ Uncomment in future if Skewt becomes more robust 84 | def test_skewt_laplace(): 85 | Tests an GAS model estimated with Laplace approximation and that the length of the 86 | latent variable list is correct, and that the estimated latent variables are not nan 87 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 88 | x = model.fit('Laplace') 89 | assert(len(model.latent_variables.z_list) == 4) 90 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 91 | assert(len(lvs[np.isnan(lvs)]) == 0) 92 | """ 93 | 94 | def test_skewt_pml(): 95 | """ 96 | Tests a PML model estimated with Laplace approximation and that the length of the 97 | latent variable list is correct, and that the estimated latent variables are not nan 98 | """ 99 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 100 | x = model.fit('PML') 101 | assert(len(model.latent_variables.z_list) == 4) 102 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 103 | assert(len(lvs[np.isnan(lvs)]) == 0) 104 | 105 | def test_skewt_predict_length(): 106 | """ 107 | Tests that the prediction dataframe length is equal to the number of steps h 108 | """ 109 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 110 | x = model.fit() 111 | x.summary() 112 | assert(model.predict(h=5).shape[0] == 5) 113 | 114 | def test_skewt_predict_is_length(): 115 | """ 116 | Tests that the prediction IS dataframe length is equal to the number of steps h 117 | """ 118 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 119 | x = model.fit() 120 | assert(model.predict_is(h=5).shape[0] == 5) 121 | 122 | def test_skewt_predict_nans(): 123 | """ 124 | Tests that the predictions are not nans 125 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 126 | """ 127 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 128 | x = model.fit() 129 | x.summary() 130 | assert(len(model.predict(h=5).values[np.isnan(model.predict(h=5).values)]) == 0) 131 | """ 132 | 133 | def test_skewt_predict_is_nans(): 134 | 135 | Tests that the in-sample predictions are not nans 136 | 137 | model = pf.GASLLEV(data=data, family=pf.Skewt()) 138 | x = model.fit() 139 | x.summary() 140 | assert(len(model.predict_is(h=5).values[np.isnan(model.predict_is(h=5).values)]) == 0) 141 | """ 142 | 143 | -------------------------------------------------------------------------------- /pyflux/gas/tests/gas_llt_tests_skewt.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pyflux as pf 3 | 4 | noise = np.random.normal(0,1,200) 5 | data = np.zeros(200) 6 | 7 | for i in range(1,len(data)): 8 | data[i] = 1.0*data[i-1] + noise[i] 9 | 10 | countdata = np.random.poisson(3,200) 11 | 12 | def test_skewt_couple_terms(): 13 | """ 14 | Tests latent variable list length is correct, and that the estimated 15 | latent variables are not nan 16 | """ 17 | model = pf.GASLLT(data=data, family=pf.Skewt()) 18 | x = model.fit() 19 | assert(len(model.latent_variables.z_list) == 5) 20 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 21 | assert(len(lvs[np.isnan(lvs)]) == 0) 22 | 23 | def test_skewt_couple_terms_integ(): 24 | """ 25 | Tests latent variable list length is correct, and that the estimated 26 | latent variables are not nan 27 | """ 28 | model = pf.GASLLT(data=data, integ=1, family=pf.Skewt()) 29 | x = model.fit() 30 | assert(len(model.latent_variables.z_list) == 5) 31 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 32 | assert(len(lvs[np.isnan(lvs)]) == 0) 33 | 34 | def test_skewt_bbvi(): 35 | """ 36 | Tests an GAS model estimated with BBVI and that the length of the latent variable 37 | list is correct, and that the estimated latent variables are not nan 38 | """ 39 | """ 40 | model = pf.GASLLT(data=data, family=pf.Skewt()) 41 | x = model.fit('BBVI',iterations=100) 42 | assert(len(model.latent_variables.z_list) == 5) 43 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 44 | assert(len(lvs[np.isnan(lvs)]) == 0) 45 | """ 46 | 47 | def test_skewt_bbvi_mini_batch(): 48 | """ 49 | Tests an ARIMA model estimated with BBVI and that the length of the latent variable 50 | list is correct, and that the estimated latent variables are not nan 51 | """ 52 | """ 53 | model = pf.GASLLT(data=data, family=pf.Skewt()) 54 | x = model.fit('BBVI',iterations=100, mini_batch=32) 55 | assert(len(model.latent_variables.z_list) == 5) 56 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 57 | assert(len(lvs[np.isnan(lvs)]) == 0) 58 | """ 59 | 60 | def test_skewt_bbvi_elbo(): 61 | """ 62 | Tests that the ELBO increases 63 | """ 64 | model = pf.GASLLT(data=data, family=pf.Skewt()) 65 | x = model.fit('BBVI',iterations=100, record_elbo=True) 66 | assert(x.elbo_records[-1]>x.elbo_records[0]) 67 | 68 | def test_skewt_bbvi_mini_batch_elbo(): 69 | """ 70 | Tests that the ELBO increases 71 | """ 72 | model = pf.GASLLT(data=data, family=pf.Skewt()) 73 | x = model.fit('BBVI',iterations=100, mini_batch=32, record_elbo=True) 74 | assert(x.elbo_records[-1]>x.elbo_records[0]) 75 | 76 | def test_skewt_mh(): 77 | """ 78 | Tests an GAS model estimated with Metropolis-Hastings and that the length of the 79 | latent variable list is correct, and that the estimated latent variables are not nan 80 | """ 81 | """ 82 | model = pf.GASLLT(data=data, family=pf.Skewt()) 83 | x = model.fit('M-H',nsims=300) 84 | assert(len(model.latent_variables.z_list) == 5) 85 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 86 | assert(len(lvs[np.isnan(lvs)]) == 0) 87 | """ 88 | 89 | """ Uncomment in future if Skewt becomes more robust 90 | def test_skewt_laplace(): 91 | Tests an GAS model estimated with Laplace approximation and that the length of the 92 | latent variable list is correct, and that the estimated latent variables are not nan 93 | model = pf.GASLLT(data=data, family=pf.Skewt()) 94 | x = model.fit('Laplace') 95 | assert(len(model.latent_variables.z_list) == 4) 96 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 97 | assert(len(lvs[np.isnan(lvs)]) == 0) 98 | """ 99 | 100 | def test_skewt_pml(): 101 | """ 102 | Tests a PML model estimated with Laplace approximation and that the length of the 103 | latent variable list is correct, and that the estimated latent variables are not nan 104 | """ 105 | model = pf.GASLLT(data=data, family=pf.Skewt()) 106 | x = model.fit('PML') 107 | assert(len(model.latent_variables.z_list) == 5) 108 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 109 | assert(len(lvs[np.isnan(lvs)]) == 0) 110 | 111 | def test_skewt_predict_length(): 112 | """ 113 | Tests that the prediction dataframe length is equal to the number of steps h 114 | """ 115 | model = pf.GASLLT(data=data, family=pf.Skewt()) 116 | x = model.fit() 117 | x.summary() 118 | assert(model.predict(h=5).shape[0] == 5) 119 | 120 | def test_skewt_predict_is_length(): 121 | """ 122 | Tests that the prediction IS dataframe length is equal to the number of steps h 123 | """ 124 | model = pf.GASLLT(data=data, family=pf.Skewt()) 125 | x = model.fit() 126 | assert(model.predict_is(h=5).shape[0] == 5) 127 | 128 | def test_skewt_predict_nans(): 129 | """ 130 | Tests that the predictions are not nans 131 | model = pf.GASLLT(data=data, family=pf.Skewt()) 132 | """ 133 | """ 134 | model = pf.GASLLT(data=data, family=pf.Skewt()) 135 | x = model.fit() 136 | x.summary() 137 | assert(len(model.predict(h=5).values[np.isnan(model.predict(h=5).values)]) == 0) 138 | """ 139 | """ 140 | 141 | def test_skewt_predict_is_nans(): 142 | 143 | Tests that the in-sample predictions are not nans 144 | 145 | model = pf.GASLLT(data=data, family=pf.Skewt()) 146 | x = model.fit() 147 | x.summary() 148 | assert(len(model.predict_is(h=5).values[np.isnan(model.predict_is(h=5).values)]) == 0) 149 | """ 150 | 151 | -------------------------------------------------------------------------------- /pyflux/gas/tests/gas_rank_tests.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pyflux as pf 3 | import pandas as pd 4 | 5 | data = pd.read_csv("http://www.pyflux.com/notebooks/nfl_data_new.csv") 6 | data["PointsDiff"] = data["HomeScore"] - data["AwayScore"] 7 | 8 | def test_mle(): 9 | """ 10 | Tests latent variable list length is correct, and that the estimated 11 | latent variables are not nan 12 | """ 13 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 14 | score_diff="PointsDiff", family=pf.Normal()) 15 | x = model.fit() 16 | assert(len(model.latent_variables.z_list) == 3) 17 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 18 | assert(len(lvs[np.isnan(lvs)]) == 0) 19 | 20 | def test_mh(): 21 | """ 22 | Tests latent variable list length is correct, and that the estimated 23 | latent variables are not nan 24 | """ 25 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 26 | score_diff="PointsDiff", family=pf.Normal()) 27 | x = model.fit('M-H', nsims=200) 28 | assert(len(model.latent_variables.z_list) == 3) 29 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 30 | assert(len(lvs[np.isnan(lvs)]) == 0) 31 | 32 | def test_pml(): 33 | """ 34 | Tests latent variable list length is correct, and that the estimated 35 | latent variables are not nan 36 | """ 37 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 38 | score_diff="PointsDiff", family=pf.Normal()) 39 | x = model.fit('PML') 40 | assert(len(model.latent_variables.z_list) == 3) 41 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 42 | assert(len(lvs[np.isnan(lvs)]) == 0) 43 | 44 | def test_laplace(): 45 | """ 46 | Tests latent variable list length is correct, and that the estimated 47 | latent variables are not nan 48 | """ 49 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 50 | score_diff="PointsDiff", family=pf.Normal()) 51 | x = model.fit('Laplace') 52 | assert(len(model.latent_variables.z_list) == 3) 53 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 54 | assert(len(lvs[np.isnan(lvs)]) == 0) 55 | 56 | def test_bbvi(): 57 | """ 58 | Tests latent variable list length is correct, and that the estimated 59 | latent variables are not nan 60 | """ 61 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 62 | score_diff="PointsDiff", family=pf.Normal()) 63 | x = model.fit('BBVI', iterations=100) 64 | assert(len(model.latent_variables.z_list) == 3) 65 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 66 | assert(len(lvs[np.isnan(lvs)]) == 0) 67 | 68 | def test_predict(): 69 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 70 | score_diff="PointsDiff", family=pf.Normal()) 71 | model.fit() 72 | prediction = model.predict("Denver Broncos","Carolina Panthers",neutral=True) 73 | assert(len(prediction[np.isnan(prediction)]) == 0) 74 | 75 | def test_mle_two_components(): 76 | """ 77 | Tests latent variable list length is correct, and that the estimated 78 | latent variables are not nan 79 | """ 80 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 81 | score_diff="PointsDiff", family=pf.Normal()) 82 | model.add_second_component("HQB","AQB") 83 | x = model.fit() 84 | assert(len(model.latent_variables.z_list) == 4) 85 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 86 | assert(len(lvs[np.isnan(lvs)]) == 0) 87 | prediction = model.predict("Denver Broncos","Carolina Panthers","Peyton Manning","Cam Newton",neutral=True) 88 | assert(len(prediction[np.isnan(prediction)]) == 0) 89 | 90 | def test_t_mle(): 91 | """ 92 | Tests latent variable list length is correct, and that the estimated 93 | latent variables are not nan 94 | """ 95 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 96 | score_diff="PointsDiff", family=pf.t()) 97 | x = model.fit() 98 | assert(len(model.latent_variables.z_list) == 4) 99 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 100 | assert(len(lvs[np.isnan(lvs)]) == 0) 101 | 102 | def test_t_pml(): 103 | """ 104 | Tests latent variable list length is correct, and that the estimated 105 | latent variables are not nan 106 | """ 107 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 108 | score_diff="PointsDiff", family=pf.t()) 109 | x = model.fit('PML') 110 | assert(len(model.latent_variables.z_list) == 4) 111 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 112 | assert(len(lvs[np.isnan(lvs)]) == 0) 113 | 114 | def test_t_laplace(): 115 | """ 116 | Tests latent variable list length is correct, and that the estimated 117 | latent variables are not nan 118 | """ 119 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 120 | score_diff="PointsDiff", family=pf.t()) 121 | x = model.fit('Laplace') 122 | assert(len(model.latent_variables.z_list) == 4) 123 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 124 | assert(len(lvs[np.isnan(lvs)]) == 0) 125 | 126 | def test_t_bbvi(): 127 | """ 128 | Tests latent variable list length is correct, and that the estimated 129 | latent variables are not nan 130 | """ 131 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 132 | score_diff="PointsDiff", family=pf.t()) 133 | x = model.fit('BBVI', iterations=100) 134 | assert(len(model.latent_variables.z_list) == 4) 135 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 136 | assert(len(lvs[np.isnan(lvs)]) == 0) 137 | 138 | def test_t_predict(): 139 | model = pf.GASRank(data=data,team_1="HomeTeam", team_2="AwayTeam", 140 | score_diff="PointsDiff", family=pf.t()) 141 | model.fit() 142 | prediction = model.predict("Denver Broncos","Carolina Panthers",neutral=True) 143 | assert(len(prediction[np.isnan(prediction)]) == 0) 144 | 145 | def test_t_mle_two_components(): 146 | """ 147 | Tests latent variable list length is correct, and that the estimated 148 | latent variables are not nan 149 | """ 150 | model = pf.GASRank(data=data.iloc[0:300,:],team_1="HomeTeam", team_2="AwayTeam", 151 | score_diff="PointsDiff", family=pf.t()) 152 | model.add_second_component("HQB","AQB") 153 | x = model.fit('BBVI',iterations=50,map_start=False) 154 | assert(len(model.latent_variables.z_list) == 5) 155 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 156 | assert(len(lvs[np.isnan(lvs)]) == 0) 157 | prediction = model.predict("Denver Broncos","Carolina Panthers","Peyton Manning","Cam Newton",neutral=True) 158 | assert(len(prediction[np.isnan(prediction)]) == 0) 159 | 160 | -------------------------------------------------------------------------------- /pyflux/gas/tests/gas_tests_skewt.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pyflux as pf 3 | 4 | # Generate some random data 5 | noise = np.random.normal(0,1,200) 6 | data = np.zeros(200) 7 | 8 | for i in range(1,len(data)): 9 | data[i] = 0.9*data[i-1] + noise[i] 10 | 11 | countdata = np.random.poisson(3,200) 12 | exponentialdata = np.random.exponential(3,200) 13 | 14 | 15 | def test_skewt_no_terms(): 16 | """ 17 | Tests an GAS model with no AR or SC terms, and that 18 | the latent variable list length is correct, and that the estimated 19 | latent variables are not nan 20 | """ 21 | model = pf.GAS(data=data, ar=0, sc=0, family=pf.Skewt()) 22 | x = model.fit() 23 | assert(len(model.latent_variables.z_list) == 4) 24 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 25 | assert(len(lvs[np.isnan(lvs)]) == 0) 26 | 27 | def test_skewt_couple_terms(): 28 | """ 29 | Tests an GAS model with 1 AR and 1 SC term and that 30 | the latent variable list length is correct, and that the estimated 31 | latent variables are not nan 32 | """ 33 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 34 | x = model.fit() 35 | assert(len(model.latent_variables.z_list) == 6) 36 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 37 | assert(len(lvs[np.isnan(lvs)]) == 0) 38 | 39 | def test_skewt_couple_terms_integ(): 40 | """ 41 | Tests an GAS model with 1 AR and 1 SC term, integrated once, and that 42 | the latent variable list length is correct, and that the estimated 43 | latent variables are not nan 44 | """ 45 | model = pf.GAS(data=data, ar=1, sc=1, integ=1, family=pf.Skewt()) 46 | x = model.fit() 47 | assert(len(model.latent_variables.z_list) == 6) 48 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 49 | assert(len(lvs[np.isnan(lvs)]) == 0) 50 | 51 | def test_skewt_bbvi(): 52 | """ 53 | Tests an GAS model estimated with BBVI and that the length of the latent variable 54 | list is correct, and that the estimated latent variables are not nan 55 | """ 56 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 57 | x = model.fit('BBVI',iterations=100) 58 | assert(len(model.latent_variables.z_list) == 6) 59 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 60 | assert(len(lvs[np.isnan(lvs)]) == 0) 61 | 62 | def test_skewt_bbvi_mini_batch(): 63 | """ 64 | Tests an ARIMA model estimated with BBVI and that the length of the latent variable 65 | list is correct, and that the estimated latent variables are not nan 66 | """ 67 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 68 | x = model.fit('BBVI',iterations=100, mini_batch=32) 69 | assert(len(model.latent_variables.z_list) == 6) 70 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 71 | assert(len(lvs[np.isnan(lvs)]) == 0) 72 | 73 | def test_skewt_bbvi_elbo(): 74 | """ 75 | Tests that the ELBO increases 76 | """ 77 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 78 | x = model.fit('BBVI',iterations=100, record_elbo=True) 79 | assert(x.elbo_records[-1]>x.elbo_records[0]) 80 | 81 | def test_skewt_bbvi_mini_batch_elbo(): 82 | """ 83 | Tests that the ELBO increases 84 | """ 85 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 86 | x = model.fit('BBVI',iterations=100, mini_batch=32, record_elbo=True) 87 | assert(x.elbo_records[-1]>x.elbo_records[0]) 88 | 89 | def test_skewt_mh(): 90 | """ 91 | Tests an GAS model estimated with Metropolis-Hastings and that the length of the 92 | latent variable list is correct, and that the estimated latent variables are not nan 93 | """ 94 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 95 | x = model.fit('M-H',nsims=300) 96 | assert(len(model.latent_variables.z_list) == 6) 97 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 98 | assert(len(lvs[np.isnan(lvs)]) == 0) 99 | 100 | """ REACTIVATE THIS TEST IF SOLUTION TO SKEW T STABILITY IS FOUND 101 | def test_skewt_laplace(): 102 | Tests an GAS model estimated with Laplace approximation and that the length of the 103 | latent variable list is correct, and that the estimated latent variables are not nan 104 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 105 | x = model.fit('Laplace') 106 | assert(len(model.latent_variables.z_list) == 6) 107 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 108 | assert(len(lvs[np.isnan(lvs)]) == 0) 109 | """ 110 | 111 | def test_skewt_pml(): 112 | """ 113 | Tests a PML model estimated with Laplace approximation and that the length of the 114 | latent variable list is correct, and that the estimated latent variables are not nan 115 | """ 116 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 117 | x = model.fit('PML') 118 | assert(len(model.latent_variables.z_list) == 6) 119 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 120 | assert(len(lvs[np.isnan(lvs)]) == 0) 121 | 122 | def test_skewt_predict_length(): 123 | """ 124 | Tests that the prediction dataframe length is equal to the number of steps h 125 | """ 126 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 127 | x = model.fit() 128 | x.summary() 129 | assert(model.predict(h=5).shape[0] == 5) 130 | 131 | def test_skewt_predict_is_length(): 132 | """ 133 | Tests that the prediction IS dataframe length is equal to the number of steps h 134 | """ 135 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 136 | x = model.fit() 137 | assert(model.predict_is(h=5).shape[0] == 5) 138 | 139 | """ REACTIVATE THIS TEST IF SOLUTION TO SKEW T STABILITY IS FOUND 140 | def test_skewt_predict_nans(): 141 | Tests that the predictions are not nans 142 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 143 | x = model.fit() 144 | x.summary() 145 | assert(len(model.predict(h=5).values[np.isnan(model.predict(h=5).values)]) == 0) 146 | """ 147 | 148 | """ REACTIVATE THIS TEST IF SOLUTION TO SKEW T STABILITY IS FOUND 149 | def test_skewt_predict_is_nans(): 150 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 151 | x = model.fit() 152 | x.summary() 153 | assert(len(model.predict_is(h=5).values[np.isnan(model.predict_is(h=5).values)]) == 0) 154 | """ 155 | 156 | def test_skewt_sample_model(): 157 | """ 158 | Tests sampling function 159 | """ 160 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 161 | x = model.fit('BBVI', iterations=100) 162 | sample = model.sample(nsims=100) 163 | assert(sample.shape[0]==100) 164 | assert(sample.shape[1]==len(data)-1) 165 | 166 | def test_skewt_ppc(): 167 | """ 168 | Tests PPC value 169 | """ 170 | model = pf.GAS(data=data, ar=1, sc=1, family=pf.Skewt()) 171 | x = model.fit('BBVI', iterations=100) 172 | p_value = model.ppc() 173 | assert(0.0 <= p_value <= 1.0) 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /pyflux/gpnarx/__init__.py: -------------------------------------------------------------------------------- 1 | from .gpnarx import GPNARX 2 | from.kernels import SquaredExponential, ARD, OrnsteinUhlenbeck, Periodic, RationalQuadratic -------------------------------------------------------------------------------- /pyflux/gpnarx/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def configuration(parent_package='', top_path=None): 5 | from numpy.distutils.misc_util import Configuration 6 | 7 | config = Configuration('gpnarx', parent_package, top_path) 8 | 9 | config.add_extension('kernel_routines', 10 | sources=['kernel_routines.c']) 11 | 12 | return config 13 | 14 | 15 | if __name__ == '__main__': 16 | from numpy.distutils.core import setup 17 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/gpnarx/tests/__pycache__/arima_tests.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gpnarx/tests/__pycache__/arima_tests.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gpnarx/tests/__pycache__/arimax_tests.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gpnarx/tests/__pycache__/arimax_tests.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/gpnarx/tests/__pycache__/gpnarx_tests.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/gpnarx/tests/__pycache__/gpnarx_tests.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/inference/__init__.py: -------------------------------------------------------------------------------- 1 | from .metropolis_hastings import MetropolisHastings 2 | from .norm_post_sim import norm_post_sim 3 | from .bbvi import BBVI, CBBVI, BBVIM 4 | -------------------------------------------------------------------------------- /pyflux/inference/bbvi_routines.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | cimport cython 4 | 5 | @cython.boundscheck(False) 6 | @cython.wraparound(False) 7 | @cython.cdivision(True) 8 | def alpha_recursion(double[:] alpha0, np.ndarray[double,ndim=2] grad_log_q, np.ndarray[double,ndim=2] gradient, int param_no): 9 | 10 | cdef Py_ssize_t lambda_i 11 | 12 | for lambda_i in range(param_no): 13 | alpha0[lambda_i] = np.cov(grad_log_q[lambda_i],gradient[lambda_i])[0][1] 14 | 15 | return alpha0 16 | 17 | @cython.boundscheck(False) 18 | @cython.wraparound(False) 19 | @cython.cdivision(True) 20 | def log_p_posterior(np.ndarray[double,ndim=2] z, neg_posterior): 21 | 22 | cdef Py_ssize_t i 23 | cdef np.ndarray[double, ndim=1, mode="c"] result = np.zeros(z.shape[0], dtype=np.float64) 24 | 25 | for i in range(z.shape[0]): 26 | result[i] = -neg_posterior(z[i]) 27 | 28 | return result 29 | 30 | @cython.boundscheck(False) 31 | @cython.wraparound(False) 32 | @cython.cdivision(True) 33 | def mb_log_p_posterior(np.ndarray[double,ndim=2] z, neg_posterior, int mini_batch): 34 | 35 | cdef Py_ssize_t i 36 | cdef np.ndarray[double, ndim=1, mode="c"] result = np.zeros(z.shape[0], dtype=np.float64) 37 | 38 | for i in range(z.shape[0]): 39 | result[i] = -neg_posterior(z[i], mini_batch) 40 | 41 | return result -------------------------------------------------------------------------------- /pyflux/inference/metropolis_hastings.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import sys 3 | if sys.version_info < (3,): 4 | range = xrange 5 | 6 | from scipy.stats import multivariate_normal 7 | 8 | from .metropolis_sampler import metropolis_sampler 9 | 10 | class MetropolisHastings(object): 11 | """ RANDOM-WALK METROPOLIS-HASTINGS MCMC 12 | 13 | Parameters 14 | ---------- 15 | posterior : function 16 | A posterior function 17 | 18 | scale : float 19 | The scale for the random walk 20 | 21 | nsims : int 22 | The number of iterations to perform 23 | 24 | initials : np.array 25 | Where to start the MCMC chain 26 | 27 | cov_matrix : np.array 28 | (optional) A covariance matrix for the random walk 29 | 30 | thinning : int 31 | By how much to thin the chains (2 means drop every other point) 32 | 33 | warm_up_period : boolean 34 | Whether to discard first half of the chain as 'warm-up' 35 | 36 | model_object : TSM object 37 | A model object (for use in SPDK sampling) 38 | 39 | quiet_progress : boolean 40 | Whether to print progress to console or stay quiet 41 | """ 42 | 43 | def __init__(self, posterior, scale, nsims, initials, 44 | cov_matrix=None, thinning=2, warm_up_period=True, model_object=None, quiet_progress=False): 45 | self.posterior = posterior 46 | self.scale = scale 47 | self.nsims = (1+warm_up_period)*nsims*thinning 48 | self.initials = initials 49 | self.param_no = self.initials.shape[0] 50 | self.phi = np.zeros([self.nsims, self.param_no]) 51 | self.phi[0] = self.initials # point from which to start the Metropolis-Hasting algorithm 52 | self.quiet_progress = quiet_progress 53 | 54 | if cov_matrix is None: 55 | self.cov_matrix = np.identity(self.param_no) * np.abs(self.initials) 56 | else: 57 | self.cov_matrix = cov_matrix 58 | 59 | self.thinning = thinning 60 | self.warm_up_period = warm_up_period 61 | 62 | if model_object is not None: 63 | self.model = model_object 64 | 65 | @staticmethod 66 | def tune_scale(acceptance, scale): 67 | """ Tunes scale for M-H algorithm 68 | 69 | Parameters 70 | ---------- 71 | acceptance : float 72 | The most recent acceptance rate 73 | 74 | scale : float 75 | The current scale parameter 76 | 77 | Returns 78 | ---------- 79 | scale : float 80 | An adjusted scale parameter 81 | 82 | Notes 83 | ---------- 84 | Ross : Initially did this by trial and error, then refined by looking at other 85 | implementations, so some credit here to PyMC3 which became a guideline for this. 86 | """ 87 | 88 | if acceptance > 0.8: 89 | scale *= 2.0 90 | elif acceptance <= 0.8 and acceptance > 0.4: 91 | scale *= 1.3 92 | elif acceptance < 0.234 and acceptance > 0.1: 93 | scale *= (1/1.3) 94 | elif acceptance <= 0.1 and acceptance > 0.05: 95 | scale *= 0.4 96 | elif acceptance <= 0.05 and acceptance > 0.01: 97 | scale *= 0.2 98 | elif acceptance <= 0.01: 99 | scale *= 0.1 100 | return scale 101 | 102 | def sample(self): 103 | """ Sample from M-H algorithm 104 | 105 | Returns 106 | ---------- 107 | chain : np.array 108 | Chains for each parameter 109 | 110 | mean_est : np.array 111 | Mean values for each parameter 112 | 113 | median_est : np.array 114 | Median values for each parameter 115 | 116 | upper_95_est : np.array 117 | Upper 95% credibility interval for each parameter 118 | 119 | lower_95_est : np.array 120 | Lower 95% credibility interval for each parameter 121 | """ 122 | 123 | acceptance = 1 124 | finish = 0 125 | 126 | while (acceptance < 0.234 or acceptance > 0.4) or finish == 0: 127 | 128 | # If acceptance is in range, proceed to sample, else continue tuning 129 | if not (acceptance < 0.234 or acceptance > 0.4): 130 | finish = 1 131 | if not self.quiet_progress: 132 | print("") 133 | print("Tuning complete! Now sampling.") 134 | sims_to_do = self.nsims 135 | else: 136 | sims_to_do = int(self.nsims/2) # For acceptance rate tuning 137 | 138 | # Holds data on acceptance rates and uniform random numbers 139 | a_rate = np.zeros([sims_to_do,1]) 140 | crit = np.random.rand(sims_to_do,1) 141 | post = multivariate_normal(np.zeros(self.param_no), self.cov_matrix) 142 | rnums = post.rvs()*self.scale 143 | 144 | for k in range(1,sims_to_do): 145 | rnums = np.vstack((rnums,post.rvs()*self.scale)) 146 | 147 | self.phi, a_rate = metropolis_sampler(sims_to_do, self.phi, self.posterior, 148 | a_rate, rnums, crit) 149 | 150 | acceptance = a_rate.sum()/a_rate.shape[0] 151 | self.scale = self.tune_scale(acceptance,self.scale) 152 | if not self.quiet_progress: 153 | print("Acceptance rate of Metropolis-Hastings is " + str(acceptance)) 154 | 155 | # Remove warm-up and thin 156 | self.phi = self.phi[int(self.nsims/2):,:][::self.thinning,:] 157 | 158 | chain = np.array([self.phi[i][0] for i in range(0, self.phi.shape[0])]) 159 | 160 | for m in range(1, self.param_no): 161 | chain = np.vstack((chain, [self.phi[i][m] for i in range(0,self.phi.shape[0])])) 162 | 163 | if self.param_no == 1: 164 | chain = np.array([chain]) 165 | 166 | mean_est = np.array([np.mean(np.array([self.phi[i][j] for i in range(0,self.phi.shape[0])])) for j in range(self.param_no)]) 167 | median_est = np.array([np.median(np.array([self.phi[i][j] for i in range(0,self.phi.shape[0])])) for j in range(self.param_no)]) 168 | upper_95_est = np.array([np.percentile(np.array([self.phi[i][j] for i in range(0,self.phi.shape[0])]), 95) for j in range(self.param_no)]) 169 | lower_95_est = np.array([np.percentile(np.array([self.phi[i][j] for i in range(0,self.phi.shape[0])]), 5) for j in range(self.param_no)]) 170 | 171 | return chain, mean_est, median_est, upper_95_est, lower_95_est -------------------------------------------------------------------------------- /pyflux/inference/metropolis_sampler.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | cimport cython 4 | 5 | @cython.boundscheck(False) 6 | @cython.wraparound(False) 7 | @cython.cdivision(True) 8 | def metropolis_sampler(int sims_to_do, np.ndarray[double,ndim=2] phi, 9 | posterior, np.ndarray[double,ndim=2] a_rate, np.ndarray[double,ndim=2] rnums, 10 | np.ndarray[double,ndim=2] crit): 11 | 12 | cdef Py_ssize_t i 13 | cdef float post_prop, lik_rate, old_lik 14 | cdef np.ndarray[double, ndim=1, mode="c"] phi_prop 15 | 16 | old_lik = -posterior(phi[0]) # Initial posterior 17 | 18 | # Sampling time! 19 | for i in range(1,sims_to_do): 20 | phi_prop = phi[i-1] + rnums[i] 21 | post_prop = -posterior(phi_prop) 22 | lik_rat = np.exp(post_prop - old_lik) 23 | 24 | if crit[i] < lik_rat: 25 | phi[i] = phi_prop 26 | a_rate[i] = 1 27 | old_lik = post_prop 28 | else: 29 | phi[i] = phi[i-1] 30 | 31 | return phi, a_rate 32 | -------------------------------------------------------------------------------- /pyflux/inference/norm_post_sim.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from math import exp 3 | import sys 4 | if sys.version_info < (3,): 5 | range = xrange 6 | 7 | from scipy.stats import multivariate_normal 8 | 9 | def norm_post_sim(modes,cov_matrix): 10 | post = multivariate_normal(modes,cov_matrix) 11 | nsims = 30000 12 | phi = np.zeros([nsims,len(modes)]) 13 | 14 | for i in range(0,nsims): 15 | phi[i] = post.rvs() 16 | 17 | chain = np.array([phi[i][0] for i in range(len(phi))]) 18 | for m in range(1,len(modes)): 19 | chain = np.vstack((chain,[phi[i][m] for i in range(len(phi))])) 20 | 21 | mean_est = [np.mean(np.array([phi[i][j] for i in range(len(phi))])) for j in range(len(modes))] 22 | median_est = [np.median(np.array([phi[i][j] for i in range(len(phi))])) for j in range(len(modes))] 23 | upper_95_est = [np.percentile(np.array([phi[i][j] for i in range(len(phi))]),95) for j in range(len(modes))] 24 | lower_95_est = [np.percentile(np.array([phi[i][j] for i in range(len(phi))]),5) for j in range(len(modes))] 25 | 26 | return chain, mean_est, median_est, upper_95_est, lower_95_est -------------------------------------------------------------------------------- /pyflux/inference/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def configuration(parent_package='', top_path=None): 5 | from numpy.distutils.misc_util import Configuration 6 | 7 | config = Configuration('inference', parent_package, top_path) 8 | 9 | config.add_extension('metropolis_sampler', 10 | sources=['metropolis_sampler.c']) 11 | config.add_extension('bbvi_routines', 12 | sources=['bbvi_routines.c']) 13 | 14 | return config 15 | 16 | 17 | if __name__ == '__main__': 18 | from numpy.distutils.core import setup 19 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/inference/stoch_optim.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class RMSProp(object): 4 | """ 5 | *** RMSProp *** 6 | 7 | Computes adaptive learning rates for each parameter. Has an EWMA of squared gradients. 8 | """ 9 | def __init__(self, starting_parameters, starting_variance, learning_rate, ewma): 10 | self.parameters = starting_parameters 11 | self.variance = starting_variance 12 | self.learning_rate = learning_rate 13 | self.ewma = ewma 14 | self.epsilon = np.power(10.0,-8) 15 | self.t = 1 16 | 17 | def update(self, gradient): 18 | self.variance = self.ewma*self.variance + (1-self.ewma)*np.power(gradient,2) 19 | if self.t > 5: 20 | self.parameters += (self.learning_rate+(self.learning_rate*15.0*(0.990**self.t)))*(gradient/np.sqrt(self.variance+self.epsilon)) 21 | self.t += 1 22 | return self.parameters 23 | 24 | class ADAM(object): 25 | """ 26 | *** Adaptive Moment Estimation (ADAM) *** 27 | 28 | Computes adaptive learning rates for each parameter. Has an EWMA of past gradients and squared gradients. 29 | """ 30 | def __init__(self, starting_parameters, starting_variance, learning_rate, ewma_1, ewma_2): 31 | self.parameters = starting_parameters 32 | self.f_gradient = 0.0 33 | self.variance = starting_variance 34 | self.learning_rate = learning_rate 35 | self.ewma_1 = ewma_1 36 | self.ewma_2 = ewma_2 37 | 38 | self.epsilon = np.power(10.0,-8) 39 | self.t = 1 40 | 41 | def update(self, gradient): 42 | self.f_gradient = self.ewma_1*self.f_gradient + (1-self.ewma_1)*gradient 43 | f_gradient_hat = self.f_gradient / (1-np.power(self.ewma_1,self.t)) 44 | self.variance = self.ewma_2*self.variance + (1-self.ewma_2)*np.power(gradient,2) 45 | variance_hat = self.variance / (1-np.power(self.ewma_2,self.t)) 46 | if self.t > 5: 47 | self.parameters += (self.learning_rate+(self.learning_rate*15.0*(0.990**self.t)))*(f_gradient_hat/(np.sqrt(variance_hat)+self.epsilon)) 48 | self.t += 1 49 | return self.parameters -------------------------------------------------------------------------------- /pyflux/output/__init__.py: -------------------------------------------------------------------------------- 1 | from .tableprinter import TablePrinter 2 | -------------------------------------------------------------------------------- /pyflux/output/tableprinter.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | # Credit to Hugh Bothwell from http://stackoverflow.com/questions/5084743/how-to-print-pretty-string-output-in-python 4 | class TablePrinter(object): 5 | "Print a list of dicts as a table" 6 | def __init__(self, fmt, sep=' ', ul=None): 7 | """ 8 | @param fmt: list of tuple(heading, key, width) 9 | heading: str, column label 10 | key: dictionary key to value to print 11 | width: int, column width in chars 12 | @param sep: string, separation between columns 13 | @param ul: string, character to underline column label, or None for no underlining 14 | """ 15 | super(TablePrinter,self).__init__() 16 | self.fmt = str(sep).join('{lb}{0}:{1}{rb}'.format(key, width, lb='{', rb='}') for heading,key,width in fmt) 17 | self.head = {key:heading for heading,key,width in fmt} 18 | self.ul = {key:str(ul)*width for heading,key,width in fmt} if ul else None 19 | self.width = {key:width for heading,key,width in fmt} 20 | 21 | def row(self, data): 22 | if sys.version_info < (3,): 23 | return self.fmt.format(**{ k:str(data.get(k,''))[:w] for k,w in self.width.iteritems() }) 24 | else: 25 | return self.fmt.format(**{ k:str(data.get(k,''))[:w] for k,w in self.width.items() }) 26 | 27 | def __call__(self, dataList): 28 | _r = self.row 29 | res = [_r(data) for data in dataList] 30 | res.insert(0, _r(self.head)) 31 | if self.ul: 32 | res.insert(1, _r(self.ul)) 33 | return '\n'.join(res) -------------------------------------------------------------------------------- /pyflux/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | PACKAGE_NAME = 'pyflux' 4 | 5 | 6 | def configuration(parent_package='', top_path=None): 7 | from numpy.distutils.misc_util import Configuration 8 | 9 | config = Configuration(PACKAGE_NAME, parent_package, top_path) 10 | 11 | config.add_subpackage('__check_build') 12 | 13 | config.add_subpackage('arma') 14 | config.add_subpackage('ensembles') 15 | config.add_subpackage('families') 16 | config.add_subpackage('garch') 17 | config.add_subpackage('gas') 18 | config.add_subpackage('gpnarx') 19 | config.add_subpackage('inference') 20 | config.add_subpackage('output') 21 | config.add_subpackage('ssm') 22 | config.add_subpackage('tests') 23 | config.add_subpackage('var') 24 | return config 25 | 26 | 27 | if __name__ == '__main__': 28 | from numpy.distutils.core import setup 29 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/ssm/__init__.py: -------------------------------------------------------------------------------- 1 | from .llm import LLEV 2 | from .llt import LLT 3 | from .nllm import NLLEV 4 | from .nllt import NLLT 5 | from .dynlin import DynReg 6 | from .dar import DAR 7 | from .ndynlin import NDynReg 8 | from .kalman import nl_univariate_KFS, nld_univariate_KFS 9 | from .local_level import LocalLevel 10 | from .local_trend import LocalTrend 11 | from .dynamic_glm import DynamicGLM -------------------------------------------------------------------------------- /pyflux/ssm/dynamic_glm.py: -------------------------------------------------------------------------------- 1 | from .. import families as fam 2 | from .. import tsm as tsm 3 | 4 | from .dynlin import * 5 | from .ndynlin import * 6 | 7 | class DynamicGLM(tsm.TSM): 8 | """ Wrapper for dynamic GLM models 9 | 10 | Parameters 11 | ---------- 12 | formula : str 13 | Patsy string specifying the regression 14 | 15 | data : pd.DataFrame or np.array 16 | Field to specify the time series data that will be used. 17 | 18 | family : 19 | e.g. pf.Normal(0,1) 20 | """ 21 | 22 | def __new__(cls, formula, data, family): 23 | if isinstance(family, fam.Normal): 24 | return DynReg(formula=formula, data=data) 25 | else: 26 | return NDynReg(formula=formula, data=data, family=family) 27 | 28 | def __init__(self, formula, data, family): 29 | pass 30 | 31 | -------------------------------------------------------------------------------- /pyflux/ssm/local_level.py: -------------------------------------------------------------------------------- 1 | from .. import families as fam 2 | from .. import tsm as tsm 3 | 4 | from .llm import * 5 | from .nllm import * 6 | 7 | class LocalLevel(tsm.TSM): 8 | """ Wrapper for local level models 9 | 10 | **** LOCAL LEVEL MODEL **** 11 | 12 | Parameters 13 | ---------- 14 | data : pd.DataFrame or np.array 15 | Field to specify the time series data that will be used. 16 | 17 | integ : int (default : 0) 18 | Specifies how many times to difference the time series. 19 | 20 | target : str (pd.DataFrame) or int (np.array) 21 | Specifies which column name or array index to use. By default, first 22 | column/array will be selected as the dependent variable. 23 | 24 | family : 25 | e.g. pf.Normal(0,1) 26 | """ 27 | 28 | def __new__(cls, data, family, integ=0, target=None): 29 | if isinstance(family, fam.Normal): 30 | return LLEV(data=data, integ=integ, target=target) 31 | else: 32 | return NLLEV(data=data, family=family, integ=integ, target=target) 33 | 34 | def __init__(self, data, family, integ=0, target=None): 35 | pass 36 | 37 | -------------------------------------------------------------------------------- /pyflux/ssm/local_trend.py: -------------------------------------------------------------------------------- 1 | from .. import families as fam 2 | from .. import tsm as tsm 3 | 4 | from .llt import * 5 | from .nllt import * 6 | 7 | class LocalTrend(tsm.TSM): 8 | """ Wrapper for local linear trend models 9 | 10 | **** LOCAL LINEAR TREND MODEL **** 11 | 12 | Parameters 13 | ---------- 14 | data : pd.DataFrame or np.array 15 | Field to specify the time series data that will be used. 16 | 17 | integ : int (default : 0) 18 | Specifies how many times to difference the time series. 19 | 20 | target : str (pd.DataFrame) or int (np.array) 21 | Specifies which column name or array index to use. By default, first 22 | column/array will be selected as the dependent variable. 23 | 24 | family : 25 | e.g. pf.Normal(0,1) 26 | """ 27 | 28 | def __new__(cls, data, family, integ=0, target=None): 29 | if isinstance(family, fam.Normal): 30 | return LLT(data=data, integ=integ, target=target) 31 | else: 32 | return NLLT(data=data, family=family, integ=integ, target=target) 33 | 34 | def __init__(self, data, family, integ=0, target=None): 35 | pass 36 | 37 | -------------------------------------------------------------------------------- /pyflux/ssm/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def configuration(parent_package='', top_path=None): 5 | from numpy.distutils.misc_util import Configuration 6 | 7 | config = Configuration('ssm', parent_package, top_path) 8 | 9 | config.add_extension('kalman', 10 | sources=['kalman.c']) 11 | 12 | return config 13 | 14 | 15 | if __name__ == '__main__': 16 | from numpy.distutils.core import setup 17 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/ssm/tests/__pycache__/dar_tests.cpython-35-PYTEST.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RJT1990/pyflux/297f2afc2095acd97c12e827dd500e8ea5da0c0f/pyflux/ssm/tests/__pycache__/dar_tests.cpython-35-PYTEST.pyc -------------------------------------------------------------------------------- /pyflux/ssm/tests/dar_tests.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pyflux as pf 3 | 4 | noise = np.random.normal(0,1,100) 5 | data = np.zeros(100) 6 | 7 | for i in range(1,len(data)): 8 | data[i] = 0.9*data[i-1] + noise[i] 9 | 10 | def test_couple_terms(): 11 | """ 12 | Tests an DAR model with 1 AR and that 13 | the latent variable list length is correct, and that the estimated 14 | latent variables are not nan 15 | """ 16 | model = pf.DAR(data=data, ar=1) 17 | x = model.fit() 18 | assert(len(model.latent_variables.z_list) == 3) 19 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 20 | assert(len(lvs[np.isnan(lvs)]) == 0) 21 | 22 | def test_couple_terms_integ(): 23 | """ 24 | Tests an DAR model with 1 AR, integrated once, and that 25 | the latent variable list length is correct, and that the estimated 26 | latent variables are not nan 27 | """ 28 | model = pf.DAR(data=data, ar=1, integ=1) 29 | x = model.fit() 30 | assert(len(model.latent_variables.z_list) == 3) 31 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 32 | assert(len(lvs[np.isnan(lvs)]) == 0) 33 | 34 | def test_bbvi(): 35 | """ 36 | Tests an DAR model estimated with BBVI and that the length of the latent variable 37 | list is correct, and that the estimated latent variables are not nan 38 | """ 39 | model = pf.DAR(data=data, ar=1) 40 | x = model.fit('BBVI',iterations=100) 41 | assert(len(model.latent_variables.z_list) == 3) 42 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 43 | assert(len(lvs[np.isnan(lvs)]) == 0) 44 | 45 | def test_mh(): 46 | """ 47 | Tests an DAR model estimated with Metropolis-Hastings and that the length of the 48 | latent variable list is correct, and that the estimated latent variables are not nan 49 | """ 50 | model = pf.DAR(data=data, ar=1) 51 | x = model.fit('M-H',nsims=300) 52 | assert(len(model.latent_variables.z_list) == 3) 53 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 54 | assert(len(lvs[np.isnan(lvs)]) == 0) 55 | 56 | def test_laplace(): 57 | """ 58 | Tests an DAR model estimated with Laplace approximation and that the length of the 59 | latent variable list is correct, and that the estimated latent variables are not nan 60 | """ 61 | model = pf.DAR(data=data, ar=1) 62 | x = model.fit('Laplace') 63 | assert(len(model.latent_variables.z_list) == 3) 64 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 65 | assert(len(lvs[np.isnan(lvs)]) == 0) 66 | 67 | def test_pml(): 68 | """ 69 | Tests a PML model estimated with Laplace approximation and that the length of the 70 | latent variable list is correct, and that the estimated latent variables are not nan 71 | """ 72 | model = pf.DAR(data=data, ar=1) 73 | x = model.fit('PML') 74 | assert(len(model.latent_variables.z_list) == 3) 75 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 76 | assert(len(lvs[np.isnan(lvs)]) == 0) 77 | 78 | def test_predict_length(): 79 | """ 80 | Tests that the prediction dataframe length is equal to the number of steps h 81 | """ 82 | model = pf.DAR(data=data, ar=2) 83 | x = model.fit() 84 | x.summary() 85 | assert(model.predict(h=5).shape[0] == 5) 86 | 87 | def test_predict_is_length(): 88 | """ 89 | Tests that the prediction IS dataframe length is equal to the number of steps h 90 | """ 91 | model = pf.DAR(data=data, ar=2) 92 | x = model.fit() 93 | assert(model.predict_is(h=5).shape[0] == 5) 94 | 95 | def test_predict_nans(): 96 | """ 97 | Tests that the predictions are not nans 98 | """ 99 | model = pf.DAR(data=data, ar=2) 100 | x = model.fit() 101 | x.summary() 102 | assert(len(model.predict(h=5).values[np.isnan(model.predict(h=5).values)]) == 0) 103 | 104 | def test_predict_is_nans(): 105 | """ 106 | Tests that the in-sample predictions are not nans 107 | """ 108 | model = pf.DAR(data=data, ar=2) 109 | x = model.fit() 110 | x.summary() 111 | assert(len(model.predict_is(h=5).values[np.isnan(model.predict_is(h=5).values)]) == 0) -------------------------------------------------------------------------------- /pyflux/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from .nhst import find_p_value 2 | -------------------------------------------------------------------------------- /pyflux/tests/nhst.py: -------------------------------------------------------------------------------- 1 | import scipy.stats as ss 2 | 3 | def find_p_value(z): 4 | p_value = 0 5 | if z>=0: 6 | p_value += (1-ss.norm.cdf(z,loc=0,scale=1)) 7 | p_value += (ss.norm.cdf(-z,loc=0,scale=1)) 8 | else: 9 | p_value += (1-ss.norm.cdf(-z,loc=0,scale=1)) 10 | p_value += (ss.norm.cdf(z,loc=0,scale=1)) 11 | return p_value -------------------------------------------------------------------------------- /pyflux/var/__init__.py: -------------------------------------------------------------------------------- 1 | from .var import VAR 2 | -------------------------------------------------------------------------------- /pyflux/var/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def configuration(parent_package='', top_path=None): 5 | from numpy.distutils.misc_util import Configuration 6 | 7 | config = Configuration('var', parent_package, top_path) 8 | 9 | config.add_extension('var_recursions', 10 | sources=['var_recursions.c']) 11 | 12 | return config 13 | 14 | 15 | if __name__ == '__main__': 16 | from numpy.distutils.core import setup 17 | setup(**configuration(top_path='').todict()) -------------------------------------------------------------------------------- /pyflux/var/tests/var_tests.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pyflux as pf 3 | import pandas as pd 4 | 5 | noise_1 = np.random.normal(0,1,350) 6 | noise_2 = np.random.normal(0,1,350) 7 | data_1 = np.zeros(350) 8 | data_2 = np.zeros(350) 9 | 10 | for i in range(1,len(data_1)): 11 | data_1[i] = 0.9*data_1[i-1] + noise_1[i] 12 | data_2[i] = 0.9*data_2[i-1] + noise_2[i] 13 | 14 | data = pd.DataFrame([data_1,data_2]).T 15 | data.columns = ['test1','test2'] 16 | 17 | # Uncomment once PML/Laplace approximation is more robust 18 | 19 | def test_couple_terms(): 20 | """ 21 | Tests an VAR model with 1 AR and 1 MA term and that 22 | the latent variable list length is correct, and that the estimated 23 | latent variables are not nan 24 | """ 25 | model = pf.VAR(data=data, lags=2) 26 | x = model.fit() 27 | assert(len(model.latent_variables.z_list) == 13) 28 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 29 | assert(len(lvs[np.isnan(lvs)]) == 0) 30 | 31 | def test_couple_terms_integ(): 32 | """ 33 | Tests an VAR model with 1 AR and 1 MA term, integrated once, and that 34 | the latent variable list length is correct, and that the estimated 35 | latent variables are not nan 36 | """ 37 | model = pf.VAR(data=data, lags=2, integ=1) 38 | x = model.fit() 39 | assert(len(model.latent_variables.z_list) == 13) 40 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 41 | assert(len(lvs[np.isnan(lvs)]) == 0) 42 | 43 | def test_bbvi(): 44 | """ 45 | Tests an VAR model estimated with BBVI and that the length of the latent variable 46 | list is correct, and that the estimated latent variables are not nan 47 | """ 48 | model = pf.VAR(data=data, lags=2) 49 | x = model.fit('BBVI',iterations=100) 50 | assert(len(model.latent_variables.z_list) == 13) 51 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 52 | assert(len(lvs[np.isnan(lvs)]) == 0) 53 | 54 | def test_mh(): 55 | """ 56 | Tests an VAR model estimated with Metropolis-Hastings and that the length of the 57 | latent variable list is correct, and that the estimated latent variables are not nan 58 | """ 59 | model = pf.VAR(data=data, lags=2) 60 | x = model.fit('M-H',nsims=300) 61 | assert(len(model.latent_variables.z_list) == 13) 62 | lvs = np.array([i.value for i in model.latent_variables.z_list]) 63 | assert(len(lvs[np.isnan(lvs)]) == 0) 64 | 65 | #def test_laplace(): 66 | # """ 67 | # Tests an VAR model estimated with Laplace approximation and that the length of the 68 | # latent variable list is correct, and that the estimated latent variables are not nan 69 | # """ 70 | # model = pf.VAR(data=data, lags=2) 71 | # x = model.fit('Laplace') 72 | # assert(len(model.latent_variables.z_list) == 13) 73 | # lvs = np.array([i.value for i in model.latent_variables.z_list]) 74 | # assert(len(lvs[np.isnan(lvs)]) == 0) 75 | 76 | #def test_pml(): 77 | # """ 78 | # Tests a PML model estimated with Laplace approximation and that the length of the 79 | # latent variable list is correct, and that the estimated latent variables are not nan 80 | # """ 81 | # model = pf.VAR(data=data, lags=2) 82 | # x = model.fit('PML') 83 | # assert(len(model.latent_variables.z_list) == 13) 84 | # lvs = np.array([i.value for i in model.latent_variables.z_list]) 85 | # assert(len(lvs[np.isnan(lvs)]) == 0) 86 | 87 | def test_predict_length(): 88 | """ 89 | Tests that the prediction dataframe length is equal to the number of steps h 90 | """ 91 | model = pf.VAR(data=data, lags=2) 92 | x = model.fit() 93 | assert(model.predict(h=5).shape[0] == 5) 94 | 95 | def test_predict_is_length(): 96 | """ 97 | Tests that the prediction IS dataframe length is equal to the number of steps h 98 | """ 99 | model = pf.VAR(data=data, lags=2) 100 | x = model.fit() 101 | assert(model.predict_is(h=5).shape[0] == 5) 102 | 103 | def test_predict_nans(): 104 | """ 105 | Tests that the predictions are not nans 106 | """ 107 | model = pf.VAR(data=data, lags=2) 108 | x = model.fit() 109 | assert(len(model.predict(h=5).values[np.isnan(model.predict(h=5).values)]) == 0) 110 | 111 | def test_predict_is_nans(): 112 | """ 113 | Tests that the in-sample predictions are not nans 114 | """ 115 | model = pf.VAR(data=data, lags=2) 116 | x = model.fit() 117 | assert(len(model.predict_is(h=5).values[np.isnan(model.predict_is(h=5).values)]) == 0) -------------------------------------------------------------------------------- /pyflux/var/var_recursions.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport numpy as np 3 | cimport cython 4 | 5 | @cython.boundscheck(False) 6 | @cython.wraparound(False) 7 | @cython.cdivision(True) 8 | def create_design_matrix(np.ndarray[double,ndim=2] Z, np.ndarray[double,ndim=2] data, int Y_len, int lag_no): 9 | 10 | cdef Py_ssize_t row_count, lag, reg 11 | 12 | row_count = 1 13 | 14 | for lag in range(1, lag_no+1): 15 | for reg in range(Y_len): 16 | Z[row_count, :] = data[reg][(lag_no-lag):-lag] 17 | row_count += 1 18 | 19 | return Z 20 | 21 | @cython.boundscheck(False) 22 | @cython.wraparound(False) 23 | @cython.cdivision(True) 24 | def custom_covariance_matrix(np.ndarray[double,ndim=2] cov_matrix, int Y_len, int lag_no, np.ndarray[double,ndim=1] parm): 25 | 26 | cdef Py_ssize_t quick_count, i, k, index 27 | 28 | quick_count = 0 29 | 30 | for i in range(0,Y_len): 31 | for k in range(0,Y_len): 32 | if i >= k: 33 | index = Y_len + lag_no*(Y_len**2) + quick_count 34 | quick_count += 1 35 | cov_matrix[i,k] = parm[index] 36 | 37 | return np.dot(cov_matrix,cov_matrix.T) 38 | 39 | @cython.boundscheck(False) 40 | @cython.wraparound(False) 41 | @cython.cdivision(True) 42 | def var_likelihood(float ll1, int mu_shape, np.ndarray[double,ndim=2] diff, np.ndarray[double,ndim=2] inverse): 43 | 44 | cdef Py_ssize_t t 45 | cdef float ll2 46 | 47 | for t in range(0,mu_shape): 48 | ll2 += np.dot(np.dot(diff[t].T,inverse),diff[t]) 49 | 50 | return -(ll1 -0.5*ll2) 51 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | numpy>=1.13.0 2 | pandas>=0.20.2 3 | scipy>=0.19.0 4 | patsy>=0.4.1 5 | numdifftools>=0.9.16 6 | matplotlib>=2.0.2 7 | seaborn>=0.7.1 8 | pandas-datareader>=0.4.0 9 | Cython 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy>=1.13.0 2 | pandas>=0.20.2 3 | scipy>=0.19.0 4 | patsy>=0.4.1 5 | numdifftools>=0.9.16 6 | matplotlib>=2.0.2 7 | seaborn>=0.7.1 8 | pandas-datareader>=0.4.0 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import io 2 | import os 3 | import re 4 | import sys 5 | import subprocess 6 | 7 | # Use of SETUP built-in adapted from scikit-learn's setup structure. 8 | 9 | if sys.version_info[0] < 3: 10 | import __builtin__ as builtins 11 | else: 12 | import builtins 13 | 14 | builtins.__PYFLUX_SETUP__ = True 15 | 16 | PACKAGE_NAME = 'pyflux' 17 | DESCRIPTION = "PyFlux: A time-series analysis library for Python" 18 | LONG_DESCRIPTION = DESCRIPTION 19 | AUTHOR = "Ross Taylor" 20 | AUTHOR_EMAIL = "rj-taylor@live.co.uk" 21 | URL = 'https://github.com/rjt1990/pyflux' 22 | DOWNLOAD_URL = 'https://github.com/rjt1990/pyflux/tarball/0.4.17' 23 | LICENSE = 'BSD' 24 | 25 | def version(package, encoding='utf-8'): 26 | """Obtain the packge version from a python file e.g. pkg/__init__.py 27 | See . 28 | """ 29 | path = os.path.join(os.path.dirname(__file__), package, '__init__.py') 30 | with io.open(path, encoding=encoding) as fp: 31 | version_info = fp.read() 32 | version_match = re.search(r"""^__version__ = ['"]([^'"]*)['"]""", 33 | version_info, re.M) 34 | if not version_match: 35 | raise RuntimeError("Unable to find version string.") 36 | return version_match.group(1) 37 | 38 | def generate_cython(package): 39 | """Cythonize all sources in the package""" 40 | cwd = os.path.abspath(os.path.dirname(__file__)) 41 | print("Cythonizing sources") 42 | p = subprocess.call([sys.executable, 43 | os.path.join(cwd, 'tools', 'cythonize.py'), 44 | package], 45 | cwd=cwd) 46 | if p != 0: 47 | raise RuntimeError("Running cythonize failed!") 48 | 49 | def configuration(parent_package='',top_path=None): 50 | from numpy.distutils.misc_util import Configuration 51 | config = Configuration(None, parent_package, top_path) 52 | config.set_options(ignore_setup_xxx_py=True, 53 | assume_default_configuration=True, 54 | delegate_options_to_subpackages=True, 55 | quiet=True) 56 | 57 | config.add_subpackage(PACKAGE_NAME) 58 | 59 | return config 60 | 61 | def setup_package(): 62 | from numpy.distutils.core import setup 63 | old_path = os.getcwd() 64 | local_path = os.path.dirname(os.path.abspath(sys.argv[0])) 65 | src_path = local_path 66 | 67 | os.chdir(local_path) 68 | sys.path.insert(0, local_path) 69 | 70 | # Run build 71 | old_path = os.getcwd() 72 | os.chdir(src_path) 73 | sys.path.insert(0, src_path) 74 | 75 | cwd = os.path.abspath(os.path.dirname(__file__)) 76 | if not os.path.exists(os.path.join(cwd, 'PKG-INFO')): 77 | # Generate Cython sources, unless building from source release 78 | generate_cython(PACKAGE_NAME) 79 | 80 | try: 81 | setup(name=PACKAGE_NAME, 82 | author=AUTHOR, 83 | author_email=AUTHOR_EMAIL, 84 | url=URL, 85 | download_url=DOWNLOAD_URL, 86 | description=DESCRIPTION, 87 | long_description = LONG_DESCRIPTION, 88 | version=version(PACKAGE_NAME), 89 | license=LICENSE, 90 | configuration=configuration, 91 | keywords = ['time series','machine learning','bayesian statistics'], 92 | install_requires=['numpy', 'pandas', 'scipy', 'numdifftools','patsy']) 93 | finally: 94 | del sys.path[0] 95 | os.chdir(old_path) 96 | 97 | return 98 | 99 | if __name__ == '__main__': 100 | setup_package() -------------------------------------------------------------------------------- /tools/cythonize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ cythonize 3 | Cythonize pyx files into C files as needed. 4 | Usage: cythonize [root_dir] 5 | Checks pyx files to see if they have been changed relative to their 6 | corresponding C files. If they have, then runs cython on these files to 7 | recreate the C files. 8 | The script detects changes in the pyx/pxd files using checksums 9 | [or hashes] stored in a database file 10 | Simple script to invoke Cython on all .pyx 11 | files; while waiting for a proper build system. Uses file hashes to 12 | figure out if rebuild is needed. 13 | It is called by ./setup.py sdist so that sdist package can be installed without 14 | cython 15 | Originally written by Dag Sverre Seljebotn, and adapted from statsmodel 0.6.1 16 | (Modified BSD 3-clause) 17 | We copied it for scikit-learn. 18 | Note: this script does not check any of the dependent C libraries; it only 19 | operates on the Cython .pyx files or their corresponding Cython header (.pxd) 20 | files. 21 | """ 22 | # Author: Arthur Mensch 23 | # Author: Raghav R V 24 | # 25 | # License: BSD 3 clause 26 | # see http://github.com/scikit-learn/scikit-learn 27 | 28 | 29 | from __future__ import division, print_function, absolute_import 30 | 31 | import os 32 | import re 33 | import sys 34 | import hashlib 35 | import subprocess 36 | 37 | HASH_FILE = 'cythonize.dat' 38 | 39 | 40 | # WindowsError is not defined on unix systems 41 | try: 42 | WindowsError 43 | except NameError: 44 | WindowsError = None 45 | 46 | 47 | def cythonize(cython_file, gen_file): 48 | try: 49 | from Cython.Compiler.Version import version as cython_version 50 | from distutils.version import LooseVersion 51 | if LooseVersion(cython_version) < LooseVersion('0.21'): 52 | raise Exception('Building scikit-learn requires Cython >= 0.21') 53 | 54 | except ImportError: 55 | pass 56 | 57 | flags = ['--fast-fail'] 58 | if gen_file.endswith('.cpp'): 59 | flags += ['--cplus'] 60 | 61 | try: 62 | try: 63 | rc = subprocess.call(['cython'] + 64 | flags + ["-o", gen_file, cython_file]) 65 | if rc != 0: 66 | raise Exception('Cythonizing %s failed' % cython_file) 67 | except OSError: 68 | # There are ways of installing Cython that don't result in a cython 69 | # executable on the path, see scipy issue gh-2397. 70 | rc = subprocess.call([sys.executable, '-c', 71 | 'import sys; from Cython.Compiler.Main ' 72 | 'import setuptools_main as main;' 73 | ' sys.exit(main())'] + flags + 74 | ["-o", gen_file, cython_file]) 75 | if rc != 0: 76 | raise Exception('Cythonizing %s failed' % cython_file) 77 | except OSError: 78 | raise OSError('Cython needs to be installed') 79 | 80 | 81 | def load_hashes(filename): 82 | """Load the hashes dict from the hashfile""" 83 | # { filename : (sha1 of header if available or 'NA', 84 | # sha1 of input, 85 | # sha1 of output) } 86 | 87 | hashes = {} 88 | try: 89 | with open(filename, 'r') as cython_hash_file: 90 | for hash_record in cython_hash_file: 91 | (filename, header_hash, 92 | cython_hash, gen_file_hash) = hash_record.split() 93 | hashes[filename] = (header_hash, cython_hash, gen_file_hash) 94 | except (KeyError, ValueError, AttributeError, IOError): 95 | hashes = {} 96 | return hashes 97 | 98 | 99 | def save_hashes(hashes, filename): 100 | """Save the hashes dict to the hashfile""" 101 | with open(filename, 'w') as cython_hash_file: 102 | for key, value in hashes.items(): 103 | cython_hash_file.write("%s %s %s %s\n" 104 | % (key, value[0], value[1], value[2])) 105 | 106 | 107 | def sha1_of_file(filename): 108 | h = hashlib.sha1() 109 | with open(filename, "rb") as f: 110 | h.update(f.read()) 111 | return h.hexdigest() 112 | 113 | 114 | def clean_path(path): 115 | """Clean the path""" 116 | path = path.replace(os.sep, '/') 117 | if path.startswith('./'): 118 | path = path[2:] 119 | return path 120 | 121 | 122 | def get_hash_tuple(header_path, cython_path, gen_file_path): 123 | """Get the hashes from the given files""" 124 | 125 | header_hash = (sha1_of_file(header_path) 126 | if os.path.exists(header_path) else 'NA') 127 | from_hash = sha1_of_file(cython_path) 128 | to_hash = (sha1_of_file(gen_file_path) 129 | if os.path.exists(gen_file_path) else 'NA') 130 | 131 | return header_hash, from_hash, to_hash 132 | 133 | 134 | def cythonize_if_unchanged(path, cython_file, gen_file, hashes): 135 | full_cython_path = os.path.join(path, cython_file) 136 | full_header_path = full_cython_path.replace('.pyx', '.pxd') 137 | full_gen_file_path = os.path.join(path, gen_file) 138 | 139 | current_hash = get_hash_tuple(full_header_path, full_cython_path, 140 | full_gen_file_path) 141 | 142 | if current_hash == hashes.get(clean_path(full_cython_path)): 143 | print('%s has not changed' % full_cython_path) 144 | return 145 | 146 | print('Processing %s' % full_cython_path) 147 | cythonize(full_cython_path, full_gen_file_path) 148 | 149 | # changed target file, recompute hash 150 | current_hash = get_hash_tuple(full_header_path, full_cython_path, 151 | full_gen_file_path) 152 | 153 | # Update the hashes dict with the new hash 154 | hashes[clean_path(full_cython_path)] = current_hash 155 | 156 | 157 | def check_and_cythonize(root_dir): 158 | print(root_dir) 159 | hashes = load_hashes(HASH_FILE) 160 | 161 | for cur_dir, dirs, files in os.walk(root_dir): 162 | for filename in files: 163 | if filename.endswith('.pyx'): 164 | gen_file_ext = '.c' 165 | # Cython files with libcpp imports should be compiled to cpp 166 | with open(os.path.join(cur_dir, filename), 'rb') as f: 167 | data = f.read() 168 | m = re.search(b"libcpp", data, re.I | re.M) 169 | if m: 170 | gen_file_ext = ".cpp" 171 | cython_file = filename 172 | gen_file = filename.replace('.pyx', gen_file_ext) 173 | cythonize_if_unchanged(cur_dir, cython_file, gen_file, hashes) 174 | 175 | # Save hashes once per module. This prevents cythonizing prev. 176 | # files again when debugging broken code in a single file 177 | save_hashes(hashes, HASH_FILE) 178 | 179 | 180 | def main(root_dir): 181 | check_and_cythonize(root_dir) 182 | 183 | 184 | if __name__ == '__main__': 185 | try: 186 | root_dir_arg = sys.argv[1] 187 | except IndexError: 188 | raise ValueError("Usage: python cythonize.py ") 189 | main(root_dir_arg) --------------------------------------------------------------------------------