Skip to content

FEA add poisson loss to MLPRegressor - #30712

Merged
ogrisel merged 8 commits into
scikit-learn:mainfrom
lorentzenchr:mpl_poisson
Mar 31, 2025
Merged

FEA add poisson loss to MLPRegressor#30712
ogrisel merged 8 commits into
scikit-learn:mainfrom
lorentzenchr:mpl_poisson

Conversation

@lorentzenchr

Copy link
Copy Markdown
Member

Reference Issues/PRs

None

What does this implement/fix? Explain your changes.

This adds the parameter loss to MLPRegressor, same as for HGBT.

Any other comments?

While in the past it was decided to not add any features to the neural nets, see https://scikit-learn.org/dev/faq.html#id9

Note that scikit-learn currently implements a simple multilayer perceptron in sklearn.neural_network. We will only accept bug fixes for this module.

I argue that it is important to support for all main model types (linear, tree-based, neural nets) the 3 most important distributions in statistics as losses:

  • binomial (log loss)
  • Poisson (Poisson deviance)
  • normal (squared error)

We have it for all but the neural nets. Therefore this PR.

@lorentzenchr lorentzenchr added New Feature Needs Decision - Include Feature Requires decision regarding including feature labels Jan 24, 2025
Comment on lines +211 to +213
# TODO: Decide what to do with the term `xlogy(y_true, y_true) - y_true`. For now,
# it is included. But the _loss module doesn't use it (for performance reasons) and
# only adds it as return of constant_to_optimal_zero (mainly for testing).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This also needs a decision.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

But the _loss module doesn't use it (for performance reasons)

Is there any real performance impact of computing this term when training a model?

I think I would favor always including it. If it used for monitoring, displaying something named "Poisson loss" which is actually not the true loss, but the loss with a constant offset can be quite surprising.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Alternatively, we could just rename this function to offset_poisson_loss to make it explicit that the computation of the constant terms are removed.

But if we expose the value of the objective function under the name "Poisson loss" via the public API, one way or another, I think we should make sure we re-add the constant terms to avoid any confusion when comparing values on resampled data (e.g. between train and test split to check for overfitting).

@OmarManzoor OmarManzoor Feb 13, 2025

Copy link
Copy Markdown
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 performence is too much of a concern with this module so we might as well keep the constant terms.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't think optimization is too much of a concern with this module so we might as well keep the constant terms.

The constant term in the loss only matters if we report/save those loss values as we do in MLP (and in GradientBoosting, but not in HistGradientBoosting). The nice thing about adding the constant term is that the minimum of the loss is then 0 exactly. Omitting it saves a bit of time.
Note also that NN libraries like pytorch usually omit the constant term (see https://pytorch.org/docs/stable/generated/torch.nn.PoissonNLLLoss.html#torch.nn.PoissonNLLLoss).

@OmarManzoor OmarManzoor Feb 13, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes Tensorflow also omits it https://www.tensorflow.org/api_docs/python/tf/keras/losses/Poisson.

I would say let's keep it for now. Would we accomplish much by saving time in this module when there are other optimal libraries specifically for implementing neural networks?

@github-actions

github-actions Bot commented Jan 24, 2025

Copy link
Copy Markdown

✔️ Linting Passed

All linting checks passed. Your pull request is in excellent shape! ☀️

Generated for commit: 9352f2b. Link to the linter CI: here

@OmarManzoor

Copy link
Copy Markdown
Contributor

From my opinion including this seems to make sense and from an overall look at the changes I don't think it adds much extra maintenance overhead as well.

What do others think @scikit-learn/core-devs

@lorentzenchr

Copy link
Copy Markdown
Member Author

In the monthly meeting on January 27, 2025, https://github.com/scikit-learn/administrative/blob/master/monthly_meetings/2025-01-27.md, we decided:

Poisson loss for MLPRegressor #30712 We say that NN won't get new features, yet I think having the three most important losses (log loss, squared error, Poisson deviance) in all major supervised learning methods (linear, tree, nn) would complete the picture.

  • there is a difference between adding new features and maintaining MLP in good working order which includes making it uniform with the rest of the library. For example:
    • completing the set of popular losses (Poisson, Gamma, Tweedie, Pinball)
    • completing array API support
    • completing metadata routing
  • There seems to be consensus on those 3 points, but not more (alternative would be to deprecate and remove nn)

@OmarManzoor

Copy link
Copy Markdown
Contributor
  • There seems to be consensus on those 3 points, but not more (alternative would be to deprecate and remove nn)

Is deprecating this module being considered as a possibility? Because if that is the case, I don't think we should add anything.

@lorentzenchr

Copy link
Copy Markdown
Member Author

The consensus was keep the module and make it consistent with the rest. Therefore add those few extensions, also the Poisson loss. Nobody has so far raised the voice to deprecate it.
Despite there being much better options for NNs, I personally think it would be a pity to deprecate it altogether. If we keep it, you can install one small library, i.e. scikit-learn, and you get basic GLMs, trees and NNs. From there on, you can start looking for more advanced options.

@OmarManzoor

Copy link
Copy Markdown
Contributor

Despite there being much better options for NNs, I personally think it would be a pity to deprecate it altogether. If we keep it, you can install one small library, i.e. scikit-learn, and you get basic GLMs, trees and NNs. From there on, you can start looking for more advanced options.

That seems fine. Thanks for explaining. I think we should move forward with reviewing this PR then.

@OmarManzoor OmarManzoor removed the Needs Decision - Include Feature Requires decision regarding including feature label Feb 12, 2025

@OmarManzoor OmarManzoor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the PR @lorentzenchr

A few comments otherwise looks nice

Comment on lines +211 to +213
# TODO: Decide what to do with the term `xlogy(y_true, y_true) - y_true`. For now,
# it is included. But the _loss module doesn't use it (for performance reasons) and
# only adds it as return of constant_to_optimal_zero (mainly for testing).

@OmarManzoor OmarManzoor Feb 13, 2025

Copy link
Copy Markdown
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 performence is too much of a concern with this module so we might as well keep the constant terms.

Comment thread sklearn/neural_network/_multilayer_perceptron.py Outdated
Comment thread sklearn/neural_network/tests/test_mlp.py
@OmarManzoor OmarManzoor changed the title ENH add poisson loss to MLPRegressor FEA add poisson loss to MLPRegressor Feb 13, 2025

@OmarManzoor OmarManzoor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@OmarManzoor OmarManzoor added the Waiting for Second Reviewer First reviewer is done, need a second one! label Feb 14, 2025
@lorentzenchr lorentzenchr added this to the 1.7 milestone Mar 10, 2025
test_mlp_vs_poisson_glm_equivalent

@ogrisel ogrisel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Besides https://github.com/scikit-learn/scikit-learn/pull/30712/files#r1954012957 and getting the tests to pass with all admissible random seeds, LGTM.

Comment thread sklearn/neural_network/tests/test_mlp.py Outdated
ogrisel and others added 2 commits March 27, 2025 18:11
test_mlp_vs_poisson_glm_equivalent
Co-authored-by: Omar Salman <omar.salman2007@gmail.com>
@ogrisel
ogrisel enabled auto-merge (squash) March 28, 2025 09:12
@ogrisel
ogrisel merged commit 3825c9a into scikit-learn:main Mar 31, 2025
@ogrisel
ogrisel deleted the mpl_poisson branch March 31, 2025 15:02
@lorentzenchr

Copy link
Copy Markdown
Member Author

@ogrisel @OmarManzoor Thanks for your reviews.

lucyleeow pushed a commit to lucyleeow/scikit-learn that referenced this pull request Apr 2, 2025
Co-authored-by: Olivier Grisel <olivier.grisel@ensta.org>
Co-authored-by: Omar Salman <omar.salman2007@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants