optima-ml 0.3.4a3__tar.gz → 0.3.5.dev1__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.
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/builtin/evaluation.py +163 -86
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/builtin/figures_of_merit.py +32 -20
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/builtin/inputs.py +276 -512
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/core/evaluation.py +471 -407
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/core/inputs.py +33 -91
- optima_ml-0.3.5.dev1/OPTIMA/core/model.py +1265 -0
- optima_ml-0.3.5.dev1/OPTIMA/core/tools.py +211 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/core/training.py +168 -296
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/core/variable_optimization.py +292 -218
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/defaults.py +7 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/keras/model.py +41 -33
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/keras/tools.py +109 -66
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/keras/training.py +17 -18
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/lightning/inputs.py +67 -67
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/lightning/training.py +26 -52
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/optima.py +504 -501
- optima_ml-0.3.5.dev1/OPTIMA/test.py +58 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/PKG-INFO +40 -20
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/README.md +27 -19
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/optima_ml.egg-info/PKG-INFO +40 -20
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/optima_ml.egg-info/SOURCES.txt +0 -1
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/tests/test_builtin.py +10 -9
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/tests/test_core.py +0 -2
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/tests/test_integration.py +0 -12
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/tests/test_preprocessing.py +281 -419
- optima_ml-0.3.4a3/OPTIMA/core/model.py +0 -306
- optima_ml-0.3.4a3/OPTIMA/core/tools.py +0 -106
- optima_ml-0.3.4a3/OPTIMA/test.py +0 -12
- optima_ml-0.3.4a3/tests/test_integration_sameMachine.py +0 -154
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/LICENSE +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/__init__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/__main__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/builtin/__init__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/builtin/model.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/builtin/search_space.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/core/__init__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/core/search_space.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/hardware_configs/Dresden_Taurus.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/hardware_configs/__init__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/hardware_configs/common.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/hardware_configs/helpers.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/helpers/__init__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/helpers/extract_data_from_NTuples.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/helpers/manage_ray_nodes.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/keras/__init__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/lightning/__init__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/resources/__init__.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/resources/config_verification.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/OPTIMA/resources/pbt_with_seed.py +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/optima_ml.egg-info/dependency_links.txt +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/optima_ml.egg-info/entry_points.txt +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/optima_ml.egg-info/requires.txt +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/optima_ml.egg-info/top_level.txt +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/setup.cfg +0 -0
- {optima_ml-0.3.4a3 → optima_ml-0.3.5.dev1}/setup.py +0 -0
|
@@ -9,8 +9,6 @@ import matplotlib.pyplot as plt
|
|
|
9
9
|
import seaborn as sns
|
|
10
10
|
from sklearn.metrics import roc_curve, auc
|
|
11
11
|
|
|
12
|
-
import ray
|
|
13
|
-
|
|
14
12
|
import OPTIMA.core.model
|
|
15
13
|
import OPTIMA.core.evaluation
|
|
16
14
|
|
|
@@ -18,14 +16,14 @@ import OPTIMA.core.evaluation
|
|
|
18
16
|
def evaluate(
|
|
19
17
|
run_config,
|
|
20
18
|
model_path,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
normalized_weights_split,
|
|
19
|
+
model_config,
|
|
20
|
+
dataset_split,
|
|
21
|
+
input_handler,
|
|
25
22
|
fig_dir,
|
|
26
23
|
native_metrics=None,
|
|
27
24
|
weighted_native_metrics=None,
|
|
28
|
-
|
|
25
|
+
custom_metrics=None,
|
|
26
|
+
composite_metrics=None,
|
|
29
27
|
class_labels=None,
|
|
30
28
|
cpus=1,
|
|
31
29
|
results_dir=None,
|
|
@@ -34,7 +32,9 @@ def evaluate(
|
|
|
34
32
|
return_unfilled=False,
|
|
35
33
|
ratio=True,
|
|
36
34
|
):
|
|
37
|
-
"""
|
|
35
|
+
"""Built-in evaluation for classification tasks.
|
|
36
|
+
|
|
37
|
+
This function assumes that the entire dataset and the model predictions can fit into memory.
|
|
38
38
|
|
|
39
39
|
Parameters
|
|
40
40
|
----------
|
|
@@ -42,13 +42,11 @@ def evaluate(
|
|
|
42
42
|
_description_
|
|
43
43
|
model_path : _type_
|
|
44
44
|
_description_
|
|
45
|
-
|
|
46
|
-
_description_
|
|
47
|
-
targets_split : _type_
|
|
45
|
+
model_config : _type_
|
|
48
46
|
_description_
|
|
49
|
-
|
|
47
|
+
dataset_split : _type_
|
|
50
48
|
_description_
|
|
51
|
-
|
|
49
|
+
input_handler : _type_
|
|
52
50
|
_description_
|
|
53
51
|
fig_dir : _type_
|
|
54
52
|
_description_
|
|
@@ -56,8 +54,10 @@ def evaluate(
|
|
|
56
54
|
_description_ (Default value = [])
|
|
57
55
|
weighted_native_metrics : _type_
|
|
58
56
|
_description_ (Default value = [])
|
|
59
|
-
|
|
57
|
+
custom_metrics : _type_
|
|
60
58
|
_description_ (Default value = [])
|
|
59
|
+
composite_metrics : _type_
|
|
60
|
+
_description_ (Default value = None)
|
|
61
61
|
class_labels : _type_
|
|
62
62
|
_description_ (Default value = None)
|
|
63
63
|
cpus : _type_
|
|
@@ -78,34 +78,62 @@ def evaluate(
|
|
|
78
78
|
_type_
|
|
79
79
|
_description_
|
|
80
80
|
"""
|
|
81
|
-
if custom_FoMs is None:
|
|
82
|
-
custom_FoMs = []
|
|
83
|
-
if weighted_native_metrics is None:
|
|
84
|
-
weighted_native_metrics = []
|
|
85
81
|
if native_metrics is None:
|
|
86
82
|
native_metrics = []
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if
|
|
83
|
+
if weighted_native_metrics is None:
|
|
84
|
+
weighted_native_metrics = []
|
|
85
|
+
if custom_metrics is None:
|
|
86
|
+
custom_metrics = []
|
|
87
|
+
if composite_metrics is None:
|
|
88
|
+
composite_metrics = []
|
|
89
|
+
|
|
90
|
+
# fetch the target labels and optional sample weights --> this saves everything into this worker's memory. If OOM
|
|
91
|
+
# error occurs, define an evaluate-function in the run-config.
|
|
92
|
+
if len(dataset_split) == 2:
|
|
90
93
|
explicit_testing_dataset = False
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
dataset_train, dataset_val = dataset_split
|
|
95
|
+
train_data = list(dataset_train.iter_batches(batch_size=dataset_train.count()))[0]
|
|
96
|
+
val_data = list(dataset_val.iter_batches(batch_size=dataset_val.count()))[0]
|
|
97
|
+
targets_train = train_data["Target"]
|
|
98
|
+
targets_val = val_data["Target"]
|
|
99
|
+
if "ScaledWeight" in dataset_train.columns():
|
|
100
|
+
weights_train = train_data["ScaledWeight"]
|
|
101
|
+
weights_val = val_data["ScaledWeight"]
|
|
102
|
+
elif "Weight" in dataset_train.columns():
|
|
103
|
+
weights_train = train_data["Weight"]
|
|
104
|
+
weights_val = val_data["Weight"]
|
|
105
|
+
else:
|
|
106
|
+
weights_train = np.ones((targets_train.shape[0],))
|
|
107
|
+
weights_val = np.ones((targets_val.shape[0],))
|
|
95
108
|
print(
|
|
96
109
|
"testing model using {} training and {} validation events".format(
|
|
97
|
-
|
|
110
|
+
targets_train.shape[0], targets_val.shape[0]
|
|
98
111
|
)
|
|
99
112
|
)
|
|
100
113
|
else:
|
|
101
114
|
explicit_testing_dataset = True
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
115
|
+
dataset_train, dataset_val, dataset_test = dataset_split
|
|
116
|
+
train_data = list(dataset_train.iter_batches(batch_size=dataset_train.count()))[0]
|
|
117
|
+
val_data = list(dataset_val.iter_batches(batch_size=dataset_val.count()))[0]
|
|
118
|
+
test_data = list(dataset_test.iter_batches(batch_size=dataset_test.count()))[0]
|
|
119
|
+
targets_train = train_data["Target"]
|
|
120
|
+
targets_val = val_data["Target"]
|
|
121
|
+
targets_test = test_data["Target"]
|
|
122
|
+
if "ScaledWeight" in dataset_train.columns():
|
|
123
|
+
weights_train = train_data["ScaledWeight"]
|
|
124
|
+
weights_val = val_data["ScaledWeight"]
|
|
125
|
+
weights_test = test_data["ScaledWeight"]
|
|
126
|
+
elif "Weight" in dataset_train.columns():
|
|
127
|
+
weights_train = train_data["Weight"]
|
|
128
|
+
weights_val = val_data["Weight"]
|
|
129
|
+
weights_test = test_data["Weight"]
|
|
130
|
+
else:
|
|
131
|
+
weights_train = np.ones((targets_train.shape[0],))
|
|
132
|
+
weights_val = np.ones((targets_val.shape[0],))
|
|
133
|
+
weights_test = np.ones((targets_test.shape[0],))
|
|
106
134
|
print(
|
|
107
135
|
"testing model using {} training, {} validation and {} testing events".format(
|
|
108
|
-
|
|
136
|
+
targets_train.shape[0], targets_val.shape[0], targets_test.shape[0]
|
|
109
137
|
)
|
|
110
138
|
)
|
|
111
139
|
|
|
@@ -116,12 +144,19 @@ def evaluate(
|
|
|
116
144
|
if not os.path.exists(results_dir):
|
|
117
145
|
os.makedirs(results_dir, exist_ok=True)
|
|
118
146
|
|
|
119
|
-
# load the model and get the model
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
147
|
+
# load the model, prepare the datasets (i.e. convert from ray datasets to ML native datasets) and get the model
|
|
148
|
+
# predictions
|
|
149
|
+
model = OPTIMA.core.model.load_model(run_config, model_config, input_handler, model_path, cpus)
|
|
150
|
+
native_datasets = model.prepare_datasets(
|
|
151
|
+
dataset_train,
|
|
152
|
+
dataset_val,
|
|
153
|
+
dataset_test if explicit_testing_dataset else None,
|
|
154
|
+
)
|
|
155
|
+
preds = model.predict(native_datasets, verbose=0)
|
|
123
156
|
if explicit_testing_dataset:
|
|
124
|
-
pred_test =
|
|
157
|
+
pred_train, pred_val, pred_test = preds
|
|
158
|
+
else:
|
|
159
|
+
pred_train, pred_val = preds
|
|
125
160
|
num_outputs = pred_train.shape[1]
|
|
126
161
|
|
|
127
162
|
# check if we have binary or multiclass classification
|
|
@@ -715,88 +750,130 @@ def evaluate(
|
|
|
715
750
|
if explicit_testing_dataset:
|
|
716
751
|
results_string_args.append(auc_test_classes[i])
|
|
717
752
|
|
|
753
|
+
# keep track of the calculated metrics to evaluate composite metrics
|
|
754
|
+
metric_values_dict = {}
|
|
755
|
+
|
|
718
756
|
# loss
|
|
719
757
|
results_string += " Loss:\n"
|
|
720
|
-
|
|
721
|
-
inputs=inputs_train, y_true=targets_train, sample_weight=normalized_weights_train, y_pred=pred_train
|
|
722
|
-
)
|
|
723
|
-
val_loss = model.loss(inputs=inputs_val, y_true=targets_val, sample_weight=normalized_weights_val, y_pred=pred_val)
|
|
758
|
+
losses = model.loss(native_datasets)
|
|
724
759
|
if explicit_testing_dataset:
|
|
725
|
-
test_loss =
|
|
726
|
-
|
|
727
|
-
|
|
760
|
+
train_loss, val_loss, test_loss = losses
|
|
761
|
+
else:
|
|
762
|
+
train_loss, val_loss = losses
|
|
728
763
|
results_string += "\ttraining: {}\n".format("{:.3f}")
|
|
729
764
|
results_string += "\tvalidation: {}\n".format("{:.3f}")
|
|
730
765
|
if explicit_testing_dataset:
|
|
731
766
|
results_string += "\ttesting: {}\n".format("{:.3f}")
|
|
732
|
-
|
|
767
|
+
metric_values_dict["loss"] = train_loss
|
|
768
|
+
metric_values_dict["val_loss"] = val_loss
|
|
769
|
+
metric_values_dict["test_loss"] = test_loss
|
|
770
|
+
results_string_args += [train_loss, val_loss, test_loss]
|
|
771
|
+
else:
|
|
772
|
+
metric_values_dict["loss"] = train_loss
|
|
773
|
+
metric_values_dict["val_loss"] = val_loss
|
|
774
|
+
results_string_args += [train_loss, val_loss]
|
|
733
775
|
|
|
734
776
|
if native_metrics != []:
|
|
735
777
|
# instantiate native metrics
|
|
736
778
|
native_metrics = [(name, metric(**kwargs)) for name, (metric, kwargs) in native_metrics]
|
|
737
779
|
|
|
780
|
+
# calculate the metric values
|
|
781
|
+
metric_values = model.calc_native_metrics(
|
|
782
|
+
native_metrics=[metric for (_, metric) in native_metrics],
|
|
783
|
+
data=native_datasets,
|
|
784
|
+
weighted=False,
|
|
785
|
+
)
|
|
786
|
+
if explicit_testing_dataset:
|
|
787
|
+
metric_values_train, metric_values_val, metric_values_test = metric_values
|
|
788
|
+
else:
|
|
789
|
+
metric_values_train, metric_values_val = metric_values
|
|
790
|
+
|
|
738
791
|
results_string += " Native metrics:\n"
|
|
739
|
-
for metric_name,
|
|
740
|
-
metric_value_train =
|
|
741
|
-
|
|
742
|
-
)
|
|
743
|
-
metric_value_val = OPTIMA.core.evaluation.calc_native_metric(run_config, metric, targets_val, pred_val)
|
|
792
|
+
for i, (metric_name, _) in enumerate(native_metrics):
|
|
793
|
+
metric_value_train = metric_values_train[i]
|
|
794
|
+
metric_value_val = metric_values_val[i]
|
|
744
795
|
if explicit_testing_dataset:
|
|
745
|
-
metric_value_test =
|
|
746
|
-
|
|
747
|
-
)
|
|
796
|
+
metric_value_test = metric_values_test[i]
|
|
797
|
+
|
|
748
798
|
results_string += "\t{} (training): {}\n".format(metric_name, "{:.3f}")
|
|
749
799
|
results_string += "\t{} (validation): {}\n".format(metric_name, "{:.3f}")
|
|
750
800
|
if explicit_testing_dataset:
|
|
751
801
|
results_string += "\t{} (testing): {}\n".format(metric_name, "{:.3f}")
|
|
752
|
-
|
|
753
|
-
[
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
802
|
+
metric_values_dict[f"{metric_name}"] = metric_value_train
|
|
803
|
+
metric_values_dict[f"val_{metric_name}"] = metric_value_val
|
|
804
|
+
metric_values_dict[f"test_{metric_name}"] = metric_value_test
|
|
805
|
+
results_string_args += [metric_value_train, metric_value_val, metric_value_test]
|
|
806
|
+
else:
|
|
807
|
+
metric_values_dict[f"{metric_name}"] = metric_value_train
|
|
808
|
+
metric_values_dict[f"val_{metric_name}"] = metric_value_val
|
|
809
|
+
results_string_args += [metric_value_train, metric_value_val]
|
|
757
810
|
|
|
758
811
|
if weighted_native_metrics != []:
|
|
759
812
|
# instantiate weighted native metrics
|
|
760
813
|
weighted_native_metrics = [(name, metric(**kwargs)) for name, (metric, kwargs) in weighted_native_metrics]
|
|
761
814
|
|
|
815
|
+
# calculate the metric values
|
|
816
|
+
metric_values = model.calc_native_metrics(
|
|
817
|
+
native_metrics=[metric for (_, metric) in weighted_native_metrics],
|
|
818
|
+
data=native_datasets,
|
|
819
|
+
weighted=True,
|
|
820
|
+
)
|
|
821
|
+
if explicit_testing_dataset:
|
|
822
|
+
metric_values_train, metric_values_val, metric_values_test = metric_values
|
|
823
|
+
else:
|
|
824
|
+
metric_values_train, metric_values_val = metric_values
|
|
825
|
+
|
|
762
826
|
results_string += " Weighted native metrics:\n"
|
|
763
|
-
for metric_name,
|
|
764
|
-
metric_value_train =
|
|
765
|
-
|
|
766
|
-
)
|
|
767
|
-
metric_value_val = OPTIMA.core.evaluation.calc_native_metric(
|
|
768
|
-
run_config, metric, targets_val, pred_val, sample_weight=normalized_weights_val
|
|
769
|
-
)
|
|
827
|
+
for i, (metric_name, _) in enumerate(weighted_native_metrics):
|
|
828
|
+
metric_value_train = metric_values_train[i]
|
|
829
|
+
metric_value_val = metric_values_val[i]
|
|
770
830
|
if explicit_testing_dataset:
|
|
771
|
-
metric_value_test =
|
|
772
|
-
|
|
773
|
-
)
|
|
831
|
+
metric_value_test = metric_values_test[i]
|
|
832
|
+
|
|
774
833
|
results_string += "\t{} (training): {}\n".format(metric_name, "{:.3f}")
|
|
775
834
|
results_string += "\t{} (validation): {}\n".format(metric_name, "{:.3f}")
|
|
776
835
|
if explicit_testing_dataset:
|
|
777
836
|
results_string += "\t{} (testing): {}\n".format(metric_name, "{:.3f}")
|
|
778
|
-
|
|
779
|
-
[
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
837
|
+
metric_values_dict[f"{metric_name}"] = metric_value_train
|
|
838
|
+
metric_values_dict[f"val_{metric_name}"] = metric_value_val
|
|
839
|
+
metric_values_dict[f"test_{metric_name}"] = metric_value_test
|
|
840
|
+
results_string_args += [metric_value_train, metric_value_val, metric_value_test]
|
|
841
|
+
else:
|
|
842
|
+
metric_values_dict[f"{metric_name}"] = metric_value_train
|
|
843
|
+
metric_values_dict[f"val_{metric_name}"] = metric_value_val
|
|
844
|
+
results_string_args += [metric_value_train, metric_value_val]
|
|
783
845
|
|
|
784
|
-
if
|
|
846
|
+
if custom_metrics != []:
|
|
785
847
|
results_string += " Custom metrics:\n"
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
results_string += "\t{} (
|
|
848
|
+
custom_metric_values = model.calc_custom_metrics(
|
|
849
|
+
custom_metrics=[metric for (_, metric) in custom_metrics],
|
|
850
|
+
data=native_datasets,
|
|
851
|
+
skip_test_dataset=False,
|
|
852
|
+
)
|
|
853
|
+
for i, (metric_name, _) in enumerate(custom_metrics):
|
|
854
|
+
results_string += "\t{} (training): {}\n".format(metric_name, "{:.3f}")
|
|
855
|
+
results_string += "\t{} (validation): {}\n".format(metric_name, "{:.3f}")
|
|
793
856
|
if explicit_testing_dataset:
|
|
794
|
-
results_string += "\t{} (testing): {}\n".format(
|
|
795
|
-
|
|
796
|
-
[
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
857
|
+
results_string += "\t{} (testing): {}\n".format(metric_name, "{:.3f}")
|
|
858
|
+
metric_values_dict[f"train_{metric_name}"] = custom_metric_values[0][i]
|
|
859
|
+
metric_values_dict[f"val_{metric_name}"] = custom_metric_values[1][i]
|
|
860
|
+
metric_values_dict[f"test_{metric_name}"] = custom_metric_values[2][i]
|
|
861
|
+
results_string_args += [
|
|
862
|
+
custom_metric_values[0][i],
|
|
863
|
+
custom_metric_values[1][i],
|
|
864
|
+
custom_metric_values[2][i],
|
|
865
|
+
]
|
|
866
|
+
else:
|
|
867
|
+
metric_values_dict[f"train_{metric_name}"] = custom_metric_values[0][i]
|
|
868
|
+
metric_values_dict[f"val_{metric_name}"] = custom_metric_values[1][i]
|
|
869
|
+
results_string_args += [custom_metric_values[0][i], custom_metric_values[1][i]]
|
|
870
|
+
|
|
871
|
+
if composite_metrics != []:
|
|
872
|
+
results_string += " Composite metrics:\n"
|
|
873
|
+
for metric_name, dep_metric_names, metric in composite_metrics:
|
|
874
|
+
dep_metric_values = (metric_values_dict[dep_metric_name] for dep_metric_name in dep_metric_names)
|
|
875
|
+
results_string += "\t{}: {}\n".format(metric_name, "{:.3f}")
|
|
876
|
+
results_string_args.append(metric(*dep_metric_values))
|
|
800
877
|
|
|
801
878
|
if print_results:
|
|
802
879
|
print(results_string.format(*results_string_args))
|
|
@@ -95,24 +95,28 @@ class FigureOfMerit:
|
|
|
95
95
|
self.func = func
|
|
96
96
|
self.kwargs = kwargs
|
|
97
97
|
|
|
98
|
-
def __call__(self,
|
|
98
|
+
def __call__(self, inputs: tuple[np.ndarray], y_pred: np.ndarray) -> Any:
|
|
99
99
|
"""Gives arrays of target labels, predictions, sample weight and possible kwargs to self.func and returns the result.
|
|
100
100
|
|
|
101
101
|
Parameters
|
|
102
102
|
----------
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
inputs : tuple[np.ndarray]
|
|
104
|
+
A tuple of numpy arrays of length 2 or 3. The first two entries are assumed to be the input features and
|
|
105
|
+
the target labels. The third, optional entry is assumed to be the sample weights.
|
|
105
106
|
y_pred : np.ndarray
|
|
106
107
|
Array of predictions corresponding to the target labels.
|
|
107
|
-
sample_weight : Optional[np.ndarray]
|
|
108
|
-
Array of sample weights for each entry in y_true and y_pred. (Default value = None)
|
|
109
108
|
|
|
110
109
|
Returns
|
|
111
110
|
-------
|
|
112
111
|
Any
|
|
113
112
|
Return value of the figure of merit calculated by self.func.
|
|
114
113
|
"""
|
|
115
|
-
|
|
114
|
+
assert isinstance(inputs, tuple) or isinstance(inputs, list)
|
|
115
|
+
assert len(inputs) in [
|
|
116
|
+
2,
|
|
117
|
+
3,
|
|
118
|
+
], f"An input-tuple or -list of length {len(inputs)} was provided, which is not supported."
|
|
119
|
+
return self.func(inputs[1], y_pred, sample_weight=inputs[2] if len(inputs) == 3 else None, **self.kwargs)
|
|
116
120
|
|
|
117
121
|
|
|
118
122
|
class HistFigureOfMerit(FigureOfMerit):
|
|
@@ -132,7 +136,7 @@ class HistFigureOfMerit(FigureOfMerit):
|
|
|
132
136
|
min_events_per_bin: Union[float, int] = 10.0,
|
|
133
137
|
min_s_per_bin: Union[float, int] = 0,
|
|
134
138
|
min_b_per_bin: Union[float, int] = 1.0,
|
|
135
|
-
**kwargs: Any
|
|
139
|
+
**kwargs: Any,
|
|
136
140
|
) -> None:
|
|
137
141
|
"""Constructs a HistFigureOfMerit object.
|
|
138
142
|
|
|
@@ -169,24 +173,28 @@ class HistFigureOfMerit(FigureOfMerit):
|
|
|
169
173
|
self.min_s_per_bin = min_s_per_bin
|
|
170
174
|
self.min_b_per_bin = min_b_per_bin
|
|
171
175
|
|
|
172
|
-
def __call__(self,
|
|
176
|
+
def __call__(self, inputs: tuple[np.ndarray], y_pred: np.ndarray) -> Any:
|
|
173
177
|
"""Calls the preprocess function to build the histograms, gives them to self.func and returns the result.
|
|
174
178
|
|
|
175
179
|
Parameters
|
|
176
180
|
----------
|
|
177
|
-
|
|
178
|
-
|
|
181
|
+
inputs : tuple[np.ndarray]
|
|
182
|
+
A tuple of numpy arrays of length 2 or 3. The first two entries are assumed to be the input features and
|
|
183
|
+
the target labels. The third, optional entry is assumed to be the sample weights.
|
|
179
184
|
y_pred : np.ndarray
|
|
180
185
|
Array of predictions corresponding to the target labels.
|
|
181
|
-
sample_weight : Optional[np.ndarray]
|
|
182
|
-
Array of sample weights for each entry in y_true and y_pred. (Default value = None)
|
|
183
186
|
|
|
184
187
|
Returns
|
|
185
188
|
-------
|
|
186
189
|
Any
|
|
187
190
|
Value of the figure of merit calculated by self.func.
|
|
188
191
|
"""
|
|
189
|
-
|
|
192
|
+
assert isinstance(inputs, tuple) or isinstance(inputs, list)
|
|
193
|
+
assert len(inputs) in [
|
|
194
|
+
2,
|
|
195
|
+
3,
|
|
196
|
+
], f"An input-tuple or -list of length {len(inputs)} was provided, which is not supported."
|
|
197
|
+
s, b, bins = self.preprocess(inputs[1], y_pred, sample_weight=inputs[2] if len(inputs) == 3 else None)
|
|
190
198
|
return self.func(s, b, bins, **self.kwargs)
|
|
191
199
|
|
|
192
200
|
def preprocess(
|
|
@@ -295,7 +303,7 @@ class NormHistFigureOfMerit(FigureOfMerit):
|
|
|
295
303
|
min_events_per_bin: Union[float, int] = 0.0,
|
|
296
304
|
min_s_per_bin: Union[float, int] = 0,
|
|
297
305
|
min_b_per_bin: Union[float, int] = 0.0,
|
|
298
|
-
**kwargs: Any
|
|
306
|
+
**kwargs: Any,
|
|
299
307
|
) -> None:
|
|
300
308
|
"""_summary_.
|
|
301
309
|
|
|
@@ -331,24 +339,28 @@ class NormHistFigureOfMerit(FigureOfMerit):
|
|
|
331
339
|
self.min_s_per_bin = min_s_per_bin
|
|
332
340
|
self.min_b_per_bin = min_b_per_bin
|
|
333
341
|
|
|
334
|
-
def __call__(self,
|
|
342
|
+
def __call__(self, inputs: tuple[np.ndarray], y_pred: np.ndarray) -> Any:
|
|
335
343
|
"""Calls the preprocess function to build the histograms, gives them to self.func and returns the result.
|
|
336
344
|
|
|
337
345
|
Parameters
|
|
338
346
|
----------
|
|
339
|
-
|
|
340
|
-
|
|
347
|
+
inputs : tuple[np.ndarray]
|
|
348
|
+
A tuple of numpy arrays of length 2 or 3. The first two entries are assumed to be the input features and
|
|
349
|
+
the target labels. The third, optional entry is assumed to be the sample weights.
|
|
341
350
|
y_pred : np.ndarray
|
|
342
351
|
Array of predictions corresponding to the target labels.
|
|
343
|
-
sample_weight : Optional[np.ndarray]
|
|
344
|
-
Array of sample weights for each entry in y_true and y_pred. (Default value = None)
|
|
345
352
|
|
|
346
353
|
Returns
|
|
347
354
|
-------
|
|
348
355
|
Any
|
|
349
356
|
Value of the figure of merit calculated by self.func.
|
|
350
357
|
"""
|
|
351
|
-
|
|
358
|
+
assert isinstance(inputs, tuple) or isinstance(inputs, list)
|
|
359
|
+
assert len(inputs) in [
|
|
360
|
+
2,
|
|
361
|
+
3,
|
|
362
|
+
], f"An input-tuple or -list of length {len(inputs)} was provided, which is not supported."
|
|
363
|
+
s, b, bins = self.preprocess(inputs[1], y_pred, sample_weight=inputs[2] if len(inputs) == 3 else None)
|
|
352
364
|
return self.func(s, b, bins, **self.kwargs)
|
|
353
365
|
|
|
354
366
|
def preprocess(
|