[BUG]SINDy defaults are instances of classes
billtubbs opened this issue · 5 comments
I don't think it's a good idea to use instances of optimizer
, feature_library
, and differentiation_method
as default values in the init method of the SINDy class because they will only be instantiated once and then all future instances of SINDy will be using the same instances of these classes.
To illustrate the problem:
from pysindy import SINDy
model_1 = SINDy()
model_2 = SINDy()
print(model_1.optimizer.threshold, model_2.optimizer.threshold)
model_1.optimizer.threshold = 0.2 # This modifies the default instance
print(model_1.optimizer.threshold, model_2.optimizer.threshold)
Output:
0.1 0.1
0.2 0.2
(model_1
and model_2
are sharing the same default optimizer object, furthermore, all future instances of SINDy will also be).
The problem is in the init method for SINDy:
def __init__(
self,
optimizer=STLSQ(),
feature_library=PolynomialFeatures(),
differentiation_method=FiniteDifference(),
feature_names=None,
discrete_time=False,
n_jobs=1,
):
The standard solution is to set the default values to None
and then instantiate new STLSQ()
, PolynomialFeatures()
or FiniteDifference()
objects if required in the body of the __init__
method.
E.g.
if optimizer is None:
self.optimizer = STLSQ()
else:
self.optimizer = optimizer
I can submit a pull-request to fix this if you like.
This is a great suggestion, thanks! If you'd like to submit a pull-request, please do. Otherwise I can make the fix sometime in the next 24 hours.
Now I'm getting 1 test fail. Any idea how this change to SINDy()
could have caused this:
optimizers = [SINDyOptimizer(o, unbias=True) for o in optimizers]
for opt in optimizers:
opt.fit(x, y)
for less_complex, more_complex in zip(optimizers, optimizers[1:]):
# relax the condition to account for
# noise and non-normalized threshold parameters
> assert less_complex.complexity <= more_complex.complexity + 1
E AssertionError: assert 4 <= (2 + 1)
E + where 4 = SINDyOptimizer(optimizer=SR3(copy_X=True, fit_intercept=True, max_iter=30,\n normalize=False, nu=1.0, threshold=0.1,\n thresholder='l1', tol=1e-05),\n unbias=True).complexity
E + and 2 = SINDyOptimizer(optimizer=Lasso(alpha=1.0, copy_X=True, fit_intercept=True,\n max_iter=100... selection='cyclic', tol=0.0001,\n warm_start=False),\n unbias=True).complexity
test/property_tests/test_optimizers_complexity.py:55: AssertionError
How does this test work?
Actually, this is not related. I just rolled back my changes and this test was failing before. My changes pass pytest test/test_pysindy.py
. So I will submit a pull-request. Not sure what the other problem is.
The test failure you saw is troubling. I will have to look into it separately.