ins-pricing 0.4.5__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.
- ins_pricing/README.md +48 -22
- ins_pricing/__init__.py +142 -90
- ins_pricing/cli/BayesOpt_entry.py +52 -50
- ins_pricing/cli/BayesOpt_incremental.py +39 -105
- ins_pricing/cli/Explain_Run.py +31 -23
- ins_pricing/cli/Explain_entry.py +532 -579
- ins_pricing/cli/Pricing_Run.py +31 -23
- ins_pricing/cli/bayesopt_entry_runner.py +11 -9
- ins_pricing/cli/utils/cli_common.py +256 -256
- ins_pricing/cli/utils/cli_config.py +375 -375
- ins_pricing/cli/utils/import_resolver.py +382 -365
- ins_pricing/cli/utils/notebook_utils.py +340 -340
- ins_pricing/cli/watchdog_run.py +209 -201
- ins_pricing/frontend/__init__.py +10 -10
- ins_pricing/frontend/example_workflows.py +1 -1
- ins_pricing/governance/__init__.py +20 -20
- ins_pricing/governance/release.py +159 -159
- ins_pricing/modelling/__init__.py +147 -92
- ins_pricing/modelling/{core/bayesopt → bayesopt}/README.md +2 -2
- ins_pricing/modelling/{core/bayesopt → bayesopt}/__init__.py +64 -102
- ins_pricing/modelling/{core/bayesopt → bayesopt}/config_preprocess.py +562 -562
- ins_pricing/modelling/{core/bayesopt → bayesopt}/core.py +965 -964
- ins_pricing/modelling/{core/bayesopt → bayesopt}/model_explain_mixin.py +296 -296
- ins_pricing/modelling/{core/bayesopt → bayesopt}/model_plotting_mixin.py +482 -548
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/__init__.py +27 -27
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_trainer.py +915 -913
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_gnn.py +788 -785
- ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_resn.py +448 -446
- ins_pricing/modelling/bayesopt/trainers/__init__.py +19 -0
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_base.py +1308 -1308
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_ft.py +3 -3
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_glm.py +197 -198
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_gnn.py +344 -344
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_resn.py +283 -283
- ins_pricing/modelling/{core/bayesopt → bayesopt}/trainers/trainer_xgb.py +346 -347
- ins_pricing/modelling/bayesopt/utils/__init__.py +67 -0
- ins_pricing/modelling/bayesopt/utils/constants.py +21 -0
- 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 +623 -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/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 +116 -83
- ins_pricing/utils/device.py +255 -255
- ins_pricing/utils/features.py +53 -0
- ins_pricing/utils/io.py +72 -0
- 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-0.4.5.dist-info → ins_pricing-0.5.0.dist-info}/METADATA +182 -182
- ins_pricing-0.5.0.dist-info/RECORD +131 -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/modelling/{core/bayesopt → bayesopt}/config_components.py +0 -0
- /ins_pricing/modelling/{core/bayesopt → bayesopt}/models/model_ft_components.py +0 -0
- /ins_pricing/modelling/{core/bayesopt → bayesopt}/utils/distributed_utils.py +0 -0
- {ins_pricing-0.4.5.dist-info → ins_pricing-0.5.0.dist-info}/WHEEL +0 -0
- {ins_pricing-0.4.5.dist-info → ins_pricing-0.5.0.dist-info}/top_level.txt +0 -0
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Mapping, Optional, Sequence
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
import pandas as pd
|
|
7
|
-
|
|
8
|
-
from .common import EPS, PlotStyle, finalize_figure, plt
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def plot_loss_curve(
|
|
12
|
-
*,
|
|
13
|
-
history: Optional[Mapping[str, Sequence[float]]] = None,
|
|
14
|
-
train: Optional[Sequence[float]] = None,
|
|
15
|
-
val: Optional[Sequence[float]] = None,
|
|
16
|
-
title: str = "Loss vs. Epoch",
|
|
17
|
-
ax: Optional[plt.Axes] = None,
|
|
18
|
-
show: bool = False,
|
|
19
|
-
save_path: Optional[str] = None,
|
|
20
|
-
style: Optional[PlotStyle] = None,
|
|
21
|
-
) -> Optional[plt.Figure]:
|
|
22
|
-
style = style or PlotStyle()
|
|
23
|
-
if history is not None:
|
|
24
|
-
if train is None:
|
|
25
|
-
train = history.get("train")
|
|
26
|
-
if val is None:
|
|
27
|
-
val = history.get("val")
|
|
28
|
-
|
|
29
|
-
train_hist = list(train or [])
|
|
30
|
-
val_hist = list(val or [])
|
|
31
|
-
if not train_hist and not val_hist:
|
|
32
|
-
return None
|
|
33
|
-
|
|
34
|
-
created_fig = ax is None
|
|
35
|
-
if created_fig:
|
|
36
|
-
fig, ax = plt.subplots(figsize=style.figsize)
|
|
37
|
-
else:
|
|
38
|
-
fig = ax.figure
|
|
39
|
-
|
|
40
|
-
if train_hist:
|
|
41
|
-
ax.plot(
|
|
42
|
-
range(1, len(train_hist) + 1),
|
|
43
|
-
train_hist,
|
|
44
|
-
label="Train Loss",
|
|
45
|
-
color="tab:blue",
|
|
46
|
-
)
|
|
47
|
-
if val_hist:
|
|
48
|
-
ax.plot(
|
|
49
|
-
range(1, len(val_hist) + 1),
|
|
50
|
-
val_hist,
|
|
51
|
-
label="Validation Loss",
|
|
52
|
-
color="tab:orange",
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
ax.set_xlabel("Epoch", fontsize=style.label_size)
|
|
56
|
-
ax.set_ylabel("Weighted Loss", fontsize=style.label_size)
|
|
57
|
-
ax.set_title(title, fontsize=style.title_size)
|
|
58
|
-
ax.tick_params(axis="both", labelsize=style.tick_size)
|
|
59
|
-
if style.grid:
|
|
60
|
-
ax.grid(True, linestyle=style.grid_style, alpha=style.grid_alpha)
|
|
61
|
-
ax.legend(loc="best", fontsize=style.legend_size, frameon=False)
|
|
62
|
-
|
|
63
|
-
if created_fig:
|
|
64
|
-
finalize_figure(fig, save_path=save_path, show=show, style=style)
|
|
65
|
-
|
|
66
|
-
return fig
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def plot_oneway(
|
|
70
|
-
df: pd.DataFrame,
|
|
71
|
-
*,
|
|
72
|
-
feature: str,
|
|
73
|
-
weight_col: str,
|
|
74
|
-
target_col: str,
|
|
75
|
-
pred_col: Optional[str] = None,
|
|
76
|
-
pred_weighted: bool = False,
|
|
77
|
-
pred_label: Optional[str] = None,
|
|
78
|
-
n_bins: int = 10,
|
|
79
|
-
is_categorical: bool = False,
|
|
80
|
-
title: Optional[str] = None,
|
|
81
|
-
ax: Optional[plt.Axes] = None,
|
|
82
|
-
show: bool = False,
|
|
83
|
-
save_path: Optional[str] = None,
|
|
84
|
-
style: Optional[PlotStyle] = None,
|
|
85
|
-
) -> Optional[plt.Figure]:
|
|
86
|
-
if feature not in df.columns:
|
|
87
|
-
raise KeyError(f"feature '{feature}' not found in data.")
|
|
88
|
-
if weight_col not in df.columns:
|
|
89
|
-
raise KeyError(f"weight_col '{weight_col}' not found in data.")
|
|
90
|
-
if target_col not in df.columns:
|
|
91
|
-
raise KeyError(f"target_col '{target_col}' not found in data.")
|
|
92
|
-
if pred_col is not None and pred_col not in df.columns:
|
|
93
|
-
raise KeyError(f"pred_col '{pred_col}' not found in data.")
|
|
94
|
-
|
|
95
|
-
style = style or PlotStyle()
|
|
96
|
-
title = title or f"Analysis of {feature}"
|
|
97
|
-
|
|
98
|
-
if is_categorical:
|
|
99
|
-
group_col = feature
|
|
100
|
-
plot_source = df
|
|
101
|
-
else:
|
|
102
|
-
group_col = f"{feature}_bins"
|
|
103
|
-
series = pd.to_numeric(df[feature], errors="coerce")
|
|
104
|
-
try:
|
|
105
|
-
bins = pd.qcut(series, n_bins, duplicates="drop")
|
|
106
|
-
except ValueError:
|
|
107
|
-
bins = pd.cut(series, bins=max(1, int(n_bins)), duplicates="drop")
|
|
108
|
-
plot_source = df.assign(**{group_col: bins})
|
|
109
|
-
|
|
110
|
-
if pred_col is not None:
|
|
111
|
-
if pred_weighted:
|
|
112
|
-
plot_source = plot_source.assign(_pred_w=plot_source[pred_col])
|
|
113
|
-
else:
|
|
114
|
-
plot_source = plot_source.assign(
|
|
115
|
-
_pred_w=plot_source[pred_col] * plot_source[weight_col]
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
plot_data = plot_source.groupby([group_col], observed=True).sum(numeric_only=True)
|
|
119
|
-
plot_data.reset_index(inplace=True)
|
|
120
|
-
|
|
121
|
-
denom = np.maximum(plot_data[weight_col].to_numpy(dtype=float), EPS)
|
|
122
|
-
plot_data["act_v"] = plot_data[target_col].to_numpy(dtype=float) / denom
|
|
123
|
-
if pred_col is not None:
|
|
124
|
-
plot_data["pred_v"] = plot_data["_pred_w"].to_numpy(dtype=float) / denom
|
|
125
|
-
|
|
126
|
-
created_fig = ax is None
|
|
127
|
-
if created_fig:
|
|
128
|
-
fig, ax = plt.subplots(figsize=style.figsize)
|
|
129
|
-
else:
|
|
130
|
-
fig = ax.figure
|
|
131
|
-
|
|
132
|
-
ax.plot(plot_data.index, plot_data["act_v"], label="Actual", color="red")
|
|
133
|
-
if pred_col is not None:
|
|
134
|
-
ax.plot(
|
|
135
|
-
plot_data.index,
|
|
136
|
-
plot_data["pred_v"],
|
|
137
|
-
label=pred_label or "Predicted",
|
|
138
|
-
color=style.palette[0],
|
|
139
|
-
)
|
|
140
|
-
ax.set_title(title, fontsize=style.title_size)
|
|
141
|
-
ax.set_xticks(plot_data.index)
|
|
142
|
-
labels = plot_data[group_col].astype(str).tolist()
|
|
143
|
-
tick_size = 3 if len(labels) > 50 else style.tick_size
|
|
144
|
-
ax.set_xticklabels(labels, rotation=90, fontsize=tick_size)
|
|
145
|
-
ax.tick_params(axis="y", labelsize=style.tick_size)
|
|
146
|
-
if style.grid:
|
|
147
|
-
ax.grid(True, linestyle=style.grid_style, alpha=style.grid_alpha)
|
|
148
|
-
if pred_col is not None:
|
|
149
|
-
ax.legend(fontsize=style.legend_size)
|
|
150
|
-
|
|
151
|
-
ax2 = ax.twinx()
|
|
152
|
-
ax2.bar(
|
|
153
|
-
plot_data.index,
|
|
154
|
-
plot_data[weight_col],
|
|
155
|
-
alpha=0.5,
|
|
156
|
-
color=style.weight_color,
|
|
157
|
-
)
|
|
158
|
-
ax2.tick_params(axis="y", labelsize=style.tick_size)
|
|
159
|
-
|
|
160
|
-
if created_fig:
|
|
161
|
-
finalize_figure(fig, save_path=save_path, show=show, style=style)
|
|
162
|
-
|
|
163
|
-
return fig
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Mapping, Optional, Sequence
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
from ins_pricing.modelling.plotting.common import EPS, PlotStyle, finalize_figure, plt
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def plot_loss_curve(
|
|
12
|
+
*,
|
|
13
|
+
history: Optional[Mapping[str, Sequence[float]]] = None,
|
|
14
|
+
train: Optional[Sequence[float]] = None,
|
|
15
|
+
val: Optional[Sequence[float]] = None,
|
|
16
|
+
title: str = "Loss vs. Epoch",
|
|
17
|
+
ax: Optional[plt.Axes] = None,
|
|
18
|
+
show: bool = False,
|
|
19
|
+
save_path: Optional[str] = None,
|
|
20
|
+
style: Optional[PlotStyle] = None,
|
|
21
|
+
) -> Optional[plt.Figure]:
|
|
22
|
+
style = style or PlotStyle()
|
|
23
|
+
if history is not None:
|
|
24
|
+
if train is None:
|
|
25
|
+
train = history.get("train")
|
|
26
|
+
if val is None:
|
|
27
|
+
val = history.get("val")
|
|
28
|
+
|
|
29
|
+
train_hist = list(train or [])
|
|
30
|
+
val_hist = list(val or [])
|
|
31
|
+
if not train_hist and not val_hist:
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
created_fig = ax is None
|
|
35
|
+
if created_fig:
|
|
36
|
+
fig, ax = plt.subplots(figsize=style.figsize)
|
|
37
|
+
else:
|
|
38
|
+
fig = ax.figure
|
|
39
|
+
|
|
40
|
+
if train_hist:
|
|
41
|
+
ax.plot(
|
|
42
|
+
range(1, len(train_hist) + 1),
|
|
43
|
+
train_hist,
|
|
44
|
+
label="Train Loss",
|
|
45
|
+
color="tab:blue",
|
|
46
|
+
)
|
|
47
|
+
if val_hist:
|
|
48
|
+
ax.plot(
|
|
49
|
+
range(1, len(val_hist) + 1),
|
|
50
|
+
val_hist,
|
|
51
|
+
label="Validation Loss",
|
|
52
|
+
color="tab:orange",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
ax.set_xlabel("Epoch", fontsize=style.label_size)
|
|
56
|
+
ax.set_ylabel("Weighted Loss", fontsize=style.label_size)
|
|
57
|
+
ax.set_title(title, fontsize=style.title_size)
|
|
58
|
+
ax.tick_params(axis="both", labelsize=style.tick_size)
|
|
59
|
+
if style.grid:
|
|
60
|
+
ax.grid(True, linestyle=style.grid_style, alpha=style.grid_alpha)
|
|
61
|
+
ax.legend(loc="best", fontsize=style.legend_size, frameon=False)
|
|
62
|
+
|
|
63
|
+
if created_fig:
|
|
64
|
+
finalize_figure(fig, save_path=save_path, show=show, style=style)
|
|
65
|
+
|
|
66
|
+
return fig
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def plot_oneway(
|
|
70
|
+
df: pd.DataFrame,
|
|
71
|
+
*,
|
|
72
|
+
feature: str,
|
|
73
|
+
weight_col: str,
|
|
74
|
+
target_col: str,
|
|
75
|
+
pred_col: Optional[str] = None,
|
|
76
|
+
pred_weighted: bool = False,
|
|
77
|
+
pred_label: Optional[str] = None,
|
|
78
|
+
n_bins: int = 10,
|
|
79
|
+
is_categorical: bool = False,
|
|
80
|
+
title: Optional[str] = None,
|
|
81
|
+
ax: Optional[plt.Axes] = None,
|
|
82
|
+
show: bool = False,
|
|
83
|
+
save_path: Optional[str] = None,
|
|
84
|
+
style: Optional[PlotStyle] = None,
|
|
85
|
+
) -> Optional[plt.Figure]:
|
|
86
|
+
if feature not in df.columns:
|
|
87
|
+
raise KeyError(f"feature '{feature}' not found in data.")
|
|
88
|
+
if weight_col not in df.columns:
|
|
89
|
+
raise KeyError(f"weight_col '{weight_col}' not found in data.")
|
|
90
|
+
if target_col not in df.columns:
|
|
91
|
+
raise KeyError(f"target_col '{target_col}' not found in data.")
|
|
92
|
+
if pred_col is not None and pred_col not in df.columns:
|
|
93
|
+
raise KeyError(f"pred_col '{pred_col}' not found in data.")
|
|
94
|
+
|
|
95
|
+
style = style or PlotStyle()
|
|
96
|
+
title = title or f"Analysis of {feature}"
|
|
97
|
+
|
|
98
|
+
if is_categorical:
|
|
99
|
+
group_col = feature
|
|
100
|
+
plot_source = df
|
|
101
|
+
else:
|
|
102
|
+
group_col = f"{feature}_bins"
|
|
103
|
+
series = pd.to_numeric(df[feature], errors="coerce")
|
|
104
|
+
try:
|
|
105
|
+
bins = pd.qcut(series, n_bins, duplicates="drop")
|
|
106
|
+
except ValueError:
|
|
107
|
+
bins = pd.cut(series, bins=max(1, int(n_bins)), duplicates="drop")
|
|
108
|
+
plot_source = df.assign(**{group_col: bins})
|
|
109
|
+
|
|
110
|
+
if pred_col is not None:
|
|
111
|
+
if pred_weighted:
|
|
112
|
+
plot_source = plot_source.assign(_pred_w=plot_source[pred_col])
|
|
113
|
+
else:
|
|
114
|
+
plot_source = plot_source.assign(
|
|
115
|
+
_pred_w=plot_source[pred_col] * plot_source[weight_col]
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
plot_data = plot_source.groupby([group_col], observed=True).sum(numeric_only=True)
|
|
119
|
+
plot_data.reset_index(inplace=True)
|
|
120
|
+
|
|
121
|
+
denom = np.maximum(plot_data[weight_col].to_numpy(dtype=float), EPS)
|
|
122
|
+
plot_data["act_v"] = plot_data[target_col].to_numpy(dtype=float) / denom
|
|
123
|
+
if pred_col is not None:
|
|
124
|
+
plot_data["pred_v"] = plot_data["_pred_w"].to_numpy(dtype=float) / denom
|
|
125
|
+
|
|
126
|
+
created_fig = ax is None
|
|
127
|
+
if created_fig:
|
|
128
|
+
fig, ax = plt.subplots(figsize=style.figsize)
|
|
129
|
+
else:
|
|
130
|
+
fig = ax.figure
|
|
131
|
+
|
|
132
|
+
ax.plot(plot_data.index, plot_data["act_v"], label="Actual", color="red")
|
|
133
|
+
if pred_col is not None:
|
|
134
|
+
ax.plot(
|
|
135
|
+
plot_data.index,
|
|
136
|
+
plot_data["pred_v"],
|
|
137
|
+
label=pred_label or "Predicted",
|
|
138
|
+
color=style.palette[0],
|
|
139
|
+
)
|
|
140
|
+
ax.set_title(title, fontsize=style.title_size)
|
|
141
|
+
ax.set_xticks(plot_data.index)
|
|
142
|
+
labels = plot_data[group_col].astype(str).tolist()
|
|
143
|
+
tick_size = 3 if len(labels) > 50 else style.tick_size
|
|
144
|
+
ax.set_xticklabels(labels, rotation=90, fontsize=tick_size)
|
|
145
|
+
ax.tick_params(axis="y", labelsize=style.tick_size)
|
|
146
|
+
if style.grid:
|
|
147
|
+
ax.grid(True, linestyle=style.grid_style, alpha=style.grid_alpha)
|
|
148
|
+
if pred_col is not None:
|
|
149
|
+
ax.legend(fontsize=style.legend_size)
|
|
150
|
+
|
|
151
|
+
ax2 = ax.twinx()
|
|
152
|
+
ax2.bar(
|
|
153
|
+
plot_data.index,
|
|
154
|
+
plot_data[weight_col],
|
|
155
|
+
alpha=0.5,
|
|
156
|
+
color=style.weight_color,
|
|
157
|
+
)
|
|
158
|
+
ax2.tick_params(axis="y", labelsize=style.tick_size)
|
|
159
|
+
|
|
160
|
+
if created_fig:
|
|
161
|
+
finalize_figure(fig, save_path=save_path, show=show, style=style)
|
|
162
|
+
|
|
163
|
+
return fig
|