diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a2049825..00000000 --- a/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.pyc -build/ -dist/ -*.egg-info diff --git a/doc/_static/.gitignore b/.nojekyll similarity index 100% rename from doc/_static/.gitignore rename to .nojekyll diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c90a56ed..00000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: python -sudo: false -python: - - "2.7" -install: - - if [[ "$TRAVIS_PYTHON_VERSION" == 2.* ]]; then - wget http://repo.continuum.io/miniconda/Miniconda-3.4.2-Linux-x86_64.sh -O miniconda.sh; - else - wget http://repo.continuum.io/miniconda/Miniconda3-3.4.2-Linux-x86_64.sh -O miniconda.sh; - fi - - bash miniconda.sh -b -p $HOME/miniconda - - export PATH="$HOME/miniconda/bin:$PATH" - - hash -r - - conda config --set always_yes yes --set changeps1 no - - conda update -q conda - # Useful for debugging any issues with conda - - conda info -a - - - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION scikit-learn - - source activate test-environment - - python setup.py install -script: python setup.py test diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 0d864db6..00000000 --- a/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015 CJ Carey and Yuan Tang - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/README.rst b/README.rst deleted file mode 100644 index f71cc873..00000000 --- a/README.rst +++ /dev/null @@ -1,72 +0,0 @@ -|Travis-CI Build Status| |License| |PyPI version| - -metric-learn -============= - -Metric Learning algorithms in Python. - -**Algorithms** - -- Large Margin Nearest Neighbor (LMNN) -- Information Theoretic Metric Learning (ITML) -- Sparse Determinant Metric Learning (SDML) -- Least Squares Metric Learning (LSML) -- Neighborhood Components Analysis (NCA) -- Local Fisher Discriminant Analysis (LFDA) -- Relative Components Analysis (RCA) - -**Dependencies** - -- Python 2.6+ -- numpy, scipy, scikit-learn -- (for running the examples only: matplotlib) - -**Installation/Setup** - -Run ``pip install metric-learn`` to download and install from PyPI. - -Run ``python setup.py install`` for default installation. - -Run ``python setup.py test`` to run all tests. - -**Usage** - -For full usage examples, see the ``test`` and ``examples`` directories. - -Each metric is a subclass of ``BaseMetricLearner``, which provides -default implementations for the methods ``metric``, ``transformer``, and -``transform``. Subclasses must provide an implementation for either -``metric`` or ``transformer``. - -For an instance of a metric learner named ``foo`` learning from a set of -``d``-dimensional points, ``foo.metric()`` returns a ``d`` by ``d`` -matrix ``M`` such that a distance between vectors ``x`` and ``y`` is -expressed ``(x-y).dot(M).dot(x-y)``. - -In the same scenario, ``foo.transformer()`` returns a ``d`` by ``d`` -matrix ``L`` such that a vector ``x`` can be represented in the learned -space as the vector ``L.dot(x)``. - -For convenience, the function ``foo.transform(X)`` is provided for -converting a matrix of points (``X``) into the learned space, in which -standard Euclidean distance can be used. - -**Notes** - -If a recent version of the Shogun Python modular (``modshogun``) library -is available, the LMNN implementation will use the fast C++ version from -there. The two implementations differ slightly, and the C++ version is -more complete. - -**TODO** - -- implement the rest of the methods on `this site`_ - -.. _this site: http://www.cs.cmu.edu/~liuy/distlearn.htm - -.. |Travis-CI Build Status| image:: https://api.travis-ci.org/all-umass/metric-learn.svg?branch=master - :target: https://travis-ci.org/all-umass/metric-learn -.. |License| image:: http://img.shields.io/:license-mit-blue.svg?style=flat - :target: http://badges.mit-license.org -.. |PyPI version| image:: https://badge.fury.io/py/metric-learn.svg - :target: http://badge.fury.io/py/metric-learn \ No newline at end of file diff --git a/_downloads/07fcc19ba03226cd3d83d4e40ec44385/auto_examples_python.zip b/_downloads/07fcc19ba03226cd3d83d4e40ec44385/auto_examples_python.zip new file mode 100644 index 00000000..f5712a9c Binary files /dev/null and b/_downloads/07fcc19ba03226cd3d83d4e40ec44385/auto_examples_python.zip differ diff --git a/_downloads/4f011433714ef22e0c66be75bbfd08e3/plot_sandwich.ipynb b/_downloads/4f011433714ef22e0c66be75bbfd08e3/plot_sandwich.ipynb new file mode 100644 index 00000000..e317ca93 --- /dev/null +++ b/_downloads/4f011433714ef22e0c66be75bbfd08e3/plot_sandwich.ipynb @@ -0,0 +1,50 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Sandwich demo\n\nSandwich demo based on code from http://nbviewer.ipython.org/6576096\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
In order to show the charts of the examples you need a graphical\n ``matplotlib`` backend installed. For intance, use ``pip install pyqt5``\n to get Qt graphical interface or use your favorite one.
In order to show the charts of the examples you need a graphical\n ``matplotlib`` backend installed. For intance, use ``pip install pyqt5``\n to get Qt graphical interface or use your favorite one.
+"""
+Base module.
+"""
+
+from sklearn.base import BaseEstimator, ClassifierMixin
+from sklearn.utils.extmath import stable_cumsum
+from sklearn.utils.validation import _is_arraylike, check_is_fitted
+from sklearn.metrics import roc_auc_score, roc_curve, precision_recall_curve
+import numpy as np
+from abc import ABCMeta, abstractmethod
+from ._util import ArrayIndexer, check_input, validate_vector
+import warnings
+
+
+
+[docs]
+class BaseMetricLearner(BaseEstimator, metaclass=ABCMeta):
+ """
+ Base class for all metric-learners.
+
+ Parameters
+ ----------
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be gotten like this: X[indices].
+ """
+
+
+
+
+
+[docs]
+ @abstractmethod
+ def score_pairs(self, pairs):
+ """
+ Returns the score between pairs
+ (can be a similarity, or a distance/metric depending on the algorithm)
+
+ .. deprecated:: 0.7.0
+ Refer to `pair_distance` and `pair_score`.
+
+ .. warning::
+ This method will be removed in 0.8.0. Please refer to `pair_distance`
+ or `pair_score`. This change will occur in order to add learners
+ that don't necessarily learn a Mahalanobis distance.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs to score, with each row corresponding to two points,
+ for 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ Returns
+ -------
+ scores : `numpy.ndarray` of shape=(n_pairs,)
+ The score of every pair.
+
+ See Also
+ --------
+ get_metric : a method that returns a function to compute the metric between
+ two points. The difference between `score_pairs` is that it works on two
+ 1D arrays and cannot use a preprocessor. Besides, the returned function
+ is independent of the metric learner and hence is not modified if the
+ metric learner is.
+ """
+
+
+
+[docs]
+ @abstractmethod
+ def pair_score(self, pairs):
+ """
+ .. versionadded:: 0.7.0 Compute the similarity score between pairs
+
+ Returns the similarity score between pairs of points (the larger the score,
+ the more similar the pair). For metric learners that learn a distance,
+ the score is simply the opposite of the distance between pairs. All
+ learners have access to this method.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs to score, with each row corresponding to two points,
+ for 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ Returns
+ -------
+ scores : `numpy.ndarray` of shape=(n_pairs,)
+ The score of every pair.
+
+ See Also
+ --------
+ get_metric : a method that returns a function to compute the metric between
+ two points. The difference with `pair_score` is that it works on two
+ 1D arrays and cannot use a preprocessor. Besides, the returned function
+ is independent of the metric learner and hence is not modified if the
+ metric learner is.
+ """
+
+
+
+[docs]
+ @abstractmethod
+ def pair_distance(self, pairs):
+ """
+ .. versionadded:: 0.7.0 Compute the distance between pairs
+
+ Returns the (pseudo) distance between pairs, when available. For metric
+ learners that do not learn a (pseudo) distance, an error is thrown
+ instead.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs for which to compute the distance, with each
+ row corresponding to two points, for 2D array of indices of pairs
+ if the metric learner uses a preprocessor.
+
+ Returns
+ -------
+ scores : `numpy.ndarray` of shape=(n_pairs,)
+ The distance between every pair.
+
+ See Also
+ --------
+ get_metric : a method that returns a function to compute the metric between
+ two points. The difference with `pair_distance` is that it works on two
+ 1D arrays and cannot use a preprocessor. Besides, the returned function
+ is independent of the metric learner and hence is not modified if the
+ metric learner is.
+ """
+
+
+ def _check_preprocessor(self):
+ """Initializes the preprocessor"""
+ if _is_arraylike(self.preprocessor):
+ self.preprocessor_ = ArrayIndexer(self.preprocessor)
+ elif callable(self.preprocessor) or self.preprocessor is None:
+ self.preprocessor_ = self.preprocessor
+ else:
+ raise ValueError("Invalid type for the preprocessor: {}. You should "
+ "provide either None, an array-like object, "
+ "or a callable.".format(type(self.preprocessor)))
+
+ def _prepare_inputs(self, X, y=None, type_of_inputs='classic',
+ **kwargs):
+ """Initializes the preprocessor and processes inputs. See `check_input`
+ for more details.
+
+ Parameters
+ ----------
+ X : array-like
+ The input data array to check.
+
+ y : array-like
+ The input labels array to check.
+
+ type_of_inputs : `str` {'classic', 'tuples'}
+ The type of inputs to check. If 'classic', the input should be
+ a 2D array-like of points or a 1D array like of indicators of points. If
+ 'tuples', the input should be a 3D array-like of tuples or a 2D
+ array-like of indicators of tuples.
+
+ **kwargs : dict
+ Arguments to pass to check_input.
+
+ Returns
+ -------
+ X : `numpy.ndarray`
+ The checked input data array.
+
+ y : `numpy.ndarray` (optional)
+ The checked input labels array.
+ """
+ self._check_preprocessor()
+
+ check_is_fitted(self, ['preprocessor_'])
+ outs = check_input(X, y,
+ type_of_inputs=type_of_inputs,
+ preprocessor=self.preprocessor_,
+ estimator=self,
+ tuple_size=getattr(self, '_tuple_size', None),
+ **kwargs)
+ # Conform to SLEP010
+ if not hasattr(self, 'n_features_in_'):
+ self.n_features_in_ = (outs if y is None else outs[0]).shape[1]
+ return outs
+
+
+[docs]
+ @abstractmethod
+ def get_metric(self):
+ """Returns a function that takes as input two 1D arrays and outputs
+ the value of the learned metric on these two points. Depending on the
+ algorithm, it can return a distance or a similarity function between
+ pairs.
+
+ This function will be independent from the metric learner that learned it
+ (it will not be modified if the initial metric learner is modified),
+ and it can be directly plugged into the `metric` argument of
+ scikit-learn's estimators.
+
+ Returns
+ -------
+ metric_fun : function
+ The function described above.
+
+
+ Examples
+ --------
+ .. doctest::
+
+ >>> from metric_learn import NCA
+ >>> from sklearn.datasets import make_classification
+ >>> from sklearn.neighbors import KNeighborsClassifier
+ >>> nca = NCA()
+ >>> X, y = make_classification()
+ >>> nca.fit(X, y)
+ >>> knn = KNeighborsClassifier(metric=nca.get_metric())
+ >>> knn.fit(X, y) # doctest: +NORMALIZE_WHITESPACE
+ KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
+ See Also
+ --------
+ pair_distance : a method that returns the distance between several
+ pairs of points. Unlike `get_metric`, this is a method of the metric
+ learner and therefore can change if the metric learner changes. Besides,
+ it can use the metric learner's preprocessor, and works on concatenated
+ arrays.
+
+ pair_score : a method that returns the similarity score between
+ several pairs of points. Unlike `get_metric`, this is a method of the
+ metric learner and therefore can change if the metric learner changes.
+ Besides, it can use the metric learner's preprocessor, and works on
+ concatenated arrays.
+ """
+
+
+
+
+
+[docs]
+class MetricTransformer(metaclass=ABCMeta):
+ """
+ Base class for all learners that can transform data into a new space
+ with the metric learned.
+ """
+
+[docs]
+ @abstractmethod
+ def transform(self, X):
+ """Applies the metric transformation.
+
+ Parameters
+ ----------
+ X : (n x d) matrix
+ Data to transform.
+
+ Returns
+ -------
+ transformed : (n x d) matrix
+ Input data transformed to the metric space by :math:`XL^{\\top}`
+ """
+
+
+
+
+
+[docs]
+class MahalanobisMixin(BaseMetricLearner, MetricTransformer,
+ metaclass=ABCMeta):
+ r"""Mahalanobis metric learning algorithms.
+
+ Algorithm that learns a Mahalanobis (pseudo) distance :math:`d_M(x, x')`,
+ defined between two column vectors :math:`x` and :math:`x'` by: :math:`d_M(x,
+ x') = \sqrt{(x-x')^T M (x-x')}`, where :math:`M` is a learned symmetric
+ positive semi-definite (PSD) matrix. The metric between points can then be
+ expressed as the euclidean distance between points embedded in a new space
+ through a linear transformation. Indeed, the above matrix can be decomposed
+ into the product of two transpose matrices (through SVD or Cholesky
+ decomposition): :math:`d_M(x, x')^2 = (x-x')^T M (x-x') = (x-x')^T L^T L
+ (x-x') = (L x - L x')^T (L x- L x')`
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_components, n_features)
+ The learned linear transformation ``L``.
+ """
+
+
+[docs]
+ def score_pairs(self, pairs):
+ r"""
+ Returns the learned Mahalanobis distance between pairs.
+
+ This distance is defined as: :math:`d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}`
+ where ``M`` is the learned Mahalanobis matrix, for every pair of points
+ ``x`` and ``x'``. This corresponds to the euclidean distance between
+ embeddings of the points in a new space, obtained through a linear
+ transformation. Indeed, we have also: :math:`d_M(x, x') = \\sqrt{(x_e -
+ x_e')^T (x_e- x_e')}`, with :math:`x_e = L x` (See
+ :class:`MahalanobisMixin`).
+
+ .. deprecated:: 0.7.0
+ Please use `pair_distance` instead.
+
+ .. warning::
+ This method will be removed in 0.8.0. Please refer to `pair_distance`
+ or `pair_score`. This change will occur in order to add learners
+ that don't necessarily learn a Mahalanobis distance.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs to score, with each row corresponding to two points,
+ for 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ Returns
+ -------
+ scores : `numpy.ndarray` of shape=(n_pairs,)
+ The learned Mahalanobis distance for every pair.
+
+ See Also
+ --------
+ get_metric : a method that returns a function to compute the metric between
+ two points. The difference with `score_pairs` is that it works on two
+ 1D arrays and cannot use a preprocessor. Besides, the returned function
+ is independent of the metric learner and hence is not modified if the
+ metric learner is.
+
+ :ref:`mahalanobis_distances` : The section of the project documentation
+ that describes Mahalanobis Distances.
+ """
+ dpr_msg = ("score_pairs will be deprecated in release 0.7.0. "
+ "Use pair_score to compute similarity scores, or "
+ "pair_distances to compute distances.")
+ warnings.warn(dpr_msg, category=FutureWarning)
+ return self.pair_distance(pairs)
+
+
+
+[docs]
+ def pair_score(self, pairs):
+ """
+ Returns the opposite of the learned Mahalanobis distance between pairs.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs to score, with each row corresponding to two points,
+ for 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ Returns
+ -------
+ scores : `numpy.ndarray` of shape=(n_pairs,)
+ The opposite of the learned Mahalanobis distance for every pair.
+
+ See Also
+ --------
+ get_metric : a method that returns a function to compute the metric between
+ two points. The difference with `pair_score` is that it works on two
+ 1D arrays and cannot use a preprocessor. Besides, the returned function
+ is independent of the metric learner and hence is not modified if the
+ metric learner is.
+
+ :ref:`mahalanobis_distances` : The section of the project documentation
+ that describes Mahalanobis Distances.
+ """
+ return -1 * self.pair_distance(pairs)
+
+
+
+[docs]
+ def pair_distance(self, pairs):
+ """
+ Returns the learned Mahalanobis distance between pairs.
+
+ This distance is defined as: :math:`d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}`
+ where ``M`` is the learned Mahalanobis matrix, for every pair of points
+ ``x`` and ``x'``. This corresponds to the euclidean distance between
+ embeddings of the points in a new space, obtained through a linear
+ transformation. Indeed, we have also: :math:`d_M(x, x') = \\sqrt{(x_e -
+ x_e')^T (x_e- x_e')}`, with :math:`x_e = L x` (See
+ :class:`MahalanobisMixin`).
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs to score, with each row corresponding to two points,
+ for 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ Returns
+ -------
+ scores : `numpy.ndarray` of shape=(n_pairs,)
+ The learned Mahalanobis distance for every pair.
+
+ See Also
+ --------
+ get_metric : a method that returns a function to compute the metric between
+ two points. The difference with `pair_distance` is that it works on two
+ 1D arrays and cannot use a preprocessor. Besides, the returned function
+ is independent of the metric learner and hence is not modified if the
+ metric learner is.
+
+ :ref:`mahalanobis_distances` : The section of the project documentation
+ that describes Mahalanobis Distances.
+ """
+ check_is_fitted(self, ['preprocessor_'])
+ pairs = check_input(pairs, type_of_inputs='tuples',
+ preprocessor=self.preprocessor_,
+ estimator=self, tuple_size=2)
+ pairwise_diffs = self.transform(pairs[:, 1, :] - pairs[:, 0, :])
+ # (for MahalanobisMixin, the embedding is linear so we can just embed the
+ # difference)
+ return np.sqrt(np.sum(pairwise_diffs**2, axis=-1))
+
+
+
+[docs]
+ def transform(self, X):
+ """Embeds data points in the learned linear embedding space.
+
+ Transforms samples in ``X`` into ``X_embedded``, samples inside a new
+ embedding space such that: ``X_embedded = X.dot(L.T)``, where ``L`` is
+ the learned linear transformation (See :class:`MahalanobisMixin`).
+
+ Parameters
+ ----------
+ X : `numpy.ndarray`, shape=(n_samples, n_features)
+ The data points to embed.
+
+ Returns
+ -------
+ X_embedded : `numpy.ndarray`, shape=(n_samples, n_components)
+ The embedded data points.
+ """
+ check_is_fitted(self, ['preprocessor_', 'components_'])
+ X_checked = check_input(X, type_of_inputs='classic', estimator=self,
+ preprocessor=self.preprocessor_,
+ accept_sparse=True)
+ return X_checked.dot(self.components_.T)
+
+
+
+[docs]
+ def get_metric(self):
+ check_is_fitted(self, 'components_')
+ components_T = self.components_.T.copy()
+
+ def metric_fun(u, v, squared=False):
+ """This function computes the metric between u and v, according to the
+ previously learned metric.
+
+ Parameters
+ ----------
+ u : array-like, shape=(n_features,)
+ The first point involved in the distance computation.
+
+ v : array-like, shape=(n_features,)
+ The second point involved in the distance computation.
+
+ squared : `bool`
+ If True, the function will return the squared metric between u and
+ v, which is faster to compute.
+
+ Returns
+ -------
+ distance : float
+ The distance between u and v according to the new metric.
+ """
+ u = validate_vector(u)
+ v = validate_vector(v)
+ transformed_diff = (u - v).dot(components_T)
+ dist = np.dot(transformed_diff, transformed_diff.T)
+ if not squared:
+ dist = np.sqrt(dist)
+ return dist
+
+ return metric_fun
+
+
+ get_metric.__doc__ = BaseMetricLearner.get_metric.__doc__
+
+
+[docs]
+ def get_mahalanobis_matrix(self):
+ """Returns a copy of the Mahalanobis matrix learned by the metric learner.
+
+ Returns
+ -------
+ M : `numpy.ndarray`, shape=(n_features, n_features)
+ The copy of the learned Mahalanobis matrix.
+ """
+ check_is_fitted(self, 'components_')
+ return self.components_.T.dot(self.components_)
+
+
+
+
+
+[docs]
+class _PairsClassifierMixin(BaseMetricLearner, ClassifierMixin):
+ """Base class for pairs learners.
+
+ Attributes
+ ----------
+ threshold_ : `float`
+ If the distance metric between two points is lower than this threshold,
+ points will be classified as similar, otherwise they will be
+ classified as dissimilar.
+ """
+
+ classes_ = np.array([0, 1])
+ _tuple_size = 2 # number of points in a tuple, 2 for pairs
+
+
+[docs]
+ def predict(self, pairs):
+ """Predicts the learned metric between input pairs. (For now it just
+ calls decision function).
+
+ Returns the learned metric value between samples in every pair. It should
+ ideally be low for similar samples and high for dissimilar samples.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs to predict, with each row corresponding to two
+ points, or 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ Returns
+ -------
+ y_predicted : `numpy.ndarray` of floats, shape=(n_constraints,)
+ The predicted learned metric value between samples in every pair.
+ """
+ check_is_fitted(self, 'preprocessor_')
+
+ if "threshold_" not in vars(self):
+ msg = ("A threshold for this estimator has not been set, "
+ "call its set_threshold or calibrate_threshold method.")
+ raise AttributeError(msg)
+ return 2 * (- self.decision_function(pairs) <= self.threshold_) - 1
+
+
+
+[docs]
+ def decision_function(self, pairs):
+ """Returns the decision function used to classify the pairs.
+
+ Returns the opposite of the learned metric value between samples in every
+ pair, to be consistent with scikit-learn conventions. Hence it should
+ ideally be low for dissimilar samples and high for similar samples.
+ This is the decision function that is used to classify pairs as similar
+ (+1), or dissimilar (-1).
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs to predict, with each row corresponding to two
+ points, or 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ Returns
+ -------
+ y_predicted : `numpy.ndarray` of floats, shape=(n_constraints,)
+ The predicted decision function value for each pair.
+ """
+ check_is_fitted(self, 'preprocessor_')
+ pairs = check_input(pairs, type_of_inputs='tuples',
+ preprocessor=self.preprocessor_,
+ estimator=self, tuple_size=self._tuple_size)
+ return self.pair_score(pairs)
+
+
+
+[docs]
+ def score(self, pairs, y):
+ """Computes score of pairs similarity prediction.
+
+ Returns the ``roc_auc`` score of the fitted metric learner. It is
+ computed in the following way: for every value of a threshold
+ ``t`` we classify all pairs of samples where the predicted distance is
+ inferior to ``t`` as belonging to the "similar" class, and the other as
+ belonging to the "dissimilar" class, and we count false positive and
+ true positives as in a classical ``roc_auc`` curve.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_pairs, 2, n_features) or (n_pairs, 2)
+ 3D Array of pairs, with each row corresponding to two points,
+ or 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ y : array-like, shape=(n_constraints,)
+ The corresponding labels.
+
+ Returns
+ -------
+ score : float
+ The ``roc_auc`` score.
+ """
+ return roc_auc_score(y, self.decision_function(pairs))
+
+
+
+[docs]
+ def set_threshold(self, threshold):
+ """Sets the threshold of the metric learner to the given value `threshold`.
+
+ See more in the :ref:`User Guide <calibration>`.
+
+ Parameters
+ ----------
+ threshold : float
+ The threshold value we want to set. It is the value to which the
+ predicted distance for test pairs will be compared. If they are superior
+ to the threshold they will be classified as similar (+1),
+ and dissimilar (-1) if not.
+
+ Returns
+ -------
+ self : `_PairsClassifier`
+ The pairs classifier with the new threshold set.
+ """
+ check_is_fitted(self, 'preprocessor_')
+ try:
+ self.threshold_ = float(threshold)
+ except TypeError:
+ raise ValueError('Parameter threshold must be a real number. '
+ 'Got {} instead.'.format(type(threshold)))
+ except ValueError:
+ raise ValueError('Parameter threshold must be a real number. '
+ 'Got {} instead.'.format(type(threshold)))
+ return self
+
+
+
+[docs]
+ def calibrate_threshold(self, pairs_valid, y_valid, strategy='accuracy',
+ min_rate=None, beta=1.):
+ """Decision threshold calibration for pairwise binary classification
+
+ Method that calibrates the decision threshold (cutoff point) of the metric
+ learner. This threshold will then be used when calling the method
+ `predict`. The methods for picking cutoff points make use of traditional
+ binary classification evaluation statistics such as the true positive and
+ true negative rates and F-scores. The threshold will be found to maximize
+ the chosen score on the validation set ``(pairs_valid, y_valid)``.
+
+ See more in the :ref:`User Guide <calibration>`.
+
+ Parameters
+ ----------
+ strategy : str, optional (default='accuracy')
+ The strategy to use for choosing the cutoff threshold.
+
+ 'accuracy'
+ Selects a decision threshold that maximizes the accuracy.
+ 'f_beta'
+ Selects a decision threshold that maximizes the f_beta score,
+ with beta given by the parameter `beta`.
+ 'max_tpr'
+ Selects a decision threshold that yields the highest true positive
+ rate with true negative rate at least equal to the value of the
+ parameter `min_rate`.
+ 'max_tnr'
+ Selects a decision threshold that yields the highest true negative
+ rate with true positive rate at least equal to the value of the
+ parameter `min_rate`.
+
+ beta : float in [0, 1], optional (default=None)
+ Beta value to be used in case strategy == 'f_beta'.
+
+ min_rate : float in [0, 1] or None, (default=None)
+ In case strategy is 'max_tpr' or 'max_tnr' this parameter must be set
+ to specify the minimal value for the true negative rate or true positive
+ rate respectively that needs to be achieved.
+
+ pairs_valid : array-like, shape=(n_pairs_valid, 2, n_features)
+ The validation set of pairs to use to set the threshold.
+
+ y_valid : array-like, shape=(n_pairs_valid,)
+ The labels of the pairs of the validation set to use to set the
+ threshold. They must be +1 for positive pairs and -1 for negative pairs.
+
+ References
+ ----------
+ .. [1] Receiver-operating characteristic (ROC) plots: a fundamental
+ evaluation tool in clinical medicine, MH Zweig, G Campbell -
+ Clinical chemistry, 1993
+
+ .. [2] Most of the code of this function is from scikit-learn's PR #10117
+
+ See Also
+ --------
+ sklearn.calibration : scikit-learn's module for calibrating classifiers
+ """
+ check_is_fitted(self, 'preprocessor_')
+
+ self._validate_calibration_params(strategy, min_rate, beta)
+
+ pairs_valid, y_valid = self._prepare_inputs(pairs_valid, y_valid,
+ type_of_inputs='tuples')
+
+ n_samples = pairs_valid.shape[0]
+ if strategy == 'accuracy':
+ scores = self.decision_function(pairs_valid)
+ scores_sorted_idces = np.argsort(scores)[::-1]
+ scores_sorted = scores[scores_sorted_idces]
+ # true labels ordered by decision_function value: (higher first)
+ y_ordered = y_valid[scores_sorted_idces]
+ # we need to add a threshold that will reject all points
+ scores_sorted = np.concatenate([[scores_sorted[0] + 1], scores_sorted])
+
+ # finds the threshold that maximizes the accuracy:
+ cum_tp = stable_cumsum(y_ordered == 1) # cumulative number of true
+ # positives
+ # we need to add the point where all samples are rejected:
+ cum_tp = np.concatenate([[0.], cum_tp])
+ cum_tn_inverted = stable_cumsum(y_ordered[::-1] == -1)
+ cum_tn = np.concatenate([[0.], cum_tn_inverted])[::-1]
+ cum_accuracy = (cum_tp + cum_tn) / n_samples
+ imax = np.argmax(cum_accuracy)
+ # we set the threshold to the lowest accepted score
+ # note: we are working with negative distances but we want the threshold
+ # to be with respect to the actual distances so we take minus sign
+ self.threshold_ = - scores_sorted[imax]
+ # note: if the best is to reject all points it's already one of the
+ # thresholds (scores_sorted[0])
+ return self
+
+ if strategy == 'f_beta':
+ precision, recall, thresholds = precision_recall_curve(
+ y_valid, self.decision_function(pairs_valid), pos_label=1)
+
+ # here the thresholds are decreasing
+ # We ignore the warnings here, in the same taste as
+ # https://github.com/scikit-learn/scikit-learn/blob/62d205980446a1abc1065
+ # f4332fd74eee57fcf73/sklearn/metrics/classification.py#L1284
+ with np.errstate(divide='ignore', invalid='ignore'):
+ f_beta = ((1 + beta**2) * (precision * recall) /
+ (beta**2 * precision + recall))
+ # We need to set nans to zero otherwise they will be considered higher
+ # than the others (also discussed in https://github.com/scikit-learn/
+ # scikit-learn/pull/10117/files#r262115773)
+ f_beta[np.isnan(f_beta)] = 0.
+ imax = np.argmax(f_beta)
+ # we set the threshold to the lowest accepted score
+ # note: we are working with negative distances but we want the threshold
+ # to be with respect to the actual distances so we take minus sign
+ self.threshold_ = - thresholds[imax]
+ # Note: we don't need to deal with rejecting all points (i.e. threshold =
+ # max_scores + 1), since this can never happen to be optimal
+ # (see a more detailed discussion in test_calibrate_threshold_extreme)
+ return self
+
+ fpr, tpr, thresholds = roc_curve(y_valid,
+ self.decision_function(pairs_valid),
+ pos_label=1)
+ # here the thresholds are decreasing
+ fpr, tpr, thresholds = fpr, tpr, thresholds
+
+ if strategy in ['max_tpr', 'max_tnr']:
+ if strategy == 'max_tpr':
+ indices = np.where(1 - fpr >= min_rate)[0]
+ imax = np.argmax(tpr[indices])
+
+ if strategy == 'max_tnr':
+ indices = np.where(tpr >= min_rate)[0]
+ imax = np.argmax(1 - fpr[indices])
+
+ imax_valid = indices[imax]
+ # note: we are working with negative distances but we want the threshold
+ # to be with respect to the actual distances so we take minus sign
+ if indices[imax] == len(thresholds): # we want to accept everything
+ self.threshold_ = - (thresholds[imax_valid] - 1)
+ else:
+ # thanks to roc_curve, the first point will always be max_scores
+ # + 1, see: https://github.com/scikit-learn/scikit-learn/pull/13523
+ self.threshold_ = - thresholds[imax_valid]
+ return self
+
+
+ @staticmethod
+ def _validate_calibration_params(strategy='accuracy', min_rate=None,
+ beta=1.):
+ """Ensure that calibration parameters have allowed values"""
+ if strategy not in ('accuracy', 'f_beta', 'max_tpr',
+ 'max_tnr'):
+ raise ValueError('Strategy can either be "accuracy", "f_beta" or '
+ '"max_tpr" or "max_tnr". Got "{}" instead.'
+ .format(strategy))
+ if strategy == 'max_tpr' or strategy == 'max_tnr':
+ if (min_rate is None or not isinstance(min_rate, (int, float)) or
+ not min_rate >= 0 or not min_rate <= 1):
+ raise ValueError('Parameter min_rate must be a number in'
+ '[0, 1]. '
+ 'Got {} instead.'.format(min_rate))
+ if strategy == 'f_beta':
+ if beta is None or not isinstance(beta, (int, float)):
+ raise ValueError('Parameter beta must be a real number. '
+ 'Got {} instead.'.format(type(beta)))
+
+
+
+
+[docs]
+class _TripletsClassifierMixin(BaseMetricLearner, ClassifierMixin):
+ """
+ Base class for triplets learners.
+ """
+
+ classes_ = np.array([0, 1])
+ _tuple_size = 3 # number of points in a tuple, 3 for triplets
+
+
+[docs]
+ def predict(self, triplets):
+ """Predicts the ordering between sample distances in input triplets.
+
+ For each triplets, returns 1 if the first element is closer to the second
+ than to the last and -1 if not.
+
+ Parameters
+ ----------
+ triplets : array-like, shape=(n_triplets, 3, n_features) or (n_triplets, 3)
+ 3D array of triplets to predict, with each row corresponding to three
+ points, or 2D array of indices of triplets if the metric learner
+ uses a preprocessor.
+
+ Returns
+ -------
+ prediction : `numpy.ndarray` of floats, shape=(n_constraints,)
+ Predictions of the ordering of pairs, for each triplet.
+ """
+ return 2 * (self.decision_function(triplets) > 0) - 1
+
+
+
+[docs]
+ def decision_function(self, triplets):
+ """Predicts differences between sample distances in input triplets.
+
+ For each triplet (X_a, X_b, X_c) in the samples, computes the difference
+ between the learned distance of the second pair (X_a, X_c) minus the
+ learned distance of the first pair (X_a, X_b). The higher it is, the more
+ probable it is that the pairs in the triplets are presented in the right
+ order, i.e. that the label of the triplet is 1. The lower it is, the more
+ probable it is that the label of the triplet is -1.
+
+ Parameters
+ ----------
+ triplet : array-like, shape=(n_triplets, 3, n_features) or \
+ (n_triplets, 3)
+ 3D array of triplets to predict, with each row corresponding to three
+ points, or 2D array of indices of triplets if the metric learner
+ uses a preprocessor.
+
+ Returns
+ -------
+ decision_function : `numpy.ndarray` of floats, shape=(n_constraints,)
+ Metric differences.
+ """
+ check_is_fitted(self, 'preprocessor_')
+ triplets = check_input(triplets, type_of_inputs='tuples',
+ preprocessor=self.preprocessor_,
+ estimator=self, tuple_size=self._tuple_size)
+ return (self.pair_score(triplets[:, :2]) -
+ self.pair_score(triplets[:, [0, 2]]))
+
+
+
+[docs]
+ def score(self, triplets):
+ """Computes score on input triplets.
+
+ Returns the accuracy score of the following classification task: a triplet
+ (X_a, X_b, X_c) is correctly classified if the predicted similarity between
+ the first pair (X_a, X_b) is higher than that of the second pair (X_a, X_c)
+
+ Parameters
+ ----------
+ triplets : array-like, shape=(n_triplets, 3, n_features) or \
+ (n_triplets, 3)
+ 3D array of triplets to score, with each row corresponding to three
+ points, or 2D array of indices of triplets if the metric learner
+ uses a preprocessor.
+
+ Returns
+ -------
+ score : float
+ The triplets score.
+ """
+ # Since the prediction is a vector of values in {-1, +1}, we need to
+ # rescale them to {0, 1} to compute the accuracy using the mean (because
+ # then 1 means a correctly classified result (pairs are in the right
+ # order), and a 0 an incorrectly classified result (pairs are in the
+ # wrong order).
+ return self.predict(triplets).mean() / 2 + 0.5
+
+
+
+
+
+[docs]
+class _QuadrupletsClassifierMixin(BaseMetricLearner, ClassifierMixin):
+ """
+ Base class for quadruplets learners.
+ """
+
+ classes_ = np.array([0, 1])
+ _tuple_size = 4 # number of points in a tuple, 4 for quadruplets
+
+
+[docs]
+ def predict(self, quadruplets):
+ """Predicts the ordering between sample distances in input quadruplets.
+
+ For each quadruplet, returns 1 if the quadruplet is in the right order (
+ first pair is more similar than second pair), and -1 if not.
+
+ Parameters
+ ----------
+ quadruplets : array-like, shape=(n_quadruplets, 4, n_features) or \
+ (n_quadruplets, 4)
+ 3D Array of quadruplets to predict, with each row corresponding to four
+ points, or 2D array of indices of quadruplets if the metric learner
+ uses a preprocessor.
+
+ Returns
+ -------
+ prediction : `numpy.ndarray` of floats, shape=(n_constraints,)
+ Predictions of the ordering of pairs, for each quadruplet.
+ """
+ return np.sign(self.decision_function(quadruplets))
+
+
+
+[docs]
+ def decision_function(self, quadruplets):
+ """Predicts differences between sample distances in input quadruplets.
+
+ For each quadruplet in the samples, computes the difference between the
+ learned metric of the second pair minus the learned metric of the first
+ pair. The higher it is, the more probable it is that the pairs in the
+ quadruplet are presented in the right order, i.e. that the label of the
+ quadruplet is 1. The lower it is, the more probable it is that the label of
+ the quadruplet is -1.
+
+ Parameters
+ ----------
+ quadruplets : array-like, shape=(n_quadruplets, 4, n_features) or \
+ (n_quadruplets, 4)
+ 3D Array of quadruplets to predict, with each row corresponding to four
+ points, or 2D array of indices of quadruplets if the metric learner
+ uses a preprocessor.
+
+ Returns
+ -------
+ decision_function : `numpy.ndarray` of floats, shape=(n_constraints,)
+ Metric differences.
+ """
+ check_is_fitted(self, 'preprocessor_')
+ quadruplets = check_input(quadruplets, type_of_inputs='tuples',
+ preprocessor=self.preprocessor_,
+ estimator=self, tuple_size=self._tuple_size)
+ return (self.pair_score(quadruplets[:, :2]) -
+ self.pair_score(quadruplets[:, 2:]))
+
+
+
+[docs]
+ def score(self, quadruplets):
+ """Computes score on input quadruplets
+
+ Returns the accuracy score of the following classification task: a record
+ is correctly classified if the predicted similarity between the first two
+ samples is higher than that of the last two.
+
+ Parameters
+ ----------
+ quadruplets : array-like, shape=(n_quadruplets, 4, n_features) or \
+ (n_quadruplets, 4)
+ 3D Array of quadruplets to score, with each row corresponding to four
+ points, or 2D array of indices of quadruplets if the metric learner
+ uses a preprocessor.
+
+ Returns
+ -------
+ score : float
+ The quadruplets score.
+ """
+ # Since the prediction is a vector of values in {-1, +1}, we need to
+ # rescale them to {0, 1} to compute the accuracy using the mean (because
+ # then 1 means a correctly classified result (pairs are in the right
+ # order), and a 0 an incorrectly classified result (pairs are in the
+ # wrong order).
+ return self.predict(quadruplets).mean() / 2 + 0.5
+
+
+
+"""
+Helper module for generating different types of constraints
+from supervised data labels.
+"""
+import numpy as np
+import warnings
+from sklearn.utils import check_random_state
+from sklearn.neighbors import NearestNeighbors
+
+
+__all__ = ['Constraints']
+
+
+
+[docs]
+class Constraints(object):
+ """
+ Class to build constraints from labeled data.
+
+ See more in the :ref:`User Guide <supervised_version>`.
+
+ Parameters
+ ----------
+ partial_labels : `numpy.ndarray` of ints, shape=(n_samples,)
+ Array of labels, with -1 indicating unknown label.
+
+ Attributes
+ ----------
+ partial_labels : `numpy.ndarray` of ints, shape=(n_samples,)
+ Array of labels, with -1 indicating unknown label.
+ """
+
+
+[docs]
+ def __init__(self, partial_labels):
+ partial_labels = np.asanyarray(partial_labels, dtype=int)
+ self.partial_labels = partial_labels
+
+
+
+[docs]
+ def positive_negative_pairs(self, n_constraints, same_length=False,
+ random_state=None, num_constraints='deprecated'):
+ """
+ Generates positive pairs and negative pairs from labeled data.
+
+ Positive pairs are formed by randomly drawing ``n_constraints`` pairs of
+ points with the same label. Negative pairs are formed by randomly drawing
+ ``n_constraints`` pairs of points with different label.
+
+ In the case where it is not possible to generate enough positive or
+ negative pairs, a smaller number of pairs will be returned with a warning.
+
+ Parameters
+ ----------
+ n_constraints : int
+ Number of positive and negative constraints to generate.
+
+ same_length : bool, optional (default=False)
+ If True, forces the number of positive and negative pairs to be
+ equal by ignoring some pairs from the larger set.
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int.
+
+ num_constraints : Renamed to n_constraints. Will be deprecated in 0.7.0
+
+ Returns
+ -------
+ a : array-like, shape=(n_constraints,)
+ 1D array of indicators for the left elements of positive pairs.
+
+ b : array-like, shape=(n_constraints,)
+ 1D array of indicators for the right elements of positive pairs.
+
+ c : array-like, shape=(n_constraints,)
+ 1D array of indicators for the left elements of negative pairs.
+
+ d : array-like, shape=(n_constraints,)
+ 1D array of indicators for the right elements of negative pairs.
+ """
+ if num_constraints != 'deprecated':
+ warnings.warn('"num_constraints" parameter has been renamed to'
+ ' "n_constraints". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ self.n_constraints = num_constraints
+ else:
+ self.n_constraints = n_constraints
+ random_state = check_random_state(random_state)
+ a, b = self._pairs(n_constraints, same_label=True,
+ random_state=random_state)
+ c, d = self._pairs(n_constraints, same_label=False,
+ random_state=random_state)
+ if same_length and len(a) != len(c):
+ n = min(len(a), len(c))
+ return a[:n], b[:n], c[:n], d[:n]
+ return a, b, c, d
+
+
+
+[docs]
+ def generate_knntriplets(self, X, k_genuine, k_impostor):
+ """
+ Generates triplets from labeled data.
+
+ For every point (X_a) the triplets (X_a, X_b, X_c) are constructed from all
+ the combinations of taking one of its `k_genuine`-nearest neighbors of the
+ same class (X_b) and taking one of its `k_impostor`-nearest neighbors of
+ other classes (X_c).
+
+ In the case a class doesn't have enough points in the same class (other
+ classes) to yield `k_genuine` (`k_impostor`) neighbors a warning will be
+ raised and the maximum value of genuine (impostor) neighbors will be used
+ for that class.
+
+ Parameters
+ ----------
+ X : (n x d) matrix
+ Input data, where each row corresponds to a single instance.
+
+ k_genuine : int
+ Number of neighbors of the same class to be taken into account.
+
+ k_impostor : int
+ Number of neighbors of different classes to be taken into account.
+
+ Returns
+ -------
+ triplets : array-like, shape=(n_constraints, 3)
+ 2D array of triplets of indicators.
+ """
+ # Ignore unlabeled samples
+ known_labels_mask = self.partial_labels >= 0
+ known_labels = self.partial_labels[known_labels_mask]
+ X = X[known_labels_mask]
+
+ labels, labels_count = np.unique(known_labels, return_counts=True)
+ len_input = known_labels.shape[0]
+
+ # Handle the case where there are too few elements to yield k_genuine or
+ # k_impostor neighbors for every class.
+
+ k_genuine_vec = np.full_like(labels, k_genuine)
+ k_impostor_vec = np.full_like(labels, k_impostor)
+
+ for i, count in enumerate(labels_count):
+ if k_genuine + 1 > count:
+ k_genuine_vec[i] = count-1
+ warnings.warn("The class {} has {} elements, which is not sufficient "
+ "to generate {} genuine neighbors as specified by "
+ "k_genuine. Will generate {} genuine neighbors instead."
+ "\n"
+ .format(labels[i], count, k_genuine+1,
+ k_genuine_vec[i]))
+ if k_impostor > len_input - count:
+ k_impostor_vec[i] = len_input - count
+ warnings.warn("The class {} has {} elements of other classes, which is"
+ " not sufficient to generate {} impostor neighbors as "
+ "specified by k_impostor. Will generate {} impostor "
+ "neighbors instead.\n"
+ .format(labels[i], k_impostor_vec[i], k_impostor,
+ k_impostor_vec[i]))
+
+ # The total number of possible triplets combinations per label comes from
+ # taking one of the k_genuine_vec[i] genuine neighbors and one of the
+ # k_impostor_vec[i] impostor neighbors for the labels_count[i] elements
+ comb_per_label = labels_count * k_genuine_vec * k_impostor_vec
+
+ # Get start and finish for later triplet assigning
+ # append zero at the begining for start and get cumulative sum
+ start_finish_indices = np.hstack((0, comb_per_label)).cumsum()
+
+ # Total number of triplets is the sum of all possible combinations per
+ # label
+ num_triplets = start_finish_indices[-1]
+ triplets = np.empty((num_triplets, 3), dtype=np.intp)
+
+ neigh = NearestNeighbors()
+
+ for i, label in enumerate(labels):
+
+ # generate mask for current label
+ gen_mask = known_labels == label
+ gen_indx = np.where(gen_mask)
+
+ # get k_genuine genuine neighbors
+ neigh.fit(X=X[gen_indx])
+ # Take elements of gen_indx according to the yielded k-neighbors
+ gen_relative_indx = neigh.kneighbors(n_neighbors=k_genuine_vec[i],
+ return_distance=False)
+ gen_neigh = np.take(gen_indx, gen_relative_indx)
+
+ # generate mask for impostors of current label
+ imp_indx = np.where(~gen_mask)
+
+ # get k_impostor impostor neighbors
+ neigh.fit(X=X[imp_indx])
+ # Take elements of imp_indx according to the yielded k-neighbors
+ imp_relative_indx = neigh.kneighbors(n_neighbors=k_impostor_vec[i],
+ X=X[gen_mask],
+ return_distance=False)
+ imp_neigh = np.take(imp_indx, imp_relative_indx)
+
+ # length = len_label*k_genuine*k_impostor
+ start, finish = start_finish_indices[i:i+2]
+
+ triplets[start:finish, :] = comb(gen_indx, gen_neigh, imp_neigh,
+ k_genuine_vec[i],
+ k_impostor_vec[i])
+
+ return triplets
+
+
+ def _pairs(self, n_constraints, same_label=True, max_iter=10,
+ random_state=np.random):
+ known_label_idx, = np.where(self.partial_labels >= 0)
+ known_labels = self.partial_labels[known_label_idx]
+ num_labels = len(known_labels)
+ ab = set()
+ it = 0
+ while it < max_iter and len(ab) < n_constraints:
+ nc = n_constraints - len(ab)
+ for aidx in random_state.randint(num_labels, size=nc):
+ if same_label:
+ mask = known_labels[aidx] == known_labels
+ mask[aidx] = False # avoid identity pairs
+ else:
+ mask = known_labels[aidx] != known_labels
+ b_choices, = np.where(mask)
+ if len(b_choices) > 0:
+ ab.add((aidx, random_state.choice(b_choices)))
+ it += 1
+ if len(ab) < n_constraints:
+ warnings.warn("Only generated %d %s constraints (requested %d)" % (
+ len(ab), 'positive' if same_label else 'negative', n_constraints))
+ ab = np.array(list(ab)[:n_constraints], dtype=int)
+ return known_label_idx[ab.T]
+
+
+[docs]
+ def chunks(self, n_chunks=100, chunk_size=2, random_state=None,
+ num_chunks='deprecated'):
+ """
+ Generates chunks from labeled data.
+
+ Each of ``n_chunks`` chunks is composed of ``chunk_size`` points from
+ the same class drawn at random. Each point can belong to at most 1 chunk.
+
+ In the case where there is not enough points to generate ``n_chunks``
+ chunks of size ``chunk_size``, a ValueError will be raised.
+
+ Parameters
+ ----------
+ n_chunks : int, optional (default=100)
+ Number of chunks to generate.
+
+ chunk_size : int, optional (default=2)
+ Number of points in each chunk.
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int.
+
+ num_chunks : Renamed to n_chunks. Will be deprecated in 0.7.0
+
+ Returns
+ -------
+ chunks : array-like, shape=(n_samples,)
+ 1D array of chunk indicators, where -1 indicates that the point does not
+ belong to any chunk.
+ """
+ if num_chunks != 'deprecated':
+ warnings.warn('"num_chunks" parameter has been renamed to'
+ ' "n_chunks". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ n_chunks = num_chunks
+ random_state = check_random_state(random_state)
+ chunks = -np.ones_like(self.partial_labels, dtype=int)
+ uniq, lookup = np.unique(self.partial_labels, return_inverse=True)
+ unknown_uniq = np.where(uniq < 0)[0]
+ all_inds = [set(np.where(lookup == c)[0]) for c in range(len(uniq))
+ if c not in unknown_uniq]
+ max_chunks = int(np.sum([len(s) // chunk_size for s in all_inds]))
+ if max_chunks < n_chunks:
+ raise ValueError(('Not enough possible chunks of %d elements in each'
+ ' class to form expected %d chunks - maximum number'
+ ' of chunks is %d'
+ ) % (chunk_size, n_chunks, max_chunks))
+ idx = 0
+ while idx < n_chunks and all_inds:
+ if len(all_inds) == 1:
+ c = 0
+ else:
+ c = random_state.randint(0, high=len(all_inds) - 1)
+ inds = all_inds[c]
+ if len(inds) < chunk_size:
+ del all_inds[c]
+ continue
+ ii = random_state.choice(list(inds), chunk_size, replace=False)
+ inds.difference_update(ii)
+ chunks[ii] = idx
+ idx += 1
+ return chunks
+
+
+
+
+def comb(A, B, C, sizeB, sizeC):
+ # generate_knntriplets helper function
+ # generate an array with all combinations of choosing
+ # an element from A, B and C
+ return np.vstack((np.tile(A, (sizeB*sizeC, 1)).ravel(order='F'),
+ np.tile(np.hstack(B), (sizeC, 1)).ravel(order='F'),
+ np.tile(C, (1, sizeB)).ravel())).T
+
+
+def wrap_pairs(X, constraints):
+ a = np.array(constraints[0])
+ b = np.array(constraints[1])
+ c = np.array(constraints[2])
+ d = np.array(constraints[3])
+ constraints = np.vstack((np.column_stack((a, b)), np.column_stack((c, d))))
+ y = np.concatenate([np.ones_like(a), -np.ones_like(c)])
+ pairs = X[constraints]
+ return pairs, y
+
+"""
+Covariance metric (baseline method)
+"""
+
+import numpy as np
+import scipy
+from sklearn.base import TransformerMixin
+
+from .base_metric import MahalanobisMixin
+from ._util import components_from_metric
+
+
+
+[docs]
+class Covariance(MahalanobisMixin, TransformerMixin):
+ """Covariance metric (baseline method)
+
+ This method does not "learn" anything, rather it calculates
+ the covariance matrix of the input data.
+
+ This is a simple baseline method first introduced in
+ On the Generalized Distance in Statistics, P.C.Mahalanobis, 1936
+
+ Read more in the :ref:`User Guide <covariance>`.
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+
+ Examples
+ --------
+ >>> from metric_learn import Covariance
+ >>> from sklearn.datasets import load_iris
+ >>> iris = load_iris()['data']
+ >>> cov = Covariance().fit(iris)
+ >>> x = cov.transform(iris)
+
+ """
+
+
+
+
+
+[docs]
+ def fit(self, X, y=None):
+ """
+ Calculates the covariance matrix of the input data.
+
+ Parameters
+ ----------
+ X : data matrix, (n x d)
+ y : unused
+ """
+ X = self._prepare_inputs(X, ensure_min_samples=2)
+ M = np.atleast_2d(np.cov(X, rowvar=False))
+ if M.size == 1:
+ M = 1. / M
+ else:
+ M = scipy.linalg.pinvh(M)
+
+ self.components_ = components_from_metric(np.atleast_2d(M))
+ return self
+
+
+
+"""
+Information Theoretic Metric Learning (ITML)
+"""
+
+import numpy as np
+from sklearn.metrics import pairwise_distances
+from sklearn.utils.validation import check_array
+from sklearn.base import TransformerMixin
+from .base_metric import _PairsClassifierMixin, MahalanobisMixin
+from .constraints import Constraints, wrap_pairs
+from ._util import components_from_metric, _initialize_metric_mahalanobis
+import warnings
+
+
+class _BaseITML(MahalanobisMixin):
+ """Information Theoretic Metric Learning (ITML)"""
+
+ _tuple_size = 2 # constraints are pairs
+
+ def __init__(self, gamma=1., max_iter=1000, tol=1e-3,
+ prior='identity', verbose=False,
+ preprocessor=None, random_state=None,
+ convergence_threshold='deprecated'):
+ if convergence_threshold != 'deprecated':
+ warnings.warn('"convergence_threshold" parameter has been '
+ ' renamed to "tol". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ tol = convergence_threshold
+ self.convergence_threshold = 'deprecated' # Avoid errors
+ self.gamma = gamma
+ self.max_iter = max_iter
+ self.tol = tol
+ self.prior = prior
+ self.verbose = verbose
+ self.random_state = random_state
+ super(_BaseITML, self).__init__(preprocessor)
+
+ def _fit(self, pairs, y, bounds=None):
+ pairs, y = self._prepare_inputs(pairs, y,
+ type_of_inputs='tuples')
+ # init bounds
+ if bounds is None:
+ X = np.unique(np.vstack(pairs), axis=0)
+ self.bounds_ = np.percentile(pairwise_distances(X), (5, 95))
+ else:
+ bounds = check_array(bounds, allow_nd=False, ensure_min_samples=0,
+ ensure_2d=False)
+ bounds = bounds.ravel()
+ if bounds.size != 2:
+ raise ValueError("`bounds` should be an array-like of two elements.")
+ self.bounds_ = bounds
+ self.bounds_[self.bounds_ == 0] = 1e-9
+ # set the prior
+ # pairs will be deduplicated into X two times, TODO: avoid that
+ A = _initialize_metric_mahalanobis(pairs, self.prior, self.random_state,
+ strict_pd=True,
+ matrix_name='prior')
+ gamma = self.gamma
+ pos_pairs, neg_pairs = pairs[y == 1], pairs[y == -1]
+ num_pos = len(pos_pairs)
+ num_neg = len(neg_pairs)
+ _lambda = np.zeros(num_pos + num_neg)
+ lambdaold = np.zeros_like(_lambda)
+ gamma_proj = 1. if gamma is np.inf else gamma / (gamma + 1.)
+ pos_bhat = np.zeros(num_pos) + self.bounds_[0]
+ neg_bhat = np.zeros(num_neg) + self.bounds_[1]
+ pos_vv = pos_pairs[:, 0, :] - pos_pairs[:, 1, :]
+ neg_vv = neg_pairs[:, 0, :] - neg_pairs[:, 1, :]
+
+ for it in range(self.max_iter):
+ # update positives
+ for i, v in enumerate(pos_vv):
+ wtw = v.dot(A).dot(v) # scalar
+ alpha = min(_lambda[i], gamma_proj * (1. / wtw - 1. / pos_bhat[i]))
+ _lambda[i] -= alpha
+ beta = alpha / (1 - alpha * wtw)
+ pos_bhat[i] = 1. / ((1 / pos_bhat[i]) + (alpha / gamma))
+ Av = A.dot(v)
+ A += np.outer(Av, Av * beta)
+
+ # update negatives
+ for i, v in enumerate(neg_vv):
+ wtw = v.dot(A).dot(v) # scalar
+ alpha = min(_lambda[i + num_pos],
+ gamma_proj * (1. / neg_bhat[i] - 1. / wtw))
+ _lambda[i + num_pos] -= alpha
+ beta = -alpha / (1 + alpha * wtw)
+ neg_bhat[i] = 1. / ((1 / neg_bhat[i]) - (alpha / gamma))
+ Av = A.dot(v)
+ A += np.outer(Av, Av * beta)
+
+ normsum = np.linalg.norm(_lambda) + np.linalg.norm(lambdaold)
+ if normsum == 0:
+ conv = np.inf
+ break
+ conv = np.abs(lambdaold - _lambda).sum() / normsum
+ if conv < self.tol:
+ break
+ lambdaold = _lambda.copy()
+ if self.verbose:
+ print('itml iter: %d, conv = %f' % (it, conv))
+
+ if self.verbose:
+ print('itml converged at iter: %d, conv = %f' % (it, conv))
+ self.n_iter_ = it
+
+ self.components_ = components_from_metric(A)
+ return self
+
+
+
+[docs]
+class ITML(_BaseITML, _PairsClassifierMixin):
+ """Information Theoretic Metric Learning (ITML)
+
+ `ITML` minimizes the (differential) relative entropy, aka Kullback-Leibler
+ divergence, between two multivariate Gaussians subject to constraints on the
+ associated Mahalanobis distance, which can be formulated into a Bregman
+ optimization problem by minimizing the LogDet divergence subject to
+ linear constraints. This algorithm can handle a wide variety of constraints
+ and can optionally incorporate a prior on the distance function. Unlike some
+ other methods, `ITML` does not rely on an eigenvalue computation or
+ semi-definite programming.
+
+ Read more in the :ref:`User Guide <itml>`.
+
+ Parameters
+ ----------
+ gamma : float, optional (default=1.0)
+ Value for slack variables
+
+ max_iter : int, optional (default=1000)
+ Maximum number of iteration of the optimization procedure.
+
+ tol : float, optional (default=1e-3)
+ Convergence tolerance.
+
+ prior : string or numpy array, optional (default='identity')
+ The Mahalanobis matrix to use as a prior. Possible options are
+ 'identity', 'covariance', 'random', and a numpy array of shape
+ (n_features, n_features). For ITML, the prior should be strictly
+ positive definite (PD).
+
+ 'identity'
+ An identity matrix of shape (n_features, n_features).
+
+ 'covariance'
+ The inverse covariance matrix.
+
+ 'random'
+ The prior will be a random SPD matrix of shape
+ `(n_features, n_features)`, generated using
+ `sklearn.datasets.make_spd_matrix`.
+
+ numpy array
+ A positive definite (PD) matrix of shape
+ (n_features, n_features), that will be used as such to set the
+ prior.
+
+ verbose : bool, optional (default=False)
+ If True, prints information while learning
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``prior='random'``, ``random_state`` is used to set the prior.
+
+ convergence_threshold : Renamed to tol. Will be deprecated in 0.7.0
+
+ Attributes
+ ----------
+ bounds_ : `numpy.ndarray`, shape=(2,)
+ Bounds on similarity, aside slack variables, s.t.
+ ``d(a, b) < bounds_[0]`` for all given pairs of similar points ``a``
+ and ``b``, and ``d(c, d) > bounds_[1]`` for all given pairs of
+ dissimilar points ``c`` and ``d``, with ``d`` the learned distance. If
+ not provided at initialization, bounds_[0] and bounds_[1] are set at
+ train time to the 5th and 95th percentile of the pairwise distances among
+ all points present in the input `pairs`.
+
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+
+ threshold_ : `float`
+ If the distance metric between two points is lower than this threshold,
+ points will be classified as similar, otherwise they will be
+ classified as dissimilar.
+
+ Examples
+ --------
+ >>> from metric_learn import ITML
+ >>> pairs = [[[1.2, 7.5], [1.3, 1.5]],
+ >>> [[6.4, 2.6], [6.2, 9.7]],
+ >>> [[1.3, 4.5], [3.2, 4.6]],
+ >>> [[6.2, 5.5], [5.4, 5.4]]]
+ >>> y = [1, 1, -1, -1]
+ >>> # in this task we want points where the first feature is close to be
+ >>> # closer to each other, no matter how close the second feature is
+ >>> itml = ITML()
+ >>> itml.fit(pairs, y)
+
+ References
+ ----------
+ .. [1] Jason V. Davis, et al. `Information-theoretic Metric Learning
+ <http://www.prateekjain.org/publications/all_papers\
+ /DavisKJSD07_ICML.pdf>`_. ICML 2007.
+ """
+
+
+[docs]
+ def fit(self, pairs, y, bounds=None, calibration_params=None):
+ """Learn the ITML model.
+
+ The threshold will be calibrated on the trainset using the parameters
+ `calibration_params`.
+
+ Parameters
+ ----------
+ pairs: array-like, shape=(n_constraints, 2, n_features) or \
+ (n_constraints, 2)
+ 3D Array of pairs with each row corresponding to two points,
+ or 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ y: array-like, of shape (n_constraints,)
+ Labels of constraints. Should be -1 for dissimilar pair, 1 for similar.
+
+ bounds : array-like of two numbers
+ Bounds on similarity, aside slack variables, s.t.
+ ``d(a, b) < bounds_[0]`` for all given pairs of similar points ``a``
+ and ``b``, and ``d(c, d) > bounds_[1]`` for all given pairs of
+ dissimilar points ``c`` and ``d``, with ``d`` the learned distance.
+ If not provided at initialization, bounds_[0] and bounds_[1] will be
+ set to the 5th and 95th percentile of the pairwise distances among all
+ points present in the input `pairs`.
+
+ calibration_params : `dict` or `None`
+ Dictionary of parameters to give to `calibrate_threshold` for the
+ threshold calibration step done at the end of `fit`. If `None` is
+ given, `calibrate_threshold` will use the default parameters.
+
+ Returns
+ -------
+ self : object
+ Returns the instance.
+ """
+ calibration_params = (calibration_params if calibration_params is not
+ None else dict())
+ self._validate_calibration_params(**calibration_params)
+ self._fit(pairs, y, bounds=bounds)
+ self.calibrate_threshold(pairs, y, **calibration_params)
+ return self
+
+
+
+
+
+[docs]
+class ITML_Supervised(_BaseITML, TransformerMixin):
+ """Supervised version of Information Theoretic Metric Learning (ITML)
+
+ `ITML_Supervised` creates pairs of similar sample by taking same class
+ samples, and pairs of dissimilar samples by taking different class
+ samples. It then passes these pairs to `ITML` for training.
+
+ Parameters
+ ----------
+ gamma : float, optional (default=1.0)
+ Value for slack variables
+
+ max_iter : int, optional (default=1000)
+ Maximum number of iterations of the optimization procedure.
+
+ tol : float, optional (default=1e-3)
+ Tolerance of the optimization procedure.
+
+ n_constraints : int, optional (default=None)
+ Number of constraints to generate. If None, default to `20 *
+ num_classes**2`.
+
+ prior : string or numpy array, optional (default='identity')
+ Initialization of the Mahalanobis matrix. Possible options are
+ 'identity', 'covariance', 'random', and a numpy array of shape
+ (n_features, n_features). For ITML, the prior should be strictly
+ positive definite (PD).
+
+ 'identity'
+ An identity matrix of shape (n_features, n_features).
+
+ 'covariance'
+ The inverse covariance matrix.
+
+ 'random'
+ The prior will be a random SPD matrix of shape
+ `(n_features, n_features)`, generated using
+ `sklearn.datasets.make_spd_matrix`.
+
+ numpy array
+ A positive definite (PD) matrix of shape
+ (n_features, n_features), that will be used as such to set the
+ prior.
+
+ verbose : bool, optional (default=False)
+ If True, prints information while learning
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``prior='random'``, ``random_state`` is used to set the prior. In any
+ case, `random_state` is also used to randomly sample constraints from
+ labels.
+
+ num_constraints : Renamed to n_constraints. Will be deprecated in 0.7.0
+
+ convergence_threshold : Renamed to tol. Will be deprecated in 0.7.0
+
+ Attributes
+ ----------
+ bounds_ : `numpy.ndarray`, shape=(2,)
+ Bounds on similarity, aside slack variables, s.t.
+ ``d(a, b) < bounds_[0]`` for all given pairs of similar points ``a``
+ and ``b``, and ``d(c, d) > bounds_[1]`` for all given pairs of
+ dissimilar points ``c`` and ``d``, with ``d`` the learned distance.
+ If not provided at initialization, bounds_[0] and bounds_[1] are set at
+ train time to the 5th and 95th percentile of the pairwise distances
+ among all points in the training data `X`.
+
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+
+ Examples
+ --------
+ >>> from metric_learn import ITML_Supervised
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> itml = ITML_Supervised(n_constraints=200)
+ >>> itml.fit(X, Y)
+
+ See Also
+ --------
+ metric_learn.ITML : The original weakly-supervised algorithm
+ :ref:`supervised_version` : The section of the project documentation
+ that describes the supervised version of weakly supervised estimators.
+ """
+
+
+[docs]
+ def __init__(self, gamma=1.0, max_iter=1000, tol=1e-3,
+ n_constraints=None, prior='identity',
+ verbose=False, preprocessor=None, random_state=None,
+ num_constraints='deprecated',
+ convergence_threshold='deprecated'):
+ _BaseITML.__init__(self, gamma=gamma, max_iter=max_iter,
+ tol=tol,
+ prior=prior, verbose=verbose,
+ preprocessor=preprocessor,
+ random_state=random_state,
+ convergence_threshold=convergence_threshold)
+ if num_constraints != 'deprecated':
+ warnings.warn('"num_constraints" parameter has been renamed to'
+ ' "n_constraints". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ n_constraints = num_constraints
+ self.n_constraints = n_constraints
+ # Avoid test get_params from failing (all params passed sholud be set)
+ self.num_constraints = 'deprecated'
+
+
+
+[docs]
+ def fit(self, X, y, bounds=None):
+ """Create constraints from labels and learn the ITML model.
+
+
+ Parameters
+ ----------
+ X : (n x d) matrix
+ Input data, where each row corresponds to a single instance.
+
+ y : (n) array-like
+ Data labels.
+
+ bounds : array-like of two numbers
+ Bounds on similarity, aside slack variables, s.t.
+ ``d(a, b) < bounds_[0]`` for all given pairs of similar points ``a``
+ and ``b``, and ``d(c, d) > bounds_[1]`` for all given pairs of
+ dissimilar points ``c`` and ``d``, with ``d`` the learned distance.
+ If not provided at initialization, bounds_[0] and bounds_[1] will be
+ set to the 5th and 95th percentile of the pairwise distances among all
+ points in the training data `X`.
+ """
+ X, y = self._prepare_inputs(X, y, ensure_min_samples=2)
+ n_constraints = self.n_constraints
+ if n_constraints is None:
+ num_classes = len(np.unique(y))
+ n_constraints = 20 * num_classes**2
+
+ c = Constraints(y)
+ pos_neg = c.positive_negative_pairs(n_constraints,
+ random_state=self.random_state)
+ pairs, y = wrap_pairs(X, pos_neg)
+ return _BaseITML._fit(self, pairs, y, bounds=bounds)
+
+
+
+"""
+Local Fisher Discriminant Analysis (LFDA)
+"""
+import numpy as np
+import scipy
+import warnings
+from sklearn.metrics import pairwise_distances
+from sklearn.base import TransformerMixin
+
+from ._util import _check_n_components
+from .base_metric import MahalanobisMixin
+
+
+
+[docs]
+class LFDA(MahalanobisMixin, TransformerMixin):
+ '''
+ Local Fisher Discriminant Analysis for Supervised Dimensionality Reduction
+
+ LFDA is a linear supervised dimensionality reduction method. It is
+ particularly useful when dealing with multimodality, where one ore more
+ classes consist of separate clusters in input space. The core optimization
+ problem of LFDA is solved as a generalized eigenvalue problem.
+
+ Read more in the :ref:`User Guide <lfda>`.
+
+ Parameters
+ ----------
+ n_components : int or None, optional (default=None)
+ Dimensionality of reduced space (if None, defaults to dimension of X).
+
+ k : int, optional (default=None)
+ Number of nearest neighbors used in local scaling method. If None,
+ defaults to min(7, n_features - 1).
+
+ embedding_type : str, optional (default: 'weighted')
+ Type of metric in the embedding space.
+
+ 'weighted'
+ weighted eigenvectors
+
+ 'orthonormalized'
+ orthonormalized
+
+ 'plain'
+ raw eigenvectors
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_components, n_features)
+ The learned linear transformation ``L``.
+
+ Examples
+ --------
+
+ >>> import numpy as np
+ >>> from metric_learn import LFDA
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> lfda = LFDA(k=2, dim=2)
+ >>> lfda.fit(X, Y)
+
+ References
+ ----------
+ .. [1] Masashi Sugiyama. `Dimensionality Reduction of Multimodal Labeled
+ Data by Local Fisher Discriminant Analysis
+ <http://www.ms.k.u-tokyo.ac.jp/2007/LFDA.pdf>`_. JMLR 2007.
+
+ .. [2] Yuan Tang. `Local Fisher Discriminant Analysis on Beer Style
+ Clustering
+ <https://gastrograph.com/resources/whitepapers/local-fisher\
+ -discriminant-analysis-on-beer-style-clustering.html#>`_.
+ '''
+
+
+[docs]
+ def __init__(self, n_components=None,
+ k=None, embedding_type='weighted', preprocessor=None):
+ if embedding_type not in ('weighted', 'orthonormalized', 'plain'):
+ raise ValueError('Invalid embedding_type: %r' % embedding_type)
+ self.n_components = n_components
+ self.embedding_type = embedding_type
+ self.k = k
+ super(LFDA, self).__init__(preprocessor)
+
+
+
+[docs]
+ def fit(self, X, y):
+ '''Fit the LFDA model.
+
+ Parameters
+ ----------
+ X : (n, d) array-like
+ Input data.
+
+ y : (n,) array-like
+ Class labels, one per point of data.
+ '''
+ X, y = self._prepare_inputs(X, y, ensure_min_samples=2)
+ unique_classes, y = np.unique(y, return_inverse=True)
+ n, d = X.shape
+ num_classes = len(unique_classes)
+
+ dim = _check_n_components(d, self.n_components)
+
+ if self.k is None:
+ k = min(7, d - 1)
+ elif self.k >= d:
+ warnings.warn('Chosen k (%d) too large, using %d instead.'
+ % (self.k, d - 1))
+ k = d - 1
+ else:
+ k = int(self.k)
+ tSb = np.zeros((d, d))
+ tSw = np.zeros((d, d))
+
+ for c in range(num_classes):
+ Xc = X[y == c]
+ nc = Xc.shape[0]
+
+ # classwise affinity matrix
+ dist = pairwise_distances(Xc, metric='l2', squared=True)
+ # distances to k-th nearest neighbor
+ k = min(k, nc - 1)
+ sigma = np.sqrt(np.partition(dist, k, axis=0)[:, k])
+
+ local_scale = np.outer(sigma, sigma)
+ with np.errstate(divide='ignore', invalid='ignore'):
+ A = np.exp(-dist / local_scale)
+ A[local_scale == 0] = 0
+
+ G = Xc.T.dot(A.sum(axis=0)[:, None] * Xc) - Xc.T.dot(A).dot(Xc)
+ tSb += G / n + (1 - nc / n) * Xc.T.dot(Xc) + _sum_outer(Xc) / n
+ tSw += G / nc
+
+ tSb -= _sum_outer(X) / n - tSw
+
+ # symmetrize
+ tSb = (tSb + tSb.T) / 2
+ tSw = (tSw + tSw.T) / 2
+
+ vals, vecs = _eigh(tSb, tSw, dim)
+ order = np.argsort(-vals)[:dim]
+ vals = vals[order].real
+ vecs = vecs[:, order]
+
+ if self.embedding_type == 'weighted':
+ vecs *= np.sqrt(vals)
+ elif self.embedding_type == 'orthonormalized':
+ vecs, _ = np.linalg.qr(vecs)
+
+ self.components_ = vecs.T
+ return self
+
+
+
+
+def _sum_outer(x):
+ s = x.sum(axis=0)
+ return np.outer(s, s)
+
+
+def _eigh(a, b, dim):
+ try:
+ return scipy.sparse.linalg.eigsh(a, k=dim, M=b, which='LA')
+ except np.linalg.LinAlgError:
+ pass # scipy already tried eigh for us
+ except (ValueError, scipy.sparse.linalg.ArpackNoConvergence):
+ try:
+ return scipy.linalg.eigh(a, b)
+ except np.linalg.LinAlgError:
+ pass
+ return scipy.linalg.eig(a, b)
+
+"""
+Large Margin Nearest Neighbor Metric learning (LMNN)
+"""
+import numpy as np
+from collections import Counter
+from sklearn.metrics import euclidean_distances
+from sklearn.base import TransformerMixin
+import warnings
+
+from ._util import _initialize_components, _check_n_components
+from .base_metric import MahalanobisMixin
+
+
+
+[docs]
+class LMNN(MahalanobisMixin, TransformerMixin):
+ """Large Margin Nearest Neighbor (LMNN)
+
+ LMNN learns a Mahalanobis distance metric in the kNN classification
+ setting. The learned metric attempts to keep close k-nearest neighbors
+ from the same class, while keeping examples from different classes
+ separated by a large margin. This algorithm makes no assumptions about
+ the distribution of the data.
+
+ Read more in the :ref:`User Guide <lmnn>`.
+
+ Parameters
+ ----------
+ init : string or numpy array, optional (default='auto')
+ Initialization of the linear transformation. Possible options are
+ 'auto', 'pca', 'identity', 'random', and a numpy array of shape
+ (n_features_a, n_features_b).
+
+ 'auto'
+ Depending on ``n_components``, the most reasonable initialization
+ will be chosen. If ``n_components <= n_classes`` we use 'lda', as
+ it uses labels information. If not, but
+ ``n_components < min(n_features, n_samples)``, we use 'pca', as
+ it projects data in meaningful directions (those of higher
+ variance). Otherwise, we just use 'identity'.
+
+ 'pca'
+ ``n_components`` principal components of the inputs passed
+ to :meth:`fit` will be used to initialize the transformation.
+ (See `sklearn.decomposition.PCA`)
+
+ 'lda'
+ ``min(n_components, n_classes)`` most discriminative
+ components of the inputs passed to :meth:`fit` will be used to
+ initialize the transformation. (If ``n_components > n_classes``,
+ the rest of the components will be zero.) (See
+ `sklearn.discriminant_analysis.LinearDiscriminantAnalysis`)
+
+ 'identity'
+ If ``n_components`` is strictly smaller than the
+ dimensionality of the inputs passed to :meth:`fit`, the identity
+ matrix will be truncated to the first ``n_components`` rows.
+
+ 'random'
+ The initial transformation will be a random array of shape
+ `(n_components, n_features)`. Each value is sampled from the
+ standard normal distribution.
+
+ numpy array
+ n_features_b must match the dimensionality of the inputs passed to
+ :meth:`fit` and n_features_a must be less than or equal to that.
+ If ``n_components`` is not None, n_features_a must match it.
+
+ n_neighbors : int, optional (default=3)
+ Number of neighbors to consider, not including self-edges.
+
+ min_iter : int, optional (default=50)
+ Minimum number of iterations of the optimization procedure.
+
+ max_iter : int, optional (default=1000)
+ Maximum number of iterations of the optimization procedure.
+
+ learn_rate : float, optional (default=1e-7)
+ Learning rate of the optimization procedure
+
+ tol : float, optional (default=0.001)
+ Tolerance of the optimization procedure. If the objective value varies
+ less than `tol`, we consider the algorithm has converged and stop it.
+
+ verbose : bool, optional (default=False)
+ Whether to print the progress of the optimization procedure.
+
+ regularization: float, optional (default=0.5)
+ Relative weight between pull and push terms, with 0.5 meaning equal
+ weight.
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ n_components : int or None, optional (default=None)
+ Dimensionality of reduced space (if None, defaults to dimension of X).
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``init='random'``, ``random_state`` is used to initialize the random
+ transformation. If ``init='pca'``, ``random_state`` is passed as an
+ argument to PCA when initializing the transformation.
+
+ k : Renamed to n_neighbors. Will be deprecated in 0.7.0
+
+ Attributes
+ ----------
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_components, n_features)
+ The learned linear transformation ``L``.
+
+ Examples
+ --------
+
+ >>> import numpy as np
+ >>> from metric_learn import LMNN
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> lmnn = LMNN(n_neighbors=5, learn_rate=1e-6)
+ >>> lmnn.fit(X, Y, verbose=False)
+
+ References
+ ----------
+ .. [1] K. Q. Weinberger, J. Blitzer, L. K. Saul. `Distance Metric
+ Learning for Large Margin Nearest Neighbor Classification
+ <http://papers.nips.cc/paper/2795-distance-metric\
+ -learning-for-large-margin-nearest-neighbor-classification>`_. NIPS
+ 2005.
+ """
+
+
+[docs]
+ def __init__(self, init='auto', n_neighbors=3, min_iter=50, max_iter=1000,
+ learn_rate=1e-7, regularization=0.5, convergence_tol=0.001,
+ verbose=False, preprocessor=None,
+ n_components=None, random_state=None, k='deprecated'):
+ self.init = init
+ if k != 'deprecated':
+ warnings.warn('"num_chunks" parameter has been renamed to'
+ ' "n_chunks". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ n_neighbors = k
+ self.k = 'deprecated' # To avoid no_attribute error
+ self.n_neighbors = n_neighbors
+ self.min_iter = min_iter
+ self.max_iter = max_iter
+ self.learn_rate = learn_rate
+ self.regularization = regularization
+ self.convergence_tol = convergence_tol
+ self.verbose = verbose
+ self.n_components = n_components
+ self.random_state = random_state
+ super(LMNN, self).__init__(preprocessor)
+
+
+
+[docs]
+ def fit(self, X, y):
+ k = self.n_neighbors
+ reg = self.regularization
+ learn_rate = self.learn_rate
+
+ X, y = self._prepare_inputs(X, y, dtype=float,
+ ensure_min_samples=2)
+ num_pts, d = X.shape
+ output_dim = _check_n_components(d, self.n_components)
+ unique_labels, label_inds = np.unique(y, return_inverse=True)
+ if len(label_inds) != num_pts:
+ raise ValueError('Must have one label per point.')
+ self.labels_ = np.arange(len(unique_labels))
+
+ self.components_ = _initialize_components(output_dim, X, y, self.init,
+ self.verbose,
+ random_state=self.random_state)
+ required_k = np.bincount(label_inds).min()
+ if self.n_neighbors > required_k:
+ raise ValueError('not enough class labels for specified k'
+ ' (smallest class has %d)' % required_k)
+
+ target_neighbors = self._select_targets(X, label_inds)
+
+ # sum outer products
+ dfG = _sum_outer_products(X, target_neighbors.flatten(),
+ np.repeat(np.arange(X.shape[0]), k))
+
+ # initialize L
+ L = self.components_
+
+ # first iteration: we compute variables (including objective and gradient)
+ # at initialization point
+ G, objective, total_active = self._loss_grad(X, L, dfG, k,
+ reg, target_neighbors,
+ label_inds)
+
+ it = 1 # we already made one iteration
+
+ if self.verbose:
+ print("iter | objective | objective difference | active constraints",
+ "| learning rate")
+
+ # main loop
+ for it in range(2, self.max_iter):
+ # then at each iteration, we try to find a value of L that has better
+ # objective than the previous L, following the gradient:
+ while True:
+ # the next point next_L to try out is found by a gradient step
+ L_next = L - learn_rate * G
+ # we compute the objective at next point
+ # we copy variables that can be modified by _loss_grad, because if we
+ # retry we don t want to modify them several times
+ (G_next, objective_next, total_active_next) = (
+ self._loss_grad(X, L_next, dfG, k, reg, target_neighbors,
+ label_inds))
+ assert not np.isnan(objective)
+ delta_obj = objective_next - objective
+ if delta_obj > 0:
+ # if we did not find a better objective, we retry with an L closer to
+ # the starting point, by decreasing the learning rate (making the
+ # gradient step smaller)
+ learn_rate /= 2
+ else:
+ # otherwise, if we indeed found a better obj, we get out of the loop
+ break
+ # when the better L is found (and the related variables), we set the
+ # old variables to these new ones before next iteration and we
+ # slightly increase the learning rate
+ L = L_next
+ G, objective, total_active = G_next, objective_next, total_active_next
+ learn_rate *= 1.01
+
+ if self.verbose:
+ print(it, objective, delta_obj, total_active, learn_rate)
+
+ # check for convergence
+ if it > self.min_iter and abs(delta_obj) < self.convergence_tol:
+ if self.verbose:
+ print("LMNN converged with objective", objective)
+ break
+ else:
+ if self.verbose:
+ print("LMNN didn't converge in %d steps." % self.max_iter)
+
+ # store the last L
+ self.components_ = L
+ self.n_iter_ = it
+ return self
+
+
+ def _loss_grad(self, X, L, dfG, k, reg, target_neighbors, label_inds):
+ # Compute pairwise distances under current metric
+ Lx = L.dot(X.T).T
+
+ # we need to find the furthest neighbor:
+ Ni = 1 + _inplace_paired_L2(Lx[target_neighbors], Lx[:, None, :])
+ furthest_neighbors = np.take_along_axis(target_neighbors,
+ Ni.argmax(axis=1)[:, None], 1)
+ impostors = self._find_impostors(furthest_neighbors.ravel(), X,
+ label_inds, L)
+
+ g0 = _inplace_paired_L2(*Lx[impostors])
+
+ # we reorder the target neighbors
+ g1, g2 = Ni[impostors]
+ # compute the gradient
+ total_active = 0
+ df = np.zeros((X.shape[1], X.shape[1]))
+ for nn_idx in reversed(range(k)): # note: reverse not useful here
+ act1 = g0 < g1[:, nn_idx]
+ act2 = g0 < g2[:, nn_idx]
+ total_active += act1.sum() + act2.sum()
+
+ targets = target_neighbors[:, nn_idx]
+ PLUS, pweight = _count_edges(act1, act2, impostors, targets)
+ df += _sum_outer_products(X, PLUS[:, 0], PLUS[:, 1], pweight)
+
+ in_imp, out_imp = impostors
+ df -= _sum_outer_products(X, in_imp[act1], out_imp[act1])
+ df -= _sum_outer_products(X, in_imp[act2], out_imp[act2])
+
+ # do the gradient update
+ assert not np.isnan(df).any()
+ G = dfG * reg + df * (1 - reg)
+ G = L.dot(G)
+ # compute the objective function
+ objective = total_active * (1 - reg)
+ objective += G.flatten().dot(L.flatten())
+ return 2 * G, objective, total_active
+
+ def _select_targets(self, X, label_inds):
+ target_neighbors = np.empty((X.shape[0], self.n_neighbors), dtype=int)
+ for label in self.labels_:
+ inds, = np.nonzero(label_inds == label)
+ dd = euclidean_distances(X[inds], squared=True)
+ np.fill_diagonal(dd, np.inf)
+ nn = np.argsort(dd)[..., :self.n_neighbors]
+ target_neighbors[inds] = inds[nn]
+ return target_neighbors
+
+ def _find_impostors(self, furthest_neighbors, X, label_inds, L):
+ Lx = X.dot(L.T)
+ margin_radii = 1 + _inplace_paired_L2(Lx[furthest_neighbors], Lx)
+ impostors = []
+ for label in self.labels_[:-1]:
+ in_inds, = np.nonzero(label_inds == label)
+ out_inds, = np.nonzero(label_inds > label)
+ dist = euclidean_distances(Lx[out_inds], Lx[in_inds], squared=True)
+ i1, j1 = np.nonzero(dist < margin_radii[out_inds][:, None])
+ i2, j2 = np.nonzero(dist < margin_radii[in_inds])
+ i = np.hstack((i1, i2))
+ j = np.hstack((j1, j2))
+ if i.size > 0:
+ # get unique (i,j) pairs using index trickery
+ shape = (i.max() + 1, j.max() + 1)
+ tmp = np.ravel_multi_index((i, j), shape)
+ i, j = np.unravel_index(np.unique(tmp), shape)
+ impostors.append(np.vstack((in_inds[j], out_inds[i])))
+ if len(impostors) == 0:
+ # No impostors detected
+ return impostors
+ return np.hstack(impostors)
+
+
+
+def _inplace_paired_L2(A, B):
+ '''Equivalent to ((A-B)**2).sum(axis=-1), but modifies A in place.'''
+ A -= B
+ return np.einsum('...ij,...ij->...i', A, A)
+
+
+def _count_edges(act1, act2, impostors, targets):
+ imp = impostors[0, act1]
+ c = Counter(zip(imp, targets[imp]))
+ imp = impostors[1, act2]
+ c.update(zip(imp, targets[imp]))
+ if c:
+ active_pairs = np.array(list(c.keys()))
+ else:
+ active_pairs = np.empty((0, 2), dtype=int)
+ return active_pairs, np.array(list(c.values()))
+
+
+def _sum_outer_products(data, a_inds, b_inds, weights=None):
+ Xab = data[a_inds] - data[b_inds]
+ if weights is not None:
+ return np.dot(Xab.T, Xab * weights[:, None])
+ return np.dot(Xab.T, Xab)
+
+"""
+Metric Learning from Relative Comparisons by Minimizing Squared Residual (LSML)
+"""
+
+import numpy as np
+import scipy.linalg
+from sklearn.base import TransformerMixin
+
+from .base_metric import _QuadrupletsClassifierMixin, MahalanobisMixin
+from .constraints import Constraints
+from ._util import components_from_metric, _initialize_metric_mahalanobis
+import warnings
+
+
+class _BaseLSML(MahalanobisMixin):
+
+ _tuple_size = 4 # constraints are quadruplets
+
+ def __init__(self, tol=1e-3, max_iter=1000, prior='identity',
+ verbose=False, preprocessor=None, random_state=None):
+ self.prior = prior
+ self.tol = tol
+ self.max_iter = max_iter
+ self.verbose = verbose
+ self.random_state = random_state
+ super(_BaseLSML, self).__init__(preprocessor)
+
+ def _fit(self, quadruplets, weights=None):
+ quadruplets = self._prepare_inputs(quadruplets,
+ type_of_inputs='tuples')
+
+ # check to make sure that no two constrained vectors are identical
+ vab = quadruplets[:, 0, :] - quadruplets[:, 1, :]
+ vcd = quadruplets[:, 2, :] - quadruplets[:, 3, :]
+ if vab.shape != vcd.shape:
+ raise ValueError('Constraints must have same length')
+ if weights is None:
+ self.w_ = np.ones(vab.shape[0])
+ else:
+ self.w_ = weights
+ self.w_ /= self.w_.sum() # weights must sum to 1
+ M, prior_inv = _initialize_metric_mahalanobis(
+ quadruplets, self.prior,
+ return_inverse=True, strict_pd=True, matrix_name='prior',
+ random_state=self.random_state)
+
+ step_sizes = np.logspace(-10, 0, 10)
+ # Keep track of the best step size and the loss at that step.
+ l_best = 0
+ s_best = self._total_loss(M, vab, vcd, prior_inv)
+ if self.verbose:
+ print('initial loss', s_best)
+ for it in range(1, self.max_iter + 1):
+ grad = self._gradient(M, vab, vcd, prior_inv)
+ grad_norm = scipy.linalg.norm(grad)
+ if grad_norm < self.tol:
+ break
+ if self.verbose:
+ print('gradient norm', grad_norm)
+ M_best = None
+ for step_size in step_sizes:
+ step_size /= grad_norm
+ new_metric = M - step_size * grad
+ w, v = scipy.linalg.eigh(new_metric)
+ new_metric = v.dot((np.maximum(w, 1e-8) * v).T)
+ cur_s = self._total_loss(new_metric, vab, vcd, prior_inv)
+ if cur_s < s_best:
+ l_best = step_size
+ s_best = cur_s
+ M_best = new_metric
+ if self.verbose:
+ print('iter', it, 'cost', s_best, 'best step', l_best * grad_norm)
+ if M_best is None:
+ break
+ M = M_best
+ else:
+ if self.verbose:
+ print("Didn't converge after", it, "iterations. Final loss:", s_best)
+ self.n_iter_ = it
+
+ self.components_ = components_from_metric(M)
+ return self
+
+ def _comparison_loss(self, metric, vab, vcd):
+ dab = np.sum(vab.dot(metric) * vab, axis=1)
+ dcd = np.sum(vcd.dot(metric) * vcd, axis=1)
+ violations = dab > dcd
+ return self.w_[violations].dot((np.sqrt(dab[violations]) -
+ np.sqrt(dcd[violations]))**2)
+
+ def _total_loss(self, metric, vab, vcd, prior_inv):
+ # Regularization loss
+ sign, logdet = np.linalg.slogdet(metric)
+ reg_loss = np.sum(metric * prior_inv) - sign * logdet
+ return self._comparison_loss(metric, vab, vcd) + reg_loss
+
+ def _gradient(self, metric, vab, vcd, prior_inv):
+ dMetric = prior_inv - np.linalg.inv(metric)
+ dabs = np.sum(vab.dot(metric) * vab, axis=1)
+ dcds = np.sum(vcd.dot(metric) * vcd, axis=1)
+ violations = dabs > dcds
+ # TODO: vectorize
+ for vab, dab, vcd, dcd in zip(vab[violations], dabs[violations],
+ vcd[violations], dcds[violations]):
+ dMetric += ((1 - np.sqrt(dcd / dab)) * np.outer(vab, vab) +
+ (1 - np.sqrt(dab / dcd)) * np.outer(vcd, vcd))
+ return dMetric
+
+
+
+[docs]
+class LSML(_BaseLSML, _QuadrupletsClassifierMixin):
+ """Least Squared-residual Metric Learning (LSML)
+
+ `LSML` proposes a simple, yet effective, algorithm that minimizes a convex
+ objective function corresponding to the sum of squared residuals of
+ constraints. This algorithm uses the constraints in the form of the
+ relative distance comparisons, such method is especially useful where
+ pairwise constraints are not natural to obtain, thus pairwise constraints
+ based algorithms become infeasible to be deployed. Furthermore, its sparsity
+ extension leads to more stable estimation when the dimension is high and
+ only a small amount of constraints is given.
+
+ Read more in the :ref:`User Guide <lsml>`.
+
+ Parameters
+ ----------
+ prior : string or numpy array, optional (default='identity')
+ Prior to set for the metric. Possible options are
+ 'identity', 'covariance', 'random', and a numpy array of
+ shape (n_features, n_features). For LSML, the prior should be strictly
+ positive definite (PD).
+
+ 'identity'
+ An identity matrix of shape (n_features, n_features).
+
+ 'covariance'
+ The inverse covariance matrix.
+
+ 'random'
+ The initial Mahalanobis matrix will be a random positive definite
+ (PD) matrix of shape `(n_features, n_features)`, generated using
+ `sklearn.datasets.make_spd_matrix`.
+
+ numpy array
+ A positive definite (PD) matrix of shape
+ (n_features, n_features), that will be used as such to set the
+ prior.
+
+ tol : float, optional (default=1e-3)
+ Convergence tolerance of the optimization procedure.
+
+ max_iter : int, optional (default=1000)
+ Maximum number of iteration of the optimization procedure.
+
+ verbose : bool, optional (default=False)
+ If True, prints information while learning
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``init='random'``, ``random_state`` is used to set the random
+ prior.
+
+ Attributes
+ ----------
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+
+ Examples
+ --------
+ >>> from metric_learn import LSML
+ >>> quadruplets = [[[1.2, 7.5], [1.3, 1.5], [6.4, 2.6], [6.2, 9.7]],
+ >>> [[1.3, 4.5], [3.2, 4.6], [6.2, 5.5], [5.4, 5.4]],
+ >>> [[3.2, 7.5], [3.3, 1.5], [8.4, 2.6], [8.2, 9.7]],
+ >>> [[3.3, 4.5], [5.2, 4.6], [8.2, 5.5], [7.4, 5.4]]]
+ >>> # we want to make closer points where the first feature is close, and
+ >>> # further if the second feature is close
+ >>> lsml = LSML()
+ >>> lsml.fit(quadruplets)
+
+ References
+ ----------
+ .. [1] Liu et al. `Metric Learning from Relative Comparisons by Minimizing
+ Squared Residual
+ <http://www.cs.ucla.edu/~weiwang/paper/ICDM12.pdf>`_. ICDM 2012.
+
+ .. [2] Code adapted from https://gist.github.com/kcarnold/5439917
+
+ See Also
+ --------
+ metric_learn.LSML : The original weakly-supervised algorithm
+
+ :ref:`supervised_version` : The section of the project documentation
+ that describes the supervised version of weakly supervised estimators.
+ """
+
+
+[docs]
+ def fit(self, quadruplets, weights=None):
+ """Learn the LSML model.
+
+ Parameters
+ ----------
+ quadruplets : array-like, shape=(n_constraints, 4, n_features) or \
+ (n_constraints, 4)
+ 3D array-like of quadruplets of points or 2D array of quadruplets of
+ indicators. In order to supervise the algorithm in the right way, we
+ should have the four samples ordered in a way such that:
+ d(pairs[i, 0],X[i, 1]) < d(X[i, 2], X[i, 3]) for all 0 <= i <
+ n_constraints.
+
+ weights : (n_constraints,) array of floats, optional
+ scale factor for each constraint
+
+ Returns
+ -------
+ self : object
+ Returns the instance.
+ """
+ return self._fit(quadruplets, weights=weights)
+
+
+
+
+
+[docs]
+class LSML_Supervised(_BaseLSML, TransformerMixin):
+ """Supervised version of Least Squared-residual Metric Learning (LSML)
+
+ `LSML_Supervised` creates quadruplets from labeled samples by taking two
+ samples from the same class, and two samples from different classes.
+ This way it builds quadruplets where the two first points must be more
+ similar than the two last points.
+
+ Parameters
+ ----------
+ tol : float, optional (default=1e-3)
+ Convergence tolerance of the optimization procedure.
+
+ max_iter : int, optional (default=1000)
+ Number of maximum iterations of the optimization procedure.
+
+ prior : string or numpy array, optional (default='identity')
+ Prior to set for the metric. Possible options are
+ 'identity', 'covariance', 'random', and a numpy array of
+ shape (n_features, n_features). For LSML, the prior should be strictly
+ positive definite (PD).
+
+ 'identity'
+ An identity matrix of shape (n_features, n_features).
+
+ 'covariance'
+ The inverse covariance matrix.
+
+ 'random'
+ The initial Mahalanobis matrix will be a random positive definite
+ (PD) matrix of shape `(n_features, n_features)`, generated using
+ `sklearn.datasets.make_spd_matrix`.
+
+ numpy array
+ A positive definite (PD) matrix of shape
+ (n_features, n_features), that will be used as such to set the
+ prior.
+
+ n_constraints: int, optional (default=None)
+ Number of constraints to generate. If None, default to `20 *
+ num_classes**2`.
+
+ weights : (n_constraints,) array of floats, optional (default=None)
+ Relative weight given to each constraint. If None, defaults to uniform
+ weights.
+
+ verbose : bool, optional (default=False)
+ If True, prints information while learning
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``init='random'``, ``random_state`` is used to set the random
+ prior. In any case, `random_state` is also used to randomly sample
+ constraints from labels.
+
+ num_constraints : Renamed to n_constraints. Will be deprecated in 0.7.0
+
+ Examples
+ --------
+ >>> from metric_learn import LSML_Supervised
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> lsml = LSML_Supervised(n_constraints=200)
+ >>> lsml.fit(X, Y)
+
+ Attributes
+ ----------
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+ """
+
+
+[docs]
+ def __init__(self, tol=1e-3, max_iter=1000, prior='identity',
+ n_constraints=None, weights=None,
+ verbose=False, preprocessor=None, random_state=None,
+ num_constraints='deprecated'):
+ _BaseLSML.__init__(self, tol=tol, max_iter=max_iter, prior=prior,
+ verbose=verbose, preprocessor=preprocessor,
+ random_state=random_state)
+ if num_constraints != 'deprecated':
+ warnings.warn('"num_constraints" parameter has been renamed to'
+ ' "n_constraints". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ self.n_constraints = num_constraints
+ else:
+ self.n_constraints = n_constraints
+ # Avoid test get_params from failing (all params passed sholud be set)
+ self.num_constraints = 'deprecated'
+ self.weights = weights
+
+
+
+[docs]
+ def fit(self, X, y):
+ """Create constraints from labels and learn the LSML model.
+
+ Parameters
+ ----------
+ X : (n x d) matrix
+ Input data, where each row corresponds to a single instance.
+
+ y : (n) array-like
+ Data labels.
+ """
+ X, y = self._prepare_inputs(X, y, ensure_min_samples=2)
+ n_constraints = self.n_constraints
+ if n_constraints is None:
+ num_classes = len(np.unique(y))
+ n_constraints = 20 * num_classes**2
+
+ c = Constraints(y)
+ pos_neg = c.positive_negative_pairs(n_constraints, same_length=True,
+ random_state=self.random_state)
+ return _BaseLSML._fit(self, X[np.column_stack(pos_neg)],
+ weights=self.weights)
+
+
+
+"""
+Metric Learning for Kernel Regression (MLKR)
+"""
+import time
+import sys
+import warnings
+import numpy as np
+from scipy.optimize import minimize
+from scipy.special import logsumexp
+from sklearn.base import TransformerMixin
+from sklearn.exceptions import ConvergenceWarning
+from sklearn.metrics import pairwise_distances
+
+from .base_metric import MahalanobisMixin
+from ._util import _initialize_components, _check_n_components
+
+EPS = np.finfo(float).eps
+
+
+
+[docs]
+class MLKR(MahalanobisMixin, TransformerMixin):
+ """Metric Learning for Kernel Regression (MLKR)
+
+ MLKR is an algorithm for supervised metric learning, which learns a
+ distance function by directly minimizing the leave-one-out regression error.
+ This algorithm can also be viewed as a supervised variation of PCA and can be
+ used for dimensionality reduction and high dimensional data visualization.
+
+ Read more in the :ref:`User Guide <mlkr>`.
+
+ Parameters
+ ----------
+ n_components : int or None, optional (default=None)
+ Dimensionality of reduced space (if None, defaults to dimension of X).
+
+ init : string or numpy array, optional (default='auto')
+ Initialization of the linear transformation. Possible options are
+ 'auto', 'pca', 'identity', 'random', and a numpy array of shape
+ (n_features_a, n_features_b).
+
+ 'auto'
+ Depending on ``n_components``, the most reasonable initialization
+ will be chosen. If ``n_components < min(n_features, n_samples)``,
+ we use 'pca', as it projects data in meaningful directions (those
+ of higher variance). Otherwise, we just use 'identity'.
+
+ 'pca'
+ ``n_components`` principal components of the inputs passed
+ to :meth:`fit` will be used to initialize the transformation.
+ (See `sklearn.decomposition.PCA`)
+
+ 'identity'
+ If ``n_components`` is strictly smaller than the
+ dimensionality of the inputs passed to :meth:`fit`, the identity
+ matrix will be truncated to the first ``n_components`` rows.
+
+ 'random'
+ The initial transformation will be a random array of shape
+ `(n_components, n_features)`. Each value is sampled from the
+ standard normal distribution.
+
+ numpy array
+ n_features_b must match the dimensionality of the inputs passed to
+ :meth:`fit` and n_features_a must be less than or equal to that.
+ If ``n_components`` is not None, n_features_a must match it.
+
+ tol : float, optional (default=None)
+ Convergence tolerance for the optimization.
+
+ max_iter : int, optional (default=1000)
+ Cap on number of conjugate gradient iterations.
+
+ verbose : bool, optional (default=False)
+ Whether to print progress messages or not.
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``init='random'``, ``random_state`` is used to initialize the random
+ transformation. If ``init='pca'``, ``random_state`` is passed as an
+ argument to PCA when initializing the transformation.
+
+ Attributes
+ ----------
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_components, n_features)
+ The learned linear transformation ``L``.
+
+ Examples
+ --------
+
+ >>> from metric_learn import MLKR
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> mlkr = MLKR()
+ >>> mlkr.fit(X, Y)
+
+ References
+ ----------
+ .. [1] K.Q. Weinberger and G. Tesauto. `Metric Learning for Kernel
+ Regression <http://proceedings.mlr.press/v2/weinberger07a\
+ /weinberger07a.pdf>`_. AISTATS 2007.
+ """
+
+
+[docs]
+ def __init__(self, n_components=None, init='auto',
+ tol=None, max_iter=1000, verbose=False,
+ preprocessor=None, random_state=None):
+ self.n_components = n_components
+ self.init = init
+ self.tol = tol
+ self.max_iter = max_iter
+ self.verbose = verbose
+ self.random_state = random_state
+ super(MLKR, self).__init__(preprocessor)
+
+
+
+[docs]
+ def fit(self, X, y):
+ """
+ Fit MLKR model
+
+ Parameters
+ ----------
+ X : (n x d) array of samples
+ y : (n) data labels
+ """
+ X, y = self._prepare_inputs(X, y, y_numeric=True,
+ ensure_min_samples=2)
+ n, d = X.shape
+ if y.shape[0] != n:
+ raise ValueError('Data and label lengths mismatch: %d != %d'
+ % (n, y.shape[0]))
+
+ m = _check_n_components(d, self.n_components)
+ m = self.n_components
+ if m is None:
+ m = d
+ # if the init is the default (None), we raise a warning
+ A = _initialize_components(m, X, y, init=self.init,
+ random_state=self.random_state,
+ # MLKR works on regression targets:
+ has_classes=False)
+
+ # Measure the total training time
+ train_time = time.time()
+
+ self.n_iter_ = 0
+ res = minimize(self._loss, A.ravel(), (X, y), method='L-BFGS-B',
+ jac=True, tol=self.tol,
+ options=dict(maxiter=self.max_iter))
+ self.components_ = res.x.reshape(A.shape)
+
+ # Stop timer
+ train_time = time.time() - train_time
+ if self.verbose:
+ cls_name = self.__class__.__name__
+ # Warn the user if the algorithm did not converge
+ if not res.success:
+ warnings.warn('[{}] MLKR did not converge: {}'
+ .format(cls_name, res.message), ConvergenceWarning)
+ print('[{}] Training took {:8.2f}s.'.format(cls_name, train_time))
+
+ return self
+
+
+ def _loss(self, flatA, X, y):
+
+ if self.n_iter_ == 0 and self.verbose:
+ header_fields = ['Iteration', 'Objective Value', 'Time(s)']
+ header_fmt = '{:>10} {:>20} {:>10}'
+ header = header_fmt.format(*header_fields)
+ cls_name = self.__class__.__name__
+ print('[{cls}]'.format(cls=cls_name))
+ print('[{cls}] {header}\n[{cls}] {sep}'.format(cls=cls_name,
+ header=header,
+ sep='-' * len(header)))
+
+ start_time = time.time()
+
+ A = flatA.reshape((-1, X.shape[1]))
+ X_embedded = np.dot(X, A.T)
+ dist = pairwise_distances(X_embedded, squared=True)
+ np.fill_diagonal(dist, np.inf)
+ softmax = np.exp(- dist - logsumexp(- dist, axis=1)[:, np.newaxis])
+ yhat = softmax.dot(y)
+ ydiff = yhat - y
+ cost = (ydiff ** 2).sum()
+
+ # also compute the gradient
+ W = softmax * ydiff[:, np.newaxis] * (y - yhat[:, np.newaxis])
+ W_sym = W + W.T
+ np.fill_diagonal(W_sym, - W.sum(axis=0))
+ grad = 4 * (X_embedded.T.dot(W_sym)).dot(X)
+
+ if self.verbose:
+ start_time = time.time() - start_time
+ values_fmt = '[{cls}] {n_iter:>10} {loss:>20.6e} {start_time:>10.2f}'
+ print(values_fmt.format(cls=self.__class__.__name__,
+ n_iter=self.n_iter_, loss=cost,
+ start_time=start_time))
+ sys.stdout.flush()
+
+ self.n_iter_ += 1
+
+ return cost, grad.ravel()
+
+
+"""Mahalanobis Metric for Clustering (MMC)"""
+import numpy as np
+from sklearn.base import TransformerMixin
+from sklearn.utils.validation import assert_all_finite
+
+from .base_metric import _PairsClassifierMixin, MahalanobisMixin
+from .constraints import Constraints, wrap_pairs
+from ._util import components_from_metric, _initialize_metric_mahalanobis
+import warnings
+
+
+class _BaseMMC(MahalanobisMixin):
+
+ _tuple_size = 2 # constraints are pairs
+
+ def __init__(self, max_iter=100, max_proj=10000, tol=1e-3,
+ init='identity', diagonal=False,
+ diagonal_c=1.0, verbose=False, preprocessor=None,
+ random_state=None,
+ convergence_threshold='deprecated'):
+ if convergence_threshold != 'deprecated':
+ warnings.warn('"convergence_threshold" parameter has been '
+ ' renamed to "tol". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ tol = convergence_threshold
+ self.convergence_threshold = 'deprecated' # Avoid errors
+ self.max_iter = max_iter
+ self.max_proj = max_proj
+ self.tol = tol
+ self.init = init
+ self.diagonal = diagonal
+ self.diagonal_c = diagonal_c
+ self.verbose = verbose
+ self.random_state = random_state
+ super(_BaseMMC, self).__init__(preprocessor)
+
+ def _fit(self, pairs, y):
+ pairs, y = self._prepare_inputs(pairs, y,
+ type_of_inputs='tuples')
+
+ self.A_ = _initialize_metric_mahalanobis(pairs, self.init,
+ random_state=self.random_state,
+ matrix_name='init')
+
+ if self.diagonal:
+ return self._fit_diag(pairs, y)
+ else:
+ return self._fit_full(pairs, y)
+
+ def _fit_full(self, pairs, y):
+ """Learn full metric using MMC.
+
+ Parameters
+ ----------
+ X : (n x d) data matrix
+ Each row corresponds to a single instance.
+ constraints : 4-tuple of arrays
+ (a,b,c,d) indices into X, with (a,b) specifying similar and (c,d)
+ dissimilar pairs.
+ """
+ num_dim = pairs.shape[2]
+
+ error2 = 1e10
+ eps = 0.01 # error-bound of iterative projection on C1 and C2
+ A = self.A_
+
+ pos_pairs, neg_pairs = pairs[y == 1], pairs[y == -1]
+
+ # Create weight vector from similar samples
+ pos_diff = pos_pairs[:, 0, :] - pos_pairs[:, 1, :]
+ w = np.einsum('ij,ik->jk', pos_diff, pos_diff).ravel()
+ # `w` is the sum of all outer products of the rows in `pos_diff`.
+ # The above `einsum` is equivalent to the much more inefficient:
+ # w = np.apply_along_axis(
+ # lambda x: np.outer(x,x).ravel(),
+ # 1,
+ # X[a] - X[b]
+ # ).sum(axis = 0)
+ t = w.dot(A.ravel()) / 100.0
+
+ w_norm = np.linalg.norm(w)
+ w1 = w / w_norm # make `w` a unit vector
+ t1 = t / w_norm # distance from origin to `w^T*x=t` plane
+
+ cycle = 1
+ alpha = 0.1 # initial step size along gradient
+ grad1 = self._fS1(pos_pairs, A) # gradient of similarity
+ # constraint function
+ grad2 = self._fD1(neg_pairs, A) # gradient of dissimilarity
+ # constraint function
+ # gradient of fD1 orthogonal to fS1:
+ M = self._grad_projection(grad1, grad2)
+
+ A_old = A.copy()
+
+ for cycle in range(self.max_iter):
+
+ # projection of constraints C1 and C2
+ satisfy = False
+
+ for it in range(self.max_proj):
+
+ # First constraint:
+ # f(A) = \sum_{i,j \in S} d_ij' A d_ij <= t (1)
+ # (1) can be rewritten as a linear constraint: w^T x = t,
+ # where x is the unrolled matrix of A,
+ # w is also an unrolled matrix of W where
+ # W_{kl}= \sum_{i,j \in S}d_ij^k * d_ij^l
+ x0 = A.ravel()
+ if w.dot(x0) <= t:
+ x = x0
+ else:
+ x = x0 + (t1 - w1.dot(x0)) * w1
+ A[:] = x.reshape(num_dim, num_dim)
+
+ # Second constraint:
+ # PSD constraint A >= 0
+ # project A onto domain A>0
+ l, V = np.linalg.eigh((A + A.T) / 2)
+ A[:] = np.dot(V * np.maximum(0, l[None, :]), V.T)
+
+ fDC2 = w.dot(A.ravel())
+ error2 = (fDC2 - t) / t
+ if error2 < eps:
+ satisfy = True
+ break
+
+ # third constraint: gradient ascent
+ # max: g(A) >= 1
+ # here we suppose g(A) = fD(A) = \sum_{I,J \in D} sqrt(d_ij' A d_ij)
+
+ obj_previous = self._fD(neg_pairs, A_old) # g(A_old)
+ obj = self._fD(neg_pairs, A) # g(A)
+
+ if satisfy and (obj > obj_previous or cycle == 0):
+
+ # If projection of 1 and 2 is successful, and such projection
+ # improves objective function, slightly increase learning rate
+ # and update from the current A.
+ alpha *= 1.05
+ A_old[:] = A
+ grad2 = self._fS1(pos_pairs, A)
+ grad1 = self._fD1(neg_pairs, A)
+ M = self._grad_projection(grad1, grad2)
+ A += alpha * M
+
+ else:
+
+ # If projection of 1 and 2 failed, or obj <= obj_previous due
+ # to projection of 1 and 2, shrink learning rate and re-update
+ # from the previous A.
+ alpha /= 2
+ A[:] = A_old + alpha * M
+
+ delta = np.linalg.norm(alpha * M) / np.linalg.norm(A_old)
+ if delta < self.tol:
+ break
+ if self.verbose:
+ print('mmc iter: %d, conv = %f, projections = %d' %
+ (cycle, delta, it + 1))
+
+ if delta > self.tol:
+ self.converged_ = False
+ if self.verbose:
+ print('mmc did not converge, conv = %f' % (delta,))
+ else:
+ self.converged_ = True
+ if self.verbose:
+ print('mmc converged at iter %d, conv = %f' % (cycle, delta))
+ self.A_[:] = A_old
+ self.n_iter_ = cycle
+
+ self.components_ = components_from_metric(self.A_)
+ return self
+
+ def _fit_diag(self, pairs, y):
+ """Learn diagonal metric using MMC.
+ Parameters
+ ----------
+ X : (n x d) data matrix
+ Each row corresponds to a single instance.
+ constraints : 4-tuple of arrays
+ (a,b,c,d) indices into X, with (a,b) specifying similar and (c,d)
+ dissimilar pairs.
+ """
+ num_dim = pairs.shape[2]
+ pos_pairs, neg_pairs = pairs[y == 1], pairs[y == -1]
+ s_sum = np.sum((pos_pairs[:, 0, :] - pos_pairs[:, 1, :]) ** 2, axis=0)
+
+ it = 0
+ error = 1.0
+ eps = 1e-6
+ reduction = 2.0
+ w = np.diag(self.A_).copy()
+
+ while error > self.tol and it < self.max_iter:
+
+ fD0, fD_1st_d, fD_2nd_d = self._D_constraint(neg_pairs, w)
+ obj_initial = np.dot(s_sum, w) + self.diagonal_c * fD0
+ fS_1st_d = s_sum # first derivative of the similarity constraints
+
+ # gradient of the objective:
+ gradient = fS_1st_d - self.diagonal_c * fD_1st_d
+ # Hessian of the objective:
+ hessian = -self.diagonal_c * fD_2nd_d + eps * np.eye(num_dim)
+ step = np.dot(np.linalg.inv(hessian), gradient)
+
+ # Newton-Rapshon update
+ # search over optimal lambda
+ lambd = 1 # initial step-size
+ w_tmp = np.maximum(0, w - lambd * step)
+ obj = (np.dot(s_sum, w_tmp) + self.diagonal_c *
+ self._D_objective(neg_pairs, w_tmp))
+ assert_all_finite(obj)
+ obj_previous = np.inf # just to get the while-loop started
+
+ inner_it = 0
+ while obj < obj_previous:
+ obj_previous = obj
+ w_previous = w_tmp.copy()
+ lambd /= reduction
+ w_tmp = np.maximum(0, w - lambd * step)
+ obj = (np.dot(s_sum, w_tmp) + self.diagonal_c *
+ self._D_objective(neg_pairs, w_tmp))
+ inner_it += 1
+ assert_all_finite(obj)
+
+ w[:] = w_previous
+ error = np.abs((obj_previous - obj_initial) / obj_previous)
+ if self.verbose:
+ print('mmc iter: %d, conv = %f' % (it, error))
+ it += 1
+
+ self.A_ = np.diag(w)
+
+ self.components_ = components_from_metric(self.A_)
+ return self
+
+ def _fD(self, neg_pairs, A):
+ r"""The value of the dissimilarity constraint function.
+
+ f = f(\sum_{ij \in D} distance(x_i, x_j))
+ i.e. distance can be L1: \sqrt{(x_i-x_j)A(x_i-x_j)'}
+ """
+ diff = neg_pairs[:, 0, :] - neg_pairs[:, 1, :]
+ return np.log(np.sum(np.sqrt(np.sum(np.dot(diff, A) * diff, axis=1))) +
+ 1e-6)
+
+ def _fD1(self, neg_pairs, A):
+ r"""The gradient of the dissimilarity constraint function w.r.t. A.
+
+ For example, let distance by L1 norm:
+ f = f(\sum_{ij \in D} \sqrt{(x_i-x_j)A(x_i-x_j)'})
+ df/dA_{kl} = f'* d(\sum_{ij \in D} \sqrt{(x_i-x_j)^k*(x_i-x_j)^l})/dA_{kl}
+
+ Note that d_ij*A*d_ij' = tr(d_ij*A*d_ij') = tr(d_ij'*d_ij*A)
+ so, d(d_ij*A*d_ij')/dA = d_ij'*d_ij
+ df/dA = f'(\sum_{ij \in D} \sqrt{tr(d_ij'*d_ij*A)})
+ * 0.5*(\sum_{ij \in D} (1/sqrt{tr(d_ij'*d_ij*A)})*(d_ij'*d_ij))
+ """
+ diff = neg_pairs[:, 0, :] - neg_pairs[:, 1, :]
+ # outer products of all rows in `diff`
+ M = np.einsum('ij,ik->ijk', diff, diff)
+ # faster version of: dist = np.sqrt(np.sum(M * A[None,:,:], axis=(1,2)))
+ dist = np.sqrt(np.einsum('ijk,jk', M, A))
+ # faster version of: sum_deri = np.sum(M /
+ # (2 * (dist[:,None,None] + 1e-6)), axis=0)
+ sum_deri = np.einsum('ijk,i->jk', M, 0.5 / (dist + 1e-6))
+ sum_dist = dist.sum()
+ return sum_deri / (sum_dist + 1e-6)
+
+ def _fS1(self, pos_pairs, A):
+ r"""The gradient of the similarity constraint function w.r.t. A.
+
+ f = \sum_{ij}(x_i-x_j)A(x_i-x_j)' = \sum_{ij}d_ij*A*d_ij'
+ df/dA = d(d_ij*A*d_ij')/dA
+
+ Note that d_ij*A*d_ij' = tr(d_ij*A*d_ij') = tr(d_ij'*d_ij*A)
+ so, d(d_ij*A*d_ij')/dA = d_ij'*d_ij
+ """
+ diff = pos_pairs[:, 0, :] - pos_pairs[:, 1, :]
+ # sum of outer products of all rows in `diff`:
+ return np.einsum('ij,ik->jk', diff, diff)
+
+ def _grad_projection(self, grad1, grad2):
+ grad2 = grad2 / np.linalg.norm(grad2)
+ gtemp = grad1 - np.sum(grad1 * grad2) * grad2
+ gtemp /= np.linalg.norm(gtemp)
+ return gtemp
+
+ def _D_objective(self, neg_pairs, w):
+ return np.log(np.sum(np.sqrt(np.sum(((neg_pairs[:, 0, :] -
+ neg_pairs[:, 1, :]) ** 2) *
+ w[None, :], axis=1) + 1e-6)))
+
+ def _D_constraint(self, neg_pairs, w):
+ """Compute the value, 1st derivative, second derivative (Hessian) of
+ a dissimilarity constraint function gF(sum_ij distance(d_ij A d_ij))
+ where A is a diagonal matrix (in the form of a column vector 'w').
+ """
+ diff = neg_pairs[:, 0, :] - neg_pairs[:, 1, :]
+ diff_sq = diff * diff
+ dist = np.sqrt(diff_sq.dot(w))
+ sum_deri1 = np.einsum('ij,i', diff_sq, 0.5 / np.maximum(dist, 1e-6))
+ sum_deri2 = np.einsum(
+ 'ij,ik->jk',
+ diff_sq,
+ diff_sq / (-4 * np.maximum(1e-6, dist**3))[:, None]
+ )
+ sum_dist = dist.sum()
+ return (
+ np.log(sum_dist),
+ sum_deri1 / sum_dist,
+ sum_deri2 / sum_dist -
+ np.outer(sum_deri1, sum_deri1) / (sum_dist * sum_dist)
+ )
+
+
+
+[docs]
+class MMC(_BaseMMC, _PairsClassifierMixin):
+ """Mahalanobis Metric for Clustering (MMC)
+
+ MMC minimizes the sum of squared distances between similar points, while
+ enforcing the sum of distances between dissimilar ones to be greater than
+ one. This leads to a convex and, thus, local-minima-free optimization
+ problem that can be solved efficiently.
+ However, the algorithm involves the computation of eigenvalues, which is the
+ main speed-bottleneck. Since it has initially been designed for clustering
+ applications, one of the implicit assumptions of MMC is that all classes form
+ a compact set, i.e., follow a unimodal distribution, which restricts the
+ possible use-cases of this method. However, it is one of the earliest and a
+ still often cited technique.
+
+ Read more in the :ref:`User Guide <mmc>`.
+
+ Parameters
+ ----------
+ max_iter : int, optional (default=100)
+ Maximum number of iterations of the optimization procedure.
+
+ max_proj : int, optional (default=10000)
+ Maximum number of projection steps.
+
+ tol : float, optional (default=1e-3)
+ Convergence threshold for the optimization procedure.
+
+ init : string or numpy array, optional (default='identity')
+ Initialization of the Mahalanobis matrix. Possible options are
+ 'identity', 'covariance', 'random', and a numpy array of
+ shape (n_features, n_features).
+
+ 'identity'
+ An identity matrix of shape (n_features, n_features).
+
+ 'covariance'
+ The (pseudo-)inverse of the covariance matrix.
+
+ 'random'
+ The initial Mahalanobis matrix will be a random SPD matrix of
+ shape
+ `(n_features, n_features)`, generated using
+ `sklearn.datasets.make_spd_matrix`.
+
+ numpy array
+ An SPD matrix of shape (n_features, n_features), that will
+ be used as such to initialize the metric.
+
+ diagonal : bool, optional (default=False)
+ If True, a diagonal metric will be learned,
+ i.e., a simple scaling of dimensions. The initialization will then
+ be the diagonal coefficients of the matrix given as 'init'.
+
+ diagonal_c : float, optional (default=1.0)
+ Weight of the dissimilarity constraint for diagonal
+ metric learning. Ignored if ``diagonal=False``.
+
+ verbose : bool, optional (default=False)
+ If True, prints information while learning
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be gotten like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``init='random'``, ``random_state`` is used to initialize the random
+ transformation.
+
+ convergence_threshold : Renamed to tol. Will be deprecated in 0.7.0
+
+ Attributes
+ ----------
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+
+ threshold_ : `float`
+ If the distance metric between two points is lower than this threshold,
+ points will be classified as similar, otherwise they will be
+ classified as dissimilar.
+
+ Examples
+ --------
+ >>> from metric_learn import MMC
+ >>> pairs = [[[1.2, 7.5], [1.3, 1.5]],
+ >>> [[6.4, 2.6], [6.2, 9.7]],
+ >>> [[1.3, 4.5], [3.2, 4.6]],
+ >>> [[6.2, 5.5], [5.4, 5.4]]]
+ >>> y = [1, 1, -1, -1]
+ >>> # in this task we want points where the first feature is close to be
+ >>> # closer to each other, no matter how close the second feature is
+ >>> mmc = MMC()
+ >>> mmc.fit(pairs, y)
+
+ References
+ ----------
+ .. [1] Xing, Jordan, Russell, Ng. `Distance metric learning with application
+ to clustering with side-information
+ <http://papers.nips.cc/paper/2164-distance-metric-\
+ learning-with-application-to-clustering-with-side-information.pdf>`_.
+ NIPS 2002.
+
+ See Also
+ --------
+ metric_learn.MMC : The original weakly-supervised algorithm
+ :ref:`supervised_version` : The section of the project documentation
+ that describes the supervised version of weakly supervised estimators.
+ """
+
+
+[docs]
+ def fit(self, pairs, y, calibration_params=None):
+ """Learn the MMC model.
+
+ The threshold will be calibrated on the trainset using the parameters
+ `calibration_params`.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_constraints, 2, n_features) or \
+ (n_constraints, 2)
+ 3D Array of pairs with each row corresponding to two points,
+ or 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ y : array-like, of shape (n_constraints,)
+ Labels of constraints. Should be -1 for dissimilar pair, 1 for similar.
+
+ calibration_params : `dict` or `None`
+ Dictionary of parameters to give to `calibrate_threshold` for the
+ threshold calibration step done at the end of `fit`. If `None` is
+ given, `calibrate_threshold` will use the default parameters.
+
+ Returns
+ -------
+ self : object
+ Returns the instance.
+ """
+ calibration_params = (calibration_params if calibration_params is not
+ None else dict())
+ self._validate_calibration_params(**calibration_params)
+ self._fit(pairs, y)
+ self.calibrate_threshold(pairs, y, **calibration_params)
+ return self
+
+
+
+
+
+[docs]
+class MMC_Supervised(_BaseMMC, TransformerMixin):
+ """Supervised version of Mahalanobis Metric for Clustering (MMC)
+
+ `MMC_Supervised` creates pairs of similar sample by taking same class
+ samples, and pairs of dissimilar samples by taking different class
+ samples. It then passes these pairs to `MMC` for training.
+
+ Parameters
+ ----------
+ max_iter : int, optional (default=100)
+ Maximum number of iterations of the optimization procedure.
+
+ max_proj : int, optional (default=10000)
+ Maximum number of projection steps.
+
+ tol : float, optional (default=1e-3)
+ Convergence threshold for the optimization procedure.
+
+ n_constraints: int, optional (default=None)
+ Number of constraints to generate. If None, default to `20 *
+ num_classes**2`.
+
+ init : string or numpy array, optional (default='identity')
+ Initialization of the Mahalanobis matrix. Possible options are
+ 'identity', 'covariance', 'random', and a numpy array of
+ shape (n_features, n_features).
+
+ 'identity'
+ An identity matrix of shape (n_features, n_features).
+
+ 'covariance'
+ The (pseudo-)inverse of the covariance matrix.
+
+ 'random'
+ The initial Mahalanobis matrix will be a random SPD matrix of
+ shape `(n_features, n_features)`, generated using
+ `sklearn.datasets.make_spd_matrix`.
+
+ numpy array
+ A numpy array of shape (n_features, n_features), that will
+ be used as such to initialize the metric.
+
+ diagonal : bool, optional (default=False)
+ If True, a diagonal metric will be learned,
+ i.e., a simple scaling of dimensions. The initialization will then
+ be the diagonal coefficients of the matrix given as 'init'.
+
+ diagonal_c : float, optional (default=1.0)
+ Weight of the dissimilarity constraint for diagonal
+ metric learning. Ignored if ``diagonal=False``.
+
+ verbose : bool, optional (default=False)
+ If True, prints information while learning
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``init='random'``, ``random_state`` is used to initialize the random
+ Mahalanobis matrix. In any case, `random_state` is also used to
+ randomly sample constraints from labels.
+
+ num_constraints : Renamed to n_constraints. Will be deprecated in 0.7.0
+
+ convergence_threshold : Renamed to tol. Will be deprecated in 0.7.0
+
+ Examples
+ --------
+ >>> from metric_learn import MMC_Supervised
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> mmc = MMC_Supervised(n_constraints=200)
+ >>> mmc.fit(X, Y)
+
+ Attributes
+ ----------
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+ """
+
+
+[docs]
+ def __init__(self, max_iter=100, max_proj=10000, tol=1e-6,
+ n_constraints=None, init='identity',
+ diagonal=False, diagonal_c=1.0, verbose=False,
+ preprocessor=None, random_state=None,
+ num_constraints='deprecated',
+ convergence_threshold='deprecated'):
+ _BaseMMC.__init__(self, max_iter=max_iter, max_proj=max_proj,
+ tol=tol,
+ init=init, diagonal=diagonal,
+ diagonal_c=diagonal_c, verbose=verbose,
+ preprocessor=preprocessor,
+ random_state=random_state,
+ convergence_threshold=convergence_threshold)
+ if num_constraints != 'deprecated':
+ warnings.warn('"num_constraints" parameter has been renamed to'
+ ' "n_constraints". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ self.n_constraints = num_constraints
+ else:
+ self.n_constraints = n_constraints
+ # Avoid test get_params from failing (all params passed sholud be set)
+ self.num_constraints = 'deprecated'
+
+
+
+[docs]
+ def fit(self, X, y):
+ """Create constraints from labels and learn the MMC model.
+
+ Parameters
+ ----------
+ X : (n x d) matrix
+ Input data, where each row corresponds to a single instance.
+
+ y : (n) array-like
+ Data labels.
+ """
+ X, y = self._prepare_inputs(X, y, ensure_min_samples=2)
+ n_constraints = self.n_constraints
+ if n_constraints is None:
+ num_classes = len(np.unique(y))
+ n_constraints = 20 * num_classes**2
+
+ c = Constraints(y)
+ pos_neg = c.positive_negative_pairs(n_constraints,
+ random_state=self.random_state)
+ pairs, y = wrap_pairs(X, pos_neg)
+ return _BaseMMC._fit(self, pairs, y)
+
+
+
+"""
+Neighborhood Components Analysis (NCA)
+"""
+
+import warnings
+import time
+import sys
+import numpy as np
+from scipy.optimize import minimize
+from scipy.special import logsumexp
+from sklearn.base import TransformerMixin
+from sklearn.exceptions import ConvergenceWarning
+from sklearn.metrics import pairwise_distances
+
+from ._util import _initialize_components, _check_n_components
+from .base_metric import MahalanobisMixin
+
+EPS = np.finfo(float).eps
+
+
+
+[docs]
+class NCA(MahalanobisMixin, TransformerMixin):
+ """Neighborhood Components Analysis (NCA)
+
+ NCA is a distance metric learning algorithm which aims to improve the
+ accuracy of nearest neighbors classification compared to the standard
+ Euclidean distance. The algorithm directly maximizes a stochastic variant
+ of the leave-one-out k-nearest neighbors(KNN) score on the training set.
+ It can also learn a low-dimensional linear transformation of data that can
+ be used for data visualization and fast classification.
+
+ Read more in the :ref:`User Guide <nca>`.
+
+ Parameters
+ ----------
+ init : string or numpy array, optional (default='auto')
+ Initialization of the linear transformation. Possible options are
+ 'auto', 'pca', 'identity', 'random', and a numpy array of shape
+ (n_features_a, n_features_b).
+
+ 'auto'
+ Depending on ``n_components``, the most reasonable initialization
+ will be chosen. If ``n_components <= n_classes`` we use 'lda', as
+ it uses labels information. If not, but
+ ``n_components < min(n_features, n_samples)``, we use 'pca', as
+ it projects data in meaningful directions (those of higher
+ variance). Otherwise, we just use 'identity'.
+
+ 'pca'
+ ``n_components`` principal components of the inputs passed
+ to :meth:`fit` will be used to initialize the transformation.
+ (See `sklearn.decomposition.PCA`)
+
+ 'lda'
+ ``min(n_components, n_classes)`` most discriminative
+ components of the inputs passed to :meth:`fit` will be used to
+ initialize the transformation. (If ``n_components > n_classes``,
+ the rest of the components will be zero.) (See
+ `sklearn.discriminant_analysis.LinearDiscriminantAnalysis`)
+
+ 'identity'
+ If ``n_components`` is strictly smaller than the
+ dimensionality of the inputs passed to :meth:`fit`, the identity
+ matrix will be truncated to the first ``n_components`` rows.
+
+ 'random'
+ The initial transformation will be a random array of shape
+ `(n_components, n_features)`. Each value is sampled from the
+ standard normal distribution.
+
+ numpy array
+ n_features_b must match the dimensionality of the inputs passed to
+ :meth:`fit` and n_features_a must be less than or equal to that.
+ If ``n_components`` is not None, n_features_a must match it.
+
+ n_components : int or None, optional (default=None)
+ Dimensionality of reduced space (if None, defaults to dimension of X).
+
+ max_iter : int, optional (default=100)
+ Maximum number of iterations done by the optimization algorithm.
+
+ tol : float, optional (default=None)
+ Convergence tolerance for the optimization.
+
+ verbose : bool, optional (default=False)
+ Whether to print progress messages or not.
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``init='random'``, ``random_state`` is used to initialize the random
+ transformation. If ``init='pca'``, ``random_state`` is passed as an
+ argument to PCA when initializing the transformation.
+
+ Examples
+ --------
+
+ >>> import numpy as np
+ >>> from metric_learn import NCA
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> nca = NCA(max_iter=1000)
+ >>> nca.fit(X, Y)
+
+ Attributes
+ ----------
+ n_iter_ : `int`
+ The number of iterations the solver has run.
+
+ components_ : `numpy.ndarray`, shape=(n_components, n_features)
+ The learned linear transformation ``L``.
+
+ References
+ ----------
+ .. [1] J. Goldberger, G. Hinton, S. Roweis, R. Salakhutdinov. `Neighbourhood
+ Components Analysis
+ <http://www.cs.nyu.edu/~roweis/papers/ncanips.pdf>`_.
+ NIPS 2005.
+
+ .. [2] Wikipedia entry on `Neighborhood Components Analysis
+ <https://en.wikipedia.org/wiki/Neighbourhood_components_analysis>`_
+ """
+
+
+[docs]
+ def __init__(self, init='auto', n_components=None,
+ max_iter=100, tol=None, verbose=False, preprocessor=None,
+ random_state=None):
+ self.n_components = n_components
+ self.init = init
+ self.max_iter = max_iter
+ self.tol = tol
+ self.verbose = verbose
+ self.random_state = random_state
+ super(NCA, self).__init__(preprocessor)
+
+
+
+[docs]
+ def fit(self, X, y):
+ """
+ X: data matrix, (n x d)
+ y: scalar labels, (n)
+ """
+ X, labels = self._prepare_inputs(X, y, ensure_min_samples=2)
+ n, d = X.shape
+ n_components = _check_n_components(d, self.n_components)
+
+ # Measure the total training time
+ train_time = time.time()
+
+ # Initialize A
+ A = _initialize_components(n_components, X, labels, self.init,
+ self.verbose, self.random_state)
+
+ # Run NCA
+ mask = labels[:, np.newaxis] == labels[np.newaxis, :]
+ optimizer_params = {'method': 'L-BFGS-B',
+ 'fun': self._loss_grad_lbfgs,
+ 'args': (X, mask, -1.0),
+ 'jac': True,
+ 'x0': A.ravel(),
+ 'options': dict(maxiter=self.max_iter),
+ 'tol': self.tol
+ }
+
+ # Call the optimizer
+ self.n_iter_ = 0
+ opt_result = minimize(**optimizer_params)
+
+ self.components_ = opt_result.x.reshape(-1, X.shape[1])
+ self.n_iter_ = opt_result.nit
+
+ # Stop timer
+ train_time = time.time() - train_time
+ if self.verbose:
+ cls_name = self.__class__.__name__
+
+ # Warn the user if the algorithm did not converge
+ if not opt_result.success:
+ warnings.warn('[{}] NCA did not converge: {}'.format(
+ cls_name, opt_result.message), ConvergenceWarning)
+
+ print('[{}] Training took {:8.2f}s.'.format(cls_name, train_time))
+
+ return self
+
+
+ def _loss_grad_lbfgs(self, A, X, mask, sign=1.0):
+
+ if self.n_iter_ == 0 and self.verbose:
+ header_fields = ['Iteration', 'Objective Value', 'Time(s)']
+ header_fmt = '{:>10} {:>20} {:>10}'
+ header = header_fmt.format(*header_fields)
+ cls_name = self.__class__.__name__
+ print('[{cls}]'.format(cls=cls_name))
+ print('[{cls}] {header}\n[{cls}] {sep}'.format(cls=cls_name,
+ header=header,
+ sep='-' * len(header)))
+
+ start_time = time.time()
+
+ A = A.reshape(-1, X.shape[1])
+ X_embedded = np.dot(X, A.T) # (n_samples, n_components)
+ # Compute softmax distances
+ p_ij = pairwise_distances(X_embedded, squared=True)
+ np.fill_diagonal(p_ij, np.inf)
+ p_ij = np.exp(-p_ij - logsumexp(-p_ij, axis=1)[:, np.newaxis])
+ # (n_samples, n_samples)
+
+ # Compute loss
+ masked_p_ij = p_ij * mask
+ p = masked_p_ij.sum(axis=1, keepdims=True) # (n_samples, 1)
+ loss = p.sum()
+
+ # Compute gradient of loss w.r.t. `transform`
+ weighted_p_ij = masked_p_ij - p_ij * p
+ weighted_p_ij_sym = weighted_p_ij + weighted_p_ij.T
+ np.fill_diagonal(weighted_p_ij_sym, - weighted_p_ij.sum(axis=0))
+ gradient = 2 * (X_embedded.T.dot(weighted_p_ij_sym)).dot(X)
+
+ if self.verbose:
+ start_time = time.time() - start_time
+ values_fmt = '[{cls}] {n_iter:>10} {loss:>20.6e} {start_time:>10.2f}'
+ print(values_fmt.format(cls=self.__class__.__name__,
+ n_iter=self.n_iter_, loss=loss,
+ start_time=start_time))
+ sys.stdout.flush()
+
+ self.n_iter_ += 1
+ return sign * loss, sign * gradient.ravel()
+
+
+"""
+Relative Components Analysis (RCA)
+"""
+
+import numpy as np
+import warnings
+from sklearn.base import TransformerMixin
+
+from ._util import _check_n_components
+from .base_metric import MahalanobisMixin
+from .constraints import Constraints
+
+
+# mean center each chunklet separately
+def _chunk_mean_centering(data, chunks):
+ n_chunks = chunks.max() + 1
+ chunk_mask = chunks != -1
+ # We need to ensure the data is float so that we can substract the
+ # mean on it
+ chunk_data = data[chunk_mask].astype(float, copy=False)
+ chunk_labels = chunks[chunk_mask]
+ for c in range(n_chunks):
+ mask = chunk_labels == c
+ chunk_data[mask] -= chunk_data[mask].mean(axis=0)
+
+ return chunk_mask, chunk_data
+
+
+
+[docs]
+class RCA(MahalanobisMixin, TransformerMixin):
+ """Relevant Components Analysis (RCA)
+
+ RCA learns a full rank Mahalanobis distance metric based on a weighted sum of
+ in-chunklets covariance matrices. It applies a global linear transformation
+ to assign large weights to relevant dimensions and low weights to irrelevant
+ dimensions. Those relevant dimensions are estimated using "chunklets",
+ subsets of points that are known to belong to the same class.
+
+ Read more in the :ref:`User Guide <rca>`.
+
+ Parameters
+ ----------
+ n_components : int or None, optional (default=None)
+ Dimensionality of reduced space (if None, defaults to dimension of X).
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ Examples
+ --------
+ >>> from metric_learn import RCA
+ >>> X = [[-0.05, 3.0],[0.05, -3.0],
+ >>> [0.1, -3.55],[-0.1, 3.55],
+ >>> [-0.95, -0.05],[0.95, 0.05],
+ >>> [0.4, 0.05],[-0.4, -0.05]]
+ >>> chunks = [0, 0, 1, 1, 2, 2, 3, 3]
+ >>> rca = RCA()
+ >>> rca.fit(X, chunks)
+
+ References
+ ----------
+ .. [1] Noam Shental, et al. `Adjustment learning and relevant component
+ analysis <http://citeseerx.ist.\
+ psu.edu/viewdoc/download?doi=10.1.1.19.2871&rep=rep1&type=pdf>`_ .
+ ECCV 2002.
+
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_components, n_features)
+ The learned linear transformation ``L``.
+ """
+
+
+[docs]
+ def __init__(self, n_components=None, preprocessor=None):
+ self.n_components = n_components
+ super(RCA, self).__init__(preprocessor)
+
+
+ def _check_dimension(self, rank, X):
+ d = X.shape[1]
+
+ if rank < d:
+ warnings.warn('The inner covariance matrix is not invertible, '
+ 'so the transformation matrix may contain Nan values. '
+ 'You should remove any linearly dependent features and/or '
+ 'reduce the dimensionality of your input, '
+ 'for instance using `sklearn.decomposition.PCA` as a '
+ 'preprocessing step.')
+
+ dim = _check_n_components(d, self.n_components)
+ return dim
+
+
+[docs]
+ def fit(self, X, chunks):
+ """Learn the RCA model.
+
+ Parameters
+ ----------
+ data : (n x d) data matrix
+ Each row corresponds to a single instance
+
+ chunks : (n,) array of ints
+ When ``chunks[i] == -1``, point i doesn't belong to any chunklet.
+ When ``chunks[i] == j``, point i belongs to chunklet j.
+ """
+ X, chunks = self._prepare_inputs(X, chunks, ensure_min_samples=2)
+
+ chunks = np.asanyarray(chunks, dtype=int)
+ chunk_mask, chunked_data = _chunk_mean_centering(X, chunks)
+
+ inner_cov = np.atleast_2d(np.cov(chunked_data, rowvar=0, bias=1))
+ dim = self._check_dimension(np.linalg.matrix_rank(inner_cov), X)
+
+ # Fisher Linear Discriminant projection
+ if dim < X.shape[1]:
+ total_cov = np.cov(X[chunk_mask], rowvar=0)
+ tmp = np.linalg.lstsq(total_cov, inner_cov, rcond=None)[0]
+ vals, vecs = np.linalg.eig(tmp)
+ inds = np.argsort(vals)[:dim]
+ A = vecs[:, inds]
+ inner_cov = np.atleast_2d(A.T.dot(inner_cov).dot(A))
+ self.components_ = _inv_sqrtm(inner_cov).dot(A.T)
+ else:
+ self.components_ = _inv_sqrtm(inner_cov).T
+
+ return self
+
+
+
+
+def _inv_sqrtm(x):
+ '''Computes x^(-1/2)'''
+ vals, vecs = np.linalg.eigh(x)
+ return (vecs / np.sqrt(vals)).dot(vecs.T)
+
+
+
+[docs]
+class RCA_Supervised(RCA):
+ """Supervised version of Relevant Components Analysis (RCA)
+
+ `RCA_Supervised` creates chunks of similar points by first sampling a
+ class, taking `chunk_size` elements in it, and repeating the process
+ `n_chunks` times.
+
+ Parameters
+ ----------
+ n_components : int or None, optional (default=None)
+ Dimensionality of reduced space (if None, defaults to dimension of X).
+
+ n_chunks: int, optional (default=100)
+ Number of chunks to generate.
+
+ chunk_size: int, optional (default=2)
+ Number of points per chunk.
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int.
+ It is used to randomly sample constraints from labels.
+
+ num_chunks : Renamed to n_chunks. Will be deprecated in 0.7.0
+
+ Examples
+ --------
+ >>> from metric_learn import RCA_Supervised
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> rca = RCA_Supervised(n_chunks=30, chunk_size=2)
+ >>> rca.fit(X, Y)
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_components, n_features)
+ The learned linear transformation ``L``.
+ """
+
+
+[docs]
+ def __init__(self, n_components=None, n_chunks=100, chunk_size=2,
+ preprocessor=None, random_state=None,
+ num_chunks='deprecated'):
+ """Initialize the supervised version of `RCA`."""
+ RCA.__init__(self, n_components=n_components, preprocessor=preprocessor)
+ if num_chunks != 'deprecated':
+ warnings.warn('"num_chunks" parameter has been renamed to'
+ ' "n_chunks". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ n_chunks = num_chunks
+ self.num_chunks = 'deprecated' # To avoid no_attribute error
+ self.n_chunks = n_chunks
+ self.chunk_size = chunk_size
+ self.random_state = random_state
+
+
+
+[docs]
+ def fit(self, X, y):
+ """Create constraints from labels and learn the RCA model.
+ Needs n_constraints specified in constructor. (Not true?)
+
+ Parameters
+ ----------
+ X : (n x d) data matrix
+ each row corresponds to a single instance
+
+ y : (n) data labels
+ """
+ X, y = self._prepare_inputs(X, y, ensure_min_samples=2)
+ chunks = Constraints(y).chunks(n_chunks=self.n_chunks,
+ chunk_size=self.chunk_size,
+ random_state=self.random_state)
+
+ if self.n_chunks * (self.chunk_size - 1) < X.shape[1]:
+ warnings.warn('Due to the parameters of RCA_Supervised, '
+ 'the inner covariance matrix is not invertible, '
+ 'so the transformation matrix will contain Nan values. '
+ 'Increase the number or size of the chunks to correct '
+ 'this problem.'
+ )
+
+ return RCA.fit(self, X, chunks)
+
+
+
+"""
+Sparse Compositional Metric Learning (SCML)
+"""
+
+from __future__ import print_function, absolute_import, division
+import numpy as np
+from .base_metric import _TripletsClassifierMixin, MahalanobisMixin
+from ._util import components_from_metric
+from sklearn.base import TransformerMixin
+from .constraints import Constraints
+from sklearn.preprocessing import normalize
+from sklearn.neighbors import NearestNeighbors
+from sklearn.cluster import KMeans
+from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
+from sklearn.utils import check_array, check_random_state
+import warnings
+
+
+class _BaseSCML(MahalanobisMixin):
+
+ _tuple_size = 3 # constraints are triplets
+ _authorized_basis = ['triplet_diffs']
+
+ def __init__(self, beta=1e-5, basis='triplet_diffs', n_basis=None,
+ gamma=5e-3, max_iter=10000, output_iter=500, batch_size=10,
+ verbose=False, preprocessor=None, random_state=None):
+ self.beta = beta
+ self.basis = basis
+ self.n_basis = n_basis
+ self.gamma = gamma
+ self.max_iter = max_iter
+ self.output_iter = output_iter
+ self.batch_size = batch_size
+ self.verbose = verbose
+ self.preprocessor = preprocessor
+ self.random_state = random_state
+ super(_BaseSCML, self).__init__(preprocessor)
+
+ def _fit(self, triplets, basis=None, n_basis=None):
+ """
+ Optimization procedure to find a sparse vector of weights to
+ construct the metric from the basis set. This is based on the
+ dual averaging method.
+ """
+
+ if not isinstance(self.max_iter, int):
+ raise ValueError("max_iter should be an integer, instead it is of type"
+ " %s" % type(self.max_iter))
+ if not isinstance(self.output_iter, int):
+ raise ValueError("output_iter should be an integer, instead it is of "
+ "type %s" % type(self.output_iter))
+ if not isinstance(self.batch_size, int):
+ raise ValueError("batch_size should be an integer, instead it is of type"
+ " %s" % type(self.batch_size))
+
+ if self.output_iter > self.max_iter:
+ raise ValueError("The value of output_iter must be equal or smaller than"
+ " max_iter.")
+
+ # Currently prepare_inputs makes triplets contain points and not indices
+ triplets = self._prepare_inputs(triplets, type_of_inputs='tuples')
+
+ # TODO:
+ # This algorithm is built to work with indices, but in order to be
+ # compliant with the current handling of inputs it is converted
+ # back to indices by the following function. This should be improved
+ # in the future.
+ triplets, X = self._to_index_points(triplets)
+
+ if basis is None:
+ basis, n_basis = self._initialize_basis(triplets, X)
+
+ dist_diff = self._compute_dist_diff(triplets, X, basis)
+
+ n_triplets = triplets.shape[0]
+
+ # weight vector
+ w = np.zeros((1, n_basis))
+ # avarage obj gradient wrt weights
+ avg_grad_w = np.zeros((1, n_basis))
+
+ # l2 norm in time of all obj gradients wrt weights
+ ada_grad_w = np.zeros((1, n_basis))
+ # slack for not dividing by zero
+ delta = 0.001
+
+ best_obj = np.inf
+
+ rng = check_random_state(self.random_state)
+ rand_int = rng.randint(low=0, high=n_triplets,
+ size=(self.max_iter, self.batch_size))
+ for iter in range(self.max_iter):
+
+ idx = rand_int[iter]
+
+ slack_val = 1 + np.matmul(dist_diff[idx, :], w.T)
+ slack_mask = np.squeeze(slack_val > 0, axis=1)
+
+ grad_w = np.sum(dist_diff[idx[slack_mask], :],
+ axis=0, keepdims=True)/self.batch_size
+ avg_grad_w = (iter * avg_grad_w + grad_w) / (iter+1)
+
+ ada_grad_w = np.sqrt(np.square(ada_grad_w) + np.square(grad_w))
+
+ scale_f = -(iter+1) / (self.gamma * (delta + ada_grad_w))
+
+ # proximal operator with negative trimming equivalent
+ w = scale_f * np.minimum(avg_grad_w + self.beta, 0)
+
+ if (iter + 1) % self.output_iter == 0:
+ # regularization part of obj function
+ obj1 = np.sum(w)*self.beta
+
+ # Every triplet distance difference in the space given by L
+ # plus a slack of one
+ slack_val = 1 + np.matmul(dist_diff, w.T)
+ # Mask of places with positive slack
+ slack_mask = slack_val > 0
+
+ # loss function of learning task part of obj function
+ obj2 = np.sum(slack_val[slack_mask])/n_triplets
+
+ obj = obj1 + obj2
+ if self.verbose:
+ count = np.sum(slack_mask)
+ print("[%s] iter %d\t obj %.6f\t num_imp %d" %
+ (self.__class__.__name__, (iter+1), obj, count))
+
+ # update the best
+ if obj < best_obj:
+ best_obj = obj
+ best_w = w
+
+ if self.verbose:
+ print("max iteration reached.")
+
+ # return L matrix yielded from best weights
+ self.n_iter_ = iter
+ self.components_ = self._components_from_basis_weights(basis, best_w)
+
+ return self
+
+ def _compute_dist_diff(self, triplets, X, basis):
+ """
+ Helper function to compute the distance difference of every triplet in the
+ space yielded by the basis set.
+ """
+ # Transformation of data by the basis set
+ XB = np.matmul(X, basis.T)
+
+ n_triplets = triplets.shape[0]
+ # get all positive and negative pairs with lowest index first
+ # np.array (2*n_triplets,2)
+ triplets_pairs_sorted = np.sort(np.vstack((triplets[:, [0, 1]],
+ triplets[:, [0, 2]])),
+ kind='stable')
+ # calculate all unique pairs and their indices
+ uniqPairs, indices = np.unique(triplets_pairs_sorted, return_inverse=True,
+ axis=0)
+ # calculate L2 distance acording to bases only for unique pairs
+ dist = np.square(XB[uniqPairs[:, 0], :] - XB[uniqPairs[:, 1], :])
+
+ # return the diference of distances between all positive and negative
+ # pairs
+ return dist[indices[:n_triplets]] - dist[indices[n_triplets:]]
+
+ def _components_from_basis_weights(self, basis, w):
+ """
+ Get components matrix (L) from computed mahalanobis matrix.
+ """
+
+ # get rid of inactive bases
+ # TODO: Maybe have a tolerance over zero?
+ active_idx, = w > 0
+ w = w[..., active_idx]
+ basis = basis[active_idx, :]
+
+ n_basis, n_features = basis.shape
+
+ if n_basis < n_features: # if metric is low-rank
+ warnings.warn("The number of bases with nonzero weight is less than the "
+ "number of features of the input, in consequence the "
+ "learned transformation reduces the dimension to %d."
+ % n_basis)
+ return np.sqrt(w.T)*basis # equivalent to np.diag(np.sqrt(w)).dot(basis)
+
+ else: # if metric is full rank
+ return components_from_metric(np.matmul(basis.T, w.T*basis))
+
+ def _to_index_points(self, triplets):
+ shape = triplets.shape
+ X, triplets = np.unique(np.vstack(triplets), return_inverse=True, axis=0)
+ triplets = triplets.reshape(shape[:2])
+ return triplets, X
+
+ def _initialize_basis(self, triplets, X):
+ """ Checks if the basis array is well constructed or constructs it based
+ on one of the available options.
+ """
+ n_features = X.shape[1]
+
+ if isinstance(self.basis, np.ndarray):
+ # TODO: should copy?
+ basis = check_array(self.basis, copy=True)
+ if basis.shape[1] != n_features:
+ raise ValueError('The dimensionality ({}) of the provided bases must'
+ ' match the dimensionality of the data '
+ '({}).'.format(basis.shape[1], n_features))
+ elif self.basis not in self._authorized_basis:
+ raise ValueError(
+ "`basis` must be one of the options '{}' "
+ "or an array of shape (n_basis, n_features)."
+ .format("', '".join(self._authorized_basis)))
+ if self.basis == 'triplet_diffs':
+ basis, n_basis = self._generate_bases_dist_diff(triplets, X)
+
+ return basis, n_basis
+
+ def _generate_bases_dist_diff(self, triplets, X):
+ """ Constructs the basis set from the differences of positive and negative
+ pairs from the triplets constraints.
+
+ The basis set is constructed iteratively by taking n_features triplets,
+ then adding and substracting respectively all the outerproducts of the
+ positive and negative pairs, and finally selecting the eigenvectors
+ of this matrix with positive eigenvalue. This is done until n_basis are
+ selected.
+ """
+ n_features = X.shape[1]
+ n_triplets = triplets.shape[0]
+
+ if self.n_basis is None:
+ # TODO: Get a good default n_basis directive
+ n_basis = n_features*80
+ warnings.warn('As no value for `n_basis` was selected, the number of '
+ 'basis will be set to n_basis= %d' % n_basis)
+ elif isinstance(self.n_basis, int):
+ n_basis = self.n_basis
+ else:
+ raise ValueError("n_basis should be an integer, instead it is of type %s"
+ % type(self.n_basis))
+
+ if n_features > n_triplets:
+ raise ValueError(
+ "Number of features (%s) is greater than the number of triplets(%s).\n"
+ "Consider using dimensionality reduction or using another basis "
+ "generation scheme." % (n_features, n_triplets))
+
+ basis = np.zeros((n_basis, n_features))
+
+ # get all positive and negative pairs with lowest index first
+ # np.array (2*n_triplets,2)
+ triplets_pairs_sorted = np.sort(np.vstack((triplets[:, [0, 1]],
+ triplets[:, [0, 2]])),
+ kind='stable')
+ # calculate all unique pairs and their indices
+ uniqPairs, indices = np.unique(triplets_pairs_sorted, return_inverse=True,
+ axis=0)
+ # calculate differences only for unique pairs
+ diff = X[uniqPairs[:, 0], :] - X[uniqPairs[:, 1], :]
+
+ diff_pos = diff[indices[:n_triplets], :]
+ diff_neg = diff[indices[n_triplets:], :]
+
+ rng = check_random_state(self.random_state)
+
+ start = 0
+ finish = 0
+ while finish != n_basis:
+ # Select triplets to yield diff
+ select_triplet = rng.choice(n_triplets, size=n_features, replace=False)
+
+ # select n_features positive differences
+ d_pos = diff_pos[select_triplet, :]
+
+ # select n_features negative differences
+ d_neg = diff_neg[select_triplet, :]
+
+ # Yield matrix
+ diff_sum = d_pos.T.dot(d_pos) - d_neg.T.dot(d_neg)
+
+ # Calculate eigenvalue and eigenvectors
+ w, v = np.linalg.eigh(diff_sum.T.dot(diff_sum))
+
+ # Add eigenvectors with positive eigenvalue to basis set
+ pos_eig_mask = w > 0
+ start = finish
+ finish += pos_eig_mask.sum()
+
+ try:
+ basis[start:finish, :] = v[pos_eig_mask]
+ except ValueError:
+ # if finish is greater than n_basis
+ basis[start:, :] = v[pos_eig_mask][:n_basis-start]
+ break
+
+ # TODO: maybe add a warning in case there are no added bases, this could
+ # be caused by a bad triplet set. This would cause an infinite loop
+
+ return basis, n_basis
+
+
+
+[docs]
+class SCML(_BaseSCML, _TripletsClassifierMixin):
+ """Sparse Compositional Metric Learning (SCML)
+
+ `SCML` learns an squared Mahalanobis distance from triplet constraints by
+ optimizing sparse positive weights assigned to a set of :math:`K` rank-one
+ PSD bases. This can be formulated as an optimization problem with only
+ :math:`K` parameters, that can be solved with an efficient stochastic
+ composite scheme.
+
+ Read more in the :ref:`User Guide <scml>`.
+
+ .. warning::
+ SCML is still a bit experimental, don't hesitate to report if
+ something fails/doesn't work as expected.
+
+ Parameters
+ ----------
+ beta: float (default=1e-5)
+ L1 regularization parameter.
+
+ basis : string or array-like, optional (default='triplet_diffs')
+ Set of bases to construct the metric. Possible options are
+ 'triplet_diffs', and an array-like of shape (n_basis, n_features).
+
+ 'triplet_diffs'
+ The basis set is constructed iteratively from differences between points
+ of `n_features` positive or negative pairs randomly sampled from the
+ triplets constraints. Requires the number of training triplets to be
+ great or equal to `n_features`.
+
+ array-like
+ A matrix of shape (n_basis, n_features), that will be used as
+ the basis set for the metric construction.
+
+ n_basis : int, optional
+ Number of basis to be yielded. In case it is not set it will be set based
+ on `basis`. If no value is selected a default will be computed based on
+ the input.
+
+ gamma: float (default = 5e-3)
+ Learning rate for the optimization algorithm.
+
+ max_iter : int (default = 10000)
+ Number of iterations for the algorithm.
+
+ output_iter : int (default = 5000)
+ Number of iterations to check current weights performance and output this
+ information in case verbose is True.
+
+ verbose : bool, optional
+ If True, prints information while learning.
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get triplets from indices. If array-like,
+ triplets will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int.
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `_components_from_basis_weights`.)
+
+ Examples
+ --------
+ >>> from metric_learn import SCML
+ >>> triplets = [[[1.2, 7.5], [1.3, 1.5], [6.2, 9.7]],
+ >>> [[1.3, 4.5], [3.2, 4.6], [5.4, 5.4]],
+ >>> [[3.2, 7.5], [3.3, 1.5], [8.2, 9.7]],
+ >>> [[3.3, 4.5], [5.2, 4.6], [7.4, 5.4]]]
+ >>> scml = SCML()
+ >>> scml.fit(triplets)
+
+ References
+ ----------
+ .. [1] Y. Shi, A. Bellet and F. Sha. `Sparse Compositional Metric Learning.
+ <http://researchers.lille.inria.fr/abellet/papers/aaai14.pdf>`_. \
+ (AAAI), 2014.
+
+ .. [2] Adapted from original `Matlab implementation. \
+ <https://github.com/bellet/SCML>`_.
+
+ See Also
+ --------
+ metric_learn.SCML_Supervised : The supervised version of the algorithm.
+
+ :ref:`supervised_version` : The section of the project documentation
+ that describes the supervised version of weakly supervised estimators.
+ """
+
+
+[docs]
+ def fit(self, triplets):
+ """Learn the SCML model.
+
+ Parameters
+ ----------
+ triplets : array-like, shape=(n_constraints, 3, n_features) or \
+ (n_constraints, 3)
+ 3D array-like of triplets of points or 2D array of triplets of
+ indicators. Triplets are assumed to be ordered such that:
+ d(triplets[i, 0],triplets[i, 1]) < d(triplets[i, 0], triplets[i, 2]).
+
+ Returns
+ -------
+ self : object
+ Returns the instance.
+ """
+
+ return self._fit(triplets)
+
+
+
+
+
+[docs]
+class SCML_Supervised(_BaseSCML, TransformerMixin):
+ """Supervised version of Sparse Compositional Metric Learning (SCML)
+
+ `SCML_Supervised` creates triplets by taking `k_genuine` neighbours
+ of the same class and `k_impostor` neighbours from different classes for each
+ point and then runs the SCML algorithm on these triplets.
+
+ Read more in the :ref:`User Guide <scml>`.
+
+ .. warning::
+ SCML is still a bit experimental, don't hesitate to report if
+ something fails/doesn't work as expected.
+
+ Parameters
+ ----------
+ beta: float (default=1e-5)
+ L1 regularization parameter.
+
+ basis : string or an array-like, optional (default='lda')
+ Set of bases to construct the metric. Possible options are
+ 'lda', and an array-like of shape (n_basis, n_features).
+
+ 'lda'
+ The `n_basis` basis set is constructed from the LDA of significant
+ local regions in the feature space via clustering, for each region
+ center k-nearest neighbors are used to obtain the LDA scalings,
+ which correspond to the locally discriminative basis.
+
+ array-like
+ A matrix of shape (n_basis, n_features), that will be used as
+ the basis set for the metric construction.
+
+ n_basis : int, optional
+ Number of basis to be yielded. In case it is not set it will be set based
+ on `basis`. If no value is selected a default will be computed based on
+ the input.
+
+ gamma: float (default = 5e-3)
+ Learning rate for the optimization algorithm.
+
+ max_iter : int (default = 100000)
+ Number of iterations for the algorithm.
+
+ output_iter : int (default = 5000)
+ Number of iterations to check current weights performance and output this
+ information in case verbose is True.
+
+ verbose : bool, optional
+ If True, prints information while learning.
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get triplets from indices. If array-like,
+ triplets will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int.
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `_components_from_basis_weights`.)
+
+ Examples
+ --------
+ >>> from metric_learn import SCML_Supervised
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> scml = SCML_Supervised(random_state=33)
+ >>> scml.fit(X, Y)
+ SCML_Supervised(random_state=33)
+ >>> scml.score_pairs([[X[0], X[1]], [X[0], X[2]]])
+ array([1.84640733, 1.55984363])
+ >>> scml.get_metric()(X[0], X[1])
+ 1.8464073327922157
+
+ References
+ ----------
+ .. [1] Y. Shi, A. Bellet and F. Sha. `Sparse Compositional Metric Learning.
+ <http://researchers.lille.inria.fr/abellet/papers/aaai14.pdf>`_. \
+ (AAAI), 2014.
+
+ .. [2] Adapted from original `Matlab implementation. \
+ <https://github.com/bellet/SCML>`_.
+
+ See Also
+ --------
+ metric_learn.SCML : The weakly supervised version of this
+ algorithm.
+ """
+ # Add supervised authorized basis construction options
+ _authorized_basis = _BaseSCML._authorized_basis + ['lda']
+
+
+[docs]
+ def __init__(self, k_genuine=3, k_impostor=10, beta=1e-5, basis='lda',
+ n_basis=None, gamma=5e-3, max_iter=10000, output_iter=500,
+ batch_size=10, verbose=False, preprocessor=None,
+ random_state=None):
+ self.k_genuine = k_genuine
+ self.k_impostor = k_impostor
+ _BaseSCML.__init__(self, beta=beta, basis=basis, n_basis=n_basis,
+ max_iter=max_iter, output_iter=output_iter,
+ batch_size=batch_size, verbose=verbose,
+ preprocessor=preprocessor, random_state=random_state)
+
+
+
+[docs]
+ def fit(self, X, y):
+ """Create constraints from labels and learn the SCML model.
+
+ Parameters
+ ----------
+ X : (n x d) matrix
+ Input data, where each row corresponds to a single instance.
+
+ y : (n) array-like
+ Data labels.
+
+ Returns
+ -------
+ self : object
+ Returns the instance.
+ """
+ X, y = self._prepare_inputs(X, y, ensure_min_samples=2)
+
+ basis, n_basis = self._initialize_basis_supervised(X, y)
+
+ if not isinstance(self.k_genuine, int):
+ raise ValueError("k_genuine should be an integer, instead it is of type"
+ " %s" % type(self.k_genuine))
+ if not isinstance(self.k_impostor, int):
+ raise ValueError("k_impostor should be an integer, instead it is of "
+ "type %s" % type(self.k_impostor))
+
+ constraints = Constraints(y)
+ triplets = constraints.generate_knntriplets(X, self.k_genuine,
+ self.k_impostor)
+
+ triplets = X[triplets]
+
+ return self._fit(triplets, basis, n_basis)
+
+
+ def _initialize_basis_supervised(self, X, y):
+ """ Constructs the basis set following one of the supervised options in
+ case one is selected.
+ """
+
+ if isinstance(self.basis, str) and self.basis == 'lda':
+ basis, n_basis = self._generate_bases_LDA(X, y)
+ else:
+ basis, n_basis = None, None
+
+ return basis, n_basis
+
+ def _generate_bases_LDA(self, X, y):
+ """ Generates bases for the 'lda' option.
+
+ The basis set is constructed using Linear Discriminant Analysis of
+ significant local regions in the feature space via clustering, for
+ each region center k-nearest neighbors are used to obtain the LDA scalings,
+ which correspond to the locally discriminative basis. Currently this is
+ done at two scales `k={10,20}` if `n_feature < 50` or else `k={20,50}`.
+ """
+
+ labels, class_count = np.unique(y, return_counts=True)
+ n_class = len(labels)
+
+ n_features = X.shape[1]
+ # Number of basis yielded from each LDA
+ num_eig = min(n_class-1, n_features)
+
+ if self.n_basis is None:
+ # TODO: Get a good default n_basis directive
+ n_basis = min(20*n_features, X.shape[0]*2*num_eig - 1)
+ warnings.warn('As no value for `n_basis` was selected, the number of '
+ 'basis will be set to n_basis= %d' % n_basis)
+
+ elif isinstance(self.n_basis, int):
+ n_basis = self.n_basis
+ else:
+ raise ValueError("n_basis should be an integer, instead it is of type %s"
+ % type(self.n_basis))
+
+ # Number of clusters needed for 2 scales given the number of basis
+ # yielded by every LDA
+ n_clusters = int(np.ceil(n_basis/(2 * num_eig)))
+
+ if n_basis < n_class:
+ warnings.warn("The number of basis is less than the number of classes, "
+ "which may lead to poor discriminative performance.")
+ elif n_basis >= X.shape[0]*2*num_eig:
+ raise ValueError("Not enough samples to generate %d LDA bases, n_basis"
+ "should be smaller than %d" %
+ (n_basis, X.shape[0]*2*num_eig))
+
+ kmeans = KMeans(n_clusters=n_clusters, n_init=10,
+ random_state=self.random_state, algorithm='elkan').fit(X)
+ cX = kmeans.cluster_centers_
+
+ n_scales = 2
+ if n_features > 50:
+ scales = [20, 50]
+ else:
+ scales = [10, 20]
+
+ k_class = np.vstack((np.minimum(class_count, scales[0]),
+ np.minimum(class_count, scales[1])))
+
+ idx_set = [np.zeros((n_clusters, sum(k_class[0, :])), dtype=np.int64),
+ np.zeros((n_clusters, sum(k_class[1, :])), dtype=np.int64)]
+
+ start_finish_indices = np.hstack((np.zeros((2, 1), np.int64),
+ k_class)).cumsum(axis=1)
+
+ neigh = NearestNeighbors()
+
+ for c in range(n_class):
+ sel_c = np.where(y == labels[c])
+
+ # get k_class same class neighbors
+ neigh.fit(X=X[sel_c])
+ # Only take the neighbors once for the biggest scale
+ neighbors = neigh.kneighbors(X=cX, n_neighbors=k_class[-1, c],
+ return_distance=False)
+
+ # add index set of neighbors for every cluster center for both scales
+ for s, k in enumerate(k_class[:, c]):
+ start, finish = start_finish_indices[s, c:c+2]
+ idx_set[s][:, start:finish] = np.take(sel_c, neighbors[:, :k])
+
+ # Compute basis for every cluster in both scales
+ basis = np.zeros((n_basis, n_features))
+ lda = LinearDiscriminantAnalysis()
+ start_finish_indices = np.hstack((np.vstack((0, n_clusters * num_eig)),
+ np.full((2, n_clusters),
+ num_eig))).cumsum(axis=1)
+
+ for s in range(n_scales):
+ for c in range(n_clusters):
+ lda.fit(X[idx_set[s][c, :]], y[idx_set[s][c, :]])
+ start, finish = start_finish_indices[s, c:c+2]
+ normalized_scalings = normalize(lda.scalings_.T)
+ try:
+ basis[start: finish, :] = normalized_scalings
+ except ValueError:
+ # handle tail
+ basis[start:, :] = normalized_scalings[:n_basis-start]
+ break
+
+ return basis, n_basis
+
+
+"""
+Sparse High-Dimensional Metric Learning (SDML)
+"""
+
+import warnings
+import numpy as np
+from sklearn.base import TransformerMixin
+from scipy.linalg import pinvh
+from sklearn.covariance import graphical_lasso
+from sklearn.exceptions import ConvergenceWarning
+
+from .base_metric import MahalanobisMixin, _PairsClassifierMixin
+from .constraints import Constraints, wrap_pairs
+from ._util import components_from_metric, _initialize_metric_mahalanobis
+try:
+ from inverse_covariance import quic
+except ImportError:
+ HAS_SKGGM = False
+else:
+ HAS_SKGGM = True
+
+
+class _BaseSDML(MahalanobisMixin):
+
+ _tuple_size = 2 # constraints are pairs
+
+ def __init__(self, balance_param=0.5, sparsity_param=0.01, prior='identity',
+ verbose=False, preprocessor=None,
+ random_state=None):
+ self.balance_param = balance_param
+ self.sparsity_param = sparsity_param
+ self.prior = prior
+ self.verbose = verbose
+ self.random_state = random_state
+ super(_BaseSDML, self).__init__(preprocessor)
+
+ def _fit(self, pairs, y):
+ if not HAS_SKGGM:
+ if self.verbose:
+ print("SDML will use scikit-learn's graphical lasso solver.")
+ else:
+ if self.verbose:
+ print("SDML will use skggm's graphical lasso solver.")
+ pairs, y = self._prepare_inputs(pairs, y,
+ type_of_inputs='tuples')
+ n_features = pairs.shape[2]
+ if n_features < 2:
+ raise ValueError(f"Cannot fit SDML with {n_features} feature(s)")
+
+ # set up (the inverse of) the prior M
+ # if the prior is the default (None), we raise a warning
+ _, prior_inv = _initialize_metric_mahalanobis(
+ pairs, self.prior,
+ return_inverse=True, strict_pd=True, matrix_name='prior',
+ random_state=self.random_state)
+ diff = pairs[:, 0] - pairs[:, 1]
+ loss_matrix = (diff.T * y).dot(diff)
+ emp_cov = prior_inv + self.balance_param * loss_matrix
+
+ # our initialization will be the matrix with emp_cov's eigenvalues,
+ # with a constant added so that they are all positive (plus an epsilon
+ # to ensure definiteness). This is empirical.
+ w, V = np.linalg.eigh(emp_cov)
+ min_eigval = np.min(w)
+ if min_eigval < 0.:
+ warnings.warn("Warning, the input matrix of graphical lasso is not "
+ "positive semi-definite (PSD). The algorithm may diverge, "
+ "and lead to degenerate solutions. "
+ "To prevent that, try to decrease the balance parameter "
+ "`balance_param` and/or to set prior='identity'.",
+ ConvergenceWarning)
+ w -= min_eigval # we translate the eigenvalues to make them all positive
+ w += 1e-10 # we add a small offset to avoid definiteness problems
+ sigma0 = (V * w).dot(V.T)
+ try:
+ if HAS_SKGGM:
+ theta0 = pinvh(sigma0)
+ M, _, _, _, _, _ = quic(emp_cov, lam=self.sparsity_param,
+ msg=self.verbose,
+ Theta0=theta0, Sigma0=sigma0)
+ else:
+ _, M = graphical_lasso(emp_cov, alpha=self.sparsity_param,
+ verbose=self.verbose,
+ cov_init=sigma0)
+ raised_error = None
+ w_mahalanobis, _ = np.linalg.eigh(M)
+ not_spd = any(w_mahalanobis < 0.)
+ not_finite = not np.isfinite(M).all()
+ # TODO: Narrow this to the specific exceptions we expect.
+ except Exception as e:
+ raised_error = e
+ not_spd = False # not_spd not applicable here so we set to False
+ not_finite = False # not_finite not applicable here so we set to False
+ if raised_error is not None or not_spd or not_finite:
+ msg = ("There was a problem in SDML when using {}'s graphical "
+ "lasso solver.").format("skggm" if HAS_SKGGM else "scikit-learn")
+ if not HAS_SKGGM:
+ skggm_advice = (" skggm's graphical lasso can sometimes converge "
+ "on non SPD cases where scikit-learn's graphical "
+ "lasso fails to converge. Try to install skggm and "
+ "rerun the algorithm (see the README.md for the "
+ "right version of skggm).")
+ msg += skggm_advice
+ if raised_error is not None:
+ msg += " The following error message was thrown: {}.".format(
+ raised_error)
+ raise RuntimeError(msg)
+
+ self.components_ = components_from_metric(np.atleast_2d(M))
+ return self
+
+
+
+[docs]
+class SDML(_BaseSDML, _PairsClassifierMixin):
+ r"""Sparse Distance Metric Learning (SDML)
+
+ SDML is an efficient sparse metric learning in high-dimensional space via
+ double regularization: an L1-penalization on the off-diagonal elements of the
+ Mahalanobis matrix :math:`\mathbf{M}`, and a log-determinant divergence
+ between :math:`\mathbf{M}` and :math:`\mathbf{M_0}` (set as either
+ :math:`\mathbf{I}` or :math:`\mathbf{\Omega}^{-1}`, where
+ :math:`\mathbf{\Omega}` is the covariance matrix).
+
+ Read more in the :ref:`User Guide <sdml>`.
+
+ Parameters
+ ----------
+ balance_param : float, optional (default=0.5)
+ Trade off between sparsity and M0 prior.
+
+ sparsity_param : float, optional (default=0.01)
+ Trade off between optimizer and sparseness (see graph_lasso).
+
+ prior : string or numpy array, optional (default='identity')
+ Prior to set for the metric. Possible options are
+ 'identity', 'covariance', 'random', and a numpy array of
+ shape (n_features, n_features). For SDML, the prior should be strictly
+ positive definite (PD).
+
+ 'identity'
+ An identity matrix of shape (n_features, n_features).
+
+ 'covariance'
+ The inverse covariance matrix.
+
+ 'random'
+ The prior will be a random positive definite (PD) matrix of shape
+ `(n_features, n_features)`, generated using
+ `sklearn.datasets.make_spd_matrix`.
+
+ numpy array
+ A positive definite (PD) matrix of shape
+ (n_features, n_features), that will be used as such to set the
+ prior.
+
+ verbose : bool, optional (default=False)
+ If True, prints information while learning.
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be gotten like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``prior='random'``, ``random_state`` is used to set the prior.
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+
+ threshold_ : `float`
+ If the distance metric between two points is lower than this threshold,
+ points will be classified as similar, otherwise they will be
+ classified as dissimilar.
+
+ Examples
+ --------
+ >>> from metric_learn import SDML_Supervised
+ >>> from sklearn.datasets import load_iris
+ >>> iris_data = load_iris()
+ >>> X = iris_data['data']
+ >>> Y = iris_data['target']
+ >>> sdml = SDML_Supervised(n_constraints=200)
+ >>> sdml.fit(X, Y)
+
+ References
+ ----------
+ .. [1] Qi et al. `An efficient sparse metric learning in high-dimensional
+ space via L1-penalized log-determinant regularization
+ <http://www.machinelearning.org/archive/icml2009/papers/46.pdf>`_.
+ ICML 2009.
+
+ .. [2] Code adapted from https://gist.github.com/kcarnold/5439945
+ """
+
+
+[docs]
+ def fit(self, pairs, y, calibration_params=None):
+ """Learn the SDML model.
+
+ The threshold will be calibrated on the trainset using the parameters
+ `calibration_params`.
+
+ Parameters
+ ----------
+ pairs : array-like, shape=(n_constraints, 2, n_features) or \
+ (n_constraints, 2)
+ 3D Array of pairs with each row corresponding to two points,
+ or 2D array of indices of pairs if the metric learner uses a
+ preprocessor.
+
+ y : array-like, of shape (n_constraints,)
+ Labels of constraints. Should be -1 for dissimilar pair, 1 for similar.
+
+ calibration_params : `dict` or `None`
+ Dictionary of parameters to give to `calibrate_threshold` for the
+ threshold calibration step done at the end of `fit`. If `None` is
+ given, `calibrate_threshold` will use the default parameters.
+
+ Returns
+ -------
+ self : object
+ Returns the instance.
+ """
+ calibration_params = (calibration_params if calibration_params is not
+ None else dict())
+ self._validate_calibration_params(**calibration_params)
+ self._fit(pairs, y)
+ self.calibrate_threshold(pairs, y, **calibration_params)
+ return self
+
+
+
+
+
+[docs]
+class SDML_Supervised(_BaseSDML, TransformerMixin):
+ """Supervised version of Sparse Distance Metric Learning (SDML)
+
+ `SDML_Supervised` creates pairs of similar sample by taking same class
+ samples, and pairs of dissimilar samples by taking different class
+ samples. It then passes these pairs to `SDML` for training.
+
+ Parameters
+ ----------
+ balance_param : float, optional (default=0.5)
+ Trade off between sparsity and M0 prior.
+
+ sparsity_param : float, optional (default=0.01)
+ Trade off between optimizer and sparseness (see graph_lasso).
+
+ prior : string or numpy array, optional (default='identity')
+ Prior to set for the metric. Possible options are
+ 'identity', 'covariance', 'random', and a numpy array of
+ shape (n_features, n_features). For SDML, the prior should be strictly
+ positive definite (PD).
+
+ 'identity'
+ An identity matrix of shape (n_features, n_features).
+
+ 'covariance'
+ The inverse covariance matrix.
+
+ 'random'
+ The prior will be a random SPD matrix of shape
+ `(n_features, n_features)`, generated using
+ `sklearn.datasets.make_spd_matrix`.
+
+ numpy array
+ A positive definite (PD) matrix of shape
+ (n_features, n_features), that will be used as such to set the
+ prior.
+
+ n_constraints : int, optional (default=None)
+ Number of constraints to generate. If None, defaults to `20 *
+ num_classes**2`.
+
+ verbose : bool, optional (default=False)
+ If True, prints information while learning.
+
+ preprocessor : array-like, shape=(n_samples, n_features) or callable
+ The preprocessor to call to get tuples from indices. If array-like,
+ tuples will be formed like this: X[indices].
+
+ random_state : int or numpy.RandomState or None, optional (default=None)
+ A pseudo random number generator object or a seed for it if int. If
+ ``init='random'``, ``random_state`` is used to set the random
+ prior. In any case, `random_state` is also used to randomly sample
+ constraints from labels.
+
+ num_constraints : Renamed to n_constraints. Will be deprecated in 0.7.0
+
+ Attributes
+ ----------
+ components_ : `numpy.ndarray`, shape=(n_features, n_features)
+ The linear transformation ``L`` deduced from the learned Mahalanobis
+ metric (See function `components_from_metric`.)
+
+ See Also
+ --------
+ metric_learn.SDML : The original weakly-supervised algorithm
+ :ref:`supervised_version` : The section of the project documentation
+ that describes the supervised version of weakly supervised estimators.
+ """
+
+
+[docs]
+ def __init__(self, balance_param=0.5, sparsity_param=0.01, prior='identity',
+ n_constraints=None, verbose=False, preprocessor=None,
+ random_state=None, num_constraints='deprecated'):
+ _BaseSDML.__init__(self, balance_param=balance_param,
+ sparsity_param=sparsity_param, prior=prior,
+ verbose=verbose,
+ preprocessor=preprocessor, random_state=random_state)
+ if num_constraints != 'deprecated':
+ warnings.warn('"num_constraints" parameter has been renamed to'
+ ' "n_constraints". It has been deprecated in'
+ ' version 0.6.3 and will be removed in 0.7.0'
+ '', FutureWarning)
+ self.n_constraints = num_constraints
+ else:
+ self.n_constraints = n_constraints
+ # Avoid test get_params from failing (all params passed sholud be set)
+ self.num_constraints = 'deprecated'
+
+
+
+[docs]
+ def fit(self, X, y):
+ """Create constraints from labels and learn the SDML model.
+
+ Parameters
+ ----------
+ X : array-like, shape (n, d)
+ data matrix, where each row corresponds to a single instance
+
+ y : array-like, shape (n,)
+ data labels, one for each instance
+
+ Returns
+ -------
+ self : object
+ Returns the instance.
+ """
+ X, y = self._prepare_inputs(X, y, ensure_min_samples=2)
+ n_constraints = self.n_constraints
+ if n_constraints is None:
+ num_classes = len(np.unique(y))
+ n_constraints = 20 * num_classes**2
+
+ c = Constraints(y)
+ pos_neg = c.positive_negative_pairs(n_constraints,
+ random_state=self.random_state)
+ pairs, y = wrap_pairs(X, pos_neg)
+ return _BaseSDML._fit(self, pairs, y)
+
+
+
' + + '' + + _("Hide Search Matches") + + "
" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/auto_examples/index.html b/auto_examples/index.html new file mode 100644 index 00000000..7503ddd2 --- /dev/null +++ b/auto_examples/index.html @@ -0,0 +1,148 @@ + + + + + + +Below is a gallery of example metric-learn use cases.
+Note
+Go to the end +to download the full example code
+This is a small walkthrough which illustrates most of the Metric Learning +algorithms implemented in metric-learn by using them on synthetic data, +with some visualizations to provide intuitions into what they are designed +to achieve.
+# License: BSD 3 clause
+# Authors: Bhargav Srinivasa Desikan <bhargavvader@gmail.com>
+# William de Vazelhes <wdevazelhes@gmail.com>
+
Note
+In order to show the charts of the examples you need a graphical
+matplotlib
backend installed. For intance, use pip install pyqt5
+to get Qt graphical interface or use your favorite one.
from sklearn.manifold import TSNE
+
+import metric_learn
+import numpy as np
+from sklearn.datasets import make_classification, make_regression
+
+# visualisation imports
+import matplotlib.pyplot as plt
+np.random.seed(42)
+
We will be using a synthetic dataset to illustrate the plotting, +using the function sklearn.datasets.make_classification from +scikit-learn. The dataset will contain: +- 100 points in 3 classes with 2 clusters per class +- 5 features, among which 3 are informative (correlated with the class +labels) and two are random noise with large magnitude
+Note that the dimensionality of the data is 5, so to plot the +transformed data in 2D, we will use the t-sne algorithm. (See +sklearn.manifold.TSNE).
+Let’s now plot the dataset as is.
+ +We can see that the classes appear mixed up: this is because t-sne +is based on preserving the original neighborhood of points in the embedding +space, but this original neighborhood is based on the euclidean +distance in the input space, in which the contribution of the noisy +features is high. So even if points from the same class are close to each +other in some subspace of the input space, this is not the case when +considering all dimensions of the input space.
+Why is Metric Learning useful? We can, with prior knowledge of which +points are supposed to be closer, figure out a better way to compute +distances between points for the task at hand. Especially in higher +dimensions when Euclidean distances are a poor way to measure distance, this +becomes very useful.
+Basically, we learn this distance: +\(D(x, x') = \sqrt{(x-x')^\top M(x-x')}\). And we learn the parameters +\(M\) of this distance to satisfy certain constraints on the distance +between points, for example requiring that points of the same class are +close together and points of different class are far away.
+For more information, check the What is Metric Learning? section +from the documentation. Some good reading material can also be found +here. It serves as a +good literature review of Metric Learning.
+We will briefly explain the metric learning algorithms implemented by +metric-learn, before providing some examples for its usage, and also +discuss how to perform metric learning with weaker supervision than class +labels.
+Metric-learn can be easily integrated with your other machine learning +pipelines, and follows scikit-learn conventions.
+LMNN is a metric learning algorithm primarily designed for k-nearest +neighbor classification. The algorithm is based on semidefinite +programming, a sub-class of convex programming (as most Metric Learning +algorithms are).
+The main intuition behind LMNN is to learn a pseudometric under which +all data instances in the training set are surrounded by at least k +instances that share the same class label. If this is achieved, the +leave-one-out error (a special case of cross validation) is minimized. +You’ll notice that the points from the same labels are closer together, +but they are not necessary in a same cluster. This is particular to LMNN +and we’ll see that some other algorithms implicitly enforce points from +the same class to cluster together.
+See more in the User Guide
See more in the documentation of the class LMNN
So what have we learned? The matrix \(M\) we talked about before.
+Now let us plot the transformed space - this tells us what the original +space looks like after being transformed with the new learned metric.
+ +Pretty neat, huh?
+The rest of this notebook will briefly explain the other Metric Learning
+algorithms before plotting them. Also, while we have first run fit
+and then transform
to see our data transformed, we can also use
+fit_transform
. The rest of the examples and illustrations will use
+fit_transform
.
ITML uses a regularizer that automatically enforces a Semi-Definite +Positive Matrix condition - the LogDet divergence. It uses soft +must-link or cannot-link constraints, and a simple algorithm based on +Bregman projections. Unlike LMNN, ITML will implicitly enforce points from +the same class to belong to the same cluster, as you can see below.
+See more in the User Guide
See more in the documentation of the class ITML
MMC is an algorithm that will try to minimize the distance between similar +points, while ensuring that the sum of distances between dissimilar points is +higher than a threshold. This is done by optimizing a cost function +subject to an inequality constraint.
+See more in the User Guide
See more in the documentation of the class MMC
Implements an efficient sparse metric learning algorithm in high +dimensional space via an \(l_1\)-penalized log-determinant +regularization. Compared to the most existing distance metric learning +algorithms, the algorithm exploits the sparsity nature underlying the +intrinsic high dimensional feature space.
+See more in the User Guide
See more in the documentation of the class SDML
/Users/william.vezelhes/miniconda3/envs/docenvbis/lib/python3.11/site-packages/sklearn/covariance/_graph_lasso.py:329: FutureWarning: The cov_init parameter is deprecated in 1.3 and will be removed in 1.5. It does not have any effect.
+ warnings.warn(
+
LSML is a simple, yet effective, algorithm that learns a Mahalanobis +metric from a given set of relative comparisons. This is done by +formulating and minimizing a convex loss function that corresponds to +the sum of squared hinge loss of violated constraints.
+See more in the User Guide
See more in the documentation of the class LSML
NCA is an extremly popular metric learning algorithm.
+Neighborhood components analysis aims at “learning” a distance metric +by finding a linear transformation of input data such that the average +leave-one-out (LOO) classification performance of a soft-nearest +neighbors rule is maximized in the transformed space. The key insight to +the algorithm is that a matrix \(A\) corresponding to the +transformation can be found by defining a differentiable objective function +for \(A\), followed by use of an iterative solver such as +scipy.optimize.fmin_l_bfgs_b. Like LMNN, this algorithm does not try to +cluster points from the same class in a unique cluster, because it +enforces conditions at a local neighborhood scale.
+See more in the User Guide
See more in the documentation of the class NCA
LFDA is a linear supervised dimensionality reduction method. It is +particularly useful when dealing with multimodality, where one ore more +classes consist of separate clusters in input space. The core +optimization problem of LFDA is solved as a generalized eigenvalue +problem. Like LMNN, and NCA, this algorithm does not try to cluster points +from the same class in a unique cluster.
+See more in the User Guide
See more in the documentation of the class LFDA
RCA is another one of the older algorithms. It learns a full rank +Mahalanobis distance metric based on a weighted sum of in-class +covariance matrices. It applies a global linear transformation to assign +large weights to relevant dimensions and low weights to irrelevant +dimensions. Those relevant dimensions are estimated using “chunklets”, +subsets of points that are known to belong to the same class.
+See more in the User Guide
See more in the documentation of the class RCA
The previous algorithms took as input a dataset with class labels. Metric +learning can also be useful for regression, when the labels are real numbers. +An algorithm very similar to NCA but for regression is Metric +Learning for Kernel Regression (MLKR). It will optimize for the average +leave-one-out regression performance from a soft-nearest neighbors +regression.
+See more in the User Guide
See more in the documentation of the class MLKR
To illustrate MLKR, let’s use the dataset +sklearn.datasets.make_regression the same way as we did with the +classification before. The dataset will contain: 100 points of 5 features +each, among which 3 are informative (i.e., used to generate the +regression target from a linear model), and two are random noise with the +same magnitude.
+ +Let’s plot the dataset as is
+ +And let’s plot the dataset after transformation by MLKR:
+Points that have the same value to regress are now closer to each +other ! This would improve the performance of +sklearn.neighbors.KNeighborsRegressor for instance.
+To learn the metric, so far we have always given the labels of the +data to supervise the algorithms. However, in many applications, +it is easier to obtain information about whether two samples are +similar or dissimilar. For instance, when annotating a dataset of face +images, it is easier for an annotator to tell if two faces belong to the same +person or not, rather than finding the ID of the face among a huge database +of every person’s faces. +Note that for some problems (e.g., in information +retrieval where the goal is to rank documents by similarity to a query +document), there is no notion of individual label but one can gather +information on which pairs of points are similar or dissimilar. +Fortunately, one of the strength of metric learning is the ability to +learn from such weaker supervision. Indeed, some of the algorithms we’ve +used above have alternate ways to pass some supervision about the metric +we want to learn. The way to go is to pass a 2D array pairs of pairs, +as well as an array of labels pairs_labels such that for each i between +0 and n_pairs we want X[pairs[i, 0], :] and X[pairs[i, 1], :] to be +similar if pairs_labels[i] == 1, and we want them to be dissimilar if +pairs_labels[i] == -1. In other words, we +want to enforce a metric that projects similar points closer together and +dissimilar points further away from each other. This kind of input is +possible for ITML, SDML, and MMC. See Weakly Supervised Metric Learning for +details on other kinds of weak supervision that some algorithms can work +with.
+For the purpose of this example, we’re going to explicitly create these +pairwise constraints through the labels we have, i.e. y. +Do keep in mind that we are doing this method because we know the labels +- we can actually create the constraints any way we want to depending on +the data!
+Note that this is what metric-learn did under the hood in the previous +examples (do check out the +constraints module!) - but we’ll try our own version of this. We’re +going to go ahead and assume that two points labeled the same will be +closer than two points in different labels.
+def create_constraints(labels):
+ import itertools
+ import random
+
+ # aggregate indices of same class
+ zeros = np.where(y == 0)[0]
+ ones = np.where(y == 1)[0]
+ twos = np.where(y == 2)[0]
+ # make permutations of all those points in the same class
+ zeros_ = list(itertools.combinations(zeros, 2))
+ ones_ = list(itertools.combinations(ones, 2))
+ twos_ = list(itertools.combinations(twos, 2))
+ # put them together!
+ sim = np.array(zeros_ + ones_ + twos_)
+
+ # similarily, put together indices in different classes
+ dis = []
+ for zero in zeros:
+ for one in ones:
+ dis.append((zero, one))
+ for two in twos:
+ dis.append((zero, two))
+ for one in ones:
+ for two in twos:
+ dis.append((one, two))
+
+ # pick up just enough dissimilar examples as we have similar examples
+ dis = np.array(random.sample(dis, len(sim)))
+
+ # return an array of pairs of indices of shape=(2*len(sim), 2), and the
+ # corresponding labels, array of shape=(2*len(sim))
+ # Each pair of similar points have a label of +1 and each pair of
+ # dissimilar points have a label of -1
+ return (np.vstack([np.column_stack([sim[:, 0], sim[:, 1]]),
+ np.column_stack([dis[:, 0], dis[:, 1]])]),
+ np.concatenate([np.ones(len(sim)), -np.ones(len(sim))]))
+
+
+pairs, pairs_labels = create_constraints(y)
+
Now that we’ve created our constraints, let’s see what it looks like!
+print(pairs)
+print(pairs_labels)
+
[[ 0 6]
+ [ 0 9]
+ [ 0 10]
+ ...
+ [77 65]
+ [72 1]
+ [55 71]]
+[ 1. 1. 1. ... -1. -1. -1.]
+
Using our constraints, let’s now train ITML again. Note that we are no
+longer calling the supervised class ITML_Supervised
but the more generic
+(weakly-supervised) ITML
, which
+takes the dataset X through the preprocessor argument (see
+this section of the documentation to learn
+about more advanced uses of preprocessor) and the pair information pairs
+and pairs_labels in the fit method.
And that’s the result of ITML after being trained on our manually +constructed constraints! A bit different from our old result, but not too +different.
+RCA and LSML also have their own specific ways of taking in inputs - +it’s worth one’s while to poke around in the constraints.py file to see +how exactly this is going on.
+Finally, one of the main advantages of metric-learn is its out-of-the box +compatibility with scikit-learn, for doing model selection, +cross-validation, and scoring for instance. Indeed, supervised algorithms are +regular sklearn.base.TransformerMixin that can be plugged into any +pipeline or cross-validation procedure. And weakly-supervised estimators are +also compatible with scikit-learn, since their input dataset format described +above allows to be sliced along the first dimension when doing +cross-validations (see also this section). You +can also look at some use cases where you could combine +metric-learn with scikit-learn estimators.
+This brings us to the end of this tutorial! Have fun Metric Learning :)
+Total running time of the script: (0 minutes 32.400 seconds)
+ + +Note
+Go to the end +to download the full example code
+Sandwich demo based on code from http://nbviewer.ipython.org/6576096
+Note
+In order to show the charts of the examples you need a graphical
+matplotlib
backend installed. For intance, use pip install pyqt5
+to get Qt graphical interface or use your favorite one.
import numpy as np
+from matplotlib import pyplot as plt
+from sklearn.metrics import pairwise_distances
+from sklearn.neighbors import NearestNeighbors
+
+from metric_learn import (LMNN, ITML_Supervised, LSML_Supervised,
+ SDML_Supervised)
+
+
+def sandwich_demo():
+ x, y = sandwich_data()
+ knn = nearest_neighbors(x, k=2)
+ ax = plt.subplot(3, 1, 1) # take the whole top row
+ plot_sandwich_data(x, y, ax)
+ plot_neighborhood_graph(x, knn, y, ax)
+ ax.set_title('input space')
+ ax.set_aspect('equal')
+ ax.set_xticks([])
+ ax.set_yticks([])
+
+ mls = [
+ LMNN(),
+ ITML_Supervised(n_constraints=200),
+ SDML_Supervised(n_constraints=200, balance_param=0.001),
+ LSML_Supervised(n_constraints=200),
+ ]
+
+ for ax_num, ml in enumerate(mls, start=3):
+ ml.fit(x, y)
+ tx = ml.transform(x)
+ ml_knn = nearest_neighbors(tx, k=2)
+ ax = plt.subplot(3, 2, ax_num)
+ plot_sandwich_data(tx, y, axis=ax)
+ plot_neighborhood_graph(tx, ml_knn, y, axis=ax)
+ ax.set_title(ml.__class__.__name__)
+ ax.set_xticks([])
+ ax.set_yticks([])
+ plt.show()
+
+
+# TODO: use this somewhere
+def visualize_class_separation(X, labels):
+ _, (ax1, ax2) = plt.subplots(ncols=2)
+ label_order = np.argsort(labels)
+ ax1.imshow(pairwise_distances(X[label_order]), interpolation='nearest')
+ ax2.imshow(pairwise_distances(labels[label_order, None]),
+ interpolation='nearest')
+
+
+def nearest_neighbors(X, k=5):
+ knn = NearestNeighbors(n_neighbors=k)
+ knn.fit(X)
+ return knn.kneighbors(X, return_distance=False)
+
+
+def sandwich_data():
+ # number of distinct classes
+ num_classes = 6
+ # number of points per class
+ num_points = 9
+ # distance between layers, the points of each class are in a layer
+ dist = 0.7
+
+ data = np.zeros((num_classes, num_points, 2), dtype=float)
+ labels = np.zeros((num_classes, num_points), dtype=int)
+
+ x_centers = np.arange(num_points, dtype=float) - num_points / 2
+ y_centers = dist * (np.arange(num_classes, dtype=float) - num_classes / 2)
+ for i, yc in enumerate(y_centers):
+ for k, xc in enumerate(x_centers):
+ data[i, k, 0] = np.random.normal(xc, 0.1)
+ data[i, k, 1] = np.random.normal(yc, 0.1)
+ labels[i, :] = i
+ return data.reshape((-1, 2)), labels.ravel()
+
+
+def plot_sandwich_data(x, y, axis=plt, colors='rbgmky'):
+ for idx, val in enumerate(np.unique(y)):
+ xi = x[y == val]
+ axis.scatter(*xi.T, s=50, facecolors='none', edgecolors=colors[idx])
+
+
+def plot_neighborhood_graph(x, nn, y, axis=plt, colors='rbgmky'):
+ for i, a in enumerate(x):
+ b = x[nn[i, 1]]
+ axis.plot((a[0], b[0]), (a[1], b[1]), colors[y[i]])
+
+
+if __name__ == '__main__':
+ sandwich_demo()
+
/Users/william.vezelhes/metric-learn/metric_learn/constraints.py:224: UserWarning: Only generated 199 positive constraints (requested 200)
+ warnings.warn("Only generated %d %s constraints (requested %d)" % (
+/Users/william.vezelhes/miniconda3/envs/docenvbis/lib/python3.11/site-packages/sklearn/covariance/_graph_lasso.py:329: FutureWarning: The cov_init parameter is deprecated in 1.3 and will be removed in 1.5. It does not have any effect.
+ warnings.warn(
+
Total running time of the script: (0 minutes 3.314 seconds)
+ + +00:35.715 total execution time for auto_examples files:
+Algorithms walkthrough ( |
+00:32.400 |
+0.0 MB |
+
Sandwich demo ( |
+00:03.314 |
+0.0 MB |
+
metric_learn
.ConstraintsClass to build constraints from labeled data.
+See more in the User Guide.
+Array of labels, with -1 indicating unknown label.
+Array of labels, with -1 indicating unknown label.
+Methods
+
|
+Generates chunks from labeled data. |
+
|
+Generates triplets from labeled data. |
+
|
+Generates positive pairs and negative pairs from labeled data. |
+
Generates chunks from labeled data.
+Each of n_chunks
chunks is composed of chunk_size
points from
+the same class drawn at random. Each point can belong to at most 1 chunk.
In the case where there is not enough points to generate n_chunks
+chunks of size chunk_size
, a ValueError will be raised.
Number of chunks to generate.
+Number of points in each chunk.
+A pseudo random number generator object or a seed for it if int.
+1D array of chunk indicators, where -1 indicates that the point does not +belong to any chunk.
+Generates triplets from labeled data.
+For every point (X_a) the triplets (X_a, X_b, X_c) are constructed from all +the combinations of taking one of its k_genuine-nearest neighbors of the +same class (X_b) and taking one of its k_impostor-nearest neighbors of +other classes (X_c).
+In the case a class doesn’t have enough points in the same class (other +classes) to yield k_genuine (k_impostor) neighbors a warning will be +raised and the maximum value of genuine (impostor) neighbors will be used +for that class.
+Input data, where each row corresponds to a single instance.
+Number of neighbors of the same class to be taken into account.
+Number of neighbors of different classes to be taken into account.
+2D array of triplets of indicators.
+Generates positive pairs and negative pairs from labeled data.
+Positive pairs are formed by randomly drawing n_constraints
pairs of
+points with the same label. Negative pairs are formed by randomly drawing
+n_constraints
pairs of points with different label.
In the case where it is not possible to generate enough positive or +negative pairs, a smaller number of pairs will be returned with a warning.
+Number of positive and negative constraints to generate.
+If True, forces the number of positive and negative pairs to be +equal by ignoring some pairs from the larger set.
+A pseudo random number generator object or a seed for it if int.
+1D array of indicators for the left elements of positive pairs.
+1D array of indicators for the right elements of positive pairs.
+1D array of indicators for the left elements of negative pairs.
+1D array of indicators for the right elements of negative pairs.
+metric_learn
.CovarianceCovariance metric (baseline method)
+This method does not “learn” anything, rather it calculates +the covariance matrix of the input data.
+This is a simple baseline method first introduced in +On the Generalized Distance in Statistics, P.C.Mahalanobis, 1936
+Read more in the User Guide.
+Examples
+>>> from metric_learn import Covariance
+>>> from sklearn.datasets import load_iris
+>>> iris = load_iris()['data']
+>>> cov = Covariance().fit(iris)
+>>> x = cov.transform(iris)
+
The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
Methods
+
|
+Calculates the covariance matrix of the input data. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Calculates the covariance matrix of the input data.
+Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn
.ITMLInformation Theoretic Metric Learning (ITML)
+ITML minimizes the (differential) relative entropy, aka Kullback-Leibler +divergence, between two multivariate Gaussians subject to constraints on the +associated Mahalanobis distance, which can be formulated into a Bregman +optimization problem by minimizing the LogDet divergence subject to +linear constraints. This algorithm can handle a wide variety of constraints +and can optionally incorporate a prior on the distance function. Unlike some +other methods, ITML does not rely on an eigenvalue computation or +semi-definite programming.
+Read more in the User Guide.
+Value for slack variables
+Maximum number of iteration of the optimization procedure.
+Convergence tolerance.
+The Mahalanobis matrix to use as a prior. Possible options are +‘identity’, ‘covariance’, ‘random’, and a numpy array of shape +(n_features, n_features). For ITML, the prior should be strictly +positive definite (PD).
+An identity matrix of shape (n_features, n_features).
+The inverse covariance matrix.
+The prior will be a random SPD matrix of shape +(n_features, n_features), generated using +sklearn.datasets.make_spd_matrix.
+A positive definite (PD) matrix of shape +(n_features, n_features), that will be used as such to set the +prior.
+If True, prints information while learning
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+prior='random'
, random_state
is used to set the prior.
References
+Jason V. Davis, et al. Information-theoretic Metric Learning. ICML 2007.
+Examples
+>>> from metric_learn import ITML
+>>> pairs = [[[1.2, 7.5], [1.3, 1.5]],
+>>> [[6.4, 2.6], [6.2, 9.7]],
+>>> [[1.3, 4.5], [3.2, 4.6]],
+>>> [[6.2, 5.5], [5.4, 5.4]]]
+>>> y = [1, 1, -1, -1]
+>>> # in this task we want points where the first feature is close to be
+>>> # closer to each other, no matter how close the second feature is
+>>> itml = ITML()
+>>> itml.fit(pairs, y)
+
Bounds on similarity, aside slack variables, s.t.
+d(a, b) < bounds_[0]
for all given pairs of similar points a
+and b
, and d(c, d) > bounds_[1]
for all given pairs of
+dissimilar points c
and d
, with d
the learned distance. If
+not provided at initialization, bounds_[0] and bounds_[1] are set at
+train time to the 5th and 95th percentile of the pairwise distances among
+all points present in the input pairs.
The number of iterations the solver has run.
+The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
If the distance metric between two points is lower than this threshold, +points will be classified as similar, otherwise they will be +classified as dissimilar.
+Methods
+
|
+Decision threshold calibration for pairwise binary classification |
+
|
+Returns the decision function used to classify the pairs. |
+
|
+Learn the ITML model. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Predicts the learned metric between input pairs. |
+
|
+Computes score of pairs similarity prediction. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Set the parameters of this estimator. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Sets the threshold of the metric learner to the given value threshold. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Decision threshold calibration for pairwise binary classification
+Method that calibrates the decision threshold (cutoff point) of the metric
+learner. This threshold will then be used when calling the method
+predict. The methods for picking cutoff points make use of traditional
+binary classification evaluation statistics such as the true positive and
+true negative rates and F-scores. The threshold will be found to maximize
+the chosen score on the validation set (pairs_valid, y_valid)
.
See more in the User Guide.
+The strategy to use for choosing the cutoff threshold.
+Selects a decision threshold that maximizes the accuracy.
+Selects a decision threshold that maximizes the f_beta score, +with beta given by the parameter beta.
+Selects a decision threshold that yields the highest true positive +rate with true negative rate at least equal to the value of the +parameter min_rate.
+Selects a decision threshold that yields the highest true negative +rate with true positive rate at least equal to the value of the +parameter min_rate.
+Beta value to be used in case strategy == ‘f_beta’.
+In case strategy is ‘max_tpr’ or ‘max_tnr’ this parameter must be set +to specify the minimal value for the true negative rate or true positive +rate respectively that needs to be achieved.
+The validation set of pairs to use to set the threshold.
+The labels of the pairs of the validation set to use to set the +threshold. They must be +1 for positive pairs and -1 for negative pairs.
+See also
+sklearn.calibration
scikit-learn’s module for calibrating classifiers
+References
+Receiver-operating characteristic (ROC) plots: a fundamental +evaluation tool in clinical medicine, MH Zweig, G Campbell - +Clinical chemistry, 1993
+Most of the code of this function is from scikit-learn’s PR #10117
+Returns the decision function used to classify the pairs.
+Returns the opposite of the learned metric value between samples in every +pair, to be consistent with scikit-learn conventions. Hence it should +ideally be low for dissimilar samples and high for similar samples. +This is the decision function that is used to classify pairs as similar +(+1), or dissimilar (-1).
+3D Array of pairs to predict, with each row corresponding to two +points, or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The predicted decision function value for each pair.
+Learn the ITML model.
+The threshold will be calibrated on the trainset using the parameters +calibration_params.
+3D Array of pairs with each row corresponding to two points, +or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+Labels of constraints. Should be -1 for dissimilar pair, 1 for similar.
+Bounds on similarity, aside slack variables, s.t.
+d(a, b) < bounds_[0]
for all given pairs of similar points a
+and b
, and d(c, d) > bounds_[1]
for all given pairs of
+dissimilar points c
and d
, with d
the learned distance.
+If not provided at initialization, bounds_[0] and bounds_[1] will be
+set to the 5th and 95th percentile of the pairwise distances among all
+points present in the input pairs.
Dictionary of parameters to give to calibrate_threshold for the +threshold calibration step done at the end of fit. If None is +given, calibrate_threshold will use the default parameters.
+Returns the instance.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Predicts the learned metric between input pairs. (For now it just +calls decision function).
+Returns the learned metric value between samples in every pair. It should +ideally be low for similar samples and high for dissimilar samples.
+3D Array of pairs to predict, with each row corresponding to two +points, or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The predicted learned metric value between samples in every pair.
+Computes score of pairs similarity prediction.
+Returns the roc_auc
score of the fitted metric learner. It is
+computed in the following way: for every value of a threshold
+t
we classify all pairs of samples where the predicted distance is
+inferior to t
as belonging to the “similar” class, and the other as
+belonging to the “dissimilar” class, and we count false positive and
+true positives as in a classical roc_auc
curve.
3D Array of pairs, with each row corresponding to two points, +or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The corresponding labels.
+The roc_auc
score.
Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Request metadata passed to the decision_function
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to decision_function
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to decision_function
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in decision_function
.
The updated object.
+Request metadata passed to the fit
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to fit
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to fit
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for bounds
parameter in fit
.
Metadata routing for calibration_params
parameter in fit
.
Metadata routing for pairs
parameter in fit
.
The updated object.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Request metadata passed to the predict
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to predict
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to predict
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in predict
.
The updated object.
+Request metadata passed to the score
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to score
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to score
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in score
.
The updated object.
+Sets the threshold of the metric learner to the given value threshold.
+See more in the User Guide.
+The threshold value we want to set. It is the value to which the +predicted distance for test pairs will be compared. If they are superior +to the threshold they will be classified as similar (+1), +and dissimilar (-1) if not.
+The pairs classifier with the new threshold set.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.ITML
metric_learn
.ITML_SupervisedSupervised version of Information Theoretic Metric Learning (ITML)
+ITML_Supervised creates pairs of similar sample by taking same class +samples, and pairs of dissimilar samples by taking different class +samples. It then passes these pairs to ITML for training.
+Value for slack variables
+Maximum number of iterations of the optimization procedure.
+Tolerance of the optimization procedure.
+Number of constraints to generate. If None, default to 20 * +num_classes**2.
+Initialization of the Mahalanobis matrix. Possible options are +‘identity’, ‘covariance’, ‘random’, and a numpy array of shape +(n_features, n_features). For ITML, the prior should be strictly +positive definite (PD).
+An identity matrix of shape (n_features, n_features).
+The inverse covariance matrix.
+The prior will be a random SPD matrix of shape +(n_features, n_features), generated using +sklearn.datasets.make_spd_matrix.
+A positive definite (PD) matrix of shape +(n_features, n_features), that will be used as such to set the +prior.
+If True, prints information while learning
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+prior='random'
, random_state
is used to set the prior. In any
+case, random_state is also used to randomly sample constraints from
+labels.
See also
+metric_learn.ITML
The original weakly-supervised algorithm
+The section of the project documentation that describes the supervised version of weakly supervised estimators.
+Examples
+>>> from metric_learn import ITML_Supervised
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> itml = ITML_Supervised(n_constraints=200)
+>>> itml.fit(X, Y)
+
Bounds on similarity, aside slack variables, s.t.
+d(a, b) < bounds_[0]
for all given pairs of similar points a
+and b
, and d(c, d) > bounds_[1]
for all given pairs of
+dissimilar points c
and d
, with d
the learned distance.
+If not provided at initialization, bounds_[0] and bounds_[1] are set at
+train time to the 5th and 95th percentile of the pairwise distances
+among all points in the training data X.
The number of iterations the solver has run.
+The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
Methods
+
|
+Create constraints from labels and learn the ITML model. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Request metadata passed to the |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Create constraints from labels and learn the ITML model.
+Input data, where each row corresponds to a single instance.
+Data labels.
+Bounds on similarity, aside slack variables, s.t.
+d(a, b) < bounds_[0]
for all given pairs of similar points a
+and b
, and d(c, d) > bounds_[1]
for all given pairs of
+dissimilar points c
and d
, with d
the learned distance.
+If not provided at initialization, bounds_[0] and bounds_[1] will be
+set to the 5th and 95th percentile of the pairwise distances among all
+points in the training data X.
Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Request metadata passed to the fit
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to fit
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to fit
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for bounds
parameter in fit
.
The updated object.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.ITML_Supervised
metric_learn
.LFDALocal Fisher Discriminant Analysis for Supervised Dimensionality Reduction
+LFDA is a linear supervised dimensionality reduction method. It is +particularly useful when dealing with multimodality, where one ore more +classes consist of separate clusters in input space. The core optimization +problem of LFDA is solved as a generalized eigenvalue problem.
+Read more in the User Guide.
+Dimensionality of reduced space (if None, defaults to dimension of X).
+Number of nearest neighbors used in local scaling method. If None, +defaults to min(7, n_features - 1).
+Type of metric in the embedding space.
+weighted eigenvectors
+orthonormalized
+raw eigenvectors
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+References
+Masashi Sugiyama. Dimensionality Reduction of Multimodal Labeled +Data by Local Fisher Discriminant Analysis. JMLR 2007.
+Yuan Tang. Local Fisher Discriminant Analysis on Beer Style +Clustering.
+Examples
+>>> import numpy as np
+>>> from metric_learn import LFDA
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> lfda = LFDA(k=2, dim=2)
+>>> lfda.fit(X, Y)
+
The learned linear transformation L
.
Methods
+
|
+Fit the LFDA model. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Fit the LFDA model.
+Input data.
+Class labels, one per point of data.
+Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.LFDA
metric_learn
.LMNNLarge Margin Nearest Neighbor (LMNN)
+LMNN learns a Mahalanobis distance metric in the kNN classification +setting. The learned metric attempts to keep close k-nearest neighbors +from the same class, while keeping examples from different classes +separated by a large margin. This algorithm makes no assumptions about +the distribution of the data.
+Read more in the User Guide.
+Initialization of the linear transformation. Possible options are +‘auto’, ‘pca’, ‘identity’, ‘random’, and a numpy array of shape +(n_features_a, n_features_b).
+Depending on n_components
, the most reasonable initialization
+will be chosen. If n_components <= n_classes
we use ‘lda’, as
+it uses labels information. If not, but
+n_components < min(n_features, n_samples)
, we use ‘pca’, as
+it projects data in meaningful directions (those of higher
+variance). Otherwise, we just use ‘identity’.
n_components
principal components of the inputs passed
+to fit()
will be used to initialize the transformation.
+(See sklearn.decomposition.PCA)
min(n_components, n_classes)
most discriminative
+components of the inputs passed to fit()
will be used to
+initialize the transformation. (If n_components > n_classes
,
+the rest of the components will be zero.) (See
+sklearn.discriminant_analysis.LinearDiscriminantAnalysis)
If n_components
is strictly smaller than the
+dimensionality of the inputs passed to fit()
, the identity
+matrix will be truncated to the first n_components
rows.
The initial transformation will be a random array of shape +(n_components, n_features). Each value is sampled from the +standard normal distribution.
+n_features_b must match the dimensionality of the inputs passed to
+fit()
and n_features_a must be less than or equal to that.
+If n_components
is not None, n_features_a must match it.
Number of neighbors to consider, not including self-edges.
+Minimum number of iterations of the optimization procedure.
+Maximum number of iterations of the optimization procedure.
+Learning rate of the optimization procedure
+Tolerance of the optimization procedure. If the objective value varies +less than tol, we consider the algorithm has converged and stop it.
+Whether to print the progress of the optimization procedure.
+Relative weight between pull and push terms, with 0.5 meaning equal +weight.
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+Dimensionality of reduced space (if None, defaults to dimension of X).
+A pseudo random number generator object or a seed for it if int. If
+init='random'
, random_state
is used to initialize the random
+transformation. If init='pca'
, random_state
is passed as an
+argument to PCA when initializing the transformation.
References
+K. Q. Weinberger, J. Blitzer, L. K. Saul. Distance Metric +Learning for Large Margin Nearest Neighbor Classification. NIPS +2005.
+Examples
+>>> import numpy as np
+>>> from metric_learn import LMNN
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> lmnn = LMNN(n_neighbors=5, learn_rate=1e-6)
+>>> lmnn.fit(X, Y, verbose=False)
+
The number of iterations the solver has run.
+The learned linear transformation L
.
Methods
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
fit |
++ |
Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.LMNN
metric_learn
.LSMLLeast Squared-residual Metric Learning (LSML)
+LSML proposes a simple, yet effective, algorithm that minimizes a convex +objective function corresponding to the sum of squared residuals of +constraints. This algorithm uses the constraints in the form of the +relative distance comparisons, such method is especially useful where +pairwise constraints are not natural to obtain, thus pairwise constraints +based algorithms become infeasible to be deployed. Furthermore, its sparsity +extension leads to more stable estimation when the dimension is high and +only a small amount of constraints is given.
+Read more in the User Guide.
+Prior to set for the metric. Possible options are +‘identity’, ‘covariance’, ‘random’, and a numpy array of +shape (n_features, n_features). For LSML, the prior should be strictly +positive definite (PD).
+An identity matrix of shape (n_features, n_features).
+The inverse covariance matrix.
+The initial Mahalanobis matrix will be a random positive definite +(PD) matrix of shape (n_features, n_features), generated using +sklearn.datasets.make_spd_matrix.
+A positive definite (PD) matrix of shape +(n_features, n_features), that will be used as such to set the +prior.
+Convergence tolerance of the optimization procedure.
+Maximum number of iteration of the optimization procedure.
+If True, prints information while learning
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+init='random'
, random_state
is used to set the random
+prior.
See also
+metric_learn.LSML
The original weakly-supervised algorithm
+The section of the project documentation that describes the supervised version of weakly supervised estimators.
+References
+Liu et al. Metric Learning from Relative Comparisons by Minimizing +Squared Residual. ICDM 2012.
+Code adapted from https://gist.github.com/kcarnold/5439917
+Examples
+>>> from metric_learn import LSML
+>>> quadruplets = [[[1.2, 7.5], [1.3, 1.5], [6.4, 2.6], [6.2, 9.7]],
+>>> [[1.3, 4.5], [3.2, 4.6], [6.2, 5.5], [5.4, 5.4]],
+>>> [[3.2, 7.5], [3.3, 1.5], [8.4, 2.6], [8.2, 9.7]],
+>>> [[3.3, 4.5], [5.2, 4.6], [8.2, 5.5], [7.4, 5.4]]]
+>>> # we want to make closer points where the first feature is close, and
+>>> # further if the second feature is close
+>>> lsml = LSML()
+>>> lsml.fit(quadruplets)
+
The number of iterations the solver has run.
+The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
Methods
+
|
+Predicts differences between sample distances in input quadruplets. |
+
|
+Learn the LSML model. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Predicts the ordering between sample distances in input quadruplets. |
+
|
+Computes score on input quadruplets |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Set the parameters of this estimator. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Embeds data points in the learned linear embedding space. |
+
Predicts differences between sample distances in input quadruplets.
+For each quadruplet in the samples, computes the difference between the +learned metric of the second pair minus the learned metric of the first +pair. The higher it is, the more probable it is that the pairs in the +quadruplet are presented in the right order, i.e. that the label of the +quadruplet is 1. The lower it is, the more probable it is that the label of +the quadruplet is -1.
+3D Array of quadruplets to predict, with each row corresponding to four +points, or 2D array of indices of quadruplets if the metric learner +uses a preprocessor.
+Metric differences.
+Learn the LSML model.
+3D array-like of quadruplets of points or 2D array of quadruplets of +indicators. In order to supervise the algorithm in the right way, we +should have the four samples ordered in a way such that: +d(pairs[i, 0],X[i, 1]) < d(X[i, 2], X[i, 3]) for all 0 <= i < +n_constraints.
+scale factor for each constraint
+Returns the instance.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Predicts the ordering between sample distances in input quadruplets.
+For each quadruplet, returns 1 if the quadruplet is in the right order ( +first pair is more similar than second pair), and -1 if not.
+3D Array of quadruplets to predict, with each row corresponding to four +points, or 2D array of indices of quadruplets if the metric learner +uses a preprocessor.
+Predictions of the ordering of pairs, for each quadruplet.
+Computes score on input quadruplets
+Returns the accuracy score of the following classification task: a record +is correctly classified if the predicted similarity between the first two +samples is higher than that of the last two.
+3D Array of quadruplets to score, with each row corresponding to four +points, or 2D array of indices of quadruplets if the metric learner +uses a preprocessor.
+The quadruplets score.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Request metadata passed to the decision_function
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to decision_function
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to decision_function
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for quadruplets
parameter in decision_function
.
The updated object.
+Request metadata passed to the fit
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to fit
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to fit
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for quadruplets
parameter in fit
.
Metadata routing for weights
parameter in fit
.
The updated object.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Request metadata passed to the predict
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to predict
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to predict
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for quadruplets
parameter in predict
.
The updated object.
+Request metadata passed to the score
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to score
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to score
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for quadruplets
parameter in score
.
The updated object.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.LSML
metric_learn
.LSML_SupervisedSupervised version of Least Squared-residual Metric Learning (LSML)
+LSML_Supervised creates quadruplets from labeled samples by taking two +samples from the same class, and two samples from different classes. +This way it builds quadruplets where the two first points must be more +similar than the two last points.
+Convergence tolerance of the optimization procedure.
+Number of maximum iterations of the optimization procedure.
+Prior to set for the metric. Possible options are +‘identity’, ‘covariance’, ‘random’, and a numpy array of +shape (n_features, n_features). For LSML, the prior should be strictly +positive definite (PD).
+An identity matrix of shape (n_features, n_features).
+The inverse covariance matrix.
+The initial Mahalanobis matrix will be a random positive definite +(PD) matrix of shape (n_features, n_features), generated using +sklearn.datasets.make_spd_matrix.
+A positive definite (PD) matrix of shape +(n_features, n_features), that will be used as such to set the +prior.
+Number of constraints to generate. If None, default to 20 * +num_classes**2.
+Relative weight given to each constraint. If None, defaults to uniform +weights.
+If True, prints information while learning
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+init='random'
, random_state
is used to set the random
+prior. In any case, random_state is also used to randomly sample
+constraints from labels.
Examples
+>>> from metric_learn import LSML_Supervised
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> lsml = LSML_Supervised(n_constraints=200)
+>>> lsml.fit(X, Y)
+
The number of iterations the solver has run.
+The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
Methods
+
|
+Create constraints from labels and learn the LSML model. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Create constraints from labels and learn the LSML model.
+Input data, where each row corresponds to a single instance.
+Data labels.
+Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.LSML_Supervised
metric_learn
.MLKRMetric Learning for Kernel Regression (MLKR)
+MLKR is an algorithm for supervised metric learning, which learns a +distance function by directly minimizing the leave-one-out regression error. +This algorithm can also be viewed as a supervised variation of PCA and can be +used for dimensionality reduction and high dimensional data visualization.
+Read more in the User Guide.
+Dimensionality of reduced space (if None, defaults to dimension of X).
+Initialization of the linear transformation. Possible options are +‘auto’, ‘pca’, ‘identity’, ‘random’, and a numpy array of shape +(n_features_a, n_features_b).
+Depending on n_components
, the most reasonable initialization
+will be chosen. If n_components < min(n_features, n_samples)
,
+we use ‘pca’, as it projects data in meaningful directions (those
+of higher variance). Otherwise, we just use ‘identity’.
n_components
principal components of the inputs passed
+to fit()
will be used to initialize the transformation.
+(See sklearn.decomposition.PCA)
If n_components
is strictly smaller than the
+dimensionality of the inputs passed to fit()
, the identity
+matrix will be truncated to the first n_components
rows.
The initial transformation will be a random array of shape +(n_components, n_features). Each value is sampled from the +standard normal distribution.
+n_features_b must match the dimensionality of the inputs passed to
+fit()
and n_features_a must be less than or equal to that.
+If n_components
is not None, n_features_a must match it.
Convergence tolerance for the optimization.
+Cap on number of conjugate gradient iterations.
+Whether to print progress messages or not.
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+init='random'
, random_state
is used to initialize the random
+transformation. If init='pca'
, random_state
is passed as an
+argument to PCA when initializing the transformation.
References
+K.Q. Weinberger and G. Tesauto. Metric Learning for Kernel +Regression. AISTATS 2007.
+Examples
+>>> from metric_learn import MLKR
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> mlkr = MLKR()
+>>> mlkr.fit(X, Y)
+
The number of iterations the solver has run.
+The learned linear transformation L
.
Methods
+
|
+Fit MLKR model |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Fit MLKR model
+Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.MLKR
metric_learn
.MMCMahalanobis Metric for Clustering (MMC)
+MMC minimizes the sum of squared distances between similar points, while +enforcing the sum of distances between dissimilar ones to be greater than +one. This leads to a convex and, thus, local-minima-free optimization +problem that can be solved efficiently. +However, the algorithm involves the computation of eigenvalues, which is the +main speed-bottleneck. Since it has initially been designed for clustering +applications, one of the implicit assumptions of MMC is that all classes form +a compact set, i.e., follow a unimodal distribution, which restricts the +possible use-cases of this method. However, it is one of the earliest and a +still often cited technique.
+Read more in the User Guide.
+Maximum number of iterations of the optimization procedure.
+Maximum number of projection steps.
+Convergence threshold for the optimization procedure.
+Initialization of the Mahalanobis matrix. Possible options are +‘identity’, ‘covariance’, ‘random’, and a numpy array of +shape (n_features, n_features).
+An identity matrix of shape (n_features, n_features).
+The (pseudo-)inverse of the covariance matrix.
+The initial Mahalanobis matrix will be a random SPD matrix of +shape +(n_features, n_features), generated using +sklearn.datasets.make_spd_matrix.
+An SPD matrix of shape (n_features, n_features), that will +be used as such to initialize the metric.
+If True, a diagonal metric will be learned, +i.e., a simple scaling of dimensions. The initialization will then +be the diagonal coefficients of the matrix given as ‘init’.
+Weight of the dissimilarity constraint for diagonal
+metric learning. Ignored if diagonal=False
.
If True, prints information while learning
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be gotten like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+init='random'
, random_state
is used to initialize the random
+transformation.
See also
+metric_learn.MMC
The original weakly-supervised algorithm
+The section of the project documentation that describes the supervised version of weakly supervised estimators.
+References
+Xing, Jordan, Russell, Ng. Distance metric learning with application +to clustering with side-information. +NIPS 2002.
+Examples
+>>> from metric_learn import MMC
+>>> pairs = [[[1.2, 7.5], [1.3, 1.5]],
+>>> [[6.4, 2.6], [6.2, 9.7]],
+>>> [[1.3, 4.5], [3.2, 4.6]],
+>>> [[6.2, 5.5], [5.4, 5.4]]]
+>>> y = [1, 1, -1, -1]
+>>> # in this task we want points where the first feature is close to be
+>>> # closer to each other, no matter how close the second feature is
+>>> mmc = MMC()
+>>> mmc.fit(pairs, y)
+
The number of iterations the solver has run.
+The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
If the distance metric between two points is lower than this threshold, +points will be classified as similar, otherwise they will be +classified as dissimilar.
+Methods
+
|
+Decision threshold calibration for pairwise binary classification |
+
|
+Returns the decision function used to classify the pairs. |
+
|
+Learn the MMC model. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Predicts the learned metric between input pairs. |
+
|
+Computes score of pairs similarity prediction. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Set the parameters of this estimator. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Sets the threshold of the metric learner to the given value threshold. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Decision threshold calibration for pairwise binary classification
+Method that calibrates the decision threshold (cutoff point) of the metric
+learner. This threshold will then be used when calling the method
+predict. The methods for picking cutoff points make use of traditional
+binary classification evaluation statistics such as the true positive and
+true negative rates and F-scores. The threshold will be found to maximize
+the chosen score on the validation set (pairs_valid, y_valid)
.
See more in the User Guide.
+The strategy to use for choosing the cutoff threshold.
+Selects a decision threshold that maximizes the accuracy.
+Selects a decision threshold that maximizes the f_beta score, +with beta given by the parameter beta.
+Selects a decision threshold that yields the highest true positive +rate with true negative rate at least equal to the value of the +parameter min_rate.
+Selects a decision threshold that yields the highest true negative +rate with true positive rate at least equal to the value of the +parameter min_rate.
+Beta value to be used in case strategy == ‘f_beta’.
+In case strategy is ‘max_tpr’ or ‘max_tnr’ this parameter must be set +to specify the minimal value for the true negative rate or true positive +rate respectively that needs to be achieved.
+The validation set of pairs to use to set the threshold.
+The labels of the pairs of the validation set to use to set the +threshold. They must be +1 for positive pairs and -1 for negative pairs.
+See also
+sklearn.calibration
scikit-learn’s module for calibrating classifiers
+References
+Receiver-operating characteristic (ROC) plots: a fundamental +evaluation tool in clinical medicine, MH Zweig, G Campbell - +Clinical chemistry, 1993
+Most of the code of this function is from scikit-learn’s PR #10117
+Returns the decision function used to classify the pairs.
+Returns the opposite of the learned metric value between samples in every +pair, to be consistent with scikit-learn conventions. Hence it should +ideally be low for dissimilar samples and high for similar samples. +This is the decision function that is used to classify pairs as similar +(+1), or dissimilar (-1).
+3D Array of pairs to predict, with each row corresponding to two +points, or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The predicted decision function value for each pair.
+Learn the MMC model.
+The threshold will be calibrated on the trainset using the parameters +calibration_params.
+3D Array of pairs with each row corresponding to two points, +or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+Labels of constraints. Should be -1 for dissimilar pair, 1 for similar.
+Dictionary of parameters to give to calibrate_threshold for the +threshold calibration step done at the end of fit. If None is +given, calibrate_threshold will use the default parameters.
+Returns the instance.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Predicts the learned metric between input pairs. (For now it just +calls decision function).
+Returns the learned metric value between samples in every pair. It should +ideally be low for similar samples and high for dissimilar samples.
+3D Array of pairs to predict, with each row corresponding to two +points, or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The predicted learned metric value between samples in every pair.
+Computes score of pairs similarity prediction.
+Returns the roc_auc
score of the fitted metric learner. It is
+computed in the following way: for every value of a threshold
+t
we classify all pairs of samples where the predicted distance is
+inferior to t
as belonging to the “similar” class, and the other as
+belonging to the “dissimilar” class, and we count false positive and
+true positives as in a classical roc_auc
curve.
3D Array of pairs, with each row corresponding to two points, +or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The corresponding labels.
+The roc_auc
score.
Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Request metadata passed to the decision_function
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to decision_function
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to decision_function
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in decision_function
.
The updated object.
+Request metadata passed to the fit
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to fit
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to fit
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for calibration_params
parameter in fit
.
Metadata routing for pairs
parameter in fit
.
The updated object.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Request metadata passed to the predict
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to predict
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to predict
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in predict
.
The updated object.
+Request metadata passed to the score
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to score
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to score
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in score
.
The updated object.
+Sets the threshold of the metric learner to the given value threshold.
+See more in the User Guide.
+The threshold value we want to set. It is the value to which the +predicted distance for test pairs will be compared. If they are superior +to the threshold they will be classified as similar (+1), +and dissimilar (-1) if not.
+The pairs classifier with the new threshold set.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.MMC
metric_learn
.MMC_SupervisedSupervised version of Mahalanobis Metric for Clustering (MMC)
+MMC_Supervised creates pairs of similar sample by taking same class +samples, and pairs of dissimilar samples by taking different class +samples. It then passes these pairs to MMC for training.
+Maximum number of iterations of the optimization procedure.
+Maximum number of projection steps.
+Convergence threshold for the optimization procedure.
+Number of constraints to generate. If None, default to 20 * +num_classes**2.
+Initialization of the Mahalanobis matrix. Possible options are +‘identity’, ‘covariance’, ‘random’, and a numpy array of +shape (n_features, n_features).
+An identity matrix of shape (n_features, n_features).
+The (pseudo-)inverse of the covariance matrix.
+The initial Mahalanobis matrix will be a random SPD matrix of +shape (n_features, n_features), generated using +sklearn.datasets.make_spd_matrix.
+A numpy array of shape (n_features, n_features), that will +be used as such to initialize the metric.
+If True, a diagonal metric will be learned, +i.e., a simple scaling of dimensions. The initialization will then +be the diagonal coefficients of the matrix given as ‘init’.
+Weight of the dissimilarity constraint for diagonal
+metric learning. Ignored if diagonal=False
.
If True, prints information while learning
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+init='random'
, random_state
is used to initialize the random
+Mahalanobis matrix. In any case, random_state is also used to
+randomly sample constraints from labels.
Examples
+>>> from metric_learn import MMC_Supervised
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> mmc = MMC_Supervised(n_constraints=200)
+>>> mmc.fit(X, Y)
+
The number of iterations the solver has run.
+The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
Methods
+
|
+Create constraints from labels and learn the MMC model. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Create constraints from labels and learn the MMC model.
+Input data, where each row corresponds to a single instance.
+Data labels.
+Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.MMC_Supervised
metric_learn
.NCANeighborhood Components Analysis (NCA)
+NCA is a distance metric learning algorithm which aims to improve the +accuracy of nearest neighbors classification compared to the standard +Euclidean distance. The algorithm directly maximizes a stochastic variant +of the leave-one-out k-nearest neighbors(KNN) score on the training set. +It can also learn a low-dimensional linear transformation of data that can +be used for data visualization and fast classification.
+Read more in the User Guide.
+Initialization of the linear transformation. Possible options are +‘auto’, ‘pca’, ‘identity’, ‘random’, and a numpy array of shape +(n_features_a, n_features_b).
+Depending on n_components
, the most reasonable initialization
+will be chosen. If n_components <= n_classes
we use ‘lda’, as
+it uses labels information. If not, but
+n_components < min(n_features, n_samples)
, we use ‘pca’, as
+it projects data in meaningful directions (those of higher
+variance). Otherwise, we just use ‘identity’.
n_components
principal components of the inputs passed
+to fit()
will be used to initialize the transformation.
+(See sklearn.decomposition.PCA)
min(n_components, n_classes)
most discriminative
+components of the inputs passed to fit()
will be used to
+initialize the transformation. (If n_components > n_classes
,
+the rest of the components will be zero.) (See
+sklearn.discriminant_analysis.LinearDiscriminantAnalysis)
If n_components
is strictly smaller than the
+dimensionality of the inputs passed to fit()
, the identity
+matrix will be truncated to the first n_components
rows.
The initial transformation will be a random array of shape +(n_components, n_features). Each value is sampled from the +standard normal distribution.
+n_features_b must match the dimensionality of the inputs passed to
+fit()
and n_features_a must be less than or equal to that.
+If n_components
is not None, n_features_a must match it.
Dimensionality of reduced space (if None, defaults to dimension of X).
+Maximum number of iterations done by the optimization algorithm.
+Convergence tolerance for the optimization.
+Whether to print progress messages or not.
+A pseudo random number generator object or a seed for it if int. If
+init='random'
, random_state
is used to initialize the random
+transformation. If init='pca'
, random_state
is passed as an
+argument to PCA when initializing the transformation.
References
+J. Goldberger, G. Hinton, S. Roweis, R. Salakhutdinov. Neighbourhood +Components Analysis. +NIPS 2005.
+Wikipedia entry on Neighborhood Components Analysis
+Examples
+>>> import numpy as np
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> nca = NCA(max_iter=1000)
+>>> nca.fit(X, Y)
+
The number of iterations the solver has run.
+The learned linear transformation L
.
Methods
+
|
+X: data matrix, (n x d) y: scalar labels, (n) |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.NCA
metric_learn
.RCARelevant Components Analysis (RCA)
+RCA learns a full rank Mahalanobis distance metric based on a weighted sum of +in-chunklets covariance matrices. It applies a global linear transformation +to assign large weights to relevant dimensions and low weights to irrelevant +dimensions. Those relevant dimensions are estimated using “chunklets”, +subsets of points that are known to belong to the same class.
+Read more in the User Guide.
+Dimensionality of reduced space (if None, defaults to dimension of X).
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+References
+Noam Shental, et al. Adjustment learning and relevant component +analysis . +ECCV 2002.
+Examples
+>>> from metric_learn import RCA
+>>> X = [[-0.05, 3.0],[0.05, -3.0],
+>>> [0.1, -3.55],[-0.1, 3.55],
+>>> [-0.95, -0.05],[0.95, 0.05],
+>>> [0.4, 0.05],[-0.4, -0.05]]
+>>> chunks = [0, 0, 1, 1, 2, 2, 3, 3]
+>>> rca = RCA()
+>>> rca.fit(X, chunks)
+
The learned linear transformation L
.
Methods
+
|
+Learn the RCA model. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Request metadata passed to the |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Learn the RCA model.
+Each row corresponds to a single instance
+When chunks[i] == -1
, point i doesn’t belong to any chunklet.
+When chunks[i] == j
, point i belongs to chunklet j.
Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Request metadata passed to the fit
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to fit
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to fit
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for chunks
parameter in fit
.
The updated object.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.RCA
metric_learn
.RCA_SupervisedSupervised version of Relevant Components Analysis (RCA)
+RCA_Supervised creates chunks of similar points by first sampling a +class, taking chunk_size elements in it, and repeating the process +n_chunks times.
+Dimensionality of reduced space (if None, defaults to dimension of X).
+Number of chunks to generate.
+Number of points per chunk.
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int. +It is used to randomly sample constraints from labels.
+Examples
+>>> from metric_learn import RCA_Supervised
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> rca = RCA_Supervised(n_chunks=30, chunk_size=2)
+>>> rca.fit(X, Y)
+
The learned linear transformation L
.
Methods
+
|
+Create constraints from labels and learn the RCA model. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Request metadata passed to the |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Initialize the supervised version of RCA.
+Create constraints from labels and learn the RCA model. +Needs n_constraints specified in constructor. (Not true?)
+each row corresponds to a single instance
+Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Request metadata passed to the fit
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to fit
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to fit
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for chunks
parameter in fit
.
The updated object.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.RCA_Supervised
metric_learn
.SCMLSparse Compositional Metric Learning (SCML)
+SCML learns an squared Mahalanobis distance from triplet constraints by +optimizing sparse positive weights assigned to a set of \(K\) rank-one +PSD bases. This can be formulated as an optimization problem with only +\(K\) parameters, that can be solved with an efficient stochastic +composite scheme.
+Read more in the User Guide.
+Warning
+SCML is still a bit experimental, don’t hesitate to report if +something fails/doesn’t work as expected.
+L1 regularization parameter.
+Set of bases to construct the metric. Possible options are +‘triplet_diffs’, and an array-like of shape (n_basis, n_features).
+The basis set is constructed iteratively from differences between points +of n_features positive or negative pairs randomly sampled from the +triplets constraints. Requires the number of training triplets to be +great or equal to n_features.
+A matrix of shape (n_basis, n_features), that will be used as +the basis set for the metric construction.
+Number of basis to be yielded. In case it is not set it will be set based +on basis. If no value is selected a default will be computed based on +the input.
+Learning rate for the optimization algorithm.
+Number of iterations for the algorithm.
+Number of iterations to check current weights performance and output this +information in case verbose is True.
+If True, prints information while learning.
+The preprocessor to call to get triplets from indices. If array-like, +triplets will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int.
+See also
+metric_learn.SCML_Supervised
The supervised version of the algorithm.
+The section of the project documentation that describes the supervised version of weakly supervised estimators.
+References
+Y. Shi, A. Bellet and F. Sha. Sparse Compositional Metric Learning.. (AAAI), 2014.
+Adapted from original Matlab implementation..
+Examples
+>>> from metric_learn import SCML
+>>> triplets = [[[1.2, 7.5], [1.3, 1.5], [6.2, 9.7]],
+>>> [[1.3, 4.5], [3.2, 4.6], [5.4, 5.4]],
+>>> [[3.2, 7.5], [3.3, 1.5], [8.2, 9.7]],
+>>> [[3.3, 4.5], [5.2, 4.6], [7.4, 5.4]]]
+>>> scml = SCML()
+>>> scml.fit(triplets)
+
The linear transformation L
deduced from the learned Mahalanobis
+metric (See function _components_from_basis_weights.)
Methods
+
|
+Predicts differences between sample distances in input triplets. |
+
|
+Learn the SCML model. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Predicts the ordering between sample distances in input triplets. |
+
|
+Computes score on input triplets. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Set the parameters of this estimator. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Embeds data points in the learned linear embedding space. |
+
Predicts differences between sample distances in input triplets.
+For each triplet (X_a, X_b, X_c) in the samples, computes the difference +between the learned distance of the second pair (X_a, X_c) minus the +learned distance of the first pair (X_a, X_b). The higher it is, the more +probable it is that the pairs in the triplets are presented in the right +order, i.e. that the label of the triplet is 1. The lower it is, the more +probable it is that the label of the triplet is -1.
+3D array of triplets to predict, with each row corresponding to three +points, or 2D array of indices of triplets if the metric learner +uses a preprocessor.
+Metric differences.
+Learn the SCML model.
+3D array-like of triplets of points or 2D array of triplets of +indicators. Triplets are assumed to be ordered such that: +d(triplets[i, 0],triplets[i, 1]) < d(triplets[i, 0], triplets[i, 2]).
+Returns the instance.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Predicts the ordering between sample distances in input triplets.
+For each triplets, returns 1 if the first element is closer to the second +than to the last and -1 if not.
+3D array of triplets to predict, with each row corresponding to three +points, or 2D array of indices of triplets if the metric learner +uses a preprocessor.
+Predictions of the ordering of pairs, for each triplet.
+Computes score on input triplets.
+Returns the accuracy score of the following classification task: a triplet +(X_a, X_b, X_c) is correctly classified if the predicted similarity between +the first pair (X_a, X_b) is higher than that of the second pair (X_a, X_c)
+3D array of triplets to score, with each row corresponding to three +points, or 2D array of indices of triplets if the metric learner +uses a preprocessor.
+The triplets score.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Request metadata passed to the decision_function
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to decision_function
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to decision_function
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for triplets
parameter in decision_function
.
The updated object.
+Request metadata passed to the fit
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to fit
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to fit
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for triplets
parameter in fit
.
The updated object.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Request metadata passed to the predict
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to predict
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to predict
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for triplets
parameter in predict
.
The updated object.
+Request metadata passed to the score
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to score
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to score
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for triplets
parameter in score
.
The updated object.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn
.SCML_SupervisedSupervised version of Sparse Compositional Metric Learning (SCML)
+SCML_Supervised creates triplets by taking k_genuine neighbours +of the same class and k_impostor neighbours from different classes for each +point and then runs the SCML algorithm on these triplets.
+Read more in the User Guide.
+Warning
+SCML is still a bit experimental, don’t hesitate to report if +something fails/doesn’t work as expected.
+L1 regularization parameter.
+Set of bases to construct the metric. Possible options are +‘lda’, and an array-like of shape (n_basis, n_features).
+The n_basis basis set is constructed from the LDA of significant +local regions in the feature space via clustering, for each region +center k-nearest neighbors are used to obtain the LDA scalings, +which correspond to the locally discriminative basis.
+A matrix of shape (n_basis, n_features), that will be used as +the basis set for the metric construction.
+Number of basis to be yielded. In case it is not set it will be set based +on basis. If no value is selected a default will be computed based on +the input.
+Learning rate for the optimization algorithm.
+Number of iterations for the algorithm.
+Number of iterations to check current weights performance and output this +information in case verbose is True.
+If True, prints information while learning.
+The preprocessor to call to get triplets from indices. If array-like, +triplets will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int.
+See also
+metric_learn.SCML
The weakly supervised version of this algorithm.
+References
+Y. Shi, A. Bellet and F. Sha. Sparse Compositional Metric Learning.. (AAAI), 2014.
+Adapted from original Matlab implementation..
+Examples
+>>> from metric_learn import SCML_Supervised
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> scml = SCML_Supervised(random_state=33)
+>>> scml.fit(X, Y)
+SCML_Supervised(random_state=33)
+>>> scml.score_pairs([[X[0], X[1]], [X[0], X[2]]])
+array([1.84640733, 1.55984363])
+>>> scml.get_metric()(X[0], X[1])
+1.8464073327922157
+
The linear transformation L
deduced from the learned Mahalanobis
+metric (See function _components_from_basis_weights.)
Methods
+
|
+Create constraints from labels and learn the SCML model. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Create constraints from labels and learn the SCML model.
+Input data, where each row corresponds to a single instance.
+Data labels.
+Returns the instance.
+Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn
.SDMLSparse Distance Metric Learning (SDML)
+SDML is an efficient sparse metric learning in high-dimensional space via +double regularization: an L1-penalization on the off-diagonal elements of the +Mahalanobis matrix \(\mathbf{M}\), and a log-determinant divergence +between \(\mathbf{M}\) and \(\mathbf{M_0}\) (set as either +\(\mathbf{I}\) or \(\mathbf{\Omega}^{-1}\), where +\(\mathbf{\Omega}\) is the covariance matrix).
+Read more in the User Guide.
+Trade off between sparsity and M0 prior.
+Trade off between optimizer and sparseness (see graph_lasso).
+Prior to set for the metric. Possible options are +‘identity’, ‘covariance’, ‘random’, and a numpy array of +shape (n_features, n_features). For SDML, the prior should be strictly +positive definite (PD).
+An identity matrix of shape (n_features, n_features).
+The inverse covariance matrix.
+The prior will be a random positive definite (PD) matrix of shape +(n_features, n_features), generated using +sklearn.datasets.make_spd_matrix.
+A positive definite (PD) matrix of shape +(n_features, n_features), that will be used as such to set the +prior.
+If True, prints information while learning.
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be gotten like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+prior='random'
, random_state
is used to set the prior.
References
+Qi et al. An efficient sparse metric learning in high-dimensional +space via L1-penalized log-determinant regularization. +ICML 2009.
+Code adapted from https://gist.github.com/kcarnold/5439945
+Examples
+>>> from metric_learn import SDML_Supervised
+>>> from sklearn.datasets import load_iris
+>>> iris_data = load_iris()
+>>> X = iris_data['data']
+>>> Y = iris_data['target']
+>>> sdml = SDML_Supervised(n_constraints=200)
+>>> sdml.fit(X, Y)
+
The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
If the distance metric between two points is lower than this threshold, +points will be classified as similar, otherwise they will be +classified as dissimilar.
+Methods
+
|
+Decision threshold calibration for pairwise binary classification |
+
|
+Returns the decision function used to classify the pairs. |
+
|
+Learn the SDML model. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Predicts the learned metric between input pairs. |
+
|
+Computes score of pairs similarity prediction. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Set the parameters of this estimator. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Sets the threshold of the metric learner to the given value threshold. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Decision threshold calibration for pairwise binary classification
+Method that calibrates the decision threshold (cutoff point) of the metric
+learner. This threshold will then be used when calling the method
+predict. The methods for picking cutoff points make use of traditional
+binary classification evaluation statistics such as the true positive and
+true negative rates and F-scores. The threshold will be found to maximize
+the chosen score on the validation set (pairs_valid, y_valid)
.
See more in the User Guide.
+The strategy to use for choosing the cutoff threshold.
+Selects a decision threshold that maximizes the accuracy.
+Selects a decision threshold that maximizes the f_beta score, +with beta given by the parameter beta.
+Selects a decision threshold that yields the highest true positive +rate with true negative rate at least equal to the value of the +parameter min_rate.
+Selects a decision threshold that yields the highest true negative +rate with true positive rate at least equal to the value of the +parameter min_rate.
+Beta value to be used in case strategy == ‘f_beta’.
+In case strategy is ‘max_tpr’ or ‘max_tnr’ this parameter must be set +to specify the minimal value for the true negative rate or true positive +rate respectively that needs to be achieved.
+The validation set of pairs to use to set the threshold.
+The labels of the pairs of the validation set to use to set the +threshold. They must be +1 for positive pairs and -1 for negative pairs.
+See also
+sklearn.calibration
scikit-learn’s module for calibrating classifiers
+References
+Receiver-operating characteristic (ROC) plots: a fundamental +evaluation tool in clinical medicine, MH Zweig, G Campbell - +Clinical chemistry, 1993
+Most of the code of this function is from scikit-learn’s PR #10117
+Returns the decision function used to classify the pairs.
+Returns the opposite of the learned metric value between samples in every +pair, to be consistent with scikit-learn conventions. Hence it should +ideally be low for dissimilar samples and high for similar samples. +This is the decision function that is used to classify pairs as similar +(+1), or dissimilar (-1).
+3D Array of pairs to predict, with each row corresponding to two +points, or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The predicted decision function value for each pair.
+Learn the SDML model.
+The threshold will be calibrated on the trainset using the parameters +calibration_params.
+3D Array of pairs with each row corresponding to two points, +or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+Labels of constraints. Should be -1 for dissimilar pair, 1 for similar.
+Dictionary of parameters to give to calibrate_threshold for the +threshold calibration step done at the end of fit. If None is +given, calibrate_threshold will use the default parameters.
+Returns the instance.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Predicts the learned metric between input pairs. (For now it just +calls decision function).
+Returns the learned metric value between samples in every pair. It should +ideally be low for similar samples and high for dissimilar samples.
+3D Array of pairs to predict, with each row corresponding to two +points, or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The predicted learned metric value between samples in every pair.
+Computes score of pairs similarity prediction.
+Returns the roc_auc
score of the fitted metric learner. It is
+computed in the following way: for every value of a threshold
+t
we classify all pairs of samples where the predicted distance is
+inferior to t
as belonging to the “similar” class, and the other as
+belonging to the “dissimilar” class, and we count false positive and
+true positives as in a classical roc_auc
curve.
3D Array of pairs, with each row corresponding to two points, +or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The corresponding labels.
+The roc_auc
score.
Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Request metadata passed to the decision_function
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to decision_function
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to decision_function
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in decision_function
.
The updated object.
+Request metadata passed to the fit
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to fit
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to fit
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for calibration_params
parameter in fit
.
Metadata routing for pairs
parameter in fit
.
The updated object.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Request metadata passed to the predict
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to predict
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to predict
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in predict
.
The updated object.
+Request metadata passed to the score
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to score
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to score
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in score
.
The updated object.
+Sets the threshold of the metric learner to the given value threshold.
+See more in the User Guide.
+The threshold value we want to set. It is the value to which the +predicted distance for test pairs will be compared. If they are superior +to the threshold they will be classified as similar (+1), +and dissimilar (-1) if not.
+The pairs classifier with the new threshold set.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.SDML
metric_learn
.SDML_SupervisedSupervised version of Sparse Distance Metric Learning (SDML)
+SDML_Supervised creates pairs of similar sample by taking same class +samples, and pairs of dissimilar samples by taking different class +samples. It then passes these pairs to SDML for training.
+Trade off between sparsity and M0 prior.
+Trade off between optimizer and sparseness (see graph_lasso).
+Prior to set for the metric. Possible options are +‘identity’, ‘covariance’, ‘random’, and a numpy array of +shape (n_features, n_features). For SDML, the prior should be strictly +positive definite (PD).
+An identity matrix of shape (n_features, n_features).
+The inverse covariance matrix.
+The prior will be a random SPD matrix of shape +(n_features, n_features), generated using +sklearn.datasets.make_spd_matrix.
+A positive definite (PD) matrix of shape +(n_features, n_features), that will be used as such to set the +prior.
+Number of constraints to generate. If None, defaults to 20 * +num_classes**2.
+If True, prints information while learning.
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be formed like this: X[indices].
+A pseudo random number generator object or a seed for it if int. If
+init='random'
, random_state
is used to set the random
+prior. In any case, random_state is also used to randomly sample
+constraints from labels.
See also
+metric_learn.SDML
The original weakly-supervised algorithm
+The section of the project documentation that describes the supervised version of weakly supervised estimators.
+The linear transformation L
deduced from the learned Mahalanobis
+metric (See function components_from_metric.)
Methods
+
|
+Create constraints from labels and learn the SDML model. |
+
|
+Fit to data, then transform it. |
+
+ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set output container. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Create constraints from labels and learn the SDML model.
+data matrix, where each row corresponds to a single instance
+data labels, one for each instance
+Returns the instance.
+Fit to data, then transform it.
+Fits transformer to X and y with optional parameters fit_params +and returns a transformed version of X.
+Input samples.
+Target values (None for unsupervised transformations).
+Additional fit parameters.
+Transformed array.
+Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set output container.
+See Introducing the set_output API +for an example on how to use the API.
+Configure output of transform and fit_transform.
+“default”: Default output format of a transformer
“pandas”: DataFrame output
None: Transform configuration is unchanged
Estimator instance.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.SDML_Supervised
metric_learn.base_metric
.BaseMetricLearnerBase class for all metric-learners.
+The preprocessor to call to get tuples from indices. If array-like, +tuples will be gotten like this: X[indices].
+Methods
++ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+
+
+New in version 0.7.0: Compute the distance between pairs + |
+
|
+
+
+New in version 0.7.0: Compute the similarity score between pairs + |
+
|
+Returns the score between pairs (can be a similarity, or a distance/metric depending on the algorithm) |
+
|
+Set the parameters of this estimator. |
+
Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+New in version 0.7.0: Compute the distance between pairs
+Returns the (pseudo) distance between pairs, when available. For metric +learners that do not learn a (pseudo) distance, an error is thrown +instead.
+3D Array of pairs for which to compute the distance, with each +row corresponding to two points, for 2D array of indices of pairs +if the metric learner uses a preprocessor.
+The distance between every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+New in version 0.7.0: Compute the similarity score between pairs
+Returns the similarity score between pairs of points (the larger the score, +the more similar the pair). For metric learners that learn a distance, +the score is simply the opposite of the distance between pairs. All +learners have access to this method.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The score of every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+Returns the score between pairs +(can be a similarity, or a distance/metric depending on the algorithm)
+Deprecated since version 0.7.0: Refer to pair_distance and pair_score.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The score of every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference between score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+metric_learn.base_metric.BaseMetricLearner
metric_learn.base_metric
.MahalanobisMixinMahalanobis metric learning algorithms.
+Algorithm that learns a Mahalanobis (pseudo) distance \(d_M(x, x')\), +defined between two column vectors \(x\) and \(x'\) by: \(d_M(x, +x') = \sqrt{(x-x')^T M (x-x')}\), where \(M\) is a learned symmetric +positive semi-definite (PSD) matrix. The metric between points can then be +expressed as the euclidean distance between points embedded in a new space +through a linear transformation. Indeed, the above matrix can be decomposed +into the product of two transpose matrices (through SVD or Cholesky +decomposition): \(d_M(x, x')^2 = (x-x')^T M (x-x') = (x-x')^T L^T L +(x-x') = (L x - L x')^T (L x- L x')\)
+The learned linear transformation L
.
Methods
++ | Returns a copy of the Mahalanobis matrix learned by the metric learner. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Returns the opposite of the learned Mahalanobis distance between pairs. |
+
|
+Returns the learned Mahalanobis distance between pairs. |
+
|
+Set the parameters of this estimator. |
+
|
+Embeds data points in the learned linear embedding space. |
+
Returns a copy of the Mahalanobis matrix learned by the metric learner.
+The copy of the learned Mahalanobis matrix.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the opposite of the learned Mahalanobis distance between pairs.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The opposite of the learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Returns the learned Mahalanobis distance between pairs.
+This distance is defined as: \(d_M(x, x') = \\sqrt{(x-x')^T M (x-x')}\)
+where M
is the learned Mahalanobis matrix, for every pair of points
+x
and x'
. This corresponds to the euclidean distance between
+embeddings of the points in a new space, obtained through a linear
+transformation. Indeed, we have also: \(d_M(x, x') = \\sqrt{(x_e -
+x_e')^T (x_e- x_e')}\), with \(x_e = L x\) (See
+MahalanobisMixin
).
Deprecated since version 0.7.0: Please use pair_distance instead.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The learned Mahalanobis distance for every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+The section of the project documentation that describes Mahalanobis Distances.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Embeds data points in the learned linear embedding space.
+Transforms samples in X
into X_embedded
, samples inside a new
+embedding space such that: X_embedded = X.dot(L.T)
, where L
is
+the learned linear transformation (See MahalanobisMixin
).
The data points to embed.
+The embedded data points.
+metric_learn.base_metric.MahalanobisMixin
metric_learn.base_metric
.MetricTransformerBase class for all learners that can transform data into a new space +with the metric learned.
+Methods
+
|
+Applies the metric transformation. |
+
metric_learn.base_metric.MetricTransformer
metric_learn.base_metric
._PairsClassifierMixinBase class for pairs learners.
+If the distance metric between two points is lower than this threshold, +points will be classified as similar, otherwise they will be +classified as dissimilar.
+Methods
+
|
+Decision threshold calibration for pairwise binary classification |
+
|
+Returns the decision function used to classify the pairs. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+
+
+New in version 0.7.0: Compute the distance between pairs + |
+
|
+
+
+New in version 0.7.0: Compute the similarity score between pairs + |
+
|
+Predicts the learned metric between input pairs. |
+
|
+Computes score of pairs similarity prediction. |
+
|
+Returns the score between pairs (can be a similarity, or a distance/metric depending on the algorithm) |
+
|
+Request metadata passed to the |
+
|
+Set the parameters of this estimator. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
|
+Sets the threshold of the metric learner to the given value threshold. |
+
Decision threshold calibration for pairwise binary classification
+Method that calibrates the decision threshold (cutoff point) of the metric
+learner. This threshold will then be used when calling the method
+predict. The methods for picking cutoff points make use of traditional
+binary classification evaluation statistics such as the true positive and
+true negative rates and F-scores. The threshold will be found to maximize
+the chosen score on the validation set (pairs_valid, y_valid)
.
See more in the User Guide.
+The strategy to use for choosing the cutoff threshold.
+Selects a decision threshold that maximizes the accuracy.
+Selects a decision threshold that maximizes the f_beta score, +with beta given by the parameter beta.
+Selects a decision threshold that yields the highest true positive +rate with true negative rate at least equal to the value of the +parameter min_rate.
+Selects a decision threshold that yields the highest true negative +rate with true positive rate at least equal to the value of the +parameter min_rate.
+Beta value to be used in case strategy == ‘f_beta’.
+In case strategy is ‘max_tpr’ or ‘max_tnr’ this parameter must be set +to specify the minimal value for the true negative rate or true positive +rate respectively that needs to be achieved.
+The validation set of pairs to use to set the threshold.
+The labels of the pairs of the validation set to use to set the +threshold. They must be +1 for positive pairs and -1 for negative pairs.
+See also
+sklearn.calibration
scikit-learn’s module for calibrating classifiers
+References
+Receiver-operating characteristic (ROC) plots: a fundamental +evaluation tool in clinical medicine, MH Zweig, G Campbell - +Clinical chemistry, 1993
+Most of the code of this function is from scikit-learn’s PR #10117
+Returns the decision function used to classify the pairs.
+Returns the opposite of the learned metric value between samples in every +pair, to be consistent with scikit-learn conventions. Hence it should +ideally be low for dissimilar samples and high for similar samples. +This is the decision function that is used to classify pairs as similar +(+1), or dissimilar (-1).
+3D Array of pairs to predict, with each row corresponding to two +points, or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The predicted decision function value for each pair.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+New in version 0.7.0: Compute the distance between pairs
+Returns the (pseudo) distance between pairs, when available. For metric +learners that do not learn a (pseudo) distance, an error is thrown +instead.
+3D Array of pairs for which to compute the distance, with each +row corresponding to two points, for 2D array of indices of pairs +if the metric learner uses a preprocessor.
+The distance between every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+New in version 0.7.0: Compute the similarity score between pairs
+Returns the similarity score between pairs of points (the larger the score, +the more similar the pair). For metric learners that learn a distance, +the score is simply the opposite of the distance between pairs. All +learners have access to this method.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The score of every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+Predicts the learned metric between input pairs. (For now it just +calls decision function).
+Returns the learned metric value between samples in every pair. It should +ideally be low for similar samples and high for dissimilar samples.
+3D Array of pairs to predict, with each row corresponding to two +points, or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The predicted learned metric value between samples in every pair.
+Computes score of pairs similarity prediction.
+Returns the roc_auc
score of the fitted metric learner. It is
+computed in the following way: for every value of a threshold
+t
we classify all pairs of samples where the predicted distance is
+inferior to t
as belonging to the “similar” class, and the other as
+belonging to the “dissimilar” class, and we count false positive and
+true positives as in a classical roc_auc
curve.
3D Array of pairs, with each row corresponding to two points, +or 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The corresponding labels.
+The roc_auc
score.
Returns the score between pairs +(can be a similarity, or a distance/metric depending on the algorithm)
+Deprecated since version 0.7.0: Refer to pair_distance and pair_score.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The score of every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference between score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+Request metadata passed to the decision_function
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to decision_function
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to decision_function
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in decision_function
.
The updated object.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Request metadata passed to the predict
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to predict
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to predict
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in predict
.
The updated object.
+Request metadata passed to the score
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to score
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to score
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for pairs
parameter in score
.
The updated object.
+Sets the threshold of the metric learner to the given value threshold.
+See more in the User Guide.
+The threshold value we want to set. It is the value to which the +predicted distance for test pairs will be compared. If they are superior +to the threshold they will be classified as similar (+1), +and dissimilar (-1) if not.
+The pairs classifier with the new threshold set.
+metric_learn.base_metric._PairsClassifierMixin
metric_learn.base_metric
._QuadrupletsClassifierMixinBase class for quadruplets learners.
+Methods
+
|
+Predicts differences between sample distances in input quadruplets. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+
+
+New in version 0.7.0: Compute the distance between pairs + |
+
|
+
+
+New in version 0.7.0: Compute the similarity score between pairs + |
+
|
+Predicts the ordering between sample distances in input quadruplets. |
+
|
+Computes score on input quadruplets |
+
|
+Returns the score between pairs (can be a similarity, or a distance/metric depending on the algorithm) |
+
|
+Request metadata passed to the |
+
|
+Set the parameters of this estimator. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
Predicts differences between sample distances in input quadruplets.
+For each quadruplet in the samples, computes the difference between the +learned metric of the second pair minus the learned metric of the first +pair. The higher it is, the more probable it is that the pairs in the +quadruplet are presented in the right order, i.e. that the label of the +quadruplet is 1. The lower it is, the more probable it is that the label of +the quadruplet is -1.
+3D Array of quadruplets to predict, with each row corresponding to four +points, or 2D array of indices of quadruplets if the metric learner +uses a preprocessor.
+Metric differences.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+New in version 0.7.0: Compute the distance between pairs
+Returns the (pseudo) distance between pairs, when available. For metric +learners that do not learn a (pseudo) distance, an error is thrown +instead.
+3D Array of pairs for which to compute the distance, with each +row corresponding to two points, for 2D array of indices of pairs +if the metric learner uses a preprocessor.
+The distance between every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+New in version 0.7.0: Compute the similarity score between pairs
+Returns the similarity score between pairs of points (the larger the score, +the more similar the pair). For metric learners that learn a distance, +the score is simply the opposite of the distance between pairs. All +learners have access to this method.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The score of every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+Predicts the ordering between sample distances in input quadruplets.
+For each quadruplet, returns 1 if the quadruplet is in the right order ( +first pair is more similar than second pair), and -1 if not.
+3D Array of quadruplets to predict, with each row corresponding to four +points, or 2D array of indices of quadruplets if the metric learner +uses a preprocessor.
+Predictions of the ordering of pairs, for each quadruplet.
+Computes score on input quadruplets
+Returns the accuracy score of the following classification task: a record +is correctly classified if the predicted similarity between the first two +samples is higher than that of the last two.
+3D Array of quadruplets to score, with each row corresponding to four +points, or 2D array of indices of quadruplets if the metric learner +uses a preprocessor.
+The quadruplets score.
+Returns the score between pairs +(can be a similarity, or a distance/metric depending on the algorithm)
+Deprecated since version 0.7.0: Refer to pair_distance and pair_score.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The score of every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference between score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+Request metadata passed to the decision_function
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to decision_function
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to decision_function
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for quadruplets
parameter in decision_function
.
The updated object.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Request metadata passed to the predict
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to predict
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to predict
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for quadruplets
parameter in predict
.
The updated object.
+Request metadata passed to the score
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to score
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to score
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for quadruplets
parameter in score
.
The updated object.
+metric_learn.base_metric
._TripletsClassifierMixinBase class for triplets learners.
+Methods
+
|
+Predicts differences between sample distances in input triplets. |
+
+ | Get metadata routing of this object. |
+
+ | Returns a function that takes as input two 1D arrays and outputs the value of the learned metric on these two points. |
+
|
+Get parameters for this estimator. |
+
|
+
+
+New in version 0.7.0: Compute the distance between pairs + |
+
|
+
+
+New in version 0.7.0: Compute the similarity score between pairs + |
+
|
+Predicts the ordering between sample distances in input triplets. |
+
|
+Computes score on input triplets. |
+
|
+Returns the score between pairs (can be a similarity, or a distance/metric depending on the algorithm) |
+
|
+Request metadata passed to the |
+
|
+Set the parameters of this estimator. |
+
|
+Request metadata passed to the |
+
|
+Request metadata passed to the |
+
Predicts differences between sample distances in input triplets.
+For each triplet (X_a, X_b, X_c) in the samples, computes the difference +between the learned distance of the second pair (X_a, X_c) minus the +learned distance of the first pair (X_a, X_b). The higher it is, the more +probable it is that the pairs in the triplets are presented in the right +order, i.e. that the label of the triplet is 1. The lower it is, the more +probable it is that the label of the triplet is -1.
+3D array of triplets to predict, with each row corresponding to three +points, or 2D array of indices of triplets if the metric learner +uses a preprocessor.
+Metric differences.
+Get metadata routing of this object.
+Please check User Guide on how the routing +mechanism works.
+A MetadataRequest
encapsulating
+routing information.
Returns a function that takes as input two 1D arrays and outputs +the value of the learned metric on these two points. Depending on the +algorithm, it can return a distance or a similarity function between +pairs.
+This function will be independent from the metric learner that learned it +(it will not be modified if the initial metric learner is modified), +and it can be directly plugged into the metric argument of +scikit-learn’s estimators.
+The function described above.
+See also
+pair_distance
a method that returns the distance between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+pair_score
a method that returns the similarity score between several pairs of points. Unlike get_metric, this is a method of the metric learner and therefore can change if the metric learner changes. Besides, it can use the metric learner’s preprocessor, and works on concatenated arrays.
+Examples
+>>> from metric_learn import NCA
+>>> from sklearn.datasets import make_classification
+>>> from sklearn.neighbors import KNeighborsClassifier
+>>> nca = NCA()
+>>> X, y = make_classification()
+>>> nca.fit(X, y)
+>>> knn = KNeighborsClassifier(metric=nca.get_metric())
+>>> knn.fit(X, y)
+KNeighborsClassifier(algorithm='auto', leaf_size=30,
+ metric=<function MahalanobisMixin.get_metric.<locals>.metric_fun
+ at 0x...>,
+ metric_params=None, n_jobs=None, n_neighbors=5, p=2,
+ weights='uniform')
+
Get parameters for this estimator.
+If True, will return the parameters for this estimator and +contained subobjects that are estimators.
+Parameter names mapped to their values.
+New in version 0.7.0: Compute the distance between pairs
+Returns the (pseudo) distance between pairs, when available. For metric +learners that do not learn a (pseudo) distance, an error is thrown +instead.
+3D Array of pairs for which to compute the distance, with each +row corresponding to two points, for 2D array of indices of pairs +if the metric learner uses a preprocessor.
+The distance between every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_distance is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+New in version 0.7.0: Compute the similarity score between pairs
+Returns the similarity score between pairs of points (the larger the score, +the more similar the pair). For metric learners that learn a distance, +the score is simply the opposite of the distance between pairs. All +learners have access to this method.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The score of every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference with pair_score is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+Predicts the ordering between sample distances in input triplets.
+For each triplets, returns 1 if the first element is closer to the second +than to the last and -1 if not.
+3D array of triplets to predict, with each row corresponding to three +points, or 2D array of indices of triplets if the metric learner +uses a preprocessor.
+Predictions of the ordering of pairs, for each triplet.
+Computes score on input triplets.
+Returns the accuracy score of the following classification task: a triplet +(X_a, X_b, X_c) is correctly classified if the predicted similarity between +the first pair (X_a, X_b) is higher than that of the second pair (X_a, X_c)
+3D array of triplets to score, with each row corresponding to three +points, or 2D array of indices of triplets if the metric learner +uses a preprocessor.
+The triplets score.
+Returns the score between pairs +(can be a similarity, or a distance/metric depending on the algorithm)
+Deprecated since version 0.7.0: Refer to pair_distance and pair_score.
+Warning
+This method will be removed in 0.8.0. Please refer to pair_distance +or pair_score. This change will occur in order to add learners +that don’t necessarily learn a Mahalanobis distance.
+3D Array of pairs to score, with each row corresponding to two points, +for 2D array of indices of pairs if the metric learner uses a +preprocessor.
+The score of every pair.
+See also
+get_metric
a method that returns a function to compute the metric between two points. The difference between score_pairs is that it works on two 1D arrays and cannot use a preprocessor. Besides, the returned function is independent of the metric learner and hence is not modified if the metric learner is.
+Request metadata passed to the decision_function
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to decision_function
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to decision_function
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for triplets
parameter in decision_function
.
The updated object.
+Set the parameters of this estimator.
+The method works on simple estimators as well as on nested objects
+(such as Pipeline
). The latter have
+parameters of the form <component>__<parameter>
so that it’s
+possible to update each component of a nested object.
Estimator parameters.
+Estimator instance.
+Request metadata passed to the predict
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to predict
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to predict
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for triplets
parameter in predict
.
The updated object.
+Request metadata passed to the score
method.
Note that this method is only relevant if
+enable_metadata_routing=True
(see sklearn.set_config()
).
+Please see User Guide on how the routing
+mechanism works.
The options for each parameter are:
+True
: metadata is requested, and passed to score
if provided. The request is ignored if metadata is not provided.
False
: metadata is not requested and the meta-estimator will not pass it to score
.
None
: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
str
: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (sklearn.utils.metadata_routing.UNCHANGED
) retains the
+existing request. This allows you to change the request for some
+parameters and not others.
New in version 1.3.
+Note
+This method is only relevant if this estimator is used as a
+sub-estimator of a meta-estimator, e.g. used inside a
+Pipeline
. Otherwise it has no effect.
Metadata routing for triplets
parameter in score
.
The updated object.
++ |
+ |
+ | + |
+ | + |
+ | + |
+ |
+ | + |
Installation
+metric-learn can be installed in either of the following ways:
+If you use Anaconda: conda install -c conda-forge metric-learn
. See more options here.
To install from PyPI: pip install metric-learn
.
For a manual install of the latest code, download the source repository and run python setup.py install
. You may then run pytest test
to run all tests (you will need to have the pytest
package installed).
Dependencies
+Python 3.6+ (the last version supporting Python 2 and Python 3.5 was +v0.5.0)
numpy>= 1.11.0, scipy>= 0.17.0, scikit-learn>=0.21.3
Optional dependencies
+For SDML, using skggm will allow the algorithm to solve problematic cases
+(install from commit a0ed406).
+pip install 'git+https://github.com/skggm/skggm.git@a0ed406586c4364ea3297a658f415e13b5cbdaf8'
to install the required version of skggm from GitHub.
For running the examples only: matplotlib
This example loads the iris dataset, and evaluates a k-nearest neighbors +algorithm on an embedding space learned with NCA.
+from metric_learn import NCA
+from sklearn.datasets import load_iris
+from sklearn.model_selection import cross_val_score
+from sklearn.pipeline import make_pipeline
+from sklearn.neighbors import KNeighborsClassifier
+
+X, y = load_iris(return_X_y=True)
+clf = make_pipeline(NCA(), KNeighborsClassifier())
+cross_val_score(clf, X, y)
+
metric-learn +contains efficient Python implementations of several popular supervised and +weakly-supervised metric learning algorithms. As part of scikit-learn-contrib, the API of metric-learn is compatible with scikit-learn, the leading library for machine learning in +Python. This allows to use all the scikit-learn routines (for pipelining, +model selection, etc) with metric learning algorithms through a unified +interface.
+If you use metric-learn in a scientific publication, we would appreciate +citations to the following paper:
+metric-learn: Metric Learning Algorithms in Python, de Vazelhes +et al., Journal of Machine Learning Research, 21(138):1-6, 2020.
+Bibtex entry:
+@article{metric-learn,
+ title = {metric-learn: {M}etric {L}earning {A}lgorithms in {P}ython},
+ author = {{de Vazelhes}, William and {Carey}, CJ and {Tang}, Yuan and
+ {Vauquier}, Nathalie and {Bellet}, Aur{\'e}lien},
+ journal = {Journal of Machine Learning Research},
+ year = {2020},
+ volume = {21},
+ number = {138},
+ pages = {1--6}
+}
+
Many approaches in machine learning require a measure of distance between data +points. Traditionally, practitioners would choose a standard distance metric +(Euclidean, City-Block, Cosine, etc.) using a priori knowledge of the +domain. However, it is often difficult to design metrics that are well-suited +to the particular data and task of interest.
+Distance metric learning (or simply, metric learning) aims at +automatically constructing task-specific distance metrics from (weakly) +supervised data, in a machine learning manner. The learned distance metric can +then be used to perform various tasks (e.g., k-NN classification, clustering, +information retrieval).
+Metric learning problems fall into two main categories depending on the type +of supervision available about the training data:
+Supervised learning: the algorithm has access to +a set of data points, each of them belonging to a class (label) as in a +standard classification problem. +Broadly speaking, the goal in this setting is to learn a distance metric +that puts points with the same label close together while pushing away +points with different labels.
Weakly supervised learning: the +algorithm has access to a set of data points with supervision only +at the tuple level (typically pairs, triplets, or quadruplets of +data points). A classic example of such weaker supervision is a set of +positive and negative pairs: in this case, the goal is to learn a distance +metric that puts positive pairs close together and negative pairs far away.
Based on the above (weakly) supervised data, the metric learning problem is +generally formulated as an optimization problem where one seeks to find the +parameters of a distance function that optimize some objective function +measuring the agreement with the training data.
+In the metric-learn package, all algorithms currently implemented learn
+so-called Mahalanobis distances. Given a real-valued parameter matrix
+\(L\) of shape (num_dims, n_features)
where n_features
is the
+number features describing the data, the Mahalanobis distance associated with
+\(L\) is defined as follows:
In other words, a Mahalanobis distance is a Euclidean distance after a
+linear transformation of the feature space defined by \(L\) (taking
+\(L\) to be the identity matrix recovers the standard Euclidean distance).
+Mahalanobis distance metric learning can thus be seen as learning a new
+embedding space of dimension num_dims
. Note that when num_dims
is
+smaller than n_features
, this achieves dimensionality reduction.
Strictly speaking, Mahalanobis distances are “pseudo-metrics”: they satisfy +three of the properties of a metric (non-negativity, symmetry, triangle inequality) but not +necessarily the identity of indiscernibles.
+Note
+Mahalanobis distances can also be parameterized by a positive semi-definite +(PSD) matrix +\(M\):
+Using the fact that a PSD matrix \(M\) can always be decomposed as +\(M=L^\top L\) for some \(L\), one can show that both +parameterizations are equivalent. In practice, an algorithm may thus solve +the metric learning problem with respect to either \(M\) or \(L\).
+There are many use-cases for metric learning. We list here a few popular +examples (for code illustrating some of these use-cases, see the +examples section of the documentation):
+Nearest neighbors models: the learned +metric can be used to improve nearest neighbors learning models for +classification, regression, anomaly detection…
Clustering: +metric learning provides a way to bias the clusters found by algorithms like +K-Means towards the intended semantics.
Information retrieval: the learned metric can be used to retrieve the +elements of a database that are semantically closest to a query element.
Dimensionality reduction: metric learning may be seen as a way to reduce the +data dimension in a (weakly) supervised setting.
More generally, the learned transformation \(L\) can be used to project +the data into a new embedding space before feeding it into another machine +learning algorithm.
The API of metric-learn is compatible with scikit-learn, the leading library for machine +learning in Python. This allows to easily pipeline metric learners with other +scikit-learn estimators to realize the above use-cases, to perform joint +hyperparameter tuning, etc.
+For more information about metric learning and its applications, one can refer +to the following resources:
+Tutorial: Similarity and Distance Metric Learning with Applications to +Computer Vision (2015)
Surveys: A Survey on Metric Learning for Feature Vectors and Structured +Data (2013), Metric Learning: A +Survey (2012)
Book: Metric Learning (2015)
|
+Class to build constraints from labeled data. |
+
+ | Base class for all metric-learners. |
+
+ | Base class for all learners that can transform data into a new space with the metric learned. |
+
+ | Mahalanobis metric learning algorithms. |
+
+ | Base class for pairs learners. |
+
+ | Base class for triplets learners. |
+
+ | Base class for quadruplets learners. |
+
|
+Local Fisher Discriminant Analysis for Supervised Dimensionality Reduction |
+
|
+Large Margin Nearest Neighbor (LMNN) |
+
|
+Metric Learning for Kernel Regression (MLKR) |
+
|
+Neighborhood Components Analysis (NCA) |
+
|
+Relevant Components Analysis (RCA) |
+
|
+Supervised version of Information Theoretic Metric Learning (ITML) |
+
|
+Supervised version of Least Squared-residual Metric Learning (LSML) |
+
|
+Supervised version of Mahalanobis Metric for Clustering (MMC) |
+
|
+Supervised version of Sparse Distance Metric Learning (SDML) |
+
|
+Supervised version of Relevant Components Analysis (RCA) |
+
|
+Supervised version of Sparse Compositional Metric Learning (SCML) |
+
|
+Information Theoretic Metric Learning (ITML) |
+
|
+Least Squared-residual Metric Learning (LSML) |
+
|
+Mahalanobis Metric for Clustering (MMC) |
+
|
+Sparse Distance Metric Learning (SDML) |
+
|
+Sparse Compositional Metric Learning (SCML) |
+
|
+Covariance metric (baseline method) |
+
Estimators in metric-learn all have a preprocessor
option at instantiation.
+Filling this argument allows them to take more compact input representation
+when fitting, predicting etc…
If preprocessor=None
, no preprocessor will be used and the user must
+provide the classical representation to the fit/predict/score/etc… methods of
+the estimators (see the documentation of the particular estimator to know the
+type of input it accepts). Otherwise, two types of objects can be put in this
+argument:
You can specify preprocessor=X
where X
is an array-like containing the
+dataset of points. In this case, the fit/predict/score/etc… methods of the
+estimator will be able to take as inputs an array-like of indices, replacing
+under the hood each index by the corresponding sample.
Example with a supervised metric learner:
+>>> from metric_learn import NCA
+>>>
+>>> X = np.array([[-0.7 , -0.23],
+>>> [-0.43, -0.49],
+>>> [ 0.14, -0.37]]) # array of 3 samples of 2 features
+>>> points_indices = np.array([2, 0, 1, 0])
+>>> y = np.array([1, 0, 1, 1])
+>>>
+>>> nca = NCA(preprocessor=X)
+>>> nca.fit(points_indices, y)
+>>> # under the hood the algorithm will create
+>>> # points = np.array([[ 0.14, -0.37],
+>>> # [-0.7 , -0.23],
+>>> # [-0.43, -0.49],
+>>> # [ 0.14, -0.37]]) and fit on it
+
Example with a weakly supervised metric learner:
+>>> from metric_learn import MMC
+>>> X = np.array([[-0.7 , -0.23],
+>>> [-0.43, -0.49],
+>>> [ 0.14, -0.37]]) # array of 3 samples of 2 features
+>>> pairs_indices = np.array([[2, 0], [1, 0]])
+>>> y_pairs = np.array([1, -1])
+>>>
+>>> mmc = MMC(preprocessor=X)
+>>> mmc.fit(pairs_indices, y_pairs)
+>>> # under the hood the algorithm will create
+>>> # pairs = np.array([[[ 0.14, -0.37], [-0.7 , -0.23]],
+>>> # [[-0.43, -0.49], [-0.7 , -0.23]]]) and fit on it
+
Alternatively, you can provide a callable as preprocessor
. Then the
+estimator will accept indicators of points instead of points. Under the hood,
+the estimator will call this callable on the indicators you provide as input
+when fitting, predicting etc… Using a callable can be really useful to
+represent lazily a dataset of images stored on the file system for instance.
+The callable should take as an input a 1D array-like, and return a 2D
+array-like. For supervised learners it will be applied on the whole 1D array of
+indicators at once, and for weakly supervised learners it will be applied on
+each column of the 2D array of tuples.
Example with a supervised metric learner:
+>>> def find_images(file_paths):
+>>> # each file contains a small image to use as an input datapoint
+>>> return np.row_stack([imread(f).ravel() for f in file_paths])
+>>>
+>>> nca = NCA(preprocessor=find_images)
+>>> nca.fit(['img01.png', 'img00.png', 'img02.png'], [1, 0, 1])
+>>> # under the hood preprocessor(indicators) will be called
+
Example with a weakly supervised metric learner:
+>>> pairs_images_paths = [['img02.png', 'img00.png'],
+>>> ['img01.png', 'img00.png']]
+>>> y_pairs = np.array([1, -1])
+>>>
+>>> mmc = NCA(preprocessor=find_images)
+>>> mmc.fit(pairs_images_paths, y_pairs)
+>>> # under the hood preprocessor(pairs_indicators[i]) will be called for each
+>>> # i in [0, 1]
+
Note
+Note that when you fill the preprocessor
option, it allows you
+to give more compact inputs, but the classical way of providing inputs
+stays valid (2D array-like for supervised learners and 3D array-like of
+tuples for weakly supervised learners). If a classical input
+is provided, the metric learner will not use the preprocessor.
Example: This will work:
+>>> from metric_learn import MMC
+>>> def preprocessor_wip(array):
+>>> raise NotImplementedError("This preprocessor does nothing yet.")
+>>>
+>>> pairs = np.array([[[ 0.14, -0.37], [-0.7 , -0.23]],
+>>> [[-0.43, -0.49], [-0.7 , -0.23]]])
+>>> y_pairs = np.array([1, -1])
+>>>
+>>> mmc = MMC(preprocessor=preprocessor_wip)
+>>> mmc.fit(pairs, y_pairs) # preprocessor_wip will not be called here
+
metric_learn
.Constraints", "metric_learn
.Covariance", "metric_learn
.ITML", "metric_learn
.ITML_Supervised", "metric_learn
.LFDA", "metric_learn
.LMNN", "metric_learn
.LSML", "metric_learn
.LSML_Supervised", "metric_learn
.MLKR", "metric_learn
.MMC", "metric_learn
.MMC_Supervised", "metric_learn
.NCA", "metric_learn
.RCA", "metric_learn
.RCA_Supervised", "metric_learn
.SCML", "metric_learn
.SCML_Supervised", "metric_learn
.SDML", "metric_learn
.SDML_Supervised", "metric_learn.base_metric
.BaseMetricLearner", "metric_learn.base_metric
.MahalanobisMixin", "metric_learn.base_metric
.MetricTransformer", "metric_learn.base_metric
._PairsClassifierMixin", "metric_learn.base_metric
._QuadrupletsClassifierMixin", "metric_learn.base_metric
._TripletsClassifierMixin", "Getting started", "metric-learn: Metric Learning in Python", "1. What is Metric Learning?", "metric_learn package", "5. Preprocessor", "2. Supervised Metric Learning", "4. Unsupervised Metric Learning", "User guide: contents", "3. Weakly Supervised Metric Learning"], "terms": {"below": [0, 1, 34, 36], "i": [0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29, 32, 33, 34, 35, 36], "galleri": [0, 1, 2], "metric": [0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 32, 35], "learn": [0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 32, 35], "us": [0, 1, 2, 4, 5, 18, 19, 26, 27, 28, 29, 32, 33, 34, 35, 36], "case": [0, 1, 4, 6, 7, 11, 13, 14, 18, 19, 20, 21, 25, 28, 32, 33, 35, 36], "sandwich": [0, 3, 7, 9, 11, 21, 22, 23, 24], "demo": [0, 3, 7, 9, 11, 21, 22, 23, 24], "algorithm": [0, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 35], "walkthrough": [0, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25], "download": [0, 1, 2, 28], "all": [0, 1, 4, 6, 7, 10, 13, 20, 22, 24, 25, 26, 27, 28, 29, 30, 32, 33, 36], "python": [0, 1, 2, 28, 30], "sourc": [0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28], "code": [0, 1, 2, 6, 10, 13, 20, 25, 28, 30, 33, 34, 36], "auto_examples_python": 0, "zip": 0, "jupyt": [0, 1, 2], "notebook": [0, 1, 2], "auto_examples_jupyt": 0, "gener": [0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 30, 34, 35], "sphinx": [0, 1, 2], "go": [1, 2, 36], "end": [1, 2, 6, 13, 20, 33, 36], "full": [1, 2, 16, 36], "thi": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 32, 33, 34, 36], "small": [1, 10, 32, 33, 36], "which": [1, 6, 12, 13, 15, 19, 20, 22, 25, 26, 27, 33, 34, 36], "illustr": [1, 30], "most": [1, 4, 6, 9, 12, 13, 15, 20, 25, 36], "implement": [1, 18, 19, 29, 30, 36], "them": [1, 30, 32, 33], "synthet": 1, "data": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 30, 34, 35], "some": [1, 4, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 30, 33, 36], "visual": [1, 12, 15, 33], "provid": [1, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 30, 32, 36], "intuit": [1, 36], "what": [1, 29, 35, 36], "thei": [1, 6, 13, 20, 25, 30, 33, 36], "ar": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "design": [1, 13, 30, 36], "achiev": [1, 6, 13, 20, 25, 30, 36], "licens": 1, "bsd": 1, "3": [1, 2, 4, 6, 7, 9, 10, 11, 13, 14, 16, 17, 18, 19, 20, 25, 26, 27, 28, 32, 33, 36], "claus": 1, "author": [1, 29, 36], "bhargav": 1, "srinivasa": 1, "desikan": 1, "bhargavvad": 1, "gmail": 1, "com": [1, 10, 20, 28, 36], "william": [1, 2, 29], "de": [1, 29], "vazelh": [1, 29], "wdevazelh": 1, "In": [1, 2, 4, 6, 7, 10, 11, 13, 14, 18, 19, 20, 21, 25, 30, 32, 33, 36], "order": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "show": [1, 2, 30], "chart": [1, 2], "you": [1, 2, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 28, 29, 32, 33, 36], "need": [1, 2, 6, 13, 17, 20, 25, 28, 33, 36], "graphic": [1, 2], "matplotlib": [1, 2, 28], "backend": [1, 2], "instal": [1, 2, 29], "For": [1, 2, 4, 6, 7, 10, 11, 13, 18, 20, 21, 22, 25, 26, 27, 28, 30, 32, 33, 34, 36], "intanc": [1, 2], "pip": [1, 2, 28], "pyqt5": [1, 2], "get": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29, 33, 36], "qt": [1, 2], "interfac": [1, 2, 29], "your": [1, 2, 33], "favorit": [1, 2], "one": [1, 2, 4, 8, 12, 13, 15, 18, 21, 30, 33, 36], "sklearn": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 33, 34, 36], "manifold": 1, "tsne": 1, "metric_learn": [1, 2, 28, 32, 33, 34, 36], "numpi": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 33, 36], "np": [1, 2, 8, 9, 15, 32, 33, 36], "make_classif": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "make_regress": 1, "visualis": 1, "pyplot": [1, 2], "plt": [1, 2], "random": [1, 2, 4, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 33, 36], "seed": [1, 4, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21], "42": [1, 33, 36], "we": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 29, 30, 33, 36], "function": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "scikit": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 35], "The": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 32, 33, 36], "contain": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29, 32, 33, 36], "100": [1, 4, 13, 14, 15, 17, 33, 36], "point": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 32, 33, 36], "class": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 30, 33, 36], "2": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 32, 33, 36], "per": [1, 2, 8, 17, 33], "5": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 33, 36], "featur": [1, 6, 10, 13, 19, 30, 32, 36], "among": [1, 6, 7, 33, 36], "correl": 1, "label": [1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 25, 26, 27, 30, 33, 36], "two": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 32, 33, 36], "nois": 1, "magnitud": 1, "x": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 32, 33, 34, 36], "y": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 32, 33, 36], "n_sampl": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 33, 36], "n_class": [1, 9, 15], "n_clusters_per_class": 1, "n_inform": 1, "class_sep": 1, "4": [1, 6, 10, 13, 16, 18, 26, 33, 36], "n_featur": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "n_redund": 1, "0": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 32, 33, 36], "shuffl": 1, "true": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 33, 36], "scale": [1, 8, 10, 13, 14, 19, 33], "1": [1, 2, 4, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, 27, 28, 29, 32, 33, 34, 36], "20": [1, 7, 11, 14, 21, 36], "note": [1, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 30, 32, 36], "dimension": [1, 8, 9, 12, 15, 16, 17, 20, 30, 33, 36], "so": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 35], "2d": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 35], "t": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "sne": 1, "see": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 26, 27, 28, 30, 32, 33, 34, 36], "def": [1, 2, 32], "plot_tsn": 1, "colormap": 1, "cm": 1, "pair": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 32, 33, 35], "figur": 1, "figsiz": 1, "8": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "6": [1, 2, 6, 9, 10, 13, 18, 28, 29, 33, 36], "clean": 1, "clf": [1, 28], "x_embed": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], "fit_transform": [1, 5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "scatter": [1, 2, 33], "c": [1, 4, 5, 6, 7, 28, 33, 34, 36], "cmap": 1, "xtick": 1, "ytick": 1, "let": [1, 36], "": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "now": [1, 6, 13, 20, 25, 33, 34, 36], "can": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 32, 33, 34, 36], "appear": 1, "mix": 1, "becaus": [1, 33, 36], "base": [1, 2, 10, 16, 18, 19, 22, 24, 25, 26, 27, 29, 30, 33, 36], "preserv": [1, 33], "origin": [1, 6, 7, 10, 13, 16, 17, 18, 19, 20, 21, 25, 26, 27, 33, 36], "embed": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 28, 30, 33, 36], "space": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 28, 30, 33, 36], "euclidean": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 30, 33], "distanc": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 34, 35, 36], "input": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, 34, 35], "contribut": 1, "noisi": 1, "high": [1, 6, 10, 12, 13, 20, 25, 33, 36], "even": 1, "same": [1, 4, 7, 9, 11, 14, 16, 19, 21, 30, 33, 36], "close": [1, 6, 9, 10, 13, 30, 33, 36], "each": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 32, 33, 36], "other": [1, 4, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 30, 33, 36], "subspac": 1, "when": [1, 6, 8, 9, 10, 12, 13, 15, 16, 20, 22, 25, 26, 27, 30, 32, 33, 36], "consid": [1, 9, 36], "dimens": [1, 8, 9, 10, 12, 13, 14, 15, 16, 17, 30, 36], "why": 1, "prior": [1, 6, 7, 10, 11, 20, 21, 36], "knowledg": [1, 30, 36], "suppos": 1, "closer": [1, 6, 10, 13, 18, 27, 36], "out": [1, 12, 15, 33], "better": 1, "wai": [1, 6, 10, 11, 13, 20, 25, 28, 30, 32, 33, 36], "comput": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 36], "between": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "task": [1, 6, 10, 13, 18, 26, 27, 30, 36], "hand": 1, "especi": [1, 10, 36], "higher": [1, 9, 10, 12, 15, 18, 26, 27, 36], "poor": 1, "measur": [1, 30, 36], "becom": [1, 10, 33, 36], "veri": 1, "basic": [1, 35], "d": [1, 2, 4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 17, 18, 19, 21, 24, 30, 33, 36], "sqrt": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 30, 33], "top": [1, 2, 24, 30], "m": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 29, 30, 33, 36], "And": 1, "paramet": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 30, 36], "satisfi": [1, 30], "certain": 1, "constraint": [1, 2, 6, 7, 10, 11, 13, 14, 17, 18, 19, 20, 21, 33, 36], "requir": [1, 18, 28, 30, 36], "togeth": [1, 30, 36], "differ": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "far": [1, 30, 33], "awai": [1, 30, 33, 36], "more": [1, 4, 5, 6, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 20, 22, 25, 26, 27, 28, 30, 32, 33, 36], "check": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "section": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 30, 33, 36], "document": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 30, 32, 36], "good": 1, "read": [1, 5, 6, 8, 9, 10, 12, 13, 15, 16, 18, 19, 20, 35], "materi": 1, "also": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 30, 33, 36], "found": [1, 6, 13, 20, 25, 30], "here": [1, 28, 30, 32, 33, 36], "It": [1, 2, 6, 7, 8, 13, 14, 15, 16, 17, 20, 21, 25, 33, 34, 36], "serv": 1, "literatur": 1, "review": 1, "briefli": 1, "explain": [1, 33, 36], "befor": [1, 30, 33, 36], "its": [1, 4, 10, 30, 33, 36], "usag": 1, "discuss": 1, "how": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "perform": [1, 18, 19, 30, 36], "than": [1, 6, 9, 10, 11, 12, 13, 15, 18, 20, 25, 26, 27, 30, 33, 36], "easili": [1, 30], "integr": [1, 33], "machin": [1, 29, 30], "pipelin": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 33], "follow": [1, 6, 10, 13, 18, 20, 25, 26, 27, 28, 29, 30, 33, 36], "convent": [1, 6, 13, 20, 25], "lmnn": [1, 2, 35], "primarili": 1, "k": [1, 2, 8, 9, 12, 15, 18, 19, 28, 30, 33, 36], "neighbor": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 30, 33], "classif": [1, 6, 9, 10, 13, 15, 18, 20, 25, 26, 27, 30, 33, 36], "semidefinit": [1, 36], "program": [1, 6, 36], "sub": [1, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "convex": [1, 10, 13, 36], "main": [1, 13, 30, 33, 36], "behind": 1, "pseudometr": 1, "under": [1, 32, 33], "instanc": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 36], "train": [1, 6, 7, 14, 15, 18, 21, 30, 33, 36], "surround": 1, "share": [1, 33], "If": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 32, 33, 36], "leav": [1, 12, 15, 33], "error": [1, 6, 7, 10, 12, 13, 16, 17, 18, 20, 22, 25, 26, 27, 33], "special": 1, "cross": [1, 36], "valid": [1, 6, 13, 20, 25, 32, 33, 36], "minim": [1, 6, 10, 12, 13, 20, 25, 33, 36], "ll": 1, "notic": 1, "necessari": 1, "particular": [1, 30, 32, 33, 36], "implicitli": 1, "enforc": [1, 13, 36], "user": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29, 32, 36], "guid": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29], "n_neighbor": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33], "learn_rat": [1, 9, 33], "1e": [1, 6, 7, 9, 10, 11, 13, 14, 18, 19, 33, 36], "x_lmnn": 1, "have": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 32, 33, 36], "matrix": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 30, 33, 34, 36], "talk": [1, 36], "about": [1, 9, 30, 33, 36], "u": [1, 36], "tell": 1, "look": [1, 33], "like": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 35, 36], "after": [1, 30, 36], "being": [1, 33, 36], "new": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 30, 33, 36], "pretti": 1, "neat": 1, "huh": 1, "rest": [1, 9, 15], "while": [1, 6, 7, 9, 10, 11, 13, 14, 18, 19, 20, 21, 30, 33, 36], "first": [1, 5, 6, 9, 10, 11, 12, 13, 15, 17, 18, 26, 27, 33, 36], "run": [1, 2, 6, 7, 9, 10, 11, 12, 13, 14, 15, 19, 28], "itml": [1, 7, 35], "regular": [1, 9, 18, 19, 20, 36], "automat": [1, 30, 36], "semi": [1, 6, 23, 30, 36], "definit": [1, 6, 7, 10, 11, 20, 21, 23, 30, 36], "posit": [1, 2, 4, 6, 7, 10, 11, 13, 18, 20, 21, 23, 25, 30, 33, 36], "condit": 1, "logdet": [1, 6, 36], "diverg": [1, 6, 20, 36], "soft": 1, "must": [1, 6, 9, 11, 12, 13, 15, 20, 25, 32], "link": 1, "cannot": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33], "simpl": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 34, 36], "bregman": [1, 6, 36], "project": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 30, 33], "unlik": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "belong": [1, 4, 6, 13, 16, 20, 25, 30, 33, 36], "itml_supervis": [1, 2], "x_itml": 1, "mmc": [1, 14, 32, 33, 35], "an": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 25, 26, 27, 28, 30, 32, 33, 34, 36], "try": [1, 33], "similar": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "ensur": 1, "sum": [1, 10, 13, 16, 33, 36], "dissimilar": [1, 6, 7, 13, 14, 20, 21, 25, 33, 36], "threshold": [1, 6, 13, 14, 20, 25, 35], "done": [1, 6, 13, 15, 20], "optim": [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 30, 33, 36], "cost": 1, "subject": [1, 6, 36], "inequ": [1, 30], "mmc_supervis": [1, 33], "x_mmc": 1, "effici": [1, 13, 18, 20, 29, 36], "via": [1, 19, 20, 36], "l_1": 1, "penal": [1, 20, 36], "log": [1, 20, 36], "compar": [1, 6, 13, 15, 20, 25, 33, 36], "exist": [1, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "exploit": 1, "sparsiti": [1, 10, 20, 21, 36], "natur": [1, 10, 36], "underli": [1, 33], "intrins": 1, "sdml": [1, 21, 28, 35], "sdml_supervis": [1, 2, 20], "sparsity_param": [1, 20, 21], "balance_param": [1, 2, 20, 21], "0015": 1, "covari": [1, 2, 6, 7, 10, 11, 13, 14, 16, 20, 21, 35, 36], "x_sdml": 1, "vezelh": [1, 2], "miniconda3": [1, 2], "env": [1, 2], "docenvbi": [1, 2], "lib": [1, 2], "python3": [1, 2], "11": [1, 2, 28, 36], "site": [1, 2], "packag": [1, 2, 28, 29, 30], "_graph_lasso": [1, 2], "py": [1, 2, 3, 28], "329": [1, 2], "futurewarn": [1, 2], "cov_init": [1, 2], "deprec": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "remov": [1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "doe": [1, 2, 4, 5, 6, 32, 34, 36], "ani": [1, 2, 4, 7, 11, 14, 16, 21, 33, 36], "effect": [1, 2, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 33, 36], "warn": [1, 2, 4], "lsml": [1, 11, 35], "yet": [1, 10, 32, 36], "given": [1, 6, 7, 10, 11, 13, 14, 16, 17, 18, 20, 25, 26, 27, 30, 36], "comparison": [1, 10, 36], "formul": [1, 6, 18, 30, 36], "loss": [1, 33, 36], "correspond": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 36], "hing": [1, 33, 36], "violat": 1, "lsml_supervis": [1, 2], "tol": [1, 6, 7, 9, 10, 11, 12, 13, 14, 15, 33, 36], "0001": 1, "max_it": [1, 6, 7, 9, 10, 11, 12, 13, 14, 15, 18, 19, 33, 36], "10000": [1, 13, 14, 18, 19, 36], "x_lsml": 1, "nca": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 32, 35], "extremli": 1, "popular": [1, 29, 30], "aim": [1, 15, 30, 33, 36], "find": [1, 30, 33, 36], "linear": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 30, 33, 36], "averag": [1, 33], "loo": 1, "rule": [1, 33], "maxim": [1, 6, 13, 15, 20, 25, 33], "kei": 1, "insight": 1, "A": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29, 30, 33, 36], "defin": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 30, 33, 36], "differenti": [1, 6, 36], "object": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 32, 33, 36], "iter": [1, 6, 7, 9, 10, 11, 12, 13, 14, 15, 18, 19], "solver": [1, 6, 7, 9, 10, 11, 12, 13, 14, 15], "scipi": [1, 28, 33, 36], "fmin_l_bfgs_b": 1, "uniqu": [1, 2], "1000": [1, 6, 7, 9, 10, 11, 12, 15, 33, 36], "x_nca": 1, "lfda": [1, 35], "reduct": [1, 8, 12, 30, 33], "method": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, 33, 34, 36], "particularli": [1, 8, 33], "deal": [1, 8, 33], "multimod": [1, 8, 33], "where": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 30, 32, 33, 36], "ore": [1, 8, 33], "consist": [1, 6, 8, 13, 20, 25, 33, 36], "separ": [1, 8, 9, 33], "core": [1, 8, 33], "problem": [1, 6, 8, 13, 18, 33, 35, 36], "solv": [1, 8, 13, 18, 28, 30, 33, 36], "eigenvalu": [1, 6, 8, 13, 33, 36], "n_compon": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 33], "x_lfda": 1, "rca": [1, 17, 35], "anoth": [1, 30], "older": 1, "rank": [1, 16, 18, 36], "weight": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "matric": [1, 16, 23, 36], "appli": [1, 16, 24, 32, 33, 36], "global": [1, 16, 36], "assign": [1, 16, 18, 36], "relev": [1, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 36], "low": [1, 6, 13, 15, 16, 20, 25, 33, 36], "irrelev": [1, 16, 36], "those": [1, 9, 12, 15, 16, 33, 36], "estim": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 32, 33, 36], "chunklet": [1, 16, 36], "subset": [1, 16, 36], "known": [1, 16, 36], "rca_supervis": 1, "n_chunk": [1, 4, 17], "30": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "chunk_siz": [1, 4, 17], "x_rca": 1, "previou": 1, "took": 1, "real": [1, 30], "number": [1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 29, 30, 33, 36], "mlkr": [1, 35], "To": [1, 28, 33, 36], "did": [1, 36], "e": [1, 6, 7, 10, 13, 14, 16, 17, 18, 20, 25, 26, 27, 29, 30, 36], "target": [1, 5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 20, 21, 33, 36], "model": [1, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 29, 30, 33, 36], "x_reg": 1, "y_reg": 1, "orang": 1, "x_mlkr": 1, "valu": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "would": [1, 29, 30, 36], "improv": [1, 15, 30, 33], "kneighborsregressor": 1, "alwai": [1, 30], "howev": [1, 13, 30, 36], "mani": [1, 30, 33, 36], "applic": [1, 13, 30, 36], "easier": 1, "obtain": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 36], "whether": [1, 9, 12, 15, 33, 36], "sampl": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 26, 27, 32, 33, 36], "annot": 1, "face": 1, "imag": [1, 32], "person": 1, "rather": [1, 5, 34, 36], "id": 1, "huge": 1, "databas": [1, 30, 36], "everi": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "g": [1, 6, 7, 10, 12, 13, 15, 16, 17, 18, 20, 25, 26, 27, 30, 36], "retriev": [1, 30], "goal": [1, 30, 33, 36], "queri": [1, 30], "notion": 1, "individu": 1, "gather": 1, "fortun": 1, "strength": 1, "abil": 1, "inde": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 33, 36], "ve": 1, "abov": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "altern": [1, 32, 33, 36], "pass": [1, 6, 7, 9, 10, 12, 13, 14, 15, 16, 17, 18, 20, 21, 25, 26, 27, 33], "want": [1, 6, 10, 13, 20, 25, 36], "arrai": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 35], "well": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 36], "pairs_label": 1, "n_pair": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "word": [1, 30], "further": [1, 10, 35, 36], "kind": 1, "possibl": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "weakli": [1, 7, 10, 13, 18, 19, 21, 29, 30, 32, 35], "detail": [1, 33, 36], "weak": 1, "work": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 36], "purpos": [1, 33, 36], "re": 1, "explicitli": 1, "creat": [1, 7, 11, 14, 17, 19, 21, 32], "pairwis": [1, 6, 7, 10, 13, 20, 25, 33, 36], "through": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 29, 36], "do": [1, 22, 25, 26, 27, 33, 36], "keep": [1, 9, 33, 36], "mind": 1, "know": [1, 32, 36], "actual": 1, "depend": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 30, 33, 36], "hood": [1, 32], "modul": [1, 6, 13, 20, 25, 29], "own": 1, "version": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 35], "ahead": 1, "assum": [1, 18, 36], "create_constraint": 1, "itertool": 1, "aggreg": 1, "indic": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 35], "zero": [1, 2, 9, 15], "ones": [1, 13, 36], "make": [1, 6, 9, 10, 13, 20, 25, 33, 36], "permut": 1, "zeros_": 1, "list": [1, 30], "combin": [1, 4, 33, 36], "ones_": 1, "twos_": 1, "put": [1, 30, 32, 36], "sim": 1, "similarili": 1, "di": 1, "append": 1, "pick": [1, 6, 13, 20, 25], "just": [1, 6, 9, 12, 13, 15, 20, 25, 36], "enough": [1, 4, 33], "len": 1, "return": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, 33, 36], "shape": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "vstack": 1, "column_stack": 1, "concaten": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33], "print": [1, 6, 7, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21], "9": [1, 2, 6, 10, 13, 18, 33, 36], "10": [1, 18, 19, 33, 36], "77": 1, "65": 1, "72": 1, "55": [1, 16, 36], "71": 1, "again": 1, "longer": 1, "call": [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 25, 30, 32, 33, 36], "take": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 32, 33, 34, 36], "preprocessor": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29, 33, 35], "argument": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 36], "advanc": [1, 36], "result": [1, 36], "manual": [1, 28, 36], "construct": [1, 4, 18, 19, 30, 36], "bit": [1, 18, 19], "old": 1, "too": 1, "specif": [1, 30, 36], "worth": 1, "poke": 1, "around": [1, 33], "file": [1, 3, 32], "exactli": 1, "final": 1, "advantag": 1, "box": 1, "compat": [1, 29, 30, 35], "select": [1, 6, 13, 18, 19, 20, 25, 29, 33, 36], "score": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 35], "transformermixin": [1, 33], "plug": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "procedur": [1, 6, 7, 9, 10, 11, 13, 14], "sinc": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "format": [1, 5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21, 36], "describ": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33], "allow": [1, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 28, 29, 30, 32, 36], "slice": 1, "along": 1, "could": 1, "bring": 1, "tutori": [1, 30], "fun": 1, "total": [1, 2, 3, 33], "time": [1, 2, 6, 7, 17, 33, 36], "script": [1, 2], "minut": [1, 2], "32": [1, 3], "400": [1, 3], "second": [1, 2, 6, 10, 13, 18, 26, 27, 36], "plot_metric_learning_exampl": [1, 3], "ipynb": [1, 2], "exampl": [2, 5, 18, 19, 26, 27, 28, 29, 30, 32, 33, 34, 36], "from": [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 30, 32, 33, 34, 36], "http": [2, 10, 20, 28, 33, 36], "nbviewer": 2, "ipython": 2, "org": [2, 33], "6576096": 2, "import": [2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 32, 33, 34, 36], "pairwise_dist": 2, "nearestneighbor": 2, "sandwich_demo": 2, "sandwich_data": 2, "knn": [2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33], "nearest_neighbor": 2, "ax": 2, "subplot": 2, "whole": [2, 32], "row": [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "plot_sandwich_data": 2, "plot_neighborhood_graph": 2, "set_titl": 2, "set_aspect": 2, "equal": [2, 4, 6, 9, 12, 13, 15, 18, 20, 25, 33, 36], "set_xtick": 2, "set_ytick": 2, "ml": 2, "n_constraint": [2, 4, 6, 7, 10, 11, 13, 14, 17, 18, 20, 21, 25, 26, 27, 33], "200": [2, 7, 11, 14, 20, 33], "001": [2, 6, 7, 9, 10, 11, 13, 36], "ax_num": 2, "enumer": 2, "start": [2, 29], "fit": [2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 34, 35], "tx": 2, "transform": [2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 30, 34, 35], "ml_knn": 2, "axi": 2, "__class__": 2, "__name__": 2, "todo": 2, "somewher": 2, "visualize_class_separ": 2, "_": [2, 33, 36], "ax1": 2, "ax2": 2, "ncol": 2, "label_ord": 2, "argsort": 2, "imshow": 2, "interpol": 2, "nearest": [2, 4, 8, 9, 15, 19, 28, 30, 33], "none": [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 36], "kneighbor": 2, "return_dist": 2, "fals": [2, 4, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 25, 26, 27, 33, 36], "distinct": 2, "num_class": [2, 7, 11, 14, 21], "num_point": 2, "layer": 2, "dist": 2, "7": [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 36], "dtype": 2, "float": [2, 6, 7, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 25, 26, 27], "int": [2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 33], "x_center": 2, "arang": 2, "y_center": 2, "yc": 2, "xc": 2, "normal": [2, 9, 12, 15, 36], "reshap": 2, "ravel": [2, 32], "color": 2, "rbgmky": 2, "idx": 2, "val": 2, "xi": 2, "50": [2, 9], "facecolor": 2, "edgecolor": 2, "nn": [2, 30], "b": [2, 4, 6, 7, 33, 36], "plot": [2, 6, 13, 20, 25], "__main__": 2, "224": 2, "userwarn": 2, "onli": [2, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 28, 30, 34, 36], "199": 2, "request": [2, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "314": [2, 3], "plot_sandwich": [2, 3], "00": 3, "35": 3, "715": 3, "execut": 3, "auto_exampl": 3, "mb": 3, "03": 3, "partial_label": 4, "build": [4, 11, 33], "ndarrai": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "unknown": [4, 33], "attribut": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 33], "__init__": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "chunk": [4, 16, 17, 36], "random_st": [4, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 33, 36], "num_chunk": [4, 17], "compos": 4, "drawn": 4, "size": [4, 36], "valueerror": 4, "rais": [4, 6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27, 32], "option": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 25, 26, 27, 28, 32, 36], "default": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "randomst": [4, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 36], "pseudo": [4, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30], "renam": [4, 6, 7, 9, 11, 13, 14, 17, 21], "Will": [4, 6, 7, 9, 11, 13, 14, 17, 21], "1d": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 36], "generate_knntriplet": 4, "k_genuin": [4, 19], "k_impostor": [4, 19], "triplet": [4, 18, 19, 27, 30, 35], "x_a": [4, 18, 27], "x_b": [4, 18, 27], "x_c": [4, 18, 27], "doesn": [4, 16, 18, 19], "yield": [4, 6, 13, 18, 19, 20, 25, 36], "maximum": [4, 6, 7, 9, 10, 11, 13, 14, 15], "genuin": 4, "impostor": 4, "n": [4, 5, 7, 8, 11, 12, 14, 15, 16, 17, 19, 21, 24, 33, 36], "singl": [4, 7, 11, 14, 16, 17, 19, 21], "taken": 4, "account": 4, "positive_negative_pair": [4, 33], "same_length": [4, 33], "num_constraint": [4, 7, 11, 14, 21], "neg": [4, 6, 13, 18, 20, 25, 30, 33], "form": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 35], "randomli": [4, 7, 11, 14, 17, 18, 21, 33], "draw": 4, "smaller": [4, 9, 12, 15, 30], "bool": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "forc": [4, 33], "ignor": [4, 6, 7, 10, 13, 14, 16, 17, 18, 20, 25, 26, 27], "larger": [4, 22, 25, 26, 27, 33, 36], "set": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 35, 36], "left": [4, 33, 36], "element": [4, 17, 18, 20, 27, 30, 36], "right": [4, 10, 18, 26, 27, 33, 36], "baselin": [5, 34], "anyth": [5, 34], "calcul": [5, 33, 34, 36], "introduc": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "On": [5, 34], "statist": [5, 6, 13, 20, 25, 34], "p": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29, 34, 36], "mahalanobi": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 34, 35, 36], "1936": [5, 34], "dataset": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 32, 33, 34, 36], "load_iri": [5, 7, 8, 9, 11, 12, 14, 15, 17, 19, 20, 28, 33, 34, 36], "iri": [5, 28, 34], "cov": [5, 34], "components_": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], "l": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 29, 30, 33, 36], "deduc": [5, 6, 7, 10, 11, 13, 14, 18, 19, 20, 21], "components_from_metr": [5, 6, 7, 10, 11, 13, 14, 20, 21], "unus": 5, "fit_param": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "n_output": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "unsupervis": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21, 29, 35], "dict": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "addit": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "x_new": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21, 33, 36], "n_features_new": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "get_mahalanobis_matrix": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 33, 36], "copi": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], "learner": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 30, 32, 33, 36], "get_metadata_rout": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "metadata": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "rout": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "pleas": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "mechan": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "metadatarequest": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "encapsul": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "inform": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 36], "get_metr": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "output": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33], "independ": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "modifi": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "initi": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "directli": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "metric_fun": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "pair_dist": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "sever": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 29, 33, 36], "therefor": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "chang": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "besid": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "pair_scor": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "kneighborsclassifi": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28], "auto": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "leaf_siz": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "mahalanobismixin": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 25, 26, 27], "local": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "0x": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "metric_param": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "n_job": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "uniform": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "get_param": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "deep": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "subobject": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "param": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "name": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "map": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "d_m": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], "x_e": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], "3d": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 35], "henc": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 36], "opposit": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "score_pair": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "instead": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 32, 33, 36], "refer": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30, 33, 34, 36], "occur": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "add": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "don": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "necessarili": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 30], "set_output": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "api": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21, 29, 30, 35], "panda": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "configur": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "datafram": [5, 7, 8, 9, 11, 12, 14, 15, 16, 17, 19, 21], "unchang": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 25, 26, 27], "self": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "set_param": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "nest": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "latter": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "compon": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 33, 36], "__": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "updat": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27], "emb": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], "insid": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 26, 27, 36], "dot": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], "gamma": [6, 7, 18, 19], "ident": [6, 7, 9, 10, 11, 12, 13, 14, 15, 20, 21, 30, 36], "verbos": [6, 7, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 33, 36], "convergence_threshold": [6, 7, 13, 14], "theoret": [6, 7, 33, 36], "rel": [6, 9, 10, 11, 36], "entropi": [6, 36], "aka": [6, 36], "kullback": [6, 36], "leibler": [6, 36], "multivari": [6, 36], "gaussian": [6, 33, 36], "associ": [6, 30, 36], "handl": [6, 36], "wide": [6, 36], "varieti": [6, 36], "incorpor": [6, 36], "reli": [6, 36], "slack": [6, 7], "variabl": [6, 7], "converg": [6, 9, 10, 11, 12, 13, 14, 15], "toler": [6, 7, 9, 10, 11, 12, 15], "string": [6, 7, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21], "should": [6, 7, 10, 11, 13, 16, 17, 18, 20, 21, 25, 26, 27, 32, 33, 36], "strictli": [6, 7, 9, 10, 11, 12, 15, 20, 21, 30], "pd": [6, 7, 10, 11, 20, 21], "invers": [6, 7, 10, 11, 13, 14, 20, 21, 36], "spd": [6, 7, 13, 14, 21], "make_spd_matrix": [6, 7, 10, 11, 13, 14, 20, 21], "callabl": [6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 35, 36], "tupl": [6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 20, 21, 22, 30, 32, 33, 35], "jason": [6, 36], "v": [6, 36], "davi": [6, 36], "et": [6, 10, 16, 20, 29, 33, 36], "al": [6, 10, 16, 20, 29, 33, 36], "icml": [6, 20, 36], "2007": [6, 8, 12, 33, 36], "matter": [6, 13, 36], "bounds_": [6, 7], "bound": [6, 7, 36], "asid": [6, 7, 36], "5th": [6, 7], "95th": [6, 7], "percentil": [6, 7], "present": [6, 10, 18, 26, 27], "n_iter_": [6, 7, 9, 10, 11, 12, 13, 14, 15], "ha": [6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 25, 26, 27, 30, 33, 36], "threshold_": [6, 13, 20, 25], "lower": [6, 10, 13, 18, 20, 25, 26, 27, 36], "classifi": [6, 10, 13, 18, 20, 25, 26, 27, 33], "otherwis": [6, 7, 9, 10, 12, 13, 15, 16, 17, 18, 20, 25, 26, 27, 32, 36], "calibrate_threshold": [6, 13, 20, 25, 36], "pairs_valid": [6, 13, 20, 25], "y_valid": [6, 13, 20, 25], "strategi": [6, 13, 20, 25], "accuraci": [6, 10, 13, 15, 18, 20, 25, 26, 27, 33, 36], "min_rat": [6, 13, 20, 25], "beta": [6, 13, 18, 19, 20, 25, 36], "decis": [6, 13, 20, 25], "calibr": [6, 13, 20, 25, 36], "binari": [6, 13, 20, 25, 36], "cutoff": [6, 13, 20, 25], "predict": [6, 10, 13, 18, 20, 25, 26, 27, 32, 33, 35], "tradit": [6, 13, 20, 25], "evalu": [6, 13, 20, 25, 28, 36], "rate": [6, 9, 13, 18, 19, 20, 25], "f": [6, 13, 18, 19, 20, 25, 32, 36], "chosen": [6, 9, 12, 13, 15, 20, 25], "str": [6, 7, 8, 10, 13, 16, 17, 18, 20, 25, 26, 27], "choos": [6, 13, 20, 25, 30], "f_beta": [6, 13, 20, 25], "max_tpr": [6, 13, 20, 25], "highest": [6, 13, 20, 25], "least": [6, 10, 11, 13, 20, 25], "max_tnr": [6, 13, 20, 25], "specifi": [6, 13, 17, 20, 25, 32, 36], "respect": [6, 13, 20, 25, 30, 33, 36], "n_pairs_valid": [6, 13, 20, 25], "receiv": [6, 13, 20, 25], "oper": [6, 13, 20, 25], "characterist": [6, 13, 20, 25], "roc": [6, 13, 20, 25], "fundament": [6, 13, 20, 25], "tool": [6, 13, 20, 25], "clinic": [6, 13, 20, 25], "medicin": [6, 13, 20, 25], "mh": [6, 13, 20, 25], "zweig": [6, 13, 20, 25], "campbel": [6, 13, 20, 25], "chemistri": [6, 13, 20, 25], "1993": [6, 13, 20, 25], "pr": [6, 13, 20, 25], "10117": [6, 13, 20, 25], "classes_": [6, 10, 13, 18, 20, 25, 26, 27], "decision_funct": [6, 10, 13, 18, 20, 25, 26, 27, 36], "ideal": [6, 13, 20, 25], "y_predict": [6, 13, 20, 25], "calibration_param": [6, 13, 20], "trainset": [6, 13, 20], "dictionari": [6, 13, 20], "give": [6, 13, 20, 32, 33, 36], "step": [6, 13, 14, 20], "roc_auc": [6, 13, 20, 25], "inferior": [6, 13, 20, 25], "count": [6, 13, 20, 25], "classic": [6, 13, 20, 25, 30, 32, 36], "curv": [6, 13, 20, 25], "set_decision_function_request": [6, 10, 13, 18, 20, 25, 26, 27], "enable_metadata_rout": [6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "set_config": [6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "meta": [6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "alia": [6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "util": [6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "metadata_rout": [6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "retain": [6, 7, 10, 13, 16, 17, 18, 20, 25, 26, 27], "set_fit_request": [6, 7, 10, 13, 16, 17, 18, 20], "set_predict_request": [6, 10, 13, 18, 20, 25, 26, 27], "set_score_request": [6, 10, 13, 18, 20, 25, 26, 27], "set_threshold": [6, 13, 20, 25, 36], "test": [6, 13, 20, 25, 28, 36], "superior": [6, 13, 20, 25], "_pairsclassifi": [6, 13, 20, 25], "supervis": [7, 8, 10, 11, 12, 13, 14, 17, 18, 19, 21, 29, 30, 32, 35], "iris_data": [7, 8, 9, 11, 12, 14, 15, 17, 19, 20, 33], "embedding_typ": 8, "fisher": [8, 33], "discrimin": [8, 9, 15, 19, 33], "analysi": [8, 15, 16, 17, 33, 36], "cluster": [8, 13, 14, 19, 30, 33, 36], "reduc": [8, 9, 12, 15, 16, 17, 30], "min": [8, 9, 12, 15], "type": [8, 30, 32, 33, 36], "eigenvector": [8, 33], "orthonorm": 8, "plain": [8, 33, 36], "raw": 8, "masashi": 8, "sugiyama": [8, 33], "jmlr": [8, 33, 36], "yuan": [8, 29], "tang": [8, 29, 33], "beer": [8, 33], "style": [8, 33], "dim": [8, 33], "init": [9, 10, 11, 12, 13, 14, 15, 21, 33, 36], "min_it": 9, "07": [9, 36], "convergence_tol": 9, "larg": [9, 16, 33, 36], "margin": [9, 33, 36], "attempt": [9, 33], "assumpt": [9, 13, 33, 36], "distribut": [9, 12, 13, 15, 33, 36], "pca": [9, 12, 15, 33], "n_features_a": [9, 12, 15], "n_features_b": [9, 12, 15], "reason": [9, 12, 15], "lda": [9, 15, 19], "meaning": [9, 12, 15], "direct": [9, 12, 15], "varianc": [9, 12, 15], "princip": [9, 12, 15], "decomposit": [9, 12, 15, 23, 33], "discriminant_analysi": [9, 15], "lineardiscriminantanalysi": [9, 15], "truncat": [9, 12, 15], "standard": [9, 12, 15, 30, 33], "match": [9, 12, 15, 33, 36], "less": [9, 12, 15, 33, 36], "includ": 9, "edg": 9, "minimum": [9, 33], "vari": 9, "stop": 9, "progress": [9, 12, 15], "pull": 9, "push": [9, 30], "term": [9, 36], "mean": [9, 30, 33, 36], "q": [9, 12], "weinberg": [9, 12, 33], "j": [9, 15, 16, 33, 36], "blitzer": 9, "saul": 9, "nip": [9, 13, 15, 33, 36], "2005": [9, 15, 33, 36], "squar": [10, 11, 13, 18, 33, 36], "residu": [10, 11, 36], "propos": [10, 36], "thu": [10, 13, 30, 36], "infeas": [10, 36], "deploi": [10, 36], "furthermor": [10, 36], "extens": [10, 36], "lead": [10, 13, 29, 30, 33, 36], "stabl": [10, 36], "amount": [10, 36], "liu": [10, 36], "icdm": [10, 36], "2012": [10, 30, 36], "adapt": [10, 18, 19, 20, 36], "gist": [10, 20, 36], "github": [10, 20, 28, 36], "kcarnold": [10, 20, 36], "5439917": [10, 36], "quadruplet": [10, 11, 26, 30, 33, 35], "minu": [10, 18, 26, 27, 36], "probabl": [10, 18, 26, 27, 33, 36], "n_quadruplet": [10, 26], "four": [10, 26], "factor": 10, "record": [10, 26, 36], "correctli": [10, 18, 26, 27, 33], "last": [10, 11, 18, 26, 27, 28, 33, 36], "kernel": [12, 33], "regress": [12, 30, 33], "view": [12, 33], "variat": [12, 33], "cap": 12, "conjug": 12, "gradient": 12, "messag": [12, 15], "tesauto": 12, "aistat": [12, 33], "max_proj": [13, 14, 36], "diagon": [13, 14, 20, 36], "diagonal_c": [13, 14, 36], "greater": [13, 36], "minima": [13, 36], "free": [13, 36], "involv": [13, 36], "speed": [13, 36], "bottleneck": [13, 36], "been": [13, 36], "implicit": [13, 36], "compact": [13, 32, 36], "unimod": [13, 36], "restrict": [13, 36], "earliest": [13, 36], "still": [13, 18, 19, 36], "often": [13, 30, 36], "cite": [13, 36], "techniqu": [13, 36], "coeffici": [13, 14], "gotten": [13, 20, 22], "xing": [13, 36], "jordan": 13, "russel": 13, "ng": 13, "side": [13, 36], "2002": [13, 16, 36], "06": 14, "neighborhood": [15, 33], "stochast": [15, 18, 33, 36], "variant": [15, 33], "fast": [15, 33], "goldberg": [15, 33], "hinton": 15, "rowei": 15, "r": [15, 36], "salakhutdinov": 15, "neighbourhood": [15, 33], "wikipedia": [15, 33, 34], "entri": [15, 29, 33, 36], "scalar": 15, "noam": 16, "shental": [16, 36], "adjust": [16, 36], "eccv": [16, 36], "05": [16, 18, 19, 36], "95": [16, 36], "repeat": 17, "process": [17, 33], "constructor": 17, "Not": 17, "basi": [18, 19, 36], "triplet_diff": 18, "n_basi": [18, 19], "005": [18, 19], "output_it": [18, 19], "500": [18, 19], "batch_siz": [18, 19], "spars": [18, 19, 20, 21, 36], "composit": [18, 19, 36], "psd": [18, 23, 30, 36], "scheme": [18, 36], "experiment": [18, 19], "hesit": [18, 19], "report": [18, 19], "someth": [18, 19], "fail": [18, 19], "expect": [18, 19], "l1": [18, 19, 20, 36], "great": 18, "5e": [18, 19], "5000": [18, 19], "current": [18, 19, 30, 33, 36], "scml_supervis": 18, "shi": [18, 19, 36], "bellet": [18, 19, 29, 36], "sha": [18, 19, 36], "aaai": [18, 19, 36], "2014": [18, 19, 36], "matlab": [18, 19, 36], "_components_from_basis_weight": [18, 19], "n_triplet": [18, 27], "three": [18, 27, 30, 36], "scml": [19, 35], "neighbour": 19, "signific": 19, "region": [19, 33], "center": 19, "100000": [19, 36], "33": 19, "84640733": 19, "55984363": 19, "8464073327922157": 19, "01": [20, 21, 36], "doubl": [20, 36], "off": [20, 21, 36], "mathbf": [20, 33, 36], "determin": [20, 36], "m_0": [20, 36], "either": [20, 28, 30, 33, 36], "omega": [20, 36], "trade": [20, 21], "m0": [20, 21], "graph_lasso": [20, 21], "qi": [20, 36], "2009": [20, 33, 36], "5439945": [20, 36], "abstract": [22, 24, 25, 26, 27], "avail": [22, 25, 26, 27, 30], "thrown": [22, 25, 26, 27], "simpli": [22, 25, 26, 27, 30, 36], "access": [22, 25, 26, 27, 30], "column": [23, 32], "vector": [23, 30, 36], "symmetr": 23, "express": 23, "decompos": [23, 30], "product": 23, "transpos": 23, "svd": 23, "choleski": 23, "xl": 24, "anaconda": 28, "conda": 28, "forg": 28, "pypi": 28, "latest": 28, "repositori": 28, "mai": [28, 30, 36], "pytest": 28, "support": 28, "wa": 28, "v0": 28, "17": 28, "21": [28, 29, 36], "skggm": 28, "problemat": 28, "commit": 28, "a0ed406": 28, "git": 28, "a0ed406586c4364ea3297a658f415e13b5cbdaf8": 28, "load": 28, "model_select": [28, 33, 36], "cross_val_scor": [28, 33, 36], "make_pipelin": 28, "return_x_i": [28, 36], "As": 29, "part": 29, "contrib": 29, "librari": [29, 30], "routin": [29, 33, 36], "etc": [29, 30, 32, 33, 36], "unifi": 29, "scientif": 29, "public": 29, "appreci": 29, "citat": 29, "paper": [29, 36], "journal": 29, "research": 29, "138": 29, "2020": 29, "bibtex": 29, "articl": 29, "titl": 29, "etric": 29, "earn": 29, "lgorithm": 29, "ython": 29, "carei": 29, "cj": 29, "vauquier": 29, "nathali": 29, "aur": 29, "lien": 29, "year": 29, "volum": 29, "page": [29, 34], "setup": 29, "quick": 29, "content": 29, "index": [29, 32], "search": 29, "approach": 30, "tradition": 30, "practition": 30, "citi": 30, "block": 30, "cosin": 30, "priori": 30, "domain": 30, "difficult": 30, "suit": 30, "interest": 30, "manner": 30, "variou": 30, "fall": 30, "categori": 30, "broadli": 30, "speak": 30, "level": 30, "typic": 30, "weaker": [30, 36], "seek": 30, "agreement": 30, "num_dim": 30, "lx": [30, 33], "recov": 30, "seen": 30, "properti": 30, "non": 30, "symmetri": 30, "triangl": 30, "indiscern": 30, "parameter": [30, 36], "fact": 30, "both": [30, 33], "equival": [30, 36], "practic": 30, "There": 30, "few": 30, "anomali": 30, "detect": 30, "bia": 30, "toward": 30, "intend": 30, "semant": [30, 33, 36], "closest": 30, "feed": 30, "realiz": 30, "joint": 30, "hyperparamet": 30, "tune": 30, "resourc": 30, "vision": 30, "2015": 30, "survei": 30, "structur": [30, 36], "2013": 30, "book": 30, "instanti": 32, "fill": 32, "represent": [32, 36], "accept": 32, "abl": [32, 36], "replac": 32, "23": [32, 36], "43": 32, "49": 32, "14": 32, "37": 32, "points_indic": 32, "pairs_indic": [32, 36], "y_pair": [32, 36], "Then": [32, 33, 36], "realli": 32, "repres": [32, 33, 36], "lazili": 32, "store": 32, "system": 32, "onc": [32, 33], "find_imag": 32, "file_path": 32, "datapoint": 32, "row_stack": 32, "imread": 32, "img01": 32, "png": 32, "img00": 32, "img02": 32, "pairs_images_path": 32, "pairs_ind": 32, "stai": 32, "preprocessor_wip": 32, "notimplementederror": 32, "noth": 32, "distant": 33, "essenti": 33, "dog": 33, "cat": 33, "anim": 33, "91884732": 33, "25406973": 33, "1545886": 33, "80350083": 33, "our": [33, 36], "49627072": [33, 36], "65287282": [33, 36], "06079877": [33, 36], "Or": [33, 36], "coordin": [33, 36], "similarli": [33, 36], "spatial": [33, 36], "4962707194621285": 33, "43680409": 33, "89169412": 33, "9542479": 33, "baseestim": 33, "gridsearchcv": [33, 36], "min_": [33, 36], "sum_": [33, 36], "eta_": 33, "ij": [33, 36], "x_i": [33, 36], "x_j": [33, 36], "y_": 33, "x_l": 33, "_i": [33, 36], "_j": [33, 36], "_l": [33, 36], "within": [33, 36], "cdot": [33, 36], "max": 33, "p_": 33, "softmax": 33, "likelihood": 33, "frac": [33, 36], "exp": [33, 36], "_2": [33, 36], "neq": 33, "qquad": [33, 36], "ii": 33, "y_j": 33, "y_i": 33, "text": [33, 36], "argmax": 33, "sum_i": 33, "p_i": 33, "idea": 33, "en": 33, "wiki": 33, "linear_discriminant_analysi": 33, "multi": 33, "modal": 33, "w": [33, 36], "fashion": 33, "nw_": 33, "w_": 33, "begin": [33, 36], "align": [33, 36], "n_l": 33, "th": 33, "affin": 33, "deriv": 33, "arg": 33, "max_": 33, "tr": [33, 36], "That": 33, "nearbi": 33, "made": 33, "apart": 33, "impos": 33, "ldfa": 33, "suffer": 33, "sign": 33, "indeterminaci": 33, "state": 33, "relat": [33, 36], "ran": 33, "might": [33, 36], "hereaft": 33, "focu": 33, "exposit": 33, "empir": 33, "develop": 33, "denot": [33, 36], "k_": 33, "pi": 33, "sigma": 33, "transit": 33, "tl": 33, "sake": [33, 36], "simplic": [33, 36], "cumul": 33, "quadrat": 33, "mathcal": 33, "hat": [33, 36], "y_jk_": 33, "_supervis": 33, "interpret": [33, 36], "discard": 33, "sometim": 33, "lenght": 33, "unlabel": 34, "zca": 34, "whiten": 34, "judgment": 36, "paragraph": 36, "These": 36, "theses": 36, "ex": 36, "appropri": 36, "my_algo": 36, "split": 36, "train_test_split": 36, "pairs_train": 36, "pairs_test": 36, "y_train": 36, "y_test": 36, "n_tupl": 36, "tuple_s": 36, "artifici": 36, "12": 36, "19": 36, "16": 36, "02": 36, "58": 36, "93": 36, "89": 36, "34": 36, "41": 36, "recommend": 36, "redund": 36, "comment": 36, "lot": 36, "memori": 36, "replic": 36, "collect": 36, "loos": 36, "tuples_indic": 36, "fetch": 36, "path": 36, "filesystem": 36, "wise": 36, "a0": 36, "24667162e": 36, "62622348e": 36, "88325421e": 36, "08": 36, "61531114e": 36, "86778289e": 36, "12654397e": 36, "27607365": 36, "88853014": 36, "276073646278203": 36, "58603894": 36, "69883982": 36, "66614919": 36, "41743549": 36, "20219519": 36, "73697721": 36, "rng": 36, "randint": 36, "next": 36, "unseen": 36, "15": 36, "75": 36, "threshold_param": 36, "caus": 36, "overfit": 36, "avoid": 36, "f1": 36, "12811124": 36, "74750256": 36, "common": 36, "accuracy_scor": 36, "roc_auc_scor": 36, "z": 36, "d_": 36, "mu": 36, "constant": 36, "textbf": 36, "kl": 36, "_0": 36, "ell": 36, "mathrm": 36, "m_": 36, "operatornam": 36, "det": 36, "quad": 36, "leq": 36, "geq": 36, "upper": 36, "www": 36, "utexa": 36, "edu": 36, "pjain": 36, "eta": 36, "xlx": 36, "lambda": 36, "_1": 36, "_n": 36, "incid": 36, "laplacian": 36, "whose": 36, "norm": 36, "n_j": 36, "ji": 36, "bar": 36, "hillel": 36, "2003": 36, "constrain": 36, "mathbb": 36, "2_": 36, "cmu": 36, "7eepx": 36, "old_pap": 36, "code_metric_onlin": 36, "tar": 36, "gz": 36, "third": 36, "triplets_indic": 36, "upcom": 36, "triplets_test": 36, "likeli": 36, "75700306": 36, "98982131": 36, "f1_score": 36, "proport": 36, "built": 36, "b_i": 36, "w_i": 36, "diag": 36, "nonneg": 36, "fix": 36, "over": 36, "ell_1": 36, "ad": 36, "x_k": 36, "d_w": 36, "quadruplets_indic": 36, "quadruplets_test": 36, "_k": 36, "h": 36, "suggest": 36, "confid": 36, "extra": 36, "experi": 36, "plu": 36, "ld": 36, "mm_0": 36}, "objects": {"metric_learn": [[4, 0, 1, "", "Constraints"], [5, 0, 1, "", "Covariance"], [6, 0, 1, "", "ITML"], [7, 0, 1, "", "ITML_Supervised"], [8, 0, 1, "", "LFDA"], [9, 0, 1, "", "LMNN"], [10, 0, 1, "", "LSML"], [11, 0, 1, "", "LSML_Supervised"], [12, 0, 1, "", "MLKR"], [13, 0, 1, "", "MMC"], [14, 0, 1, "", "MMC_Supervised"], [15, 0, 1, "", "NCA"], [16, 0, 1, "", "RCA"], [17, 0, 1, "", "RCA_Supervised"], [18, 0, 1, "", "SCML"], [19, 0, 1, "", "SCML_Supervised"], [20, 0, 1, "", "SDML"], [21, 0, 1, "", "SDML_Supervised"]], "metric_learn.Constraints": [[4, 1, 1, "", "__init__"], [4, 1, 1, "", "chunks"], [4, 1, 1, "", "generate_knntriplets"], [4, 1, 1, "", "positive_negative_pairs"]], "metric_learn.Covariance": [[5, 1, 1, "", "__init__"], [5, 1, 1, "", "fit"], [5, 1, 1, "", "fit_transform"], [5, 1, 1, "", "get_mahalanobis_matrix"], [5, 1, 1, "", "get_metadata_routing"], [5, 1, 1, "", "get_metric"], [5, 1, 1, "", "get_params"], [5, 1, 1, "", "pair_distance"], [5, 1, 1, "", "pair_score"], [5, 1, 1, "", "score_pairs"], [5, 1, 1, "", "set_output"], [5, 1, 1, "", "set_params"], [5, 1, 1, "", "transform"]], "metric_learn.ITML": [[6, 1, 1, "", "__init__"], [6, 1, 1, "", "calibrate_threshold"], [6, 2, 1, "", "classes_"], [6, 1, 1, "", "decision_function"], [6, 1, 1, "", "fit"], [6, 1, 1, "", "get_mahalanobis_matrix"], [6, 1, 1, "", "get_metadata_routing"], [6, 1, 1, "", "get_metric"], [6, 1, 1, "", "get_params"], [6, 1, 1, "", "pair_distance"], [6, 1, 1, "", "pair_score"], [6, 1, 1, "", "predict"], [6, 1, 1, "", "score"], [6, 1, 1, "", "score_pairs"], [6, 1, 1, "", "set_decision_function_request"], [6, 1, 1, "", "set_fit_request"], [6, 1, 1, "", "set_params"], [6, 1, 1, "", "set_predict_request"], [6, 1, 1, "", "set_score_request"], [6, 1, 1, "", "set_threshold"], [6, 1, 1, "", "transform"]], "metric_learn.ITML_Supervised": [[7, 1, 1, "", "__init__"], [7, 1, 1, "", "fit"], [7, 1, 1, "", "fit_transform"], [7, 1, 1, "", "get_mahalanobis_matrix"], [7, 1, 1, "", "get_metadata_routing"], [7, 1, 1, "", "get_metric"], [7, 1, 1, "", "get_params"], [7, 1, 1, "", "pair_distance"], [7, 1, 1, "", "pair_score"], [7, 1, 1, "", "score_pairs"], [7, 1, 1, "", "set_fit_request"], [7, 1, 1, "", "set_output"], [7, 1, 1, "", "set_params"], [7, 1, 1, "", "transform"]], "metric_learn.LFDA": [[8, 1, 1, "", "__init__"], [8, 1, 1, "", "fit"], [8, 1, 1, "", "fit_transform"], [8, 1, 1, "", "get_mahalanobis_matrix"], [8, 1, 1, "", "get_metadata_routing"], [8, 1, 1, "", "get_metric"], [8, 1, 1, "", "get_params"], [8, 1, 1, "", "pair_distance"], [8, 1, 1, "", "pair_score"], [8, 1, 1, "", "score_pairs"], [8, 1, 1, "", "set_output"], [8, 1, 1, "", "set_params"], [8, 1, 1, "", "transform"]], "metric_learn.LMNN": [[9, 1, 1, "", "__init__"], [9, 1, 1, "", "fit"], [9, 1, 1, "", "fit_transform"], [9, 1, 1, "", "get_mahalanobis_matrix"], [9, 1, 1, "", "get_metadata_routing"], [9, 1, 1, "", "get_metric"], [9, 1, 1, "", "get_params"], [9, 1, 1, "", "pair_distance"], [9, 1, 1, "", "pair_score"], [9, 1, 1, "", "score_pairs"], [9, 1, 1, "", "set_output"], [9, 1, 1, "", "set_params"], [9, 1, 1, "", "transform"]], "metric_learn.LSML": [[10, 1, 1, "", "__init__"], [10, 2, 1, "", "classes_"], [10, 1, 1, "", "decision_function"], [10, 1, 1, "", "fit"], [10, 1, 1, "", "get_mahalanobis_matrix"], [10, 1, 1, "", "get_metadata_routing"], [10, 1, 1, "", "get_metric"], [10, 1, 1, "", "get_params"], [10, 1, 1, "", "pair_distance"], [10, 1, 1, "", "pair_score"], [10, 1, 1, "", "predict"], [10, 1, 1, "", "score"], [10, 1, 1, "", "score_pairs"], [10, 1, 1, "", "set_decision_function_request"], [10, 1, 1, "", "set_fit_request"], [10, 1, 1, "", "set_params"], [10, 1, 1, "", "set_predict_request"], [10, 1, 1, "", "set_score_request"], [10, 1, 1, "", "transform"]], "metric_learn.LSML_Supervised": [[11, 1, 1, "", "__init__"], [11, 1, 1, "", "fit"], [11, 1, 1, "", "fit_transform"], [11, 1, 1, "", "get_mahalanobis_matrix"], [11, 1, 1, "", "get_metadata_routing"], [11, 1, 1, "", "get_metric"], [11, 1, 1, "", "get_params"], [11, 1, 1, "", "pair_distance"], [11, 1, 1, "", "pair_score"], [11, 1, 1, "", "score_pairs"], [11, 1, 1, "", "set_output"], [11, 1, 1, "", "set_params"], [11, 1, 1, "", "transform"]], "metric_learn.MLKR": [[12, 1, 1, "", "__init__"], [12, 1, 1, "", "fit"], [12, 1, 1, "", "fit_transform"], [12, 1, 1, "", "get_mahalanobis_matrix"], [12, 1, 1, "", "get_metadata_routing"], [12, 1, 1, "", "get_metric"], [12, 1, 1, "", "get_params"], [12, 1, 1, "", "pair_distance"], [12, 1, 1, "", "pair_score"], [12, 1, 1, "", "score_pairs"], [12, 1, 1, "", "set_output"], [12, 1, 1, "", "set_params"], [12, 1, 1, "", "transform"]], "metric_learn.MMC": [[13, 1, 1, "", "__init__"], [13, 1, 1, "", "calibrate_threshold"], [13, 2, 1, "", "classes_"], [13, 1, 1, "", "decision_function"], [13, 1, 1, "", "fit"], [13, 1, 1, "", "get_mahalanobis_matrix"], [13, 1, 1, "", "get_metadata_routing"], [13, 1, 1, "", "get_metric"], [13, 1, 1, "", "get_params"], [13, 1, 1, "", "pair_distance"], [13, 1, 1, "", "pair_score"], [13, 1, 1, "", "predict"], [13, 1, 1, "", "score"], [13, 1, 1, "", "score_pairs"], [13, 1, 1, "", "set_decision_function_request"], [13, 1, 1, "", "set_fit_request"], [13, 1, 1, "", "set_params"], [13, 1, 1, "", "set_predict_request"], [13, 1, 1, "", "set_score_request"], [13, 1, 1, "", "set_threshold"], [13, 1, 1, "", "transform"]], "metric_learn.MMC_Supervised": [[14, 1, 1, "", "__init__"], [14, 1, 1, "", "fit"], [14, 1, 1, "", "fit_transform"], [14, 1, 1, "", "get_mahalanobis_matrix"], [14, 1, 1, "", "get_metadata_routing"], [14, 1, 1, "", "get_metric"], [14, 1, 1, "", "get_params"], [14, 1, 1, "", "pair_distance"], [14, 1, 1, "", "pair_score"], [14, 1, 1, "", "score_pairs"], [14, 1, 1, "", "set_output"], [14, 1, 1, "", "set_params"], [14, 1, 1, "", "transform"]], "metric_learn.NCA": [[15, 1, 1, "", "__init__"], [15, 1, 1, "", "fit"], [15, 1, 1, "", "fit_transform"], [15, 1, 1, "", "get_mahalanobis_matrix"], [15, 1, 1, "", "get_metadata_routing"], [15, 1, 1, "", "get_metric"], [15, 1, 1, "", "get_params"], [15, 1, 1, "", "pair_distance"], [15, 1, 1, "", "pair_score"], [15, 1, 1, "", "score_pairs"], [15, 1, 1, "", "set_output"], [15, 1, 1, "", "set_params"], [15, 1, 1, "", "transform"]], "metric_learn.RCA": [[16, 1, 1, "", "__init__"], [16, 1, 1, "", "fit"], [16, 1, 1, "", "fit_transform"], [16, 1, 1, "", "get_mahalanobis_matrix"], [16, 1, 1, "", "get_metadata_routing"], [16, 1, 1, "", "get_metric"], [16, 1, 1, "", "get_params"], [16, 1, 1, "", "pair_distance"], [16, 1, 1, "", "pair_score"], [16, 1, 1, "", "score_pairs"], [16, 1, 1, "", "set_fit_request"], [16, 1, 1, "", "set_output"], [16, 1, 1, "", "set_params"], [16, 1, 1, "", "transform"]], "metric_learn.RCA_Supervised": [[17, 1, 1, "", "__init__"], [17, 1, 1, "", "fit"], [17, 1, 1, "", "fit_transform"], [17, 1, 1, "", "get_mahalanobis_matrix"], [17, 1, 1, "", "get_metadata_routing"], [17, 1, 1, "", "get_metric"], [17, 1, 1, "", "get_params"], [17, 1, 1, "", "pair_distance"], [17, 1, 1, "", "pair_score"], [17, 1, 1, "", "score_pairs"], [17, 1, 1, "", "set_fit_request"], [17, 1, 1, "", "set_output"], [17, 1, 1, "", "set_params"], [17, 1, 1, "", "transform"]], "metric_learn.SCML": [[18, 1, 1, "", "__init__"], [18, 2, 1, "", "classes_"], [18, 1, 1, "", "decision_function"], [18, 1, 1, "", "fit"], [18, 1, 1, "", "get_mahalanobis_matrix"], [18, 1, 1, "", "get_metadata_routing"], [18, 1, 1, "", "get_metric"], [18, 1, 1, "", "get_params"], [18, 1, 1, "", "pair_distance"], [18, 1, 1, "", "pair_score"], [18, 1, 1, "", "predict"], [18, 1, 1, "", "score"], [18, 1, 1, "", "score_pairs"], [18, 1, 1, "", "set_decision_function_request"], [18, 1, 1, "", "set_fit_request"], [18, 1, 1, "", "set_params"], [18, 1, 1, "", "set_predict_request"], [18, 1, 1, "", "set_score_request"], [18, 1, 1, "", "transform"]], "metric_learn.SCML_Supervised": [[19, 1, 1, "", "__init__"], [19, 1, 1, "", "fit"], [19, 1, 1, "", "fit_transform"], [19, 1, 1, "", "get_mahalanobis_matrix"], [19, 1, 1, "", "get_metadata_routing"], [19, 1, 1, "", "get_metric"], [19, 1, 1, "", "get_params"], [19, 1, 1, "", "pair_distance"], [19, 1, 1, "", "pair_score"], [19, 1, 1, "", "score_pairs"], [19, 1, 1, "", "set_output"], [19, 1, 1, "", "set_params"], [19, 1, 1, "", "transform"]], "metric_learn.SDML": [[20, 1, 1, "", "__init__"], [20, 1, 1, "", "calibrate_threshold"], [20, 2, 1, "", "classes_"], [20, 1, 1, "", "decision_function"], [20, 1, 1, "", "fit"], [20, 1, 1, "", "get_mahalanobis_matrix"], [20, 1, 1, "", "get_metadata_routing"], [20, 1, 1, "", "get_metric"], [20, 1, 1, "", "get_params"], [20, 1, 1, "", "pair_distance"], [20, 1, 1, "", "pair_score"], [20, 1, 1, "", "predict"], [20, 1, 1, "", "score"], [20, 1, 1, "", "score_pairs"], [20, 1, 1, "", "set_decision_function_request"], [20, 1, 1, "", "set_fit_request"], [20, 1, 1, "", "set_params"], [20, 1, 1, "", "set_predict_request"], [20, 1, 1, "", "set_score_request"], [20, 1, 1, "", "set_threshold"], [20, 1, 1, "", "transform"]], "metric_learn.SDML_Supervised": [[21, 1, 1, "", "__init__"], [21, 1, 1, "", "fit"], [21, 1, 1, "", "fit_transform"], [21, 1, 1, "", "get_mahalanobis_matrix"], [21, 1, 1, "", "get_metadata_routing"], [21, 1, 1, "", "get_metric"], [21, 1, 1, "", "get_params"], [21, 1, 1, "", "pair_distance"], [21, 1, 1, "", "pair_score"], [21, 1, 1, "", "score_pairs"], [21, 1, 1, "", "set_output"], [21, 1, 1, "", "set_params"], [21, 1, 1, "", "transform"]], "metric_learn.base_metric": [[22, 0, 1, "", "BaseMetricLearner"], [23, 0, 1, "", "MahalanobisMixin"], [24, 0, 1, "", "MetricTransformer"], [25, 0, 1, "", "_PairsClassifierMixin"], [26, 0, 1, "", "_QuadrupletsClassifierMixin"], [27, 0, 1, "", "_TripletsClassifierMixin"]], "metric_learn.base_metric.BaseMetricLearner": [[22, 1, 1, "", "__init__"], [22, 1, 1, "", "get_metadata_routing"], [22, 1, 1, "", "get_metric"], [22, 1, 1, "", "get_params"], [22, 1, 1, "", "pair_distance"], [22, 1, 1, "", "pair_score"], [22, 1, 1, "", "score_pairs"], [22, 1, 1, "", "set_params"]], "metric_learn.base_metric.MahalanobisMixin": [[23, 1, 1, "", "__init__"], [23, 1, 1, "", "get_mahalanobis_matrix"], [23, 1, 1, "", "get_metadata_routing"], [23, 1, 1, "", "get_metric"], [23, 1, 1, "", "get_params"], [23, 1, 1, "", "pair_distance"], [23, 1, 1, "", "pair_score"], [23, 1, 1, "", "score_pairs"], [23, 1, 1, "", "set_params"], [23, 1, 1, "", "transform"]], "metric_learn.base_metric.MetricTransformer": [[24, 1, 1, "", "transform"]], "metric_learn.base_metric._PairsClassifierMixin": [[25, 1, 1, "", "__init__"], [25, 1, 1, "", "calibrate_threshold"], [25, 2, 1, "", "classes_"], [25, 1, 1, "", "decision_function"], [25, 1, 1, "", "get_metadata_routing"], [25, 1, 1, "", "get_metric"], [25, 1, 1, "", "get_params"], [25, 1, 1, "", "pair_distance"], [25, 1, 1, "", "pair_score"], [25, 1, 1, "", "predict"], [25, 1, 1, "", "score"], [25, 1, 1, "", "score_pairs"], [25, 1, 1, "", "set_decision_function_request"], [25, 1, 1, "", "set_params"], [25, 1, 1, "", "set_predict_request"], [25, 1, 1, "", "set_score_request"], [25, 1, 1, "", "set_threshold"]], "metric_learn.base_metric._QuadrupletsClassifierMixin": [[26, 1, 1, "", "__init__"], [26, 2, 1, "", "classes_"], [26, 1, 1, "", "decision_function"], [26, 1, 1, "", "get_metadata_routing"], [26, 1, 1, "", "get_metric"], [26, 1, 1, "", "get_params"], [26, 1, 1, "", "pair_distance"], [26, 1, 1, "", "pair_score"], [26, 1, 1, "", "predict"], [26, 1, 1, "", "score"], [26, 1, 1, "", "score_pairs"], [26, 1, 1, "", "set_decision_function_request"], [26, 1, 1, "", "set_params"], [26, 1, 1, "", "set_predict_request"], [26, 1, 1, "", "set_score_request"]], "metric_learn.base_metric._TripletsClassifierMixin": [[27, 1, 1, "", "__init__"], [27, 2, 1, "", "classes_"], [27, 1, 1, "", "decision_function"], [27, 1, 1, "", "get_metadata_routing"], [27, 1, 1, "", "get_metric"], [27, 1, 1, "", "get_params"], [27, 1, 1, "", "pair_distance"], [27, 1, 1, "", "pair_score"], [27, 1, 1, "", "predict"], [27, 1, 1, "", "score"], [27, 1, 1, "", "score_pairs"], [27, 1, 1, "", "set_decision_function_request"], [27, 1, 1, "", "set_params"], [27, 1, 1, "", "set_predict_request"], [27, 1, 1, "", "set_score_request"]]}, "objtypes": {"0": "py:class", "1": "py:method", "2": "py:attribute"}, "objnames": {"0": ["py", "class", "Python class"], "1": ["py", "method", "Python method"], "2": ["py", "attribute", "Python attribute"]}, "titleterms": {"exampl": [0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25], "algorithm": [1, 31, 33, 34, 36], "walkthrough": 1, "import": 1, "load": 1, "our": 1, "dataset": 1, "set": [1, 30], "up": 1, "plot": 1, "metric": [1, 29, 30, 33, 34, 36], "learn": [1, 29, 30, 31, 33, 34, 36], "larg": 1, "margin": 1, "nearest": 1, "neighbour": 1, "fit": [1, 33, 36], "transform": [1, 33, 36], "inform": 1, "theoret": 1, "mahalanobi": [1, 30], "cluster": 1, "spars": 1, "determin": 1, "least": 1, "squar": 1, "neighborhood": 1, "compon": 1, "analysi": 1, "local": 1, "fisher": 1, "discrimin": 1, "rel": 1, "regress": 1, "kernel": 1, "from": 1, "weaker": 1, "supervis": [1, 31, 33, 36], "sandwich": 2, "demo": 2, "comput": 3, "time": 3, "metric_learn": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 31], "constraint": 4, "covari": [5, 34], "itml": [6, 36], "us": [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25, 30], "itml_supervis": 7, "lfda": [8, 33], "lmnn": [9, 33], "lsml": [10, 36], "lsml_supervis": 11, "mlkr": [12, 33], "mmc": [13, 36], "mmc_supervis": 14, "nca": [15, 33], "rca": [16, 36], "rca_supervis": 17, "scml": [18, 36], "scml_supervis": 19, "sdml": [20, 36], "sdml_supervis": 21, "base_metr": [22, 23, 24, 25, 26, 27], "basemetriclearn": 22, "mahalanobismixin": 23, "metrictransform": 24, "_pairsclassifiermixin": 25, "_quadrupletsclassifiermixin": 26, "_tripletsclassifiermixin": 27, "get": 28, "start": 28, "instal": 28, "setup": 28, "quick": 28, "python": 29, "document": 29, "outlin": 29, "what": 30, "i": 30, "problem": 30, "distanc": 30, "case": 30, "further": 30, "read": 30, "packag": 31, "modul": 31, "content": 31, "base": 31, "class": 31, "weakli": [31, 33, 36], "unsupervis": [31, 34], "preprocessor": [32, 36], "arrai": [32, 36], "like": 32, "callabl": 32, "gener": [33, 36], "api": [33, 36], "input": [33, 36], "data": [33, 36], "so": [33, 36], "scikit": [33, 36], "compat": [33, 36], "version": 33, "user": 35, "guid": 35, "basic": 36, "form": 36, "3d": 36, "tupl": 36, "2d": 36, "indic": 36, "predict": 36, "score": 36, "pair": 36, "threshold": 36, "triplet": 36, "quadruplet": 36}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx.ext.intersphinx": 1, "sphinx": 60}, "alltitles": {"Examples": [[0, "examples"]], "Algorithms walkthrough": [[1, "algorithms-walkthrough"]], "Imports": [[1, "imports"]], "Loading our dataset and setting up plotting": [[1, "loading-our-dataset-and-setting-up-plotting"]], "Metric Learning": [[1, "metric-learning"]], "Large Margin Nearest Neighbour": [[1, "large-margin-nearest-neighbour"]], "Fit and then transform!": [[1, "fit-and-then-transform"]], "Information Theoretic Metric Learning": [[1, "information-theoretic-metric-learning"]], "Mahalanobis Metric for Clustering": [[1, "mahalanobis-metric-for-clustering"]], "Sparse Determinant Metric Learning": [[1, "sparse-determinant-metric-learning"]], "Least Squares Metric Learning": [[1, "least-squares-metric-learning"]], "Neighborhood Components Analysis": [[1, "neighborhood-components-analysis"]], "Local Fisher Discriminant Analysis": [[1, "local-fisher-discriminant-analysis"]], "Relative Components Analysis": [[1, "relative-components-analysis"]], "Regression example: Metric Learning for Kernel Regression": [[1, "regression-example-metric-learning-for-kernel-regression"]], "Metric Learning from Weaker Supervision": [[1, "metric-learning-from-weaker-supervision"]], "Sandwich demo": [[2, "sandwich-demo"]], "Computation times": [[3, "computation-times"]], "metric_learn.Constraints": [[4, "metric-learn-constraints"]], "metric_learn.Covariance": [[5, "metric-learn-covariance"]], "metric_learn.ITML": [[6, "metric-learn-itml"]], "Examples using metric_learn.ITML": [[6, "examples-using-metric-learn-itml"]], "metric_learn.ITML_Supervised": [[7, "metric-learn-itml-supervised"]], "Examples using metric_learn.ITML_Supervised": [[7, "examples-using-metric-learn-itml-supervised"]], "metric_learn.LFDA": [[8, "metric-learn-lfda"]], "Examples using metric_learn.LFDA": [[8, "examples-using-metric-learn-lfda"]], "metric_learn.LMNN": [[9, "metric-learn-lmnn"]], "Examples using metric_learn.LMNN": [[9, "examples-using-metric-learn-lmnn"]], "metric_learn.LSML": [[10, "metric-learn-lsml"]], "Examples using metric_learn.LSML": [[10, "examples-using-metric-learn-lsml"]], "metric_learn.LSML_Supervised": [[11, "metric-learn-lsml-supervised"]], "Examples using metric_learn.LSML_Supervised": [[11, "examples-using-metric-learn-lsml-supervised"]], "metric_learn.MLKR": [[12, "metric-learn-mlkr"]], "Examples using metric_learn.MLKR": [[12, "examples-using-metric-learn-mlkr"]], "metric_learn.MMC": [[13, "metric-learn-mmc"]], "Examples using metric_learn.MMC": [[13, "examples-using-metric-learn-mmc"]], "metric_learn.MMC_Supervised": [[14, "metric-learn-mmc-supervised"]], "Examples using metric_learn.MMC_Supervised": [[14, "examples-using-metric-learn-mmc-supervised"]], "metric_learn.NCA": [[15, "metric-learn-nca"]], "Examples using metric_learn.NCA": [[15, "examples-using-metric-learn-nca"]], "metric_learn.RCA": [[16, "metric-learn-rca"]], "Examples using metric_learn.RCA": [[16, "examples-using-metric-learn-rca"]], "metric_learn.RCA_Supervised": [[17, "metric-learn-rca-supervised"]], "Examples using metric_learn.RCA_Supervised": [[17, "examples-using-metric-learn-rca-supervised"]], "metric_learn.SCML": [[18, "metric-learn-scml"]], "metric_learn.SCML_Supervised": [[19, "metric-learn-scml-supervised"]], "metric_learn.SDML": [[20, "metric-learn-sdml"]], "Examples using metric_learn.SDML": [[20, "examples-using-metric-learn-sdml"]], "metric_learn.SDML_Supervised": [[21, "metric-learn-sdml-supervised"]], "Examples using metric_learn.SDML_Supervised": [[21, "examples-using-metric-learn-sdml-supervised"]], "metric_learn.base_metric.BaseMetricLearner": [[22, "metric-learn-base-metric-basemetriclearner"]], "Examples using metric_learn.base_metric.BaseMetricLearner": [[22, "examples-using-metric-learn-base-metric-basemetriclearner"]], "metric_learn.base_metric.MahalanobisMixin": [[23, "metric-learn-base-metric-mahalanobismixin"]], "Examples using metric_learn.base_metric.MahalanobisMixin": [[23, "examples-using-metric-learn-base-metric-mahalanobismixin"]], "metric_learn.base_metric.MetricTransformer": [[24, "metric-learn-base-metric-metrictransformer"]], "Examples using metric_learn.base_metric.MetricTransformer": [[24, "examples-using-metric-learn-base-metric-metrictransformer"]], "metric_learn.base_metric._PairsClassifierMixin": [[25, "metric-learn-base-metric-pairsclassifiermixin"]], "Examples using metric_learn.base_metric._PairsClassifierMixin": [[25, "examples-using-metric-learn-base-metric-pairsclassifiermixin"]], "metric_learn.base_metric._QuadrupletsClassifierMixin": [[26, "metric-learn-base-metric-quadrupletsclassifiermixin"]], "metric_learn.base_metric._TripletsClassifierMixin": [[27, "metric-learn-base-metric-tripletsclassifiermixin"]], "Getting started": [[28, "getting-started"]], "Installation and Setup": [[28, "installation-and-setup"]], "Quick start": [[28, "quick-start"]], "metric-learn: Metric Learning in Python": [[29, "metric-learn-metric-learning-in-python"]], "Documentation outline": [[29, "documentation-outline"]], "What is Metric Learning?": [[30, "what-is-metric-learning"]], "Problem Setting": [[30, "problem-setting"]], "Mahalanobis Distances": [[30, "mahalanobis-distances"]], "Use-cases": [[30, "use-cases"]], "Further reading": [[30, "further-reading"]], "metric_learn package": [[31, "metric-learn-package"]], "Module Contents": [[31, "module-contents"]], "Base Classes": [[31, "base-classes"]], "Supervised Learning Algorithms": [[31, "supervised-learning-algorithms"]], "Weakly Supervised Learning Algorithms": [[31, "weakly-supervised-learning-algorithms"]], "Unsupervised Learning Algorithms": [[31, "unsupervised-learning-algorithms"]], "Preprocessor": [[32, "preprocessor"]], "Array-like": [[32, "array-like"]], "Callable": [[32, "callable"]], "Supervised Metric Learning": [[33, "supervised-metric-learning"]], "General API": [[33, "general-api"], [36, "general-api"]], "Input data": [[33, "input-data"], [36, "input-data"]], "Fit, transform, and so on": [[33, "fit-transform-and-so-on"], [36, "fit-transform-and-so-on"]], "Scikit-learn compatibility": [[33, "scikit-learn-compatibility"], [36, "scikit-learn-compatibility"]], "Algorithms": [[33, "algorithms"], [34, "algorithms"], [36, "algorithms"], [36, "id10"], [36, "id16"]], "LMNN": [[33, "lmnn"]], "NCA": [[33, "nca"]], "LFDA": [[33, "lfda"]], "MLKR": [[33, "mlkr"]], "Supervised versions of weakly-supervised algorithms": [[33, "supervised-versions-of-weakly-supervised-algorithms"]], "Unsupervised Metric Learning": [[34, "unsupervised-metric-learning"]], "Covariance": [[34, "covariance"]], "User Guide": [[35, "user-guide"]], "Weakly Supervised Metric Learning": [[36, "weakly-supervised-metric-learning"]], "Basic form": [[36, "basic-form"]], "3D array of tuples": [[36, "d-array-of-tuples"]], "2D array of indicators + preprocessor": [[36, "d-array-of-indicators-preprocessor"]], "Prediction and scoring": [[36, "prediction-and-scoring"]], "Learning on pairs": [[36, "learning-on-pairs"]], "Fitting": [[36, "fitting"], [36, "id7"], [36, "id13"]], "Prediction": [[36, "prediction"], [36, "triplets-predicting"], [36, "quadruplets-predicting"]], "Prediction threshold": [[36, "prediction-threshold"]], "Scoring": [[36, "scoring"], [36, "triplets-scoring"], [36, "quadruplets-scoring"]], "ITML": [[36, "itml"]], "SDML": [[36, "sdml"]], "RCA": [[36, "rca"]], "MMC": [[36, "mmc"]], "Learning on triplets": [[36, "learning-on-triplets"]], "SCML": [[36, "scml"]], "Learning on quadruplets": [[36, "learning-on-quadruplets"]], "LSML": [[36, "lsml"]]}, "indexentries": {"constraints (class in metric_learn)": [[4, "metric_learn.Constraints"]], "__init__() (metric_learn.constraints method)": [[4, "metric_learn.Constraints.__init__"]], "chunks() (metric_learn.constraints method)": [[4, "metric_learn.Constraints.chunks"]], "generate_knntriplets() (metric_learn.constraints method)": [[4, "metric_learn.Constraints.generate_knntriplets"]], "positive_negative_pairs() (metric_learn.constraints method)": [[4, "metric_learn.Constraints.positive_negative_pairs"]], "covariance (class in metric_learn)": [[5, "metric_learn.Covariance"]], "__init__() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.__init__"]], "fit() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.fit"]], "fit_transform() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.get_metadata_routing"]], "get_metric() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.get_metric"]], "get_params() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.get_params"]], "pair_distance() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.pair_distance"]], "pair_score() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.pair_score"]], "score_pairs() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.score_pairs"]], "set_output() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.set_output"]], "set_params() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.set_params"]], "transform() (metric_learn.covariance method)": [[5, "metric_learn.Covariance.transform"]], "itml (class in metric_learn)": [[6, "metric_learn.ITML"]], "__init__() (metric_learn.itml method)": [[6, "metric_learn.ITML.__init__"]], "calibrate_threshold() (metric_learn.itml method)": [[6, "metric_learn.ITML.calibrate_threshold"]], "classes_ (metric_learn.itml attribute)": [[6, "metric_learn.ITML.classes_"]], "decision_function() (metric_learn.itml method)": [[6, "metric_learn.ITML.decision_function"]], "fit() (metric_learn.itml method)": [[6, "metric_learn.ITML.fit"]], "get_mahalanobis_matrix() (metric_learn.itml method)": [[6, "metric_learn.ITML.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.itml method)": [[6, "metric_learn.ITML.get_metadata_routing"]], "get_metric() (metric_learn.itml method)": [[6, "metric_learn.ITML.get_metric"]], "get_params() (metric_learn.itml method)": [[6, "metric_learn.ITML.get_params"]], "pair_distance() (metric_learn.itml method)": [[6, "metric_learn.ITML.pair_distance"]], "pair_score() (metric_learn.itml method)": [[6, "metric_learn.ITML.pair_score"]], "predict() (metric_learn.itml method)": [[6, "metric_learn.ITML.predict"]], "score() (metric_learn.itml method)": [[6, "metric_learn.ITML.score"]], "score_pairs() (metric_learn.itml method)": [[6, "metric_learn.ITML.score_pairs"]], "set_decision_function_request() (metric_learn.itml method)": [[6, "metric_learn.ITML.set_decision_function_request"]], "set_fit_request() (metric_learn.itml method)": [[6, "metric_learn.ITML.set_fit_request"]], "set_params() (metric_learn.itml method)": [[6, "metric_learn.ITML.set_params"]], "set_predict_request() (metric_learn.itml method)": [[6, "metric_learn.ITML.set_predict_request"]], "set_score_request() (metric_learn.itml method)": [[6, "metric_learn.ITML.set_score_request"]], "set_threshold() (metric_learn.itml method)": [[6, "metric_learn.ITML.set_threshold"]], "transform() (metric_learn.itml method)": [[6, "metric_learn.ITML.transform"]], "itml_supervised (class in metric_learn)": [[7, "metric_learn.ITML_Supervised"]], "__init__() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.__init__"]], "fit() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.fit"]], "fit_transform() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.get_metadata_routing"]], "get_metric() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.get_metric"]], "get_params() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.get_params"]], "pair_distance() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.pair_distance"]], "pair_score() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.pair_score"]], "score_pairs() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.score_pairs"]], "set_fit_request() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.set_fit_request"]], "set_output() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.set_output"]], "set_params() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.set_params"]], "transform() (metric_learn.itml_supervised method)": [[7, "metric_learn.ITML_Supervised.transform"]], "lfda (class in metric_learn)": [[8, "metric_learn.LFDA"]], "__init__() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.__init__"]], "fit() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.fit"]], "fit_transform() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.get_metadata_routing"]], "get_metric() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.get_metric"]], "get_params() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.get_params"]], "pair_distance() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.pair_distance"]], "pair_score() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.pair_score"]], "score_pairs() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.score_pairs"]], "set_output() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.set_output"]], "set_params() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.set_params"]], "transform() (metric_learn.lfda method)": [[8, "metric_learn.LFDA.transform"]], "lmnn (class in metric_learn)": [[9, "metric_learn.LMNN"]], "__init__() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.__init__"]], "fit() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.fit"]], "fit_transform() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.get_metadata_routing"]], "get_metric() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.get_metric"]], "get_params() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.get_params"]], "pair_distance() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.pair_distance"]], "pair_score() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.pair_score"]], "score_pairs() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.score_pairs"]], "set_output() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.set_output"]], "set_params() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.set_params"]], "transform() (metric_learn.lmnn method)": [[9, "metric_learn.LMNN.transform"]], "lsml (class in metric_learn)": [[10, "metric_learn.LSML"]], "__init__() (metric_learn.lsml method)": [[10, "metric_learn.LSML.__init__"]], "classes_ (metric_learn.lsml attribute)": [[10, "metric_learn.LSML.classes_"]], "decision_function() (metric_learn.lsml method)": [[10, "metric_learn.LSML.decision_function"]], "fit() (metric_learn.lsml method)": [[10, "metric_learn.LSML.fit"]], "get_mahalanobis_matrix() (metric_learn.lsml method)": [[10, "metric_learn.LSML.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.lsml method)": [[10, "metric_learn.LSML.get_metadata_routing"]], "get_metric() (metric_learn.lsml method)": [[10, "metric_learn.LSML.get_metric"]], "get_params() (metric_learn.lsml method)": [[10, "metric_learn.LSML.get_params"]], "pair_distance() (metric_learn.lsml method)": [[10, "metric_learn.LSML.pair_distance"]], "pair_score() (metric_learn.lsml method)": [[10, "metric_learn.LSML.pair_score"]], "predict() (metric_learn.lsml method)": [[10, "metric_learn.LSML.predict"]], "score() (metric_learn.lsml method)": [[10, "metric_learn.LSML.score"]], "score_pairs() (metric_learn.lsml method)": [[10, "metric_learn.LSML.score_pairs"]], "set_decision_function_request() (metric_learn.lsml method)": [[10, "metric_learn.LSML.set_decision_function_request"]], "set_fit_request() (metric_learn.lsml method)": [[10, "metric_learn.LSML.set_fit_request"]], "set_params() (metric_learn.lsml method)": [[10, "metric_learn.LSML.set_params"]], "set_predict_request() (metric_learn.lsml method)": [[10, "metric_learn.LSML.set_predict_request"]], "set_score_request() (metric_learn.lsml method)": [[10, "metric_learn.LSML.set_score_request"]], "transform() (metric_learn.lsml method)": [[10, "metric_learn.LSML.transform"]], "lsml_supervised (class in metric_learn)": [[11, "metric_learn.LSML_Supervised"]], "__init__() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.__init__"]], "fit() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.fit"]], "fit_transform() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.get_metadata_routing"]], "get_metric() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.get_metric"]], "get_params() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.get_params"]], "pair_distance() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.pair_distance"]], "pair_score() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.pair_score"]], "score_pairs() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.score_pairs"]], "set_output() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.set_output"]], "set_params() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.set_params"]], "transform() (metric_learn.lsml_supervised method)": [[11, "metric_learn.LSML_Supervised.transform"]], "mlkr (class in metric_learn)": [[12, "metric_learn.MLKR"]], "__init__() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.__init__"]], "fit() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.fit"]], "fit_transform() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.get_metadata_routing"]], "get_metric() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.get_metric"]], "get_params() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.get_params"]], "pair_distance() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.pair_distance"]], "pair_score() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.pair_score"]], "score_pairs() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.score_pairs"]], "set_output() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.set_output"]], "set_params() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.set_params"]], "transform() (metric_learn.mlkr method)": [[12, "metric_learn.MLKR.transform"]], "mmc (class in metric_learn)": [[13, "metric_learn.MMC"]], "__init__() (metric_learn.mmc method)": [[13, "metric_learn.MMC.__init__"]], "calibrate_threshold() (metric_learn.mmc method)": [[13, "metric_learn.MMC.calibrate_threshold"]], "classes_ (metric_learn.mmc attribute)": [[13, "metric_learn.MMC.classes_"]], "decision_function() (metric_learn.mmc method)": [[13, "metric_learn.MMC.decision_function"]], "fit() (metric_learn.mmc method)": [[13, "metric_learn.MMC.fit"]], "get_mahalanobis_matrix() (metric_learn.mmc method)": [[13, "metric_learn.MMC.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.mmc method)": [[13, "metric_learn.MMC.get_metadata_routing"]], "get_metric() (metric_learn.mmc method)": [[13, "metric_learn.MMC.get_metric"]], "get_params() (metric_learn.mmc method)": [[13, "metric_learn.MMC.get_params"]], "pair_distance() (metric_learn.mmc method)": [[13, "metric_learn.MMC.pair_distance"]], "pair_score() (metric_learn.mmc method)": [[13, "metric_learn.MMC.pair_score"]], "predict() (metric_learn.mmc method)": [[13, "metric_learn.MMC.predict"]], "score() (metric_learn.mmc method)": [[13, "metric_learn.MMC.score"]], "score_pairs() (metric_learn.mmc method)": [[13, "metric_learn.MMC.score_pairs"]], "set_decision_function_request() (metric_learn.mmc method)": [[13, "metric_learn.MMC.set_decision_function_request"]], "set_fit_request() (metric_learn.mmc method)": [[13, "metric_learn.MMC.set_fit_request"]], "set_params() (metric_learn.mmc method)": [[13, "metric_learn.MMC.set_params"]], "set_predict_request() (metric_learn.mmc method)": [[13, "metric_learn.MMC.set_predict_request"]], "set_score_request() (metric_learn.mmc method)": [[13, "metric_learn.MMC.set_score_request"]], "set_threshold() (metric_learn.mmc method)": [[13, "metric_learn.MMC.set_threshold"]], "transform() (metric_learn.mmc method)": [[13, "metric_learn.MMC.transform"]], "mmc_supervised (class in metric_learn)": [[14, "metric_learn.MMC_Supervised"]], "__init__() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.__init__"]], "fit() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.fit"]], "fit_transform() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.get_metadata_routing"]], "get_metric() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.get_metric"]], "get_params() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.get_params"]], "pair_distance() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.pair_distance"]], "pair_score() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.pair_score"]], "score_pairs() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.score_pairs"]], "set_output() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.set_output"]], "set_params() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.set_params"]], "transform() (metric_learn.mmc_supervised method)": [[14, "metric_learn.MMC_Supervised.transform"]], "nca (class in metric_learn)": [[15, "metric_learn.NCA"]], "__init__() (metric_learn.nca method)": [[15, "metric_learn.NCA.__init__"]], "fit() (metric_learn.nca method)": [[15, "metric_learn.NCA.fit"]], "fit_transform() (metric_learn.nca method)": [[15, "metric_learn.NCA.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.nca method)": [[15, "metric_learn.NCA.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.nca method)": [[15, "metric_learn.NCA.get_metadata_routing"]], "get_metric() (metric_learn.nca method)": [[15, "metric_learn.NCA.get_metric"]], "get_params() (metric_learn.nca method)": [[15, "metric_learn.NCA.get_params"]], "pair_distance() (metric_learn.nca method)": [[15, "metric_learn.NCA.pair_distance"]], "pair_score() (metric_learn.nca method)": [[15, "metric_learn.NCA.pair_score"]], "score_pairs() (metric_learn.nca method)": [[15, "metric_learn.NCA.score_pairs"]], "set_output() (metric_learn.nca method)": [[15, "metric_learn.NCA.set_output"]], "set_params() (metric_learn.nca method)": [[15, "metric_learn.NCA.set_params"]], "transform() (metric_learn.nca method)": [[15, "metric_learn.NCA.transform"]], "rca (class in metric_learn)": [[16, "metric_learn.RCA"]], "__init__() (metric_learn.rca method)": [[16, "metric_learn.RCA.__init__"]], "fit() (metric_learn.rca method)": [[16, "metric_learn.RCA.fit"]], "fit_transform() (metric_learn.rca method)": [[16, "metric_learn.RCA.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.rca method)": [[16, "metric_learn.RCA.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.rca method)": [[16, "metric_learn.RCA.get_metadata_routing"]], "get_metric() (metric_learn.rca method)": [[16, "metric_learn.RCA.get_metric"]], "get_params() (metric_learn.rca method)": [[16, "metric_learn.RCA.get_params"]], "pair_distance() (metric_learn.rca method)": [[16, "metric_learn.RCA.pair_distance"]], "pair_score() (metric_learn.rca method)": [[16, "metric_learn.RCA.pair_score"]], "score_pairs() (metric_learn.rca method)": [[16, "metric_learn.RCA.score_pairs"]], "set_fit_request() (metric_learn.rca method)": [[16, "metric_learn.RCA.set_fit_request"]], "set_output() (metric_learn.rca method)": [[16, "metric_learn.RCA.set_output"]], "set_params() (metric_learn.rca method)": [[16, "metric_learn.RCA.set_params"]], "transform() (metric_learn.rca method)": [[16, "metric_learn.RCA.transform"]], "rca_supervised (class in metric_learn)": [[17, "metric_learn.RCA_Supervised"]], "__init__() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.__init__"]], "fit() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.fit"]], "fit_transform() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.get_metadata_routing"]], "get_metric() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.get_metric"]], "get_params() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.get_params"]], "pair_distance() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.pair_distance"]], "pair_score() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.pair_score"]], "score_pairs() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.score_pairs"]], "set_fit_request() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.set_fit_request"]], "set_output() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.set_output"]], "set_params() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.set_params"]], "transform() (metric_learn.rca_supervised method)": [[17, "metric_learn.RCA_Supervised.transform"]], "scml (class in metric_learn)": [[18, "metric_learn.SCML"]], "__init__() (metric_learn.scml method)": [[18, "metric_learn.SCML.__init__"]], "classes_ (metric_learn.scml attribute)": [[18, "metric_learn.SCML.classes_"]], "decision_function() (metric_learn.scml method)": [[18, "metric_learn.SCML.decision_function"]], "fit() (metric_learn.scml method)": [[18, "metric_learn.SCML.fit"]], "get_mahalanobis_matrix() (metric_learn.scml method)": [[18, "metric_learn.SCML.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.scml method)": [[18, "metric_learn.SCML.get_metadata_routing"]], "get_metric() (metric_learn.scml method)": [[18, "metric_learn.SCML.get_metric"]], "get_params() (metric_learn.scml method)": [[18, "metric_learn.SCML.get_params"]], "pair_distance() (metric_learn.scml method)": [[18, "metric_learn.SCML.pair_distance"]], "pair_score() (metric_learn.scml method)": [[18, "metric_learn.SCML.pair_score"]], "predict() (metric_learn.scml method)": [[18, "metric_learn.SCML.predict"]], "score() (metric_learn.scml method)": [[18, "metric_learn.SCML.score"]], "score_pairs() (metric_learn.scml method)": [[18, "metric_learn.SCML.score_pairs"]], "set_decision_function_request() (metric_learn.scml method)": [[18, "metric_learn.SCML.set_decision_function_request"]], "set_fit_request() (metric_learn.scml method)": [[18, "metric_learn.SCML.set_fit_request"]], "set_params() (metric_learn.scml method)": [[18, "metric_learn.SCML.set_params"]], "set_predict_request() (metric_learn.scml method)": [[18, "metric_learn.SCML.set_predict_request"]], "set_score_request() (metric_learn.scml method)": [[18, "metric_learn.SCML.set_score_request"]], "transform() (metric_learn.scml method)": [[18, "metric_learn.SCML.transform"]], "scml_supervised (class in metric_learn)": [[19, "metric_learn.SCML_Supervised"]], "__init__() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.__init__"]], "fit() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.fit"]], "fit_transform() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.get_metadata_routing"]], "get_metric() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.get_metric"]], "get_params() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.get_params"]], "pair_distance() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.pair_distance"]], "pair_score() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.pair_score"]], "score_pairs() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.score_pairs"]], "set_output() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.set_output"]], "set_params() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.set_params"]], "transform() (metric_learn.scml_supervised method)": [[19, "metric_learn.SCML_Supervised.transform"]], "sdml (class in metric_learn)": [[20, "metric_learn.SDML"]], "__init__() (metric_learn.sdml method)": [[20, "metric_learn.SDML.__init__"]], "calibrate_threshold() (metric_learn.sdml method)": [[20, "metric_learn.SDML.calibrate_threshold"]], "classes_ (metric_learn.sdml attribute)": [[20, "metric_learn.SDML.classes_"]], "decision_function() (metric_learn.sdml method)": [[20, "metric_learn.SDML.decision_function"]], "fit() (metric_learn.sdml method)": [[20, "metric_learn.SDML.fit"]], "get_mahalanobis_matrix() (metric_learn.sdml method)": [[20, "metric_learn.SDML.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.sdml method)": [[20, "metric_learn.SDML.get_metadata_routing"]], "get_metric() (metric_learn.sdml method)": [[20, "metric_learn.SDML.get_metric"]], "get_params() (metric_learn.sdml method)": [[20, "metric_learn.SDML.get_params"]], "pair_distance() (metric_learn.sdml method)": [[20, "metric_learn.SDML.pair_distance"]], "pair_score() (metric_learn.sdml method)": [[20, "metric_learn.SDML.pair_score"]], "predict() (metric_learn.sdml method)": [[20, "metric_learn.SDML.predict"]], "score() (metric_learn.sdml method)": [[20, "metric_learn.SDML.score"]], "score_pairs() (metric_learn.sdml method)": [[20, "metric_learn.SDML.score_pairs"]], "set_decision_function_request() (metric_learn.sdml method)": [[20, "metric_learn.SDML.set_decision_function_request"]], "set_fit_request() (metric_learn.sdml method)": [[20, "metric_learn.SDML.set_fit_request"]], "set_params() (metric_learn.sdml method)": [[20, "metric_learn.SDML.set_params"]], "set_predict_request() (metric_learn.sdml method)": [[20, "metric_learn.SDML.set_predict_request"]], "set_score_request() (metric_learn.sdml method)": [[20, "metric_learn.SDML.set_score_request"]], "set_threshold() (metric_learn.sdml method)": [[20, "metric_learn.SDML.set_threshold"]], "transform() (metric_learn.sdml method)": [[20, "metric_learn.SDML.transform"]], "sdml_supervised (class in metric_learn)": [[21, "metric_learn.SDML_Supervised"]], "__init__() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.__init__"]], "fit() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.fit"]], "fit_transform() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.fit_transform"]], "get_mahalanobis_matrix() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.get_metadata_routing"]], "get_metric() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.get_metric"]], "get_params() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.get_params"]], "pair_distance() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.pair_distance"]], "pair_score() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.pair_score"]], "score_pairs() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.score_pairs"]], "set_output() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.set_output"]], "set_params() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.set_params"]], "transform() (metric_learn.sdml_supervised method)": [[21, "metric_learn.SDML_Supervised.transform"]], "basemetriclearner (class in metric_learn.base_metric)": [[22, "metric_learn.base_metric.BaseMetricLearner"]], "__init__() (metric_learn.base_metric.basemetriclearner method)": [[22, "metric_learn.base_metric.BaseMetricLearner.__init__"]], "get_metadata_routing() (metric_learn.base_metric.basemetriclearner method)": [[22, "metric_learn.base_metric.BaseMetricLearner.get_metadata_routing"]], "get_metric() (metric_learn.base_metric.basemetriclearner method)": [[22, "metric_learn.base_metric.BaseMetricLearner.get_metric"]], "get_params() (metric_learn.base_metric.basemetriclearner method)": [[22, "metric_learn.base_metric.BaseMetricLearner.get_params"]], "pair_distance() (metric_learn.base_metric.basemetriclearner method)": [[22, "metric_learn.base_metric.BaseMetricLearner.pair_distance"]], "pair_score() (metric_learn.base_metric.basemetriclearner method)": [[22, "metric_learn.base_metric.BaseMetricLearner.pair_score"]], "score_pairs() (metric_learn.base_metric.basemetriclearner method)": [[22, "metric_learn.base_metric.BaseMetricLearner.score_pairs"]], "set_params() (metric_learn.base_metric.basemetriclearner method)": [[22, "metric_learn.base_metric.BaseMetricLearner.set_params"]], "mahalanobismixin (class in metric_learn.base_metric)": [[23, "metric_learn.base_metric.MahalanobisMixin"]], "__init__() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.__init__"]], "get_mahalanobis_matrix() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.get_mahalanobis_matrix"]], "get_metadata_routing() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.get_metadata_routing"]], "get_metric() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.get_metric"]], "get_params() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.get_params"]], "pair_distance() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.pair_distance"]], "pair_score() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.pair_score"]], "score_pairs() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.score_pairs"]], "set_params() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.set_params"]], "transform() (metric_learn.base_metric.mahalanobismixin method)": [[23, "metric_learn.base_metric.MahalanobisMixin.transform"]], "metrictransformer (class in metric_learn.base_metric)": [[24, "metric_learn.base_metric.MetricTransformer"]], "transform() (metric_learn.base_metric.metrictransformer method)": [[24, "metric_learn.base_metric.MetricTransformer.transform"]], "_pairsclassifiermixin (class in metric_learn.base_metric)": [[25, "metric_learn.base_metric._PairsClassifierMixin"]], "__init__() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.__init__"]], "calibrate_threshold() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.calibrate_threshold"]], "classes_ (metric_learn.base_metric._pairsclassifiermixin attribute)": [[25, "metric_learn.base_metric._PairsClassifierMixin.classes_"]], "decision_function() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.decision_function"]], "get_metadata_routing() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.get_metadata_routing"]], "get_metric() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.get_metric"]], "get_params() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.get_params"]], "pair_distance() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.pair_distance"]], "pair_score() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.pair_score"]], "predict() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.predict"]], "score() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.score"]], "score_pairs() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.score_pairs"]], "set_decision_function_request() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.set_decision_function_request"]], "set_params() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.set_params"]], "set_predict_request() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.set_predict_request"]], "set_score_request() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.set_score_request"]], "set_threshold() (metric_learn.base_metric._pairsclassifiermixin method)": [[25, "metric_learn.base_metric._PairsClassifierMixin.set_threshold"]], "_quadrupletsclassifiermixin (class in metric_learn.base_metric)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin"]], "__init__() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.__init__"]], "classes_ (metric_learn.base_metric._quadrupletsclassifiermixin attribute)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.classes_"]], "decision_function() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.decision_function"]], "get_metadata_routing() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.get_metadata_routing"]], "get_metric() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.get_metric"]], "get_params() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.get_params"]], "pair_distance() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.pair_distance"]], "pair_score() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.pair_score"]], "predict() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.predict"]], "score() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.score"]], "score_pairs() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.score_pairs"]], "set_decision_function_request() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.set_decision_function_request"]], "set_params() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.set_params"]], "set_predict_request() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.set_predict_request"]], "set_score_request() (metric_learn.base_metric._quadrupletsclassifiermixin method)": [[26, "metric_learn.base_metric._QuadrupletsClassifierMixin.set_score_request"]], "_tripletsclassifiermixin (class in metric_learn.base_metric)": [[27, "metric_learn.base_metric._TripletsClassifierMixin"]], "__init__() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.__init__"]], "classes_ (metric_learn.base_metric._tripletsclassifiermixin attribute)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.classes_"]], "decision_function() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.decision_function"]], "get_metadata_routing() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.get_metadata_routing"]], "get_metric() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.get_metric"]], "get_params() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.get_params"]], "pair_distance() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.pair_distance"]], "pair_score() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.pair_score"]], "predict() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.predict"]], "score() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.score"]], "score_pairs() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.score_pairs"]], "set_decision_function_request() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.set_decision_function_request"]], "set_params() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.set_params"]], "set_predict_request() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.set_predict_request"]], "set_score_request() (metric_learn.base_metric._tripletsclassifiermixin method)": [[27, "metric_learn.base_metric._TripletsClassifierMixin.set_score_request"]]}})
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 8d95aa1e..00000000
--- a/setup.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[bdist_wheel]
-universal = 1
-
-[metadata]
-description-file = README.rst
\ No newline at end of file
diff --git a/setup.py b/setup.py
deleted file mode 100755
index 1dcf10a1..00000000
--- a/setup.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-from setuptools import setup
-
-version = "0.1.0"
-setup(name='metric-learn',
- version=version,
- description='Python implementations of metric learning algorithms',
- author=['CJ Carey', 'Yuan Tang'],
- author_email='ccarey@cs.umass.edu',
- url='http://github.com/all-umass/metric-learn',
- license='MIT',
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'License :: OSI Approved :: MIT License',
- 'Programming Language :: Python',
- 'Operating System :: OS Independent',
- 'Intended Audience :: Science/Research',
- 'Topic :: Scientific/Engineering'
- ],
- packages=['metric_learn'],
- install_requires=[
- 'numpy',
- 'scipy',
- 'scikit-learn'
- ],
- extras_require=dict(
- docs=['sphinx', 'numpydoc'],
- demo=['matplotlib'],
- ),
- test_suite='test',
- keywords=[
- 'Metric Learning',
- 'Large Margin Nearest Neighbor',
- 'Information Theoretic Metric Learning',
- 'Sparse Determinant Metric Learning',
- 'Least Squares Metric Learning',
- 'Neighborhood Components Analysis'
- ])
diff --git a/supervised.html b/supervised.html
new file mode 100644
index 00000000..61913b4d
--- /dev/null
+++ b/supervised.html
@@ -0,0 +1,496 @@
+
+
+
+
+
+
+ Supervised metric learning algorithms take as inputs points X and target +labels y, and learn a distance matrix that make points from the same class +(for classification) or with close target value (for regression) close to each +other, and points from different classes or with distant target values far away +from each other.
+Supervised metric learning algorithms essentially use the same API as +scikit-learn.
+In order to train a model, you need two array-like objects, X and y. X +should be a 2D array-like of shape (n_samples, n_features), where +n_samples is the number of points of your dataset and n_features is the +number of attributes describing each point. y should be a 1D +array-like +of shape (n_samples,), containing for each point in X the class it +belongs to (or the value to regress for this sample, if you use MLKR for +instance).
+Here is an example of a dataset of two dogs and one +cat (the classes are ‘dog’ and ‘cat’) an animal being represented by +two numbers.
+>>> import numpy as np
+>>> X = np.array([[2.3, 3.6], [0.2, 0.5], [6.7, 2.1]])
+>>> y = np.array(['dog', 'cat', 'dog'])
+
Note
+You can also use a preprocessor instead of directly giving the inputs as +2D arrays. See the Preprocessor section for more details.
+The goal of supervised metric-learning algorithms is to transform +points in a new space, in which the distance between two points from the +same class will be small, and the distance between two points from different +classes will be large. To do so, we fit the metric learner (example: +NCA).
+>>> from metric_learn import NCA
+>>> nca = NCA(random_state=42)
+>>> nca.fit(X, y)
+NCA(init='auto', max_iter=100, n_components=None,
+ preprocessor=None, random_state=42, tol=None, verbose=False)
+
Now that the estimator is fitted, you can use it on new data for several +purposes.
+First, you can transform the data in the learned space, using transform: +Here we transform two points in the new embedding space.
+>>> X_new = np.array([[9.4, 4.1], [2.1, 4.4]])
+>>> nca.transform(X_new)
+array([[ 5.91884732, 10.25406973],
+ [ 3.1545886 , 6.80350083]])
+
Also, as explained before, our metric learners has learn a distance between +points. You can use this distance in two main ways:
+You can either return the distance between pairs of points using the +pair_distance function:
>>> nca.pair_distance([[[3.5, 3.6], [5.6, 2.4]], [[1.2, 4.2], [2.1, 6.4]], [[3.3, 7.8], [10.9, 0.1]]])
+array([0.49627072, 3.65287282, 6.06079877])
+
Or you can return a function that will return the distance (in the new +space) between two 1D arrays (the coordinates of the points in the original +space), similarly to distance functions in scipy.spatial.distance.
>>> metric_fun = nca.get_metric()
+>>> metric_fun([3.5, 3.6], [5.6, 2.4])
+0.4962707194621285
+
Alternatively, you can use pair_score to return the score between +pairs of points (the larger the score, the more similar the pair). +For Mahalanobis learners, it is equal to the opposite of the distance.
>>> score = nca.pair_score([[[3.5, 3.6], [5.6, 2.4]], [[1.2, 4.2], [2.1, 6.4]], [[3.3, 7.8], [10.9, 0.1]]])
+>>> score
+array([-0.49627072, -3.65287282, -6.06079877])
+
This is useful because pair_score matches the score semantic of +scikit-learn’s Classification metrics.
+Note
+If the metric learner that you use learns a Mahalanobis distance (like it is the case for all algorithms +currently in metric-learn), you can get the plain learned Mahalanobis +matrix using get_mahalanobis_matrix.
+>>> nca.get_mahalanobis_matrix()
+array([[0.43680409, 0.89169412],
+ [0.89169412, 1.9542479 ]])
+
All supervised algorithms are scikit-learn estimators +(sklearn.base.BaseEstimator) and transformers +(sklearn.base.TransformerMixin) so they are compatible with pipelines +(sklearn.pipeline.Pipeline) and +scikit-learn model selection routines +(sklearn.model_selection.cross_val_score, +sklearn.model_selection.GridSearchCV, etc). +You can also use some of the scoring functions from sklearn.metrics.
+LMNN
Large Margin Nearest Neighbor Metric Learning
+(LMNN
)
LMNN learns a Mahalanobis distance metric in the kNN classification +setting. The learned metric attempts to keep close k-nearest neighbors +from the same class, while keeping examples from different classes +separated by a large margin. This algorithm makes no assumptions about +the distribution of the data.
+The distance is learned by solving the following optimization problem:
+where \(\mathbf{x}_i\) is a data point, \(\mathbf{x}_j\) is one +of its k-nearest neighbors sharing the same label, and \(\mathbf{x}_l\) +are all the other instances within that region with different labels, +\(\eta_{ij}, y_{ij} \in \{0, 1\}\) are both the indicators, +\(\eta_{ij}\) represents \(\mathbf{x}_{j}\) is the k-nearest +neighbors (with same labels) of \(\mathbf{x}_{i}\), \(y_{ij}=0\) +indicates \(\mathbf{x}_{i}, \mathbf{x}_{j}\) belong to different classes, +\([\cdot]_+=\max(0, \cdot)\) is the Hinge loss.
+Example Code
+import numpy as np
+from metric_learn import LMNN
+from sklearn.datasets import load_iris
+
+iris_data = load_iris()
+X = iris_data['data']
+Y = iris_data['target']
+
+lmnn = LMNN(n_neighbors=5, learn_rate=1e-6)
+lmnn.fit(X, Y, verbose=False)
+
References
+[1]. Weinberger et al. Distance Metric Learning for Large Margin Nearest Neighbor Classification. JMLR 2009.
+ +NCA
Neighborhood Components Analysis (NCA
)
NCA is a distance metric learning algorithm which aims to improve the +accuracy of nearest neighbors classification compared to the standard +Euclidean distance. The algorithm directly maximizes a stochastic variant +of the leave-one-out k-nearest neighbors (KNN) score on the training set. +It can also learn a low-dimensional linear transformation of data that can +be used for data visualization and fast classification.
+They use the decomposition \(\mathbf{M} = \mathbf{L}^T\mathbf{L}\) and +define the probability \(p_{ij}\) that \(\mathbf{x}_i\) is the +neighbor of \(\mathbf{x}_j\) by calculating the softmax likelihood of +the Mahalanobis distance:
+Then the probability that \(\mathbf{x}_i\) will be correctly classified +by the stochastic nearest neighbors rule is:
+The optimization problem is to find matrix \(\mathbf{L}\) that maximizes +the sum of probability of being correctly classified:
+Example Code
+import numpy as np
+from metric_learn import NCA
+from sklearn.datasets import load_iris
+
+iris_data = load_iris()
+X = iris_data['data']
+Y = iris_data['target']
+
+nca = NCA(max_iter=1000)
+nca.fit(X, Y)
+
References
+[1]. Goldberger et al. Neighbourhood Components Analysis. NIPS 2005.
+ +LFDA
Local Fisher Discriminant Analysis (LFDA
)
LFDA is a linear supervised dimensionality reduction method which effectively combines the ideas of Linear Discriminant Analysis <https://en.wikipedia.org/wiki/Linear_discriminant_analysis> and Locality-Preserving Projection . It is +particularly useful when dealing with multi-modality, where one ore more classes +consist of separate clusters in input space. The core optimization problem of +LFDA is solved as a generalized eigenvalue problem.
+The algorithm define the Fisher local within-/between-class scatter matrix +\(\mathbf{S}^{(w)}/ \mathbf{S}^{(b)}\) in a pairwise fashion:
+where
+here \(\mathbf{A}_{i,j}\) is the \((i,j)\)-th entry of the affinity +matrix \(\mathbf{A}\):, which can be calculated with local scaling methods, n and n_l are the total number of points and the number of points per cluster l respectively.
+Then the learning problem becomes derive the LFDA transformation matrix +\(\mathbf{L}_{LFDA}\):
+That is, it is looking for a transformation matrix \(\mathbf{L}\) such that +nearby data pairs in the same class are made close and the data pairs in +different classes are separated from each other; far apart data pairs in the +same class are not imposed to be close.
+Example Code
+import numpy as np
+from metric_learn import LFDA
+from sklearn.datasets import load_iris
+
+iris_data = load_iris()
+X = iris_data['data']
+Y = iris_data['target']
+
+lfda = LFDA(k=2, dim=2)
+lfda.fit(X, Y)
+
Note
+LDFA suffers from a problem called “sign indeterminacy”, which means the sign of the components
and the output from transform depend on a random state. This is directly related to the calculation of eigenvectors in the algorithm. The same input ran in different times might lead to different transforms, but both valid.
To work around this, fit instances of this class to data once, then keep the instance around to do transformations.
+References
+[1]. Sugiyama. Dimensionality Reduction of Multimodal Labeled Data by Local Fisher Discriminant Analysis. JMLR 2007.
+[2]. Tang. Local Fisher Discriminant Analysis on Beer Style Clustering.
+MLKR
Metric Learning for Kernel Regression (MLKR
)
MLKR is an algorithm for supervised metric learning, which learns a +distance function by directly minimizing the leave-one-out regression error. +This algorithm can also be viewed as a supervised variation of PCA and can be +used for dimensionality reduction and high dimensional data visualization.
+Theoretically, MLKR can be applied with many types of kernel functions and +distance metrics, we hereafter focus the exposition on a particular instance +of the Gaussian kernel and Mahalanobis metric, as these are used in our +empirical development. The Gaussian kernel is denoted as:
+where \(d(\cdot, \cdot)\) is the squared distance under some metrics, +here in the fashion of Mahalanobis, it should be \(d(\mathbf{x}_i, +\mathbf{x}_j) = ||\mathbf{L}(\mathbf{x}_i - \mathbf{x}_j)||\), the transition +matrix \(\mathbf{L}\) is derived from the decomposition of Mahalanobis +matrix \(\mathbf{M=L^TL}\).
+Since \(\sigma^2\) can be integrated into \(d(\cdot)\), we can set +\(\sigma^2=1\) for the sake of simplicity. Here we use the cumulative +leave-one-out quadratic regression error of the training samples as the +loss function:
+where the prediction \(\hat{y}_i\) is derived from kernel regression by +calculating a weighted average of all the training samples:
+Example Code
+from metric_learn import MLKR
+from sklearn.datasets import load_iris
+
+iris_data = load_iris()
+X = iris_data['data']
+Y = iris_data['target']
+
+mlkr = MLKR()
+mlkr.fit(X, Y)
+
References
+[1]. Weinberger et al. Metric Learning for Kernel Regression. AISTATS 2007.
+Each weakly-supervised algorithm +has a supervised version of the form *_Supervised where similarity tuples are +randomly generated from the labels information and passed to the underlying +algorithm.
+Warning
+Supervised versions of weakly-supervised algorithms interpret label -1 +(or any negative label) as a point with unknown label. +Those points are discarded in the learning process.
+For pairs learners (see Learning on pairs), pairs (tuple of two points +from the dataset), and pair labels (int indicating whether the two points +are similar (+1) or dissimilar (-1)), are sampled with the function +metric_learn.constraints.positive_negative_pairs. To sample positive pairs +(of label +1), this method will look at all the samples from the same label and +sample randomly a pair among them. To sample negative pairs (of label -1), this +method will look at all the samples from a different class and sample randomly +a pair among them. The method will try to build n_constraints positive +pairs and n_constraints negative pairs, but sometimes it cannot find enough +of one of those, so forcing same_length=True will return both times the +minimum of the two lenghts.
+For using quadruplets learners (see Learning on quadruplets) in a +supervised way, positive and negative pairs are sampled as above and +concatenated so that we have a 3D array of +quadruplets, where for each quadruplet the two first points are from the same +class, and the two last points are from a different class (so indeed the two +last points should be less similar than the two first points).
+Example Code
+from metric_learn import MMC_Supervised
+from sklearn.datasets import load_iris
+
+iris_data = load_iris()
+X = iris_data['data']
+Y = iris_data['target']
+
+mmc = MMC_Supervised(n_constraints=200)
+mmc.fit(X, Y)
+
Unsupervised metric learning algorithms only take as input an (unlabeled) +dataset X. For now, in metric-learn, there only is Covariance, which is a +simple baseline algorithm (see below).
+Covariance does not “learn” anything, rather it calculates +the covariance matrix of the input data. This is a simple baseline method. +It can be used for ZCA whitening of the data (see the Wikipedia page of +whitening transformation).
+Example Code
+from metric_learn import Covariance
+from sklearn.datasets import load_iris
+
+iris = load_iris()['data']
+
+cov = Covariance().fit(iris)
+x = cov.transform(iris)
+
References
+[1]. On the Generalized Distance in Statistics, P.C.Mahalanobis, 1936.
+Weakly supervised algorithms work on weaker information about the data points +than supervised algorithms. Rather than labeled points, they take as input +similarity judgments on tuples of data points, for instance pairs of similar +and dissimilar points. Refer to the documentation of each algorithm for its +particular form of input data.
+In the following paragraph we talk about tuples for sake of generality. These +can be pairs, triplets, quadruplets etc, depending on the particular metric +learning algorithm we use.
+Every weakly supervised algorithm will take as input tuples of +points, and if needed labels for theses tuples. The tuples of points can +also be called “constraints”. They are a set of points that we consider (ex: +two points, three points, etc…). The label is some information we have +about this set of points (e.g. “these two points are similar”). Note that +some information can be contained in the ordering of these tuples (see for +instance the section Learning on quadruplets). For more details about +specific forms of tuples, refer to the appropriate sections +(Learning on pairs or Learning on quadruplets).
+The tuples argument is the first argument of every method (like the X +argument for classical algorithms in scikit-learn). The second argument is the +label of the tuple: its semantic depends on the algorithm used. For instance +for pairs learners y is a label indicating whether the pair is of similar +samples or dissimilar samples.
+Then one can fit a Weakly Supervised Metric Learner on this tuple, like this:
+>>> my_algo.fit(tuples, y)
+
Like in a classical setting we split the points X between train and test, +here we split the tuples between train and test.
+>>> from sklearn.model_selection import train_test_split
+>>> pairs_train, pairs_test, y_train, y_test = train_test_split(pairs, y)
+
These are two data structures that can be used to represent tuple in metric +learn:
+The most intuitive way to represent tuples is to provide the algorithm with a +3D array-like of tuples of shape (n_tuples, tuple_size, n_features), where +n_tuples is the number of tuples, tuple_size is the number of elements +in a tuple (2 for pairs, 3 for triplets for instance), and n_features is +the number of features of each point.
+Example Code
+Here is an artificial dataset of 4 pairs of 2 points of 3 features each:
+>>> import numpy as np
+>>> tuples = np.array([[[-0.12, -1.21, -0.20],
+>>> [+0.05, -0.19, -0.05]],
+>>>
+>>> [[-2.16, +0.11, -0.02],
+>>> [+1.58, +0.16, +0.93]],
+>>>
+>>> [[+1.58, +0.16, +0.93], # same as tuples[1, 1, :]
+>>> [+0.89, -0.34, +2.41]],
+>>>
+>>> [[-0.12, -1.21, -0.20], # same as tuples[0, 0, :]
+>>> [-2.16, +0.11, -0.02]]]) # same as tuples[1, 0, :]
+>>> y = np.array([-1, 1, 1, -1])
+
Warning
+This way of specifying pairs is not recommended for a large number +of tuples, as it is redundant (see the comments in the example) and hence +takes a lot of memory. Indeed each feature vector of a point will be +replicated as many times as a point is involved in a tuple. The second way +to specify pairs is more efficient
+Instead of forming each point in each tuple, a more efficient representation +would be to keep the dataset of points X aside, and just represent tuples +as a collection of tuples of indices from the points in X. Since we loose +the feature dimension there, the resulting array is 2D.
+Example Code
+An equivalent representation of the above pairs would be:
+>>> X = np.array([[-0.12, -1.21, -0.20],
+>>> [+0.05, -0.19, -0.05],
+>>> [-2.16, +0.11, -0.02],
+>>> [+1.58, +0.16, +0.93],
+>>> [+0.89, -0.34, +2.41]])
+>>>
+>>> tuples_indices = np.array([[0, 1],
+>>> [2, 3],
+>>> [3, 4],
+>>> [0, 2]])
+>>> y = np.array([-1, 1, 1, -1])
+
In order to fit metric learning algorithms with this type of input, we need to +give the original dataset of points X to the estimator so that it knows +the points the indices refer to. We do this when initializing the estimator, +through the argument preprocessor (see below Fit, transform, and so on)
+Note
+Instead of an array-like, you can give a callable in the argument +preprocessor, which will go fetch and form the tuples. This allows to +give more general indicators than just indices from an array (for instance +paths in the filesystem, name of records in a database etc…) See section +Preprocessor for more details on how to use the preprocessor.
+The goal of weakly-supervised metric-learning algorithms is to transform +points in a new space, in which the tuple-wise constraints between points +are respected.
+>>> from metric_learn import MMC
+>>> mmc = MMC(random_state=42)
+>>> mmc.fit(tuples, y)
+MMC(A0='deprecated', tol=0.001, diagonal=False,
+ diagonal_c=1.0, init='auto', max_iter=100, max_proj=10000,
+ preprocessor=None, random_state=42, verbose=False)
+
Or alternatively (using a preprocessor):
+>>> from metric_learn import MMC
+>>> mmc = MMC(preprocessor=X, random_state=42)
+>>> mmc.fit(pairs_indice, y)
+
Now that the estimator is fitted, you can use it on new data for several +purposes.
+First, you can transform the data in the learned space, using transform: +Here we transform two points in the new embedding space.
+>>> X_new = np.array([[9.4, 4.1, 4.2], [2.1, 4.4, 2.3]])
+>>> mmc.transform(X_new)
+array([[-3.24667162e+01, 4.62622348e-07, 3.88325421e-08],
+ [-3.61531114e+01, 4.86778289e-07, 2.12654397e-08]])
+
Also, as explained before, our metric learner has learned a distance between +points. You can use this distance in two main ways:
+You can either return the distance between pairs of points using the +pair_distance function:
>>> mmc.pair_distance([[[3.5, 3.6, 5.2], [5.6, 2.4, 6.7]],
+... [[1.2, 4.2, 7.7], [2.1, 6.4, 0.9]]])
+array([7.27607365, 0.88853014])
+
Or you can return a function that will return the distance +(in the new space) between two 1D arrays (the coordinates of the points in +the original space), similarly to distance functions in +scipy.spatial.distance. To do that, use the get_metric method.
>>> metric_fun = mmc.get_metric()
+>>> metric_fun([3.5, 3.6, 5.2], [5.6, 2.4, 6.7])
+7.276073646278203
+
Alternatively, you can use pair_score to return the score between +pairs of points (the larger the score, the more similar the pair). +For Mahalanobis learners, it is equal to the opposite of the distance.
>>> score = mmc.pair_score([[[3.5, 3.6], [5.6, 2.4]], [[1.2, 4.2], [2.1, 6.4]], [[3.3, 7.8], [10.9, 0.1]]])
+>>> score
+array([-0.49627072, -3.65287282, -6.06079877])
+
++This is useful because pair_score matches the score semantic of +scikit-learn’s Classification metrics.
+
Note
+If the metric learner that you use learns a Mahalanobis distance (like it is the case for all algorithms +currently in metric-learn), you can get the plain Mahalanobis matrix using +get_mahalanobis_matrix.
+>>> mmc.get_mahalanobis_matrix()
+array([[ 0.58603894, -5.69883982, -1.66614919],
+ [-5.69883982, 55.41743549, 16.20219519],
+ [-1.66614919, 16.20219519, 4.73697721]])
+
Since weakly supervised are also able, after being fitted, to predict for a +given tuple what is its label (for pairs) or ordering (for quadruplets). See +the appropriate section for more details, either this +one for pairs, or this one for quadruplets.
+They also implement a default scoring method, score, that can be +used to evaluate the performance of a metric-learner on a test dataset. See +the appropriate section for more details, either this +one for pairs, or this one +for quadruplets.
+Weakly supervised estimators are compatible with scikit-learn routines for +model selection (sklearn.model_selection.cross_val_score, +sklearn.model_selection.GridSearchCV, etc).
+Example:
+>>> from metric_learn import MMC
+>>> import numpy as np
+>>> from sklearn.datasets import load_iris
+>>> from sklearn.model_selection import cross_val_score
+>>> rng = np.random.RandomState(42)
+>>> X, _ = load_iris(return_X_y=True)
+>>> # let's sample 30 random pairs and labels of pairs
+>>> pairs_indices = rng.randint(X.shape[0], size=(30, 2))
+>>> y = 2 * rng.randint(2, size=30) - 1
+>>> mmc = MMC(preprocessor=X)
+>>> cross_val_score(mmc, pairs_indices, y)
+
Some metric learning algorithms learn on pairs of samples. In this case, one +should provide the algorithm with n_samples pairs of points, with a +corresponding target containing n_samples values being either +1 or -1. +These values indicate whether the given pairs are similar points or +dissimilar points.
+Here is an example for fitting on pairs (see Fit, transform, and so on for more details on +the input data format and how to fit, in the general case of learning on +tuples).
+>>> from metric_learn import MMC
+>>> pairs = np.array([[[1.2, 3.2], [2.3, 5.5]],
+>>> [[4.5, 2.3], [2.1, 2.3]]])
+>>> y_pairs = np.array([1, -1])
+>>> mmc = MMC(random_state=42)
+>>> mmc.fit(pairs, y_pairs)
+MMC(tol=0.001, diagonal=False,
+ diagonal_c=1.0, init='auto', max_iter=100, max_proj=10000, preprocessor=None,
+ random_state=42, verbose=False)
+
Here, we learned a metric that puts the two first points closer +together in the transformed space, and the two next points further away from +each other.
+When a pairs learner is fitted, it is also able to predict, for an unseen +pair, whether it is a pair of similar or dissimilar points.
+>>> mmc.predict([[[0.6, 1.6], [1.15, 2.75]],
+... [[3.2, 1.1], [5.4, 6.1]]])
+array([1, -1])
+
Predicting whether a new pair represents similar or dissimilar +samples requires to set a threshold on the learned distance, so that points +closer (in the learned space) than this threshold are predicted as similar, +and points further away are predicted as dissimilar. Several methods are +possible for this thresholding.
+Calibration at fit time: The threshold is set with calibrate_threshold +(see below) on the training set. You can specify the calibration +parameters directly +in the fit method with the threshold_params parameter (see the +documentation of the fit method of any metric learner that learns on pairs +of points for more information). Note that calibrating on the training set +may cause some overfitting. If you want to avoid that, calibrate the +threshold after fitting, on a validation set.
+>>> mmc.fit(pairs, y) # will fit the threshold automatically after fitting
+
Calibration on validation set: calling calibrate_threshold will +calibrate the threshold to achieve a particular score on a validation set, +the score being among the classical scores for classification (accuracy, f1 +score…).
+>>> mmc.calibrate_threshold(pairs, y)
+
Manual threshold: calling set_threshold will set the threshold to a +particular value.
+>>> mmc.set_threshold(0.4)
+
See also: sklearn.calibration.
+Pair metric learners can also return a decision_function for a set of pairs. +It is basically the “score” that will be thresholded to find the prediction +for the pair. This score corresponds to the opposite of the distance in the +new space (higher score means points are similar, and lower score dissimilar).
+>>> mmc.decision_function([[[0.6, 1.6], [1.15, 2.75]],
+... [[3.2, 1.1], [5.4, 6.1]]])
+array([-0.12811124, -0.74750256])
+
This allows to use common scoring functions for binary classification, like +sklearn.metrics.accuracy_score for instance, which +can be used inside cross-validation routines:
+>>> from sklearn.model_selection import cross_val_score
+>>> pairs_test = np.array([[[0.6, 1.6], [1.15, 2.75]],
+... [[3.2, 1.1], [5.4, 6.1]],
+... [[7.7, 5.6], [1.23, 8.4]]])
+>>> y_test = np.array([-1., 1., -1.])
+>>> cross_val_score(mmc, pairs_test, y_test, scoring='accuracy')
+array([1., 0., 1.])
+
Pairs learners also have a default score, which basically +returns the sklearn.metrics.roc_auc_score (which is threshold-independent).
+>>> pairs_test = np.array([[[0.6, 1.6], [1.15, 2.75]],
+... [[3.2, 1.1], [5.4, 6.1]],
+... [[7.7, 5.6], [1.23, 8.4]]])
+>>> y_test = np.array([1., -1., -1.])
+>>> mmc.score(pairs_test, y_test)
+1.0
+
Note
+See Fit, transform, and so on for more details on metric learners functions that are +not specific to learning on pairs, like transform, pair_distance, +pair_score, get_metric and get_mahalanobis_matrix.
+ITML
Information Theoretic Metric Learning (ITML
)
ITML minimizes the (differential) relative entropy, aka Kullback–Leibler +divergence, between two multivariate Gaussians subject to constraints on the +associated Mahalanobis distance, which can be formulated into a Bregman +optimization problem by minimizing the LogDet divergence subject to +linear constraints. This algorithm can handle a wide variety of constraints +and can optionally incorporate a prior on the distance function. Unlike some +other methods, ITML does not rely on an eigenvalue computation or +semi-definite programming.
+Given a Mahalanobis distance parameterized by \(M\), its corresponding +multivariate Gaussian is denoted as:
+where \(Z\) is the normalization constant, the inverse of Mahalanobis +matrix \(\mathbf{M}^{-1}\) is the covariance of the Gaussian.
+Given pairs of similar points \(S\) and pairs of dissimilar points +\(D\), the distance metric learning problem is to minimize the LogDet +divergence, which is equivalent as minimizing \(\textbf{KL}(p(\mathbf{x}; +\mathbf{M}_0) || p(\mathbf{x}; \mathbf{M}))\):
+where \(u\) and \(l\) is the upper and the lower bound of distance +for similar and dissimilar pairs respectively, and \(\mathbf{M}_0\) +is the prior distance metric, set to identity matrix by default, +\(D_{\ell \mathrm{d}}(\cdot)\) is the log determinant.
+Example Code
+from metric_learn import ITML
+
+pairs = [[[1.2, 7.5], [1.3, 1.5]],
+ [[6.4, 2.6], [6.2, 9.7]],
+ [[1.3, 4.5], [3.2, 4.6]],
+ [[6.2, 5.5], [5.4, 5.4]]]
+y = [1, 1, -1, -1]
+
+# in this task we want points where the first feature is close to be closer
+# to each other, no matter how close the second feature is
+
+
+itml = ITML()
+itml.fit(pairs, y)
+
References
+[1]. Jason V. Davis, et al. Information-theoretic Metric Learning. ICML 2007.
+[2]. Adapted from Matlab code at http://www.cs.utexas.edu/users/pjain/itml/ .
+SDML
Sparse High-Dimensional Metric Learning
+(SDML
)
SDML is an efficient sparse metric learning in high-dimensional space via +double regularization: an L1-penalization on the off-diagonal elements of the +Mahalanobis matrix \(\mathbf{M}\), and a log-determinant divergence between +\(\mathbf{M}\) and \(\mathbf{M_0}\) (set as either \(\mathbf{I}\) +or \(\mathbf{\Omega}^{-1}\), where \(\mathbf{\Omega}\) is the +covariance matrix).
+The formulated optimization on the semidefinite matrix \(\mathbf{M}\) +is convex:
+where \(\mathbf{X}=[\mathbf{x}_1, \mathbf{x}_2, ..., \mathbf{x}_n]\) is +the training data, the incidence matrix \(\mathbf{K}_{ij} = 1\) if +\((\mathbf{x}_i, \mathbf{x}_j)\) is a similar pair, otherwise -1. The +Laplacian matrix \(\mathbf{L}=\mathbf{D}-\mathbf{K}\) is calculated from +\(\mathbf{K}\) and \(\mathbf{D}\), a diagonal matrix whose entries are +the sums of the row elements of \(\mathbf{K}\)., \(||\cdot||_{1, off}\) +is the off-diagonal L1 norm.
+Example Code
+from metric_learn import SDML
+
+pairs = [[[1.2, 7.5], [1.3, 1.5]],
+ [[6.4, 2.6], [6.2, 9.7]],
+ [[1.3, 4.5], [3.2, 4.6]],
+ [[6.2, 5.5], [5.4, 5.4]]]
+y = [1, 1, -1, -1]
+
+# in this task we want points where the first feature is close to be closer
+# to each other, no matter how close the second feature is
+
+sdml = SDML()
+sdml.fit(pairs, y)
+
References
+[1]. Qi et al. An efficient sparse metric learning in high-dimensional space via L1-penalized log-determinant regularization. ICML 2009.
+[2]. Code adapted from https://gist.github.com/kcarnold/5439945 .
+RCA
Relative Components Analysis (RCA
)
RCA learns a full rank Mahalanobis distance metric based on a weighted sum of +in-chunklets covariance matrices. It applies a global linear transformation to +assign large weights to relevant dimensions and low weights to irrelevant +dimensions. Those relevant dimensions are estimated using “chunklets”, subsets +of points that are known to belong to the same class.
+For a training set with \(n\) training points in \(k\) chunklets, the +algorithm is efficient since it simply amounts to computing
+where chunklet \(j\) consists of \(\{\mathbf{x}_{ji}\}_{i=1}^{n_j}\) +with a mean \(\hat{m}_j\). The inverse of \(\mathbf{C}^{-1}\) is used +as the Mahalanobis matrix.
+Example Code
+from metric_learn import RCA
+
+X = [[-0.05, 3.0],[0.05, -3.0],
+ [0.1, -3.55],[-0.1, 3.55],
+ [-0.95, -0.05],[0.95, 0.05],
+ [0.4, 0.05],[-0.4, -0.05]]
+chunks = [0, 0, 1, 1, 2, 2, 3, 3]
+
+rca = RCA()
+rca.fit(X, chunks)
+
References
+[1]. Shental et al. Adjustment learning and relevant component analysis. ECCV 2002.
+[2]. Bar-Hillel et al. Learning distance functions using equivalence relations. ICML 2003.
+[3]. Bar-Hillel et al. Learning a Mahalanobis metric from equivalence constraints. JMLR 2005.
+MMC
Metric Learning with Application for Clustering with Side Information
+(MMC
)
MMC minimizes the sum of squared distances between similar points, while +enforcing the sum of distances between dissimilar ones to be greater than one. +This leads to a convex and, thus, local-minima-free optimization problem that +can be solved efficiently. +However, the algorithm involves the computation of eigenvalues, which is the +main speed-bottleneck. Since it has initially been designed for clustering +applications, one of the implicit assumptions of MMC is that all classes form +a compact set, i.e., follow a unimodal distribution, which restricts the +possible use-cases of this method. However, it is one of the earliest and a +still often cited technique.
+The algorithm aims at minimizing the sum of distances between all the similar +points, while constrains the sum of distances between dissimilar points:
+Example Code
+from metric_learn import MMC
+
+pairs = [[[1.2, 7.5], [1.3, 1.5]],
+ [[6.4, 2.6], [6.2, 9.7]],
+ [[1.3, 4.5], [3.2, 4.6]],
+ [[6.2, 5.5], [5.4, 5.4]]]
+y = [1, 1, -1, -1]
+
+# in this task we want points where the first feature is close to be closer
+# to each other, no matter how close the second feature is
+
+mmc = MMC()
+mmc.fit(pairs, y)
+
References
+[1]. Xing et al. Distance metric learning with application to clustering with side-information. NIPS 2002.
+[2]. Adapted from Matlab code http://www.cs.cmu.edu/%7Eepxing/papers/Old_papers/code_Metric_online.tar.gz .
+Some metric learning algorithms learn on triplets of samples. In this case, +one should provide the algorithm with n_samples triplets of points. The +semantic of each triplet is that the first point should be closer to the +second point than to the third one.
+Here is an example for fitting on triplets (see Fit, transform, and so on for more +details on the input data format and how to fit, in the general case of +learning on tuples).
+>>> from metric_learn import SCML
+>>> triplets = np.array([[[1.2, 3.2], [2.3, 5.5], [2.1, 0.6]],
+>>> [[4.5, 2.3], [2.1, 2.3], [7.3, 3.4]]])
+>>> scml = SCML(random_state=42)
+>>> scml.fit(triplets)
+SCML(beta=1e-5, B=None, max_iter=100000, verbose=False,
+ preprocessor=None, random_state=None)
+
Or alternatively (using a preprocessor):
+>>> X = np.array([[[1.2, 3.2],
+>>> [2.3, 5.5],
+>>> [2.1, 0.6],
+>>> [4.5, 2.3],
+>>> [2.1, 2.3],
+>>> [7.3, 3.4]])
+>>> triplets_indices = np.array([[0, 1, 2], [3, 4, 5]])
+>>> scml = SCML(preprocessor=X, random_state=42)
+>>> scml.fit(triplets_indices)
+SCML(beta=1e-5, B=None, max_iter=100000, verbose=False,
+ preprocessor=array([[1.2, 3.2],
+ [2.3, 5.5],
+ [2.4, 6.7],
+ [2.1, 0.6],
+ [4.5, 2.3],
+ [2.1, 2.3],
+ [0.6, 1.2],
+ [7.3, 3.4]]),
+ random_state=None)
+
Here, we want to learn a metric that, for each of the two +triplets, will make the first point closer to the +second point than to the third one.
+When a triplets learner is fitted, it is also able to predict, for an +upcoming triplet, whether the first point is closer to the second point +than to the third one (+1), or not (-1).
+>>> triplets_test = np.array(
+... [[[5.6, 5.3], [2.2, 2.1], [1.2, 3.4]],
+... [[6.0, 4.2], [4.3, 1.2], [0.1, 7.8]]])
+>>> scml.predict(triplets_test)
+array([-1., 1.])
+
Triplet metric learners can also return a decision_function for a set of triplets, +which corresponds to the distance between the first two points minus the distance +between the first and last points of the triplet (the higher the value, the more +similar the first point to the second point compared to the last one). This “score” +can be interpreted as a measure of likeliness of having a +1 prediction for this +triplet.
+>>> scml.decision_function(triplets_test)
+array([-1.75700306, 4.98982131])
+
In the above example, for the first triplet in triplets_test, the first +point is predicted less similar to the second point than to the last point +(they are further away in the transformed space).
+Unlike pairs learners, triplets learners do not allow to give a y when fitting: we +assume that the ordering of points within triplets is such that the training triplets +are all positive. Therefore, it is not possible to use scikit-learn scoring functions +(such as ‘f1_score’) for triplets learners.
+However, triplets learners do have a default scoring function, which will +basically return the accuracy score on a given test set, i.e. the proportion +of triplets that have the right predicted ordering.
+>>> scml.score(triplets_test)
+0.5
+
Note
+See Fit, transform, and so on for more details on metric learners functions that are +not specific to learning on pairs, like transform, pair_distance, +pair_score, get_metric and get_mahalanobis_matrix.
+SCML
Sparse Compositional Metric Learning
+(SCML
)
SCML learns a squared Mahalanobis distance from triplet constraints by +optimizing sparse positive weights assigned to a set of \(K\) rank-one +PSD bases. This can be formulated as an optimization problem with only +\(K\) parameters, that can be solved with an efficient stochastic +composite scheme.
+The Mahalanobis matrix \(M\) is built from a basis set \(B = \{b_i\}_{i=\{1,...,K\}}\) +weighted by a \(K\) dimensional vector \(w = \{w_i\}_{i=\{1,...,K\}}\) as:
+Learning \(M\) in this form makes it PSD by design, as it is a +nonnegative sum of PSD matrices. The basis set \(B\) is fixed in advance +and it is possible to construct it from the data. The optimization problem +over \(w\) is formulated as a classic margin-based hinge loss function +involving the set \(C\) of triplets. A regularization \(\ell_1\) +is added to yield a sparse combination. The formulation is the following:
+where \([\cdot]_+\) is the hinge loss.
+Example Code
+from metric_learn import SCML
+
+triplets = [[[1.2, 7.5], [1.3, 1.5], [6.2, 9.7]],
+ [[1.3, 4.5], [3.2, 4.6], [5.4, 5.4]],
+ [[3.2, 7.5], [3.3, 1.5], [8.2, 9.7]],
+ [[3.3, 4.5], [5.2, 4.6], [7.4, 5.4]]]
+
+scml = SCML()
+scml.fit(triplets)
+
References
+[1]. Y. Shi, A. Bellet and F. Sha. Sparse Compositional Metric Learning.. (AAAI), 2014.
+[2]. Adapted from original Matlab implementation..
+Some metric learning algorithms learn on quadruplets of samples. In this case, +one should provide the algorithm with n_samples quadruplets of points. The +semantic of each quadruplet is that the first two points should be closer +together than the last two points.
+Here is an example for fitting on quadruplets (see Fit, transform, and so on for more +details on the input data format and how to fit, in the general case of +learning on tuples).
+>>> from metric_learn import LSML
+>>> quadruplets = np.array([[[1.2, 3.2], [2.3, 5.5], [2.4, 6.7], [2.1, 0.6]],
+>>> [[4.5, 2.3], [2.1, 2.3], [0.6, 1.2], [7.3, 3.4]]])
+>>> lsml = LSML(random_state=42)
+>>> lsml.fit(quadruplets)
+LSML(max_iter=1000, preprocessor=None, prior=None, random_state=42, tol=0.001,
+ verbose=False)
+
Or alternatively (using a preprocessor):
+>>> X = np.array([[1.2, 3.2],
+>>> [2.3, 5.5],
+>>> [2.4, 6.7],
+>>> [2.1, 0.6],
+>>> [4.5, 2.3],
+>>> [2.1, 2.3],
+>>> [0.6, 1.2],
+>>> [7.3, 3.4]])
+>>> quadruplets_indices = np.array([[0, 1, 2, 3], [4, 5, 6, 7]])
+>>> lsml = LSML(preprocessor=X, random_state=42)
+>>> lsml.fit(quadruplets_indices)
+LSML(max_iter=1000,
+ preprocessor=array([[1.2, 3.2],
+ [2.3, 5.5],
+ [2.4, 6.7],
+ [2.1, 0.6],
+ [4.5, 2.3],
+ [2.1, 2.3],
+ [0.6, 1.2],
+ [7.3, 3.4]]),
+ prior=None, random_state=42, tol=0.001, verbose=False)
+
Here, we want to learn a metric that, for each of the two +quadruplets, will put the two first points closer together than the two +last points.
+When a quadruplets learner is fitted, it is also able to predict, for an +upcoming quadruplet, whether the two first points are more similar than the +two last points (+1), or not (-1).
+>>> quadruplets_test = np.array(
+... [[[5.6, 5.3], [2.2, 2.1], [0.4, 0.6], [1.2, 3.4]],
+... [[6.0, 4.2], [4.3, 1.2], [4.5, 0.6], [0.1, 7.8]]])
+>>> lsml.predict(quadruplets_test)
+array([-1., 1.])
+
Quadruplet metric learners can also return a decision_function for a set of +quadruplets, which corresponds to the distance between the first pair of points minus +the distance between the second pair of points of the triplet (the higher the value, +the more similar the first pair is than the last pair). +This “score” can be interpreted as a measure of likeliness of having a +1 prediction +for this quadruplet.
+>>> lsml.decision_function(quadruplets_test)
+array([-1.75700306, 4.98982131])
+
In the above example, for the first quadruplet in quadruplets_test, the +two first points are predicted less similar than the two last points (they +are further away in the transformed space).
+Like triplet learners, quadruplets learners do not allow to give a y when fitting: we +assume that the ordering of points within triplets is such that the training triplets +are all positive. Therefore, it is not possible to use scikit-learn scoring functions +(such as ‘f1_score’) for triplets learners.
+However, quadruplets learners do have a default scoring function, which will +basically return the accuracy score on a given test set, i.e. the proportion +of quadruplets have the right predicted ordering.
+>>> lsml.score(quadruplets_test)
+0.5
+
Note
+See Fit, transform, and so on for more details on metric learners functions that are +not specific to learning on pairs, like transform, pair_distance, +pair_score, get_metric and get_mahalanobis_matrix.
+LSML
Metric Learning from Relative Comparisons by Minimizing Squared Residual
+(LSML
)
LSML proposes a simple, yet effective, algorithm that minimizes a convex +objective function corresponding to the sum of squared residuals of +constraints. This algorithm uses the constraints in the form of the +relative distance comparisons, such method is especially useful where +pairwise constraints are not natural to obtain, thus pairwise constraints +based algorithms become infeasible to be deployed. Furthermore, its sparsity +extension leads to more stable estimation when the dimension is high and +only a small amount of constraints is given.
+The loss function of each constraint +\(d(\mathbf{x}_i, \mathbf{x}_j) < d(\mathbf{x}_k, \mathbf{x}_l)\) is +denoted as:
+where \(H(\cdot)\) is the squared Hinge loss function defined as:
+The summed loss function \(L(C)\) is the simple sum over all constraints +\(C = \{(\mathbf{x}_i , \mathbf{x}_j , \mathbf{x}_k , \mathbf{x}_l) +: d(\mathbf{x}_i , \mathbf{x}_j) < d(\mathbf{x}_k , \mathbf{x}_l)\}\). The +original paper suggested here should be a weighted sum since the confidence +or probability of each constraint might differ. However, for the sake of +simplicity and assumption of no extra knowledge provided, we just deploy +the simple sum here as well as what the authors did in the experiments.
+The distance metric learning problem becomes minimizing the summed loss +function of all constraints plus a regularization term w.r.t. the prior +knowledge:
+where \(\mathbf{M}_0\) is the prior metric matrix, set as identity +by default, \(D_{ld}(\mathbf{\cdot, \cdot})\) is the LogDet divergence:
+Example Code
+from metric_learn import LSML
+
+quadruplets = [[[1.2, 7.5], [1.3, 1.5], [6.4, 2.6], [6.2, 9.7]],
+ [[1.3, 4.5], [3.2, 4.6], [6.2, 5.5], [5.4, 5.4]],
+ [[3.2, 7.5], [3.3, 1.5], [8.4, 2.6], [8.2, 9.7]],
+ [[3.3, 4.5], [5.2, 4.6], [8.2, 5.5], [7.4, 5.4]]]
+
+# we want to make closer points where the first feature is close, and
+# further if the second feature is close
+
+lsml = LSML()
+lsml.fit(quadruplets)
+
References
+[1]. Liu et al. Metric Learning from Relative Comparisons by Minimizing Squared Residual. ICDM 2012.
+[2]. Code adapted from https://gist.github.com/kcarnold/5439917 .
+