superglm 0.12.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.
- superglm-0.12.0/.gitignore +73 -0
- superglm-0.12.0/LICENSE +21 -0
- superglm-0.12.0/PKG-INFO +345 -0
- superglm-0.12.0/README.md +295 -0
- superglm-0.12.0/pyproject.toml +150 -0
- superglm-0.12.0/src/superglm/__init__.py +227 -0
- superglm-0.12.0/src/superglm/_debug.py +18 -0
- superglm-0.12.0/src/superglm/_fit_trace.py +296 -0
- superglm-0.12.0/src/superglm/_group_matrix/__init__.py +1 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_algebra.py +1025 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_bin_space.py +374 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_bins.py +28 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_centered.py +990 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_core.py +288 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_discretized.py +429 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_execution.py +415 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_kernels.py +172 -0
- superglm-0.12.0/src/superglm/_group_matrix/_group_matrix_tabmat.py +286 -0
- superglm-0.12.0/src/superglm/_tweedie_profile_kernel.py +491 -0
- superglm-0.12.0/src/superglm/_tweedie_series.py +207 -0
- superglm-0.12.0/src/superglm/_utils.py +46 -0
- superglm-0.12.0/src/superglm/constraints.py +659 -0
- superglm-0.12.0/src/superglm/debug_weights.py +272 -0
- superglm-0.12.0/src/superglm/diagnostics/__init__.py +27 -0
- superglm-0.12.0/src/superglm/diagnostics/discretize.py +288 -0
- superglm-0.12.0/src/superglm/diagnostics/spline_checks.py +108 -0
- superglm-0.12.0/src/superglm/diagnostics/term_diagnostics.py +226 -0
- superglm-0.12.0/src/superglm/distributions.py +418 -0
- superglm-0.12.0/src/superglm/dm_builder.py +1270 -0
- superglm-0.12.0/src/superglm/editor/__init__.py +5 -0
- superglm-0.12.0/src/superglm/editor/_types.py +63 -0
- superglm-0.12.0/src/superglm/editor/app/__init__.py +1 -0
- superglm-0.12.0/src/superglm/editor/app/api/client.js +105 -0
- superglm-0.12.0/src/superglm/editor/app/api/contracts.js +157 -0
- superglm-0.12.0/src/superglm/editor/app/api.js +7 -0
- superglm-0.12.0/src/superglm/editor/app/chart/geometry.js +293 -0
- superglm-0.12.0/src/superglm/editor/app/chart.js +1137 -0
- superglm-0.12.0/src/superglm/editor/app/format.js +40 -0
- superglm-0.12.0/src/superglm/editor/app/history.js +42 -0
- superglm-0.12.0/src/superglm/editor/app/index.html +458 -0
- superglm-0.12.0/src/superglm/editor/app/interactions.js +764 -0
- superglm-0.12.0/src/superglm/editor/app/main.js +1492 -0
- superglm-0.12.0/src/superglm/editor/app/metrics.js +45 -0
- superglm-0.12.0/src/superglm/editor/app/reports.js +163 -0
- superglm-0.12.0/src/superglm/editor/app/state/actions.js +603 -0
- superglm-0.12.0/src/superglm/editor/app/state/selectors.js +90 -0
- superglm-0.12.0/src/superglm/editor/app/state/store.js +348 -0
- superglm-0.12.0/src/superglm/editor/app/state/timing.js +70 -0
- superglm-0.12.0/src/superglm/editor/app/styles/chart.css +51 -0
- superglm-0.12.0/src/superglm/editor/app/styles/dialogs.css +456 -0
- superglm-0.12.0/src/superglm/editor/app/styles/panels.css +177 -0
- superglm-0.12.0/src/superglm/editor/app/styles/shell.css +233 -0
- superglm-0.12.0/src/superglm/editor/app/styles/tokens.css +82 -0
- superglm-0.12.0/src/superglm/editor/app/styles.css +768 -0
- superglm-0.12.0/src/superglm/editor/app/summary.js +781 -0
- superglm-0.12.0/src/superglm/editor/app/views/app_bar.js +102 -0
- superglm-0.12.0/src/superglm/editor/app/views/context_bar.js +24 -0
- superglm-0.12.0/src/superglm/editor/app/views/export_dialog.js +229 -0
- superglm-0.12.0/src/superglm/editor/app/views/help_content.js +176 -0
- superglm-0.12.0/src/superglm/editor/app/views/help_drawer.js +40 -0
- superglm-0.12.0/src/superglm/editor/app/views/inspector.js +165 -0
- superglm-0.12.0/src/superglm/editor/app/views/popover.js +239 -0
- superglm-0.12.0/src/superglm/editor/app/views/structural_confirm.js +128 -0
- superglm-0.12.0/src/superglm/editor/app/views/tool_rail.js +139 -0
- superglm-0.12.0/src/superglm/editor/apply.py +540 -0
- superglm-0.12.0/src/superglm/editor/assets.py +37 -0
- superglm-0.12.0/src/superglm/editor/collapse.py +492 -0
- superglm-0.12.0/src/superglm/editor/controls.py +226 -0
- superglm-0.12.0/src/superglm/editor/evaluation.py +158 -0
- superglm-0.12.0/src/superglm/editor/evaluation_cache.py +113 -0
- superglm-0.12.0/src/superglm/editor/evidence.py +149 -0
- superglm-0.12.0/src/superglm/editor/group_display.py +127 -0
- superglm-0.12.0/src/superglm/editor/io.py +106 -0
- superglm-0.12.0/src/superglm/editor/level_order.py +52 -0
- superglm-0.12.0/src/superglm/editor/metrics.py +187 -0
- superglm-0.12.0/src/superglm/editor/native_dialogs.py +108 -0
- superglm-0.12.0/src/superglm/editor/operations.py +237 -0
- superglm-0.12.0/src/superglm/editor/payloads.py +351 -0
- superglm-0.12.0/src/superglm/editor/persistence.py +249 -0
- superglm-0.12.0/src/superglm/editor/refit.py +42 -0
- superglm-0.12.0/src/superglm/editor/reports.py +165 -0
- superglm-0.12.0/src/superglm/editor/server.py +474 -0
- superglm-0.12.0/src/superglm/editor/session.py +1438 -0
- superglm-0.12.0/src/superglm/editor/summaries.py +378 -0
- superglm-0.12.0/src/superglm/editor/terms.py +182 -0
- superglm-0.12.0/src/superglm/editor/widget.py +1169 -0
- superglm-0.12.0/src/superglm/export/__init__.py +5 -0
- superglm-0.12.0/src/superglm/export/excel.py +221 -0
- superglm-0.12.0/src/superglm/export/rating_tables.py +670 -0
- superglm-0.12.0/src/superglm/export/summary.py +380 -0
- superglm-0.12.0/src/superglm/families.py +67 -0
- superglm-0.12.0/src/superglm/features/__init__.py +41 -0
- superglm-0.12.0/src/superglm/features/_spline_build.py +245 -0
- superglm-0.12.0/src/superglm/features/_spline_cardinal.py +120 -0
- superglm-0.12.0/src/superglm/features/_spline_cardinal_spec.py +100 -0
- superglm-0.12.0/src/superglm/features/_spline_config.py +178 -0
- superglm-0.12.0/src/superglm/features/_spline_constraints.py +54 -0
- superglm-0.12.0/src/superglm/features/_spline_extrapolation.py +75 -0
- superglm-0.12.0/src/superglm/features/_spline_factory.py +165 -0
- superglm-0.12.0/src/superglm/features/_spline_identifiability.py +96 -0
- superglm-0.12.0/src/superglm/features/_spline_knots.py +57 -0
- superglm-0.12.0/src/superglm/features/_spline_multi_penalty.py +31 -0
- superglm-0.12.0/src/superglm/features/_spline_penalties.py +52 -0
- superglm-0.12.0/src/superglm/features/_spline_runtime.py +192 -0
- superglm-0.12.0/src/superglm/features/_spline_select.py +164 -0
- superglm-0.12.0/src/superglm/features/_spline_subclass_ops.py +77 -0
- superglm-0.12.0/src/superglm/features/categorical.py +193 -0
- superglm-0.12.0/src/superglm/features/constraint.py +28 -0
- superglm-0.12.0/src/superglm/features/grouping.py +184 -0
- superglm-0.12.0/src/superglm/features/interaction.py +1290 -0
- superglm-0.12.0/src/superglm/features/numeric.py +48 -0
- superglm-0.12.0/src/superglm/features/ordered_categorical.py +563 -0
- superglm-0.12.0/src/superglm/features/polynomial.py +90 -0
- superglm-0.12.0/src/superglm/features/spline.py +1015 -0
- superglm-0.12.0/src/superglm/group_matrix.py +441 -0
- superglm-0.12.0/src/superglm/inference/__init__.py +71 -0
- superglm-0.12.0/src/superglm/inference/_metrics_design.py +289 -0
- superglm-0.12.0/src/superglm/inference/_ordered_reference.py +85 -0
- superglm-0.12.0/src/superglm/inference/_term_covariance.py +248 -0
- superglm-0.12.0/src/superglm/inference/_term_helpers.py +358 -0
- superglm-0.12.0/src/superglm/inference/_term_interactions.py +79 -0
- superglm-0.12.0/src/superglm/inference/_term_model_ops.py +340 -0
- superglm-0.12.0/src/superglm/inference/_term_ops.py +493 -0
- superglm-0.12.0/src/superglm/inference/_term_types.py +186 -0
- superglm-0.12.0/src/superglm/inference/coef_tables.py +968 -0
- superglm-0.12.0/src/superglm/inference/covariance.py +358 -0
- superglm-0.12.0/src/superglm/inference/metrics.py +1320 -0
- superglm-0.12.0/src/superglm/inference/summary.py +886 -0
- superglm-0.12.0/src/superglm/inference/term.py +53 -0
- superglm-0.12.0/src/superglm/links.py +466 -0
- superglm-0.12.0/src/superglm/model/__init__.py +8 -0
- superglm-0.12.0/src/superglm/model/api.py +1557 -0
- superglm-0.12.0/src/superglm/model/base.py +753 -0
- superglm-0.12.0/src/superglm/model/explain_ops.py +254 -0
- superglm-0.12.0/src/superglm/model/fit_data_guard.py +123 -0
- superglm-0.12.0/src/superglm/model/fit_ops.py +1332 -0
- superglm-0.12.0/src/superglm/model/fit_state.py +697 -0
- superglm-0.12.0/src/superglm/model/fit_workspace.py +97 -0
- superglm-0.12.0/src/superglm/model/input_validation.py +110 -0
- superglm-0.12.0/src/superglm/model/monotone_ops.py +29 -0
- superglm-0.12.0/src/superglm/model/path_ops.py +113 -0
- superglm-0.12.0/src/superglm/model/plot_ops.py +308 -0
- superglm-0.12.0/src/superglm/model/profile_ops.py +430 -0
- superglm-0.12.0/src/superglm/model/reml_debug.py +392 -0
- superglm-0.12.0/src/superglm/model/reml_execute.py +372 -0
- superglm-0.12.0/src/superglm/model/reml_finalize.py +472 -0
- superglm-0.12.0/src/superglm/model/reml_ops.py +333 -0
- superglm-0.12.0/src/superglm/model/reml_setup.py +162 -0
- superglm-0.12.0/src/superglm/model/reml_state.py +79 -0
- superglm-0.12.0/src/superglm/model/report_ops.py +523 -0
- superglm-0.12.0/src/superglm/model/runtime_canonicalize.py +454 -0
- superglm-0.12.0/src/superglm/model/shape_ops.py +764 -0
- superglm-0.12.0/src/superglm/model/state_ops.py +492 -0
- superglm-0.12.0/src/superglm/model/telemetry_ops.py +363 -0
- superglm-0.12.0/src/superglm/model_selection.py +433 -0
- superglm-0.12.0/src/superglm/penalties/__init__.py +16 -0
- superglm-0.12.0/src/superglm/penalties/base.py +154 -0
- superglm-0.12.0/src/superglm/penalties/flavors.py +68 -0
- superglm-0.12.0/src/superglm/penalties/group_elastic_net.py +80 -0
- superglm-0.12.0/src/superglm/penalties/group_lasso.py +61 -0
- superglm-0.12.0/src/superglm/penalties/ridge.py +50 -0
- superglm-0.12.0/src/superglm/penalties/sparse_group_lasso.py +73 -0
- superglm-0.12.0/src/superglm/plotting/__init__.py +14 -0
- superglm-0.12.0/src/superglm/plotting/common.py +261 -0
- superglm-0.12.0/src/superglm/plotting/comparison.py +267 -0
- superglm-0.12.0/src/superglm/plotting/comparison_plotly.py +313 -0
- superglm-0.12.0/src/superglm/plotting/curve_similarity.py +152 -0
- superglm-0.12.0/src/superglm/plotting/data.py +428 -0
- superglm-0.12.0/src/superglm/plotting/diagnostics.py +544 -0
- superglm-0.12.0/src/superglm/plotting/group_display.py +180 -0
- superglm-0.12.0/src/superglm/plotting/interactions.py +1026 -0
- superglm-0.12.0/src/superglm/plotting/main_effects.py +922 -0
- superglm-0.12.0/src/superglm/plotting/main_effects_plotly.py +1744 -0
- superglm-0.12.0/src/superglm/profiling/__init__.py +34 -0
- superglm-0.12.0/src/superglm/profiling/_reporting.py +154 -0
- superglm-0.12.0/src/superglm/profiling/harness.py +281 -0
- superglm-0.12.0/src/superglm/profiling/nb.py +583 -0
- superglm-0.12.0/src/superglm/profiling/tweedie.py +5976 -0
- superglm-0.12.0/src/superglm/reml/__init__.py +56 -0
- superglm-0.12.0/src/superglm/reml/direct.py +868 -0
- superglm-0.12.0/src/superglm/reml/discrete.py +1160 -0
- superglm-0.12.0/src/superglm/reml/efs.py +418 -0
- superglm-0.12.0/src/superglm/reml/gradient.py +281 -0
- superglm-0.12.0/src/superglm/reml/multi_penalty.py +356 -0
- superglm-0.12.0/src/superglm/reml/objective.py +293 -0
- superglm-0.12.0/src/superglm/reml/observed_geometry.py +900 -0
- superglm-0.12.0/src/superglm/reml/penalty_algebra.py +902 -0
- superglm-0.12.0/src/superglm/reml/result.py +94 -0
- superglm-0.12.0/src/superglm/reml/runner.py +414 -0
- superglm-0.12.0/src/superglm/reml/scale.py +311 -0
- superglm-0.12.0/src/superglm/reml/scop_efs.py +1851 -0
- superglm-0.12.0/src/superglm/reml/scop_geometry.py +904 -0
- superglm-0.12.0/src/superglm/reml/w_derivatives.py +471 -0
- superglm-0.12.0/src/superglm/sklearn.py +796 -0
- superglm-0.12.0/src/superglm/solvers/__init__.py +6 -0
- superglm-0.12.0/src/superglm/solvers/centered_system.py +347 -0
- superglm-0.12.0/src/superglm/solvers/constrained_qp.py +199 -0
- superglm-0.12.0/src/superglm/solvers/dispersion.py +35 -0
- superglm-0.12.0/src/superglm/solvers/irls_direct.py +2242 -0
- superglm-0.12.0/src/superglm/solvers/irls_state.py +195 -0
- superglm-0.12.0/src/superglm/solvers/pirls.py +1495 -0
- superglm-0.12.0/src/superglm/solvers/rank.py +895 -0
- superglm-0.12.0/src/superglm/solvers/scop.py +299 -0
- superglm-0.12.0/src/superglm/solvers/scop_exact_support.py +31 -0
- superglm-0.12.0/src/superglm/solvers/scop_newton.py +1091 -0
- superglm-0.12.0/src/superglm/solvers/working_rows.py +125 -0
- superglm-0.12.0/src/superglm/stats/__init__.py +31 -0
- superglm-0.12.0/src/superglm/stats/davies.py +183 -0
- superglm-0.12.0/src/superglm/stats/model_tests.py +473 -0
- superglm-0.12.0/src/superglm/stats/wood_pvalue.py +250 -0
- superglm-0.12.0/src/superglm/types.py +316 -0
- superglm-0.12.0/src/superglm/validation.py +789 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Virtual environment
|
|
2
|
+
.venv/
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
|
|
12
|
+
# Coverage
|
|
13
|
+
.coverage
|
|
14
|
+
coverage.xml
|
|
15
|
+
htmlcov/
|
|
16
|
+
|
|
17
|
+
# IDE
|
|
18
|
+
.idea/
|
|
19
|
+
.vscode/
|
|
20
|
+
*.swp
|
|
21
|
+
|
|
22
|
+
# OS
|
|
23
|
+
.DS_Store
|
|
24
|
+
|
|
25
|
+
# Data
|
|
26
|
+
data/
|
|
27
|
+
|
|
28
|
+
# Other
|
|
29
|
+
.claude/
|
|
30
|
+
.ruff_cahce/
|
|
31
|
+
scratch/
|
|
32
|
+
|
|
33
|
+
# Benchmark outputs (generated, not tracked)
|
|
34
|
+
benchmarks/results/
|
|
35
|
+
|
|
36
|
+
# Generated parity/reference CSVs (keep local, do not track)
|
|
37
|
+
tests/fixtures/mgcv_gamma_mtpl2sev_fitted.csv
|
|
38
|
+
tests/fixtures/mgcv_nb2_mtpl2_fitted.csv
|
|
39
|
+
tests/fixtures/mtpl2_freq_50k.csv
|
|
40
|
+
tests/fixtures/mtpl2_sev_merged.csv
|
|
41
|
+
|
|
42
|
+
# MkDocs build output
|
|
43
|
+
site/
|
|
44
|
+
|
|
45
|
+
AGENTS.md
|
|
46
|
+
ROADMAP.md
|
|
47
|
+
TESTING_AUDIT_PLAN.md
|
|
48
|
+
ISSUE_WORKING_WEIGHTS.md
|
|
49
|
+
REML_IMPLEMENTATION_PLAN.md
|
|
50
|
+
|
|
51
|
+
# scratch/ is a playground for local dev only — not for public release.
|
|
52
|
+
# Benchmarks, experiments, R comparisons, and throwaway scripts live here.
|
|
53
|
+
scratch/
|
|
54
|
+
docs/notebooks/spline_diagnostics/
|
|
55
|
+
.superglm-debug/
|
|
56
|
+
|
|
57
|
+
# Superpowers skill artifacts
|
|
58
|
+
docs/superpowers/
|
|
59
|
+
docs/reml_freml_paper_checklist.md
|
|
60
|
+
|
|
61
|
+
# Agentic harness artifacts
|
|
62
|
+
.harness/
|
|
63
|
+
PLAN.md
|
|
64
|
+
REVIEW.md
|
|
65
|
+
PROGRESS.md
|
|
66
|
+
GENERATOR_STATUS.md
|
|
67
|
+
REML_BAD_BEHAVIOUR.txt
|
|
68
|
+
.omx/
|
|
69
|
+
|
|
70
|
+
# Frontend development
|
|
71
|
+
node_modules/
|
|
72
|
+
playwright-report/
|
|
73
|
+
test-results/
|
superglm-0.12.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Max Hicks
|
|
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.
|
superglm-0.12.0/PKG-INFO
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: superglm
|
|
3
|
+
Version: 0.12.0
|
|
4
|
+
Summary: Penalised GLMs for insurance pricing: group lasso, P-splines, Tweedie
|
|
5
|
+
Project-URL: Documentation, https://strudeldoodles.github.io/superglm/
|
|
6
|
+
Project-URL: Homepage, https://github.com/StrudelDoodleS/superglm
|
|
7
|
+
Project-URL: Issues, https://github.com/StrudelDoodleS/superglm/issues
|
|
8
|
+
Project-URL: Repository, https://github.com/StrudelDoodleS/superglm
|
|
9
|
+
Author: Max Hicks
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: actuarial,generalized-additive-models,generalized-linear-models,insurance-pricing,splines
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Requires-Dist: fastapi>=0.115
|
|
27
|
+
Requires-Dist: matplotlib>=3.7
|
|
28
|
+
Requires-Dist: numba>=0.57
|
|
29
|
+
Requires-Dist: numpy>=1.24
|
|
30
|
+
Requires-Dist: openpyxl>=3.1
|
|
31
|
+
Requires-Dist: pandas>=2.0
|
|
32
|
+
Requires-Dist: scikit-learn>=1.3
|
|
33
|
+
Requires-Dist: scipy>=1.10
|
|
34
|
+
Requires-Dist: tabmat>=4.2.1
|
|
35
|
+
Requires-Dist: uvicorn>=0.30
|
|
36
|
+
Provides-Extra: bench
|
|
37
|
+
Requires-Dist: glum>=3.4.1; extra == 'bench'
|
|
38
|
+
Requires-Dist: pyarrow>=10.0; extra == 'bench'
|
|
39
|
+
Requires-Dist: statsmodels>=0.14; extra == 'bench'
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: playwright>=1.55; extra == 'dev'
|
|
42
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
43
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
44
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
46
|
+
Requires-Dist: ty==0.0.61; extra == 'dev'
|
|
47
|
+
Provides-Extra: plotting
|
|
48
|
+
Requires-Dist: plotly>=5.24; extra == 'plotting'
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<img src="https://raw.githubusercontent.com/StrudelDoodleS/superglm/master/docs/images/logo.png" alt="SuperGLM" width="300">
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
[](https://github.com/StrudelDoodleS/superglm/actions/workflows/ci.yml)
|
|
56
|
+
[](https://codecov.io/github/StrudelDoodleS/superglm)
|
|
57
|
+
[](https://github.com/StrudelDoodleS/superglm/actions/workflows/ci.yml)
|
|
58
|
+
|
|
59
|
+
Penalised GLMs and GAM-style pricing models for insurance. SuperGLM combines
|
|
60
|
+
explicit feature specs, exact REML, large-`n` discrete REML, solver-backed
|
|
61
|
+
monotone splines, actuarial validation tooling, and deployable fitted
|
|
62
|
+
estimators for Poisson, Gamma, NB2, Tweedie, Binomial, and Gaussian models.
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
Install SuperGLM from PyPI:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install superglm
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Plotly-based interactive charts are optional:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install "superglm[plotting]"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The local model editor is included in the normal installation.
|
|
79
|
+
|
|
80
|
+
## Recommended Workflow
|
|
81
|
+
|
|
82
|
+
For spline-based pricing models, the default path is:
|
|
83
|
+
|
|
84
|
+
1. define explicit feature specs
|
|
85
|
+
2. fit with `fit_reml()` and `selection_penalty=0`
|
|
86
|
+
3. compare candidates with `cross_validate(..., fit_mode="fit_reml")`
|
|
87
|
+
4. refit on all training data
|
|
88
|
+
5. evaluate holdout Lorenz and double-lift charts
|
|
89
|
+
6. serialize the fitted estimator for scoring
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from superglm import Categorical, Numeric, Spline, SuperGLM
|
|
93
|
+
|
|
94
|
+
features = {
|
|
95
|
+
"DrivAge": Spline(kind="ps", k=14, knot_strategy="quantile_rows"),
|
|
96
|
+
"VehAge": Spline(kind="cr", k=10, knot_strategy="quantile_rows"),
|
|
97
|
+
"BonusMalus": Spline(kind="cr", k=12, knot_strategy="quantile_tempered"),
|
|
98
|
+
"Area": Categorical(base="most_exposed"),
|
|
99
|
+
"LogDensity": Numeric(),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
model = SuperGLM(
|
|
103
|
+
family="poisson",
|
|
104
|
+
selection_penalty=0.0,
|
|
105
|
+
features=features,
|
|
106
|
+
)
|
|
107
|
+
model.fit_reml(train_df, y_train, sample_weight=exposure_train, max_reml_iter=30)
|
|
108
|
+
|
|
109
|
+
mu_holdout = model.predict(holdout_df)
|
|
110
|
+
print(model.summary())
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Choosing A Fit Path
|
|
114
|
+
|
|
115
|
+
### `fit_reml()` with `selection_penalty=0`
|
|
116
|
+
|
|
117
|
+
This is the recommended path for spline-heavy GAM-style pricing models. Use it
|
|
118
|
+
when you want automatic smoothness selection, interpretable smooth terms, and
|
|
119
|
+
mgcv-style modeling rather than sparse screening.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
model = SuperGLM(
|
|
123
|
+
family="poisson",
|
|
124
|
+
selection_penalty=0.0,
|
|
125
|
+
features=features,
|
|
126
|
+
)
|
|
127
|
+
model.fit_reml(df, y, sample_weight=exposure)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### `fit_reml(discrete=True)`
|
|
131
|
+
|
|
132
|
+
Use this when the model is still a REML pricing model, but the data is large
|
|
133
|
+
enough that exact REML becomes expensive. This is the production-scale path for
|
|
134
|
+
large frequency models.
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
model = SuperGLM(
|
|
138
|
+
family="poisson",
|
|
139
|
+
selection_penalty=0.0,
|
|
140
|
+
discrete=True,
|
|
141
|
+
n_bins=256,
|
|
142
|
+
features=features,
|
|
143
|
+
)
|
|
144
|
+
model.fit_reml(df, y, sample_weight=exposure)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### `fit()` with `selection_penalty > 0`
|
|
148
|
+
|
|
149
|
+
Use this when you want sparse screening, compression, or fixed-penalty
|
|
150
|
+
regularisation. This is a different modeling story from REML smoothness
|
|
151
|
+
selection.
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
model = SuperGLM(
|
|
155
|
+
family="poisson",
|
|
156
|
+
penalty="group_elastic_net",
|
|
157
|
+
selection_penalty=0.01,
|
|
158
|
+
spline_penalty=0.1,
|
|
159
|
+
features=features,
|
|
160
|
+
)
|
|
161
|
+
model.fit(df, y, sample_weight=exposure)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### `select=True`
|
|
165
|
+
|
|
166
|
+
`select=True` on spline terms adds mgcv-style double-penalty shrinkage. This is
|
|
167
|
+
the REML-native way to let smooth terms shrink toward linear or zero while
|
|
168
|
+
staying in the `fit_reml()` workflow.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
features = {
|
|
172
|
+
"DrivAge": Spline(kind="ps", k=14, select=True),
|
|
173
|
+
"VehAge": Spline(kind="cr", k=10, select=True),
|
|
174
|
+
"Area": Categorical(base="most_exposed"),
|
|
175
|
+
}
|
|
176
|
+
model = SuperGLM(family="poisson", selection_penalty=0.0, features=features)
|
|
177
|
+
model.fit_reml(df, y, sample_weight=exposure)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Validation And Model Comparison
|
|
181
|
+
|
|
182
|
+
`cross_validate()` should be part of the standard pricing workflow, not an
|
|
183
|
+
afterthought. It gives fold-level metrics, timing, convergence information, and
|
|
184
|
+
out-of-fold predictions for challenger comparisons.
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from sklearn.model_selection import KFold
|
|
188
|
+
from superglm import cross_validate
|
|
189
|
+
from superglm.validation import double_lift_chart, lorenz_curve
|
|
190
|
+
|
|
191
|
+
cv = cross_validate(
|
|
192
|
+
model,
|
|
193
|
+
train_df,
|
|
194
|
+
y_train,
|
|
195
|
+
cv=KFold(n_splits=5, shuffle=True, random_state=42),
|
|
196
|
+
sample_weight=exposure_train,
|
|
197
|
+
fit_mode="fit_reml",
|
|
198
|
+
scoring=("deviance", "nll", "gini"),
|
|
199
|
+
return_oof=True,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
gini = lorenz_curve(y_holdout, mu_holdout, exposure=exposure_holdout)
|
|
203
|
+
lift = double_lift_chart(
|
|
204
|
+
y_obs=y_holdout,
|
|
205
|
+
y_pred_model=mu_holdout,
|
|
206
|
+
y_pred_current=mu_baseline,
|
|
207
|
+
exposure=exposure_holdout,
|
|
208
|
+
)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Key outputs:
|
|
212
|
+
|
|
213
|
+
- `cv.fold_scores`: per-fold metrics, fit time, convergence, and EDF
|
|
214
|
+
- `cv.mean_scores` / `cv.std_scores`: summary comparisons
|
|
215
|
+
- `cv.oof_predictions`: out-of-fold predictions for the training rows
|
|
216
|
+
- `lorenz_curve(...)`: ranking power via Gini
|
|
217
|
+
- `double_lift_chart(...)`: business-facing champion/challenger evidence
|
|
218
|
+
|
|
219
|
+
## Monotone Splines
|
|
220
|
+
|
|
221
|
+
SuperGLM supports solver-backed monotone spline fitting. This is the preferred
|
|
222
|
+
way to enforce business shape constraints inside the model itself.
|
|
223
|
+
|
|
224
|
+
- `BSplineSmooth(..., monotone="increasing", monotone_mode="fit")`:
|
|
225
|
+
constrained QP path
|
|
226
|
+
- `CubicRegressionSpline(..., monotone="decreasing", monotone_mode="fit")`:
|
|
227
|
+
constrained QP path
|
|
228
|
+
- `PSpline(..., monotone="increasing", monotone_mode="fit")`:
|
|
229
|
+
SCOP path
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
from superglm import BSplineSmooth, PSpline, SuperGLM
|
|
233
|
+
|
|
234
|
+
qp_model = SuperGLM(
|
|
235
|
+
family="gaussian",
|
|
236
|
+
selection_penalty=0.0,
|
|
237
|
+
features={
|
|
238
|
+
"x": BSplineSmooth(n_knots=8, monotone="increasing", monotone_mode="fit"),
|
|
239
|
+
},
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
scop_model = SuperGLM(
|
|
243
|
+
family="gaussian",
|
|
244
|
+
selection_penalty=0.0,
|
|
245
|
+
features={
|
|
246
|
+
"x": PSpline(n_knots=10, monotone="increasing", monotone_mode="fit"),
|
|
247
|
+
},
|
|
248
|
+
)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Post-fit isotonic repair still exists, but it should be treated as a manual
|
|
252
|
+
fallback rather than the main monotone workflow.
|
|
253
|
+
|
|
254
|
+
## Feature Highlights
|
|
255
|
+
|
|
256
|
+
- `Spline(kind="ps")`, `Spline(kind="cr")`, and `Spline(kind="ns")` cover the
|
|
257
|
+
main spline basis choices.
|
|
258
|
+
- `OrderedCategorical(...)` smooths ordered factor levels without forcing a
|
|
259
|
+
plain one-hot representation and reports one whole-smooth test rather than
|
|
260
|
+
separate p-values at arbitrary level positions.
|
|
261
|
+
- `collapse_levels(...)` lets you merge sparse categorical levels while still
|
|
262
|
+
expanding back to original levels for inference and plotting.
|
|
263
|
+
- `interactions=[(...)]` supports spline-categorical, numeric-categorical,
|
|
264
|
+
tensor, and other interaction types.
|
|
265
|
+
- `m=(...)` supports multi-order spline penalties with separate REML lambdas.
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
from superglm import Categorical, OrderedCategorical, Spline, collapse_levels
|
|
269
|
+
|
|
270
|
+
area_grouping = collapse_levels(train_df["Area"], groups={"Rural": ["E", "F"]})
|
|
271
|
+
|
|
272
|
+
features = {
|
|
273
|
+
"VehAge": Spline(kind="cr", k=10),
|
|
274
|
+
"Area": Categorical(base="most_exposed", grouping=area_grouping),
|
|
275
|
+
"BonusClass": OrderedCategorical(
|
|
276
|
+
order=["A", "B", "C", "D"],
|
|
277
|
+
basis=Spline(kind="ps", k=6),
|
|
278
|
+
),
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Weights And Offsets
|
|
283
|
+
|
|
284
|
+
Public fitting examples use `sample_weight=`. In insurance settings this means
|
|
285
|
+
exposure / frequency weight, not inverse-variance weight.
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
import numpy as np
|
|
289
|
+
|
|
290
|
+
# Raw count target: offset absorbs exposure, model estimates a rate
|
|
291
|
+
model.fit(df, claim_counts, offset=np.log(exposure))
|
|
292
|
+
|
|
293
|
+
# Rate target: sample_weight carries exposure
|
|
294
|
+
model.fit(df, claim_rate, sample_weight=exposure)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Validation helpers such as `lorenz_curve(...)` and `double_lift_chart(...)`
|
|
298
|
+
still use `exposure=...`, which is correct for that API.
|
|
299
|
+
|
|
300
|
+
## Deployment
|
|
301
|
+
|
|
302
|
+
A fitted `SuperGLM` is the deployment artifact. It already contains:
|
|
303
|
+
|
|
304
|
+
- registered feature specs
|
|
305
|
+
- learned knot geometry and constraints
|
|
306
|
+
- fitted coefficients and intercept
|
|
307
|
+
- REML smoothing parameters
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
import pickle
|
|
311
|
+
|
|
312
|
+
with open("pricing_model.pkl", "wb") as f:
|
|
313
|
+
pickle.dump(model, f)
|
|
314
|
+
|
|
315
|
+
with open("pricing_model.pkl", "rb") as f:
|
|
316
|
+
loaded = pickle.load(f)
|
|
317
|
+
|
|
318
|
+
mu = loaded.predict(score_df)
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
The loaded model can still score, print summaries, rebuild curves, and produce
|
|
322
|
+
relativity views without refitting.
|
|
323
|
+
|
|
324
|
+
## Advanced Penalty Objects
|
|
325
|
+
|
|
326
|
+
At the top-level model API, prefer `selection_penalty=` and `spline_penalty=`.
|
|
327
|
+
Low-level penalty objects still expose `lambda1`, for example:
|
|
328
|
+
|
|
329
|
+
```python
|
|
330
|
+
from superglm import GroupElasticNet
|
|
331
|
+
|
|
332
|
+
penalty = GroupElasticNet(lambda1=0.01, alpha=0.5)
|
|
333
|
+
model = SuperGLM(family="poisson", penalty=penalty, features=features)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
That is advanced usage. It should not be your default starting point.
|
|
337
|
+
|
|
338
|
+
## Learn More
|
|
339
|
+
|
|
340
|
+
- [Recommended workflows](docs/guide/workflows.md)
|
|
341
|
+
- [Choosing a fitting path](docs/guide/fitting.md)
|
|
342
|
+
- [Monotone splines](docs/guide/monotone.md)
|
|
343
|
+
- [Validation and model comparison](docs/guide/validation.md)
|
|
344
|
+
- [Deployment](docs/guide/deployment.md)
|
|
345
|
+
- [Optimization and solver internals](docs/guide/optimization.md)
|