Benchmarkers
hgp_lib.benchmarkers.gp_benchmarker.GPBenchmarker
Benchmarker for Boolean GP: runs multiple independent experiments with stratified train/test split and k-fold CV per run, then aggregates results.
Data flow per run:
- Stratified train/test split (using
test_size). - For each of the
n_foldsfolds:
a. A fresh copy of the binarizer is fitted on the training fold.
b. The validation fold is transformed using the same fitted binarizer.
c. Binarized data is converted to boolean numpy arrays and used for GP
training.
- The best fold (highest validation score) is selected. Its binarizer is used to transform the held-out test set for final evaluation.
Raw (non-binarized) data should be passed as a
pandas.DataFrame in BenchmarkerConfig.data. Binarization happens
internally per fold to prevent data leakage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
BenchmarkerConfig
|
Configuration with data,
labels, binarizer, trainer_config template, and benchmarker-specific
options. See |
required |
Examples:
>>> import numpy as np
>>> import pandas as pd
>>> from hgp_lib.configs import BooleanGPConfig, TrainerConfig, BenchmarkerConfig
>>> from hgp_lib.benchmarkers import GPBenchmarker
>>> from hgp_lib.rules import Rule
>>> data = pd.DataFrame({
... "f1": [True, False, True, False, True, False, True, False],
... "f2": [False, True, True, False, False, True, True, False],
... })
>>> labels = np.array([1, 0, 1, 0, 1, 0, 1, 0])
>>> def acc(p, l): return float((p == l).mean())
>>> gp_config = BooleanGPConfig(score_fn=acc, optimize_scorer=False)
>>> trainer_config = TrainerConfig(gp_config=gp_config, num_epochs=3, progress_bar=False)
>>> config = BenchmarkerConfig(
... data=data, labels=labels, trainer_config=trainer_config,
... num_runs=2, n_folds=2, n_jobs=1,
... )
>>> benchmarker = GPBenchmarker(config)
>>> result = benchmarker.fit()
>>> len(result.runs)
2
>>> isinstance(result.best_rule, Rule)
True
Source code in hgp_lib\benchmarkers\gp_benchmarker.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
fit()
Run all benchmark runs (parallel or sequential) and aggregate results.
Each run performs a stratified train/test split, k-fold CV with per-fold binarization, and test-set evaluation. Results across runs are aggregated into an ExperimentResult.
Returns:
| Name | Type | Description |
|---|---|---|
ExperimentResult |
ExperimentResult
|
Contains all run results with methods to get best_run, best_rule, test scores statistics, etc. |
Source code in hgp_lib\benchmarkers\gp_benchmarker.py
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
hgp_lib.benchmarkers.runner.execute_single_run(run_id, seed, config, progress_queue=None)
Execute one benchmark run: stratified train/test split, per-fold binarization, k-fold CV training, best-fold selection, and test-set evaluation.
This is a module-level function so it can be pickled for multiprocessing.
Per-fold binarization: For each fold a fresh clone of the configured
binarizer is fitted on the training fold (with labels, enabling supervised
binning for numerical features) and used to transform the validation fold.
After selecting the best fold, its binarizer transforms the held-out test
data. This prevents data leakage across folds and between train/test sets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_id
|
int
|
Index of the run (0-based). |
required |
seed
|
int
|
Random seed for stratified split and k-fold. |
required |
config
|
BenchmarkerConfig
|
Configuration for the benchmark run. |
required |
progress_queue
|
Queue | None
|
Optional queue for sending progress updates. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
RunResult |
RunResult
|
Contains run_id, seed, folds, test_score, best_rule, feature_names. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If no best rule is available after training a fold. |
Source code in hgp_lib\benchmarkers\runner.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
hgp_lib.benchmarkers.progress.ProgressListener
Listener thread for aggregating progress updates from worker processes.
Runs in the main process and listens to a multiprocessing queue for progress updates from worker processes. Updates three tqdm progress bars: - Experiments (runs) - Folds - Epochs
The listener uses timeouts on queue.get() to periodically check for stop signals, preventing indefinite hangs if workers crash.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
progress_queue
|
Queue
|
Multiprocessing queue for receiving progress updates. |
required |
config
|
ProgressConfig
|
Progress configuration with totals and display settings. |
required |
Examples:
>>> from multiprocessing import Queue
>>> from hgp_lib.benchmarkers.progress import ProgressConfig, ProgressListener
>>> q = Queue()
>>> cfg = ProgressConfig(
... total_runs=1, total_folds=1, total_epochs=1,
... show_run_progress=False, show_fold_progress=False,
... show_epoch_progress=False,
... )
>>> listener = ProgressListener(q, cfg)
>>> listener.start()
>>> q.put(("epoch", 1))
>>> q.put(("fold", 1))
>>> q.put(("run", 1))
>>> listener.join()
Source code in hgp_lib\benchmarkers\progress.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
start()
Start the listener thread.
Source code in hgp_lib\benchmarkers\progress.py
78 79 80 81 82 | |
stop()
Signal the listener to stop and wait for it to finish.
Source code in hgp_lib\benchmarkers\progress.py
84 85 86 87 88 89 90 91 92 93 | |
join()
Wait for the listener thread to finish naturally (all runs completed).
Source code in hgp_lib\benchmarkers\progress.py
95 96 97 98 | |
hgp_lib.benchmarkers.progress.send_progress(progress_queue, msg_type, count=1)
Send a progress update to the listener queue.
This is a safe helper that no-ops if the queue is None (sequential mode).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
progress_queue
|
Queue | None
|
Multiprocessing queue or |
required |
msg_type
|
str
|
Type of progress ( |
required |
count
|
int
|
Number to increment by. Default: |
1
|
Examples:
>>> from hgp_lib.benchmarkers.progress import send_progress
>>> send_progress(None, "epoch", 5) # no-op when queue is None
>>> from multiprocessing import Queue
>>> q = Queue()
>>> send_progress(q, "fold", 1)
>>> q.get()
('fold', 1)
Source code in hgp_lib\benchmarkers\progress.py
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |