def test_small(): two = np.arange(2) three = np.arange(3) # spectral - No errors for data in [two, three]: assert dxdt(data, data, kind='spectral').shape == data.shape # spline - TypeError: length of input > order for spline interpolation kwargs = {'s': .01, 'order': 2} with pytest.raises(TypeError): dxdt(two, two, kind='spline', **kwargs) assert three.shape == dxdt(three, three, kind='spline', **kwargs).shape # trend_filtered - ValueError: Requires that the number of points n > order + 1 to compute the objective kwargs = {'order': 1, 'alpha': .01, 'max_iter': 1e3} with pytest.raises(ValueError): dxdt(two, two, kind='trend_filtered', **kwargs) assert three.shape == dxdt(three, three, kind='trend_filtered', **kwargs).shape # finite_difference - No errors for data in [two, three]: assert data.shape == dxdt(data, data, kind='finite_difference', k=1).shape # savitzky_golay - RankWarning: The fit may be poorly conditioned if order >= points in window kwargs = {'left': 2, 'right': 2, 'iwindow': True, 'order': 2} with pytest.warns(UserWarning): # numpy.RankWarning is of type UserWarning assert two.shape == dxdt(two, two, kind='savitzky_golay', **kwargs).shape assert three.shape == dxdt(three, three, kind='savitzky_golay', **kwargs).shape
def test_empty(): empty = np.array([]) # spectral assert 0 == dxdt(empty, empty, kind='spectral').size # spline assert 0 == dxdt(empty, empty, kind='spline', order=1, s=.01).size # trend_filtered assert 0 == dxdt(empty, empty, kind='trend_filtered', order=1, alpha=.01, max_iter=1e3).size # finite_difference assert 0 == dxdt(empty, empty, kind='finite_difference', k=1).size # savitzky_golay assert 0 == dxdt(empty, empty, kind='savitzky_golay', order=1, left=2, right=2, iwindow=True).size
def test_one(): one = np.arange(1) twobyone = np.arange(2).reshape(2,1) for data in [one, twobyone]: # spectral assert np.all(data == dxdt(data, one, kind='spectral')) # spline assert np.all(data == dxdt(data, one, kind='spline', order=1, s=.01)) # trend_filtered assert np.all(data == dxdt(data, one, kind='trend_filtered', order=1, alpha=.01, max_iter=1e3)) # finite_difference assert np.all(data == dxdt(data, one, kind='finite_difference', k=1)) # savitzky_golay assert np.all(data == dxdt(data, one, kind='savitzky_golay', order=1, left=2, right=2, iwindow=True))
def test_wrapper_equivalence_with_dxdt(data, derivative_kws): x, _ = data t = np.arange(x.shape[0]) if np.ndim(x) == 1: np.testing.assert_allclose( dxdt(x.reshape(-1, 1), t, axis=0, **derivative_kws), SINDyDerivative(**derivative_kws)(x, t), ) else: np.testing.assert_allclose( dxdt(x, t, axis=0, **derivative_kws), SINDyDerivative(**derivative_kws)(x, t), )
def _differentiate(self, x, t=1): if isinstance(t, (int, float)): if t < 0: raise ValueError("t must be a positive constant or an array") t = arange(x.shape[0]) * t return dxdt(x, t, axis=0, **self.kwargs)
def __call__(self, x, t): """ Perform numerical differentiation by calling the ``dxdt`` method. Paramters --------- x: np.ndarray, shape (n_samples, n_features) Data to be differentiated. Rows should correspond to different points in time and columns to different features. t: np.ndarray, shape (n_samples, ) Time points for each sample (row) in ``x``. Returns ------- x_dot: np.ndarray, shape (n_samples, n_features) """ x = validate_input(x, t=t) if isinstance(t, (int, float)): if t < 0: raise ValueError("t must be a positive constant or an array") t = arange(x.shape[0]) * t return dxdt(x, t, axis=0, **self.kwargs)
def test_derivative_package_equivalence(data, kws): x, t, _ = data x_dot_pykoopman = Derivative(**kws)(x, t) x_dot_derivative = dxdt(x, t, axis=0, **kws).reshape(x_dot_pykoopman.shape) np.testing.assert_array_equal(x_dot_pykoopman, x_dot_derivative)
def test_axis(): """ Checking the default method only. The other implementations follow if they satisfy the interface contract. """ ts = np.arange(10) xs = np.array([ts, ts**2]) shape1 = xs.shape # Regular: 2,10 test1 = dxdt(xs, ts, axis=1).shape assert shape1 == test1 # Transpose: 10,2 test2 = dxdt(xs.T, ts, axis=0).shape[::-1] assert shape1 == test2 # Flat shape2 = ts.shape test3 = dxdt(ts, ts, axis=1).shape assert shape2 == test3
def trend_filter_der(y, x, lambd=0, order=3, verbose=False): """ trend_filter(y, lambda = 0, order = 3) finds the solution of the l1 trend estimation problem minimize (1/2)||y-x||^2+lambda*||Dx||_1, with variable x, and problem data y and lambda, with lambda >0. D is the k-th order difference matrix. This function calls cvxpy to solve the optimization problem above Input arguments: - y: n-vector; original signal - x: n-vector; independent variable - lambda: scalar; positive regularization parameter - order: scalar: order of the difference matrices Output arguments: - u: n-1-vector with derivatives at the midpoints of x Adapted from "l1 Trend Filtering", S. Kim, K. Koh, ,S. Boyd and D. Gorinevsky Based on code available at: https://www.cvxpy.org/examples/applications/l1_trend_filter.html Author: Alexandre Cortiella Affiliation: University of Colorado Boulder Department: Aerospace Engineering Sciences Date: 11/09/2020 Version: v1.0 Updated: 11/09/2020 """ n = len(y) m = n - 1 #Generate difference matrix D = diff_mat(n - 1, order + 1) #Generate integral matrix (constant grid size dx) dx = x[1] - x[0] A = int_mat(n - 1, dx) #Generate input vector yhat = y[1:] - y[0] # Solve l1 trend filtering problem. dy = dxdt(y, x, kind="trend_filtered", order=order, alpha=lambd, max_iter=10000) u = 0.5 * (dy[0:-1] + dy[1:]) #Compute residuals with current solution residual = norm(A * u - yhat) reg_residual = norm(D * u, ord=1) #Compute degrees of freedom and GCV df = norm(D * u, ord=1) + order + 1 GCV = (m * norm(A * u - yhat)**2) / (m - df)**2 return [dy, (residual, reg_residual), (GCV, df)]
def run(self): return dxdt(self.fn(self.t), self.t, self.kind, self.axis, **self.kwargs)