Skip to content

Commit

Permalink
CircleCI update of dev docs (631).
Browse files Browse the repository at this point in the history
  • Loading branch information
Circle CI committed Jul 18, 2024
1 parent 11b8822 commit b0eca50
Show file tree
Hide file tree
Showing 47 changed files with 1,093 additions and 97 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n# Comparison of different DR methods and the use of affinity matcher\n\nWe illustrate the basic usage of TorchDR with different Neighbor Embedding methods\non the swiss roll dataset.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import torch\nimport matplotlib.pyplot as plt\nfrom sklearn.datasets import make_swiss_roll\n\nfrom torchdr import (\n AffinityMatcher,\n SNE,\n UMAP,\n TSNE,\n EntropicAffinity,\n NormalizedGaussianAffinity,\n)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load toy images\n\nFirst, let's load 5 classes of the digits dataset from sklearn.\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"torch.manual_seed(0)\nn_samples = 500\nX, t = make_swiss_roll(n_samples=n_samples, noise=0.1, random_state=0)\n\ninit_embedding = torch.normal(0, 1, size=(n_samples, 2), dtype=torch.double)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Compute the different embedding\n\nTune the different hyperparameters for better results.\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"perplexity = 30\nlr = 1e-1\noptim_params = {\n \"init\": init_embedding,\n \"early_exaggeration_iter\": 0,\n \"optimizer\": \"Adam\",\n \"optimizer_kwargs\": None,\n \"early_exaggeration\": 1.0,\n \"max_iter\": 100,\n}\n\nsne = SNE(n_components=2, perplexity=perplexity, lr=lr, **optim_params)\n\numap = UMAP(n_neighbors=perplexity, n_components=2, lr=lr, **optim_params)\n\ntsne = TSNE(n_components=2, perplexity=perplexity, lr=lr, **optim_params)\n\nall_methods = {\n \"TSNE\": tsne,\n \"SNE\": sne,\n \"UMAP\": umap,\n}\n\nfor method_name, method in all_methods.items():\n print(\"--- Computing {} ---\".format(method_name))\n method.fit(X)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Plot the different embeddings\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"fig = plt.figure(figsize=(15, 4))\nfs = 24\nax = fig.add_subplot(1, 4, 1, projection=\"3d\")\nax.scatter(X[:, 0], X[:, 1], X[:, 2], c=t, s=20)\nax.set_title(\"Swiss Roll in ambient space\", font=\"Times New Roman\", fontsize=fs)\nax.view_init(azim=-66, elev=12)\n\nfor i, (method_name, method) in enumerate(all_methods.items()):\n ax = fig.add_subplot(1, 4, i + 2)\n emb = method.embedding_.detach().numpy() # get the embedding\n ax.scatter(emb[:, 0], emb[:, 1], c=t, s=20)\n ax.set_title(\"{0}\".format(method_name), font=\"Times New Roman\", fontsize=fs)\n ax.set_xticks([])\n ax.set_yticks([])\nplt.tight_layout()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Using AffinityMatcher\n\nWe can reproduce the same kind of results using the\nflexible class AffinityMatcher\n:class:`torchdr.AffinityMatcher`. It take as input\ntwo affinities and minimize a certain matching loss\nbetween them. To reproduce the SNE algorithm\nwe can match with the cross entropy loss\nan EntropicAffinity\n:class:`torchdr.EntropicAffinity` with given\nperplexity and a NormalizedGaussianAffinity\n:class:`torchdr.NormalizedGaussianAffinity`.\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"sne_affinity_matcher = AffinityMatcher(\n n_components=2,\n # SNE matches an EntropicAffinity\n affinity_in=EntropicAffinity(perplexity=perplexity),\n # with a Gaussian kernel normalized by row\n affinity_out=NormalizedGaussianAffinity(normalization_dim=1),\n loss_fn=\"cross_entropy_loss\", # and the cross_entropy loss\n init=init_embedding,\n max_iter=200,\n lr=lr,\n)\nsne_affinity_matcher.fit(X)\n\nfig = plt.figure(figsize=(10, 4))\nfs = 24\ntwo_sne_dict = {\"SNE\": sne, \"SNE (with affinity matcher)\": sne_affinity_matcher}\nfor i, (method_name, method) in enumerate(two_sne_dict.items()):\n ax = fig.add_subplot(1, 2, i + 1)\n emb = method.embedding_.detach().numpy() # get the embedding\n ax.scatter(emb[:, 0], emb[:, 1], c=t, s=20)\n ax.set_title(\"{0}\".format(method_name), font=\"Times New Roman\", fontsize=fs)\n ax.set_xticks([])\n ax.set_yticks([])\nplt.tight_layout()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.14"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
r"""
Comparison of different DR methods and the use of affinity matcher
==================================================================
We illustrate the basic usage of TorchDR with different Neighbor Embedding methods
on the swiss roll dataset.
"""

# %%
import torch
import matplotlib.pyplot as plt
from sklearn.datasets import make_swiss_roll

from torchdr import (
AffinityMatcher,
SNE,
UMAP,
TSNE,
EntropicAffinity,
NormalizedGaussianAffinity,
)

# %%
# Load toy images
# ---------------
#
# First, let's load 5 classes of the digits dataset from sklearn.
torch.manual_seed(0)
n_samples = 500
X, t = make_swiss_roll(n_samples=n_samples, noise=0.1, random_state=0)

init_embedding = torch.normal(0, 1, size=(n_samples, 2), dtype=torch.double)
# %%
# Compute the different embedding
# -------------------------------
#
# Tune the different hyperparameters for better results.
perplexity = 30
lr = 1e-1
optim_params = {
"init": init_embedding,
"early_exaggeration_iter": 0,
"optimizer": "Adam",
"optimizer_kwargs": None,
"early_exaggeration": 1.0,
"max_iter": 100,
}

sne = SNE(n_components=2, perplexity=perplexity, lr=lr, **optim_params)

umap = UMAP(n_neighbors=perplexity, n_components=2, lr=lr, **optim_params)

tsne = TSNE(n_components=2, perplexity=perplexity, lr=lr, **optim_params)

all_methods = {
"TSNE": tsne,
"SNE": sne,
"UMAP": umap,
}

for method_name, method in all_methods.items():
print("--- Computing {} ---".format(method_name))
method.fit(X)

# %%
# Plot the different embeddings
# -----------------------------
fig = plt.figure(figsize=(15, 4))
fs = 24
ax = fig.add_subplot(1, 4, 1, projection="3d")
ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=t, s=20)
ax.set_title("Swiss Roll in ambient space", font="Times New Roman", fontsize=fs)
ax.view_init(azim=-66, elev=12)

for i, (method_name, method) in enumerate(all_methods.items()):
ax = fig.add_subplot(1, 4, i + 2)
emb = method.embedding_.detach().numpy() # get the embedding
ax.scatter(emb[:, 0], emb[:, 1], c=t, s=20)
ax.set_title("{0}".format(method_name), font="Times New Roman", fontsize=fs)
ax.set_xticks([])
ax.set_yticks([])
plt.tight_layout()
# %%
# Using AffinityMatcher
# -----------------------------
#
# We can reproduce the same kind of results using the
# flexible class AffinityMatcher
# :class:`torchdr.AffinityMatcher`. It take as input
# two affinities and minimize a certain matching loss
# between them. To reproduce the SNE algorithm
# we can match with the cross entropy loss
# an EntropicAffinity
# :class:`torchdr.EntropicAffinity` with given
# perplexity and a NormalizedGaussianAffinity
# :class:`torchdr.NormalizedGaussianAffinity`.

sne_affinity_matcher = AffinityMatcher(
n_components=2,
# SNE matches an EntropicAffinity
affinity_in=EntropicAffinity(perplexity=perplexity),
# with a Gaussian kernel normalized by row
affinity_out=NormalizedGaussianAffinity(normalization_dim=1),
loss_fn="cross_entropy_loss", # and the cross_entropy loss
init=init_embedding,
max_iter=200,
lr=lr,
)
sne_affinity_matcher.fit(X)

fig = plt.figure(figsize=(10, 4))
fs = 24
two_sne_dict = {"SNE": sne, "SNE (with affinity matcher)": sne_affinity_matcher}
for i, (method_name, method) in enumerate(two_sne_dict.items()):
ax = fig.add_subplot(1, 2, i + 1)
emb = method.embedding_.detach().numpy() # get the embedding
ax.scatter(emb[:, 0], emb[:, 1], c=t, s=20)
ax.set_title("{0}".format(method_name), font="Times New Roman", fontsize=fs)
ax.set_xticks([])
ax.set_yticks([])
plt.tight_layout()
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 24 additions & 13 deletions dev/_modules/torchdr/affinity/entropic.html
Original file line number Diff line number Diff line change
Expand Up @@ -913,11 +913,11 @@ <h1>Source code for torchdr.affinity.entropic</h1><div class="highlight"><pre>
<div class="viewcode-block" id="NormalizedGaussianAffinity">
<a class="viewcode-back" href="../../../gen_modules/torchdr.NormalizedGaussianAffinity.html#torchdr.NormalizedGaussianAffinity">[docs]</a>
<span class="k">class</span> <span class="nc">NormalizedGaussianAffinity</span><span class="p">(</span><span class="n">LogAffinity</span><span class="p">):</span>
<span class="w"> </span><span class="sa">r</span><span class="sd">&quot;&quot;&quot;Computes the Gaussian affinity matrix which can be normalized along a dimension.</span>
<span class="w"> </span><span class="sa">r</span><span class="sd">&quot;&quot;&quot;Compute the Gaussian affinity matrix which can be normalized along a dimension.</span>

<span class="sd"> The algorthm computes :math:`\exp( - \mathbf{C} / \sigma)`</span>
<span class="sd"> where : math: `\mathbf{C}` is the pairwise distance matrix and</span>
<span class="sd"> : math: `\sigma` is the bandwidth parameter. The affinity can be normalized</span>
<span class="sd"> where :math:`\mathbf{C}` is the pairwise distance matrix and</span>
<span class="sd"> :math:`\sigma` is the bandwidth parameter. The affinity can be normalized</span>
<span class="sd"> according to the specified normalization dimension.</span>

<span class="sd"> Parameters</span>
Expand Down Expand Up @@ -990,18 +990,24 @@ <h1>Source code for torchdr.affinity.entropic</h1><div class="highlight"><pre>



<div class="viewcode-block" id="NormalizedStudentAffinity">
<a class="viewcode-back" href="../../../gen_modules/torchdr.NormalizedStudentAffinity.html#torchdr.NormalizedStudentAffinity">[docs]</a>
<span class="k">class</span> <span class="nc">NormalizedStudentAffinity</span><span class="p">(</span><span class="n">LogAffinity</span><span class="p">):</span>
<span class="w"> </span><span class="sa">r</span><span class="sd">&quot;&quot;&quot;Computes the Student affinity matrix.</span>
<span class="w"> </span><span class="sa">r</span><span class="sd">&quot;&quot;&quot;Compute the Student affinity matrix which can be normalized along a dimension.</span>

<span class="sd"> The formula is given by :math:`(1 + \mathbf{C} / \sigma) ^ {-1}`</span>
<span class="sd"> where : math: `\mathbf{C}` is the pairwise distance matrix and</span>
<span class="sd"> : math: `\sigma` is the bandwidth parameter. The affinity can be normalized</span>
<span class="sd"> Its expression is given by:</span>

<span class="sd"> .. math::</span>
<span class="sd"> \left(1 + \frac{\mathbf{C}}{\nu}\right)^{-\frac{\nu + 1}{2}}</span>

<span class="sd"> where :math:`\nu &gt; 0` is the degrees of freedom parameter.</span>
<span class="sd"> The affinity can be normalized</span>
<span class="sd"> according to the specified normalization dimension.</span>

<span class="sd"> Parameters</span>
<span class="sd"> ----------</span>
<span class="sd"> sigma : float, optional</span>
<span class="sd"> Bandwidth parameter.</span>
<span class="sd"> degrees_of_freedom : int, optional</span>
<span class="sd"> Degrees of freedom for the Student-t distribution.</span>
<span class="sd"> metric : str, optional</span>
<span class="sd"> Metric to use for pairwise distances computation.</span>
<span class="sd"> zero_diag : bool, optional</span>
Expand All @@ -1018,7 +1024,7 @@ <h1>Source code for torchdr.affinity.entropic</h1><div class="highlight"><pre>

<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">sigma</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">,</span>
<span class="n">degrees_of_freedom</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">,</span>
<span class="n">metric</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">&quot;sqeuclidean&quot;</span><span class="p">,</span>
<span class="n">zero_diag</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
<span class="n">device</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">&quot;auto&quot;</span><span class="p">,</span>
Expand All @@ -1033,7 +1039,7 @@ <h1>Source code for torchdr.affinity.entropic</h1><div class="highlight"><pre>
<span class="n">keops</span><span class="o">=</span><span class="n">keops</span><span class="p">,</span>
<span class="n">verbose</span><span class="o">=</span><span class="n">verbose</span><span class="p">,</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sigma</span> <span class="o">=</span> <span class="n">sigma</span>
<span class="bp">self</span><span class="o">.</span><span class="n">degrees_of_freedom</span> <span class="o">=</span> <span class="n">degrees_of_freedom</span>
<span class="bp">self</span><span class="o">.</span><span class="n">normalization_dim</span> <span class="o">=</span> <span class="n">normalization_dim</span>

<span class="k">def</span> <span class="nf">_compute_log_affinity</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">:</span> <span class="n">torch</span><span class="o">.</span><span class="n">Tensor</span><span class="p">):</span>
Expand All @@ -1052,7 +1058,11 @@ <h1>Source code for torchdr.affinity.entropic</h1><div class="highlight"><pre>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">C</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_distance_matrix</span><span class="p">(</span><span class="n">X</span><span class="p">)</span>

<span class="n">log_affinity_matrix</span> <span class="o">=</span> <span class="o">-</span> <span class="n">torch</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">C</span><span class="o">/</span><span class="bp">self</span><span class="o">.</span><span class="n">sigma</span><span class="p">)</span>
<span class="n">log_affinity_matrix</span> <span class="o">=</span> <span class="p">(</span>
<span class="o">-</span><span class="mf">0.5</span>
<span class="o">*</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">degrees_of_freedom</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="o">*</span> <span class="p">(</span><span class="n">C</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">degrees_of_freedom</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">log</span><span class="p">()</span>
<span class="p">)</span>

<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">normalization_dim</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log_normalization_</span> <span class="o">=</span> <span class="n">logsumexp_red</span><span class="p">(</span>
Expand All @@ -1064,7 +1074,8 @@ <h1>Source code for torchdr.affinity.entropic</h1><div class="highlight"><pre>
<span class="n">n_samples_in</span> <span class="o">=</span> <span class="n">X</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">log_affinity_matrix</span> <span class="o">-=</span> <span class="n">math</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">n_samples_in</span><span class="p">)</span>

<span class="k">return</span> <span class="n">log_affinity_matrix</span>
<span class="k">return</span> <span class="n">log_affinity_matrix</span></div>

</pre></div>

</div>
Expand Down
3 changes: 2 additions & 1 deletion dev/_sources/all.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ Simple Affinities
StudentAffinity
ScalarProductAffinity
NormalizedGaussianAffinity

NormalizedStudentAffinity


Affinities Normalized by kNN Distances
"""""""""""""""""""""""""""""""""""""""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ This affinity is an important component of the **TSNE** algorithm.

.. rst-class:: sphx-glr-timing

**Total running time of the script:** (0 minutes 3.223 seconds)
**Total running time of the script:** (0 minutes 2.748 seconds)


.. _sphx_glr_download_auto_examples_affinities_demo_ea_adaptivity.py:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

Computation times
=================
**00:03.223** total execution time for 1 file **from auto_examples/affinities**:
**00:02.748** total execution time for 1 file **from auto_examples/affinities**:

.. container::

Expand All @@ -33,5 +33,5 @@ Computation times
- Time
- Mem (MB)
* - :ref:`sphx_glr_auto_examples_affinities_demo_ea_adaptivity.py` (``demo_ea_adaptivity.py``)
- 00:03.223
- 00:02.748
- 0.0
Loading

0 comments on commit b0eca50

Please sign in to comment.