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

Handle prediction intervals in TSDataset similar to target components #97

Merged
merged 28 commits into from Oct 9, 2023

Conversation

brsnw250
Copy link
Collaborator

@brsnw250 brsnw250 commented Oct 4, 2023

Before submitting (must do checklist)

  • Did you read the contribution guide?
  • Did you update the docs? We use Numpy format for all the methods and classes.
  • Did you write any new necessary tests?
  • Did you update the CHANGELOG?

Proposed Changes

Closing issues

closes #88

@brsnw250 brsnw250 self-assigned this Oct 4, 2023
@github-actions
Copy link

github-actions bot commented Oct 4, 2023

🚀 Deployed on https://deploy-preview-97--etna-docs.netlify.app

@github-actions github-actions bot temporarily deployed to pull request October 4, 2023 11:39 Inactive
@brsnw250 brsnw250 changed the title Issue 88 Handle prediction intervals in TSDataset similar to target components Oct 4, 2023
@codecov
Copy link

codecov bot commented Oct 4, 2023

Codecov Report

Attention: 3 lines in your changes are missing coverage. Please review.

Comparison is base (be58b43) 89.14% compared to head (d9565c1) 89.18%.

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #97      +/-   ##
==========================================
+ Coverage   89.14%   89.18%   +0.04%     
==========================================
  Files         195      195              
  Lines       12554    12551       -3     
==========================================
+ Hits        11191    11194       +3     
+ Misses       1363     1357       -6     
Files Coverage Δ
etna/models/mixins.py 96.39% <100.00%> (+0.13%) ⬆️
etna/models/nn/deepar.py 97.40% <100.00%> (-0.10%) ⬇️
etna/models/nn/tft.py 97.87% <100.00%> (-0.07%) ⬇️
etna/pipeline/base.py 95.72% <100.00%> (+0.01%) ⬆️
etna/pipeline/hierarchical_pipeline.py 95.18% <100.00%> (+0.11%) ⬆️
etna/reconciliation/base.py 95.23% <100.00%> (+0.64%) ⬆️
etna/transforms/base.py 92.85% <100.00%> (-0.05%) ⬇️
...forms/decomposition/change_points_based/detrend.py 100.00% <100.00%> (ø)
etna/transforms/decomposition/detrend.py 96.00% <100.00%> (-0.30%) ⬇️
etna/transforms/decomposition/stl.py 93.33% <100.00%> (-0.34%) ⬇️
... and 7 more

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@github-actions github-actions bot temporarily deployed to pull request October 4, 2023 12:05 Inactive
@brsnw250 brsnw250 marked this pull request as ready for review October 5, 2023 06:43
@d-a-bunin d-a-bunin self-requested a review October 5, 2023 07:43
etna/datasets/tsdataset.py Show resolved Hide resolved
etna/datasets/tsdataset.py Show resolved Hide resolved
etna/datasets/tsdataset.py Outdated Show resolved Hide resolved
@@ -208,7 +208,7 @@ def __init__(self, required_features: Union[Literal["all"], List[str]]):
super().__init__(required_features=required_features)

@abstractmethod
def _inverse_transform(self, df: pd.DataFrame) -> pd.DataFrame:
def _inverse_transform(self, df: pd.DataFrame, prediction_intervals: Tuple[str, ...]) -> pd.DataFrame:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we somehow avoid changing the signature in backward incompatible way?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make this field optional, but it requires doing the same check in many different places.
But how does this make changes backward incompatible? We make this change only in internal private methods and classes that are not intended for external use cases.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A small follow up, we can do it without the check at all.
The question is still relevant.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imagine that someone created their own transforms. With these changes their transforms stop working and need rework to support new way of handling intervals.

With models we still use match_target_quantiles for extracting quantiles from adapters. Can't we make smth like this for transforms too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

Unfortunately, we can't use match_target_quantiles, because transforms should work with any interval borders, not only quantilies, so they might not follow name convention. In this case, we should propagate interval names from the top level (where we work with datasets). Built-in models intervals produce quantiles, that's why we can use this function there.

@@ -114,13 +115,15 @@ def _transform(self, df: pd.DataFrame) -> pd.DataFrame:

return transformed_features

def _inverse_transform(self, df: pd.DataFrame) -> pd.DataFrame:
def _inverse_transform(self, df: pd.DataFrame, prediction_intervals: Tuple[str, ...]) -> pd.DataFrame:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't we have to handle prediction intervals in this transform too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This transform handles all columns of df similarly. Intervals are stored in df directly, so they are transformed as well.


@pytest.fixture()
def ts_with_prediction_intervals(ts_without_target_components, prediction_intervals_df):
ts = deepcopy(ts_without_target_components)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that it is necessary to make deepcopy in fixtures.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't do so, this fixture will modify ts_without_target_components inplace. But we want it untouched.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that fixtures doesn't interact with each other during creation.

tests/test_datasets/test_dataset.py Outdated Show resolved Hide resolved
tests/test_models/nn/test_deepar.py Show resolved Hide resolved
tests/test_pipeline/test_hierarchical_pipeline.py Outdated Show resolved Hide resolved
tests/test_pipeline/test_hierarchical_pipeline.py Outdated Show resolved Hide resolved
@github-actions github-actions bot temporarily deployed to pull request October 5, 2023 10:41 Inactive
@github-actions github-actions bot temporarily deployed to pull request October 9, 2023 10:53 Inactive
@@ -515,9 +525,17 @@ def target_components_names(self) -> Tuple[str, ...]:
return self._target_components_names

@property
@deprecated(
reason="Usage of this property may mislead while accessing prediction intervals. Use `prediction_intervals_names` property to access intervals names!"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to set a version in which it is going to be removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idealy, it should be removed when new prediction intervals are completely stable and moved from experimental. Right now, it seems like an open question.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't remove this property without major update. So, let's set version 3.0 for example for this property to be removed.

for quantile_column_nm in quantiles:
# inverse transformation of columns that are left (e.g. prediction intervals)
other_columns = set(df.columns.get_level_values("feature")) - set(self.in_column)
for column_nm in other_columns:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use column_name?

@github-actions github-actions bot temporarily deployed to pull request October 9, 2023 12:30 Inactive
d-a-bunin
d-a-bunin previously approved these changes Oct 9, 2023
@github-actions github-actions bot temporarily deployed to pull request October 9, 2023 12:40 Inactive
@github-actions github-actions bot temporarily deployed to pull request October 9, 2023 14:24 Inactive
@brsnw250 brsnw250 merged commit 799ccb1 into master Oct 9, 2023
16 checks passed
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

Successfully merging this pull request may close these issues.

Handle prediction intervals in TSDataset similar to target components
2 participants