MilesCranmer commited on
Commit
d16abb4
1 Parent(s): fc67c56

Rename loss => elementwise_loss and full_objective => loss_function

Browse files
README.md CHANGED
@@ -214,7 +214,7 @@ model = PySRRegressor(
214
  ],
215
  extra_sympy_mappings={"inv": lambda x: 1 / x},
216
  # ^ Define operator for SymPy as well
217
- loss="loss(prediction, target) = (prediction - target)^2",
218
  # ^ Custom loss function (julia syntax)
219
  )
220
  ```
 
214
  ],
215
  extra_sympy_mappings={"inv": lambda x: 1 / x},
216
  # ^ Define operator for SymPy as well
217
+ elementwise_loss="loss(prediction, target) = (prediction - target)^2",
218
  # ^ Custom loss function (julia syntax)
219
  )
220
  ```
docs/examples.md CHANGED
@@ -144,7 +144,7 @@ but there are still some additional steps you can take to reduce the effect of n
144
 
145
  One thing you could do, which we won't detail here, is to create a custom log-likelihood
146
  given some assumed noise model. By passing weights to the fit function, and
147
- defining a custom loss function such as `loss="myloss(x, y, w) = w * (x - y)^2"`,
148
  you can define any sort of log-likelihood you wish. (However, note that it must be bounded at zero)
149
 
150
  However, the simplest thing to do is preprocessing, just like for feature selection. To do this,
@@ -380,7 +380,7 @@ end
380
  model = PySRRegressor(
381
  niterations=100,
382
  binary_operators=["*", "+", "-"],
383
- full_objective=objective,
384
  )
385
  ```
386
 
@@ -462,7 +462,7 @@ let's also create a custom loss function
462
  that looks at the error in log-space:
463
 
464
  ```python
465
- loss = """function loss_fnc(prediction, target)
466
  scatter_loss = abs(log((abs(prediction)+1e-20) / (abs(target)+1e-20)))
467
  sign_loss = 10 * (sign(prediction) - sign(target))^2
468
  return scatter_loss + sign_loss
@@ -476,7 +476,7 @@ Now let's define our model:
476
  model = PySRRegressor(
477
  binary_operators=["+", "-", "*", "/"],
478
  unary_operators=["square"],
479
- loss=loss,
480
  complexity_of_constants=2,
481
  maxsize=25,
482
  niterations=100,
 
144
 
145
  One thing you could do, which we won't detail here, is to create a custom log-likelihood
146
  given some assumed noise model. By passing weights to the fit function, and
147
+ defining a custom loss function such as `elementwise_loss="myloss(x, y, w) = w * (x - y)^2"`,
148
  you can define any sort of log-likelihood you wish. (However, note that it must be bounded at zero)
149
 
150
  However, the simplest thing to do is preprocessing, just like for feature selection. To do this,
 
380
  model = PySRRegressor(
381
  niterations=100,
382
  binary_operators=["*", "+", "-"],
383
+ loss_function=objective,
384
  )
385
  ```
386
 
 
462
  that looks at the error in log-space:
463
 
464
  ```python
465
+ elementwise_loss = """function loss_fnc(prediction, target)
466
  scatter_loss = abs(log((abs(prediction)+1e-20) / (abs(target)+1e-20)))
467
  sign_loss = 10 * (sign(prediction) - sign(target))^2
468
  return scatter_loss + sign_loss
 
476
  model = PySRRegressor(
477
  binary_operators=["+", "-", "*", "/"],
478
  unary_operators=["square"],
479
+ elementwise_loss=elementwise_loss,
480
  complexity_of_constants=2,
481
  maxsize=25,
482
  niterations=100,
docs/options.md CHANGED
@@ -243,7 +243,7 @@ train the parameters within JAX (and is differentiable).
243
 
244
  The default loss is mean-square error, and weighted mean-square error.
245
  One can pass an arbitrary Julia string to define a custom loss, using,
246
- e.g., `loss="myloss(x, y) = abs(x - y)^1.5"`. For more details,
247
  see the
248
  [Losses](https://milescranmer.github.io/SymbolicRegression.jl/dev/losses/)
249
  page for SymbolicRegression.jl.
@@ -253,26 +253,26 @@ Here are some additional examples:
253
  abs(x-y) loss
254
 
255
  ```python
256
- PySRRegressor(..., loss="f(x, y) = abs(x - y)^1.5")
257
  ```
258
 
259
  Note that the function name doesn't matter:
260
 
261
  ```python
262
- PySRRegressor(..., loss="loss(x, y) = abs(x * y)")
263
  ```
264
 
265
  With weights:
266
 
267
  ```python
268
- model = PySRRegressor(..., loss="myloss(x, y, w) = w * abs(x - y)")
269
  model.fit(..., weights=weights)
270
  ```
271
 
272
  Weights can be used in arbitrary ways:
273
 
274
  ```python
275
- model = PySRRegressor(..., weights=weights, loss="myloss(x, y, w) = abs(x - y)^2/w^2")
276
  model.fit(..., weights=weights)
277
  ```
278
 
@@ -280,13 +280,13 @@ Built-in loss (faster) (see [losses](https://astroautomata.com/SymbolicRegressio
280
  This one computes the L3 norm:
281
 
282
  ```python
283
- PySRRegressor(..., loss="LPDistLoss{3}()")
284
  ```
285
 
286
  Can also uses these losses for weighted (weighted-average):
287
 
288
  ```python
289
- model = PySRRegressor(..., weights=weights, loss="LPDistLoss{3}()")
290
  model.fit(..., weights=weights)
291
  ```
292
 
 
243
 
244
  The default loss is mean-square error, and weighted mean-square error.
245
  One can pass an arbitrary Julia string to define a custom loss, using,
246
+ e.g., `elementwise_loss="myloss(x, y) = abs(x - y)^1.5"`. For more details,
247
  see the
248
  [Losses](https://milescranmer.github.io/SymbolicRegression.jl/dev/losses/)
249
  page for SymbolicRegression.jl.
 
253
  abs(x-y) loss
254
 
255
  ```python
256
+ PySRRegressor(..., elementwise_loss="f(x, y) = abs(x - y)^1.5")
257
  ```
258
 
259
  Note that the function name doesn't matter:
260
 
261
  ```python
262
+ PySRRegressor(..., elementwise_loss="loss(x, y) = abs(x * y)")
263
  ```
264
 
265
  With weights:
266
 
267
  ```python
268
+ model = PySRRegressor(..., elementwise_loss="myloss(x, y, w) = w * abs(x - y)")
269
  model.fit(..., weights=weights)
270
  ```
271
 
272
  Weights can be used in arbitrary ways:
273
 
274
  ```python
275
+ model = PySRRegressor(..., weights=weights, elementwise_loss="myloss(x, y, w) = abs(x - y)^2/w^2")
276
  model.fit(..., weights=weights)
277
  ```
278
 
 
280
  This one computes the L3 norm:
281
 
282
  ```python
283
+ PySRRegressor(..., elementwise_loss="LPDistLoss{3}()")
284
  ```
285
 
286
  Can also uses these losses for weighted (weighted-average):
287
 
288
  ```python
289
+ model = PySRRegressor(..., weights=weights, elementwise_loss="LPDistLoss{3}()")
290
  model.fit(..., weights=weights)
291
  ```
292
 
example.py CHANGED
@@ -18,7 +18,7 @@ model = PySRRegressor(
18
  ],
19
  extra_sympy_mappings={"inv": lambda x: 1 / x},
20
  # ^ Define operator for SymPy as well
21
- loss="loss(x, y) = (x - y)^2",
22
  # ^ Custom loss function (julia syntax)
23
  )
24
 
 
18
  ],
19
  extra_sympy_mappings={"inv": lambda x: 1 / x},
20
  # ^ Define operator for SymPy as well
21
+ elementwise_loss="loss(x, y) = (x - y)^2",
22
  # ^ Custom loss function (julia syntax)
23
  )
24
 
examples/pysr_demo.ipynb CHANGED
@@ -576,7 +576,7 @@
576
  "outputs": [],
577
  "source": [
578
  "model = PySRRegressor(\n",
579
- " loss=\"myloss(x, y, w) = w * abs(x - y)\", # Custom loss function with weights.\n",
580
  " niterations=20,\n",
581
  " populations=20, # Use more populations\n",
582
  " binary_operators=[\"+\", \"*\"],\n",
 
576
  "outputs": [],
577
  "source": [
578
  "model = PySRRegressor(\n",
579
+ " elementwise_loss=\"myloss(x, y, w) = w * abs(x - y)\", # Custom loss function with weights.\n",
580
  " niterations=20,\n",
581
  " populations=20, # Use more populations\n",
582
  " binary_operators=[\"+\", \"*\"],\n",
pysr/__init__.py CHANGED
@@ -4,10 +4,9 @@
4
  from .julia_import import jl, SymbolicRegression # isort:skip
5
 
6
  from . import sklearn_monkeypatch
7
- from .deprecated import best, best_callable, best_row, best_tex, pysr
8
  from .export_jax import sympy2jax
9
  from .export_torch import sympy2torch
10
- from .julia_helpers import install
11
  from .sr import PySRRegressor
12
 
13
  # This file is created by setuptools_scm during the build process:
@@ -28,5 +27,4 @@ __all__ = [
28
  "best_tex",
29
  "pysr",
30
  "__version__",
31
- "install",
32
  ]
 
4
  from .julia_import import jl, SymbolicRegression # isort:skip
5
 
6
  from . import sklearn_monkeypatch
7
+ from .deprecated import best, best_callable, best_row, best_tex, install, pysr
8
  from .export_jax import sympy2jax
9
  from .export_torch import sympy2torch
 
10
  from .sr import PySRRegressor
11
 
12
  # This file is created by setuptools_scm during the build process:
 
27
  "best_tex",
28
  "pysr",
29
  "__version__",
 
30
  ]
pysr/deprecated.py CHANGED
@@ -2,6 +2,22 @@
2
  import warnings
3
 
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  def pysr(X, y, weights=None, **kwargs): # pragma: no cover
6
  from .sr import PySRRegressor
7
 
@@ -55,39 +71,28 @@ def best_callable(*args, **kwargs): # pragma: no cover
55
  )
56
 
57
 
58
- def make_deprecated_kwargs_for_pysr_regressor():
59
- """Create dict of deprecated kwargs."""
60
-
61
- deprecation_string = """
62
- fractionReplaced => fraction_replaced
63
- fractionReplacedHof => fraction_replaced_hof
64
- npop => population_size
65
- hofMigration => hof_migration
66
- shouldOptimizeConstants => should_optimize_constants
67
- weightAddNode => weight_add_node
68
- weightDeleteNode => weight_delete_node
69
- weightDoNothing => weight_do_nothing
70
- weightInsertNode => weight_insert_node
71
- weightMutateConstant => weight_mutate_constant
72
- weightMutateOperator => weight_mutate_operator
73
- weightSwapOperands => weight_swap_operands
74
- weightRandomize => weight_randomize
75
- weightSimplify => weight_simplify
76
- crossoverProbability => crossover_probability
77
- perturbationFactor => perturbation_factor
78
- batchSize => batch_size
79
- warmupMaxsizeBy => warmup_maxsize_by
80
- useFrequency => use_frequency
81
- useFrequencyInTournament => use_frequency_in_tournament
82
- ncyclesperiteration => ncycles_per_iteration
83
- """
84
- # Turn this into a dict:
85
- deprecated_kwargs = {}
86
- for line in deprecation_string.splitlines():
87
- line = line.replace(" ", "")
88
- if line == "":
89
- continue
90
- old, new = line.split("=>")
91
- deprecated_kwargs[old] = new
92
-
93
- return deprecated_kwargs
 
2
  import warnings
3
 
4
 
5
+ def install(*args, **kwargs):
6
+ del args, kwargs
7
+ warnings.warn(
8
+ "The `install` function has been removed. "
9
+ "PySR now uses the `juliacall` package to install its dependencies automatically at import time. "
10
+ )
11
+
12
+
13
+ def init_julia(*args, **kwargs):
14
+ del args, kwargs
15
+ warnings.warn(
16
+ "The `init_julia` function has been removed. "
17
+ "Julia is now initialized automatically at import time."
18
+ )
19
+
20
+
21
  def pysr(X, y, weights=None, **kwargs): # pragma: no cover
22
  from .sr import PySRRegressor
23
 
 
71
  )
72
 
73
 
74
+ DEPRECATED_KWARGS = {
75
+ "fractionReplaced": "fraction_replaced",
76
+ "fractionReplacedHof": "fraction_replaced_hof",
77
+ "npop": "population_size",
78
+ "hofMigration": "hof_migration",
79
+ "shouldOptimizeConstants": "should_optimize_constants",
80
+ "weightAddNode": "weight_add_node",
81
+ "weightDeleteNode": "weight_delete_node",
82
+ "weightDoNothing": "weight_do_nothing",
83
+ "weightInsertNode": "weight_insert_node",
84
+ "weightMutateConstant": "weight_mutate_constant",
85
+ "weightMutateOperator": "weight_mutate_operator",
86
+ "weightSwapOperands": "weight_swap_operands",
87
+ "weightRandomize": "weight_randomize",
88
+ "weightSimplify": "weight_simplify",
89
+ "crossoverProbability": "crossover_probability",
90
+ "perturbationFactor": "perturbation_factor",
91
+ "batchSize": "batch_size",
92
+ "warmupMaxsizeBy": "warmup_maxsize_by",
93
+ "useFrequency": "use_frequency",
94
+ "useFrequencyInTournament": "use_frequency_in_tournament",
95
+ "ncyclesperiteration": "ncycles_per_iteration",
96
+ "loss": "elementwise_loss",
97
+ "full_objective": "loss_function",
98
+ }
 
 
 
 
 
 
 
 
 
 
 
pysr/julia_helpers.py CHANGED
@@ -1,9 +1,9 @@
1
  """Functions for initializing the Julia environment and installing deps."""
2
- import warnings
3
 
4
  import numpy as np
5
  from juliacall import convert as jl_convert # type: ignore
6
 
 
7
  from .julia_import import jl
8
 
9
  jl.seval("using Serialization: Serialization")
@@ -15,14 +15,6 @@ PythonCall = jl.PythonCall
15
  jl.seval("using SymbolicRegression: plus, sub, mult, div, pow")
16
 
17
 
18
- def install(*args, **kwargs):
19
- del args, kwargs
20
- warnings.warn(
21
- "The `install` function has been removed. "
22
- "PySR now uses the `juliacall` package to install its dependencies automatically at import time. "
23
- )
24
-
25
-
26
  def _escape_filename(filename):
27
  """Turn a path into a string with correctly escaped backslashes."""
28
  str_repr = str(filename)
 
1
  """Functions for initializing the Julia environment and installing deps."""
 
2
 
3
  import numpy as np
4
  from juliacall import convert as jl_convert # type: ignore
5
 
6
+ from .deprecated import init_julia, install
7
  from .julia_import import jl
8
 
9
  jl.seval("using Serialization: Serialization")
 
15
  jl.seval("using SymbolicRegression: plus, sub, mult, div, pow")
16
 
17
 
 
 
 
 
 
 
 
 
18
  def _escape_filename(filename):
19
  """Turn a path into a string with correctly escaped backslashes."""
20
  str_repr = str(filename)
pysr/param_groupings.yml CHANGED
@@ -10,8 +10,8 @@
10
  - population_size
11
  - ncycles_per_iteration
12
  - The Objective:
13
- - loss
14
- - full_objective
15
  - model_selection
16
  - dimensional_constraint_penalty
17
  - Working with Complexities:
 
10
  - population_size
11
  - ncycles_per_iteration
12
  - The Objective:
13
+ - elementwise_loss
14
+ - loss_function
15
  - model_selection
16
  - dimensional_constraint_penalty
17
  - Working with Complexities:
pysr/sr.py CHANGED
@@ -25,7 +25,7 @@ from sklearn.utils import check_array, check_consistent_length, check_random_sta
25
  from sklearn.utils.validation import _check_feature_names_in, check_is_fitted
26
 
27
  from .denoising import denoise, multi_denoise
28
- from .deprecated import make_deprecated_kwargs_for_pysr_regressor
29
  from .export_jax import sympy2jax
30
  from .export_latex import sympy2latex, sympy2latextable, sympy2multilatextable
31
  from .export_numpy import sympy2numpy
@@ -268,7 +268,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
268
  arguments are treated the same way, and the max of each
269
  argument is constrained.
270
  Default is `None`.
271
- loss : str
272
  String of Julia code specifying an elementwise loss function.
273
  Can either be a loss from LossFunctions.jl, or your own loss
274
  written as a function. Examples of custom written losses include:
@@ -284,11 +284,11 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
284
  `ModifiedHuberLoss()`, `L2MarginLoss()`, `ExpLoss()`,
285
  `SigmoidLoss()`, `DWDMarginLoss(q)`.
286
  Default is `"L2DistLoss()"`.
287
- full_objective : str
288
  Alternatively, you can specify the full objective function as
289
  a snippet of Julia code, including any sort of custom evaluation
290
  (including symbolic manipulations beforehand), and any sort
291
- of loss function or regularizations. The default `full_objective`
292
  used in SymbolicRegression.jl is roughly equal to:
293
  ```julia
294
  function eval_loss(tree, dataset::Dataset{T,L}, options)::L where {T,L}
@@ -637,7 +637,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
637
  ... "inv(x) = 1/x", # Custom operator (julia syntax)
638
  ... ],
639
  ... model_selection="best",
640
- ... loss="loss(x, y) = (x - y)^2", # Custom loss function (julia syntax)
641
  ... )
642
  >>> model.fit(X, y)
643
  >>> model
@@ -675,8 +675,8 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
675
  timeout_in_seconds: Optional[float] = None,
676
  constraints: Optional[Dict[str, Union[int, Tuple[int, int]]]] = None,
677
  nested_constraints: Optional[Dict[str, Dict[str, int]]] = None,
678
- loss: Optional[str] = None,
679
- full_objective: Optional[str] = None,
680
  complexity_of_operators: Optional[Dict[str, Union[int, float]]] = None,
681
  complexity_of_constants: Union[int, float] = 1,
682
  complexity_of_variables: Union[int, float] = 1,
@@ -769,8 +769,8 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
769
  self.timeout_in_seconds = timeout_in_seconds
770
  self.early_stop_condition = early_stop_condition
771
  # - Loss parameters
772
- self.loss = loss
773
- self.full_objective = full_objective
774
  self.complexity_of_operators = complexity_of_operators
775
  self.complexity_of_constants = complexity_of_constants
776
  self.complexity_of_variables = complexity_of_variables
@@ -849,11 +849,10 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
849
  # Once all valid parameters have been assigned handle the
850
  # deprecated kwargs
851
  if len(kwargs) > 0: # pragma: no cover
852
- deprecated_kwargs = make_deprecated_kwargs_for_pysr_regressor()
853
  for k, v in kwargs.items():
854
  # Handle renamed kwargs
855
- if k in deprecated_kwargs:
856
- updated_kwarg_name = deprecated_kwargs[k]
857
  setattr(self, updated_kwarg_name, v)
858
  warnings.warn(
859
  f"{k} has been renamed to {updated_kwarg_name} in PySRRegressor. "
@@ -1251,8 +1250,10 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1251
  "to True and `procs` to 0 will result in non-deterministic searches. "
1252
  )
1253
 
1254
- if self.loss is not None and self.full_objective is not None:
1255
- raise ValueError("You cannot set both `loss` and `full_objective`.")
 
 
1256
 
1257
  # NotImplementedError - Values that could be supported at a later time
1258
  if self.optimizer_algorithm not in VALID_OPTIMIZER_ALGORITHMS:
@@ -1587,9 +1588,13 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1587
  complexity_of_operators_str += ")"
1588
  complexity_of_operators = jl.seval(complexity_of_operators_str)
1589
 
1590
- custom_loss = jl.seval(str(self.loss) if self.loss is not None else "nothing")
 
 
 
 
1591
  custom_full_objective = jl.seval(
1592
- str(self.full_objective) if self.full_objective is not None else "nothing"
1593
  )
1594
 
1595
  early_stop_condition = jl.seval(
 
25
  from sklearn.utils.validation import _check_feature_names_in, check_is_fitted
26
 
27
  from .denoising import denoise, multi_denoise
28
+ from .deprecated import DEPRECATED_KWARGS
29
  from .export_jax import sympy2jax
30
  from .export_latex import sympy2latex, sympy2latextable, sympy2multilatextable
31
  from .export_numpy import sympy2numpy
 
268
  arguments are treated the same way, and the max of each
269
  argument is constrained.
270
  Default is `None`.
271
+ elementwise_loss : str
272
  String of Julia code specifying an elementwise loss function.
273
  Can either be a loss from LossFunctions.jl, or your own loss
274
  written as a function. Examples of custom written losses include:
 
284
  `ModifiedHuberLoss()`, `L2MarginLoss()`, `ExpLoss()`,
285
  `SigmoidLoss()`, `DWDMarginLoss(q)`.
286
  Default is `"L2DistLoss()"`.
287
+ loss_function : str
288
  Alternatively, you can specify the full objective function as
289
  a snippet of Julia code, including any sort of custom evaluation
290
  (including symbolic manipulations beforehand), and any sort
291
+ of loss function or regularizations. The default `loss_function`
292
  used in SymbolicRegression.jl is roughly equal to:
293
  ```julia
294
  function eval_loss(tree, dataset::Dataset{T,L}, options)::L where {T,L}
 
637
  ... "inv(x) = 1/x", # Custom operator (julia syntax)
638
  ... ],
639
  ... model_selection="best",
640
+ ... elementwise_loss="loss(x, y) = (x - y)^2", # Custom loss function (julia syntax)
641
  ... )
642
  >>> model.fit(X, y)
643
  >>> model
 
675
  timeout_in_seconds: Optional[float] = None,
676
  constraints: Optional[Dict[str, Union[int, Tuple[int, int]]]] = None,
677
  nested_constraints: Optional[Dict[str, Dict[str, int]]] = None,
678
+ elementwise_loss: Optional[str] = None,
679
+ loss_function: Optional[str] = None,
680
  complexity_of_operators: Optional[Dict[str, Union[int, float]]] = None,
681
  complexity_of_constants: Union[int, float] = 1,
682
  complexity_of_variables: Union[int, float] = 1,
 
769
  self.timeout_in_seconds = timeout_in_seconds
770
  self.early_stop_condition = early_stop_condition
771
  # - Loss parameters
772
+ self.elementwise_loss = elementwise_loss
773
+ self.loss_function = loss_function
774
  self.complexity_of_operators = complexity_of_operators
775
  self.complexity_of_constants = complexity_of_constants
776
  self.complexity_of_variables = complexity_of_variables
 
849
  # Once all valid parameters have been assigned handle the
850
  # deprecated kwargs
851
  if len(kwargs) > 0: # pragma: no cover
 
852
  for k, v in kwargs.items():
853
  # Handle renamed kwargs
854
+ if k in DEPRECATED_KWARGS:
855
+ updated_kwarg_name = DEPRECATED_KWARGS[k]
856
  setattr(self, updated_kwarg_name, v)
857
  warnings.warn(
858
  f"{k} has been renamed to {updated_kwarg_name} in PySRRegressor. "
 
1250
  "to True and `procs` to 0 will result in non-deterministic searches. "
1251
  )
1252
 
1253
+ if self.elementwise_loss is not None and self.loss_function is not None:
1254
+ raise ValueError(
1255
+ "You cannot set both `elementwise_loss` and `loss_function`."
1256
+ )
1257
 
1258
  # NotImplementedError - Values that could be supported at a later time
1259
  if self.optimizer_algorithm not in VALID_OPTIMIZER_ALGORITHMS:
 
1588
  complexity_of_operators_str += ")"
1589
  complexity_of_operators = jl.seval(complexity_of_operators_str)
1590
 
1591
+ custom_loss = jl.seval(
1592
+ str(self.elementwise_loss)
1593
+ if self.elementwise_loss is not None
1594
+ else "nothing"
1595
+ )
1596
  custom_full_objective = jl.seval(
1597
+ str(self.loss_function) if self.loss_function is not None else "nothing"
1598
  )
1599
 
1600
  early_stop_condition = jl.seval(
pysr/test/test.py CHANGED
@@ -80,7 +80,7 @@ class TestPipeline(unittest.TestCase):
80
  multithreading=False,
81
  turbo=True,
82
  early_stop_condition="stop_if(loss, complexity) = loss < 1e-10 && complexity == 1",
83
- full_objective="""
84
  function my_objective(tree::Node{T}, dataset::Dataset{T}, options::Options) where T
85
  prediction, flag = eval_tree_array(tree, dataset.X, options)
86
  !flag && return T(Inf)
@@ -100,7 +100,7 @@ class TestPipeline(unittest.TestCase):
100
  model = PySRRegressor(
101
  **self.default_test_kwargs,
102
  early_stop_condition="stop_if(loss, complexity) = loss < 1e-4 && complexity == 3",
103
- loss="my_loss(prediction, target) = (prediction - target)^2",
104
  precision=64,
105
  parsimony=0.01,
106
  warm_start=True,
 
80
  multithreading=False,
81
  turbo=True,
82
  early_stop_condition="stop_if(loss, complexity) = loss < 1e-10 && complexity == 1",
83
+ loss_function="""
84
  function my_objective(tree::Node{T}, dataset::Dataset{T}, options::Options) where T
85
  prediction, flag = eval_tree_array(tree, dataset.X, options)
86
  !flag && return T(Inf)
 
100
  model = PySRRegressor(
101
  **self.default_test_kwargs,
102
  early_stop_condition="stop_if(loss, complexity) = loss < 1e-4 && complexity == 3",
103
+ elementwise_loss="my_loss(prediction, target) = (prediction - target)^2",
104
  precision=64,
105
  parsimony=0.01,
106
  warm_start=True,