From 6a042258ea54aaaabc59a96b56404385d747708d Mon Sep 17 00:00:00 2001 From: Taimoor Sohail Date: Tue, 30 Jun 2026 16:42:41 +1000 Subject: [PATCH 1/2] Add PET training notebook --- .../tutorial/AutoEncoder_PET_Training.ipynb | 384 ++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 docs/notebooks/tutorial/AutoEncoder_PET_Training.ipynb diff --git a/docs/notebooks/tutorial/AutoEncoder_PET_Training.ipynb b/docs/notebooks/tutorial/AutoEncoder_PET_Training.ipynb new file mode 100644 index 00000000..47973cce --- /dev/null +++ b/docs/notebooks/tutorial/AutoEncoder_PET_Training.ipynb @@ -0,0 +1,384 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Autoencoder Training With PyEarthTools\n", + "\n", + "This tutorial extends the autoencoder workflow by using PyEarthTools for both data loading and model training. The data pipeline prepares Himawari satellite imagery, `PipelineLightningDataModule` turns that pipeline into PyTorch dataloaders, and `pyearthtools.training.lightning.Train` runs a PyTorch Lightning training loop.\n", + "\n", + "The model and `LightningWrapper` are defined in this notebook, so this tutorial is self contained and does not require code from any other project." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import datetime\n", + "from pathlib import Path\n", + "import warnings\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "import torch.optim as optim\n", + "import lightning as L\n", + "\n", + "import pyearthtools.data as petdata\n", + "import pyearthtools.pipeline as petpipe\n", + "import pyearthtools.training" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "warnings.filterwarnings(\"ignore\")\n", + "torch.manual_seed(42)\n", + "\n", + "device = \"gpu\" if torch.cuda.is_available() else \"cpu\"\n", + "accelerator = \"gpu\" if torch.cuda.is_available() else \"cpu\"\n", + "workdir = Path(\"AutoEncoder_PET_Training_Output\")\n", + "workdir.mkdir(exist_ok=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Site Archive\n", + "\n", + "Select the site archive module for the system where the notebook is running. The original tutorial uses JASMIN; at NCI, change this import to the NCI site archive." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import site_archive_jasmin" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build The Data Pipeline\n", + "\n", + "The pipeline reads Himawari surface global irradiance, sorts and aligns dimensions, selects a smaller spatial domain, normalises values, converts the result to NumPy, and reshapes the sample to the PyTorch image convention: time, channel, height, width." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "himawari = petdata.archive.Himawari(\"surface_global_irradiance\")\n", + "\n", + "training_pipeline = petpipe.Pipeline(\n", + " himawari,\n", + " petpipe.operations.xarray.Sort(order=[\"time\", \"latitude\", \"longitude\"]),\n", + " petpipe.operations.xarray.AlignDataVariableDimensionsToDatasetCoords(),\n", + " petdata.transform.region.Bounding(-35, -25, 138, 150),\n", + " petpipe.operations.xarray.normalisation.SingleValueDivision(1200),\n", + " petpipe.operations.xarray.conversion.ToNumpy(),\n", + " petpipe.operations.numpy.reshape.Rearrange(\"c t h w -> t c h w\"),\n", + " iterator=petpipe.iterators.DateRange(\"20200101T00\", \"20200301T00\", interval=\"10 minutes\"),\n", + " exceptions_to_ignore=petdata.exceptions.DataNotFoundError,\n", + ")\n", + "\n", + "training_pipeline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "selected_date = datetime.datetime(2021, 6, 9, 2, 0)\n", + "eda_pipeline = petpipe.Pipeline(\n", + " himawari,\n", + " petpipe.operations.xarray.Sort(order=[\"time\", \"latitude\", \"longitude\"]),\n", + " petpipe.operations.xarray.AlignDataVariableDimensionsToDatasetCoords(),\n", + " petdata.transform.region.Bounding(-35, -25, 138, 150),\n", + " petpipe.operations.xarray.normalisation.SingleValueDivision(1200),\n", + " iterator=petpipe.iterators.DateRange(\"20210101T00\", \"20210103T00\", interval=\"1 hour\"),\n", + " exceptions_to_ignore=petdata.exceptions.DataNotFoundError,\n", + ")\n", + "\n", + "fig, axes = plt.subplots(1, 3, figsize=(18, 5), constrained_layout=True)\n", + "for i, ax in enumerate(axes):\n", + " plot_time = selected_date + datetime.timedelta(hours=i)\n", + " eda_pipeline[plot_time][\"surface_global_irradiance\"][0].plot.imshow(ax=ax)\n", + " ax.set_title(str(plot_time))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define Train And Validation Splits\n", + "\n", + "The pipeline itself is reusable; the PET Lightning data module below swaps in the training or validation iterator as needed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train_split = petpipe.iterators.DateRange(\"20200101T00\", \"20200215T00\", interval=\"10 minutes\")\n", + "valid_split = petpipe.iterators.DateRange(\"20200215T00\", \"20200301T00\", interval=\"10 minutes\")\n", + "\n", + "batch_size = 8\n", + "num_workers = 0\n", + "max_epochs = 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define The Autoencoder\n", + "\n", + "This compact convolutional autoencoder reconstructs the input image. The final interpolation makes the output spatial shape match the input even when the input dimensions are odd." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class AutoEncoder(nn.Module):\n", + " def __init__(self, input_channel_count=1, output_channel_count=1):\n", + " super().__init__()\n", + " self.encoder = nn.Sequential(\n", + " nn.Conv2d(input_channel_count, 16, kernel_size=4, stride=2, padding=1),\n", + " nn.ReLU(),\n", + " nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1),\n", + " nn.ReLU(),\n", + " nn.Conv2d(32, 64, kernel_size=7, padding=3),\n", + " nn.ReLU(),\n", + " )\n", + " self.decoder = nn.Sequential(\n", + " nn.Conv2d(64, 32, kernel_size=7, padding=3),\n", + " nn.ReLU(),\n", + " nn.Upsample(scale_factor=2, mode=\"bilinear\", align_corners=False),\n", + " nn.Conv2d(32, 16, kernel_size=3, padding=1),\n", + " nn.ReLU(),\n", + " nn.Upsample(scale_factor=2, mode=\"bilinear\", align_corners=False),\n", + " nn.Conv2d(16, output_channel_count, kernel_size=3, padding=1),\n", + " nn.Sigmoid(),\n", + " )\n", + "\n", + " def forward(self, x):\n", + " input_size = x.shape[-2:]\n", + " latent = self.encoder(x)\n", + " reconstructed = self.decoder(latent)\n", + " return F.interpolate(reconstructed, size=input_size, mode=\"bilinear\", align_corners=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Wrap The Model For Lightning\n", + "\n", + "PET's training wrapper expects a Lightning module. This `LightningWrapper` keeps the autoencoder architecture separate from the training, validation, prediction, loss, and optimiser logic." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class LightningWrapper(L.LightningModule):\n", + " def __init__(self, model, lr=1e-3):\n", + " super().__init__()\n", + " self.model = model\n", + " self.lr = lr\n", + " self.criterion = nn.L1Loss()\n", + "\n", + " def _unpack_batch(self, batch):\n", + " x = batch\n", + " while isinstance(x, (tuple, list)):\n", + " x = x[0]\n", + " if isinstance(x, dict):\n", + " x = next(iter(x.values()))\n", + " x = torch.as_tensor(x).float()\n", + " if x.ndim == 5 and x.shape[1] == 1:\n", + " x = x[:, 0]\n", + " return torch.nan_to_num(x, nan=0.0, posinf=0.0, neginf=0.0)\n", + "\n", + " def forward(self, x):\n", + " return self.model(x)\n", + "\n", + " def _shared_step(self, batch, stage):\n", + " x = self._unpack_batch(batch)\n", + " x_hat = self(x)\n", + " loss = self.criterion(x_hat, x)\n", + " self.log(f\"{stage}_loss\", loss, prog_bar=True, on_epoch=True, on_step=False)\n", + " return loss\n", + "\n", + " def training_step(self, batch, batch_idx):\n", + " return self._shared_step(batch, \"train\")\n", + "\n", + " def validation_step(self, batch, batch_idx):\n", + " return self._shared_step(batch, \"valid\")\n", + "\n", + " def predict_step(self, batch, batch_idx):\n", + " x = self._unpack_batch(batch)\n", + " x_hat = self(x)\n", + " return {\"x\": x.detach().cpu(), \"x_hat\": x_hat.detach().cpu()}\n", + "\n", + " def configure_optimizers(self):\n", + " return optim.Adam(self.parameters(), lr=self.lr)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "base_model = AutoEncoder(input_channel_count=1, output_channel_count=1)\n", + "model = LightningWrapper(base_model, lr=1e-3)\n", + "model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create The PET Lightning Data Module\n", + "\n", + "`PipelineLightningDataModule` converts the PET pipeline and date iterators into Lightning-compatible dataloaders. The model sees batches of tensors produced from the same pipeline used for exploration." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data_module = pyearthtools.training.data.lightning.PipelineLightningDataModule(\n", + " training_pipeline,\n", + " train_split=train_split,\n", + " valid_split=valid_split,\n", + " batch_size=batch_size,\n", + " num_workers=num_workers,\n", + ")\n", + "\n", + "data_module" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train With PET\n", + "\n", + "`pyearthtools.training.lightning.Train` owns the Lightning trainer setup, checkpoint/log directory, and dataloader connection. Setting `load=False` starts a fresh run rather than resuming from an existing checkpoint in `workdir`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "trainer = pyearthtools.training.lightning.Train(\n", + " model,\n", + " data_module,\n", + " path=workdir,\n", + " trainer_kwargs={\n", + " \"max_epochs\": max_epochs,\n", + " \"accelerator\": accelerator,\n", + " \"devices\": 1,\n", + " \"num_sanity_val_steps\": 0,\n", + " \"logger\": False,\n", + " \"enable_checkpointing\": False,\n", + " \"enable_model_summary\": False,\n", + " },\n", + ")\n", + "\n", + "trainer.fit(load=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Predict And Plot Reconstructions\n", + "\n", + "After training, use the Lightning trainer directly for a small validation batch and compare the input, reconstruction, and reconstruction error." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "validation_loader = data_module.val_dataloader()\n", + "predictions = trainer.trainer.predict(model, dataloaders=validation_loader)\n", + "\n", + "x = torch.cat([batch[\"x\"] for batch in predictions], dim=0).numpy()\n", + "x_hat = torch.cat([batch[\"x_hat\"] for batch in predictions], dim=0).numpy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, axes = plt.subplots(3, 3, figsize=(12, 10), constrained_layout=True)\n", + "for row in range(3):\n", + " axes[row, 0].imshow(x[row, 0], vmin=0, vmax=1)\n", + " axes[row, 0].set_title(\"Input\")\n", + " axes[row, 1].imshow(x_hat[row, 0], vmin=0, vmax=1)\n", + " axes[row, 1].set_title(\"Reconstruction\")\n", + " axes[row, 2].imshow(x_hat[row, 0] - x[row, 0], cmap=\"RdBu_r\")\n", + " axes[row, 2].set_title(\"Error\")\n", + " for ax in axes[row]:\n", + " ax.set_axis_off()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "The same pattern can be reused for more realistic models: keep the PET pipeline responsible for data preparation, keep the Lightning module responsible for model-specific training logic, and let `pyearthtools.training.lightning.Train` run the training loop." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 57b1ae3f47dd2f3158612f862dea0ea1bfc5b642 Mon Sep 17 00:00:00 2001 From: Taimoor Sohail Date: Wed, 1 Jul 2026 14:40:00 +1000 Subject: [PATCH 2/2] Added the tutorial for review --- .../AutoEncoder_ImprovingResults.ipynb | 6 +- .../tutorial/AutoEncoder_PET_Training.ipynb | 101 +++++++++++++++--- 2 files changed, 92 insertions(+), 15 deletions(-) diff --git a/docs/notebooks/tutorial/AutoEncoder_ImprovingResults.ipynb b/docs/notebooks/tutorial/AutoEncoder_ImprovingResults.ipynb index 6e3d5ae9..dd2331c6 100644 --- a/docs/notebooks/tutorial/AutoEncoder_ImprovingResults.ipynb +++ b/docs/notebooks/tutorial/AutoEncoder_ImprovingResults.ipynb @@ -3609,9 +3609,9 @@ ], "metadata": { "kernelspec": { - "display_name": "pet_dev_nb_gpu_jasmin", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "pet_dev_nb_gpu_jasmin" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -3623,7 +3623,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.11" + "version": "3.11.7" }, "nbsphinx": { "orphan": true diff --git a/docs/notebooks/tutorial/AutoEncoder_PET_Training.ipynb b/docs/notebooks/tutorial/AutoEncoder_PET_Training.ipynb index 47973cce..1bc90548 100644 --- a/docs/notebooks/tutorial/AutoEncoder_PET_Training.ipynb +++ b/docs/notebooks/tutorial/AutoEncoder_PET_Training.ipynb @@ -2,6 +2,7 @@ "cells": [ { "cell_type": "markdown", + "id": "a5c34806", "metadata": {}, "source": [ "# Autoencoder Training With PyEarthTools\n", @@ -13,7 +14,8 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, + "id": "a079123e", "metadata": {}, "outputs": [], "source": [ @@ -36,7 +38,8 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, + "id": "0bb05545", "metadata": {}, "outputs": [], "source": [ @@ -51,6 +54,7 @@ }, { "cell_type": "markdown", + "id": "faecec86", "metadata": {}, "source": [ "## Site Archive\n", @@ -60,15 +64,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, + "id": "2b10298d", "metadata": {}, "outputs": [], "source": [ - "import site_archive_jasmin" + "import site_archive_nci" ] }, { "cell_type": "markdown", + "id": "c633afd9", "metadata": {}, "source": [ "## Build The Data Pipeline\n", @@ -78,9 +84,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, + "id": "da5d81d0", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "AttributeError", + "evalue": "module 'pyearthtools.pipeline.operations.xarray' has no attribute 'AlignDataVariableDimensionsToDatasetCoords'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mAttributeError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[7]\u001b[39m\u001b[32m, line 6\u001b[39m\n\u001b[32m 1\u001b[39m himawari = petdata.archive.Himawari(\u001b[33m\"\u001b[39m\u001b[33msurface_global_irradiance\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 3\u001b[39m training_pipeline = petpipe.Pipeline(\n\u001b[32m 4\u001b[39m himawari,\n\u001b[32m 5\u001b[39m petpipe.operations.xarray.Sort(order=[\u001b[33m\"\u001b[39m\u001b[33mtime\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mlatitude\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mlongitude\u001b[39m\u001b[33m\"\u001b[39m]),\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m \u001b[43mpetpipe\u001b[49m\u001b[43m.\u001b[49m\u001b[43moperations\u001b[49m\u001b[43m.\u001b[49m\u001b[43mxarray\u001b[49m\u001b[43m.\u001b[49m\u001b[43mAlignDataVariableDimensionsToDatasetCoords\u001b[49m(),\n\u001b[32m 7\u001b[39m petdata.transform.region.Bounding(-\u001b[32m35\u001b[39m, -\u001b[32m25\u001b[39m, \u001b[32m138\u001b[39m, \u001b[32m150\u001b[39m),\n\u001b[32m 8\u001b[39m petpipe.operations.xarray.normalisation.SingleValueDivision(\u001b[32m1200\u001b[39m),\n\u001b[32m 9\u001b[39m petpipe.operations.xarray.conversion.ToNumpy(),\n\u001b[32m 10\u001b[39m petpipe.operations.numpy.reshape.Rearrange(\u001b[33m\"\u001b[39m\u001b[33mc t h w -> t c h w\u001b[39m\u001b[33m\"\u001b[39m),\n\u001b[32m 11\u001b[39m iterator=petpipe.iterators.DateRange(\u001b[33m\"\u001b[39m\u001b[33m20200101T00\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33m20200301T00\u001b[39m\u001b[33m\"\u001b[39m, interval=\u001b[33m\"\u001b[39m\u001b[33m10 minutes\u001b[39m\u001b[33m\"\u001b[39m),\n\u001b[32m 12\u001b[39m exceptions_to_ignore=petdata.exceptions.DataNotFoundError,\n\u001b[32m 13\u001b[39m )\n\u001b[32m 15\u001b[39m training_pipeline\n", + "\u001b[31mAttributeError\u001b[39m: module 'pyearthtools.pipeline.operations.xarray' has no attribute 'AlignDataVariableDimensionsToDatasetCoords'" + ] + } + ], "source": [ "himawari = petdata.archive.Himawari(\"surface_global_irradiance\")\n", "\n", @@ -102,6 +121,7 @@ { "cell_type": "code", "execution_count": null, + "id": "5a320858", "metadata": {}, "outputs": [], "source": [ @@ -125,6 +145,7 @@ }, { "cell_type": "markdown", + "id": "11bbf028", "metadata": {}, "source": [ "## Define Train And Validation Splits\n", @@ -135,6 +156,7 @@ { "cell_type": "code", "execution_count": null, + "id": "a4c04dd4", "metadata": {}, "outputs": [], "source": [ @@ -148,6 +170,7 @@ }, { "cell_type": "markdown", + "id": "d6d0ccdd", "metadata": {}, "source": [ "## Define The Autoencoder\n", @@ -158,6 +181,7 @@ { "cell_type": "code", "execution_count": null, + "id": "e52c4944", "metadata": {}, "outputs": [], "source": [ @@ -192,6 +216,7 @@ }, { "cell_type": "markdown", + "id": "4eaf027d", "metadata": {}, "source": [ "## Wrap The Model For Lightning\n", @@ -202,6 +227,7 @@ { "cell_type": "code", "execution_count": null, + "id": "e0822a6f", "metadata": {}, "outputs": [], "source": [ @@ -251,6 +277,7 @@ { "cell_type": "code", "execution_count": null, + "id": "3659185e", "metadata": {}, "outputs": [], "source": [ @@ -261,6 +288,7 @@ }, { "cell_type": "markdown", + "id": "69747363", "metadata": {}, "source": [ "## Create The PET Lightning Data Module\n", @@ -271,6 +299,7 @@ { "cell_type": "code", "execution_count": null, + "id": "94fb4287", "metadata": {}, "outputs": [], "source": [ @@ -287,6 +316,7 @@ }, { "cell_type": "markdown", + "id": "396282a8", "metadata": {}, "source": [ "## Train With PET\n", @@ -297,6 +327,7 @@ { "cell_type": "code", "execution_count": null, + "id": "6bbb68d1", "metadata": {}, "outputs": [], "source": [ @@ -320,6 +351,7 @@ }, { "cell_type": "markdown", + "id": "0169975c", "metadata": {}, "source": [ "## Predict And Plot Reconstructions\n", @@ -329,9 +361,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, + "id": "12235bff", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'data_module' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m validation_loader = \u001b[43mdata_module\u001b[49m.val_dataloader()\n\u001b[32m 2\u001b[39m predictions = trainer.trainer.predict(model, dataloaders=validation_loader)\n\u001b[32m 4\u001b[39m x = torch.cat([batch[\u001b[33m\"\u001b[39m\u001b[33mx\u001b[39m\u001b[33m\"\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m batch \u001b[38;5;129;01min\u001b[39;00m predictions], dim=\u001b[32m0\u001b[39m).numpy()\n", + "\u001b[31mNameError\u001b[39m: name 'data_module' is not defined" + ] + } + ], "source": [ "validation_loader = data_module.val_dataloader()\n", "predictions = trainer.trainer.predict(model, dataloaders=validation_loader)\n", @@ -342,9 +387,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, + "id": "2b5cd2c7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'x' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[5]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m fig, axes = plt.subplots(\u001b[32m3\u001b[39m, \u001b[32m3\u001b[39m, figsize=(\u001b[32m12\u001b[39m, \u001b[32m10\u001b[39m), constrained_layout=\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[32m 2\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m row \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[32m3\u001b[39m):\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m axes[row, \u001b[32m0\u001b[39m].imshow(\u001b[43mx\u001b[49m[row, \u001b[32m0\u001b[39m], vmin=\u001b[32m0\u001b[39m, vmax=\u001b[32m1\u001b[39m)\n\u001b[32m 4\u001b[39m axes[row, \u001b[32m0\u001b[39m].set_title(\u001b[33m\"\u001b[39m\u001b[33mInput\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 5\u001b[39m axes[row, \u001b[32m1\u001b[39m].imshow(x_hat[row, \u001b[32m0\u001b[39m], vmin=\u001b[32m0\u001b[39m, vmax=\u001b[32m1\u001b[39m)\n", + "\u001b[31mNameError\u001b[39m: name 'x' is not defined" + ] + }, + { + "data": { + "image/png": "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z//Ba6r9vJUfpeRHPvmRT37kkx8jyY/qv5/RID/yyY988iOf/Bhp3PIjqwL//M//nE2ZMiX76U9/mh04cCC7++67s4suuih74403cucfOnQou/DCC7O77747O3DgQPbTn/40mzJlSvb000+P8corp9w9ufvuu7Pvfve72X/+539mr732WrZ+/fpsypQp2X//93+P8corq9x9Oevtt9/O5s2bl7W2tmZXXXXV2Cx2DBXZly9/+cvZ4sWLs66uruzw4cPZf/zHf2SvvvrqGK668srdl127dmWTJk3KfvCDH2SHDh3Kdu3alX32s5/NVqxYMcYrr5zOzs5sw4YN2TPPPJNFRPbcc8996PxqP2/lRyn5kU9+5JMf+eRHKflR3fczGuRHPvmRT37kkx+lxis/qqLsuvrqq7O2trYRY5/+9KezdevW5c7/+7//++zTn/70iLGvfe1r2Re+8IWKrXGslbsneT7zmc9kGzduHO2ljaui+7Jy5crsH/7hH7L7778/ybApd1/+5V/+JWtsbMyOHz8+FssbN+Xuyz/+4z9m8+bNGzH20EMPZbNmzarYGsfT+YRNtZ+38qOU/MgnP/LJj3zy48PJjw9U0/2MBvmRT37kkx/55MeHG8v8GPevMZ48eTL27dsXra2tI8ZbW1tj9+7dudfs2bOnZP71118fe/fujffff79iax0rRfbk9505cyZOnDgRF198cSWWOC6K7stjjz0Wr7/+etx///2VXuK4KLIvL7zwQixatCi+973vxWWXXRZXXnll3HPPPfG73/1uLJY8JorsS0tLSxw9ejQ6Ozsjy7J488034+mnn44bb7xxLJZclar5vJUfpeRHPvmRT37kkx+jo5rPW/lRSn7kkx/55Ec++TE6Ruu8rR3thZWrv78/Tp8+HU1NTSPGm5qaoq+vL/eavr6+3PmnTp2K/v7+mDFjRsXWOxaK7Mnv+/73vx/vvvtu3HzzzZVY4rgosi+//vWvY926dbFr166orR33H/eKKLIvhw4dildeeSXq6+vjueeei/7+/vj6178eb731VjLfmy+yLy0tLbF9+/ZYuXJl/O///m+cOnUqvvzlL8cPf/jDsVhyVarm81Z+lJIf+eRHPvmRT36Mjmo+b+VHKfmRT37kkx/55MfoGK3zdtw/2XVWTU3NiOdZlpWM/aH5eeMTWbl7ctaTTz4Z3/nOd2LHjh1xySWXVGp54+Z89+X06dNxyy23xMaNG+PKK68cq+WNm3J+Xs6cORM1NTWxffv2uPrqq+OGG26IBx98MB5//PGk3l2JKG9fDhw4EKtXr4777rsv9u3bFy+++GIcPnw42traxmKpVavaz1v5UUp+5JMf+eRHPvnx0VX7eSs/SsmPfPIjn/zIJz8+utE4b8e9ap4+fXpMnjy5pOk8duxYSZt31qWXXpo7v7a2NqZNm1axtY6VInty1o4dO+LOO++Mp556Kq699tpKLnPMlbsvJ06ciL1790Z3d3d885vfjIgPDtksy6K2tjZ27twZ11xzzZisvZKK/LzMmDEjLrvssmhsbBwemz9/fmRZFkePHo0rrriiomseC0X2paOjI5YuXRr33ntvRER87nOfi4suuiiWLVsWDzzwwIR/17aIaj5v5Ucp+ZFPfuSTH/nkx+io5vNWfpSSH/nkRz75kU9+jI7ROm/H/ZNdU6dOjebm5ujq6hox3tXVFS0tLbnXLFmypGT+zp07Y9GiRTFlypSKrXWsFNmTiA/eUbn99tvjiSeeSPI7vuXuS0NDQ/zyl7+M/fv3Dz/a2triU5/6VOzfvz8WL148VkuvqCI/L0uXLo3f/va38c477wyPvfbaazFp0qSYNWtWRdc7Vorsy//b3h2rNBJFARie1RAIPoEQ0MbGThHbND6CnUgaH0CtfAoLIVoFO19DA/ZTGSvBQrAVAmnPVmY3O5fFgUwSx++DVEkx9yL3h2PIHY/H2crK9LG4urqaZdmf/yb8NMt83upHkX6k6UeafqTpx2ws83mrH0X6kaYfafqRph+zMbPzttTP2Vfk83rOfr8fw+EwTk9PY21tLV5fXyMi4uLiIo6Pjyef/7yK8uzsLIbDYfT7/dpe/fvVPbm7u4tGoxG9Xi/e398nr4+Pj0UtoRJl9+Vfdb0Npey+jEajaLfbcXh4GE9PTzEYDGJraytOTk4WtYRKlN2X29vbaDQacX19HS8vL/H4+Bh7e3uxv7+/qCXM3Gg0ijzPI8/zyLIsLi8vI8/zyXXI3+281Y8i/UjTjzT9SNOPIv1Y7vXMgn6k6UeafqTpR9Gi+rEUw66IiF6vFxsbG9FsNmN3dzcGg8HkvW63G51OZ+rzDw8PsbOzE81mMzY3N+Pm5mbOT1y9MnvS6XQiy7LCq9vtzv/BK1b2b+VvdY1NRPl9eX5+joODg2i1WtFut+P8/DzG4/Gcn7p6Zffl6uoqtre3o9Vqxfr6ehwdHcXb29ucn7o69/f3/z0rvuN5qx9F+pGmH2n6kaYf0/Rj+dczC/qRph9p+pGmH9MW1Y9fET/0u3EAAAAA1M7Cf7MLAAAAAGbFsAsAAACA2jDsAgAAAKA2DLsAAAAAqA3DLgAAAABqw7ALAAAAgNow7AIAAACgNgy7AAAAAKgNwy4AAAAAasOwCwAAAIDaMOwCAAAAoDZ+A9TQYIT9hQUWAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "fig, axes = plt.subplots(3, 3, figsize=(12, 10), constrained_layout=True)\n", "for row in range(3):\n", @@ -360,6 +428,7 @@ }, { "cell_type": "markdown", + "id": "adf4f4c4", "metadata": {}, "source": [ "## Next Steps\n", @@ -370,13 +439,21 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "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", - "pygments_lexer": "ipython3" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" } }, "nbformat": 4,