MilesCranmer commited on
Commit
465f35e
2 Parent(s): a934083 496cedf

Merge pull request #208 from MilesCranmer/update-backend

Browse files
Files changed (3) hide show
  1. pysr/sr.py +50 -35
  2. pysr/version.py +2 -2
  3. test/test.py +4 -1
pysr/sr.py CHANGED
@@ -476,6 +476,11 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
476
  algorithm than regularized evolution, but does cycles 15%
477
  faster. May be algorithmically less efficient.
478
  Default is `False`.
 
 
 
 
 
479
  precision : int
480
  What precision to use for the data. By default this is `32`
481
  (float32), but you can select `64` or `16` as well, giving
@@ -692,6 +697,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
692
  batching=False,
693
  batch_size=50,
694
  fast_cycle=False,
 
695
  precision=32,
696
  random_state=None,
697
  deterministic=False,
@@ -779,6 +785,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
779
  self.batching = batching
780
  self.batch_size = batch_size
781
  self.fast_cycle = fast_cycle
 
782
  self.precision = precision
783
  self.random_state = random_state
784
  self.deterministic = deterministic
@@ -1518,25 +1525,22 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1518
  str(self.early_stop_condition) if self.early_stop_condition else None
1519
  )
1520
 
1521
- mutation_weights = np.array(
1522
- [
1523
- self.weight_mutate_constant,
1524
- self.weight_mutate_operator,
1525
- self.weight_add_node,
1526
- self.weight_insert_node,
1527
- self.weight_delete_node,
1528
- self.weight_simplify,
1529
- self.weight_randomize,
1530
- self.weight_do_nothing,
1531
- ],
1532
- dtype=float,
1533
  )
1534
 
1535
  # Call to Julia backend.
1536
  # See https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/OptionsStruct.jl
1537
  options = SymbolicRegression.Options(
1538
- binary_operators=Main.eval(str(tuple(binary_operators)).replace("'", "")),
1539
- unary_operators=Main.eval(str(tuple(unary_operators)).replace("'", "")),
1540
  bin_constraints=bin_constraints,
1541
  una_constraints=una_constraints,
1542
  complexity_of_operators=complexity_of_operators,
@@ -1545,45 +1549,47 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1545
  nested_constraints=nested_constraints,
1546
  loss=custom_loss,
1547
  maxsize=int(self.maxsize),
1548
- hofFile=_escape_filename(self.equation_file_),
1549
  npopulations=int(self.populations),
1550
  batching=self.batching,
1551
- batchSize=int(min([batch_size, len(X)]) if self.batching else len(X)),
1552
- mutationWeights=mutation_weights,
1553
- probPickFirst=self.tournament_selection_p,
1554
- ns=self.tournament_selection_n,
1555
  # These have the same name:
1556
  parsimony=self.parsimony,
1557
  alpha=self.alpha,
1558
  maxdepth=maxdepth,
1559
  fast_cycle=self.fast_cycle,
 
1560
  migration=self.migration,
1561
- hofMigration=self.hof_migration,
1562
- fractionReplacedHof=self.fraction_replaced_hof,
1563
- shouldOptimizeConstants=self.should_optimize_constants,
1564
- warmupMaxsizeBy=self.warmup_maxsize_by,
1565
- useFrequency=self.use_frequency,
1566
- useFrequencyInTournament=self.use_frequency_in_tournament,
1567
  npop=self.population_size,
1568
- ncyclesperiteration=self.ncyclesperiteration,
1569
- fractionReplaced=self.fraction_replaced,
1570
  topn=self.topn,
1571
  verbosity=self.verbosity,
1572
  optimizer_algorithm=self.optimizer_algorithm,
1573
  optimizer_nrestarts=self.optimizer_nrestarts,
1574
- optimize_probability=self.optimize_probability,
1575
  optimizer_iterations=self.optimizer_iterations,
1576
- perturbationFactor=self.perturbation_factor,
1577
  annealing=self.annealing,
1578
- stateReturn=True, # Required for state saving.
1579
  progress=progress,
1580
  timeout_in_seconds=self.timeout_in_seconds,
1581
- crossoverProbability=self.crossover_probability,
1582
  skip_mutation_failures=self.skip_mutation_failures,
1583
  max_evals=self.max_evals,
1584
- earlyStopCondition=early_stop_condition,
1585
  seed=seed,
1586
  deterministic=self.deterministic,
 
1587
  )
1588
 
1589
  # Convert data to desired precision
@@ -1603,7 +1609,16 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1603
  else:
1604
  Main.weights = None
1605
 
1606
- cprocs = 0 if multithreading else self.procs
 
 
 
 
 
 
 
 
 
1607
 
1608
  # Call to Julia backend.
1609
  # See https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/SymbolicRegression.jl
@@ -1614,8 +1629,8 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1614
  niterations=int(self.niterations),
1615
  varMap=self.feature_names_in_.tolist(),
1616
  options=options,
1617
- numprocs=int(cprocs),
1618
- multithreading=bool(multithreading),
1619
  saved_state=self.raw_julia_state_,
1620
  addprocs_function=cluster_manager,
1621
  )
 
476
  algorithm than regularized evolution, but does cycles 15%
477
  faster. May be algorithmically less efficient.
478
  Default is `False`.
479
+ turbo: bool
480
+ (Experimental) Whether to use LoopVectorization.jl to speed up the
481
+ search evaluation. Certain operators may not be supported.
482
+ Does not support 16-bit precision floats.
483
+ Default is `False`.
484
  precision : int
485
  What precision to use for the data. By default this is `32`
486
  (float32), but you can select `64` or `16` as well, giving
 
697
  batching=False,
698
  batch_size=50,
699
  fast_cycle=False,
700
+ turbo=False,
701
  precision=32,
702
  random_state=None,
703
  deterministic=False,
 
785
  self.batching = batching
786
  self.batch_size = batch_size
787
  self.fast_cycle = fast_cycle
788
+ self.turbo = turbo
789
  self.precision = precision
790
  self.random_state = random_state
791
  self.deterministic = deterministic
 
1525
  str(self.early_stop_condition) if self.early_stop_condition else None
1526
  )
1527
 
1528
+ mutation_weights = SymbolicRegression.MutationWeights(
1529
+ mutate_constant=self.weight_mutate_constant,
1530
+ mutate_operator=self.weight_mutate_operator,
1531
+ add_node=self.weight_add_node,
1532
+ insert_node=self.weight_insert_node,
1533
+ delete_node=self.weight_delete_node,
1534
+ simplify=self.weight_simplify,
1535
+ randomize=self.weight_randomize,
1536
+ do_nothing=self.weight_do_nothing,
 
 
 
1537
  )
1538
 
1539
  # Call to Julia backend.
1540
  # See https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/OptionsStruct.jl
1541
  options = SymbolicRegression.Options(
1542
+ binary_operators=Main.eval(str(binary_operators).replace("'", "")),
1543
+ unary_operators=Main.eval(str(unary_operators).replace("'", "")),
1544
  bin_constraints=bin_constraints,
1545
  una_constraints=una_constraints,
1546
  complexity_of_operators=complexity_of_operators,
 
1549
  nested_constraints=nested_constraints,
1550
  loss=custom_loss,
1551
  maxsize=int(self.maxsize),
1552
+ output_file=_escape_filename(self.equation_file_),
1553
  npopulations=int(self.populations),
1554
  batching=self.batching,
1555
+ batch_size=int(min([batch_size, len(X)]) if self.batching else len(X)),
1556
+ mutation_weights=mutation_weights,
1557
+ tournament_selection_p=self.tournament_selection_p,
1558
+ tournament_selection_n=self.tournament_selection_n,
1559
  # These have the same name:
1560
  parsimony=self.parsimony,
1561
  alpha=self.alpha,
1562
  maxdepth=maxdepth,
1563
  fast_cycle=self.fast_cycle,
1564
+ turbo=self.turbo,
1565
  migration=self.migration,
1566
+ hof_migration=self.hof_migration,
1567
+ fraction_replaced_hof=self.fraction_replaced_hof,
1568
+ should_optimize_constants=self.should_optimize_constants,
1569
+ warmup_maxsize_by=self.warmup_maxsize_by,
1570
+ use_frequency=self.use_frequency,
1571
+ use_frequency_in_tournament=self.use_frequency_in_tournament,
1572
  npop=self.population_size,
1573
+ ncycles_per_iteration=self.ncyclesperiteration,
1574
+ fraction_replaced=self.fraction_replaced,
1575
  topn=self.topn,
1576
  verbosity=self.verbosity,
1577
  optimizer_algorithm=self.optimizer_algorithm,
1578
  optimizer_nrestarts=self.optimizer_nrestarts,
1579
+ optimizer_probability=self.optimize_probability,
1580
  optimizer_iterations=self.optimizer_iterations,
1581
+ perturbation_factor=self.perturbation_factor,
1582
  annealing=self.annealing,
1583
+ return_state=True, # Required for state saving.
1584
  progress=progress,
1585
  timeout_in_seconds=self.timeout_in_seconds,
1586
+ crossover_probability=self.crossover_probability,
1587
  skip_mutation_failures=self.skip_mutation_failures,
1588
  max_evals=self.max_evals,
1589
+ early_stop_condition=early_stop_condition,
1590
  seed=seed,
1591
  deterministic=self.deterministic,
1592
+ define_helper_functions=False,
1593
  )
1594
 
1595
  # Convert data to desired precision
 
1609
  else:
1610
  Main.weights = None
1611
 
1612
+ if self.procs == 0 and not multithreading:
1613
+ parallelism = "serial"
1614
+ elif multithreading:
1615
+ parallelism = "multithreading"
1616
+ else:
1617
+ parallelism = "multiprocessing"
1618
+
1619
+ cprocs = (
1620
+ None if parallelism in ["serial", "multithreading"] else int(self.procs)
1621
+ )
1622
 
1623
  # Call to Julia backend.
1624
  # See https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/SymbolicRegression.jl
 
1629
  niterations=int(self.niterations),
1630
  varMap=self.feature_names_in_.tolist(),
1631
  options=options,
1632
+ numprocs=cprocs,
1633
+ parallelism=parallelism,
1634
  saved_state=self.raw_julia_state_,
1635
  addprocs_function=cluster_manager,
1636
  )
pysr/version.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "0.11.5"
2
- __symbolic_regression_jl_version__ = "0.12.6"
 
1
+ __version__ = "0.11.6"
2
+ __symbolic_regression_jl_version__ = "0.14.0"
test/test.py CHANGED
@@ -70,12 +70,13 @@ class TestPipeline(unittest.TestCase):
70
  print(model.equations_)
71
  self.assertLessEqual(model.get_best()["loss"], 1e-4)
72
 
73
- def test_multiprocessing(self):
74
  y = self.X[:, 0]
75
  model = PySRRegressor(
76
  **self.default_test_kwargs,
77
  procs=2,
78
  multithreading=False,
 
79
  early_stop_condition="stop_if(loss, complexity) = loss < 1e-4 && complexity == 1",
80
  )
81
  model.fit(self.X, y)
@@ -108,6 +109,8 @@ class TestPipeline(unittest.TestCase):
108
  verbosity=0,
109
  **self.default_test_kwargs,
110
  procs=0,
 
 
111
  # Test custom operators with constraints:
112
  nested_constraints={"square_op": {"square_op": 3}},
113
  constraints={"square_op": 10},
 
70
  print(model.equations_)
71
  self.assertLessEqual(model.get_best()["loss"], 1e-4)
72
 
73
+ def test_multiprocessing_turbo(self):
74
  y = self.X[:, 0]
75
  model = PySRRegressor(
76
  **self.default_test_kwargs,
77
  procs=2,
78
  multithreading=False,
79
+ turbo=True,
80
  early_stop_condition="stop_if(loss, complexity) = loss < 1e-4 && complexity == 1",
81
  )
82
  model.fit(self.X, y)
 
109
  verbosity=0,
110
  **self.default_test_kwargs,
111
  procs=0,
112
+ # Test custom operators with turbo:
113
+ turbo=True,
114
  # Test custom operators with constraints:
115
  nested_constraints={"square_op": {"square_op": 3}},
116
  constraints={"square_op": 10},