Spaces:
Running
Running
MilesCranmer
commited on
Commit
•
a4bb529
1
Parent(s):
139b8d0
Run in `Main`
Browse files- pysr/julia_helpers.py +7 -4
- pysr/sr.py +14 -18
- pysr/test/test.py +6 -6
pysr/julia_helpers.py
CHANGED
@@ -11,11 +11,8 @@ if os.environ.get("PYTHON_JULIACALL_HANDLE_SIGNALS", "yes") != "yes":
|
|
11 |
|
12 |
os.environ["PYTHON_JULIACALL_HANDLE_SIGNALS"] = "yes"
|
13 |
|
14 |
-
import juliacall
|
15 |
import juliapkg
|
16 |
-
|
17 |
-
jl = juliacall.newmodule("PySR")
|
18 |
-
|
19 |
from juliacall import convert as jl_convert
|
20 |
|
21 |
jl.seval("using PythonCall: PythonCall")
|
@@ -53,3 +50,9 @@ def _backend_version_assertion():
|
|
53 |
def _load_cluster_manager(cluster_manager):
|
54 |
jl.seval(f"using ClusterManagers: addprocs_{cluster_manager}")
|
55 |
return jl.seval(f"addprocs_{cluster_manager}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
os.environ["PYTHON_JULIACALL_HANDLE_SIGNALS"] = "yes"
|
13 |
|
|
|
14 |
import juliapkg
|
15 |
+
from juliacall import Main as jl
|
|
|
|
|
16 |
from juliacall import convert as jl_convert
|
17 |
|
18 |
jl.seval("using PythonCall: PythonCall")
|
|
|
50 |
def _load_cluster_manager(cluster_manager):
|
51 |
jl.seval(f"using ClusterManagers: addprocs_{cluster_manager}")
|
52 |
return jl.seval(f"addprocs_{cluster_manager}")
|
53 |
+
|
54 |
+
|
55 |
+
def jl_array(x):
|
56 |
+
if x is None:
|
57 |
+
return None
|
58 |
+
return jl_convert(jl.Array, x)
|
pysr/sr.py
CHANGED
@@ -37,6 +37,7 @@ from .julia_helpers import (
|
|
37 |
_escape_filename,
|
38 |
_load_cluster_manager,
|
39 |
jl,
|
|
|
40 |
jl_convert,
|
41 |
)
|
42 |
from .utils import (
|
@@ -1618,8 +1619,8 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
|
|
1618 |
options = SymbolicRegression.Options(
|
1619 |
binary_operators=jl.seval(str(binary_operators).replace("'", "")),
|
1620 |
unary_operators=jl.seval(str(unary_operators).replace("'", "")),
|
1621 |
-
bin_constraints=
|
1622 |
-
una_constraints=
|
1623 |
complexity_of_operators=complexity_of_operators,
|
1624 |
complexity_of_constants=self.complexity_of_constants,
|
1625 |
complexity_of_variables=self.complexity_of_variables,
|
@@ -1684,16 +1685,16 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
|
|
1684 |
np_dtype = {32: np.complex64, 64: np.complex128}[self.precision]
|
1685 |
|
1686 |
# This converts the data into a Julia array:
|
1687 |
-
jl_X =
|
1688 |
if len(y.shape) == 1:
|
1689 |
-
jl_y =
|
1690 |
else:
|
1691 |
-
jl_y =
|
1692 |
if weights is not None:
|
1693 |
if len(weights.shape) == 1:
|
1694 |
-
jl_weights =
|
1695 |
else:
|
1696 |
-
jl_weights =
|
1697 |
else:
|
1698 |
jl_weights = None
|
1699 |
|
@@ -1711,17 +1712,12 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
|
|
1711 |
if len(y.shape) > 1:
|
1712 |
# We set these manually so that they respect Python's 0 indexing
|
1713 |
# (by default Julia will use y1, y2...)
|
1714 |
-
jl_y_variable_names =
|
1715 |
-
|
1716 |
)
|
1717 |
else:
|
1718 |
jl_y_variable_names = None
|
1719 |
|
1720 |
-
jl_feature_names = jl_convert(jl.Vector, self.feature_names_in_.tolist())
|
1721 |
-
jl_display_feature_names = jl_convert(
|
1722 |
-
jl.Vector, self.display_feature_names_in_.tolist()
|
1723 |
-
)
|
1724 |
-
|
1725 |
PythonCall.GC.disable()
|
1726 |
# Call to Julia backend.
|
1727 |
# See https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/SymbolicRegression.jl
|
@@ -1730,11 +1726,11 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
|
|
1730 |
jl_y,
|
1731 |
weights=jl_weights,
|
1732 |
niterations=int(self.niterations),
|
1733 |
-
variable_names=
|
1734 |
-
display_variable_names=
|
1735 |
y_variable_names=jl_y_variable_names,
|
1736 |
-
X_units=self.X_units_,
|
1737 |
-
y_units=self.y_units_,
|
1738 |
options=options,
|
1739 |
numprocs=cprocs,
|
1740 |
parallelism=parallelism,
|
|
|
37 |
_escape_filename,
|
38 |
_load_cluster_manager,
|
39 |
jl,
|
40 |
+
jl_array,
|
41 |
jl_convert,
|
42 |
)
|
43 |
from .utils import (
|
|
|
1619 |
options = SymbolicRegression.Options(
|
1620 |
binary_operators=jl.seval(str(binary_operators).replace("'", "")),
|
1621 |
unary_operators=jl.seval(str(unary_operators).replace("'", "")),
|
1622 |
+
bin_constraints=jl_array(bin_constraints),
|
1623 |
+
una_constraints=jl_array(una_constraints),
|
1624 |
complexity_of_operators=complexity_of_operators,
|
1625 |
complexity_of_constants=self.complexity_of_constants,
|
1626 |
complexity_of_variables=self.complexity_of_variables,
|
|
|
1685 |
np_dtype = {32: np.complex64, 64: np.complex128}[self.precision]
|
1686 |
|
1687 |
# This converts the data into a Julia array:
|
1688 |
+
jl_X = jl_array(np.array(X, dtype=np_dtype).T)
|
1689 |
if len(y.shape) == 1:
|
1690 |
+
jl_y = jl_array(np.array(y, dtype=np_dtype))
|
1691 |
else:
|
1692 |
+
jl_y = jl_array(np.array(y, dtype=np_dtype).T)
|
1693 |
if weights is not None:
|
1694 |
if len(weights.shape) == 1:
|
1695 |
+
jl_weights = jl_array(np.array(weights, dtype=np_dtype))
|
1696 |
else:
|
1697 |
+
jl_weights = jl_array(np.array(weights, dtype=np_dtype).T)
|
1698 |
else:
|
1699 |
jl_weights = None
|
1700 |
|
|
|
1712 |
if len(y.shape) > 1:
|
1713 |
# We set these manually so that they respect Python's 0 indexing
|
1714 |
# (by default Julia will use y1, y2...)
|
1715 |
+
jl_y_variable_names = jl_array(
|
1716 |
+
[f"y{_subscriptify(i)}" for i in range(y.shape[1])]
|
1717 |
)
|
1718 |
else:
|
1719 |
jl_y_variable_names = None
|
1720 |
|
|
|
|
|
|
|
|
|
|
|
1721 |
PythonCall.GC.disable()
|
1722 |
# Call to Julia backend.
|
1723 |
# See https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/SymbolicRegression.jl
|
|
|
1726 |
jl_y,
|
1727 |
weights=jl_weights,
|
1728 |
niterations=int(self.niterations),
|
1729 |
+
variable_names=jl_array(self.feature_names_in_.tolist()),
|
1730 |
+
display_variable_names=jl_array(self.display_feature_names_in_.tolist()),
|
1731 |
y_variable_names=jl_y_variable_names,
|
1732 |
+
X_units=jl_array(self.X_units_),
|
1733 |
+
y_units=jl_array(self.y_units_),
|
1734 |
options=options,
|
1735 |
numprocs=cprocs,
|
1736 |
parallelism=parallelism,
|
pysr/test/test.py
CHANGED
@@ -106,11 +106,11 @@ class TestPipeline(unittest.TestCase):
|
|
106 |
warm_start=True,
|
107 |
)
|
108 |
model.fit(self.X, y)
|
109 |
-
from pysr.sr import
|
110 |
|
111 |
# We should have that the model state is now a Float64 hof:
|
112 |
-
|
113 |
-
self.assertTrue(
|
114 |
|
115 |
def test_multioutput_custom_operator_quiet_custom_complexity(self):
|
116 |
y = self.X[:, [0, 1]] ** 2
|
@@ -229,11 +229,11 @@ class TestPipeline(unittest.TestCase):
|
|
229 |
early_stop_condition=None,
|
230 |
)
|
231 |
# Check that the the julia state is saved:
|
232 |
-
from pysr.sr import
|
233 |
|
234 |
# We should have that the model state is now a Float32 hof:
|
235 |
-
|
236 |
-
self.assertTrue(
|
237 |
# This should exit almost immediately, and use the old equations
|
238 |
regressor.fit(X, y)
|
239 |
|
|
|
106 |
warm_start=True,
|
107 |
)
|
108 |
model.fit(self.X, y)
|
109 |
+
from pysr.sr import jl
|
110 |
|
111 |
# We should have that the model state is now a Float64 hof:
|
112 |
+
jl.test_state = model.raw_julia_state_
|
113 |
+
self.assertTrue(jl.seval("typeof(test_state[2]).parameters[1] == Float64"))
|
114 |
|
115 |
def test_multioutput_custom_operator_quiet_custom_complexity(self):
|
116 |
y = self.X[:, [0, 1]] ** 2
|
|
|
229 |
early_stop_condition=None,
|
230 |
)
|
231 |
# Check that the the julia state is saved:
|
232 |
+
from pysr.sr import jl
|
233 |
|
234 |
# We should have that the model state is now a Float32 hof:
|
235 |
+
jl.test_state = regressor.raw_julia_state_
|
236 |
+
self.assertTrue(jl.eval("typeof(test_state[2]).parameters[1] == Float32"))
|
237 |
# This should exit almost immediately, and use the old equations
|
238 |
regressor.fit(X, y)
|
239 |
|