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

Add root mean squared scaled error to metrics #2031

Conversation

Beerstabr
Copy link
Contributor

Added root mean squared scaled error as used during the M5 competition to metrics.
Also see this link for explanation.

Is this something you are interested in? If so, I'll add some tests.

@madtoinou
Copy link
Collaborator

It looks interesting but wouldn't be simpler to just add an argument to mse? Or at least reuse it in rmsse?

@Beerstabr
Copy link
Contributor Author

Thanks for having a look @madtoinou .

I think you are right about reusing rmse() in rmsse(). I changed it in the PR.

Adding an argument to mse() would make mse more complicated then it needs to be.

I think the way rmsse() is now included is in line with how mase is included, as well as in line with how rmse() relates to mse().

What do you think?

Copy link
Collaborator

@dennisbader dennisbader left a comment

Choose a reason for hiding this comment

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

Hi @Beerstabr and thanks for this, looks like a great start 🚀
You can go ahead with the PR!

Main suggestion was to refactor the MASE and RMSSE so that they both use the same functions.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks @Beerstabber for this contribution and sorry for the late review.
I think we can indeed add this to Darts (keeping in mind that RMSSE also has its cons, e.g. when the naive score is bad).

As @madtoinou mentioned, we should try to simplify this a bit.
It is using a similar logic to MASE, can we refactor it so that both functions make use of the same logic?

Copy link
Contributor Author

@Beerstabr Beerstabr Nov 10, 2023

Choose a reason for hiding this comment

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

@dennisbader I refactored the code such that mase and rmsse are wrapped similar to the other metrics. Might be possible to further refactor by for example combining multi_ts_support() and multi_ts_support_insample(). Not sure if it is worth the effort. Let me know what you think.

Also just copied the mase tests for rmsse. Will refactor it if you like the other changes I've made so far.

Would like to add the Scaled Quantile Loss metric as well if you agree that this would be a worthwhile addition.

Copy link
Collaborator

@dennisbader dennisbader left a comment

Choose a reason for hiding this comment

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

This looks very neat now, great job and thanks @Beerstabr 🚀

Apart from some minor suggestions, I think it makes sense to combine the multi_ts_support for the non-scaled and scaled logic. I left a comment there with a suggestions.

@@ -277,11 +282,9 @@ def test_smape(self):
self.helper_test_nan(metrics.smape)

def test_mase(self):

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 parametrize this test with pytest to check both metrics:

@pytest.mark.parametrize("metric", [metrics.mase, metrics.rmsse])
def test_scaled_metrics(self, metric):

then we can replace metrics.mape with metric and remove the test_rmsse test.

Copy link
Collaborator

Choose a reason for hiding this comment

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

can we add a check for MASE, RMSSE that verifies an expected metric score for a prediction that is not equal to the target (e.g. MASE/RMSSE != 0)?

@@ -107,6 +107,104 @@ def wrapper_multi_ts_support(*args, **kwargs):
return wrapper_multi_ts_support


def multi_ts_support_insample(func):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice job with refactoring the scaled logic!

It would indeed be nice to have the multi ts support handled by the same wrapper, as only the insample handling is different between the two.

You could check for example that "insample" is part of func's signature to know which logic to use.

What do you think?

elif len(args) > 3:
m = args[3]
else:
m = 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

we should use the func's default parameters here and for intersect:

Suggested change
m = 1
m = signature(func).parameters["m"].default

)
m = 1

value_list.append(func(y_true, y_hat, x_t, m, *args[3:], **kwargs))
Copy link
Collaborator

Choose a reason for hiding this comment

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

if m is passed in args, then this will give it twice to func (once through m, and another time through *args[3:]).

Do we have to exclude it from args when we retrieve it at the top?

Comment on lines +914 to +915
raise_if_not(
not np.isclose(scale, 0),
Copy link
Collaborator

Choose a reason for hiding this comment

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

below might be more interpretable

Suggested change
raise_if_not(
not np.isclose(scale, 0),
raise_if(
np.isclose(scale, 0),

Comment on lines +1430 to +1431
raise_if_not(
not np.isclose(scale, 0),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
raise_if_not(
not np.isclose(scale, 0),
raise_if(
np.isclose(scale, 0),

@dennisbader dennisbader marked this pull request as ready for review November 14, 2023 16:44
@dennisbader
Copy link
Collaborator

Hi @Beerstabr, just wanted to check in whether you're still working on this PR? :)

@dennisbader dennisbader mentioned this pull request Mar 27, 2024
3 tasks
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.

3 participants