MilesCranmer commited on
Commit
5bf2e55
·
unverified ·
2 Parent(s): 2ab2a53 f2294b3

Merge pull request #493 from MilesCranmer/heap-size-hint

Browse files

Add parameter for specifying `--heap-size-hint` on spawned Julia processes

Files changed (4) hide show
  1. pysr/param_groupings.yml +1 -0
  2. pysr/sr.py +98 -85
  3. pysr/version.py +2 -2
  4. setup.py +1 -1
pysr/param_groupings.yml CHANGED
@@ -67,6 +67,7 @@
67
  - procs
68
  - multithreading
69
  - cluster_manager
 
70
  - batching
71
  - batch_size
72
  - precision
 
67
  - procs
68
  - multithreading
69
  - cluster_manager
70
+ - heap_size_hint_in_bytes
71
  - batching
72
  - batch_size
73
  - precision
pysr/sr.py CHANGED
@@ -11,7 +11,7 @@ from datetime import datetime
11
  from io import StringIO
12
  from multiprocessing import cpu_count
13
  from pathlib import Path
14
- from typing import List, Optional
15
 
16
  import numpy as np
17
  import pandas as pd
@@ -171,7 +171,7 @@ def _check_assertions(
171
 
172
 
173
  # Class validation constants
174
- VALID_OPTIMIZER_ALGORITHMS = ["NelderMead", "BFGS"]
175
 
176
 
177
  class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
@@ -455,6 +455,12 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
455
  "htc". If set to one of these, PySR will run in distributed
456
  mode, and use `procs` to figure out how many processes to launch.
457
  Default is `None`.
 
 
 
 
 
 
458
  batching : bool
459
  Whether to compare population members on small batches during
460
  evolution. Still uses full dataset for comparing against hall
@@ -653,89 +659,92 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
653
 
654
  def __init__(
655
  self,
656
- model_selection="best",
657
  *,
658
- binary_operators=None,
659
- unary_operators=None,
660
- niterations=40,
661
- populations=15,
662
- population_size=33,
663
- max_evals=None,
664
- maxsize=20,
665
- maxdepth=None,
666
- warmup_maxsize_by=0.0,
667
- timeout_in_seconds=None,
668
- constraints=None,
669
- nested_constraints=None,
670
- loss=None,
671
- full_objective=None,
672
- complexity_of_operators=None,
673
- complexity_of_constants=1,
674
- complexity_of_variables=1,
675
- parsimony=0.0032,
676
- dimensional_constraint_penalty=None,
677
- use_frequency=True,
678
- use_frequency_in_tournament=True,
679
- adaptive_parsimony_scaling=20.0,
680
- alpha=0.1,
681
- annealing=False,
682
- early_stop_condition=None,
683
- ncyclesperiteration=550,
684
- fraction_replaced=0.000364,
685
- fraction_replaced_hof=0.035,
686
- weight_add_node=0.79,
687
- weight_insert_node=5.1,
688
- weight_delete_node=1.7,
689
- weight_do_nothing=0.21,
690
- weight_mutate_constant=0.048,
691
- weight_mutate_operator=0.47,
692
- weight_randomize=0.00023,
693
- weight_simplify=0.0020,
694
- weight_optimize=0.0,
695
- crossover_probability=0.066,
696
- skip_mutation_failures=True,
697
- migration=True,
698
- hof_migration=True,
699
- topn=12,
700
- should_simplify=None,
701
- should_optimize_constants=True,
702
- optimizer_algorithm="BFGS",
703
- optimizer_nrestarts=2,
704
- optimize_probability=0.14,
705
- optimizer_iterations=8,
706
- perturbation_factor=0.076,
707
- tournament_selection_n=10,
708
- tournament_selection_p=0.86,
709
- procs=cpu_count(),
710
- multithreading=None,
711
- cluster_manager=None,
712
- batching=False,
713
- batch_size=50,
714
- fast_cycle=False,
715
- turbo=False,
716
- precision=32,
717
- enable_autodiff=False,
 
 
 
718
  random_state=None,
719
- deterministic=False,
720
- warm_start=False,
721
- verbosity=1,
722
- update_verbosity=None,
723
- print_precision=5,
724
- progress=True,
725
- equation_file=None,
726
- temp_equation_file=False,
727
- tempdir=None,
728
- delete_tempfiles=True,
729
- julia_project=None,
730
- update=False,
731
- output_jax_format=False,
732
- output_torch_format=False,
733
- extra_sympy_mappings=None,
734
- extra_torch_mappings=None,
735
- extra_jax_mappings=None,
736
- denoise=False,
737
- select_k_features=None,
738
- julia_kwargs=None,
739
  **kwargs,
740
  ):
741
  # Hyperparameters
@@ -800,10 +809,11 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
800
  # -- Selection parameters
801
  self.tournament_selection_n = tournament_selection_n
802
  self.tournament_selection_p = tournament_selection_p
803
- # Solver parameters
804
  self.procs = procs
805
  self.multithreading = multithreading
806
  self.cluster_manager = cluster_manager
 
807
  self.batching = batching
808
  self.batch_size = batch_size
809
  self.fast_cycle = fast_cycle
@@ -1637,7 +1647,9 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1637
  fraction_replaced_hof=self.fraction_replaced_hof,
1638
  should_simplify=self.should_simplify,
1639
  should_optimize_constants=self.should_optimize_constants,
1640
- warmup_maxsize_by=self.warmup_maxsize_by,
 
 
1641
  use_frequency=self.use_frequency,
1642
  use_frequency_in_tournament=self.use_frequency_in_tournament,
1643
  adaptive_parsimony_scaling=self.adaptive_parsimony_scaling,
@@ -1720,6 +1732,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1720
  saved_state=self.raw_julia_state_,
1721
  return_state=True,
1722
  addprocs_function=cluster_manager,
 
1723
  progress=progress and self.verbosity > 0 and len(y.shape) == 1,
1724
  verbosity=int(self.verbosity),
1725
  )
 
11
  from io import StringIO
12
  from multiprocessing import cpu_count
13
  from pathlib import Path
14
+ from typing import Callable, Dict, List, Literal, Optional, Tuple, Union
15
 
16
  import numpy as np
17
  import pandas as pd
 
171
 
172
 
173
  # Class validation constants
174
+ VALID_OPTIMIZER_ALGORITHMS = ["BFGS", "NelderMead"]
175
 
176
 
177
  class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
 
455
  "htc". If set to one of these, PySR will run in distributed
456
  mode, and use `procs` to figure out how many processes to launch.
457
  Default is `None`.
458
+ heap_size_hint_in_bytes : int
459
+ For multiprocessing, this sets the `--heap-size-hint` parameter
460
+ for new Julia processes. This can be configured when using
461
+ multi-node distributed compute, to give a hint to each process
462
+ about how much memory they can use before aggressive garbage
463
+ collection.
464
  batching : bool
465
  Whether to compare population members on small batches during
466
  evolution. Still uses full dataset for comparing against hall
 
659
 
660
  def __init__(
661
  self,
662
+ model_selection: Literal["best", "accuracy", "score"] = "best",
663
  *,
664
+ binary_operators: Optional[List[str]] = None,
665
+ unary_operators: Optional[List[str]] = None,
666
+ niterations: int = 40,
667
+ populations: int = 15,
668
+ population_size: int = 33,
669
+ max_evals: Optional[int] = None,
670
+ maxsize: int = 20,
671
+ maxdepth: Optional[int] = None,
672
+ warmup_maxsize_by: Optional[float] = None,
673
+ timeout_in_seconds: Optional[float] = None,
674
+ constraints: Optional[Dict[str, Union[int, Tuple[int, int]]]] = None,
675
+ nested_constraints: Optional[Dict[str, Dict[str, int]]] = None,
676
+ loss: Optional[str] = None,
677
+ full_objective: Optional[str] = None,
678
+ complexity_of_operators: Optional[Dict[str, Union[int, float]]] = None,
679
+ complexity_of_constants: Union[int, float] = 1,
680
+ complexity_of_variables: Union[int, float] = 1,
681
+ parsimony: float = 0.0032,
682
+ dimensional_constraint_penalty: Optional[float] = None,
683
+ use_frequency: bool = True,
684
+ use_frequency_in_tournament: bool = True,
685
+ adaptive_parsimony_scaling: float = 20.0,
686
+ alpha: float = 0.1,
687
+ annealing: bool = False,
688
+ early_stop_condition: Optional[Union[float, str]] = None,
689
+ ncyclesperiteration: int = 550,
690
+ fraction_replaced: float = 0.000364,
691
+ fraction_replaced_hof: float = 0.035,
692
+ weight_add_node: float = 0.79,
693
+ weight_insert_node: float = 5.1,
694
+ weight_delete_node: float = 1.7,
695
+ weight_do_nothing: float = 0.21,
696
+ weight_mutate_constant: float = 0.048,
697
+ weight_mutate_operator: float = 0.47,
698
+ weight_randomize: float = 0.00023,
699
+ weight_simplify: float = 0.0020,
700
+ weight_optimize: float = 0.0,
701
+ crossover_probability: float = 0.066,
702
+ skip_mutation_failures: bool = True,
703
+ migration: bool = True,
704
+ hof_migration: bool = True,
705
+ topn: int = 12,
706
+ should_simplify: Optional[bool] = None,
707
+ should_optimize_constants: bool = True,
708
+ optimizer_algorithm: Literal["BFGS", "NelderMead"] = "BFGS",
709
+ optimizer_nrestarts: int = 2,
710
+ optimize_probability: float = 0.14,
711
+ optimizer_iterations: int = 8,
712
+ perturbation_factor: float = 0.076,
713
+ tournament_selection_n: int = 10,
714
+ tournament_selection_p: float = 0.86,
715
+ procs: int = cpu_count(),
716
+ multithreading: Optional[bool] = None,
717
+ cluster_manager: Optional[
718
+ Literal["slurm", "pbs", "lsf", "sge", "qrsh", "scyld", "htc"]
719
+ ] = None,
720
+ heap_size_hint_in_bytes: Optional[int] = None,
721
+ batching: bool = False,
722
+ batch_size: int = 50,
723
+ fast_cycle: bool = False,
724
+ turbo: bool = False,
725
+ precision: int = 32,
726
+ enable_autodiff: bool = False,
727
  random_state=None,
728
+ deterministic: bool = False,
729
+ warm_start: bool = False,
730
+ verbosity: int = 1,
731
+ update_verbosity: Optional[int] = None,
732
+ print_precision: int = 5,
733
+ progress: bool = True,
734
+ equation_file: Optional[str] = None,
735
+ temp_equation_file: bool = False,
736
+ tempdir: Optional[str] = None,
737
+ delete_tempfiles: bool = True,
738
+ julia_project: Optional[str] = None,
739
+ update: bool = False,
740
+ output_jax_format: bool = False,
741
+ output_torch_format: bool = False,
742
+ extra_sympy_mappings: Optional[Dict[str, Callable]] = None,
743
+ extra_torch_mappings: Optional[Dict[Callable, Callable]] = None,
744
+ extra_jax_mappings: Optional[Dict[Callable, str]] = None,
745
+ denoise: bool = False,
746
+ select_k_features: Optional[int] = None,
747
+ julia_kwargs: Optional[Dict] = None,
748
  **kwargs,
749
  ):
750
  # Hyperparameters
 
809
  # -- Selection parameters
810
  self.tournament_selection_n = tournament_selection_n
811
  self.tournament_selection_p = tournament_selection_p
812
+ # -- Performance parameters
813
  self.procs = procs
814
  self.multithreading = multithreading
815
  self.cluster_manager = cluster_manager
816
+ self.heap_size_hint_in_bytes = heap_size_hint_in_bytes
817
  self.batching = batching
818
  self.batch_size = batch_size
819
  self.fast_cycle = fast_cycle
 
1647
  fraction_replaced_hof=self.fraction_replaced_hof,
1648
  should_simplify=self.should_simplify,
1649
  should_optimize_constants=self.should_optimize_constants,
1650
+ warmup_maxsize_by=0.0
1651
+ if self.warmup_maxsize_by is None
1652
+ else self.warmup_maxsize_by,
1653
  use_frequency=self.use_frequency,
1654
  use_frequency_in_tournament=self.use_frequency_in_tournament,
1655
  adaptive_parsimony_scaling=self.adaptive_parsimony_scaling,
 
1732
  saved_state=self.raw_julia_state_,
1733
  return_state=True,
1734
  addprocs_function=cluster_manager,
1735
+ heap_size_hint_in_bytes=self.heap_size_hint_in_bytes,
1736
  progress=progress and self.verbosity > 0 and len(y.shape) == 1,
1737
  verbosity=int(self.verbosity),
1738
  )
pysr/version.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "0.16.5"
2
- __symbolic_regression_jl_version__ = "0.22.5"
 
1
+ __version__ = "0.16.6"
2
+ __symbolic_regression_jl_version__ = "0.23.0"
setup.py CHANGED
@@ -26,5 +26,5 @@ setuptools.setup(
26
  "Programming Language :: Python :: 3",
27
  "Operating System :: OS Independent",
28
  ],
29
- python_requires=">=3.7",
30
  )
 
26
  "Programming Language :: Python :: 3",
27
  "Operating System :: OS Independent",
28
  ],
29
+ python_requires=">=3.8",
30
  )