{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Initialization Schemes for Input Convex Neural Network" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As input convex neural networks (ICNN) are notoriously difficult to train , Bunne et al. propose to use closed-form solutions between Gaussian approximations to derive relevant parameter initializations for ICNNs: given two measures $\\mu$ and $\\nu$, one can initialize ICNN parameters so that they are (initially) meaningful in the context of OT, namely that its gradient is able to approximately map source measure $\\mu$ into a target measure $\\nu$. These initializations rely on closed-form solutions available for Gaussian measures .\n", "In this notebook, we introduce the *identity* and *Gaussian approximation*-based initialization schemes, and illustrate how they can be used within the OTT library and its ICNN-based NeuralDual module." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import sys\n", "\n", "if \"google.colab\" in sys.modules:\n", " !pip install -q git+https://github.com/ott-jax/ott@main" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import jax\n", "import jax.numpy as jnp\n", "import numpy as np\n", "import optax\n", "import matplotlib.pyplot as plt\n", "from torch.utils.data import IterableDataset\n", "from torch.utils.data import DataLoader\n", "from ott.tools.sinkhorn_divergence import sinkhorn_divergence\n", "from ott.geometry import pointcloud\n", "from ott.solvers.nn import icnn, neuraldual" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## Helper Functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us define some helper functions which we use for the subsequent analysis." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def plot_ot_map(neural_dual, source, target, inverse=False):\n", " \"\"\"Plot data and learned optimal transport map.\"\"\"\n", "\n", " def draw_arrows(a, b):\n", " plt.arrow(\n", " a[0], a[1], b[0] - a[0], b[1] - a[1], color=[0.5, 0.5, 1], alpha=0.3\n", " )\n", "\n", " if not inverse:\n", " grad_state_s = neural_dual.transport(source)\n", " else:\n", " grad_state_s = neural_dual.inverse_transport(source)\n", "\n", " fig = plt.figure()\n", " ax = fig.add_subplot(111)\n", "\n", " if not inverse:\n", " ax.scatter(\n", " target[:, 0],\n", " target[:, 1],\n", " color=\"#A7BED3\",\n", " alpha=0.5,\n", " label=r\"$target$\",\n", " )\n", " ax.scatter(\n", " source[:, 0],\n", " source[:, 1],\n", " color=\"#1A254B\",\n", " alpha=0.5,\n", " label=r\"$source$\",\n", " )\n", " ax.scatter(\n", " grad_state_s[:, 0],\n", " grad_state_s[:, 1],\n", " color=\"#F2545B\",\n", " alpha=0.5,\n", " label=r\"$\\nabla g(source)$\",\n", " )\n", " else:\n", " ax.scatter(\n", " target[:, 0],\n", " target[:, 1],\n", " color=\"#A7BED3\",\n", " alpha=0.5,\n", " label=r\"$source$\",\n", " )\n", " ax.scatter(\n", " source[:, 0],\n", " source[:, 1],\n", " color=\"#1A254B\",\n", " alpha=0.5,\n", " label=r\"$target$\",\n", " )\n", " ax.scatter(\n", " grad_state_s[:, 0],\n", " grad_state_s[:, 1],\n", " color=\"#F2545B\",\n", " alpha=0.5,\n", " label=r\"$\\nabla f(target)$\",\n", " )\n", "\n", " plt.legend()\n", "\n", " for i in range(source.shape[0]):\n", " draw_arrows(source[i, :], grad_state_s[i, :])" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def get_optimizer(optimizer, lr, b1, b2, eps):\n", " \"\"\"Returns a flax optimizer object based on config.\"\"\"\n", "\n", " if optimizer == \"Adam\":\n", " optimizer = optax.adam(learning_rate=lr, b1=b1, b2=b2, eps=eps)\n", " elif optimizer == \"SGD\":\n", " optimizer = optax.sgd(learning_rate=lr, momentum=None, nesterov=False)\n", " else:\n", " raise NotImplementedError(f\"Optimizer {optimizer} not supported yet!\")\n", "\n", " return optimizer" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup Training and Validation Datasets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To test the ICNN initialization methods, we choose the NeuralDual of the OTT library as an example. Here, we aim at computing the map between two toy datasets representing both, source and target distribution. For more details on the execution of the NeuralDual module, we refer the reader to [this](https://ott-jax.readthedocs.io/en/latest/notebooks/neural_dual.html) notebook.\n", "In this tutorial, the user can choose between the datasets simple (data clustered in one center), circle (two-dimensional Gaussians arranged on a circle), square_five (two-dimensional Gaussians on a square with one Gaussian in the center), and square_four (two-dimensional Gaussians in the corners of a rectangle)." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "class ToyDataset(IterableDataset):\n", " def __init__(self, name):\n", " self.name = name\n", "\n", " def __iter__(self):\n", " return self.create_sample_generators()\n", "\n", " def create_sample_generators(self, scale=5.0, variance=0.5):\n", " # given name of dataset, select centers\n", " if self.name == \"simple\":\n", " centers = np.array([0, 0])\n", "\n", " elif self.name == \"circle\":\n", " centers = np.array(\n", " [\n", " (1, 0),\n", " (-1, 0),\n", " (0, 1),\n", " (0, -1),\n", " (1.0 / np.sqrt(2), 1.0 / np.sqrt(2)),\n", " (1.0 / np.sqrt(2), -1.0 / np.sqrt(2)),\n", " (-1.0 / np.sqrt(2), 1.0 / np.sqrt(2)),\n", " (-1.0 / np.sqrt(2), -1.0 / np.sqrt(2)),\n", " ]\n", " )\n", "\n", " elif self.name == \"square_five\":\n", " centers = np.array([[0, 0], [1, 1], [-1, 1], [-1, -1], [1, -1]])\n", "\n", " elif self.name == \"square_four\":\n", " centers = np.array([[1, 0], [0, 1], [-1, 0], [0, -1]])\n", "\n", " else:\n", " raise NotImplementedError()\n", "\n", " # create generator which randomly picks center and adds noise\n", " centers = scale * centers\n", " while True:\n", " center = centers[np.random.choice(len(centers))]\n", " point = center + variance**2 * np.random.randn(2)\n", "\n", " yield point\n", "\n", "\n", "def load_toy_data(\n", " name_source: str,\n", " name_target: str,\n", " batch_size: int = 1024,\n", " valid_batch_size: int = 1024,\n", "):\n", " dataloaders = (\n", " iter(DataLoader(ToyDataset(name_source), batch_size=batch_size)),\n", " iter(DataLoader(ToyDataset(name_target), batch_size=batch_size)),\n", " iter(DataLoader(ToyDataset(name_source), batch_size=valid_batch_size)),\n", " iter(DataLoader(ToyDataset(name_target), batch_size=valid_batch_size)),\n", " )\n", " input_dim = 2\n", " return dataloaders, input_dim" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Experimental Setup " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to solve the neural dual, we need to define our dataloaders. The only requirement is that the corresponding source and target train and validation datasets are *iterators*." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "(dataloader_source, dataloader_target, _, _), input_dim = load_toy_data(\n", " \"simple\", \"circle\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To visualize the initialization schemes, let's sample data from the source and target distribution." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "data_source = next(dataloader_source).numpy()\n", "data_target = next(dataloader_target).numpy()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# initialize optimizers\n", "optimizer_f = get_optimizer(\"Adam\", lr=0.0001, b1=0.5, b2=0.9, eps=0.00000001)\n", "optimizer_g = get_optimizer(\"Adam\", lr=0.0001, b1=0.5, b2=0.9, eps=0.00000001)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Identity Initialization Method" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we define the architectures parameterizing the dual potentials $f$ and $g$. These need to be parameterized by ICNNs. You can adapt the size of the ICNNs by passing a sequence containing hidden layer sizes. While ICNNs are by default containing partially positive weights, we can solve the NeuralDual using approximations to this positivity constraint (via weight clipping and a weight penalization). For this, set positive weights to True in both the ICNN architecture and NeuralDualSolver configuration. For more details on how to customize the ICNN architectures, we refer you to the documentation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We first explore the identity-initialization method. This initialization method is the default choice of the current ICNN and data independent, thus no further arguments need to be passed to the ICNN architecture." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "# initialize models using identity initialization (default)\n", "neural_f = icnn.ICNN(dim_hidden=[64, 64, 64, 64], dim_data=2)\n", "neural_g = icnn.ICNN(dim_hidden=[64, 64, 64, 64], dim_data=2)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "6149d916e1ca484a94c4f5b218825e1d", "version_major": 2, "version_minor": 0 }, "text/plain": [ "0it [00:00, ?it/s]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "neural_dual_solver = NeuralDualSolver(\n", " input_dim, neural_f, neural_g, optimizer_f, optimizer_g, num_train_iters=0\n", ")\n", "neural_dual = neural_dual_solver(\n", " dataloader_source, dataloader_target, dataloader_source, dataloader_target\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we can plot the corresponding transport from source to target using the gradient of the learning potential NeuralDual.g, i.e., $\\nabla g(\\text{source})$, or from target to source via the gradient of the learning potential NeuralDual.f, i.e., $\\nabla f(\\text{target})$." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "