TorchPairwise [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/inspiros/torchpairwise/build_wheels.yml)](https://github.com/inspiros/torchpairwise/actions) [![PyPI - Version](https://img.shields.io/pypi/v/torchpairwise)](https://pypi.org/project/torchpairwise/) [![Downloads](https://static.pepy.tech/badge/torchpairwise)](https://pepy.tech/project/torchpairwise) [![GitHub - License](https://img.shields.io/github/license/inspiros/torchpairwise)](LICENSE.txt)
======
This package provides highly-efficient pairwise metrics for **PyTorch**.
## News
- **v0.1.1:** Added **SNR** distance (``torchpairwise.snr_distances``) presented in https://arxiv.org/abs/1904.02616.
## Highlights
``torchpairwise`` is a collection of **general purpose** pairwise metric functions that behave similar to
``torch.cdist`` (which only implements $L_p$ distance).
Instead, we offer a lot more metrics ported from other packages such as
``scipy.spatial.distance`` and ``sklearn.metrics.pairwise``.
For task-specific metrics (e.g. for evaluation of classification, regression, clustering, ...), you should be in the
wrong place, please head to the [TorchMetrics](https://github.com/Lightning-AI/torchmetrics) repo.
Written in ``torch``'s C++ API, the main differences are that our metrics:
- are all (_except some boolean distances_) **differentiable** with backward formulas manually derived, implemented,
and verified with ``torch.autograd.gradcheck``.
- are **batched** and can exploit GPU parallelization.
- can be integrated seamlessly within **PyTorch**-based projects, all functions are ``torch.jit.script``-able.
### List of pairwise distance metrics
| ``torchpairwise`` ops | Equivalences in other libraries | Differentiable |
|:---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------:|
| ``euclidean_distances`` | [``sklearn.metrics.pairwise.euclidean_distances``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.euclidean_distances.html) | ✔️ |
| ``haversine_distances`` | [``sklearn.metrics.pairwise.haversine_distances``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.haversine_distances.html) | ✔️ |
| ``manhattan_distances`` | [``sklearn.metrics.pairwise.manhattan_distances``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.manhattan_distances.html) | ✔️ |
| ``cosine_distances`` | [``sklearn.metrics.pairwise.cosine_distances``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.cosine_distances.html) | ✔️ |
| ``l1_distances`` | _(Alias of ``manhattan_distances``)_ | ✔️ |
| ``l2_distances`` | _(Alias of ``euclidean_distances``)_ | ✔️ |
| ``lp_distances`` | _(Alias of ``minkowski_distances``)_ | ✔️ |
| ``linf_distances`` | _(Alias of ``chebyshev_distances``)_ | ✔️ |
| ``directed_hausdorff_distances`` | [``scipy.spatial.distance.directed_hausdorff``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.directed_hausdorff.html) [^1] | ✔️ |
| ``minkowski_distances`` | [``scipy.spatial.distance.minkowski``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html) [^1] | ✔️ |
| ``wminkowski_distances`` | [``scipy.spatial.distance.wminkowski``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.wminkowski.html) [^1] | ✔️ |
| ``sqeuclidean_distances`` | [``scipy.spatial.distance.sqeuclidean_distances``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.sqeuclidean_distances.html) [^1] | ✔️ |
| ``correlation_distances`` | [``scipy.spatial.distance.correlation``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.correlation.html) [^1] | ✔️ |
| ``hamming_distances`` | [``scipy.spatial.distance.hamming``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.hamming.html) [^1] | ❌[^2] |
| ``jaccard_distances`` | [``scipy.spatial.distance.jaccard``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.jaccard.html) [^1] | ❌[^2] |
| ``kulsinski_distances`` | [``scipy.spatial.distance.kulsinski``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.kulsinski.html) [^1] | ❌[^2] |
| ``kulczynski1_distances`` | [``scipy.spatial.distance.kulczynski1``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.kulczynski1.html) [^1] | ❌[^2] |
| ``seuclidean_distances`` | [``scipy.spatial.distance.seuclidean``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.seuclidean.html) [^1] | ✔️ |
| ``cityblock_distances`` | [``scipy.spatial.distance.cityblock``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cityblock.html) [^1] _(Alias of ``manhattan_distances``)_ | ✔️ |
| ``mahalanobis_distances`` | [``scipy.spatial.distance.mahalanobis``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.mahalanobis.html) [^1] | ✔️ |
| ``chebyshev_distances`` | [``scipy.spatial.distance.chebyshev``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.chebyshev.html) [^1] | ✔️ |
| ``braycurtis_distances`` | [``scipy.spatial.distance.braycurtis``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.braycurtis.html) [^1] | ✔️ |
| ``canberra_distances`` | [``scipy.spatial.distance.canberra``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.canberra.html) [^1] | ✔️ |
| ``jensenshannon_distances`` | [``scipy.spatial.distance.jensenshannon``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.jensenshannon.html) [^1] | ✔️ |
| ``yule_distances`` | [``scipy.spatial.distance.yule``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.yule.html) [^1] | ❌[^2] |
| ``dice_distances`` | [``scipy.spatial.distance.dice``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.dice.html) [^1] | ❌[^2] |
| ``rogerstanimoto_distances`` | [``scipy.spatial.distance.rogerstanimoto``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.rogerstanimoto.html) [^1] | ❌[^2] |
| ``russellrao_distances`` | [``scipy.spatial.distance.russellrao``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.russellrao.html) [^1] | ❌[^2] |
| ``sokalmichener_distances`` | [``scipy.spatial.distance.sokalmichener``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.sokalmichener.html) [^1] | ❌[^2] |
| ``sokalsneath_distances`` | [``scipy.spatial.distance.sokalsneath``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.sokalsneath.html) [^1] | ❌[^2] |
| ``snr_distances`` | [``pytorch_metric_learning.distances.SNRDistance``](https://kevinmusgrave.github.io/pytorch-metric-learning/distances/#snrdistance) [^1] | ✔️ |
[^1]: These metrics are not pairwise but a pairwise form can be computed by
calling ``scipy.spatial.distance.cdist(x1, x2, metric="[metric_name_or_callable]")``.
[^2]: These are boolean distances. ``hamming_distances`` can be applied for floating point inputs but involves
comparison.
### Other pairwise metrics or kernel functions
These metrics are usually used to compute kernel for machine learning algorithms.
| ``torchpairwise`` ops | Equivalences in other libraries | Differentiable |
|:-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------:|
| ``linear_kernel`` | [``sklearn.metrics.pairwise.linear_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.linear_kernel.html) | ✔️ |
| ``polynomial_kernel`` | [``sklearn.metrics.pairwise.polynomial_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.polynomial_kernel.html) | ✔️ |
| ``sigmoid_kernel`` | [``sklearn.metrics.pairwise.sigmoid_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.sigmoid_kernel.html) | ✔️ |
| ``rbf_kernel`` | [``sklearn.metrics.pairwise.rbf_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.rbf_kernel.html) | ✔️ |
| ``laplacian_kernel`` | [``sklearn.metrics.pairwise.laplacian_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.laplacian_kernel.html) | ✔️ |
| ``cosine_similarity`` | [``sklearn.metrics.pairwise.cosine_similarity``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.cosine_similarity.html) | ✔️ |
| ``additive_chi2_kernel`` | [``sklearn.metrics.pairwise.additive_chi2_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.additive_chi2_kernel.html) | ✔️ |
| ``chi2_kernel`` | [``sklearn.metrics.pairwise.chi2_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.chi2_kernel.html) | ✔️ |
### Custom ``cdist`` and ``pdist``
Furthermore, we provide a convenient wrapper function analoguous to ``torch.cdist`` excepts that it takes a string
``metric: str = "minkowski"`` indicating the desired metric to be used as the third argument,
and extra metric-specific arguments are passed as keywords.
```python
import torch, torchpairwise
# directed_hausdorff_distances is a pairwise 2d metric
x1 = torch.rand(10, 6, 3)
x2 = torch.rand(8, 5, 3)
generator = torch.Generator().manual_seed(1)
output = torchpairwise.cdist(x1, x2,
metric="directed_hausdorff",
shuffle=True, # kwargs exclusive to directed_hausdorff
generator=generator)
```
Note that pairwise metrics on the second table are currently not allowed keys for ``cdist``
because they are not _dist_.
We have a similar plan for ``pdist`` (which is equivalent to calling ``cdist(x1, x1)`` but avoid storing duplicated
positions).
However, that requires a total overhaul of existing C++/Cuda kernels and won't be available soon.
## Future Improvements
- Add more metrics (contact me or create a feature request issue).
- Add memory-efficient ``argkmin`` for retrieving pairwise neighbors' distances and indices without storing the whole
pairwise distance matrix.
- Add an equivalence of ``torch.pdist`` with ``metric: str = "minkowski"`` argument.
- (_Unlikely_) Support sparse layouts.
## Requirements
- `torch>=2.1.0` (`torch>=1.9.0` if compiled from source)
## Installation
#### From PyPI:
To install prebuilt wheels from [torchpairwise](https://pypi.org/project/torchpairwise), simply run:
```console
pip install torchpairwise
```
Note that the Linux and Windows wheels in **PyPI** are compiled with ``torch==2.1.0`` and **Cuda 12.1**.
We only do a non-strict version checking and a warning will be raised if ``torch``'s and ``torchpairwise``'s
Cuda versions do not match.
#### From Source:
Make sure your machine has a C++17 and a Cuda compiler installed, then clone the repo and run:
```console
pip install .
```
## Usage
The basic usecase is very straight-forward if you are familiar with
``sklearn.metrics.pairwise`` and ``scipy.spatial.distance``:
<table>
<tr>
<th>scikit-learn / SciPy</th>
<th>TorchPairwise</th>
</tr>
<tr>
<td>
<sub>
```python
import numpy as np
import sklearn.metrics.pairwise as sklearn_pairwise
x1 = np.random.rand(10, 5)
x2 = np.random.rand(12, 5)
output = sklearn_pairwise.cosine_similarity(x1, x2)
print(output)
```
</sub>
<td>
<sub>
```python
import torch
import torchpairwise
x1 = torch.rand(10, 5, device='cuda')
x2 = torch.rand(12, 5, device='cuda')
output = torchpairwise.cosine_similarity(x1, x2)
print(output)
```
</sub>
</td>
</tr>
<tr>
<td>
<sub>
```python
import numpy as np
import scipy.spatial.distance as distance
x1 = np.random.binomial(
1, p=0.6, size=(10, 5)).astype(np.bool_)
x2 = np.random.binomial(
1, p=0.7, size=(12, 5)).astype(np.bool_)
output = distance.cdist(x1, x2, metric='jaccard')
print(output)
```
</sub>
<td>
<sub>
```python
import torch
import torchpairwise
x1 = torch.bernoulli(
torch.full((10, 5), fill_value=0.6, device='cuda')).to(torch.bool)
x2 = torch.bernoulli(
torch.full((12, 5), fill_value=0.7, device='cuda')).to(torch.bool)
output = torchpairwise.jaccard_distances(x1, x2)
print(output)
```
</sub>
</td>
</tr>
</table>
Please check the [tests](tests) folder where we will add more examples.
## License
The code is released under the MIT license. See [`LICENSE.txt`](LICENSE.txt) for details.
Raw data
{
"_id": null,
"home_page": "https://github.com/inspiros/torchpairwise",
"name": "torchpairwise",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "pairwise_metric,pairwise_distance,kernel_function",
"author": "Hoang-Nhat Tran (inspiros)",
"author_email": "hnhat.tran@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/c3/a2/ab7a2ed4e179b681223ba43fb1cf4ab55b3970182f641ce49d4afe4a8594/torchpairwise-0.1.1.tar.gz",
"platform": null,
"description": "TorchPairwise [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/inspiros/torchpairwise/build_wheels.yml)](https://github.com/inspiros/torchpairwise/actions) [![PyPI - Version](https://img.shields.io/pypi/v/torchpairwise)](https://pypi.org/project/torchpairwise/) [![Downloads](https://static.pepy.tech/badge/torchpairwise)](https://pepy.tech/project/torchpairwise) [![GitHub - License](https://img.shields.io/github/license/inspiros/torchpairwise)](LICENSE.txt)\n======\n\nThis package provides highly-efficient pairwise metrics for **PyTorch**.\n\n## News\n- **v0.1.1:** Added **SNR** distance (``torchpairwise.snr_distances``) presented in https://arxiv.org/abs/1904.02616.\n\n## Highlights\n\n``torchpairwise`` is a collection of **general purpose** pairwise metric functions that behave similar to\n``torch.cdist`` (which only implements $L_p$ distance).\nInstead, we offer a lot more metrics ported from other packages such as\n``scipy.spatial.distance`` and ``sklearn.metrics.pairwise``.\nFor task-specific metrics (e.g. for evaluation of classification, regression, clustering, ...), you should be in the\nwrong place, please head to the [TorchMetrics](https://github.com/Lightning-AI/torchmetrics) repo.\n\nWritten in ``torch``'s C++ API, the main differences are that our metrics:\n\n- are all (_except some boolean distances_) **differentiable** with backward formulas manually derived, implemented,\n and verified with ``torch.autograd.gradcheck``.\n- are **batched** and can exploit GPU parallelization.\n- can be integrated seamlessly within **PyTorch**-based projects, all functions are ``torch.jit.script``-able.\n\n### List of pairwise distance metrics\n\n| ``torchpairwise`` ops | Equivalences in other libraries | Differentiable |\n|:---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------:|\n| ``euclidean_distances`` | [``sklearn.metrics.pairwise.euclidean_distances``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.euclidean_distances.html) | \u2714\ufe0f |\n| ``haversine_distances`` | [``sklearn.metrics.pairwise.haversine_distances``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.haversine_distances.html) | \u2714\ufe0f |\n| ``manhattan_distances`` | [``sklearn.metrics.pairwise.manhattan_distances``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.manhattan_distances.html) | \u2714\ufe0f |\n| ``cosine_distances`` | [``sklearn.metrics.pairwise.cosine_distances``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.cosine_distances.html) | \u2714\ufe0f |\n| ``l1_distances`` | _(Alias of ``manhattan_distances``)_ | \u2714\ufe0f |\n| ``l2_distances`` | _(Alias of ``euclidean_distances``)_ | \u2714\ufe0f |\n| ``lp_distances`` | _(Alias of ``minkowski_distances``)_ | \u2714\ufe0f |\n| ``linf_distances`` | _(Alias of ``chebyshev_distances``)_ | \u2714\ufe0f |\n| ``directed_hausdorff_distances`` | [``scipy.spatial.distance.directed_hausdorff``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.directed_hausdorff.html) [^1] | \u2714\ufe0f |\n| ``minkowski_distances`` | [``scipy.spatial.distance.minkowski``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html) [^1] | \u2714\ufe0f |\n| ``wminkowski_distances`` | [``scipy.spatial.distance.wminkowski``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.wminkowski.html) [^1] | \u2714\ufe0f |\n| ``sqeuclidean_distances`` | [``scipy.spatial.distance.sqeuclidean_distances``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.sqeuclidean_distances.html) [^1] | \u2714\ufe0f |\n| ``correlation_distances`` | [``scipy.spatial.distance.correlation``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.correlation.html) [^1] | \u2714\ufe0f |\n| ``hamming_distances`` | [``scipy.spatial.distance.hamming``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.hamming.html) [^1] | \u274c[^2] |\n| ``jaccard_distances`` | [``scipy.spatial.distance.jaccard``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.jaccard.html) [^1] | \u274c[^2] |\n| ``kulsinski_distances`` | [``scipy.spatial.distance.kulsinski``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.kulsinski.html) [^1] | \u274c[^2] |\n| ``kulczynski1_distances`` | [``scipy.spatial.distance.kulczynski1``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.kulczynski1.html) [^1] | \u274c[^2] |\n| ``seuclidean_distances`` | [``scipy.spatial.distance.seuclidean``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.seuclidean.html) [^1] | \u2714\ufe0f |\n| ``cityblock_distances`` | [``scipy.spatial.distance.cityblock``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cityblock.html) [^1] _(Alias of ``manhattan_distances``)_ | \u2714\ufe0f |\n| ``mahalanobis_distances`` | [``scipy.spatial.distance.mahalanobis``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.mahalanobis.html) [^1] | \u2714\ufe0f |\n| ``chebyshev_distances`` | [``scipy.spatial.distance.chebyshev``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.chebyshev.html) [^1] | \u2714\ufe0f |\n| ``braycurtis_distances`` | [``scipy.spatial.distance.braycurtis``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.braycurtis.html) [^1] | \u2714\ufe0f |\n| ``canberra_distances`` | [``scipy.spatial.distance.canberra``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.canberra.html) [^1] | \u2714\ufe0f |\n| ``jensenshannon_distances`` | [``scipy.spatial.distance.jensenshannon``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.jensenshannon.html) [^1] | \u2714\ufe0f |\n| ``yule_distances`` | [``scipy.spatial.distance.yule``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.yule.html) [^1] | \u274c[^2] |\n| ``dice_distances`` | [``scipy.spatial.distance.dice``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.dice.html) [^1] | \u274c[^2] |\n| ``rogerstanimoto_distances`` | [``scipy.spatial.distance.rogerstanimoto``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.rogerstanimoto.html) [^1] | \u274c[^2] |\n| ``russellrao_distances`` | [``scipy.spatial.distance.russellrao``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.russellrao.html) [^1] | \u274c[^2] |\n| ``sokalmichener_distances`` | [``scipy.spatial.distance.sokalmichener``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.sokalmichener.html) [^1] | \u274c[^2] |\n| ``sokalsneath_distances`` | [``scipy.spatial.distance.sokalsneath``](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.sokalsneath.html) [^1] | \u274c[^2] |\n| ``snr_distances`` | [``pytorch_metric_learning.distances.SNRDistance``](https://kevinmusgrave.github.io/pytorch-metric-learning/distances/#snrdistance) [^1] | \u2714\ufe0f |\n\n[^1]: These metrics are not pairwise but a pairwise form can be computed by\ncalling ``scipy.spatial.distance.cdist(x1, x2, metric=\"[metric_name_or_callable]\")``.\n\n[^2]: These are boolean distances. ``hamming_distances`` can be applied for floating point inputs but involves\ncomparison.\n\n### Other pairwise metrics or kernel functions\n\nThese metrics are usually used to compute kernel for machine learning algorithms.\n\n| ``torchpairwise`` ops | Equivalences in other libraries | Differentiable |\n|:-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------:|\n| ``linear_kernel`` | [``sklearn.metrics.pairwise.linear_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.linear_kernel.html) | \u2714\ufe0f |\n| ``polynomial_kernel`` | [``sklearn.metrics.pairwise.polynomial_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.polynomial_kernel.html) | \u2714\ufe0f |\n| ``sigmoid_kernel`` | [``sklearn.metrics.pairwise.sigmoid_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.sigmoid_kernel.html) | \u2714\ufe0f |\n| ``rbf_kernel`` | [``sklearn.metrics.pairwise.rbf_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.rbf_kernel.html) | \u2714\ufe0f |\n| ``laplacian_kernel`` | [``sklearn.metrics.pairwise.laplacian_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.laplacian_kernel.html) | \u2714\ufe0f |\n| ``cosine_similarity`` | [``sklearn.metrics.pairwise.cosine_similarity``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.cosine_similarity.html) | \u2714\ufe0f |\n| ``additive_chi2_kernel`` | [``sklearn.metrics.pairwise.additive_chi2_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.additive_chi2_kernel.html) | \u2714\ufe0f |\n| ``chi2_kernel`` | [``sklearn.metrics.pairwise.chi2_kernel``](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.chi2_kernel.html) | \u2714\ufe0f |\n\n### Custom ``cdist`` and ``pdist``\n\nFurthermore, we provide a convenient wrapper function analoguous to ``torch.cdist`` excepts that it takes a string\n``metric: str = \"minkowski\"`` indicating the desired metric to be used as the third argument,\nand extra metric-specific arguments are passed as keywords.\n\n```python\nimport torch, torchpairwise\n\n# directed_hausdorff_distances is a pairwise 2d metric\nx1 = torch.rand(10, 6, 3)\nx2 = torch.rand(8, 5, 3)\n\ngenerator = torch.Generator().manual_seed(1)\noutput = torchpairwise.cdist(x1, x2,\n metric=\"directed_hausdorff\",\n shuffle=True, # kwargs exclusive to directed_hausdorff\n generator=generator)\n```\n\nNote that pairwise metrics on the second table are currently not allowed keys for ``cdist``\nbecause they are not _dist_.\nWe have a similar plan for ``pdist`` (which is equivalent to calling ``cdist(x1, x1)`` but avoid storing duplicated\npositions).\nHowever, that requires a total overhaul of existing C++/Cuda kernels and won't be available soon.\n\n## Future Improvements\n\n- Add more metrics (contact me or create a feature request issue).\n- Add memory-efficient ``argkmin`` for retrieving pairwise neighbors' distances and indices without storing the whole\n pairwise distance matrix.\n- Add an equivalence of ``torch.pdist`` with ``metric: str = \"minkowski\"`` argument.\n- (_Unlikely_) Support sparse layouts.\n\n## Requirements\n\n- `torch>=2.1.0` (`torch>=1.9.0` if compiled from source)\n\n## Installation\n\n#### From PyPI:\n\nTo install prebuilt wheels from [torchpairwise](https://pypi.org/project/torchpairwise), simply run:\n\n```console\npip install torchpairwise\n```\n\nNote that the Linux and Windows wheels in **PyPI** are compiled with ``torch==2.1.0`` and **Cuda 12.1**.\nWe only do a non-strict version checking and a warning will be raised if ``torch``'s and ``torchpairwise``'s\nCuda versions do not match.\n\n#### From Source:\n\nMake sure your machine has a C++17 and a Cuda compiler installed, then clone the repo and run:\n\n```console\npip install .\n```\n\n## Usage\n\nThe basic usecase is very straight-forward if you are familiar with\n``sklearn.metrics.pairwise`` and ``scipy.spatial.distance``:\n\n<table>\n<tr>\n<th>scikit-learn / SciPy</th>\n<th>TorchPairwise</th>\n</tr>\n\n<tr>\n<td>\n<sub>\n\n```python\nimport numpy as np\nimport sklearn.metrics.pairwise as sklearn_pairwise\n\nx1 = np.random.rand(10, 5)\nx2 = np.random.rand(12, 5)\n\noutput = sklearn_pairwise.cosine_similarity(x1, x2)\nprint(output)\n```\n\n</sub>\n<td>\n<sub>\n\n```python\nimport torch\nimport torchpairwise\n\nx1 = torch.rand(10, 5, device='cuda')\nx2 = torch.rand(12, 5, device='cuda')\n\noutput = torchpairwise.cosine_similarity(x1, x2)\nprint(output)\n```\n\n</sub>\n</td>\n</tr>\n\n<tr>\n<td>\n<sub>\n\n```python\nimport numpy as np\nimport scipy.spatial.distance as distance\n\nx1 = np.random.binomial(\n 1, p=0.6, size=(10, 5)).astype(np.bool_)\nx2 = np.random.binomial(\n 1, p=0.7, size=(12, 5)).astype(np.bool_)\n\noutput = distance.cdist(x1, x2, metric='jaccard')\nprint(output)\n```\n\n</sub>\n<td>\n<sub>\n\n```python\nimport torch\nimport torchpairwise\n\nx1 = torch.bernoulli(\n torch.full((10, 5), fill_value=0.6, device='cuda')).to(torch.bool)\nx2 = torch.bernoulli(\n torch.full((12, 5), fill_value=0.7, device='cuda')).to(torch.bool)\n\noutput = torchpairwise.jaccard_distances(x1, x2)\nprint(output)\n```\n\n</sub>\n</td>\n</tr>\n\n</table>\n\nPlease check the [tests](tests) folder where we will add more examples.\n\n## License\n\nThe code is released under the MIT license. See [`LICENSE.txt`](LICENSE.txt) for details.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Pairwise Metrics for PyTorch",
"version": "0.1.1",
"project_urls": {
"Homepage": "https://github.com/inspiros/torchpairwise",
"Source": "https://github.com/inspiros/torchpairwise"
},
"split_keywords": [
"pairwise_metric",
"pairwise_distance",
"kernel_function"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "1b0ca7a41fc8d421f13062a0b413ced31ed4ce320e237301c2a8e478615876e7",
"md5": "430550290f199dc0bc19268458a9d677",
"sha256": "1d104d18e02c6a5fe11bdc6751cd0aac6c597287f5dbb3b4ab1a17f528dbbb2b"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp310-cp310-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "430550290f199dc0bc19268458a9d677",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.8",
"size": 757518,
"upload_time": "2023-10-16T10:15:36",
"upload_time_iso_8601": "2023-10-16T10:15:36.077607Z",
"url": "https://files.pythonhosted.org/packages/1b/0c/a7a41fc8d421f13062a0b413ced31ed4ce320e237301c2a8e478615876e7/torchpairwise-0.1.1-cp310-cp310-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5031f3777fec5a33481a487d11799370450766d9ba4d85f720e5aee3896dc9c6",
"md5": "c28887ba903236d37b5fe134e54624d4",
"sha256": "ecbbe463f184dee1fba97d5820cec6cf8397ea38420d7ab9328036e8c78f27a8"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "c28887ba903236d37b5fe134e54624d4",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.8",
"size": 45416291,
"upload_time": "2023-10-16T10:15:39",
"upload_time_iso_8601": "2023-10-16T10:15:39.069293Z",
"url": "https://files.pythonhosted.org/packages/50/31/f3777fec5a33481a487d11799370450766d9ba4d85f720e5aee3896dc9c6/torchpairwise-0.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "fc58fce93960091c4c77f4ea05e3b2b8201c70116d2edcaada5d104771db1027",
"md5": "967d4b565c94edc9b32248c2e21ced63",
"sha256": "29f6171a0650522864aae5701b9234156ad197938679c0ead54e07c1b2835c7b"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp310-cp310-win_amd64.whl",
"has_sig": false,
"md5_digest": "967d4b565c94edc9b32248c2e21ced63",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.8",
"size": 16449907,
"upload_time": "2023-10-16T10:15:43",
"upload_time_iso_8601": "2023-10-16T10:15:43.206707Z",
"url": "https://files.pythonhosted.org/packages/fc/58/fce93960091c4c77f4ea05e3b2b8201c70116d2edcaada5d104771db1027/torchpairwise-0.1.1-cp310-cp310-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "95bbf3033c06c24a1158f04ed38b6900c354259ccc4c5a5b8dd89dd49365cad0",
"md5": "4a75dce6adeb4c6f6fdba7f84e3ae437",
"sha256": "7bad619bd7888e1a8561758f981af1fa9f447fdf453378dcc227f1e206567de5"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp311-cp311-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "4a75dce6adeb4c6f6fdba7f84e3ae437",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.8",
"size": 757517,
"upload_time": "2023-10-16T10:15:45",
"upload_time_iso_8601": "2023-10-16T10:15:45.710166Z",
"url": "https://files.pythonhosted.org/packages/95/bb/f3033c06c24a1158f04ed38b6900c354259ccc4c5a5b8dd89dd49365cad0/torchpairwise-0.1.1-cp311-cp311-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "24dfa68ee15e46d590872d3e7f2cb1cddcb04abdc79fc5438946a5cb352a11ed",
"md5": "edefe85482e8a6dc2bdc03880aa539cf",
"sha256": "62a45a155a56e2f46e89ac1870dae7ce87102f421c84d0ea0a2df2af6c2afd4f"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "edefe85482e8a6dc2bdc03880aa539cf",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.8",
"size": 45417416,
"upload_time": "2023-10-16T10:15:48",
"upload_time_iso_8601": "2023-10-16T10:15:48.777033Z",
"url": "https://files.pythonhosted.org/packages/24/df/a68ee15e46d590872d3e7f2cb1cddcb04abdc79fc5438946a5cb352a11ed/torchpairwise-0.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "214afd642ef680974691b3dbe4d2a8f2a906b074fabe1fd16dc5f77e6219e785",
"md5": "f216630e014f077ca307b290cb99cecb",
"sha256": "26a555ac644f45db2928fc3e3c685cf3bc379910cf524276656b576877c98d08"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp311-cp311-win_amd64.whl",
"has_sig": false,
"md5_digest": "f216630e014f077ca307b290cb99cecb",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.8",
"size": 16449656,
"upload_time": "2023-10-16T10:15:52",
"upload_time_iso_8601": "2023-10-16T10:15:52.393278Z",
"url": "https://files.pythonhosted.org/packages/21/4a/fd642ef680974691b3dbe4d2a8f2a906b074fabe1fd16dc5f77e6219e785/torchpairwise-0.1.1-cp311-cp311-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4ac6e604bfb200cf064eef4de6cf9872c3e7a1195e75829aa94ca7606cf93274",
"md5": "c1caa28c8f0a7238f0dd22d29f395466",
"sha256": "416d46a1b1e615d0fe31dfafadcec72cc8b4a2834ac9833288214870ba3ef1ba"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp38-cp38-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "c1caa28c8f0a7238f0dd22d29f395466",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 757492,
"upload_time": "2023-10-16T10:15:55",
"upload_time_iso_8601": "2023-10-16T10:15:55.044677Z",
"url": "https://files.pythonhosted.org/packages/4a/c6/e604bfb200cf064eef4de6cf9872c3e7a1195e75829aa94ca7606cf93274/torchpairwise-0.1.1-cp38-cp38-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8353f174de1762dfe70b3df61b5f3c08f2f62fcbee1ddb794cb5ae9b056729aa",
"md5": "c246a1c18eb3d049d0f7a10fb64f9cd5",
"sha256": "32fcb746485e4d139bd2b92fd3184287db0cb8421109ffe9e9c7285abf35bf28"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "c246a1c18eb3d049d0f7a10fb64f9cd5",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 45416137,
"upload_time": "2023-10-16T10:15:57",
"upload_time_iso_8601": "2023-10-16T10:15:57.442186Z",
"url": "https://files.pythonhosted.org/packages/83/53/f174de1762dfe70b3df61b5f3c08f2f62fcbee1ddb794cb5ae9b056729aa/torchpairwise-0.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "834d1505accd1b931edac22b68047865b121135ecc83b341a06b73914be90504",
"md5": "6a10cd26152598ee2ee3a922546dcdd0",
"sha256": "42cac2c1b73496c7b7349197a68a52a3e36037f9ed20d4d0ab81ef8f19ef1e8a"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp38-cp38-win_amd64.whl",
"has_sig": false,
"md5_digest": "6a10cd26152598ee2ee3a922546dcdd0",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 16450327,
"upload_time": "2023-10-16T10:16:01",
"upload_time_iso_8601": "2023-10-16T10:16:01.492384Z",
"url": "https://files.pythonhosted.org/packages/83/4d/1505accd1b931edac22b68047865b121135ecc83b341a06b73914be90504/torchpairwise-0.1.1-cp38-cp38-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5e1825ba537df84b37b068bcd0c17d8b8fdf6fdf4a3876fe6bcf43522cc66d25",
"md5": "b2575eee3330adfdf3e0aa84979ad90e",
"sha256": "a568f0e7facb6c4034422f732d2a535563e78b43c4d292dbe5c964af6498b120"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp39-cp39-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "b2575eee3330adfdf3e0aa84979ad90e",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.8",
"size": 757493,
"upload_time": "2023-10-16T10:16:03",
"upload_time_iso_8601": "2023-10-16T10:16:03.996438Z",
"url": "https://files.pythonhosted.org/packages/5e/18/25ba537df84b37b068bcd0c17d8b8fdf6fdf4a3876fe6bcf43522cc66d25/torchpairwise-0.1.1-cp39-cp39-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "bf2f00b28d4fe8a6297aca6e14cc9a96a0a37c7b46bd9b5f0f2a3e3cb2f694ee",
"md5": "f8408827fdc4f7b1f7f614a2c455bc01",
"sha256": "dd8c18c39b1d1301fd54fdb306b90e37dda6680441a8d5340b00501067762658"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "f8408827fdc4f7b1f7f614a2c455bc01",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.8",
"size": 45416786,
"upload_time": "2023-10-16T10:16:06",
"upload_time_iso_8601": "2023-10-16T10:16:06.835622Z",
"url": "https://files.pythonhosted.org/packages/bf/2f/00b28d4fe8a6297aca6e14cc9a96a0a37c7b46bd9b5f0f2a3e3cb2f694ee/torchpairwise-0.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7601136fbac0c6af1680c36d0fd8b3520d5de9c253cffff68a10cc962e107180",
"md5": "d3a9637d3a800807643f019498f5ef7b",
"sha256": "905cc6671cdd3641316d00a7c40c25d22988e49ec57a96a1236d16903ecc2038"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1-cp39-cp39-win_amd64.whl",
"has_sig": false,
"md5_digest": "d3a9637d3a800807643f019498f5ef7b",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.8",
"size": 16450062,
"upload_time": "2023-10-16T10:16:11",
"upload_time_iso_8601": "2023-10-16T10:16:11.034053Z",
"url": "https://files.pythonhosted.org/packages/76/01/136fbac0c6af1680c36d0fd8b3520d5de9c253cffff68a10cc962e107180/torchpairwise-0.1.1-cp39-cp39-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c3a2ab7a2ed4e179b681223ba43fb1cf4ab55b3970182f641ce49d4afe4a8594",
"md5": "e8e3bd32d6a0fcf5828592851ba5365e",
"sha256": "ee8a766e361ec5364df84160748debd1da4c9ec9408d4a6b74060bfeeda78b8a"
},
"downloads": -1,
"filename": "torchpairwise-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "e8e3bd32d6a0fcf5828592851ba5365e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 50444,
"upload_time": "2023-10-16T10:16:13",
"upload_time_iso_8601": "2023-10-16T10:16:13.263726Z",
"url": "https://files.pythonhosted.org/packages/c3/a2/ab7a2ed4e179b681223ba43fb1cf4ab55b3970182f641ce49d4afe4a8594/torchpairwise-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-10-16 10:16:13",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "inspiros",
"github_project": "torchpairwise",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "torchpairwise"
}