catadjust 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- catadjust-0.1.0/.gitignore +161 -0
- catadjust-0.1.0/LICENSE +21 -0
- catadjust-0.1.0/PKG-INFO +49 -0
- catadjust-0.1.0/README.md +10 -0
- catadjust-0.1.0/catadjust/__init__.py +1 -0
- catadjust-0.1.0/catadjust/hazelt_adjust.py +212 -0
- catadjust-0.1.0/pyproject.toml +28 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# pdm
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
+
#pdm.lock
|
|
107
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
108
|
+
# in version control.
|
|
109
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
110
|
+
.pdm.toml
|
|
111
|
+
|
|
112
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
113
|
+
__pypackages__/
|
|
114
|
+
|
|
115
|
+
# Celery stuff
|
|
116
|
+
celerybeat-schedule
|
|
117
|
+
celerybeat.pid
|
|
118
|
+
|
|
119
|
+
# SageMath parsed files
|
|
120
|
+
*.sage.py
|
|
121
|
+
|
|
122
|
+
# Environments
|
|
123
|
+
.env
|
|
124
|
+
.venv
|
|
125
|
+
env/
|
|
126
|
+
venv/
|
|
127
|
+
ENV/
|
|
128
|
+
env.bak/
|
|
129
|
+
venv.bak/
|
|
130
|
+
|
|
131
|
+
# Spyder project settings
|
|
132
|
+
.spyderproject
|
|
133
|
+
.spyproject
|
|
134
|
+
|
|
135
|
+
# Rope project settings
|
|
136
|
+
.ropeproject
|
|
137
|
+
|
|
138
|
+
# mkdocs documentation
|
|
139
|
+
/site
|
|
140
|
+
|
|
141
|
+
# mypy
|
|
142
|
+
.mypy_cache/
|
|
143
|
+
.dmypy.json
|
|
144
|
+
dmypy.json
|
|
145
|
+
|
|
146
|
+
# Pyre type checker
|
|
147
|
+
.pyre/
|
|
148
|
+
|
|
149
|
+
# pytype static type analyzer
|
|
150
|
+
.pytype/
|
|
151
|
+
|
|
152
|
+
# Cython debug symbols
|
|
153
|
+
cython_debug/
|
|
154
|
+
|
|
155
|
+
# PyCharm
|
|
156
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
157
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
158
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
159
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
160
|
+
#.idea/
|
|
161
|
+
.DS_Store
|
catadjust-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mutahar Chalmers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
catadjust-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: catadjust
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Adjustment tools for catastrophe models
|
|
5
|
+
Project-URL: Homepage, https://github.com/MutaharChalmers/catadjust
|
|
6
|
+
Author-email: Mutahar Chalmers <mutahar.chalmers@gmail.com>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2025 Mutahar Chalmers
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Classifier: Development Status :: 4 - Beta
|
|
30
|
+
Classifier: Intended Audience :: Science/Research
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Operating System :: OS Independent
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
35
|
+
Requires-Python: >=3.8
|
|
36
|
+
Requires-Dist: numpy>=1.24
|
|
37
|
+
Requires-Dist: pandas>=2.0
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# CatAdjust - Tools for adjusting catastrophe models
|
|
41
|
+
Current tools:
|
|
42
|
+
- Hazard ELT Adjustment Tool - Given a location-level ELT with hazard values, and a collection of *target* hazard EEF curves at all locations, this tool adjusts the rates of all events in the ELT, such that the hazard EEF curves from the rate-adjusted ELT match the target hazard EEF curves as closely as possible.
|
|
43
|
+
|
|
44
|
+
Future tools:
|
|
45
|
+
- Loss Adjustment Tool - Given a stochastic ELT or YLT from a catastrophe model, and some historic loss experience, this tool adjusts the losses in the ELT or YLT such that the adjusted OEP curve matches the empirical historic loss OEP curve over some user-defined range.
|
|
46
|
+
|
|
47
|
+
- Industry Loss Conversion Tool - Given two stochastic industry ELTs or YLTs with losses at sub-national (e.g. CRESTA) level, scale the losses from one ELT/YLT such that the EP curves match the EP curves derived from the other ELT/YLT both at aggregate and sub-national level.
|
|
48
|
+
|
|
49
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# CatAdjust - Tools for adjusting catastrophe models
|
|
2
|
+
Current tools:
|
|
3
|
+
- Hazard ELT Adjustment Tool - Given a location-level ELT with hazard values, and a collection of *target* hazard EEF curves at all locations, this tool adjusts the rates of all events in the ELT, such that the hazard EEF curves from the rate-adjusted ELT match the target hazard EEF curves as closely as possible.
|
|
4
|
+
|
|
5
|
+
Future tools:
|
|
6
|
+
- Loss Adjustment Tool - Given a stochastic ELT or YLT from a catastrophe model, and some historic loss experience, this tool adjusts the losses in the ELT or YLT such that the adjusted OEP curve matches the empirical historic loss OEP curve over some user-defined range.
|
|
7
|
+
|
|
8
|
+
- Industry Loss Conversion Tool - Given two stochastic industry ELTs or YLTs with losses at sub-national (e.g. CRESTA) level, scale the losses from one ELT/YLT such that the EP curves match the EP curves derived from the other ELT/YLT both at aggregate and sub-national level.
|
|
9
|
+
|
|
10
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .hazelt_adjust import HazardELTAdjustment
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from tqdm.auto import tqdm
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HazardELTAdjustment:
|
|
10
|
+
"""Adjust a catastrophe model location-level ELT with hazard values
|
|
11
|
+
to match arbitrary target location-level hazard EEF curves as closely
|
|
12
|
+
as possible by scaling event rates.
|
|
13
|
+
"""
|
|
14
|
+
def __init__(self, elt_raw, loccol, eventcol, ratecol, hazcol):
|
|
15
|
+
"""Load raw location-level ELT and pre-process.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
elt_raw : DataFrame
|
|
20
|
+
Raw location-level ELT.
|
|
21
|
+
loccol: str
|
|
22
|
+
Name of column containing locationIDs.
|
|
23
|
+
eventcol: str
|
|
24
|
+
Name of column containing eventIDs.
|
|
25
|
+
ratecol: str
|
|
26
|
+
Name of column containing event rates.
|
|
27
|
+
hazcol: str
|
|
28
|
+
Name of column containing event-location hazard intensity.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
# Load ELT to be adjusted and pre-process
|
|
32
|
+
elt = elt_raw.astype({loccol: np.int64, eventcol: np.int64,
|
|
33
|
+
ratecol: np.float64, hazcol: np.float64}
|
|
34
|
+
).drop_duplicates([loccol, eventcol]
|
|
35
|
+
).sort_values([loccol, hazcol], ascending=[True, False])
|
|
36
|
+
self.loccol = loccol
|
|
37
|
+
self.eventcol = eventcol
|
|
38
|
+
self.ratecol = ratecol
|
|
39
|
+
self.hazcol = hazcol
|
|
40
|
+
self.elt = self.calc_eef(elt)
|
|
41
|
+
m = self.elt.shape[0]
|
|
42
|
+
|
|
43
|
+
# Sorted array of unique eventIDs
|
|
44
|
+
eventIDs_unique = np.sort(self.elt[eventcol].unique())
|
|
45
|
+
self.nevents = eventIDs_unique.size
|
|
46
|
+
|
|
47
|
+
# Convert eventIDs in ELT to indices in event array
|
|
48
|
+
self.loceventixs = np.searchsorted(eventIDs_unique, self.elt[eventcol])
|
|
49
|
+
|
|
50
|
+
# Indices in ELT where location changes
|
|
51
|
+
locbreaks = np.nonzero(np.diff(self.elt[loccol]))[0] + 1
|
|
52
|
+
self.loc_slicers = np.stack([np.r_[0, locbreaks], np.r_[locbreaks, m]]).T
|
|
53
|
+
|
|
54
|
+
def calc_eef(self, elt):
|
|
55
|
+
"""Calculate EEFs from a location-level ELT sorted by descending hazard.
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
elt : DataFrame
|
|
60
|
+
Processed and sorted (in descending hazard intensity) location-level ELT.
|
|
61
|
+
|
|
62
|
+
Returns
|
|
63
|
+
-------
|
|
64
|
+
elt : DataFrame
|
|
65
|
+
Input ELT with additional EEF column.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
elt['eef'] = elt.groupby(self.loccol, sort=False)[self.ratecol].transform(np.cumsum)
|
|
69
|
+
return elt
|
|
70
|
+
|
|
71
|
+
def adjust(self, eefs_targ, x0=None, min_rate=1e-12, tol=1e-4, niter=1000, alpha=0.001):
|
|
72
|
+
"""Adjust ELT to match location-level hazard curves.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
eefs_targ : Series or ndarray
|
|
77
|
+
Target EEFs in the same order as the processed ELT.
|
|
78
|
+
x0 : Series or ndarray, optional
|
|
79
|
+
Initial guess to use for rate adjustment.
|
|
80
|
+
min_rate : float, optional
|
|
81
|
+
Minimum allowable rate constraint.
|
|
82
|
+
tol : float, optional
|
|
83
|
+
Convergence criterion for cost function. Iteration stops
|
|
84
|
+
once the cost function (mean square error) is less than this value.
|
|
85
|
+
niter : int, optional
|
|
86
|
+
Maximum number of iterations.
|
|
87
|
+
alpha : float, optional
|
|
88
|
+
Learning rate in Adam gradient descent algorithm.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
elt_adj : DataFrame
|
|
93
|
+
Adjusted ELT.
|
|
94
|
+
res : dict
|
|
95
|
+
Results dict.
|
|
96
|
+
fs : ndarray
|
|
97
|
+
Learning curve.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
if x0 is None:
|
|
101
|
+
x0 = self.elt.groupby(self.eventcol)[self.ratecol].mean().values
|
|
102
|
+
else:
|
|
103
|
+
x0 = np.array(x0)
|
|
104
|
+
|
|
105
|
+
eefs_targ = np.array(eefs_targ)
|
|
106
|
+
args = (eefs_targ,)
|
|
107
|
+
res, fs = self._adam(self._cost, x0, args, alpha=alpha, niter=niter, tol=tol, amin=min_rate)
|
|
108
|
+
elt_adj = self.elt.copy()
|
|
109
|
+
elt_adj[self.ratecol] = res['x'][self.loceventixs]
|
|
110
|
+
elt_adj = self.calc_eef(elt_adj)
|
|
111
|
+
return elt_adj, res, fs
|
|
112
|
+
|
|
113
|
+
def _cost(self, theta, eefs_targ):
|
|
114
|
+
"""Cost function for fitting an ELT to a target EEF by adjusting event rates.
|
|
115
|
+
|
|
116
|
+
Parameters
|
|
117
|
+
----------
|
|
118
|
+
theta : ndarray
|
|
119
|
+
Rates to calculate cost function for, in unique eventID order.
|
|
120
|
+
eefs_targ : ndarray
|
|
121
|
+
Target EEFs for location-events in the same order as the
|
|
122
|
+
pre-processed ELT.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
cost : float
|
|
127
|
+
Cost function evaluated at theta.
|
|
128
|
+
cost_grad : ndarray
|
|
129
|
+
Gradient of cost function.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
# Calculate EEFs for each location by chunked cumulative sums
|
|
133
|
+
eefs_pred = np.empty_like(eefs_targ)
|
|
134
|
+
|
|
135
|
+
# Expand event rates to event-location rates
|
|
136
|
+
rates = theta[self.loceventixs]
|
|
137
|
+
for a, b in self.loc_slicers:
|
|
138
|
+
eefs_pred[a:b] = rates[a:b].cumsum()
|
|
139
|
+
|
|
140
|
+
# Calculate deltas and cost function for current parameters
|
|
141
|
+
deltas = eefs_pred - eefs_targ
|
|
142
|
+
cost = (deltas**2).mean()
|
|
143
|
+
|
|
144
|
+
# Calculate gradient of cost function wrt to event rates
|
|
145
|
+
grad_cost = np.zeros_like(theta)
|
|
146
|
+
for a, b in self.loc_slicers:
|
|
147
|
+
grad_cost[self.loceventixs[a:b]] += deltas[a:b][::-1].cumsum()[::-1]
|
|
148
|
+
|
|
149
|
+
return cost, 2*grad_cost/deltas.size
|
|
150
|
+
|
|
151
|
+
def _adam(self, fun, x0, args=(), alpha=0.001, beta1=0.9, beta2=0.999,
|
|
152
|
+
eps=1e-8, niter=1000, tol=1e-6, amin=-np.inf, amax=np.inf):
|
|
153
|
+
"""Adaptive Moment Estimation gradient descent with weight clipping.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
cost : function
|
|
158
|
+
Cost function which returns cost and gradient.
|
|
159
|
+
x0 : ndarray
|
|
160
|
+
Initial values for optimisation.
|
|
161
|
+
args : tuple, optional
|
|
162
|
+
Arguments to be passed to cost function.
|
|
163
|
+
alpha : float, optional
|
|
164
|
+
Learning rate.
|
|
165
|
+
beta1 : float, optional
|
|
166
|
+
Exponential decay rate for gradient momentum.
|
|
167
|
+
beta2 : float, optional
|
|
168
|
+
Exponential decay rate for gradient variance.
|
|
169
|
+
tol : float, optional
|
|
170
|
+
Convergence criterion for cost function. Iteration stops
|
|
171
|
+
once the cost function (mean square error) is less than this value.
|
|
172
|
+
amin : float, optional
|
|
173
|
+
Minimum value allowed for input values.
|
|
174
|
+
amax : float, optional
|
|
175
|
+
Maximum value allowed for input values.
|
|
176
|
+
|
|
177
|
+
Returns
|
|
178
|
+
-------
|
|
179
|
+
cost : float
|
|
180
|
+
Cost function evaluated at theta.
|
|
181
|
+
cost_grad : ndarray
|
|
182
|
+
Gradient of cost function.
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
x, m, v = x0, 0, 0
|
|
186
|
+
fs = np.zeros(niter)
|
|
187
|
+
|
|
188
|
+
pbar = tqdm(range(niter))
|
|
189
|
+
for i in pbar:
|
|
190
|
+
fs[i], grad = fun(x, *args)
|
|
191
|
+
|
|
192
|
+
pbar.set_description(f'f={fs[i]:.2e}{">" if fs[i] > tol else "<="}{tol:.2e}')
|
|
193
|
+
if fs[i] < tol:
|
|
194
|
+
return dict(x=x, fun=fs[i], jac=grad, nit=i), fs
|
|
195
|
+
|
|
196
|
+
# Estimates of first and second moment of gradient
|
|
197
|
+
m = (1 - beta1)*grad + beta1*m
|
|
198
|
+
v = (1 - beta2)*grad**2 + beta2*v
|
|
199
|
+
|
|
200
|
+
# Bias correction
|
|
201
|
+
mhat = m/(1 - beta1**(i+1))
|
|
202
|
+
vhat = v/(1 - beta2**(i+1))
|
|
203
|
+
|
|
204
|
+
# Update step
|
|
205
|
+
x = x - alpha * mhat/(np.sqrt(vhat) + eps)
|
|
206
|
+
|
|
207
|
+
# Weight clipping
|
|
208
|
+
x = np.clip(x, amin, amax)
|
|
209
|
+
|
|
210
|
+
f, grad = fun(x, *args)
|
|
211
|
+
print('Warning: Iteration limit reached before cost function converged within tolerance')
|
|
212
|
+
return dict(x=x, fun=f, jac=grad, nit=i), fs
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "catadjust"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Adjustment tools for catastrophe models"
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Mutahar Chalmers", email = "mutahar.chalmers@gmail.com" },
|
|
11
|
+
]
|
|
12
|
+
license = { file = "LICENSE" }
|
|
13
|
+
readme = "README.md"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Science/Research",
|
|
20
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
21
|
+
]
|
|
22
|
+
requires-python = ">=3.8"
|
|
23
|
+
dependencies = [
|
|
24
|
+
"numpy>=1.24", "pandas>=2.0"
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
"Homepage" = "https://github.com/MutaharChalmers/catadjust"
|