Document model inversion, and pin the constants the book quotes - #478
Merged
Conversation
The inversion and O-PLS APIs landed with docstrings but no narrative page, so the reasoning behind them lived only in the book. The new user-guide page covers PLS.invert, walking the null space, why inversion can need more components than prediction does, the equivalence with the O-PLS orthogonal space, how well the null-space direction is actually determined, and why a specification region is not the box of per-input ranges that summarises it. The tests close a real gap. Most numbers in the book's worked example are printed by code blocks a reader can run, so a change here would show up there. A handful are quoted in prose without appearing in any output: the T-squared and SPE limits, the score norms either side of the direct-inversion solution, the step at which T-squared is least, the angle between each weight and its own loading before and after the orthogonal variation is removed, the agreement between the PLS and O-PLS regression coefficients, and the split of the sum of squares in X. Nothing would have caught a silent change to those. The tolerances match the precision the text quotes, so a failure means a sentence needs rewriting rather than a digit having moved far downstream. Version is a patch bump: documentation and tests only, no behaviour change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DsTypY4FcRbrXRxorb9raz
The test skipped on `mcp`, but newer releases ship a top-level `mcp` package without `mcp.server.fastmcp`. With every extra installed, as CI does, the coarse guard did not fire and the test failed on the import instead of skipping. The sibling test in test_mcp_server.py already guards on the submodule; this matches it. Not caused by this branch: the test has been unchanged since #389 and fails the same way on main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DsTypY4FcRbrXRxorb9raz
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.
Follow-up to #470, which added
PLS.invert()andOPLS. Companion to thepid-book PR kgdunn/pid-book#259, which writes the same material up as a chapter.
Documentation
PLS.invert()andOPLSlanded with docstrings but no narrative page, so thereasoning behind them lived only in the book.
docs/user_guide/model_inversion.rstcovers:
null_space_coordinates, and what risingHotelling's T-squared along that walk means;
describe the X-space well enough to map a score back into it;
is the same linear space as the PLS null space;
cheddar-cheese example is not well at all;
that summarises it.
It is linked from the hidden toctree in
multivariate.rst, besidepca,pls,tplsandmultiblock.Tests
These close a real gap rather than adding coverage for its own sake.
Most numbers in the book's worked example are printed by code blocks a reader
can run, so a change in this library would be visible there. A handful are
quoted in prose without appearing in any output, and nothing would have caught
a silent change to them:
The tolerances match the precision the text quotes, so a failure means a
sentence in the book needs rewriting, not that a digit moved far downstream.
Two of the tests check identities rather than only values: that
||tau_DI + s g||^2 == ||tau_DI||^2 + s^2for the steps taken, and thatw'p == 1, which is what makesp - wa plain subtraction.The last test pins the specification-region result: of the eight corners of
the box of three ranges, exactly two predict an acceptable taste, both of those
are beyond the T-squared limit, and therefore none is an acceptable lot.
Verification
ruff checkandmypy src/process_improveclean. The 26 tests in this file andtest_multivariate_opls.pypass.The wider suite has pre-existing failures in this sandbox from missing optional
extras (
seaborn,ridgeplot, and the DOE solver); they reproduce identicallyon
mainwith this branch stashed, and CI installs--all-extras.Version is a patch bump, 1.62.0 to 1.62.1: documentation and tests only, no
behaviour change.
CITATION.cffandCHANGELOG.mdupdated in step.Generated by Claude Code