Spaces:
Sleeping
Sleeping
MilesCranmer
commited on
Merge pull request #208 from MilesCranmer/update-backend
Browse files- pysr/sr.py +50 -35
- pysr/version.py +2 -2
- 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 =
|
1522 |
-
|
1523 |
-
|
1524 |
-
|
1525 |
-
|
1526 |
-
|
1527 |
-
|
1528 |
-
|
1529 |
-
|
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(
|
1539 |
-
unary_operators=Main.eval(str(
|
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 |
-
|
1549 |
npopulations=int(self.populations),
|
1550 |
batching=self.batching,
|
1551 |
-
|
1552 |
-
|
1553 |
-
|
1554 |
-
|
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 |
-
|
1562 |
-
|
1563 |
-
|
1564 |
-
|
1565 |
-
|
1566 |
-
|
1567 |
npop=self.population_size,
|
1568 |
-
|
1569 |
-
|
1570 |
topn=self.topn,
|
1571 |
verbosity=self.verbosity,
|
1572 |
optimizer_algorithm=self.optimizer_algorithm,
|
1573 |
optimizer_nrestarts=self.optimizer_nrestarts,
|
1574 |
-
|
1575 |
optimizer_iterations=self.optimizer_iterations,
|
1576 |
-
|
1577 |
annealing=self.annealing,
|
1578 |
-
|
1579 |
progress=progress,
|
1580 |
timeout_in_seconds=self.timeout_in_seconds,
|
1581 |
-
|
1582 |
skip_mutation_failures=self.skip_mutation_failures,
|
1583 |
max_evals=self.max_evals,
|
1584 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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=
|
1618 |
-
|
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.
|
2 |
-
__symbolic_regression_jl_version__ = "0.
|
|
|
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
|
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},
|