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

Added MASE metric and y_train parameter to objectives #4221

Merged
merged 45 commits into from
Jul 18, 2023
Merged

Conversation

remyogasawara
Copy link
Collaborator

Resolves #4217

@codecov
Copy link

codecov bot commented Jun 30, 2023

Codecov Report

Merging #4221 (c6f52e4) into main (4d20d58) will increase coverage by 0.1%.
The diff coverage is 100.0%.

@@           Coverage Diff           @@
##            main   #4221     +/-   ##
=======================================
+ Coverage   99.7%   99.7%   +0.1%     
=======================================
  Files        349     349             
  Lines      38281   38309     +28     
=======================================
+ Hits       38162   38190     +28     
  Misses       119     119             
Impacted Files Coverage Δ
evalml/objectives/__init__.py 100.0% <ø> (ø)
evalml/tests/data_checks_tests/test_data_checks.py 100.0% <ø> (ø)
evalml/objectives/cost_benefit_matrix.py 100.0% <100.0%> (ø)
evalml/objectives/fraud_cost.py 100.0% <100.0%> (ø)
evalml/objectives/lead_scoring.py 100.0% <100.0%> (ø)
evalml/objectives/objective_base.py 100.0% <100.0%> (ø)
evalml/objectives/standard_metrics.py 100.0% <100.0%> (ø)
evalml/pipelines/pipeline_base.py 98.5% <100.0%> (ø)
...ata_checks_tests/test_invalid_target_data_check.py 100.0% <100.0%> (ø)
...alml/tests/objective_tests/test_fraud_detection.py 100.0% <100.0%> (ø)
... and 2 more


def objective_function(self, y_true, y_predicted, X=None, sample_weight=None):
"""Objective function for mean absolute percentage error for time series regression."""
y_train = y_true
Copy link
Collaborator Author

@remyogasawara remyogasawara Jul 5, 2023

Choose a reason for hiding this comment

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

MASE takes in training data as a parameter, since we don't use training data we just used the actual data in place of training data for now, but wanted to see what others think

Copy link
Contributor

Choose a reason for hiding this comment

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

This brings up a very interesting question. A quick test shows that the results do change based on what you pass in to the y_train argument, meaning that the results we pass in with this are going to be less correct.

Looking through where we score pipelines, I don't think it would be too much extra lift to add the ability to pass y_train through. We have access to it in the upper level time series pipeline scoring functions, as it's pretty common for time series related things in general to require the historical data.

I'm curious what others think though - should we update our objective functions to have access to y_train, or should we keep it as is like this?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should update it to support MASE properly but lets work on it in a followup issue. @remyogasawara can you file the follow up in EvalML? Just basically stating the requirements that @eccabay wrote above?

Copy link
Contributor

@eccabay eccabay left a comment

Choose a reason for hiding this comment

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

This metric is a tricky one - I think there's a few details we need to discuss before it can be merged in! Curious for other team members' input on this as well.

evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved
evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved

def objective_function(self, y_true, y_predicted, X=None, sample_weight=None):
"""Objective function for mean absolute percentage error for time series regression."""
y_train = y_true
Copy link
Contributor

Choose a reason for hiding this comment

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

This brings up a very interesting question. A quick test shows that the results do change based on what you pass in to the y_train argument, meaning that the results we pass in with this are going to be less correct.

Looking through where we score pipelines, I don't think it would be too much extra lift to add the ability to pass y_train through. We have access to it in the upper level time series pipeline scoring functions, as it's pretty common for time series related things in general to require the historical data.

I'm curious what others think though - should we update our objective functions to have access to y_train, or should we keep it as is like this?

evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved
evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved
if isinstance(y_train, pd.Series):
y_train = y_train.to_numpy()
mase = MeanAbsoluteScaledError()
return mase(y_true, y_predicted, y_train=y_train) * 100
Copy link
Contributor

Choose a reason for hiding this comment

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

According to the documentation, another parameter that we may want to consider leveraging is sp. With our Decomposer.determine_periodicity function (or, if the pipeline has a Decomposer, the decomposer's saved sp parameter), we should have the information necessary to pass that through. The question remains how, since we need information from X and y train, but it could be done. From brief testing, it looks like adding the sp argument gives us lower values (aka "better" scores), and they would once again be considered to be more accurate, since we use sp during training.

I'm curious what other people think about the need to include sp as well.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree we should support this! @remyogasawara can you file another issue for this so we can prioritize after decomp is added for multiseries?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved
evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved
evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved

def objective_function(self, y_true, y_predicted, X=None, sample_weight=None):
"""Objective function for mean absolute percentage error for time series regression."""
y_train = y_true
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should update it to support MASE properly but lets work on it in a followup issue. @remyogasawara can you file the follow up in EvalML? Just basically stating the requirements that @eccabay wrote above?

evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved
@eccabay
Copy link
Contributor

eccabay commented Jul 6, 2023

One other small thing I forgot to request, can you add this (as well as SMAPE, because I forgot before 😅) to the API reference?

@remyogasawara remyogasawara marked this pull request as draft July 8, 2023 00:26
@remyogasawara remyogasawara changed the title Add MASE metric Add MASE metric and y_train parameter to objectives Jul 14, 2023
@remyogasawara remyogasawara changed the title Add MASE metric and y_train parameter to objectives Added MASE metric and y_train parameter to objectives Jul 14, 2023
@remyogasawara remyogasawara marked this pull request as ready for review July 15, 2023 02:15
Copy link
Collaborator

@jeremyliweishih jeremyliweishih left a comment

Choose a reason for hiding this comment

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

LGTM good work!

Copy link
Contributor

@eccabay eccabay left a comment

Choose a reason for hiding this comment

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

Looks good, great job being thorough with your changes! Just a few small nitpicks, but otherwise this looks ready to go

evalml/objectives/cost_benefit_matrix.py Outdated Show resolved Hide resolved
evalml/tests/objective_tests/test_standard_metrics.py Outdated Show resolved Hide resolved
evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved
evalml/objectives/standard_metrics.py Outdated Show resolved Hide resolved
Comment on lines 1074 to 1076
if (isinstance(y_train, pd.DataFrame) and (y_train.values == 0).all()) or (
isinstance(y_train, pd.Series) and (y_train == 0).all()
):
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need to split it up this way - y_train.values should work regardless of whether it's a dataframe or a series!

@remyogasawara remyogasawara merged commit 09bd86e into main Jul 18, 2023
@remyogasawara remyogasawara deleted the 4217_add_mase branch July 18, 2023 19:54
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.

Time series regression: add MASE/MAPE/SMAPE as metrics
3 participants