Skip to content

[0.9.0] - 2026-08-23

Pre-release
Pre-release

Choose a tag to compare

@MechaCritter MechaCritter released this 07 Sep 15:42
· 99 commits to main since this release

Fixed

  • PSNR.similarity_score accepts a channel-less grayscale image again: a 2-D
    array passed with the default dims="HWC" raised instead of being read as
    single-channel, unlike SSIM and the rest of the library.
  • make test-types no longer prints a DeprecationWarning: the
    numpy.typing.mypy_plugin entry is removed from the mypy configuration.
  • The development interpreter is pinned to Python 3.10 (.python-version), the
    project's minimum supported version and the one every CI job already uses.
  • The ruff check CI step no longer fails on import sorting (I001) in
    tests/neural_networks/test_oxford_flowers_quick.py and
    test_oxford_flowers_slow.py.

Added

  • load_from_disk now forwards keyword arguments to from_dict, so an
    embedder can be handed the objects its file cannot hold. The Siamese
    networks use it for their transform:
    ContrastiveSiameseNetwork.load_from_disk(path, transform=transform)
    restores the exact embeddings of a network built with a custom one.
  • The embedders of pyvisim.neural_networks (ClipEmbedder,
    ContrastiveSiameseNetwork, BCESiameseNetwork) are now serialisable to a
    safetensors .embedder file via save_to_disk/load_from_disk, weights
    included; a reloaded embedder produces identical embeddings without downloading
    any pretrained weights.
  • NeuralImageEmbedder (in pyvisim.neural_networks): the shared base for the
    neural embedders, both a SerializableImageEmbedder and a torch.nn.Module.
    SiameseNetworkBase now derives from it, so the Siamese networks and the
    classic embedders expose the same embed/similarity_score surface.
  • Clustering models can now be built from a fitted scikit-learn estimator:
    KMeans.from_sklearn, DiagCovarGaussianMixture.from_sklearn and
    PCA.from_sklearn, plus load_clustering_model_from_sklearn on VLADEncoder
    and FisherVectorEncoder to drop one straight into an encoder. Handy for reusing
    a vocabulary you already trained with scikit-learn.

Changed

  • The Siamese networks now store the repr of their transform in the .embedder
    file and warn on load_from_disk when the rebuilt network's transform differs
    from it, instead of warning on every save of a custom transform.
  • tqdm and requests are no longer runtime dependencies of the core
    package; they moved into the nn extra. Only pyvisim.datasets uses them,
    and that module already requires torch from the same extra.
  • CI restores the Oxford Flowers dataset and the pretrained backbone weights from
    the GitHub Actions cache instead of re-downloading them on every run; the new
    Warm asset cache workflow keeps that cache populated on main.
  • The similarity_func registry in pyvisim._utils now maps the metric names
    straight onto pyvisim.distance.
  • ℹ️ Dropped scikit-learn as a runtime dependency.
  • Added PSNR (under pyvisim.pixelwise) and SSIM/MSSSIM (under
    pyvisim.structural) metrics as well as their benchmark scripts against
    existing implementations under docs/pixelwise/benchmarks and
    docs/structural/benchmarks.
  • BCESiameseNetwork (in pyvisim.neural_networks): the pair-classifying
    Siamese variant of Koch, Zemel & Salakhutdinov (2015).
  • The Siamese networks are split along a shared abstract base,
    SiameseNetworkBase.
  • Removed the Siamese Network's train scripts. This is now demonstrated
    in a notebook in the "examples" repository.

Breaking

  • ⚠️ VLADEmbedder, FisherVectorEmbedder and Pipeline moved from
    pyvisim.encoders to pyvisim.classic.

  • ⚠️ The bundled pretrained VLAD and Fisher Vector encoders are removed to make the binary smaller, together
    with from_pretrained, PretrainedVLAD/PretrainedFisher, the deprecated
    weights= argument and KMeansWeights/GMMWeights. Train a vocabulary with
    learn() and persist it with save_to_disk/load_from_disk instead.

  • ⚠️ "Encoder" is now "embedder" throughout: ImageEncoderBase -> ImageEmbedderBase,
    VLADEncoder -> VLADEmbedder, FisherVectorEncoder -> FisherVectorEmbedder,
    the Encoder protocol -> Embedder, encode() -> embed() and store.encoder
    -> store.embedder.

  • ⚠️ Saved models use the .embedder suffix and an embedder_class state key, so
    existing .encoder files no longer load. Re-save them with save_to_disk.

  • ⚠️ SiameseNeuralNetwork is renamed to ContrastiveSiameseNetwork
    (pyvisim.neural_networks.siamese.siamese_neural_network is gone; the base
    class now lives in pyvisim.neural_networks.siamese._base_siamese):

    from pyvisim.neural_networks import ContrastiveSiameseNetwork
    
    model = ContrastiveSiameseNetwork(backbone="resnet18", embedding_dim=128)
    score = model.similarity_score(image1, image2)  # cosine similarity in [-1, 1]
  • ⚠️ The clustering models (KMeans, DiagCovarGaussianMixture, PCA,
    ClusteringModelBase) are now internal to the encoders package and moved from
    pyvisim.clustering to pyvisim.classic._clustering.

  • ⚠️ Encoder clustering parameters changed: pass rng instead of random_state
    inside kmeans_params / gmm_params / pca_params (see
    vlad.md and
    fisher_vector.md for every accepted key).