|
| 1 | +# Clustering models |
| 2 | + |
| 3 | +The `pyvisim.clustering` module holds the small models the encoders use to build |
| 4 | +their visual vocabulary and to reduce dimensionality. Each one owns an underlying |
| 5 | +scikit-learn estimator and exposes just the attributes the encoders need through |
| 6 | +typed getters, so the encoders never touch scikit-learn's `*_` fitted attributes |
| 7 | +directly. |
| 8 | + |
| 9 | +| Object | File | Backed by | Used by | |
| 10 | +|--------|------|-----------|---------| |
| 11 | +| `KMeans` | [`kmeans.py`](../../pyvisim/clustering/kmeans.py) | `sklearn.cluster.KMeans` | `VLADEncoder` | |
| 12 | +| `GaussianMixtureModel` | [`gmm.py`](../../pyvisim/clustering/gmm.py) | `sklearn.mixture.GaussianMixture` | `FisherVectorEncoder` | |
| 13 | +| `PCA` | [`pca.py`](../../pyvisim/clustering/pca.py) | `sklearn.decomposition.PCA` | both encoders (optional) | |
| 14 | + |
| 15 | +`KMeans` and `GaussianMixtureModel` are clustering models and share |
| 16 | +[`ClusteringModelBase`](../../pyvisim/clustering/_base_clustering.py). `PCA` is not a |
| 17 | +clustering model, so it sits directly on the shared `_SklearnModelBase` instead. |
| 18 | + |
| 19 | +## How they work |
| 20 | + |
| 21 | +You create a model unfitted, passing the scikit-learn constructor parameters straight |
| 22 | +through: |
| 23 | + |
| 24 | +```python |
| 25 | +from pyvisim.clustering import KMeans, GaussianMixtureModel, PCA |
| 26 | + |
| 27 | +kmeans = KMeans(n_clusters=256, random_state=0) |
| 28 | +gmm = GaussianMixtureModel(n_components=256, random_state=0) |
| 29 | +pca = PCA(n_components=64, whiten=True) |
| 30 | +``` |
| 31 | + |
| 32 | +`n_clusters` / `n_components` are explicit; everything else is forwarded verbatim to |
| 33 | +the wrapped estimator. Call `fit(features)` to train, and check `is_fitted` at any |
| 34 | +time. The fitted-only getters (`cluster_centers`, `weights`, `means`, `covariances`, |
| 35 | +`n_features_in`, ...) raise `NotFittedError` if you read them before fitting, so you |
| 36 | +get a clear error instead of an `AttributeError` from scikit-learn. |
| 37 | + |
| 38 | +In normal use you don't build these yourself: the encoders create the matching model |
| 39 | +for you from the parameters passed to their constructors (see |
| 40 | +[encoders/base_encoder.md](../encoders/base_encoder.md)). |
| 41 | + |
| 42 | +## What each model exposes |
| 43 | + |
| 44 | +**`KMeans`** |
| 45 | +- `n_clusters` — number of clusters. |
| 46 | +- `cluster_centers` — `(n_clusters, n_features)` centroid coordinates. |
| 47 | +- `predict(features)` — nearest cluster index per row. This is the hard assignment |
| 48 | + VLAD uses. |
| 49 | + |
| 50 | +**`GaussianMixtureModel`** |
| 51 | +- `n_clusters` — number of mixture components (the `ClusteringModelBase` name for it). |
| 52 | +- `weights`, `means`, `covariances` — the GMM parameters the Fisher Vector gradients |
| 53 | + are computed from. |
| 54 | +- `predict_proba(features)` — posterior probability per component, i.e. the soft |
| 55 | + assignment Fisher Vectors use. |
| 56 | +- Diagonal covariance only. Asking for any other `covariance_type` raises `ValueError` |
| 57 | + up front, because the Fisher Vector math assumes diagonal covariances (and training |
| 58 | + is much faster that way). |
| 59 | + |
| 60 | +**`PCA`** |
| 61 | +- `n_components` — number of components of the fitted PCA. |
| 62 | +- `transform(features)` — projects features onto the principal components. |
| 63 | + |
| 64 | +## Adopting a pretrained scikit-learn estimator |
| 65 | + |
| 66 | +There's an internal `_from_sklearn` classmethod used to wrap an already-fitted |
| 67 | +estimator loaded from a legacy `KMeansWeights` / `GMMWeights` pickle. It type-checks |
| 68 | +the estimator (and, for the GMM, re-validates the diagonal covariance) before adopting |
| 69 | +it. You won't call this directly; it backs the deprecated weight-loading path described |
| 70 | +in [encoders/weights.md](../encoders/weights.md). |
0 commit comments