├── .coveragerc ├── .github └── workflows │ ├── build-and-tests.yml │ └── publish-to-pypi.yml ├── .gitignore ├── .readthedocs.yaml ├── LICENSE ├── README.rst ├── docs ├── Makefile ├── make.bat ├── requirements.txt └── source │ ├── _static │ ├── blue_pysloth_logo.png │ ├── inverted_pysloth_logo.png │ └── pysloth_logo.png │ ├── api_reference │ └── index.rst │ ├── conf.py │ ├── index.rst │ ├── installation │ └── index.rst │ └── quickstart │ └── index.rst ├── etc ├── old_icpd_repo │ ├── CCPD.py │ ├── CRPS.py │ ├── CRPS_function.py │ ├── README.md │ ├── SCPD.py │ └── notebook.ipynb ├── requirements-dev.txt └── requirements.txt ├── pysloth └── __init__.py ├── setup.cfg ├── setup.py └── tests ├── __init__.py └── test_pysloth.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = pysloth 4 | 5 | [report] 6 | exclude_lines = 7 | if self.debug: 8 | pragma: no cover 9 | raise NotImplementedError 10 | if __name__ == .__main__.: 11 | ignore_errors = True 12 | omit = 13 | tests/* 14 | docs/* 15 | etc/* 16 | setup.py 17 | 18 | [html] 19 | directory = coverage_html_report 20 | -------------------------------------------------------------------------------- /.github/workflows/build-and-tests.yml: -------------------------------------------------------------------------------- 1 | name: build-and-tests 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | python-version: [3.6, 3.7, 3.8, 3.9] 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up Python ${{ matrix.python-version }} 20 | uses: actions/setup-python@v2 21 | with: 22 | python-version: ${{ matrix.python-version }} 23 | - name: Install dependencies 24 | run: | 25 | python -m pip install --upgrade pip 26 | python -m pip install flake8 pytest 27 | python -m pip install . 28 | python -m pip install codecov 29 | python -m pip install pytest-cov 30 | - name: Lint with flake8 31 | run: | 32 | # stop the build if there are Python syntax errors or undefined names 33 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 34 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 35 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 36 | - name: Test with pytest and generate report 37 | run: | 38 | pytest --cov=./ --cov-report=xml 39 | - name: Upload coverage to Codecov 40 | uses: codecov/codecov-action@v1 41 | with: 42 | token: ${{ secrets.CODECOV_TOKEN }} 43 | files: ./coverage.xml 44 | directory: ./coverage/reports/ 45 | flags: unittests 46 | env_vars: OS,PYTHON 47 | name: codecov-umbrella 48 | fail_ci_if_error: true 49 | path_to_write_report: ./coverage/codecov_report.txt 50 | verbose: true 51 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-pypi.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | deploy: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Python 18 | uses: actions/setup-python@v2 19 | with: 20 | python-version: '3.x' 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | pip install setuptools wheel twine 25 | - name: Build and publish 26 | with: 27 | user: __token__ 28 | password: ${{ secrets.PYPI_API_TOKEN }} 29 | run: | 30 | python setup.py sdist bdist_wheel 31 | twine upload dist/* 32 | 33 | -------------------------------------------------------------------------------- /.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 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Build documentation in the docs/ directory with Sphinx 9 | sphinx: 10 | configuration: docs/source/conf.py 11 | 12 | # Optionally set the version of Python and requirements required to build your docs 13 | python: 14 | version: 3.7 15 | install: 16 | - requirements: docs/requirements.txt 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021 PySloth 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://img.shields.io/pypi/v/pysloth 2 | :target: https://pypi.org/project/pysloth/ 3 | 4 | .. image:: https://readthedocs.org/projects/pysloth/badge/?version=latest 5 | :target: https://pysloth.readthedocs.io/en/latest/?badge=latest 6 | :alt: Documentation Status 7 | 8 | .. image:: https://github.com/PySloth/pysloth/actions/workflows/build-and-tests.yml/badge.svg 9 | :target: https://github.com/PySloth/pysloth 10 | 11 | .. image:: https://codecov.io/gh/PySloth/pysloth/branch/main/graph/badge.svg?token=gAMTe66DIg 12 | :target: https://codecov.io/gh/PySloth/pysloth 13 | 14 | pysloth 15 | ======= 16 | A Python package for Probabilistic Prediction 17 | 18 | v0.0.3 19 | 20 | Installation 21 | ------------ 22 | This package supports Python 3.6, 3.7, 3.8, and 3.9 23 | 24 | Install via PyPI 25 | ~~~~~~~~~~~~~~~~ 26 | Run ``pip install pysloth`` 27 | 28 | Install from repository 29 | ~~~~~~~~~~~~~~~~~~~~~~~ 30 | * Clone repo with SSH ``git clone git@github.com:PySloth/pysloth.git`` 31 | * Change directory to where ``README.md`` (this file) is located and run ``pip install .`` 32 | 33 | Quickstart 34 | ---------- 35 | The following is a code sample showing ``scpd`` and ``ccpd`` in action 36 | 37 | .. code-block:: python 38 | 39 | from pysloth import scpd_function, ccpd_function 40 | 41 | import numpy as np 42 | import statsmodels.api as sm 43 | 44 | np.random.seed(142) 45 | n = 1000 # training set 46 | m = int(0.8 * n) # proper training set 47 | n_cal = n - m # Calibration = training - proper training 48 | 49 | n_test = 100 50 | sd_noise = 1 51 | 52 | n_delta = 1000 # discretization for y values in interval y_hat +/- 3 * delta 53 | w = 2 # the weights 54 | 55 | x_train = w * np.random.random(m) - 1 56 | x_cal = w * np.random.random(n_cal) - 1 57 | x_test = w * np.random.random(n_test) - 1 58 | 59 | y_train = w * x_train + np.random.randn(m) * sd_noise 60 | y_cal = w * x_cal + np.random.randn(n_cal) * sd_noise 61 | y_test = w * x_test + np.random.randn(n_test) * sd_noise 62 | 63 | x_train_cal = np.reshape(np.hstack((x_train, x_cal)), (n, 1)) 64 | y_train_cal = np.reshape(np.hstack((y_train, y_cal)), (n, 1)) 65 | xy_train_cal = np.hstack((x_train_cal, y_train_cal)) 66 | 67 | model = sm.OLS(y_train, x_train).fit() 68 | predictions = model.predict(x_train) 69 | model.summary() 70 | y_hat = model.predict(x_test) 71 | 72 | delta = 3 * np.std(y_hat) 73 | y_grid = np.linspace(y_hat.min() - delta, y_hat.max() + delta, n_delta) 74 | 75 | print(ccpd_function(x_train_cal, y_train_cal, x_test, y_grid, 5, n_delta)) 76 | print(scpd_function(x_train, x_cal, y_train, y_cal, x_test, y_test, y_grid, 5, n_delta)) 77 | 78 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | pydata-sphinx-theme>=0.5.0 2 | . 3 | -------------------------------------------------------------------------------- /docs/source/_static/blue_pysloth_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PySloth/pysloth/f7e9cbae912202a1ed2676609d114758e838f854/docs/source/_static/blue_pysloth_logo.png -------------------------------------------------------------------------------- /docs/source/_static/inverted_pysloth_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PySloth/pysloth/f7e9cbae912202a1ed2676609d114758e838f854/docs/source/_static/inverted_pysloth_logo.png -------------------------------------------------------------------------------- /docs/source/_static/pysloth_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PySloth/pysloth/f7e9cbae912202a1ed2676609d114758e838f854/docs/source/_static/pysloth_logo.png -------------------------------------------------------------------------------- /docs/source/api_reference/index.rst: -------------------------------------------------------------------------------- 1 | API Reference 2 | ============= 3 | 4 | .. automodule:: pysloth 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'pysloth' 21 | copyright = '2021, PySloth' 22 | author = 'PySloth' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = 'v0.0.2' 26 | 27 | master_doc = 'index' 28 | 29 | # -- General configuration --------------------------------------------------- 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = [ 35 | 'sphinx.ext.autodoc', 36 | 'sphinx.ext.napoleon' 37 | ] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ['_templates'] 41 | 42 | # List of patterns, relative to source directory, that match files and 43 | # directories to ignore when looking for source files. 44 | # This pattern also affects html_static_path and html_extra_path. 45 | exclude_patterns = [] 46 | 47 | 48 | # -- Options for HTML output ------------------------------------------------- 49 | 50 | # The theme to use for HTML and HTML Help pages. See the documentation for 51 | # a list of builtin themes. 52 | # 53 | html_theme = 'pydata_sphinx_theme' 54 | 55 | html_theme_options = { 56 | "github_url": "https://github.com/PySloth/pysloth", 57 | "show_prev_next": False, 58 | } 59 | 60 | # Add any paths that contain custom static files (such as style sheets) here, 61 | # relative to this directory. They are copied after the builtin static files, 62 | # so a file named "default.css" will overwrite the builtin "default.css". 63 | html_static_path = ['_static'] 64 | html_logo = "_static/blue_pysloth_logo.png" 65 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | PySloth 2 | ======= 3 | A Python package for Probabilistic Prediction 4 | 5 | .. toctree:: 6 | :maxdepth: 1 7 | 8 | installation/index 9 | 10 | quickstart/index 11 | 12 | api_reference/index 13 | -------------------------------------------------------------------------------- /docs/source/installation/index.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | This package supports Python 3.6, 3.7, 3.8, and 3.9 4 | 5 | Install via PyPI 6 | ~~~~~~~~~~~~~~~~ 7 | Run ``pip install pysloth`` 8 | 9 | Install from repository 10 | ~~~~~~~~~~~~~~~~~~~~~~~ 11 | * Clone repo with SSH ``git clone git@github.com:PySloth/pysloth.git`` 12 | * Change directory to where ``README.md`` (this file) is located and run ``pip install .`` -------------------------------------------------------------------------------- /docs/source/quickstart/index.rst: -------------------------------------------------------------------------------- 1 | Quickstart 2 | ========== 3 | 4 | The following is a code sample showing ``scpd`` and ``ccpd`` in action 5 | 6 | .. code-block:: python 7 | 8 | from pysloth import scpd_function, ccpd_function 9 | 10 | import numpy as np 11 | import statsmodels.api as sm 12 | 13 | np.random.seed(142) 14 | n = 1000 # training set 15 | m = int(0.8 * n) # proper training set 16 | n_cal = n - m # Calibration = training - proper training 17 | 18 | n_test = 100 19 | sd_noise = 1 20 | 21 | n_delta = 1000 # discretization for y values in interval y_hat +/- 3 * delta 22 | w = 2 # the weights 23 | 24 | x_train = w * np.random.random(m) - 1 25 | x_cal = w * np.random.random(n_cal) - 1 26 | x_test = w * np.random.random(n_test) - 1 27 | 28 | y_train = w * x_train + np.random.randn(m) * sd_noise 29 | y_cal = w * x_cal + np.random.randn(n_cal) * sd_noise 30 | y_test = w * x_test + np.random.randn(n_test) * sd_noise 31 | 32 | x_train_cal = np.reshape(np.hstack((x_train, x_cal)), (n, 1)) 33 | y_train_cal = np.reshape(np.hstack((y_train, y_cal)), (n, 1)) 34 | xy_train_cal = np.hstack((x_train_cal, y_train_cal)) 35 | 36 | model = sm.OLS(y_train, x_train).fit() 37 | predictions = model.predict(x_train) 38 | model.summary() 39 | y_hat = model.predict(x_test) 40 | 41 | delta = 3 * np.std(y_hat) 42 | y_grid = np.linspace(y_hat.min() - delta, y_hat.max() + delta, n_delta) 43 | 44 | print(ccpd_function(x_train_cal, y_train_cal, x_test, y_grid, 5, n_delta)) 45 | print(scpd_function(x_train, x_cal, y_train, y_cal, x_test, y_test, y_grid, 5, n_delta)) 46 | 47 | -------------------------------------------------------------------------------- /etc/old_icpd_repo/CCPD.py: -------------------------------------------------------------------------------- 1 | # Implement Cross Conformal Predictive Distributions 2 | 3 | import numpy as np 4 | from sklearn.model_selection import KFold 5 | import statsmodels.api as sm 6 | 7 | 8 | def CCPD_function(x_train_cal, y_train_cal, x_test, y_test, y_grid, K, n_delta): 9 | xy_train_cal = np.concatenate((x_train_cal, np.reshape(y_train_cal, (len(x_train_cal), 1))), axis=1) 10 | 11 | n = len(x_train_cal) 12 | n_test = len(x_test) 13 | S = np.empty(K) 14 | S[:] = np.NaN 15 | 16 | alpha_y_fold = np.empty((n_test, n_delta)) 17 | 18 | Q_folds = np.empty((n_test, n_delta, K)) 19 | Q_folds[:] = np.NaN 20 | 21 | p_folds = np.zeros((n_test, n_delta)) 22 | p_folds = np.zeros((n_test, n_delta)) 23 | 24 | kf = KFold(n_splits=K) 25 | 26 | 27 | # compute Q 28 | 29 | alpha_y_fold = np.empty((n_test, n_delta)) 30 | 31 | for l in range(len(x_test)): 32 | k = 0 33 | alpha_y_fold[:] = np.NaN 34 | for train_ind, cal_ind in kf.split(xy_train_cal): 35 | train_data = xy_train_cal[train_ind] 36 | cal_data = xy_train_cal[cal_ind] 37 | x_train = train_data[:, :-1] 38 | y_train = train_data[:, -1] 39 | x_cal = cal_data[:, :-1] 40 | y_cal = cal_data[:, -1] 41 | S[k] = len(x_cal) 42 | # train the model on the k-th training set 43 | model = sm.OLS(y_train, x_train).fit() 44 | y_hat_cal = model.predict(x_cal) # predictions on the calibration set 45 | y_hat = model.predict(x_test) # make predictions on the test set 46 | 47 | alpha_y_fold[l] = y_grid - y_hat[l] # compute alpha for test point 48 | alpha_cal_fold = y_cal - y_hat_cal 49 | 50 | # Compute Q 51 | for i in range(len(y_grid)): 52 | Q_folds[l, i, k] = 1 / (len(x_cal) + 1) * np.sum(alpha_cal_fold < alpha_y_fold[l, i]) 53 | k = k + 1 54 | 55 | # compute p 56 | for l in range(len(x_test)): 57 | for i in range(len(y_grid)): 58 | for k in range(K): 59 | p_folds[l, i] = p_folds[l, i] + S[k] / n * Q_folds[l, i, k] 60 | 61 | return (Q_folds, p_folds) # (Q_folds, p_folds) 62 | -------------------------------------------------------------------------------- /etc/old_icpd_repo/CRPS.py: -------------------------------------------------------------------------------- 1 | """ 2 | Function CRPS (formula in "Experimental results" section of the "Conformal predictive 3 | distributions based on kernel ridge regression" paper) 4 | Created on Fri Nov 24 18:24:26 2017 5 | @author: VM 6 | 7 | # yRange - range over which Q was computed 8 | # Q - distribution function (the prediction) 9 | # y - y-value of the test point 10 | # n - number of points in the training set 11 | """ 12 | import numpy as np 13 | 14 | 15 | def CRPS(yRange, Q, y, n): 16 | step = (yRange[-1] - yRange[0])/(len(yRange)-1) 17 | ind = np.max(np.where(y >= yRange)) 18 | Q1 = Q[0:(ind+1)] 19 | Q1 = (Q1 - 0.5/(n+1)) 20 | Q1[Q1 <= 0] = 0 21 | 22 | sum1 = np.sum(Q1[0:ind] ** 2) * step 23 | sum1 = sum1 + (Q1[ind] ** 2) * (y-yRange[ind]) 24 | 25 | Q2 = Q[ind:] 26 | Q2 = (1 - 0.5/(n+1) - Q2) 27 | Q2[Q2 <= 0] = 0 28 | 29 | sum2 = (Q2[1] ** 2) * (step - (y - yRange[ind])) 30 | sum2 = sum2 + np.sum(Q2[2:len(Q2)]**2) * step 31 | sum = sum1 + sum2 32 | return(sum) 33 | -------------------------------------------------------------------------------- /etc/old_icpd_repo/CRPS_function.py: -------------------------------------------------------------------------------- 1 | """ 2 | Function CRPS 3 | Created March 26 2018 4 | @author: VM 5 | 6 | # yRange - range over which Q was computed 7 | # Q - distribution function (the prediction) 8 | # y - y-value of the test point 9 | """ 10 | import numpy as np 11 | 12 | 13 | def CRPS_function(yRange, Q, y): 14 | step = (yRange[-1] - yRange[0])/(len(yRange)-1) 15 | ind = np.max(np.where(y >= yRange)) 16 | Q1 = Q[0:(ind+1)] 17 | 18 | #Q1[Q1<=0] = 0 19 | sum1 = np.sum(Q1[0:ind] ** 2) * step 20 | sum1 = sum1 + (Q1[ind] ** 2) * (y-yRange[ind]) 21 | 22 | Q2 = Q[ind:] 23 | Q2 = (1 - Q2) 24 | #Q2[Q2<=0] = 0 25 | 26 | sum2 = (Q2[1] ** 2) * (step - (y - yRange[ind])) 27 | sum2 = sum2 + np.sum(Q2[2:len(Q2)]**2) * step 28 | sum = sum1 + sum2 29 | return(sum) 30 | -------------------------------------------------------------------------------- /etc/old_icpd_repo/README.md: -------------------------------------------------------------------------------- 1 | # ICPD-python 2 | ICPD Python code for the paper "Split conformal predictive distributions" http://proceedings.mlr.press/v91/vovk18a.html # synthetic data set 3 | -------------------------------------------------------------------------------- /etc/old_icpd_repo/SCPD.py: -------------------------------------------------------------------------------- 1 | # Implement Split Conformal Predictive Distributions 2 | 3 | import numpy as np 4 | import statsmodels.api as sm 5 | 6 | 7 | def SCPD_function(x_train, x_cal, y_train, y_cal, x_test, y_test, y_grid, K, n_delta, shuffle_ind=True): 8 | n_test = len(x_test) 9 | if shuffle_ind == True: 10 | x_train_cal = np.concatenate((x_train, x_cal), axis=0) 11 | y_train_cal = np.concatenate((y_train, y_cal), axis=0) 12 | if (len(x_train_cal.shape) == 1): 13 | x_train_cal = np.reshape(x_train_cal, (-1, 1)) 14 | 15 | y_train_cal = np.reshape(y_train_cal, (-1, 1)) 16 | xy_train_cal = np.concatenate((x_train_cal, y_train_cal), axis=1) 17 | np.random.shuffle(xy_train_cal) 18 | n = len(xy_train_cal) 19 | n_cal = int(n/K) 20 | n_train = n - n_cal 21 | 22 | train_data = xy_train_cal[0:n_train] 23 | cal_data = xy_train_cal[n_train:] 24 | 25 | x_train = train_data[:, :-1] 26 | y_train = train_data[:, -1] 27 | x_cal = cal_data[:, :-1] 28 | y_cal = cal_data[:, -1] 29 | 30 | else: 31 | n_train = len(x_train) 32 | n_cal = len(x_cal) 33 | n = n_train + n_cal 34 | 35 | # Note the difference in argument order 36 | model = sm.OLS(y_train, x_train).fit() 37 | 38 | # Split (inductive) Conformal Predictive Distributions 39 | y_hat_cal = model.predict(x_cal) # make predictions on the calibration set 40 | alpha_cal = y_cal - y_hat_cal # compute alphas (conformity scores) on the calibrations set 41 | 42 | # initialize vector for storing CRPS for the test set 43 | CRPS = np.empty(n_test) 44 | 45 | # initialize array to store Q (the output of split conformal trancducer as per formua (1) in the paper) 46 | # Q_min corresponds to the value of tau = 0, Q_max corresponds to the value of tau = 1 47 | Q = np.empty((n_test, n_delta)) 48 | Q[:] = np.NaN 49 | # initialize array for storing alphas for the test set 50 | alpha_y = np.empty((n_test, n_delta)) 51 | alpha_y[:] = np.NaN 52 | 53 | # initialize array to store predictions of the underlying algorithm on the test set 54 | y_hat = np.empty(n_test) 55 | y_hat[:] = np.NaN 56 | 57 | # compute y_hat (predictions of the underlyin algorithm) on the test and calibration sets 58 | y_hat = model.predict(x_test) # make predictions by the model for the test set 59 | # delta = 6 * np.std(y_hat) # +/- delta around y_hat (predicted value of y_test, length of range around y_hat is 2 * delta 60 | #y_grid = np.linspace(y_hat.min() - delta, y_hat.max() + delta, n_delta) 61 | 62 | # compute Q & CRPS for the test set 63 | for l in range(n_test): 64 | # create the grid around y_hat 65 | alpha_y[l] = y_grid - y_hat[l] 66 | 67 | for i in range(len(y_grid)): 68 | Q[l, i] = 1 / (n_cal) * np.sum(alpha_cal < alpha_y[l, i]) 69 | 70 | CRPS[l] = CRPS_function(y_grid, Q[l], y_test[l]) 71 | 72 | return (Q, CRPS) 73 | 74 | 75 | def CRPS_function(yRange, Q, y): 76 | step = (yRange[-1] - yRange[0])/(len(yRange)-1) 77 | ind = np.max(np.where(y >= yRange)) 78 | Q1 = Q[0:(ind+1)] 79 | 80 | #Q1[Q1<=0] = 0 81 | sum1 = np.sum(Q1[0:ind] ** 2) * step 82 | sum1 = sum1 + (Q1[ind] ** 2) * (y-yRange[ind]) 83 | 84 | Q2 = Q[ind:] 85 | Q2 = (1 - Q2) 86 | #Q2[Q2<=0] = 0 87 | 88 | sum2 = 0 89 | 90 | if len(Q2) > 1: 91 | sum2 = (Q2[1] ** 2) * (step - (y - yRange[ind])) 92 | 93 | sum2 = sum2 + np.sum(Q2[2:len(Q2)]**2) * step 94 | sum = sum1 + sum2 95 | 96 | return(sum) 97 | -------------------------------------------------------------------------------- /etc/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | attrs==20.3.0 2 | autopep8==1.5.6 3 | flake8==3.9.0 4 | iniconfig==1.1.1 5 | joblib==1.0.1 6 | mccabe==0.6.1 7 | numpy==1.20.2 8 | packaging==20.9 9 | pandas==1.2.3 10 | patsy==0.5.1 11 | pluggy==0.13.1 12 | py==1.10.0 13 | pycodestyle==2.7.0 14 | pyflakes==2.3.1 15 | pyparsing==2.4.7 16 | pytest==6.2.3 17 | python-dateutil==2.8.1 18 | pytz==2021.1 19 | scikit-learn==0.24.1 20 | scipy==1.6.2 21 | six==1.15.0 22 | statsmodels==0.12.2 23 | threadpoolctl==2.1.0 24 | toml==0.10.2 25 | -------------------------------------------------------------------------------- /etc/requirements.txt: -------------------------------------------------------------------------------- 1 | joblib==1.0.1 2 | numpy==1.20.2 3 | pandas==1.2.3 4 | patsy==0.5.1 5 | python-dateutil==2.8.1 6 | pytz==2021.1 7 | scikit-learn==0.24.1 8 | scipy==1.6.2 9 | six==1.15.0 10 | statsmodels==0.12.2 11 | threadpoolctl==2.1.0 12 | -------------------------------------------------------------------------------- /pysloth/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import Tuple 2 | import numpy as np 3 | import statsmodels.api as sm 4 | from sklearn.model_selection import KFold 5 | 6 | 7 | def scpd_function( 8 | x_train: np.ndarray, 9 | x_cal: np.ndarray, 10 | y_train: np.ndarray, 11 | y_cal: np.ndarray, 12 | x_test: np.ndarray, 13 | y_test: np.ndarray, 14 | y_grid: np.ndarray, 15 | k: int, 16 | n_delta: int, 17 | shuffle_ind: bool = True 18 | ) -> Tuple[np.ndarray, np.ndarray]: 19 | """ Split Conformal Predictive Distributions 20 | 21 | Parameters 22 | ---------- 23 | x_train: np.ndarray 24 | Training features 25 | x_cal: np.ndarray 26 | Calibration features 27 | y_train: np.ndarray 28 | Training target 29 | y_cal: np.ndarray 30 | Calibration target 31 | x_test: np.ndarray 32 | Test features 33 | y_test: np.ndarray 34 | Test target 35 | y_grid: np.ndarray 36 | Target grid 37 | k: int 38 | Number of fold 39 | n_delta: int 40 | Number of discrete values in an interval 41 | shuffle_ind: bool 42 | Whether to shuffle indicators (default=True) 43 | 44 | Returns 45 | ------- 46 | Tuple[np.ndarray, np.ndarray] 47 | Output of split-conformal transducer (Q) and CRPS 48 | 49 | """ 50 | 51 | n_test = len(x_test) 52 | 53 | if shuffle_ind == True: 54 | x_train_cal = np.concatenate((x_train, x_cal), axis=0) 55 | y_train_cal = np.concatenate((y_train, y_cal), axis=0) 56 | if (len(x_train_cal.shape) == 1): 57 | x_train_cal = np.reshape(x_train_cal, (-1, 1)) 58 | 59 | y_train_cal = np.reshape(y_train_cal, (-1, 1)) 60 | xy_train_cal = np.concatenate((x_train_cal, y_train_cal), axis=1) 61 | np.random.shuffle(xy_train_cal) 62 | n = len(xy_train_cal) 63 | n_cal = int(n / k) 64 | n_train = n - n_cal 65 | 66 | train_data = xy_train_cal[0:n_train] 67 | cal_data = xy_train_cal[n_train:] 68 | 69 | x_train = train_data[:, :-1] 70 | y_train = train_data[:, -1] 71 | x_cal = cal_data[:, :-1] 72 | y_cal = cal_data[:, -1] 73 | 74 | else: 75 | n_train = len(x_train) 76 | n_cal = len(x_cal) 77 | n = n_train + n_cal 78 | 79 | model = sm.OLS(y_train, x_train).fit() 80 | 81 | y_hat_cal = model.predict(x_cal) 82 | alpha_cal = y_cal - y_hat_cal 83 | 84 | crps = np.empty(n_test) 85 | 86 | # Initialize array to store Q 87 | # Q_min corresponds to the value of tau = 0 88 | # Q_max corresponds to the value of tau = 1 89 | q = np.empty((n_test, n_delta)) 90 | q[:] = np.NaN 91 | 92 | alpha_y = np.empty((n_test, n_delta)) 93 | alpha_y[:] = np.NaN 94 | 95 | y_hat = np.empty(n_test) 96 | y_hat[:] = np.NaN 97 | y_hat = model.predict(x_test) 98 | 99 | # Compute Q & CRPS for the test set 100 | for l in range(n_test): 101 | alpha_y[l] = y_grid - y_hat[l] 102 | for i in range(len(y_grid)): 103 | q[l, i] = 1 / (n_cal) * np.sum(alpha_cal < alpha_y[l, i]) 104 | crps[l] = crps_function(y_grid, q[l], y_test[l]) 105 | 106 | return (q, crps) 107 | 108 | 109 | def ccpd_function( 110 | x_train_cal: np.ndarray, 111 | y_train_cal: np.ndarray, 112 | x_test: np.ndarray, 113 | y_grid: np.ndarray, 114 | k: int, 115 | n_delta: int 116 | ) -> Tuple[np.ndarray, np.ndarray]: 117 | """ Cross Conformal Predictive Distributions 118 | 119 | Parameters 120 | ---------- 121 | x_train_cal: np.ndarray 122 | Train and calibration features 123 | y_train_cal: np.ndarray 124 | Train and calibration target 125 | x_test: np.ndarray 126 | Test features 127 | y_grid: np.ndarray 128 | Target grid 129 | k: int 130 | Number of fold 131 | n_delta: int 132 | Number of discrete values in an interval 133 | 134 | Returns 135 | ------- 136 | Tuple[np.ndarray, np.ndarray] 137 | Q folds and p folds 138 | 139 | """ 140 | 141 | xy_train_cal = np.concatenate( 142 | (x_train_cal, np.reshape(y_train_cal, (len(x_train_cal), 1))), axis=1 143 | ) 144 | 145 | n = len(x_train_cal) 146 | n_test = len(x_test) 147 | s = np.empty(k) 148 | s[:] = np.NaN 149 | 150 | alpha_y_fold = np.empty((n_test, n_delta)) 151 | 152 | q_folds = np.empty((n_test, n_delta, k)) 153 | q_folds[:] = np.NaN 154 | 155 | p_folds = np.zeros((n_test, n_delta)) 156 | p_folds = np.zeros((n_test, n_delta)) 157 | 158 | kf = KFold(n_splits=k) 159 | 160 | alpha_y_fold = np.empty((n_test, n_delta)) 161 | 162 | for l in range(len(x_test)): 163 | k_ = 0 164 | alpha_y_fold[:] = np.NaN 165 | for train_ind, cal_ind in kf.split(xy_train_cal): 166 | train_data = xy_train_cal[train_ind] 167 | cal_data = xy_train_cal[cal_ind] 168 | x_train = train_data[:, :-1] 169 | y_train = train_data[:, -1] 170 | x_cal = cal_data[:, :-1] 171 | y_cal = cal_data[:, -1] 172 | s[k_] = len(x_cal) 173 | 174 | model = sm.OLS(y_train, x_train).fit() 175 | y_hat_cal = model.predict(x_cal) 176 | y_hat = model.predict(x_test) 177 | 178 | alpha_y_fold[l] = y_grid - y_hat[l] 179 | alpha_cal_fold = y_cal - y_hat_cal 180 | 181 | for i in range(len(y_grid)): 182 | q_folds[l, i, k_] = ( 183 | 1 / (len(x_cal) + 1) * np.sum(alpha_cal_fold < alpha_y_fold[l, i]) 184 | ) 185 | k_ = k_ + 1 186 | 187 | for l in range(len(x_test)): 188 | for i in range(len(y_grid)): 189 | for k_ in range(k): 190 | p_folds[l, i] = p_folds[l, i] + s[k_] / n * q_folds[l, i, k_] 191 | 192 | return (q_folds, p_folds) 193 | 194 | 195 | def crps_function(y_range: np.ndarray, q: np.ndarray, y: float) -> float: 196 | """ Continuously Ranked Probabilistic System 197 | 198 | Parameters 199 | ---------- 200 | y_range: np.ndarray 201 | Range over which Q was computed 202 | q: np.ndarray 203 | Distribution function 204 | y: float 205 | Target 206 | 207 | Returns 208 | ------- 209 | float 210 | Sum 211 | 212 | """ 213 | step = (y_range[-1] - y_range[0]) / (len(y_range) - 1) 214 | ind = np.max(np.where(y >= y_range)) 215 | q1 = q[0:(ind + 1)] 216 | 217 | sum1 = np.sum(q1[0:ind] ** 2) * step 218 | sum1 = sum1 + (q1[ind] ** 2) * (y - y_range[ind]) 219 | 220 | q2 = q[ind:] 221 | q2 = (1 - q2) 222 | 223 | sum2 = 0 224 | 225 | if len(q2) > 1: 226 | sum2 = (q2[1] ** 2) * (step - (y - y_range[ind])) 227 | 228 | sum2 = sum2 + np.sum(q2[2:len(q2)]**2) * step 229 | total_sum = sum1 + sum2 230 | 231 | return total_sum 232 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 100 3 | ignore = 4 | E203, # space before : (needed for how black formats slicing) 5 | W503, # line break before binary operator 6 | exclude = setup.py,docs/conf.py,node_modules,docs,build,dist -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | with open("README.rst", "r", encoding="utf-8") as fh: 4 | long_description = fh.read() 5 | 6 | setup( 7 | name="pysloth", 8 | version="0.0.3", 9 | packages=find_packages(exclude=["etc", "tests", "docs"]), 10 | 11 | description="Probabilistic Predictions", 12 | long_description=long_description, 13 | long_description_content_type="text/x-rst", 14 | 15 | url="https://github.com/PySloth/pysloth", 16 | author="PySloth", 17 | author_email="pysloth.python@gmail.com", 18 | 19 | license="Apache Software License", 20 | classifiers=[ 21 | "Programming Language :: Python :: 3", 22 | "License :: OSI Approved :: Apache Software License", 23 | "Operating System :: OS Independent", 24 | "Topic :: Scientific/Engineering :: Artificial Intelligence", 25 | "Topic :: Scientific/Engineering :: Mathematics", 26 | 27 | ], 28 | install_requires=[ 29 | "statsmodels>=0.12.2", 30 | "scikit-learn>=0.24.1", 31 | "numpy>=1.19.2", 32 | ], 33 | 34 | python_requires=">=3.6", 35 | tests_require=["pytest"], 36 | setup_requires=['pytest-runner'] 37 | ) 38 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PySloth/pysloth/f7e9cbae912202a1ed2676609d114758e838f854/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_pysloth.py: -------------------------------------------------------------------------------- 1 | from pysloth import scpd_function, ccpd_function, crps_function 2 | 3 | 4 | def test_scpd_function(): 5 | # NOTE: To implement 6 | ... 7 | 8 | 9 | def test_ccpd_function(): 10 | # NOTE: To implement 11 | ... 12 | 13 | 14 | def test_crps_function(): 15 | # NOTE: To implement 16 | ... 17 | --------------------------------------------------------------------------------