Skip to content

Commit

Permalink
[MNT] 0.15.0 deprecation actions (#3952)
Browse files Browse the repository at this point in the history
Deprecation actions for the 0.15.0 release:

* changed `check_is_scitype` parameter `msg_legacy_interface` to `False`
* `ExpandingWindowSplitter` had `start_with_window` argument removed. From now on, `initial_window=0` should be used instead of `start_with_window=False`. Contains bugfix #3953 as the deprecation logic was incomplete.
* Test `test_methods_do_not_change_state` renamed to `test_non_state_changing_method_contract`
* row transformers have been removed, replaced by base class vectorization/broadcasting
* changed default for `default_fc_parameters` in `tsfresh` transformers to follow the default of `tsfresh`, which currently is `comprehensive`
* removed module `transformations.series.compose`. All contents were moved to `transformations.compose`.

Delayed to 0.16.0:
* base class of `ProbabilityThresholdEarlyClassifier` change to `BaseEarlyClassifier`. Unclear what to do here, deprecation action specified breaks the interface compliance tests. Attempt to fix here #3962 but fails `fit_idempotent` test (unclear why, will drop for this release).
* change of forecaster `cutoff` attribute to `pd.Index` type
  • Loading branch information
fkiraly committed Dec 21, 2022
1 parent 8c72514 commit 36c4d5e
Show file tree
Hide file tree
Showing 15 changed files with 19 additions and 154 deletions.
2 changes: 1 addition & 1 deletion examples/01_forecasting.ipynb
Expand Up @@ -6526,8 +6526,8 @@
" SlidingWindowSplitter,\n",
")\n",
"from sktime.forecasting.naive import NaiveForecaster\n",
"from sktime.transformations.compose import OptionalPassthrough\n",
"from sktime.transformations.series.adapt import TabularToSeriesAdaptor\n",
"from sktime.transformations.series.compose import OptionalPassthrough\n",
"from sktime.transformations.series.detrend import Deseasonalizer"
]
},
Expand Down
Expand Up @@ -22,10 +22,10 @@
from sktime.utils.validation.panel import check_X


# TODO: remove message in v0.15.0 and change base class
# TODO: remove message in v0.16.0 and change base class
@deprecated(
version="0.13.0",
reason="The base class of ProbabilityThresholdEarlyClassifier will be changed to BaseEarlyClassifier in v0.15.0. This will change how classification safety decisions are made and returned, see BaseEarlyClassifier or TEASER for the new interface.", # noqa: E501
reason="The base class of ProbabilityThresholdEarlyClassifier will be changed to BaseEarlyClassifier in v0.16.0. This will change how classification safety decisions are made and returned, see BaseEarlyClassifier or TEASER for the new interface.", # noqa: E501
category=FutureWarning,
)
class ProbabilityThresholdEarlyClassifier(BaseClassifier):
Expand Down
6 changes: 2 additions & 4 deletions sktime/datatypes/_check.py
Expand Up @@ -333,15 +333,14 @@ def mtype(
return mtypes_positive[0]


# todo 0.15.0: change msg_legacy_interface default to False
# todo 0.16.0: remove msg_legacy_interface arg, and remove msg_legacy variable inside
def check_is_scitype(
obj,
scitype: Union[str, List[str]],
return_metadata=False,
var_name="obj",
exclude_mtypes=AMBIGUOUS_MTYPES,
msg_legacy_interface=True,
msg_legacy_interface=False,
):
"""Check object for compliance with scitype specification, return metadata.
Expand Down Expand Up @@ -461,8 +460,7 @@ def check_is_scitype(
warn(
"return msg (2nd argument) of check_is_scitype will change to "
"dict from list type. Set msg_legacy_interface=False for "
"post-deprecation behaviour. Default msg_legacy_interface "
"will change to True in 0.15.0. Argument msg_legacy_interface "
"post-deprecation behaviour. Argument msg_legacy_interface "
"will be removed in 0.16.0.",
DeprecationWarning,
)
Expand Down
2 changes: 1 addition & 1 deletion sktime/forecasting/base/_fh.py
Expand Up @@ -696,7 +696,7 @@ def _to_relative(fh: ForecastingHorizon, cutoff=None) -> ForecastingHorizon:
# Out: Index([<0 * Hours>, <4 * Hours>, <8 * Hours>], dtype = 'object')
# [v - periods[0] for v in periods]
# Out: Index([<0 * Hours>, <2 * Hours>, <4 * Hours>], dtype='object')
# TODO: 0.15.0: Check if this comment below can be removed,
# TODO: 0.16.0: Check if this comment below can be removed,
# so check if pandas has released the fix to PyPI:
# This bug was reported: https://github.com/pandas-dev/pandas/issues/45999
# and fixed: https://github.com/pandas-dev/pandas/pull/46006
Expand Down
4 changes: 2 additions & 2 deletions sktime/forecasting/compose/tests/test_pipeline.py
Expand Up @@ -28,10 +28,10 @@
from sktime.forecasting.naive import NaiveForecaster
from sktime.forecasting.sarimax import SARIMAX
from sktime.forecasting.trend import PolynomialTrendForecaster
from sktime.transformations.compose import OptionalPassthrough
from sktime.transformations.hierarchical.aggregate import Aggregator
from sktime.transformations.series.adapt import TabularToSeriesAdaptor
from sktime.transformations.series.boxcox import LogTransformer
from sktime.transformations.series.compose import OptionalPassthrough
from sktime.transformations.series.detrend import Detrender
from sktime.transformations.series.difference import Differencer
from sktime.transformations.series.exponent import ExponentTransformer
Expand Down Expand Up @@ -110,8 +110,8 @@ def test_skip_inverse_transform():
def test_nesting_pipelines():
"""Test that nesting of pipelines works."""
from sktime.forecasting.ets import AutoETS
from sktime.transformations.compose import OptionalPassthrough
from sktime.transformations.series.boxcox import LogTransformer
from sktime.transformations.series.compose import OptionalPassthrough
from sktime.transformations.series.detrend import Detrender
from sktime.utils._testing.scenarios_forecasting import (
ForecasterFitPredictUnivariateWithX,
Expand Down
2 changes: 1 addition & 1 deletion sktime/tests/_config.py
Expand Up @@ -103,7 +103,7 @@
# #2 amd #3 are due to predict/predict_proba returning two items and that breaking
# assert_array_equal
"TEASER": [
"test_methods_do_not_change_state",
"test_non_state_changing_method_contract",
"test_fit_idempotent",
"test_persistence_via_pickle",
"test_save_estimators_to_file",
Expand Down
11 changes: 1 addition & 10 deletions sktime/tests/test_all_estimators.py
Expand Up @@ -13,7 +13,6 @@
from copy import deepcopy
from inspect import getfullargspec, isclass, signature
from tempfile import TemporaryDirectory
from warnings import warn

import joblib
import numpy as np
Expand Down Expand Up @@ -1151,7 +1150,7 @@ def test_fit_does_not_overwrite_hyper_params(self, estimator_instance, scenario)
% (estimator.__class__.__name__, param_name, original_value, new_value)
)

def test_methods_do_not_change_state(
def test_non_state_changing_method_contract(
self, estimator_instance, scenario, method_nsc
):
"""Check that non-state-changing methods behave as per interface contract.
Expand All @@ -1164,14 +1163,6 @@ def test_methods_do_not_change_state(
list of BaseEstimator methdos tested: get_fitted_params
scitype specific method outputs are tested in TestAll[estimatortype] class
"""
warn(
"name of test_methods_do_not_change_state will change to "
"test_non_state_changing_method_contract in 0.15.0. "
"For a safe transition in a case where the old name "
"has been used as part of an argument in `check_estimator`, use "
"both the new and the old name in test/fixture exclusion or inclusion. ",
DeprecationWarning,
)
estimator = estimator_instance
set_random_state(estimator)

Expand Down
4 changes: 2 additions & 2 deletions sktime/transformations/compose.py
Expand Up @@ -1283,7 +1283,7 @@ class OptionalPassthrough(_DelegatedTransformer):
--------
>>> from sktime.datasets import load_airline
>>> from sktime.forecasting.naive import NaiveForecaster
>>> from sktime.transformations.series.compose import OptionalPassthrough
>>> from sktime.transformations.compose import OptionalPassthrough
>>> from sktime.transformations.series.detrend import Deseasonalizer
>>> from sktime.transformations.series.adapt import TabularToSeriesAdaptor
>>> from sktime.forecasting.compose import TransformedTargetForecaster
Expand Down Expand Up @@ -1416,7 +1416,7 @@ class ColumnwiseTransformer(BaseTransformer):
--------
>>> from sktime.datasets import load_longley
>>> from sktime.transformations.series.detrend import Detrender
>>> from sktime.transformations.series.compose import ColumnwiseTransformer
>>> from sktime.transformations.compose import ColumnwiseTransformer
>>> _, X = load_longley()
>>> transformer = ColumnwiseTransformer(Detrender())
>>> Xt = transformer.fit_transform(X)
Expand Down
91 changes: 1 addition & 90 deletions sktime/transformations/panel/compose.py
Expand Up @@ -4,28 +4,17 @@
This module has meta-transformations that is build using the pre-existing
transformations as building blocks.
"""
from warnings import warn

import numpy as np
import pandas as pd
from deprecated.sphinx import deprecated
from scipy import sparse
from sklearn.base import clone
from sklearn.compose import ColumnTransformer as _ColumnTransformer

from sktime.transformations.base import BaseTransformer, _PanelToPanelTransformer
from sktime.transformations.series.adapt import TabularToSeriesAdaptor
from sktime.utils.multiindex import flatten_multiindex
from sktime.utils.sklearn import is_sklearn_estimator
from sktime.utils.validation.panel import check_X

__author__ = ["mloning", "sajaysurya", "fkiraly"]
__all__ = [
"ColumnTransformer",
"SeriesToPrimitivesRowTransformer",
"SeriesToSeriesRowTransformer",
"ColumnConcatenator",
]
__all__ = ["ColumnTransformer", "ColumnConcatenator"]


class ColumnTransformer(_ColumnTransformer, _PanelToPanelTransformer):
Expand Down Expand Up @@ -272,81 +261,3 @@ def _transform(self, X, y=None):
Xt.index = pd.MultiIndex.from_arrays([inst_idx, t_idx])
Xt.index.names = X.index.names
return Xt


row_trafo_deprec_msg = (
"All row transformers are deprecated since 0.14.0 and will be removed "
"in 0.15.0. Vectorization functionality from Series to Panel is natively "
"integrated to all transformers via the base class. Simply use fit "
"or transform on Panel data, no row transformer is necessary anymore."
)


class _RowTransformer(BaseTransformer):
"""Base class for RowTransformer."""

_tags = {"fit_is_empty": True}

def __init__(self, transformer, check_transformer=None):

warn(row_trafo_deprec_msg)

self.transformer = transformer
transformer_ = clone(transformer)
# safer wrapping: coerce to sktime transformer
if is_sklearn_estimator(transformer_):
transformer_ = TabularToSeriesAdaptor(transformer_)
self.transformer_ = transformer_

self.check_transformer = check_transformer
super(_RowTransformer, self).__init__()
self.clone_tags(transformer_)
# fit needs to be run, or the internal fit may not be updated
self.set_tags(**{"fit_is_empty": False})

def _fit(self, *args, **kwargs):
"""Fit to the data."""
return self.transformer_.fit(*args, **kwargs)

def _transform(self, *args, **kwargs):
"""Transform the data."""
return self.transformer_.transform(*args, **kwargs)

def _inverse_transform(self, *args, **kwargs):
"""Inverse transform the data."""
return self.transformer_.inverse_transform(*args, **kwargs)

def _update(self, *args, **kwargs):
"""Update with the data."""
return self.transformer_.update(*args, **kwargs)

@classmethod
def get_test_params(cls):
"""Return testing parameter settings for the estimator."""
from sktime.transformations.series.exponent import ExponentTransformer

params = {"transformer": ExponentTransformer()}
return params


class SeriesToPrimitivesRowTransformer(_RowTransformer, BaseTransformer):
"""Series-to-primitives row transformer."""


class SeriesToSeriesRowTransformer(_RowTransformer, BaseTransformer):
"""Series-to-series row transformer."""


@deprecated(version="0.14.0", reason=row_trafo_deprec_msg, category=FutureWarning)
def make_row_transformer(transformer, transformer_type=None, **kwargs):
"""Old vectorization utility for transformers for panel data.
This is now integrated into BaseTransformer, so no longer needed.
Deprecated from version 0.14.0, will be removed in 0.15.0.
Returns
-------
transformer, reference to input `transformer` (unchanged)
"""
return transformer
17 changes: 2 additions & 15 deletions sktime/transformations/panel/tsfresh.py
Expand Up @@ -125,17 +125,6 @@ def _get_extraction_params(self):
)
else:
fc_parameters = fc_param_lookup[self.default_fc_parameters]
# TODO: remove elif in v0.15.0
# this will pass None to tsfresh, and hence default to "comprehensive"
elif self.default_fc_parameters is None:
fc_parameters = fc_param_lookup["efficient"]
warn(
"Passing None to default_fc_parameters currently defaults "
"to 'efficient', this behaviour has been is deprecated. From 0.15.0, "
"this will change to passing default_fc_parameters directly to tsfresh,"
" which in turn defaults to 'comprehensive'.",
DeprecationWarning,
)
else:
fc_parameters = self.default_fc_parameters
extraction_params["default_fc_parameters"] = fc_parameters
Expand All @@ -150,7 +139,6 @@ def _get_extraction_params(self):
return extraction_params


# todo 0.15.0: change default_fc_parameters docstring to "comprehensive" default"
class TSFreshFeatureExtractor(_TSFreshFeatureExtractor):
"""Transformer for extracting time series features via `tsfresh.extract_features`.
Expand All @@ -159,7 +147,7 @@ class TSFreshFeatureExtractor(_TSFreshFeatureExtractor):
Parameters
----------
default_fc_parameters : str, FCParameters object or None,
default=None = "efficient"
default=None = tsfresh default = "comprehensive"
Specifies pre-defined feature sets to be extracted
If str, should be in ["minimal", "efficient", "comprehensive"]
See [3] for more details.
Expand Down Expand Up @@ -358,7 +346,6 @@ def get_test_params(cls, parameter_set="default"):
]


# todo 0.15.0: change default_fc_parameters docstring to "comprehensive" default"
class TSFreshRelevantFeatureExtractor(_TSFreshFeatureExtractor):
"""Transformer for extracting time series features via `tsfresh.extract_features`.
Expand All @@ -368,7 +355,7 @@ class TSFreshRelevantFeatureExtractor(_TSFreshFeatureExtractor):
Parameters
----------
default_fc_parameters : str, FCParameters object or None,
default=None = "efficient"
default=None = tsfresh default = "comprehensive"
Specifies pre-defined feature sets to be extracted
If str, should be in ["minimal", "efficient", "comprehensive"]
See [3] for more details.
Expand Down
22 changes: 0 additions & 22 deletions sktime/transformations/series/compose.py

This file was deleted.

2 changes: 1 addition & 1 deletion sktime/transformations/series/tests/test_featureizer.py
Expand Up @@ -6,7 +6,7 @@

from sktime.datasets import load_longley
from sktime.forecasting.model_selection import temporal_train_test_split
from sktime.transformations.series.compose import YtoX
from sktime.transformations.compose import YtoX
from sktime.transformations.series.exponent import ExponentTransformer
from sktime.transformations.series.lag import Lag

Expand Down
Expand Up @@ -5,8 +5,8 @@
import pytest
from pandas.testing import assert_series_equal

from sktime.transformations.compose import OptionalPassthrough
from sktime.transformations.series.boxcox import BoxCoxTransformer
from sktime.transformations.series.compose import OptionalPassthrough
from sktime.utils._testing.series import _make_series


Expand Down
2 changes: 1 addition & 1 deletion sktime/transformations/tests/test_compose.py
Expand Up @@ -13,11 +13,11 @@
from sktime.transformations.compose import (
FeatureUnion,
InvertTransform,
OptionalPassthrough,
TransformerPipeline,
)
from sktime.transformations.panel.padder import PaddingTransformer
from sktime.transformations.series.boxcox import LogTransformer
from sktime.transformations.series.compose import OptionalPassthrough
from sktime.transformations.series.exponent import ExponentTransformer
from sktime.transformations.series.impute import Imputer
from sktime.transformations.series.subset import ColumnSelect
Expand Down
2 changes: 1 addition & 1 deletion sktime/transformations/tests/test_optionalpassthrough.py
Expand Up @@ -24,8 +24,8 @@ def test_optionalpassthrough():
SlidingWindowSplitter,
)
from sktime.forecasting.naive import NaiveForecaster
from sktime.transformations.compose import OptionalPassthrough
from sktime.transformations.series.adapt import TabularToSeriesAdaptor
from sktime.transformations.series.compose import OptionalPassthrough
from sktime.transformations.series.detrend import Deseasonalizer

# create pipeline
Expand Down

0 comments on commit 36c4d5e

Please sign in to comment.