Give informed callers a narrow opt-out from the PLS uncentred-block warning - #575
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H7cg6VtfMGvqwCtgZBKwU2
PLS(scale=False) fits no intercept, so an un-centred block displaces every
prediction; fit() has warned about this since 1.77. The warning is correct and
stays on. What was missing was a way to permit one deliberate un-centred fit: a
caller proving that some other centring check fires had only
simplefilter("ignore", SpecificationWarning), which also hides clamped component
counts and NIPALS non-convergence, and under filterwarnings = error the warning
arrived as an exception indistinguishable from a failed fit.
Two escapes, narrowest first:
* PLS(..., warn_on_uncentred=False) skips the check for that model only. Stored
verbatim in __init__ and read in fit(), so it survives clone() and reaches a
fit that a Pipeline or grid search constructs. No effect under scale=True,
where the model centres both blocks itself.
* UncentredDataWarning, a SpecificationWarning subclass, is now the category the
warning is raised under, so "ignore::...UncentredDataWarning" leaves every
other SpecificationWarning in force. Subclassing keeps existing filters and
pytest.warns(SpecificationWarning) assertions matching.
Both warning classes are now importable from process_improve.multivariate, so
the filter idiom does not reach into a private module. The message names the
flag, so a caller who hits this by surprise finds the remedy in the text.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7cg6VtfMGvqwCtgZBKwU2
- docs/user_guide/pls.rst: a "Centring and the Missing Intercept" section explaining why scale=False fits no intercept, and a table of the three opt-outs ordered narrowest first, so a reader reaches for the flag before the category filter and the category filter before silencing SpecificationWarning wholesale. - docs/api/multivariate.rst: a Warnings section, so both classes are documented at the path a filterwarnings entry should name. - docs/development/error_handling.rst: when to give a warning its own subclass, since the same question will come up the next time a diagnostic has a legitimate opt-out. - Version 1.93.1 -> 1.94.0 (new public class and constructor parameter), with CITATION.cff and CHANGELOG.md in step. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H7cg6VtfMGvqwCtgZBKwU2
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PLS(scale=False)fits no intercept, so an un-centred block displaces every prediction, andfithas warned about that since 1.77. The warning is correct and stays on by default. What was missing was a way to permit one deliberate un-centred fit. A caller proving that some other centring check fires had onlysimplefilter("ignore", SpecificationWarning), which also hides clamped component counts and NIPALS non-convergence, and under afilterwarnings = errorpolicy the warning arrived as an exception indistinguishable from a failed fit.Two escapes, narrowest first:
PLS(..., warn_on_uncentred=False)skips the check for that model alone. Stored verbatim in__init__and read infit(), so it survivesclone()and reaches a fit that aPipelineor a grid search constructs. No effect underscale=True, where the model centres both blocks itself. It changes only whether the warning is emitted, never the numbers.UncentredDataWarning, a newSpecificationWarningsubclass, is now the category the warning is raised under, soignore::process_improve.multivariate.UncentredDataWarningleaves every other specification diagnostic in force. For when the model is built by code you do not own.Both warning classes are now importable from
process_improve.multivariate, so afilterwarningsentry never has to name the private_commonmodule. The warning text itself names the flag, so a caller who hits this by surprise finds the remedy without searching.Backwards compatible:
UncentredDataWarningsubclassesSpecificationWarning, so existing filters,except SpecificationWarninghandlers andpytest.warns(SpecificationWarning)assertions all keep matching. Only an exact-identity test (record[0].category is SpecificationWarning) changes behaviour, which is noted in the changelog.Docs: a "Centring and the Missing Intercept" section in the PLS user guide (with the three opt-outs ordered narrowest first, so a reader reaches for the flag before the category filter and the category filter before blanket suppression); a Warnings section in the multivariate API reference; and a note in
docs/development/error_handling.rston when a diagnostic earns its own subclass, since the question will recur.Test plan
tests/test_multivariate_centring_traps.py::TestUncentredWarningOptOut, covering: the flag silencing the warning undersimplefilter("error"); the flag not silencing a second, unrelatedSpecificationWarningraised by the samefitcall; the category filter as the wider opt-out; identical predictions with and without the flag; no-op underscale=True;get_params()/clone()round-trip; the default staying on; and the message naming the flag.uv run pytestfull suite: 3369 passed, 41 skipped (every skip is a dataset download blocked by this sandbox's proxy, unrelated to the change).uv run python -O -m pytest tests/test_multivariate_centring_traps.py tests/test_multivariate.py: 252 passed, 2 skipped.uv run ruff check .anduv run ruff format --check .: both clean.uv run mypy src/process_improve: no issues in 163 source files.-W --keep-going) of the touched pages: no warnings from any edited file. Notebook directories were excluded locally becausepandocis not installed in this sandbox; the only remaining warnings are intersphinx inventories the proxy blocks.Checklist
pyproject.toml(MINOR: 1.93.1 → 1.94.0, new public class and constructor parameter), withCITATION.cffin stepruff check .passesCHANGELOG.mdupdated🤖 Generated with Claude Code
https://claude.ai/code/session_01H7cg6VtfMGvqwCtgZBKwU2