From f83557a2eece7917a70e30ee7f617cc7983ce676 Mon Sep 17 00:00:00 2001 From: Andrewwango Date: Fri, 19 Jul 2024 12:53:06 +0100 Subject: [PATCH] add tomography splitting loss example --- demo_splitting_loss_tomography.ipynb | 379 ++++++++++++ docs/demo_splitting_loss_tomography.html | 540 ++++++++++++++++++ .../figure-html/cell-10-output-1.png | Bin 0 -> 10068 bytes .../figure-html/cell-11-output-1.png | Bin 0 -> 9727 bytes .../figure-html/cell-9-output-1.png | Bin 0 -> 9916 bytes docs/search.json | 26 +- 6 files changed, 939 insertions(+), 6 deletions(-) create mode 100644 demo_splitting_loss_tomography.ipynb create mode 100644 docs/demo_splitting_loss_tomography.html create mode 100644 docs/demo_splitting_loss_tomography_files/figure-html/cell-10-output-1.png create mode 100644 docs/demo_splitting_loss_tomography_files/figure-html/cell-11-output-1.png create mode 100644 docs/demo_splitting_loss_tomography_files/figure-html/cell-9-output-1.png diff --git a/demo_splitting_loss_tomography.ipynb b/demo_splitting_loss_tomography.ipynb new file mode 100644 index 0000000..d44585b --- /dev/null +++ b/demo_splitting_loss_tomography.ipynb @@ -0,0 +1,379 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Self-supervised learning with measurement splitting\n", + "\n", + "We demonstrate self-supervised learning with measurement splitting, to train a denoiser network on the MNIST dataset. The physics here is noisy computed tomography, as is the case in [Noise2Inverse](https://arxiv.org/abs/2001.11801). Note this example can also be easily applied to undersampled multicoil MRI as is the case in [SSDU](https://pubmed.ncbi.nlm.nih.gov/32614100/).\n", + "\n", + "Measurement splitting constructs a ground-truth free loss $\\frac{m}{m_2}\\| y_2 - A_2 \\inversef{y_1}{A_1}\\|^2$ by splitting the measurement and the forward operator using a randomly generated mask.\n", + "\n", + "See :class:`deepinv.loss.SplittingLoss` for full details." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\s2558406\\Documents\\Repos\\deepinv\\venv\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "import deepinv as dinv\n", + "from torch.utils.data import DataLoader\n", + "import torch\n", + "from torchvision import transforms, datasets\n", + "from deepinv.models.utils import get_weights_url" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "torch.manual_seed(0)\n", + "device = dinv.utils.get_freer_gpu() if torch.cuda.is_available() else \"cpu\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Define loss\n", + "\n", + "Our implementation has multiple optional parameters that control how the splitting is to be achieved. For example, you can:\n", + "\n", + "- Use `split_ratio` to set the ratio of pixels used in the forward pass vs the loss;\n", + "- Define custom masking methods using a `mask_generator` such as :class:`deepinv.physics.generator.BernoulliSplittingMaskGenerator`;\n", + "- Use `eval_n_samples` to set how many realisations of the random mask is used at evaluation time;\n", + "- Optionally disable measurement splitting at evaluation time using `eval_split_input` (as is the case in [SSDU](https://pubmed.ncbi.nlm.nih.gov/32614100/)).\n", + "- Average over both input and output masks at evaluation time using `eval_split_output`. See :class:`deepinv.loss.SplittingLoss` for details.\n", + "\n", + "Note that after the model has been defined, the loss must also \"adapt\" the model." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "loss = dinv.loss.SplittingLoss(split_ratio=0.6, eval_split_input=True, eval_n_samples=5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prepare data\n", + "\n", + "We use the `torchvision` MNIST dataset, and use noisy tomography physics (with number of angles equal to the image size) for the forward operator.\n", + "\n", + ".. note::\n", + "\n", + " We use a subset of the whole training set to reduce the computational load of the example.\n", + " We recommend to use the whole set by setting ``train_datapoints=test_datapoints=None`` to get the best results.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "transform = transforms.Compose([transforms.ToTensor()])\n", + "\n", + "train_dataset = datasets.MNIST(\n", + " root=\".\", train=True, transform=transform, download=True\n", + ")\n", + "test_dataset = datasets.MNIST(\n", + " root=\".\", train=False, transform=transform, download=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dataset has been saved in MNIST\n" + ] + } + ], + "source": [ + "physics = dinv.physics.Tomography(\n", + " angles=28, \n", + " img_width=28, \n", + " noise_model=dinv.physics.noise.GaussianNoise(0.1)\n", + ")\n", + "\n", + "deepinv_datasets_path = dinv.datasets.generate_dataset(\n", + " train_dataset=train_dataset,\n", + " test_dataset=test_dataset,\n", + " physics=physics,\n", + " device=device,\n", + " save_dir=\"MNIST\",\n", + " train_datapoints=100,\n", + " test_datapoints=10,\n", + ")\n", + "\n", + "train_dataset = dinv.datasets.HDF5Dataset(path=deepinv_datasets_path, train=True)\n", + "test_dataset = dinv.datasets.HDF5Dataset(path=deepinv_datasets_path, train=False)\n", + "\n", + "train_dataloader = DataLoader(train_dataset, shuffle=True)\n", + "test_dataloader = DataLoader(test_dataset, shuffle=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Define model\n", + "\n", + "We use a simple U-Net architecture with 2 scales as the denoiser network. \n", + "\n", + "To reduce training time, we use a pretrained model. Here we demonstrate training with 100 images for 1 epoch, after having loaded a pretrained model trained that was with 1000 images for 20 epochs.\n", + "\n", + ".. note::\n", + "\n", + " When using the splitting loss, the model must be \"adapted\" by the loss, as its forward pass takes only a subset of the pixels, not the full image." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "model = dinv.models.ArtifactRemoval(\n", + " dinv.models.UNet(in_channels=1, out_channels=1, scales=2).to(device), pinv=True\n", + ")\n", + "model = loss.adapt_model(model)\n", + "\n", + "optimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-8)\n", + "\n", + "# Load pretrained model\n", + "file_name = \"demo_measplit_mnist_tomography.pth\"\n", + "url = get_weights_url(model_name=\"measplit\", file_name=file_name)\n", + "ckpt = torch.hub.load_state_dict_from_url(\n", + " url, map_location=lambda storage, loc: storage, file_name=file_name\n", + ")\n", + "\n", + "model.load_state_dict(ckpt[\"state_dict\"])\n", + "optimizer.load_state_dict(ckpt[\"optimizer\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train and test network" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The model has 444737 trainable parameters\n", + "Train epoch 0: TotalLoss=0.032, PSNR=29.155\n", + "Train epoch 1: TotalLoss=0.035, PSNR=28.895\n", + "Train epoch 2: TotalLoss=0.035, PSNR=28.837\n" + ] + } + ], + "source": [ + "trainer = dinv.Trainer(\n", + " model=model,\n", + " physics=physics,\n", + " epochs=3,\n", + " losses=loss,\n", + " optimizer=optimizer,\n", + " device=device,\n", + " train_dataloader=train_dataloader,\n", + " plot_images=False,\n", + " save_path=None,\n", + " verbose=True,\n", + " show_progress_bar=False,\n", + " wandb_vis=False,\n", + ")\n", + "\n", + "model = trainer.train()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test and visualise the model outputs using a small test set. We set the output to average over 5 iterations of random mask realisations. The trained model improves on the no-learning reconstruction by ~7dB." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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1rF61yrlPiiaYODti8QDLBTH/bAWi9fKfpBjUzbFPpwnnXRSy7L+A5QXr5WyrnVseUN5xKamSonrs7aX3XdsSBK+dAAAWJzoBgUAACgxHtYAAABKjIc1AACAEutYgkE745HpWC29rOPI8uKzdJyYHpleH4sOIPcCva36sVg7/XosoDfv9di0Walj082FlFHxrUB4HavYcOTIkaDMuie8a2Ltf/ny5ea6lmPHjgVl1vGL2IH71v69Y7USHKy4Sy+ZwrpHi86q4NX3rpV1rJVKJSh79dVXzfpW4kaelAD5orMVpIyq3+7+2+Vtc67iV73zT0kmsKS8L0Xf13aTMYD5RssaAABAifGwBgAAUGI8rAEAAJTYcc8NGosjy8YCpIwnJhIfG+2UU05pWV62bJm7ro7PicXHvf766y3Lhw8fblnOxkjErkG7552N+YptCwAALE60rAEAAJQY002hI958882gzJvCyMoStbK1vNkmrKzBotM6idjHqltQ844rJfO0aP2UllLdsiziZ6Na27WmhfKmBqvX60HZueeea6576NChoMzKnPWyPt944w2zvBOKZkimvA+zNV1TUd45Fd2ul01qfW6s+9vLsLSOq2iZx5oiTcT+jrCOazaycYG5RMsaAABAiRVuWYuN86Xlxazpuvp13XLQ1dXVspyNUdPbi83Pqel96TGkzjzzzJblgwcPNv+vWx1060Zs3ynjz8XmBk2dBBsAACwM/IUHAAAoMR7WAAAASowEA3SEntZLxA+6t8qtoP+UoP3Vq1cHZdZURyJht7qIn8zw4osvBmVWgLwXoG8Fe1vBzl4AdNHr6u3fCuK2EgG8bnQrmWHv3r3muqeddlpQZr2vXuKHl5Disa5tStB6Sn3r/bGumTdFmvf+WKxgeuu4vHu2aEhEyhROKYrW946/6PmL2OeakrgxV1NzAe067nHWYnNT5s0NqtfVX9L6j6n+46i/7LPHEvui0HVjY7rpL9/zzz+/+f/TTz+95bXnnnsud9uxL5G8uDR9vfVxku0EAMDiRDcoAABAifGwBgAAUGKFu0F112Vs6qTs+rp7T3cf6m5PHSejp4zS3YvegKAiYffg22+/3bKsj013k+pu0Ozr73vf+1pe0921zz77bMuynspKd23mTYXF9FIAAJyYSDBAR1hB695DtH749ugH64YPfOADQdnHP/7xoOzy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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test PSNR: No learning rec.: 24.549+-1.052 | Model: 31.911+-2.220. \n" + ] + }, + { + "data": { + "text/plain": [ + "(31.911066627502443, 2.219884675922773, 24.548791694641114, 1.0523162766060832)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "trainer.plot_images = True\n", + "trainer.test(test_dataloader, pinv=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Demonstrate the effect of not averaging over multiple realisations of the splitting mask at evaluation time, by setting `eval_n_samples=1`. We have a worse performance:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmsAAAC+CAYAAABqIEhRAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAmwUlEQVR4nO3de2xlVfXA8TUq8pgZ5nYGEAYBaZFAiDxuQVHBqLSJb4y2EBJIjAntH4R/TJjSEDSSmEmr/+gfms4k/oc6tJEYiaJtUQQfAVrkocijlwGG58D0Mi8Q1P7+IL2/c9de6+yz597S0873k0wyZ9+zz9nn3HNvzz17rb3XLCwsLAgAAABK6T3L3QAAAAD4uFkDAAAoMW7WAAAASoybNQAAgBLjZg0AAKDEuFkDAAAoMW7WAAAASoybNQAAgBJbNTdrXV1dMjExsdzNAAAAaKtVc7O21Gq12nI3AQAAHIa4WStoaGhIZmdnl7sZaJPu7m5Zs2aN1Ov1Rtns7Kx0d3cnb2vNmjVtbJmtXq8H7QUAHB5W7c1aR0eHjI6OSnd3t3R1dTU9Gevq6pKhoSHp6uqSjo6Oppuw7B/e0dFRGRwclMHBQZmYmJD+/v5D+mOOcurp6ZGhoaHlbkYhlUpFZmZmpFKpLHdTsMQWv7N6e3ult7dXuru7CfFAKdXrdenv72/8Le3u7papqSkReefvZ1dXV+NfR0dH0zIPP9Ks2pu1er0unZ2dMjMzI9VqtenLrlarSW9vr8zNzcnw8LD09/fnbmtsbEx6enpkfHxcZmZmlrrpeJcMDQ3JbbfdtmKeVlWr1eVuAt4lIyMjMjk5KZOTkzI9Pc2TfZROrVaT008/vfG3dH5+XrZv3954fcuWLTI3Nydzc3MyPj4u9Xq9sTw3N8f3WaJVe7Mm8s6TExGRiy66SObm5szXtmzZIrVabcX8wUb7bNy4UQYGBtynaxMTE9Ld3S3d3d0yODhYaJsTExONX47ZHwiLvz67uroavzxFpLHc3d0ttVot94lw9qlv3nrbtm1rtHvxaTDX98pVqVSkp6en6boBltvQ0JAMDAzIwMBAo6xarTb+tqK9VvXNWkqXEd1Lh6fh4WHz6drs7Kxs3bpVpqenG92PsS7T2dlZGRoakpmZGZmbm5OxsbHGa4ODg41fmNknubVaTUZGRmR6elo6OztznwhneevV6/VGG7Zv3y71ep3u0xVuampKbrvtNunr6xMR/wfB1NRUozx7g+796PBu+Gu1WqOM7ip4JiYmCv+IRetW9c1ansUvoNHR0eBx7OKX3OTkZKOsUqnwBG4VqlQqMjAwIFu3bm0q37Fjh1x55ZWNm5zh4WHZtm1b7rZ27NghIu88Revt7ZVardZ4GrL4a7NarUq9Xm+6jsbGxppupvKeCGd5623cuLHx/z179uS2GeV07bXXSnd3t3R0dMjIyIg8/fTT0tnZ6f4gqNVq0t/f3ygfHx+XSqWS+6PDu+GfmJiQnp4euqvgWryx7+zsXOaWHD7et9wNWC5jY2PywAMPiIjI+Ph4o3xgYEAuu+wy6ezslM7OzsYf0d7eXrn22muls7NTpqeneVKxigwPDzdiL1qxadMm6evrk5GRkeC10dFRuf/++816+guv6LVlrVepVKRSqTQSYbIxJFg5tm/fLn19fTI1NSWDg4ON9zr7g0BEGj8IZmdn5Yorrmist3hNWT86Tj/99MY1at3wV6tV6e/vl1qtJoODg3RrIbB4fdVqtcb/F79zenp6zO9AtGbV3KzpJxALCwuN/2/ZsiVYP9tFVaRc981j9ahUKnLFFVc0fcFceeWV0t/fLwMDA42nEVdccUXudvr6+qS3t1eGh4cbT2I3btwoU1NTjWDxer2+pJl9i09Lsj9AsHL19PRIZ2enjI6OypYtW9wfBIfaVWnd8Pf09MjMzEwjA37xxhHI6unpkbGxsca1ODMzI9u2bWvqkUL7HLbdoEDWyMhIUwB3tVqVkZGRRuyOiH8jv6izs1NGRkbksssua4oP6unpacQBLT6dXSqVSkUmJiZkzZo1jVR6Yo5WtrGxMdm6davU63Xp6+uTiYmJRjf6YmhGX19fU+zlYvmVV14pY2NjjfIiPzoWn5Zs2bJFhoeH3SfCOLyNjY3Jtm3bouEhaJOFw9Bhetg4DGzZsmVhZGSksTw5ObnQ2dm5jC1Cqmq1ujA+Pt5UNjAwsDAwMLCwsLCwMD4+vlCtVheq1epCT0/Pwvz8fKO8s7NzobOzc6Gnp2dhbm4uKF/cxsJC8/fgyMhI0/at7VSr1YXJycklO26sPPPz8wt9fX2N68W6dhcWFhZmZmb4u9uiNQsLmf5CACva0NCQbNq0qdH1nx1TEACwMnGzBqwyg4ODMjU11YhH2r59Oxl9ALCCcbMGAABQYiQYAAAAlBg3awAAACVWeJy1I444Ivd13ZuancdQv/be9763afl///tf7nJ2W9b2ssuxbb/nPe9p6fW8dWM9yrpt//3vf3PXz6P3rbfVyrYBAEB58GQNAACgxFbNDAZYXtn5KBcdddRRhetbTwL108NFBw8eDMqOPPLIoMx7Kmo9AfWeir7vfeFH5JhjjgnK5ufnzfrr1q0Lyqxj9dqqnyp7vPZb9a1j+s9//mPWt8qt+iL2e7B79+6g7P3vf79Zf/369UHZrl27zHVF7HPrsY7Daod3Hq33zFrXOzfW+6uftC966623gjLrffR6O6x2WcfvXVtWu6xtplyzVlmr17yI/R1hlVnn1Fv3wIED7v5S2gYUVSTPkydrAAAAJXbIT9Zid4LZXyz6V6n+RaVf179O9fqxuLSir4mExxGLl0tZNxZXpvedFy+XFxMo4v9KBwAAKxtP1gAAAEqMmzUAAIASI8EAbZEyVIgV7GyVeV3YXhC35nUNW219++23zXWtwGRr/14yhbVda/9eW61yq01vvvmmWd8K2i/aJhE7acBrq5VkYSUBePVjIQuaFRzuJUpY75m1Py+8o+hELymJHt45t86Pdazevqzjsup7IR5W/ZQEiaLnyksgSplUx2pXSrIS4SNYKQrfrMXGStNfknl/vGPb0nVjGTjZD6z+UOpt623pD3ssjizvuFIzhWJxaNl96z82+g82WUoAAKxOdIMCAACUGDdrAAAAJcbNGgAAQIkdcsxaSjCwjvPScWCx8cm0vPk8YzFpsW3rGLe8GLZYrF1szlMdh5YXD+cFwAMAgNWNbFC0RdEparx1Ld7Na9Gpb7ysUSsZw8p6FGn9Jtma0mj//v1BmfcjwjoHVvu9c2qdAytz1DtXVuapNd2WiH2sRTMbRUT27t1rlntSsgaLTneUMgWTtW5Km1KyIVMyHItO95SiaAb2UvGOteh7mFIfKCO6QQEAAEqs8M+lWFdl3tRLsbr69ZQxu/S+Y0N36CFGUrtcs9uLTTeljyPWlrwu3Nj0UowXBADA6sSTNQAAgBLjZg0AAKDESDBAW1jB5f/+97/Nda2gXitoPWU6HGtfVps83r6s7R599NFBmTXVkrddK1jbC+C2QgKKlonY0y9ZSRNe0oC13d27d5vrbtiwwSzXvHMdC0nQik6r5ElJBrDCDKzz6AWsH3HEEYXXLZpA4p3HomEkKVNrWec1pf0pCQ4pU1sVfb9TQ2uAsjnkm7VYvFb2Ax+bsin2gdNfdPoPUF68Vsq6VtvyhvKITU2VEtdnbS+779iQJEw3BQDA6kQ3KAAAQIlxswYAAFBi3KwBAACUWNsSDFoZj0zHaullHUeWF5+l48T0yPS6LTqAPDZSd96YbrG2xAKa816PTZtVxgDalFHxrUB4KyhbRGTfvn1BmXVNeOfE2v/69evNdS0HDx4Myqz2i9iB+9b+vbZaCQ5W3KWXTGFdo0VnVfDqe+fKamulUgnKXnvtNbO+lbiRJ2UGAavcOo9e0HzR69NLqkmJKS06Q4en6JiL3jVrXR9FZ9JI4R2T9b3htbXodltNUACWG1cqAABAiXGzBgAAUGLcrAEAAJTYIc8NGosjy8ZdpIwnJhIfG+2oo45qWl63bp27ro6/iMXHHThwoGl57969TcvZeIjYOWj1uLOxG7FtAQCA1YknawAAACXGdFNoizfffDMo86YwsrK9rKwsL4PLyhosOq2TiN1W/QQ1r10pmadF66c8KdVPlkX8bDlru9a0UF4WY71eD8pOPvlkc909e/YEZVbmrJf1+cYbb5jlHus8pkyBlJJhWfQ997ILU97zout6+0o5rqL1U7ImW72+W80ytbJ0U6auA8qIJ2sAAAAlVvjJWmycLy0vZk3X1a/rJwcdHR1Ny9kYNb292Pycmt6XHkPq+OOPb1p++eWXG//XTx30043YvlPGn4vNDcp4QQAArE78hQcAACgxbtYAAABKjAQDtIWe1kvED7q3yq2g/5Sg/c2bNwdl1lRHImG3uoifzPDSSy8FZVaAvBegX3TqIC/Queh5TZnmyEoE8LrRrWSGnTt3muuuXbs2KLPeVy/xw0tI8bQaCG9JCYS33gfv2PSQQCL+dGpFt5vSVmtd69oSsZNVrDLvXFv7SkkAsqQkbqQkk5BggJXikMdZi81NmTc3qF5Xf0nrP6b6j6P+kGfbEvvw6bqxMd30F+ppp53W+P+xxx7b9Nrzzz+fu+3Yl2teXJo+37qdfOkAALA60Q0KAABQYtysAQAAlFjhblDddRmbOim7vu7e092HuttTx8noKaN096I3IKhI2D341ltvNS3rtuluUt0Nmn39Ax/4QNNrurv2mWeeaVrWcSu6azNvKiymlwIA4PBEggHawgpa926i9c23R99YL/rQhz4UlH384x8Pyj760Y+a9a2geav9IiIPP/xwUPbCCy8EZd4I6VbiQsoI7VbQvhWY7Y3+r8cNFLFnJfBmcLB4yQxvv/12UGYdq/e+euWeosHlIva1aL033o8iq7y/vz8ou+aaa8z6VjKB9T6IiIyPjwdlk5OTQZn3nhUN5rfeLxH782kdv5cAZLGOP2XWDa+t1nuY8r6uNH19fUHZtddea65rfU9ZCT8iIrfeemtQZiVXPfXUU7EmYonQDQoAAFBi3KwBAACUWOFu0NRpnLKv6xg1Pf6VjvWKDUuR112i19XLsbF99OPy2DAjWfq49HHMzc01LetH0nnxc7pdeVNTAQCA1YMnawAAACXGzRoAAECJrVko2H+mu/R0N2het1y7u0G9jBZr3dRu0Fh3b7YbVGcV6nX37dvXtBzrBtWy5zS1G9TLnloqZ511VlDmZXtZWWRWBppXv6urKyi7/vrrg7KLL77YrG9lM3pT71jTBFmzRbzyyitm/aJZiF5YgfU+WtNoefu3skkff/zxoOzPf/6zWf/uu+8u1CYR+321pubyvnKs+k8++aS5rojIunXr3NeK7NPKmvTaZmUz/vGPfwzKrExlEfucedNNWetamZ8vvviiWV/PpCLSPPPKIm+KNWtf1ufD+myI2J/lXbt2BWU/+MEPzPrWe+59Pi0HDx4Myrxzbb3f3nGJpGVyL4VarRaUeddcq/TfLxGRf/zjH0uyr6VgXXOjo6Pmug888MBSNydXkduwwjFrmzZtalrev39/07KOI8v+kUidPkp/Wek/rnqYguwfutiHSf+hja0fuynN0l8IJ5xwQtOyfkP0B09/SWT3pduhj8P6owgAAFY+ukEBAABKjJs1AACAEuNmDQAAoMQKx6zpQGUdn6UDqbPBvzoQWMd96bo6dksHHusYt+z2dNCsjhOLTXUUSzDI7kufAx0EqxMr9HnQx/Gvf/2raTkbB6jX1XGAevndZgWjekGTVmCzlWxhTQslIvLPf/4zKLv99tsLrSci8vrrrwdlGzZsMNft7OwMyqxkis2bN5v1rWQEK8nFO1YrQeHVV18Nyk488USz/kknnRSU6TltRUR2795t1r/33nuDMm9qK+tYrWBvb5xEbxqrFN41ZyVwWAkNXgKSte7NN98clHV3d5v1H3zwwaDsvPPOM9ft7e0Nys4555yg7JRTTjHrW6zrKCUByPrMpkxx9rGPfSwos6ZDEhHZunVrUJYyFZn1HnoJPNY1W2bW1FLnnnuuue5jjz0WlJ199tnmutVqNSj79Kc/HZR5SVvPPfdcUJZyfVqs69P7nrK+5yzPPvusWb7cCQZF8GQNAACgxLhZAwAAKDFu1gAAAEqscMyaHvtMz5F53HHHNS1nY3D0mGw6PkkPwhiLG9MxCdkYCx0Pp+Mv9L51nJleP298M92nruvqOA89eKEe3PX4449vWn766acb/9+4cWPTa3rcu9hgvwAAYGXiyRoAAECJ8TgGbbFnz56gLGWKF2tmCCvDVMR+ivirX/0qKNPZuIuszDLvyaSVpWllfnpTH1lT11hTQHnnysqss9pvZXiKiFx33XVBmTXbhTd1kX4qLuK/L9Y0SVZmoZf16Z2Ddih6zXlZh1Y24fT0dFB21113mfWtrMPJyUlz3R/+8IdBmXUdWteGiJ25aX0WvGtWz7wiIvLSSy8V3v/27duDMuu99bJBUzI/rffQKvOmSFtpPRLWNWeVee68887C61ojDJx//vnmujMzM0HZRRddVHhfFmuEgCeeeMJc18p81b1RIuGUjysJT9YAAABKrPDPCv0LRN+16nir7C9R/au2Xq83LetfjfqXVSwOLbt9HUcWG3dN/+KKjR+XFZs3VI8xpbf9iU98oml5cHCwaTk7ds3s7GzTa6+99lrTsjX2FgAAWPl4sgYAAFBi3KwBAACU2MqKrkRpWQHQVqCviB3sbQW9e0HBVn09BItIOCRMan0Re7ok3QUtEg5ls8gK9rZ4QfdWALQ1jYs3tYsVGK+nNRMReeihh8z61pRC3vtiTeVmBdZ7U2sVPVdLyWuDdR6t8+BdR1aihTfVkXV9Wkkd1rXptct6b6w2idifW6utl19+uVnfmvpHh3GIiPziF78w61v7avXa8Ornhbkc7ubn54OyP/zhD4XrpyQ+FPX1r3/dLLeSIR555JGgbMeOHW1v07ul8M2azvzRcxHqL+Dsl7z+AtNjsnnzfXn0l1n2y0V/0PVybAw3/UWn62ePU2er6G3p2DudUaXjzD71qU81LZ9xxhniueeee9zXAADA6kE3KAAAQIlxswYAAFBihbtB9dRIXtzJomx3oo6N0PFJeuqkV155pWizgu3reIvYsB86ZkHHCOUNmqjjQGIDLOq4k9/+9rdNy7qP/5Of/GTj/3oAS31cXhwRAABY2UgwQFukJAgUHXXcCrQWsQOQrTJvRHwrqDhl5HrrWK1AfI91U59ys22NzO0F3lqzJVjxjjt37jTrW8efMjOFdaxesLcX8O6x9uddM9ZxFN2miH19WdtMCVj3EnCsa6HoDAwi9vtjnduUBIMzzzwzKPv+979v1reSZX76058GZd6Pcuvz5Un53rCstBkMDifWTBo//vGPzXWtz+Itt9wSlFkz7awUdIMCAACUGDdrAAAAJVb4GfCGDRualnVXhp4IOtsd4D2uX6SHBdFdCXpoj7zH3Pq12FAdum36sbiOS8t2Mei6el09tIce90sP3aG7JR5//PHG/z/zmc80vabPWewcAwCAlYknawAAACXGzRoAAECJkQqDtkjJ5LOyAa36Xne3lcFlZXN6mV7Wdr0MRWu7KfWtLCVrm16G5cknnxyUXXrppUHZWWedZdZ/8skng7KHH344KNNd9ou8KZEs1pRGRacuEimesbko5X0omjmaEk7Q6rop13dKW4t+Fr1zZb0/N954Y1DmTbFmTY1lZSBb14tI8WxxEfu8WNdRSpYvyuG6664Lyo4//nhzXWtqrGwY0WpQ+GZNp1O/8MILTcv6CyL7gdEfCP0loT9csTHF9BuTTXVPnUMu1ha9nDemm56r78CBA03LOhZPp+jrfb388suN/997771Nr5133nlNy95FDAAAVja6QQEAAEqMmzUAAIAS42YNAACgxArHrOk4MT2liI5Ly4sjiy3rKXJ08LWOFavX6247YvS+845Dr6/X1eOo6UBhHeSqA2zzphzatWtX07I+J2eccYZb991gBc17AeNWALR17F59a0ofKyg7JenBmiJHxI6BtMq89+7II48Myqxgae9YP/zhDwdlX/va14Ky5557zqx/xx13BGV///vfgzIrKFzEnq7K+4xZQdzeeS1aP491zlKSF1KmqyqazJByDN66RZMyvKD7ogH63jV7/vnnB2Wf//zngzJvaq1vfOMbQdlTTz1VqE2eVs9ryvuKd192HuxFVlKL56tf/WpQ9uijj7bSpNLhyRoAAECJcbMGAABQYtysAQAAlFjhmDUde6LjNfLiD3RsQyxOTA+2WKlUmpb1OGxHHXVU4/96jlJNtzMW16Rfz9bXr+l25409JxLGS+i2Zc+Lji955plnmpa9ASYBAMDKxgwGaAsr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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test PSNR: No learning rec.: 24.549+-1.052 | Model: 30.434+-2.487. \n" + ] + }, + { + "data": { + "text/plain": [ + "(30.434445762634276, 2.486670644991658, 24.548791694641114, 1.0523162766060832)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.eval_n_samples = 1\n", + "trainer.test(test_dataloader, pinv=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Furthermore, we can disable measurement splitting at evaluation altogether by setting `eval_split_input` to False (this is done in [SSDU](https://pubmed.ncbi.nlm.nih.gov/32614100/)). This generally is worse than MC averaging:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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AACADKOxBgAAkGENSzCoZz4yHault3UcWVx8lo4T0zPT63PRAeS+QG+rfijWTj8eCnyNezy0bFbauenmQppZ8a1AeB2rWHHmzBmnzLonfNfEev6WlhZzX8v58+edMuv8RezAfev5fedqJThYcZe+ZArrHk26qoKvvu9aWeeay+WcslOnTpn1rcSNZqo3zjNNIHuaQPhmxJ82I8A/zWoRzWKdl3XPplkeEcgietYAAAAyjMYaAABAhtFYAwAAyLBLXhs0FEcWjSVIM5+YSHhutCuvvLJme+XKld59dXxOKD7u3LlzNdszMzM129HYh9A1qPd1R2O+QscCAACLEz1rAAAAGcZyU2iId955xynzLWFkZYlaGVy+1SasrMGkyzqJ2Oeqe1DjzitN5mnS+ml6SnXPsog/G9U6rrUslG9psHK57JRdf/315r6nT592yqzMWV/W54ULF8xynzQZivUcU8TOJpzL50qzXFYzet2bca3TZJP6sjmtz4g0mZ+s/IKFgp41AACADEvcsxaa50uLi1nTdfXjuuegtbW1Zjsao6aPF1qfU9PPpeeQWrNmTc328ePHq//XvQ66dyP03GnmnwutDZp2EWwAALAw8A0PAACQYTTWAAAAMowEAzSEXtZLxB90b5VbQf9pgvbXrVvnlFlLHYm4w+oi/mSGN9980ymzAuR9AfpWYLYVAO0Lik56XX3PbwVQW4kAvmF0K5nh0KFD5r4rVqxwyqz31Zf44UtI8bFemy9gPGmAvi8437o+aQL5kyYN+Mqtpdd89esNurekef3NWNrKd382I/EByKJLnmcttDZl3Nqgel/9Ia2/TPWXo/6wj55L6ENJ1w3N6aY/JG+88cbq/6+66qqax15//fXYY4c+sOLi0vT11ufJ2ncAACxODIMCAABkGI01AACADEs8DKqHLkNLJ0X318N7evhQD3vqOBm9ZJQeXvRNCCriDg++++67Ndv63PQwqR4GjT5+zTXX1Dymh2tfe+21mm29lJUe2oxbCovlpQAAuDyRYICGsILWfY1o3fj20Q3rio9+9KNO2ac//Wmn7PbbbzfrW0Hz1vmLiDz//PNO2RtvvOGU+YKarWDvNAHQVtC+FaDvm/1fzxsoYq9K4FvBweJLZnjvvfecMuu1+t5XX7lPvcHlafa17tk777zTKevq6jLr6x+oIu6PuYonnnjCKfvnP//plJ04ccKsnyaZwZI0caPepIE0Kxj4JN03zQoIWdbZ2emU7dixw9zX+pyyEn5ERH75y186ZVZy1YEDB0KniCZhGBQAACDDaKwBAABkWOJh0LTLOEUf10MAev4rHesVmpYibrhE76u3fXM8Veju+tA0I1H6denXMTU1VbOtu6Tj4uf0ecUtTQUAABYPetYAAAAyjMYaAABAhi2ZTTh+pof09DBo3LBco4dBfRkt1r5ph0FDw73RYVCdVaj3PXPmTM12aBhUi17TtMOgVmZeM910001OmS8b1Fouycq289Vvb293yu677z6n7I477jDrW9mM1rJOIu50KyJ2ZpkvM896DVYGmi+swHofrWW0fM9vZZO+/PLLTtnTTz9t1t+3b1+icxKx31draS7fR45V/9VXXzX3FbGzetMsN2Vdc1/91atXO2VWBt3HP/5xs77Fd89Z94x1z/oymK1s3zRZydb9bYV/+LKCret67Ngxp+znP/+5Wf+pp55KdE4i6ZYcs1jHjftcnu+lrEqlklNmZcc3gv7+ErGzkrPq6NGjTtng4KC57zPPPNPs04mVpBmWOGZNf1idPXu2ZlvHkUW/JNIuH6W/DPSHgp6mIPrhEPpj0n+cof1DjdIoPSfb2rVra7b1G6L/8HTDIPpc+jz067C+FAEAwMLHMCgAAECG0VgDAADIMBprAAAAGZY4Zk0HKuv4LB0Uu3LlSvP/Im7cl66rY7d04LGOcYseTwfS6jix0FJHoQSD6HPpa6ADhnVihb4O+nX8+9//rtmOxgHqfXUcoN6ea1Ywqi9o0gp2toJ6rQByEZF//etfTtlvfvObRPuJiLz99ttO2apVq8x98/m8U2YlU6xbt86sbwUwW0kuvtdqBZu/9dZbTtm1115r1r/uuuucMr2mrYjIyZMnzfpWsLdvaSvrtZ4/f94p882T6AtY96l3WaI0cxOeOnXKKfvpT3/qlN1yyy1mfSsZwEoUERHZvHmzU7Zp0yanzPeeW/diaF7M0L7Wezs9PW3Wt17Xpz71KafslVdeMev/+c9/dsrSvNf1Lq2VZdbSUr577qWXXnLKbr75ZnPfQqHglH3uc59zynxJW0eOHHHKbrjhBnPfpKzPPt/nlPU5Zzl8+LBZPt8JBknQswYAAJBhNNYAAAAyjMYaAABAhiWOWdNzn+lJEq+++uqa7WgMjp6TTccnzczM1GyH4sZ0zE80pk3HIOh4N/3cOs5M7x83v5keU9d1dWyWnrxQT+66Zs2amu2DBw9W/9/W1lbzmJ73LjTZLwAAWJjoWQMAAMgwumPQEFa2m86WrbCytaysLCvDVMTuRfztb3/rlOls3AorG9HXM2llaVrZdjrTt8JarspaAsp3rVpaWpwy6/ytDE8RkXvvvdcps1a7sJYDEnF7xUX874u1DJW1hJQv69N3DXzSLDWUJkPQYmVIjo6OOmXj4+NmfSuzLU2GppXtbS2B5Xsu6z72/X1YGfNWBvKGDRvM+g899JBTZl3//fv3m/Wtv0Xf+5o0mzPNclVZZt1fvnvOsnfv3sT7WvecldUrIjIxMeGUWVnNaVgzBPgyiK3MVz0aJeIu+biQ0LMGAACQYYl71vSvHd1q1fFW0V+N+leVXmhY/+rTPQehOLTo8fWvytC8a7o3IDR/XFRo3VA9x5Q+9p133lmz3dPTU7MdnbtmcnKy5jE975P1yxcAACx89KwBAABkGI01AACADCPBAA1hBTCnCfa2gt6tgHVffT0Fi4g7JUza+iL2cknW0kN6KpsKa2ktiy/o3gq2tpZx8S3tYgWx62XNRESee+45s761tJTvfbEC063Abt/SWkmvVUW9SQNJE11E7HAIq74vkD3Na7POQYeOiNjLpvnOIc1yW9Y9Y/0d3H777WZ9axmsZ5991ikbGxsz61vn70vGSHoP1HuvXI6s5cSeeOKJxPXTJD4k9a1vfcsst5IhXnjhBadsz549DT+nuZK4saaz0vQfpP4Ajn7I6y9CPSebb70vH/2HF/0g0n/oejs0h5v+ItL1o69TZ6voY+nYuzfffLNmW8eZffazn63Z3rhxo/g8+eST3scAAMDiwTAoAABAhtFYAwAAyLDEw6B6aSRf3ElFdDhRT7Wh45P05I4nTpxIelrO8XVsRmjaDx2LomOE4pZx0jE6oSWf9GSiv//972u29Rj/Zz7zmer/9aSr+nX54ogAAMDCRoIBGiJNgkDSmed9QcFWALJV5psR3woWt1YFELEDm63XagXi+1iN+jSNbWtmbl/grbVaghXveOjQIbO+9frTrExhvVZfsL212kGcNPdMmtUO6nl+H+u80pxrGkmfyxe0b92LN910k1N2//33m/Wt9/zhhx92ynwJElaiSpoEgWa815h7a9eudcp+8YtfmPta9/KDDz7olFkr7SwUDIMCAABkGI01AACADEs8DLpq1aqabT2UoReCjg41hbqg9bQgephKT+0R1yWuHwtN1aHPTXfh6y756BCQrqv31VN76Hm/9NQdehjo5Zdfrv7/85//fM1j+prRzQ8AwOJEzxoAAECG0VgDAADIMLJB0RBpMvmsbECrvm+428o2s7I5fVOpWMf1ZShax01T38pSso7py7C8/vrrnbK7777bKbOy9UREXn31Vafs+eefd8r0kH2Fb/kki5XFZw3P+47py05MI80SZ/Vmk9ar3mzSNMdN81qtaZl6enqcsmuuucasb91zjz32mFMWmuooiXpfK8tQZde9997rlK1Zs8bc11oaKxpGtBgk/mvR0xW88cYbNdv6yzb6was/nPUXm/6QDs0ppt+YaKp52vUFQ+eit+PmdNPr5507d65mW8fi6RR5/VzHjx+v/v+pp56qeeyTn/xkzbbvJgYAAAsbw6AAAAAZRmMNAAAgw2isAQAAZFjimDUdJ3bx4sWabR2XFhdHFtrWS+To4GsdK1Yul73nEaKfO+516P31vnoeNR1Aq4NZdUB23JJDR48erdnW12Tjxo3eunPBCpr3BYxbyQTWa/fVt5aLsoKV0yQ96Pu5woqBtMp8793SpUudMisA2vdaP/axjzll99xzj1N25MgRs/7jjz/ulD377LNOmV63tsJarsr3N2YFa/uua9L6aff3Be2nCTrPonqXUEpzz23atMkps5Yz88UH/+xnP3PKrPvTl2Bg3V9pkk/qTcbA3Iuug13x/e9/P3H9b3zjG07Ziy++WM8pZQ49awAAABlGYw0AACDDaKwBAABkWOKYNR17ouMV4sb+dYxRKE5s+fLlNdu5XK5mW8/DFp3EUa9RqunzDMU16cej9fVj+rzj5p4TcWMr9LlFr4uOiXrttddqtq0JSQEAwMLHCgZoCCsQ3Uo6ELFny7eCjX0BzFYAcpqgYitYWU/6HMc6L1/QvfVjwHqtq1evNusXCgWnTP8oEBF55ZVXzPpWgoEV9G8lbYj430OLlWRhJVj4+FZR8GnGCgD1HnMuA9bT3PPWvr76VrC2/oEsIrJ//36z/sMPP+yU1ZsM4atv/d3N98oUSO9LX/qSU2at6jI+Pm7W/+tf/9rwc8oahkEBAAAyjMYaAABAhl3y2qC6W1kPgUSHenRXtR5yCa2xqYedrr766prttra26v9bWlpqHtPz+5w9e7ZmW78O/Tr1osbRISjdTauHcUJDSKG56qLXRcek6WuoY9gAAMDiQM8aAABAhtFYAwAAyDCyQdEQeuhaxJ/NaWVg+fZNWt/K8PRlep07dy7xc+lhcBE7c9K3HI6VhWZlsFnZdiIid9xxh1N24sQJp2x4eNisb71WHQog4r/+Vuaqb2kt61pZ94WPlVEcpxnZmM1agiqLSyD57rkvfvGLTpmV1fyjH/3IrG9l9VpTC6XJ0Kw3m5Osz2zwZd1b95wVRvTDH/7QrB+3VONikbixpm92/eGuL1b0QusPfP1lp+vqP+wLFy7UbOsP9bVr11b/f+2119Y89pGPfKRm+9ChQzXbb7/9ds12NP7Neq7o69JrgerXFYrV0x9AcfOwhdY8TdMAAQAACwfDoAAAABlGYw0AACDDEg+D6tiT0JBfdFoLHe+gh1D1th4O1MOoevgx+nh7e3vNY5/4xCdqtnWcho7f0VN96GHTw4cPV/+vh2/169TXJLS8lBa3FFZoCBUAACwOJBigIaxlhXzzzFn7WkH7vqB3K9jYCoT3LaFkLdfkey4rcNV6rjTL4axbt84p+9rXvmbWt/Z98cUXnTLf0j9nzpxxyvRchL7z9JX7rpX14+Kqq65KtJ9IuqWtROY/aLzeJZSaxfr7sN6z733ve2b99evXO2VPP/20U+Zb4sf6+2jW0lzzveQX0nnggQfM8ltvvdUp27t3r1P2l7/8peHntFDQHQMAAJBhNNYAAAAyLPEwqI6JCsVjRR/Xwx56Xz38obvs9XCWHkaLTr+hl13Sz6W7+PUwTblcrtk+duyY97lCy0vpITS9Hbqml7ovAABYPOhZAwAAyDASDNAQeuJikXRB69YM53qh+worQD3NqgLWvtbs+yJ20LsVrG0lTYiI5HI5p+yuu+5yyr7+9a+b9a3Z4B977DGnzEokELGvYZoZ4q1r7Qvgtsqt6+dL/EizioVI/cHlaa5DM57f91zWfWv9zaR5ri1btjhl3/3ud819rff8oYceSrSfiJ1gUK96VzBIe1zU78tf/rJT9oMf/MDcV8/wICLy4IMPNvycFjJ61gAAADIs8U+g119/vWZb94TUE1MV+iWmf/3oXpzotl43cWJiomZbz6umf+Xr5ap0j0s07kz3Guhj6V99oV9xcXOn6cd0L0TcnGwAAGDhomcNAAAgw2isAQAAZBiNNQAAgAxLHLM2NTVVs71ixYqabb3mZjTeSse3heZoC82zprejsWM6K07PmxZa01TXX716dc32smXLqv+3Mhjjjq2FXnf08dCx0mbSNZp1LXyxiFYGlxVz53tNVnl0LdoKX9ahda5WfRE7G9OKPfTdC3ptWhGRr3zlK06ZtSyTiMgf/vAHp+yFF15wys6dO2fWt66rL3PVYi23ZS3XJZI889OXwZd2fdtmZH7O5VJFvueqN0NRr48sYmfWWZnKIiKPPvqoU7Zv3z6nzPd+JT3/Zi3XNd/v6+VIf0+K2BnEvs/03/3ud07Z3/72t/pPbBGhZw0AACDDaKwBAABkGI01AACADEscszY9PV2zrWN5omtmitTG8OjYJT1uHYph03E3ep616CztvjglH30uep42/bpaWlrM/4uEY/P0dQjF4sUdS8cH6fnjAADA4sByU2gIKwHCCs4XsYPeraD1NMvWWMf01bf29Z2rFRCrG+kiIm1tbWb973znO07Zbbfd5pQdOHDArL93716n7Pjx406Zb1JkK3HCeq98weJWuW9pq6SJG75lxNJMpC2SLpB8IS0rZJ2r9T747u+f/OQnTtmGDRucssOHD5v1rWQE67qmSTBo1rJQ1nGblbgAf4KA9Tll3XM6UbHCtwwV/h/DoAAAABlGYw0AACDDLnkYVM/rpLtHo13kurtcd2mH1tDUsVz6eNHH9dBAKG5MzyOlz0XHhp0+fbr6/5mZmdhj63VFfXN5VeihrOjr0uehh+3ozgcAYHGiZw0AACDDSDBAQ1iBp76gdyswOc3s9VYgepoEgzS9kNZzWYH0t956q1l/06ZNTpmVILBnzx6z/t///nenzEqG8GUSR1fcqEi60oCI/b5YCRYidkayda1877XvfvFJuipBI8xl0LzFujbFYtHcd/PmzU6Z9Z5biQQiIqVSySmz3rM0Qf+WNK+/GatVID1rdQwRkY6OjkT177//frPcl3iA/5e4sab/APSQnv5Si27rPxS9b2iYNLQdPZfQkGnouUPnEvfY+fPna7Z11lvoAyfuXPV56w/v+V5uCgAANAfDoAAAABlGYw0AACDDaKwBAABkWOKYNR1PpWOmdDxWdDs0M3kosFjHY4WWo4oKTd0RCjzVj0evgz62Pk99XqF4uLi4v3pi6wAAwMJFNigawmosWpmIIu7cdr4yPZdfxYoVK5wyK+vQ14i3ztXX2LUySm+55Ran7Nvf/rZZf+XKlU7Zr3/9a6fsySefNOtbmZ9WMome06/C+qFkvVbr+om4STMi/kSZpUuXOmXW0lK++QbTZASL1J+hmeY+aIY091xra6tT9uMf/9isb/3d/epXv3LKfBnIvntprqTJ5iTzs3luvPFGp+yPf/xj4voPPPCAU/b444/XdU6XM4ZBAQAAMozGGgAAQIYlHgbVwym6+zlujjD9mK4bin9LM++aHiIKPZcWF3snEj9/XGgIJu3caNHHQ9efrn8AABYnetYAAAAyjAQDNIS1nI2vp9EKOreCqpcvX27Wt3pHrV5KXxayVe471/Xr1ztlX/jCF5yym2++2axv9Xj+4x//cMoOHz6cuL6VdOALzrdeq29pKYsvGcCSNPFhZmbGrF/v8k2NUO85+Oqnuees97y/v98pu+GGGxLXf/TRR819Lc1YRqtZ17VejEj4dXd3O2XW56HPvn37nDKu96WjZw0AACDDEvespZ2PLLodN1fZpUizhqame3BCa25qaX4ZhOaHC8W8Rc8lNK9aFnolAABA49GzBgAAkGE01gAAADKMxhoAAECGJY5Z0/FXOqMsLpYrLsbMPCkVV2YtRRR3/Ljz0lmLum7ouaOxYaG5ztLOhRZXX18znaWXJsOvGayYOd/7ZmV+WmW+15Q05tEXx2dlrvoy6zZu3OiUffWrX3XKrrvuOrN+qVRyyqwMSd+ce9Z1sbJpL1y4YNZvaWlxyqzrZ2WYitjn6ovrPHPmjFNmLX3kW9qqmXGXSWNN0yxrVG9933182223OWX33HOPU2bdxyL2NbeWbrOWBxNJfq18519vxl8zskl9iPV931133eWU3XffffNwJvChZw0AACDDaKwBAABkGI01AACADLvkedZ0jE3c+p6h2C19LB3rlGZeNn1sHesVOpaOk9LnHo0hCq1pqh8PzZUWRx97vmPUAADA3GC5KTREmgBqqzzpUkUidmC1FSBvBVr7nst3rh0dHU6ZFZjtC/A/dOiQU/bSSy85Zb6G+/nz550yK2ng7NmzZn3rulhLSPmCzS2+BAHrGlrJCL6gbt/73SxpgsuTBr373sc0SR3f/OY3nTLrnrWST0REpqamnDLrnqs3uD6UKHapmhH0zzJH8e6++26nbOXKlYnrW/ec7zMJl4ZhUAAAgAyjsQYAAJBhlxyzFppTLNpFHlobNNSdXk8Xtj6vNLF2lmisWOh1hWLUQtchOlylY9R03dBcdAAAYGGiZw0AACDDSDBAQ1jB4fVmrPqC9q1yK0De10tqBb1bgfwiIqdOnXLKjhw54pSNjY2Z9f/0pz85ZUePHnXKfLPRW+VWgkCaZArruqRZ7cHHCni3esV9Pem+99snzetIqt5A9DTPb72PIiLHjh1zyqwVCA4ePGjW7+/vd8qmp6cTP/9cXYO5XD3A91ysYJDOc889Z5Zv2bLFKTt9+nSzT+eykrixlvamju6vh+wavUxT3DQhoaFG/Xhouo241xUazvUtKWQd2zqXuOfyZYYBAICFjWFQAACADKOxBgAAkGE01gAAADKsYVN36GDVaLxVaHqMUNxYKNYrei6huLHQclNpzi0Uxxd6XaHYvGh9va+eqiN0jQAAwMK0ZDZh6o8OYM9qYy30ckKNNd3Yi5uXLW3ygn487ZqpUaHG2lyvHdra2uqU+d4Lq9y3hJGlXC47ZdYSTMuXLzfrv/XWW07ZqlWrzH2tJVfWrVvnlM3MzJj1rczRpEsXidgZe1bWpO++trJkz5w5k+h5ROwfP75kFus1WEkyaZZkst7rCuu11bOOsEi6rMFmLWFkvRfr1693yg4cOGDWt96zNMvBJZXm9VvP5fthXe+1TpMlbH1OxmVAkz2KZkhyfzMMCgAAkGE01gAAADKsYfOs6a7juHm/QsODekgvNA9b3PPGzVVm0c8VN7QZGtbUj4e6OvXrjtYPXaNQrB4AAFiY6FkDAADIMKa9R0NYy9kAzXTx4sX5PgVcZpqVVAKE0LMGAACQYYmn7gAAAMDco2cNAAAgw2isAQAAZBiNNQAAgAyjsQYAAJBhNNYAAAAyjMYaAABAhtFYAwAAyDAaawAAABlGYw0AACDD/g9ELvyyc2Id3wAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test PSNR: No learning rec.: 24.549+-1.052 | Model: 31.003+-2.107. \n" + ] + }, + { + "data": { + "text/plain": [ + "(31.002875900268556, 2.106733038650352, 24.548791694641114, 1.0523162766060832)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.eval_split_input = False\n", + "trainer.test(test_dataloader, pinv=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/demo_splitting_loss_tomography.html b/docs/demo_splitting_loss_tomography.html new file mode 100644 index 0000000..bccb9d3 --- /dev/null +++ b/docs/demo_splitting_loss_tomography.html @@ -0,0 +1,540 @@ + + + + + + + + + +Self-supervised learning with measurement splitting + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+
+

Self-supervised learning with measurement splitting

+
+ + + +
+ + + + +
+ + +
+ +

We demonstrate self-supervised learning with measurement splitting, to train a denoiser network on the MNIST dataset. The physics here is noisy computed tomography, as is the case in Noise2Inverse. Note this example can also be easily applied to undersampled multicoil MRI as is the case in SSDU.

+

Measurement splitting constructs a ground-truth free loss \(\frac{m}{m_2}\| y_2 - A_2 \inversef{y_1}{A_1}\|^2\) by splitting the measurement and the forward operator using a randomly generated mask.

+

See :class:deepinv.loss.SplittingLoss for full details.

+
+
import deepinv as dinv
+from torch.utils.data import DataLoader
+import torch
+from torchvision import transforms, datasets
+from deepinv.models.utils import get_weights_url
+
+
c:\Users\s2558406\Documents\Repos\deepinv\venv\Lib\site-packages\tqdm\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
+  from .autonotebook import tqdm as notebook_tqdm
+
+
+
+
torch.manual_seed(0)
+device = dinv.utils.get_freer_gpu() if torch.cuda.is_available() else "cpu"
+
+
+

Define loss

+

Our implementation has multiple optional parameters that control how the splitting is to be achieved. For example, you can:

+
    +
  • Use split_ratio to set the ratio of pixels used in the forward pass vs the loss;
  • +
  • Define custom masking methods using a mask_generator such as :class:deepinv.physics.generator.BernoulliSplittingMaskGenerator;
  • +
  • Use eval_n_samples to set how many realisations of the random mask is used at evaluation time;
  • +
  • Optionally disable measurement splitting at evaluation time using eval_split_input (as is the case in SSDU).
  • +
  • Average over both input and output masks at evaluation time using eval_split_output. See :class:deepinv.loss.SplittingLoss for details.
  • +
+

Note that after the model has been defined, the loss must also “adapt” the model.

+
+
loss = dinv.loss.SplittingLoss(split_ratio=0.6, eval_split_input=True, eval_n_samples=5)
+
+
+
+

Prepare data

+

We use the torchvision MNIST dataset, and use noisy tomography physics (with number of angles equal to the image size) for the forward operator.

+

.. note::

+
  We use a subset of the whole training set to reduce the computational load of the example.
+  We recommend to use the whole set by setting ``train_datapoints=test_datapoints=None`` to get the best results.
+
+
transform = transforms.Compose([transforms.ToTensor()])
+
+train_dataset = datasets.MNIST(
+    root=".", train=True, transform=transform, download=True
+)
+test_dataset = datasets.MNIST(
+    root=".", train=False, transform=transform, download=True
+)
+
+
+
physics = dinv.physics.Tomography(
+    angles=28, 
+    img_width=28, 
+    noise_model=dinv.physics.noise.GaussianNoise(0.1)
+)
+
+deepinv_datasets_path = dinv.datasets.generate_dataset(
+    train_dataset=train_dataset,
+    test_dataset=test_dataset,
+    physics=physics,
+    device=device,
+    save_dir="MNIST",
+    train_datapoints=100,
+    test_datapoints=10,
+)
+
+train_dataset = dinv.datasets.HDF5Dataset(path=deepinv_datasets_path, train=True)
+test_dataset = dinv.datasets.HDF5Dataset(path=deepinv_datasets_path, train=False)
+
+train_dataloader = DataLoader(train_dataset, shuffle=True)
+test_dataloader = DataLoader(test_dataset,  shuffle=False)
+
+
Dataset has been saved in MNIST
+
+
+
+
+

Define model

+

We use a simple U-Net architecture with 2 scales as the denoiser network.

+

To reduce training time, we use a pretrained model. Here we demonstrate training with 100 images for 1 epoch, after having loaded a pretrained model trained that was with 1000 images for 20 epochs.

+

.. note::

+
  When using the splitting loss, the model must be "adapted" by the loss, as its forward pass takes only a subset of the pixels, not the full image.
+
+
model = dinv.models.ArtifactRemoval(
+    dinv.models.UNet(in_channels=1, out_channels=1, scales=2).to(device), pinv=True
+)
+model = loss.adapt_model(model)
+
+optimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-8)
+
+# Load pretrained model
+file_name = "demo_measplit_mnist_tomography.pth"
+url = get_weights_url(model_name="measplit", file_name=file_name)
+ckpt = torch.hub.load_state_dict_from_url(
+    url, map_location=lambda storage, loc: storage, file_name=file_name
+)
+
+model.load_state_dict(ckpt["state_dict"])
+optimizer.load_state_dict(ckpt["optimizer"])
+
+
+
+

Train and test network

+
+
trainer = dinv.Trainer(
+    model=model,
+    physics=physics,
+    epochs=3,
+    losses=loss,
+    optimizer=optimizer,
+    device=device,
+    train_dataloader=train_dataloader,
+    plot_images=False,
+    save_path=None,
+    verbose=True,
+    show_progress_bar=False,
+    wandb_vis=False,
+)
+
+model = trainer.train()
+
+
The model has 444737 trainable parameters
+Train epoch 0: TotalLoss=0.032, PSNR=29.155
+Train epoch 1: TotalLoss=0.035, PSNR=28.895
+Train epoch 2: TotalLoss=0.035, PSNR=28.837
+
+
+

Test and visualise the model outputs using a small test set. We set the output to average over 5 iterations of random mask realisations. The trained model improves on the no-learning reconstruction by ~7dB.

+
+
trainer.plot_images = True
+trainer.test(test_dataloader, pinv=True)
+
+

+
+
+
Test PSNR: No learning rec.: 24.549+-1.052 | Model: 31.911+-2.220. 
+
+
+
(31.911066627502443, 2.219884675922773, 24.548791694641114, 1.0523162766060832)
+
+
+

Demonstrate the effect of not averaging over multiple realisations of the splitting mask at evaluation time, by setting eval_n_samples=1. We have a worse performance:

+
+
model.eval_n_samples = 1
+trainer.test(test_dataloader, pinv=True)
+
+

+
+
+
Test PSNR: No learning rec.: 24.549+-1.052 | Model: 30.434+-2.487. 
+
+
+
(30.434445762634276, 2.486670644991658, 24.548791694641114, 1.0523162766060832)
+
+
+

Furthermore, we can disable measurement splitting at evaluation altogether by setting eval_split_input to False (this is done in SSDU). This generally is worse than MC averaging:

+
+
model.eval_split_input = False
+trainer.test(test_dataloader, pinv=True)
+
+

+
+
+
Test PSNR: No learning rec.: 24.549+-1.052 | Model: 31.003+-2.107. 
+
+
+
(31.002875900268556, 2.106733038650352, 24.548791694641114, 1.0523162766060832)
+
+
+ + +
+ +
+ +
+ + + + \ No newline at end of file diff --git a/docs/demo_splitting_loss_tomography_files/figure-html/cell-10-output-1.png b/docs/demo_splitting_loss_tomography_files/figure-html/cell-10-output-1.png new file mode 100644 index 0000000000000000000000000000000000000000..262169ba9fff2c0538abf363dcb97ead5b411d57 GIT binary patch literal 10068 zcmZ{K3p|tk`~P&%0ZD~QC?({uBIKM(PKl^7hbhcySPpZTMo*q1LNbILa;(ROZJ0KP zba0q6*_<{>j&rtAj{n7$}_Nl8WFqRC?Wmazzt(IR=}6+yKe;b2Z03dZ9jS5=oNZ^KxgZW zuj$_oel^1k^@88wzF$y1xA^kdSRn5~ULKEx%Td}s`nT%dls!d0t2lVb=-Iv*$v?wy zyzDx7@x@EyqOA$Zw6-&wk(y-*N1x_+-`XX~WBdJeV{Qu1lkxW)W$?i-o0})AYyBB8 z_B3gn)z#g$l6XVeZHUy~H$Lc(Y}X0JS2GlV$6nyYrmvUBC#(fZ8UN_Kaw9A7B_Q202QznB`_yq)-yvfW8r%cG5qMlKo9W3e7 zr%x+uXvifdCMxUbv?gM(H}R0fZgair1#&=G7_0(0#0thVCo3wetIPQN`z!0}Dsj=( z1Z{Qoh81Yeolw%*#kR!5LJ2WS6r-`Ru@**!SD#e5t@r2ky6bCRgO#^S z?qV_(nM|hgrAs#M>A?T7j&XgGdt+*KsT9ibT5W?o!XR)&xvk>L)BDSBku3B;g*T!s zbiw01V}*9-?d`n6!oo=kPx3%V$8&yu{>Jz3FX!TH@oJkDIn@wutF1|j5YsfWaCrFM z(quodh+a&}or1zbF=jkLsk^TadhGb|7pbYoQq$8D2?RntA|fIp*70SZ%)4@1v+LKd zyP(mwnp#@^S$o|=*gZfZhym9QTx-T`x3G_=r-=`BMs1SKJ}k7gr|!#_+qv4I5wjZ; z^FBWi<+i!cX3qtmJ$rWlR+IsI`&=?VgR?t3JHPr)e@hws{@o=PXZd!1myhsYx6dh` zKY!AW?BjiIh~OM)A2OO0oBj$o=e`PWyV;7s>E2UPbJ_;%nVBS8JU#e0@dturi#Mr; zAt`b7_4R2!1&f*6C+Iy`Nm$s@30?kPacneTrkwG2P6h-tHa13SZ*aQ1`uZj}Prm8# z>>3&xl9iN{OfkuSv6lOhI-CV0WoD)XrRb||6=80A+I}qggf5FbC}5-H?CiYwey3nm zRO62y!MP9a-o30uomQTlp2oJdwbe^@vRJTp%l(La63Ge(Y=|WxnqN>*-3e?<@aR4Z z#3nHzA>nH|kpJ(tHrHCwt9&IB<#4<;uymGhFCMx_yl}=wV>_rA3`SX1ReE~?Ry5Zl zE?+yYw--R-XtaE>JB}P|2G!HNskgzYSM_AhTNm8{(2!z_KMNclfH+kei~$n9eoM60 zA4u+&xyxm)J%hMOnS*?Me6d@|KBBaZ-hjcKJo}YaXYQNZ=lnhkTVKS~Z3h|%1$gJq zow0>N*7m*zvw^Ftt9bzIoXvZCFfA0xy)3tAa_yGy`o!G2|h!zAs>+y+4Q8&Zk98eg5Bys`jPV8;8 zQyip%K)BFHK^1)gDgqGQr%#_=S6_8JD zy1J~}YUj_Fo(G=W58#a&3p_;hub!zZ=H~4m*4H28R*^{lueYCtg>LtJe3WDz2kSpv zSz7rDTwwPye&%*j&*P@1CTT4noc7Yv5+AU}vFy*3Kv5A95up71pbq4y^6{l^UIEGX z0|55wFMHd`%@Vgd2r5U{SlwTB#v>{0!e(bDZ@Hw4*N*n+e{v<2rL5liVtlvkr~o zy|pnH?$2n?UBQ!kXcau5%OUeFe|HW@D?hIdtna6+s5t7&t;cLT^Bvsoj|O`LCHQG^ z+KY|ZEurT;b$Ga$(KU0JVZ-k)o#Xb=#>U56SJ`wt9}VZs?f)z5Txiv@9T)Gs+8(~? zOefRut5VCMrJ*ac+0(%9)@L2Kaxp$&5mb`UDgyTG0Vffg~UqBg|uB|*o(*sZ+(W9RIqWk2tcJ7?Mx zW&VywV52$RDdU?kb_OET`n@pAAAWDW*_$5$l4L3{h~3=waD! zTPAxzAbBzKfA-PSbs+Bq<=auh(_Tp-4!y90mdATUQIg9&X`W!N^C`YG;S;mcCN^`a<$B<%+=**oxu+5= z4RTvN3dgF!jS#0oPf0*Fu)Ch-jMGd{nxx)t@U%7|9vVJvBe#DD_qpDr+wnz6c$M=& z7s~nAr9MI2rp1&u+j~+lR3T1buF_KFv6HWRABL@`wkoIwH35NeHv=Me{5L!5TaSZ4 zm!FFJwb+`RFO6I3^1Vw~Xez7vsqK8hgW%0RO0GIuVS{t;L2%{`E{YJbm+o$~%) zw5%axZ&jJeQ5c+oikQK*N?>@3Q4W zT=_)kOG`=F(-eJxg_z*x+w*O#;jAyF1j;HGdx6TSalRTfaq7Ay)t)pEW2T-Tf0~|L zr8L;fv3w@F3-o^KQ{q3FkJ0(db~bgRTbnDjz(QriRj*hGdI+C16OfPU3Pn!e&c%( z2gCwvGjNFC_E`Ll2G2>jxM8wrR{qE*P9uk+sQFM^%`%Af(uYv-X-C=;EZ!{rPCcj} zdusuIIaprS?wZR`4Msl|WfnaCsefyg%Wg#}{*7SVa!l_ZYxK?P3fp}LAcOfSH|{y) z8o1q=p9&qPc_Q*H_t9XXGpeMTq{;*tI4@7ppk_R*<3T68+w?Evr*ev#S0f82UdFIg z5e||DZe2#h;)&eq;qvl{Ksz%FP_mfyx&L($y{Fm*j>nvCu6M|LCUf?Xq}a@x+&E8L z7}+O-S{zp!^|?X((*10YkU3VhS#w`-RIi3Rw~|BoHF@SohLEQ0ZkBFcIf!m>}(@ z?oStgCcq4K!69R~6zCk9v*6z`-({W=fGk0x8MS71f3s~MxGge|j2TwEMD>!YgG)xGPl(pV`HSEqiA z#3OCPevYPyZ86NnIo+|nHCFXmF|7i$VEt`$u0ICK&3|b7uAOC%GwG(E1Svq7%-+Ig zZ?vYX?}5{A8%o_HQ=+n3=DSS6yWxf1O?J&wI`J+~GPHuy z*gz>&lO?gN!3!TvjTXv|??oE#`;*MtGuO*`epzZWz|(-7-UUH8u=@`Y67S%Y=j`p) zOpHOqyfZ#|XA+;^eVFv^c>^@2)htzA{SC}I+?cIbuo|Dc`P^;b(AxYYg>Zq%5uNfV z%%K0+A~Z-0aQc_p^|Gily(tKoeVXnNCF8*)2vn-sDFDbb3#Z@dJM3e@L>)`ll%v+n zvbvd(lmV-TrU|*+fR!BelW&ZAb$-z8kgAI8ib)?!ra&5IW2fYg%iRbHbve~7)5DhT zD^EeFAkQfjr0f8Foxk>or~ku#+ZCT2ZY$Yv$OgRH5vh9wi&-C$6r|~{cE+c1@!26o z8&Xn&dh7QsmOt=;cfnbECn4Xi(Du$iI%HwM>BKkMx~a^-K*7E@lr)qwY7S()Uh-~%PK_q53X)h)U){bJ#au1097wjSYV9I z0t>Azd5G7hfLsW1dT_cx37#JMaA63=aOp4=13z#M_9C8>v%>)95GqTuw{xo#8lH&^~86aAQ zT_Fqp6o(Kit8IWp{07LcDvyWC_J$WwIRWbKFtRs{FmHhgiN(^Wc8q z$F_J8YzV`?h%*EhN(cw?!jxE&f7ii3H#c{TBB(w8-cnu0I$@yn!v#dTnzyGdt2R8m zn;3Vxc{9N%L)Ro6I;mHTe)(uxlF}P#y!AR3FG-ba?Q+~J^XmSUZerL~&K~n{W0#fu zf!FaLS91X|4$=M9wEiu=_c!1sFT=&N@^`)^)zxYqv}wRhQZxfi_ecQEc6vFW0~dEV z#te1D^nBy2Y1U5hT}6lGIUyYl3nk$jMIIVrd)_d5d>^8JGF^A)qV*FYcS%WJ_ssaD zr51q*tH@F}mIwIoGE$4H?2P zZfY-FBW)VXWE{axYIqx53!Gzl(`#2)p%KbRPkFWt{w@;v>KgKR(GixaoAiB~eFCr@ zFUn_I)rU@CQ9(iJT*(LXb=lKZOKmEQnVA^@TARlBtL$m4)y)fRI~-e9nx}EKrQn9| zG9ezLAWJH^dPoQ$=m?8sW#Lq=1bUw~UDeK&{>5@UGqm{KtaH4M2sQ(=+&4z)@l=&v z;}q(NV?&JX+I3d!Et35(wm5e8S|+h(T%lce4F|0m+{bJ1o0|U1)WF?uNt0N+(Vh@8 z=-Z&G=;nN%^U_OG*I4kw(HODr3;X(x@`(!;j(|Bes8^{lJ>&xwW??aV>XM*N@N0=d z?yn-fI$0>THB{;A+>JmFQhV>#ffW%J+bWp{*pLRty`f%OT@58jjSDga=1Q*#|LE0Mi(Ftd2?u zJE!!m7EHfr3~_y(!kx^B2$V&)hCm}BYQr2(fJGp~At;rL$9-&SGWKUmZq7#ny<6Ot z@gyqaod-sw3IS=al9E~k8i6otYk6iMLYZC7CF)x#>)}^A&Mg%f*?H(3qN}xb{i3`8<=Vf& zcWtPAD!6DGd~2hq0#>4~$aaifO}V3RK#__OHxv;IGTZtV9V?k4oUVR5{z5)^uX#XuIw094QR36y zyQ@R>>mV4NT`@+N&fM_C2!&G4Fn22+Ishj%?q9A5)?a~u%2Z=x)XQUpkCqgw9u^9j zcpV8KAA5zh=43YNx|<$qg%H-UHf=&gpd|21UmXk~IgizQ5>OahV{v-;tx8}+1pPw3k{O-gopk5+~dh5f2kJ*K1bdPYk zCE-j3@{3avA>R|Sy&B@gy^-D2{Q1_jw)IYbp(*g!>6EI?9o^2vkR?nACk49PY!KeT z_4DFa-!Ld-yTx0%6-{_g_G)F^${%Ub<-RpnRm}3OKlbe%fPg^;2q1g<{~~*jsruY6 zMzF!A9Iv39xY&*bWAs#>H7q3Go%Cpi9URkJDyiwJ->`R7Annb_Wv87AQ_xU+Lzc42V-yZnN*0};B`l9SsL*|nFbkqE80f%_ zeKsqH?&A=zC;0iLme-s!2C%y#RNA#wWY++ujii%bz{6I%vv}dGct7^isPRu$DX#1o z{{b2LjpKSisRy`t`!_}M;2|tjWd?WTUkU~CoI4ujj26w z$F+XOBO;LdZMg6T@t|FBz?T?`P?ndq|CCuwTYCo8A7q6n+Umul+ALp)S{4+YOKW-V z$Iqe|Bq~>BujTNpvQ$Gie~#~gXKk&IZ#OMG^1+ChexH@O&Yd@AnUHn_Z7n*;F;HUK z0Ad+44peAQi{**j_=>K)uHj$B{NJ)__@%0NXwHc0;y1wnud50-ZwOY{yuF>4%)R7g zD2}=fz$wnsjI1KU$a8F`GfE}{$76M54%M4ZRKVL~;=mzescvb>)jVf;K<{bw{Jidb z@&}nFngkcQsFj=D9)b%D`D2D2&%?G+_wIM0mq3bumf*L3*j)P_ zoqUKNmmLna84MLvguJID-5p+Vy)~crY|8QC#GolhHZA-4i?3Mao%*!t0|tkWRC%)k zy3K&b(7HKk9OSZJBXPs)S!n1-;!MKdOR5BbKFbAK^*`ivUN3lgY7uLDj*J< z?EbIZn0`La+Y_IJ5;a;TybIe^LbZ4D_nPu49EsB^_6QlNkB!|bajdPG1bFC|&5gD6 zWUlYTNK5_4rx%0tCmYHrVlwo{N5qPhLSX?n(sUy=p8%c_?tu2c1`&X9@OYLYvOv^E8JYPq8L8GQM9W_i)j$S&_iatUZ%EIDUIo&$>H+V+jvbHmTb@K55)VrLfsi_IH zh5#!F?*h4Y!<)1zhO838=HF<&b8(5DxLEU*ISOZn&-!Np{?z%Lxd-D~t{YWvk6Xul zP)DpfF(h>{M52ss_%K^9kWw7i-X$5fkstP9pUlP0@NZ9L)T)>31j9-_LdM%N%$iGT zH__dGYMZV7*2|R~`|Q<9Cj#K=$|6rx^gaj4shQ0pUU$bE?HLRYV9!|fZ?qWg#TwE+~B#2`nNg3euxn+5;I|dC+jeHqD zqgIVgRu_ig_=LBEedcJkBJQnomG2l1@Ha5v3FdyaiXFq%a#-ACS``NRM-jcIN(?Da zzrQrrs^4c_vnWieDWA=a*FBD9hHq`SZeZ4ycf-*NS4uKq?}CbPlA;X~pzj5DyFw9a# zsvhUGKQkkr+DZI~oG@HMI~Hc5J-dms1#cN_v*v9%KrI1`9txisxS?(Gbuk}M*aS2G zHb;)`1AvG4vWU$_=^P|R>3CA2#IrM%iyoF2tFG2WiF15*o7x#4mXb;`k(Q-?e_{HF z*bJ^6#Fb>RqNCPV8MOy!xNAFv)=m^WD?nzjv3I@M>mg4i@Uh0GEAin|bc{fqQ z+H7loPxqZk8Ku5Tl?}ezNYkw=&+@;F$7U2bcAKC2@p$k5a=m_0V*(&-fO(WzGlEg< zZAEbI5|5hai=;Crvm*>?DMM@K!FGkkKFZIYY)m z36dKVhQQ7Y9|!;NwSgg9Wbe5TN&m1M{>Kr&QoNGNdW; zvA|h{a|zLRtH1h^bi7ZDM4_1^W7{9wiuvTc#0iP|{B6|Rv|-QW!pJsHdk@%7eDV)_ z_qT}>cIM)c$Y`8@Vof*rD2 zRhB(5v6lvWuwX#ij8$jZxNpH8>34#{=j;n#F(8LEjm{g5Nbj{7vMS69Lt7La78VWZ zwiw>>&Hsnz8`#LqM%&A51YcYWhU$6JT+d(RscDJVFnBrAZq_bTMV}ID?Xcrz3eD&qa|H;a#Sv_ z94!BQ^AVrYd3Kh6n}&XB(#cZih6AL{zv~3F=^*T^Z(x0_fq~ocgM=Yb`MN8g+KejN zl2%}$j2Ic|gVk@a*FcCZKzHKV8GG0pgtpkAR%nwF-4`<#I;6t3d%8!C1hcVpO*cx# zzn<_CG)>CBUkOZ>m7A$lDqqhQom>M?4t=`kNBCnTo%6Yv%HgEw2SUS7awr6!u3o3mO*f$^vKlvs-AI9G`Fa3bZ;E5;z1X0WquthTG%1fnw8l!?&wt1Tl2>T?1gY zgxNNoLEoq~pbJU^bbU$Y(An0gA5WDb_1UWBSasIjsV{nR&~SQr=@I9{XuTVF=cQ$2 zQr7(s`}F(F!xj$%@N3;%AJ-G4g)Nh^09onmu9~hQ?N9FUc&}ipk<{mj>h~xFeiIl0 z@iA(F!u^P-HCvgRuO{9$!TS%cfV;2$ChQqb^4@r?5Kwqf&I?Gnk>W|EoZgzUs$Q*x z^@R~9=DD}dxp2q$jBqDldSa9DTlD?iqvZUmWMUy5?}U$FS}ruaHNg#DZC{JQNz{sgIDq$J=v6sBMedzRWKD{Sp* zW`HGcR0U4nkatk8nDg?o@xqb55IPp8*!~41j-~Q?@*`oD@oFSwtnkj5xK-y%LvUO> ztwL)QYt@2kzclhJd%D?i)6XKX%UC9r3ry54T;WD&=UM3ZXIcSfBv!p;mCYy-q~Vs_ z;4hs zZ|UyHT1h|w8siiR*N#Vt7gky0U4>q7Q|DfoD(#~c*KV%D-S=tR*KJQ3f6tMAGwDd} zwzRl=jp;)wBGi0xzH^4rz==UWUN*u$6)Ug0L%1@IBohATH!B;PM z{w`ph3QP~x4&jg)qKN%+?3dcGM-Nd40H+IF$_lO3!QT{3vaEGi{=>RF3ULC+BFmB)nmaHx_lFZ1IgPSzemn_F^V3O59rEx?-RNk$Hk5c8w7mYXI2# zkhA|SmwfVKBk%ZLU6=>ypb9sFr55`UCA;B&`(0|Ps&INOyO{cj__w_Y z>H5>!XLoYp8LPZ!1#{)iPP=h-=AWx&CRuA4Qqt~BPdgg!7(nlwNmHTwcF;BS#$Gx< zB5vC{xbU7k*1O@`?9?Lp1^+zU(Y$T9Nuq{e}yYKfe z*ZOy>rB}Sx3MlnbW1UmezOLY-Ai_@aHU+k7%-bddPQDKaBhjD7;A}REYawo``avB) z5DX!*zo2gdv`l2-J|B zDZ3@@Q4=j2u!6Wf))7PjF}0U$TdQI(R+WbA05zxtIz&6MJs6=KEhC<-X7|%xFv&>A z*Bep2dSO*ABJ88MGpSgG%j{~HOLeUr;5b)R2xr_>l)l>Kj1j@D_^!+{T`@%h0C!Rx zEXc9C8lv|sCR4s7%w+6MIhY+vnh3ZjCAH_kiTjSHi;kGSZuCCN%>D;3%DrEy>O6O5 zRXP%8^*4@csU5Img)P;eBTZmNQQq|wRUod08LO2fuJgF;=mk9>5E{SBC4Xpq#mlTL z$Jw)A&ySc1@hT)?JxU%1{x%|oB`CmsUZ6SM->LO$=>Kmx{&LxVFUkLFSML^&Rr-$h VZ;T=@;JZM^1~;!2U%C6}{{Vwe`9S~x literal 0 HcmV?d00001 diff --git a/docs/demo_splitting_loss_tomography_files/figure-html/cell-11-output-1.png b/docs/demo_splitting_loss_tomography_files/figure-html/cell-11-output-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6be1d5f5123e6a21a263ce7d3a684a84683756eb GIT binary patch literal 9727 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 P6y&y!!FBvq>%jj4uImUS literal 0 HcmV?d00001 diff --git a/docs/search.json b/docs/search.json index 1ef9fa2..c33968b 100644 --- a/docs/search.json +++ b/docs/search.json @@ -6,6 +6,20 @@ "section": "", "text": "%cd ..\n\nc:\\Users\\s2558406\\Documents\\Repos\\cmr-experiments\n\n\nc:\\Users\\s2558406\\Documents\\Repos\\cmr-experiments\\venv\\Lib\\site-packages\\IPython\\core\\magics\\osm.py:417: UserWarning: This is now an optional IPython functionality, setting dhist requires you to install the `pickleshare` library.\n self.shell.db['dhist'] = compress_dhist(dhist)[-100:]\n\n\n\nfrom utils.edipo.data.transforms import CineNetDataTransform\nfrom utils.edipo.data.mri_data import RawDataSample\nfrom utils.edipo.models.crnn import CRNN\nfrom utils import *\nfrom pathlib import Path\nfrom torch.utils.data import DataLoader, random_split\nimport torch\nimport numpy as np\n\n\n# ONLY RUN when new dataset_cache run on Linux\nimport pathlib, pickle\nwith open(\"dataset_cache.pkl\", \"rb\") as f:\n with set_posix_windows():\n dataset_cache = pickle.load(f)\n \n new_cache = {\n pathlib.WindowsPath(r\"M:\\data\\CMRxRecon\\SingleCoil\\Cine\\TrainingSet\"):\n [\n RawDataSample(r.fname.replace(\"/home/s2558406/RDS\", \"M:\").replace(\"/\", \"\\\\\"), r.slice_ind, r.metadata) for r in dataset_cache[\n pathlib.WindowsPath('/home/s2558406/RDS/data/CMRxRecon/SingleCoil/Cine/TrainingSet')\n ]\n ]}\n\nwith open(\"dataset_cache_windows.pkl\", \"wb\") as f:\n pickle.dump(new_cache, f)\n \n\n\ndataset = DeepinvSliceDataset(\n Path(r\"M:\\data\\CMRxRecon\"), \n transform=CineNetDataTransform(time_window=12, apply_mask=True, normalize=False), \n set_name=\"TrainingSet\",\n acc_folders=[\"FullSample\"],\n mask_folder=\"TimeVaryingGaussianMask16\",#\"AccFactor08\",\n dataset_cache_file=\"dataset_cache_windows.pkl\"\n )\n\nUsing dataset cache file\n\n\n\ntrain_dataset, test_dataset = random_split(dataset, (0.8, 0.2))\n\n\ntrain_dataloader = DataLoader(dataset=train_dataset, batch_size=1, shuffle=False)\ntest_dataloader = DataLoader(dataset= test_dataset, batch_size=1, shuffle=False)\n\n\nx, y, mask = next(iter(train_dataloader))\n\n\nphysics = DynamicMRI((1, 2, 12, 512, 256))\ny2 = physics(x, mask=mask)\n\n\nx_hat = physics.A_adjoint(y2, mask=mask)\n\n\nmodel = ArtifactRemovalCRNN(\n CRNN(num_cascades=2)\n).to(\"cpu\")\n\n\nphysics.set_mask(mask)\nx_recon = model(y, physics)\n\n\nplot_gif([x, y, y2, x_hat, mask], titles=[\"x\", \"y\", \"y2\", \"x_hat\", \"mask\"], display=True)\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Once\n \n Loop\n \n Reflect\n \n \n\n\n\n\n\n\n\n\n\n\nimport deepinv as dinv\n\n\nclass Undersampling(dinv.physics.DecomposablePhysics):\n def __init__(self, mask, device=\"cpu\", **kwargs):\n super().__init__(**kwargs)\n self.mask = torch.nn.Parameter(mask.to(device), requires_grad=False)\n\n\nloss = YamanSplittingLoss(split_ratio=0.9)\n\nmask2 = loss.subsample_mask(loss.rng, physics.mask.data.detach().clone())\n\ninp = Undersampling(mask2, device=y.device)\n\ninp2 = Undersampling(mask - mask2, device=y.device)\n\nphysics1 = DynamicMRI(physics.img_size)\nphysics1.set_mask(mask2)\nphysics2 = DynamicMRI(physics.img_size)\nphysics2.set_mask(mask - mask2)\n\n# divide measurements\ny1 = inp.A(y)\ny2 = inp2.A(y)\n\n\nplot_videos([\n mask, mask2, mask-mask2, \n y, y1, y2, \n physics.A_adjoint(y, mask=mask), physics1.A_adjoint(y1, mask=mask2), physics2.A_adjoint(y2, mask=mask-mask2)\n], display=True)\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Once\n \n Loop\n \n Reflect" }, + { + "objectID": "demo_splitting_loss.html", + "href": "demo_splitting_loss.html", + "title": "Self-supervised learning with measurement splitting", + "section": "", + "text": "We demonstrate self-supervised learning with measurement splitting, to train a denoiser network on the MNIST dataset.\nMeasurement splitting constructs a ground-truth free loss \\(\\frac{m}{m_2}\\| y_2 - A_2 \\inversef{y_1}{A_1}\\|^2\\) by splitting the measurement and the forward operator using a randomly generated mask.\nSee :class:deepinv.loss.SplittingLoss for full details.\nimport deepinv as dinv\nfrom torch.utils.data import DataLoader\nimport torch\nfrom torchvision import transforms, datasets\nfrom deepinv.models.utils import get_weights_url\n\nc:\\Users\\s2558406\\Documents\\Repos\\deepinv\\venv\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n from .autonotebook import tqdm as notebook_tqdm\ntorch.manual_seed(0)\ndevice = dinv.utils.get_freer_gpu() if torch.cuda.is_available() else \"cpu\"" + }, + { + "objectID": "demo_splitting_loss.html#train-and-test-network", + "href": "demo_splitting_loss.html#train-and-test-network", + "title": "Self-supervised learning with measurement splitting", + "section": "Train and test network", + "text": "Train and test network\n\ntrainer = dinv.Trainer(\n model=model,\n physics=physics,\n epochs=1,\n losses=loss,\n optimizer=optimizer,\n device=device,\n train_dataloader=train_dataloader,\n plot_images=False,\n save_path=None,\n verbose=True,\n show_progress_bar=False,\n wandb_vis=False,\n)\n\nmodel = trainer.train()\n\nThe model has 444737 trainable parameters\nTrain epoch 0: TotalLoss=0.017, PSNR=11.59\n\n\nTest and visualise the model outputs using a small test set. We set the output to average over 50 iterations of random mask realisations. The trained model improves on the no-learning reconstruction by ~3dB.\n\ntrainer.plot_images = True\nmodel.MC_samples = 50\ntrainer.test(test_dataloader)\n\n\n\n\nTest PSNR: No learning rec.: 19.356+-1.523 | Model: 23.150+-1.996. \n\n\n(23.150262069702148,\n 1.9961603806415074,\n 19.355849266052246,\n 1.5233685706910973)\n\n\nSince this is a denoising example, above, we have set eval_split_output to True (see :class:deepinv.loss.SplittingLoss for details). Alternatively, we get worse results when we set eval_split_output to False:\n\nmodel.eval_split_output = False\ntrainer.test(test_dataloader)\n\n\n\n\nTest PSNR: No learning rec.: 19.356+-1.523 | Model: 14.441+-1.520. \n\n\n(14.44115686416626, 1.5199918435073472, 19.355849266052246, 1.5233685706910973)\n\n\nFurthermore, we can disable measurement splitting at evaluation altogether by setting eval_split_input to False (this is done in SSDU):\n\nmodel.eval_split_input = False\ntrainer.test(test_dataloader)\n\n\n\n\nTest PSNR: No learning rec.: 19.356+-1.523 | Model: 9.650+-1.670. \n\n\n(9.650477170944214, 1.6700495788637173, 19.355849266052246, 1.5233685706910973)" + }, { "objectID": "demo_ei.html", "href": "demo_ei.html", @@ -14,17 +28,17 @@ "text": "Train a neural network to solve an image inpainting inverse problem, using perspective-EI and the deepinv library.\n\nimport deepinv as dinv\n\n\n\ntorch imports\nimport torch\nfrom torch.utils.data import DataLoader, random_split\nfrom torchvision.datasets import ImageFolder\nfrom torchvision.transforms import Compose, ToTensor, CenterCrop, Resize\nfrom torchvision.datasets.utils import download_and_extract_archive\n\n\nDefine inpainting experiment to reconstruct images from images masked with a random mask:\n\nphysics = dinv.physics.Inpainting((3, 256, 256), mask=0.6, device=\"cpu\")\n\nLoad Urban100 dataset of natural urban scenes:\n\n\nDownload dataset from HuggingFace\ndownload_and_extract_archive(\n \"https://huggingface.co/datasets/eugenesiow/Urban100/resolve/main/data/Urban100_HR.tar.gz?download=true\",\n \"Urban100\",\n filename=\"Urban100_HR.tar.gz\",\n md5=\"65d9d84a34b72c6f7ca1e26a12df1e4c\"\n)\n\n\n\ntrain_dataset, test_dataset = random_split(\n ImageFolder(\"Urban100\", transform=Compose([ToTensor(), Resize(256), CenterCrop(256)])),\n (0.8, 0.2)\n )\n \ntrain_dataloader, test_dataloader = DataLoader(train_dataset, shuffle=True), DataLoader(test_dataset)\n\nAs these scenes are imaged with a camera free to move and rotate in the world, we can impose perspective invariance on the unknown image set \\(x\\in X\\). Define measurement consistency and EI losses:\n\ntransform = dinv.transform.Homography(theta_max=10)\n\nlosses = [\n dinv.loss.MCLoss(), \n dinv.loss.EILoss(transform)\n]\n\nFor training, use a small UNet for the model with Adam optimizer:\n\nmodel = dinv.models.UNet(\n in_channels=3, \n out_channels=3,\n scales=2,\n circular_padding=True,\n batch_norm=False\n)\n\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-8)\n\nTrain the model using deepinv’s Trainer:\n\nmodel = dinv.Trainer(\n model=model,\n physics=physics,\n online_measurements=True,\n train_dataloader=train_dataloader,\n eval_dataloader=test_dataloader,\n epochs=1,\n losses=losses,\n optimizer=optimizer,\n verbose=True,\n show_progress_bar=False,\n save_path=None,\n device=\"cpu\"\n).train()\n\nThe model has 444867 trainable parameters\nEval epoch 0: PSNR=10.078\nTrain epoch 0: MCLoss=0.002, EILoss=0.021, TotalLoss=0.023, PSNR=15.948\n\n\nShow results of a pretrained model trained using a larger UNet for 40 epochs:\n\n\nLoad pretrained model from HuggingFace\nmodel = dinv.models.UNet(\n in_channels=3, \n out_channels=3,\n scales=3,\n circular_padding=True,\n batch_norm=False\n)\n\nckpt = torch.hub.load_state_dict_from_url(\n dinv.models.utils.get_weights_url(\"ei\", \"Urban100_inpainting_homography_model.pth\"),\n map_location=\"cpu\",\n)\n\nmodel.load_state_dict(ckpt[\"state_dict\"])\n\n\n<All keys matched successfully>\n\n\n\nx, _ = next(iter(train_dataloader))\ny = physics(x)\nx_hat = model(y)\n\ndinv.utils.plot([x, y, x_hat], [\"x\", \"y\", \"reconstruction\"])" }, { - "objectID": "demo_splitting_loss.html", - "href": "demo_splitting_loss.html", + "objectID": "demo_splitting_loss_tomography.html", + "href": "demo_splitting_loss_tomography.html", "title": "Self-supervised learning with measurement splitting", "section": "", - "text": "We demonstrate self-supervised learning with measurement splitting, to train a denoiser network on the MNIST dataset.\nMeasurement splitting constructs a ground-truth free loss \\(\\frac{m}{m_2}\\| y_2 - A_2 \\inversef{y_1}{A_1}\\|^2\\) by splitting the measurement and the forward operator using a randomly generated mask.\nSee :class:deepinv.loss.SplittingLoss for full details.\nimport deepinv as dinv\nfrom torch.utils.data import DataLoader\nimport torch\nfrom torchvision import transforms, datasets\nfrom deepinv.models.utils import get_weights_url\n\nc:\\Users\\s2558406\\Documents\\Repos\\deepinv\\venv\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n from .autonotebook import tqdm as notebook_tqdm\ntorch.manual_seed(0)\ndevice = dinv.utils.get_freer_gpu() if torch.cuda.is_available() else \"cpu\"" + "text": "We demonstrate self-supervised learning with measurement splitting, to train a denoiser network on the MNIST dataset. The physics here is noisy computed tomography, as is the case in Noise2Inverse. Note this example can also be easily applied to undersampled multicoil MRI as is the case in SSDU.\nMeasurement splitting constructs a ground-truth free loss \\(\\frac{m}{m_2}\\| y_2 - A_2 \\inversef{y_1}{A_1}\\|^2\\) by splitting the measurement and the forward operator using a randomly generated mask.\nSee :class:deepinv.loss.SplittingLoss for full details.\nimport deepinv as dinv\nfrom torch.utils.data import DataLoader\nimport torch\nfrom torchvision import transforms, datasets\nfrom deepinv.models.utils import get_weights_url\n\nc:\\Users\\s2558406\\Documents\\Repos\\deepinv\\venv\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n from .autonotebook import tqdm as notebook_tqdm\ntorch.manual_seed(0)\ndevice = dinv.utils.get_freer_gpu() if torch.cuda.is_available() else \"cpu\"" }, { - "objectID": "demo_splitting_loss.html#train-and-test-network", - "href": "demo_splitting_loss.html#train-and-test-network", + "objectID": "demo_splitting_loss_tomography.html#train-and-test-network", + "href": "demo_splitting_loss_tomography.html#train-and-test-network", "title": "Self-supervised learning with measurement splitting", "section": "Train and test network", - "text": "Train and test network\n\ntrainer = dinv.Trainer(\n model=model,\n physics=physics,\n epochs=1,\n losses=loss,\n optimizer=optimizer,\n device=device,\n train_dataloader=train_dataloader,\n plot_images=False,\n save_path=None,\n verbose=True,\n show_progress_bar=False,\n wandb_vis=False,\n)\n\nmodel = trainer.train()\n\nThe model has 444737 trainable parameters\nTrain epoch 0: TotalLoss=0.017, PSNR=11.59\n\n\nTest and visualise the model outputs using a small test set. We set the output to average over 50 iterations of random mask realisations. The trained model improves on the no-learning reconstruction by ~3dB.\n\ntrainer.plot_images = True\nmodel.MC_samples = 50\ntrainer.test(test_dataloader)\n\n\n\n\nTest PSNR: No learning rec.: 19.356+-1.523 | Model: 23.150+-1.996. \n\n\n(23.150262069702148,\n 1.9961603806415074,\n 19.355849266052246,\n 1.5233685706910973)\n\n\nSince this is a denoising example, above, we have set eval_split_output to True (see :class:deepinv.loss.SplittingLoss for details). Alternatively, we get worse results when we set eval_split_output to False:\n\nmodel.eval_split_output = False\ntrainer.test(test_dataloader)\n\n\n\n\nTest PSNR: No learning rec.: 19.356+-1.523 | Model: 14.441+-1.520. \n\n\n(14.44115686416626, 1.5199918435073472, 19.355849266052246, 1.5233685706910973)\n\n\nFurthermore, we can disable measurement splitting at evaluation altogether by setting eval_split_input to False (this is done in SSDU):\n\nmodel.eval_split_input = False\ntrainer.test(test_dataloader)\n\n\n\n\nTest PSNR: No learning rec.: 19.356+-1.523 | Model: 9.650+-1.670. \n\n\n(9.650477170944214, 1.6700495788637173, 19.355849266052246, 1.5233685706910973)" + "text": "Train and test network\n\ntrainer = dinv.Trainer(\n model=model,\n physics=physics,\n epochs=3,\n losses=loss,\n optimizer=optimizer,\n device=device,\n train_dataloader=train_dataloader,\n plot_images=False,\n save_path=None,\n verbose=True,\n show_progress_bar=False,\n wandb_vis=False,\n)\n\nmodel = trainer.train()\n\nThe model has 444737 trainable parameters\nTrain epoch 0: TotalLoss=0.032, PSNR=29.155\nTrain epoch 1: TotalLoss=0.035, PSNR=28.895\nTrain epoch 2: TotalLoss=0.035, PSNR=28.837\n\n\nTest and visualise the model outputs using a small test set. We set the output to average over 5 iterations of random mask realisations. The trained model improves on the no-learning reconstruction by ~7dB.\n\ntrainer.plot_images = True\ntrainer.test(test_dataloader, pinv=True)\n\n\n\n\nTest PSNR: No learning rec.: 24.549+-1.052 | Model: 31.911+-2.220. \n\n\n(31.911066627502443, 2.219884675922773, 24.548791694641114, 1.0523162766060832)\n\n\nDemonstrate the effect of not averaging over multiple realisations of the splitting mask at evaluation time, by setting eval_n_samples=1. We have a worse performance:\n\nmodel.eval_n_samples = 1\ntrainer.test(test_dataloader, pinv=True)\n\n\n\n\nTest PSNR: No learning rec.: 24.549+-1.052 | Model: 30.434+-2.487. \n\n\n(30.434445762634276, 2.486670644991658, 24.548791694641114, 1.0523162766060832)\n\n\nFurthermore, we can disable measurement splitting at evaluation altogether by setting eval_split_input to False (this is done in SSDU). This generally is worse than MC averaging:\n\nmodel.eval_split_input = False\ntrainer.test(test_dataloader, pinv=True)\n\n\n\n\nTest PSNR: No learning rec.: 24.549+-1.052 | Model: 31.003+-2.107. \n\n\n(31.002875900268556, 2.106733038650352, 24.548791694641114, 1.0523162766060832)" } ] \ No newline at end of file