Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Parameter Carryover in SINDyDerivative from set_params. (And a minor dependency conflict with the default Google colab runtime) #546

Open
djpasseyjr opened this issue Aug 16, 2024 · 1 comment

Comments

@djpasseyjr
Copy link

Hi all, first of all thanks for your hard work on the package. It's a very cool algorithm and I've been making good use of it.

I ran into two small bugs, but I think they would be a low priority for you. Still I found a fix for one of them and wanted to publish it here since it took some time to figure it out.

The main issue is that set_params allows differentiation_method__kwargs arguments to carry over from previous initializations and this can cause grid search to fail.

If you express your parameter grid slightly differently, then you won't run into any issues.

I made a PUBLIC GOOGLE COLAB REPRODUCING THE BUG where you can easily play with the error.

(You will also see that the version of importlib-metadata used by the default Google colab runtime conflicts with PySINDy so you need to restart the runtime after installing PySINDY. Something to think about updating but definitely not a huge deal.)

Reproducing code example:

import pysindy as ps
import numpy as np

sindy = ps.SINDy(differentiation_method=ps.SINDyDerivative())


sindy.set_params(differentiation_method__kwargs = {'kind': 'savitzky_golay', 'order': 2, 'left': 0.1, 'right': 0.1},)

# The differentiation_method__kwargs from savitzky_golay carry over 
# when the parameters of differention method are set.
sindy.set_params(differentiation_method__kwargs = {'kind': 'trend_filtered', "order": 0, "alpha": 0.01})

sindy.get_params()

The parameters above will should not contain both differentiation_method__alpha and differentiation_method__left, but they will. This leads to an error when calling fit:

# This will throw an error because of extra parameters.
sindy.fit(np.random.rand(100, 10), np.arange(100))

Error message:

TypeError Traceback (most recent call last)
in <cell line: 1>()
----> 1 sindy.fit(np.random.rand(100, 10), np.arange(100))

11 frames
/usr/local/lib/python3.10/dist-packages/pysindy/pysindy.py in fit(self, x, t, x_dot, u, multiple_trajectories, unbias, quiet, ensemble, library_ensemble, replace, n_candidates_to_drop, n_subset, n_models, ensemble_aggregator)
341 )
342 self.n_control_features_ = u[0].shape[u[0].ax_coord]
--> 343 x, x_dot = self._process_multiple_trajectories(x, t, x_dot)
344
345 # Set ensemble variables

/usr/local/lib/python3.10/dist-packages/pysindy/pysindy.py in _process_multiple_trajectories(self, x, t, x_dot)
663 x = [xi[:-1] for xi in x]
664 else:
--> 665 x_dot = [
666 self.feature_library.calc_trajectory(
667 self.differentiation_method, xi, ti

/usr/local/lib/python3.10/dist-packages/pysindy/pysindy.py in (.0)
664 else:
665 x_dot = [
--> 666 self.feature_library.calc_trajectory(
667 self.differentiation_method, xi, ti
668 )

/usr/local/lib/python3.10/dist-packages/pysindy/feature_library/base.py in calc_trajectory(self, diff_method, x, t)
85 def calc_trajectory(self, diff_method, x, t):
86 axes = x.dict
---> 87 x_dot = diff_method(x, t=t)
88 return AxesArray(x_dot, axes)
89

/usr/local/lib/python3.10/dist-packages/pysindy/differentiation/base.py in call(self, x, t)
47
48 def call(self, x, t=1):
---> 49 return self._differentiate(x, t)

/usr/local/lib/python3.10/dist-packages/pysindy/differentiation/sindy_derivative.py in _differentiate(self, x, t)
71 t = arange(x.shape[0]) * t
72
---> 73 return dxdt(x, t, axis=0, **self.kwargs)

/usr/local/lib/python3.10/dist-packages/derivative/differentiation.py in dxdt(x, t, kind, axis, **kwargs)
54 else:
55 method = _gen_method(x, t, kind, axis, **kwargs)
---> 56 return method.d(x, t, axis=axis)
57
58

/usr/local/lib/python3.10/dist-packages/derivative/differentiation.py in d(self, X, t, axis)
198 dX = X
199 else:
--> 200 dX = np.array([list(self.compute_for(t, x, np.arange(len(t)))) for x in X])
201
202 return _restore_axes(dX, axis, flat)

/usr/local/lib/python3.10/dist-packages/derivative/differentiation.py in (.0)
198 dX = X
199 else:
--> 200 dX = np.array([list(self.compute_for(t, x, np.arange(len(t)))) for x in X])
201
202 return _restore_axes(dX, axis, flat)

/usr/local/lib/python3.10/dist-packages/derivative/dglobal.py in compute_for(self, t, x, indices)
177
178 def compute_for(self, t, x, indices):
--> 179 x_dot_hat = self._global(t, x)[1]
180 for i in indices:
181 yield x_dot_hat[i]

/usr/local/lib/python3.10/dist-packages/derivative/utils.py in wrapper_func(*args, **kwargs)
131 except KeyError: pass
132 misses += 1
--> 133 result = wrapped_func(*args, **kwargs)
134 if maxsize > 0:
135 arg_dict[cache_key] = result

/usr/local/lib/python3.10/dist-packages/derivative/dglobal.py in _global(self, t, x)
162 A = proj.dot(X1)
163 b = proj.dot(self._x - self._x[0])
--> 164 self._model = Lasso(alpha=self.alpha / n, fit_intercept=False, **self.kwargs)
165 self._model.fit(A, b)
166

TypeError: Lasso.init() got an unexpected keyword argument 'left'

PySINDy/Python version information:

1.7.5 3.10.12 (main, Jul 29 2024, 16:56:48) [GCC 11.4.0]

How to Fix:

sindy = ps.SINDy(differentiation_method=ps.SINDyDerivative())

sindy.set_params(differentiation_method=ps.SINDyDerivative(kind="savitzky_golay"), differentiation_method__kwargs={'order': 2, 'left': 0.1, 'right': 0.1})
sindy.set_params(differentiation_method=ps.SINDyDerivative(kind="finite_difference"), differentiation_method__kwargs={"k": 1})

# No error this time.
sindy.fit(np.random.rand(100, 10), np.arange(100))

Thanks again, DJ

@djpasseyjr
Copy link
Author

I should clarify the point of this is for grid search:

You need to organize params like this:

{'optimizer__threshold': [0.0001, 0.001],
 'optimizer__alpha': [0.0001, 0.01],
 'discrete_time': [True, False],
 'feature_library': [ps.PolynomialLibrary(), ps.FourierLibrary()],
 'differentiation_method': [
     ps.SINDyDerivative(kind='finite_difference', k=1),
     ps.SINDyDerivative(kind='spline', s=0.1),
     ps.SINDyDerivative(kind='savitzky_golay', order=2, left=0.1, right=0.1),
     ps.SINDyDerivative(kind='trend_filtered', order=0, alpha=0.01)
 ]
}

and NOT like this:

method_param_grid={
          'optimizer__threshold': [0.0001, 0.001],
           'optimizer__alpha': [0.0001, 0.01],
           'discrete_time': [True, False],
           'feature_library': [ps.PolynomialLibrary(), ps.FourierLibrary()],
            'differentiation_method__kwargs': [
                {'kind': 'finite_difference', 'k': 1},
                {'kind': 'spline', 's': 0.1},
                {'kind': 'savitzky_golay', 'order': 2, 'left': .1, 'right': .1},
                {'kind': 'trend_filtered', 'order': 0, 'alpha': 1e-2}
            ]
        },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant