tabpackage 0.0.1__tar.gz → 0.0.2.dev0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: tabpackage
3
- Version: 0.0.1
3
+ Version: 0.0.2.dev0
4
4
  Summary: TabPack: efficient parallel training and ensembling of MLPs for tabular deep learning.
5
5
  Keywords: artificial intelligence,classification,deep learning,library,machine learning,python,pytorch,regression,research,torch,tabular,tabular data
6
6
  Author: Yury Gorishniy
@@ -29,7 +29,7 @@ keywords = [
29
29
  name = "tabpackage"
30
30
  readme = "README.md"
31
31
  requires-python = ">=3.11,<4"
32
- version = "0.0.1"
32
+ version = "0.0.2.dev0"
33
33
 
34
34
  [[project.authors]]
35
35
  name = "Yury Gorishniy"
@@ -35,7 +35,7 @@ license = { file = "LICENSE" }
35
35
  name = "tabpackage"
36
36
  readme = "README.md"
37
37
  requires-python = ">=3.11,<4"
38
- version = "0.0.1"
38
+ version = "0.0.2.dev0"
39
39
 
40
40
  [project.optional-dependencies]
41
41
  sklearn = [
@@ -1493,7 +1493,10 @@ class _TabPackConfig:
1493
1493
  ensembles: dict[EnsembleName, EnsembleConfig]
1494
1494
  ensemble_eval_metrics: dict[DatasetName, dict[MetricName, MetricFn]]
1495
1495
  ensemble_eval_criterion: EvalCriterionConfig | None
1496
+
1497
+ # Training loop
1496
1498
  stop_when_all_ensembles_are_finalized: bool
1499
+ training_loop_time_budget: float | None
1497
1500
 
1498
1501
  # Efficiency
1499
1502
  max_pack_size: int
@@ -1754,6 +1757,12 @@ def _check_train_args(
1754
1757
  ):
1755
1758
  raise ValueError('Set `max_epochs` either globally or per model, not both')
1756
1759
 
1760
+ if config.training_loop_time_budget is not None and (
1761
+ not math.isfinite(config.training_loop_time_budget)
1762
+ or config.training_loop_time_budget <= 0
1763
+ ):
1764
+ raise ValueError('The training loop time budget must be finite and positive')
1765
+
1757
1766
  if not (
1758
1767
  config.max_epochs is not None
1759
1768
  or (
@@ -1772,11 +1781,12 @@ def _check_train_args(
1772
1781
  for x in config.ensembles.values()
1773
1782
  )
1774
1783
  )
1784
+ or config.training_loop_time_budget is not None
1775
1785
  ):
1776
1786
  raise ValueError(
1777
- 'Training has no stopping condition. Set an epoch limit globally or for'
1778
- ' every model, enable early stopping for models, or configure all ensembles'
1779
- ' with `online=True` and early stopping and set'
1787
+ 'Training has no stopping condition. Set a time budget, set an epoch limit'
1788
+ ' globally or for every model, enable early stopping for models, or'
1789
+ ' configure all ensembles with `online=True` and early stopping and set'
1780
1790
  ' `stop_when_all_ensembles_are_finalized=True`'
1781
1791
  )
1782
1792
 
@@ -2873,12 +2883,17 @@ def _train(
2873
2883
 
2874
2884
  # >>> Stopping condition
2875
2885
 
2876
- training_loop_is_running = len(
2877
- finished_best_checkpoint_keys
2878
- ) < config.n_models and (
2879
- not ensembles
2880
- or not config.stop_when_all_ensembles_are_finalized
2881
- or any(x.is_running() for x in ensembles.values())
2886
+ training_loop_is_running = (
2887
+ len(finished_best_checkpoint_keys) < config.n_models
2888
+ and (
2889
+ not ensembles
2890
+ or not config.stop_when_all_ensembles_are_finalized
2891
+ or any(x.is_running() for x in ensembles.values())
2892
+ )
2893
+ and (
2894
+ config.training_loop_time_budget is None
2895
+ or get_training_loop_time() < config.training_loop_time_budget
2896
+ )
2882
2897
  )
2883
2898
 
2884
2899
  # >>> Models replacement and removal
@@ -2968,7 +2983,7 @@ def _train(
2968
2983
 
2969
2984
  training_loop_time = get_training_loop_time()
2970
2985
 
2971
- # Ensemble-level stopping can leave models unfinished; save their best
2986
+ # Training-loop-level stopping can leave models unfinished; save their best
2972
2987
  # checkpoints too, even if no ensemble selected them.
2973
2988
  running_pack_mask = training_state.is_running(
2974
2989
  early_stopping_patience=config.early_stopping_patience
@@ -3086,6 +3101,7 @@ def train(
3086
3101
  ) = _MISSING,
3087
3102
  ensemble_eval_criterion: EvalCriterionConfig | _Missing | None = _MISSING,
3088
3103
  stop_when_all_ensembles_are_finalized: bool | _Missing = _MISSING,
3104
+ training_loop_time_budget: float | None = None,
3089
3105
  seed: int | None = None,
3090
3106
  max_pack_size: int | None = None,
3091
3107
  device: int | str | torch.device,
@@ -3112,7 +3128,7 @@ def train(
3112
3128
  models trained in parallel is limited, models that have not started yet begin
3113
3129
  training as others finish. Depending on the provided arguments, the run continues
3114
3130
  either until all models finish or until all ensembles are finalized (even if some
3115
- models are still training).
3131
+ models are still training), or until the time budget is reached.
3116
3132
 
3117
3133
  The result contains the selected checkpoints for making predictions with individual
3118
3134
  models or ensembles on new data, along with evaluation histories for inspecting
@@ -3168,6 +3184,9 @@ def train(
3168
3184
  stop_when_all_ensembles_are_finalized: whether to end training once all
3169
3185
  ensembles are finalized, even if some models are still training.
3170
3186
  Must be provided when `ensembles` is nonempty.
3187
+ training_loop_time_budget: the time budget in seconds for the global training
3188
+ loop. `None` means infinite time budget. Checked after each complete epoch,
3189
+ so at least one epoch runs and the budget may be exceeded.
3171
3190
  seed: the seed for the PyTorch **global** random generators used during
3172
3191
  training. Also, if provided, when the function returns, the state of the
3173
3192
  generators is restored to what it was before the function call. `None` means
@@ -3360,6 +3379,7 @@ def retrain(
3360
3379
  ensemble_eval_metrics={},
3361
3380
  ensemble_eval_criterion=None,
3362
3381
  stop_when_all_ensembles_are_finalized=False,
3382
+ training_loop_time_budget=None,
3363
3383
  )
3364
3384
  with (
3365
3385
  contextlib.nullcontext()
@@ -172,7 +172,9 @@ class _TabPackEstimator(BaseEstimator):
172
172
  ensemble_eval_metrics: list[MetricName] | None = None,
173
173
  ensemble_eval_criterion_dataset: DatasetName | None = None,
174
174
  ensemble_eval_criterion_metric: MetricName | Literal['none'] | None = None,
175
+ # Training loop
175
176
  stop_when_all_ensembles_are_finalized: bool = True,
177
+ training_loop_time_budget: float | None = None,
176
178
  # Reproducibility
177
179
  random_state: int | np.random.RandomState | None = None,
178
180
  # Efficiency
@@ -251,6 +253,10 @@ class _TabPackEstimator(BaseEstimator):
251
253
  version of each ensemble and guide its early stopping.
252
254
  stop_when_all_ensembles_are_finalized: whether to end training once all
253
255
  ensembles are finalized, even if some models are still training.
256
+ training_loop_time_budget: the time budget in seconds for the global
257
+ training loop. `None` means infinite time budget. Checked after each
258
+ complete epoch, so at least one epoch runs and the budget may be
259
+ exceeded. Not applied during `refit`.
254
260
  random_state: controls randomness in hyperparameter sampling and training.
255
261
  max_pack_size: the maximum number of models trained in parallel.
256
262
  device: the device used for training and prediction.
@@ -312,9 +318,11 @@ class _TabPackEstimator(BaseEstimator):
312
318
  self.ensemble_eval_metrics = ensemble_eval_metrics
313
319
  self.ensemble_eval_criterion_dataset = ensemble_eval_criterion_dataset
314
320
  self.ensemble_eval_criterion_metric = ensemble_eval_criterion_metric
321
+
315
322
  self.stop_when_all_ensembles_are_finalized = (
316
323
  stop_when_all_ensembles_are_finalized
317
324
  )
325
+ self.training_loop_time_budget = training_loop_time_budget
318
326
 
319
327
  self.random_state = random_state
320
328
 
@@ -746,6 +754,7 @@ class _TabPackEstimator(BaseEstimator):
746
754
  'eval_criterion': eval_criterion,
747
755
  'eval_batch_size': eval_batch_size,
748
756
  'ensembles': ensemble_configs,
757
+ 'training_loop_time_budget': self.training_loop_time_budget,
749
758
  'max_pack_size': self.max_pack_size,
750
759
  'device': device,
751
760
  'aux_device': aux_device,
@@ -904,6 +913,15 @@ class _TabPackEstimator(BaseEstimator):
904
913
  prediction_ensemble = self._resolve_prediction_ensemble(
905
914
  list(train_kwargs['ensembles'])
906
915
  )
916
+ if (
917
+ prediction_ensemble is not None
918
+ and not train_kwargs['ensembles'][prediction_ensemble].online
919
+ and train_kwargs['training_loop_time_budget'] is not None
920
+ ):
921
+ raise ValueError(
922
+ 'Setting the training time budget is not allowed when the prediction'
923
+ ' ensemble is an offline ensemble'
924
+ )
907
925
  predictor_key = (
908
926
  None
909
927
  if prediction_ensemble is None
@@ -1068,6 +1086,7 @@ class _TabPackEstimator(BaseEstimator):
1068
1086
  'ensemble_eval_metrics',
1069
1087
  'ensemble_eval_criterion',
1070
1088
  'stop_when_all_ensembles_are_finalized',
1089
+ 'training_loop_time_budget',
1071
1090
  ):
1072
1091
  train_kwargs.pop(name, None)
1073
1092
  train_kwargs.update(
File without changes
File without changes