.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/plot_rdr_1d.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_plot_rdr_1d.py: ========================================= Relative density ratio for 1D Gaussians ========================================= This notebook-style example follows the one-dimensional mean-shift experiment from the original RDR repository. We compare .. math:: p=\mathcal N(0,1), \qquad q=\mathcal N(1,1) and estimate .. math:: r(x)=\frac{2p(x)}{p(x)+q(x)}. The Gaussian densities are known, so the learned curve can be compared with the exact RDR. Values above one favor the real distribution ``p`` and values below one favor the generated distribution ``q``. .. GENERATED FROM PYTHON SOURCE LINES 20-24 Author: RDR contributors %% Imports and reproducibility --------------------------- .. GENERATED FROM PYTHON SOURCE LINES 24-35 .. code-block:: Python import numpy as np import matplotlib.pyplot as plt import torch from rdr import Divergence, RDRTrainer SEED = 123 np.random.seed(SEED) torch.manual_seed(SEED) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 36-38 Generate real and generated samples ----------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 38-66 .. code-block:: Python n_real, n_generated = 2_000, 1_600 generated_mean = 1.0 x_real = torch.randn(n_real, 1) x_generated = torch.randn(n_generated, 1) + generated_mean grid = torch.linspace(-4.0, 5.0, 500).reshape(-1, 1) def normal_pdf(x, mean=0.0, std=1.0): return torch.exp(-0.5 * ((x - mean) / std) ** 2) / ( std * torch.sqrt(torch.tensor(2.0 * torch.pi)) ) p_grid = normal_pdf(grid, mean=0.0) q_grid = normal_pdf(grid, mean=generated_mean) true_rdr = 2.0 * p_grid / (p_grid + q_grid) fig, ax = plt.subplots(figsize=(6.4, 3.2)) ax.hist(x_real.numpy(), bins=60, density=True, alpha=0.35, label="real samples $p$") ax.hist(x_generated.numpy(), bins=60, density=True, alpha=0.35, label="generated samples $q$") ax.plot(grid, p_grid, linewidth=2) ax.plot(grid, q_grid, linewidth=2) ax.set(title="One-dimensional mean shift", xlabel="$x$", ylabel="density") ax.legend() fig.tight_layout() .. image-sg:: /auto_examples/images/sphx_glr_plot_rdr_1d_001.png :alt: One-dimensional mean shift :srcset: /auto_examples/images/sphx_glr_plot_rdr_1d_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 67-71 Define the ratio network ------------------------ The final line contains the *only* output sigmoid. The trainer consumes and returns this already-bounded ratio without applying another activation. .. GENERATED FROM PYTHON SOURCE LINES 71-86 .. code-block:: Python class RatioNet1D(torch.nn.Module): def __init__(self): super().__init__() self.body = torch.nn.Sequential( torch.nn.Linear(1, 32), torch.nn.Tanh(), torch.nn.Linear(32, 32), torch.nn.Tanh(), torch.nn.Linear(32, 1), ) def forward(self, x): return 2.0 * torch.sigmoid(self.body(x)) .. GENERATED FROM PYTHON SOURCE LINES 87-89 Fit the RDR estimator --------------------- .. GENERATED FROM PYTHON SOURCE LINES 89-122 .. code-block:: Python trainer = RDRTrainer( RatioNet1D(), divergence=Divergence.HELLINGER, lr=1e-3, weight_decay=0.0, device="cpu", ) _, losses = trainer.fit( x_real, x_generated, num_epochs=500, batch_size=256, validation_fraction=0.2, test_fraction=0.1, split_seed=SEED, early_stopping_patience=25, early_stopping_start=50, min_delta=1e-5, restore_best=True, verbose=False, ) fig, ax = plt.subplots(figsize=(6.4, 3.0)) ax.plot(losses, label="training") ax.plot(trainer.validation_history, label="validation") if trainer.best_epoch is not None: ax.axvline(trainer.best_epoch, color="0.4", linestyle=":", label="best epoch") ax.set(title="RDR training", xlabel="epoch", ylabel="Hellinger objective") ax.legend() ax.grid(alpha=0.25) fig.tight_layout() .. image-sg:: /auto_examples/images/sphx_glr_plot_rdr_1d_002.png :alt: RDR training :srcset: /auto_examples/images/sphx_glr_plot_rdr_1d_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 123-125 Compare the exact and estimated ratios -------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 125-144 .. code-block:: Python estimated_rdr = trainer.score(grid).cpu().reshape(-1, 1) mae = torch.mean(torch.abs(estimated_rdr - true_rdr)).item() fig, ax = plt.subplots(figsize=(6.4, 3.4)) ax.plot(grid, true_rdr, "k--", linewidth=2.2, label="exact $r(x)$") ax.plot(grid, estimated_rdr, linewidth=2.2, label="estimated $r(x)$") ax.axhline(1.0, color="0.5", linestyle=":", label="equal support") ax.set( xlabel="$x$", ylabel="$r(x)$", ylim=(-0.05, 2.05), title=f"RDR estimate (grid MAE={mae:.3f}, test loss={trainer.test_loss:.3f})", ) ax.legend() ax.grid(alpha=0.2) fig.tight_layout() plt.show() .. image-sg:: /auto_examples/images/sphx_glr_plot_rdr_1d_003.png :alt: RDR estimate (grid MAE=0.090, test loss=-0.048) :srcset: /auto_examples/images/sphx_glr_plot_rdr_1d_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 4.071 seconds) .. _sphx_glr_download_auto_examples_plot_rdr_1d.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_rdr_1d.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_rdr_1d.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_rdr_1d.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_