metric-learn: scikit-learn-compatible metric learning algorithms
Metric learning algorithms in Python
At a glance
- What is it?
- metric-learn packages ten supervised and weakly-supervised metric learning algorithms behind the scikit-learn estimator API. It is a good fit when you need a learned Mahalanobis distance inside an existing sklearn pipeline, and the wrong tool when you need deep metric learning or a maintained release cadence.
- Who is it for?
- Adopt metric-learn if you already run scikit-learn pipelines and need a learned distance metric that drops into them without a new abstraction layer. Do not adopt it if you need deep metric learning, triplet-loss training on raw images, or a library with a fast release cadence; the gap between v0.6.2 in 2020 and v0.7.0 in 2023 is the evidence.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 180 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem metric-learn solves: a learned distance instead of a default one
Most scikit-learn estimators assume a fixed notion of distance. KNeighborsClassifier defaults to Euclidean distance unless you hand it a metric, and clustering routines such as KMeans inherit the same assumption. When your features are on different scales, correlated, or partly irrelevant, that default distance is the wrong one, and the usual workaround is manual feature engineering or a PCA step that is not optimized for the downstream task. metric-learn targets that gap. It implements algorithms that learn a linear transformation of the feature space from labeled data, so that distances computed after the transformation separate classes better than distances computed before it. The README lists ten algorithms: LMNN, ITML, SDML, LSML, SCML, NCA, LFDA, RCA, MLKR, and MMC. The intended audience is an engineer or researcher who already works inside scikit-learn and wants a learned metric without leaving that ecosystem. The README states the API is compatible with scikit-learn and that this allows all the scikit-learn routines for pipelining and model selection to be used with metric learning algorithms through a unified interface. That compatibility claim is the project's main selling point, and it is what separates it from research code that ships a bespoke training loop.
How the algorithms fit into a scikit-learn pipeline
The mechanism is a transformer. A metric learning estimator is fitted on feature matrix X and labels y, then exposes a learned transformation, typically a matrix that maps the original feature space into a new one. After fitting, you can call transform to project data, or obtain the learned Mahalanobis matrix and use it directly as the metric argument of a distance-based estimator. Because the estimators follow the scikit-learn convention, they can sit inside a Pipeline, be passed to GridSearchCV, and be composed with scalers or selectors in the usual way. The README does not spell out the internal optimization of each algorithm, and this review cannot confirm those details from the supplied material. What the README does confirm is the shape of the interface and the dependency floor: numpy>=1.11.0, scipy>=0.17.0, and scikit-learn>=0.21.3, with Python 3.6 or newer. The algorithms split into supervised and weakly-supervised groups. Supervised methods such as LMNN and NCA use class labels directly. Weakly-supervised methods work from constraints, for example pairs known to be similar or dissimilar, which matters when you have relative judgements rather than clean class assignments. MLKR is listed separately because it targets regression rather than classification, learning a metric for kernel regression. That range is the practical reason to pick this library over writing one algorithm yourself: the interface is uniform across all ten, so switching from LMNN to NCA is a constructor change, not a rewrite.
Installing metric-learn: pip, conda, and the skggm caveat for SDML
Installation is ordinary. From PyPI: pip install metric-learn. Under Anaconda: conda install -c conda-forge metric-learn, and the README points to the conda-forge feedstock for additional options. For the latest source, the README instructs you to download the repository and run python setup.py install. Tests run with pytest test, which requires the pytest package to be installed. The one dependency worth reading carefully is optional. For SDML, the README states that using skggm allows the algorithm to solve problematic cases, and it pins a specific commit rather than a release: pip install 'git+https://github.com/skggm/skggm.git@a0ed406586c4364ea3297a658f415e13b5cbdaf8'. Pinning to a commit hash means you are installing unreleased code from a Git URL, which is a supply-chain and reproducibility decision, not just a convenience. If your environment forbids Git-based installs, SDML is effectively the algorithm you cannot rely on. matplotlib is listed as optional and only for running the examples. Note that the version floors are old by current standards: scikit-learn>=0.21.3 dates from 2019. The floor is a minimum, not a tested maximum, and the README does not state which newer scikit-learn versions are validated, so a modern scikit-learn release is an untested combination from the documentation's point of view.
Where metric-learn stops being the right tool
The library is linear. The algorithms learn a transformation of the feature space, which means the learned distance is a Mahalanobis-style distance in the original coordinates. If your data needs a nonlinear embedding before distances become meaningful, this library does not provide one, and the README describes no neural or deep metric learning component. Projects that need triplet-loss training on images, or a Siamese network, are outside its scope. There is a second limitation in the maintenance record. The releases listed are v0.7.0 in September 2023, and before that v0.6.2 and v0.6.1, both in July 2020. That is a three-year gap between minor releases. A repository can receive commits without cutting releases, and the last push date is recent, but the release history is what a user actually installs, and it is sparse. A third limitation is documentation depth in the README itself. The README defers to the Sphinx documentation site for installation, API, usage, and examples. Everything beyond the algorithm list, dependencies, and install commands lives there, so this review cannot confirm the details of each algorithm's parameters, convergence behavior, or failure modes. If you need to know how LMNN behaves on a small sample, the README will not tell you.
metric-learn compared with learning the metric yourself
The obvious alternative is to implement the metric learning step directly, either by writing the optimization for a single algorithm or by using a general-purpose framework that includes metric learning losses among many others. The difference in approach is not the math, it is the integration surface. A hand-written LMNN gives you control over the optimizer and the regularization, and it can be adapted to a nonstandard constraint format. What it does not give you is a scikit-learn estimator, which means you lose Pipeline composition, GridSearchCV over hyperparameters, and cross-validation helpers unless you write the wrapper yourself. That wrapper is small but it is not free, and it is the part that tends to rot as scikit-learn's internals change. metric-learn takes the opposite trade: it accepts the scikit-learn estimator contract and the constraints that come with it, in exchange for interoperability. The same trade appears in the dependency choice. A general framework may support nonlinear metrics and GPU training, but it will not accept your existing pandas-and-sklearn workflow without a conversion step. If your pipeline is already scikit-learn and your features are tabular, metric-learn is the shorter path. If your features are images or sequences, the shorter path is elsewhere.
Maintenance, licensing, and what to check before adopting
metric-learn is MIT licensed, which is permissive and imposes few obligations beyond retaining the copyright notice and permission text; this is a description of the license identifier, not legal advice, and you should confirm the terms in the repository's LICENSE file for your own use. The project is not archived, and the last push is recent, so the repository is active even though releases are infrequent. The maintenance cost for a user is mostly the dependency floor and the optional skggm pin. Because the code follows the scikit-learn API, upgrades to scikit-learn are the main compatibility risk, and the README's stated floor of >=0.21.3 does not tell you which newer versions have been tested. The upgrade path is also worth weighing: if a future scikit-learn release changes estimator internals in a way that breaks metric-learn, the fix depends on a new release, and the release history suggests those do not come often. The project asks for citation in scientific publications, with a JMLR paper by de Vazelhes et al. from 2020 and a BibTeX entry in the README. That is a norm for academic software, not a licensing condition, but it is a real expectation if you publish results obtained with these algorithms. Before adopting, check three things: that your scikit-learn version satisfies the floor, that the algorithm you need is in the list of ten, and whether SDML without skggm converges on your data.
Editorial conclusion
Adopt metric-learn if you already run scikit-learn pipelines and need a learned distance metric that drops into them without a new abstraction layer. Do not adopt it if you need deep metric learning, triplet-loss training on raw images, or a library with a fast release cadence; the gap between v0.6.2 in 2020 and v0.7.0 in 2023 is the evidence. Before committing, verify that your scikit-learn version satisfies the >=0.21.3 floor, and if you plan to use SDML, test whether the algorithm converges without the skggm optional dependency, because the README states skggm is what lets SDML solve problematic cases.
Community notes