ins-pricing 0.4.5__py3-none-any.whl → 0.5.1__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.
- ins_pricing/README.md +48 -22
- ins_pricing/__init__.py +142 -90
- ins_pricing/cli/BayesOpt_entry.py +58 -46
- ins_pricing/cli/BayesOpt_incremental.py +77 -110
- ins_pricing/cli/Explain_Run.py +42 -23
- ins_pricing/cli/Explain_entry.py +551 -577
- ins_pricing/cli/Pricing_Run.py +42 -23
- ins_pricing/cli/bayesopt_entry_runner.py +51 -16
- ins_pricing/cli/utils/bootstrap.py +23 -0
- ins_pricing/cli/utils/cli_common.py +256 -256
- ins_pricing/cli/utils/cli_config.py +379 -360
- ins_pricing/cli/utils/import_resolver.py +375 -358
- ins_pricing/cli/utils/notebook_utils.py +256 -242
- ins_pricing/cli/watchdog_run.py +216 -198
- ins_pricing/frontend/__init__.py +10 -10
- ins_pricing/frontend/app.py +132 -61
- ins_pricing/frontend/config_builder.py +33 -0
- ins_pricing/frontend/example_config.json +11 -0
- ins_pricing/frontend/example_workflows.py +1 -1
- ins_pricing/frontend/runner.py +340 -388
- ins_pricing/governance/__init__.py +20 -20
- ins_pricing/governance/release.py +159 -159
- ins_pricing/modelling/README.md +1 -1
- ins_pricing/modelling/__init__.py +147 -92
- ins_pricing/modelling/{core/bayesopt → bayesopt}/README.md +31 -13
- ins_pricing/modelling/{core/bayesopt → bayesopt}/__init__.py +64 -102
- ins_pricing/modelling/{core/bayesopt → bayesopt}/config_components.py +12 -0
- ins_pricing/modelling/{core/bayesopt → bayesopt}/config_preprocess.py +589 -552
- ins_pricing/modelling/{core/bayesopt → bayesopt}/core.py +987 -958
- ins_pricing/modelling/{core/bayesopt → bayesopt}/model_explain_mixin.py +296 -296
- ins_pricing/modelling/{core/bayesopt → bayesopt}/model_plotting_mixin.py +488 -548
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/__init__.py +27 -27
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_components.py +349 -342
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_trainer.py +921 -913
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_gnn.py +794 -785
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_resn.py +454 -446
- ins_pricing/modelling/bayesopt/trainers/__init__.py +19 -0
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_base.py +1294 -1282
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_ft.py +64 -56
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_glm.py +203 -198
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_gnn.py +333 -325
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_resn.py +279 -267
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_xgb.py +515 -313
- ins_pricing/modelling/bayesopt/utils/__init__.py +67 -0
- ins_pricing/modelling/bayesopt/utils/constants.py +21 -0
- ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/distributed_utils.py +193 -186
- ins_pricing/modelling/bayesopt/utils/io_utils.py +7 -0
- ins_pricing/modelling/bayesopt/utils/losses.py +27 -0
- ins_pricing/modelling/bayesopt/utils/metrics_and_devices.py +17 -0
- ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/torch_trainer_mixin.py +636 -623
- ins_pricing/modelling/{core/evaluation.py → evaluation.py} +113 -104
- ins_pricing/modelling/explain/__init__.py +55 -55
- ins_pricing/modelling/explain/metrics.py +27 -174
- ins_pricing/modelling/explain/permutation.py +237 -237
- ins_pricing/modelling/plotting/__init__.py +40 -36
- ins_pricing/modelling/plotting/compat.py +228 -0
- ins_pricing/modelling/plotting/curves.py +572 -572
- ins_pricing/modelling/plotting/diagnostics.py +163 -163
- ins_pricing/modelling/plotting/geo.py +362 -362
- ins_pricing/modelling/plotting/importance.py +121 -121
- ins_pricing/pricing/__init__.py +27 -27
- ins_pricing/pricing/factors.py +67 -56
- ins_pricing/production/__init__.py +35 -25
- ins_pricing/production/{predict.py → inference.py} +140 -57
- ins_pricing/production/monitoring.py +8 -21
- ins_pricing/reporting/__init__.py +11 -11
- ins_pricing/setup.py +1 -1
- ins_pricing/tests/production/test_inference.py +90 -0
- ins_pricing/utils/__init__.py +112 -78
- ins_pricing/utils/device.py +258 -237
- ins_pricing/utils/features.py +53 -0
- ins_pricing/utils/io.py +72 -0
- ins_pricing/utils/logging.py +34 -1
- ins_pricing/{modelling/core/bayesopt/utils → utils}/losses.py +125 -129
- ins_pricing/utils/metrics.py +158 -24
- ins_pricing/utils/numerics.py +76 -0
- ins_pricing/utils/paths.py +9 -1
- ins_pricing/utils/profiling.py +8 -4
- {ins_pricing-0.4.5.dist-info → ins_pricing-0.5.1.dist-info}/METADATA +1 -1
- ins_pricing-0.5.1.dist-info/RECORD +132 -0
- ins_pricing/modelling/core/BayesOpt.py +0 -146
- ins_pricing/modelling/core/__init__.py +0 -1
- ins_pricing/modelling/core/bayesopt/trainers/__init__.py +0 -19
- ins_pricing/modelling/core/bayesopt/utils/__init__.py +0 -86
- ins_pricing/modelling/core/bayesopt/utils/constants.py +0 -183
- ins_pricing/modelling/core/bayesopt/utils/io_utils.py +0 -126
- ins_pricing/modelling/core/bayesopt/utils/metrics_and_devices.py +0 -555
- ins_pricing/modelling/core/bayesopt/utils.py +0 -105
- ins_pricing/modelling/core/bayesopt/utils_backup.py +0 -1503
- ins_pricing/tests/production/test_predict.py +0 -233
- ins_pricing-0.4.5.dist-info/RECORD +0 -130
- {ins_pricing-0.4.5.dist-info → ins_pricing-0.5.1.dist-info}/WHEEL +0 -0
- {ins_pricing-0.4.5.dist-info → ins_pricing-0.5.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Iterable, List, Mapping, Optional, Sequence, Tuple
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
from ins_pricing.modelling.plotting.common import PlotStyle, plt
|
|
9
|
+
from ins_pricing.modelling.plotting.curves import (
|
|
10
|
+
plot_double_lift_curve,
|
|
11
|
+
plot_lift_curve,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _safe_tag(value: str) -> str:
|
|
16
|
+
return "".join(ch if ch.isalnum() or ch in "-_." else "_" for ch in str(value))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _to_array(values: Sequence[float], name: str) -> np.ndarray:
|
|
20
|
+
if values is None:
|
|
21
|
+
raise ValueError(f"{name} is required.")
|
|
22
|
+
return np.asarray(values, dtype=float).reshape(-1)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _resolve_pred_pairs_from_df(
|
|
26
|
+
df: pd.DataFrame,
|
|
27
|
+
pred_cols: Optional[Sequence[str] | Mapping[str, object]],
|
|
28
|
+
pred_labels: Optional[Sequence[str]],
|
|
29
|
+
) -> List[Tuple[str, np.ndarray]]:
|
|
30
|
+
if pred_cols is None:
|
|
31
|
+
raise ValueError("pred_cols is required when data is a DataFrame.")
|
|
32
|
+
|
|
33
|
+
pairs: List[Tuple[str, np.ndarray]] = []
|
|
34
|
+
if isinstance(pred_cols, Mapping):
|
|
35
|
+
for label, col in pred_cols.items():
|
|
36
|
+
if isinstance(col, str) and col in df.columns:
|
|
37
|
+
arr = df[col].to_numpy()
|
|
38
|
+
else:
|
|
39
|
+
arr = np.asarray(col, dtype=float).reshape(-1)
|
|
40
|
+
pairs.append((str(label), arr))
|
|
41
|
+
return pairs
|
|
42
|
+
|
|
43
|
+
if isinstance(pred_cols, str):
|
|
44
|
+
label = pred_cols if not pred_labels else str(pred_labels[0])
|
|
45
|
+
return [(label, df[pred_cols].to_numpy())]
|
|
46
|
+
|
|
47
|
+
labels = list(pred_labels) if pred_labels else [str(c) for c in pred_cols]
|
|
48
|
+
for col, label in zip(pred_cols, labels):
|
|
49
|
+
if isinstance(col, str) and col in df.columns:
|
|
50
|
+
arr = df[col].to_numpy()
|
|
51
|
+
else:
|
|
52
|
+
arr = np.asarray(col, dtype=float).reshape(-1)
|
|
53
|
+
pairs.append((str(label), arr))
|
|
54
|
+
return pairs
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _resolve_pred_pairs_from_arrays(
|
|
58
|
+
preds: object,
|
|
59
|
+
pred_labels: Optional[Sequence[str]],
|
|
60
|
+
) -> List[Tuple[str, np.ndarray]]:
|
|
61
|
+
if isinstance(preds, Mapping):
|
|
62
|
+
return [(str(k), np.asarray(v, dtype=float).reshape(-1)) for k, v in preds.items()]
|
|
63
|
+
|
|
64
|
+
if isinstance(preds, (list, tuple)):
|
|
65
|
+
labels = list(pred_labels) if pred_labels else [f"model_{idx + 1}" for idx in range(len(preds))]
|
|
66
|
+
return [
|
|
67
|
+
(str(label), np.asarray(arr, dtype=float).reshape(-1))
|
|
68
|
+
for label, arr in zip(labels, preds)
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
return [("model_1", np.asarray(preds, dtype=float).reshape(-1))]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def plot_lift_list(
|
|
75
|
+
data_or_preds: pd.DataFrame | Mapping[str, object] | Sequence[object],
|
|
76
|
+
pred_cols: Optional[Sequence[str] | Mapping[str, object]] = None,
|
|
77
|
+
actual: Optional[Sequence[float]] = None,
|
|
78
|
+
weight: Optional[Sequence[float]] = None,
|
|
79
|
+
*,
|
|
80
|
+
actual_col: str = "w_act",
|
|
81
|
+
weight_col: str = "weight",
|
|
82
|
+
pred_labels: Optional[Sequence[str]] = None,
|
|
83
|
+
n_bins: int = 10,
|
|
84
|
+
pred_weighted: bool = False,
|
|
85
|
+
actual_weighted: bool = True,
|
|
86
|
+
show: bool = False,
|
|
87
|
+
save_dir: Optional[str] = None,
|
|
88
|
+
filename_prefix: str = "lift",
|
|
89
|
+
style: Optional[PlotStyle] = None,
|
|
90
|
+
) -> List[plt.Figure]:
|
|
91
|
+
"""Compatibility helper: plot multiple lift curves in one call."""
|
|
92
|
+
if isinstance(data_or_preds, pd.DataFrame):
|
|
93
|
+
df = data_or_preds
|
|
94
|
+
pairs = _resolve_pred_pairs_from_df(df, pred_cols, pred_labels)
|
|
95
|
+
actual_arr = _to_array(df[actual_col], actual_col) if actual is None else _to_array(actual, "actual")
|
|
96
|
+
weight_arr = None
|
|
97
|
+
if weight is not None:
|
|
98
|
+
weight_arr = _to_array(weight, "weight")
|
|
99
|
+
elif weight_col in df.columns:
|
|
100
|
+
weight_arr = _to_array(df[weight_col], weight_col)
|
|
101
|
+
else:
|
|
102
|
+
pairs = _resolve_pred_pairs_from_arrays(data_or_preds, pred_labels)
|
|
103
|
+
actual_arr = _to_array(actual, "actual")
|
|
104
|
+
weight_arr = _to_array(weight, "weight") if weight is not None else None
|
|
105
|
+
|
|
106
|
+
figs: List[plt.Figure] = []
|
|
107
|
+
for label, pred in pairs:
|
|
108
|
+
save_path = None
|
|
109
|
+
if save_dir:
|
|
110
|
+
safe_dir = save_dir.rstrip("/\\")
|
|
111
|
+
save_path = f"{safe_dir}/{filename_prefix}_{_safe_tag(label)}.png"
|
|
112
|
+
fig = plot_lift_curve(
|
|
113
|
+
pred,
|
|
114
|
+
actual_arr,
|
|
115
|
+
weight_arr,
|
|
116
|
+
n_bins=n_bins,
|
|
117
|
+
title=f"{label} Lift Chart",
|
|
118
|
+
pred_label="Predicted",
|
|
119
|
+
act_label="Actual",
|
|
120
|
+
weight_label="Earned Exposure",
|
|
121
|
+
pred_weighted=pred_weighted,
|
|
122
|
+
actual_weighted=actual_weighted,
|
|
123
|
+
show=show,
|
|
124
|
+
save_path=save_path,
|
|
125
|
+
style=style,
|
|
126
|
+
)
|
|
127
|
+
figs.append(fig)
|
|
128
|
+
return figs
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def plot_dlift_list(
|
|
132
|
+
data_or_preds: pd.DataFrame | Mapping[str, object] | Sequence[object],
|
|
133
|
+
pred_cols: Optional[Sequence[str] | Mapping[str, object]] = None,
|
|
134
|
+
actual: Optional[Sequence[float]] = None,
|
|
135
|
+
weight: Optional[Sequence[float]] = None,
|
|
136
|
+
*,
|
|
137
|
+
actual_col: str = "w_act",
|
|
138
|
+
weight_col: str = "weight",
|
|
139
|
+
pred_labels: Optional[Sequence[str]] = None,
|
|
140
|
+
pairs: Optional[Iterable[Tuple[object, object]]] = None,
|
|
141
|
+
n_bins: int = 10,
|
|
142
|
+
pred_weighted: bool = False,
|
|
143
|
+
actual_weighted: bool = True,
|
|
144
|
+
show: bool = False,
|
|
145
|
+
save_dir: Optional[str] = None,
|
|
146
|
+
filename_prefix: str = "double_lift",
|
|
147
|
+
style: Optional[PlotStyle] = None,
|
|
148
|
+
) -> List[plt.Figure]:
|
|
149
|
+
"""Compatibility helper: plot double-lift curves for multiple model pairs."""
|
|
150
|
+
if isinstance(data_or_preds, pd.DataFrame):
|
|
151
|
+
df = data_or_preds
|
|
152
|
+
pairs_list = _resolve_pred_pairs_from_df(df, pred_cols, pred_labels)
|
|
153
|
+
actual_arr = _to_array(df[actual_col], actual_col) if actual is None else _to_array(actual, "actual")
|
|
154
|
+
weight_arr = None
|
|
155
|
+
if weight is not None:
|
|
156
|
+
weight_arr = _to_array(weight, "weight")
|
|
157
|
+
elif weight_col in df.columns:
|
|
158
|
+
weight_arr = _to_array(df[weight_col], weight_col)
|
|
159
|
+
else:
|
|
160
|
+
pairs_list = _resolve_pred_pairs_from_arrays(data_or_preds, pred_labels)
|
|
161
|
+
actual_arr = _to_array(actual, "actual")
|
|
162
|
+
weight_arr = _to_array(weight, "weight") if weight is not None else None
|
|
163
|
+
|
|
164
|
+
pred_map = {label: arr for label, arr in pairs_list}
|
|
165
|
+
labels = [label for label, _ in pairs_list]
|
|
166
|
+
|
|
167
|
+
pair_labels: List[Tuple[str, str]] = []
|
|
168
|
+
if pairs is None:
|
|
169
|
+
for idx, first in enumerate(labels):
|
|
170
|
+
for second in labels[idx + 1 :]:
|
|
171
|
+
pair_labels.append((first, second))
|
|
172
|
+
else:
|
|
173
|
+
for left, right in pairs:
|
|
174
|
+
if isinstance(left, int):
|
|
175
|
+
left_label = labels[left]
|
|
176
|
+
else:
|
|
177
|
+
left_label = str(left)
|
|
178
|
+
if isinstance(right, int):
|
|
179
|
+
right_label = labels[right]
|
|
180
|
+
else:
|
|
181
|
+
right_label = str(right)
|
|
182
|
+
pair_labels.append((left_label, right_label))
|
|
183
|
+
|
|
184
|
+
figs: List[plt.Figure] = []
|
|
185
|
+
for label1, label2 in pair_labels:
|
|
186
|
+
pred1 = pred_map.get(label1)
|
|
187
|
+
pred2 = pred_map.get(label2)
|
|
188
|
+
if pred1 is None or pred2 is None:
|
|
189
|
+
continue
|
|
190
|
+
save_path = None
|
|
191
|
+
if save_dir:
|
|
192
|
+
safe_dir = save_dir.rstrip("/\\")
|
|
193
|
+
tag = f"{_safe_tag(label1)}_vs_{_safe_tag(label2)}"
|
|
194
|
+
save_path = f"{safe_dir}/{filename_prefix}_{tag}.png"
|
|
195
|
+
fig = plot_double_lift_curve(
|
|
196
|
+
pred1,
|
|
197
|
+
pred2,
|
|
198
|
+
actual_arr,
|
|
199
|
+
weight_arr,
|
|
200
|
+
n_bins=n_bins,
|
|
201
|
+
title=f"Double Lift: {label1} vs {label2}",
|
|
202
|
+
label1=label1,
|
|
203
|
+
label2=label2,
|
|
204
|
+
pred1_weighted=pred_weighted,
|
|
205
|
+
pred2_weighted=pred_weighted,
|
|
206
|
+
actual_weighted=actual_weighted,
|
|
207
|
+
show=show,
|
|
208
|
+
save_path=save_path,
|
|
209
|
+
style=style,
|
|
210
|
+
)
|
|
211
|
+
figs.append(fig)
|
|
212
|
+
return figs
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class PlotUtils:
|
|
216
|
+
"""Compatibility wrapper for legacy plotting helpers."""
|
|
217
|
+
|
|
218
|
+
plot_lift_curve = staticmethod(plot_lift_curve)
|
|
219
|
+
plot_double_lift_curve = staticmethod(plot_double_lift_curve)
|
|
220
|
+
plot_lift_list = staticmethod(plot_lift_list)
|
|
221
|
+
plot_dlift_list = staticmethod(plot_dlift_list)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
__all__ = [
|
|
225
|
+
"PlotUtils",
|
|
226
|
+
"plot_lift_list",
|
|
227
|
+
"plot_dlift_list",
|
|
228
|
+
]
|