diff --git a/darts/dataprocessing/pipeline.py b/darts/dataprocessing/pipeline.py index dac4003603..053e7ff93f 100644 --- a/darts/dataprocessing/pipeline.py +++ b/darts/dataprocessing/pipeline.py @@ -230,7 +230,7 @@ def inverse_transform( idx_params=idx_params if ( isinstance(transformer, FittableDataTransformer) - and transformer._global_fit + and not transformer._global_fit ) else None, ) @@ -243,7 +243,7 @@ def inverse_transform( idx_params=idx_params if ( isinstance(transformer, FittableDataTransformer) - and transformer._global_fit + and not transformer._global_fit ) else None, ) diff --git a/darts/tests/dataprocessing/test_pipeline.py b/darts/tests/dataprocessing/test_pipeline.py index c9b4ded041..65a6b573f7 100644 --- a/darts/tests/dataprocessing/test_pipeline.py +++ b/darts/tests/dataprocessing/test_pipeline.py @@ -121,13 +121,13 @@ def ts_fit( @staticmethod def ts_transform(data: TimeSeries, params: Mapping[str, Any]) -> TimeSeries: - return data.append_values(params["fitted"]) + return data + params["fitted"] @staticmethod def ts_inverse_transform( data: TimeSeries, params: Mapping[str, Any] ) -> TimeSeries: - return data[:-1] + return data - params["fitted"] def test_transform(self): # given @@ -148,6 +148,11 @@ def test_transform(self): assert not t.inverse_transform_called def test_transform_prefitted(self): + """Check that when multiple series are passed to fit transformers with global_fit=False, + transform behave as expected when idx_params is specified. + + Note: the transformers are fitted independently to make the expected results more intuitive + """ data = [ constant_timeseries(value=0, length=2), constant_timeseries(value=10, length=2), @@ -166,11 +171,13 @@ def get_transf(global_fit: bool, fit: bool, coef: int): ]) transformed = p.transform(data) + # ts + (data[0][0] + 1) + (data[0][0] + 5) = 6 np.testing.assert_array_almost_equal( - transformed[0].values(), np.array([[0, 0, 1, 5]]).T + transformed[0].values(), np.array([[6, 6]]).T ) + # ts + (data[1][0] + 1) + (data[1][0] + 5) = 10 + 11 + 15 = 36 np.testing.assert_array_almost_equal( - transformed[1].values(), np.array([[10, 10, 11, 15]]).T + transformed[1].values(), np.array([[36, 36]]).T ) # implicitely use the first params of each transformer np.testing.assert_array_almost_equal( @@ -181,8 +188,9 @@ def get_transf(global_fit: bool, fit: bool, coef: int): transformed[0].values(), p.transform(data[0], idx_params=[0]).values() ) # implicitely use the first params of each transformer + # ts + (data[0][0] + 1) + (data[0][0] + 5) = 10 + 1 + 5 = 16 np.testing.assert_array_almost_equal( - np.array([[10, 10, 1, 5]]).T, p.transform(data[1]).values() + np.array([[16, 16]]).T, p.transform(data[1]).values() ) # explicitely use the second params of each transformer np.testing.assert_array_almost_equal( @@ -195,11 +203,13 @@ def get_transf(global_fit: bool, fit: bool, coef: int): get_transf(global_fit=True, fit=True, coef=90), ]) transformed = p.transform(data) + # ts + (data[0][0] + 1) + (sum(data[;, 0]) + 90) = 0 + 1 + 100 np.testing.assert_array_almost_equal( - transformed[0].values(), np.array([[0, 0, 1, 100]]).T + transformed[0].values(), np.array([[101, 101]]).T ) + # ts + (data[1][0] + 1) + (sum(data[;, 0]) + 90) = 10 + 11 + 100 np.testing.assert_array_almost_equal( - transformed[1].values(), np.array([[10, 10, 11, 100]]).T + transformed[1].values(), np.array([[121, 121]]).T ) # implicitely use the first params of first transformer, the second is global np.testing.assert_array_almost_equal( @@ -210,8 +220,9 @@ def get_transf(global_fit: bool, fit: bool, coef: int): transformed[0].values(), p.transform(data[0], idx_params=[0]).values() ) # implicitely use the first params of first transformer, the second is global + # ts + (data[0][0] + 1) + (sum(data[;, 0]) + 90) = 10 + 1 + 100 np.testing.assert_array_almost_equal( - np.array([[10, 10, 1, 100]]).T, p.transform(data[1]).values() + np.array([[111, 111]]).T, p.transform(data[1]).values() ) # explicitely use the second params of first transformer, the second is global np.testing.assert_array_almost_equal( @@ -309,6 +320,92 @@ def test_inverse_transform(self): # then assert data == back + def test_inverse_transform_prefitted(self): + """Check that when multiple series are passed to fit transformers with global_fit=False, + inverse_transform behave as expected when idx_params is specified. + + Note: the transformers are fitted independently to make the expected results more intuitive + """ + data = [ + constant_timeseries(value=0, length=2), + constant_timeseries(value=10, length=2), + ] + + def get_transf(global_fit: bool, fit: bool, coef: int): + transf = self.ExtendTransformer(global_fit=global_fit, coef=coef) + if fit: + transf.fit(data) + return transf + + # multiple series, global_fit=False + p = Pipeline([ + get_transf(global_fit=False, fit=True, coef=1), + get_transf(global_fit=False, fit=True, coef=5), + ]) + transformed = p.transform(data) + + # implicitely use the first params of each transformer + np.testing.assert_array_almost_equal( + data[0].values(), p.inverse_transform(transformed[0]).values() + ) + # explicitely use the first params of each transformer + np.testing.assert_array_almost_equal( + data[0].values(), + p.inverse_transform(transformed[0], idx_params=[0]).values(), + ) + + # 10 + 11 + 15 + np.testing.assert_array_almost_equal( + np.array([[36, 36]]).T, transformed[1].values() + ) + # implicitely use the first params of each transformer + # inverse_transform[0][0] = lambda x: x - 1, inverse_transform[1][0] = lamdda x: x - 5 + np.testing.assert_array_almost_equal( + np.array([[30, 30]]).T, p.inverse_transform(transformed[1]).values() + ) + np.testing.assert_array_almost_equal( + np.array([[30, 30]]).T, + p.inverse_transform(transformed[1], idx_params=0).values(), + ) + # explicitely use the second params of each transformer + # inverse_transform[0][0] = lambda x: x - 11, inverse_transform[1][0] = lamdda x: x - 15 + np.testing.assert_array_almost_equal( + data[1].values(), p.inverse_transform(transformed[1], idx_params=1).values() + ) + + # multiple series, mixture of local and global transformers + p = Pipeline([ + get_transf(global_fit=False, fit=True, coef=1), + get_transf(global_fit=True, fit=True, coef=90), + ]) + transformed = p.transform(data) + + # implicitely use the first params of each transformer + np.testing.assert_array_almost_equal( + data[0].values(), p.inverse_transform(transformed[0]).values() + ) + # explicitely use the first params of each transformer + np.testing.assert_array_almost_equal( + data[0].values(), + p.inverse_transform(transformed[0], idx_params=[0]).values(), + ) + # 10 + 11 + 100 + np.testing.assert_array_almost_equal( + np.array([[121, 121]]).T, transformed[1].values() + ) + + # implicitely use the first params of each transformer + # inverse_transform[0][0] = lambda x: x - 1, inverse_transform = lamdda x: x - 100 + np.testing.assert_array_almost_equal( + np.array([[20, 20]]).T, p.inverse_transform(transformed[1]).values() + ) + # explicitely use the second params of each transformer + # inverse_transform[0][1] = lambda x: x - 11, inverse_transform = lamdda x: x - 100 + np.testing.assert_array_almost_equal( + data[1].values(), + p.inverse_transform(transformed[1], idx_params=[1]).values(), + ) + def test_getitem(self): # given