├── docs
├── readme.rst
├── modules.rst
├── index.rst
├── Makefile
├── _templates
│ ├── custom-class-template.rst
│ └── custom-module-template.rst
├── make.bat
└── conf.py
├── tests
├── test_ensemble
│ ├── ia_sample_compile_true_t.npy
│ ├── ia_sample_compile_true_actual.npy
│ └── ia_sample_compile_true_expected.npy
├── test_score.py
├── test_split.py
├── test_datasets.py
├── test_methods.py
└── test_ensemble.py
├── src
└── tryangle
│ ├── utils
│ ├── __init__.py
│ ├── datasets.py
│ └── data
│ │ ├── swiss_train.csv
│ │ ├── cas_test.csv
│ │ ├── sme_test.csv
│ │ ├── swiss_test.csv
│ │ ├── cas_train.csv
│ │ └── sme_train.csv
│ ├── __init__.py
│ ├── model_selection
│ ├── __init__.py
│ └── split.py
│ ├── metrics
│ ├── __init__.py
│ ├── base.py
│ └── score.py
│ ├── core
│ ├── __init__.py
│ ├── base.py
│ └── methods.py
│ └── ensemble
│ ├── __init__.py
│ ├── losses.py
│ ├── optimizers.py
│ └── base.py
├── tox.ini
├── MANIFEST.in
├── examples
├── plot_auto_ensemble.py
├── plot_gridsearch_pipeline.py
└── plot_optuna_integration.py
├── pyproject.toml
├── Makefile
├── README.md
├── .gitignore
└── LICENSE
/docs/readme.rst:
--------------------------------------------------------------------------------
1 | .. include:: ../README.rst
--------------------------------------------------------------------------------
/tests/test_ensemble/ia_sample_compile_true_t.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/casact/tryangle/HEAD/tests/test_ensemble/ia_sample_compile_true_t.npy
--------------------------------------------------------------------------------
/tests/test_ensemble/ia_sample_compile_true_actual.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/casact/tryangle/HEAD/tests/test_ensemble/ia_sample_compile_true_actual.npy
--------------------------------------------------------------------------------
/tests/test_ensemble/ia_sample_compile_true_expected.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/casact/tryangle/HEAD/tests/test_ensemble/ia_sample_compile_true_expected.npy
--------------------------------------------------------------------------------
/src/tryangle/utils/__init__.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | """
6 | Utilities for Tryangle. Currently only houses sample datasets.
7 | """
8 |
--------------------------------------------------------------------------------
/docs/modules.rst:
--------------------------------------------------------------------------------
1 | API Reference
2 | =============
3 |
4 | Modules
5 | -------
6 |
7 | .. autosummary::
8 | :toctree: _autosummary
9 | :template: custom-module-template.rst
10 | :recursive:
11 |
12 | tryangle.core
13 | tryangle.ensemble
14 | tryangle.metrics
15 | tryangle.model_selection
16 | tryangle.utils
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | envlist = {py3.9.17, py3.10.12, py3.11.4}-chainladder{0.8.14}
3 |
4 | [testenv]
5 | # install pytest in the virtualenv where commands will be executed
6 | deps =
7 | pytest
8 | chainladder0.8.14: chainladder==0.8.14
9 | commands =
10 | # NOTE: you can run any command line tool here - not just tests
11 | pytest
--------------------------------------------------------------------------------
/src/tryangle/__init__.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | from tryangle.core import * # noqa (API import)
6 | from tryangle.metrics import * # noqa (API import)
7 |
8 | __version__ = "0.2.2"
9 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE
2 | include requirements.txt
3 | include README.md
4 |
5 | include src/tryangle/utils/data/cas_test.csv
6 | include src/tryangle/utils/data/cas_train.csv
7 | include src/tryangle/utils/data/sme_test.csv
8 | include src/tryangle/utils/data/sme_train.csv
9 | include src/tryangle/utils/data/swiss_test.csv
10 | include src/tryangle/utils/data/swiss_train.csv
--------------------------------------------------------------------------------
/src/tryangle/model_selection/__init__.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | """
6 | The :mod:`tryangle.model_selection` module includes the TriangleSplit
7 | cross-validation splitting class.
8 | """
9 | from tryangle.model_selection.split import TriangleSplit # noqa (API Import)
10 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. tryangle documentation master file, created by
2 | sphinx-quickstart on Tue May 18 09:01:26 2021.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to tryangle's documentation!
7 | ====================================
8 |
9 |
10 | .. toctree::
11 | :maxdepth: 2
12 | :caption: Contents:
13 |
14 | readme
15 | modules
16 |
17 |
18 |
19 | .. Indices and tables
20 | .. ==================
21 |
22 | .. * :ref:`genindex`
23 | .. * :ref:`modindex`
24 | .. * :ref:`search`
25 |
--------------------------------------------------------------------------------
/src/tryangle/metrics/__init__.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | """
6 | The :mod:`tryangle.metrics` module includes scoring metrics used
7 | when finding the optimal reserving parameters.
8 | """
9 | from tryangle.metrics.base import * # noqa (API Import)
10 | from tryangle.metrics.score import ( # noqa (API Import)
11 | neg_ave_scorer,
12 | neg_cdr_scorer,
13 | neg_weighted_ave_scorer,
14 | neg_weighted_cdr_scorer,
15 | )
16 |
--------------------------------------------------------------------------------
/src/tryangle/core/__init__.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | """
6 | The :mod:`tryangle.core` module includes the TryangleData data structure
7 | and core chainladder methods.
8 | """
9 | from tryangle.core.base import TryangleData # noqa (API Import)
10 | from tryangle.core.methods import ( # noqa (API Import)
11 | Chainladder,
12 | BornhuetterFerguson,
13 | CapeCod,
14 | VotingChainladder,
15 | )
16 | from tryangle.core.methods import Development # noqa (API Import)
17 |
--------------------------------------------------------------------------------
/src/tryangle/ensemble/__init__.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | """
6 | The :mod:`tryangle.ensemble` module includes ensemble-based methods for
7 | VotingChainladder
8 | """
9 | from tryangle.ensemble.base import AutoEnsemble # noqa (API Import)
10 | from tryangle.ensemble.optimizers import (
11 | SGD,
12 | AdaGrad,
13 | RMSProp,
14 | Adam,
15 | ) # noqa (API Import)
16 | from tryangle.ensemble.losses import (
17 | MeanSquaredError,
18 | MeanAbsolutePercentageError,
19 | ) # noqa (API Import)
20 |
--------------------------------------------------------------------------------
/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 = .
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/_templates/custom-class-template.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. currentmodule:: {{ module }}
4 |
5 | .. autoclass:: {{ objname }}
6 | :members:
7 | :show-inheritance:
8 | :inherited-members:
9 |
10 | {% block methods %}
11 | .. automethod:: __init__
12 |
13 | {% if methods %}
14 | .. rubric:: {{ _('Methods') }}
15 |
16 | .. autosummary::
17 | {% for item in methods %}
18 | ~{{ name }}.{{ item }}
19 | {%- endfor %}
20 | {% endif %}
21 | {% endblock %}
22 |
23 | {% block attributes %}
24 | {% if attributes %}
25 | .. rubric:: {{ _('Attributes') }}
26 |
27 | .. autosummary::
28 | {% for item in attributes %}
29 | ~{{ name }}.{{ item }}
30 | {%- endfor %}
31 | {% endif %}
32 | {% endblock %}
--------------------------------------------------------------------------------
/examples/plot_auto_ensemble.py:
--------------------------------------------------------------------------------
1 | """
2 | ======================
3 | AutoEnsemble CL and BF
4 | ======================
5 |
6 | Finds optimal weights to combine chainladder and bornhuetter
7 | ferguson methods to reduce prediction error.
8 | """
9 | from tryangle.model_selection import TriangleSplit
10 | from tryangle.utils.datasets import load_sample
11 | from tryangle.ensemble import AutoEnsemble, Adam
12 | from tryangle import Chainladder, BornhuetterFerguson
13 |
14 | X = load_sample("swiss")
15 |
16 | cl = Chainladder()
17 | bf = BornhuetterFerguson(apriori=0.6)
18 | estimators = [("cl", cl), ("bf", bf)]
19 |
20 | tscv = TriangleSplit(n_splits=10)
21 |
22 | model = AutoEnsemble(
23 | estimators=estimators,
24 | cv=tscv,
25 | optimizer=Adam(learning_rate=0.01),
26 | dropout=0.1,
27 | broad_dropout=0.1,
28 | )
29 |
30 | model.fit(X)
31 |
32 | print(model.weights_)
33 |
--------------------------------------------------------------------------------
/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=.
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 |
--------------------------------------------------------------------------------
/src/tryangle/ensemble/losses.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | class MeanSquaredError:
5 | def _loss(self, y_pred, y_true):
6 | print(((y_pred - y_true)))
7 | return ((y_pred - y_true) ** 2).mean()
8 |
9 | def _loss_gradient(self, y_pred, y_true):
10 | return 2 * (y_pred - y_true)
11 |
12 |
13 | class MeanAbsolutePercentageError:
14 | def _loss(self, y_pred, y_true):
15 | _y_true = y_true + 1e-7
16 | return np.abs((y_pred - _y_true) / _y_true).mean()
17 |
18 | def _loss_gradient(self, y_pred, y_true):
19 | _y_true = y_true + 1e-7
20 | less_than_mask = y_pred < _y_true
21 | greater_than_mask = y_pred > _y_true
22 | return (1 / (_y_true.size * _y_true)) * greater_than_mask - (
23 | 1 / (_y_true.size * _y_true)
24 | ) * less_than_mask
25 |
26 |
27 | LOSS_FUNCTIONS = {
28 | "mse": MeanSquaredError,
29 | "mape": MeanAbsolutePercentageError,
30 | }
31 |
--------------------------------------------------------------------------------
/tests/test_score.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import pytest
6 | import chainladder as cl
7 | from tryangle.metrics.score import (
8 | neg_ave_scorer,
9 | neg_weighted_ave_scorer,
10 | neg_cdr_scorer,
11 | neg_weighted_cdr_scorer,
12 | )
13 | from tryangle.core.base import TryangleData
14 | from tryangle.core.methods import Chainladder
15 |
16 |
17 | @pytest.mark.parametrize(
18 | "scorer, true_score",
19 | [
20 | (neg_ave_scorer, -2222.357324),
21 | (neg_weighted_ave_scorer, -2372.370821),
22 | (neg_cdr_scorer, -5064.408237),
23 | (neg_weighted_cdr_scorer, -5891.385703),
24 | ],
25 | )
26 | def test_scorers(scorer, true_score):
27 | X = TryangleData(cl.load_sample("raa"))
28 | score = scorer(Chainladder(), X, X)
29 | assert (score - true_score) < 0.001
30 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools>=67.0", "wheel"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [project]
6 | name = "tryangle"
7 | version = "0.2.2"
8 | description = "Tryangle Package - Scientific P&C Loss Reserving"
9 | readme = "README.md"
10 | maintainers = [{ name = "Caesar Balona", email = "caesar.balona@gmail.com" }]
11 | classifiers = [
12 | "Intended Audience :: Financial and Insurance Industry",
13 | "Intended Audience :: Science/Research",
14 | "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
15 | "Operating System :: OS Independent",
16 | "Programming Language :: Python :: 3",
17 | "Topic :: Office/Business :: Financial",
18 | "Topic :: Scientific/Engineering :: Artificial Intelligence",
19 | ]
20 | dependencies = ["chainladder<=0.8.14", "pandas<2.0", "scikit-learn>=1.2"]
21 | license = { text = "MPL-2.0" }
22 | requires-python = ">=3.11"
23 |
24 | [project.urls]
25 | Homepage = "https://github.com/casact/tryangle"
26 |
27 | [project.optional-dependencies]
28 | dev = ["ruff", "black", "mypy", "pytest", "tox", "twine"]
29 |
30 |
--------------------------------------------------------------------------------
/examples/plot_gridsearch_pipeline.py:
--------------------------------------------------------------------------------
1 | """
2 | =============================
3 | GridSearchCV using a pipeline
4 | =============================
5 |
6 | Finds the optimal development and CapeCod parameters
7 | using the unweighted CDR score.
8 |
9 | Since selecting development factors is a transformation,
10 | it can be pipelined with an estimator
11 | """
12 | from sklearn.model_selection import GridSearchCV
13 | from sklearn.pipeline import Pipeline
14 | from tryangle import Development, CapeCod
15 | from tryangle.metrics import neg_cdr_scorer
16 | from tryangle.model_selection import TriangleSplit
17 | from tryangle.utils.datasets import load_sample
18 |
19 | X = load_sample("swiss")
20 | tscv = TriangleSplit(n_splits=5)
21 |
22 | param_grid = {
23 | "dev__n_periods": range(15, 20),
24 | "dev__drop_high": [True, False],
25 | "dev__drop_low": [True, False],
26 | "cc__decay": [0.25, 0.5, 0.75, 0.95],
27 | }
28 |
29 | pipe = Pipeline([("dev", Development()), ("cc", CapeCod())])
30 |
31 | model = GridSearchCV(
32 | pipe, param_grid=param_grid, scoring=neg_cdr_scorer, cv=tscv, verbose=1, n_jobs=-1
33 | )
34 | model.fit(X, X)
35 | print(model.best_params_)
36 |
37 | # TODO add plotting
38 |
--------------------------------------------------------------------------------
/docs/_templates/custom-module-template.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. automodule:: {{ fullname }}
4 |
5 | {% block attributes %}
6 | {% if attributes %}
7 | .. rubric:: Module Attributes
8 |
9 | .. autosummary::
10 | :toctree:
11 | {% for item in attributes %}
12 | {{ item }}
13 | {%- endfor %}
14 | {% endif %}
15 | {% endblock %}
16 |
17 | {% block functions %}
18 | {% if functions %}
19 | .. rubric:: {{ _('Functions') }}
20 |
21 | .. autosummary::
22 | :toctree:
23 | {% for item in functions %}
24 | {{ item }}
25 | {%- endfor %}
26 | {% endif %}
27 | {% endblock %}
28 |
29 | {% block classes %}
30 | {% if classes %}
31 | .. rubric:: {{ _('Classes') }}
32 |
33 | .. autosummary::
34 | :toctree:
35 | :template: custom-class-template.rst
36 | {% for item in classes %}
37 | {{ item }}
38 | {%- endfor %}
39 | {% endif %}
40 | {% endblock %}
41 |
42 | {% block exceptions %}
43 | {% if exceptions %}
44 | .. rubric:: {{ _('Exceptions') }}
45 |
46 | .. autosummary::
47 | :toctree:
48 | {% for item in exceptions %}
49 | {{ item }}
50 | {%- endfor %}
51 | {% endif %}
52 | {% endblock %}
53 |
54 | {% block modules %}
55 | {% if modules %}
56 | .. rubric:: Modules
57 |
58 | .. autosummary::
59 | :toctree:
60 | :template: custom-module-template.rst
61 | :recursive:
62 | {% for item in modules %}
63 | {{ item }}
64 | {%- endfor %}
65 | {% endif %}
66 | {% endblock %}
--------------------------------------------------------------------------------
/src/tryangle/metrics/base.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 |
6 | def get_expected(estimator, X):
7 | """Get the expected incremental claims for the next diagonal
8 | given an estimator.
9 |
10 | Args:
11 | estimator : tryangle implementation of chainladder method
12 | X : TryangleData
13 |
14 | Returns:
15 | ndarray : Array of expected incremental claims
16 | """
17 | valuation_date = X.latest_diagonal.valuation[0]
18 | X_test = X[X.triangle.valuation < valuation_date]
19 |
20 | expected = estimator.fit_predict(X_test)
21 |
22 | expected = expected.full_triangle_.cum_to_incr()
23 | expected = expected[expected.valuation == valuation_date].latest_diagonal
24 |
25 | return expected.to_frame().fillna(0).to_numpy()
26 |
27 |
28 | def get_actual_expected(estimator, X):
29 | """Get actual and expected given an estimator
30 |
31 | Args:
32 | estimator : tryangle implementation of chainladder method
33 | X : TryangleData
34 |
35 | Returns:
36 | (ndarray, ndarray) : Tuple of actual, expected incremental claims
37 | """
38 | # ! TODO: Rewrite a better method that avoids fillna(0) as this could mask some error
39 |
40 | actual = X.latest_diagonal.to_frame().fillna(0).to_numpy()[:-1]
41 | expected = get_expected(estimator, X)
42 |
43 | return actual, expected
44 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: venv setup ruff format test check clean build test-publish
2 |
3 | SHELL := /bin/bash
4 |
5 | PYTHON_INTERPRETER := python
6 | VENV := source .venv/bin/activate
7 | PROJECT_CONFIG := pyproject.toml
8 |
9 | venv: .venv/touchfile
10 |
11 | .venv/touchfile: requirements.txt requirements-dev.txt
12 | $(VENV); pip-sync requirements.txt requirements-dev.txt
13 | $(VENV); pip install -e .
14 | touch .venv/touchfile
15 |
16 | requirements.txt: $(PROJECT_CONFIG)
17 | $(VENV); pip-compile --output-file=requirements.txt --resolver=backtracking $(PROJECT_CONFIG)
18 |
19 | requirements-dev.txt: $(PROJECT_CONFIG)
20 | $(VENV); pip-compile --extra=dev --output-file=requirements-dev.txt --resolver=backtracking $(PROJECT_CONFIG)
21 |
22 | test: venv
23 | $(VENV); tox
24 |
25 | build:
26 | rm -rf build dist
27 | $(VENV); python -m build
28 |
29 | test-publish:
30 | $(VENV); python -m twine upload --repository testpypi dist/* --verbose
31 |
32 | publish:
33 | $(VENV); python -m twine upload --repository tryangle dist/* --verbose
34 |
35 | setup:
36 | virtualenv .venv
37 | $(VENV); pip install --upgrade pip setuptools wheel build
38 | $(VENV); pip install pip-tools
39 |
40 | ruff:
41 | $(VENV); ruff .
42 |
43 | format:
44 | $(VENV); ruff .
45 | $(VENV); black .
46 |
47 | check:
48 | $(VENV); ruff check .
49 | $(VENV); black --check .
50 |
51 | clean:
52 | find . -type d -name ".ipynb_checkpoints" -exec rm -r {} +
53 | find . -type d -name ".pytest_cache" -exec rm -rf {} +
54 | find . -type d -name "__pycache__" -exec rm -rf {} +
55 | rm -rf build dist
--------------------------------------------------------------------------------
/tests/test_split.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import pytest
6 | from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
7 | from sklearn.utils.validation import check_is_fitted
8 | from tryangle.model_selection.split import TriangleSplit
9 | from tryangle.core.methods import CapeCod
10 | from tryangle.metrics.score import neg_ave_scorer
11 | from tryangle.utils.datasets import load_sample
12 |
13 |
14 | def test_split():
15 | X = load_sample("swiss")
16 | triangle = X.triangle.copy()
17 | sample_weight = X.sample_weight.copy()
18 | tscv = TriangleSplit(n_splits=10)
19 | val_years = list(range(1988, 1998))
20 |
21 | for i, (train_idx, _) in enumerate(tscv.split(X)):
22 | assert (
23 | X[train_idx].triangle == triangle[triangle.valuation.year <= val_years[i]]
24 | )
25 | assert (
26 | X[train_idx].sample_weight
27 | == sample_weight[sample_weight.origin.year <= val_years[i]]
28 | )
29 |
30 |
31 | @pytest.mark.parametrize("SearchClass", [(GridSearchCV), (RandomizedSearchCV)])
32 | def test_search_methods(SearchClass):
33 | X = load_sample("swiss")
34 | tscv = TriangleSplit(n_splits=5)
35 |
36 | model = GridSearchCV(
37 | CapeCod(),
38 | param_grid={"decay": [0.2, 0.8]},
39 | scoring=neg_ave_scorer,
40 | cv=tscv,
41 | n_jobs=1,
42 | ).fit(X, X)
43 | assert check_is_fitted(model) is None
44 |
--------------------------------------------------------------------------------
/src/tryangle/model_selection/split.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import numpy as np
6 | from sklearn.model_selection._split import TimeSeriesSplit
7 |
8 |
9 | class TriangleSplit(TimeSeriesSplit):
10 | """Triangle cross-validation across calendar periods
11 |
12 | Splits a ``TryangleData`` instance into k sub-triangles or folds
13 | over the latest k calendar periods or diagonals. Thus, successive
14 | folds are supersets of previous folds.
15 |
16 | Parameters
17 | ----------
18 | n_splits : int, default=5
19 | Number of splits, must be at least 2.
20 | """
21 |
22 | def __init__(self, n_splits=5, *, max_train_size=None, test_size=None, gap=0):
23 | super().__init__(n_splits=n_splits, max_train_size=None, test_size=1, gap=0)
24 |
25 | def split(self, X, y=None, groups=None):
26 | valuation_date = X.triangle.latest_diagonal.valuation[0]
27 | valuation_dates = np.array(
28 | [
29 | date
30 | for date in X.triangle.valuation.drop_duplicates().sort_values()
31 | if date.date() <= valuation_date.date()
32 | ]
33 | )
34 | for train, test in super().split(valuation_dates):
35 | indices = np.arange(X.triangle.shape[2] * X.triangle.shape[3])
36 | test_start = test[0]
37 | yield (
38 | indices[X.triangle.valuation <= valuation_dates[test_start]],
39 | indices[X.triangle.valuation <= valuation_dates[test_start]],
40 | )
41 |
--------------------------------------------------------------------------------
/tests/test_datasets.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import os
6 | import pandas as pd
7 | import pytest
8 |
9 | from chainladder import Triangle
10 | from tryangle.core import TryangleData
11 | from tryangle.utils import datasets
12 |
13 |
14 | @pytest.mark.parametrize(
15 | "key",
16 | [
17 | ("swiss"),
18 | ("cas"),
19 | ("sme"),
20 | ],
21 | )
22 | def test_load_dataset(key):
23 | # Load TryangleData
24 | train, test = datasets.load_sample(key), datasets.load_test_sample(key)
25 |
26 | # Load raw data
27 | train_raw = pd.read_csv(
28 | os.path.join(os.path.dirname(datasets.__file__), "data", f"{key}_train.csv")
29 | )
30 | test_raw = pd.read_csv(
31 | os.path.join(os.path.dirname(datasets.__file__), "data", f"{key}_test.csv")
32 | )
33 |
34 | max_train_lag = train_raw.lag.max()
35 |
36 | for X, raw in zip([train, test], [train_raw, test_raw]):
37 | assert isinstance(X, TryangleData)
38 |
39 | assert isinstance(X.triangle, Triangle)
40 | if X.sample_weight:
41 | assert isinstance(X.sample_weight, Triangle)
42 |
43 | assert X.triangle.shape == (1, 1, max_train_lag + 1, max_train_lag + 1)
44 | assert X.shape == (X.triangle.shape[2] * X.triangle.shape[3], 1)
45 |
46 | if X.sample_weight:
47 | assert (X.triangle.origin == X.sample_weight.origin).all()
48 |
49 | assert (X.triangle.sum().sum() - raw.claim.sum()) < 0.01
50 | if X.sample_weight:
51 | assert (X.sample_weight.sum() - raw.claim.sum()) < 0.01
52 |
53 | assert (train.triangle.origin == test.triangle.origin).all()
54 |
--------------------------------------------------------------------------------
/tests/test_methods.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import pytest
6 | import numpy as np
7 | from sklearn.pipeline import Pipeline
8 | from tryangle.core.methods import (
9 | Benktander,
10 | BornhuetterFerguson,
11 | CapeCod,
12 | Chainladder,
13 | ClarkLDF,
14 | MackChainladder,
15 | Development,
16 | DevelopmentConstant,
17 | IncrementalAdditive,
18 | VotingChainladder,
19 | )
20 | from tryangle.utils.datasets import load_sample
21 |
22 | base_estimators = [
23 | Chainladder,
24 | MackChainladder,
25 | BornhuetterFerguson,
26 | CapeCod,
27 | Benktander,
28 | ]
29 |
30 | base_transformers = [
31 | Development,
32 | DevelopmentConstant,
33 | IncrementalAdditive,
34 | ClarkLDF,
35 | ]
36 |
37 |
38 | @pytest.fixture
39 | def sample_data():
40 | yield load_sample("swiss")
41 |
42 |
43 | @pytest.mark.parametrize("estimator", base_estimators)
44 | def test_estimators(estimator, sample_data):
45 | X = sample_data
46 |
47 | estimator().fit_predict(X)
48 |
49 |
50 | @pytest.mark.parametrize("transformer", base_transformers)
51 | def test_transformers(transformer, sample_data):
52 | X = sample_data
53 | kwargs = {}
54 |
55 | if isinstance(transformer(), DevelopmentConstant):
56 | n = len(sample_data.triangle.development)
57 | x = np.linspace(1, n, n)
58 | ldf = 1 - np.exp(-x)
59 | print(x)
60 | kwargs.update({"patterns": {(i + 1) * 12: l for i, l in enumerate(ldf)}})
61 |
62 | transformer(**kwargs).fit_transform(X)
63 |
64 |
65 | def test_voting_estimator(sample_data):
66 | X = sample_data
67 | estimators = [
68 | ("cl", Chainladder()),
69 | ("bf", BornhuetterFerguson()),
70 | ("cc", CapeCod()),
71 | ]
72 | VotingChainladder(estimators=estimators).fit_predict(X)
73 |
74 |
75 | def test_pipeline(sample_data):
76 | X = sample_data
77 | pipe = Pipeline([("development", Development()), ("cl", Chainladder())])
78 | pipe.fit_predict(X)
79 |
--------------------------------------------------------------------------------
/docs/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('../src'))
16 | print(sys.path[0])
17 | sys.setrecursionlimit(1500)
18 |
19 |
20 | # -- Project information -----------------------------------------------------
21 |
22 | project = 'tryangle'
23 | copyright = '2021, Caesar Balona & Ronald Richman'
24 | author = 'Caesar Balona & Ronald Richman'
25 |
26 |
27 | # -- General configuration ---------------------------------------------------
28 |
29 | # Add any Sphinx extension module names here, as strings. They can be
30 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
31 | # ones.
32 | extensions = [
33 | 'sphinx.ext.autodoc',
34 | 'sphinx.ext.napoleon',
35 | 'sphinx.ext.autosummary',
36 | ]
37 | autosummary_generate = True
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 = ['_build', 'Thumbs.db', '.DS_Store']
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 = 'alabaster'
54 |
55 | # Add any paths that contain custom static files (such as style sheets) here,
56 | # relative to this directory. They are copied after the builtin static files,
57 | # so a file named "default.css" will overwrite the builtin "default.css".
58 | html_static_path = ['_static']
59 |
--------------------------------------------------------------------------------
/examples/plot_optuna_integration.py:
--------------------------------------------------------------------------------
1 | import optuna
2 | from optuna.visualization import (
3 | plot_optimization_history,
4 | plot_contour,
5 | plot_param_importances,
6 | )
7 | from joblib import Parallel, delayed
8 | from sklearn.model_selection import cross_val_score
9 | from sklearn.pipeline import Pipeline
10 |
11 | from tryangle import Development, CapeCod
12 | from tryangle.model_selection import TriangleSplit
13 | from tryangle.utils.datasets import load_sample
14 | from tryangle.metrics import neg_weighted_cdr_scorer
15 |
16 | X = load_sample("swiss")
17 | tscv = TriangleSplit(n_splits=13)
18 |
19 |
20 | def objective(trial):
21 |
22 | dev_params = {
23 | "n_periods": trial.suggest_int("dev__n_periods", 5, 19),
24 | "drop_low": trial.suggest_categorical("dev__drop_low", [True, False]),
25 | "drop_high": trial.suggest_categorical("dev__drop_high", [True, False]),
26 | }
27 | cc_params = {
28 | "decay": trial.suggest_float("cc_decay", 0.0, 1.0),
29 | "trend": trial.suggest_float("cc_trend", -1.0, 1.0),
30 | }
31 |
32 | pipe = Pipeline(
33 | [
34 | ("dev", Development(**dev_params)),
35 | ("cc", CapeCod(**cc_params)),
36 | ]
37 | )
38 |
39 | score = cross_val_score(
40 | pipe, X=X, y=X, scoring=neg_weighted_cdr_scorer, cv=tscv, n_jobs=1
41 | ).mean()
42 |
43 | return score
44 |
45 |
46 | def optimize(n_trials):
47 | study = optuna.load_study(
48 | study_name="opt_ibnr", storage="sqlite:///opt_ibnr.sqlite3"
49 | )
50 | study.optimize(objective, n_trials=n_trials)
51 |
52 |
53 | study = optuna.create_study(
54 | study_name="opt_ibnr", storage="sqlite:///opt_ibnr.sqlite3", direction="maximize"
55 | )
56 | r = Parallel(n_jobs=-1)([delayed(optimize)(1) for _ in range(100)])
57 |
58 | print("Number of finished trials: ", len(study.trials))
59 | print("Best trial:")
60 | trial = study.best_trial
61 | print(" Value: ", trial.value)
62 | print(" Params: ")
63 | for key, value in trial.params.items():
64 | print(" {}: {}".format(key, value))
65 |
66 |
67 | study = optuna.load_study(study_name="opt_ibnr", storage="sqlite:///opt_ibnr.sqlite3")
68 |
69 | plot_optimization_history(study)
70 |
71 | plot_contour(study)
72 |
73 | plot_param_importances(study)
74 |
--------------------------------------------------------------------------------
/src/tryangle/core/base.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import numpy as np
6 |
7 |
8 | class TryangleData:
9 | """
10 | TryangleData is an internal data structure used by Tryangle which is built
11 | to work with optimization libraries to allow hyperparameter optimization
12 | and parallel processing.
13 |
14 | TryangleData can only hold chainladder ``Triangle``'s that are singular in
15 | the first and second axis. That is, the shape of the ``Triangle`` must be
16 | (1, 1, n_origin, n_development). The sample_weight must also be singular
17 | in its development axis, i.e. a shape of (1, 1, n_origin, 1).
18 |
19 | Parameters
20 | ----------
21 | triangle : chainladder ``Triangle`` object of shape (1, 1, n_origin, n_development)
22 | The loss triangle to be reserved.
23 |
24 | sample_weight : chainladder ``Triangle`` object of shape (1, 1, n_origin, 1), default=None
25 | The exposure data for exposure based methods.
26 | """
27 |
28 | def __init__(self, triangle, sample_weight=None):
29 | self.triangle = triangle
30 | self.sample_weight = sample_weight
31 | self.shape = self.triangle.shape[2] * self.triangle.shape[3], 1
32 | self.latest_diagonal = triangle.cum_to_incr().latest_diagonal
33 | if self.latest_diagonal.shape != ():
34 | self.actual = self.latest_diagonal[
35 | self.latest_diagonal.origin < self.latest_diagonal.origin[-1]
36 | ]
37 |
38 | def __getitem__(self, x):
39 | indices = np.full((self.shape[0],), False)
40 | indices[x] = True
41 | spliced_triangle = self.triangle[indices]
42 | if self.sample_weight is not None:
43 | sample_weight_indices = np.array(
44 | [
45 | origin in spliced_triangle.origin
46 | for origin in self.sample_weight.origin
47 | ]
48 | )
49 | return TryangleData(
50 | self.triangle[indices],
51 | self.sample_weight[sample_weight_indices],
52 | )
53 | else:
54 | return TryangleData(self.triangle[indices], None)
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tryangle: Machine Learning Techniques for Chainladder Methods
2 |
3 | *Tryangle* is an automatic chainladder reserving framework. It provides
4 | scoring and optimisation methods based on machine learning techniques to
5 | automatically select optimal parameters to minimise reserve prediction
6 | error. Tryangle is built on top of the
7 | [chainladder](https://chainladder-python.readthedocs.io/en/latest/index.html)
8 | reserving package.
9 |
10 | ## Key Features
11 |
12 | Tryangle is flexible and modular in how it can be applied:
13 |
14 | - Optimising loss development factors
15 | - Use [sklearn's](https://scikit-learn.org/) GridSearchCV or RandomizedSearchCV to find the optimal
18 | method to calculate loss development factors
19 | - Choosing between multiple reserving methods
20 | - Not sure if you should go with a basic chainladder,
21 | Bornhuetter-Ferguson, or Cape-Cod method? Let Tryangle decide.
22 | - Finding the optimal blend of reserving methods
23 | - Or why not combine all three, and let Tryangle find the optimal
24 | blend.
25 | - Using advanced optimisation methods
26 | - Not satisfied with an exhaustive grid search? Tryangle can be
27 | used with any optimisation framework, but we recommend
28 | [Optuna](https://optuna.org/)
29 |
30 | ## Basic Example
31 |
32 | ``` python
33 | from sklearn.model_selection import GridSearchCV
34 | from sklearn.pipeline import Pipeline
35 | from tryangle import Development, CapeCod
36 | from tryangle.metrics import neg_cdr_scorer
37 | from tryangle.model_selection import TriangleSplit
38 | from tryangle.utils.datasets import load_sample
39 |
40 | X = load_sample("swiss")
41 | tscv = TriangleSplit(n_splits=5)
42 |
43 | param_grid = {
44 | "dev__n_periods": range(15, 20),
45 | "dev__drop_high": [True, False],
46 | "dev__drop_low": [True, False],
47 | "cc__decay": [0.25, 0.5, 0.75, 0.95],
48 | }
49 |
50 | pipe = Pipeline([("dev", Development()), ("cc", CapeCod())])
51 |
52 | model = GridSearchCV(
53 | pipe, param_grid=param_grid, scoring=neg_cdr_scorer, cv=tscv, verbose=1, n_jobs=-1
54 | )
55 | model.fit(X, X)
56 | ```
57 |
58 | ## Installation
59 |
60 | Tryangle is available at [the Python Package
61 | Index](https://pypi.org/project/tryangle/).
62 |
63 | ``` console
64 | pip install tryangle
65 | ```
66 |
67 | Tryangle supports Python 3.9.
68 |
69 | ## Reference
70 |
71 | Caesar Balona, Ronald Richman. 2021. The Actuary and IBNR Techniques: A
72 | Machine Learning Approach
73 | ([SSRN](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3697256)).
74 |
--------------------------------------------------------------------------------
/src/tryangle/utils/datasets.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import os
6 | import pandas as pd
7 | from chainladder.core.triangle import Triangle
8 | from tryangle.core import TryangleData
9 |
10 |
11 | def load_sample(key, *args, **kwargs):
12 | """Function to load training datasets included in the tryangle package.
13 |
14 | Args:
15 | key (str): Key to identify dataset
16 |
17 | Returns:
18 | [TryangleData]: TryangleData object of the loaded dataset.
19 | """
20 | path = os.path.dirname(os.path.abspath(__file__))
21 |
22 | if key in ["swiss", "cas", "sme"]:
23 | df = pd.read_csv(os.path.join(path, "data", key.lower() + "_train.csv"))
24 | sample_weight = df[["origin", "premium", "development"]].drop_duplicates()
25 | columns = ["claim"]
26 | else:
27 | raise KeyError(
28 | "No such dataset exists. Available datasets are 'swiss', 'cas' and 'sme'."
29 | )
30 |
31 | claim = Triangle(
32 | df,
33 | origin="origin",
34 | development="development",
35 | index=None,
36 | columns=columns,
37 | cumulative=True,
38 | *args,
39 | **kwargs
40 | )
41 | sample_weight = Triangle(
42 | sample_weight,
43 | origin="origin",
44 | index=None,
45 | development="development",
46 | columns=["premium"],
47 | cumulative=True,
48 | *args,
49 | **kwargs
50 | ).latest_diagonal
51 |
52 | return TryangleData(claim, sample_weight)
53 |
54 |
55 | def load_test_sample(key, *args, **kwargs):
56 | """Function to load test datasets included in the tryangle package.
57 |
58 | Args:
59 | key (str): Key to identify dataset
60 |
61 | Returns:
62 | [TryangleData]: TryangleData object of the loaded dataset.
63 | """
64 | path = os.path.dirname(os.path.abspath(__file__))
65 |
66 | df = pd.read_csv(os.path.join(path, "data", key.lower() + "_test.csv"))
67 |
68 | claim = Triangle(
69 | df,
70 | origin="origin",
71 | development="development",
72 | index=None,
73 | columns=["claim"],
74 | cumulative=True,
75 | *args,
76 | **kwargs
77 | )
78 |
79 | if key.lower() in ["swiss"]:
80 | claim = claim[claim.development <= 240]
81 | claim = claim[claim.origin.year <= 1997]
82 | claim = claim[claim.valuation.year > 1997]
83 | elif key.lower() in ["cas", "sme"]:
84 | claim = claim[claim.development <= 63]
85 | claim = claim[claim.origin.year <= 2014]
86 | claim = claim[claim.valuation.year > 2014]
87 |
88 | return TryangleData(claim)
89 |
90 |
91 | if __name__ == "__main__":
92 | pass
93 |
--------------------------------------------------------------------------------
/tests/test_ensemble.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import os
6 | from distutils import dir_util
7 |
8 | import numpy as np
9 | import pytest
10 | from chainladder.utils import load_sample
11 | from tryangle.core.base import TryangleData
12 | from tryangle.core.methods import BornhuetterFerguson, CapeCod, Chainladder
13 | from tryangle.ensemble.base import AutoEnsemble
14 | from tryangle.model_selection.split import TriangleSplit
15 |
16 |
17 | @pytest.fixture
18 | def auto_ensemble():
19 | estimators = [
20 | ("cl", Chainladder()),
21 | ("bf", BornhuetterFerguson()),
22 | ("cc", CapeCod()),
23 | ]
24 | tscv = TriangleSplit(n_splits=3)
25 | yield AutoEnsemble(
26 | estimators=estimators,
27 | cv=tscv,
28 | )
29 |
30 |
31 | @pytest.fixture
32 | def sample_data():
33 | ia = load_sample("ia_sample")
34 | X = TryangleData(ia["loss"], ia["exposure"].latest_diagonal)
35 | yield X
36 |
37 |
38 | @pytest.fixture # https://stackoverflow.com/a/29631801
39 | def data_dir(tmpdir, request):
40 | """
41 | Fixture responsible for searching a folder with the same name of test
42 | module and, if available, moving all contents to a temporary directory so
43 | tests can use them freely.
44 | """
45 | filename = request.module.__file__
46 | test_dir, _ = os.path.splitext(filename)
47 |
48 | if os.path.isdir(test_dir):
49 | dir_util.copy_tree(test_dir, str(tmpdir))
50 |
51 | return tmpdir
52 |
53 |
54 | def test_compile(auto_ensemble, sample_data, data_dir):
55 | ens = auto_ensemble
56 | X = sample_data
57 | ens.compile(X)
58 |
59 | with open(data_dir.join("ia_sample_compile_true_actual.npy"), "rb") as f:
60 | true_actual = np.load(f, allow_pickle=True)
61 | assert ens.actual_.shape == (3, 6, 1)
62 | assert np.allclose(ens.actual_, true_actual)
63 |
64 | with open(data_dir.join("ia_sample_compile_true_expected.npy"), "rb") as f:
65 | true_expected = np.load(f, allow_pickle=True)
66 | assert ens.expected_.shape == (3, 6, 3)
67 | assert np.allclose(ens.expected_, true_expected)
68 |
69 | with open(data_dir.join("ia_sample_compile_true_t.npy"), "rb") as f:
70 | true_t = np.load(f, allow_pickle=True)
71 | assert ens.t_.shape == (3, 6, 1)
72 | assert np.allclose(ens.t_, true_t)
73 |
74 |
75 | def test_softmax(auto_ensemble):
76 | ens = auto_ensemble
77 | assert np.allclose(
78 | ens._softmax(np.stack((-np.ones((5, 2)), np.zeros((5, 2)), np.ones((5, 2))))),
79 | 0.5 * np.ones((3, 5, 2)),
80 | )
81 |
82 |
83 | def test_softmax_gradient(auto_ensemble):
84 | ens = auto_ensemble
85 | assert np.allclose(
86 | ens._softmax_gradient(0.5 * np.ones((3, 5, 2))),
87 | -0.25 * np.ones((3, 5, 2, 2)) + 0.5 * np.eye(2),
88 | )
89 |
90 |
91 | # TODO: Expand tests on finalisation of autoensemble
92 |
--------------------------------------------------------------------------------
/src/tryangle/metrics/score.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import numpy as np
6 |
7 | from tryangle.metrics.base import get_actual_expected
8 |
9 | from sklearn.metrics._scorer import _BaseScorer
10 | from sklearn.metrics import mean_squared_error
11 |
12 |
13 | class AVEScore(_BaseScorer):
14 | """Base AvE scoring class"""
15 |
16 | def __init__(
17 | self,
18 | score_func=mean_squared_error,
19 | sign=-1,
20 | kwargs={"squared": False},
21 | weighted=False,
22 | ):
23 | self.weighted = weighted
24 | super().__init__(score_func, sign, kwargs)
25 |
26 | def _sample_weight(self, X, valuation_date):
27 | X_prior = X[X.triangle.valuation < valuation_date]
28 | return np.abs(
29 | X.triangle.latest_diagonal.to_frame().to_numpy()[:-1]
30 | - X_prior.triangle.latest_diagonal.to_frame().to_numpy()
31 | )
32 |
33 | def _score(self, method_caller, estimator, X, y_true=None, sample_weight=None):
34 | """Evaluate predicted target values for X relative to y_true.""" # TODO: Update docstring
35 |
36 | valuation_date = X.triangle.cum_to_incr().latest_diagonal.valuation[0]
37 | actual, expected = get_actual_expected(estimator, X)
38 |
39 | if self.weighted:
40 | sample_weight = self._sample_weight(X, valuation_date)
41 | return self._sign * self._score_func(
42 | actual, expected, sample_weight=sample_weight, **self._kwargs
43 | )
44 | else:
45 | return self._sign * self._score_func(actual, expected, **self._kwargs)
46 |
47 |
48 | class CDRScore(AVEScore):
49 | """Base CDR scoring class"""
50 |
51 | def _score(self, method_caller, estimator, X, y_true, sample_weight=None):
52 | """Evaluate predicted target values for X relative to y_true.""" # TODO: Update docstring
53 |
54 | valuation_date = y_true.triangle.latest_diagonal.valuation[0]
55 | X_k = X[X.triangle.valuation < valuation_date]
56 | X_k_1 = X
57 |
58 | # We only need actual as the expected will be in ibnr_k
59 | actual, _ = get_actual_expected(estimator, X)
60 |
61 | # ! TODO: Rewrite a better method that avoids fillna(0) as this could mask some error
62 | ibnr_k = estimator.fit_predict(X_k).ibnr_.to_frame().fillna(0).to_numpy()
63 | ibnr_k_1 = (
64 | estimator.fit_predict(X_k_1).ibnr_.to_frame().fillna(0).to_numpy()[:-1]
65 | )
66 |
67 | if self.weighted:
68 | sample_weight = super()._sample_weight(X, valuation_date)
69 | return self._sign * self._score_func(
70 | actual + ibnr_k_1, ibnr_k, sample_weight=sample_weight, **self._kwargs
71 | )
72 | else:
73 | return self._sign * self._score_func(
74 | actual + ibnr_k_1, ibnr_k, **self._kwargs
75 | )
76 |
77 |
78 | neg_ave_scorer = AVEScore()
79 | neg_weighted_ave_scorer = AVEScore(weighted=True)
80 | neg_cdr_scorer = CDRScore()
81 | neg_weighted_cdr_scorer = CDRScore(weighted=True)
82 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/python,jupyternotebooks,visualstudiocode
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=python,jupyternotebooks,visualstudiocode
3 |
4 | ### JupyterNotebooks ###
5 | # gitignore template for Jupyter Notebooks
6 | # website: http://jupyter.org/
7 |
8 | .ipynb_checkpoints
9 | */.ipynb_checkpoints/*
10 |
11 | # IPython
12 | profile_default/
13 | ipython_config.py
14 |
15 | # Remove previous ipynb_checkpoints
16 | # git rm -r .ipynb_checkpoints/
17 |
18 | ### Python ###
19 | # Byte-compiled / optimized / DLL files
20 | __pycache__/
21 | *.py[cod]
22 | *$py.class
23 |
24 | # C extensions
25 | *.so
26 |
27 | # Distribution / packaging
28 | .Python
29 | build/
30 | develop-eggs/
31 | dist/
32 | downloads/
33 | eggs/
34 | .eggs/
35 | parts/
36 | sdist/
37 | var/
38 | wheels/
39 | pip-wheel-metadata/
40 | share/python-wheels/
41 | *.egg-info/
42 | .installed.cfg
43 | *.egg
44 | MANIFEST
45 |
46 | # PyInstaller
47 | # Usually these files are written by a python script from a template
48 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
49 | *.manifest
50 | *.spec
51 |
52 | # Installer logs
53 | pip-log.txt
54 | pip-delete-this-directory.txt
55 |
56 | # Unit test / coverage reports
57 | htmlcov/
58 | .tox/
59 | .nox/
60 | .coverage
61 | .coverage.*
62 | .cache
63 | nosetests.xml
64 | coverage.xml
65 | *.cover
66 | *.py,cover
67 | .hypothesis/
68 | .pytest_cache/
69 | pytestdebug.log
70 |
71 | # Translations
72 | *.mo
73 | *.pot
74 |
75 | # Django stuff:
76 | *.log
77 | local_settings.py
78 | db.sqlite3
79 | db.sqlite3-journal
80 |
81 | # Flask stuff:
82 | instance/
83 | .webassets-cache
84 |
85 | # Scrapy stuff:
86 | .scrapy
87 |
88 | # Sphinx documentation
89 | docs/_build/
90 | doc/_build/
91 | docs/_autosummary/
92 |
93 | # PyBuilder
94 | target/
95 |
96 | # Jupyter Notebook
97 |
98 | # IPython
99 |
100 | # pyenv
101 | .python-version
102 |
103 | # pipenv
104 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
105 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
106 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
107 | # install all needed dependencies.
108 | #Pipfile.lock
109 |
110 | # poetry
111 | #poetry.lock
112 |
113 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
114 | __pypackages__/
115 |
116 | # Celery stuff
117 | celerybeat-schedule
118 | celerybeat.pid
119 |
120 | # SageMath parsed files
121 | *.sage.py
122 |
123 | # Environments
124 | # .env
125 | .env/
126 | .venv/
127 | env/
128 | venv/
129 | ENV/
130 | env.bak/
131 | venv.bak/
132 | pythonenv*
133 |
134 | # Spyder project settings
135 | .spyderproject
136 | .spyproject
137 |
138 | # Rope project settings
139 | .ropeproject
140 |
141 | # mkdocs documentation
142 | /site
143 |
144 | # mypy
145 | .mypy_cache/
146 | .dmypy.json
147 | dmypy.json
148 |
149 | # Pyre type checker
150 | .pyre/
151 |
152 | # pytype static type analyzer
153 | .pytype/
154 |
155 | # operating system-related files
156 | # file properties cache/storage on macOS
157 | *.DS_Store
158 | # thumbnail cache on Windows
159 | Thumbs.db
160 |
161 | # profiling data
162 | .prof
163 |
164 |
165 | ### VisualStudioCode ###
166 | .vscode/*
167 | *.code-workspace
168 |
169 | ### VisualStudioCode Patch ###
170 | # Ignore all local history of files
171 | .history
172 | .ionide
173 |
174 | # End of https://www.toptal.com/developers/gitignore/api/python,jupyternotebooks,visualstudiocode
175 |
176 |
177 | ### Project ###
178 | requirements.txt
179 | requirements-dev.txt
--------------------------------------------------------------------------------
/src/tryangle/utils/data/swiss_train.csv:
--------------------------------------------------------------------------------
1 | origin,development,lag,claim,premium
2 | 1979,1979,0,3670,17684
3 | 1979,1980,1,5817,17684
4 | 1979,1981,2,6462,17684
5 | 1979,1982,3,6671,17684
6 | 1979,1983,4,6775,17684
7 | 1979,1984,5,7002,17684
8 | 1979,1985,6,7034,17684
9 | 1979,1986,7,7096,17684
10 | 1979,1987,8,7204,17684
11 | 1979,1988,9,7326,17684
12 | 1979,1989,10,7395,17684
13 | 1979,1990,11,7438,17684
14 | 1979,1991,12,7468,17684
15 | 1979,1992,13,7541,17684
16 | 1979,1993,14,7580,17684
17 | 1979,1994,15,7677,17684
18 | 1979,1995,16,7794,17684
19 | 1979,1996,17,7919,17684
20 | 1979,1997,18,8047,17684
21 | 1980,1980,0,4827,18762
22 | 1980,1981,1,7600,18762
23 | 1980,1982,2,8274,18762
24 | 1980,1983,3,8412,18762
25 | 1980,1984,4,9059,18762
26 | 1980,1985,5,9197,18762
27 | 1980,1986,6,9230,18762
28 | 1980,1987,7,9277,18762
29 | 1980,1988,8,9331,18762
30 | 1980,1989,9,9435,18762
31 | 1980,1990,10,9864,18762
32 | 1980,1991,11,9621,18762
33 | 1980,1992,12,9654,18762
34 | 1980,1993,13,9704,18762
35 | 1980,1994,14,9743,18762
36 | 1980,1995,15,9745,18762
37 | 1980,1996,16,9745,18762
38 | 1980,1997,17,9748,18762
39 | 1981,1981,0,7130,22056
40 | 1981,1982,1,10852,22056
41 | 1981,1983,2,11422,22056
42 | 1981,1984,3,12024,22056
43 | 1981,1985,4,12320,22056
44 | 1981,1986,5,12346,22056
45 | 1981,1987,6,12379,22056
46 | 1981,1988,7,12426,22056
47 | 1981,1989,8,12460,22056
48 | 1981,1990,9,12500,22056
49 | 1981,1991,10,12508,22056
50 | 1981,1992,11,12547,22056
51 | 1981,1993,12,12557,22056
52 | 1981,1994,13,12624,22056
53 | 1981,1995,14,12639,22056
54 | 1981,1996,15,12644,22056
55 | 1981,1997,16,12647,22056
56 | 1982,1982,0,9244,25489
57 | 1982,1983,1,13340,25489
58 | 1982,1984,2,13758,25489
59 | 1982,1985,3,13853,25489
60 | 1982,1986,4,13894,25489
61 | 1982,1987,5,13942,25489
62 | 1982,1988,6,13980,25489
63 | 1982,1989,7,14001,25489
64 | 1982,1990,8,14012,25489
65 | 1982,1991,9,14070,25489
66 | 1982,1992,10,14085,25489
67 | 1982,1993,11,14098,25489
68 | 1982,1994,12,14111,25489
69 | 1982,1995,13,14118,25489
70 | 1982,1996,14,14120,25489
71 | 1982,1997,15,14133,25489
72 | 1983,1983,0,10019,24819
73 | 1983,1984,1,14223,24819
74 | 1983,1985,2,15403,24819
75 | 1983,1986,3,15579,24819
76 | 1983,1987,4,15732,24819
77 | 1983,1988,5,15921,24819
78 | 1983,1989,6,16187,24819
79 | 1983,1990,7,16420,24819
80 | 1983,1991,8,16531,24819
81 | 1983,1992,9,16559,24819
82 | 1983,1993,10,16568,24819
83 | 1983,1994,11,16585,24819
84 | 1983,1995,12,16597,24819
85 | 1983,1996,13,16614,24819
86 | 1983,1997,14,16617,24819
87 | 1984,1984,0,9966,26887
88 | 1984,1985,1,14599,26887
89 | 1984,1986,2,15181,26887
90 | 1984,1987,3,15431,26887
91 | 1984,1988,4,15506,26887
92 | 1984,1989,5,15538,26887
93 | 1984,1990,6,15906,26887
94 | 1984,1991,7,16014,26887
95 | 1984,1992,8,16537,26887
96 | 1984,1993,9,16833,26887
97 | 1984,1994,10,16951,26887
98 | 1984,1995,11,17038,26887
99 | 1984,1996,12,17040,26887
100 | 1984,1997,13,17195,26887
101 | 1985,1985,0,10441,31782
102 | 1985,1986,1,15043,31782
103 | 1985,1987,2,15577,31782
104 | 1985,1988,3,15784,31782
105 | 1985,1989,4,15926,31782
106 | 1985,1990,5,16054,31782
107 | 1985,1991,6,16087,31782
108 | 1985,1992,7,16107,31782
109 | 1985,1993,8,16311,31782
110 | 1985,1994,9,16366,31782
111 | 1985,1995,10,16396,31782
112 | 1985,1996,11,16414,31782
113 | 1985,1997,12,16419,31782
114 | 1986,1986,0,10578,32585
115 | 1986,1987,1,15657,32585
116 | 1986,1988,2,16352,32585
117 | 1986,1989,3,16714,32585
118 | 1986,1990,4,17048,32585
119 | 1986,1991,5,17289,32585
120 | 1986,1992,6,17632,32585
121 | 1986,1993,7,17646,32585
122 | 1986,1994,8,17662,32585
123 | 1986,1995,9,17678,32585
124 | 1986,1996,10,17693,32585
125 | 1986,1997,11,17700,32585
126 | 1987,1987,0,11214,32726
127 | 1987,1988,1,16482,32726
128 | 1987,1989,2,17197,32726
129 | 1987,1990,3,17518,32726
130 | 1987,1991,4,18345,32726
131 | 1987,1992,5,18480,32726
132 | 1987,1993,6,18505,32726
133 | 1987,1994,7,18520,32726
134 | 1987,1995,8,18578,32726
135 | 1987,1996,9,18633,32726
136 | 1987,1997,10,18671,32726
137 | 1988,1988,0,11442,36372
138 | 1988,1989,1,17621,36372
139 | 1988,1990,2,18465,36372
140 | 1988,1991,3,18693,36372
141 | 1988,1992,4,18882,36372
142 | 1988,1993,5,18965,36372
143 | 1988,1994,6,20464,36372
144 | 1988,1995,7,20522,36372
145 | 1988,1996,8,20558,36372
146 | 1988,1997,9,20607,36372
147 | 1989,1989,0,11720,36873
148 | 1989,1990,1,17779,36873
149 | 1989,1991,2,18655,36873
150 | 1989,1992,3,18940,36873
151 | 1989,1993,4,19098,36873
152 | 1989,1994,5,19368,36873
153 | 1989,1995,6,19970,36873
154 | 1989,1996,7,20162,36873
155 | 1989,1997,8,20195,36873
156 | 1990,1990,0,13293,38938
157 | 1990,1991,1,20689,38938
158 | 1990,1992,2,21696,38938
159 | 1990,1993,3,22439,38938
160 | 1990,1994,4,22798,38938
161 | 1990,1995,5,23054,38938
162 | 1990,1996,6,23394,38938
163 | 1990,1997,7,23554,38938
164 | 1991,1991,0,15063,42109
165 | 1991,1992,1,22917,42109
166 | 1991,1993,2,23543,42109
167 | 1991,1994,3,24032,42109
168 | 1991,1995,4,24156,42109
169 | 1991,1996,5,24232,42109
170 | 1991,1997,6,24360,42109
171 | 1992,1992,0,16986,40818
172 | 1992,1993,1,23958,40818
173 | 1992,1994,2,25090,40818
174 | 1992,1995,3,25392,40818
175 | 1992,1996,4,25546,40818
176 | 1992,1997,5,26099,40818
177 | 1993,1993,0,16681,43180
178 | 1993,1994,1,24867,43180
179 | 1993,1995,2,25871,43180
180 | 1993,1996,3,26463,43180
181 | 1993,1997,4,26941,43180
182 | 1994,1994,0,17595,47061
183 | 1994,1995,1,25152,47061
184 | 1994,1996,2,26140,47061
185 | 1994,1997,3,27090,47061
186 | 1995,1995,0,16547,48428
187 | 1995,1996,1,25396,48428
188 | 1995,1997,2,26506,48428
189 | 1996,1996,0,15449,52565
190 | 1996,1997,1,22702,52565
191 | 1997,1997,0,18043,52728
192 |
--------------------------------------------------------------------------------
/src/tryangle/core/methods.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | from chainladder.development.clark import ClarkLDF as _cl_ClarkLDF
6 | from chainladder.development.constant import (
7 | DevelopmentConstant as _cl_DevelopmentConstant,
8 | )
9 | from chainladder.development.development import Development as _cl_Development
10 | from chainladder.development.incremental import (
11 | IncrementalAdditive as _cl_IncrementalAdditive,
12 | )
13 | from chainladder.methods.benktander import Benktander as _cl_Benktander
14 | from chainladder.methods.bornferg import BornhuetterFerguson as _cl_BornhuetterFerguson
15 | from chainladder.methods.capecod import CapeCod as _cl_CapeCod
16 | from chainladder.methods.chainladder import Chainladder as _cl_Chainladder
17 | from chainladder.methods.mack import MackChainladder as _cl_MackChainladder
18 | from chainladder.workflow.voting import VotingChainladder as _cl_VotingChainladder
19 | from tryangle.core.base import TryangleData
20 |
21 |
22 | class EstimatorMixin:
23 | """
24 | Fit and predict a chainladder estimator
25 | """
26 |
27 | def fit(self, X, y=None, sample_weight=None):
28 | return super().fit(X.triangle, y=None, sample_weight=X.sample_weight)
29 |
30 | def predict(self, X, sample_weight=None):
31 | return super().predict(X.triangle, sample_weight=X.sample_weight)
32 |
33 | def fit_predict(self, X, sample_weight=None):
34 | self.fit(X)
35 | return self.predict(X)
36 |
37 |
38 | class TransformerMixin:
39 | """
40 | Fit and transform a chainladder transfomer
41 | """
42 |
43 | def fit(self, X, y=None, sample_weight=None):
44 | return super().fit(X.triangle, y=None, sample_weight=X.sample_weight)
45 |
46 | def transform(self, X):
47 | return TryangleData(super().transform(X.triangle), X.sample_weight)
48 |
49 |
50 | class Development(TransformerMixin, _cl_Development):
51 | __doc__ = _cl_Development.__doc__
52 |
53 | def __init__(
54 | self,
55 | n_periods=-1,
56 | average="volume",
57 | sigma_interpolation="log-linear",
58 | drop=None,
59 | drop_high=None,
60 | drop_low=None,
61 | drop_valuation=None,
62 | fillna=None,
63 | ):
64 | super().__init__(
65 | n_periods=n_periods,
66 | average=average,
67 | sigma_interpolation=sigma_interpolation,
68 | drop=drop,
69 | drop_high=drop_high,
70 | drop_low=drop_low,
71 | drop_valuation=drop_valuation,
72 | fillna=fillna,
73 | )
74 |
75 |
76 | class DevelopmentConstant(TransformerMixin, _cl_DevelopmentConstant):
77 | __doc__ = _cl_DevelopmentConstant.__doc__
78 |
79 | def __init__(
80 | self,
81 | patterns=None,
82 | style="ldf",
83 | callable_axis=0,
84 | ):
85 | super().__init__(
86 | patterns=patterns,
87 | style=style,
88 | callable_axis=callable_axis,
89 | )
90 |
91 |
92 | class IncrementalAdditive(TransformerMixin, _cl_IncrementalAdditive):
93 | __doc__ = _cl_IncrementalAdditive.__doc__
94 |
95 | def __init__(
96 | self,
97 | trend=0.0,
98 | n_periods=-1,
99 | average="volume",
100 | future_trend=0,
101 | drop=None,
102 | drop_high=None,
103 | drop_low=None,
104 | drop_valuation=None,
105 | ):
106 | super().__init__(
107 | trend=trend,
108 | n_periods=n_periods,
109 | average=average,
110 | future_trend=future_trend,
111 | drop=drop,
112 | drop_high=drop_high,
113 | drop_low=drop_low,
114 | drop_valuation=drop_valuation,
115 | )
116 |
117 |
118 | class ClarkLDF(TransformerMixin, _cl_ClarkLDF):
119 | __doc__ = _cl_ClarkLDF.__doc__
120 |
121 | def __init__(self, growth="loglogistic"):
122 | super().__init__(
123 | growth=growth,
124 | )
125 |
126 |
127 | class Chainladder(EstimatorMixin, _cl_Chainladder):
128 | __doc__ = _cl_Chainladder.__doc__
129 |
130 |
131 | class MackChainladder(EstimatorMixin, _cl_MackChainladder):
132 | __doc__ = _cl_MackChainladder.__doc__
133 |
134 |
135 | class BornhuetterFerguson(EstimatorMixin, _cl_BornhuetterFerguson):
136 | __doc__ = _cl_BornhuetterFerguson.__doc__
137 |
138 | def __init__(self, apriori=1.0, apriori_sigma=0.0, random_state=None):
139 | super().__init__(
140 | apriori=apriori, apriori_sigma=apriori_sigma, random_state=random_state
141 | )
142 |
143 |
144 | class CapeCod(EstimatorMixin, _cl_CapeCod):
145 | __doc__ = _cl_CapeCod.__doc__
146 |
147 | def __init__(self, trend=0, decay=1):
148 | super().__init__(trend=trend, decay=decay)
149 |
150 |
151 | class Benktander(EstimatorMixin, _cl_Benktander):
152 | __doc__ = _cl_Benktander.__doc__
153 |
154 | def __init__(self, apriori=1.0, n_iters=1, apriori_sigma=0, random_state=None):
155 | super().__init__(
156 | apriori=apriori,
157 | n_iters=n_iters,
158 | apriori_sigma=apriori_sigma,
159 | random_state=random_state,
160 | )
161 |
162 |
163 | class VotingChainladder(EstimatorMixin, _cl_VotingChainladder):
164 | __doc__ = _cl_VotingChainladder.__doc__
165 |
166 | def __init__(
167 | self,
168 | estimators,
169 | weights=None,
170 | default_weighting=None,
171 | n_jobs=None,
172 | verbose=False,
173 | ):
174 | # Convert tryangle estimators to chainladder estimators
175 | estimators = [
176 | (
177 | name,
178 | globals()["_cl_" + estimator.__class__.__name__](**estimator.__dict__),
179 | )
180 | for name, estimator in estimators
181 | ]
182 | super().__init__(
183 | estimators=estimators,
184 | weights=weights,
185 | default_weighting=default_weighting,
186 | n_jobs=n_jobs,
187 | verbose=verbose,
188 | )
189 |
--------------------------------------------------------------------------------
/src/tryangle/utils/data/cas_test.csv:
--------------------------------------------------------------------------------
1 | origin,development,lag,claim,premium
2 | 2010/03/31,2015/03/31,20,9455.582936,0
3 | 2010/06/30,2015/03/31,19,5807.656259,0
4 | 2010/06/30,2015/06/30,20,5802.727068,0
5 | 2010/09/30,2015/03/31,18,7821.904961,0
6 | 2010/09/30,2015/06/30,19,7821.405067,0
7 | 2010/09/30,2015/09/30,20,8155.834385,0
8 | 2010/12/31,2015/03/31,17,5920.818388,0
9 | 2010/12/31,2015/06/30,18,6165.941,0
10 | 2010/12/31,2015/09/30,19,6196.027664,0
11 | 2010/12/31,2015/12/31,20,6026.017085,0
12 | 2011/03/31,2015/03/31,16,8708.868662,0
13 | 2011/03/31,2015/06/30,17,9367.636407,0
14 | 2011/03/31,2015/09/30,18,9670.723512,0
15 | 2011/03/31,2015/12/31,19,10318.90047,0
16 | 2011/03/31,2016/03/31,20,10078.6838,0
17 | 2011/06/30,2015/03/31,15,7050.81212,0
18 | 2011/06/30,2015/06/30,16,6987.592923,0
19 | 2011/06/30,2015/09/30,17,7024.759487,0
20 | 2011/06/30,2015/12/31,18,7182.156453,0
21 | 2011/06/30,2016/03/31,19,6672.333972,0
22 | 2011/06/30,2016/06/30,20,6675.705353,0
23 | 2011/09/30,2015/03/31,14,8560.597674,0
24 | 2011/09/30,2015/06/30,15,8368.7545,0
25 | 2011/09/30,2015/09/30,16,8322.810722,0
26 | 2011/09/30,2015/12/31,17,8495.471904,0
27 | 2011/09/30,2016/03/31,18,8286.097551,0
28 | 2011/09/30,2016/06/30,19,8254.976221,0
29 | 2011/09/30,2016/09/30,20,8536.265608,0
30 | 2011/12/31,2015/03/31,13,9206.937813,0
31 | 2011/12/31,2015/06/30,14,9792.186212,0
32 | 2011/12/31,2015/09/30,15,9953.245195,0
33 | 2011/12/31,2015/12/31,16,10001.54894,0
34 | 2011/12/31,2016/03/31,17,9407.197813,0
35 | 2011/12/31,2016/06/30,18,9451.769788,0
36 | 2011/12/31,2016/09/30,19,8273.228178,0
37 | 2011/12/31,2016/12/31,20,8370.95171,0
38 | 2012/03/31,2015/03/31,12,2504.505551,0
39 | 2012/03/31,2015/06/30,13,2677.771256,0
40 | 2012/03/31,2015/09/30,14,2594.393529,0
41 | 2012/03/31,2015/12/31,15,2648.196111,0
42 | 2012/03/31,2016/03/31,16,2660.832975,0
43 | 2012/03/31,2016/06/30,17,2521.048566,0
44 | 2012/03/31,2016/09/30,18,2529.395639,0
45 | 2012/03/31,2016/12/31,19,2370.231604,0
46 | 2012/03/31,2017/03/31,20,2370.231604,0
47 | 2012/06/30,2015/03/31,11,4719.5839,0
48 | 2012/06/30,2015/06/30,12,5136.530661,0
49 | 2012/06/30,2015/09/30,13,5207.515658,0
50 | 2012/06/30,2015/12/31,14,5588.958295,0
51 | 2012/06/30,2016/03/31,15,6253.538765,0
52 | 2012/06/30,2016/06/30,16,6507.101453,0
53 | 2012/06/30,2016/09/30,17,6507.101453,0
54 | 2012/06/30,2016/12/31,18,6593.048404,0
55 | 2012/06/30,2017/03/31,19,6603.650814,0
56 | 2012/06/30,2017/06/30,20,6659.034458,0
57 | 2012/09/30,2015/03/31,10,7024.701359,0
58 | 2012/09/30,2015/06/30,11,7046.092187,0
59 | 2012/09/30,2015/09/30,12,7394.181408,0
60 | 2012/09/30,2015/12/31,13,10204.44792,0
61 | 2012/09/30,2016/03/31,14,9914.892836,0
62 | 2012/09/30,2016/06/30,15,9643.392079,0
63 | 2012/09/30,2016/09/30,16,9928.971256,0
64 | 2012/09/30,2016/12/31,17,10268.88779,0
65 | 2012/09/30,2017/03/31,18,10221.3397,0
66 | 2012/09/30,2017/06/30,19,10808.43654,0
67 | 2012/09/30,2017/09/30,20,10913.05397,0
68 | 2012/12/31,2015/03/31,9,4983.900129,0
69 | 2012/12/31,2015/06/30,10,4971.553901,0
70 | 2012/12/31,2015/09/30,11,5328.397086,0
71 | 2012/12/31,2015/12/31,12,5752.481874,0
72 | 2012/12/31,2016/03/31,13,5802.343428,0
73 | 2012/12/31,2016/06/30,14,5553.616928,0
74 | 2012/12/31,2016/09/30,15,6082.888786,0
75 | 2012/12/31,2016/12/31,16,6529.6432,0
76 | 2012/12/31,2017/03/31,17,6522.784185,0
77 | 2012/12/31,2017/06/30,18,6564.868313,0
78 | 2012/12/31,2017/09/30,19,6569.704501,0
79 | 2012/12/31,2017/12/31,20,6519.645313,0
80 | 2013/03/31,2015/03/31,8,4766.701849,0
81 | 2013/03/31,2015/06/30,9,5146.912188,0
82 | 2013/03/31,2015/09/30,10,5977.108817,0
83 | 2013/03/31,2015/12/31,11,5955.415727,0
84 | 2013/03/31,2016/03/31,12,6004.498377,0
85 | 2013/03/31,2016/06/30,13,6077.296944,0
86 | 2013/03/31,2016/09/30,14,6227.974401,0
87 | 2013/03/31,2016/12/31,15,6501.928128,0
88 | 2013/03/31,2017/03/31,16,6590.22342,0
89 | 2013/03/31,2017/06/30,17,6602.709153,0
90 | 2013/03/31,2017/09/30,18,7606.764385,0
91 | 2013/03/31,2017/12/31,19,7754.256468,0
92 | 2013/03/31,2018/03/31,20,7754.256468,0
93 | 2013/06/30,2015/03/31,7,10614.36128,0
94 | 2013/06/30,2015/06/30,8,11270.87369,0
95 | 2013/06/30,2015/09/30,9,11901.05445,0
96 | 2013/06/30,2015/12/31,10,11493.18717,0
97 | 2013/06/30,2016/03/31,11,11492.57102,0
98 | 2013/06/30,2016/06/30,12,11778.18507,0
99 | 2013/06/30,2016/09/30,13,11795.65812,0
100 | 2013/06/30,2016/12/31,14,11238.04342,0
101 | 2013/06/30,2017/03/31,15,11358.48308,0
102 | 2013/06/30,2017/06/30,16,11098.73565,0
103 | 2013/06/30,2017/09/30,17,11107.0711,0
104 | 2013/06/30,2017/12/31,18,11450.11487,0
105 | 2013/06/30,2018/03/31,19,11413.3087,0
106 | 2013/06/30,2018/06/30,20,11607.40721,0
107 | 2013/09/30,2015/03/31,6,4882.154192,0
108 | 2013/09/30,2015/06/30,7,4970.077469,0
109 | 2013/09/30,2015/09/30,8,4877.07387,0
110 | 2013/09/30,2015/12/31,9,5969.377893,0
111 | 2013/09/30,2016/03/31,10,6023.157224,0
112 | 2013/09/30,2016/06/30,11,6167.719694,0
113 | 2013/09/30,2016/09/30,12,6383.557797,0
114 | 2013/09/30,2016/12/31,13,7814.511175,0
115 | 2013/09/30,2017/03/31,14,7804.362157,0
116 | 2013/09/30,2017/06/30,15,7262.162799,0
117 | 2013/09/30,2017/09/30,16,8047.078301,0
118 | 2013/09/30,2017/12/31,17,8041.846848,0
119 | 2013/09/30,2018/03/31,18,8288.318012,0
120 | 2013/09/30,2018/06/30,19,8340.237271,0
121 | 2013/09/30,2018/09/30,20,8329.809243,0
122 | 2013/12/31,2015/03/31,5,7356.631205,0
123 | 2013/12/31,2015/06/30,6,7117.693333,0
124 | 2013/12/31,2015/09/30,7,7671.250756,0
125 | 2013/12/31,2015/12/31,8,7983.905606,0
126 | 2013/12/31,2016/03/31,9,8775.831254,0
127 | 2013/12/31,2016/06/30,10,9575.278568,0
128 | 2013/12/31,2016/09/30,11,9614.851599,0
129 | 2013/12/31,2016/12/31,12,9884.143521,0
130 | 2013/12/31,2017/03/31,13,9907.88269,0
131 | 2013/12/31,2017/06/30,14,7871.127116,0
132 | 2013/12/31,2017/09/30,15,8005.029048,0
133 | 2013/12/31,2017/12/31,16,7982.185039,0
134 | 2013/12/31,2018/03/31,17,7897.8424,0
135 | 2013/12/31,2018/06/30,18,7899.597843,0
136 | 2013/12/31,2018/09/30,19,7894.447769,0
137 | 2013/12/31,2018/12/31,20,7732.237866,0
138 | 2014/03/31,2015/03/31,4,5070.777116,0
139 | 2014/03/31,2015/06/30,5,5653.839931,0
140 | 2014/03/31,2015/09/30,6,6389.265893,0
141 | 2014/03/31,2015/12/31,7,7468.130895,0
142 | 2014/03/31,2016/03/31,8,7458.226012,0
143 | 2014/03/31,2016/06/30,9,7303.293641,0
144 | 2014/03/31,2016/09/30,10,7229.983554,0
145 | 2014/03/31,2016/12/31,11,7365.826936,0
146 | 2014/03/31,2017/03/31,12,7498.264061,0
147 | 2014/03/31,2017/06/30,13,8081.245498,0
148 | 2014/03/31,2017/09/30,14,8312.684955,0
149 | 2014/03/31,2017/12/31,15,8778.70274,0
150 | 2014/03/31,2018/03/31,16,8854.465797,0
151 | 2014/03/31,2018/06/30,17,9395.583989,0
152 | 2014/03/31,2018/09/30,18,9567.431389,0
153 | 2014/03/31,2018/12/31,19,10067.05835,0
154 | 2014/03/31,2019/03/31,20,10907.65976,0
155 | 2014/06/30,2015/03/31,3,10026.34602,0
156 | 2014/06/30,2015/06/30,4,10224.50182,0
157 | 2014/06/30,2015/09/30,5,10712.86372,0
158 | 2014/06/30,2015/12/31,6,11673.96291,0
159 | 2014/06/30,2016/03/31,7,11833.42921,0
160 | 2014/06/30,2016/06/30,8,11639.13306,0
161 | 2014/06/30,2016/09/30,9,12485.36119,0
162 | 2014/06/30,2016/12/31,10,12278.86995,0
163 | 2014/06/30,2017/03/31,11,12327.17369,0
164 | 2014/06/30,2017/06/30,12,11754.22502,0
165 | 2014/06/30,2017/09/30,13,11808.58562,0
166 | 2014/06/30,2017/12/31,14,11776.18549,0
167 | 2014/06/30,2018/03/31,15,11853.77375,0
168 | 2014/06/30,2018/06/30,16,11686.86716,0
169 | 2014/06/30,2018/09/30,17,11708.78114,0
170 | 2014/06/30,2018/12/31,18,11364.81895,0
171 | 2014/06/30,2019/03/31,19,11469.4945,0
172 | 2014/06/30,2019/06/30,20,10940.32727,0
173 | 2014/09/30,2015/03/31,2,6178.124471,0
174 | 2014/09/30,2015/06/30,3,8651.020424,0
175 | 2014/09/30,2015/09/30,4,10214.28305,0
176 | 2014/09/30,2015/12/31,5,11282.7084,0
177 | 2014/09/30,2016/03/31,6,11203.48095,0
178 | 2014/09/30,2016/06/30,7,11551.5818,0
179 | 2014/09/30,2016/09/30,8,12697.20014,0
180 | 2014/09/30,2016/12/31,9,12468.06252,0
181 | 2014/09/30,2017/03/31,10,12828.07945,0
182 | 2014/09/30,2017/06/30,11,14162.85548,0
183 | 2014/09/30,2017/09/30,12,13961.60732,0
184 | 2014/09/30,2017/12/31,13,14113.86584,0
185 | 2014/09/30,2018/03/31,14,14931.72786,0
186 | 2014/09/30,2018/06/30,15,16580.93744,0
187 | 2014/09/30,2018/09/30,16,16279.29189,0
188 | 2014/09/30,2018/12/31,17,15667.74672,0
189 | 2014/09/30,2019/03/31,18,15625.05807,0
190 | 2014/09/30,2019/06/30,19,17347.31035,0
191 | 2014/09/30,2019/09/30,20,17165.33718,0
192 | 2014/12/31,2015/03/31,1,4341.617273,0
193 | 2014/12/31,2015/06/30,2,4786.546492,0
194 | 2014/12/31,2015/09/30,3,6309.515306,0
195 | 2014/12/31,2015/12/31,4,7942.635259,0
196 | 2014/12/31,2016/03/31,5,8481.951506,0
197 | 2014/12/31,2016/06/30,6,8669.772274,0
198 | 2014/12/31,2016/09/30,7,8747.348902,0
199 | 2014/12/31,2016/12/31,8,9149.728974,0
200 | 2014/12/31,2017/03/31,9,9373.867648,0
201 | 2014/12/31,2017/06/30,10,9823.168036,0
202 | 2014/12/31,2017/09/30,11,10711.74767,0
203 | 2014/12/31,2017/12/31,12,11521.55326,0
204 | 2014/12/31,2018/03/31,13,11241.58918,0
205 | 2014/12/31,2018/06/30,14,12279.20709,0
206 | 2014/12/31,2018/09/30,15,13806.30294,0
207 | 2014/12/31,2018/12/31,16,13720.93726,0
208 | 2014/12/31,2019/03/31,17,13857.64092,0
209 | 2014/12/31,2019/06/30,18,14243.54773,0
210 | 2014/12/31,2019/09/30,19,16558.00043,0
211 | 2014/12/31,2019/12/31,20,16405.61403,0
212 |
--------------------------------------------------------------------------------
/src/tryangle/utils/data/sme_test.csv:
--------------------------------------------------------------------------------
1 | origin,development,lag,claim,premium
2 | 2010/03/31,2015/03/31,20,24096.95571,0
3 | 2010/06/30,2015/03/31,19,22592.40107,0
4 | 2010/06/30,2015/06/30,20,22589.88616,0
5 | 2010/09/30,2015/03/31,18,17754.29048,0
6 | 2010/09/30,2015/06/30,19,17754.29048,0
7 | 2010/09/30,2015/09/30,20,17754.29048,0
8 | 2010/12/31,2015/03/31,17,23829.94857,0
9 | 2010/12/31,2015/06/30,18,23829.94857,0
10 | 2010/12/31,2015/09/30,19,23828.50131,0
11 | 2010/12/31,2015/12/31,20,23774.35964,0
12 | 2011/03/31,2015/03/31,16,26000.57381,0
13 | 2011/03/31,2015/06/30,17,26000.57381,0
14 | 2011/03/31,2015/09/30,18,26000.57381,0
15 | 2011/03/31,2015/12/31,19,26000.57381,0
16 | 2011/03/31,2016/03/31,20,26000.57381,0
17 | 2011/06/30,2015/03/31,15,22062.42012,0
18 | 2011/06/30,2015/06/30,16,22062.42012,0
19 | 2011/06/30,2015/09/30,17,22062.42012,0
20 | 2011/06/30,2015/12/31,18,22062.42012,0
21 | 2011/06/30,2016/03/31,19,22062.42012,0
22 | 2011/06/30,2016/06/30,20,22062.42012,0
23 | 2011/09/30,2015/03/31,14,25940.09743,0
24 | 2011/09/30,2015/06/30,15,25940.09743,0
25 | 2011/09/30,2015/09/30,16,25940.09743,0
26 | 2011/09/30,2015/12/31,17,25940.09743,0
27 | 2011/09/30,2016/03/31,18,25927.68897,0
28 | 2011/09/30,2016/06/30,19,25921.44916,0
29 | 2011/09/30,2016/09/30,20,25931.95957,0
30 | 2011/12/31,2015/03/31,13,32463.95455,0
31 | 2011/12/31,2015/06/30,14,32463.95455,0
32 | 2011/12/31,2015/09/30,15,32463.95455,0
33 | 2011/12/31,2015/12/31,16,32463.95455,0
34 | 2011/12/31,2016/03/31,17,32463.95455,0
35 | 2011/12/31,2016/06/30,18,32463.95455,0
36 | 2011/12/31,2016/09/30,19,32463.95455,0
37 | 2011/12/31,2016/12/31,20,32463.95455,0
38 | 2012/03/31,2015/03/31,12,29765.69719,0
39 | 2012/03/31,2015/06/30,13,29764.65326,0
40 | 2012/03/31,2015/09/30,14,29763.63307,0
41 | 2012/03/31,2015/12/31,15,29763.63307,0
42 | 2012/03/31,2016/03/31,16,29763.63307,0
43 | 2012/03/31,2016/06/30,17,29763.63307,0
44 | 2012/03/31,2016/09/30,18,29759.90816,0
45 | 2012/03/31,2016/12/31,19,29759.90816,0
46 | 2012/03/31,2017/03/31,20,29759.90816,0
47 | 2012/06/30,2015/03/31,11,27184.00337,0
48 | 2012/06/30,2015/06/30,12,27184.00337,0
49 | 2012/06/30,2015/09/30,13,27184.00337,0
50 | 2012/06/30,2015/12/31,14,27043.73802,0
51 | 2012/06/30,2016/03/31,15,27043.73802,0
52 | 2012/06/30,2016/06/30,16,27043.73802,0
53 | 2012/06/30,2016/09/30,17,27043.73802,0
54 | 2012/06/30,2016/12/31,18,27043.73802,0
55 | 2012/06/30,2017/03/31,19,27043.73802,0
56 | 2012/06/30,2017/06/30,20,27043.73802,0
57 | 2012/09/30,2015/03/31,10,32479.8032,0
58 | 2012/09/30,2015/06/30,11,32317.23586,0
59 | 2012/09/30,2015/09/30,12,32441.72372,0
60 | 2012/09/30,2015/12/31,13,32413.25309,0
61 | 2012/09/30,2016/03/31,14,32454.13218,0
62 | 2012/09/30,2016/06/30,15,32454.13218,0
63 | 2012/09/30,2016/09/30,16,32560.84962,0
64 | 2012/09/30,2016/12/31,17,32564.50335,0
65 | 2012/09/30,2017/03/31,18,32564.50335,0
66 | 2012/09/30,2017/06/30,19,32560.56492,0
67 | 2012/09/30,2017/09/30,20,32560.56492,0
68 | 2012/12/31,2015/03/31,9,41486.03907,0
69 | 2012/12/31,2015/06/30,10,41475.59983,0
70 | 2012/12/31,2015/09/30,11,41551.30801,0
71 | 2012/12/31,2015/12/31,12,41551.30801,0
72 | 2012/12/31,2016/03/31,13,41551.30801,0
73 | 2012/12/31,2016/06/30,14,41551.30801,0
74 | 2012/12/31,2016/09/30,15,41583.40865,0
75 | 2012/12/31,2016/12/31,16,41583.40865,0
76 | 2012/12/31,2017/03/31,17,41583.40865,0
77 | 2012/12/31,2017/06/30,18,41255.9963,0
78 | 2012/12/31,2017/09/30,19,41214.38172,0
79 | 2012/12/31,2017/12/31,20,41214.38172,0
80 | 2013/03/31,2015/03/31,8,38508.0814,0
81 | 2013/03/31,2015/06/30,9,38516.29044,0
82 | 2013/03/31,2015/09/30,10,38526.65849,0
83 | 2013/03/31,2015/12/31,11,38510.71494,0
84 | 2013/03/31,2016/03/31,12,38510.71494,0
85 | 2013/03/31,2016/06/30,13,38510.71494,0
86 | 2013/03/31,2016/09/30,14,38776.89169,0
87 | 2013/03/31,2016/12/31,15,38729.01356,0
88 | 2013/03/31,2017/03/31,16,38726.64101,0
89 | 2013/03/31,2017/06/30,17,38726.64101,0
90 | 2013/03/31,2017/09/30,18,38726.64101,0
91 | 2013/03/31,2017/12/31,19,38726.64101,0
92 | 2013/03/31,2018/03/31,20,38737.05652,0
93 | 2013/06/30,2015/03/31,7,26322.95634,0
94 | 2013/06/30,2015/06/30,8,26318.30614,0
95 | 2013/06/30,2015/09/30,9,26309.00573,0
96 | 2013/06/30,2015/12/31,10,26621.18629,0
97 | 2013/06/30,2016/03/31,11,26621.18629,0
98 | 2013/06/30,2016/06/30,12,26639.73965,0
99 | 2013/06/30,2016/09/30,13,26639.73965,0
100 | 2013/06/30,2016/12/31,14,26624.34178,0
101 | 2013/06/30,2017/03/31,15,26624.34178,0
102 | 2013/06/30,2017/06/30,16,26623.63002,0
103 | 2013/06/30,2017/09/30,17,26623.63002,0
104 | 2013/06/30,2017/12/31,18,26623.63002,0
105 | 2013/06/30,2018/03/31,19,26623.63002,0
106 | 2013/06/30,2018/06/30,20,26623.63002,0
107 | 2013/09/30,2015/03/31,6,27364.72075,0
108 | 2013/09/30,2015/06/30,7,27262.70096,0
109 | 2013/09/30,2015/09/30,8,27243.91034,0
110 | 2013/09/30,2015/12/31,9,27246.16426,0
111 | 2013/09/30,2016/03/31,10,27256.55605,0
112 | 2013/09/30,2016/06/30,11,27246.14054,0
113 | 2013/09/30,2016/09/30,12,27246.14054,0
114 | 2013/09/30,2016/12/31,13,27258.64389,0
115 | 2013/09/30,2017/03/31,14,27258.64389,0
116 | 2013/09/30,2017/06/30,15,27258.64389,0
117 | 2013/09/30,2017/09/30,16,27258.64389,0
118 | 2013/09/30,2017/12/31,17,27258.64389,0
119 | 2013/09/30,2018/03/31,18,27258.64389,0
120 | 2013/09/30,2018/06/30,19,27258.66762,0
121 | 2013/09/30,2018/09/30,20,27258.64389,0
122 | 2013/12/31,2015/03/31,5,45806.36363,0
123 | 2013/12/31,2015/06/30,6,44432.8451,0
124 | 2013/12/31,2015/09/30,7,44633.70546,0
125 | 2013/12/31,2015/12/31,8,44637.71508,0
126 | 2013/12/31,2016/03/31,9,44694.01577,0
127 | 2013/12/31,2016/06/30,10,44694.01577,0
128 | 2013/12/31,2016/09/30,11,44683.57653,0
129 | 2013/12/31,2016/12/31,12,44481.43499,0
130 | 2013/12/31,2017/03/31,13,44528.71998,0
131 | 2013/12/31,2017/06/30,14,44567.20279,0
132 | 2013/12/31,2017/09/30,15,44675.6522,0
133 | 2013/12/31,2017/12/31,16,44707.04108,0
134 | 2013/12/31,2018/03/31,17,44790.29398,0
135 | 2013/12/31,2018/06/30,18,44837.1519,0
136 | 2013/12/31,2018/09/30,19,44883.06081,0
137 | 2013/12/31,2018/12/31,20,44814.47029,0
138 | 2014/03/31,2015/03/31,4,37946.52177,0
139 | 2014/03/31,2015/06/30,5,37692.44505,0
140 | 2014/03/31,2015/09/30,6,37686.37131,0
141 | 2014/03/31,2015/12/31,7,37629.2165,0
142 | 2014/03/31,2016/03/31,8,37634.19886,0
143 | 2014/03/31,2016/06/30,9,37634.19886,0
144 | 2014/03/31,2016/09/30,10,37612.44255,0
145 | 2014/03/31,2016/12/31,11,37612.44255,0
146 | 2014/03/31,2017/03/31,12,37599.79684,0
147 | 2014/03/31,2017/06/30,13,37599.79684,0
148 | 2014/03/31,2017/09/30,14,37599.79684,0
149 | 2014/03/31,2017/12/31,15,37599.79684,0
150 | 2014/03/31,2018/03/31,16,37599.79684,0
151 | 2014/03/31,2018/06/30,17,37599.82057,0
152 | 2014/03/31,2018/09/30,18,37599.82057,0
153 | 2014/03/31,2018/12/31,19,37599.79684,0
154 | 2014/03/31,2019/03/31,20,37599.82057,0
155 | 2014/06/30,2015/03/31,3,38611.97551,0
156 | 2014/06/30,2015/06/30,4,37948.23001,0
157 | 2014/06/30,2015/09/30,5,38007.56757,0
158 | 2014/06/30,2015/12/31,6,38109.23148,0
159 | 2014/06/30,2016/03/31,7,38098.74479,0
160 | 2014/06/30,2016/06/30,8,38210.08871,0
161 | 2014/06/30,2016/09/30,9,38178.84219,0
162 | 2014/06/30,2016/12/31,10,38178.84219,0
163 | 2014/06/30,2017/03/31,11,38177.65591,0
164 | 2014/06/30,2017/06/30,12,38177.65591,0
165 | 2014/06/30,2017/09/30,13,38177.65591,0
166 | 2014/06/30,2017/12/31,14,38177.65591,0
167 | 2014/06/30,2018/03/31,15,38177.65591,0
168 | 2014/06/30,2018/06/30,16,38177.65591,0
169 | 2014/06/30,2018/09/30,17,38177.65591,0
170 | 2014/06/30,2018/12/31,18,38175.40199,0
171 | 2014/06/30,2019/03/31,19,38175.40199,0
172 | 2014/06/30,2019/06/30,20,38185.72259,0
173 | 2014/09/30,2015/03/31,2,35282.14447,0
174 | 2014/09/30,2015/06/30,3,34872.14355,0
175 | 2014/09/30,2015/09/30,4,35780.52301,0
176 | 2014/09/30,2015/12/31,5,35467.41716,0
177 | 2014/09/30,2016/03/31,6,35473.39599,0
178 | 2014/09/30,2016/06/30,7,35477.31071,0
179 | 2014/09/30,2016/09/30,8,35450.19242,0
180 | 2014/09/30,2016/12/31,9,35662.91555,0
181 | 2014/09/30,2017/03/31,10,35628.34744,0
182 | 2014/09/30,2017/06/30,11,35557.69281,0
183 | 2014/09/30,2017/09/30,12,35557.69281,0
184 | 2014/09/30,2017/12/31,13,35563.69537,0
185 | 2014/09/30,2018/03/31,14,35563.69537,0
186 | 2014/09/30,2018/06/30,15,35576.12755,0
187 | 2014/09/30,2018/09/30,16,35576.12755,0
188 | 2014/09/30,2018/12/31,17,35570.88421,0
189 | 2014/09/30,2019/03/31,18,35570.88421,0
190 | 2014/09/30,2019/06/30,19,35568.91499,0
191 | 2014/09/30,2019/09/30,20,35555.58124,0
192 | 2014/12/31,2015/03/31,1,35454.98498,0
193 | 2014/12/31,2015/06/30,2,36729.97137,0
194 | 2014/12/31,2015/09/30,3,37065.5453,0
195 | 2014/12/31,2015/12/31,4,36676.58892,0
196 | 2014/12/31,2016/03/31,5,36631.46296,0
197 | 2014/12/31,2016/06/30,6,36391.88253,0
198 | 2014/12/31,2016/09/30,7,36360.65973,0
199 | 2014/12/31,2016/12/31,8,36376.36603,0
200 | 2014/12/31,2017/03/31,9,36386.78154,0
201 | 2014/12/31,2017/06/30,10,36420.49552,0
202 | 2014/12/31,2017/09/30,11,36420.49552,0
203 | 2014/12/31,2017/12/31,12,36430.91103,0
204 | 2014/12/31,2018/03/31,13,36445.02772,0
205 | 2014/12/31,2018/06/30,14,36449.70165,0
206 | 2014/12/31,2018/09/30,15,36449.86773,0
207 | 2014/12/31,2018/12/31,16,36436.98477,0
208 | 2014/12/31,2019/03/31,17,36436.98477,0
209 | 2014/12/31,2019/06/30,18,36436.98477,0
210 | 2014/12/31,2019/09/30,19,36436.98477,0
211 | 2014/12/31,2019/12/31,20,36436.98477,0
212 |
--------------------------------------------------------------------------------
/src/tryangle/ensemble/optimizers.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import numpy as np
6 |
7 |
8 | class SGD:
9 | """
10 | Stochastic Gradient Descent optimizer with decay and momentum
11 |
12 | Parameters
13 | ----------
14 | learning_rate : float, default=0.0001
15 | The initial learning rate used. It controls the step-size used
16 | in updating the weights and biases.
17 |
18 | decay : float, default=0.0
19 | The learning rate decay over epochs.
20 |
21 | momentum : float, default=0.0
22 | The value of momentum used. Must be larger than or equal to 0.
23 | """
24 |
25 | def __init__(self, learning_rate=0.0001, decay=0.0, momentum=0.0):
26 | self.learning_rate = learning_rate
27 | self._learning_rate = learning_rate
28 | self.decay = decay
29 | self.momentum = momentum
30 |
31 | def reset(self, model):
32 | model.weight_momentums = np.zeros_like(model.initial_weight)
33 | model.bias_momentums = np.zeros_like(model.initial_bias)
34 |
35 | def pre_update_params(self, epoch):
36 | if self.decay:
37 | self._learning_rate = self.learning_rate * (
38 | 1.0 / (1.0 + self.decay * epoch)
39 | )
40 |
41 | def update_params(self, model, epoch):
42 | if self.momentum:
43 | if not hasattr(model, "weight_momentums"):
44 | self.reset(model)
45 |
46 | weight_updates = (
47 | self.momentum * model.weight_momentums
48 | - self._learning_rate * model._w_grad
49 | )
50 | model.weight_momentums = weight_updates
51 |
52 | bias_updates = (
53 | self.momentum * model.bias_momentums
54 | - self._learning_rate * model._b_grad
55 | )
56 | model.bias_momentums = bias_updates
57 | else:
58 | weight_updates = -self._learning_rate * model._w_grad
59 | bias_updates = -self._learning_rate * model._b_grad
60 |
61 | model.weights = model.weights + weight_updates
62 | model.biases = model.biases + bias_updates
63 |
64 |
65 | class AdaGrad:
66 | """
67 | Adaptive Gradient Algorithm with decay
68 |
69 | Parameters
70 | ----------
71 | learning_rate : float, default=0.0001
72 | The initial learning rate used. It controls the step-size used
73 | in updating the weights and biases.
74 |
75 | decay : float, default=0.0
76 | The learning rate decay over epochs.
77 |
78 | epsilon : float, default=1e-7
79 | A small constant for numerical stability.
80 | """
81 |
82 | def __init__(self, learning_rate=0.0001, decay=0.0, epsilon=1e-7):
83 | self.learning_rate = learning_rate
84 | self._learning_rate = learning_rate
85 | self.decay = decay
86 | self.epsilon = epsilon
87 |
88 | def pre_update_params(self, epoch):
89 | if self.decay:
90 | self._learning_rate = self.learning_rate * (
91 | 1.0 / (1.0 + self.decay * epoch)
92 | )
93 |
94 | def update_params(self, model, epoch):
95 | if not hasattr(model, "weight_cache"):
96 | model.weight_cache = np.zeros_like(model.weights)
97 | model.bias_cache = np.zeros_like(model.biases)
98 |
99 | model.weight_cache += model._w_grad**2
100 | model.bias_cache += model._b_grad**2
101 |
102 | model.weights += (
103 | -model.optimizer._learning_rate
104 | * model._w_grad
105 | / (np.sqrt(model.weight_cache) + self.epsilon)
106 | )
107 | model.biases += (
108 | -model.optimizer._learning_rate
109 | * model._w_grad
110 | / (np.sqrt(model.bias_cache) + self.epsilon)
111 | )
112 |
113 |
114 | class RMSProp:
115 | """
116 | RMSProp with decay
117 |
118 | Parameters
119 | ----------
120 | learning_rate : float, default=0.0001
121 | The initial learning rate used. It controls the step-size used
122 | in updating the weights and biases.
123 |
124 | decay : float, default=0.0
125 | The learning rate decay over epochs.
126 |
127 | epsilon : float, default=1e-7
128 | A small constant for numerical stability.
129 |
130 | rho : float, default=0.9
131 | Discounting factor for the history/coming gradient.
132 | """
133 |
134 | def __init__(self, learning_rate=0.0001, decay=0.0, epsilon=1e-7, rho=0.9):
135 | self.learning_rate = learning_rate
136 | self._learning_rate = learning_rate
137 | self.decay = decay
138 | self.epsilon = epsilon
139 | self.rho = rho
140 |
141 | def reset(self, model):
142 | model.weight_cache = np.zeros_like(model.weights)
143 | model.bias_cache = np.zeros_like(model.biases)
144 |
145 | def pre_update_params(self, epoch):
146 | if self.decay:
147 | self._learning_rate = self.learning_rate * (
148 | 1.0 / (1.0 + self.decay * epoch)
149 | )
150 |
151 | def update_params(self, model, epoch):
152 | if not hasattr(model, "weight_cache"):
153 | self.reset(model)
154 |
155 | model.weight_cache += (
156 | self.rho * model.weight_cache + (1 - self.rho) * model._w_grad**2
157 | )
158 | model.bias_cache += (
159 | self.rho * model.bias_cache + (1 - self.rho) * model._b_grad**2
160 | )
161 |
162 | model.weights += (
163 | -model.optimizer._learning_rate
164 | * model._w_grad
165 | / (np.sqrt(model.weight_cache) + self.epsilon)
166 | )
167 | model.biases += (
168 | -model.optimizer._learning_rate
169 | * model._w_grad
170 | / (np.sqrt(model.bias_cache) + self.epsilon)
171 | )
172 |
173 |
174 | class Adam:
175 | """
176 | Adam optimizer with decay
177 |
178 | Parameters
179 | ----------
180 | learning_rate : float, default=0.0001
181 | The initial learning rate used. It controls the step-size used
182 | in updating the weights and biases.
183 |
184 | decay : float, default=0.0
185 | The learning rate decay over epochs.
186 |
187 | epsilon : float, default=1e-7
188 | A small constant for numerical stability.
189 |
190 | beta_1 : float, default=0.9
191 | Exponential decay rate for the 1st moment estimates.
192 |
193 | beta_2 : float, default=0.999
194 | Exponential decay rate for the 2nd moment estimates.
195 | """
196 |
197 | def __init__(
198 | self, learning_rate=0.0001, decay=0.0, epsilon=1e-7, beta_1=0.9, beta_2=0.999
199 | ):
200 |
201 | self.learning_rate = learning_rate
202 | self._learning_rate = learning_rate
203 | self.decay = decay
204 | self.epsilon = epsilon
205 | self.beta_1 = beta_1
206 | self.beta_2 = beta_2
207 |
208 | def reset(self, model):
209 | model.weight_momentums = np.zeros_like(model.weights)
210 | model.weight_cache = np.zeros_like(model.weights)
211 | model.bias_momentums = np.zeros_like(model.biases)
212 | model.bias_cache = np.zeros_like(model.biases)
213 |
214 | def pre_update_params(self, epoch):
215 | if self.decay:
216 | self._learning_rate = self.learning_rate * (
217 | 1.0 / (1.0 + self.decay * epoch)
218 | )
219 |
220 | def update_params(self, model, epoch):
221 | if not hasattr(model, "weight_cache"):
222 | self.reset(model)
223 |
224 | model.weight_momentums = (
225 | self.beta_1 * model.weight_momentums + (1 - self.beta_1) * model._w_grad
226 | )
227 | model.bias_momentums = (
228 | self.beta_1 * model.bias_momentums + (1 - self.beta_1) * model._b_grad
229 | )
230 |
231 | weight_momentums_corrected = model.weight_momentums / (
232 | 1 - self.beta_1 ** (epoch + 1)
233 | )
234 | bias_momentums_corrected = model.bias_momentums / (
235 | 1 - self.beta_1 ** (epoch + 1)
236 | )
237 |
238 | model.weight_cache += (
239 | self.beta_2 * model.weight_cache + (1 - self.beta_2) * model._w_grad**2
240 | )
241 | model.bias_cache += (
242 | self.beta_2 * model.bias_cache + (1 - self.beta_2) * model._b_grad**2
243 | )
244 |
245 | weight_cache_corrected = model.weight_cache / (1 - self.beta_2 ** (epoch + 1))
246 | bias_cache_corrected = model.bias_cache / (1 - self.beta_2 ** (epoch + 1))
247 |
248 | model.weights += (
249 | -model.optimizer._learning_rate
250 | * weight_momentums_corrected
251 | / (np.sqrt(weight_cache_corrected) + self.epsilon)
252 | )
253 | model.biases += (
254 | -model.optimizer._learning_rate
255 | * bias_momentums_corrected
256 | / (np.sqrt(bias_cache_corrected) + self.epsilon)
257 | )
258 |
--------------------------------------------------------------------------------
/src/tryangle/utils/data/swiss_test.csv:
--------------------------------------------------------------------------------
1 | origin,development,lag,claim,premium
2 | 1979,1998,19,8051,0
3 | 1980,1998,18,9749,0
4 | 1980,1999,19,9749,0
5 | 1981,1998,17,12666,0
6 | 1981,1999,18,12711,0
7 | 1981,2000,19,12713,0
8 | 1982,1998,16,14141,0
9 | 1982,1999,17,14145,0
10 | 1982,2000,18,14166,0
11 | 1982,2001,19,14167,0
12 | 1983,1998,15,16619,0
13 | 1983,1999,16,16681,0
14 | 1983,2000,17,16681,0
15 | 1983,2001,18,16687,0
16 | 1983,2002,19,16711,0
17 | 1984,1998,14,17298,0
18 | 1984,1999,15,17307,0
19 | 1984,2000,16,17308,0
20 | 1984,2001,17,17308,0
21 | 1984,2002,18,17309,0
22 | 1984,2003,19,17310,0
23 | 1985,1998,13,16426,0
24 | 1985,1999,14,16480,0
25 | 1985,2000,15,16480,0
26 | 1985,2001,16,16480,0
27 | 1985,2002,17,16480,0
28 | 1985,2003,18,16482,0
29 | 1985,2004,19,16482,0
30 | 1986,1998,12,17706,0
31 | 1986,1999,13,17706,0
32 | 1986,2000,14,17712,0
33 | 1986,2001,15,17713,0
34 | 1986,2002,16,17718,0
35 | 1986,2003,17,17719,0
36 | 1986,2004,18,17719,0
37 | 1986,2005,19,17719,0
38 | 1987,1998,11,18689,0
39 | 1987,1999,12,18746,0
40 | 1987,2000,13,18772,0
41 | 1987,2001,14,18774,0
42 | 1987,2002,15,18804,0
43 | 1987,2003,16,18804,0
44 | 1987,2004,17,18804,0
45 | 1987,2005,18,18806,0
46 | 1987,2006,19,18806,0
47 | 1988,1998,10,20611,0
48 | 1988,1999,11,21250,0
49 | 1988,2000,12,21257,0
50 | 1988,2001,13,22505,0
51 | 1988,2002,14,22509,0
52 | 1988,2003,15,22516,0
53 | 1988,2004,16,22518,0
54 | 1988,2005,17,22522,0
55 | 1988,2006,18,22523,0
56 | 1988,2007,19,22527,0
57 | 1989,1998,9,20415,0
58 | 1989,1999,10,20510,0
59 | 1989,2000,11,20594,0
60 | 1989,2001,12,20657,0
61 | 1989,2002,13,20752,0
62 | 1989,2003,14,20823,0
63 | 1989,2004,15,20899,0
64 | 1989,2005,16,20983,0
65 | 1989,2006,17,21124,0
66 | 1989,2007,18,21622,0
67 | 1989,2008,19,21627,0
68 | 1990,1998,8,23888,0
69 | 1990,1999,9,24061,0
70 | 1990,2000,10,24096,0
71 | 1990,2001,11,24301,0
72 | 1990,2002,12,24356,0
73 | 1990,2003,13,24389,0
74 | 1990,2004,14,24391,0
75 | 1990,2005,15,24784,0
76 | 1990,2006,16,24784,0
77 | 1990,2007,17,24794,0
78 | 1990,2008,18,24894,0
79 | 1990,2009,19,24900,0
80 | 1991,1998,7,24410,0
81 | 1991,1999,8,24884,0
82 | 1991,2000,9,24896,0
83 | 1991,2001,10,24968,0
84 | 1991,2002,11,25031,0
85 | 1991,2003,12,25172,0
86 | 1991,2004,13,25459,0
87 | 1991,2005,14,25460,0
88 | 1991,2006,15,25470,0
89 | 1991,2007,16,25734,0
90 | 1991,2008,17,25774,0
91 | 1991,2009,18,25877,0
92 | 1991,2010,19,25883,0
93 | 1992,1998,6,26129,0
94 | 1992,1999,7,26149,0
95 | 1992,2000,8,26166,0
96 | 1992,2001,9,26231,0
97 | 1992,2002,10,26328,0
98 | 1992,2003,11,26743,0
99 | 1992,2004,12,27023,0
100 | 1992,2005,13,27048,0
101 | 1992,2006,14,27075,0
102 | 1992,2007,15,27168,0
103 | 1992,2008,16,27234,0
104 | 1992,2009,17,27276,0
105 | 1992,2010,18,27386,0
106 | 1992,2011,19,27392,0
107 | 1993,1998,5,27120,0
108 | 1993,1999,6,27164,0
109 | 1993,2000,7,27183,0
110 | 1993,2001,8,27250,0
111 | 1993,2002,9,27490,0
112 | 1993,2003,10,27497,0
113 | 1993,2004,11,27561,0
114 | 1993,2005,12,27565,0
115 | 1993,2006,13,27582,0
116 | 1993,2007,14,27706,0
117 | 1993,2008,15,27787,0
118 | 1993,2009,16,27855,0
119 | 1993,2010,17,27898,0
120 | 1993,2011,18,28010,0
121 | 1993,2012,19,28017,0
122 | 1994,1998,4,27568,0
123 | 1994,1999,5,27637,0
124 | 1994,2000,6,27805,0
125 | 1994,2001,7,28003,0
126 | 1994,2002,8,28223,0
127 | 1994,2003,9,28240,0
128 | 1994,2004,10,28245,0
129 | 1994,2005,11,28250,0
130 | 1994,2006,12,28257,0
131 | 1994,2007,13,28297,0
132 | 1994,2008,14,28347,0
133 | 1994,2009,15,28430,0
134 | 1994,2010,16,28499,0
135 | 1994,2011,17,28543,0
136 | 1994,2012,18,28658,0
137 | 1994,2013,19,28665,0
138 | 1995,1998,3,27043,0
139 | 1995,1999,4,27866,0
140 | 1995,2000,5,27882,0
141 | 1995,2001,6,27903,0
142 | 1995,2002,7,27933,0
143 | 1995,2003,8,28492,0
144 | 1995,2004,9,28545,0
145 | 1995,2005,10,28564,0
146 | 1995,2006,11,28686,0
147 | 1995,2007,12,28695,0
148 | 1995,2008,13,28897,0
149 | 1995,2009,14,28948,0
150 | 1995,2010,15,29033,0
151 | 1995,2011,16,29104,0
152 | 1995,2012,17,29149,0
153 | 1995,2013,18,29266,0
154 | 1995,2014,19,29273,0
155 | 1996,1998,2,23909,0
156 | 1996,1999,3,24690,0
157 | 1996,2000,4,26083,0
158 | 1996,2001,5,26525,0
159 | 1996,2002,6,26567,0
160 | 1996,2003,7,26640,0
161 | 1996,2004,8,26695,0
162 | 1996,2005,9,26801,0
163 | 1996,2006,10,26814,0
164 | 1996,2007,11,27018,0
165 | 1996,2008,12,27078,0
166 | 1996,2009,13,27269,0
167 | 1996,2010,14,27317,0
168 | 1996,2011,15,27397,0
169 | 1996,2012,16,27463,0
170 | 1996,2013,17,27506,0
171 | 1996,2014,18,27616,0
172 | 1996,2015,19,27623,0
173 | 1997,1998,1,26918,0
174 | 1997,1999,2,28256,0
175 | 1997,2000,3,28569,0
176 | 1997,2001,4,28964,0
177 | 1997,2002,5,29268,0
178 | 1997,2003,6,29344,0
179 | 1997,2004,7,29393,0
180 | 1997,2005,8,30159,0
181 | 1997,2006,9,30936,0
182 | 1997,2007,10,30966,0
183 | 1997,2008,11,31122,0
184 | 1997,2009,12,31190,0
185 | 1997,2010,13,31410,0
186 | 1997,2011,14,31466,0
187 | 1997,2012,15,31558,0
188 | 1997,2013,16,31635,0
189 | 1997,2014,17,31684,0
190 | 1997,2015,18,31811,0
191 | 1997,2016,19,31819,0
192 | 1998,1998,0,17655,0
193 | 1998,1999,1,26241,0
194 | 1998,2000,2,27369,0
195 | 1998,2001,3,28063,0
196 | 1998,2002,4,28346,0
197 | 1998,2003,5,28780,0
198 | 1998,2004,6,29024,0
199 | 1998,2005,7,29180,0
200 | 1998,2006,8,29250,0
201 | 1998,2007,9,29575,0
202 | 1998,2008,10,29660,0
203 | 1998,2009,11,29809,0
204 | 1998,2010,12,29875,0
205 | 1998,2011,13,30085,0
206 | 1998,2012,14,30138,0
207 | 1998,2013,15,30227,0
208 | 1998,2014,16,30300,0
209 | 1998,2015,17,30347,0
210 | 1998,2016,18,30469,0
211 | 1998,2017,19,30476,0
212 | 1999,1999,0,16789,0
213 | 1999,2000,1,25547,0
214 | 1999,2001,2,27099,0
215 | 1999,2002,3,27801,0
216 | 1999,2003,4,27919,0
217 | 1999,2004,5,28052,0
218 | 1999,2005,6,30020,0
219 | 1999,2006,7,30035,0
220 | 1999,2007,8,30456,0
221 | 1999,2008,9,30663,0
222 | 1999,2009,10,30750,0
223 | 1999,2010,11,30905,0
224 | 1999,2011,12,30973,0
225 | 1999,2012,13,31192,0
226 | 1999,2013,14,31247,0
227 | 1999,2014,15,31338,0
228 | 1999,2015,16,31415,0
229 | 1999,2016,17,31463,0
230 | 1999,2017,18,31590,0
231 | 1999,2018,19,31597,0
232 | 2000,2000,0,15538,0
233 | 2000,2001,1,23830,0
234 | 2000,2002,2,25202,0
235 | 2000,2003,3,26462,0
236 | 2000,2004,4,27056,0
237 | 2000,2005,5,27480,0
238 | 2000,2006,6,27564,0
239 | 2000,2007,7,27612,0
240 | 2000,2008,8,27873,0
241 | 2000,2009,9,28062,0
242 | 2000,2010,10,28143,0
243 | 2000,2011,11,28284,0
244 | 2000,2012,12,28347,0
245 | 2000,2013,13,28546,0
246 | 2000,2014,14,28597,0
247 | 2000,2015,15,28681,0
248 | 2000,2016,16,28751,0
249 | 2000,2017,17,28795,0
250 | 2000,2018,18,28911,0
251 | 2000,2019,19,28917,0
252 | 2001,2001,0,15113,0
253 | 2001,2002,1,23405,0
254 | 2001,2003,2,26822,0
255 | 2001,2004,3,27711,0
256 | 2001,2005,4,28080,0
257 | 2001,2006,5,29203,0
258 | 2001,2007,6,29647,0
259 | 2001,2008,7,29751,0
260 | 2001,2009,8,30032,0
261 | 2001,2010,9,30236,0
262 | 2001,2011,10,30323,0
263 | 2001,2012,11,30475,0
264 | 2001,2013,12,30542,0
265 | 2001,2014,13,30758,0
266 | 2001,2015,14,30812,0
267 | 2001,2016,15,30903,0
268 | 2001,2017,16,30978,0
269 | 2001,2018,17,31025,0
270 | 2001,2019,18,31150,0
271 | 2001,2020,19,31157,0
272 | 2002,2002,0,14543,0
273 | 2002,2003,1,22674,0
274 | 2002,2004,2,23603,0
275 | 2002,2005,3,24159,0
276 | 2002,2006,4,24242,0
277 | 2002,2007,5,24425,0
278 | 2002,2008,6,24767,0
279 | 2002,2009,7,24854,0
280 | 2002,2010,8,25089,0
281 | 2002,2011,9,25260,0
282 | 2002,2012,10,25332,0
283 | 2002,2013,11,25459,0
284 | 2002,2014,12,25515,0
285 | 2002,2015,13,25695,0
286 | 2002,2016,14,25741,0
287 | 2002,2017,15,25816,0
288 | 2002,2018,16,25879,0
289 | 2002,2019,17,25919,0
290 | 2002,2020,18,26023,0
291 | 2002,2021,19,26029,0
292 | 2003,2003,0,14590,0
293 | 2003,2004,1,22337,0
294 | 2003,2005,2,23442,0
295 | 2003,2006,3,24031,0
296 | 2003,2007,4,24665,0
297 | 2003,2008,5,24942,0
298 | 2003,2009,6,25292,0
299 | 2003,2010,7,25380,0
300 | 2003,2011,8,25621,0
301 | 2003,2012,9,25794,0
302 | 2003,2013,10,25868,0
303 | 2003,2014,11,25998,0
304 | 2003,2015,12,26056,0
305 | 2003,2016,13,26239,0
306 | 2003,2017,14,26286,0
307 | 2003,2018,15,26363,0
308 | 2003,2019,16,26427,0
309 | 2003,2020,17,26468,0
310 | 2003,2021,18,26574,0
311 | 2003,2022,19,26580,0
312 | 2004,2004,0,13976,0
313 | 2004,2005,1,21527,0
314 | 2004,2006,2,22615,0
315 | 2004,2007,3,23242,0
316 | 2004,2008,4,23653,0
317 | 2004,2009,5,23918,0
318 | 2004,2010,6,24254,0
319 | 2004,2011,7,24339,0
320 | 2004,2012,8,24569,0
321 | 2004,2013,9,24736,0
322 | 2004,2014,10,24806,0
323 | 2004,2015,11,24931,0
324 | 2004,2016,12,24986,0
325 | 2004,2017,13,25162,0
326 | 2004,2018,14,25207,0
327 | 2004,2019,15,25281,0
328 | 2004,2020,16,25342,0
329 | 2004,2021,17,25381,0
330 | 2004,2022,18,25483,0
331 | 2004,2023,19,25489,0
332 | 2005,2005,0,12932,0
333 | 2005,2006,1,20118,0
334 | 2005,2007,2,21309,0
335 | 2005,2008,3,21824,0
336 | 2005,2009,4,22209,0
337 | 2005,2010,5,22459,0
338 | 2005,2011,6,22774,0
339 | 2005,2012,7,22853,0
340 | 2005,2013,8,23070,0
341 | 2005,2014,9,23226,0
342 | 2005,2015,10,23293,0
343 | 2005,2016,11,23410,0
344 | 2005,2017,12,23462,0
345 | 2005,2018,13,23627,0
346 | 2005,2019,14,23669,0
347 | 2005,2020,15,23738,0
348 | 2005,2021,16,23796,0
349 | 2005,2022,17,23832,0
350 | 2005,2023,18,23928,0
351 | 2005,2024,19,23934,0
352 | 2006,2006,0,12538,0
353 | 2006,2007,1,20357,0
354 | 2006,2008,2,21435,0
355 | 2006,2009,3,21953,0
356 | 2006,2010,4,22341,0
357 | 2006,2011,5,22592,0
358 | 2006,2012,6,22909,0
359 | 2006,2013,7,22989,0
360 | 2006,2014,8,23206,0
361 | 2006,2015,9,23364,0
362 | 2006,2016,10,23431,0
363 | 2006,2017,11,23548,0
364 | 2006,2018,12,23600,0
365 | 2006,2019,13,23767,0
366 | 2006,2020,14,23809,0
367 | 2006,2021,15,23879,0
368 | 2006,2022,16,23937,0
369 | 2006,2023,17,23974,0
370 | 2006,2024,18,24070,0
371 | 2006,2025,19,24076,0
372 | 2007,2007,0,12888,0
373 | 2007,2008,1,19413,0
374 | 2007,2009,2,20441,0
375 | 2007,2010,3,20935,0
376 | 2007,2011,4,21304,0
377 | 2007,2012,5,21544,0
378 | 2007,2013,6,21846,0
379 | 2007,2014,7,21922,0
380 | 2007,2015,8,22130,0
381 | 2007,2016,9,22280,0
382 | 2007,2017,10,22344,0
383 | 2007,2018,11,22456,0
384 | 2007,2019,12,22506,0
385 | 2007,2020,13,22664,0
386 | 2007,2021,14,22704,0
387 | 2007,2022,15,22771,0
388 | 2007,2023,16,22826,0
389 | 2007,2024,17,22861,0
390 | 2007,2025,18,22953,0
391 | 2007,2026,19,22959,0
392 |
--------------------------------------------------------------------------------
/src/tryangle/utils/data/cas_train.csv:
--------------------------------------------------------------------------------
1 | origin,development,lag,claim,premium
2 | 2010/03/31,2010/03/31,0,2013.946441,25728.2402
3 | 2010/03/31,2010/06/30,1,3924.798392,25728.2402
4 | 2010/03/31,2010/09/30,2,6027.319135,25728.2402
5 | 2010/03/31,2010/12/31,3,6476.875283,25728.2402
6 | 2010/03/31,2011/03/31,4,5624.078779,25728.2402
7 | 2010/03/31,2011/06/30,5,5159.316543,25728.2402
8 | 2010/03/31,2011/09/30,6,5213.851529,25728.2402
9 | 2010/03/31,2011/12/31,7,6240.692643,25728.2402
10 | 2010/03/31,2012/03/31,8,6705.35025,25728.2402
11 | 2010/03/31,2012/06/30,9,6716.243297,25728.2402
12 | 2010/03/31,2012/09/30,10,7373.267224,25728.2402
13 | 2010/03/31,2012/12/31,11,7695.745579,25728.2402
14 | 2010/03/31,2013/03/31,12,9011.246614,25728.2402
15 | 2010/03/31,2013/06/30,13,9229.502811,25728.2402
16 | 2010/03/31,2013/09/30,14,8408.513538,25728.2402
17 | 2010/03/31,2013/12/31,15,8448.179574,25728.2402
18 | 2010/03/31,2014/03/31,16,8824.216376,25728.2402
19 | 2010/03/31,2014/06/30,17,9202.496891,25728.2402
20 | 2010/03/31,2014/09/30,18,9388.457588,25728.2402
21 | 2010/03/31,2014/12/31,19,9349.686712,25728.2402
22 | 2010/06/30,2010/06/30,0,2531.220834,25975.3502
23 | 2010/06/30,2010/09/30,1,4102.412015,25975.3502
24 | 2010/06/30,2010/12/31,2,3674.700088,25975.3502
25 | 2010/06/30,2011/03/31,3,3868.18245,25975.3502
26 | 2010/06/30,2011/06/30,4,4796.172364,25975.3502
27 | 2010/06/30,2011/09/30,5,6866.351106,25975.3502
28 | 2010/06/30,2011/12/31,6,6072.077117,25975.3502
29 | 2010/06/30,2012/03/31,7,6013.984744,25975.3502
30 | 2010/06/30,2012/06/30,8,5986.455679,25975.3502
31 | 2010/06/30,2012/09/30,9,5787.881369,25975.3502
32 | 2010/06/30,2012/12/31,10,5951.207315,25975.3502
33 | 2010/06/30,2013/03/31,11,5957.566436,25975.3502
34 | 2010/06/30,2013/06/30,12,6047.884556,25975.3502
35 | 2010/06/30,2013/09/30,13,6064.741458,25975.3502
36 | 2010/06/30,2013/12/31,14,5876.618428,25975.3502
37 | 2010/06/30,2014/03/31,15,5969.354642,25975.3502
38 | 2010/06/30,2014/06/30,16,5986.537057,25975.3502
39 | 2010/06/30,2014/09/30,17,5997.383602,25975.3502
40 | 2010/06/30,2014/12/31,18,5766.676548,25975.3502
41 | 2010/09/30,2010/09/30,0,2373.056588,24954.4902
42 | 2010/09/30,2010/12/31,1,4426.390053,24954.4902
43 | 2010/09/30,2011/03/31,2,7274.148638,24954.4902
44 | 2010/09/30,2011/06/30,3,6513.62333,24954.4902
45 | 2010/09/30,2011/09/30,4,6699.130635,24954.4902
46 | 2010/09/30,2011/12/31,5,7062.867711,24954.4902
47 | 2010/09/30,2012/03/31,6,7602.893111,24954.4902
48 | 2010/09/30,2012/06/30,7,7727.29705,24954.4902
49 | 2010/09/30,2012/09/30,8,7130.492953,24954.4902
50 | 2010/09/30,2012/12/31,9,7655.498271,24954.4902
51 | 2010/09/30,2013/03/31,10,7948.796747,24954.4902
52 | 2010/09/30,2013/06/30,11,8586.568929,24954.4902
53 | 2010/09/30,2013/09/30,12,9113.050679,24954.4902
54 | 2010/09/30,2013/12/31,13,7730.296416,24954.4902
55 | 2010/09/30,2014/03/31,14,7925.092455,24954.4902
56 | 2010/09/30,2014/06/30,15,8275.576519,24954.4902
57 | 2010/09/30,2014/09/30,16,8179.631681,24954.4902
58 | 2010/09/30,2014/12/31,17,7820.881922,24954.4902
59 | 2010/12/31,2010/12/31,0,3664.585946,24478.1902
60 | 2010/12/31,2011/03/31,1,6028.330549,24478.1902
61 | 2010/12/31,2011/06/30,2,5679.334543,24478.1902
62 | 2010/12/31,2011/09/30,3,5792.775683,24478.1902
63 | 2010/12/31,2011/12/31,4,5157.665729,24478.1902
64 | 2010/12/31,2012/03/31,5,5202.586468,24478.1902
65 | 2010/12/31,2012/06/30,6,4824.10832,24478.1902
66 | 2010/12/31,2012/09/30,7,4749.066041,24478.1902
67 | 2010/12/31,2012/12/31,8,5152.469153,24478.1902
68 | 2010/12/31,2013/03/31,9,5240.392431,24478.1902
69 | 2010/12/31,2013/06/30,10,5260.829972,24478.1902
70 | 2010/12/31,2013/09/30,11,5360.622834,24478.1902
71 | 2010/12/31,2013/12/31,12,5261.911138,24478.1902
72 | 2010/12/31,2014/03/31,13,5605.582689,24478.1902
73 | 2010/12/31,2014/06/30,14,5472.92468,24478.1902
74 | 2010/12/31,2014/09/30,15,5358.541878,24478.1902
75 | 2010/12/31,2014/12/31,16,6050.686289,24478.1902
76 | 2011/03/31,2011/03/31,0,3685.244371,23899.4402
77 | 2011/03/31,2011/06/30,1,6009.229935,23899.4402
78 | 2011/03/31,2011/09/30,2,6655.209685,23899.4402
79 | 2011/03/31,2011/12/31,3,5535.06271,23899.4402
80 | 2011/03/31,2012/03/31,4,6291.728368,23899.4402
81 | 2011/03/31,2012/06/30,5,6971.88694,23899.4402
82 | 2011/03/31,2012/09/30,6,6792.68063,23899.4402
83 | 2011/03/31,2012/12/31,7,6362.015838,23899.4402
84 | 2011/03/31,2013/03/31,8,6510.12407,23899.4402
85 | 2011/03/31,2013/06/30,9,6456.658626,23899.4402
86 | 2011/03/31,2013/09/30,10,6734.030235,23899.4402
87 | 2011/03/31,2013/12/31,11,6836.148187,23899.4402
88 | 2011/03/31,2014/03/31,12,7816.882767,23899.4402
89 | 2011/03/31,2014/06/30,13,8117.493651,23899.4402
90 | 2011/03/31,2014/09/30,14,8601.71689,23899.4402
91 | 2011/03/31,2014/12/31,15,8508.050641,23899.4402
92 | 2011/06/30,2011/06/30,0,5623.509132,21730.2502
93 | 2011/06/30,2011/09/30,1,9330.190833,21730.2502
94 | 2011/06/30,2011/12/31,2,8640.313384,21730.2502
95 | 2011/06/30,2012/03/31,3,7675.807932,21730.2502
96 | 2011/06/30,2012/06/30,4,7066.06471,21730.2502
97 | 2011/06/30,2012/09/30,5,6535.025784,21730.2502
98 | 2011/06/30,2012/12/31,6,7004.298695,21730.2502
99 | 2011/06/30,2013/03/31,7,6964.644285,21730.2502
100 | 2011/06/30,2013/06/30,8,7006.577283,21730.2502
101 | 2011/06/30,2013/09/30,9,7243.748086,21730.2502
102 | 2011/06/30,2013/12/31,10,7123.773443,21730.2502
103 | 2011/06/30,2014/03/31,11,7118.960507,21730.2502
104 | 2011/06/30,2014/06/30,12,7294.074659,21730.2502
105 | 2011/06/30,2014/09/30,13,7250.979116,21730.2502
106 | 2011/06/30,2014/12/31,14,6981.222177,21730.2502
107 | 2011/09/30,2011/09/30,0,6359.527992,15231.7602
108 | 2011/09/30,2011/12/31,1,8484.695112,15231.7602
109 | 2011/09/30,2012/03/31,2,9147.194626,15231.7602
110 | 2011/09/30,2012/06/30,3,6628.157263,15231.7602
111 | 2011/09/30,2012/09/30,4,6883.138256,15231.7602
112 | 2011/09/30,2012/12/31,5,6989.906388,15231.7602
113 | 2011/09/30,2013/03/31,6,7416.58365,15231.7602
114 | 2011/09/30,2013/06/30,7,7768.218634,15231.7602
115 | 2011/09/30,2013/09/30,8,8116.935629,15231.7602
116 | 2011/09/30,2013/12/31,9,7775.496165,15231.7602
117 | 2011/09/30,2014/03/31,10,7907.968167,15231.7602
118 | 2011/09/30,2014/06/30,11,7946.192646,15231.7602
119 | 2011/09/30,2014/09/30,12,7905.085056,15231.7602
120 | 2011/09/30,2014/12/31,13,7503.623394,15231.7602
121 | 2011/12/31,2011/12/31,0,3654.86707,11990.0202
122 | 2011/12/31,2012/03/31,1,4337.501863,11990.0202
123 | 2011/12/31,2012/06/30,2,3999.759293,11990.0202
124 | 2011/12/31,2012/09/30,3,4567.848528,11990.0202
125 | 2011/12/31,2012/12/31,4,6659.162338,11990.0202
126 | 2011/12/31,2013/03/31,5,6570.506657,11990.0202
127 | 2011/12/31,2013/06/30,6,6598.896005,11990.0202
128 | 2011/12/31,2013/09/30,7,6949.194062,11990.0202
129 | 2011/12/31,2013/12/31,8,7302.991379,11990.0202
130 | 2011/12/31,2014/03/31,9,7384.113769,11990.0202
131 | 2011/12/31,2014/06/30,10,8192.291796,11990.0202
132 | 2011/12/31,2014/09/30,11,8634.616914,11990.0202
133 | 2011/12/31,2014/12/31,12,8644.114906,11990.0202
134 | 2012/03/31,2012/03/31,0,1202.803924,11731.1402
135 | 2012/03/31,2012/06/30,1,2897.120245,11731.1402
136 | 2012/03/31,2012/09/30,2,3288.560769,11731.1402
137 | 2012/03/31,2012/12/31,3,2418.360967,11731.1402
138 | 2012/03/31,2013/03/31,4,2197.326288,11731.1402
139 | 2012/03/31,2013/06/30,5,3144.428441,11731.1402
140 | 2012/03/31,2013/09/30,6,3153.228906,11731.1402
141 | 2012/03/31,2013/12/31,7,3073.071429,11731.1402
142 | 2012/03/31,2014/03/31,8,3108.656931,11731.1402
143 | 2012/03/31,2014/06/30,9,2366.918351,11731.1402
144 | 2012/03/31,2014/09/30,10,1991.509322,11731.1402
145 | 2012/03/31,2014/12/31,11,2082.80398,11731.1402
146 | 2012/06/30,2012/06/30,0,1110.253717,11502.8702
147 | 2012/06/30,2012/09/30,1,2110.96082,11502.8702
148 | 2012/06/30,2012/12/31,2,3328.017546,11502.8702
149 | 2012/06/30,2013/03/31,3,5474.017472,11502.8702
150 | 2012/06/30,2013/06/30,4,5593.375966,11502.8702
151 | 2012/06/30,2013/09/30,5,5660.38506,11502.8702
152 | 2012/06/30,2013/12/31,6,4710.016155,11502.8702
153 | 2012/06/30,2014/03/31,7,4873.516482,11502.8702
154 | 2012/06/30,2014/06/30,8,4568.569306,11502.8702
155 | 2012/06/30,2014/09/30,9,4547.131976,11502.8702
156 | 2012/06/30,2014/12/31,10,4600.667173,11502.8702
157 | 2012/09/30,2012/09/30,0,775.7081453,13316.5402
158 | 2012/09/30,2012/12/31,1,3290.351088,13316.5402
159 | 2012/09/30,2013/03/31,2,6314.549126,13316.5402
160 | 2012/09/30,2013/06/30,3,7099.383249,13316.5402
161 | 2012/09/30,2013/09/30,4,7206.38389,13316.5402
162 | 2012/09/30,2013/12/31,5,6951.123887,13316.5402
163 | 2012/09/30,2014/03/31,6,6910.562692,13316.5402
164 | 2012/09/30,2014/06/30,7,6848.320033,13316.5402
165 | 2012/09/30,2014/09/30,8,6906.168272,13316.5402
166 | 2012/09/30,2014/12/31,9,6825.708533,13316.5402
167 | 2012/12/31,2012/12/31,0,1857.653892,14269.7402
168 | 2012/12/31,2013/03/31,1,3064.352342,14269.7402
169 | 2012/12/31,2013/06/30,2,3964.894568,14269.7402
170 | 2012/12/31,2013/09/30,3,3906.174421,14269.7402
171 | 2012/12/31,2013/12/31,4,4058.235306,14269.7402
172 | 2012/12/31,2014/03/31,5,4269.934748,14269.7402
173 | 2012/12/31,2014/06/30,6,4018.813405,14269.7402
174 | 2012/12/31,2014/09/30,7,3867.275665,14269.7402
175 | 2012/12/31,2014/12/31,8,5107.385658,14269.7402
176 | 2013/03/31,2013/03/31,0,1607.706719,15193.1202
177 | 2013/03/31,2013/06/30,1,4000.340565,15193.1202
178 | 2013/03/31,2013/09/30,2,4989.08508,15193.1202
179 | 2013/03/31,2013/12/31,3,4800.183144,15193.1202
180 | 2013/03/31,2014/03/31,4,4794.533176,15193.1202
181 | 2013/03/31,2014/06/30,5,5481.643767,15193.1202
182 | 2013/03/31,2014/09/30,6,4777.978535,15193.1202
183 | 2013/03/31,2014/12/31,7,4847.149962,15193.1202
184 | 2013/06/30,2013/06/30,0,3120.317258,15076.7802
185 | 2013/06/30,2013/09/30,1,3906.220923,15076.7802
186 | 2013/06/30,2013/12/31,2,7001.938728,15076.7802
187 | 2013/06/30,2014/03/31,3,9182.175605,15076.7802
188 | 2013/06/30,2014/06/30,4,9679.802988,15076.7802
189 | 2013/06/30,2014/09/30,5,7915.826971,15076.7802
190 | 2013/06/30,2014/12/31,6,10125.44136,15076.7802
191 | 2013/09/30,2013/09/30,0,1186.749178,18804.4802
192 | 2013/09/30,2013/12/31,1,1948.716041,18804.4802
193 | 2013/09/30,2014/03/31,2,3061.969125,18804.4802
194 | 2013/09/30,2014/06/30,3,4515.324745,18804.4802
195 | 2013/09/30,2014/09/30,4,4628.405496,18804.4802
196 | 2013/09/30,2014/12/31,5,4755.134526,18804.4802
197 | 2013/12/31,2013/12/31,0,508.1251647,17929.9502
198 | 2013/12/31,2014/03/31,1,1844.156745,17929.9502
199 | 2013/12/31,2014/06/30,2,4444.653635,17929.9502
200 | 2013/12/31,2014/09/30,3,6455.914597,17929.9502
201 | 2013/12/31,2014/12/31,4,7419.199377,17929.9502
202 | 2014/03/31,2014/03/31,0,631.9129553,18824.7102
203 | 2014/03/31,2014/06/30,1,1950.552862,18824.7102
204 | 2014/03/31,2014/09/30,2,2235.318258,18824.7102
205 | 2014/03/31,2014/12/31,3,4024.533126,18824.7102
206 | 2014/06/30,2014/06/30,0,575.9015377,20181.3402
207 | 2014/06/30,2014/09/30,1,3531.009527,20181.3402
208 | 2014/06/30,2014/12/31,2,8147.766322,20181.3402
209 | 2014/09/30,2014/09/30,0,1548.602932,20891.3602
210 | 2014/09/30,2014/12/31,1,4806.751524,20891.3602
211 | 2014/12/31,2014/12/31,0,1877.010266,23653.9902
212 |
--------------------------------------------------------------------------------
/src/tryangle/utils/data/sme_train.csv:
--------------------------------------------------------------------------------
1 | origin,development,lag,claim,premium
2 | 2010/03/31,2010/03/31,0,15885.64381,51346.66641
3 | 2010/03/31,2010/06/30,1,25177.51136,51346.66641
4 | 2010/03/31,2010/09/30,2,26571.78973,51346.66641
5 | 2010/03/31,2010/12/31,3,25520.48766,51346.66641
6 | 2010/03/31,2011/03/31,4,25047.47172,51346.66641
7 | 2010/03/31,2011/06/30,5,25025.26462,51346.66641
8 | 2010/03/31,2011/09/30,6,24961.98862,51346.66641
9 | 2010/03/31,2011/12/31,7,24447.97496,51346.66641
10 | 2010/03/31,2012/03/31,8,24411.81725,51346.66641
11 | 2010/03/31,2012/06/30,9,24305.19471,51346.66641
12 | 2010/03/31,2012/09/30,10,24305.07608,51346.66641
13 | 2010/03/31,2012/12/31,11,24285.31271,51346.66641
14 | 2010/03/31,2013/03/31,12,24201.01589,51346.66641
15 | 2010/03/31,2013/06/30,13,24159.40131,51346.66641
16 | 2010/03/31,2013/09/30,14,24170.83702,51346.66641
17 | 2010/03/31,2013/12/31,15,24108.41514,51346.66641
18 | 2010/03/31,2014/03/31,16,24096.95571,51346.66641
19 | 2010/03/31,2014/06/30,17,24096.95571,51346.66641
20 | 2010/03/31,2014/09/30,18,24096.95571,51346.66641
21 | 2010/03/31,2014/12/31,19,24096.95571,51346.66641
22 | 2010/06/30,2010/06/30,0,18399.93339,53877.27641
23 | 2010/06/30,2010/09/30,1,24209.50963,53877.27641
24 | 2010/06/30,2010/12/31,2,22952.86308,53877.27641
25 | 2010/06/30,2011/03/31,3,22781.44611,53877.27641
26 | 2010/06/30,2011/06/30,4,22709.81873,53877.27641
27 | 2010/06/30,2011/09/30,5,22939.48188,53877.27641
28 | 2010/06/30,2011/12/31,6,22276.51933,53877.27641
29 | 2010/06/30,2012/03/31,7,22394.64875,53877.27641
30 | 2010/06/30,2012/06/30,8,22331.79982,53877.27641
31 | 2010/06/30,2012/09/30,9,22614.84542,53877.27641
32 | 2010/06/30,2012/12/31,10,22614.84542,53877.27641
33 | 2010/06/30,2013/03/31,11,22614.75052,53877.27641
34 | 2010/06/30,2013/06/30,12,22614.75052,53877.27641
35 | 2010/06/30,2013/09/30,13,22614.75052,53877.27641
36 | 2010/06/30,2013/12/31,14,22593.94322,53877.27641
37 | 2010/06/30,2014/03/31,15,22590.24204,53877.27641
38 | 2010/06/30,2014/06/30,16,22592.40107,53877.27641
39 | 2010/06/30,2014/09/30,17,22592.40107,53877.27641
40 | 2010/06/30,2014/12/31,18,22592.40107,53877.27641
41 | 2010/09/30,2010/09/30,0,15765.26046,54577.09641
42 | 2010/09/30,2010/12/31,1,18859.94774,54577.09641
43 | 2010/09/30,2011/03/31,2,17972.3044,54577.09641
44 | 2010/09/30,2011/06/30,3,18029.22195,54577.09641
45 | 2010/09/30,2011/09/30,4,18099.71051,54577.09641
46 | 2010/09/30,2011/12/31,5,17914.79371,54577.09641
47 | 2010/09/30,2012/03/31,6,17918.92195,54577.09641
48 | 2010/09/30,2012/06/30,7,17802.40586,54577.09641
49 | 2010/09/30,2012/09/30,8,17854.41223,54577.09641
50 | 2010/09/30,2012/12/31,9,17854.3885,54577.09641
51 | 2010/09/30,2013/03/31,10,17867.88833,54577.09641
52 | 2010/09/30,2013/06/30,11,17843.83064,54577.09641
53 | 2010/09/30,2013/09/30,12,17828.90728,54577.09641
54 | 2010/09/30,2013/12/31,13,17828.90728,54577.09641
55 | 2010/09/30,2014/03/31,14,17762.30971,54577.09641
56 | 2010/09/30,2014/06/30,15,17762.30971,54577.09641
57 | 2010/09/30,2014/09/30,16,17754.29048,54577.09641
58 | 2010/09/30,2014/12/31,17,17754.29048,54577.09641
59 | 2010/12/31,2010/12/31,0,18049.1514,55527.48641
60 | 2010/12/31,2011/03/31,1,24586.08129,55527.48641
61 | 2010/12/31,2011/06/30,2,24557.61065,55527.48641
62 | 2010/12/31,2011/09/30,3,24341.73203,55527.48641
63 | 2010/12/31,2011/12/31,4,23850.18645,55527.48641
64 | 2010/12/31,2012/03/31,5,23923.40344,55527.48641
65 | 2010/12/31,2012/06/30,6,23912.37107,55527.48641
66 | 2010/12/31,2012/09/30,7,23959.22899,55527.48641
67 | 2010/12/31,2012/12/31,8,23949.21682,55527.48641
68 | 2010/12/31,2013/03/31,9,23823.18679,55527.48641
69 | 2010/12/31,2013/06/30,10,23921.38677,55527.48641
70 | 2010/12/31,2013/09/30,11,23836.0223,55527.48641
71 | 2010/12/31,2013/12/31,12,23862.87961,55527.48641
72 | 2010/12/31,2014/03/31,13,23862.85588,55527.48641
73 | 2010/12/31,2014/06/30,14,23853.15214,55527.48641
74 | 2010/12/31,2014/09/30,15,23829.94857,55527.48641
75 | 2010/12/31,2014/12/31,16,23829.94857,55527.48641
76 | 2011/03/31,2011/03/31,0,22716.20089,56767.61641
77 | 2011/03/31,2011/06/30,1,28799.4986,56767.61641
78 | 2011/03/31,2011/09/30,2,28139.21703,56767.61641
79 | 2011/03/31,2011/12/31,3,26890.42363,56767.61641
80 | 2011/03/31,2012/03/31,4,27203.1736,56767.61641
81 | 2011/03/31,2012/06/30,5,27014.27091,56767.61641
82 | 2011/03/31,2012/09/30,6,26813.00722,56767.61641
83 | 2011/03/31,2012/12/31,7,26542.22772,56767.61641
84 | 2011/03/31,2013/03/31,8,26363.69308,56767.61641
85 | 2011/03/31,2013/06/30,9,26522.72533,56767.61641
86 | 2011/03/31,2013/09/30,10,26259.32447,56767.61641
87 | 2011/03/31,2013/12/31,11,26256.54858,56767.61641
88 | 2011/03/31,2014/03/31,12,26050.51605,56767.61641
89 | 2011/03/31,2014/06/30,13,26000.57381,56767.61641
90 | 2011/03/31,2014/09/30,14,26000.57381,56767.61641
91 | 2011/03/31,2014/12/31,15,26000.57381,56767.61641
92 | 2011/06/30,2011/06/30,0,17629.56535,57243.72641
93 | 2011/06/30,2011/09/30,1,24164.4074,57243.72641
94 | 2011/06/30,2011/12/31,2,23772.50905,57243.72641
95 | 2011/06/30,2012/03/31,3,23060.50582,57243.72641
96 | 2011/06/30,2012/06/30,4,22775.34865,57243.72641
97 | 2011/06/30,2012/09/30,5,22658.66648,57243.72641
98 | 2011/06/30,2012/12/31,6,22348.52632,57243.72641
99 | 2011/06/30,2013/03/31,7,22241.50044,57243.72641
100 | 2011/06/30,2013/06/30,8,22254.90537,57243.72641
101 | 2011/06/30,2013/09/30,9,22228.85473,57243.72641
102 | 2011/06/30,2013/12/31,10,22228.85473,57243.72641
103 | 2011/06/30,2014/03/31,11,22197.63193,57243.72641
104 | 2011/06/30,2014/06/30,12,22114.45021,57243.72641
105 | 2011/06/30,2014/09/30,13,22062.42012,57243.72641
106 | 2011/06/30,2014/12/31,14,22062.42012,57243.72641
107 | 2011/09/30,2011/09/30,0,20852.10953,58405.12641
108 | 2011/09/30,2011/12/31,1,28044.43353,58405.12641
109 | 2011/09/30,2012/03/31,2,27322.34695,58405.12641
110 | 2011/09/30,2012/06/30,3,27051.21156,58405.12641
111 | 2011/09/30,2012/09/30,4,26749.75495,58405.12641
112 | 2011/09/30,2012/12/31,5,26292.91982,58405.12641
113 | 2011/09/30,2013/03/31,6,26136.59229,58405.12641
114 | 2011/09/30,2013/06/30,7,26133.00973,58405.12641
115 | 2011/09/30,2013/09/30,8,26309.78867,58405.12641
116 | 2011/09/30,2013/12/31,9,26223.90225,58405.12641
117 | 2011/09/30,2014/03/31,10,25942.89704,58405.12641
118 | 2011/09/30,2014/06/30,11,25952.4347,58405.12641
119 | 2011/09/30,2014/09/30,12,25941.99547,58405.12641
120 | 2011/09/30,2014/12/31,13,25940.09743,58405.12641
121 | 2011/12/31,2011/12/31,0,21489.49596,59911.59641
122 | 2011/12/31,2012/03/31,1,32918.53575,59911.59641
123 | 2011/12/31,2012/06/30,2,32872.43704,59911.59641
124 | 2011/12/31,2012/09/30,3,32830.06324,59911.59641
125 | 2011/12/31,2012/12/31,4,32575.06122,59911.59641
126 | 2011/12/31,2013/03/31,5,32552.94902,59911.59641
127 | 2011/12/31,2013/06/30,6,32536.26997,59911.59641
128 | 2011/12/31,2013/09/30,7,32443.52686,59911.59641
129 | 2011/12/31,2013/12/31,8,32453.46786,59911.59641
130 | 2011/12/31,2014/03/31,9,32324.49587,59911.59641
131 | 2011/12/31,2014/06/30,10,32324.49587,59911.59641
132 | 2011/12/31,2014/09/30,11,32495.50951,59911.59641
133 | 2011/12/31,2014/12/31,12,32474.15653,59911.59641
134 | 2012/03/31,2012/03/31,0,18254.16372,60339.49641
135 | 2012/03/31,2012/06/30,1,29871.29953,60339.49641
136 | 2012/03/31,2012/09/30,2,30149.22042,60339.49641
137 | 2012/03/31,2012/12/31,3,29904.39665,60339.49641
138 | 2012/03/31,2013/03/31,4,30122.22077,60339.49641
139 | 2012/03/31,2013/06/30,5,30281.72752,60339.49641
140 | 2012/03/31,2013/09/30,6,30003.61683,60339.49641
141 | 2012/03/31,2013/12/31,7,30047.31926,60339.49641
142 | 2012/03/31,2014/03/31,8,29792.98155,60339.49641
143 | 2012/03/31,2014/06/30,9,29747.97422,60339.49641
144 | 2012/03/31,2014/09/30,10,29722.30319,60339.49641
145 | 2012/03/31,2014/12/31,11,29755.30541,60339.49641
146 | 2012/06/30,2012/06/30,0,21811.61752,61308.49641
147 | 2012/06/30,2012/09/30,1,29825.69906,61308.49641
148 | 2012/06/30,2012/12/31,2,28046.97216,61308.49641
149 | 2012/06/30,2013/03/31,3,27959.59103,61308.49641
150 | 2012/06/30,2013/06/30,4,28009.27229,61308.49641
151 | 2012/06/30,2013/09/30,5,27812.51645,61308.49641
152 | 2012/06/30,2013/12/31,6,27604.58588,61308.49641
153 | 2012/06/30,2014/03/31,7,27430.53538,61308.49641
154 | 2012/06/30,2014/06/30,8,27502.7559,61308.49641
155 | 2012/06/30,2014/09/30,9,27206.96969,61308.49641
156 | 2012/06/30,2014/12/31,10,27183.78984,61308.49641
157 | 2012/09/30,2012/09/30,0,25062.3239,60262.30641
158 | 2012/09/30,2012/12/31,1,35858.55629,60262.30641
159 | 2012/09/30,2013/03/31,2,36143.49993,60262.30641
160 | 2012/09/30,2013/06/30,3,35174.40683,60262.30641
161 | 2012/09/30,2013/09/30,4,34845.02526,60262.30641
162 | 2012/09/30,2013/12/31,5,34032.33087,60262.30641
163 | 2012/09/30,2014/03/31,6,33252.09301,60262.30641
164 | 2012/09/30,2014/06/30,7,33128.10338,60262.30641
165 | 2012/09/30,2014/09/30,8,32078.79425,60262.30641
166 | 2012/09/30,2014/12/31,9,32282.07462,60262.30641
167 | 2012/12/31,2012/12/31,0,27478.65076,60512.84641
168 | 2012/12/31,2013/03/31,1,41905.36413,60512.84641
169 | 2012/12/31,2013/06/30,2,42866.65153,60512.84641
170 | 2012/12/31,2013/09/30,3,42488.20556,60512.84641
171 | 2012/12/31,2013/12/31,4,42368.36789,60512.84641
172 | 2012/12/31,2014/03/31,5,41576.12491,60512.84641
173 | 2012/12/31,2014/06/30,6,41451.42351,60512.84641
174 | 2012/12/31,2014/09/30,7,40987.37582,60512.84641
175 | 2012/12/31,2014/12/31,8,41403.85382,60512.84641
176 | 2013/03/31,2013/03/31,0,26771.0842,62668.15641
177 | 2013/03/31,2013/06/30,1,40483.56414,62668.15641
178 | 2013/03/31,2013/09/30,2,39967.65244,62668.15641
179 | 2013/03/31,2013/12/31,3,40057.5722,62668.15641
180 | 2013/03/31,2014/03/31,4,40010.85663,62668.15641
181 | 2013/03/31,2014/06/30,5,38822.58706,62668.15641
182 | 2013/03/31,2014/09/30,6,38480.74959,62668.15641
183 | 2013/03/31,2014/12/31,7,38506.08846,62668.15641
184 | 2013/06/30,2013/06/30,0,20361.60787,63109.32641
185 | 2013/06/30,2013/09/30,1,26804.96426,63109.32641
186 | 2013/06/30,2013/12/31,2,26388.29646,63109.32641
187 | 2013/06/30,2014/03/31,3,26454.27717,63109.32641
188 | 2013/06/30,2014/06/30,4,26380.03998,63109.32641
189 | 2013/06/30,2014/09/30,5,26321.22438,63109.32641
190 | 2013/06/30,2014/12/31,6,26310.42926,63109.32641
191 | 2013/09/30,2013/09/30,0,19766.45289,62933.52641
192 | 2013/09/30,2013/12/31,1,29064.96359,62933.52641
193 | 2013/09/30,2014/03/31,2,28266.90785,62933.52641
194 | 2013/09/30,2014/06/30,3,27855.69692,62933.52641
195 | 2013/09/30,2014/09/30,4,27475.28173,62933.52641
196 | 2013/09/30,2014/12/31,5,27402.4918,62933.52641
197 | 2013/12/31,2013/12/31,0,27034.74604,63694.44641
198 | 2013/12/31,2014/03/31,1,43552.72275,63694.44641
199 | 2013/12/31,2014/06/30,2,45623.39232,63694.44641
200 | 2013/12/31,2014/09/30,3,45858.20392,63694.44641
201 | 2013/12/31,2014/12/31,4,45471.02695,63694.44641
202 | 2014/03/31,2014/03/31,0,19600.13691,64467.46641
203 | 2014/03/31,2014/06/30,1,35431.71023,64467.46641
204 | 2014/03/31,2014/09/30,2,37810.95408,64467.46641
205 | 2014/03/31,2014/12/31,3,38378.89588,64467.46641
206 | 2014/06/30,2014/06/30,0,22220.45589,66842.73641
207 | 2014/06/30,2014/09/30,1,35361.36403,66842.73641
208 | 2014/06/30,2014/12/31,2,38685.95172,66842.73641
209 | 2014/09/30,2014/09/30,0,22583.36164,68593.77641
210 | 2014/09/30,2014/12/31,1,34819.30679,68593.77641
211 | 2014/12/31,2014/12/31,0,25472.84679,69620.50641
212 |
--------------------------------------------------------------------------------
/src/tryangle/ensemble/base.py:
--------------------------------------------------------------------------------
1 | # This Source Code Form is subject to the terms of the Mozilla Public
2 | # License, v. 2.0. If a copy of the MPL was not distributed with this
3 | # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 |
5 | import numpy as np
6 | from chainladder.workflow.voting import _BaseTriangleEnsemble
7 | from sklearn.base import clone
8 | from sklearn.ensemble._base import _fit_single_estimator
9 | from sklearn.utils.validation import _deprecate_positional_args
10 | from tryangle.ensemble.optimizers import Adam
11 | from tryangle.metrics.base import get_expected
12 | from tryangle.ensemble.losses import LOSS_FUNCTIONS
13 |
14 |
15 | class AutoEnsemble(_BaseTriangleEnsemble):
16 | """Automated ensembling of chainladder methods
17 |
18 | `AutoEnsemble` uses a neural network to find optimal weights
19 | to ensemble multiple chainladder methods.
20 |
21 | Read more in the :ref:`User Guide `
22 |
23 | .. versionadded:: 0.1.0
24 |
25 | Parameters
26 | ----------
27 | estimators : list of (str, estimator) tuples
28 | Invoking the ``fit`` method on the ``AutoEnsemble`` will fit clones
29 | of those original estimators across the cv folds of the triangle and
30 | store the expected incremental claims for the next diagonal for each
31 | of the folds.
32 |
33 | cv : `TriangleSplit` cross-validation generator
34 | Determines the number of cross-validation folds
35 | over which to fit. Must be an instance of `TriangleSplit`
36 |
37 | Refer :ref:`User Guide `
38 |
39 | max_iter : int, default=1000
40 | Maximum number of iterations (or epochs) used to train the neural
41 | network. Currently the optimizers use all iterations.
42 |
43 | optimizer : optimizer object, default=Adam()
44 | The optimization method to find optimal weights and biases.
45 |
46 | initial_weight : ndarray of shape (1, num_estimators), default=None
47 | Force the initial weights instead of using a random initialization
48 |
49 | initial_bias : ndarray of shape (1, num_estimators), default=None
50 | Force the initial biases instead of using a random initialization
51 |
52 | weight_function : 'linear', 'poly(n)', or None, default='linear'
53 | Specify a function to constrain the voting weights.
54 | ``poly(n)`` will fit an n-term polynomial:
55 | t^n * w + t^(n-1) * w + ... + t^(2) * w + t * w + b
56 | where t is the origin period, w is the weight, and b is the bias
57 | ``linear`` is equivalent to ``poly(1)``
58 | ``None`` will not constrain the weights meaning each origin period
59 | will have its own vector of weights.
60 |
61 | random_state : int or None, default=None
62 | Specify the seed for random weight and bias initialization.
63 |
64 | n_jobs : int, default=None
65 | Number of jobs to run in parallel
66 | ``None`` means 1.
67 | ``-1`` means using all processors.
68 | Currently only the compilation step is run in parallel. Optimization
69 | is not.
70 |
71 | verbose : int, default=False
72 | Controls the verbosity: the higher, the more messages.
73 |
74 | dropout : float, default=False
75 | Randomly sets incremental claim amounts equal to 0 equivalently for
76 | actual and expected. That is, the same incremental claims set to
77 | zero for actual are set to zero for expected. Parameter is given as
78 | a proportion of number of incremental claims data points.
79 |
80 | broad_dropout : float, default=False
81 | Randomly sets entire folds to zero equivalently for actual and expected.
82 | Parameter is given as a proportion of the number of folds and rounded to
83 | the nearest integer.
84 |
85 | Attributes
86 | ----------
87 |
88 | actual_ : ndarray
89 | The actual incremental claims for each fold.
90 |
91 | expected_ : ndarray
92 | The expected incremental claims for each estimator for each fold.
93 |
94 | weights_ : ndarray
95 | The optimal weights found to ensemble the estimators.
96 |
97 | Notes
98 | -----
99 |
100 | ``AutoEnsemble`` is still experimental and may change with future versions.
101 | """
102 |
103 | @_deprecate_positional_args
104 | def __init__(
105 | self,
106 | estimators,
107 | cv,
108 | max_iter=1000,
109 | optimizer=Adam(),
110 | initial_weight=None,
111 | initial_bias=None,
112 | weight_function="linear",
113 | loss="mse",
114 | random_state=None,
115 | n_jobs=None,
116 | verbose=False,
117 | dropout=False,
118 | broad_dropout=False,
119 | ):
120 | self.estimators = estimators
121 | self.cv = cv
122 | self.max_iter = max_iter
123 | self.optimizer = optimizer
124 | self.initial_weight = initial_weight
125 | self.initial_bias = initial_bias
126 | self.weight_function = weight_function
127 | self.loss = loss
128 | self.random_state = random_state
129 | self.n_jobs = n_jobs
130 | self.verbose = verbose
131 | self.dropout = dropout
132 | self.broad_dropout = broad_dropout
133 |
134 | def _log_message(self, name, idx, total):
135 | if self.verbose < 2:
136 | return None
137 | return "(%d of %d) Processing %s" % (idx, total, name)
138 |
139 | def initialize_weights(self):
140 | if self.weight_function is None:
141 | weight_dim = self.origin_dim
142 | elif self.weight_function == "linear":
143 | weight_dim = 1
144 | elif "poly" in self.weight_function:
145 | self.weight_polynomial = int(
146 | self.weight_function[
147 | self.weight_function.find("(") + 1 : self.weight_function.find(")")
148 | ]
149 | )
150 | weight_dim = 1
151 | else:
152 | raise Exception(
153 | "Unknown weight function provided. Options are None, linear, or poly(n)."
154 | )
155 |
156 | if self.initial_weight is None:
157 | np.random.seed(self.random_state)
158 | self.weights = np.random.normal(
159 | 0,
160 | np.sqrt(2 / (2 * len(self.estimators))),
161 | size=(weight_dim, len(self.estimators)),
162 | )
163 | else:
164 | self.weights = self.initial_weight
165 | if self.initial_bias is None:
166 | np.random.seed(self.random_state)
167 | self.biases = np.zeros((weight_dim, len(self.estimators)))
168 | else:
169 | self.biases = self.initial_bias
170 |
171 | def preprocess(self, X, y=None, sample_weight=None):
172 | """
173 | In order to find optimal weights, the actual incremental claims
174 | and expected incremental claims for each estimator is required.
175 | This method also returns the `t` array.
176 | """
177 |
178 | names, clfs = self._validate_estimators()
179 |
180 | actual = X.latest_diagonal.to_frame().fillna(0).to_numpy()[:-1]
181 | actual = actual[np.newaxis, ...]
182 | expected = np.array(
183 | [
184 | get_expected(
185 | _fit_single_estimator(
186 | clone(clf),
187 | X,
188 | X,
189 | sample_weight=None,
190 | message_clsname=f"Preprocessing - {names[idx]}_expected",
191 | message=self._log_message(names[idx], idx + 1, len(clfs)),
192 | ),
193 | X,
194 | )
195 | for idx, clf in enumerate(clfs)
196 | ]
197 | )
198 |
199 | t = (
200 | np.arange(1, actual.shape[1] + 1).reshape(-1, 1)[np.newaxis, ...]
201 | / actual.shape[1]
202 | )
203 |
204 | return actual, expected, t
205 |
206 | def compile(self, X, y=None, sample_weight=None):
207 | """
208 | Obtain the actual, expected, and t, arrays for each estimator
209 | for each fold and reshape for input to the neural network.
210 | """
211 | # Fit individual estimators
212 | if self.verbose > 1:
213 | print("\n[Compiling]\n")
214 |
215 | names, clfs = self._validate_estimators()
216 |
217 | self.actual_ = []
218 | self.expected_ = []
219 |
220 | # Preprocessing for each fold
221 | for fold, (train, _) in enumerate(self.cv.split(X)):
222 |
223 | zeros_to_pad = self.cv.n_splits - fold
224 |
225 | fold_actual, fold_expected, _ = self.preprocess(X[train])
226 |
227 | # Pad actuals to have same shape
228 | fold_actual = np.pad(
229 | fold_actual,
230 | [
231 | [0, 0],
232 | [zeros_to_pad, 0],
233 | [0, 0],
234 | ],
235 | )
236 |
237 | self.actual_.append(fold_actual)
238 |
239 | # Pad expecteds to have same shape
240 | fold_expected = np.pad(
241 | fold_expected,
242 | [
243 | [0, 0],
244 | [zeros_to_pad, 0],
245 | [0, 0],
246 | ],
247 | )
248 |
249 | self.expected_.append(fold_expected)
250 |
251 | self.actual_ = np.concatenate(self.actual_, axis=0)
252 | self.expected_ = np.concatenate(self.expected_, axis=2).T
253 | self.t_ = (
254 | np.repeat(
255 | np.arange(1, self.actual_.shape[1] + 1).reshape(-1, 1)[np.newaxis, ...],
256 | self.cv.n_splits,
257 | axis=0,
258 | )
259 | / self.actual_.shape[1]
260 | )
261 | self._output = np.zeros(self.actual_.shape)
262 | self.origin_dim = self.actual_.shape[1]
263 |
264 | if self.verbose:
265 | print()
266 |
267 | return self
268 |
269 | def _softmax(self, x):
270 | return np.exp(x) / np.exp(x).sum(axis=2, keepdims=True)
271 |
272 | def _softmax_gradient(self, x):
273 | identity = np.repeat(
274 | np.repeat(np.eye(x.shape[2])[np.newaxis, ...], x.shape[1], axis=0)[
275 | np.newaxis, ...
276 | ],
277 | x.shape[0],
278 | axis=0,
279 | )
280 | lhs_jacobian = identity * self._softmax(x)[..., np.newaxis]
281 | rhs_jacobian = np.einsum("fij,kif->fijk", self._softmax(x), self._softmax(x).T)
282 | return lhs_jacobian - rhs_jacobian
283 |
284 | def dense(self, t):
285 | if self.weight_function is None:
286 | return t * self.weights + self.biases
287 | elif self.weight_function == "linear":
288 | return np.matmul(t, self.weights) + self.biases
289 | elif self.weight_function[:4] == "poly":
290 | return (
291 | sum(
292 | [t ** (n + 1) * self.weights for n in range(self.weight_polynomial)]
293 | )
294 | + self.biases
295 | )
296 | else:
297 | raise Exception(
298 | "Unknown weight function provided. Options are None, linear, or poly(n)."
299 | )
300 |
301 | def _dense_gradient(self, t):
302 | if self.weight_function is None:
303 | return t
304 | elif self.weight_function == "linear":
305 | return t
306 | elif self.weight_function[:4] == "poly":
307 | return sum([(n + 1) * t ** (n) for n in range(self.weight_polynomial)])
308 | else:
309 | raise Exception(
310 | "Unknown weight function provided. Options are None, linear, or poly(n)."
311 | )
312 |
313 | def activation(self, x):
314 | return self._softmax(x)
315 |
316 | def output(self, expected, activation):
317 | return (expected * activation).sum(axis=2, keepdims=True)
318 |
319 | def compute_loss(self, output, actual):
320 | return self.Loss()._loss(output, actual)
321 |
322 | def forward_pass(self, actual, expected, t, text_file=None):
323 | if self.verbose > 2:
324 | print("Starting weights: ", self.weights, " ", self.biases, file=text_file)
325 | self._dense = self.dense(t)
326 | self._activation = self.activation(self._dense)
327 | self._output = self.output(expected, self._activation)
328 | self._compute_loss = self.compute_loss(self._output, actual)
329 | if self.verbose > 2:
330 | print("Loss: ", self._compute_loss, file=text_file)
331 |
332 | return self
333 |
334 | def backward_pass(self, actual, expected, t, epoch, text_file):
335 | dLdy = self.Loss()._loss_gradient(self._output, actual)
336 | dyds = expected
337 | dsdd = self._softmax_gradient(self._dense)
338 | dddw = self._dense_gradient(t)
339 | dddb = np.ones(t.shape)
340 |
341 | dLdd = np.einsum("fkij,fkj->fki", dsdd, dLdy * dyds)
342 |
343 | self._w_grad = (dLdd * dddw).mean(axis=(0, 1))
344 | self._b_grad = (dLdd * dddb).mean(axis=(0, 1))
345 |
346 | self.optimizer.pre_update_params(epoch)
347 | self.optimizer.update_params(self, epoch)
348 |
349 | if self.verbose > 2:
350 | print(
351 | "[EPOCH: ",
352 | epoch,
353 | "]: cust_w_grad: ",
354 | self._w_grad,
355 | ", cust_b_grad: ",
356 | self._b_grad,
357 | file=text_file,
358 | )
359 |
360 | return self
361 |
362 | def _log_epoch(self, epoch):
363 | if not epoch % 10:
364 | print(
365 | f"[Epoch {epoch}/{self.max_iter}] "
366 | + f"loss: {self._loss:.4f} "
367 | + f"lr: {self.optimizer._learning_rate:.8f}"
368 | )
369 |
370 | def fit(self, X, y=None, sample_weight=None, loss="mse", text_file=None):
371 |
372 | self.compile(X, y, sample_weight)
373 | self.Loss = LOSS_FUNCTIONS[self.loss]
374 |
375 | if self.verbose:
376 | print("[Training]\n")
377 |
378 | num_folds = self.actual_.shape[0]
379 |
380 | weights = []
381 | biases = []
382 | eval_losses = []
383 |
384 | for p in range(num_folds):
385 |
386 | actual_train = np.delete(self.actual_, p, axis=0)
387 | expected_train = np.delete(self.expected_, p, axis=0)
388 | t_train = np.delete(self.t_, p, axis=0)
389 |
390 | actual_test = self.actual_[np.newaxis, p, :, :]
391 | expected_test = self.expected_[np.newaxis, p, :, :]
392 | t_test = self.t_[np.newaxis, p, :, :]
393 |
394 | self.initialize_weights()
395 | self.optimizer.reset(self)
396 |
397 | for epoch in range(self.max_iter + 1):
398 | _actual_train = actual_train
399 | _expected_train = expected_train
400 | _t_train = t_train
401 |
402 | if self.dropout:
403 | drop_mask = np.ones_like(
404 | _actual_train.reshape(-1, _actual_train.shape[-1])
405 | )
406 | choices = list(range(drop_mask.shape[0]))
407 | drop_idx = np.random.choice(
408 | choices, int(len(choices) * self.dropout)
409 | )
410 | drop_mask[drop_idx] = 0
411 | drop_mask = drop_mask.reshape(_actual_train.shape)
412 |
413 | _actual_train = _actual_train * drop_mask
414 | _expected_train = _expected_train * drop_mask
415 |
416 | if self.broad_dropout:
417 | choices = list(range(_actual_train.shape[0]))
418 | drop_idx = np.random.choice(
419 | choices, int(len(choices) * self.broad_dropout)
420 | )
421 | drop_mask = np.ones_like(_actual_train)
422 | drop_mask[drop_idx, :, :] = 0
423 |
424 | _actual_train = _actual_train * drop_mask
425 | _expected_train = _expected_train * drop_mask
426 |
427 | self.forward_pass(_actual_train, _expected_train, _t_train, text_file)
428 | self.backward_pass(
429 | _actual_train, _expected_train, _t_train, epoch, text_file
430 | )
431 |
432 | if self.verbose:
433 | self._log_epoch(epoch)
434 |
435 | weights.append(self.weights)
436 | biases.append(self.biases)
437 |
438 | eval_loss = self.compute_loss(
439 | self._predict(expected_test, t_test), actual_test
440 | )
441 | eval_loss = eval_loss / actual_test.mean()
442 | eval_losses.append(eval_loss)
443 |
444 | self.weights = np.average(np.stack(weights, axis=1), axis=1)
445 | self.biases = np.average(np.stack(biases, axis=1), axis=1)
446 |
447 | self.weights_ = self._activation[-1]
448 |
449 | print()
450 | if self.verbose:
451 | print("\n")
452 |
453 | return self
454 |
455 | def _predict(self, expected, t):
456 | dense = self.dense(t)
457 | activation = self.activation(dense)
458 | output = self.output(expected, activation)
459 | return output
460 |
461 | def predict(self, X, y=None, sample_weight=None):
462 | _, expected, t = self.preprocess(X, y, sample_weight)
463 | return self._predict(expected, t)
464 |
465 | def evaluate(self, X, y=None, sample_weight=None):
466 | actual, expected, t = self.preprocess(X, y, sample_weight)
467 | output = self._predict(expected, t)
468 | return self.compute_loss(output, actual)
469 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
--------------------------------------------------------------------------------