Skip to content

Commit

Permalink
introduce MockTransformer to be a placeholder during deprecation
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyBagnall committed May 18, 2024
1 parent b42f4e3 commit 82586c6
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 72 deletions.
18 changes: 8 additions & 10 deletions aeon/forecasting/compose/_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,9 @@ def get_test_params(cls, parameter_set="default"):

from aeon.forecasting.compose._reduce import DirectReductionForecaster
from aeon.forecasting.naive import NaiveForecaster
from aeon.testing.mock_estimators import MockTransformer
from aeon.transformations.adapt import TabularToSeriesAdaptor
from aeon.transformations.detrend import Detrender
from aeon.transformations.exponent import ExponentTransformer

# StandardScaler does not skip fit, NaiveForecaster is not probabilistic
STEPS1 = [
Expand All @@ -252,7 +252,7 @@ def get_test_params(cls, parameter_set="default"):

# ARIMA has probabilistic methods, ExponentTransformer skips fit
STEPS2 = [
("transformer", ExponentTransformer()),
("transformer", MockTransformer()),
("forecaster", DirectReductionForecaster.create_test_instance()),
]
params2 = {"steps": STEPS2}
Expand Down Expand Up @@ -1682,32 +1682,30 @@ def get_test_params(cls, parameter_set="default"):
`create_test_instance` uses the first (or only) dictionary in `params`
"""
from aeon.forecasting.naive import NaiveForecaster
from aeon.transformations.boxcox import BoxCoxTransformer
from aeon.transformations.exponent import ExponentTransformer
from aeon.testing.mock_estimators import MockTransformer

# transformers mixed with-without fit, ForecastingPipeline
# steps are (str, estimator)
params1 = {
"estimator": ForecastingPipeline(
[
("foo", BoxCoxTransformer()),
("bar", ExponentTransformer(3)),
("bar", MockTransformer(3)),
("foobar", NaiveForecaster()),
]
),
"permutation": ["bar", "foo", "foobar"],
"permutation": ["foo", "foobar"],
}

# transformers have no fit, TransformedTargetForecaster
# steps are only estimator
params2 = {
"estimator": TransformedTargetForecaster(
[ExponentTransformer(0.5), NaiveForecaster(), ExponentTransformer(3)]
[MockTransformer(0.5), NaiveForecaster(), MockTransformer(3)]
),
"permutation": [
"NaiveForecaster",
"ExponentTransformer_1",
"ExponentTransformer_2",
"MockTransformer_1",
"MockTransformer_2",
],
}

Expand Down
23 changes: 11 additions & 12 deletions aeon/forecasting/compose/tests/test_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@
from aeon.forecasting.naive import NaiveForecaster
from aeon.forecasting.sarimax import SARIMAX
from aeon.forecasting.trend import PolynomialTrendForecaster
from aeon.testing.mock_estimators import MockForecaster
from aeon.testing.mock_estimators import MockForecaster, MockTransformer
from aeon.testing.utils.data_gen import get_examples, make_series
from aeon.testing.utils.estimator_checks import _assert_array_almost_equal
from aeon.transformations.adapt import TabularToSeriesAdaptor
from aeon.transformations.boxcox import LogTransformer
from aeon.transformations.compose import OptionalPassthrough
from aeon.transformations.detrend import Detrender
from aeon.transformations.difference import Differencer
from aeon.transformations.exponent import ExponentTransformer
from aeon.transformations.hierarchical.aggregate import Aggregator
from aeon.transformations.impute import Imputer
from aeon.transformations.outlier_detection import HampelFilter
Expand All @@ -47,7 +46,7 @@ def test_pipeline():

forecaster = TransformedTargetForecaster(
[
("t1", ExponentTransformer()),
("t1", MockTransformer()),
("t2", TabularToSeriesAdaptor(MinMaxScaler())),
("forecaster", NaiveForecaster()),
]
Expand All @@ -59,7 +58,7 @@ def test_pipeline():
def compute_expected_y_pred(y_train, fh):
# fitting
yt = y_train.copy()
t1 = ExponentTransformer()
t1 = MockTransformer()
yt = t1.fit_transform(yt)
t2 = TabularToSeriesAdaptor(MinMaxScaler())
yt = t2.fit_transform(yt)
Expand Down Expand Up @@ -275,10 +274,10 @@ def test_forecasting_pipeline_dunder_endog():
y = load_airline()
y_train, y_test = temporal_train_test_split(y)

forecaster = ExponentTransformer() * MinMaxScaler() * NaiveForecaster()
forecaster = MockTransformer() * MinMaxScaler() * NaiveForecaster()

assert isinstance(forecaster, TransformedTargetForecaster)
assert isinstance(forecaster.steps[0], ExponentTransformer)
assert isinstance(forecaster.steps[0], MockTransformer)
assert isinstance(forecaster.steps[1], TabularToSeriesAdaptor)
assert isinstance(forecaster.steps[2], NaiveForecaster)

Expand All @@ -289,7 +288,7 @@ def test_forecasting_pipeline_dunder_endog():
def compute_expected_y_pred(y_train, fh):
# fitting
yt = y_train.copy()
t1 = ExponentTransformer()
t1 = MockTransformer()
yt = t1.fit_transform(yt)
t2 = TabularToSeriesAdaptor(MinMaxScaler())
yt = t2.fit_transform(yt)
Expand Down Expand Up @@ -318,20 +317,20 @@ def test_forecasting_pipeline_dunder_exog():
X_train, X_test = temporal_train_test_split(X)

forecaster = (
ExponentTransformer()
MockTransformer()
** MinMaxScaler()
** ExponentialSmoothing(sp=12, random_state=3)
)
forecaster_alt = (ExponentTransformer() * MinMaxScaler()) ** ExponentialSmoothing(
forecaster_alt = (MockTransformer() * MinMaxScaler()) ** ExponentialSmoothing(
sp=12, random_state=3
)

assert isinstance(forecaster, ForecastingPipeline)
assert isinstance(forecaster.steps[0], ExponentTransformer)
assert isinstance(forecaster.steps[0], MockTransformer)
assert isinstance(forecaster.steps[1], TabularToSeriesAdaptor)
assert isinstance(forecaster.steps[2], ExponentialSmoothing)
assert isinstance(forecaster_alt, ForecastingPipeline)
assert isinstance(forecaster_alt.steps[0], ExponentTransformer)
assert isinstance(forecaster_alt.steps[0], MockTransformer)
assert isinstance(forecaster_alt.steps[1], TabularToSeriesAdaptor)
assert isinstance(forecaster_alt.steps[2], ExponentialSmoothing)

Expand All @@ -350,7 +349,7 @@ def compute_expected_y_pred(y_train, X_train, X_test, fh):
# fitting
yt = y_train.copy()
Xt = X_train.copy()
t1 = ExponentTransformer()
t1 = MockTransformer()
Xt = t1.fit_transform(Xt)
t2 = TabularToSeriesAdaptor(MinMaxScaler())
Xt = t2.fit_transform(Xt)
Expand Down
6 changes: 3 additions & 3 deletions aeon/pipeline/tests/test_make_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
from aeon.forecasting.naive import NaiveForecaster
from aeon.pipeline import make_pipeline
from aeon.regression import DummyRegressor
from aeon.testing.mock_estimators import MockTransformer
from aeon.testing.utils.data_gen import make_example_2d_numpy, make_example_3d_numpy
from aeon.transformations.base import BaseTransformer
from aeon.transformations.collection import PaddingTransformer, Tabularizer
from aeon.transformations.collection.feature_based import SevenNumberSummaryTransformer
from aeon.transformations.exponent import ExponentTransformer


@pytest.mark.parametrize(
Expand Down Expand Up @@ -52,8 +52,8 @@ def test_make_pipeline(pipeline):
@pytest.mark.parametrize(
"pipeline",
[
[ExponentTransformer(), NaiveForecaster()],
[ExponentTransformer(), ExponentTransformer(power=3)],
[MockTransformer(), NaiveForecaster()],
[MockTransformer(), MockTransformer(power=3)],
],
)
def test_make_pipeline_legacy(pipeline):
Expand Down
37 changes: 11 additions & 26 deletions aeon/transformations/compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from sklearn import clone

from aeon.base import _HeterogenousMetaEstimator
from aeon.testing.mock_estimators import MockTransformer
from aeon.transformations._delegate import _DelegatedTransformer
from aeon.transformations.base import BaseTransformer
from aeon.utils.multiindex import flatten_multiindex
Expand Down Expand Up @@ -381,11 +382,11 @@ def get_test_params(cls, parameter_set="default"):
`create_test_instance` uses the first (or only) dictionary in `params`.
"""
# imports
from aeon.transformations.exponent import ExponentTransformer
from aeon.testing.mock_estimators import MockTransformer

t1 = ExponentTransformer(power=2)
t2 = ExponentTransformer(power=0.5)
t3 = ExponentTransformer(power=1)
t1 = MockTransformer(power=2)
t2 = MockTransformer(power=0.5)
t3 = MockTransformer(power=1)

# construct without names
params1 = {"steps": [t1, t2]}
Expand Down Expand Up @@ -609,26 +610,12 @@ def _transform(self, X, y=None):
@classmethod
def get_test_params(cls, parameter_set="default"):
"""Test parameters for FeatureUnion."""
from aeon.transformations.boxcox import BoxCoxTransformer
from aeon.transformations.exponent import ExponentTransformer

# with name and estimator tuple, all transformers don't have fit
TRANSFORMERS = [
("transformer1", ExponentTransformer(power=4)),
("transformer2", ExponentTransformer(power=0.25)),
("transformer1", MockTransformer(power=4)),
("transformer2", MockTransformer(power=0.25)),
]
params1 = {"transformer_list": TRANSFORMERS}

# only with estimators, some transformers have fit, some not
params2 = {
"transformer_list": [
ExponentTransformer(power=4),
ExponentTransformer(power=0.25),
BoxCoxTransformer(),
]
}

return [params1, params2]
return {"transformer_list": TRANSFORMERS}


class FitInTransform(BaseTransformer):
Expand Down Expand Up @@ -1045,9 +1032,9 @@ class InvertTransform(_DelegatedTransformer):
--------
>>> from aeon.datasets import load_airline
>>> from aeon.transformations.compose import InvertTransform
>>> from aeon.transformations.exponent import ExponentTransformer
>>> from aeon.testing.mock_estimators import MockTransformer
>>>
>>> inverse_exponent = InvertTransform(ExponentTransformer(power=3))
>>> inverse_exponent = InvertTransform(MockTransformer(power=3))
>>> X = load_airline()
>>> Xt = inverse_exponent.fit_transform(X) # computes 3rd square root
"""
Expand Down Expand Up @@ -1170,10 +1157,8 @@ def get_test_params(cls, parameter_set="default"):
`create_test_instance` uses the first (or only) dictionary in `params`
"""
from aeon.transformations.boxcox import BoxCoxTransformer
from aeon.transformations.exponent import ExponentTransformer

# ExponentTransformer skips fit
params1 = {"transformer": ExponentTransformer()}
params1 = {"transformer": MockTransformer()}
# BoxCoxTransformer has fit
params2 = {"transformer": BoxCoxTransformer()}

Expand Down
6 changes: 3 additions & 3 deletions aeon/transformations/tests/test_featureizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

from aeon.datasets import load_longley
from aeon.forecasting.model_selection import temporal_train_test_split
from aeon.testing.mock_estimators import MockTransformer
from aeon.transformations.compose import YtoX
from aeon.transformations.exponent import ExponentTransformer
from aeon.transformations.lag import Lag

y, X = load_longley()
Expand All @@ -21,11 +21,11 @@ def test_featurized_values():
is done without YtoX.
"""
lags = len(y_test)
featurizer = YtoX() * ExponentTransformer() * Lag(lags)
featurizer = YtoX() * MockTransformer() * Lag(lags)
featurizer.fit(X_train, y_train)
X_hat = featurizer.transform(X_test, y_test)

exp_transformer = ExponentTransformer()
exp_transformer = MockTransformer()
expected_len = lags + len(y_test)
y_hat = exp_transformer.fit_transform(y[-expected_len:])
assert_array_equal(X_hat[f"lag_{lags}__TOTEMP"].values, y_hat.values)
18 changes: 9 additions & 9 deletions aeon/transformations/tests/test_multiplexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
)
from aeon.forecasting.naive import NaiveForecaster
from aeon.performance_metrics.forecasting import mean_absolute_percentage_error
from aeon.testing.mock_estimators import MockTransformer
from aeon.transformations.compose import MultiplexTransformer
from aeon.transformations.exponent import ExponentTransformer


def test_multiplex_transformer_alone():
Expand All @@ -32,8 +32,8 @@ def test_multiplex_transformer_alone():
y.loc[y.sample(frac=0.1).index] = np.nan
# Note - we select two transformers which are deterministic.
transformer_tuples = [
("two", ExponentTransformer(2)),
("three", ExponentTransformer(3)),
("two", MockTransformer(2)),
("three", MockTransformer(3)),
]
transformer_names = [name for name, _ in transformer_tuples]
transformers = [transformer for _, transformer in transformer_tuples]
Expand Down Expand Up @@ -79,8 +79,8 @@ def test_multiplex_transformer_in_grid():
y.iloc[[5, 10, 15, 25, 32]] = -1
# Note - we select two transformers which are deterministic.
transformer_tuples = [
("two", ExponentTransformer(2)),
("three", ExponentTransformer(3)),
("two", MockTransformer(2)),
("three", MockTransformer(3)),
]
transformer_names = [name for name, _ in transformer_tuples]
multiplex_transformer = MultiplexTransformer(transformers=transformer_tuples)
Expand Down Expand Up @@ -115,15 +115,15 @@ def test_multiplex_or_dunder():
as expected on all the use cases, and raises the expected error in some others.
"""
# test a simple | example with two transformers:
multiplex_two_transformers = ExponentTransformer(2) | ExponentTransformer(3)
multiplex_two_transformers = MockTransformer(2) | MockTransformer(3)
assert isinstance(multiplex_two_transformers, MultiplexTransformer)
assert len(multiplex_two_transformers.transformers) == 2
# now test that | also works on two MultiplexTransformers:
multiplex_one = MultiplexTransformer(
[("exp_2", ExponentTransformer(2)), ("exp_3", ExponentTransformer(3))]
[("exp_2", MockTransformer(2)), ("exp_3", MockTransformer(3))]
)
multiplex_two = MultiplexTransformer(
[("exp_4", ExponentTransformer(4)), ("exp_5", ExponentTransformer(5))]
[("exp_4", MockTransformer(4)), ("exp_5", MockTransformer(5))]
)

multiplex_two_multiplex = multiplex_one | multiplex_two
Expand All @@ -132,7 +132,7 @@ def test_multiplex_or_dunder():
# last we will check 3 transformers with the same name - should check both that
# MultiplexTransformer | transformer works, and that ensure_unique_names works
multiplex_same_name_three_test = (
ExponentTransformer(2) | ExponentTransformer(3) | ExponentTransformer(4)
MockTransformer(2) | MockTransformer(3) | MockTransformer(4)
)
assert isinstance(multiplex_same_name_three_test, MultiplexTransformer)
assert len(multiplex_same_name_three_test._transformers) == 3
Expand Down
12 changes: 6 additions & 6 deletions aeon/utils/estimator_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,29 +69,29 @@ def check_estimator(
Examples
--------
>>> from aeon.transformations.exponent import ExponentTransformer
>>> from aeon.testing.mock_estimators import MockTransformer
>>> from aeon.testing.estimator_checks import check_estimator
Running all tests for ExponentTransformer class,
this uses all instances from get_test_params and compatible scenarios
>>> results = check_estimator(ExponentTransformer)
>>> results = check_estimator(MockTransformer)
All tests PASSED!
Running all tests for a specific ExponentTransformer
Running all tests for a specific MockTransformer
this uses the instance that is passed and compatible scenarios
>>> results = check_estimator(ExponentTransformer(42))
>>> results = check_estimator(MockTransformer(42))
All tests PASSED!
Running specific test (all fixtures) for ExponentTransformer
>>> results = check_estimator(ExponentTransformer, tests_to_run="test_clone")
>>> results = check_estimator(MockTransformer, tests_to_run="test_clone")
All tests PASSED!
{'test_clone[ExponentTransformer-0]': 'PASSED',
'test_clone[ExponentTransformer-1]': 'PASSED'}
Running one specific test-fixture-combination for ExponentTransformer
>>> check_estimator(
... ExponentTransformer, fixtures_to_run="test_clone[ExponentTransformer-1]"
... MockTransformer, fixtures_to_run="test_clone[ExponentTransformer-1]"
... )
All tests PASSED!
{'test_clone[ExponentTransformer-1]': 'PASSED'}
Expand Down
5 changes: 2 additions & 3 deletions aeon/utils/tests/test_check_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import pytest

from aeon.testing.estimator_checks import check_estimator
from aeon.testing.mock_estimators import MockClassifier, MockSegmenter
from aeon.transformations.exponent import ExponentTransformer
from aeon.testing.mock_estimators import MockClassifier, MockSegmenter, MockTransformer

EXAMPLE_CLASSES = [MockClassifier, MockSegmenter]

Expand Down Expand Up @@ -48,7 +47,7 @@ def test_check_estimator_subset_tests():
expected_tests = set(tests_to_run).difference(tests_to_exclude)

results = check_estimator(
ExponentTransformer,
MockTransformer,
verbose=False,
tests_to_run=tests_to_run,
tests_to_exclude=tests_to_exclude,
Expand Down

0 comments on commit 82586c6

Please sign in to comment.