github yzhao062/pyod v3.5.1

2 hours ago

PyOD v3.5.1

Patch release with bug fixes across LUNAR, DIF, SOS, SUOD, LOF, and the GAAL family, plus the v3.5.0 follow-on work and the NSF funding acknowledgment.

Bug fixes

  • LUNAR (#502): LUNAR.__init__ previously defaulted to a single shared MinMaxScaler() instance, so two LUNAR instances with different feature dimensions invalidated each other's predict path. Default is now scaler=None, materialized to a fresh MinMaxScaler per fit via _resolve_scaler(). User-supplied scalers are deep-copied. False disables scaling entirely. The fitted scaler lives on self.scaler_ so sklearn.base.clone() round-trips. Thanks to @jbbqqf for the fix.
  • DIF (#546): DIF.fit double-normalized: it min-max-scaled X, then called self.decision_function(X) on the already-scaled data, and decision_function re-scales internally. decision_scores_ and decision_function(X_train) now match. Thanks to @jbbqqf.
  • SUOD (#640): module import no longer print-then-crashes when the optional suod package is absent; the actionable ImportError ("Install it with pip install suod") now fires only when SUOD() is constructed. Thanks to @jbbqqf.
  • LOF (#638): class docstring now correctly states novelty=True as the PyOD default. PyOD's BaseDetector contract is fit-then-predict on unseen data, which scikit-learn's LocalOutlierFactor only allows in novelty mode; the code default has been True for years but the docstring claimed False. Regression test pins both the inspect.signature default and the docstring substring. Thanks to @jbbqqf.
  • GAAL family (#660): pyod/models/gaal_base.py print-then-crash optional-torch handling replaced with a guarded import and an actionable ImportError. Follow-up extends the same fix to pyod/models/mo_gaal.py, pyod/models/so_gaal.py, and pyod/models/so_gaal_new.py, so user-visible imports like from pyod.models.mo_gaal import MO_GAAL no longer print-then-crash when torch is missing. All four GAAL files now raise the unified message pointing at pip install pyod[torch] or pip install torch. Thanks to @tuanaiseo for the initial PR.

Performance

  • SOS (#635): _get_perplexity inner-loop reductions use ndarray.sum() directly. Numerical equivalence test asserts bit-exact match against the previous np.sum form. Thanks to @jbbqqf.

Funding

PyOD is now supported in part by the U.S. National Science Foundation under Award No. 2346158, "NSF POSE: Phase II: OpenAD: An Integrated Open-Source Ecosystem for Anomaly Detection." See the Acknowledgments section in the README for the full attribution.

Tests

6 new regression tests added (1 each in test_lof, test_dif, test_sos, test_suod; 2 in test_lunar).

Migration

No breaking API changes. No deprecated APIs removed.

Acknowledgments

External contributors this release: @jbbqqf (5 PRs) and @tuanaiseo (1 PR).

Don't miss a new pyod release

NewReleases is sending notifications on new releases.