ins-pricing 0.4.4__py3-none-any.whl → 0.5.0__py3-none-any.whl

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.
Files changed (96) hide show
  1. ins_pricing/README.md +74 -56
  2. ins_pricing/__init__.py +142 -90
  3. ins_pricing/cli/BayesOpt_entry.py +52 -50
  4. ins_pricing/cli/BayesOpt_incremental.py +832 -898
  5. ins_pricing/cli/Explain_Run.py +31 -23
  6. ins_pricing/cli/Explain_entry.py +532 -579
  7. ins_pricing/cli/Pricing_Run.py +31 -23
  8. ins_pricing/cli/bayesopt_entry_runner.py +1440 -1438
  9. ins_pricing/cli/utils/cli_common.py +256 -256
  10. ins_pricing/cli/utils/cli_config.py +375 -375
  11. ins_pricing/cli/utils/import_resolver.py +382 -365
  12. ins_pricing/cli/utils/notebook_utils.py +340 -340
  13. ins_pricing/cli/watchdog_run.py +209 -201
  14. ins_pricing/frontend/README.md +573 -419
  15. ins_pricing/frontend/__init__.py +10 -10
  16. ins_pricing/frontend/config_builder.py +1 -0
  17. ins_pricing/frontend/example_workflows.py +1 -1
  18. ins_pricing/governance/__init__.py +20 -20
  19. ins_pricing/governance/release.py +159 -159
  20. ins_pricing/modelling/README.md +67 -0
  21. ins_pricing/modelling/__init__.py +147 -92
  22. ins_pricing/modelling/bayesopt/README.md +59 -0
  23. ins_pricing/modelling/{core/bayesopt → bayesopt}/__init__.py +64 -102
  24. ins_pricing/modelling/{core/bayesopt → bayesopt}/config_preprocess.py +562 -550
  25. ins_pricing/modelling/{core/bayesopt → bayesopt}/core.py +965 -962
  26. ins_pricing/modelling/{core/bayesopt → bayesopt}/model_explain_mixin.py +296 -296
  27. ins_pricing/modelling/{core/bayesopt → bayesopt}/model_plotting_mixin.py +482 -548
  28. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/__init__.py +27 -27
  29. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_trainer.py +915 -913
  30. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_gnn.py +788 -785
  31. ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_resn.py +448 -446
  32. ins_pricing/modelling/bayesopt/trainers/__init__.py +19 -0
  33. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_base.py +1308 -1308
  34. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_ft.py +3 -3
  35. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_glm.py +197 -198
  36. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_gnn.py +344 -344
  37. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_resn.py +283 -283
  38. ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_xgb.py +346 -347
  39. ins_pricing/modelling/bayesopt/utils/__init__.py +67 -0
  40. ins_pricing/modelling/bayesopt/utils/constants.py +21 -0
  41. ins_pricing/modelling/bayesopt/utils/io_utils.py +7 -0
  42. ins_pricing/modelling/bayesopt/utils/losses.py +27 -0
  43. ins_pricing/modelling/bayesopt/utils/metrics_and_devices.py +17 -0
  44. ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/torch_trainer_mixin.py +623 -623
  45. ins_pricing/modelling/{core/evaluation.py → evaluation.py} +113 -104
  46. ins_pricing/modelling/explain/__init__.py +55 -55
  47. ins_pricing/modelling/explain/metrics.py +27 -174
  48. ins_pricing/modelling/explain/permutation.py +237 -237
  49. ins_pricing/modelling/plotting/__init__.py +40 -36
  50. ins_pricing/modelling/plotting/compat.py +228 -0
  51. ins_pricing/modelling/plotting/curves.py +572 -572
  52. ins_pricing/modelling/plotting/diagnostics.py +163 -163
  53. ins_pricing/modelling/plotting/geo.py +362 -362
  54. ins_pricing/modelling/plotting/importance.py +121 -121
  55. ins_pricing/pricing/__init__.py +27 -27
  56. ins_pricing/production/__init__.py +35 -25
  57. ins_pricing/production/{predict.py → inference.py} +140 -57
  58. ins_pricing/production/monitoring.py +8 -21
  59. ins_pricing/reporting/__init__.py +11 -11
  60. ins_pricing/setup.py +1 -1
  61. ins_pricing/tests/production/test_inference.py +90 -0
  62. ins_pricing/utils/__init__.py +116 -83
  63. ins_pricing/utils/device.py +255 -255
  64. ins_pricing/utils/features.py +53 -0
  65. ins_pricing/utils/io.py +72 -0
  66. ins_pricing/{modelling/core/bayesopt/utils → utils}/losses.py +125 -129
  67. ins_pricing/utils/metrics.py +158 -24
  68. ins_pricing/utils/numerics.py +76 -0
  69. ins_pricing/utils/paths.py +9 -1
  70. {ins_pricing-0.4.4.dist-info → ins_pricing-0.5.0.dist-info}/METADATA +55 -35
  71. ins_pricing-0.5.0.dist-info/RECORD +131 -0
  72. ins_pricing/CHANGELOG.md +0 -272
  73. ins_pricing/RELEASE_NOTES_0.2.8.md +0 -344
  74. ins_pricing/docs/LOSS_FUNCTIONS.md +0 -78
  75. ins_pricing/docs/modelling/BayesOpt_USAGE.md +0 -945
  76. ins_pricing/docs/modelling/README.md +0 -34
  77. ins_pricing/frontend/QUICKSTART.md +0 -152
  78. ins_pricing/modelling/core/BayesOpt.py +0 -146
  79. ins_pricing/modelling/core/__init__.py +0 -1
  80. ins_pricing/modelling/core/bayesopt/PHASE2_REFACTORING_SUMMARY.md +0 -449
  81. ins_pricing/modelling/core/bayesopt/PHASE3_REFACTORING_SUMMARY.md +0 -406
  82. ins_pricing/modelling/core/bayesopt/REFACTORING_SUMMARY.md +0 -247
  83. ins_pricing/modelling/core/bayesopt/trainers/__init__.py +0 -19
  84. ins_pricing/modelling/core/bayesopt/utils/__init__.py +0 -86
  85. ins_pricing/modelling/core/bayesopt/utils/constants.py +0 -183
  86. ins_pricing/modelling/core/bayesopt/utils/io_utils.py +0 -126
  87. ins_pricing/modelling/core/bayesopt/utils/metrics_and_devices.py +0 -555
  88. ins_pricing/modelling/core/bayesopt/utils.py +0 -105
  89. ins_pricing/modelling/core/bayesopt/utils_backup.py +0 -1503
  90. ins_pricing/tests/production/test_predict.py +0 -233
  91. ins_pricing-0.4.4.dist-info/RECORD +0 -137
  92. /ins_pricing/modelling/{core/bayesopt → bayesopt}/config_components.py +0 -0
  93. /ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_components.py +0 -0
  94. /ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/distributed_utils.py +0 -0
  95. {ins_pricing-0.4.4.dist-info → ins_pricing-0.5.0.dist-info}/WHEEL +0 -0
  96. {ins_pricing-0.4.4.dist-info → ins_pricing-0.5.0.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,10 @@
1
- """
2
- Insurance Pricing Frontend Package
3
- Web-based interface for configuring and running insurance pricing model tasks.
4
- """
5
-
6
- from .config_builder import ConfigBuilder
7
- from .runner import TaskRunner, TrainingRunner
8
- from .ft_workflow import FTWorkflowHelper
9
-
10
- __all__ = ['ConfigBuilder', 'TaskRunner', 'TrainingRunner', 'FTWorkflowHelper']
1
+ """
2
+ Insurance Pricing Frontend Package
3
+ Web-based interface for configuring and running insurance pricing model tasks.
4
+ """
5
+
6
+ from ins_pricing.frontend.config_builder import ConfigBuilder
7
+ from ins_pricing.frontend.runner import TaskRunner, TrainingRunner
8
+ from ins_pricing.frontend.ft_workflow import FTWorkflowHelper
9
+
10
+ __all__ = ['ConfigBuilder', 'TaskRunner', 'TrainingRunner', 'FTWorkflowHelper']
@@ -32,6 +32,7 @@ class ConfigBuilder:
32
32
  "save_preprocess": False,
33
33
  "preprocess_artifact_path": None,
34
34
  "bo_sample_limit": None,
35
+ "build_oht": True,
35
36
  "cache_predictions": False,
36
37
  "prediction_cache_dir": None,
37
38
  "prediction_cache_format": "parquet",
@@ -19,7 +19,7 @@ from ins_pricing.modelling.plotting import (
19
19
  plot_oneway,
20
20
  )
21
21
  from ins_pricing.modelling.plotting.common import finalize_figure, plt
22
- from ins_pricing.production.predict import load_predictor_from_config
22
+ from ins_pricing.production.inference import load_predictor_from_config
23
23
 
24
24
 
25
25
  def _parse_csv_list(value: str) -> List[str]:
@@ -1,20 +1,20 @@
1
- from __future__ import annotations
2
-
3
- from .approval import ApprovalAction, ApprovalRequest, ApprovalStore
4
- from .audit import AuditEvent, AuditLogger
5
- from .registry import ModelArtifact, ModelRegistry, ModelVersion
6
- from .release import DeploymentState, ModelRef, ReleaseManager
7
-
8
- __all__ = [
9
- "ApprovalAction",
10
- "ApprovalRequest",
11
- "ApprovalStore",
12
- "AuditEvent",
13
- "AuditLogger",
14
- "ModelArtifact",
15
- "ModelRegistry",
16
- "ModelVersion",
17
- "DeploymentState",
18
- "ModelRef",
19
- "ReleaseManager",
20
- ]
1
+ from __future__ import annotations
2
+
3
+ from ins_pricing.governance.approval import ApprovalAction, ApprovalRequest, ApprovalStore
4
+ from ins_pricing.governance.audit import AuditEvent, AuditLogger
5
+ from ins_pricing.governance.registry import ModelArtifact, ModelRegistry, ModelVersion
6
+ from ins_pricing.governance.release import DeploymentState, ModelRef, ReleaseManager
7
+
8
+ __all__ = [
9
+ "ApprovalAction",
10
+ "ApprovalRequest",
11
+ "ApprovalStore",
12
+ "AuditEvent",
13
+ "AuditLogger",
14
+ "ModelArtifact",
15
+ "ModelRegistry",
16
+ "ModelVersion",
17
+ "DeploymentState",
18
+ "ModelRef",
19
+ "ReleaseManager",
20
+ ]
@@ -1,159 +1,159 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from dataclasses import asdict, dataclass, field
5
- from datetime import datetime
6
- from pathlib import Path
7
- from typing import List, Optional
8
-
9
- from .audit import AuditLogger
10
- from .registry import ModelRegistry
11
-
12
-
13
- @dataclass
14
- class ModelRef:
15
- name: str
16
- version: str
17
- activated_at: str
18
- actor: Optional[str] = None
19
- note: Optional[str] = None
20
-
21
-
22
- @dataclass
23
- class DeploymentState:
24
- env: str
25
- active: Optional[ModelRef] = None
26
- history: List[ModelRef] = field(default_factory=list)
27
- updated_at: Optional[str] = None
28
-
29
-
30
- class ReleaseManager:
31
- """Environment release manager with rollback support."""
32
-
33
- def __init__(
34
- self,
35
- state_dir: str | Path,
36
- *,
37
- registry: Optional[ModelRegistry] = None,
38
- audit_logger: Optional[AuditLogger] = None,
39
- ):
40
- self.state_dir = Path(state_dir)
41
- self.state_dir.mkdir(parents=True, exist_ok=True)
42
- self.registry = registry
43
- self.audit_logger = audit_logger
44
-
45
- def _state_path(self, env: str) -> Path:
46
- return self.state_dir / f"{env}.json"
47
-
48
- def _load(self, env: str) -> DeploymentState:
49
- path = self._state_path(env)
50
- if not path.exists():
51
- return DeploymentState(env=env)
52
- with path.open("r", encoding="utf-8") as fh:
53
- payload = json.load(fh)
54
- active = payload.get("active")
55
- history = payload.get("history", [])
56
- return DeploymentState(
57
- env=payload.get("env", env),
58
- active=ModelRef(**active) if active else None,
59
- history=[ModelRef(**item) for item in history],
60
- updated_at=payload.get("updated_at"),
61
- )
62
-
63
- def _save(self, state: DeploymentState) -> None:
64
- payload = {
65
- "env": state.env,
66
- "active": asdict(state.active) if state.active else None,
67
- "history": [asdict(item) for item in state.history],
68
- "updated_at": state.updated_at,
69
- }
70
- path = self._state_path(state.env)
71
- with path.open("w", encoding="utf-8") as fh:
72
- json.dump(payload, fh, indent=2, ensure_ascii=True)
73
-
74
- def get_active(self, env: str) -> Optional[ModelRef]:
75
- state = self._load(env)
76
- return state.active
77
-
78
- def list_history(self, env: str) -> List[ModelRef]:
79
- return self._load(env).history
80
-
81
- def deploy(
82
- self,
83
- env: str,
84
- name: str,
85
- version: str,
86
- *,
87
- actor: Optional[str] = None,
88
- note: Optional[str] = None,
89
- update_registry_status: bool = True,
90
- registry_status: str = "production",
91
- ) -> DeploymentState:
92
- state = self._load(env)
93
- if state.active and state.active.name == name and state.active.version == version:
94
- return state
95
-
96
- if state.active is not None:
97
- state.history.append(state.active)
98
-
99
- now = datetime.utcnow().isoformat()
100
- state.active = ModelRef(
101
- name=name,
102
- version=version,
103
- activated_at=now,
104
- actor=actor,
105
- note=note,
106
- )
107
- state.updated_at = now
108
- self._save(state)
109
-
110
- if self.registry and update_registry_status:
111
- self.registry.promote(name, version, new_status=registry_status)
112
-
113
- if self.audit_logger:
114
- self.audit_logger.log(
115
- "deploy",
116
- actor or "unknown",
117
- metadata={"env": env, "name": name, "version": version},
118
- note=note,
119
- )
120
-
121
- return state
122
-
123
- def rollback(
124
- self,
125
- env: str,
126
- *,
127
- actor: Optional[str] = None,
128
- note: Optional[str] = None,
129
- update_registry_status: bool = False,
130
- registry_status: str = "production",
131
- ) -> DeploymentState:
132
- state = self._load(env)
133
- if not state.history:
134
- raise ValueError("No history available to rollback.")
135
-
136
- previous = state.history.pop()
137
- now = datetime.utcnow().isoformat()
138
- state.active = ModelRef(
139
- name=previous.name,
140
- version=previous.version,
141
- activated_at=now,
142
- actor=actor or previous.actor,
143
- note=note or previous.note,
144
- )
145
- state.updated_at = now
146
- self._save(state)
147
-
148
- if self.registry and update_registry_status:
149
- self.registry.promote(previous.name, previous.version, new_status=registry_status)
150
-
151
- if self.audit_logger:
152
- self.audit_logger.log(
153
- "rollback",
154
- actor or "unknown",
155
- metadata={"env": env, "name": previous.name, "version": previous.version},
156
- note=note,
157
- )
158
-
159
- return state
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from dataclasses import asdict, dataclass, field
5
+ from datetime import datetime
6
+ from pathlib import Path
7
+ from typing import List, Optional
8
+
9
+ from ins_pricing.governance.audit import AuditLogger
10
+ from ins_pricing.governance.registry import ModelRegistry
11
+
12
+
13
+ @dataclass
14
+ class ModelRef:
15
+ name: str
16
+ version: str
17
+ activated_at: str
18
+ actor: Optional[str] = None
19
+ note: Optional[str] = None
20
+
21
+
22
+ @dataclass
23
+ class DeploymentState:
24
+ env: str
25
+ active: Optional[ModelRef] = None
26
+ history: List[ModelRef] = field(default_factory=list)
27
+ updated_at: Optional[str] = None
28
+
29
+
30
+ class ReleaseManager:
31
+ """Environment release manager with rollback support."""
32
+
33
+ def __init__(
34
+ self,
35
+ state_dir: str | Path,
36
+ *,
37
+ registry: Optional[ModelRegistry] = None,
38
+ audit_logger: Optional[AuditLogger] = None,
39
+ ):
40
+ self.state_dir = Path(state_dir)
41
+ self.state_dir.mkdir(parents=True, exist_ok=True)
42
+ self.registry = registry
43
+ self.audit_logger = audit_logger
44
+
45
+ def _state_path(self, env: str) -> Path:
46
+ return self.state_dir / f"{env}.json"
47
+
48
+ def _load(self, env: str) -> DeploymentState:
49
+ path = self._state_path(env)
50
+ if not path.exists():
51
+ return DeploymentState(env=env)
52
+ with path.open("r", encoding="utf-8") as fh:
53
+ payload = json.load(fh)
54
+ active = payload.get("active")
55
+ history = payload.get("history", [])
56
+ return DeploymentState(
57
+ env=payload.get("env", env),
58
+ active=ModelRef(**active) if active else None,
59
+ history=[ModelRef(**item) for item in history],
60
+ updated_at=payload.get("updated_at"),
61
+ )
62
+
63
+ def _save(self, state: DeploymentState) -> None:
64
+ payload = {
65
+ "env": state.env,
66
+ "active": asdict(state.active) if state.active else None,
67
+ "history": [asdict(item) for item in state.history],
68
+ "updated_at": state.updated_at,
69
+ }
70
+ path = self._state_path(state.env)
71
+ with path.open("w", encoding="utf-8") as fh:
72
+ json.dump(payload, fh, indent=2, ensure_ascii=True)
73
+
74
+ def get_active(self, env: str) -> Optional[ModelRef]:
75
+ state = self._load(env)
76
+ return state.active
77
+
78
+ def list_history(self, env: str) -> List[ModelRef]:
79
+ return self._load(env).history
80
+
81
+ def deploy(
82
+ self,
83
+ env: str,
84
+ name: str,
85
+ version: str,
86
+ *,
87
+ actor: Optional[str] = None,
88
+ note: Optional[str] = None,
89
+ update_registry_status: bool = True,
90
+ registry_status: str = "production",
91
+ ) -> DeploymentState:
92
+ state = self._load(env)
93
+ if state.active and state.active.name == name and state.active.version == version:
94
+ return state
95
+
96
+ if state.active is not None:
97
+ state.history.append(state.active)
98
+
99
+ now = datetime.utcnow().isoformat()
100
+ state.active = ModelRef(
101
+ name=name,
102
+ version=version,
103
+ activated_at=now,
104
+ actor=actor,
105
+ note=note,
106
+ )
107
+ state.updated_at = now
108
+ self._save(state)
109
+
110
+ if self.registry and update_registry_status:
111
+ self.registry.promote(name, version, new_status=registry_status)
112
+
113
+ if self.audit_logger:
114
+ self.audit_logger.log(
115
+ "deploy",
116
+ actor or "unknown",
117
+ metadata={"env": env, "name": name, "version": version},
118
+ note=note,
119
+ )
120
+
121
+ return state
122
+
123
+ def rollback(
124
+ self,
125
+ env: str,
126
+ *,
127
+ actor: Optional[str] = None,
128
+ note: Optional[str] = None,
129
+ update_registry_status: bool = False,
130
+ registry_status: str = "production",
131
+ ) -> DeploymentState:
132
+ state = self._load(env)
133
+ if not state.history:
134
+ raise ValueError("No history available to rollback.")
135
+
136
+ previous = state.history.pop()
137
+ now = datetime.utcnow().isoformat()
138
+ state.active = ModelRef(
139
+ name=previous.name,
140
+ version=previous.version,
141
+ activated_at=now,
142
+ actor=actor or previous.actor,
143
+ note=note or previous.note,
144
+ )
145
+ state.updated_at = now
146
+ self._save(state)
147
+
148
+ if self.registry and update_registry_status:
149
+ self.registry.promote(previous.name, previous.version, new_status=registry_status)
150
+
151
+ if self.audit_logger:
152
+ self.audit_logger.log(
153
+ "rollback",
154
+ actor or "unknown",
155
+ metadata={"env": env, "name": previous.name, "version": previous.version},
156
+ note=note,
157
+ )
158
+
159
+ return state
@@ -0,0 +1,67 @@
1
+ # Modelling
2
+
3
+ This directory contains reusable training tooling and frameworks centered on BayesOpt.
4
+
5
+ ## Key locations
6
+
7
+ - `core/bayesopt/` - core training/tuning package
8
+ - `explain/` - explainability helpers
9
+ - `plotting/` - plotting utilities
10
+ - `ins_pricing/cli/` - CLI entry points
11
+ - `examples/` - example configs and notebooks (repo only)
12
+
13
+ ## Common usage
14
+
15
+ - CLI training: `python ins_pricing/cli/BayesOpt_entry.py --config-json config_template.json`
16
+ - Notebook API: `from ins_pricing.modelling import BayesOptModel`
17
+
18
+ ## Explainability
19
+
20
+ - CLI: `python ins_pricing/cli/Explain_entry.py --config-json config_explain_template.json`
21
+ - Notebook: `examples/04 Explain_Run.ipynb`
22
+
23
+ ## Loss functions
24
+
25
+ Configure the regression/classification loss with `loss_name` in the BayesOpt config.
26
+
27
+ Supported `loss_name` values:
28
+ - `auto` (default): legacy behavior based on model name
29
+ - `tweedie`: Tweedie deviance
30
+ - `poisson`: Poisson deviance
31
+ - `gamma`: Gamma deviance
32
+ - `mse`: mean squared error
33
+ - `mae`: mean absolute error
34
+
35
+ Mapping summary:
36
+ - Tweedie deviance -> `tweedie`
37
+ - Poisson deviance -> `poisson`
38
+ - Gamma deviance -> `gamma`
39
+ - Mean squared error -> `mse`
40
+ - Mean absolute error -> `mae`
41
+ - Classification log loss -> `logloss` (classification only)
42
+ - Classification BCE -> `bce` (classification only)
43
+
44
+ Classification tasks:
45
+ - `loss_name` can be `auto`, `logloss`, or `bce`.
46
+ - Training uses `BCEWithLogits` for torch models; evaluation uses log loss.
47
+
48
+ Where to set `loss_name`:
49
+
50
+ ```json
51
+ {
52
+ "task_type": "regression",
53
+ "loss_name": "mse"
54
+ }
55
+ ```
56
+
57
+ Behavior notes:
58
+ - When `loss_name` is `mse` or `mae`, tuning does not sample Tweedie power.
59
+ - When `loss_name` is `poisson` or `gamma`, power is fixed (1.0 / 2.0).
60
+ - When `loss_name` is `tweedie`, power is sampled as usual.
61
+ - XGBoost objective is selected from the loss name.
62
+
63
+ ## Notes
64
+
65
+ - Models load from `output_dir/model` by default (override with `explain.model_dir`).
66
+ - Training outputs are written to `plot/`, `Results/`, and `model/` under `output_dir`.
67
+ - Keep large data and secrets outside the repo; use environment variables or `.env` files.