Skip to content

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 30 Jul 20:49
e77c432

A map can now be used as a scikit-learn estimator, and the plain-string deprecation from 0.5.0 is
withdrawn. Nothing breaks and no numerical results change: train is untouched, both option spellings
work, and scikit-learn remains optional.

Added

  • python_som.sklearn.SOMEstimator, a scikit-learn estimator, behind a new sklearn extra:

    pip install "python-som[sklearn]"

    The methods on SOM are enough when you call them yourself. They are not enough when scikit-learn
    does the calling: since 1.7, Pipeline.predict, GridSearchCV and cross_val_score all require
    __sklearn_tags__, which in practice means inheriting BaseEstimator. So the integration lives
    in its own module and scikit-learn stays optional. Importing python_som still pulls in nothing
    but NumPy, which a test asserts in a subprocess.

    input_len is absent from its constructor, since scikit-learn infers the feature count from X.
    Unlike SOM.fit, the estimator's fit starts over rather than continuing, because GridSearchCV
    fits one cloned estimator fold after fold, and carrying weights across folds would leak one fold
    into the next.

    All five integration points have tests that call the real library rather than asserting about it:
    clone, Pipeline.fit, Pipeline.predict, GridSearchCV, cross_val_score.

  • An estimator interface on SOM: fit, transform, predict, fit_transform, score,
    get_params and set_params, modelled on KMeans. train remains the primary way to train and
    is unchanged, so nothing existing is affected.

    predict returns a flat node index rather than (row, column), because a 1-D label array is
    what scorers, confusion_matrix and cross_val_score assume;
    np.unravel_index(som.predict(X), som.get_shape()) recovers the grid position, and winner()
    still returns coordinates. score is the negated quantization error, since GridSearchCV
    maximises and without the sign a search would select the worst map.

    Fitted attributes follow the convention: weights_ for cluster_centers_,
    quantization_error_ for inertia_, plus n_features_in_.

    Two deliberate differences from scikit-learn, both documented: fit continues rather than
    resetting, because a SOM's models are its state; and the models exist before training, since
    initialization is a separate step.

    set_params changes the rates, radii, decays and distance function. It refuses to change the grid
    shape or input_len, which would leave a map whose models no longer match its own description.
    It is what set_learning_rate and set_neighborhood_radius become; both still work.

    These names alone are not enough for Pipeline.predict or GridSearchCV, which since
    scikit-learn 1.7 require __sklearn_tags__. A separate python_som.sklearn adapter follows.

Changed

  • The plain-string deprecation introduced in 0.5.0 is withdrawn. Strings are permanently
    supported, the DeprecationWarning is gone, and 1.0.0 will not remove them. If you migrated to
    the enums while 0.5.0 was current, nothing you wrote breaks: the enums are staying too.

    0.5.0 was wrong, and the reason is worth stating rather than quietly reverting. Every comparable
    library passes options as plain strings and none export enums: scikit-learn
    (KMeans(init="k-means++")), numpy (np.pad(mode="constant")), scipy
    (linkage(method="single")), and both SOM libraries, minisom and sompy. Removing the string form
    would have made this the only library in its ecosystem to reject mode="batch".

    The benefit originally claimed for enums was that a type checker catches typos. That is already
    delivered by the Literal unions added in 0.4.0, with strings still working: mode="bacth" is a
    type error while mode="batch" is not. The deprecation bought nothing that was not already had.

    The decision was made without checking what comparable libraries do. That check is now part of
    planning any future API change.