From a14b3c5553799d87bca0c9e15430c243447b500c Mon Sep 17 00:00:00 2001
From: Brian Nord <184985+bnord@users.noreply.github.com>
Date: Mon, 18 Nov 2024 11:59:50 -0600
Subject: [PATCH 1/5] upload notebook tutorial
---
...geClassificationWithTensorflow_Draft.ipynb | 1870 +++++++++++++++++
1 file changed, 1870 insertions(+)
create mode 100644 AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb
diff --git a/AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb b/AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb
new file mode 100644
index 0000000..9939bcd
--- /dev/null
+++ b/AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb
@@ -0,0 +1,1870 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "tags": []
+ },
+ "source": [
+ " \n",
+ " AI0: Introduction to AI-based Image Classification with Tensorflow \n",
+ "Contact author: Brian Nord \n",
+ "Last verified to run: YYYY-MM-DD \n",
+ "LSST Science Pipelines version: ?? \n",
+ "Container size: medium \n",
+ "Targeted learning level: beginner "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "jce50kKEfHC1"
+ },
+ "source": [
+ "**Description:** An introduction to the classification of images with AI-based classification algorithms."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "jce50kKEfHC1"
+ },
+ "source": [
+ "**Skills:** Examine AI training data, prepare it for a classification task, perform classification with a neural network, and examine the diagnostics of the classification task."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**LSST Data Products:** None; MNIST data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Packages:** numpy, matplotlib, sklearn, tensorflow"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Credits and Acknowledgments:** None"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Get Support:**\n",
+ "Find DP0-related documentation and resources at dp0.lsst.io. Questions are welcome as new topics in the Support - Data Preview 0 Category of the Rubin Community Forum. Rubin staff will respond to all questions posted there."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 1. Introduction\n",
+ "\n",
+ "This Jupyter Notebook introduces artificial intelligence (AI)-based image classification. It demonstrates how to perform a few key steps:\n",
+ "1. examine and prepare data for classification;\n",
+ "2. train an AI algorithm;\n",
+ "3. plot diagnostics of the training performance;\n",
+ "4. initially assess those diagnostics. \n",
+ "\n",
+ "AI is a class of algorithms for building statistical models. These algorithms primarily use data for training, as opposed to models that use analytic formulae or models that are based on physical reasoning. Machine learning is a subclass of algorithms -- e.g., random forests. Deep learning is a subclass of algorithms -- e.g., neural networks. \n",
+ "\n",
+ "This notebook uses `tensorflow`, one of the two most commonly used `python` libraries for deep learning. `Tensorflow` is often easier to use because of how it handles data sets and the logic used for model building. However, it is typically also difficult to develop network models creatively. We use `tensorflow` first in this series of tutorials so that users who are new to deep learning can focus on learning AI. In later tutorials, we will use `pytorch` because it is more flexible and more commonly used in science applications. \n",
+ "\n",
+ "This notebook uses [MNIST AI benchmarking data](https://en.wikipedia.org/wiki/MNIST_database). In a future notebook, we will we'll use stars and galaxies drawn from DP0 data.\n",
+ "\n",
+ "The use of data in this notebook requires a medium-sized ram allocation (8Gi).\n",
+ "\n",
+ "The end of this notebook contains a Glossary of Terms and a comment regarding usage of terms in AI contexts."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%reload_ext pycodestyle_magic\n",
+ "%flake8_on\n",
+ "import logging\n",
+ "logging.getLogger(\"flake8\").setLevel(logging.FATAL)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "V3xHhKu6c5-e"
+ },
+ "source": [
+ "### 1.1. Import Packages\n",
+ "\n",
+ "[`numpy`](https://numpy.org/) is a widely used Python library for computations and mathematical operations on multi-dimensional arrays.\n",
+ "\n",
+ "[`matplotlib`](https://matplotlib.org/) is a widely used Python plot library. \n",
+ "\n",
+ "[`tensorflow`](https://www.tensorflow.org) is a widely used library from Google for fast tensor operations --- often used for building neural network models. \n",
+ "\n",
+ "[`sklearn`](https://scikit-learn.org/stable/) is a library for machine learning."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "puW54XTfdo1C"
+ },
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import os\n",
+ "import datetime\n",
+ "\n",
+ "import matplotlib.pyplot as plt\n",
+ "from matplotlib.pyplot import cm\n",
+ "\n",
+ "import tensorflow as tf\n",
+ "\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.metrics import ConfusionMatrixDisplay, confusion_matrix\n",
+ "from sklearn.metrics import roc_curve, roc_auc_score, auc, RocCurveDisplay\n",
+ "from sklearn.preprocessing import LabelBinarizer"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.2 Define Functions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def normalizeInputs(x_temp, input_minimum, input_maximum):\n",
+ " \"\"\"Normalize a datum that is an input to the neural network\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_temp: `numpy.array`\n",
+ " image data\n",
+ " input_minimum: `float`\n",
+ " minimum value for normalization\n",
+ " input_maximum: `float`\n",
+ " maximum value for normalization\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " x_temp_norm: `numpy.array`\n",
+ " normalized image data\n",
+ " \"\"\"\n",
+ " x_temp_norm = (x_temp - input_minimum)/input_maximum\n",
+ " return x_temp_norm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def createFileUidTimestamp():\n",
+ " \"\"\"Create a timestamp for a filename.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " None\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " file_uid_timestamp : `string`\n",
+ " String from date and time.\n",
+ " \"\"\"\n",
+ " file_uid_timestamp = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
+ " return file_uid_timestamp\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def createFileName(file_prefix=\"\", file_location=\"Data/Sandbox/\",\n",
+ " file_suffix=\"\", useuid=True, verbose=True):\n",
+ " \"\"\"Create a file name.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " file_prefix: `string`\n",
+ " prefix of file name\n",
+ " file_location: `string`\n",
+ " path to file\n",
+ " file_suffix: `string`\n",
+ " suffix/extension of file name\n",
+ " useuid: 'bool'\n",
+ " choose to use a unique id\n",
+ " verbose: 'bool'\n",
+ " choose to print the file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " file_final: `string`\n",
+ " filename used for saving\n",
+ " \"\"\"\n",
+ " if useuid:\n",
+ " file_uid = createFileUidTimestamp()\n",
+ " else:\n",
+ " file_uid = \"\"\n",
+ "\n",
+ " file_final = file_location + file_prefix + \"_\" + file_uid + file_suffix\n",
+ "\n",
+ " if verbose:\n",
+ " print(file_final)\n",
+ "\n",
+ " return file_final\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotArrayImageExamples(x_tra, y_tra, num=10,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot an array of examples of images and labels\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_tra: `numpy.ndarray`\n",
+ " training data images\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training data labels\n",
+ " num: `int`, optional\n",
+ " number examples to plot\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " num_row = 2\n",
+ " num_col = 5\n",
+ " images = x_tra[:num]\n",
+ " labels = y_tra[:num]\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ " for i in range(num):\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " ax.imshow(images[i], cmap='gray')\n",
+ " ax.set_title('Label: {}'.format(labels[i]))\n",
+ "\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotROCMulticlassOnevsrest(y_tra, y_tes, y_pred_tes, label_target_list,\n",
+ " color_list,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot Receiver Operator Curve for one-vs-rest scenario\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training data images\n",
+ " y_tes: `numpy.ndarray`\n",
+ " test data images\n",
+ " y_pred_tes: `numpy.ndarray`\n",
+ " test data predicted labels\n",
+ " label_target_list: 'list'\n",
+ " color_list: 'list'\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " file_final: `string`\n",
+ " \"\"\"\n",
+ " fig, ax = plt.subplots(figsize=(6, 6))\n",
+ "\n",
+ " for label_target, color in zip(label_target_list, color_list):\n",
+ "\n",
+ " label_binarizer = LabelBinarizer().fit(y_tra)\n",
+ " y_onehot_tes = label_binarizer.transform(y_tes)\n",
+ "\n",
+ " class_id = np.flatnonzero(label_binarizer.classes_ == label_target)[0]\n",
+ "\n",
+ " display = RocCurveDisplay.from_predictions(\n",
+ " y_onehot_tes[:, class_id],\n",
+ " y_pred_tes[:, class_id],\n",
+ " name=f\"{label_target} vs the rest\",\n",
+ " color=color,\n",
+ " ax=ax,\n",
+ " plot_chance_level=(class_id == 0)\n",
+ " )\n",
+ "\n",
+ " _ = display.ax_.set(\n",
+ " xlabel=\"False Positive Rate\",\n",
+ " ylabel=\"True Positive Rate\",\n",
+ " title=\"ROC: One-vs-Rest\",\n",
+ " )\n",
+ "\n",
+ " if save_file:\n",
+ " createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotROCMulticlassOnevsone(y_tra, y_tes, y_pred_tes, label_target_list,\n",
+ " color_list, save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot Receiver Operator Curve for one-vs-one scenario\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training data true labels\n",
+ " y_tes: `numpy.ndarray`\n",
+ " test data true labels\n",
+ " y_pred_tes: `numpy.ndarray`\n",
+ " test data predicted labels\n",
+ " label_target_list: 'list'\n",
+ " color_list: 'list'\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " fig, ax = plt.subplots(figsize=(6, 6))\n",
+ "\n",
+ " for label_target, color in zip(label_target_list, color_list):\n",
+ "\n",
+ " label_binarizer = LabelBinarizer().fit(y_tra)\n",
+ " y_onehot_tes = label_binarizer.transform(y_tes)\n",
+ "\n",
+ " class_id = np.flatnonzero(label_binarizer.classes_ == label_target)[0]\n",
+ "\n",
+ " display = RocCurveDisplay.from_predictions(\n",
+ " y_onehot_tes[:, class_id],\n",
+ " y_pred_tes[:, class_id],\n",
+ " name=f\"{label_target} vs the rest\",\n",
+ " color=color,\n",
+ " ax=ax,\n",
+ " plot_chance_level=(class_id == 0)\n",
+ " )\n",
+ "\n",
+ " _ = display.ax_.set(\n",
+ " xlabel=\"False Positive Rate\",\n",
+ " ylabel=\"True Positive Rate\",\n",
+ " title=\"ROC: One-vs-Rest\",\n",
+ " )\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotArrayHistogramExamples(x_tra, y_tra, num=10,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histograms of image pixel values\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_tra: `numpy.ndarray`\n",
+ " training image data\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training label data\n",
+ " num: `int`, optional\n",
+ " number of examples to show\n",
+ " file_prefix: 'string', optional\n",
+ " prefix of file name\n",
+ " file_location: 'string', optional\n",
+ " path to file\n",
+ " file_suffix: 'string', optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " n_bins = 10\n",
+ " num = 10\n",
+ " num_row = 2\n",
+ " num_col = 5\n",
+ " images = x_tra[:num]\n",
+ " labels = y_tra[:num]\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ "\n",
+ " for i in range(num):\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " ax.hist(images[i], bins=n_bins)\n",
+ " ax.set_title('Label: {}'.format(labels[i]))\n",
+ "\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotPredictionHistogram(y_prediction_a, y_prediction_b=None,\n",
+ " y_prediction_c=None, n_classes=None,\n",
+ " n_objects_a=None, n_colors=None,\n",
+ " title_a=None, title_b=None,\n",
+ " title_c=None, label_a=None,\n",
+ " label_b=None, label_c=None,\n",
+ " alpha=0.5, figsize=(12, 5),\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histogram of predicted labels\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " y_prediction_a: `numpy.ndarray`\n",
+ " y_prediction_b: `numpy.ndarray`, optional\n",
+ " y_prediction_c: `numpy.ndarray`, optional\n",
+ " n_classes: `int`, optional\n",
+ " n_objects_a: `int`, optional\n",
+ " n_colors: `int`, optional\n",
+ " title_a: `string`, optional\n",
+ " title_b: `string`, optional\n",
+ " title_c: `string`, optional\n",
+ " label_a: `string`, optional\n",
+ " label_b: `string`, optional\n",
+ " label_c: `string`, optional\n",
+ " alpha: `float`, optional\n",
+ " transparency\n",
+ " figsize: `tuple`, optional\n",
+ " figure size\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " ndim = y_prediction_a.ndim\n",
+ "\n",
+ " if ndim == 2:\n",
+ " fig, (axa, axb, axc) = plt.subplots(1, 3, figsize=figsize)\n",
+ " fig.subplots_adjust(wspace=0.35)\n",
+ " elif ndim == 1:\n",
+ " fig, ax = plt.subplots(figsize=figsize)\n",
+ "\n",
+ " shape_a = np.shape(y_prediction_a)\n",
+ "\n",
+ " if n_objects_a is None:\n",
+ " n_objects_a = shape_a[0]\n",
+ "\n",
+ " if ndim == 2:\n",
+ " if n_classes == None:\n",
+ " n_classes = shape_a[1]\n",
+ " if n_colors is None:\n",
+ " n_colors = n_classes\n",
+ " elif ndim == 1:\n",
+ " if n_colors is None:\n",
+ " n_colors = 1\n",
+ "\n",
+ " if ndim == 2:\n",
+ " colors = cm.Purples(np.linspace(0, 1, n_colors))\n",
+ " xlabel = \"Probability for Each Class\"\n",
+ "\n",
+ " axa.set_ylim(0, n_objects_a)\n",
+ " axa.set_xlabel(xlabel)\n",
+ " axa.set_title(title_a)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axa.hist(y_prediction_a[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " shape_b = np.shape(y_prediction_b)\n",
+ " axb.set_ylim(0, shape_b[0])\n",
+ " axb.set_xlabel(xlabel)\n",
+ " axb.set_title(title_b)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axb.hist(y_prediction_b[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " shape_c = np.shape(y_prediction_c)\n",
+ " axc.set_ylim(0, shape_c[0])\n",
+ " axc.set_xlabel(xlabel)\n",
+ " axc.set_title(title_c)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axc.hist(y_prediction_c[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " elif ndim == 1:\n",
+ " ya, xa, _ = plt.hist(y_prediction_a, alpha=alpha, color='purple',\n",
+ " label=label_a)\n",
+ " y_max_list = [max(ya)]\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " yb, xb, _ = plt.hist(y_prediction_b, alpha=alpha, color='blue',\n",
+ " label=label_b)\n",
+ " y_max_list.append(max(yb))\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " yc, xc, _ = plt.hist(y_prediction_c, alpha=alpha, color='green',\n",
+ " label=label_c)\n",
+ " y_max_list.append(max(yc))\n",
+ "\n",
+ " plt.ylim(0, np.max(y_max_list)*1.1)\n",
+ " plt.xlabel(\"Top Choice-Class\")\n",
+ "\n",
+ " plt.legend(loc='upper right')\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotLossHistory(history, figsize=(8, 5),\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot loss history of the model as function of epoch\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " history: `keras.src.callbacks.history.History`\n",
+ " keras callback history object containing the losses at each epoch\n",
+ " figsize: `tuple`, optional\n",
+ " figure size\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=figsize)\n",
+ "\n",
+ " loss_tra = np.array(history.history['loss'])\n",
+ " loss_val = np.array(history.history['val_loss'])\n",
+ " loss_dif = loss_val - loss_tra\n",
+ "\n",
+ " ax1.plot(loss_tra, label='Training')\n",
+ " ax1.plot(loss_val, label='Validation')\n",
+ " ax1.legend()\n",
+ "\n",
+ " ax2.plot(loss_dif, color='red', label='residual')\n",
+ " ax2.axhline(y=0, color='grey', linestyle='dashed', label='zero bias')\n",
+ " ax2.sharex(ax1)\n",
+ " ax2.legend()\n",
+ "\n",
+ " ax1.set_title('Loss History')\n",
+ " ax1.set_ylabel('Loss')\n",
+ " ax2.set_ylabel('Loss Residual')\n",
+ " ax2.set_xlabel('Epoch')\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotConfusionMatrix(cm_tra, cm_val, cm_tes, save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot the confusion matrix of predictions.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " confusion_matrix_tra: `numpy.ndarray`\n",
+ " confusion matrix for the training data\n",
+ " confusion_matrix_val: `numpy.ndarray`\n",
+ " confusion matrix for the validation data\n",
+ " confusion_matrix_tes: `numpy.ndarray`\n",
+ " confusion matrix for the test data\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ "\n",
+ " cm_display_tra = ConfusionMatrixDisplay(confusion_matrix=cm_tra)\n",
+ " cm_display_val = ConfusionMatrixDisplay(confusion_matrix=cm_val)\n",
+ " cm_display_tes = ConfusionMatrixDisplay(confusion_matrix=cm_tes)\n",
+ "\n",
+ " fig, (axa, axb, axc) = plt.subplots(1, 3, figsize=(22, 5))\n",
+ "\n",
+ " cm_display_tra.plot(ax=axa)\n",
+ " cm_display_val.plot(ax=axb)\n",
+ " cm_display_tes.plot(ax=axc)\n",
+ "\n",
+ " axa.set_title(\"Training\")\n",
+ " axb.set_title(\"Validation\")\n",
+ " axc.set_title(\"Testing\")\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotArrayImageConfusion(x_tra, y_tra, y_pred_tra_topchoice,\n",
+ " title_main=None, num=10,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot images of examples objects that are misclassified.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_tra: `numpy.ndarray`\n",
+ " training image data\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training label data\n",
+ " y_pred_tra_topchoice: `numpy.ndarray`\n",
+ " top choice of the predicted labels\n",
+ " title_main: `string`, optional\n",
+ " title for the plot\n",
+ " num: `int`, optional\n",
+ " number of examples\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " num_row = 2\n",
+ " num_col = 5\n",
+ " images = x_tra[:num]\n",
+ " labels_true = y_tra[:num]\n",
+ " labels_pred = y_pred_tra_topchoice[:num]\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ "\n",
+ " fig.patch.set_linewidth(5)\n",
+ " fig.patch.set_edgecolor('cornflowerblue')\n",
+ "\n",
+ " for i in range(num):\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " ax.imshow(images[i], cmap='gray')\n",
+ " ax.set_title(r'True: {}'.format(labels_true[i]) + '\\n'\n",
+ " + 'Pred: {}'.format(labels_pred[i]))\n",
+ "\n",
+ " fig.suptitle(title_main)\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotArrayHistogramConfusion(x_tra, y_tra, y_pred_tra_topchoice,\n",
+ " title_main=None, num=10,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histograms of pixel values for images that are misclassified.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_tra: `numpy.ndarray`\n",
+ " training image data\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training label data\n",
+ " y_pred_tra_topchoice: `numpy.ndarray`\n",
+ " top choice of the predicted labels\n",
+ " title_main: `string`, optional\n",
+ " title of plot\n",
+ " num: `int`, optional\n",
+ " number of examples\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " n_bins = 10\n",
+ " num_row = 2\n",
+ " num_col = 5\n",
+ " images = x_tra[:num]\n",
+ " labels_true = y_tra[:num]\n",
+ " labels_pred = y_pred_tra_topchoice[:num]\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ "\n",
+ " fig.patch.set_linewidth(5)\n",
+ " fig.patch.set_edgecolor('cornflowerblue')\n",
+ "\n",
+ " for i in range(num):\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " ax.hist(images[i], bins=n_bins)\n",
+ " ax.set_title(r'True: {}'.format(labels_true[i]) + '\\n'\n",
+ " + 'Pred: {}'.format(labels_pred[i]))\n",
+ "\n",
+ " fig.suptitle(title_main)\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.3 Define Paths for Data and Plots"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Neural network training (i.e., model fitting) typically requires many numerical experiments to achieve an ideal model. To facilitate the comparison of these experiments/models, it is helpful to organize data carefully. We set paths for the model weight parameters and diagnostic figures. We also set the variable `run_label` for each training run. We also save these paths in a dictionary to facilitate passing information to plotting functions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "run_label = \"Run000\"\n",
+ "\n",
+ "path_dict = {'run_label': run_label,\n",
+ " 'dir_data_model': \"Data/Models/\",\n",
+ " 'dir_data_figures': \"Data/Figures/\",\n",
+ " 'file_model_prefix': \"Model\",\n",
+ " 'file_figure_prefix': \"Figure\",\n",
+ " 'file_figure_suffix': \".png\",\n",
+ " 'file_model_suffix': \".keras\"\n",
+ " }\n",
+ "\n",
+ "if not os.path.exists(path_dict['dir_data_model']):\n",
+ " os.makedirs(path_dict['dir_data_model'])\n",
+ "\n",
+ "if not os.path.exists(path_dict['dir_data_figures']):\n",
+ " os.makedirs(path_dict['dir_data_figures'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "jce50kKEfHC1"
+ },
+ "source": [
+ "## 2. Load and Prepare data: MNIST Handwritten Digits"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "-dHXIDGEfLmO"
+ },
+ "source": [
+ "### 2.1. Download Dataset"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "-dHXIDGEfLmO"
+ },
+ "source": [
+ "The [`MNIST handwritten digits dataset`](https://ieeexplore.ieee.org/document/6296535) comprises 10 classes --- one for each digit. This is a useful dataset for learning the basics of neural networks and other AI algorithms. MNIST is one of a few canonical AI benchmark data sets for image classification. `tensorflow` has a simple function easily downloading the MNIST data to your local server for free. It automatically downloads the data into.\n",
+ "\n",
+ "The **input** data are held in `x_`, while the **output** (aka, label) data are held in `y_`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "zDRvT2QkfISn",
+ "outputId": "68276f81-5e32-443a-d9c3-5291ef61715c"
+ },
+ "outputs": [],
+ "source": [
+ "mnist = tf.keras.datasets.mnist\n",
+ "train_temp, test_temp = mnist.load_data()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "O4FPxkLKiJKe"
+ },
+ "source": [
+ "### 2.2. Split Data into Train/Validation/Test"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "O4FPxkLKiJKe"
+ },
+ "source": [
+ "It is essential to split for a proper 'blind' analysis and optimization of an AI model.\n",
+ "\n",
+ "There are three primary data sets used in model optimization:\n",
+ "\n",
+ "* **Training** (`_tra`) data is used directly by the algorithm to update the parameters of the AI model -- e.g., the weights of the computational neurons on the edges in neural networks.\n",
+ "* **Validation** (`_val`) data is used indirectly to update the hyperparameters of the AI model -- e.g., the batchsize, the learning rate, or the layers in the architecture of a neural network. Each time the neural network has completed training with the training data, the human looks at those diagnostics when run on the training and the validation data.\n",
+ "* **Test(ing)** (`_tes`) data is only used when the model is trained and validated and will no longer be update or further trained. \n",
+ "\n",
+ "The `TF` class automatically downloads data into training and test data sets. Therefore, we use the `sklearn` `train_test_split()` function to further split the training set into training and validation data sets. We then \n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "RgjGyErDfNrg"
+ },
+ "outputs": [],
+ "source": [
+ "fraction_validation = 0.25"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# set the test data sets from the temp data at read-in\n",
+ "x_tes, y_tes = test_temp[0], test_temp[1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# set the training and validata data sets from the temp data at read-in\n",
+ "# use the sklearn train_test_split function\n",
+ "x_tra, x_val, y_tra, y_val = train_test_split(train_temp[0], train_temp[1],\n",
+ " test_size=fraction_validation,\n",
+ " random_state=1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "e8Ab7Yx7v1CY"
+ },
+ "source": [
+ "### 2.3. Normalize data\n",
+ "\n",
+ "First, we make sure that the input data are floats. This allows us to perform computations on the real number line for the inputs.\n",
+ "\n",
+ "Second, we normalize the data according to the maximum value in all the data sets. The inputs will all exist on a smaller range. This improves the stability of the training."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "ci1q1O8hv8U6"
+ },
+ "outputs": [],
+ "source": [
+ "# set to floats\n",
+ "x_tra = x_tra.astype('float32')\n",
+ "x_val = x_val.astype('float32')\n",
+ "x_tes = x_tes.astype('float32')\n",
+ "\n",
+ "# calculate min and max across all input images\n",
+ "input_minimum = np.min([np.min(x_tra), np.min(x_val), np.min(x_tes)])\n",
+ "input_maximum = np.max([np.max(x_tra), np.max(x_val), np.max(x_tes)])\n",
+ "\n",
+ "print(\"Before\")\n",
+ "print(\"min/max\", np.min(x_tra), np.max(x_tra))\n",
+ "\n",
+ "x_tra = normalizeInputs(x_tra, input_minimum, input_maximum)\n",
+ "x_val = normalizeInputs(x_val, input_minimum, input_maximum)\n",
+ "x_tes = normalizeInputs(x_tes, input_minimum, input_maximum)\n",
+ "\n",
+ "print(\"After\")\n",
+ "print(\"min/max\", np.min(x_tra), np.max(x_tra))\n",
+ "\n",
+ "# get shapes\n",
+ "image_shape = x_tra[0, :, :].shape"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "CdwlTbFafOYc"
+ },
+ "source": [
+ "### 2.4. Examine Raw Data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "CdwlTbFafOYc"
+ },
+ "source": [
+ "Review data shapes. \n",
+ "\n",
+ "The zeroth elements of the `x` and `y` shapes should match. The first and second elements of `x` should be equal: these are the dimensions of the images. The image size, in part determines the depth of the neural network that can be created."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Print the data shapes to make sure you understand how many objects there are and what the number of pixels is for each image."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 484
+ },
+ "id": "u3nrxn00fRUE",
+ "outputId": "5bac7964-621b-4984-be23-8e711bd00dc4"
+ },
+ "outputs": [],
+ "source": [
+ "print('check data shapes')\n",
+ "print('x_train:', x_tra.shape)\n",
+ "print('y_train:', y_tra.shape)\n",
+ "print('x_valid:', x_val.shape)\n",
+ "print('y_valid:', y_val.shape)\n",
+ "print('x_test:', x_tes.shape)\n",
+ "print('y_test:', y_tes.shape)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot examples to gain visual familiarity. Do these all look like hand-written digits?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 484
+ },
+ "id": "u3nrxn00fRUE",
+ "outputId": "5bac7964-621b-4984-be23-8e711bd00dc4"
+ },
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Example_Image_Array\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "plotArrayImageExamples(x_tra, y_tra,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot pixel distributions to further understand data. Is it normalized? Do the disributions of the pixel values make sense according to what you see in the related images above? \n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Example_Histogram_Array\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotArrayHistogramExamples(x_tra, y_tra,\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "rmAXXIHOfUnD"
+ },
+ "source": [
+ "## 3. Train Model: Dense Neural Network"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-07-14T14:21:02.040978Z",
+ "iopub.status.busy": "2024-07-14T14:21:02.040269Z",
+ "iopub.status.idle": "2024-07-14T14:21:02.043255Z",
+ "shell.execute_reply": "2024-07-14T14:21:02.042798Z",
+ "shell.execute_reply.started": "2024-07-14T14:21:02.040956Z"
+ },
+ "id": "bKRmx2k2wNtE"
+ },
+ "source": [
+ "### 3.1. Define Model Training Parameters"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-07-14T14:21:02.040978Z",
+ "iopub.status.busy": "2024-07-14T14:21:02.040269Z",
+ "iopub.status.idle": "2024-07-14T14:21:02.043255Z",
+ "shell.execute_reply": "2024-07-14T14:21:02.042798Z",
+ "shell.execute_reply.started": "2024-07-14T14:21:02.040956Z"
+ },
+ "id": "bKRmx2k2wNtE"
+ },
+ "source": [
+ "Define optimizer\n",
+ "Define loss\n",
+ "Define accuracy\n",
+ "Define batch_size\n",
+ "Define epochs\n",
+ "Define metrics"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "tlgJk3oLwRnh"
+ },
+ "outputs": [],
+ "source": [
+ "epochs = 10\n",
+ "batch_size = 32\n",
+ "verbose = True\n",
+ "optimizer = \"sgd\"\n",
+ "loss = tf.keras.losses.SparseCategoricalCrossentropy()\n",
+ "metrics = ['accuracy']\n",
+ "dropout_rate = 0.3\n",
+ "learning_rate = 0.01\n",
+ "momentum = 0.9\n",
+ "seed = 1000"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the random seed for neural network weight initialization"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tf.keras.utils.set_random_seed(seed)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "rmAXXIHOfUnD"
+ },
+ "source": [
+ "### 3.2. Define Model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "rmAXXIHOfUnD"
+ },
+ "source": [
+ "Define Sequential Model\n",
+ "Define layers\n",
+ "Define flat layer\n",
+ "Define dense layers\n",
+ "Define activation function; define types activation functions -- sigmoid and relu\n",
+ "Define weights and biases"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "U6vymJn1wJBu"
+ },
+ "outputs": [],
+ "source": [
+ "model_layers = [tf.keras.layers.Input(shape=image_shape),\n",
+ " tf.keras.layers.Flatten(),\n",
+ " tf.keras.layers.Dense(256, activation='sigmoid'),\n",
+ " tf.keras.layers.Dense(64, activation='sigmoid'),\n",
+ " tf.keras.layers.Dropout(dropout_rate),\n",
+ " tf.keras.layers.Dense(10, activation='softmax')]\n",
+ "\n",
+ "model = tf.keras.models.Sequential(model_layers)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "U6vymJn1wJBu"
+ },
+ "source": [
+ "View a summary of the network architecture. Examine the shapes of the layers and the numbers of parameters. Too few parameters may prevent the model from being flexible enough to model the data. Too many parameters could lead to overfitting of the model and a high computational cost."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "U6vymJn1wJBu"
+ },
+ "outputs": [],
+ "source": [
+ "model.summary()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-07-14T14:21:02.040978Z",
+ "iopub.status.busy": "2024-07-14T14:21:02.040269Z",
+ "iopub.status.idle": "2024-07-14T14:21:02.043255Z",
+ "shell.execute_reply": "2024-07-14T14:21:02.042798Z",
+ "shell.execute_reply.started": "2024-07-14T14:21:02.040956Z"
+ },
+ "id": "bKRmx2k2wNtE"
+ },
+ "source": [
+ "### 3.3. Compile and Train Model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Compile the model with the model settings created earlier."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "YwLTHCccwTeo",
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "model.compile(optimizer=optimizer, loss=loss, metrics=metrics)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Train (fit) the model. The output `history` contains the loss value of the training data and the validation data for each epoch."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "history = model.fit(x_tra, y_tra,\n",
+ " batch_size=batch_size,\n",
+ " epochs=epochs,\n",
+ " validation_data=(x_val, y_val),\n",
+ " verbose=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Save the model as a `.keras` zip archive so that it can be used later -- e.g., for comparison to other models."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_model_prefix'] + \"_\" + path_dict['run_label']\n",
+ "file_name_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_model'],\n",
+ " file_suffix=path_dict['file_model_suffix'],\n",
+ " useuid=True,\n",
+ " verbose=True)\n",
+ "\n",
+ "model.save(file_name_final)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "suHSArn6wb27"
+ },
+ "source": [
+ "## 4. Diagnosing the Results of the Classification Model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.1. Key Terms for Diagnostic Metrics\n",
+ "\n",
+ "We use the following diagnostics to assess the status of the network optimization and efficacy. \n",
+ "https://scikit-learn.org/stable/modules/model_evaluation.html\n",
+ "\n",
+ "\n",
+ "* **Metrics**\n",
+ " * Loss:\n",
+ " * Accuracy: Use as a rough indicator of model training progress/convergence for balanced datasets. For model performance, use only in combination with other metrics. Avoid for imbalanced datasets. Consider using another metric.\n",
+ " * tpr (Recall): Use when false negatives are more expensive than false positives.\n",
+ " * for: Use when false positives are more expensive than false negatives.\n",
+ " * precision: Use when it's very important for positive predictions to be accurate.\n",
+ " * \n",
+ "* **Generalization Error**: The Generalization Error (GE) is the difference in loss when the model is applied to training data versus when it is applied to validation data and test data.\n",
+ "* **Confusion Matrix**:\n",
+ "* **Receiver Operator Characteristic (ROC) Curve**:\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.2. Classification Predictions"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Predict classification probabilities on the training, validation and test sets."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_pred_tra = model.predict(x_tra, verbose=True)\n",
+ "y_pred_val = model.predict(x_val, verbose=True)\n",
+ "y_pred_tes = model.predict(x_tes, verbose=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Identify what the top-choice class is for each object in the training, validation and test sets."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_pred_tra_topchoice = y_pred_tra.argmax(axis=1)\n",
+ "y_pred_val_topchoice = y_pred_val.argmax(axis=1)\n",
+ "y_pred_tes_topchoice = y_pred_tes.argmax(axis=1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"10 probabilities for each object:\", np.shape(y_pred_tra))\n",
+ "print(\"Top choice for each object:\", np.shape(y_pred_tra_topchoice))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Histograms of prediction distributions by class"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Histograms_top_choice\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "plotPredictionHistogram(y_pred_tra_topchoice,\n",
+ " y_prediction_b=y_pred_val_topchoice,\n",
+ " y_prediction_c=y_pred_tes_topchoice,\n",
+ " label_a=\"Training Set\",\n",
+ " label_b=\"Validation Set\",\n",
+ " label_c=\"Testing Set\",\n",
+ " figsize=(12, 5),\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Histograms_class_probabilities\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "plotPredictionHistogram(y_pred_tra,\n",
+ " y_prediction_b=y_pred_val,\n",
+ " y_prediction_c=y_pred_tes,\n",
+ " title_a='Training Set',\n",
+ " title_b='Validation Set',\n",
+ " title_c='Testing Set',\n",
+ " figsize=(15, 4),\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Observations about these histograms ...\n",
+ "1. very similar shapes across the data sets: that's good"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "jp-MarkdownHeadingCollapsed": true
+ },
+ "source": [
+ "### 4.3. Generalization Error\n",
+ "\n",
+ "The primary task in optimizing a network is to minimize the Generalization Error. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.3.1. Loss History: History of Loss and Accuracy during Training"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot the loss history for the validation and training sets. We reserve the test set for a 'blind' analysis."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "EIiJTdK-weWf"
+ },
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"LossHistory\"\\\n",
+ " + \"_\"\\\n",
+ " + path_dict['run_label']\n",
+ "plotLossHistory(history,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.3.2. Confusion Matrix: Bias in Trained Model?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Compute confusion matrices"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cm_tra = confusion_matrix(y_pred_tra_topchoice, y_tra)\n",
+ "cm_val = confusion_matrix(y_pred_val_topchoice, y_val)\n",
+ "cm_tes = confusion_matrix(y_pred_tes_topchoice, y_tes)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "plot confusion matrices for training, validation, and test samples (left, right, middle)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plotConfusionMatrix(cm_tra, cm_val, cm_tes)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.3.4. Investigating Errant Classifications: Look at the examples\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Choose a digit/class (human option/choice) for examination."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class_value = 2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Find all objects that have that class value. \n",
+ "Obtain indices for the true positives (tp's), false positives (fp's), true negatives (tn's), and false negatives (fn's)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ind_class_tp_tra = np.where((y_tra == class_value)\n",
+ " & (y_pred_tra_topchoice == class_value))[0]\n",
+ "\n",
+ "ind_class_fp_tra = np.where((y_tra != class_value)\n",
+ " & (y_pred_tra_topchoice == class_value))[0]\n",
+ "\n",
+ "ind_class_tn_tra = np.where((y_tra != class_value)\n",
+ " & (y_pred_tra_topchoice != class_value))[0]\n",
+ "\n",
+ "ind_class_fn_tra = np.where((y_tra == class_value)\n",
+ " & (y_pred_tra_topchoice != class_value))[0]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "plot examples of false positives"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_TruePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ "plotArrayImageConfusion(x_tra[ind_class_tp_tra],\n",
+ " y_tra[ind_class_tp_tra],\n",
+ " y_pred_tra_topchoice[ind_class_tp_tra],\n",
+ " title_main=\"True Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_FalsePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ "plotArrayImageConfusion(x_tra[ind_class_fp_tra],\n",
+ " y_tra[ind_class_fp_tra],\n",
+ " y_pred_tra_topchoice[ind_class_fp_tra],\n",
+ " title_main=\"False Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_TrueNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ "plotArrayImageConfusion(x_tra[ind_class_tn_tra],\n",
+ " y_tra[ind_class_tn_tra],\n",
+ " y_pred_tra_topchoice[ind_class_tn_tra],\n",
+ " title_main=\"True Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_FalseNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ "plotArrayImageConfusion(x_tra[ind_class_fn_tra],\n",
+ " y_tra[ind_class_fn_tra],\n",
+ " y_pred_tra_topchoice[ind_class_fn_tra],\n",
+ " title_main=\"False Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot histograms of images pixels of true positives, false positives, true negatives, and false negatives."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_TruePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ "plotArrayHistogramConfusion(x_tra[ind_class_tp_tra],\n",
+ " y_tra[ind_class_tp_tra],\n",
+ " y_pred_tra_topchoice[ind_class_tp_tra],\n",
+ " title_main=\"True Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_FalsePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ "plotArrayHistogramConfusion(x_tra[ind_class_fp_tra],\n",
+ " y_tra[ind_class_fp_tra],\n",
+ " y_pred_tra_topchoice[ind_class_fp_tra],\n",
+ " title_main=\"False Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_TrueNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ "plotArrayHistogramConfusion(x_tra[ind_class_tn_tra],\n",
+ " y_tra[ind_class_tn_tra],\n",
+ " y_pred_tra_topchoice[ind_class_tn_tra],\n",
+ " title_main=\"True Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_FalseNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ "plotArrayHistogramConfusion(x_tra[ind_class_fn_tra],\n",
+ " y_tra[ind_class_fn_tra],\n",
+ " y_pred_tra_topchoice[ind_class_fn_tra],\n",
+ " title_main=\"False Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 5. Exercises for the Learner"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Each time you train a new model, re-run all the diagnostic plots.\n",
+ "\n",
+ "1. How do the loss and accuracy histories change when batch size is small or large? Why?\n",
+ "2. Does the NN take more or less time (more or fewer epochs) to converge if the input image data are normalized or not normalized? Why?\n",
+ "3. How does the size of the training set affect the model's accuracy and loss -- keeping the number of epochs the same? Why?\n",
+ "3. How does the random seed for the weight initialization affect the model's accuracy and loss -- keeping the number of epochs the same?\n",
+ "5. Use the `time` module to estimate the time for the model fitting. Record that time. Increase and then decrease the number of weights in the NN by an order of magnitude. Train the NN for each of those models and record the times. How does the number of weights in the neural network affect the training time and model loss and accuracy?\n",
+ "6. Use the `time` module to estimate the time for the model fitting. Record that time. Increase and then decrease the number of layers in the NN. Train the NN for each of those models and record the times. How does the number of weights in the neural network affect the training time and model loss and accuracy?\n",
+ "7. Use the `time` module to estimate the time for the model fitting. Record that time. Add a convolutional layer to the NN. Train the NN for each of those models and record the times. How does the number of weights in the neural network affect the training time and model loss and accuracy?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 6. Glossary of neural network terms\n",
+ "\n",
+ "1. network weights\n",
+ "2. deep learning\n",
+ "3. machine learning\n",
+ "4. learning\n",
+ "5. activation function\n",
+ "6. pool(ing)\n",
+ "7. convolution\n",
+ "8. layer\n",
+ "9. loss function\n",
+ "10. confusion matrix\n",
+ "11. epoch\n",
+ "12. batch size\n",
+ "13. learning rate\n",
+ "14. momentum\n",
+ "15. stochastic gradient descent\n",
+ "16. optimizer\n",
+ "17. receiver operator characteristic (ROC)\n",
+ "18. area under the curve (AUC)\n",
+ "19. training\n",
+ "20. validation\n",
+ "21. testing\n",
+ "22. class\n",
+ "23. hyperparameter (vs. parameter)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 7. AI is math, not magic.\n",
+ "\n",
+ "AI is firmly based in math, computer science, and statistics. Additionally, some of the approaches are inspired by concepts or notions in biology (e.g., the computational neuron) and in physics (e.g., the reverse Boltzmann machine). \n",
+ "\n",
+ "Much of the jargon in AI is anthropomorphic, which can make it appear that some other than math is happening. For example, consider the following list of terms that are very often used in AI -- and what these terms actually mean mathematically.\n",
+ "\n",
+ "1. learn $\\rightarrow$ fit\n",
+ "2. hallucinate/lie $\\rightarrow$ predict incorrectly\n",
+ "3. understand $\\rightarrow$ model has converged\n",
+ "4. cheat $\\rightarrow$ more efficiently guesses the best weight parameters of the model\n",
+ "5. believe $\\rightarrow$ predict/infer based on statistical priors\n",
+ "\n",
+ "When we over-anthropomorphize this mathematical tool, we obfuscate how it actually works, and that makes it harder to build and refine models. That is, AI models are not 'learning' or 'understanding'; they are large-parameter models that are being fit to data. The only learning that's happening is what we do with these models."
+ ]
+ }
+ ],
+ "metadata": {
+ "colab": {
+ "provenance": [],
+ "toc_visible": true
+ },
+ "kernelspec": {
+ "display_name": "LSST",
+ "language": "python",
+ "name": "lsst"
+ },
+ "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.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
From 6e3d13758ec4f4404ff154b3301cc7539b2f792b Mon Sep 17 00:00:00 2001
From: MelissaGraham
Date: Mon, 25 Nov 2024 20:17:48 +0000
Subject: [PATCH 2/5] add 16a
---
README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 8ec5f12..9307751 100644
--- a/README.md
+++ b/README.md
@@ -36,6 +36,7 @@ Tutorial titles in **bold** have Spanish-language versions.
| 13a. Using The Image Cutout Tool With DP0.2 | Demonstration of the use of the image cutout tool with a few science applications. |
| 14. Injecting Synthetic Sources Into Single-Visit Images | Inject artificial stars and galaxies into images. |
| 15. Survey Property Maps | Use the tools to visualize full-area survey property maps. |
+| 16a. Introduction to Tensorflow | Learn to classify images with AI-based classification algorithms. |
## DP0.3 Tutorials
@@ -119,7 +120,7 @@ The *content* of these notebooks are licensed under the Apache 2.0 License. Tha
| **13a. Using The Image Cutout Tool With DP0.2** **Level:** Beginner **Description:** This notebook demonstrates how to use the Rubin Image Cutout Service. **Skills:** Run the Rubin Image Cutout Service for visual inspection of small cutouts of LSST images. **Data Products:** Images (deepCoadd, calexp), catalogs (objectTable, diaObject, truthTables, ivoa.ObsCore). **Packages:** PyVO, lsst.rsp.get_tap_service, lsst.pipe.tasks.registerImage, lsst.afw.display |
| **14. Injecting Synthetic Sources Into Single-Visit Images** **Level:** Advanced **Description:** This tutorial demonstrates a method to inject artificial sources (stars and galaxies) into calexp images using the measured point-spread function of the given calexp image. Confirmation that the synthetic sources were correctly injected into the image is done by running a difference imaging task from the pipelines. **Skills:** Use the `source_injection` tools to inject synthetic sources into images. Create a difference image from a `calexp` with injected sources. **Data Products:** Butler calexp images and corresponding src catalogs, goodSeeingDiff_templateExp images, and injection_catalogs. **Packages:** lsst.source.injection |
| **15. Survey Property Maps** **Level:** Intermediate **Description:** Use the tools to visualize full-area survey property maps. **Skills:** Load and visualize survey property maps using healsparse and skyproj. **Data Products:** Survey property maps. **Packages:** healsparse, skyproj, lsst.daf.butler |
-
+| **16a. Introduction to Tensorflow** **Level:** Beginner **Description:** An introduction to the classification of images with AI-based classification algorithms. **Skills:** Examine AI training data, prepare it for a classification task, perform classification with a neural network, and examine the diagnostics of the classification task. **Data Products:** MNIST data. **Packages:** sklearn, tensorflow |
| Skills in **DP0.3** Tutorial Notebooks |
|---|
From fab6265ebcbf5b8c9b20b759190b2dff59efea1d Mon Sep 17 00:00:00 2001
From: MelissaGraham
Date: Tue, 26 Nov 2024 00:28:51 +0000
Subject: [PATCH 3/5] MLG edits
---
...geClassificationWithTensorflow_Draft.ipynb | 293 ++++++++++++------
1 file changed, 192 insertions(+), 101 deletions(-)
diff --git a/AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb b/AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb
index 9939bcd..e7aafd0 100644
--- a/AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb
+++ b/AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb
@@ -7,10 +7,10 @@
},
"source": [
" \n",
- " AI0: Introduction to AI-based Image Classification with Tensorflow \n",
+ " Introduction to AI-based Image Classification with Tensorflow \n",
"Contact author: Brian Nord \n",
- "Last verified to run: YYYY-MM-DD \n",
- "LSST Science Pipelines version: ?? \n",
+ "Last verified to run: 2024-11-25 \n",
+ "LSST Science Pipelines version: Weekly 2024_42 \n",
"Container size: medium \n",
"Targeted learning level: beginner "
]
@@ -76,13 +76,25 @@
"\n",
"AI is a class of algorithms for building statistical models. These algorithms primarily use data for training, as opposed to models that use analytic formulae or models that are based on physical reasoning. Machine learning is a subclass of algorithms -- e.g., random forests. Deep learning is a subclass of algorithms -- e.g., neural networks. \n",
"\n",
- "This notebook uses `tensorflow`, one of the two most commonly used `python` libraries for deep learning. `Tensorflow` is often easier to use because of how it handles data sets and the logic used for model building. However, it is typically also difficult to develop network models creatively. We use `tensorflow` first in this series of tutorials so that users who are new to deep learning can focus on learning AI. In later tutorials, we will use `pytorch` because it is more flexible and more commonly used in science applications. \n",
+ "This notebook uses `tensorflow`, one of the two most commonly used `python` libraries for deep learning. `Tensorflow` is often easier to use because of how it handles data sets and the logic used for model building. However, it is typically also difficult to develop network models creatively. This tutorial is the first in a series, and uses `tensorflow` so that users who are new to deep learning can focus on learning AI. In later tutorials, `pytorch` will be used because it is more flexible and more commonly used in science applications. \n",
"\n",
- "This notebook uses [MNIST AI benchmarking data](https://en.wikipedia.org/wiki/MNIST_database). In a future notebook, we will we'll use stars and galaxies drawn from DP0 data.\n",
+ "Instead of using DP0 data, this tutorials uses [MNIST AI benchmarking data](https://en.wikipedia.org/wiki/MNIST_database), a large database of handwritten digits that is commonly used for training and testing machine learning algorithms. It is simple to understand, so that users who are new to deep learning can focus on learning AI. Later tutorials in this series will use stars and galaxies drawn from DP0 data.\n",
"\n",
- "The use of data in this notebook requires a medium-sized ram allocation (8Gi).\n",
+ "### 1.1. AI is math, not magic.\n",
"\n",
- "The end of this notebook contains a Glossary of Terms and a comment regarding usage of terms in AI contexts."
+ "AI is firmly based in math, computer science, and statistics. Additionally, some of the approaches are inspired by concepts or notions in biology (e.g., the computational neuron) and in physics (e.g., the reverse Boltzmann machine). \n",
+ "\n",
+ "Much of the jargon in AI is anthropomorphic, which can make it appear that some other than math is happening. For example, consider the following list of terms that are very often used in AI -- and what these terms actually mean mathematically.\n",
+ "\n",
+ "1. learn $\\rightarrow$ fit\n",
+ "2. hallucinate/lie $\\rightarrow$ predict incorrectly\n",
+ "3. understand $\\rightarrow$ model has converged\n",
+ "4. cheat $\\rightarrow$ more efficiently guesses the best weight parameters of the model\n",
+ "5. believe $\\rightarrow$ predict/infer based on statistical priors\n",
+ "\n",
+ "When we over-anthropomorphize this mathematical tool, we obfuscate how it actually works, and that makes it harder to build and refine models. That is, AI models are not 'learning' or 'understanding'; they are large-parameter models that are being fit to data. The only learning that's happening is what we do with these models.\n",
+ "\n",
+ "The end of this notebook contains a glossary of AI-related terms."
]
},
{
@@ -103,7 +115,7 @@
"id": "V3xHhKu6c5-e"
},
"source": [
- "### 1.1. Import Packages\n",
+ "### 1.2. Import packages\n",
"\n",
"[`numpy`](https://numpy.org/) is a widely used Python library for computations and mathematical operations on multi-dimensional arrays.\n",
"\n",
@@ -141,7 +153,13 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### 1.2 Define Functions"
+ "### 1.3. Define functions\n",
+ "\n",
+ "The following functions are defined and used throughout this notebook.\n",
+ "\n",
+ "It is not necessary to understand exactly what every funtion does in order to proceed with this tutorial.\n",
+ "\n",
+ "Execute all cells and move on to Section 2."
]
},
{
@@ -539,7 +557,7 @@
" n_objects_a = shape_a[0]\n",
"\n",
" if ndim == 2:\n",
- " if n_classes == None:\n",
+ " if n_classes is None:\n",
" n_classes = shape_a[1]\n",
" if n_colors is None:\n",
" n_colors = n_classes\n",
@@ -871,14 +889,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### 1.3 Define Paths for Data and Plots"
+ "### 1.4. Define paths for data and plots"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "Neural network training (i.e., model fitting) typically requires many numerical experiments to achieve an ideal model. To facilitate the comparison of these experiments/models, it is helpful to organize data carefully. We set paths for the model weight parameters and diagnostic figures. We also set the variable `run_label` for each training run. We also save these paths in a dictionary to facilitate passing information to plotting functions."
+ "Neural network training (i.e., model fitting) typically requires many numerical experiments to achieve an ideal model. To facilitate the comparison of these experiments/models, it is helpful to organize data carefully. \n",
+ "\n",
+ "Set the variable `run_label` for each training run. \n",
+ "Set paths for the model weight parameters and diagnostic figures, and\n",
+ "save these paths in the dictionary `path_dict` to facilitate passing information to plotting functions.\n",
+ "Check whether the paths exist, and if not, create them."
]
},
{
@@ -889,14 +912,16 @@
"source": [
"run_label = \"Run000\"\n",
"\n",
+ "temppath = os.getenv(\"HOME\") + '/dp02_16a_temp/'\n",
"path_dict = {'run_label': run_label,\n",
- " 'dir_data_model': \"Data/Models/\",\n",
- " 'dir_data_figures': \"Data/Figures/\",\n",
+ " 'dir_data_model': temppath + \"Data/Models/\",\n",
+ " 'dir_data_figures': temppath + \"Data/Figures/\",\n",
" 'file_model_prefix': \"Model\",\n",
" 'file_figure_prefix': \"Figure\",\n",
" 'file_figure_suffix': \".png\",\n",
" 'file_model_suffix': \".keras\"\n",
" }\n",
+ "del temppath\n",
"\n",
"if not os.path.exists(path_dict['dir_data_model']):\n",
" os.makedirs(path_dict['dir_data_model'])\n",
@@ -911,7 +936,7 @@
"id": "jce50kKEfHC1"
},
"source": [
- "## 2. Load and Prepare data: MNIST Handwritten Digits"
+ "## 2. Load and prepare data: MNIST Handwritten Digits"
]
},
{
@@ -920,7 +945,7 @@
"id": "-dHXIDGEfLmO"
},
"source": [
- "### 2.1. Download Dataset"
+ "### 2.1. Download the dataset"
]
},
{
@@ -929,9 +954,11 @@
"id": "-dHXIDGEfLmO"
},
"source": [
- "The [`MNIST handwritten digits dataset`](https://ieeexplore.ieee.org/document/6296535) comprises 10 classes --- one for each digit. This is a useful dataset for learning the basics of neural networks and other AI algorithms. MNIST is one of a few canonical AI benchmark data sets for image classification. `tensorflow` has a simple function easily downloading the MNIST data to your local server for free. It automatically downloads the data into.\n",
+ "The [MNIST handwritten digits dataset](https://ieeexplore.ieee.org/document/6296535) comprises 10 classes --- one for each digit. This is a useful dataset for learning the basics of neural networks and other AI algorithms. MNIST is one of a few canonical AI benchmark data sets for image classification. `Tensorflow` has a simple function easily downloading the MNIST data to your local server for free.\n",
"\n",
- "The **input** data are held in `x_`, while the **output** (aka, label) data are held in `y_`."
+ "Automatically download the data using `tf.keras.datasets.mnist`.\n",
+ "The `tf` class automatically downloads data into training and test data sets;\n",
+ "load them into variables `train_temp` and `test_temp`, respectively."
]
},
{
@@ -956,7 +983,7 @@
"id": "O4FPxkLKiJKe"
},
"source": [
- "### 2.2. Split Data into Train/Validation/Test"
+ "### 2.2. Split data into training, validation, and testing"
]
},
{
@@ -973,7 +1000,7 @@
"* **Validation** (`_val`) data is used indirectly to update the hyperparameters of the AI model -- e.g., the batchsize, the learning rate, or the layers in the architecture of a neural network. Each time the neural network has completed training with the training data, the human looks at those diagnostics when run on the training and the validation data.\n",
"* **Test(ing)** (`_tes`) data is only used when the model is trained and validated and will no longer be update or further trained. \n",
"\n",
- "The `TF` class automatically downloads data into training and test data sets. Therefore, we use the `sklearn` `train_test_split()` function to further split the training set into training and validation data sets. We then \n"
+ "Set the fraction of the data set to use for validation as 25%."
]
},
{
@@ -987,24 +1014,37 @@
"fraction_validation = 0.25"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The **input** data are held in `x_`, while the **output** (aka, label) data are held in `y_`.\n",
+ "\n",
+ "Set the test data sets from `test_temp`, which was loaded above."
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "# set the test data sets from the temp data at read-in\n",
"x_tes, y_tes = test_temp[0], test_temp[1]"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use the `sklearn` `train_test_split()` function to further split the training set into training and validation data sets."
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "# set the training and validata data sets from the temp data at read-in\n",
- "# use the sklearn train_test_split function\n",
"x_tra, x_val, y_tra, y_val = train_test_split(train_temp[0], train_temp[1],\n",
" test_size=fraction_validation,\n",
" random_state=1)"
@@ -1018,9 +1058,10 @@
"source": [
"### 2.3. Normalize data\n",
"\n",
- "First, we make sure that the input data are floats. This allows us to perform computations on the real number line for the inputs.\n",
+ "Make sure that the input data are type float, to enable computations on the real number line for the inputs.\n",
"\n",
- "Second, we normalize the data according to the maximum value in all the data sets. The inputs will all exist on a smaller range. This improves the stability of the training."
+ "Calculate the minimum and maximum value across all data sub-sets.\n",
+ "Use the `normalizeInputs` function to normalize the data according to the minimum and maximum value in all the data sets. The inputs will all exist on a smaller range. This improves the stability of the training."
]
},
{
@@ -1031,27 +1072,20 @@
},
"outputs": [],
"source": [
- "# set to floats\n",
"x_tra = x_tra.astype('float32')\n",
"x_val = x_val.astype('float32')\n",
"x_tes = x_tes.astype('float32')\n",
"\n",
- "# calculate min and max across all input images\n",
"input_minimum = np.min([np.min(x_tra), np.min(x_val), np.min(x_tes)])\n",
"input_maximum = np.max([np.max(x_tra), np.max(x_val), np.max(x_tes)])\n",
"\n",
- "print(\"Before\")\n",
- "print(\"min/max\", np.min(x_tra), np.max(x_tra))\n",
+ "print(\"Before normalization, min and max: \", np.min(x_tra), np.max(x_tra))\n",
"\n",
"x_tra = normalizeInputs(x_tra, input_minimum, input_maximum)\n",
"x_val = normalizeInputs(x_val, input_minimum, input_maximum)\n",
"x_tes = normalizeInputs(x_tes, input_minimum, input_maximum)\n",
"\n",
- "print(\"After\")\n",
- "print(\"min/max\", np.min(x_tra), np.max(x_tra))\n",
- "\n",
- "# get shapes\n",
- "image_shape = x_tra[0, :, :].shape"
+ "print(\"After normalization, min and max: \", np.min(x_tra), np.max(x_tra))"
]
},
{
@@ -1060,7 +1094,7 @@
"id": "CdwlTbFafOYc"
},
"source": [
- "### 2.4. Examine Raw Data"
+ "### 2.4. Examine raw data"
]
},
{
@@ -1071,14 +1105,27 @@
"source": [
"Review data shapes. \n",
"\n",
- "The zeroth elements of the `x` and `y` shapes should match. The first and second elements of `x` should be equal: these are the dimensions of the images. The image size, in part determines the depth of the neural network that can be created."
+ "The variable `image_shape` will be used again in Section 3.2."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"The shape of the input training set is:\")\n",
+ "image_shape = x_tra[0, :, :].shape\n",
+ "print(image_shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "Print the data shapes to make sure you understand how many objects there are and what the number of pixels is for each image."
+ "The zeroth elements of the `x` and `y` shapes should match. The first and second elements of `x` should be equal: these are the dimensions of the images. The image size, in part determines the depth of the neural network that can be created.\n",
+ "\n",
+ "Print the data shapes to understand how many objects there are and what the number of pixels is for each image."
]
},
{
@@ -1094,7 +1141,6 @@
},
"outputs": [],
"source": [
- "print('check data shapes')\n",
"print('x_train:', x_tra.shape)\n",
"print('y_train:', y_tra.shape)\n",
"print('x_valid:', x_val.shape)\n",
@@ -1107,7 +1153,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Plot examples to gain visual familiarity. Do these all look like hand-written digits?"
+ "Plot examples to gain visual familiarity. All images should look like hand-written digits."
]
},
{
@@ -1136,7 +1182,13 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Plot pixel distributions to further understand data. Is it normalized? Do the disributions of the pixel values make sense according to what you see in the related images above? \n"
+ "> Figure 1: Two rows of five images, each a handwritten number in white on a black background.\n",
+ "\n",
+ "Plot the distributions of pixel values to further understand data.\n",
+ "\n",
+ "Note that all pixel data has been normalized, and pixels have values between 0 and 1 only.\n",
+ "\n",
+ "Note that the distribution of pixel values matches the images shown above: mostly black (values near 0) pixels, with some white (values near 1), and a few grey (values in between 0 and 1)."
]
},
{
@@ -1162,7 +1214,9 @@
"id": "rmAXXIHOfUnD"
},
"source": [
- "## 3. Train Model: Dense Neural Network"
+ "> Figure 2: Two rows of five plots, each showing the distribution of pixel values (number of pixels of a given value) for the handwritten digit images shown in Figure 1.\n",
+ "\n",
+ "## 3. Train the model: dense neural network"
]
},
{
@@ -1178,7 +1232,7 @@
"id": "bKRmx2k2wNtE"
},
"source": [
- "### 3.1. Define Model Training Parameters"
+ "### 3.1. Define model training parameters"
]
},
{
@@ -1194,12 +1248,17 @@
"id": "bKRmx2k2wNtE"
},
"source": [
- "Define optimizer\n",
- "Define loss\n",
- "Define accuracy\n",
- "Define batch_size\n",
- "Define epochs\n",
- "Define metrics"
+ " * `epochs` : \n",
+ " * `batch_size` : \n",
+ " * `verbose` : When `True`, the code will write more output to screen. This can help users diagnose issues.\n",
+ " * `optimizer` : \n",
+ " * `loss` : \n",
+ " * `metrics` : \n",
+ " * `dropout_rate` : \n",
+ " * `learning_rate` : \n",
+ " * `momentum` :\n",
+ "\n",
+ "Define the variables to hold the model training parameters."
]
},
{
@@ -1218,15 +1277,14 @@
"metrics = ['accuracy']\n",
"dropout_rate = 0.3\n",
"learning_rate = 0.01\n",
- "momentum = 0.9\n",
- "seed = 1000"
+ "momentum = 0.9"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "Set the random seed for neural network weight initialization"
+ "Set the random seed for neural network weight initialization."
]
},
{
@@ -1235,6 +1293,7 @@
"metadata": {},
"outputs": [],
"source": [
+ "seed = 1000\n",
"tf.keras.utils.set_random_seed(seed)"
]
},
@@ -1244,7 +1303,7 @@
"id": "rmAXXIHOfUnD"
},
"source": [
- "### 3.2. Define Model"
+ "### 3.2. Define the model"
]
},
{
@@ -1253,12 +1312,16 @@
"id": "rmAXXIHOfUnD"
},
"source": [
- "Define Sequential Model\n",
- "Define layers\n",
- "Define flat layer\n",
- "Define dense layers\n",
- "Define activation function; define types activation functions -- sigmoid and relu\n",
- "Define weights and biases"
+ " * layers : \n",
+ " * flat layer : \n",
+ " * dense layers : \n",
+ " * activation function : \n",
+ " * sigmoid : \n",
+ " * softmax : \n",
+ " * weights and biases : \n",
+ " * sequential model :\n",
+ "\n",
+ "Define `model_layers` and use it to set `model` as a sequential model."
]
},
{
@@ -1312,7 +1375,7 @@
"id": "bKRmx2k2wNtE"
},
"source": [
- "### 3.3. Compile and Train Model"
+ "### 3.3. Compile and train the model"
]
},
{
@@ -1383,29 +1446,31 @@
"id": "suHSArn6wb27"
},
"source": [
- "## 4. Diagnosing the Results of the Classification Model"
+ "## 4. Diagnosing the results of the classification model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "### 4.1. Key Terms for Diagnostic Metrics\n",
+ "### 4.1. Key terms for diagnostic metrics\n",
+ "\n",
+ "Use the following diagnostics to assess the status of the network optimization and efficacy. \n",
+ "\n",
+ "A good reference is this [scikit-learn page on metrics and scoring](https://scikit-learn.org/stable/modules/model_evaluation.html).\n",
+ "\n",
+ "**Metrics**\n",
+ " * Loss:\n",
+ " * Accuracy: Use as a rough indicator of model training progress/convergence for balanced datasets. For model performance, use only in combination with other metrics. Avoid for imbalanced datasets. Consider using another metric.\n",
+ " * True Positive Rate (TPR; \"Recall\"): Use when false negatives are more expensive than false positives.\n",
+ " * for: Use when false positives are more expensive than false negatives.\n",
+ " * precision: Use when it's very important for positive predictions to be accurate.\n",
"\n",
- "We use the following diagnostics to assess the status of the network optimization and efficacy. \n",
- "https://scikit-learn.org/stable/modules/model_evaluation.html\n",
+ "**Generalization Error**: The Generalization Error (GE) is the difference in loss when the model is applied to training data versus when it is applied to validation data and test data.\n",
"\n",
+ "**Confusion Matrix**:\n",
"\n",
- "* **Metrics**\n",
- " * Loss:\n",
- " * Accuracy: Use as a rough indicator of model training progress/convergence for balanced datasets. For model performance, use only in combination with other metrics. Avoid for imbalanced datasets. Consider using another metric.\n",
- " * tpr (Recall): Use when false negatives are more expensive than false positives.\n",
- " * for: Use when false positives are more expensive than false negatives.\n",
- " * precision: Use when it's very important for positive predictions to be accurate.\n",
- " * \n",
- "* **Generalization Error**: The Generalization Error (GE) is the difference in loss when the model is applied to training data versus when it is applied to validation data and test data.\n",
- "* **Confusion Matrix**:\n",
- "* **Receiver Operator Characteristic (ROC) Curve**:\n"
+ "**Receiver Operator Characteristic (ROC) Curve**:\n"
]
},
{
@@ -1451,6 +1516,13 @@
"y_pred_tes_topchoice = y_pred_tes.argmax(axis=1)"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Verify that the shapes `y_pred_tra` match the length of 45000, as in Section 2.4."
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -1465,7 +1537,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Histograms of prediction distributions by class"
+ "Use the `plotPredictionHistogram` function to plot histograms of prediction distributions by class."
]
},
{
@@ -1486,8 +1558,22 @@
" figsize=(12, 5),\n",
" file_prefix=file_prefix,\n",
" file_location=path_dict['dir_data_figures'],\n",
- " file_suffix=path_dict['file_figure_suffix'])\n",
- "\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 3: Histograms of the number of images for which the top-choice class was each number 0 through 9, for the training, validation, and test sets. Note that these are overlapping histograms, not stacked."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
"file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
" + \"Histograms_class_probabilities\"\\\n",
" + \"_\" + path_dict['run_label']\n",
@@ -1507,8 +1593,10 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Observations about these histograms ...\n",
- "1. very similar shapes across the data sets: that's good"
+ "> Figure 4: Histograms of the number of images (y-axis) that had a probability (x-axis) of being each class 0 through 9 (light to dark shades).\n",
+ "\n",
+ "In both of Figure 3 and 4, the histograms show very similar shapes across the classification categories.\n",
+ "This is a good sign because it indicates the model does not 'prefer' a class."
]
},
{
@@ -1526,14 +1614,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### 4.3.1. Loss History: History of Loss and Accuracy during Training"
+ "### 4.3.1. Loss History: history of loss and accuracy during training"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "Plot the loss history for the validation and training sets. We reserve the test set for a 'blind' analysis."
+ "Plot the loss history for the validation and training sets, but reserve the test set for a 'blind' analysis."
]
},
{
@@ -1558,14 +1646,16 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### 4.3.2. Confusion Matrix: Bias in Trained Model?"
+ "> Figure 5: In the top panel, the loss history as a function of epoch for the training and validation sets decreases with time, as it should as the model improves. In the bottom panel, the loss residual (validation - training) shows a dip at epoch 2, indicating the model caused a divergence in the training and validation set classifications, but that this was rectified in later epochs.\n",
+ "\n",
+ "### 4.3.2. Confusion matrix: look for bias in the trained model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "Compute confusion matrices"
+ "Compute the confusion matrices."
]
},
{
@@ -1583,7 +1673,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "plot confusion matrices for training, validation, and test samples (left, right, middle)"
+ "Plot the confusion matrices for the training, validation, and test samples (left, right, middle)."
]
},
{
@@ -1599,14 +1689,21 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### 4.3.4. Investigating Errant Classifications: Look at the examples\n"
+ "> Figure 6: Confusion matrices for the training, validation, and test sets (left to right). The number of images with a given true (y-axis) and predicted (x-axis) classification is written in each box, and boxes are colored based on the number (from purple to yellow). The diagonal represents images that were correctly classified."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.3.4. Investigating errant classifications: look at the examples"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "Choose a digit/class (human option/choice) for examination."
+ "Choose to investigate explore the digit classification `class_value` = 2."
]
},
{
@@ -1649,7 +1746,11 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "plot examples of false positives"
+ "Display 10 images that exemplify:\n",
+ " * true positives (correctly classified digits; a true 2 classified as 2);\n",
+ " * false positives (another digit classified as 2);\n",
+ " * true negatives (another digit classified as another digit); and\n",
+ " * false negatives (a true 2 classified as another digit)."
]
},
{
@@ -1711,6 +1812,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
+ "> Figure 7: Four panels of 10 images each, representing true positives (top), false positives (second), true negatives (third), and false negatives (bottom), for classification category 2.\n",
+ "\n",
"Plot histograms of images pixels of true positives, false positives, true negatives, and false negatives."
]
},
@@ -1773,6 +1876,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
+ "> Figure 8: Histograms of the pixel flux values for the images shown in Figure 7.\n",
+ "\n",
"## 5. Exercises for the Learner"
]
},
@@ -1825,21 +1930,7 @@
{
"cell_type": "markdown",
"metadata": {},
- "source": [
- "## 7. AI is math, not magic.\n",
- "\n",
- "AI is firmly based in math, computer science, and statistics. Additionally, some of the approaches are inspired by concepts or notions in biology (e.g., the computational neuron) and in physics (e.g., the reverse Boltzmann machine). \n",
- "\n",
- "Much of the jargon in AI is anthropomorphic, which can make it appear that some other than math is happening. For example, consider the following list of terms that are very often used in AI -- and what these terms actually mean mathematically.\n",
- "\n",
- "1. learn $\\rightarrow$ fit\n",
- "2. hallucinate/lie $\\rightarrow$ predict incorrectly\n",
- "3. understand $\\rightarrow$ model has converged\n",
- "4. cheat $\\rightarrow$ more efficiently guesses the best weight parameters of the model\n",
- "5. believe $\\rightarrow$ predict/infer based on statistical priors\n",
- "\n",
- "When we over-anthropomorphize this mathematical tool, we obfuscate how it actually works, and that makes it harder to build and refine models. That is, AI models are not 'learning' or 'understanding'; they are large-parameter models that are being fit to data. The only learning that's happening is what we do with these models."
- ]
+ "source": []
}
],
"metadata": {
From b97dbc45b35e9fe01ff1cbee9ba3ddeacd20eff9 Mon Sep 17 00:00:00 2001
From: Brian Nord <184985+bnord@users.noreply.github.com>
Date: Mon, 10 Feb 2025 08:23:26 -0600
Subject: [PATCH 4/5] commit for review
---
DP02_16a_Introduction_to_AI.ipynb.ipynb | 3212 +++++++++++++++++++++++
1 file changed, 3212 insertions(+)
create mode 100644 DP02_16a_Introduction_to_AI.ipynb.ipynb
diff --git a/DP02_16a_Introduction_to_AI.ipynb.ipynb b/DP02_16a_Introduction_to_AI.ipynb.ipynb
new file mode 100644
index 0000000..bceac82
--- /dev/null
+++ b/DP02_16a_Introduction_to_AI.ipynb.ipynb
@@ -0,0 +1,3212 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \n",
+ " Introduction to AI-based Image Classification with Pytorch \n",
+ "Contact author: Brian Nord \n",
+ "Last verified to run: 2024-07-01 \n",
+ "LSST Science Pipelines version: Weekly 2024_16 \n",
+ "Container size: medium \n",
+ "Targeted learning level: beginner "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Description:** An introduction to the classification of images with AI-based classification algorithms."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Skills:** Examine AI training data, prepare it for a classification task, perform classification with a neural network, and examine the diagnostics of the classification task."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**LSST Data Products:** None; MNIST data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Packages:** numpy, matplotlib, sklearn, pytorch"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Credits and Acknowledgments:** We thank Ryan Lau and Melissa Graham for feedback on the notebook."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Get Support:**\n",
+ "Find DP0-related documentation and resources at dp0.lsst.io. Questions are welcome as new topics in the Support - Data Preview 0 Category of the Rubin Community Forum. Rubin staff will respond to all questions posted there."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 1. Introduction\n",
+ "\n",
+ "This Jupyter Notebook introduces artificial intelligence (AI)-based image classification. It demonstrates how to perform a few key steps:\n",
+ "1. examine and prepare data for classification;\n",
+ "2. train an AI algorithm;\n",
+ "3. plot diagnostics of the training performance;\n",
+ "4. initially assess those diagnostics. \n",
+ "\n",
+ "AI is a class of algorithms for building statistical models. These algorithms primarily use data for training, as opposed to models that use analytic formulae or models that are based on physical reasoning. Machine learning is a subclass of algorithms -- e.g., random forests. Deep learning is a subclass of algorithms -- e.g., neural networks. \n",
+ "\n",
+ "In this notebook, we use `pytorch`, which is currently the library most often used in deep learning studies. `Pytorch` is more complicated to use in some ways --- i.e., requires acclimating to how it handles tensors, data sets, and model building. At the same time, there is more flexibility for overall model development: you can more easily get creative with model structures. \n",
+ "\n",
+ "Instead of using DP0 data, this tutorials uses [MNIST AI benchmarking data](https://en.wikipedia.org/wiki/MNIST_database), a large database of handwritten digits that is commonly used for training and testing machine learning algorithms. It is simple to understand, so that users who are new to deep learning can focus on learning AI. Later tutorials in this series will use stars and galaxies drawn from DP0 data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.1. AI is math, not magic.\n",
+ "\n",
+ "AI is firmly based in math, computer science, and statistics. Additionally, some of the approaches are inspired by concepts or notions in biology (e.g., the computational neuron) and in physics (e.g., the Reverse Boltzmann Machine). \n",
+ "\n",
+ "Much of the jargon in AI is anthropomorphic, which can make it appear that some other than math is happening. For example, consider the following list of terms that are very often used in AI -- and what these terms actually mean mathematically.\n",
+ "\n",
+ "1. `learn` $\\rightarrow$ fit\n",
+ "2. `hallucinate`/`lie` $\\rightarrow$ predict incorrectly\n",
+ "3. `understand` $\\rightarrow$ model fit has converged\n",
+ "4. `cheat` $\\rightarrow$ more efficiently guesses the best weight parameters of the model\n",
+ "5. `believe` $\\rightarrow$ predict/infer based on statistical priors\n",
+ "\n",
+ "When we over-anthropomorphize these mathematical concepts, we obfuscate how they actually work. That makes it harder to build and refine models. That is, AI models are not 'learning' or 'understanding'; they are merely large-parameter models that are being fit to data, and AI includes novel methods for that fitting process. The only learning that's happening is what humans do with these models.\n",
+ "\n",
+ "Many of the most useful AI-related terms are defined throughout this tutorial."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.2. Import packages\n",
+ "\n",
+ "[`numpy`](https://numpy.org/) is used for computations and mathematical operations on multi-dimensional arrays.\n",
+ "\n",
+ "[`matplotlib`](https://matplotlib.org/) is a plot library. \n",
+ "\n",
+ "[`sklearn`](https://scikit-learn.org/stable/) is a library for machine learning.\n",
+ "\n",
+ "[`torch`](https://www.pytorch.org) is used for fast tensor operations --- often used for building neural network models."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:40.895553Z",
+ "iopub.status.busy": "2025-02-09T23:00:40.895367Z",
+ "iopub.status.idle": "2025-02-09T23:00:49.712635Z",
+ "shell.execute_reply": "2025-02-09T23:00:49.711587Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:40.895535Z"
+ },
+ "id": "JyaaGkFE8VOl"
+ },
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import time\n",
+ "import datetime\n",
+ "import os\n",
+ "\n",
+ "import matplotlib\n",
+ "import matplotlib.pyplot as plt\n",
+ "from matplotlib.pyplot import cm\n",
+ "from matplotlib.colors import LogNorm\n",
+ "import seaborn as sns\n",
+ "\n",
+ "from sklearn.metrics import confusion_matrix\n",
+ "\n",
+ "import torch\n",
+ "import torch.nn as nn\n",
+ "import torch.optim as optim\n",
+ "import torch.nn.functional as F\n",
+ "import torchvision\n",
+ "from torch.utils.data import Dataset, DataLoader, Subset, random_split"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.3. Define functions"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The following functions are defined and used throughout this notebook. It is not necessary to understand exactly what every function does to proceed with this tutorial. Execute all cells and move on to Section 2."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:49.714597Z",
+ "iopub.status.busy": "2025-02-09T23:00:49.713821Z",
+ "iopub.status.idle": "2025-02-09T23:00:49.863235Z",
+ "shell.execute_reply": "2025-02-09T23:00:49.862202Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:49.714555Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def normalizeInputs(x_temp, input_minimum, input_maximum):\n",
+ " \"\"\"Normalize a datum that is an input to the neural network\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_temp: `numpy.array`\n",
+ " image data\n",
+ " input_minimum: `float`\n",
+ " minimum value for normalization\n",
+ " input_maximum: `float`\n",
+ " maximum value for normalization\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " x_temp_norm: `numpy.array`\n",
+ " normalized image data\n",
+ " \"\"\"\n",
+ " x_temp_norm = (x_temp - input_minimum)/input_maximum\n",
+ " return x_temp_norm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:49.866230Z",
+ "iopub.status.busy": "2025-02-09T23:00:49.865802Z",
+ "iopub.status.idle": "2025-02-09T23:00:49.998210Z",
+ "shell.execute_reply": "2025-02-09T23:00:49.997647Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:49.866185Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def createFileUidTimestamp():\n",
+ " \"\"\"Create a timestamp for a filename.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " None\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " file_uid_timestamp : `string`\n",
+ " String from date and time.\n",
+ " \"\"\"\n",
+ " file_uid_timestamp = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
+ " return file_uid_timestamp"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:49.998965Z",
+ "iopub.status.busy": "2025-02-09T23:00:49.998779Z",
+ "iopub.status.idle": "2025-02-09T23:00:50.155942Z",
+ "shell.execute_reply": "2025-02-09T23:00:50.154901Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:49.998948Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def createFileName(file_prefix=\"\", file_location=\"Data/Sandbox/\",\n",
+ " file_suffix=\"\", useuid=True, verbose=True):\n",
+ " \"\"\"Create a file name.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " file_prefix: `string`\n",
+ " prefix of file name\n",
+ " file_location: `string`\n",
+ " path to file\n",
+ " file_suffix: `string`\n",
+ " suffix/extension of file name\n",
+ " useuid: 'bool'\n",
+ " choose to use a unique id\n",
+ " verbose: 'bool'\n",
+ " choose to print the file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " file_final: `string`\n",
+ " filename used for saving\n",
+ " \"\"\"\n",
+ " if useuid:\n",
+ " file_uid = createFileUidTimestamp()\n",
+ " else:\n",
+ " file_uid = \"\"\n",
+ "\n",
+ " file_final = file_location + file_prefix + \"_\" + file_uid + file_suffix\n",
+ "\n",
+ " if verbose:\n",
+ " print(file_final)\n",
+ "\n",
+ " return file_final"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:50.157469Z",
+ "iopub.status.busy": "2025-02-09T23:00:50.157104Z",
+ "iopub.status.idle": "2025-02-09T23:00:50.298215Z",
+ "shell.execute_reply": "2025-02-09T23:00:50.297620Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:50.157432Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def plotArrayImageExamples(subset_train,\n",
+ " num_row=3, num_col=3,\n",
+ " object_index_start=0,\n",
+ " save_file=False,\n",
+ " file_prefix=\"ImageExamples\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot an array of examples of images and labels\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " subset_train: `numpy.ndarray`\n",
+ " training data images\n",
+ " num_row: `int`, optional\n",
+ " number of rows to plot\n",
+ " num_col: `int`, optional\n",
+ " number of columns to plot\n",
+ " object_index_start: `int`, optional\n",
+ " starting index for set of images to plot\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " From: https://pytorch.org/tutorials/beginner/basics/data_tutorial.html\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " labels_map = {\n",
+ " 0: \"0\",\n",
+ " 1: \"1\",\n",
+ " 2: \"2\",\n",
+ " 3: \"3\",\n",
+ " 4: \"4\",\n",
+ " 5: \"5\",\n",
+ " 6: \"6\",\n",
+ " 7: \"7\",\n",
+ " 8: \"8\",\n",
+ " 9: \"9\",\n",
+ " }\n",
+ "\n",
+ " figure = plt.figure(figsize=(8, 8))\n",
+ "\n",
+ " for i in range(1, num_row * num_col + 1):\n",
+ " sample_idx = object_index_start + i\n",
+ " img, label = subset_train[sample_idx]\n",
+ " figure.add_subplot(num_row, num_col, i)\n",
+ " plt.title(labels_map[label])\n",
+ " plt.axis(\"off\")\n",
+ " plt.imshow(img.squeeze(), cmap=\"gray\")\n",
+ "\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:50.299193Z",
+ "iopub.status.busy": "2025-02-09T23:00:50.298861Z",
+ "iopub.status.idle": "2025-02-09T23:00:50.463522Z",
+ "shell.execute_reply": "2025-02-09T23:00:50.462425Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:50.299174Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
pycodestyleINFO: 20:35: W291 trailing whitespace
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "def plotArrayHistogramExamples(subset_train,\n",
+ " num_row=3, num_col=3,\n",
+ " n_bins=10,\n",
+ " object_index_start=0,\n",
+ " save_file=False,\n",
+ " file_prefix=\"HistogramExamples\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histograms of image pixel values\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " subset_train: `numpy.ndarray`\n",
+ " training data images\n",
+ " num_row: `int`, optional\n",
+ " number of rows to plot\n",
+ " num_col: `int`, optional\n",
+ " number of columns to plot\n",
+ " n_bins: `int`, optional\n",
+ " number of bins in histogram \n",
+ " object_index_start: `int`, optional\n",
+ " starting index for set of images to plot\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " labels_map = {\n",
+ " 0: \"0\",\n",
+ " 1: \"1\",\n",
+ " 2: \"2\",\n",
+ " 3: \"3\",\n",
+ " 4: \"4\",\n",
+ " 5: \"5\",\n",
+ " 6: \"6\",\n",
+ " 7: \"7\",\n",
+ " 8: \"8\",\n",
+ " 9: \"9\",\n",
+ " }\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ "\n",
+ " for i in range(0, num_row * num_col + 0):\n",
+ " sample_idx = object_index_start + i\n",
+ " img, label = subset_train[sample_idx]\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " img_temp = img[0, :, :]\n",
+ " img_temp = np.array(img_temp).flat\n",
+ " ax.hist(img_temp, bins=n_bins, color='gray')\n",
+ " ax.set_title(labels_map[label])\n",
+ " ax.set_xlabel(\"Pixel Values\")\n",
+ "\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:50.465449Z",
+ "iopub.status.busy": "2025-02-09T23:00:50.465057Z",
+ "iopub.status.idle": "2025-02-09T23:00:50.612203Z",
+ "shell.execute_reply": "2025-02-09T23:00:50.611165Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:50.465413Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def predict(dataloader, model, dataset_type):\n",
+ " \"\"\"Predict labels of inputs\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " dataloader: `numpy.ndarray`\n",
+ " training data images\n",
+ " model: `int`, optional\n",
+ " number of rows to plot\n",
+ " dataset_type: `int`, optional\n",
+ " number of columns to plot\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " y_prob_list: `numpy.ndarray`\n",
+ " probabilities for each class for each input\n",
+ " y_choice_list: `numpy.ndarray`\n",
+ " highest-probability class for each input\n",
+ " y_true_list: `numpy.ndarray`\n",
+ " true class for each input\n",
+ " x_list: `numpy.ndarray`\n",
+ " input\n",
+ " \"\"\"\n",
+ " size = len(dataloader.dataset)\n",
+ " num_batches = len(dataloader)\n",
+ " model.eval()\n",
+ "\n",
+ " y_prob_list = []\n",
+ " y_choice_list = []\n",
+ " y_true_list = []\n",
+ " x_list = []\n",
+ "\n",
+ " i = 0\n",
+ " loss, accuracy = 0, 0\n",
+ " with torch.no_grad():\n",
+ " for inputs, labels in dataloader:\n",
+ " inputs = inputs.to(device)\n",
+ " labels = labels.to(device)\n",
+ "\n",
+ " y = model(inputs)\n",
+ " y_prob = torch.softmax(y, dim=1)\n",
+ " y_choice = (torch.max(torch.exp(y), 1)[1]).data.cpu().numpy()\n",
+ "\n",
+ " loss += loss_fn(y, labels).item()\n",
+ " loss /= num_batches\n",
+ " accuracy_temp = y.argmax(1) == labels\n",
+ " accuracy += accuracy_temp.type(torch.float).sum().item()\n",
+ " accuracy /= size\n",
+ "\n",
+ " y_prob_list.append(y_prob.detach())\n",
+ " y_choice_list.append(y_choice)\n",
+ " y_true_list.append(labels)\n",
+ " x_list.append(inputs)\n",
+ " labels = labels.data.cpu().numpy()\n",
+ "\n",
+ " i += 1\n",
+ "\n",
+ " y_prob_list = np.array(y_prob_list)\n",
+ " y_choice_list = np.array(y_choice_list)\n",
+ " y_true_list = np.array(y_true_list)\n",
+ " x_list = np.array(x_list)\n",
+ "\n",
+ " y_prob_list = np.squeeze(y_prob_list)\n",
+ " y_choice_list = np.squeeze(y_choice_list)\n",
+ " y_true_list = np.squeeze(y_true_list)\n",
+ " x_list = np.squeeze(x_list)\n",
+ "\n",
+ " print(f\"{dataset_type : <10} data set ...\\\n",
+ " Accuracy: {(100*accuracy):>0.1f}%, Avg loss: {loss:>8f}\")\n",
+ "\n",
+ " return y_prob_list, y_choice_list, y_true_list, x_list"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:50.614078Z",
+ "iopub.status.busy": "2025-02-09T23:00:50.613693Z",
+ "iopub.status.idle": "2025-02-09T23:00:50.840445Z",
+ "shell.execute_reply": "2025-02-09T23:00:50.839384Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:50.614040Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def plotPredictionHistogram(y_prediction_a, y_prediction_b=None,\n",
+ " y_prediction_c=None, n_classes=None,\n",
+ " n_objects_a=None, n_colors=None,\n",
+ " title_a=None, title_b=None,\n",
+ " title_c=None, label_a=None,\n",
+ " label_b=None, label_c=None,\n",
+ " alpha=1.0, figsize=(12, 5),\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " xlabel_plot=\"Class label\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histogram of predicted labels\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " y_prediction_a: `numpy.ndarray`\n",
+ " y_prediction_b: `numpy.ndarray`, optional\n",
+ " y_prediction_c: `numpy.ndarray`, optional\n",
+ " n_classes: `int`, optional\n",
+ " n_objects_a: `int`, optional\n",
+ " n_colors: `int`, optional\n",
+ " title_a: `string`, optional\n",
+ " title_b: `string`, optional\n",
+ " title_c: `string`, optional\n",
+ " label_a: `string`, optional\n",
+ " label_b: `string`, optional\n",
+ " label_c: `string`, optional\n",
+ " alpha: `float`, optional\n",
+ " transparency\n",
+ " figsize: `tuple`, optional\n",
+ " figure size\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " ndim = y_prediction_a.ndim\n",
+ "\n",
+ " if ndim == 2:\n",
+ " fig, (axa, axb, axc) = plt.subplots(1, 3, figsize=figsize)\n",
+ " fig.subplots_adjust(wspace=0.35)\n",
+ " elif ndim == 1:\n",
+ " fig, ax = plt.subplots(figsize=figsize)\n",
+ "\n",
+ " shape_a = np.shape(y_prediction_a)\n",
+ "\n",
+ " if n_objects_a is None:\n",
+ " n_objects_a = shape_a[0]\n",
+ "\n",
+ " if ndim == 2:\n",
+ " if n_classes is None:\n",
+ " n_classes = shape_a[1]\n",
+ " if n_colors is None:\n",
+ " n_colors = n_classes\n",
+ " elif ndim == 1:\n",
+ " if n_colors is None:\n",
+ " n_colors = 1\n",
+ "\n",
+ " if ndim == 2:\n",
+ " colors = cm.Purples(np.linspace(0, 1, n_colors))\n",
+ " xlabel = \"Probability for Each Class\"\n",
+ "\n",
+ " axa.set_ylim(0, n_objects_a)\n",
+ " axa.set_xlabel(xlabel)\n",
+ " axa.set_title(title_a)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axa.hist(y_prediction_a[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " shape_b = np.shape(y_prediction_b)\n",
+ " axb.set_ylim(0, shape_b[0])\n",
+ " axb.set_xlabel(xlabel)\n",
+ " axb.set_title(title_b)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axb.hist(y_prediction_b[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " shape_c = np.shape(y_prediction_c)\n",
+ " axc.set_ylim(0, shape_c[0])\n",
+ " axc.set_xlabel(xlabel)\n",
+ " axc.set_title(title_c)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axc.hist(y_prediction_c[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " elif ndim == 1:\n",
+ " ya, xa, _ = plt.hist(y_prediction_a, alpha=alpha, color='orange',\n",
+ " label=label_a)\n",
+ " y_max_list = [max(ya)]\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " yb, xb, _ = plt.hist(y_prediction_b, alpha=alpha, color='green',\n",
+ " label=label_b)\n",
+ " y_max_list.append(max(yb))\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " yc, xc, _ = plt.hist(y_prediction_c, alpha=alpha, color='purple',\n",
+ " label=label_c)\n",
+ " y_max_list.append(max(yc))\n",
+ "\n",
+ " plt.ylim(0, np.max(y_max_list)*1.1)\n",
+ " plt.xlabel(xlabel_plot)\n",
+ "\n",
+ " plt.legend(loc='upper right')\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:50.842666Z",
+ "iopub.status.busy": "2025-02-09T23:00:50.842278Z",
+ "iopub.status.idle": "2025-02-09T23:00:51.020147Z",
+ "shell.execute_reply": "2025-02-09T23:00:51.019064Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:50.842629Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def plotTrueLabelHistogram(y_prediction_a, y_prediction_b=None,\n",
+ " y_prediction_c=None, n_classes=None,\n",
+ " n_objects_a=None, n_colors=None,\n",
+ " title_a=None, title_b=None,\n",
+ " title_c=None, label_a=None,\n",
+ " label_b=None, label_c=None,\n",
+ " alpha=1.0, figsize=(12, 5),\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " xlabel_plot=\"Class label\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histogram of predicted labels\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " y_prediction_a: `numpy.ndarray`\n",
+ " y_prediction_b: `numpy.ndarray`, optional\n",
+ " y_prediction_c: `numpy.ndarray`, optional\n",
+ " n_classes: `int`, optional\n",
+ " n_objects_a: `int`, optional\n",
+ " n_colors: `int`, optional\n",
+ " title_a: `string`, optional\n",
+ " title_b: `string`, optional\n",
+ " title_c: `string`, optional\n",
+ " label_a: `string`, optional\n",
+ " label_b: `string`, optional\n",
+ " label_c: `string`, optional\n",
+ " alpha: `float`, optional\n",
+ " transparency\n",
+ " figsize: `tuple`, optional\n",
+ " figure size\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ "\n",
+ " ndim = y_prediction_a.ndim\n",
+ "\n",
+ " if ndim == 2:\n",
+ " fig, (axa, axb, axc) = plt.subplots(1, 3, figsize=figsize)\n",
+ " fig.subplots_adjust(wspace=0.35)\n",
+ " elif ndim == 1:\n",
+ " fig, ax = plt.subplots(figsize=figsize)\n",
+ "\n",
+ " shape_a = np.shape(y_prediction_a)\n",
+ "\n",
+ " if n_objects_a is None:\n",
+ " n_objects_a = shape_a[0]\n",
+ "\n",
+ " if ndim == 2:\n",
+ " if n_classes is None:\n",
+ " n_classes = shape_a[1]\n",
+ " if n_colors is None:\n",
+ " n_colors = n_classes\n",
+ " elif ndim == 1:\n",
+ " if n_colors is None:\n",
+ " n_colors = 1\n",
+ "\n",
+ " if ndim == 2:\n",
+ " colors = cm.Purples(np.linspace(0, 1, n_colors))\n",
+ " xlabel = \"Probability for Each Class\"\n",
+ "\n",
+ " axa.set_ylim(0, n_objects_a)\n",
+ " axa.set_xlabel(xlabel)\n",
+ " axa.set_title(title_a)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axa.hist(y_prediction_a[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " shape_b = np.shape(y_prediction_b)\n",
+ " axb.set_ylim(0, shape_b[0])\n",
+ " axb.set_xlabel(xlabel)\n",
+ " axb.set_title(title_b)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axb.hist(y_prediction_b[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " shape_c = np.shape(y_prediction_c)\n",
+ " axc.set_ylim(0, shape_c[0])\n",
+ " axc.set_xlabel(xlabel)\n",
+ " axc.set_title(title_c)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axc.hist(y_prediction_c[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " elif ndim == 1:\n",
+ " ya, xa, _ = plt.hist(y_prediction_a, alpha=alpha, color='orange',\n",
+ " label=label_a)\n",
+ " y_max_list = [max(ya)]\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " yb, xb, _ = plt.hist(y_prediction_b, alpha=alpha, color='green',\n",
+ " label=label_b)\n",
+ " y_max_list.append(max(yb))\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " yc, xc, _ = plt.hist(y_prediction_c, alpha=alpha, color='purple',\n",
+ " label=label_c)\n",
+ " y_max_list.append(max(yc))\n",
+ "\n",
+ " plt.ylim(0, np.max(y_max_list)*1.1)\n",
+ " plt.xlabel(xlabel_plot)\n",
+ "\n",
+ " plt.legend(loc='upper right')\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:51.021678Z",
+ "iopub.status.busy": "2025-02-09T23:00:51.021279Z",
+ "iopub.status.idle": "2025-02-09T23:00:51.185198Z",
+ "shell.execute_reply": "2025-02-09T23:00:51.184585Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:51.021643Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def plotLossHistory(history, figsize=(8, 5),\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot loss history of the model as function of epoch\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " history: `keras.src.callbacks.history.History`\n",
+ " keras callback history object containing the losses at each epoch\n",
+ " figsize: `tuple`, optional\n",
+ " figure size\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=figsize)\n",
+ "\n",
+ " loss_tra = np.array(history['loss'])\n",
+ " loss_val = np.array(history['val_loss'])\n",
+ " loss_dif = loss_val - loss_tra\n",
+ "\n",
+ " ax1.plot(loss_tra, label='Training')\n",
+ " ax1.plot(loss_val, label='Validation')\n",
+ " ax1.legend()\n",
+ "\n",
+ " ax2.plot(loss_dif, color='red', label='residual')\n",
+ " ax2.axhline(y=0, color='grey', linestyle='dashed', label='zero bias')\n",
+ " ax2.sharex(ax1)\n",
+ " ax2.legend()\n",
+ "\n",
+ " ax1.set_title('Loss History')\n",
+ " ax1.set_ylabel('Loss')\n",
+ " ax2.set_ylabel('Loss Residual')\n",
+ " ax2.set_xlabel('Epoch')\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:51.186307Z",
+ "iopub.status.busy": "2025-02-09T23:00:51.186054Z",
+ "iopub.status.idle": "2025-02-09T23:00:51.343743Z",
+ "shell.execute_reply": "2025-02-09T23:00:51.342674Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:51.186287Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def plotArrayImageConfusion(x_tra, y_tra, y_pred_tra_topchoice,\n",
+ " title_main=None, num=10,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot images of examples objects that are misclassified.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_tra: `numpy.ndarray`\n",
+ " training image data\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training label data\n",
+ " y_pred_tra_topchoice: `numpy.ndarray`\n",
+ " top choice of the predicted labels\n",
+ " title_main: `string`, optional\n",
+ " title for the plot\n",
+ " num: `int`, optional\n",
+ " number of examples\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " num_row = 2\n",
+ " num_col = 5\n",
+ " images = x_tra[:num]\n",
+ " labels_true = y_tra[:num]\n",
+ " labels_pred = y_pred_tra_topchoice[:num]\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ "\n",
+ " fig.patch.set_linewidth(5)\n",
+ " fig.patch.set_edgecolor('cornflowerblue')\n",
+ "\n",
+ " for i in range(num):\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " ax.imshow(images[i], cmap='gray')\n",
+ " ax.set_title(r'True: {}'.format(labels_true[i]) + '\\n'\n",
+ " + 'Pred: {}'.format(labels_pred[i]))\n",
+ "\n",
+ " fig.suptitle(title_main)\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:51.348809Z",
+ "iopub.status.busy": "2025-02-09T23:00:51.348383Z",
+ "iopub.status.idle": "2025-02-09T23:00:51.591750Z",
+ "shell.execute_reply": "2025-02-09T23:00:51.591165Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:51.348771Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def plotArrayHistogramConfusion(x_tra, y_tra, y_pred_tra_topchoice,\n",
+ " title_main=None, num=10,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histograms of pixel values for images that are misclassified.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_tra: `numpy.ndarray`\n",
+ " training image data\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training label data\n",
+ " y_pred_tra_topchoice: `numpy.ndarray`\n",
+ " top choice of the predicted labels\n",
+ " title_main: `string`, optional\n",
+ " title of plot\n",
+ " num: `int`, optional\n",
+ " number of examples\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " n_bins = 10\n",
+ " num_row = 2\n",
+ " num_col = 5\n",
+ " images = x_tra[:num]\n",
+ " labels_true = y_tra[:num]\n",
+ " labels_pred = y_pred_tra_topchoice[:num]\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ "\n",
+ " fig.patch.set_linewidth(5)\n",
+ " fig.patch.set_edgecolor('cornflowerblue')\n",
+ "\n",
+ " for i in range(num):\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " images_temp = images[i, :, :].flat\n",
+ " ax.hist(images_temp, bins=n_bins, color='gray')\n",
+ " ax.set_title(r'True: {}'.format(labels_true[i]) + '\\n'\n",
+ " + 'Pred: {}'.format(labels_pred[i]))\n",
+ " ax.set_xlabel('Pixel Values')\n",
+ "\n",
+ " fig.suptitle(title_main)\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.4. Define paths for data and figures"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Neural network training (i.e., model fitting) typically requires many numerical experiments to achieve an ideal model. To facilitate the comparison of these experiments/models, it is helpful to organize data carefully. \n",
+ "\n",
+ "Set the variable `run_label` for each training run. \n",
+ "Set paths for the model weight parameters and diagnostic figures, and\n",
+ "save these paths in the dictionary `path_dict` to facilitate passing information to plotting functions.\n",
+ "Check whether the paths exist, and if not, create them."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:51.592497Z",
+ "iopub.status.busy": "2025-02-09T23:00:51.592305Z",
+ "iopub.status.idle": "2025-02-09T23:00:51.743517Z",
+ "shell.execute_reply": "2025-02-09T23:00:51.742419Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:51.592481Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "run_label = \"Run000\"\n",
+ "\n",
+ "path_temp = os.getenv(\"HOME\") + '/dp02_16a_temp/'\n",
+ "path_dict = {'run_label': run_label,\n",
+ " 'dir_data_model': path_temp + \"Data/Models/\",\n",
+ " 'dir_data_figures': path_temp + \"Data/Figures/\",\n",
+ " 'file_model_prefix': \"Model\",\n",
+ " 'file_figure_prefix': \"Figure\",\n",
+ " 'file_figure_suffix': \".png\",\n",
+ " 'file_model_suffix': \".pt\"\n",
+ " }\n",
+ "del path_temp\n",
+ "\n",
+ "if not os.path.exists(path_dict['dir_data_model']):\n",
+ " os.makedirs(path_dict['dir_data_model'])\n",
+ "\n",
+ "if not os.path.exists(path_dict['dir_data_figures']):\n",
+ " os.makedirs(path_dict['dir_data_figures'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 2. Load and Prepare data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.1 Data Set: MNIST Handwritten Digits"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The [`MNIST handwritten digits dataset`](https://ieeexplore.ieee.org/document/6296535) comprises 10 classes --- one for each digit. This is a useful dataset for learning the basics of neural networks and other AI algorithms. MNIST is one of a few canonical AI benchmark data sets for image classification. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.2. Obtain the dataset"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`pytorch` has a simple function to download the MNIST data to your local server for free. While downloading, we use the `transforms` method to normalize the data; this makes the model training more efficient."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 2.2.1 Normalize data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Create a `transform` that is used to convert the data sets to tensors that can be used in `pytorch`. This also transforms all the data from the range $[0,255]$ to $[0.,1.]$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:51.745068Z",
+ "iopub.status.busy": "2025-02-09T23:00:51.744707Z",
+ "iopub.status.idle": "2025-02-09T23:00:51.884959Z",
+ "shell.execute_reply": "2025-02-09T23:00:51.884286Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:51.745032Z"
+ },
+ "id": "kMzao03zcF5i",
+ "outputId": "0401d0af-d607-436a-908f-385ffc85812c"
+ },
+ "outputs": [],
+ "source": [
+ "transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 2.2.2 Download data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Download the data from a remote reserver."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:51.886408Z",
+ "iopub.status.busy": "2025-02-09T23:00:51.885839Z",
+ "iopub.status.idle": "2025-02-09T23:00:52.170282Z",
+ "shell.execute_reply": "2025-02-09T23:00:52.169224Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:51.886378Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "dataset = torchvision.datasets.MNIST(root='./newdata', train=True,\n",
+ " download=True, transform=transform)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.3. Split data into training, validation, and testing"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Split for a proper 'blind' analysis and optimization of an AI model.\n",
+ "\n",
+ "There are three primary data sets used in model development and optimization:\n",
+ "\n",
+ "* `Training` (with filename tag `_tra`) data is used directly by the algorithm to update the parameters of the AI model -- e.g., the weights of the computational neurons on the edges in neural networks.\n",
+ "* `Validation` (`_val`) data is used indirectly to update the hyperparameters of the AI model -- e.g., the batch size (`batchsize`), the learning rate, or the layers in the architecture of a neural network. Each time the neural network has completed training with the training data, the human looks at those diagnostics when run on the training and the validation data.\n",
+ "* `Test(ing)` (`_tes`) data is only used when the model is trained and validated and will no longer be update or further trained. This is the data that you would consider to be the new data that has not been examined before -- e.g., newly observed data that has not bene previously characterized."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We use most of the data for training to maximize the accuracy and generalization of the model. We use a small amount of validation data, because only a little bit is needed to check the model optimization during training. We also use only a small amount of testing data, assuming that new data sets to examine are smaller than existing training data sets."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the fractions for the training, validation, and test sets."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:52.172134Z",
+ "iopub.status.busy": "2025-02-09T23:00:52.171340Z",
+ "iopub.status.idle": "2025-02-09T23:00:52.297172Z",
+ "shell.execute_reply": "2025-02-09T23:00:52.296634Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:52.172083Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "fraction_tra = 0.8\n",
+ "fraction_val = 0.1\n",
+ "fraction_tes = 0.1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Split the data according to those fractions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:52.297980Z",
+ "iopub.status.busy": "2025-02-09T23:00:52.297800Z",
+ "iopub.status.idle": "2025-02-09T23:00:52.444477Z",
+ "shell.execute_reply": "2025-02-09T23:00:52.443440Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:52.297963Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "fraction_list = [fraction_tra, fraction_val, fraction_tes]\n",
+ "\n",
+ "data_tra_full, data_val_full, data_tes_full = \\\n",
+ " torch.utils.data.random_split(dataset, fraction_list)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Print the data set sizes to make sure there's enough data for optimizing the model. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:52.445854Z",
+ "iopub.status.busy": "2025-02-09T23:00:52.445490Z",
+ "iopub.status.idle": "2025-02-09T23:00:52.586869Z",
+ "shell.execute_reply": "2025-02-09T23:00:52.586295Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:52.445819Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "training: 48000\n",
+ "validation: 6000\n",
+ "test 6000\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(\"training:\", len(data_tra_full.indices))\n",
+ "print(\"validation:\", len(data_val_full.indices))\n",
+ "print(\"test\", len(data_tes_full.indices))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.4. Create a subset of the training data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use only a subset of each data to make the training faster for this tutorial. Consider increasing the sizes of these data sets in your exploration of the tutorial elements."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:52.587896Z",
+ "iopub.status.busy": "2025-02-09T23:00:52.587639Z",
+ "iopub.status.idle": "2025-02-09T23:00:52.723891Z",
+ "shell.execute_reply": "2025-02-09T23:00:52.722872Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:52.587879Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "subset_size = 5000\n",
+ "\n",
+ "subset_indices_tra = np.arange(subset_size)\n",
+ "subset_indices_val = np.arange(subset_size)\n",
+ "subset_indices_tes = np.arange(subset_size)\n",
+ "\n",
+ "data_tra = Subset(data_tra_full, subset_indices_tra)\n",
+ "data_val = Subset(data_val_full, subset_indices_val)\n",
+ "data_tes = Subset(data_tes_full, subset_indices_tes)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.4. Examine raw data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Review the raw data shapes by looking at a single datum in the training set. Each datum in the training set is an image-label pair. The image is a tensor, and the label is an integer. The image size in part determines the depth (number of layers) of the neural network. This will be discussed in a later section on model training."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:52.725316Z",
+ "iopub.status.busy": "2025-02-09T23:00:52.724942Z",
+ "iopub.status.idle": "2025-02-09T23:00:52.875460Z",
+ "shell.execute_reply": "2025-02-09T23:00:52.874383Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:52.725278Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The image shape is torch.Size([1, 28, 28]).\n",
+ "The label for this image is 6.\n"
+ ]
+ }
+ ],
+ "source": [
+ "sample_index = 0\n",
+ "image, label = data_tra[sample_index]\n",
+ "print(f\"The image shape is {image.shape}.\")\n",
+ "print(f\"The label for this image is {label}.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Print the image labels and their corresponding indices within a dataset object. This is useful for verifying that you undesrtand your data set."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:52.876528Z",
+ "iopub.status.busy": "2025-02-09T23:00:52.876301Z",
+ "iopub.status.idle": "2025-02-09T23:00:53.000692Z",
+ "shell.execute_reply": "2025-02-09T23:00:53.000075Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:52.876509Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{0: '0 - zero',\n",
+ " 1: '1 - one',\n",
+ " 2: '2 - two',\n",
+ " 3: '3 - three',\n",
+ " 4: '4 - four',\n",
+ " 5: '5 - five',\n",
+ " 6: '6 - six',\n",
+ " 7: '7 - seven',\n",
+ " 8: '8 - eight',\n",
+ " 9: '9 - nine'}"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "{v: k for k, v in dataset.class_to_idx.items()}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot examples of the raw data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:53.001744Z",
+ "iopub.status.busy": "2025-02-09T23:00:53.001327Z",
+ "iopub.status.idle": "2025-02-09T23:00:53.833152Z",
+ "shell.execute_reply": "2025-02-09T23:00:53.832087Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:53.001716Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAp8AAAMVCAYAAAAxtJ8CAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABEtklEQVR4nO39d5iW1b03bq8REFQgUtRI1GBvSLDXZGMEVJTEhr1Gd5SoO1iwobHXRLearUaiUZBgwx2MCrKVoMbHsiUYG3YpPmCjKAxiwZnfH++bPDHX9zb3zNyz7mE4z+PIH/m4jmu+GWcxn1zMmlVTX19fnwAAIIMVqj0AAADLD+UTAIBslE8AALJRPgEAyEb5BAAgG+UTAIBslE8AALJRPgEAyEb5BAAgG+WzGT3//PNpn332ST169Egrr7xy2mSTTdJFF12UPv3002qPBjTBk08+mQYOHJi6dOmSVlpppbThhhumiy++uNpjAY1QW1ubhg4dmnr06JE6dOiQ+vTpk+66665qj9Wqta32AK3VtGnT0k477ZQ23njjdO2116bu3bunJ554Il100UXpL3/5S7r//vurPSLQCGPGjElHHHFEOvDAA9OoUaNSx44d09tvv53mzJlT7dGARthvv/3Sc889l6644oq00UYbpTFjxqRDDjkk1dXVpUMPPbTa47VKNe52bx7nnntuuvTSS9Nbb72V1l9//b/nxx9/fBoxYkSaP39+6tKlSxUnBBpq9uzZaeONN05HHnlkuvHGG6s9DtBE48ePT3vttdffC+ffDBgwIL3yyitp1qxZqU2bNlWcsHXy1+7NpF27dimllL71rW99LV911VXTCiuskFZcccVqjAU0wS233JIWL16czjzzzGqPAlTAH/7wh9SxY8c0ePDgr+XHHHNMmjNnTnr22WerNFnrpnw2k6OOOiqtuuqqaciQIemdd95JixYtSg8++GC6+eab04knnphWWWWVao8INNATTzyRunbtml577bXUp0+f1LZt27T66qunE044IS1cuLDa4wEN9PLLL6dNN900tW379Z9C7N2799//OZWnfDaTnj17pqeffjq9/PLLaf3110+dO3dOgwYNSkcddVS67rrrqj0e0AizZ89On376aRo8eHA66KCD0qOPPpqGDRuWRo0alQYOHJj8FBMsW+bNm5e6du1ayP+WzZs3L/dIywUHjprJjBkz0qBBg9Iaa6yRxo4dm1ZbbbX07LPPpksuuSTV1tamW2+9tdojAg1UV1eXPvvss3T++eens846K6WUUt++fdOKK66Yhg4dmiZNmpT69etX5SmBhqipqWnUP6PxvPlsJmeddVZauHBhmjhxYtp///3TD37wgzRs2LB07bXXpt/97nfp8ccfr/aIQAN169YtpZTS7rvv/rV8zz33TCmlNHXq1OwzAY3XrVu38O3m/PnzU0opfCtK0ymfzeSvf/1r2myzzQo/27ntttumlPwcCSyL/vZzYP/sb3/dvsIK/kiFZckWW2yRXn311bR06dKv5S+99FJKKaVevXpVY6xWz5+UzaRHjx7plVdeSbW1tV/Ln3766ZRSSmuttVY1xgKaYP/9908ppTRhwoSv5ePHj08ppbTDDjtknwlovH333TfV1tam++6772v5yJEjU48ePdL2229fpclaNz/z2UyGDh2a9tlnn9S/f/90yimnpO7du6dnnnkmXX755WmzzTb7+1/TAcuOAQMGpEGDBqWLLroo1dXVpR122CFNmTIlXXjhhWnvvfdOu+yyS7VHBBpgzz33TP37909DhgxJCxcuTBtssEG6884708MPP5xGjx7td3w2E79kvhlNnjw5XXHFFenFF19Mn3zySVp77bXToEGD0tlnn/33nx0Dli1LlixJF154YRozZkx67733Uo8ePdJhhx2Wzj///NS+fftqjwc0UG1tbRo+fHi655570vz589Mmm2ySzj777HTwwQdXe7RWS/kEACAbP/MJAEA2yicAANkonwAAZKN8AgCQjfIJAEA2yicAANmU/Uvma2pqmnMO+Jf8VrDKs6+pNvu6suxpqq2cPe3NJwAA2SifAABko3wCAJCN8gkAQDbKJwAA2SifAABko3wCAJCN8gkAQDbKJwAA2SifAABko3wCAJCN8gkAQDbKJwAA2SifAABko3wCAJCN8gkAQDbKJwAA2SifAABko3wCAJCN8gkAQDbKJwAA2SifAABk07baA7QknTp1CvNf/epXYb7uuuuG+fvvv1/I3nnnnQY9o1+/fmG+5pprFrIRI0aEa4cNGxbmixYtCnNojdq0aRPm66+/fph/9tlnYT5r1qyKzQRUXo8ePcJ8yJAhYX7IIYcUsnbt2oVrd9tttzB/9913w7yurq6Qffnll+Ha5ZE3nwAAZKN8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z//8T5hfd911YX7kkUdWbCaWXf369St77fTp05txkuXDvvvuW8g6derUoGeUOqicizefAABko3wCAJCN8gkAQDbKJwAA2SifAABk43rNMpS6nur1118P8+7duxeySl0h9+ijjxayffbZJ1y7ZMmSinzMlsI1fJVXjX0dnRp/7bXXwrWlfhtEqT1Zid/w0KZNmzC/6qqrClmpKwHHjBkT5scee2yYf/HFF+UNVyGlTsa+9NJLYb722muHeanPVUPY15XV0q/M3XDDDcP8/fffr+hMrdmUKVMK2VZbbRWuHT16dJgfffTRYV5XV9fouf7G9ZoAALQoyicAANkonwAAZKN8AgCQjfIJAEA2y+3d7r169Spkd955Z7h28803b9CzoztTS91Rffrpp4f5hRdeGOb9+/cvZKXuiy71bKimTz75pJC988474doddtghzC+66KIwj+6Ib+hJ8m233TbMS51sj5x33nlhnvtUeylt28Z/9Ffi9DqkVPpraeuttw7zhx56qDnHWSb16dMnzDfaaKOynzFnzpwwr8Sp9qbw5hMAgGyUTwAAslE+AQDIRvkEACAb5RMAgGxa/Wn3UndA33777YVss802C9f+9a9/DfOf/OQnDVofueyyy8L8rbfeCvP/+q//KmQnn3xyg+YoddcrVMsll1wS5nfffXeYn3nmmWH+5ptvFrK77rorXLtkyZIwL/WbKRpi4cKFTX5Gpay66qqF7LrrrgvXdu/ePcx/+ctfVnIklgMdOnQI8+OOOy7MnXYv+tGPfhTm0ef2jTfeCNfecMMNFZ2pUrz5BAAgG+UTAIBslE8AALJRPgEAyKamvr6+vqyFNTXNPUuzKHWg56yzzipkv//978O1P/3pT8O81IGF5jRy5MhCdvjhh4drf/WrX4V5qcMaLV2ZX6o0QEvf16ecckqYX3rppWHevn37QlbqB/FLHXA46aSTwrxdu3ZhHik134IFC8p+xuOPPx7mO+64Y5h/73vfC/N+/foVsh49eoRrS31O9t9//zCvBPu6sqqxp6NDLaUO7s2fPz/MSx12Wx784he/CPNzzz03zKPrcY899thw7W233db4wRqpnD3tzScAANkonwAAZKN8AgCQjfIJAEA2yicAANm0mtPupa7RfP3118N85syZhWznnXcO137xxReNH6zCnHanklr6vi5lq622CvPoZGevXr2ae5yCUp/XanwNP/nkk4Ws1AnY6Nrh5mZfV1Y19vRqq61WyD744INw7eLFi8N82223DfPXXnut8YO1MKV+a0SpKzBXX331MD/11FML2a9//etw7VdffVXmdJXjtDsAAC2K8gkAQDbKJwAA2SifAABko3wCAJBN8YLQZVSpe01L3RcbnS6rxqn2nj17hvkJJ5wQ5kcccUTZz37//fcbMxK0eFOnTg3zbbbZppD17t07XFvq5On3v//9sucodRp13LhxYf7OO++U/exSpkyZEubTpk0L8+jPtWqcgKX1mjt3biErdYL7xBNPDPNHHnkkzPv371/IWtIJ+FLfw6MT6aW+r0d3taeU0quvvhrmv/vd7wrZsranvfkEACAb5RMAgGyUTwAAslE+AQDIRvkEACCbVnPavZRSd4yutdZaheyUU04J1z711FNhXuq0bHS37qqrrhquPfDAA8O8Y8eOYR554IEHwnz06NFlPwNagy+//LKQ/eUvfwnXlsobonPnzmG+cOHCJj8blhXR99nzzjsvXLvTTjuF+ZZbbhnmzz33XCEbMWJEuPa0004rNWLZom6QUkoHHHBAmB9//PFhvvHGG5f9MaOT8Sml9Nvf/jbMFy9eXPazWypvPgEAyEb5BAAgG+UTAIBslE8AALKpqS91IuefFwaHaFqSIUOGhPnVV18d5h06dChkZX4q/qXoc1Xq2aV+cLi2tjbMf/nLXxayUgeLPvroo1IjLpMq9e+H/6el72taP/u6slr6ni51+Pbiiy8O8+g6zlJfM59++mmj5/qbNm3ahHnUGb7Jm2++Wch23333cO2sWbPCvK6urkEfs6UoZ0978wkAQDbKJwAA2SifAABko3wCAJCN8gkAQDat5rR7KaWuxBo0aFAh22qrrcK1PXv2DPP77rsvzKPP1dixY8O1r7/+epi/8cYbYb48cyq28pbVfU3rYV9X1rK6p0vNvc8++xSyCy64IFy7xRZbVHCirxs1alSYT5o0KczvvPPOQrZ06dKKztRSOe0OAECLonwCAJCN8gkAQDbKJwAA2SifAABk0+pPu9N6OBVbefY11WZfV5Y9TbU57Q4AQIuifAIAkI3yCQBANsonAADZKJ8AAGSjfAIAkI3yCQBANsonAADZKJ8AAGSjfAIAkI3yCQBANsonAADZKJ8AAGSjfAIAkI3yCQBANsonAADZKJ8AAGSjfAIAkI3yCQBANsonAADZKJ8AAGSjfAIAkE1NfX19fbWHAABg+eDNJwAA2SifAABko3wCAJCN8gkAQDbKJwAA2SifAABko3wCAJCN8gkAQDbKJwAA2SifAABko3wCAJCN8gkAQDbKJwAA2SifAABko3wCAJCN8tmMamtr09ChQ1OPHj1Shw4dUp8+fdJdd91V7bGAJli0aFE644wz0oABA9Jqq62Wampq0gUXXFDtsYBGOvroo1NNTU3J/zzzzDPVHrHVaVvtAVqz/fbbLz333HPpiiuuSBtttFEaM2ZMOuSQQ1JdXV069NBDqz0e0Ajz5s1LI0aMSN/73vfSPvvsk2655ZZqjwQ0wXnnnZdOOOGEQj5o0KDUvn37tO2221ZhqtZN+Wwm48ePT4888sjfC2dKKe26665p5syZadiwYemggw5Kbdq0qfKUQEN997vfTQsWLEg1NTVp7ty5yics49Zff/20/vrrfy17/PHH09y5c9O5557re3Uz8NfuzeQPf/hD6tixYxo8ePDX8mOOOSbNmTMnPfvss1WaDGiKv/1VHNB63Xrrrammpib95Cc/qfYorZLy2UxefvnltOmmm6a2bb/+crl3795//+cAQMvyySefpLFjx6bddtstrbvuutUep1VSPpvJvHnzUteuXQv537J58+blHgkA+BfuvPPOtGTJknTsscdWe5RWS/lsRt/0V3P+2g4AWp5bb701devWLe27777VHqXVUj6bSbdu3cK3m/Pnz08ppfCtKABQPS+++GKaMmVKOvzww1P79u2rPU6rpXw2ky222CK9+uqraenSpV/LX3rppZRSSr169arGWABACbfeemtKKaXjjjuuypO0bspnM9l3331TbW1tuu+++76Wjxw5MvXo0SNtv/32VZoMAPhnn3/+eRo9enTabrvtvCBqZn7PZzPZc889U//+/dOQIUPSwoUL0wYbbJDuvPPO9PDDD6fRo0f7vWGwDJswYUJavHhxWrRoUUoppWnTpqWxY8emlFIaOHBgWnnllas5HtAI48aNS/Pnz/fWM4Oa+vr6+moP0VrV1tam4cOHp3vuuSfNnz8/bbLJJunss89OBx98cLVHA5qgZ8+eaebMmeE/mz59eurZs2fegYAmGzBgQHrqqafSe++9lzp16lTtcVo15RMAgGz8zCcAANkonwAAZKN8AgCQ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PgEAyEb5BAAgG+UTAIBslE8AALJRPgEAyKbsu90BAKCpvPkEACAb5RMAgGyUTwAAslE+AQDIRvkEACAb5RMAgGyUTwAAslE+AQDIRvkEACAb5RMAgGyUTwAAslE+AQDIRvkEACAb5RMAgGyUz2b25JNPpoEDB6YuXbqklVZaKW244Ybp4osvrvZYQIXccsstqaamJnXs2LHaowAN9Nhjj6WamprwP88880y1x2u12lZ7gNZszJgx6YgjjkgHHnhgGjVqVOrYsWN6++2305w5c6o9GlABs2fPTqeffnrq0aNH+uSTT6o9DtBIl112Wdp1112/lvXq1atK07R+NfX19fXVHqI1mj17dtp4443TkUcemW688cZqjwM0g0GDBqWamprUtWvXNHbs2FRbW1vtkYAGeOyxx9Kuu+6a7r333nTAAQdUe5zlhr92bya33HJLWrx4cTrzzDOrPQrQDEaPHp0ef/xx/+cSoIGUz2byxBNPpK5du6bXXnst9enTJ7Vt2zatvvrq6YQTTkgLFy6s9nhAE3z44Ydp6NCh6YorrkhrrbVWtccBmujEE09Mbdu2TZ07d0677757evLJJ6s9UqumfDaT2bNnp08//TQNHjw4HXTQQenRRx9Nw4YNS6NGjUoDBw5MftoBll0/+9nP0sYbb5yGDBlS7VGAJvjWt76Vfv7zn6ebb745TZ48OV133XXp3XffTX379k0TJ06s9nitlgNHzaSuri599tln6fzzz09nnXVWSimlvn37phVXXDENHTo0TZo0KfXr16/KUwINdd9996UHHnggPf/886mmpqba4wBNsOWWW6Ytt9zy7//9+9//ftp3333TFltskc4444y0++67V3G61subz2bSrVu3lFIqfOHuueeeKaWUpk6dmn0moGlqa2vTiSeemE4++eTUo0eP9PHHH6ePP/44ffHFFymllD7++OO0ePHiKk8JNMWqq66a9t577/Tiiy+mJUuWVHucVkn5bCa9e/cO87/9dfsKK/jUw7Jm7ty56YMPPkhXX3116tKly9//c+edd6bFixenLl26pMMOO6zaYwJN9Lfv1f52o3n4a/dmsv/++6cRI0akCRMmfO2V/vjx41NKKe2www7VGg1opG9/+9tp8uTJhfyKK65Ijz/+eJowYULq3r17FSYDKmXBggXpwQcfTH369EkdOnSo9jitkvLZTAYMGJAGDRqULrroolRXV5d22GGHNGXKlHThhRemvffeO+2yyy7VHhFooA4dOqS+ffsW8ttvvz21adMm/GdAy3XooYemddZZJ22zzTape/fu6c0330xXX311+uCDD9Ltt99e7fFaLeWzGd19993pwgsvTCNGjEgXXnhh6tGjRzrllFPS+eefX+3RAGC517t373T33Xen3/zmN6m2tjZ17do17bLLLumOO+5I2267bbXHa7XccAQAQDZOvQAAkI3yCQBANsonAADZKJ8AAGSjfAIAkI3yCQBANsonAADZlP1L5t1vSrX5lbSVZ19TbfZ1ZdnTVFs5e9qbTwAAslE+AQDIRvkEACAb5RMAgGyUTwAAslE+AQDIRvkEACAb5RMAgGyUTwAAslE+AQDIpuzrNWmaVVZZJcwnT54c5uuss06Y77HHHoXsr3/9a6PnAgDIyZtPAACyUT4BAMhG+QQAIBvlEwCAbJRPAACyqamvr68va2FNTXPP0mp06dKlkI0bNy5cu8suu4R5qX8tY8aMKWRHHnlk+cMtw8r8UqUB7Guqzb6uLHuaaitnT3vzCQBANsonAADZKJ8AAGSjfAIAkI3yCQBANu52bwYnnnhiIdt5550b9Ix33nknzE855ZRGzQQArVm7du3CvFu3bmU/44QTTgjz1VZbrUHrI2PHjg3zQw89NMy/+uqrsp+9rPHmEwCAbJRPAACyUT4BAMhG+QQAIBvlEwCAbJx2b4IddtghzM8888yyn/HZZ5+F+bBhw8J83rx5ZT8bAJYXp512WphfcsklTX52TU1NmJe6xzz6jTUbbrhhuLZfv35hPnHixDKnW/Z48wkAQDbKJwAA2SifAABko3wCAJCNA0dlWH311cP8hhtuCPOVVlqp7GcfcMABYT5hwoSynwEAy7tNN9202Z79xRdfhPm9994b5tFV2A4M/z/efAIAkI3yCQBANsonAADZKJ8AAGSjfAIAkI3T7v+gTZs2Yf5f//VfYd6nT5+ynz1+/Pgwd6odqISNN944zE866aRCtuaaa4Zr77///jC/4447Gj8YVFi3bt3CfK+99mrys88666wwL/U9fNq0aU3+mMsjbz4BAMhG+QQAIBvlEwCAbJRPAACyUT4BAMjGafd/UOpe2P322y/M6+vrw3zBggWF7Kijjmr8YNDK7bnnnmF+wAEHhPn1118f5i+88ELFZmqpOnfuHOa///3vw3yrrbYq+9lvvvlmo2aCnE4++eQwX3XVVRv0nLFjxxaya665JlxbV1fXoGfzzbz5BAAgG+UTAIBslE8AALJRPgEAyEb5BAAgG6fd/8Ef//jHijznhhtuKGTz58+vyLNhWbfOOusUsjvvvDNcW+pk97777hvm+++/fyGbPHlyA6Zr+Q499NAwb8ip9lI222yzJj8Dmtsqq6wS5jU1NQ16zsSJEwuZU+15ePMJAEA2yicAANkonwAAZKN8AgCQzXJ74Ci67vK73/1uuLbUNZpPP/10mF955ZWNHwxaiQ4dOoT5zTffXMhKHSwq5aOPPgrzt99+u0HPack6deoU5gceeGCTn/3KK6+E+WmnndbkZ0Nz22OPPcK81PfqmTNnhvnDDz9cyFZfffVwbXRtdkqlD+ktWrSokL3zzjvh2uWRN58AAGSjfAIAkI3yCQBANsonAADZKJ8AAGTT6k+7b7755mF++eWXN/nZv/rVr8J8yZIlTX42LOv69+8f5rvvvnuTn33YYYeF+axZs5r87JZi7733DvO+ffs2+dlPPfVUmL/11ltNfjZU0umnn17ISp0wL3XavdRvsrnnnnsKWffu3cO177//fph///vfD/PoSu3Ro0eHa6NT9yml9D//8z9h3hp48wkAQDbKJwAA2SifAABko3wCAJCN8gkAQDY19aWOh/3zwpqa5p6lWRxxxBFhfvvttxeyFVaIu/h1110X5kOHDi17jlL3xe66665hvvXWW5f97FJ+85vfhPmyer9smV+qNEBz7uvnnnsuzBvytT19+vQw//GPfxzm0Wn3lVZaKVxbW1sb5osXLy5zuspp3759IXv22WfDtb17927yxzvkkEPC/O67727ysxvKvq6sZfV7danf7jB27NhC1q5du3Btc34tlfq8NufH/N///d8wP/zwwwtZS/q+Xs7nxJtPAACyUT4BAMhG+QQAIBvlEwCAbJRPAACyafV3u5e6pzU6jfXFF1+Eax955JEw79SpU5hHp/ZGjBgRrl155ZXLnq+hTj311DC/6aabwvzkk09u8seEv/nqq6+a/Ix11103zF988cUwf/311wvZBhtsEK59/vnnw3zatGllTlc50endSpxqTymlRYsWFbK6urqKPBsq5eyzzw7ztm1bfU0pafvttw/zKVOmFLJLL700XHv11VdX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G+Wzmfz1r39Ne+21V1pnnXXSSiutlLp27Zp23HHHNHr06GqPBjRBbW1tGjp0aOrRo0fq0KFD6tOnT7rrrruqPRbQSIsWLUpnnHFGGjBgQFpttdVSTU1NuuCCC6o9VqumfDaTjz/+OK299trpsssuS+PHj0+jRo1KPXv2TEcccUS65JJLqj0e0Ej77bdfGjlyZDr//PPThAkT0rbbbpsOOeSQNGbMmGqPBjTCvHnz0ogRI9Lnn3+e9tlnn2qPs1yoqa+vr6/2EMuTHXbYIc2ZMyfNmjWr2qMADTR+/Pi01157pTFjxqRDDjnk7/mAAQPSK6+8kmbNmpXatGlTxQmBhvpbDaqpqUlz585Nq622Wjr//PO9/WxG3nxm1r1799S2bdtqjwE0wh/+8IfUsWPHNHjw4K/lxxxzTJozZ0569tlnqzQZ0Fg1NTWppqam2mMsV5TPZlZXV5eWLl2aPvroo3TjjTemiRMnpjPPPLPaYwGN8PLLL6dNN9208H8ge/fu/fd/DsA38wqumf3sZz9LN998c0oppRVXXDFdf/316fjjj6/yVEBjzJs3L6233nqFvGvXrn//5wB8M+WzmZ1zzjnpuOOOSx9++GF64IEH0kknnZQWL16cTj/99GqPBjTCN/31nL+6A/jXlM9mts4666R11lknpZTSwIEDU0opnX322emoo45Kq622WjVHAxqoW7du4dvN+fPnp5T+3xtQAErzM5+Zbbfddmnp0qXpnXfeqfYoQANtscUW6dVXX01Lly79Wv7SSy+llFLq1atXNcYCWKYon5lNnjw5rbDCCuHPjQEt27777ptqa2vTfffd97V85MiRqUePHmn77bev0mQAyw5/7d5MfvrTn6bOnTun7bbbLq2xxhpp7ty56d5770133313GjZsmL9yh2XQnnvumfr375+GDBmSFi5cmDbYYIN05513pocffjiNHj3a7/iEZdSECRPS4sWL06JFi1JKKU2bNi2NHTs2pfT/+5G5lVdeuZrjtTp+yXwzue2229Jtt92WXn311fTxxx+njh07pu9973vpuOOOS4cffni1xwMaqba2Ng0fPjzdc889af78+WmTTTZJZ599djr44IOrPRrQSD179kwzZ84M/9n06dNTz5498w7UyimfAABk42c+AQDIRvkEACAb5RMAgGyUTwAAslE+AQDIRvkEACCbsn/JfE1NTXPOAf+S3wpWefY11WZfV5Y9TbWVs6e9+QQAIBvlEwCAbJRPAACyUT4BAMhG+QQAIBvlEwCAbJRPAACyUT4BAMhG+QQAIBvlEwCAbJRPAACyUT4BAMhG+QQAIBvlEwCAbJRPAACyUT4BAMhG+QQAIBvlEwCAbJRPAACyUT4BAMhG+QQAIBvlEwCAbNpWewCAZcEKKxT/v/p6660Xrj3qqKPCfMMNNwzzHj16FLJp06aFaz/66KMwv/baa8N83rx5YQ5QLd58AgCQjfIJAEA2yicAANkonwAAZKN8AgCQTU19fX19WQtrapp7FvhGZX6p0gDL875u06ZNmB999NFh3rdv30J22GGHVXCipnnxxRfDfLfdditkLekEvH1dWcvznl5WXXXVVWF+wgknhPn3v//9QvbCCy9UdKamKGdPe/MJAEA2yicAANkonwAAZKN8AgCQjes1myC6bi+llL7zne8UsgMOOCBcG/3g8DfZaaedCtkaa6zRoGeU+mHg6Nq+7373u+Hazz77rEEfE6ql1NfwxRdfHOaHH3542c9eunRpmC9cuDDM33zzzTC/++67y/6YW2+9dZiXOvw0adKkQtavX79w7dy5c8ueA2iYbbbZJsyHDBkS5u3atQvzrl27VmymavHmEwCAbJRPAACyUT4BAMhG+QQAIBvlEwCAbFr9afdSJ11/85vfFLJS1+2Vssoqq4R5dKKt1CnSBx98MMxXX331MI9Oqpc6vf7ll1+G+eOPPx7mTz31VCErdZoXWqJov0+cODFcu9FGG4X5ggULwvz2228vZH/+85/DtePGjYsHrICNN964QeujU/DnnHNOuPbUU09t1EzAvzZw4MAwX3nllcP8008/DfM33nijYjNVizefAABko3wCAJCN8gkAQDbKJwAA2SifAABk0+pPu5e6Y3nq1KmF7IEHHqjIx6ytrS1kL7/8cri21L3sw4cPD/O+ffsWsltvvTVce8cdd4T5E088EeawrDvvvPMK2XrrrReu/c///M8wv/7668N85syZjR+sgl5//fUwv+SSS8J80KBBhax///7h2lJ/Hn3wwQdlTgeklNLgwYML2bBhwxr0jF/84hdhPnv27EbN1JJ48wkAQDbKJwAA2SifAABko3wCAJCN8gkAQDY19aUuBv/nhTU1zT1LqxHd+X7AAQeEa6+88sowf/rpp8P8pJNOKmSt4eRbOcr8UqUBWvq+7tixY5jfeOONYR6dyi6193r37h3mixYtKnO6ZcPll19eyEqduv3Vr34V5meddVZFZ/pH9nVltfQ93dr06tUrzB977LFC1rVr13DtrFmzwnzIkCFhPmHChPKGq5Jy9rQ3nwAAZKN8AgCQjfIJAEA2yicAANm0+us1q+HEE08sZKV+YP/nP/95mI8ePTrM/XA+rVGbNm3C/OSTTw7zww8/PMyHDh1ayP7yl7+Ea3/729+G+cEHHxzmy6qzzz67kP30pz+twiTQvKIrLVNK6cknnwzz9957r+xnd+rUKcxLHX7s0qVLIVu8eHG4ttTVuC39YFFTePMJAEA2yicAANkonwAAZKN8AgCQjfIJAEA2Trs3wUYbbRTml156aSF75JFHwrV33XVXmDvVzvJk/fXXD/NoL32TrbbaqpAdffTR4drtt9++Qc9uTebMmRPma6yxRpiXurLRn1O0JM8//3yYN+RUe+fOncP8ggsuCPNddtklzKO98etf/zpce8stt5Q3XCvizScAANkonwAAZKN8AgCQjfIJAEA2yicAANnU1Jd5XLHUacfl2QorxN09OgU/bty4cO2KK64Y5oceemiYP/PMM+UN1wo5WVt5LWVfX3nllWE+bNiwMF+wYEGY9+nTp5C9++67jZ6rtTrllFPC/Oqrrw7zDh06hPkXX3zR5Fns68pqKXt6WbX//vuH+T333BPmpT7f0frDDjssXPvVV1+VOd2yoZw97c0nAADZKJ8AAGSjfAIAkI3yCQBANsonAADZuNu9Cerq6sL8tddeK2Sl7n9t6J3vffv2LWQzZsyIB4QWKPotEWuvvXa4dtGiRWH+4x//OMydbAfKddxxxxWyESNGNOgZkyZNCvOf/exnhay1nWpvCm8+AQDIRvkEACAb5RMAgGyUTwAAsnG9ZpV17949zK+44oow33nnnQtZdKVgSil9/vnnjZ6rJXINX+VVY1+3b9++kC1ZsiRcO3/+/DAvtW8oj+s1Wy/fq4vWWmutMH/55ZcLWadOncK1tbW1Yb7XXnuF+ZNPPlnmdK2P6zUBAGhRlE8AALJRPgEAyEb5BAAgG+UTAIBsXK9ZZXPnzg3z+++/P8x/8pOfFLLDDz88XHvrrbc2fjBoJtHXMHkdc8wx1R4BKq5bt25h/sc//jHMo5PtCxcuDNfedNNNYb48n2pvCm8+AQDIRvkEACAb5RMAgGyUTwAAslE+AQDIxmn3FurRRx8te22PHj2acRKorEWLFpW99tVXX23GSZYP6623XiFbd911qzAJNK+LL744zPv06RPm0R3kDz74YLj2ggsuaOxYBLz5BAAgG+UTAIBslE8AALJRPgEAyEb5BAAgG6fdW6g99tij7LWTJ09uxkmgsu69995CNmrUqHCt0+5Nd9pppxWyVVZZJVz72muvhXldXV1FZ4Km2HnnncP88MMPD/Oampowj77ehwwZEq794osvypyOcnjzCQBANsonAADZKJ8AAGSjfAIAkE1NfXS/VLSwxA/s0jwmTZoU5l9++WUh23vvvcO1S5curehM1VbmlyoNUI193b59+0K2ZMmScO38+fPDvHv37hWdqTXYf//9w/yWW24pZHPmzAnX9uvXL8zfe++9xg/2L9jXldXavld369atkL3yyivh2tVWWy3MP/vsszDffPPNC9mMGTPKH45QOXvam08AALJRPgEAyEb5BAAgG+UTAIBslE8AALJxvWYmbdq0CfNSV3mVuj5s3333LWSt7VQ7rdtXX31VyF588cVw7VprrdXc4yxzLr744jA/66yzwjz6s+fnP/95uLY5T7XDN4l+C0ZKKV1//fWFrNSp9lKOOuqoMHeyvXq8+QQAIBvlEwCAbJRPAACyUT4BAMhG+QQAIBun3ZtBu3btCtkvfvGLcO2wYcPCvNQ9zRMmTGj8YNACRL+dYeLEieHa008/PcxvvfXWML/66qsL2bRp0xowXfPq2bNnmO+1116F7Pjjjw/XbrrppmFe6jdqvPzyy4XsvvvuKzEhVMdJJ50U5gcccEDZzzj44IPDfOzYsY2aiebjzScAANkonwAAZKN8AgCQjfIJAEA2yicAANnU1NfX15e1sKamuWdpsdq2jX8pQL9+/cL8nHPOKWSl7qI99dRTw9yp9qIyv1RpgJayr1ddddUwnzRpUphvueWWYb548eJC9v7774drb7zxxvKG+wbrrLNOmB955JFhHv0mjJRS6tixY5NnKfUbAIYPH17IPvzwwyZ/vEqxryurpezpUgYPHhzm1113XZh/+9vfLmQXXXRRuPayyy4L8y+++KLM6aiEcva0N58AAGSjfAIAkI3yCQBANsonAADZOHD0D9ZYY40wv+aaa8J8v/32C/PbbrutkJ1//vnh2o8++qjM6XAwofJa+r4udRDpT3/6U5j36dOn+YbJ7He/+12YT548OczvvPPOMK+rq6vYTM3Bvq6slrKnV1555TAvdZXuzjvvHObjxo0rZIcddli4dsmSJeUNR7Ny4AgAgBZF+QQAIBvlEwCAbJRPAACyUT4BAMgmvjcys6222irM995770JW6lqtUrp06RLm/fv3L2RXX311uHb8+PFhvvHGG4f5rFmzypwO+CYff/xxmG+77bZh/qMf/aiQXXDBBeHa3r17N2iWhpzKnj59epj//ve/D/PXX3+9kI0ZM6bJc0C1nH766WG+0047hfmCBQvCPDrZ7lT7ss+bTwAAslE+AQDIRvkEACAb5RMAgGyUTwAAssl6t3uHDh3C/I033gjz448/vpAtXbo0XHvooYeGeXT6NaWU7r///kJ21llnhWs//PDDMCcvp3wrr6XcA83yy76urJayp9dee+0wf/TRR8N83rx5YX7kkUcWsrfeeqvxg9Hs3O0OAECLonwCAJCN8gkAQDbKJwAA2SifAABkk/W0e6lnlDr9tuOOOxayt99+O1xb6sT8pZdeGubPP/98IXPqsmXz76fyWsrJWJZf9nVl2dNUm9PuAAC0KMonAADZKJ8AAGSjfAIAkE3WA0fQFA4mVJ59TbXZ15VlT1NtDhwBANCiKJ8AAGSjfAIAkI3yCQBANsonAADZKJ8AAGSjfAIAkI3yCQBANsonAADZKJ8AAGSjfAIAkE3Zd7sDAEBTefMJAEA2yicAANkonwAAZKN8AgCQjfIJAEA2yicAANkonwAAZKN8AgCQjfIJAEA2/x/J07HvHPtCTgAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Example_Image_Array\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotArrayImageExamples(data_tra,\n",
+ " num_row=4, num_col=3,\n",
+ " save_file=False,\n",
+ " object_index_start=0,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 1: Two rows of five images, each a handwritten number in white on a black background."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot the distributions of pixel values to understand the data further. All pixel data has been normalized, and pixels have values between 0 and 1 only.\n",
+ "\n",
+ "The distribution of pixel values matches the images shown above: mostly black (values near 0) pixels, with some white (values near 1), and a few grey (values in between 0 and 1)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:53.834798Z",
+ "iopub.status.busy": "2025-02-09T23:00:53.834404Z",
+ "iopub.status.idle": "2025-02-09T23:00:55.262207Z",
+ "shell.execute_reply": "2025-02-09T23:00:55.261170Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:53.834762Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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8GGzZs2Sv7+/wsPDNXbsWO3Zs8d2SW2Khhzwca+++qpqa2uVmppquxT4mJMnT+rMmTN65JFH9NOf/lTbtm3Tk08+qZdffln333+/jDG2S4SPmTlzpm666Sb94he/sF0KfFRERIR++ctf6oUXXtCOHTv0u9/9TidOnNDIkSP19ttv2y6vzbCGHPBx69evV2RkpB566CHbpcDHNDQ06OzZs1qyZImefvppSdLIkSMVGBiotLQ0bd++XaNHj7ZcJXzF66+/rvz8fO3fv5/lmWixQYMGadCgQZ779957rx566CENGDBACxcu1NixYy1W13aYIQd82MGDB/X+++9r8uTJcrvdtsuBj4mMjJSkS17gxo0bJ0nat29fu9cE31RTU6NZs2Zp9uzZio2N1ddff62vv/5a9fX1kqSvv/5ap0+ftlwlfFWPHj2UnJysgwcPqra21nY5bYKGHPBh69evlyT9/Oc/t1wJfNFtt9122e0Xlqp068ZLBJrmyy+/1BdffKFVq1apZ8+enturr76q06dPq2fPnpo0aZLtMuHDLhyXOuu7LyxZAXxUXV2dcnJyNGTIkE792axoOz/5yU+UlZWlLVu2eL1F/Oabb0pSl/rIMbROTEyMduzYccn2Z555RoWFhdqyZYuioqIsVIbOoKKiQn/5y190++23KygoyHY5bYKGvJ1t2bJFp0+fVnV1tSTp6NGjns9ovf/++xUSEmKzPPiQN954Q1999RWz42ixpKQkPfDAA1q2bJkaGhp011136f3339fSpUuVnJyse+65x3aJ8BFBQUEaOXLkJds3bNggPz+/yz4GXM7EiRN13XXXKTExUVFRUfrwww+1atUqffHFF9qwYYPt8tqMy3AZfbvq27evPv3008s+VlJSor59+7ZvQfBZSUlJKioqUmlpqcLCwmyXAx9VW1urpUuXKjc3V6WlpYqNjdWkSZO0ZMkSrktAq02bNk2vvfaaampqbJcCH/HMM89o8+bNKikpUU1NjXr16qV77rlHixYt6tTfRE1DDgAAAFjEFTsAAACARTTkAAAAgEU05AAAAIBFNOQAAACARTTkAAAAgEU05AAAAIBFNOQAAACART75TZ0NDQ36/PPPFRYWJpfLZbucLscYo+rqasXGxqpbN98+pyNLdpElOIUswSlkCU5pTpZ8siH//PPPFRcXZ7uMLu/EiRO69tpr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LqC15s2bpylTpigxMVF33323srKydPz4cc2YMcN2aT6vpqZGH330ked+SUmJDhw4oF69eum6666zWFnbIEtthyyRJaeQJbLkFLJElpziSJYc/awXS55//nnTp08fExgYaH7wgx+YwsJC2yV1Cjt27DCSLrlNnTrVdmlthiy1DbJElpxClsiSU8gSWXKKE1lyGWNM684LAAAAALSUT68hBwAAAHwdDTkAAABgEQ05AAAAYBENOQAAAGARDTkAAABgEQ05AAAAYBENOQAAAGARDTkAAABgUZdtyNPT03X77bc79nw7d+6Uy+XS119/7dhzXo7L5dIbb7zRpr8DzUOW4BSyBKeQJTiFLLWPTtuQT5s2TS6XSy6XSwEBAbr++uu1YMECnT59WpK0YMECbd++vV1qqa+vV1RUlJYvX37Zx1esWKGoqCjV19e3Sz1oHrIEp5AlOIUswSlkqWPotA25JP3whz9UaWmpPvnkEy1fvlzr1q3TggULJEndu3dXZGRku9QRGBioyZMna8OGDTLGXPJ4dna2pkyZosDAwHapB81HluAUsgSnkCU4hSzZ16kbcrfbrZiYGMXFxWnixImaNGmS5+2L774Fc/bsWd166616/PHHPT9bUlKiiIgIvfjii5IkY4xWrlyp66+/XsHBwRo4cKBee+21JteSmpqqjz/+WLt27fLavnv3bn344YdKTU3V3r17NWbMGEVFRSkiIkIjRozQvn37Gn3Oy73tc+DAAblcLv3tb3/zbCsqKtLw4cMVHBysuLg4zZkzx3PmK0nr1q1TfHy8goKCFB0drYcffrjJ+9VVkKXzyFLrkaXzyFLrkaXzyFLrkaXzbGapUzfkFwsODtY333xzyfagoCD94Q9/0MaNG/XGG2/o3LlzmjJliu677z499thjkqRf/epXys7OVmZmpo4cOaK5c+dq8uTJKiwsbNLvHjBggO644w5lZ2d7bf/973+vIUOGKCEhQdXV1Zo6dap2796td955R/Hx8br//vtVXV3d4n0+dOiQxo4dqwkTJujgwYPavHmz9uzZoyeeeEKS9P7772vOnDlatmyZjh07prfeekvDhw9v8e/rKsgSWXIKWSJLTiFLZMkpZMlClkwnNXXqVPPjH//Yc//dd981kZGRJiUlxRhjzJIlS8zAgQO9fmblypUmKirKzJ4928TExJi///3vxhhjampqTFBQkCkqKvIan5qaan72s58ZY4zZsWOHkWQqKioarSkzM9OEhoaa6upqY4wx1dXVJjQ01LzwwguXHf/tt9+asLAwk5+f79kmyeTl5TX6O/fv328kmZKSEmOMMVOmTDGPP/641/Pu3r3bdOvWzdTW1prXX3/dhIeHm6qqqkbr7urIUokxhiw5gSyVGGPIkhPIUokxhiw5gSyVGGPsZ6lTN+R+fn4mNDTUuN1u061bN/PQQw+ZL774whhz+YCdO3fODBs2zEgyW7Zs8Wx/7733jCQTGhrqdQsICDBDhgwxxjQtYF9//bUJDg42L730kjHGmJdeesmEhISYyspKY4wxX3zxhZk+fbqJj4834eHhJjQ01LhcLvP88897nqO5AbvllltMYGCgV90hISFGkjl69KipqqoyAwYMMFFRUWby5MkmJyfHnD59uiV/8k6LLJUYY8iSE8hSiTGGLDmBLJUYY8iSE8hSiTHGfpb8nZtr73juu+8+ZWZmKiAgQLGxsQoICLji+PLych07dkx+fn768MMP9cMf/lCS1NDQIEn693//d/3DP/yD18+43e4m1xMREaGHH35Y2dnZSk1NVXZ2th5++GGFh4dLOn+l89///netXr1affr0kdvt1t13393o1cTdup1fcWS+c+HDxW8xNTQ0aPr06ZozZ84lP3/dddcpMDBQ+/bt086dO7V161b9y7/8i9LT07V371716NGjyfvW2ZElsuQUskSWnEKWyJJTyFIHyJJjrX0Hc/FbMBe73BnfuHHjzMiRI80f/vAHExQUZI4cOWKMMaaqqsq43W7z8ssvN/p8TTnjM8aYnTt3GkkmPz/fSDKFhYWex7p37+71O44fP24kmeeee86zTd854zt69KiR5KnTGGOysrK8zvgmTpxo/vEf//GKNX1XTU2N8ff3N6+//nqTf6azI0slxhiy5ASyVGKMIUtOIEslxhiy5ASyVGKMsZ+lTj1D3hzPP/+8/vrXv+rgwYOKi4vTli1bNGnSJL377rsKCwvTggULNHfuXDU0NOiee+5RVVWVioqK1L17d02dOrXJv2fEiBHq37+/Hn30UfXv39/rgoD+/fvrlVdeUWJioqqqqvTkk08qODi40efq37+/4uLilJ6eruXLl+vDDz/UqlWrvMY89dRTuuuuuzRr1iw99thjCg0N1QcffKCCggKtWbNGf/nLX/TJJ59o+PDh6tmzp9588001NDTopptuav4fEZLIEllyDlkiS04hS2TJKWSpjbLkSFvfATXnjO+DDz4wwcHBJjc31/N4ZWWl6du3r1m4cKExxpiGhgbzu9/9ztx0000mICDAfO973zNjx471nLE19YzPGGMyMjKMJJORkeG1fd++fSYxMdG43W4THx9v/vjHP5o+ffo0esZnjDF79uwxAwYMMEFBQebee+81f/zjH73O+Iw5v6ZrzJgxpnv37iY0NNTcdttt5je/+Y0x5vwFCyNGjDA9e/Y0wcHB5rbbbjObN2++6j50JWSpxDOGLLUOWSrxjCFLrUOWSjxjyFLrkKUSzxibWXL9/6IBAAAAWNClPoccAAAA6GhoyAEAAACLaMgBAAAAi2jIAQAAAItoyAEAAACLaMgBAAAAi2jIAQAAAItoyAEAAACLaMgBAAAAi2jIAQAAAItoyAEAAACLaMgBAAAAi/4fQmsB65GGNNEAAAAASUVORK5CYII=",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Example_Histogram_Array\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotArrayHistogramExamples(data_tra,\n",
+ " num_row=2, num_col=5,\n",
+ " save_file=False,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 2: Two rows of five plots, each showing the distribution of pixel values (number of pixels of a given value) for the handwritten digit images shown in Figure 1."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-12-15T20:26:20.181221Z",
+ "iopub.status.busy": "2024-12-15T20:26:20.180895Z",
+ "iopub.status.idle": "2024-12-15T20:26:20.186166Z",
+ "shell.execute_reply": "2024-12-15T20:26:20.185452Z",
+ "shell.execute_reply.started": "2024-12-15T20:26:20.181199Z"
+ }
+ },
+ "source": [
+ "Use the `plotPredictionHistogram` function to plot histograms of true label distributions by class."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:55.263752Z",
+ "iopub.status.busy": "2025-02-09T23:00:55.263376Z",
+ "iopub.status.idle": "2025-02-09T23:00:57.303748Z",
+ "shell.execute_reply": "2025-02-09T23:00:57.302743Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:55.263717Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA9oAAAHACAYAAABdxRCTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABCO0lEQVR4nO3deVRU9/3G8WdkBwEVlZGIAlFcInEBY0RbsaLWxK3GJYkaTdCY4lJc4lKjGROFaiqaamM1ScVojWYzjWYTNW6hNkolcQsxCW4NFJPyAxccFOb3R45zOu4jFwfw/TrnnsP9zufe+7nTaXsev3cx2Ww2mwAAAAAAgCFquLoBAAAAAACqE4I2AAAAAAAGImgDAAAAAGAggjYAAAAAAAYiaAMAAAAAYCCCNgAAAAAABiJoAwAAAABgIII2AAAAAAAGcnd1A7ejrKxMP/zwg/z9/WUymVzdDgAAAACgmrPZbDpz5oxCQkJUo8aN56yrZND+4YcfFBoa6uo2AAAAAAB3mZMnT6phw4Y3rKmSQdvf31/SzycYEBDg4m4AAAAAANVdUVGRQkND7Xn0Rqpk0L58uXhAQABBGwAAAABwx9zK7cs8DA0AAAAAAAMRtAEAAAAAMBBBGwAAAAAAA1XJe7QBAAAA4FpsNpsuXbqk0tJSV7eCKsjDw0Nubm7l3g9BGwAAAEC1UFJSotzcXJ0/f97VraCKMplMatiwoWrWrFmu/RC0AQAAAFR5ZWVlysnJkZubm0JCQuTp6XlLT4cGLrPZbDp9+rROnTqlpk2blmtmm6ANAAAAoMorKSlRWVmZQkND5evr6+p2UEXVq1dPx44d08WLF8sVtHkYGgAAAIBqo0YNIg5un1FXQfArBAAAAADAQARtAAAAAKhm4uLilJSUdMv1x44dk8lkUlZWVoX1dDchaAMAAACAi5hMphsuI0eOvK39vvfee3rxxRdvuT40NFS5ublq1arVbR3PGe+++646dOigwMBA+fv767777tPkyZOd2ofJZNL7779fMQ0agIehAQAAAKjevrLc2ePdf+vHy83Ntf+9fv16zZ49W9nZ2fYxHx8fh/qLFy/Kw8PjpvutU6fOLfcgSW5ubjKbzU5tczu2bNmiRx99VMnJyerbt69MJpMOHz6srVu3Vvix7yRmtAEAAADARcxms30JDAyUyWSyr1+4cEG1atXSW2+9pbi4OHl7e2vNmjX66aef9Nhjj6lhw4by9fVVVFSU3nzzTYf9XnnpeFhYmJKTk/XUU0/J399fjRo10ooVK+yfX3np+Pbt22UymbR161bFxMTI19dXsbGxDv8IIElz585V/fr15e/vr1GjRmn69Olq06bNdc9306ZN6ty5s5599lk1a9ZMkZGR6t+/v5YsWeJQt3HjRkVHR8vb21sRERGaM2eOLl26ZD8XSfrNb34jk8lkX69MCNoAAAAAUIlNmzZNEyZM0JEjR9SzZ09duHBB0dHR2rRpkw4ePKinn35aw4cP1z//+c8b7mfhwoWKiYnR/v37lZiYqN/+9rf6+uuvb7jNzJkztXDhQu3bt0/u7u566qmn7J/97W9/07x58zR//nxlZmaqUaNGWrZs2Q33ZzabdejQIR08ePC6NZ9++qmGDRumCRMm6PDhw1q+fLnS0tI0b948SdLevXslSStXrlRubq59vTIhaAMAAABAJZaUlKQBAwYoPDxcISEhuueeezRlyhS1adNGERERGj9+vHr27Km33377hvt56KGHlJiYqCZNmmjatGmqW7eutm/ffsNt5s2bpy5duqhly5aaPn26MjIydOHCBUnSkiVLlJCQoCeffFKRkZGaPXu2oqKibri/8ePHq3379oqKilJYWJgeffRR/fWvf5XVanU45vTp0zVixAhFRESoe/fuevHFF7V8+XJJP7/rWpJq1aols9lsX69MCNoAAAAAUInFxMQ4rJeWlmrevHm6//77FRQUpJo1a2rz5s06ceLEDfdz//332/++fIl6fn7+LW/ToEEDSbJvk52drQceeMCh/sr1K/n5+enDDz/Ut99+q+eee041a9bU5MmT9cADD+j8+fOSpMzMTL3wwguqWbOmfRk9erRyc3PtNZUdD0MDAAAAgErMz8/PYX3hwoVatGiRFi9erKioKPn5+SkpKUklJSU33M+VD1EzmUwqKyu75W1MJpMkOWxzeewym812w/1ddu+99+ree+/VqFGjNHPmTEVGRmr9+vV68sknVVZWpjlz5mjAgAFXbeft7X1L+3c1gjYAAAAAVCG7du1Sv379NGzYMEk/B9+jR4+qRYsWd7SPZs2a6YsvvtDw4cPtY/v27XN6P2FhYfL19dW5c+ckSe3atVN2draaNGly3W08PDxUWlrqfNN3CEEbAAAAAKqQJk2a6N1331VGRoZq166t1NRU5eXl3fGgPX78eI0ePVoxMTGKjY3V+vXr9dVXXykiIuK621gsFp0/f14PPfSQGjdurP/7v//Tn/70J128eFHdu3eXJM2ePVu9e/dWaGioBg0apBo1auirr77SgQMHNHfuXEk/h/OtW7eqU6dO8vLyUu3ate/IOd8q7tEGAAAAgCpk1qxZateunXr27Km4uDiZzWb179//jvcxdOhQzZgxQ1OmTFG7du2Uk5OjkSNH3vDy7i5duuj777/XE088oebNm6tXr17Ky8vT5s2b1axZM0lSz549tWnTJqWnp6t9+/Z68MEHlZqaqsaNG9v3s3DhQqWnpys0NFRt27at8HN1lsl2qxfRVyJFRUUKDAxUYWGhAgICXN0OAAAAABe7cOGCcnJyFB4eXmXu462OunfvLrPZrNWrV7u6ldtyo9+RMzmUS8cBAAAAAE47f/68/vKXv6hnz55yc3PTm2++qS1btig9Pd3VrbkcQRsAAAAA4DSTyaSPPvpIc+fOldVqVbNmzfTuu+8qPj7e1a25HEEbAAAAAOA0Hx8fbdmyxdVtVEo8DA0AAAAAAAMRtAEAAAAAMBBBGwAAAAAAAxG0AQAAAAAwEEEbAAAAAAADEbQBAAAAADAQQRsAAAAAqri4uDglJSXZ18PCwrR48eIbbmMymfT++++X+9hG7ac64T3aAAAAAKo1y3bLnT1e3K0fr0+fPiouLr7m+6j/8Y9/KDY2VpmZmWrXrp1TPezdu1d+fn5ObXMzFotF77//vrKyshzGc3NzVbt2bUOPdaXS0lItWLBAq1at0vHjx+Xj46PIyEiNGTNGTz755C3tY/v27eratasKCgpUq1atCu2XoI0q507/D+XdwJn/MwAAAIBxEhISNGDAAB0/flyNGzd2+Oyvf/2r2rRp43TIlqR69eoZ1eJNmc3mCj+GxWLRihUrtHTpUsXExKioqEj79u1TQUFBhR/7dnDpOAAAAAC4SO/evVW/fn2lpaU5jJ8/f17r169XQkKCfvrpJz322GNq2LChfH19FRUVpTfffPOG+73y0vGjR4/ql7/8pby9vdWyZUulp6dftc20adMUGRkpX19fRUREaNasWbp48aIkKS0tTXPmzNGXX34pk8kkk8lk7/nKS8cPHDigX/3qV/Lx8VFQUJCefvppnT171v75yJEj1b9/f/3xj39UgwYNFBQUpLFjx9qPdS0bN25UYmKiBg0apPDwcLVu3VoJCQmaNGmSvcZms2nBggWKiIiQj4+PWrdurXfeeUeSdOzYMXXt2lWSVLt2bZlMJo0cOfKG32F5MKMNAAAAAC7i7u6uJ554QmlpaZo9e7ZMJpMk6e2331ZJSYmGDh2q8+fPKzo6WtOmTVNAQIA+/PBDDR8+XBEREerQocNNj1FWVqYBAwaobt262rNnj4qKihzu577M399faWlpCgkJ0YEDBzR69Gj5+/tr6tSpGjJkiA4ePKhPPvnEfpl7YGDgVfs4f/68fv3rX+vBBx/U3r17lZ+fr1GjRmncuHEO/5jw2WefqUGDBvrss8/07bffasiQIWrTpo1Gjx59zXMwm83atm2bEhMTrztb/9xzz+m9997TsmXL1LRpU+3cuVPDhg1TvXr11LlzZ7377rt65JFHlJ2drYCAAPn4+Nz0u7tdBG0AAAAAcKGnnnpKL730kv0eYunny8YHDBig2rVrq3bt2poyZYq9fvz48frkk0/09ttv31LQ3rJli44cOaJjx46pYcOGkqTk5GT16tXLoe65556z/x0WFqbJkydr/fr1mjp1qnx8fFSzZk25u7vf8FLxv/3tbyouLtYbb7xhv0d86dKl6tOnj+bPn6/g4GBJP88qL126VG5ubmrevLkefvhhbd269bpBOzU1VQMHDpTZbNZ9992n2NhY9evXz34O586dU2pqqrZt26aOHTtKkiIiIrR7924tX75cXbp0UZ06dSRJ9evX5x5tAAAAAKjOmjdvrtjYWP31r39V165d9d1332nXrl3avHmzpJ8fBPaHP/xB69ev17///W9ZrVZZrdZbftjZkSNH1KhRI3vIlmQPo//rnXfe0eLFi/Xtt9/q7NmzunTpkgICApw6lyNHjqh169YOvXXq1EllZWXKzs62B+377rtPbm5u9poGDRrowIED191vy5YtdfDgQWVmZmr37t3auXOn+vTpo5EjR+q1117T4cOHdeHCBXXv3t1hu5KSErVt29apczAC92gDAAAAgIslJCTo3XffVVFRkVauXKnGjRurW7dukqSFCxdq0aJFmjp1qrZt26asrCz17NlTJSUlt7Rvm8121djlS9Qv27Nnjx599FH16tVLmzZt0v79+zVz5sxbPsb/HuvKfV/rmB4eHld9VlZWdsN916hRQ+3b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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "y_tra = []\n",
+ "y_val = []\n",
+ "y_tes = []\n",
+ "\n",
+ "for i in np.arange(subset_size):\n",
+ " image, label_tra = data_tra[i]\n",
+ " image, label_val = data_val[i]\n",
+ " image, label_tes = data_tes[i]\n",
+ " y_tra.append(label_tra)\n",
+ " y_val.append(label_val)\n",
+ " y_tes.append(label_tes)\n",
+ "\n",
+ "y_tra = np.array(y_tra)\n",
+ "y_val = np.array(y_val)\n",
+ "y_tes = np.array(y_tes)\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Histograms_true_class\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotPredictionHistogram(y_tra,\n",
+ " y_prediction_b=y_val,\n",
+ " y_prediction_c=y_tes,\n",
+ " label_a=\"Training Set\",\n",
+ " label_b=\"Validation Set\",\n",
+ " label_c=\"Testing Set\",\n",
+ " figsize=(12, 5),\n",
+ " alpha=0.5,\n",
+ " xlabel_plot=\"True class label\",\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 3: The histograms of true class labels for each data set. Each histogram is for a different data set used during model training --- training data, validation data, and test data. Note that these are overlapping histograms, not stacked. Please compare to Figure 4, which shows histograms of the predicted class labels."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 2.5. Create Dataloaders for training"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the batch size, which will be used in dataloaders and in training. To simplify data-handling, we set the batch size to the size of the subset that we select. This means that there is one batch used in training."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:57.305293Z",
+ "iopub.status.busy": "2025-02-09T23:00:57.304947Z",
+ "iopub.status.idle": "2025-02-09T23:00:57.453279Z",
+ "shell.execute_reply": "2025-02-09T23:00:57.452205Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:57.305259Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "batch_size = subset_size"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Create dataloaders for the training, validation, and test set data loaders."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:57.454746Z",
+ "iopub.status.busy": "2025-02-09T23:00:57.454386Z",
+ "iopub.status.idle": "2025-02-09T23:00:57.589881Z",
+ "shell.execute_reply": "2025-02-09T23:00:57.589215Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:57.454711Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "trainloader = torch.utils.data.DataLoader(data_tra, batch_size=batch_size,\n",
+ " shuffle=False)\n",
+ "\n",
+ "validloader = torch.utils.data.DataLoader(data_val, batch_size=batch_size,\n",
+ " shuffle=False)\n",
+ "\n",
+ "testloader = torch.utils.data.DataLoader(data_tes, batch_size=batch_size,\n",
+ " shuffle=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 3. Train the model: Convolutional Neural Network"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-12-15T21:16:11.080821Z",
+ "iopub.status.busy": "2024-12-15T21:16:11.079938Z",
+ "iopub.status.idle": "2024-12-15T21:16:11.085835Z",
+ "shell.execute_reply": "2024-12-15T21:16:11.085097Z",
+ "shell.execute_reply.started": "2024-12-15T21:16:11.080794Z"
+ }
+ },
+ "source": [
+ "In `pytorch`, neural network models are defined as classes. This is slightly different than typical `tensorflow` usage, in which people build a `sequential` model or use a pre-built `model` class and add layers to that model. \n",
+ "\n",
+ "The other major difference between `pytorch` and `tensorflow` is the shape of the tensors and the inputs for each layer. \n",
+ "\n",
+ "In particular, in `pytorch` one has to explicitly match the output from one layer to the input of the next layer. Sometimes, this can be done with a calculation. But, more often, one must perform guess-and-check. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 3.1. Define model training hyperparameters"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the seed that for the random initial model weights."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:57.590774Z",
+ "iopub.status.busy": "2025-02-09T23:00:57.590515Z",
+ "iopub.status.idle": "2025-02-09T23:00:57.739275Z",
+ "shell.execute_reply": "2025-02-09T23:00:57.738219Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:57.590755Z"
+ },
+ "id": "Zsc_pqZtWftJ",
+ "outputId": "8238aa09-2afd-47ef-c93e-3910b342fe38"
+ },
+ "outputs": [],
+ "source": [
+ "seed = 1729\n",
+ "new = torch.manual_seed(seed)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Define the loss function. We choose cross-entropy, which is the standard loss function for classification of discrete labels."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:57.741224Z",
+ "iopub.status.busy": "2025-02-09T23:00:57.740823Z",
+ "iopub.status.idle": "2025-02-09T23:00:57.892170Z",
+ "shell.execute_reply": "2025-02-09T23:00:57.891536Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:57.741190Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "loss_fn = nn.CrossEntropyLoss()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 3.2. Define the neural network model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.1. Define model architecture elements"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Below is a list of important terms for elements of an architecture:\n",
+ "\n",
+ " * `activation function`: a function within a neuron that takes inputs from a previous layer and produces an output -- usually, this function is non-linear. Examples include \"sigmoid,\" \"softmax,\" and \"reLu\" (rectified linear unit).\n",
+ " * `sigmoid`: an activation function that takes points from the Real line and maps them to the range [-1,1].\n",
+ " * `softmax`: an activation function that takes points from the Real line and maps them to the range [0,1]. This is often used to obtain a 'probability score.'\n",
+ " * `weights`: the weight factor within an activation function.\n",
+ " * `biases`: the bias factor applied after an activation function.\n",
+ " * `layer`: one set of nodes/neurons that receive input data simultaneously.\n",
+ " * `linear (Dense) layer`: occurs due to the \"flattening\" of a higher-dimensional data vector, like an image. It only has an activation function -- as opposed to a convolutional layer which makes a convolution operation.\n",
+ " * `convolutional layer`: a layer that applies a convolution operation to an input sample."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.2. Implement model architecture elements in an object class"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Typically, there are two functions within this class.\n",
+ "\n",
+ "The constructor function (`__init__`) defines the available layers of the network. These layers require specific settings related to the data set shapes. \n",
+ "* `Conv2d`: defines a two-dimensional convolutional layer. Four inputs are considered here:\n",
+ " * `in_channels` (required): the number of input channels.\n",
+ " * `out_channels` (required): the number of output channels.\n",
+ " * `kernel_size` (required): the size on one dimension of the convolutional kernel.\n",
+ " * `stride` (optional): the stride of the convolution\n",
+ "* `Dropout`: defines a dropout layer. The fraction of neuron weights that are set to zero. Typically, this is used only\n",
+ "* `Linear`: defines a linear layer. Two inputs are considered here:\n",
+ " * `in_features` (required): the size of the sample input to the layer.\n",
+ " * `out_features` (required): the size of the sample output from the layer.\n",
+ "\n",
+ "The function `forward` defines the order of operations during a forward pass of the model. During training, the `forward` function is applied to the input data to make predictions. After each round of predictions (epoch), the optimizer is engaged to take the difference between the true labels and the predicted labels and then use that difference to update the model weights. \n",
+ "\n",
+ "The `forward` function uses the layers defined in the constructor, as well as other layers that don't require inputs that depend on the data. These layers are defined in the `torch.nn.functional` submodule, which contains predefined functions for layers that operate directly on the data and don't require an instance of that layer. These `functional` layers are \n",
+ "* `relu`: applies the activation function, the `Rectified Linear Unit`. It requires one input, the sample from the previous layer.\n",
+ "* `max_pool2d`: the max pooling function is applied to the sample from the previous layer. It requires the input sample and the size of the kernel of the pooling.\n",
+ "* `flatten`: reshapes the sample input into a one-dimensional tensor."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.3. Define the object class that represents the model. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:57.893245Z",
+ "iopub.status.busy": "2025-02-09T23:00:57.892802Z",
+ "iopub.status.idle": "2025-02-09T23:00:58.065150Z",
+ "shell.execute_reply": "2025-02-09T23:00:58.064028Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:57.893224Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "class ConvNet(nn.Module):\n",
+ " def __init__(self):\n",
+ " super(ConvNet, self).__init__()\n",
+ " self.conv1 = nn.Conv2d(1, 32, 3, 1)\n",
+ " self.conv2 = nn.Conv2d(32, 64, 3, 1)\n",
+ " self.dropout1 = nn.Dropout(0.25)\n",
+ " self.dropout2 = nn.Dropout(0.5)\n",
+ " self.fc1 = nn.Linear(9216, 128)\n",
+ " self.fc2 = nn.Linear(128, 10)\n",
+ "\n",
+ " def forward(self, x):\n",
+ " x = self.conv1(x)\n",
+ " x = F.relu(x)\n",
+ " x = self.conv2(x)\n",
+ " x = F.relu(x)\n",
+ " x = F.max_pool2d(x, 2)\n",
+ " x = self.dropout1(x)\n",
+ " x = torch.flatten(x, 1)\n",
+ " x = self.fc1(x)\n",
+ " x = F.relu(x)\n",
+ " x = self.dropout2(x)\n",
+ " x = self.fc2(x)\n",
+ " output = x\n",
+ " return output"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Instantiate a neural network model object."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 32,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:58.066569Z",
+ "iopub.status.busy": "2025-02-09T23:00:58.066197Z",
+ "iopub.status.idle": "2025-02-09T23:00:58.205918Z",
+ "shell.execute_reply": "2025-02-09T23:00:58.204825Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:58.066533Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "model = ConvNet()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Define the device. This is important especially when a GPU is available. This is necessary because the model and the data get moved to that device.\n",
+ "\n",
+ "In our case, the device is a CPU because that's what is currently available on the RSP."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:58.207635Z",
+ "iopub.status.busy": "2025-02-09T23:00:58.207117Z",
+ "iopub.status.idle": "2025-02-09T23:00:58.346979Z",
+ "shell.execute_reply": "2025-02-09T23:00:58.345787Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:58.207575Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "device = torch.device('cuda') if torch.cuda.is_available()\\\n",
+ " else torch.device('cpu')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Put the model on the device where the computations will be performed.\n",
+ "\n",
+ "When placing the model on the device, it also shows a summary of the network architecture. Examine the shapes of the layers and the numbers of parameters. Too few parameters may prevent the model from being flexible enough to model the data. Too many parameters could lead to overfitting of the model and a high computational cost."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:58.348374Z",
+ "iopub.status.busy": "2025-02-09T23:00:58.348049Z",
+ "iopub.status.idle": "2025-02-09T23:00:58.484854Z",
+ "shell.execute_reply": "2025-02-09T23:00:58.484286Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:58.348343Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Model Summary:\n",
+ "\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "ConvNet(\n",
+ " (conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1))\n",
+ " (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1))\n",
+ " (dropout1): Dropout(p=0.25, inplace=False)\n",
+ " (dropout2): Dropout(p=0.5, inplace=False)\n",
+ " (fc1): Linear(in_features=9216, out_features=128, bias=True)\n",
+ " (fc2): Linear(in_features=128, out_features=10, bias=True)\n",
+ ")"
+ ]
+ },
+ "execution_count": 34,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "print(\"Model Summary:\\n\")\n",
+ "model.to(device)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.4. Define hyperparameter terms for the training schedule"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* `learning rate`: A multiplicative factor defining the amount that the model weights will change in response to the size of the error (loss) in the model prediction for that epoch. The lower the learning rate, the smaller the change to the weights, and usually the longer it will take to train the model. However, if the learning rate is too high, the weights can change too quickly: then, the loss can fluctuate significantly and not decrease quickly.\n",
+ "* `momentum`: A multiplicative factor on the aggregate of previous gradients. This aggregate term is combined with the weight gradient term to define the total change in the value of the weights. The smaller the momentum, the lesser the influence of the aggregated gradients, and usually the longer it will take train the model.\n",
+ "* `optimizer`: The method/algorithm used to update the network weights. Stochastic Gradient Descent (SGD) is the most commonly used method.\n",
+ "* `epoch`: One loop of training the model. Each loop includes the entire data set (all the batches) once, and it includes at least one round of weight updates.\n",
+ "* `n_epochs`: The number of epochs to train the network."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.5. Assign hyperparameters for the training schedule"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:58.485804Z",
+ "iopub.status.busy": "2025-02-09T23:00:58.485463Z",
+ "iopub.status.idle": "2025-02-09T23:00:58.610914Z",
+ "shell.execute_reply": "2025-02-09T23:00:58.609882Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:58.485785Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "learning_rate = 0.01\n",
+ "momentum = 0.9\n",
+ "optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=momentum)\n",
+ "n_epochs = 50"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 3.4. Train the model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the model into a training context. This ensures that layers like \"batchnorm\" and \"dropout\" will be activated. In contrast, when the model is set to an evaluation context (later in this tutorial), those layers will be deactivated."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:58.612344Z",
+ "iopub.status.busy": "2025-02-09T23:00:58.611972Z",
+ "iopub.status.idle": "2025-02-09T23:00:58.756735Z",
+ "shell.execute_reply": "2025-02-09T23:00:58.755676Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:58.612300Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%capture\n",
+ "model.train()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use a loop over epochs, optimize the network weight parameters. \n",
+ "\n",
+ "Use lists to track the loss values on the training data, the loss values on the testing data, and the accuracy values on the testing data. Define the \"history\" dictionary to hold those lists. We will visualize these later to study the fitting efficacy and generalization capacity of the network."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 37,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:00:58.758266Z",
+ "iopub.status.busy": "2025-02-09T23:00:58.757903Z",
+ "iopub.status.idle": "2025-02-09T23:13:23.377226Z",
+ "shell.execute_reply": "2025-02-09T23:13:23.376192Z",
+ "shell.execute_reply.started": "2025-02-09T23:00:58.758217Z"
+ },
+ "id": "zB1OY3o8VWF_",
+ "outputId": "7bdd7e85-cef2-47af-f16b-5f8bbd66f67f"
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch ( 0): accuracy (9.78 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 1): accuracy (10.26 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 2): accuracy (10.44 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 3): accuracy (11.30 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 4): accuracy (12.58 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 5): accuracy (14.20 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 6): accuracy (16.96 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 7): accuracy (18.42 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 8): accuracy (19.68 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 9): accuracy (21.68 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 10): accuracy (23.16 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 11): accuracy (24.86 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 12): accuracy (24.88 %), train loss (0.0005), valid loss (0.0005) \n",
+ "Epoch ( 13): accuracy (26.24 %), train loss (0.0005), valid loss (0.0004) \n",
+ "Epoch ( 14): accuracy (28.46 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 15): accuracy (28.84 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 16): accuracy (29.86 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 17): accuracy (32.38 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 18): accuracy (33.24 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 19): accuracy (36.54 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 20): accuracy (38.86 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 21): accuracy (39.54 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 22): accuracy (42.22 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 23): accuracy (44.86 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 24): accuracy (48.12 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 25): accuracy (49.74 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 26): accuracy (53.24 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 27): accuracy (53.98 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 28): accuracy (56.04 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 29): accuracy (56.62 %), train loss (0.0004), valid loss (0.0004) \n",
+ "Epoch ( 30): accuracy (59.60 %), train loss (0.0004), valid loss (0.0003) \n",
+ "Epoch ( 31): accuracy (60.46 %), train loss (0.0003), valid loss (0.0003) \n",
+ "Epoch ( 32): accuracy (59.72 %), train loss (0.0003), valid loss (0.0003) \n",
+ "Epoch ( 33): accuracy (61.94 %), train loss (0.0003), valid loss (0.0003) \n",
+ "Epoch ( 34): accuracy (63.48 %), train loss (0.0003), valid loss (0.0003) \n",
+ "Epoch ( 35): accuracy (64.74 %), train loss (0.0003), valid loss (0.0002) \n",
+ "Epoch ( 36): accuracy (66.14 %), train loss (0.0002), valid loss (0.0002) \n",
+ "Epoch ( 37): accuracy (67.70 %), train loss (0.0002), valid loss (0.0002) \n",
+ "Epoch ( 38): accuracy (68.60 %), train loss (0.0002), valid loss (0.0002) \n",
+ "Epoch ( 39): accuracy (69.16 %), train loss (0.0002), valid loss (0.0002) \n",
+ "Epoch ( 40): accuracy (71.06 %), train loss (0.0002), valid loss (0.0002) \n",
+ "Epoch ( 41): accuracy (72.12 %), train loss (0.0002), valid loss (0.0002) \n",
+ "Epoch ( 42): accuracy (72.66 %), train loss (0.0002), valid loss (0.0002) \n",
+ "Epoch ( 43): accuracy (74.16 %), train loss (0.0002), valid loss (0.0002) \n",
+ "Epoch ( 44): accuracy (75.68 %), train loss (0.0002), valid loss (0.0001) \n",
+ "Epoch ( 45): accuracy (77.04 %), train loss (0.0002), valid loss (0.0001) \n",
+ "Epoch ( 46): accuracy (77.06 %), train loss (0.0001), valid loss (0.0001) \n",
+ "Epoch ( 47): accuracy (78.44 %), train loss (0.0001), valid loss (0.0001) \n",
+ "Epoch ( 48): accuracy (79.26 %), train loss (0.0001), valid loss (0.0001) \n",
+ "Epoch ( 49): accuracy (79.56 %), train loss (0.0001), valid loss (0.0001) \n",
+ "Total training time: 744.4417\n"
+ ]
+ }
+ ],
+ "source": [
+ "time_start = time.time()\n",
+ "\n",
+ "loss_train_list = []\n",
+ "loss_test_list = []\n",
+ "accuracy_test_list = []\n",
+ "\n",
+ "for epoch in np.arange(n_epochs):\n",
+ "\n",
+ " loss_train = 0\n",
+ " for inputs, labels in trainloader:\n",
+ " inputs = inputs.to(device)\n",
+ " labels = labels.to(device)\n",
+ " y_pred = model(inputs)\n",
+ " loss = loss_fn(y_pred, labels)\n",
+ " optimizer.zero_grad()\n",
+ " loss.backward()\n",
+ " optimizer.step()\n",
+ " loss_train += loss.item()\n",
+ "\n",
+ " loss_train /= batch_size\n",
+ "\n",
+ " accuracy_test = 0\n",
+ " loss_test = 0\n",
+ " count_test = 0\n",
+ " for inputs, labels in testloader:\n",
+ " inputs = inputs.to(device)\n",
+ " labels = labels.to(device)\n",
+ " y_pred = model(inputs)\n",
+ " loss = loss_fn(y_pred, labels)\n",
+ " accuracy_test += (torch.argmax(y_pred, 1) == labels).float().sum()\n",
+ " loss_test += loss.item()\n",
+ " count_test += len(labels)\n",
+ "\n",
+ " accuracy_test /= count_test\n",
+ " loss_test /= batch_size\n",
+ "\n",
+ " loss_train_list.append(loss_train)\n",
+ " loss_test_list.append(loss_test)\n",
+ " accuracy_test_list.append(accuracy_test)\n",
+ "\n",
+ " output = f\"Epoch ({epoch:3d}): accuracy ({accuracy_test*100:.2f} %),\\\n",
+ " train loss ({loss_train:.4f}), valid loss ({loss_test:.4f}) \"\n",
+ " print(output)\n",
+ "\n",
+ "time_end = time.time()\n",
+ "\n",
+ "time_difference = time_end - time_start\n",
+ "\n",
+ "history = {\"loss\": loss_train_list,\n",
+ " \"val_loss\": loss_test_list,\n",
+ " \"accuracy_test\": accuracy_test_list}\n",
+ "\n",
+ "print(f\"Total training time: {time_difference:2.4f}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Save model to file: \"pt\" is the common suffix used for pytorch model files. This saves the architecture and weights of the model."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 38,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:23.378889Z",
+ "iopub.status.busy": "2025-02-09T23:13:23.378481Z",
+ "iopub.status.idle": "2025-02-09T23:13:23.551547Z",
+ "shell.execute_reply": "2025-02-09T23:13:23.550467Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:23.378864Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "/home/bnord/dp02_16a_temp/Data/Models/Model_Run000_20250209_231323.pt\n"
+ ]
+ }
+ ],
+ "source": [
+ "file_prefix = path_dict['file_model_prefix'] + \"_\" + path_dict['run_label']\n",
+ "file_name_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_model'],\n",
+ " file_suffix=path_dict['file_model_suffix'],\n",
+ " useuid=True,\n",
+ " verbose=True)\n",
+ "\n",
+ "torch.save(model.state_dict(), file_name_final)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the model from a \"pt\" file."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 39,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:23.553120Z",
+ "iopub.status.busy": "2025-02-09T23:13:23.552767Z",
+ "iopub.status.idle": "2025-02-09T23:13:23.711074Z",
+ "shell.execute_reply": "2025-02-09T23:13:23.709943Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:23.553086Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%capture\n",
+ "model.load_state_dict(torch.load(file_name_final, weights_only=False))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-01-14T23:05:09.388295Z",
+ "iopub.status.busy": "2025-01-14T23:05:09.387717Z",
+ "iopub.status.idle": "2025-01-14T23:05:09.481703Z",
+ "shell.execute_reply": "2025-01-14T23:05:09.481106Z",
+ "shell.execute_reply.started": "2025-01-14T23:05:09.388255Z"
+ }
+ },
+ "source": [
+ "Set the model to evaluation mode so that the \"batchnorm\" and \"dropout\" layers are deactivated. This is necessary for consistent inference."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 40,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:23.712652Z",
+ "iopub.status.busy": "2025-02-09T23:13:23.712268Z",
+ "iopub.status.idle": "2025-02-09T23:13:24.006950Z",
+ "shell.execute_reply": "2025-02-09T23:13:24.005916Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:23.712613Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%%capture\n",
+ "model.eval()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 4. Diagnosing the Results of Model Training"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.1. Key terms for diagnostics and model evaluation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use the following diagnostics to assess the status of the network optimization and efficacy. The [scikit-learn page on metrics and scoring](https://scikit-learn.org/stable/modules/model_evaluation.html) provides a good in-depth reference for these terms.\n",
+ "\n",
+ "Model Predictions:\n",
+ " * `Classification threshold`: The user-chosen value $[0,1]$ that sets the threshold for a positive classification. \n",
+ " * `Probability score`: The output from the classifier neural network. One typically uses the `softmax` activation function in the last layer of the NN to provide an output in the range $[0,1]$.\n",
+ " * `Classification score`: The predicted class label is the class that received the highest probability score.\n",
+ "\n",
+ "Metrics:\n",
+ " * `Loss`: A function of the difference between the true labels and predicted labels.\n",
+ " * `Accuracy`: A rough indicator of model training progress/convergence for balanced datasets. For model performance, use only in combination with other metrics. Avoid this metric when you have unbalanced training datasets. Consider using another metric.\n",
+ " * `True Positive Rate (TPR; \"Recall\")`: Use when false negatives are more expensive than false positives.\n",
+ " * `False Positive Rate (FPR)`: Use when false positives are more expensive than false negatives.\n",
+ " * `Precision`: Use when positive predictions need to be accurate.\n",
+ "\n",
+ "The `Generalization Error` (GE) is the difference in loss when the model is applied to training data versus when applied to validation and test data.\n",
+ "\n",
+ "The `Confusion Matrix` is a visual representation of the classification accuracy. Each row is the set of predictions for each true value (with one true value per column). Values along the diagonal indicate true positives (correct predictions). Values below the diagonal indicate false positives. Values above the diagonal indicate false negatives. The optimal scenario is one in which the off-diagonal values are all zero.\n",
+ "\n",
+ "The `Receiver Operator Characteristic (ROC) Curve` curve presents a comparison between the true positive rate (y-axis) and the false positive rate (x-axis) --- for a given false positive rate, the number of true positives that exist. Each point on the curve is for a distinct choice of the Classification threshold for the probability score $[0,1]$: the choice of classification threshold determines which objects are considered correctly classified. The optimal scenario is where the ROC curve is constant at a true positive rate $=1$. If the curve is along the diagonal (lower left to upper right), it indicates that the model performance is equivalent to 50-50 guessing.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.2. Predict classifications with the trained model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Predict classification probabilities on the training, validation, and test sets. Produce both the probabilities of each digit and the top choice for each prediction."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 41,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:24.013950Z",
+ "iopub.status.busy": "2025-02-09T23:13:24.012874Z",
+ "iopub.status.idle": "2025-02-09T23:13:36.594110Z",
+ "shell.execute_reply": "2025-02-09T23:13:36.593536Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:24.013906Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "test data set ... Accuracy: 86.4%, Avg loss: 0.467137\n",
+ "validation data set ... Accuracy: 86.2%, Avg loss: 0.487235\n",
+ "training data set ... Accuracy: 86.0%, Avg loss: 0.487080\n"
+ ]
+ }
+ ],
+ "source": [
+ "y_prob_tes, y_choice_tes, y_true_tes, x_tes = predict(testloader, model,\n",
+ " \"test\")\n",
+ "y_prob_val, y_choice_val, y_true_val, x_val = predict(validloader, model,\n",
+ " \"validation\")\n",
+ "y_prob_tra, y_choice_tra, y_true_tra, x_tra = predict(trainloader, model,\n",
+ " \"training\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Print the shapes and verify that the shape of `y_prob_tes` matches the length of the input data `x_tes` and the number of classes. (as in Section 2.4)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 42,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:36.595037Z",
+ "iopub.status.busy": "2025-02-09T23:13:36.594822Z",
+ "iopub.status.idle": "2025-02-09T23:13:36.743092Z",
+ "shell.execute_reply": "2025-02-09T23:13:36.742096Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:36.595018Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The input data has the shape (5000, 28, 28): there the 5000 images each image has 28 pixels on a side.\n",
+ "The predicted probability score array has the shape (5000, 10): there are 5000 predictions, with 10 probability scores predicted for each input image.\n",
+ "The predicted classes array has has the shape (5000,): there is one top choice (highest probability score) for each prediction.\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(f\"The input data has the shape {np.shape(x_tes)}: there the {subset_size}\\\n",
+ " images each image has 28 pixels on a side.\")\n",
+ "print(f\"The predicted probability score array has the shape\\\n",
+ " {np.shape(y_prob_tes)}: there are {subset_size} predictions,\\\n",
+ " with 10 probability scores predicted for each input image.\")\n",
+ "print(f\"The predicted classes array has has the shape {np.shape(y_choice_tes)}:\\\n",
+ " there is one top choice (highest probability score) for each prediction.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use the `plotPredictionHistogram` function to plot histograms of prediction distributions by class."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 43,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:36.744923Z",
+ "iopub.status.busy": "2025-02-09T23:13:36.744545Z",
+ "iopub.status.idle": "2025-02-09T23:13:37.112883Z",
+ "shell.execute_reply": "2025-02-09T23:13:37.111880Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:36.744887Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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4bLnYLFY9PHHHyshIeGKs/Vz587V22+/rbS0NIWGhmrHjh0aPXq0mjZtql69eumtt97SAw88oNzcXHl7e8vd3f03v7trRdAGAAAAAAcaN26cXnzxRds9xNL5y8aHDh2qxo0bq3HjxpoxY4atfsqUKfrwww/1z3/+s1pBe9u2bTp48KAOHz6s5s2bS5KSk5PVv39/u7q5c+fa/t2qVStNnz5dGzdu1MyZM+Xu7q6GDRvK2dn5qpeK/+Mf/1Bpaalee+012z3iy5cv18CBA7Vo0SIFBARIOj+rvHz5cjk5Oalt27a6//77tX379isG7dTUVD344IOyWCzq0KGDIiMjNXjwYNs5nD59Wqmpqfr444/Vo0cPSVJISIh27dqlFStWqHfv3vL19ZUk+fv7c482AAAAANRnbdu2VWRkpP7+97+rT58++v7777Vz505t3bpV0vkHgb3wwgvauHGj/vOf/6isrExlZWXVftjZwYMH1aJFC1vIlmQLo7/25ptvatmyZfruu+906tQpnTt37jffF325Y3Xq1Mmut549e6qqqkq5ubm2oN2hQwc5OTnZapo1a6Z9+/Zdcb/t27fX/v37lZOTo127dmnHjh0aOHCgxo4dq//6r//S119/rbNnz6pv375225WXl6tLly41OgcjcI82AAAAADhYfHy83nrrLZWUlGj16tVq2bKloqOjJUlLlizR0qVLNXPmTH388cfau3evYmNjVV5eXq19W63WS8YuXKJ+waeffqqHH35Y/fv315YtW7Rnzx7NmTOn2sf49bEu3vfljuni4nLJuqqqqqvuu0GDBurevbumTp2qTZs2KT09XatWrVJeXp5t2/fee0979+61LV9//bXtPu0biRltAAAAAHCwYcOG6cknn9T69eu1Zs0aTZgwwRZMd+7cqcGDB2v06NGSzt9zfejQIbVr165a+27fvr2OHj2q48ePKzAwUNL5V4f92r/+9S+1bNlSc+bMsY0dOXLErsbV1VWVlZW/eaw1a9bo9OnTtlntf/3rX2rQoIHatGlTrX6rq3379pLOXzbevn17mc1mHT16VL17975svaurqyT95jkYgRltAAAAAHCwhg0bavjw4Xr66ad1/Phxuydit27dWhkZGcrOztbBgwc1ceJEFRQUVHvfMTExuuOOO/TII4/oyy+/1M6dO+0C9YVjHD16VBs2bND333+vl156SZs2bbKradWqlfLy8rR37179/PPPKisru+RYo0aNkpubm+Li4rR//3598sknmjJlisaMGWO7bPxaPPjgg1q6dKk+++wzHTlyRJmZmZo0aZLatGmjtm3bysvLSzNmzNDUqVO1Zs0aff/999qzZ4/++te/as2aNZKkli1bymQyacuWLTpx4oTdk9CNRtAGAAAAgDogPj5eRUVFiomJUYsWLWzjzzzzjLp27arY2FhFRUXJYrFoyJAh1d5vgwYNtGnTJpWVlemuu+7S+PHjtXDhQruawYMHa+rUqZo8ebI6d+6s7OxsPfPMM3Y1DzzwgH7/+9+rT58+atq06WVfMebh4aGPPvpI//u//6vu3bvrwQcfVHR0tJYvX16zL+MisbGx2rx5swYOHKg2bdooLi5Obdu21datW+XsfP5C7eeee07z5s1TSkqK2rVrZ9smODhYknTbbbdp/vz5euqppxQQEKDJkydfV09XY7Je7oL9Oq6kpEQ+Pj4qLi6u8c35uPklZSY5uoV6JykqydEtAAAAXJezZ88qLy9PwcHBcnNzc3Q7uEld7XdUkxzKjDYAAAAAAAYiaAMAAAAAYCCCNgAAAAAABiJoAwAAAABgIII2AAAAAAAGImgDAAAAAGAggjYAAAAAAAYiaAMAAAAAYCCCNgAAAAAABiJoAwAAAMAtIj09XY0aNXJ0G/Wes6MbAAAAAIDalJmUeUOPF5UUVe1ak8l01fVxcXFKT0+/pj5atWqlxMREJSYm2saGDx+u++6775r2VxOVlZVavHix1qxZoyNHjsjd3V1t2rTRxIkT9eijj1ZrH5mZmerTp4+Kiopuuj8OELQBAAAAwEHy8/Nt/964caPmzZun3Nxc25i7u7uhx3N3dzd8n5eTlJSklStXavny5erWrZtKSkr0xRdfqKioqNaPXRdw6TgAAAAAOIjFYrEtPj4+MplMdmM7duxQeHi43NzcFBISovnz5+vcuXO27ZOSktSiRQuZzWYFBgbqiSeekCRFRUXpyJEjmjp1qkwmk23m/OJLx5OSktS5c2etXbtWrVq1ko+Pjx5++GGdPHnSVnPy5EmNGjVKnp6eatasmZYuXaqoqCi7mfKLbd68WQkJCXrooYcUHBysTp06KT4+XtOmTbPVWK1WLV68WCEhIXJ3d1enTp305ptvSpIOHz6sPn36SJIaN24sk8mksWPHXu/XfcMQtAEAAACgDvroo480evRoPfHEE/r666+1YsUKpaena+HChZKkN998U0uXLtWKFSt06NAhvfPOOwoLC5Mkvf3222revLkWLFig/Px8u5nzi33//fd65513tGXLFm3ZskVZWVl64YUXbOunTZumf/3rX3r33XeVkZGhnTt36t///vdVe7dYLPr444914sSJK9bMnTtXq1evVlpamg4cOKCpU6dq9OjRysrKUlBQkN566y1JUm5urvLz8/WXv/yl2t+do3HpOAAAAADUQQsXLtRTTz2luLg4SVJISIiee+45zZw5U88++6yOHj0qi8WimJgYubi4qEWLFrrrrrskSb6+vnJycpKXl5csFstVj1NVVaX09HR5eXlJksaMGaPt27dr4cKFOnnypNasWaP169crOjpakrR69WoFBgZedZ+pqal68MEHZbFY1KFDB0VGRmrw4MHq37+/JOn06dNKTU3Vxx9/rB49etjOb9euXVqxYoV69+4tX19fSZK/v/9Nd482M9oAAAAAUAfl5ORowYIFatiwoW2ZMGGC8vPzdebMGT300EMqLS1VSEiIJkyYoE2bNtldVl5drVq1soVsSWrWrJkKCwslST/88IMqKipsAV6SfHx8dMcdd1x1n+3bt9f+/fv16aef6tFHH9VPP/2kgQMHavz48ZKkr7/+WmfPnlXfvn3tzu+1117T999/X+NzqGuY0QYAAACAOqiqqkrz58/X0KFDL1nn5uamoKAg5ebmKiMjQ9u2bVNCQoJefPFFZWVlycXFpdrHubjWZDKpqqpK0vn7qC+M/dqF8atp0KCBunfvru7du2vq1Klat26dxowZozlz5tj2/9577+m2226z285sNle797qKoA0AAAAAdVDXrl2Vm5ur1q1bX7HG3d1dgwYN0qBBgzRp0iS1bdtW+/btU9euXeXq6qrKysrr6uH222+Xi4uLPv/8cwUFBUmSSkpKdOjQIfXu3btG+2rfvr2k85eNt2/fXmazWUePHr3iflxdXSXpus/BEQjaAAAAAFAHzZs3TwMGDFBQUJAeeughNWjQQF999ZX27dun559/Xunp6aqsrFRERIQ8PDy0du1aubu7q2XLlpLOXxK+Y8cOPfzwwzKbzWrSpEmNe/Dy8lJcXJz+9Kc/ydfXV/7+/nr22WfVoEGDq74D/MEHH1TPnj0V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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Histograms_top_choice\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotPredictionHistogram(y_choice_tra,\n",
+ " y_prediction_b=y_choice_val,\n",
+ " y_prediction_c=y_choice_tes,\n",
+ " label_a=\"Training Set\",\n",
+ " label_b=\"Validation Set\",\n",
+ " label_c=\"Testing Set\",\n",
+ " figsize=(12, 5),\n",
+ " alpha=0.5,\n",
+ " xlabel_plot=\"Predicted class label\",\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 4: Histograms of the number of images for which the top-choice class was each number 0 through 9. Each histogram is for a different data set used during model training --- training data, validation data, and test data. Note that these are overlapping histograms, not stacked. Please compare to Figure 3, which shows the distributions of true class labels for each data set. Consider which classes are represented differently between the true labels and the predicted labels."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:37.114356Z",
+ "iopub.status.busy": "2025-02-09T23:13:37.114005Z",
+ "iopub.status.idle": "2025-02-09T23:13:38.178779Z",
+ "shell.execute_reply": "2025-02-09T23:13:38.178135Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:37.114322Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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dHVpdklJSZo6daruvvtuPf/887rsssv01Vdf6euvv5ZU8qOM/2jYsGE6cuSIbr/9drVp00aenp76+eefNXXqVHl4eOiJJ56QJNWqVUuvvfaakpKSdOjQIQ0YMED169fX/v379eOPP2r//v32MyKKdjpeeeUVJSUlydvbW82bN3c4qgQANUmHDh3Url07TZs2TcYYh0swpbM7Gs8995zGjx9vf1rXs88+q8aNG+v06dNlWpaHh4eee+45DR06VLfddpvuv/9+HTlyRKmpqcUuw7z55ps1ZcoUJSQkaNiwYTp48KD+9re/lXimVdu2bbVgwQK9//77atKkifz8/ByaTH80adIkde/eXTfccIMee+wx+fj4aMaMGfrpp5/03nvvlXg2d3m0bt1aXbt2Ve/evdW0aVOdPHlSa9as0csvv6ywsDD7z7lz584aNmyY7r33Xq1fv17XX3+9AgMDlZ2drRUrVqht27Z64IEH7Ou5cOFCzZw5U+3bt5eHh4fDzg0AwNGdd96p+fPn66abbtLDDz+sa665Rt7e3tq9e7eWLl2qW265RbfddpveeOMNffvtt7r55pvVqFEjnTx50n65fLdu3SSdPQstKipKn376qbp27aqQkBDVrVtX0dHRl1RjSkqKZs+erd69e+vZZ59VWFiY3n33Xf3888+SLr7P1LNnTzVo0EB9+/ZVixYtVFhYqMzMTL388suqVauWHn74YUlSdHS0nn32WT311FPatm2bevXqpTp16mjv3r1au3atAgMDNWHCBEn/v8/04osvqnfv3vL09FS7du3sJyCgmnLl0wWACznf0zBbt25d4viVK1eauLg4ExAQYOrVq2eGDh1qvv/++2JP/jrf0zBvvvnmYvOMj493eKLY+Z6GeW6d51vOzp07Tf/+/U2tWrVMUFCQuf32282XX35pJJlPP/30fD8KY4wxX3/9tbnvvvtMq1atjNVqNV5eXiYiIsL079/frFq1qtj4ZcuWmZtvvtmEhIQYb29v86c//cncfPPN5sMPP3QYN27cOBMZGWk8PDxK9YQZAKjuXnnlFSPJtGrVqthn+fn55rHHHjN/+tOfjJ+fn7nqqqvMJ598YpKSkoo9mVEXeRpmkX/84x8mJibG+Pj4mGbNmpnZs2eXOL/Zs2eb5s2bG19fX9OkSRMzadIkM2vWrGJPHMvKyjI9evQwQUFB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fPLJJ7rsssvk6emplJSUSllGZerSpUul1R0dHa1p06ZVyrwB4FKQT+6PfAJQE5FP7o98qrloltVAycnJslgsslgs8vb2VpMmTfTYY4/p+PHjri6tVBo2bKjs7Gy1adOmxM8HDRqkX375xf6+okJIkoYPH64BAwZo165deu655ypknkX++Hv546tXr14VupzyyMvL01NPPaUWLVrIz89P4eHh6tatmxYuXChjjKvLA1BNkE/lRz6RTwAqD/lUfuQT+VRVebm6ALhGr169NGfOHJ06dUrLly/X0KFDdfz4cc2cObPY2FOnTsnb29sFVZbM09NT4eHh5/3c399f/v7+Fb7cY8eOad++ferZs6ciIyPLPZ+CggL5+PiU+FnR7+WPfH19y72sinDkyBFde+21ys3N1fPPP6+rr75aXl5eWrZsmcaOHasbb7yx0o5EAah5yKeyI5/IJwCVj3wqO/KJfKrKOLOshvL19VV4eLgaNmyohIQEDR482H7qbtGRhNmzZ6tJkyby9fWVMUY7d+7ULbfcolq1aik4OFgDBw7U3r17i837zTffVMOGDRUQEKA77rjDfnqvJK1bt07du3dX3bp1ZbVaFR8fr++//77YPLKzs9W7d2/5+/urcePG+vDDD+2fnXsa8bn+eBpxWlqaJkyYoB9//NF+pCEtLU333Xef+vTp4/C906dPKzw8XLNnzy42z4yMDAUFBUmSbrzxRlksFmVkZEiSPv74Y7Vu3Vq+vr6Kjo7Wyy+/7PDd6OhoPf/880pOTpbVatX9999fYt3S//9e/viqU6eO/fMpU6aobdu2CgwMVMOGDTVy5EgdO3bMYR7//ve/FR8fr4CAANWpU0c9e/bU4cOH7Z8XFhZq7NixCgkJUXh4uFJTU89bjyT9+c9/VlZWltasWaOkpCS1atVKzZo10/3336/MzEzVqlWrxO9drNYdO3aob9++qlOnjgIDA9W6dWt9+eWXkqTDhw9r8ODBqlevnvz9/RUTE1MsBAFUT+QT+UQ+AXBH5BP5RD7VLDTLIOns0YRTp07Z3//3v//VBx98oI8//ti+Ub311lt16NAhLVu2TEuWLNFvv/2mQYMGOcyn6Hv//Oc/lZ6erszMTD344IP2z48ePaqkpCQtX75cq1evVkxMjG666SYdPXrUYT5PP/20br/9dv3444+6++67ddddd2nLli1lXq9BgwZpzJgxat26tbKzs5Wdna1BgwZp6NChSk9PV3Z2tn3sl19+qWPHjmngwIHF5tOpUydt3bpV0tmNe3Z2tjp16qQNGzZo4MCBuvPOO7Vx40alpqbq6aefVlpamsP3X3rpJbVp00YbNmzQ008/Xeb1KOLh4aFXX31VP/30k+bOnatvv/1WY8eOtX+emZmprl27qnXr1lq1apVWrFihvn376syZM/Yxc+fOVWBgoNasWaPJkyfr2Wef1ZIlS0pcXmFhoRYsWKDBgweXeDSoVq1a8vIq+QTVi9X64IMPKj8/X9999502btyoF1980R4cTz/9tDZv3qyvvvpKW7Zs0cyZM1W3bt1y/cwAVG3kE/lUEvIJgKuRT+RTScinasSgxklKSjK33HKL/f2aNWtMaGioGThwoDHGmPHjxxtvb2+zb98++5jFixcbT09Ps3PnTvu0TZs2GUlm7dq19u95enqaXbt22cd89dVXxsPDw2RnZ5dYy+nTp01QUJD55z//aZ8myYwYMcJhXGxsrHnggQeMMcZs377dSDI//PCDMcaYpUuXGknm8OHDxhhj5syZY6xWq/2748ePN5dffnmxZbdq1cq8+OKL9ve33nqrSU5OLrFOY4w5fPiwkWSWLl1qn5aQkGC6d+/uMO7xxx83rVq1sr+Piooyt95663nnWyQpKcl4enqawMBAh9ezzz573u988MEHJjQ01P7+rrvuMp07dz7v+Pj4eHPttdc6TLv66qvNE088UeL4vXv3GklmypQpF60/KirKTJ06tdS1tm3b1qSmppY4tm/fvubee++96DIBVC/k01nk01nkEwB3QT6dRT6dRT7VDJxZVkN9/vnnqlWrlvz8/BQXF6frr79er732mv3zqKgo1atXz/5+y5YtatiwoRo2bGif1qpVK9WuXdvhiEWjRo3UoEED+/u4uDgVFhbajyrs27dPI0aMULNmzWS1WmW1WnXs2DHt3LnTob64uLhi78tzZORChg4daj81dd++ffriiy903333lWkeW7ZsUefOnR2mde7cWb/++qvD0YgOHTqUan433HCDMjMzHV5/PLK0dOlSde/eXX/6058UFBSke+65RwcPHrTfXLToyMiFtGvXzuF9RESE9u3bV+JYY7v5pMViKVX9f3SxWkePHq3nn39enTt31vjx4/Wf//zH/t0HHnhACxYs0BVXXKGxY8dq5cqVZV4+gKqJfCKfipBPANwJ+UQ+FSGfagaaZTVU0UZl69atOnnypBYuXKj69evbPw8MDHQYb4wp8S/8+aYXKfqs6L/JycnasGGDpk2bppUrVyozM1OhoaEqKCi4aM3l2eBcyD333KNt27Zp1apVmjdvnqKjo3XdddeVaR4lrb8p4ekm5/48zycwMFCXXXaZwyskJETS2WvUb7rpJrVp00Yff/yxNmzYoNdff12S7KeAl+bGnOfebNRisaiwsLDEsfXq1VOdOnXKHLSlqXXo0KHatm2bEhMTtXHjRnXo0MH+D47evXtrx44dSklJ0Z49e9S1a1c99thjZaoBQNVEPpFPRcgnAO6EfCKfipBPNQPNshqqaKMSFRVVqie1tGrVSjt37tSuXbvs0zZv3qzc3Fy1bNnSPm3nzp3as2eP/f2qVavk4eGhZs2aSZKWL1+u0aNH66abbrLf1PHAgQPFlrd69epi71u0aFHm9ZQkHx8fh6MURUJDQ3Xrrbdqzpw5mjNnju69994yz7tVq1ZasWKFw7SVK1eqWbNm8vT0LFe957N+/XqdPn1aL7/8sjp27KhmzZo5/Kyls0c9/vWvf1XYMj08PDRo0CDNnz+/2LIk6fjx4zp9+nS5apXOPsZ6xIgRWrhwocaMGaO33nrL/lm9evWUnJysefPmadq0afr73/9eYesFwH2RT+RTaZBPAJyNfCKfSoN8qj5KvrMccI5u3bqpXbt2Gjx4sKZNm6bTp09r5MiRio+PdzhF1s/PT0lJSfrb3/6mvLw8jR49WgMHDrQ/qviyyy7TO++8ow4dOigvL0+PP/54id38Dz/8UB06dNC1116r+fPna+3atZo1a1a5ao+Ojtb27duVmZmpBg0aKCgoyP444aFDh6pPnz46c+aMkpKSyjzvMWPG6Oqrr9Zzzz2nQYMGadWqVZo+fbpmzJhRrlrz8/OVk5PjMM3Ly0t169ZV06ZNdfr0ab322mvq27ev/v3vf+uNN95wGDtu3Di1bdtWI0eO1IgRI+Tj46OlS5fqjjvuKPcNHidOnKiMjAzFxsbqr3/9qzp06CBvb28tX75ckyZN0rp164o9+rg0taakpKh3795q1qyZDh8+rG+//db+D4dnnnlG7du3V+vWrZWfn6/PP//c4R8VAFCEfCoZ+UQ+AXAt8qlk5BP5VGW44D5pcLFzb1B5rvPd0HHHjh2mX79+JjAw0AQFBZk77rjD5OTkFPvejBkzTGRkpPHz8zP9+/c3hw4dso/5/vvvTYcOHYyvr6+JiYkxH374YbEbG0oyr7/+uunevbvx9fU1UVFR5r333rN/XtYbVJ48edLcfvvtpnbt2kaSmTNnjv2zwsJCExUVZW666aaL/txKukGlMcZ89NFHplWrVsbb29s0atTIvPTSSw6fX+zGjUWSkpKMpGKv5s2b28dMmTLFREREGH9/f9OzZ0/z9ttvO6y7McZkZGSYTp06GV9fX1O7dm3Ts2dP++fx8fHm4YcfdljuLbfcYpKSki5Y25EjR8yTTz5pYmJijI+PjwkLCzPdunUzixYtMoWFhSWu58Vqfeihh0zTpk2Nr6+vqVevnklMTDQHDhwwxhjz3HPPmZYtWxp/f38TEhJibrnlFrNt27aL/gwBVG3k0xz7Z+QT+QTAfZBPc+yfkU/kU01hMaaEC4SBGuL3339XZGSkZs+erf79+7u6HAAAJJFPAAD3RD6hpuAyTNRIhYWFysnJ0csvvyyr1ap+/fq5uiQAAMgnAIBbIp9Q09AsQ420c+dONW7cWA0aNFBaWpq8vPirAABwPfIJAOCOyCfUNFyGCQAAAAAAANh4uLoAAAAAAAAAwF3QLAMAAAAAAABsaJYBAAAAAAAANjTLAAAAAAAAABuaZQAAAAAAAIANzTIAAAAAAADAhmYZAAAAAAAAYEOzDAAAAAAAALD5P9Tjuee4SdPYAAAAAElFTkSuQmCC",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Histograms_class_probabilities\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotPredictionHistogram(y_prob_tra,\n",
+ " y_prediction_b=y_prob_val,\n",
+ " y_prediction_c=y_prob_tes,\n",
+ " title_a='Training Set',\n",
+ " title_b='Validation Set',\n",
+ " title_c='Testing Set',\n",
+ " figsize=(15, 4),\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 5: Histograms of the number of images (y-axis) that had a probability (x-axis) of being each class 0 through 9 (light to dark shades)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In both of Figure 3 and 4, the histograms show very similar shapes across the classification categories.\n",
+ "This is a good sign because it indicates the model is not heavily biased toward a particular class."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.3. Generalization Error\n",
+ "\n",
+ "The primary task in optimizing a network is to minimize the Generalization Error. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.3.1. Loss History: History of Loss and Accuracy during Training"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot the loss history for the validation and training sets. We reserve the test set for a 'blind' analysis."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:38.179887Z",
+ "iopub.status.busy": "2025-02-09T23:13:38.179456Z",
+ "iopub.status.idle": "2025-02-09T23:13:38.694470Z",
+ "shell.execute_reply": "2025-02-09T23:13:38.693818Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:38.179865Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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d21wLHy62pjENHvQ2H0ikSsbBDCwZWjp3lsRKFhUEgoWIiIiItWQLQtO7jVDxqn9EHcY4iPNrlXxR8GWcYETWMA79KyB43VyZ6zyCwev0CK3eJS14nyerRw1FhERERGpKhysENjI3M5ly4KkE2bIsAeOw9mh47D5PDPFnB434ShErszn/I7m7FT20BEBYZeb63RUYgoWIiIiIiKlxcFqtkZ4h0KdTue/bxhwJibvbFX2QeTZ4SMrPfe9HG1vVbAQEREREZFsFgt4Bplb2OXnv2+zQeLx7BaPs0JHRNfyr2sxKViIiIiIiFQWDg7ZA79rQXjniq5NsVS9dcVFRERERKTSUbAQEREREZESU7AQEREREZESU7AQEREREZESU7AQEREREZES06xQZShnUfOEhIQKromIiIiISPHlfI7N+VxbGAWLMpSYmAhAWFhYBddEREREROTiJSYm4uPjU2gZi1GU+CEXxWazcezYMby8vLBYLOV67YSEBMLCwjh8+DDe3t7lem2pHPRv4NKm77/o38ClTd//S1tpfv8NwyAxMZHQ0FAcHAofRaEWizLk4OBA7dq1K7QO3t7e+oFyidO/gUubvv+ifwOXNn3/L22l9f2/UEtFDg3eFhERERGRElOwEBERERGRElOwqKZcXFx47rnncHFxqeiqSAXRv4FLm77/on8DlzZ9/y9tFfX91+BtEREREREpMbVYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYiIiIiIhIiSlYlJN//vmHQYMGERoaisViYd68eWV6vcmTJ2OxWPJswcHBZXpNEREREbl0KViUkzNnztCqVSvefffdcrtms2bNOH78uH3bunVruV1bRERERC4tjhVdgUtF//796d+/f4Hvp6en8/TTT/P1118TFxdH8+bNee211+jRo8dFX9PR0VGtFCIiIiJSLtRiUUncdtttrFixgu+++44tW7Zwww030K9fP/bs2XPR59yzZw+hoaHUrVuXkSNHsn///lKssYiIiIhILothGEZFV+JSY7FYmDt3LkOHDgVg3759NGjQgCNHjhAaGmov17t3bzp06MDLL79c7GssWLCA5ORkGjZsyIkTJ5gyZQr//fcf27dvp0aNGqV1KyIiIiIigFosKoUNGzZgGAYNGzbE09PTvi1dupR9+/YBcPDgwfMGY5+7jRs3zn7O/v37c91119GiRQt69+7Nr7/+CsDnn39eIfcoIiIiItWbxlhUAjabDavVyvr167FarXne8/T0BKBWrVrs3Lmz0PP4+fkV+J6HhwctWrQoUdcqEREREZGCKFhUAm3atCErK4vo6Gi6du2abxknJycaN2580ddIS0tj586dBZ5fRERERKQkFCzKSVJSEnv37rW/PnDgAJs2bcLf35+GDRty8803c+uttzJ16lTatGlDbGwsS5YsoUWLFgwYMKDY15swYQKDBg2iTp06REdHM2XKFBISEhg9enRp3paIiIiICKDB2+Xm77//pmfPnuftHz16NJ999hkZGRlMmTKFL774gqNHj1KjRg06d+7M888/T4sWLYp9vZEjR/LPP/8QGxtLYGAgnTp14sUXX6Rp06alcTsiIiIiInkoWIiIiIiISIlpVigRERERESkxBQsRERERESkxDd4uQzabjWPHjuHl5YXFYqno6oiIiIiIFIthGCQmJhIaGoqDQ+FtEgoWZejYsWOEhYVVdDVERERERErk8OHD1K5du9Ayl1SwmDFjBm+88QbHjx+nWbNmTJ8+vdB1HZYuXcojjzzC9u3bCQ0N5fHHH+eee+4p8vW8vLwA8xvh7e1d4vqLiIiIiJSnhIQEwsLC7J9rC3PJBItZs2Yxfvx4ZsyYQZcuXfjwww/p378/O3bsoE6dOueVP3DgAAMGDGDs2LF89dVXrFixgvvuu4/AwECuu+66Il0zp/uTt7e3goWIiIiIVFlF6dZ/yUw327FjR9q2bcv7779v39ekSROGDh3KK6+8cl75iRMnMn/+fHbu3Gnfd88997B582ZWrVpVpGsmJCTg4+NDfHy8goWIiIiIVDnF+Tx7SbRYpKens379ep544ok8+/v06cPKlSvzPWbVqlX06dMnz76+ffvyySefkJGRgZOTU7Gun56eft5+BwcHHB0d85QriMViyXPN4pTNyMigoPxYVmUBnJ2dL6psZmYmNputVMo6OTnZE3ZZlc3KyiIrK6tUyjo6OtoHRlWGsjabjczMzALLWq1WrFZrpSlrGAYZGRmlUvbs/59lVRYK/7+snxH5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w15AaQWLS2aMhVRibm7Qo4e5gfkhft263KCxfLnZWgFml64+faBvX7M1w9OzfOro7Gy2ogQGFq18QoIZMnKCxtmhIzLSHJuSM92gYUBysrkVl59fbsg4N3RERJhf29IUHw9HjuSOqTl82AxWrVrBVVdB/fpqfRERkUvWW2+9VaRpXqsrBQupfJyd4YorzG3SJLP71PbtuV2LqgJvb2je3NwKkplptszkhIrCtjNnIDoaDhzI3WJj4fRpc9uwIf9r5IwFydn8/PK+Pnfz9ja7g50dHM7eLjROJSzMDBg5W+3axf3KiYiIVJj09PRiTa96Lp9LvCeBgoVUfo6O5l/EqxtHR3OA98UO8k5MNMeZHDyYN3DkbImJud21Dh0qvXr7+poBImfz8TG7sq1aZYaPzz83N4AGDaBXLzNk9OhR9BYfERGRctCjRw+aN2+Os7MzX3zxBc2aNeP9999nwoQJ/PPPP3h4eNCnTx+mTZtGQEAAALNnz+b5559n7969uLu706ZNG3766Sc8PDzO6wp15swZ7r33Xn788Ue8vLyYMGHCeXWwWCzMnTuXoUOH2vf5+voyffp0xowZA8DEiROZO3cuR44cITg4mJtvvplnn322VFfNLg0KFiJVlZeXOai9RYvz3zMMsyUjJsYc75Hfdvr0+fvi481WjbODQ85Wu7b5WFD3s+RkWLHCnI1syRKzO9uePeb2wQdmmZwuU127mucKCjLDRml32RIRkYqV0823Iri7F6tb7ueff869997LihUrOHXqFN27d2fs2LG8+eabpKSkMHHiRIYPH86SJUs4fvw4N954I6+//jrXXnstiYmJLFu2rMDuT4899hh//fUXc+fOJTg4mCeffJL169fTunXrYt2Sl5cXn332GaGhoWzdupWxY8fi5eXF448/XqzzlDUFC5HqyGLJXZujvLi7m7NxXX21+TouzhwjkxM0tm6FzZvNbdq0vMd6eZkBIyjo/C1nf0BA7lS/3t5lv8iiiIhcvOTk8hsHea6kJHPmxSKqX78+r7/+OgDPPvssbdu25eWXX7a//+mnnxIWFsbu3btJSkoiMzOTYcOG2ddCa5HfH/iApKQkPvnkE7744guuzv7d+Pnnn1P7IroJP/300/bnERERPProo8yaNUvBQkQuEb6+MHiwuYE5YP3vv3NbM6KjzS093ey2lZgI+/cX/fzu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fqjr7wOCgoKca6pK1KxZk7p16zqP6x7wbtOnT2fw4ME0bNiQrKws5syZQ05ODmPGjLHn3wC31JoS27388stWo0aNrOrVq1sdO3Z0lp8U7/PJJ59YwFnbmDFjLMsy5eZiYmKssLAwy9/f3+rZs6eVkpJib9BSLs513QHr9ddfdz5H19+73XPPPc5/66+66iqrX79+1qZNm5zndf19zx/LzVqW7gFvd+utt1r169e3qlWrZoWHh1vDhw+39uzZ4zzv6evvsCzLck/KIiIiIiIivkJrLEREREREpMyUWIiIiIiISJkpsRARERERkTJTYiEiIiIiImWmxEJERERERMpMiYWIiIiIiJSZEgsRERERESkzJRYiIiIiIlJmSixERMTnOBwO1q1bZ3cYIiJeRYmFiIh41NixY3E4HGdtAwcOtDs0EREpg6p2ByAiIr5n4MCBvP766y7H/P39bYpGRETKg0YsRETE4/z9/QkLC3PZateuDZhpSnFxcURHRxMQEECTJk1Yu3aty+tTUlLo27cvAQEB1K1bl3HjxnHixAmX5yxfvpw2bdrg7+9P/fr1mTRpksv5o0ePMmzYMAIDA2nevDkJCQnu/aNFRLycEgsREalwnnjiCUaMGMHXX3/NnXfeye23387evXsBOHnyJAMHDqR27dokJSWxdu1aPvroI5fEIS4ujokTJzJu3DhSUlJISEigWbNmLu/x1FNPccstt7B7925uuukm7rjjDo4dO+bRv1NExJs4LMuy7A5CRER8x9ixY1m1ahU1atRwOf7oo4/yxBNP4HA4GD9+PHFxcc5z3bp1o2PHjixevJhXX32VRx99lPT0dGrWrAnA+vXrGTx4MBkZGYSGhnL11Vdz9913M2fOnHPG4HA4ePzxx3n66acByMvLIygoiPXr12uth4jIZdIaCxER8bg+ffq4JA4AderUce5HRUW5nIuKiiI5ORmAvXv3EhkZ6UwqAK6//nqKi4tJTU3F4XCQkZFBv379LhhD+/btnfs1a9YkKCiIrKysy/2TRER8nhILERHxuJo1a541NeliHA4HAJZlOffP9ZyAgIBS/b5q1aqd9dri4uJLiklERM7QGgsREalwtm/fftbjVq1aAdC6dWuSk5PJy8tznv/iiy/w8/OjRYsWBAUF0bhxYz7++GOPxiwi4us0YiEiIh5XUFBAZmamy7GqVatSr149ANauXUvnzp3p3r07q1evZseOHSxbtgyAO+64g5iYGMaMGUNsbCw///wzkydPZvTo0YSGhgIQGxvL+PHjCQkJITo6mtzcXL744gsmT57s2T9URMSHKLEQERGP+/DDD6lfv77LsZYtW7Jv3z7AVGxas2YNEyZMICwsjNWrV9O6dWsAAgMD2bhxI1OmTOHaa68lMDCQESNG8MILLzh/15gxY8jPz2fhwoVMnz6devXqMXLkSM/9gSIiPkhVoUREpEJxOBzEx8czdOhQu0MREZFLoDUWIiIiIiJSZkosRERERESkzLTGQkREKhTN0BURqZw0YiEiIiIiImWmxEJERERERMpMiYWIiIiIiJSZEgsRERERESkzJRYiIiIiIlJmSixERERERKTMlFiIiIiIiEiZKbEQEREREZEyU2IhIiIiIiJl9v8n2zGbtn0X/AAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"LossHistory\"\\\n",
+ " + \"_\"\\\n",
+ " + path_dict['run_label']\n",
+ "\n",
+ "plotLossHistory(history,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 6: In the top panel, the loss history as a function of epoch for the training and validation sets decreases with time, as it should as the model improves. In the bottom panel, the loss residual (validation - training) shows a dip at epoch 2, indicating the model caused a divergence in the training and validation set classifications, but that this was rectified in later epochs."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-10-26T18:50:41.751869Z",
+ "iopub.status.busy": "2024-10-26T18:50:41.751239Z",
+ "iopub.status.idle": "2024-10-26T18:50:41.757103Z",
+ "shell.execute_reply": "2024-10-26T18:50:41.756503Z",
+ "shell.execute_reply.started": "2024-10-26T18:50:41.751843Z"
+ }
+ },
+ "source": [
+ "### 4.3.2. Confusion Matrix: Bias in Trained Model?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Compute and plot the confusion matrices for the training, validation, and test samples (left, right, middle)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 46,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:38.695466Z",
+ "iopub.status.busy": "2025-02-09T23:13:38.695205Z",
+ "iopub.status.idle": "2025-02-09T23:13:40.428933Z",
+ "shell.execute_reply": "2025-02-09T23:13:40.427883Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:38.695446Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAABMgAAAE6CAYAAADjrG66AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABl40lEQVR4nO3deZyO9f7H8fdtlnvGYOw7gwglhBSSjkohaScpQidx6kglkwolUylNqaGslY60qNMi5bRLsqTlxJF+lilGtuzmHjPz/f3hzJxuM6b7mrmuuea+7tfzPK7Haa77uj/X575xvef6XpvPGGMEAAAAAAAARKhybjcAAAAAAAAAuIkBMgAAAAAAAEQ0BsgAAAAAAAAQ0RggAwAAAAAAQERjgAwAAAAAAAARjQEyAAAAAAAARDQGyAAAAAAAABDRGCADAAAAAABARGOADAAAAAAAABGNATIP8Pl8IU2ffvppidYzYcIE+Xy+Yr33008/taWHkqw7b4qNjVWNGjXUpUsXjRs3Tlu3bi127e3bt2vChAn69ttv7WsYADzqiiuuUHx8vPbt23fSZa6//nrFxMTot99+C7muz+fThAkT8n+2kjmDBw9Wo0aNQl7XH6WlpWnevHkF5m/ZskU+n6/Q15yWl9V5U/ny5VW/fn1dfPHFmjZtmg4ePFjs2suXL9eECROK/PMDANijtPbxJOnIkSOaMGFCyLXyci5viomJUbVq1XTWWWfpjjvu0I8//lhqvQB2ina7AZTcV199FfTzQw89pE8++UQff/xx0PzTTjutROsZNmyYLrnkkmK9t127dvrqq69K3ENJTJ48WX/5y1+Uk5OjPXv26Ouvv9acOXP05JNPaubMmbr++ust19y+fbsmTpyoRo0aqW3btvY3DQAeMnToUL311lv6xz/+oREjRhR4ff/+/XrzzTd16aWXqlatWsVeT2llTlpamqpXr67BgwcHza9Tp46++uornXLKKY6uvyhLlixRYmKisrKytH37dn300UcaM2aMpkyZonfeeUdt2rSxXHP58uWaOHGiBg8erMqVK9vfNAAgX2nt40nHB6UmTpwoSTr//PNDft9tt92mAQMGKDc3V/v27dPatWs1Z84cTZs2TSkpKbr77rtLrRfADgyQecA555wT9HONGjVUrly5AvNPdOTIEZUvXz7k9dSvX1/169cvVo+VKlX6036c1qxZs6AeLrvsMt1555268MILNXjwYLVu3VpnnHGGix0CgLf17NlTdevW1Zw5cwodIFuwYIGOHj2qoUOHlmg9bmeO3+93PfPat2+v6tWr5//cv39//e1vf1O3bt102WWX6aeffpLf73exQwBAUYq7j1eaGjZsGNRPr169NHr0aF155ZUaM2aMWrVqpZ49e7rYIWANl1hGiPPPP1+tWrXS559/rs6dO6t8+fIaMmSIJGnhwoXq0aOH6tSpo/j4eLVs2VJjx47V4cOHg2oUdollo0aNdOmll2rJkiVq166d4uPj1aJFC82ZMydoucIudxk8eLAqVKign3/+Wb169VKFChXUoEED3XnnnQoEAkHv//XXX3X11VerYsWKqly5sq6//nqtWrWqxJewVK1aVc8995yys7P15JNP5s//+eefddNNN6lZs2YqX7686tWrpz59+uiHH34I+kxnnXWWJOmmm27KP8U47zKf1atXq3///mrUqJHi4+PVqFEjXXfddSW6pBMAwllUVJQGDRqkNWvWBG1P88ydO1d16tRRz549tWvXLo0YMUKnnXaaKlSooJo1a6p79+764osv/nQ9J7vEct68eWrevLn8fr9atmypF198sdD3T5w4UWeffbaqVq2qSpUqqV27dpo9e7aMMfnLNGrUSD/++KM+++yz/O1/3qWaJ7vEctmyZbrgggtUsWJFlS9fXp07d9Z7771XoEefz6dPPvlEt956q6pXr65q1arpyiuv1Pbt2//0sxelTZs2GjdunNLT07Vw4cL8+UuXLlXfvn1Vv359xcXFqWnTprrlllu0e/fu/GUmTJiQfyZA48aNC1zaE+rvEgAA+2RlZWnSpElq0aKF/H6/atSooZtuukm7du0KWu7jjz/W+eefr2rVqik+Pl4NGzbUVVddpSNHjmjLli2qUaOGpOP5l7d9P/Hs6FDFx8dr9uzZiomJ0ZQpU/Lnh5Lrf9ZLKPtoQElwBlkEycjI0MCBAzVmzBhNnjxZ5codHx/duHGjevXqpVGjRikhIUH/+c9/9Oijj2rlypUFTuEtzHfffac777xTY8eOVa1atTRr1iwNHTpUTZs21XnnnVfke48dO6bLLrtMQ4cO1Z133qnPP/9cDz30kBITE/XAAw9Ikg4fPqy//OUv2rt3rx599FE1bdpUS5YsUb9+/Ur+pUg666yzVKdO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27evFDsrWrVq1bRy5coC83fs2GFL/ZUrV2rHjh1BO2bz58/XjTfeqMmTJwctu3v37pAebb9//369++67Gj9+vMaOHZs/PxAI5F9/DwCRKj4+Xtddd51mzpypjIwMzZkzRxUrVtQ111yTv8z8+fN1/vnna/r06UHvPXjwoOX15Q02FZYbJ8575ZVXFBMTo3fffTfoAM5bb71leb15qlSponLlyikjI6PAa3k33i+t+1LmnbWXdw+3f//73/ruu+80b948DRo0KH+5n3/+OeSa4fC7BAB4Td5DXJYsWVLo6xUrVsz/765du6pr167KycnR6tWrNW3aNI0aNUq1atVS//79be9t27ZtWrNmjbp166bo6ONDDnbkekn30YA/wxlkES5v0OzEGws/99xzbrRTqG7duungwYN6//33g+a/8sorJa69d+9eDR8+XDExMbrjjjvy5/t8vgLfyXvvvadt27YFzTvZEX2fzydjTIEas2bNUk5OTon7BoBwN3ToUOXk5GjKlClavHix+vfvr/Lly+e/Xth2+Pvvv9dXX31leV3NmzdXnTp1tGDBgqBLPrZu3arly5cHLevz+RQdHa2oqKj8eUePHtVLL71UoG6oZ0snJCTo7LPP1qJFi4KWz83N1fz581W/fn2deuqplj+XVd99950mT56sRo0a6dprr5Vk7feAojIv1BoAAHtceuml2rNnj3JyctShQ4cCU2E3rI+KitLZZ5+tZ599VpL0zTffSLLvLOW8GsOGDVN2drbGjBmTPz/UXC+ql1D30YDi4gyyCNe5c2dVqVJFw4cP1/jx4xUTE6OXX35Z3333ndut5Rs0aJCefPJJDRw4UJMmTVLTpk31/vvv64MPPpCkAk8fO5mNGzdqxYoVys3N1Z49e/T1119r9uzZOnDggF588UWdfvrp+cteeumlmjdvnlq0aKHWrVtrzZo1mjJlSv4TKvOccsopio+P18svv6yWLVuqQoUKqlu3rurWravzzjtPU6ZMUfXq1dWoUSN99tlnmj17Nkc3AEBShw4d1Lp1a6WmpsoYE3QWr3R8O/zQQw9p/Pjx6tatmzZs2KAHH3xQjRs3VnZ2tqV1lStXTg899JCGDRumK664QjfffLP27dunCRMmFLjEsnfv3po6daoGDBigv/71r9qzZ48ef/zxQp9QecYZZ+iVV17RwoUL1aRJE8XF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tadPn67WrVurUqVKqlSpkjp16qT333/fltp/lJKSIp/Pp1GjRtlSb8KECfL5fEFT7dq1baktSdu2bdPAgQNVrVo1lS9fXm3bttWaNWtKXLdRo0YF+vb5fBo5cmSJa2dnZ+u+++5T48aNFR8fryZNmujBBx9Ubm5uiWtL0sGDBzVq1CglJSUpPj5enTt31qpVq2ypDcA68iwYeVY48qwg8gwoW8Itz5zMMok8OxnyrCDyzB4RO0C2cOFCjRo1SuPGjdPatWvVtWtX9ezZM+hRocV1+PBhtWnTRs8884wNnQb77LPPNHLkSK1YsUJLly5Vdna2evToocOHD5e4dv369fXII49o9erVWr16tbp3766+ffvqxx9/tKHz41atWqXnn39erVu3tq2mJJ1++unKyMjIn3744Qdb6v7+++/q0qWLYmJi9P7772vdunV64oknVLly5RLXXrVqVVDPS5culSRdc801Ja796KOPasaMGXrmmWe0fv16PfbYY5oyZYqmTZtW4tqSNGzYMC1dulQvvfSSfvjhB/Xo0UMXXnihtm3bZkt9AKEjzwoizwoizwpHngFlRzjmmZNZJpFnhSHPCkee2cREqI4dO5rhw4cHzWvRooUZO3asreuRZN58801ba/7Rzp07jSTz2WefOVK/SpUqZtasWbbUOnjwoGnWrJlZunSp6datm/n73/9uS93x48ebNm3a2FLrRPfcc48599xzHal9or///e/mlFNOMbm5uSWu1bt3bzNkyJCgeVdeeaUZOHBgiWsfOXLEREVFmXfffTdofps2bcy4ceNKXB+ANeRZaMgz8uxE5BlQtnghz5zOMmPIM/KsIPLMPhF5BllWVpbWrFmjHj16BM3v0aOHli9f7lJXxbN//35JUtWqVW2tm5OTo1deeUWHDx9Wp06dbKk5cuRI9e7dWxdeeKEt9f5o48aNqlu3rho3bqz+/ftr06ZNttR9++231aFDB11zzTWqWbOmzjzzTM2cOdOW2n+UlZWl+fPna8iQIfL5fCWud+655+qjjz7STz/9JEn67rvvtGzZMvXq1avEtbOzs5WTk6O4uLig+fHx8Vq2bFmJ6wMIHXn258iz48izgsgzoOzwSp45lWUSeZaHPCuIPLOR2yN0bti2bZuRZL788sug+Q8//LA59dRTbV2XHDxCkZuba/r06WPrCPr3339vEhISTFRUlElMTDTvvfeeLXUXLFhgWrVqZY4ePWqMMbYeoVi8eLF5/fXXzffff59/9KNWrVpm9+7dJa7t9/uN3+83ycnJ5ptvvjEzZswwcXFx5oUXXrCh8/9ZuHChiYqKMtu2bbOlXm5urhk7dqzx+XwmOjra+Hw+M3nyZFtqG2NMp06dTLdu3cy2bdtMdna2eemll4zP57P93w+AopFnJ0eeBSPPCkeeAWWDF/LMiSwzhjw7EXlWOPLMHhE9QLZ8+fKg+ZMmTTLNmze3dV1O7lCMGDHCJCUlmV9++cW2moFAwGzcuNGsWrXKjB071lSvXt38+OOPJaqZnp5uatasab799tv8eXZugE906NAhU6tWLfPEE0+UuFZMTIzp1KlT0LzbbrvNnHPOOSWu/Uc9evQwl156qW31FixYYOrXr28WLFhgvv/+e/Piiy+aqlWrmnnz5tlS/+effzbnnXeekWSioqLMWWedZa6//nrTsmVLW+oDCA15dnLkWTDyrHDkGVA2eCHPnMgyY8izE5FnhSPP7BGRA2SBQMBERUWZRYsWBc2//fbbzXnnnWfrupzaAP/tb38z9evXN5s2bbK99h9dcMEF5q9//WuJarz55pv5/1DzJknG5/OZqKgok52dbVO3/3PhhRcWuIdBcTRs2NAMHTo0aF5aWpqpW7duiWvn2bJliylXrpx56623bKtZv35988wzzwTNe+ihh2z/BePQoUNm+/btxhhjrr32WtOrVy9b6wMoGnkWOvKMPCsKeQa4K9zzrLSyzBjyjDwrGnlWMhF5D7LY2Fi1b98+/6kUeZYuXarOnTu71FVojDH629/+pkWLFunjjz9W48aNHV9fIBAoUY0LLrhAP/zwg7799tv8qUOHDrr++uv17bffKioqyqZujwsEAlq/fr3q1KlT4lpdunQp8Kjmn376SUlJSSWunWfu3LmqWbOmevfubVvNI0eOqFy54H/eUVFRtj1GOE9CQoLq1Kmj33//XR988IH69u1ra30ARSPPrK2PPCPPToY8A9wVrnlW2lmWt07yjDw7GfKshNwcnXPTK6+8YmJiYszs2bPNunXrzKhRo0xCQoLZsmVLiWsfPHjQrF271qxdu9ZIMlOnTjVr1641W7duLXHtW2+91SQmJppPP/3UZGRk5E9Hjhwpce3k5GTz+eefm82bN5vvv//e3HvvvaZcuXLmww8/LHHtE9l5Cu+dd95pPv30U7Np0yazYsUKc+mll5qKFSva8me5cuVKEx0dbR5++GGzceNG8/LLL5vy5cub+fPn29C5MTk5OaZhw4bmnnvusaVenkGDBpl69eqZd99912zevNksWrTIVK9e3YwZM8aW+kuWLDHvv/++2bRpk/nwww9NmzZtTMeOHU1WVpYt9QGEjjwriDwriDwrHHkGlB3hmGdOZpkx5FlhyLPCkWf2iNgBMmOMefbZZ01SUpKJjY017dq1s+1xvJ988omRVGAaNGhQiWsXVleSmTt3bolrDxkyJP/7qFGjhrngggsc2fgaY+8GuF+/fqZOnTomJibG1K1b11x55ZUlvi7/j9555x3TqlUr4/f7TYsWLczzzz9vW+0PPvjASDIbNmywraYxxhw4cMD8/e9/Nw0bNjRxcXGmSZMmZty4cSYQCNhSf+HChaZJkyYmNjbW1K5d24wcOdLs27fPltoArCPPgpFnhSPPCiLPgLIl3PLMySwzhjw7GfKsIPLMHj5jjHHwBDUAAAAAAACgTIvIe5ABAAAAAAAAeRggAwAAAAAAQERjgAwAAAAAAAARjQEyAAAAAAAARDQGyAAAAAAAABDRGCADAAAAAABARGOADAAAAAAAABGNATIAAAAAAABENAbI4Gnz5s1T5cqVS1zH5/PprbfeKnEdAACKgzwDAHgBeYayjAEyFODz+YqcBg8eXGq9DB48WJdffnmprQ8A4B3kGQDAC8gzoHREu90Ayp6MjIz8/164cKEeeOABbdiwIX9efHx80PLHjh1TTExMqfUHAEAoyDMAgBeQZ0Dp4AwyFFC7du38KTExUT6fL//nzMxMVa5cWa+++qrOP/98xcXFaf78+ZowYYLatm0bVCc1NVWNGjUKmjd37ly1bNlScXFxatGihdLS0krU69SpU3XGGWcoISFBDRo00IgRI3To0KECy7311ls69dRTFRcXp4suuki//PJL0OvvvPOO2rdvr7i4ODVp0kQTJ05UdnZ2iXoDALiLPCPPAMALyDPyDKWDATIUyz333KPbb79d69ev18UXXxzSe2bOnKlx48bp4Ycf1vr16zV58mTdf//9euGFF4rdR7ly5fT000/r3//+t1544QV9/PHHGjNmTNAyR44c0cMPP6wXXnhBX375pQ4cOKD+/fvnv/7BBx9o4MCBuv3227Vu3To999xzmjdvnh5++OFi9wUACA/kGQDAC8gzwAYGKMLcuXNNYmJi/s+bN282kkxqamrQcuPHjzdt2rQJmvfkk0+apKSk/J8bNGhg/vGPfwQt89BDD5lOnTqddP2DBg0yffv2DbnfV1991VSrVi2of0lmxYoV+fPWr19vJJmvv/7aGGNM165dzeTJk4PqvPTSS6ZOnTr5P0syb775Zsh9AADKFvLsOPIMAMIbeXYceQYncA8yFEuHDh0sLb9r1y798ssvGjp0qG6++eb8+dnZ2UpMTCx2H5988okmT56sdevW6cCBA8rOzlZmZqYOHz6shIQESVJ0dHRQvy1atFDlypW1fv16dezYUWvWrNGqVauCjkjk5OQoMzNTR44cUfny5YvdHwCgbCPPAABeQJ4BJccAGYolb+OWp1y5cjLGBM07duxY/n/n5uZKOn4a79lnnx20XFRUVLF62Lp1q3r16qXhw4froYceUtWqVbVs2TINHTo0aN3S8Se/nChvXm5uriZOnKgrr7yywDJxcXHF6g0AEB7IMwCAF5BnQMkxQAZb1KhRQzt27JAxJn/D9u233+a/XqtWLdWrV0+bNm3S9ddfb8s6V69erezsbD3xxBMqV+747fReffXVAstlZ2dr9erV6tixoyRpw4YN2rdvn1q0aCFJateunTZs2KCmTZva0hcAIHyRZwAALyDPAOsYIIMtzj//fO3atUuPPfaYrr76ai1ZskTvv/++KlWqlL/MhAkTdPvtt6tSpUrq2bOnAoGAVq9erd9//12jR48+ae39+/cHbcwlqWrVqjrllFOUnZ2tadOmqU+fPvryyy81Y8aMAu+PiYnRbbfdpqeffloxMTH629/+pnPOOSd/g/zAAw/o0ksvVYMGDXTNNdeoXLly+v777/XDDz9o0qRJ9nxBAICwQJ4BALyAPAOKwc0boKHsO9lNINeuXVtg2enTp5sGDRqYhIQEc+ONN5qHH3446CaQxhjz8ssvm7Zt25rY2FhTpUoVc95555lFixaddP2DBg0ykgpMgwYNMsYYM3XqVFOnTh0THx9vLr74YvPiiy8aSeb3338P6v+NN94wTZo0MbGxsaZ79+5my5YtQetZsmSJ6dy5s4mPjzeVKlUyHTt2NM8//3z+6+ImkAAQ1siz48gzAAhv5Nlx5Bmc4DPmhAuTAQAAAAAAgAhSzu0GAAAAAAAAADcxQAYAAAAAAICIxgAZAAAAAAAAIhoDZAAAAAAAAIhoDJABAAAAAAAgojFABgAAAAAAgIjGABkAAAAAAAAiGgNkAAAAAAAAiGgMkAEAAAAAACCiMUAGAAAAAACAiMYAGQAAAAAAACLa/wNMFaT3NuQmVgAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "classes = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')\n",
+ "figsize = (15, 3)\n",
+ "linewidths = 0.01\n",
+ "linecolor = 'white'\n",
+ "ylabel = \"Predicted Label\"\n",
+ "xlabel = \"True Label\"\n",
+ "\n",
+ "cm_tra = confusion_matrix(y_true_tra, y_choice_tra)\n",
+ "cm_val = confusion_matrix(y_true_val, y_choice_val)\n",
+ "cm_tes = confusion_matrix(y_true_tes, y_choice_tes)\n",
+ "\n",
+ "df_cm_tra = pd.DataFrame(cm_tra / np.sum(cm_tra, axis=1)[:, None],\n",
+ " index=[i for i in classes],\n",
+ " columns=[i for i in classes])\n",
+ "df_cm_val = pd.DataFrame(cm_val / np.sum(cm_val, axis=1)[:, None],\n",
+ " index=[i for i in classes],\n",
+ " columns=[i for i in classes])\n",
+ "df_cm_tes = pd.DataFrame(cm_tes / np.sum(cm_tes, axis=1)[:, None],\n",
+ " index=[i for i in classes],\n",
+ " columns=[i for i in classes])\n",
+ "\n",
+ "fig, (axa, axb, axc) = plt.subplots(1, 3, figsize=figsize)\n",
+ "fig.subplots_adjust(wspace=0.5)\n",
+ "\n",
+ "ax1 = sns.heatmap(df_cm_tra, annot=False, linewidths=linewidths,\n",
+ " linecolor=linecolor, square=True, ax=axa)\n",
+ "_ = ax1.set(xlabel=xlabel, ylabel=ylabel, title=\"Training Data\")\n",
+ "\n",
+ "ax2 = sns.heatmap(df_cm_val, annot=False, linewidths=linewidths,\n",
+ " linecolor=linecolor, square=True, ax=axb)\n",
+ "_ = ax2.set(xlabel=xlabel, ylabel=ylabel, title=\"Validation Data\")\n",
+ "\n",
+ "ax3 = sns.heatmap(df_cm_tes, annot=False, linewidths=linewidths,\n",
+ " linecolor=linecolor, square=True, ax=axc)\n",
+ "_ = ax3.set(xlabel=xlabel, ylabel=ylabel, title=\"Test Data\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 7: Confusion matrices for the training, validation, and test data sets (left to right). Each cell in the matrix shows the fraction (see the color bars) of the total objects with that true label that have been predicted to be a given label. The diagonal represents images that were correctly classified. All off-diagonal cells represent false positives (lower left) or false negatives (upper right). Consider some examples. First, the class \"0\" is almost always predicted to be \"0\" with a lighter color in the top-most, left-most cell; all the other cells in the column are completely dark. Second, consider the cell that represents a prediction \"4\", when the true label is \"9\": that cell is not completely dark. A \"4\" has a similar morphology or shape as a \"9.\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "vvAqrZwjVYBt"
+ },
+ "source": [
+ "### 4.3.4. Investigating predictions"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 4.3.4.1. Define of classification metrics"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-01-26T21:19:35.897282Z",
+ "iopub.status.busy": "2025-01-26T21:19:35.896488Z",
+ "iopub.status.idle": "2025-01-26T21:19:36.705672Z",
+ "shell.execute_reply": "2025-01-26T21:19:36.705022Z",
+ "shell.execute_reply.started": "2025-01-26T21:19:35.897242Z"
+ }
+ },
+ "source": [
+ "Consider the example of true class label being \"2\". Then, we define the following metrics.\n",
+ "\n",
+ "* `True Positive (TP)`: correctly classified input digit image --- e.g., a \"2\" classified as \"2\"\n",
+ "* `False Positive (FP)`: another digit classified as \"2\"\n",
+ "* `True Negative (TN)`: another digit classified as another digit); and\n",
+ "* `False Negative (FN)`: a \"2\" classified as something other than \"2\"."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 4.3.4.2. Explore the classification of the training data for an example class value"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Investigate the case in which the true digit label is \"2\"."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 47,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:40.430615Z",
+ "iopub.status.busy": "2025-02-09T23:13:40.430250Z",
+ "iopub.status.idle": "2025-02-09T23:13:40.575406Z",
+ "shell.execute_reply": "2025-02-09T23:13:40.574407Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:40.430564Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "class_value = 2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Find all objects that have that class value. Obtain indices for the tp's, fp's, tn's, and fn's. Create subsets of the data according to those indices."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 48,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:40.576471Z",
+ "iopub.status.busy": "2025-02-09T23:13:40.576232Z",
+ "iopub.status.idle": "2025-02-09T23:13:40.727095Z",
+ "shell.execute_reply": "2025-02-09T23:13:40.725923Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:40.576451Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "TP count: 439\n",
+ "FP count: 58\n",
+ "TN count: 4435\n",
+ "FN count: 68\n"
+ ]
+ }
+ ],
+ "source": [
+ "ind_class_tp_tra = np.where((y_true_tra == class_value)\n",
+ " & (y_choice_tra == class_value))[0]\n",
+ "\n",
+ "ind_class_fp_tra = np.where((y_true_tra != class_value)\n",
+ " & (y_choice_tra == class_value))[0]\n",
+ "\n",
+ "ind_class_tn_tra = np.where((y_true_tra != class_value)\n",
+ " & (y_choice_tra != class_value))[0]\n",
+ "\n",
+ "ind_class_fn_tra = np.where((y_true_tra == class_value)\n",
+ " & (y_choice_tra != class_value))[0]\n",
+ "\n",
+ "x_tra_tp = x_tra[ind_class_tp_tra]\n",
+ "y_true_tra_tp = y_true_tra[ind_class_tp_tra]\n",
+ "y_choice_tra_tp = y_choice_tra[ind_class_tp_tra]\n",
+ "\n",
+ "x_tra_fp = x_tra[ind_class_fp_tra]\n",
+ "y_true_tra_fp = y_true_tra[ind_class_fp_tra]\n",
+ "y_choice_tra_fp = y_choice_tra[ind_class_fp_tra]\n",
+ "\n",
+ "x_tra_tn = x_tra[ind_class_tn_tra]\n",
+ "y_true_tra_tn = y_true_tra[ind_class_tn_tra]\n",
+ "y_choice_tra_tn = y_choice_tra[ind_class_tn_tra]\n",
+ "\n",
+ "x_tra_fn = x_tra[ind_class_fn_tra]\n",
+ "y_true_tra_fn = y_true_tra[ind_class_fn_tra]\n",
+ "y_choice_tra_fn = y_choice_tra[ind_class_fn_tra]\n",
+ "\n",
+ "n_tp = len(ind_class_tp_tra)\n",
+ "n_fp = len(ind_class_fp_tra)\n",
+ "n_tn = len(ind_class_tn_tra)\n",
+ "n_fn = len(ind_class_fn_tra)\n",
+ "\n",
+ "print(f\"TP count: {n_tp:4d}\")\n",
+ "print(f\"FP count: {n_fp:4d}\")\n",
+ "print(f\"TN count: {n_tn:4d}\")\n",
+ "print(f\"FN count: {n_fn:4d}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 49,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:40.728669Z",
+ "iopub.status.busy": "2025-02-09T23:13:40.728301Z",
+ "iopub.status.idle": "2025-02-09T23:13:45.386481Z",
+ "shell.execute_reply": "2025-02-09T23:13:45.385906Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:40.728632Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAuQAAAGOCAYAAADfIxbEAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABVWElEQVR4nO3deXQUVd7G8SeQEBINYU+IbBFBUBYdFDEiRIEIDg7qjIoroCyyiMgoL4hIEARFh8GFuCAmooArKiqoGYGII4wsKpviMqCoRFYJghIC9f4xh7JvhXS6O9WpDvl+zulz7q9ud/VN54HcdG7fihowc7clAAAAAJ6o4vUAAAAAgMqMCTkAAADgoWjngVlDa3sxDgAAAKDSGJi1x27zDjkAAADgISbkAAAAgIeYkAMAAAAeYkIOAAAAeIgJOQAAAOAhJuQAAACAh5iQAzihRUVFBXRbtmyZp+NMT083xhMXF6d27dppxowZOnr0qOvPl5OTo6ioKG3dutU+Nm/ePM2YMeO494+KilJmZqbr4wAAHGcfcgA4kaxYscKoJ02apKVLl2rJkiXG8TPOOKM8h3Vcp556qubOnStJ2rFjh5588kndcccd2r59ux588EFXn+vPf/6zVqxYoQYNGtjH5s2bpw0bNmjkyJHF7r9ixQo1bNjQ1TEAAP6HCTmAE1rHjh2Nul69eqpSpUqx404HDx5UfHx8OIdWTFxcnDGunj17qmXLlnr88cc1efJkxcTEuPZc9erVU7169QK+f2mvFwAgdCxZAVDppaenq3Xr1vrwww+Vlpam+Ph43XzzzZJKXqrRtGlT9evXzziWn5+vwYMHq2HDhqpWrZpSU1M1ceJEFRUVhTSumJgYtW/fXgcPHtTOnTslSRs2bFDv3r1Vq1YtVa9eXWeddZaee+4543FHjx7V5MmTdfrppysuLk41a9ZU27Zt9cgjj9j3cS5ZSU9P1zvvvKPvvvvOWDpzjO/r8PnnnysqKkqzZ88uNubFixcrKipKCxcutI99/fXXuu6661S/fn3FxsaqVatWmjlzZtBjBoATFe+QA4Ck7du364YbbtDo0aM1ZcoUVakS3PsV+fn56tChg6pUqaJ7771XzZo104oVKzR58mRt3bpV2dnZIY3r22+/VXR0tGrVqqXNmzcrLS1N9evX16OPPqo6derohRdeUL9+/fTzzz9r9OjRkqRp06YpMzNT99xzjzp37qzDhw/ryy+/1C+//FLi82RlZWnQoEH69ttv9frrr/sdU7t27XT22WcrOztbt9xyi9GXk5Oj+vXr69JLL5Ukbdq0SWlpaWrcuLH+8Y9/KDk5We+9955GjBihXbt2acKECSGPGQBOFEzIAUDSnj179Morr+jiiy8O6fGZmZnau3evNm7cqMaNG0uSunbtqri4ON1555266667Alqnfuzd9J07d+rRRx/V2rVrddVVVykuLk6ZmZkqLCzU0qVL1ahRI0nSpZdeql9++UUTJ07U4MGDlZiYqH//+99q06aN8c7+JZdc4vd5zzjjDNWsWVOxsbEBLU/p37+/RowYoa+++kotWrSQJO3du1dvvvmmhg8frujo//14GTVqlBISEvTRRx+pRo0akqTu3bvr0KFDeuCBBzRixAjVqlUrpDEDwImCJSsAIKlWrVohT8Yl6e2339ZFF12klJQUFRUV2beePXtKkvLy8ko9x8aNGxUTE6OYmBilpKToH//4h66//nrNmjVLkrRkyRJ17drVnowf069fPx08eND+AGuHDh30+eefa+jQoXrvvfdUUFAQ8tdVkuuvv16xsbHKycmxj82fP1+HDh1S//79JUm///67PvjgA11xxRWKj483XpdLL71Uv//+u1auXFluYwaASMWEHAAkY7eRUPz8889666237An1sduZZ54pSdq1a1ep52jWrJlWrVql1atXa8OGDfrll1/0wgsvKDExUZK0e/fu444zJSXF7peksWPH6uGHH9bKlSvVs2dP1alTR127dtXq1avL9DX6ql27tv7yl79ozpw5OnLkiKT/LVfp0KGD/TXv3r1bRUVFeuyxx4q9LseWtBx7XcpjzAAQqViyAgCS8QFGX7GxsTp06FCx48cmv8fUrVtXbdu21f3333/c8xybNPtTvXp1nXPOOSX216lTR9u3by92/KeffrLHIEnR0dEaNWqURo0apV9++UX/+te/dPfdd+uSSy7Rtm3bXNs9pn///nrllVeUm5urxo0ba9WqVXriiSfs/lq1aqlq1aq68cYbNWzYsOOeIzU1tVzHDACRiAk5APjRtGlTrVu3zji2ZMkS/frrr8axXr16adGiRWrWrJlq1aoVlrF07dpVr7/+un766Sdjgj9nzhzFx8cfd+13zZo19be//U0//vijRo4cqa1bt5a4lj02Nla//fZbwOPJyMjQKaecouzsbDVu3FjVq1fXtddea/fHx8froosu0qeffqq2bduqWrVqAZ03mDEDwImACTkA+HHjjTdq/Pjxuvfee9WlSxdt2rRJjz/+uL2M5Jj77rtPubm5SktL04gRI3T66afr999/19atW7Vo0SI9+eSTZb6wzoQJE+y16vfee69q166tuXPn6p133tG0adPsMV122WVq3bq1zjnnHNWrV0/fffedZsyYoSZNmqh58+Ylnr9NmzZasGCBnnjiCbVv315VqlTx+4591apVddNNN2n69OmqUaOGrrzyymKvyyOPPKJOnTrpwgsv1JAhQ9S0aVPt379f33zzjd566y37Ak2hjhkATgRMyAHAj7vuuksFBQXKycnRww8/rA4dOujll19W7969jfs1aNBAq1ev1qRJk/TQQw/phx9+UEJCglJTU9WjRw9X3jU//fTT9fHHH+vuu+/WsGHD9Ntvv6lVq1bKzs429kS/6KKL9Nprr+mZZ55RQUGBkpOT1b17d40fP97vxYVuv/12bdy4UXfffbf27dsny7JkWZbfMfXv319Tp07Vzp077Q9z+jrjjDO0du1aTZo0Sffcc4927NihmjVrqnnz5vY68rKMGQBOBFEDZu42/redNbS2V2MBAAAAKoWBWXvsNrusAAAAAB5iQg4AAAB4iAk5AAAA4CEm5AAAAICHmJADAAAAHmJCDgAAAHiICTkAAADgISbkAAAAgIeYkAMAAAAeYkIOAAAAeIgJOQAAAOAhJuQAAACAh5iQAwAAAB5iQg4AAAB4iAk5AAAA4CEm5AAAAICHmJADAAAAHmJCDgAAAHiICTkAAADgISbkAAAAgIeYkAMAAAAeYkIOAAAAeKhSTsijoqICui1btszroRazfft23XPPPTr//PNVt25d1ahRQ+3bt9fTTz+tI0eOeD28SocswS1kCW4hS3ALWSo/0V4PwAsrVqww6kmTJmnp0qVasmSJcfyMM84oz2EFZM2aNZozZ45uuukmjR8/XjExMVq8eLGGDBmilStX6tlnn/V6iJUKWYJbyBLcQpbgFrJUfqIGzNxt+R6YNbS2V2PxTL9+/fTqq6/q119/9Xu/gwcPKj4+vpxGdXx79+7VySefrJiYGOP48OHDNXPmTH3//fdq1KiRR6MDWYJbyBLcQpbgFrLkroFZe+x2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yyrx0smxsbGKjY0NxzA81blzZ7tdr149o8+5hry09eiVGVkKn3/9619G/eCDDxr1+PHj7XaVKubv7l26dDFqr9eQByKSsuR7qfnZs2eH7XnCpVWrVkbtXB87YMAAoz569GjYx1SeIilLFZHvJe8nTJgQ8nnKsv48UpCl8uO73CcSufoOeXJysqTie1Du2LGj2G+BgD9kCW4hS3ALWYJbyBKcXJ2Qp6amKjk5Wbm5ufaxwsJC5eXlKS0tzc2nwgmOLMEtZAluIUtwC1mCU9BLVn799Vd98803dr1lyxZ99tlnql27tho3bqyRI0dqypQpat68uZo3b64pU6YoPj5e1113nasDR8VHluAWsgS3kCW4hSwhGEFPyFevXq2LLrrIrkeNGiVJ6tu3r3JycjR69Gj99ttvGjp0qPbu3avzzjtP77//fsTvqek2373HnWvGnfWXX35ZLmOKNGQpssyaNcuofdeQRzqyVL5ee+01o967d69R//vf/y7P4biKLIVfWdaNL1u2zL2BhBlZcl+DBg2M+rTTTgv4sX369HF7OK6KGjBztzE7nDW0tldjkfS/fTUTExM9HYMbFi9ebLd9tzWSik/InRfVqCj27dunGjVqeD2MEp0oWSovp5xyilF///33Jd73xRdfNOrrr7++TM9NliqWL774wqidH1x3/sn9q6++CvuYjiFLkW/p0qV22/cDnoHwnZD7TnbDgSxFHueEPCcnx25369bN72Pbtm1r1OV5VdSSsjQwa4/ddnUNOQAAAIDgMCEHAAAAPFQx10pEoDvuuMOofZepOPcUvemmm8plTIgcvmsC//znPxt9F198sVE7//zvz/bt2416+vTpRu37gaLSdOrUKeD7+lvOghNT69at7XZqaqrRN2LECKMuzyUqCJ3vcpFwrs12LtMMhnNc4V6mgsj23HPPGXXXrl09Gon7eIccAAAA8BATcgAAAMBDLFlxyemnn27Uvn+ic25r+Prrr5fLmBA+devWNeoLLrjAqJ37yF511VWuPO/xLrPs68orrzTqe++91247L29/0kknGfWkSZNKfK7CwkKj7/HHHw9wxKioWrRoYdS+SwfWr19v9DmzhcjgvLR8ly5djDqYHU4mTpxo1P6WuLi5raHzeXFic+6iUpYlKs7sOHeHijS8Qw4AAAB4iAk5AAAA4CEm5AAAAICHWEMeos6dOxv1oEGDjNp3be+8efOMvoMHD4ZvYAgb36uAOS8dfvLJJ/t9bFm2/QrmvM4tE33Xha9cudLoc141rFmzZiWe+/Dhw0bfjz/+GPxg4brGjRsbdVm2o3SuGR8/frxR16pVq8TnhXd814H7XgHTbc514WVZJ+5PadsaOtfFB9oH74wZM8aot27datQLFiyw275X3pTKtq2h8+fW0aNHQz5XeeAdcgAAAMBDTMgBAAAADzEhBwAAADzEGvIQjR071qida3l96/vvv79cxgR3Ofca/+c//2m3S1sz7uT7uYG5c+cafZ9//rlRL1++3KgvvPDCEs+bkZFh1H/5y1+M2vdrWLx4cWCDPQ72mQ6fU045xah79uxp1Oeff75Rn3vuuXa7Tp06Rt/u3btDHkdKSopR+64Zl6SNGzfa7aKiopCfB2Xj3Ds8nOvGw8V3r/HS1ow7vz7fr7+0x8I9f/rTn4x6wIABRn3ZZZeV+FjnZ5uc17X4xz/+YbeTk5ODGtd3331nt3v16mX0leUzNV7gHXIAAADAQ0zIAQAAAA8xIQcAAAA8xBryALVv396oneupoqKijHrKlClhHxPC68EHHzTqM844o8T7fvbZZ0b9f//3f0a9bt06u71jx46gxrFhw4YS+5zrwp25bNiwod0Odm3eL7/8YrfvvvvuoB4L/3zXXz766KNGn/PzKO+++65Rz58/326/9NJLRl9+fr7f523VqpXd/te//mX0Va1a1aidOW3ZsqXddq5VHzlypFHPmTPHqJ37ASN0ZVkz7lxz7buWO1zXSiiNc018abXvmH3bcNdf//pXo3b+m65evXrI546JiTHqk046KeRzTZs2zW5v2rQp5PNEAt4hBwAAADzEhBwAAADwEEtWAjR9+nSjdm43tnPnTqOeNWtW2MeE8IqLiwv4vs4lKs7lAOHiXDrw8ccfG/XVV18d8LkKCgqMevDgwXb70KFDIYwOJfHdRtK5JMm5ndgnn3wS8vOceuqpRu27tKRGjRpG33XXXWfUzuUwvtsxjh8/3uhzbovZrl07o37ooYfs9rZt20oZNXyV5XLwzqWUznNNmDAh5HOXhe8yFOeSFCfnshS2Ogyf66+/3m47l9KVZYlKOI0bN85uO7cBHj16tGvPs337dqM+cOCAa+c+hnfIAQAAAA8xIQcAAAA8xIQcAAAA8BBryP3o3LnzcduSdPToUaN2Xg7d3yVbnZeRbdKkiVH7bj81aNAgo8936zGp+GXVfR87b948o+/GG28scUwom/K6RO9pp51m1FlZWUbdtWvXkM/9n//8x6hfffXVkM8F/7766iu7/fPPPxt9ZVkz7txu9eabbzZq30tW9+jRw+jLzc31e27fLTadn5Fwbos5bNgwo/Zdf968eXO/zwNTWdZ5e7WVoZsmTpzo9RAqjRdeeMFuO+c44fTGG2/Y7csvvzyox6akpNjt3r17G33OuiyuuOIKo164cKFr5z6Gd8gBAAAADwU1IZ86darOPfdcJSQkqH79+rr88su1efNm4z6WZSkzM1MpKSmKi4tTenq6Nm7c6OqgUfGRJbiFLMEtZAluIUsIVlAT8ry8PA0bNkwrV65Ubm6uioqKlJGRYWz/Mm3aNE2fPl2PP/64Vq1apeTkZHXv3l379+93ffCouMgS3EKW4BayBLeQJQQrasDM3cYis1lDawf84J07d6p+/frKy8tT586dZVmWUlJSNHLkSHtf5kOHDikpKUkPPvigsa9xSQoKCpSYmBjklxEevmsmnftbOtfmOddr79q1y24713nXrVvXqBs3blziuZ37yDqf11+/c6/gqVOnyk379u0rtpdxqCIxS849e52vp6/PP//cqK+99lqj/u9//2u3a9asafRVq1bNqFNTU436b3/7m90eMWKE0RfMGlHn5cvffvtto77jjjuMujz3iz7Rs+R0yimn2O233nrL6Nu7d69RO9drN2jQwG4795l3vobOz7bceeeddnvfvn1BjDg4HTt2NGrfNaLOHDr3O37iiSeM+tdffw3quU+0LHm1Dty5/7dzLbdv/9KlS42+0vYW98e5z7hzHOXpRMtSaXzXjbuZuy1bthh1v379jPqLL76w261atTL6/v73vxt1p06djPqkk06y27GxsSGP0Xkdjvfee8+onZ+LcV4DpDQlZWlg1h67XaY15Mf+Q69d+3+T+C1btig/P9+YvMbGxqpLly7FLlhyzKFDh1RQUGDcUPmQJbiFLMEtZAluIUsoTcgTcsuyNGrUKHXq1EmtW7eWJOXn50uSkpKSjPsmJSXZfU5Tp05VYmKifWvUqFGoQ0IFRZbgFrIEt5AluIUsIRAhT8iHDx+udevWaf78+cX6jreMwnnsmLFjx2rfvn32jcsqVz5kCW4hS3ALWYJbyBIC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e/dq48aNaty4sSSpa9euiouL05133qm77rrLXndVtWpVVa1aVVFRUUE/z/vvv6/nn39et99+u+rUqRPSWBFeZAluIUtwC1mCW8hS2bFkxY9atWqFHC5Jevvtt3XRRRcpJSVFRUVF9q1nz56SpLy8PPu+s2fPVlFRkZo0aRLUc6xdu1ZXX321OnbsqKlTp4Y8VoQXWYJbyBLcQpbgFrJUdrxD7keDBg3K9Piff/5Zb7311nHXMEnSrl27ynT+Tz/9VN27d1fz5s21aNEixcbGlul8CB+yBLeQJbiFLMEtZKnsmJD7UdKfQ2JjY3Xo0KFix3fv3m3UdevWVdu2bXX//fcf9zwpKSkhj+3TTz9Vt27d1KRJE73//vtKTEwM+VwIP7IEt5AluIUswS1kqeyYkIegadOmWrdunXFsyZIlxbYB6tWrlxYtWqRmzZqpVq1arj3/Z599pm7duqlhw4bKzc119dwoX2QJbiFLcAtZglvIUuBYQx6CG2+8UYsXL9a9996rDz74QI899piGDBlS7Leu++67TzExMUpLS9MTTzyhJUuWaNGiRcrKylKvXr2MLXduueUWRUdH67vvvvP73Js3b1a3bt0kSffff7++/vprrVy50r7t3LnT/S8YYUOW4BayBLeQJbiFLAWOd8hDcNddd6mgoEA5OTl6+OGH1aFDB7388svq3bu3cb8GDRpo9erVmjRpkh566CH98MMPSkhIUGpqqnr06GH8pnbkyBEdOXJElmU5n86wYsUK+089l112WbH+7OzsYnt7InKRJbiFLMEtZAluIUuB40qdAAAAQDnjSp0AAABAhGBCDgAAAHiICTkAAADgISbkAAAAgIcq5YQ8JydHUVFR9i06OloNGzZU//799eOPP5bLGJo2bRryp3vXrFmjYcOGqU2bNkpISFBSUpK6deumJUuWuDtIlIoswS1kCW4hS3ALWSo/lXJCfkx2drZWrFih3NxcDRw4UPPnz9eFF16oAwcOeD00v+bPn69PPvlEN998s958800988wzio2NVdeuXTVnzhyvh1cpkSW4hSzBLWQJbiFL5WDAzN2W760yyM7OtiRZq1atMo6PHz/ekmS98MILJT72wIEDroyhSZMmVt++fUN67M8//1zsWFFRkdW2bVurWbNmZRwZgkGW4BayBLeQJbiFLIWX7/y7Ur9D7tSxY0dJsq/+1K9fP5188slav369MjIylJCQoK5du0qSCgsLNXnyZLVs2VKxsbGqV6+e+vfvX+zKT4cPH9bo0aOVnJys+Ph4derUSZ988kmZxlm/fv1ix6pWrar27dtr27ZtZTo33EGW4BayBLeQJbiFLLmPK3X6+OabbyRJ9erVs48VFhbqL3/5iwYPHqwxY8aoqKhIR48eVe/evbV8+XKNHj1aaWlp+u677zRhwgSlp6dr9erViouLkyQNHDhQc+bM0Z133qnu3btrw4YNuvLKK7V///5iz9+0aVNJ0tatW4Mee1FRkZYvX64zzzwz+C8criNLcAtZglvIEtxClsKgMi9ZWblypXX48GFr//791ttvv23Vq1fPSkhIsPLz8y3Lsqy+fftakqxnn33WePz8+fMtSdZrr71mHF+1apUlycrKyrIsy7K++OILS5J1xx13GPebO3euJanYn2CaNWsW8p9Qxo0bZ0my3njjjZAej9CQJbiFLMEtZAluIUvh5Tv/rtQTcuetTZs21kcffWTf71jA9u3bZzz++uuvt2rWrGkVFhZahw8fNm7JycnW1VdfbVmWZWVlZVmSrNWrVxuPP3z4sBUdHR3ymiinWbNmWZKsv//9766cD4EjS3ALWYJbyBLcQpbCy3f+XamXrMyZM0etWrVSdHS0kpKS1KBBg2L3iY+PV40aNYxjP//8s3755RdVq1btuOfdtWuXJGn37t2SpOTkZKM/OjpaderUceNLUHZ2tgYPHqxBgwbpoYcecuWcCB5ZglvIEtxCluAWshR+lXpC3qpVK51zzjl+7xMVFVXsWN26dVWnTh29++67x31MQkKCJNkhys/P1ymnnGL3FxUV2eEri+zsbA0YMEB9+/bVk08+edyxonyQJbiFLMEtZAluIUvhV6kn5KHq1auXXnzxRR05ckTnnXdeifdLT0+XJM2dO1ft27e3j7/88ssqKioq0xhycnI0YMAA3XDDDXrmmWciMlwoHVmCW8gS3EKW4BayFDgm5CHo06eP5s6dq0svvVS33367OnTooJiYGP3www9aunSpevfurSuuuEKtWrXSDTfcoBkzZigmJkbdunXThg0b9PDDDxf7s44knXbaaZL++PRySV555RXdcsstOuusszR48OBi2wKdffbZio2Nde8LRtiQJbiFLMEtZAluIUuBY0IegqpVq2rhwoV65JFH9Pzzz2vq1Kn25WS7dOmiNm3a2PedPXu2kpKSlJOTo0cffVRnnXWWXnvtNfXp06fYeQP9LfCdd97R0aNHtXbtWl1wwQXF+rds2WJvCYTIRpbgFrIEt5AluIUsBS5qwMzdlu+BWUNrezUWAAAAoFIYmLXHbnOlTgAAAMBDTMgBAAAADzEhBwAAADzEhBwAAADwEBNyAAAAwENhm5BnZWUpNTVV1atXV/v27bV8+fJwPRVOcGQJbiFLcAtZglvIEqQw7UP+0ksvaeTIkcrKytIFF1ygp556Sj179tSmTZvUuHFjv489evSofvrpJyUkJETs1ZQqO8uytH//fqWkpKhKlfD+kYUsndjIEtxCluAWsgS3BJWlATN3W743N3To0MG69dZbjWMtW7a0xowZU+pjt23bZkniVgFu27ZtcyUv/pClynEjS9zIErdIu5ElbuHOku/82/Vf/QoLC7VmzRplZGQYxzMyMvTxxx8Xu/+hQ4dUUFBg3yzLcntICJOEhISwnp8sVR5kCW4hS3ALWYJbAsmS6xPyXbt26ciRI0pKSjKOJyUlKT8/v9j9p06dqsTERPtW2p9oEDnC/ScyslR5kCW4hSzBLWQJbgkkS2FbHOV8csuyjjugsWPHat++ffZt27Zt4RoSKiiyBLeQJbiFLMEtZAlSGD7UWbduXVWtWrXYb3c7duwo9lugJMXGxio2NtbtYeAEQJbgFrIEt5AluIUswZfr75BXq1ZN7du3V25urnE8NzdXaWlpbj8dTmBkCW4hS3ALWYJbyBJ8hWXbw1GjRunGG2/UOeeco/PPP19PP/20vv/+e916663heDqcwMgS3EKW4BayBLeQJRwTlgn5Nddco927d+u+++7T9u3b1bp1ay1atEhNmjQJx9PhBEaW4BayBLeQJbiFLOGYqAEzdxv75swaWtursUiSCgoKlJiY6OkYEJh9+/apRo0aXg+jRGSp4iBLcAtZglvIEtxSUpYGZu2x2+G9BBUAAAAAv8KyZAUAEH6nnXaaUXfv3t2ov/nmG6Peu3dviffNyckx6u3bt7swQpyoYmJi7PbZZ59t9I0fP96o//znPxu175Z+BQUFRt8ll1xi1CtXrizTOIGKgnfIAQAAAA8xIQcAAAA8xIQcAAAA8BBryP1ISUmx23feeafRN3LkSKNeuHChUT/wwAN2mzVwAEJ15plnGrXv/z3XXHON0XfSSScZtWUZm2j5deGFFxr1iBEjjNq5Hh0ntuhoc3rQtGlTox4yZIjddv48dHLm0Lc++eSTjb633nrLqNPT041648aNfp8LqKh4hxwAAADwEBNyAAAAwENMyAEAAAAPsYbch3Otmu9atvj4eKPPuSbusssuM2rfvVQPHz5s9E2YMMGon376aaM+cOBAYANGpVO3bl2j7tGjh1FffPHFRt2rVy+77Vyr+dtvvxm17+ceJOmhhx4KeZwI3Omnn27U48aNM+rLL7/cqJ3/F7klIyPDqO+++26jvvnmm8PyvIgMVaqY78/dc889Ru3cW9yf9evXG/Xy5cuN+ujRo3Z7+PDhRl/t2ubVwocNG2bUQ4cODXgcCJ8WLVoYdVxcnN0uKioy+lj3HxjeIQcAAAA8xIQcAAAA8BBLVnw4/1Rclj8NV6tWzW7HxsYafQ8//LBRp6amGrVzuzFULvXr1zfqli1b2u0ZM2YYfWeddZbfc+3YscNuOy9R7XyeqVOnGvXVV19ttwcMGGD0ff75536fF4HbtGmTUQezVWE4nXvuuV4PAeWoatWqRn3TTTcZtXMZyuOPP263v/32W6Pvk08+MWrnMkzf52rUqJHR17t3b6Pu2LGjUScmJtrtffv2CeGRkJBg1H369DFq55JG3yWRzmW6eXl5AT/vqlWrjDqYpVIVHe+QAwAAAB5iQg4AAAB4iAk5AAAA4KFKvYb89ttvN+q0tDSj3rt3r90eOHCg0edc9+l0xx132O1Bgwb5va/z0ti+a7f279/v97Go+Dp06GDUzzzzjFG3adPGbjvXF//3v/816smTJxv1m2++WeLzOvPuuyZUktq3b2+3nVveOf/tIDI5v/8//fRTifd1rhFF5eJc99upUyej/v333416z549IT/XkSNH7PaUKVOMPuca8nbt2hm17/2dWyKibDp37my3n3rqKaOvefPmAZ/H9zN0ktStW7eAH+u8b0xMjFGPGTMm4HNVNLxDDgAAAHiICTkAAADgISbkAAAAgIcq9Rpy51ql6tWrG/WQIUPs9uuvvx7UuX3X8nbt2tXoO/XUU406PT3dqH3Xbt16661Gn3MvaVQ8zrWZr776qlE79wdfsWKF3Z41a5bR99577xm1vzXCTu+8847fcf3f//2f3XbulQ/3REVF+e33XW8rSUuXLrXbb7zxhtHnvET5hg0bSjzvSSedZNQ9evTwOw5ULsH8X1IWzs/BfP3110btXLvsuy+5757kEvuSl1WvXr3sdjBrxsPp73//u1HXq1fPqCdNmmS3t27dWh5DChveIQcAAAA8xIQcAAAA8BATcgAAAMBDlXoN+T/+8Q+j/uWXX4z67bffDvncP/zwg93u3r270bd+/Xqjjo+PN+prrrnGbr/yyitGX7Br2REZGjRoYLfvuusuo8+5Zvw///mPUffs2dNuh3ONpO+++05nn3122J63spswYYJRf/PNN0b93XffGfXHH3/syvM696x3fk7giy++cOV5AH+c+5mvXbvWqJ1rmc866yy7XbduXaOPNeRl4/uzqbCw0Ohz7kvuu3Zbkpo0aWK3nf93jB8/3qid17Fw7lvuq2rVqkbdr18/o77ooovs9gUXXGD0bd++vcTzRiLeIQcAAAA8FPSE/MMPP9Rll12mlJQURUVFFfuUv2VZyszMVEpKiuLi4pSenq6NGze6NV6cQMgS3EKW4BayBLeQJQQj6CUrBw4cULt27dS/f3/99a9/LdY/bdo0TZ8+XTk5OWrRooUmT56s7t27a/PmzcYl4SPBsmXL/NZucW7FM2PGDKMePXq0UUdH//Ft8d16UTqxlqycSFlyatGihVHn5uba7ZNPPtnou+2224x67ty5Rh2uP8M6xzFo0CCjtizLbjt/kESaipwl559+w+mKK66w24MHD/Z7399++y3cw4lIFTlLFZFzSYJz+2GnQ4cO2W3nlqCRpqJl6ejRo3bbOR8aMWKE38fu3LmzxD7n5e6dW1v6zoni4uJKHJNk/lySpMaNG9vtm266yeh78MEHSx5wBAp6Qt6zZ09jTasvy7I0Y8YMjRs3TldeeaUk6bnnnlNSUpLmzZtX6g8AVC5kCW4hS3ALWYJbyBKC4eoa8i1btig/P18ZGRn2sdjYWHXp0qXEDyIdOnRIBQUFxg0gS3ALWYJbyBLcQpbg5OqEPD8/X5KUlJRkHE9KSrL7nKZOnarExET71qhRIzeHhAqKLMEtZAluIUtwC1mCU1i2PXReCtqyrBIvDz127FiNGjXKrgsKCk74kDm3ADr256pjWrZsabfPPPNMo++MM84w6k2bNrk8ushSUbN06qmnGvW6devs9v3332/0rVy5slzG5NSnTx+jdo7Zdw2xc517RVRRs+SmJ554wm7722pMkqZMmRLu4VRYZMk97dq1M+revXv7vb/vdsQV/VLpUmRlqUePHnZ7w4YNrp3Xafbs2SX2PfbYY0YdGxsb8HlbtWoV8pgigasT8uTkZEn/+83Pd9/lHTt2FPst8JjY2NigXnBUDmQJbiFLcAtZglvIEpxcXbKSmpqq5ORkY0eJwsJC5eXlKS0tzc2nwgmOLMEtZAluIUtwC1mCU9DvkP/666/GleS2bNmizz77TLVr11bjxo01cuRITZkyRc2bN1fz5s01ZcoUxcfH67rrrnN14Kj4yBLcQpbgFrIEt5AlBCPoCfnq1auNS5UeW8/Ut29f5eTkaPTo0frtt980dOhQ7d27V+edd57ef/999mf1w7lXZnZ2tt0+9metY5x/yqrIa8hP5Cy9++67fuvyUqXKH38E69y5s9H30EMPGbXv/r5S8UurR7ITOUvBqF27tlHPnz/fqGvVqlXiY533jfS958OFLIWf717Tr776qt/7Oq/DMGfOnLCMKRwqWpZ8360vT75rylesWGH0rV+/PuDzOD9jd9JJJxn1gQMHQhhd+Ql6Qp6enl5sY3ZfUVFRyszMVGZmZlnGhUqALMEtZAluIUtwC1lCMFxdQw4AAAAgOEzIAQAAAA+FZR9yAJHB99P6r7/+utGXmJho1G+++aZRT506NXwDgyuca8aHDBli1N26dSvxsQcPHjTq0tbyAm7p27ev3W7SpInf+65du9aoffchx4nH+bm41atXG3X79u1LfKxzH/L4+HijjvQ15LxDDgAAAHiICTkAAADgIZasRADnZXJLumyuZG5jh8rB9ypu5513ntG3aNEio3ZeRnnx4sV227kF1COPPGLUd9xxR5nGifJRv359u33//fcbfTfffLNR+9vhYdy4cUbtXLIEuMW5xarvkpXS+LvMOiJHz5497fbFF19s9Pn7f6g0wcyPnD8Pf//9d6OO9G0Qmd0BAAAAHmJCDgAAAHiICTkAAADgIdaQRwDn+ip/663uvfdeo/7ggw/CMiaEz2mnnWbUs2bNMmrnOvGqVava7ZiYGKPPuUbOub6usLDQbk+aNMnomzhxYoAjhpfq1q1r1L7bvv3pT38K6ly+W18+9dRTZRsYIk5ycrJRjx071qida2YbNmxot7t37x7Uc/luk/nf//7X6HN+lqFly5ZGHcxnoXbv3h3UuBAeCQkJRj1hwgSjHjx4sN12bjfo5hpyf+f661//atRnnHGGUe/Zs8eoL7/8cru9d+/eEEfoHt4hBwAAADzEhBwAAADwEBNyAAAAwEOsIa9gqlWr5vUQEIDGjRsb9YgRI+y271o7qfjeqDt27DDqnTt32u0zzzzT6KtevbrfcURH//FPvEaNGkbf0aNH/T4WkcG5P3gw68Y///xzox44cKDdPnToUNkGFiannHKKUf/4448ejaRi8F0H6/yciHMNrZuGDh3qynnmzZtn1M7150eOHHHleRAc55rx7Oxso/bNXaRq1aqVUTvXoy9btsxub9++3eh77rnnjHrNmjVG/dVXX7kwQhPvkAMAAAAeYkIOAAAAeIgJOQAAAOAh1pCH6JxzzjFq53q6jh072u3S9tFMTEx0eXQIN+e67549exr1M888Y9S+67ed63qd+4GvX7/eqG+//Xa77VxDvn//fqN+/PHHjfq2226z23379jX6pk+fbtTbtm0TvHfJJZcYtfP/Gn+c681vvPFGo3buQx0u1157rVH37t3bbjsz7FSzZk2j/uijj0o8L6RLL73UbjvXjDs/j+L83MDatWvtdps2bYy+U0891a0h+uX8v/Tw4cPl8rzwz/n9L8uacece3765k6SuXbuGfO6y8P2/yPn/Urdu3Yx68eLFRn3ZZZe5Ph7eIQcAAAA8xIQcAAAA8BBLVgLk/POFc6umOnXqlPjYYC79iorh+eefN2rnn/Ocl3u+6qqr7PaiRYuMPuefmV966SWj9t3m7uuvvzb6nMsbCgsLjbpPnz52OzU11ej729/+ZtT//Oc/Be85t6f03bqyNM4tAh944IES7+tcotC6dWujdv6fVpZtMn0vlR7sea6++mq7zZKV4Fx33XVGvXTp0hLv69xS97fffgvLmJy6d+9u1GlpaUb98ccfl8s4YNq0aZNRf/jhh0bduXPngM+1fPlyo27SpEnoA/NIvXr1wv4cvEMOAAAAeIgJOQAAAOAhJuQAAACAh1hDHiDntobO9ZXOy/tOmTLFbn/zzTdG36xZs4zauXbPn5YtWxr1BRdcYNT//ve/Az4X/GvXrp1RT5gwwW7/+c9/Nvrefvtto77vvvuM+rPPPrPbQ4YMMfpGjx5t1M5Lh/uuA3766aeNvq1btx5n5H/w/azDuHHjjD7WkFcMwXzmxPn/VFk+r+Jc6+3WuYI9z7fffhvy81Z2jRs39ts/fPhwux3sNm779u2z2y+//LLRt2DBAqO+4oorjHrQoEF2Oz4+3ujr0aOHUX/55ZdGvWfPnqDGidA4t590fvbJOffw/ayL72dGJHPb02A5z+X8HJXzZ6Iv55axzp/bzuz58mJrRt4hBwAAADzEhBwAAADwUFAT8qlTp+rcc89VQkKC6tevr8svv1ybN2827mNZljIzM5WSkqK4uDilp6dr48aNrg4aFR9ZglvIEtxCluAWsoRgBbWGPC8vT8OGDdO5556roqIijRs3ThkZGdq0aZN9+dtp06Zp+vTpysnJUYsWLTR58mR1795dmzdvVkJCQli+iHA57bTT7Pa5555r9BUVFRn1tGnTjDorK8tuO/d+DWbN+AcffGDUv//+u1FXr1494HNFkkjMUu3atY167NixRt2zZ0+7PX/+fKPvrrvuMuqzzjrLqH0/N+C8hP2qVauM+qGHHjLqRx991M+o/fvqq69K7Dv99NON2rnP6s6dO0N+3vIUiVkqi4ULFxq1c29x52cMKoJff/3Vbh88eNDvfd977z2jdu7LH04nWpZmzJhh1M7PGLRt29Zul/ZzafXq1UY9adIku+38DI3TunXrjLpTp05223kdBudnXXz3oZekTz75xG47vx7fnHntRMvSww8/bNTOtd233Xab3U5JSTH6yvL5E+e1Ne644w6jfueddwI+l+81PSSpS5cudvvGG280+iZPnmzUBw4cCPh5QhXUhPzdd9816uzsbNWvX19r1qxR586dZVmWZsyYoXHjxunKK6+UJD333HNKSkrSvHnzNHjw4GLnPHTokA4dOmTXBQUFoXwdqGDIEtxCluAWsgS3kCUEq0xryI99yvrYO4tbtmxRfn6+MjIy7PvExsaqS5cuJV5ta+rUqUpMTLRvjRo1KsuQUEGRJbiFLMEtZAluIUsoTcgTcsuyNGrUKHXq1Mm+5HJ+fr4kKSkpybhvUlKS3ec0duxY7du3z75t27Yt1CGhgiJLcAtZglvIEtxClhCIkPchHz58uNatW6ePPvqoWF9UVJRRW5ZV7NgxsbGxio2NDXUYYeW71vGXX34x+mrWrGnUzv1e//Wvf9lt5xo55/6+Tr5rzq+77jqjb9euXX4fWxFFSpac+8P36tXLqH33Fneua122bJlRt2rVyqh91/5///33Rp9z3929e/cGNuAA+I7Ld9/gE1WkZKksfP8kLZn730v/e5fsGOe6/9J89913dtu5h71z3ef27duNOph1oC+++KJRL1myxG5XlH3FT4Qs1ahRw6id+zL7cv5ccn52JTMz06j3798f8DicE8yJEyfa7dI+I9C8efMS659++snoGzNmTMBjKk8nQpacnJ+b892L3nkNj1tvvTXk5/G9Dof0v7X5oXLuLe5bR8J1OEJ6h/y2227TwoULtXTpUjVs2NA+npycLKn4P74dO3YU+y0QkMgS3EOW4BayBLeQJQQqqAm5ZVkaPny4FixYoCVLlig1NdXoT01NVXJysnJzc+1jhYWFysvLU1pamjsjxgmBLMEtZAluIUtwC1lCsIJasjJs2DDNmzdPb775phISEuzf7BITExUXF6eoqCiNHDlSU6ZMUfPmzdW8eXNNmTJF8fHxxZZeVAQNGjSw2y1atDD6fC8TK0k33HBDwOd1buOzYsUKo77qqqvstpvLFyJJJGbJuSzpkUceMWrfSzY7t0RcuXKl39p3OYyzL5x8lxk4L2ft/HoryjaHTpGYJTfl5OQYte9yOOeShNL4fo+d32/ntp+V8RLlFTFLvss/nFsXOrdyy87ONur333/fbvtODKXw/ux57bXX7Papp55q9DmXNziXg/bp08duP//882EYnTsqYpbKwncJnHM53Jtvvlm+g6mggpqQP/HEE5Kk9PR043h2drb69esnSRo9erR+++03DR06VHv37tV5552n999/P+L21IS3yBLcQpbgFrIEt5AlBCuoCXkgH+qJiopSZmZmsQ+AAL7IEtxCluAWsgS3kCUEq0z7kAMAAAAom6gBM3cbv8bNGlq7pPuWi4KCAiUmJno6huNxrmubOXNmwI+95557jNp5CWLn2r2KYt++fUGvYS1PkZolFEeW4BayBLeQJbilpCwNzPrjszq8Qw4AAAB4iAk5AAAA4CEm5AAAAICHgtplpTJ78skn/dYAAABAKHiHHAAAAPAQE3IAAADAQ0zIAQAAAA8xIQcAAAA8xIQcAAAA8BATcgAAAMBDTMgBAAAADzEhBwAAADzEhBwAAADwEBNyAAAAwENMyAEAAAAPMSEHAAAAPMSEHAAAAPBQxE3ILcvyeggIUKR/ryJ9fPhDpH+vIn18+EOkf68ifXz4Q6R/ryJ9fPhDIN+riJuQ79+/3+shIECR/r2K9PHhD5H+vYr08eEPkf69ivTx4Q+R/r2K9PHhD4F8r6LLYRxBSUlJ0bZt22RZlho3bqxt27apRo0aXg8rohUUFKhRo0bl9lpZlqX9+/crJSUl7M9VFmQpeGTp+MhS8MjS8ZGl4JGl4yNLwYvkLEXchLxKlSpq2LChCgoKJEk1atQgYAEqz9cqMTGxXJ6nLMhS6MiSiSyFjiyZyFLoyJKJLIUuErMUcUtWAAAAgMqECTkAAADgoYidkMfGxmrChAmKjY31eigRj9fKP16fwPFa+cfrEzheK/94fQLHa+Ufr0/gIvm1ihowc7exF8usobW9GgsAAABQKQzM2mO3I/YdcgAAAKAyYEIOAAAAeIgJOQAAAOAhJuQAAACAh5iQAwAAAB6K2Al5VlaWUlNTVb16dbVv317Lly/3ekiemjp1qs4991wlJCSofv36uvzyy7V582bjPpZlKTMzUykpKYqLi1N6ero2btzo0YgjB1kykaXQkSUTWQodWTKRpdCRJVNFzVJETshfeukljRw5UuPGjdOnn36qCy+8UD179tT333/v9dA8k5eXp2HDhmnlypXKzc1VUVGRMjIydODAAfs+06ZN0/Tp0/X4449r1apVSk5OVvfu3bV//34PR+4tslQcWQoNWSqOLIWGLBVHlkJDloqrsFkaMHO35XuLBB06dLBuvfVW41jLli2tMWPGeDSiyLNjxw5LkpWXl2dZlmUdPXrUSk5Oth544AH7Pr///ruVmJhoPfnkk14N03NkqXRkKTBkqXRkKTBkqXRkKTBkqXSRnCXf+XfEvUNeWFioNWvWKCMjwziekZGhjz/+2KNRRZ59+/ZJkmrX/t+FnLZs2aL8/HzjdYuNjVWXLl0q7etGlgJDlkpHlgJDlkpHlgJDlkpHlgJTUbIUcRPyXbt26ciRI0pKSjKOJyUlKT8/36NRRRbLsjRq1Ch16tRJrVu3liT7teF1+wNZKh1ZCgxZKh1ZCgxZKh1ZCgxZKl1FylK0Z89ciqioKKO2LKvYscpq+PDhWrdunT766KNifbxuxfGalIwsBYfXpGRkKTi8JiUjS8HhNSlZRcpSxL1DXrduXVWtWrXYbyk7duwo9ttMZXTbbbdp4cKFWrp0qRo2bGgfT05OliReNx9kyT+yFDiy5B9ZChxZ8o8sBY4s+VfRshRxE/Jq1aqpffv2ys3NNY7n5uYqLS3No1F5z7IsDR8+XAsWLNCSJUuUmppq9Kempio5Odl43QoLC5WXl1dpXzeydHxkKXhk6fjIUvDI0vGRpeCRpeOrsFmKxF1WXnzxRSsmJsaaPXu2tWnTJmvkyJHWSSedZG3dutXroXlmyJAhVmJiorVs2TJr+/bt9u3gwYP2fR544AErMTHRWrBggbV+/Xrr2muvtRo0aGAVFBR4OHJvkaXiyFJoyFJxZCk0ZKk4shQaslRcRcqS7/w7IifklmVZM2fOtJo0aWJVq1bN+tOf/mRvV1NZSTruLTs7277P0aNHrQkTJljJyclWbGys1blzZ2v9+vXeDTpCkCUTWQodWTKRpdCRJRNZCh1ZMlWkLPnOv6MGzNxt+b5jPmto7fC9HQ8AAABAA7P22O2IW0MOAAAAVCZMyAEAAAAPMSEHAAAAPMSEHAAAAPAQE3IAAADAQ0zIAQAAAA8xIQcAAAA8xIQcAAAA8FC084DvJuUAAAAAwot3yAEAAAAPMSEHAAAAPPT/KhxZQa8CNjMAAAAASUVORK5CYII=",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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wQE5EdH/FxISghMnTgjbYmNj8eDBA2Fbhw4dsHPnTpQrVw7FixdX5b3nzJmDLVu2YNasWWb7LH2/Zs2aYdOmTdi1a5c8nQUANmzYIDzPYDBAkiQYjUZh++eff46MjAxh2/PnWHrW3NXVFX379sXSpUtx8OBBJCQkmM1f79ChAzZs2ICMjAw0aNDA4uM2aNAAlStXxrp163D06FEOyImowOCAnIjo/+vbty/effddzJgxA82aNcOZM2ewbNky+Pj4CM977733sG/fPoSFheGdd95BpUqV8OTJEyQmJmLnzp1YuXIlgoKCrHrv0NBQDBs2LMvpGJa+X79+/bBkyRL06dMHc+bMQfny5bFr1y7s2bMHAOTVZIoWLYqmTZvi/fffh5+fH0JCQhAfH49Vq1ahWLFiwntXq1YNAPDpp5/C29sbnp6eCA0Nha+vb7Zfy8CBA7FgwQL06tULXl5eZqu89OjRA+vWrcOrr76KUaNGoX79+nB3d8eVK1cQFxeHTp06oXPnzli5ciViY2PRvn17BAcH48mTJ/jiiy8AAK1atbLq8yUi0jPOISci+v8mTJggrxLy2muvYevWrdi0aZPZILV06dJISEhAREQE3n//fbRt2xZ9+/bFF198gZo1a9p81nz69OkoWrSo2XZL369w4cLyut0TJ07EG2+8gUuXLiE6OhoAhK9j/fr1aN68OSZOnIguXbogISEB+/btM/vlIzQ0FEuXLsVvv/2G8PBw1KtXD99++22OX0fFihURFhaGK1euoEuXLmbHdHV1xY4dOzB16lRs27YNnTt3xuuvv4758+fD09MTL7/8MoC/p/Kkp6dj5syZaNeuHfr27Ytbt25hx44diIiIsPrzJSLSK8Pg5cmS6YbPhpfQqi9ERGQH8+bNw/Tp03Hp0iWrz9wTEZF9DIn+55odTlkhIipAli1bBgCoXLkynj17htjYWHz00Ufo06cPB+NERDrFATkRUQFSqFAhLFmyBImJiXj69CmCg4MxadIkTJ8+XeuuERFRNjggJyIqQAYOHIiBAwdq3Q0iIrICL+okIiIiItIQB+RERERERBrigJyIiIiISEMckBMRERERaYgDciIiIiIiDXFATkRERESkIQ7IiYiIiIg0xAE5EREREZGGOCAnIiIiItIQB+RERERERBrigJyIiIiISEMckBMRERERaYgDciIiIiIiDXFATkRERESkIQ7IiYiIiIg0xAE5EREREZGGOCAnIiIiItIQB+RERERERBrigJyIiIiISENOOSA3GAwWPfbv3691V7N1+/ZtjBo1CiEhITAajfD390e7du1w584drbvmVBw9SykpKZg2bRoqVqyIQoUKoUyZMujWrRtOnz6tddecjqNnCQA2bNiAmjVrwtPTE4GBgRg9ejQePHigdbecDrNEanH0LK1duxY9evRApUqV4OLigpCQEK27lC03rTughV9++UWoZ8+ejbi4OMTGxgrbq1atmp/dsti1a9fQpEkTuLm54d1330WFChVw+/ZtxMXFIS0tTevuORVHz9Jrr72GhIQEREZGom7durhy5Qree+89vPLKKzh58iTKli2rdRedhqNnad26dejTpw8GDx6MJUuW4Ny5c5g0aRLOnDmDvXv3at09p8IskVocPUtffvklkpKSUL9+fWRmZuLZs2dadylbTjkgb9iwoVCXLFkSLi4uZtuVHj16hEKFCtmzaxYZPnw4nj59ioSEBBQvXlze3qVLFw175ZwcOUvnz5/HgQMHMH36dEyYMEHeXr58eYSFhWHbtm0YM2aMhj10Lo6cpYyMDEyYMAERERH47LPPAADNmzeHt7c3evfujV27dqFdu3aa9tGZMEukFkfOEgDs2bMHLi5/Twbp0KEDTp06pXGPsueUU1YsER4ejmrVquHAgQMICwtDoUKFMHDgQAB//wknMjLS7DUhISHo37+/sC0pKQlDhw5FUFAQPDw8EBoailmzZiE9Pd2mfiUmJmLHjh0YMmSIMBgn/dJrltzd3QEAPj4+wvZixYoBADw9PW06LtmPXrN06NAhXL9+HQMGDBC2d+vWDUWKFMF//vMfm45L9sMskVr0miUA8mDcEThOTzVw/fp19OnTB7169cLOnTsxfPhwq17//M8ke/bswYwZM7Br1y4MGjQIUVFRGDJkiPDc/v37w2AwIDExMcdjHjx4EJIkITAwED179kSRIkXg6emJ8PBwsz8tkX7oMUtly5ZFp06dsGTJEsTFxeHBgwf4448/8M477yA4OBg9evSw9sukfKDHLD0/61S9enVhu7u7OypXrqzrs1LOjFkitegxS47GKaesWOrOnTvYvHkzWrRoYdPrIyMjcffuXZw+fRrBwcEAgJYtW8LLywvjx4/HhAkT5HlXrq6ucHV1hcFg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8XZUgDFLosKFCwt1XFycUCvnFLZt21ZuHz9+3G79cgTMEqmFWSK1MEv0nF0G5N27d0dycjLee+89XL9+HdWqVcPOnTtRtmxZe7wdFWDMEqmFWSK1MEukFmaJnjMMXp4srJvz2fASWvUFAJCSkgIfHx9N+0CWuX//PooWLap1N7JVELNUUM+QM0ukFmaJ1MIskVqyy9KQ6Dty2763oCIiIiIiohzZZcoKEamnePHicnv79u3Cvjp16gi18kYRY8eOldv/+te/1O8cERER5RnPkBMRERERaYgDciIiIiIiDXFATkRERESkIc4hJ9K5ESNGyO1GjRrl+Ny//vpLqMeMGWOXPhFRwebu7i7Uvr6+2T5XuWZ2yZIlc9xvasuWLULdq1cvoc7IyMixn0QFBc+QExERERFpiANyIiIiIiINcUBORERERKQhziEn0pmGDRsK9aRJk7J97pMnT4R6woQJQp2cnKxex4jIaYwbN06o58yZY/FrDQaDUCvvj2B6rUuFChWEfa1atRLqPXv2WPy+RI6MZ8iJiIiIiDTEATkRERERkYY4ZcXBde3aVag3b94stzt06CDs+/777/OlT2SdUqVKCfXy5cuF2svLK9vXKv/9d+3apV7HiMhpValSxebXpqWlCbXpzyVAXI6V0+qcj4uLeC64TJkyclv5M61JkyY5HissLExu+/v75/hc5dSpW7duye2yZcsK+5TTQfMDz5ATEREREWmIA3IiIiIiIg1xQE5EREREpCHOIdeBwoULC3VoaKjcrlevnrDvvffeE+oDBw4IdWZmpsq9I7W5uroK9bJly4S6Zs2a2b52586dQs0546RHlSpVEuqRI0fK7dKlSwv7vvnmG6H+8ssv7dcxypavr69Qt2/f3uLXTp48WaiV36fOnDlje8dIl5RzrleuXCm3lT/jlJRjnrp168rt27dvC/u+++47oVZec2U6L1w5R/zZs2dCHR8fL9Q///yz3E5PT8+xz/mBZ8iJiIiIiDTEATkRERERkYY4ICciIiIi0hDnkFvI3d1dqNu0aSPUjRo1EuqOHTtafGw3N/GfoWjRonJbOV9KqUePHtnuU976mOuQ64Nyfd8uXboItXIe3N27d+V2v3797Ncx0kS7du2EWrkO70cffSTUv/32m937ZC3T71kAsG7dOqGuXbt2tq/9888/7dInss7bb78t1MWK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sea5gJjxH374IcfnknqUS/s2bNgw2+fevHlTqJXTP5Q/a7Zs2ZK3zv1/L730klArl30tV66cUPv4+Mjt9u3bC/s++ugjoX727JkaXaR8dPv2baFu3bq1UCuXmN61a5fcrlmzprBPuVy13vEMORERERGRhjggJyIiIiLSEAfkREREREQacuo55BMnTsyX91HO21MuVahcus50SaBp06YJ+/73v/8JtTXLqZH9KOeqpaenZ/tc5e2eo6OjhTosLMzi9z148KBQjxw50uLXKm9h7uvrK9Smy29yDnnejBs3TqjbtGkjtx8/fizs8/f3F+rLly8Ltb1uFT1o0CChVuZBedt1a8yYMUNu37171+bjkHVOnjwp1Mr5t+3atZPbH374obBvzZo19uuYidOnTwu1cinPb7/9VqhN+9y0aVNhn/L6ilOnTqnRRdKQck658hqDgQMHyu0+ffoI+xzt5xbPkBMRERERaYgDciIiIiIiDXFATkRERESkIaeeQ25PzZs3l9vbt28X9hUpUiTH15rOKV64cKGq/SL7UM5VVM77LVasmNzu0aOHsM+a290rb1muXMP84cOH2b5Wud6vh4eHxe9LefN///d/OdZ6oOyTMi+maz4r1yFXUs7d3LNnTx57R7a4fv26UCuvSVLWevT7778LtekccnI+Od3HIDAwMB97oj6eISciIiIi0hAH5EREREREGuKAnIiIiIhIQ5xDrpLu3bsLtel60LnNGb9w4YJQL1++XL2OkSYOHDgg1KZzv11cxN+DTdedB4Bz584J9dixY+X2mTNnhH3e3t5CXa1aNaH+17/+Jbf79euX42uVc9k579e5KecXK3NrKiYmRqiV6+Er1+knspTy+5apX375RaiV9+mggqdt27bZ7ouLi8vHnqiPZ8iJiIiIiDTEATkRERERkYY4ZcVCymW+lEvGKW8z7O7unu2xrl69KtSvvvqqUCunLJDjSUhIEGrT6SDKKSrKqSLKKU6myyQql0ysXbu2UFepUsXiPirfV3kL6ylTplh8LHJ8hQsXFuqWLVtm+1xldipUqCDUnKJCtvriiy+E2s/PT6hNs/fgwQNh3+PHj+3XMdIF5XS4vXv3yu1Dhw7ld3dUxTPkREREREQa4oCciIiIiEhDHJATEREREWmIc8gtpFwi7u7duxa/9q+//hLqxYsXCzXnjBc8ytv7/vbbb3K7Zs2aOb62dOnSQt27d+9sn6u8tkE5tzcnFy9eFOpOnTpZ/FoqeH788UehLlmyZLbP3bJli1Arl30lbSivXWrTpo1QHzx4UKjv379v9z5lpXjx4nJ7yZIlwr6+ffsKtXK5zT///FNuDxs2zA69Iy25uroKtfLfuFGjRkLduXNnuZ2enm6/juUDniEnIiIiItIQB+RERERERBqyakAeFRWFevXqwdvbG6VKlcLrr7+Os2fPCs+RJAmRkZEIDAyEl5cXwsPDzZZTI2KWSC3MEqmFWSK1MEtkLavmkMfHx2PEiBGoV68e0tPTMW3aNERERODMmTPyGrYLFy7E4sWLERMTg4oVK2LOnDlo3bo1zp49azYPW+98fHzk9ubNm20+jnIO8K+//mrzsQqKgp6l69evC/XYsWPldmxsrN3eV3ltw/fffy+3lWvl//HHH0Kt7LOjKOhZyi/K+yMoPXv2TG7v3r3b3t3RhKNnqWrVqkK9fft2ob5w4YJQf/TRR3J748aNwr6bN2/m+F4VK1aU215eXsI+Za2cB9yiRQu5rbxmRnkdTFpamlCPGTNGbicmJubYRy05epbyk+m1DzNmzBD2TZgwQajfeOMNod61a5f9OpbPrBqQK78Jr169GqVKlcKRI0fQtGlTSJKEpUuXYtq0aejSpQuAvwcB/v7+WL9+PYYOHWp2zKdPnwo3kUhJSbHl6yAHwyyRWpglUguzRGphlshaeZpD/vwK7RIlSgD4+7fvpKQkREREyM8xGo1o1qwZfv755yyPERUVBR8fH/nxwgsv5KVL5KCYJVILs0RqYZZILcwS5cbmAbkkSRg7diwaN26MatWqAQCSkpIAAP7+/sJz/f395X1KU6ZMwf379+XH5cuXbe0SOShmidTCLJFamCVSC7NElrB5HfKRI0fixIkT+Omnn8z2ZbU2snLbc0ajEUaj0dZuqOr5b67Pmc65bdmyZY6vPX/+vFCvXbtWbpuuQU3mCmKWlBISEmx+7ZkzZ+T27NmzhX0HDhwQatN5vgBw584dm9/XETlDluylSpUqOe7PyMiQ28o1ywsiR8xSamqqUCv//4eGhgq16RrgI0aMEPblNj+7YcOGcrtIkSLCPjXvjxAdHS3UptfFOApHzJKa3NzEoWarVq2EeurUqXJbef8D03XGgYI1Z1zJpjPkb7/9Nnbs2IG4uDgEBQXJ2wMCAgDA7Le7mzdvmv0WSAQwS6QeZonUwiyRWpglspRVA3JJkjBy5Ehs27YNsbGxZr9th4aGIiAgAPv27ZO3paWlIT4+HmFhYer0mAoEZonUwiyRWpglUguzRNayasrKiBEjsH79enzzzTfw9vaWf7Pz8fGBl5cXDAYDRo8ejXnz5qFChQqoUKEC5s2bh0KFCqFXr152+QLywtfXV6hXr14t1K+++qrFx9q5c6dQz5071/aOOYGClqXcPHz4UG4rbw1MeeNsWbIX5XSo5ys/PJeZmSm3/fz8hH2XLl2yX8fykaNn6a+//hLqUaNGCfWXX36Z7WsrVKgg1OXLl1evYzlYuHChUH/88cdC7ajLsTp6lvJCeYZ/8eLFQq383mI69po5c6aw79atWyr3Tr+sGpCvWLECABAeHi5sX716Nfr37w8AmDhxIh4/fozhw4fj7t27aNCgAfbu3etUa2pS7pglUguzRGphlkgtzBJZy6oBuSUXZhgMBkRGRiIyMtLWPpETYJZILcwSqYVZIrUwS2StPK1DTkREREREeWPzsocFwSuvvCLU7du3t/i1ynlNN27cUKVPRERa+Prrr3OsyfEcOXJEqD/44AOhrlu3rtxWTq3Ii/j4eKFWLlVnuqSwcmnG9PR01fpBOatdu7ZQd+jQQW6/9957Ob62ePHiQt26dWu5rcyZ8hq7SpUqCXVBuQYlr3iGnIiIiIhIQxyQExERERFpiANyIiIiIiINOfUccmvcvn1bqNu0aSPUv/32W352h4iIKEfnzp0T6kmTJmnUE9IDT09Pod6+fbtQDx06VG6bzgkHYLY2eseOHYX6m2++kdt16tQR9t28edPqvjojniEnIiIiItIQB+RERERERBrigJyIiIiISENOPYf8999/F+oLFy4IddGiReV2RESEsI9zxomIiMhRPH36VKj//PNPod66davc/t///ifsU16PoJxjfuzYMbltyV1KyRzPkBMRERERaYgDciIiIiIiDTn1lBXln2TKly+vUU+IiIiI7Ec5laRly5Ya9YSywjPkREREREQa4oCciIiIiEhDHJATEREREWmIA3IiIiIiIg1xQE5EREREpCEOyImIiIiINKS7ATnv8OQ49P5vpff+0T/0/m+l9/7RP/T+b6X3/tE/9P5vpff+0T8s+bfS3YA8NTVV6y6QhfT+b6X3/tE/9P5vpff+0T/0/m+l9/7RP/T+b6X3/tE/LPm30t2NgQIDA3H58mVIkoTg4GBcvnwZRYsW1bpbupaSkoIXXngh3z4rSZKQmpqKwMBAu79XXjBL1mOWssYsWY9ZyhqzZD1mKWvMkvX0nCXdDchdXFwQFBSElJQUAEDRokUZMAvl52fl4+OTL++TF8yS7ZglEbNkO2ZJxCzZjlkSMUu202OWdDdlhYiIiIjImXBATkRERESkId0OyI1GI2bOnAmj0ah1V3SPn1XO+PlYjp9Vzvj5WI6fVc74+ViOn1XO+PlYTs+flWHw8mRhLZbPhpfQqi9ERERERE5hSPQdua3bM+RERERERM6AA3IiIiIiIg1xQE5EREREpCEOyImIiIiINMQBORERERGRhnQ7II+OjkZoaCg8PT1Rp04dHDx4UOsuaSoqKgr16tWDt7c3SpUqhddffx1nz54VniNJEiIjIxEYGAgvLy+Eh4fj9OnTGvVYP5glEbNkO2ZJxCzZjlkSMUu2Y5ZEjpolXQ7IN27ciNGjR2PatGk4duwYmjRpgnbt2uHSpUtad00z8fHxGDFiBA4dOoR9+/YhPT0dERERePjwofychQsXYvHixVi2bBkOHz6MgIAAtG7dGqmpqRr2XFvMkjlmyTbMkjlmyTbMkjlmyTbMkjmHzdLg5cmS6UMP6tevL7311lvCtsqVK0uTJ0/WqEf6c/PmTQmAFB8fL0mSJGVmZkoBAQHS/Pnz5ec8efJE8vHxkVauXKlVNzXHLOWOWbIMs5Q7ZskyzFLumCXLMEu503OWTMffujtDnpaWhiNHjiAiIkLYHhERgZ9//lmjXunP/fv3AQAlSvx9I6cLFy4gKSlJ+NyMRiOaNWvmtJ8bs2QZZil3zJJlmKXcMUuWYZZyxyxZxlGypLsB+e3bt5GRkQF/f39hu7+/P5KSkjTqlb5IkoSxY8eicePGqFatGgDInw0/t38wS7ljlizDLOWOWbIMs5Q7ZskyzFLuHClLbpq9cy4MBoNQS5Jkts1ZjRw5EidOnMBPP/1kto+fmzl+JtljlqzDzyR7zJJ1+Jlkj1myDj+T7DlSlnR3htzPzw+urq5mv6XcvHnT7LcZZ/T2229jx44diIuLQ1BQkLw9ICAAAPi5mWCWcsYsWY5ZyhmzZDlmKWfMkuWYpZw5WpZ0NyD38PBAnTp1sG/fPmH7vn37EBYWplGvtCdJEkaOHIlt27YhNjYWoaGhwv7Q0FAEBAQIn1taWhri4+Od9nNjlrLGLFmPWcoas2Q9ZilrzJL1mKWsOWyW9LjKyoYNGyR3d3dp1apV0pkzZ6TRo0dLhQsXlhITE7XummaGDRsm+fj4SPv375euX78uPx49eiQ/Z/78+ZKPj4+0bds26eTJk1LPnj2l0qVLSykpKRr2XFvMkjlmyTbMkjlmyTbMkjlmyTbMkjlHypLp+FuXA3JJkqTly5dLZcuWlTw8PKTatWvLy9U4KwBZPlavXi0/JzMzU5o5c6YUEBAgGY1GqWnTptLJkye167ROMEsiZsl2zJKIWbIdsyRilmzHLIkcKUum42/D4OXJkukZ88+Gl7Df6XgiIiIiIsKQ6DtyW3dzyImIiIiInAkH5EREREREGuKAnIiIiIhIQxyQExERERFpiANyIiIiIiINcUBORERERKQhDsiJiIiIiDTEATkRERERkYbclBtMFyknIiIiIiL74hlyIiIiIiINcUBORERERKSh/wdcIrvdV0SxcwAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "if n_tp > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_TruePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayImageConfusion(x_tra_tp,\n",
+ " y_true_tra_tp,\n",
+ " y_choice_tra_tp,\n",
+ " title_main=\"True Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_fp > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_FalsePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayImageConfusion(x_tra_fp,\n",
+ " y_true_tra_fp,\n",
+ " y_choice_tra_fp,\n",
+ " title_main=\"False Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_tn > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_TrueNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayImageConfusion(x_tra_tn,\n",
+ " y_true_tra_tn,\n",
+ " y_choice_tra_tn,\n",
+ " title_main=\"True Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_fn > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_FalseNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayImageConfusion(x_tra_fn,\n",
+ " y_true_tra_fn,\n",
+ " y_choice_tra_fn,\n",
+ " title_main=\"False Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 8: Four panels of 10 images each, representing true positives (top), false positives (second), true negatives (third), and false negatives (bottom), for classification category 2.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot histograms of images pixels of true positives, false positives, true negatives, and false negatives."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 50,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:45.387543Z",
+ "iopub.status.busy": "2025-02-09T23:13:45.387337Z",
+ "iopub.status.idle": "2025-02-09T23:13:50.807474Z",
+ "shell.execute_reply": "2025-02-09T23:13:50.806324Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:45.387525Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAuQAAAGMCAYAAACS67fPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABEsElEQVR4nO3de1hVZd7/8c+WwwYUEIFAEtHUHA/YAceU8jSCpo9l4/j4dNC00CxrzIycaSqlMp2xk2ViZQVaVmaNzWh2oDTTUctTk5pPPytMLchjgpkgcP/+cNyPW9AEblhsfL+ua12XrH3vtb5r92nv7zrstV2jZu03AgAAAOCIBk4XAAAAAJzLaMgBAAAAB/mfOmPO2CZO1AEAAACcM0ZnHvD8myPkAAAAgINoyAEAAAAH0ZADAAAADqIhBwAAABxEQw4AAAA4iIYcAAAAcBANOYB6zeVyndX08ccfO1pnr169vOoJDg7WRRddpBkzZqisrMz6+rKzs+VyubRjxw7PvFdffVUzZsyocLzL5VJGRob1OgAAFdyHHADqkzVr1nj9/fDDD2v58uVatmyZ1/z27dvXZlkVuuCCCzR//nxJ0p49e/Tss8/qrrvuUl5env72t79ZXdd//dd/ac2aNWratKln3quvvqotW7Zo/Pjx5cavWbNGzZo1s1oDAOA4GnIA9VrXrl29/o6OjlaDBg3KzT/VkSNHFBISUpOllRMcHOxVV//+/fWb3/xGzzzzjKZMmaKAgABr64qOjlZ0dPRZj/+11wsAUHVcsgLgnNerVy917NhRn3zyiZKTkxUSEqKbb75Z0ukv1WjRooVGjhzpNS8/P19jxoxRs2bNFBgYqJYtW+rBBx9USUlJleoKCAhQUlKSjhw5or1790qStmzZokGDBikiIkJBQUG6+OKLNXfuXK/nlZWVacqUKWrbtq2Cg4PVuHFjderUSU899ZRnzKmXrPTq1UvvvPOOvvvuO69LZ044+XX497//LZfLpRdffLFcze+++65cLpf++c9/euZt375d119/vc477zy53W61a9dOs2bNqnTNAFBfcYQcACTl5eVp2LBhmjhxoqZOnaoGDSp3vCI/P19dunRRgwYNNGnSJLVq1Upr1qzRlClTtGPHDmVlZVWprm+++Ub+/v6KiIjQV199peTkZJ133nl6+umnFRkZqVdeeUUjR47Ujz/+qIkTJ0qSpk+froyMDN1///3q0aOHjh07pv/93//VTz/9dNr1ZGZm6pZbbtE333yjRYsWnbGmiy66SJdccomysrKUlpbm9Vh2drbOO+88DRgwQJL05ZdfKjk5Wc2bN9fjjz+u2NhYvf/++xo3bpz27dunyZMnV7lmAKgvaMgBQNKBAwe0cOFC/e53v6vS8zMyMnTw4EFt3bpVzZs3lyT16dNHwcHBSk9P1z333HNW16mfOJq+d+9ePf3009q4caP++7//W8HBwcrIyFBxcbGWL1+u+Ph4SdKAAQP0008/6cEHH9SYMWMUHh6uf/3rX0pMTPQ6st+vX78zrrd9+/Zq3Lix3G73WV2ectNNN2ncuHH6f//v/+nCCy+UJB08eFD/+Mc/dMcdd8jf//jHy4QJExQaGqpVq1YpLCxMkpSamqqioiL99a9/1bhx4xQREVGlmgGgvuCSFQCQFBERUeVmXJKWLFmi3r17Ky4uTiUlJZ6pf//+kqQVK1b86jK2bt2qgIAABQQEKC4uTo8//rhuuOEGzZkzR5K0bNky9enTx9OMnzBy5EgdOXLE8wXWLl266N///rfGjh2r999/XwUFBVXertO54YYb5Ha7lZ2d7Zn32muvqaioSDfddJMk6ejRo/roo4/0+9//XiEhIV6vy4ABA3T06FGtXbu21moGgLqKhhwAJK+7jVTFjz/+qMWLF3sa6hNThw4dJEn79u371WW0atVK69at0/r167Vlyxb99NNPeuWVVxQeHi5J2r9/f4V1xsXFeR6XpHvvvVePPfaY1q5dq/79+ysyMlJ9+vTR+vXrq7WNJ2vSpImuvvpqzZs3T6WlpZKOX67SpUsXzzbv379fJSUlmjlzZrnX5cQlLSdel9qoGQDqKi5ZAQDJ6wuMJ3O73SoqKio3/0Tze0JUVJQ6deqkRx55pMLlnGiazyQoKEidO3c+7eORkZHKy8srN/+HH37w1CBJ/v7+mjBhgiZMmKCffvpJH374of7yl7+oX79+2rVrl7W7x9x0001auHChcnJy1Lx5c61bt06zZ8/2PB4RESE/Pz8NHz5ct99+e4XLaNmyZa3WDAB1EQ05AJxBixYt9MUXX3jNW7ZsmQ4fPuw1b+DAgVq6dKlatWqliIiIGqmlT58+WrRokX744QevBn/evHkKCQmp8Nrvxo0ba8iQIfr+++81fvx47dix47TXsrvdbv3yyy9nXU/fvn11/vnnKysrS82bN1dQUJCuu+46z+MhISHq3bu3Nm3apE6dOikwMPCslluZmgGgPqAhB4AzGD58uB544AFNmjRJPXv21JdffqlnnnnGcxnJCQ899JBycnKUnJyscePGqW3btjp69Kh27NihpUuX6tlnn632D+tMnjzZc636pEmT1KRJE82fP1/vvPOOpk+f7qnpqquuUseOHdW5c2dFR0fru+++04wZM5SQkKA2bdqcdvmJiYn6+9//rtmzZyspKUkNGjQ44xF7Pz8/3XjjjXriiScUFhamwYMHl3tdnnrqKV1xxRXq3r27brvtNrVo0UKFhYX6+uuvtXjxYs8PNFW1ZgCoD2jIAeAM7rnnHhUUFCg7O1uPPfaYunTpojfeeEODBg3yGte0aVOtX79eDz/8sB599FHt3r1boaGhatmypa688korR83btm2r1atX6y9/+Ytuv/12/fLLL2rXrp2ysrK87oneu3dvvfXWW3rhhRdUUFCg2NhYpaam6oEHHjjjjwvdeeed2rp1q/7yl7/o0KFDMsbIGHPGmm666SZNmzZNe/fu9XyZ82Tt27fXxo0b9fDDD+v+++/Xnj171LhxY7Vp08ZzHXl1agaA+sA1atZ+r3fbOWObOFULAAAAcE4YnXnA82/usgIAAAA4iIYcAAAAcBANOQAAAOAgGnIAAADAQTTkAAAAgINoyAEAAAAH0ZADAAAADqIhBwAAABxEQw4AAAA4iIYcAAAAcBANOQAAAOAgGnIAAADAQTTkAAAAgINoyAEAAAAH0ZADAAAADqIhBwAAABxEQw4AAAA4iIYcAAAAcBANOQAAAOAgGnIAAADAQTTkAAAAgINoyAEAAAAH0ZADAAAADqIhBwAAABxEQ/4fLpfrrKaPP/7Y6VLLycvL0/33369u3bopKipKYWFhSkpK0vPPP6/S0lKnyzvnkCXYQpZgC1mCLWSpZvg7uvY6ZM2aNV5/P/zww1q+fLmWLVvmNb99+/a1WdZZ2bBhg+bNm6cbb7xRDzzwgAICAvTuu+/qtttu09q1a/XSSy85XeI5hSzBFrIEW8gSbCFLNcM1atZ+c/KMOWObOFVLnTJy5Ei9+eabOnz48BnHHTlyRCEhIbVUVcUOHjyoRo0aKSAgwGv+HXfcoVmzZmnnzp2Kj493qDqQJdhClmALWYItZKnqRmce8PybS1YqoVevXurYsaM++eQTJScnKyQkRDfffLOk46dwMjIyyj2nRYsWGjlypNe8/Px8jRkzRs2aNVNgYKBatmypBx98UCUlJVWqKyIioly4JKlLly6SpN27d1dpuag5ZAm2kCXYQpZgC1mqPC5ZqaS8vDwNGzZMEydO1NSpU9WgQeX2afLz89WlSxc1aNBAkyZNUqtWrbRmzRpNmTJFO3bsUFZWlmfsyJEjNXfuXOXm5qpFixaVrnXZsmXy9/fXhRdeWOnnouaRJdhClmALWYItZKlyaMgr6cCBA1q4cKF+97vfVen5GRkZOnjwoLZu3armzZtLkvr06aPg4GClp6frnnvu8Vx35efnJz8/P7lcrkqv54MPPtDLL7+sO++8U5GRkVWqFTWLLMEWsgRbyBJsIUuVwyUrlRQREVHlcEnSkiVL1Lt3b8XFxamkpMQz9e/fX5K0YsUKz9gXX3xRJSUlSkhIqNQ6Nm7cqKFDh6pr166aNm1alWtFzSJLsIUswRayBFvIUuVwhLySmjZtWq3n//jjj1q8eHGF1zBJ0r59+6q1/E2bNik1NVVt2rTR0qVL5Xa7q7U81ByyBFvIEmwhS7CFLFUODXklne50iNvtVlFRUbn5+/fv9/o7KipKnTp10iOPPFLhcuLi4qpc26ZNm5SSkqKEhAR98MEHCg8Pr/KyUPPIEmwhS7CFLMEWslQ5NOSWtGjRQl988YXXvGXLlpW7DdDAgQO1dOlStWrVShEREdbW//nnnyslJUXNmjVTTk6O1WWjdpEl2EKWYAtZgi1kqWJcQ27J8OHD9e6772rSpEn66KOPNHPmTN12223l9roeeughBQQEKDk5WbNnz9ayZcu0dOlSZWZmauDAgV633ElLS5O/v7++++67M677q6++UkpKiiTpkUce0fbt27V27VrPtHfvXvsbjBpDlmALWYItZAm2kKWKcYTcknvuuUcFBQXKzs7WY489pi5duuiNN97QoEGDvMY1bdpU69ev18MPP6xHH31Uu3fvVmhoqFq2bKkrr7zSa0+ttLRUpaWlMsacujova9as8Zzqueqqq8o9npWVVe7enqi7yBJsIUuwhSzBFrJUMX6pEwAAAKhl/FInAAAAUEfQkAMAAAAOoiEHAAAAHERDDgAAADiIhvw/srOz5XK5PJO/v7+aNWumm266Sd9//32t1NCiRYsqf7t3w4YNuv3225WYmKjQ0FDFxMQoJSVFy5Yts1skfhVZgi1kCbaQJdhClmoGDfkpsrKytGbNGuXk5Gj06NF67bXX1L17d/38889Ol3ZGr732mj777DPdfPPN+sc//qEXXnhBbrdbffr00bx585wu75xElmALWYItZAm2kCXLRs3ab06ezlVZWVlGklm3bp3X/AceeMBIMq+88sppn/vzzz9bqSEhIcGMGDGiSs/98ccfy80rKSkxnTp1Mq1atapmZagMsgRbyBJsIUuwhSzZc3L/zRHyX9G1a1dJ8vz608iRI9WoUSNt3rxZffv2VWhoqPr06SNJKi4u1pQpU/Sb3/xGbrdb0dHRuummm8r98tOxY8c0ceJExcbGKiQkRFdccYU+++yzatV53nnnlZvn5+enpKQk7dq1q1rLhh1kCbaQJdhClmALWaoefqnzV3z99deSpOjoaM+84uJiXX311RozZoz+/Oc/q6SkRGVlZRo0aJBWrlypiRMnKjk5Wd99950mT56sXr16af369QoODpYkjR49WvPmzVN6erpSU1O1ZcsWDR48WIWFheXW36JFC0nSjh07Kl17SUmJVq5cqQ4dOlR+w2EdWYItZAm2kCXYQpaqiUtWjjtxCmbt2rXm2LFjprCw0CxZssRER0eb0NBQk5+fb4wxZsSIEUaSeemll7ye/9prrxlJ5q233vKav27dOiPJZGZmGmOM2bZtm5Fk7rrrLq9x8+fPN5LKnYJp1apVlU+h3HfffUaSefvtt6v0fFQNWYItZAm2kCXYQpbsObn/piH/jxMBO3VKTEw0q1at8ow7EbBDhw55Pf+GG24wjRs3NsXFxebYsWNeU2xsrBk6dKgxxpjMzEwjyaxfv97r+ceOHTP+/v5VvibqVHPmzDGSzN13321leTh7ZAm2kCXYQpZgC1my5+T+m0tWTjFv3jy1a9dO/v7+iomJUdOmTcuNCQkJUVhYmNe8H3/8UT/99JMCAwMrXO6+ffskSfv375ckxcbGej3u7++vyMhIG5ugrKwsjRkzRrfccoseffRRK8tE5ZEl2EKWYAtZgi1kyS4a8lO0a9dOnTt3PuMYl8tVbl5UVJQiIyP13nvvVfic0NBQSfKEKD8/X+eff77n8ZKSEk/4qiMrK0ujRo3SiBEj9Oyzz1ZYK2oHWYItZAm2kCXYQpbsoiG3ZODAgXr99ddVWlqqyy677LTjevXqJUmaP3++kpKSPPPfeOMNlZSUVKuG7OxsjRo1SsOGDdMLL7zgeLhQNWQJtpAl2EKWYAtZqhgNuSXXXnut5s+frwEDBujOO+9Uly5dFBAQoN27d2v58uUaNGiQfv/736tdu3YaNmyYZsyYoYCAAKWkpGjLli167LHHyp3WkaTWrVtL+r9vL5/OwoULlZaWposvvlhjxowpd1ugSy65RG63294Go8aQJdhClmALWYItZKliNOSW+Pn56Z///Keeeuopvfzyy5o2bZrn52R79uypxMREz9gXX3xRMTExys7O1tNPP62LL75Yb731lq699tpyyz3bvcB33nlHZWVl2rhxoy6//PJyj+fm5npuCYS6jSzBFrIEW8gSbCFLFXONmrXfnDxjztgmtV4EAAAAcC4ZnXnA829+qRMAAABwEA05AAAA4CAacgAAAMBBNOQAAACAg2jIAQAAAAfRkAMAAAAO8sn7kJeVlemHH35QaGhonfh1pXONMUaFhYWKi4tTgwa+vU9HlpxFlmALWYItZAm2VCZLPtmQ//DDD4qPj3e6jHPerl271KxZM6fLqBayVDeQJdhClmALWYItZ5Mln2zIQ0NDJR3fwIp+PhU1q6CgQPHx8Z7/Dr6MLDmLLMEWsgRbyBJsqUyWfLIhP3HaJSwsjIA5qD6c/iJLdQNZgi1kCbaQJdhyNlny7YujAAAAAB/nk0fIT+fBBx884+OTJ0+upUrg68gSbCFLsIUswRayVPdwhBwAAABwEA05AAAA4CAacgAAAMBBNOQAAACAg2jIAQAAAAfRkMMRGRkZcrlcXlNsbKzncWOMMjIyFBcXp+DgYPXq1Utbt271WkZRUZH++Mc/KioqSg0bNtTVV1+t3bt31/amAKgneF8C4BQacjimQ4cOysvL80ybN2/2PDZ9+nQ98cQTeuaZZ7Ru3TrFxsYqNTVVhYWFnjHjx4/XokWL9Prrr2vVqlU6fPiwBg4cqNLSUic2B0A9wPsSACfQkMMx/v7+io2N9UzR0dGSjh+FmjFjhu677z4NHjxYHTt21Ny5c3XkyBG9+uqrkqRDhw7pxRdf1OOPP66UlBRdcskleuWVV7R582Z9+OGHTm4WAB/G+xJs4GwLKouGHI7Zvn274uLi1LJlS1177bX69ttvJUm5ubnKz89X3759PWPdbrd69uyp1atXS5I2bNigY8eOeY2Ji4tTx44dPWMqUlRUpIKCAq8JAE7gfQm2cLYFlUFDDkdcdtllmjdvnt5//33NmTNH+fn5Sk5O1v79+5Wfny9JiomJ8XpOTEyM57H8/HwFBgYqIiLitGMqMm3aNIWHh3um+Ph4y1sGwFfxvgSbnDjbws6d76IhhyP69++vP/zhD0pMTFRKSoreeecdSdLcuXM9Y1wul9dzjDHl5p3q18bce++9OnTokGfatWtXNbYCQH3C+xJscuJsCzt3vouGHHVCw4YNlZiYqO3bt3uuszv1iNKePXs8R6diY2NVXFysgwcPnnZMRdxut8LCwrwmAKgI70uoKqfOtrBz57toyFEnFBUVadu2bWratKlatmyp2NhY5eTkeB4vLi7WihUrlJycLElKSkpSQECA15i8vDxt2bLFMwYAqoP3JVSVU2db2LnzXTTkcER6erpWrFih3NxcffrppxoyZIgKCgo0YsQIuVwujR8/XlOnTtWiRYu0ZcsWjRw5UiEhIbr++uslSeHh4UpLS9Pdd9+tjz76SJs2bdKwYcM8b34AUFm8L6Gm1NbZFviuSjXk3MYHtuzevVvXXXed2rZtq8GDByswMFBr165VQkKCJGnixIkaP368xo4dq86dO+v777/XBx98oNDQUM8ynnzySV1zzTUaOnSoLr/8coWEhGjx4sXy8/NzarPgAN6XYAvvS6gpnG3Br/Gv7BM6dOjg9Q3fk99kTtzGJzs7WxdeeKGmTJmi1NRUffXVV543rPHjx2vx4sV6/fXXFRkZqbvvvlsDBw7Uhg0beMM6h7z++utnfNzlcikjI0MZGRmnHRMUFKSZM2dq5syZlquDr+F9CTbwvgRb0tPTddVVV6l58+bas2ePpkyZUuHZljZt2qhNmzaaOnXqac+2REZGqkmTJkpPT+dsSz1W6Yb8xG18TnXqbXyk49dKxcTE6NVXX9WYMWM8t/F5+eWXPYF65ZVXFB8frw8//FD9+vWr5uYAOBc58b5UVFSkoqIiz9/cXgzACSfOtuzbt0/R0dHq2rVrubMtv/zyi8aOHauDBw/qsssuq/Bsi7+/v4YOHapffvlFffr0UXZ2NgcJ6qlKX0POjyYAqGu4vRiAuuT111/XDz/8oOLiYn3//fd666231L59e8/jJ8625OXl6ejRo1qxYoU6duzotYwTZ1v279+vI0eOaPHixbzP1GOVasj50QQAdQ23FwMA+LpKXbLSv39/z78TExPVrVs3tWrVSnPnzlXXrl0l1dyPJkyYMMHzd0FBAU05AEnOvS+53W653e5qVA4AwHHVuu0hP5oAoK7h9mIAAF9TrYac2/gAqGt4XwIA+JpKXbLCbXwA1DW8LwEAfF2lGnJu4wOgruF9CQDg6yrVkPOjCQDqGt6XAAC+rlrXkAMAAACoHhpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA6iIQcAAAAcREMOAAAAOIiGHAAAAHAQDTkAAADgIBpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA6iIQcAAAAcREMOAAAAOIiGHAAAAHAQDTkAAADgIBpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA6iIQcAAAAcREMOAAAAOIiGHAAAAHAQDTkAAADgIBpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA6iIQcAAAAcREMOAAAAOIiGHAAAAHCQv9MFAAAA1JQHH3zwV8dMnjy5FioBTo8j5AAAAICDaMgBAAAAB9GQAwAAAA7iGnIA1nCtJgCgvqrJzziOkAMAAAAOoiEHAAAAHERDDgAAADiIhhwAAABwEA05AAAA4CAacgAAAMBBNOQAAACAg7gPObh3NAAAgIM4Qg4AAAA4iIYcAAAAcBCXrAAA6hwupQNwLnG0Ic/MzNSjjz6qvLw8dejQQTNmzFD37t2dLAk+iizBFrIEW+pilnxtR+fX6q1Ltdakupgl2OVYQ75gwQKNHz9emZmZuvzyy/Xcc8+pf//++vLLL9W8eXOnyoIPciJLdelD7WxqORu/Vq+t9dRl53qWagtZqv+fcedirmsK70vnBsca8ieeeEJpaWkaNWqUJGnGjBl6//33NXv2bE2bNs1rbFFRkYqKijx/Hzp0SJJUUFDgNe7o0aNnXOe9995ro/RfXc6p9dfUes5mXWezjF973STv1/rEv40xv/q82uBEls7G2bz2tZWls2Hr/49fQ5Yqr7b+29h4z6lNZMnbqeMrUtn3+6qytR4ntpksnZ3ael/yNVXO0qhZ+83JU20oKioyfn5+5u9//7vX/HHjxpkePXqUGz958mQjiamOTbt27aqVvJwJWaofE1liIkvOv3ZMZImpdrN0cv/tyBHyffv2qbS0VDExMV7zY2JilJ+fX278vffeqwkTJnj+Lisr04EDBxQZGSmXyyXp+F5IfHy8du3apbCwsJrdgHPMqa+tMUaFhYWKi4tzujSy5GPIEmwhS7CFLMGW6mTJ0S91ngjHCcaYcvMkye12y+12e81r3LhxhcsMCwsjYDXk5Nc2PDzc4Wq8kSXfQpZgC1mCLWQJtlQlS47chzwqKkp+fn7l9u727NlTbi8QOBOyBFvIEmwhS7CFLJ07HGnIAwMDlZSUpJycHK/5OTk5Sk5OdqIk+CiyBFvIEmwhS7CFLJ07HLtkZcKECRo+fLg6d+6sbt266fnnn9fOnTt16623Vml5brdbkydPLneqBtVX119bsuQ76vprS5Z8R11/bcmS76jrry1Z8h3VeW1do2btNyfPmDO2ibXCfk1mZqamT5+uvLw8dezYUU8++aR69OhRa+tH/UGWYAtZgi1kCbaQpfppdOYBz78dbcgBAACAc9HJDbkj15ADAAAAOI6GHAAAAHAQDTkAAADgIBpyAAAAwEH1oiHPzMxUy5YtFRQUpKSkJK1cudLpkuqFTz75RFdddZXi4uLkcrn09ttvO11SjSNLNYMskSVbyBJZsoUskSVbbGTJ5xvyBQsWaPz48brvvvu0adMmde/eXf3799fOnTudLs3n/fzzz7rooov0zDPPOF1KrSBLNYcskSVbyBJZsoUskSVbbGTJ5297eNlll+nSSy/V7NmzPfPatWuna665RtOmTXOwsvrF5XJp0aJFuuaaa5wupcaQpdpBlsiSLWSJLNlClsiSLZXJUr257WFxcbE2bNigvn37es3v27evVq9e7VBV8EVkCbaQJdhClmALWar7fLoh37dvn0pLSxUTE+M1PyYmRvn5+Q5VBV9ElmALWYItZAm2kKW6z6cb8hNcLpfX38aYcvOAs0GWYAtZgi1kCbaQpbrLpxvyqKgo+fn5ldu727NnT7m9QOBMyBJsIUuwhSzBFrJU9/l0Qx4YGKikpCTl5OR4zc/JyVFycrJDVcEXkSXYQpZgC1mCLWSp7vN3uoDqmjBhgoYPH67OnTurW7duev7557Vz507deuutTpfm8w4fPqyvv/7a83dubq4+//xzNWnSRM2bN3ewsppBlmoOWSJLtpAlsmQLWSJLtljJ0qhZ+83Jky+aNWuWSUhIMIGBgebSSy81K1ascLqkemH58uVGUrlpxIgRTpdWY8hSzSBLZMkWskSWbCFLZMmWqmbp5P7b5+9DDgAAAPiaenMfcgAAAMDX0ZADAAAADqIhBwAAABxEQw4AAAA4iIYcAAAAcBANOQAAAOAgGnIAAADAQedsQ56RkaGLL77Y2vI+/vhjuVwu/fTTT9aWWRGXy6W33367RteByiFLsIUswRayBFvIUu2otw35yJEj5XK55HK5FBAQoAsuuEDp6en6+eefJUnp6en66KOPaqWW4uJiRUVFacqUKRU+Pm3aNEVFRam4uLhW6kHlkCXYQpZgC1mCLWSpbqi3DbkkXXnllcrLy9O3336rKVOmKDMzU+np6ZKkRo0aKTIyslbqCAwM1LBhw5SdnS1jTLnHs7KyNHz4cAUGBtZKPag8sgRbyBJsIUuwhSw5r1435G63W7GxsYqPj9f111+vG264wXP64uRTMEePHlWHDh10yy23eJ6bm5ur8PBwzZkzR5JkjNH06dN1wQUXKDg4WBdddJHefPPNs64lLS1N33zzjT755BOv+StXrtT27duVlpamdevWKTU1VVFRUQoPD1fPnj21cePG0y6zotM+n3/+uVwul3bs2OGZt3r1avXo0UPBwcGKj4/XuHHjPHu+kpSZmak2bdooKChIMTExGjJkyFlv17mCLB1HlqqPLB1HlqqPLB1HlqqPLB3nZJbqdUN+quDgYB07dqzc/KCgIM2fP19z587V22+/rdLSUg0fPly9e/fW6NGjJUn333+/srKyNHv2bG3dulV33XWXhg0bphUrVpzVuhMTE/Xb3/5WWVlZXvNfeukldenSRR07dlRhYaFGjBihlStXau3atWrTpo0GDBigwsLCKm/z5s2b1a9fPw0ePFhffPGFFixYoFWrVumOO+6QJK1fv17jxo3TQw89pK+++krvvfeeevToUeX1nSvIElmyhSyRJVvIElmyhSw5kKVRs/abk6f6YsSIEWbQoEGevz/99FMTGRlphg4daowxZvLkyeaiiy7yes706dNNVFSU+eMf/2hiY2PN3r17jTHGHD582AQFBZnVq1d7jU9LSzPXXXedMcaY5cuXG0nm4MGDp61p9uzZpmHDhqawsNAYY0xhYaFp2LChee655yocX1JSYkJDQ83ixYs98ySZRYsWnXadmzZtMpJMbm6uMcaY4cOHm1tuucVruStXrjQNGjQwv/zyi3nrrbdMWFiYKSgoOG3d5zqylGuMIUs2kKVcYwxZsoEs5RpjyJINZCnXGONMlk7uv+v1EfIlS5aoUaNGCgoKUrdu3dSjRw/NnDnztOPvvvtutW3bVjNnzlRWVpaioqIkSV9++aWOHj2q1NRUNWrUyDPNmzdP33zzzVnXc91116msrEwLFiyQJC1YsEDGGF177bWSpD179ujWW2/VhRdeqPDwcIWHh+vw4cPauXNnlV+DDRs2KDs726vufv36qaysTLm5uUpNTVVCQoIuuOACDR8+XPPnz9eRI0eqvL76iiyRJVvIElmyhSyRJVvIkvNZ8re2pDqod+/emj17tgICAhQXF6eAgIAzjt+zZ4+++uor+fn5afv27bryyislSWVlZZKkd955R+eff77Xc9xu91nXEx4eriFDhigrK0tpaWnKysrSkCFDFBYWJun4N5337t2rGTNmKCEhQW63W926dTvtt4kbNDi+P2VO+uLDqaeYysrKNGbMGI0bN67c85s3b67AwEBt3LhRH3/8sT744ANNmjRJGRkZWrdunRo3bnzW21bfkSWyZAtZIku2kCWyZAtZcj5L9bohb9iwoVq3bn3W42+++WZ17NhRo0ePVlpamvr06aP27durffv2crvd2rlzp3r27FmtmtLS0tSrVy8tWbJE//rXvzR16lTPYytXrlRmZqYGDBggSdq1a5f27dt32mVFR0dLkvLy8hQRESHp+JcUTnbppZdq69atZ3wd/P39lZKSopSUFE2ePFmNGzfWsmXLNHjw4KpuZr1DlsiSLWSJLNlClsiSLWTJ+SzV64a8MmbNmqU1a9boiy++UHx8vN59913dcMMN+vTTTxUaGqr09HTdddddKisr0xVXXKGCggKtXr1ajRo10ogRI856PT179lTr1q114403qnXr1l5fCGjdurVefvllde7cWQUFBbrnnnsUHBx82mW1bt1a8fHxysjI0JQpU7R9+3Y9/vjjXmP+9Kc/qWvXrrr99ts1evRoNWzYUNu2bVNOTo5mzpypJUuW6Ntvv1WPHj0UERGhpUuXqqysTG3btq38iwhJZIks2UOWyJItZIks2UKWaihL58qXOk918pcUtm3bZoKDg82rr77qefzQoUOmRYsWZuLEicYYY8rKysxTTz1l2rZtawICAkx0dLTp16+fWbFihTHm7L6kcMLUqVONJDN16lSv+Rs3bjSdO3c2brfbtGnTxixcuNAkJCSYJ5980jNGJ31JwRhjVq1aZRITE01QUJDp3r27WbhwodeXFIwx5rPPPjOpqammUaNGpmHDhqZTp07mkUceMcYc/8JCz549TUREhAkODjadOnUyCxYs+NVtOJeQpVzPGLJUPWQp1zOGLFUPWcr1jCFL1UOWcj1jajtLJ/ffrlGz9nvdeX3O2CZ2On0AAAAAFRqdecDz73p9lxUAAACgrqMhBwAAABxEQw4AAAA4iIYcAAAAcBANOQAAAOAgGnIAAADAQTTkAAAAgINoyAEAAAAH0ZADAAAADqIhBwAAABxEQw4AAAA4iIYcAAAAcBANOQAAAOAgGnIAAADAQTTkAAAAgINoyAEAAAAH0ZADAAAADqIh/w+Xy3VW08cff+x0qeXk5eXp/vvvV7du3RQVFaWwsDAlJSXp+eefV2lpqdPlnXPIEmwhS7CFLMEWslQz/B1dex2yZs0ar78ffvhhLV++XMuWLfOa3759+9os66xs2LBB8+bN04033qgHHnhAAQEBevfdd3Xbbbdp7dq1eumll5wu8ZxClmALWYItZAm2kKWa4Ro1a785ecacsU2cqqVOGTlypN58800dPnz4jOOOHDmikJCQWqqqYgcPHlSjRo0UEBDgNf+OO+7QrFmztHPnTsXHxztUHcgSbCFLsIUswRayVHWjMw94/s0lK5XQq1cvdezYUZ988omSk5MVEhKim2++WdLxUzgZGRnlntOiRQuNHDnSa15+fr7GjBmjZs2aKTAwUC1bttSDDz6okpKSKtUVERFRLlyS1KVLF0nS7t27q7Rc1ByyBFvIEmwhS7CFLFUel6xUUl5enoYNG6aJEydq6tSpatCgcvs0+fn56tKlixo0aKBJkyapVatWWrNmjaZMmaIdO3YoKyvLM3bkyJGaO3eucnNz1aJFi0rXumzZMvn7++vCCy+s9HNR88gSbCFLsIUswRayVDk05JV04MABLVy4UL/73e+q9PyMjAwdPHhQW7duVfPmzSVJffr0UXBwsNLT03XPPfd4rrvy8/OTn5+fXC5XpdfzwQcf6OWXX9add96pyMjIKtWKmkWWYAtZgi1kCbaQpcrhkpVKioiIqHK4JGnJkiXq3bu34uLiVFJS4pn69+8vSVqxYoVn7IsvvqiSkhIlJCRUah0bN27U0KFD1bVrV02bNq3KtaJmkSXYQpZgC1mCLWSpcjhCXklNmzat1vN//PFHLV68uMJrmCRp37591Vr+pk2blJqaqjZt2mjp0qVyu93VWh5qDlmCLWQJtpAl2EKWKoeGvJJOdzrE7XarqKio3Pz9+/d7/R0VFaVOnTrpkUceqXA5cXFxVa5t06ZNSklJUUJCgj744AOFh4dXeVmoeWQJtpAl2EKWYAtZqhwacktatGihL774wmvesmXLyt0GaODAgVq6dKlatWqliIgIa+v//PPPlZKSombNmiknJ8fqslG7yBJsIUuwhSzBFrJUMa4ht2T48OF69913NWnSJH300UeaOXOmbrvttnJ7XQ899JACAgKUnJys2bNna9myZVq6dKkyMzM1cOBAr1vupKWlyd/fX999990Z1/3VV18pJSVFkvTII49o+/btWrt2rWfau3ev/Q1GjSFLsIUswRayBFvIUsU4Qm7JPffco4KCAmVnZ+uxxx5Tly5d9MYbb2jQoEFe45o2bar169fr4Ycf1qOPPqrdu3crNDRULVu21JVXXum1p1ZaWqrS0lIZY05dnZc1a9Z4TvVcddVV5R7Pysoqd29P1F1kCbaQJdhClmALWaoYv9QJAAAA1DJ+qRMAAACoI2jIAQAAAAfRkAMAAAAOoiEHAAAAHERDDgAAADiIhvw/srOz5XK5PJO/v7+aNWumm266Sd9//32t1NCiRYsq325nw4YNuv3225WYmKjQ0FDFxMQoJSVFy5Yts1skfhVZgi1kCbaQJdhClmoGDfkpsrKytGbNGuXk5Gj06NF67bXX1L17d/38889Ol3ZGr732mj777DPdfPPN+sc//qEXXnhBbrdbffr00bx585wu75xElmALWYItZAm2kCXLRs3ab06ezlVZWVlGklm3bp3X/AceeMBIMq+88sppn/vzzz9bqSEhIcGMGDGiSs/98ccfy80rKSkxnTp1Mq1atapmZagMsgRbyBJsIUuwhSzZc3L/zRHyX9G1a1dJ8vwc68iRI9WoUSNt3rxZffv2VWhoqPr06SNJKi4u1pQpU/Sb3/xGbrdb0dHRuummm8r9FOuxY8c0ceJExcbGKiQkRFdccYU+++yzatV53nnnlZvn5+enpKQk7dq1q1rLhh1kCbaQJdhClmALWaoef8fW7CO+/vprSVJ0dLRnXnFxsa6++mqNGTNGf/7zn1VSUqKysjINGjRIK1eu1MSJE5WcnKzvvvtOkydPVq9evbR+/XoFBwdLkkaPHq158+YpPT1dqamp2rJliwYPHqzCwsJy62/RooUkaceOHZWuvaSkRCtXrlSHDh0qv+GwjizBFrIEW8gSbCFL1cQlK8edOAWzdu1ac+zYMVNYWGiWLFlioqOjTWhoqMnPzzfGGDNixAgjybz00ktez3/ttdeMJPPWW295zV+3bp2RZDIzM40xxmzbts1IMnfddZfXuPnz5xtJ5U7BtGrVqsqnUO677z4jybz99ttVej6qhizBFrIEW8gSbCFL9pzcf9OQ/8eJgJ06JSYmmlWrVnnGnQjYoUOHvJ5/ww03mMaNG5vi4mJz7Ngxryk2NtYMHTrUGGNMZmamkWTWr1/v9fxjx44Zf3//Kl8Tdao5c+YYSebuu++2sjycPbIEW8gSbCFLsIUs2XNy/80lK6eYN2+e2rVrJ39/f8XExKhp06blxoSEhCgsLMxr3o8//qiffvpJgYGBFS533759kqT9+/dLkmJjY70e9/f3V2RkpI1NUFZWlsaMGaNbbrlFjz76qJVlovLIEmwhS7CFLMEWsmQXDfkp2rVrp86dO59xjMvlKjcvKipKkZGReu+99yp8TmhoqCR5QpSfn6/zzz/f83hJSYknfNWRlZWlUaNGacSIEXr22WcrrBW1gyzBFrIEW8gSbCFLdtGQWzJw4EC9/vrrKi0t1WWXXXbacb169ZIkzZ8/X0lJSZ75b7zxhkpKSqpVQ3Z2tkaNGqVhw4bphRdecDxcqBqyBFvIEmwhS7CFLFWMhtySa6+9VvPnz9eAAQN05513qkuXLgoICNDu3bu1fPlyDRo0SL///e/Vrl07DRs2TDNmzFBAQIBSUlK0ZcsWPfbYY+VO60hS69atJf3ft5dPZ+HChUpLS9PFF1+sMWPGlLst0CWXXCK3221vg1FjyBJsIUuwhSzBFrJUMRpyS/z8/PTPf/5TTz31lF5++WVNmzbN83OyPXv2VGJiomfsiy++qJiYGGVnZ+vpp5/WxRdfrLfeekvXXnttueWe7V7gO++8o7KyMm3cuFGXX355ucdzc3M9twRC3UaWYAtZgi1kCbaQpYq5Rs3ab06eMWdsk1ovAgAAADiXjM484Pk3v9QJAAAAOIiGHAAAAHAQDTkAAADgIBpyAAAAwEE05AAAAICDfPK2h2VlZfrhhx8UGhpaJ27mfq4xxqiwsFBxcXFq0MC39+nIkrPIEmwhS7CFLMGWymTJJxvyH374QfHx8U6Xcc7btWuXmjVr5nQZ1UKW6gayBFvIEmwhS7DlbLLkkw15aGiopOMbWNGvNaFmFRQUKD4+3vPfwZeRJWeRJdhClmALWYItlcmSTzbkJ067hIWFETAH1YfTX2SpbiBLsIUswRayBFvOJku+fXEUAAAA4ON88gj56Tz44INnfHzy5Mm1VAl8HVmCLWQJtpAl2EKW6h6OkAMAAAAOoiEHAAAAHERDDgAAADiIhhwAAABwEA05AAAA4CAacgAAAMBBNOQAAACAg2jIAQAAAAfRkAMAAFiUkZEhl8vlNcXGxnoeN8YoIyNDcXFxCg4OVq9evbR161avZRQVFemPf/yjoqKi1LBhQ1199dXavXt3bW8KagkNOQCfxgcfgLqoQ4cOysvL80ybN2/2PDZ9+nQ98cQTeuaZZ7Ru3TrFxsYqNTVVhYWFnjHjx4/XokWL9Prrr2vVqlU6fPiwBg4cqNLSUic2BzWMhhyAz+ODDzawcweb/P39FRsb65mio6MlHc/RjBkzdN9992nw4MHq2LGj5s6dqyNHjujVV1+VJB06dEgvvviiHn/8caWkpOiSSy7RK6+8os2bN+vDDz90crNQQ2jI4Qg++GATH3ywhZ072LJ9+3bFxcWpZcuWuvbaa/Xtt99KknJzc5Wfn6++fft6xrrdbvXs2VOrV6+WJG3YsEHHjh3zGhMXF6eOHTt6xlSkqKhIBQUFXhN8Aw05HMMHH2zhgw+2sHMHGy677DLNmzdP77//vubMmaP8/HwlJydr//79ys/PlyTFxMR4PScmJsbzWH5+vgIDAxUREXHaMRWZNm2awsPDPVN8fLzlLUNNqVRDzlFN2MQHH2zggw82sXMHG/r3768//OEPSkxMVEpKit555x1J0ty5cz1jXC6X13OMMeXmnerXxtx77706dOiQZ9q1a1c1tgK1qdJHyDmqCVv44IMNfPDBFnbuUFMaNmyoxMREbd++3XMg89RM7Nmzx5Ov2NhYFRcX6+DBg6cdUxG3262wsDCvCb6h0g05RzVhAx98qCl88KGq2LlDTSkqKtK2bdvUtGlTtWzZUrGxscrJyfE8XlxcrBUrVig5OVmSlJSUpICAAK8xeXl52rJli2cM6pdKN+Qc1YQNfPChpvDBB1vYuUNVpaena8WKFcrNzdWnn36qIUOGqKCgQCNGjJDL5dL48eM1depULVq0SFu2bNHIkSMVEhKi66+/XpIUHh6utLQ03X333froo4+0adMmDRs2zPOZifqnUg05RzVRU/jgQ1XxwYeaws4dqmr37t267rrr1LZtWw0ePFiBgYFau3atEhISJEkTJ07U+PHjNXbsWHXu3Fnff/+9PvjgA4WGhnqW8eSTT+qaa67R0KFDdfnllyskJESLFy+Wn5+fU5uFGuRfmcH9+/f3/DsxMVHdunVTq1atNHfuXHXt2lVSzR3VnDBhgufvgoICmvJ65sQHX/fu3b0++C655BJJ//fB97e//U2S9wff0KFDJf3fB9/06dMd2w7UvhMffPv27VN0dLS6du1a7oPvl19+0dixY3Xw4EFddtllFX7w+fv7a+jQofrll1/Up08fZWdn88F3jklPT9dVV12l5s2ba8+ePZoyZUqFO3dt2rRRmzZtNHXq1NPu3EVGRqpJkyZKT09n5+4c9Prrr5/xcZfLpYyMDGVkZJx2TFBQkGbOnKmZM2darg51UaUa8lOdfFTzmmuukXT8qGbTpk09Y053VPPko+R79uw549EDt9stt9tdnVJRx/DBB1v44IMt7NwBcEq1GnKOaqKq+OADUNewcwfAKZVqyDmqCVv44AMAADiuUg05RzUBAAAAuyrVkHNUEwAAALCr0vchBwAAAGAPDTkAAADgIBpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA6iIQcAAAAcREMOAAAAOIiGHAAAAHAQDTkAAADgIBpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA6iIQcAAAAcREMOAAAAOIiGHAAAAHAQDTkAAADgIBpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA6iIQcAAAAcREMOAAAAOIiGHAAAAHAQDTkAAADgIBpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA6iIQcAAAAcREMOAAAAOIiGHAAAAHAQDTkAAADgIBpyAAAAwEE05AAAAICDaMgBAAAAB9GQAwAAAA7yd7oAAAAAoK578MEHf3XM5MmTq7RsGnIAQJ1Tkx98AFDXcMkKAAAA4CCOkAMAgHqLsy3wBRwhBwAAABxEQw4AAAA4iEtWwOk8AAAAB9GQA7CGnTsAACqPS1YAAAAAB9GQAwAAAA6iIQcAAAAc5GhDnpmZqZYtWyooKEhJSUlauXKlk+XAh5El2EKWYAtZgi1kqf5z7EudCxYs0Pjx45WZmanLL79czz33nPr3768vv/xSzZs3d6os+CCyBFvIEmwhS7CFLNnxazcdcPqGA4415E888YTS0tI0atQoSdKMGTP0/vvva/bs2Zo2bZpTZfncXSLOpt76zoks2XrdbWSptmo5F7JWV7PEe47vOdc/43hfsqeuZqm2+Np7ZFU50pAXFxdrw4YN+vOf/+w1v2/fvlq9enW58UVFRSoqKvL8fejQIUlSQUGB17ijR4+ecb333ntvVUuukeX4kpNf6xP/NsY4VY6HU1mypS5lqbZqIUuVV5dyUpeQJW/18TOO9yXfzlJtsVGvrW2uapYcacj37dun0tJSxcTEeM2PiYlRfn5+ufHTpk2rcA8pPj6+xmqEt7/+9a/l5hUWFio8PNyBav4PWfI9ZAm2kCXYQpZgS1Wz5OgPA7lcLq+/jTHl5knH91omTJjg+busrEwHDhxQZGSkZ3xBQYHi4+O1a9cuhYWF1Wzh55hTX1tjjAoLCxUXF+d0aR5kyTeQJdhClmALWYIt1cmSIw15VFSU/Pz8yu3d7dmzp9xeoCS53W653W6veY0bN65w2WFhYQSshpz82jp91OAEsuSbyBJsIUuwhSzBlqpkyZHbHgYGBiopKUk5OTle83NycpScnOxESfBRZAm2kCXYQpZgC1k6dzh2ycqECRM0fPhwde7cWd26ddPzzz+vnTt36tZbb3WqJPgosgRbyBJsIUuwhSydGxxryP/nf/5H+/fv10MPPaS8vDx17NhRS5cuVUJCQpWW53a7NXny5HKnalB9df21JUu+o66/tmTJd9T115Ys+Y66/tqSJd9RndfWNWrWfq97scwZ28RaYQAAAADKG515wPNvR64hBwAAAHAcDTkAAADgIBpyAAAAwEE05AAAAICD6kVDnpmZqZYtWyooKEhJSUlauXKl0yXVC5988omuuuoqxcXFyeVy6e2333a6pBpHlmoGWSJLtpAlsmQLWSJLttjIks835AsWLND48eN13333adOmTerevbv69++vnTt3Ol2az/v555910UUX6ZlnnnG6lFpBlmoOWSJLtpAlsmQLWSJLttjIks/f9vCyyy7TpZdeqtmzZ3vmtWvXTtdcc42mTZvmYGX1i8vl0qJFi3TNNdc4XUqNIUu1gyyRJVvIElmyhSyRJVsqk6V6c9vD4uJibdiwQX379vWa37dvX61evdqhquCLyBJsIUuwhSzBFrJU9/l0Q75v3z6VlpYqJibGa35MTIzy8/Mdqgq+iCzBFrIEW8gSbCFLdZ9PN+QnuFwur7+NMeXmAWeDLMEWsgRbyBJsIUt1l0835FFRUfLz8yu3d7dnz55ye4HAmZAl2EKWYAtZgi1kqe7z6YY8MDBQSUlJysnJ8Zqfk5Oj5ORkh6qCLyJLsIUswRayBFvIUt3n73QB1TVhwgQNHz5cnTt3Vrdu3fT8889r586duvXWW50uzecdPnxYX3/9tefv3Nxcff7552rSpImaN2/uYGU1gyzVHLJElmwhS2TJFrJElmyxkqVRs/abkydfNGvWLJOQkGACAwPNpZdealasWOF0SfXC8uXLjaRy04gRI5wurcaQpZpBlsiSLWSJLNlClsiSLVXN0sn9t8/fhxwAAADwNfXmPuQAAACAr6MhBwAAABxEQw4AAAA4iIYcAAAAcBANOQAAAOAgGnIAAADAQTTkAAAAgINoyAEAAAAHnbMNeUZGhi6++GJry/v444/lcrn0008/WVtmRVwul95+++0aXQcqhyzBFrIEW8gSbCFLtaPeNuQjR46Uy+WSy+VSQECALrjgAqWnp+vnn3+WJKWnp+ujjz6qlVqKi4sVFRWlKVOmVPj4tGnTFBUVpeLi4lqpB5VDlmALWYItZAm2kKW6od425JJ05ZVXKi8vT99++62mTJmizMxMpaenS5IaNWqkyMjIWqkjMDBQw4YNU3Z2towx5R7PysrS8OHDFRgYWCv1oPLIEmwhS7CFLMEWsuS8et2Qu91uxcbGKj4+Xtdff71uuOEGz+mLk0/BHD16VB06dNAtt9zieW5ubq7Cw8M1Z84cSZIxRtOnT9cFF1yg4OBgXXTRRXrzzTfPupa0tDR98803+uSTT7zmr1y5Utu3b1daWprWrVun1NRURUVFKTw8XD179tTGjRtPu8yKTvt8/vnncrlc2rFjh2fe6tWr1aNHDwUHBys+Pl7jxo3z7PlKUmZmptq0aaOgoCDFxMRoyJAhZ71d5wqydBxZqj6ydBxZqj6ydBxZqj6ydJyTWarXDfmpgoODdezYsXLzg4KCNH/+fM2dO1dvv/22SktLNXz4cPXu3VujR4+WJN1///3KysrS7NmztXXrVt11110aNmyYVqxYcVbrTkxM1G9/+1tlZWV5zX/ppZfUpUsXdezYUYWFhRoxYoRWrlyptWvXqk2bNhowYIAKCwurvM2bN29Wv379NHjwYH3xxRdasGCBVq1apTvuuEOStH79eo0bN04PPfSQvvrqK7333nvq0aNHldd3riBLZMkWskSWbCFLZMkWsuRAlkbN2m9OnuqLESNGmEGDBnn+/vTTT01kZKQZOnSoMcaYyZMnm4suusjrOdOnTzdRUVHmj3/8o4mNjTV79+41xhhz+PBhExQUZFavXu01Pi0tzVx33XXGGGOWL19uJJmDBw+etqbZs2ebhg0bmsLCQmOMMYWFhaZhw4bmueeeq3B8SUmJCQ0NNYsXL/bMk2QWLVp02nVu2rTJSDK5ubnGGGOGDx9ubrnlFq/lrly50jRo0MD88ssv5q233jJhYWGmoKDgtHWf68hSrjGGLNlAlnKNMWTJBrKUa4whSzaQpVxjjDNZOrn/rtdHyJcsWaJGjRopKChI3bp1U48ePTRz5szTjr/77rvVtm1bzZw5U1lZWYqKipIkffnllzp69KhSU1PVqFEjzzRv3jx98803Z13Pddddp7KyMi1YsECStGDBAhljdO2110qS9uzZo1tvvVUXXnihwsPDFR4ersOHD2vnzp1Vfg02bNig7Oxsr7r79eunsrIy5ebmKjU1VQkJCbrgggs0fPhwzZ8/X0eOHKny+uorskSWbCFLZMkWskSWbCFLzmfJ39qS6qDevXtr9uzZCggIUFxcnAICAs44fs+ePfrqq6/k5+en7du368orr5QklZWVSZLeeecdnX/++V7PcbvdZ11PeHi4hgwZoqysLKWlpSkrK0tDhgxRWFiYpOPfdN67d69mzJihhIQEud1udevW7bTfJm7Q4Pj+lDnpiw+nnmIqKyvTmDFjNG7cuHLPb968uQIDA7Vx40Z9/PHH+uCDDzRp0iRlZGRo3bp1aty48VlvW31HlsiSLWSJLNlClsiSLWTJ+SzV64a8YcOGat269VmPv/nmm9WxY0eNHj1aaWlp6tOnj9q3b6/27dvL7XZr586d6tmzZ7VqSktLU69evbRkyRL961//0tSpUz2PrVy5UpmZmRowYIAkadeuXdq3b99plxUdHS1JysvLU0REhKTjX1I42aWXXqqtW7ee8XXw9/dXSkqKUlJSNHnyZDVu3FjLli3T4MGDq7qZ9Q5ZIku2kCWyZAtZIku2kCXns1SvG/LKmDVrltasWaMvvvhC8fHxevfdd3XDDTfo008/VWhoqNLT03XXXXeprKxMV1xxhQoKCrR69Wo1atRII0aMOOv19OzZU61bt9aNN96o1q1be30hoHXr1nr55ZfVuXNnFRQU6J577lFwcPBpl9W6dWvFx8crIyNDU6ZM0fbt2/X44497jfnTn/6krl276vbbb9fo0aPVsGFDbdu2TTk5OZo5c6aWLFmib7/9Vj169FBERISWLl2qsrIytW3btvIvIiSRJbJkD1kiS7aQJbJkC1mqoSydK1/qPNXJX1LYtm2bCQ4ONq+++qrn8UOHDpkWLVqYiRMnGmOMKSsrM0899ZRp27atCQgIMNHR0aZfv35mxYoVxpiz+5LCCVOnTjWSzNSpU73mb9y40XTu3Nm43W7Tpk0bs3DhQpOQkGCefPJJzxid9CUFY4xZtWqVSUxMNEFBQaZ79+5m4cKFXl9SMMaYzz77zKSmpppGjRqZhg0bmk6dOplHHnnEGHP8Cws9e/Y0ERERJjg42HTq1MksWLDgV7fhXEKWcj1jyFL1kKVczxiyVD1kKdczhixVD1nK9Yyp7Syd3H+7Rs3a73Xn9Tljm9jp9AEAAABUaHTmAc+/6/VdVgAAAIC6joYcAAAAcBANOQAAAOAgGnIAAADAQTTkAAAAgINoyAEAAAAH0ZADAAAADqIhBwAAABzkf+qMk29SDgAAAKBmcYQcAAAAcBANOQAAAOCg/w+6qooudaaLywAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAuQAAAGMCAYAAACS67fPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABLzklEQVR4nO3deViU9f7/8dewDYjgAgSiiCZqmmi5a+WSounXsjzW0dTQcOlYmRVZ/azEMv0eO5XlEU/HDNfcMjsnM8vSSHPJrZNpV1liaol7gpog8Pn94XG+jrgBN94z8Hxc131dzmfu5T3Tq3vec9/33DgGTzliBAAAAMAWPnYXAAAAAJRnNOQAAACAjfwuHJg2vKoddQAAAADlxpDUo65/c4QcAAAAsBENOQAAAGAjGnIAAADARjTkAAAAgI1oyAEAAAAb0ZADAAAANqIhB1AmzZgxQw6H46JTcnLyVa9n9+7dcjgcmjFjRukVe4ltnpt8fHwUFham7t27a926daWyzQ4dOqhDhw6ux6dOnVJKSoq++OKLQvOee293795dKrUAQHlT6D7kAFCWpKWl6YYbbnAbi46Otqmaonn00Ud1//33Kz8/X9u3b9fYsWPVsWNHrVu3TjfffLOl20pNTXV7fOrUKY0dO1aS3Bp1Sfqf//kfrVu3TtWqVbO0BgAor2jIAZRpjRo1UvPmze0uo1hq1qyp1q1bS5JuueUWxcXFqVOnTkpNTdW0adMs3VbDhg2vet6IiAhFRERYun0AKM+4ZAVAufTTTz9p0KBBqlu3ripUqKDq1avrzjvv1LZt26647KFDhzR06FDFxMTI6XQqIiJCt9xyiz777DO3+T777DN16tRJoaGhqlChgm655RZ9/vnnxa75XHP+yy+/uMbeeecdNWnSRIGBgapataruueceff/9927L7dq1S3369FF0dLScTqciIyPVqVMnffPNN655zr9kZffu3a6Ge+zYsa5LZwYOHCip8CUrI0eOVHBwsLKysgrV/Oc//1mRkZE6c+aMa2zBggVq06aNgoODVbFiRXXt2lVbt24tcs0AUFbQkAMo0/Lz85WXl+c2SdJvv/2msLAw/e///q+WL1+uKVOmyM/PT61atdIPP/xw2XUOGDBAH3zwgV544QV9+umnevvtt9W5c2cdOXLENc+cOXPUpUsXhYaGaubMmVq4cKGqVq2qrl27Frsp/+mnnyTJ1SxPmDBBSUlJuvHGG/X+++/rjTfe0Lfffqs2bdpo586druW6d++uzZs3a+LEiVqxYoWmTp2qm2++Wb///vtFt1OtWjUtX75ckpSUlKR169Zp3bp1ev755y86/4MPPqhTp05p4cKFbuO///67/vWvf6l///7y9/eXJI0fP159+/ZVw4YNtXDhQs2ePVvZ2dm67bbbtGPHjmLXDABebfCUI+b8CQDKgrS0NCPpotOZM2cKzZ+Xl2dyc3NN3bp1zeOPP+4az8jIMJJMWlqaa6xixYpm5MiRl9z2yZMnTdWqVc2dd97pNp6fn2+aNGliWrZsednaz23zr3/9qzlz5ow5ffq02bx5s2nRooWRZD766CNz7NgxExQUZLp37+627J49e4zT6TT333+/McaYw4cPG0lm0qRJl91m+/btTfv27V2PDx06ZCSZMWPGFJr33HubkZHhGmvatKlp27at23ypqalGktm2bZurNj8/P/Poo4+6zZednW2ioqLMfffdV6SaAcCbnd9/cw05gDJt1qxZatCggduYn5+f8vLyNHHiRM2ZM0c//fST2yUVF17ycaGWLVtqxowZCgsLU+fOndWsWTPXEWBJWrt2rY4eParExETXEflz7rjjDk2cOFEnT55UcHDwZbfz9NNP6+mnn3Y9joyM1FtvvaXu3bvr448/1h9//OG6jOScmJgY3X777a6j8FWrVlWdOnX0yiuvKD8/Xx07dlSTJk3k42PtCdJBgwbp0Ucf1Q8//KD69etLOvuD2hYtWqhRo0aSpE8++UR5eXl64IEH3N6XwMBAtW/fXqtWrbqmNQOAp2DvBqBMa9CggZo3b+42SdITTzyh559/Xnfffbc+/PBDbdiwQRs3blSTJk30xx9/XHadCxYsUGJiot5++221adNGVatW1QMPPKDMzExJ0oEDByRJvXv3lr+/v9v017/+VcYYHT169Iq1P/bYY9q4caM2b96sn3/+Wfv379fQoUMlyXV5zMXudBIdHe163uFw6PPPP1fXrl01ceJENW3aVBERERoxYoSys7Ov8l28sn79+snpdLpuD7ljxw5t3LhRgwYNcs1z7n1p0aJFofdlwYIFOnz48DWtGQA8BUfIAZRLc+bM0QMPPKDx48e7jR8+fFiVK1e+7LLh4eGaNGmSJk2apD179ujf//63nnnmGR08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r/Xr1+vWW291ja9Zs0aSdOTIkWLVitLliVliv+SdPDFLF/r999/1/vvvKyEhwbUNeB5PzJIn75c4Ql5EVapUKXa4JGnp0qXq2LGjoqOjlZeX55rOXSKQnp7umnf69OnKy8tTbGzsZddZUFAgSapRo4YWL16srl27qlevXlq+fLl8fHw0ceLEYteL0uOJWerXr5+qVq2qoUOHasOGDfr99981b9481485OTXsmTwxS+yXvJMnZulCc+fO1enTpzV48OBi14nS54lZ8uT9EkfIi6hatWolWv7AgQP68MMPC10ScM7hw4eLvM6wsDBJUufOneXr6+sar1atmpo0aaItW7YUr1iUKk/MUnh4uJYvX67ExETXD3TCwsL02muvKSkpSdWrVy9RzSgdnpgl9kveyROzdKHp06crIiJCPXv2LPG6UHo8MUuevF+iIS+iS50OcTqdysnJKTR+4Sn+8PBwNW7cWC+//PJF1xMdHV3kmi53esUYw1FND+WJWZKkFi1aaMeOHdq9e7dOnjypunXravPmzZKkdu3aFWudKF2emCX2S97JE7N0vq1bt2rr1q168sknL9mowTN4YpY8eb9EQ26RWrVqFfrB28qVK3XixAm3sR49emjZsmWqU6eOZb/wbdWqlWrUqKFPP/1U+fn5rm99v/32m/7zn//o/vvvt2Q7uDbszNKFdUhnd1KvvvqqoqOjde+991q+HZQe9kuwiqfsl6ZPny5JSkpKsnzduDbYL10chygsMmDAAH388cd64YUX9Pnnn2vy5Mn6y1/+okqVKrnN9+KLL8rf319t27bV1KlTtXLlSi1btkypqanq0aOH9u3b55o3KSlJfn5++uWXXy67bR8fH73++uv64Ycf1LNnT3300UdauHChunbtqoCAAD377LOl8ppROuzMkiSNHj1a8+fPV3p6umbPnq3bb79dy5Yt05w5cxQUFGT560XpYb8Eq9i9X5Kk06dP691331Xbtm3VoEEDS18frh32SxfHEXKLPPXUU8rKytKMGTP0t7/9TS1bttTChQsLXeNWrVo1bdq0SS+99JJeeeUV7du3TyEhIapdu7buuOMOt2+B+fn5ys/PlzHmitvv3bu3lixZopdfflm9e/eW0+lU+/bttWDBAtWpU8fy14vSY3eWjh07pqefflqZmZkKDQ1V+/bttWHDBsXHx1v+WlG67M4S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6tGjh/Lz8+14ObARWQLgSThQgKIqUkNOwGAlPz8/RUVFuaaIiAhJZ3M0adIkjR49Wr169VKjRo00c+ZMnTp1Su+++64k6fjx45o+fbpeffVVde7cWTfffLPmzJmjbdu26bPPPrvkNnNycpSVleU2wfvZkSUAuBwOFKAoinyEnIDBKjt37lR0dLRq166tPn36aNeuXZKkjIwMZWZmqkuXLq55nU6n2rdvr7Vr10qSNm/erDNnzrjNEx0drUaNGrnmuZgJEyaoUqVKrikmJqaUXh2uJTuyxJe7soeDTrASBwpQFEVuyAkYrNCqVSvNmjVLn3zyiaZNm6bMzEy1bdtWR44cUWZmpiQpMjLSbZnIyEjXc5mZmQoICFCVKlUuOc/FPPvsszp+/Lhr2rt3r8WvDNeaXVniy13ZxEEnWIUDBSiKIjfkBAxW6Natm/70pz8pPj5enTt31kcffSRJmjlzpmseh8PhtowxptDYha40j9PpVGhoqNsE72ZXlvhyVzZxKR2swIECFFWRGnIChtISHBys+Ph47dy503WK+MJMHDx40JWvqKgo5ebm6tixY5ecB+XTtcoSX+7KJi6lgxU4UICiKlJDTsBQWnJycvT999+rWrVqql27tqKiorRixQrX87m5uUpPT1fbtm0lSc2aNZO/v7/bPPv379d3333nmgflE1lCcXEpHUoLBwpwJSW67SEBQ3ElJycrPT1dGRkZ2rBhg3r37q2srCwlJibK4XBo5MiRGj9+vJYsWaLvvvtOAwcOVIUKFXT//fdLkipVqqSkpCQ9+eST+vzzz7V161b179/f9WUR5QdZglW4lA6lhQMFuBK/kix8LmC33XabW8BuvvlmSf8XsL/+9a+S3AN23333Sfq/gE2cOLGELwXeZN++ferbt68OHz6siIgItW7dWuvXr1dsbKwkadSoUfrjjz80fPhwHTt2TK1atdKnn36qkJAQ1zpef/11+fn56b777tMff/yhTp06acaMGfL19bXrZcEGZAml5fyDTnfffbekswedqlWr5prnUgedzj9KfvDgQZqociY5OVl33nmnatasqYMHD2rcuHEXPVBQt25d1a1bV+PHj7/kgYKwsDBVrVpVycnJHCgow4rUkBMwWGX+/PmXfd7hcCglJUUpKSmXnCcwMFCTJ0/W5MmTLa4O3oQsobRw0AnFxYECFFWRGnIC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Tzniduf1acOrWtPpAwAAALioIalHXf8u03dZAQAAADwdDTkAAABgIxpyAAAAwEY05AAAAICNaMgBAAAAG9GQAwAAADaiIQcAAABsREMOAAAA2IiGHAAAALARDTkAAABgIxpyAAAAwEY05AAAAICNaMgBAAAAG9GQAwAAADaiIQcAAABsREMOAAAA2IiGHAAAALARDfl/ORyOq5q++OILu0u9qKysLI0ePVr16tVThQoVVL16dd17773avn273aWVO96epVmzZqlPnz6qX7++fHx8VKtWLbtLKre8PUuDBw9Wo0aNVLlyZQUFBalevXp66qmndPjwYbtLK3e8PUt8xnkOb89Sdna2RowYoerVq8vpdKpevXqaOHGi8vPzba3Lz9ate5B169a5PX7ppZe0atUqrVy50m28YcOG17Ksq3bnnXdq06ZNSklJUfPmzbVv3z69+OKLatOmjbZt26bY2Fi7Syw3vD1Ls2fPVmZmplq2bKmCggKdOXPG7pLKLW/P0smTJzV06FDFxcUpMDBQmzZt0ssvv6xly5Zp69atCggIsLvEcsPbs8RnnOfw5izl5eUpISFBP/74o1566SXVq1dPy5cv1zPPPKN9+/bpzTfftK02GvL/at26tdvjiIgI+fj4FBq/0KlTp1ShQoXSLO2KfvrpJ3355Zd67rnn9NRTT7nG4+Li1LZtW73//vt6/PHHbaywfPHmLEnSJ598Ih+fsyfPevTooe+++87misovb8/SvHnz3B7ffvvtCgkJ0fDhw7VmzRrdfvvtNlVW/nhzlviM8yzenKX33ntPGzZs0OLFi9WrVy9JUkJCgk6cOKEpU6bo4YcfVv369W2pjUtWiqBDhw5q1KiRvvzyS7Vt21YVKlTQgw8+KOnsKZyUlJRCy9SqVUsDBw50G8vMzNSwYcNUo0YNBQQEqHbt2ho7dqzy8vKKVZe/v78kqVKlSm7jlStXliQFBgYWa70oPZ6aJUmuZhzewZOzdDERERGSJD8/jgd5Gk/NEp9x3sdTs/TVV1/J4XCoW7dubuM9evRQQUGBlixZUqz1WoE9YhHt379f/fv316hRozR+/PgiNy/nLgXw8fHRCy+8oDp16mjdunUaN26cdu/erbS0NNe8AwcO1MyZM5WRkXHZ63hjY2PVs2dPvf7662rWrJlatGihffv2acSIEapZs6b69OlT3JeLUuSJWYJ38vQs5eXlKScnR998842ef/553XrrrbrllluKVCOuDU/MEp9x3skTs5SbmysfHx/Xl7xznE6nJOnbb78tUo1WoiEvoqNHj2rRokXFPtWakpKiY8eOafv27apZs6YkqVOnTgoKClJycrKeeuop13VXvr6+8vX1lcPhuOJ6Fy1apIcfftitrsaNGys9PV1VqlQpVq0oXZ6aJXgfT87S+vXr1aZNG9fj7t27a/78+fL19S1WrShdnpolPuO8jydmqWHDhsrPz9f69et16623usbXrFkjSTpy5EixarUC56aLqEqVKiW67nHp0qXq2LGjoqOjlZeX55rOnT5JT093zTt9+nTl5eVd1Y9V/vKXv2jx4sV6/fXXlZ6ergULFiggIEC33367fvnll2LXi9LjqVmC9/HkLMXHx2vjxo1KT0/XG2+8oa1btyohIUGnTp0qdr0oPZ6aJT7jvI8nZqlfv36qWrWqhg4dqg0bNuj333/XvHnzXD/mtPOSTY6QF1G1atVKtPyBAwf04YcfFjpdck5xbge2fPlyTZ8+XYsWLVLv3r1d4126dFGtWrWUkpLidmoHnsETswTv5MlZCg4OVvPmzSVJ7dq1U6tWrdS6dWu99dZb/BDPA3lilviM806emKXw8HAtX75ciYmJrh+hhoWF6bXXXlNSUpKqV69eoppLgoa8iC51OsTpdConJ6fQ+IWnP8LDw9W4cWO9/PLLF11PdHR0kWv65ptvJEktWrRwG69cubLi4uK4S4aH8sQswTt5U5aaN28uHx8f/fjjj5atE9bxxCzxGeedPDFL0tkc7dixQ7t379bJkydVt25dbd68WdLZgwZ2oSG3SK1atQr9GGDlypU6ceKE21iPHj20bNky1alTx7Lr3s6Fcv369W6na44cOaIff/xRnTp1smQ7uDbszBLKFk/MUnp6ugoKChQXF1eq24G1+IyDVTxlv3Tux5/GGL366quKjo7Wvffea/l2rhbXkFtkwIAB+vjjj/XCCy/o888/1+TJk/WXv/yl0G2aXnzxRfn7+6tt27aaOnWqVq5cqWXLlik1NVU9evTQvn37XPMmJSXJz8/vitfH9erVS7GxsfrLX/6iV199VatWrdK7776rzp0769SpU3rsscdK5TWjdNiZJUnasWOH3nvvPb333nvKzMzUqVOnXI937Nhh+etF6bEzS0uX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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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kSNHKjw8XL169SpUrQDgLmjIAeC/oqKi9MMPP7iMrVq1SqdOnXIZ69atm5YuXapatWqpYsWKlrz3uHHj9PHHH2vMmDG5nsvr+7Vt21bz58/XsmXLnKezSNLcuXNd5nM4HDLGyM/Pz2X8n//8p7Kzs13GLs6T16PmXl5e6t+/vyZPnqx169Zp06ZNuc5f79atm+bOnavs7Gy1aNEiz8tt0aKF6tatq9mzZ2vz5s005ABKDBpyAPiv/v376+WXX9Yrr7yitm3baufOnXrnnXdUoUIFl/leffVVrVy5UjExMRoxYoTq1Kmjc+fOac+ePVq6dKneffddValSJV/vXaNGDT366KNXPB0jr+83YMAATZo0Sf369dO4ceMUHR2tZcuWacWKFZLkvJtM+fLl1aZNG7355psKDQ1VVFSUUlJSNGPGDAUHB7u8d/369SVJ77//voKCguTv768aNWooJCTkqusyePBgvf766+rTp48CAgJy3eWlV69emj17tu688049+eSTat68uXx8fLR//36tXr1a3bt313333ad3331Xq1at0l133aVq1arp3Llz+uCDDyRJHTp0yNf2BQB3xjnkAPBfo0aNct4l5O6779bChQs1f/78XE1q5cqVtWnTJnXq1ElvvvmmunTpov79++uDDz5Q48aNC3zU/KWXXlL58uVzjef1/QIDA5337R49erTuv/9+7d27V4mJiZLksh5z5sxR+/btNXr0aPXo0UObNm3SypUrc335qFGjhiZPnqz//Oc/ateunW699VZ99tln11yPG2+8UTExMdq/f7969OiRa5leXl769NNP9cILL+iTTz7Rfffdp3vvvVevvfaa/P391aBBA0kXTuXJyspSfHy8unbtqv79++vPP//Up59+qk6dOuV7+wKAu3IMmXrUXDowfXglu2oBABSBCRMm6KWXXtLevXvzfeQeAFA0hib+3zU7nLICACXIO++8I0mqW7euzp8/r1WrVukf//iH+vXrRzMOAG6KhhwASpCyZctq0qRJ2rNnjzIyMlStWjU9++yzeumll+wuDQBwFTTkAFCCDB48WIMHD7a7DABAPnBRJwAAAGAjGnIAAADARjTkAAAAgI1oyAEAAAAb0ZADAAAANqIhBwAAAGxEQw4AAADYiIYcAAAAsBENOQAAAGAjGnIAAADARjTkAAAAgI1oyAEAAAAb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UlLy9N4NGjTQrbfeqqSkJJfxDz74QM2bN1f9+vWVnp6uAQMGaN26ddqwYYNq166tO++8U+np6QVe523btqlz587q0aOHfvjhB82bN09ff/21Hn/8cUnSpk2bNGLECL366qv66aeftHz5crVp06bA71dakCWyZBWyRJasQpbIklXIkg1ZGjL1qLl0KikGDBhgunfv7nz87bffmpCQEPPggw8aY4yJj483jRo1cnnNG2+8YUJDQ80TTzxhIiIizJ9//mmMMebUqVPG39/frF+/3mX+2NhY07t3b2OMMatXrzaSzPHjx69a07Rp00xgYKBJT083xhiTnp5uAgMDzXvvvXfF+bOyskxQUJD57LPPnGOSzKJFi676nlu2bDGSzO7du40xxvTv3988/PDDLstdt26dKVOmjDl79qxZuHChKV++vElLS7tq3aUdWdptjCFLViBLu40xZMkKZGm3MYYsWYEs7TbG2JOlS/vvEn2EfMmSJSpXrpz8/f3VqlUrtWnTRlOmTLnq/M8884zq1KmjKVOmKCkpSaGhoZKknTt36ty5c+rYsaPKlSvnnGbNmqVff/01z/X07t1bOTk5mjdvniRp3rx5MsaoV69ekqTDhw/rkUce0Y033qgKFSqoQoUKOnXqlPbu3VvgbfD9998rOTnZpe7OnTsrJydHu3fvVseOHVW9enXVrFlT/fv31+zZs3XmzJkCv19JRZbIklXIElmyClkiS1YhS/ZnyduyJbmh9u3ba9q0afLx8VFkZKR8fHyuOf/hw4f1008/ycvLS7t27VKXLl0kSTk5OZKkzz//XDfccIPLa/z8/PJcT4UKFdSzZ08lJSUpNjZWSUlJ6tmzp8qXLy/pwpXOf/75pyZPnqzq1avLz89PrVq1uurVxGXKXPg+ZS658OHyn5hycnI0bNgwjRgxItfrq1WrJl9fX23evFlr1qzRF198oVdeeUUJCQnauHGjgoOD87xuJR1ZIktWIUtkySpkiSxZhSzZn6US3ZAHBgYqOjo6z/MPHjxY9evX19ChQxUbG6s77rhDN910k2666Sb5+flp7969atu2baFqio2NVbt27bRkyRL9+9//1oQJE5zPrVu3TomJibrzzjslSfv27dORI0euuqywsDBJ0sGDB1WxYkVJFy5SuNQtt9yiHTt2XHM7eHt7q0OHDurQoYPi4+MVHBysVatW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dal++vBKdtUCAAAAlApDE485/80pKwAAAICNaMgBAAAAG9GQAwAAADaiIQcAAABsREMOAAAA2IiG/L+Sk5PlcDick7e3t6pUqaJBgwbpjz/+KJYaoqKiNHDgwAK9NiEhwaX+y6e5c+daWyyuytOzdNH27dv1wAMPKCwsTH5+foqKitLw4cOtKRB5UlKydNGXX37pXBcr/4Q6rs/Ts7Rnzx72b27C07O0b98+3XfffapZs6YCAwNVoUIFNWnSRO+8846ysrKsLTQfuA/5ZZKSklS3bl2dPXtWa9eu1cSJE5WSkqJt27YpMDDQ7vKuasiQIerSpUuu8aFDh+rXX3+94nMoWp6aJUlavXq17rrrLrVu3VrvvvuuQkNDtXfvXm3ZssXu0kolT87SRadOndLQoUMVGRmpAwcO2F1OqeXpWXriiSdy/cXg2rVr21RN6eapWTp9+rTKly+vl19+WdWqVVNmZqaWLl2qJ554Qlu3btU///lPW+qiIb9M/fr11axZM0lS+/btlZ2drbFjx2rx4sXq27fvFV9z5swZlS1btjjLzKVKlSqqUqWKy9iePXu0Y8cO9e3bV8HBwfYUVop5apbOnDmjvn376vbbb9dnn30mh8PhfK5///42VlZ6eWqWLvXcc8+pYsWKuuuuuzRu3Di7yym1PD1L1apVU8uWLe0uA/LcLNWtW1czZ850GevatasOHz6smTNnaurUqfLz8yv2ujhl5Tou/o9/8c+xDhw4UOXKldO2bdvUqVMnBQUF6Y477pAkZWZmaty4capbt678/PwUFhamQYMG6c8//3RZ5vnz5zV69GhFRESobNmy+stf/qLvvvvO8to/+OADGWP4y51uwlOytGDBAh08eFCjRo1yacbhPjwlSxetW7dO77//vv75z3/Ky8vLkmXCGp6WJbgvT89SWFiYypQpY9tnFEfIr+OXX36RdOE/1EWZmZm65557NGzYMD333HPKyspSTk6OunfvrnXr1mn06NGKiYnR77//rvj4eLVr106bNm1SQECApAunkcyaNUtxcXHq2LGjtm/frh49eig9PT3X+0dFRUm6cLQ7P3JycpScnKzo6Gi1bdu2YCsPS3lKltauXSvpwp8ivvjhFxgYqC5duujtt99WZGSkBVsDheEpWZKks2fPKjY2ViNHjtQtt9yiTz/9tPAbAJbxpCxJ0muvvaYX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2FGOC3fOUmnLSV5duq3JUsnMSXGtE1nKv5KYNyuUlCxJectTXrJkRVbcKW/u/rlkS0N+5MgRZWdnKzw83GU8PDxcqampueafOHHiFb/9VK1atchqxP957bXXrjienp6uChUqFHM1rsiS57lSnsgSCoIswSolJUsSebJbQbNk6x8GcjgcLo+NMbnGpAvfap5++mnn45ycHB07dkwhISHO+dPS0lS1alXt27dP5cuXL9rCS5ErbVdjjNLT0xUZGWlzdf+HLHmGy7ctWUJBkSVYpSRlSbp+nshS0SlMlmxpyENDQ+Xl5ZXr293hw4dzfQuUJD8/P/n5+bmMBQcHX3HZ5cuXJ2BF4PLtavdRg4vIkme6dNuSJRQGWYJVSkKWpLzniSwVnYJkyZbbHvr6+qpp06ZauXKly/jKlSsVExNjR0nwUGQJViFLsApZglXIUulh2ykrTz/9tPr3769mzZqpVatWev/997V371498sgjdpUED0WWYBWyBKuQJViFLJUOtjXkDz30kI4ePapXX31VBw8eVP369bV06VJVr169QMvz8/NTfHx8rp9pUDiesF3Jkudw921LljyHu29bsuQ53H3bkiXPUZht6xgy9ajLvVimD69kWWEAAAAAchuaeMz5b1vOIQcAAABwAQ05AAAAYCMacgAAAMBGNOQAAACAjUpEQ56YmKgaNWrI399fTZs21bp16+wuqURYu3at7r77bkVGRsrhcGjx4sV2l1TkyFLRIEtkySpkiSxZhSyRJatYkSWPb8jnzZunkSNH6sUXX9SWLVvUunVrde3aVXv37rW7NI93+vRpNWrUSO+8847dpRQLslR0yBJZsgpZIktWIUtkySpWZMnjb3vYokUL3XLLLZo2bZpzrF69err33ns1ceJEGysrWRwOhxYtWqR7773X7lKKDFkqHmSJLFmFLJElq5AlsmSV/GSpxNz2MDMzU99//706derkMt6pUyetX7/epqrgicgSrEKWYBWyBKuQJffn0Q35kSNHlJ2drfDwcJfx8PBwpaam2lQVPBFZglXIEqxClmAVsuT+PLohv8jhcLg8NsbkGgPygizBKmQJViFLsApZcl8e3ZCHhobKy8sr17e7w4cP5/oWCFwLWYJVyBKsQpZgFbLk/jy6Iff19VXTpk21cuVKl/GVK1cqJibGpqrgicgSrEKWYBWyBKuQJffn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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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6FFlZ2drxowZefbn4pCWi498fO655/Tqq69q06ZN6t27t0JCQtStWzd9++23ReofAJQljCEHUK5dHHM9efJkt/YjR46oatWqV31vaGiopk2bpmnTpmn//v36+OOP9eyzz+rQoUP69NNPFRoaKkmaMWPGFZ8ykl9RfDUTJ07UnDlz9Je//MVVuF7an4Js7/z583I4HPmOF7/4ZeKipUuX6tSpU/rXv/6lOnXquNq3b99eqH7nZ+TIkVq8eLFWr16t2rVra/PmzZo1a5ZrfrVq1eTl5aVhw4bpkUceyXcd9erVk3ThfoBx48Zp3Lhx+v333/X555/rL3/5i3r27KkDBw7I39+/2P0FALtQkAMo1xwOh5xOp1vbJ598ol9++UUNGjQo8Hpq166tRx99VF988YX+/e9/S5JuueUWVa1aVd9//70effRRS/obEhKiZ555RhMmTMgz3KWg2/P19VXr1q21dOlSvfrqq65hKydPntTy5cvdlr34pJRLPyNjjN59990863U6nYU6Y96jRw/VrFlTSUlJql27tipXrqx77rnHNd/f319du3bVtm3b1KJFC7fhNVdTtWpVDRw4UL/88ovGjh2rn3/+WU2bNi1wvwCgrKEgB1Cu9enTR8nJyWrcuLFatGihLVu26JVXXvnDH7E5ceKEunbtqnvvvVeNGzdWYGCgNm/e7Hp6iXRhTPaMGTM0fPhwHTt2TAMHDtQ111yjw4cP6z//+Y8OHz7sdka4oMaOHauZM2dq5cqVbu2F2d6LL76oO+64Qz179tQTTzyhnJwcvfLKK6pSpYrbMJro6Gj5+vrqnnvu0fjx43X27FnNmjVLx48fz9Ov5s2b61//+pdmzZqlVq1aqVKlSld99ruXl5fuu+8+vf766woKCtKAAQMUHBzstsz06dN16623qmPHjnr44YdVt25dZWZmau/evVq2bJnWrFkjSerbt6/rWfNhYWHat2+fpk2bpjp16qhhw4aF/owBoCyhIAdQrk2fPl0+Pj6aMmWKTp48qZtuukn/+te/NHHixKu+r3Llymrbtq3mz5+vn3/+WefPn1ft2rX1zDPPaPz48a7lhg4dqtq1a2vq1KkaPXq0MjMzdc011+iGG27QiBEjitRnf39/xcfH68EHH8wzr6Db69Wrl5YsWaIXXnhBf/7znxUREaExY8bo119/1fz5813LNW7cWEuWLNHEiRM1YMAAhYSE6N5779W4cePUu3dvt20/8cQT2rVrl/7yl7/oxIkTMsbIGHPVfRk5cqSmTJmiw4cPu27mvFTTpk21detWvfTSS5o4caIOHTqkqlWrqmHDhq5x5JLUtWtXLVmyRO+9954yMjIUERGh6OhoPf/882X6100BoCAcD8w86nY0fXdMdbv6AgAoQefPn9cNN9ygmjVratWqVXZ3BwAqtFGJ/3e1kjPkAFBOxcTEKDo6WjVq1FB6erreeust7d69m1+3BIAyhoIcAMqpzMxMxcbG6vDhw/Lx8dFNN92kFStWqHv37nZ3DQBwCQpyACinPvjgA7u7AAAoAH4YCAAAALARBTkAAABgIwpyAAAAwEYU5AAAAICNKMgBAAAAG1GQAwAAADaiIAcAAABsREEOAAAA2IiCHAAAALARBTkAAABgIwpyAAAAwEYU5AAAAICNKMgBAAAAG1GQAwAAADaiIAcAAABsREEOAAAA2IiCHAAAALARBTkAAABgIwpyAAAAwEYU5AAAAICNKMgBAAAAG1GQ/y+Hw1Ggad26dXZ3NY+0tDRNnDhR7du3V2hoqIKCgtSqVSu98847ysnJsbt7FQ5ZglXIEqxClmAVslQyvG3dehny1Vdfub1+6aWXtHbtWq1Zs8atvWnTpqXZrQLZsmWL5s2bp/vuu0/PP/+8fHx8tHLlSj388MPatGmT5syZY3cXKxSyBKuQJViFLMEqZKlkOB6YedRc2vDumOp29aVMGTFihD788EOdPHnyqsudPn1a/v7+pdSr/B0/flxVqlSRj4+PW/ujjz6qmTNnav/+/YqKirKpdyBLsApZglXIEqxClopuVOIx178ZslIIXbp0UbNmzbR+/Xp16NBB/v7+uv/++yVduIQTHx+f5z1169bViBEj3NrS09M1evRo1apVS76+vqpXr54mTZqk7OzsIvWrWrVqecIlSW3atJEkHTx4sEjrRckhS7AKWYJVyBKsQpYKjyErhZSWlqahQ4dq/Pjxmjx5sipVKtx3mvT0dLVp00aVKlXSCy+8oPr16+urr75SQkKCfv75ZyUlJbmWHTFihObOnavU1FTVrVu30H1ds2aNvL29dd111xX6vSh5ZAlWIUuwClmCVchS4VCQF9KxY8e0ePFi3XbbbUV6f3x8vI4fP65du3apdu3akqRu3brJz89PsbGxevrpp13jrry8vOTl5SWHw1Ho7axatUrz58/XE088oZCQkCL1FSWLLMEqZAlWIUuwClkqHIasFFK1atWKHC5JWr58ubp27arIyEhlZ2e7pt69e0uSUlJSXMvOnj1b2dnZqlOnTqG2sXXrVg0aNEjt2rXTlClTitxXlCyyBKuQJViFLMEqZKlwOENeSDVq1CjW+3/77TctW7Ys3zFMknTkyJFirX/btm2Kjo5Ww4YNtWLFCjmdzmKtDyWHLMEqZAlWIUuwClkqHAryQrrS5RCn06lz587laT969Kjb69DQULVo0UIvv/xyvuuJjIwsct+2bdum7t27q06dOlq1apWCg4OLvC6UPLIEq5AlWIUswSpkqXAoyC1St25dfffdd25ta9asyfMYoD59+mjFihWqX7++qlWrZtn2t2/fru7du6tWrVpavXq1petG6SJLsApZglXIEqxClvLHGHKLDBs2TCtXrtQLL7ygL774QjNmzNDDDz+c51vXiy++KB8fH3Xo0EGzZs3SmjVrtGLFCiUmJqpPnz5uj9yJiYmRt7e39u3bd9Vt//DDD+revbsk6eWXX9aePXu0adMm13T48GHrdxglhizBKmQJViFLsApZyh9nyC3y9NNPKyMjQ8nJyXr11VfVpk0bffDBB+rXr5/bcjVq1NC3336rl156Sa+88ooOHjyowMBA1atXT7169XL7ppaTk6OcnBwZYy7fnJuvvvrKdamnb9++eeYnJSXlebYnyi6yBKuQJViFLMEqZCl//FInAAAAUMr4pU4AAACgjKAgBwAAAGxEQQ4AAADYiIIcAAAAsBEF+f9KTk6Ww+FwTd7e3qpVq5ZGjhypX375pVT6ULdu3WLf3btz50796U9/UlhYmJxOp+rWrasxY8ZY00EUSHnJ0kWff/65a1+K+8toKJzykiWOS/YrL1m6iOOSfcpDliZOnKg+ffqoZs2acjgcZeIpPTz28DJJSUlq3Lixzpw5o/Xr12vKlClKSUnRjh07FBAQYHf3rmrt2rW644471LFjR7311lsKDQ3V/v37tW3bNru7ViF5cpYuOnnypEaNGqXIyEj9+uuvdnenwvLkLHFcKls8OUsXcVwqGzw5S2+88YZatGihO++8U3PmzLG7O5IoyPNo1qyZWrduLUnq2rWrcnJy9NJLL2np0qUaMmRIvu85ffq0/P39S7Ob+fZh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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "if n_tp > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_TruePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayHistogramConfusion(x_tra_tp,\n",
+ " y_true_tra_tp,\n",
+ " y_choice_tra_tp,\n",
+ " title_main=\"True Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_fp > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_FalsePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayHistogramConfusion(x_tra_fp,\n",
+ " y_true_tra_fp,\n",
+ " y_choice_tra_fp,\n",
+ " title_main=\"False Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_tn > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_TrueNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayHistogramConfusion(x_tra_tn,\n",
+ " y_true_tra_tn,\n",
+ " y_choice_tra_tn,\n",
+ " title_main=\"True Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_fn > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_FalseNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayHistogramConfusion(x_tra_fn,\n",
+ " y_true_tra_fn,\n",
+ " y_choice_tra_fn,\n",
+ " title_main=\"False Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 9: Histograms of the pixel flux values for the images shown in Figure 7. Here, it is difficult to infer reasons for network classification errors like false positives and false negatives. If it is expected that a particular would have a particular distribution of pixel brightnesses, but the histogram for the predicted digit has a different distribution, that may help you identify a pattern. This may be a more useful diagnostic for physics-related data, like galaxy light profiles."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 4.3.4.3. Investigate morphological features of images with feature maps"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The last diagnostic of this tutorial is the `feature map`, which shows how that one layer affects or processes the input image after the weights have been set during the model training. The morphological elements in the feature maps are \n",
+ "\n",
+ "The feature map is obtained by passing an input image through one layer of the trained neural network model. More specifically, we first choose an input datum (image) by setting the array index of interest. Then, we make the image a `tensor` with the appropriate number of dimensions using `unsqueeze`. Then, we transfer it to the `device`. Next, we choose the `conv1` layer defined the section above where we defined the `model`. Finally, we use the number of convolutional kernels (32) that exist in the `conv1` layer of the model. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-02-09T23:13:50.809088Z",
+ "iopub.status.busy": "2025-02-09T23:13:50.808737Z",
+ "iopub.status.idle": "2025-02-09T23:13:55.192290Z",
+ "shell.execute_reply": "2025-02-09T23:13:55.191710Z",
+ "shell.execute_reply.started": "2025-02-09T23:13:50.809054Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "index_input_image = 1\n",
+ "number_conv_kernels = 32\n",
+ "\n",
+ "input_image = dataset.data[index_input_image].type(torch.float32)\n",
+ "input_image = input_image.clone().detach()\n",
+ "input_image = input_image.unsqueeze(0)\n",
+ "input_image = input_image.to(device)\n",
+ "\n",
+ "with torch.no_grad():\n",
+ " feature_maps = model.conv1(input_image).cpu()\n",
+ "\n",
+ "fig, ax = plt.subplots(4, 8, sharex=True, sharey=True, figsize=(16, 8))\n",
+ "\n",
+ "for i in range(0, number_conv_kernels):\n",
+ " row, col = i//8, i%8\n",
+ " ax[row][col].imshow(feature_maps[i])\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 10: `Feature maps` of one input from the `conv1` layer of the `model`. The units on the x- and y-axes are the pixel indices. There are 32 images because there are 32 convolutional kernels in the `conv1` layer.\n",
+ ">\n",
+ "> The feature maps derived from the trained model show which morphological features --- e.g., lines and edges --- are favored by the model. When the model is accurate, these features and feature maps will accurately reflect the input image. In this example, the handwritten digit is \"0,\" and the feature maps all appear as \"0's\". Some maps have more clearly defined edges and \"0\"-like features than others, because each convolutional kernel has a distinct weight parameter associated with it. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 5. Exercises for the Learner"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Each time you train a new model, re-run all the diagnostic plots.\n",
+ "\n",
+ "1. How do the loss and accuracy histories change when batch size is small or large? Why?\n",
+ "2. Does the NN take more or less time (more or fewer epochs) to converge if the input image data are normalized or not normalized? Why?\n",
+ "3. How does the size of the training set affect the model's accuracy and loss -- keeping the number of epochs the same? Why?\n",
+ "3. How does the random seed for the weight initialization affect the model's accuracy and loss -- keeping the number of epochs the same?\n",
+ "5. Use the `time` module to estimate the time for the model fitting. Record that time. Increase and then decrease the number of weights in the NN by an order of magnitude. Train the NN for each of those models and record the times. How does the number of weights in the neural network affect the training time and model loss and accuracy?\n",
+ "6. Use the `time` module to estimate the time for the model fitting. Record that time. Increase and then decrease the number of layers in the NN. Train the NN for each of those models and record the times. How does the number of weights in the neural network affect the training time and model loss and accuracy?\n",
+ "7. Use the `time` module to estimate the time for the model fitting. Record that time. Add a convolutional layer to the NN. Train the NN for each of those models and record the times. How does the number of weights in the neural network affect the training time and model loss and accuracy?"
+ ]
+ }
+ ],
+ "metadata": {
+ "accelerator": "GPU",
+ "colab": {
+ "gpuType": "T4",
+ "machine_shape": "hm",
+ "provenance": []
+ },
+ "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.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
From 291451e4d4eb88973069d659cf13054e5fcff699 Mon Sep 17 00:00:00 2001
From: Brian Nord <184985+bnord@users.noreply.github.com>
Date: Tue, 8 Apr 2025 08:38:45 -0500
Subject: [PATCH 5/5] updated notebook after review
renamed from "AI0_Intro_AI_ImageClassificationWithTensorflow_Draft.ipynb"
Addressed Lau comments
Added more section-by-section outlines
Added the ROC Curve Diagnostic
---
DP02_16a_Introduction_to_AI.ipynb | 2672 +++++++++++++++++++++++++++++
1 file changed, 2672 insertions(+)
create mode 100644 DP02_16a_Introduction_to_AI.ipynb
diff --git a/DP02_16a_Introduction_to_AI.ipynb b/DP02_16a_Introduction_to_AI.ipynb
new file mode 100644
index 0000000..1f45658
--- /dev/null
+++ b/DP02_16a_Introduction_to_AI.ipynb
@@ -0,0 +1,2672 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \n",
+ " Introduction to AI-based Image Classification with Pytorch \n",
+ "Contact author: Brian Nord \n",
+ "Last verified to run: 2025-03-25 \n",
+ "LSST Science Pipelines version: Weekly 2025_09 \n",
+ "Container size: medium \n",
+ "Targeted learning level: beginner "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Description:** An introduction to the classification of images with AI-based classification algorithms."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Skills:** Examine AI training data, prepare it for a classification task, perform classification with a neural network, and examine the diagnostics of the classification task."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**LSST Data Products:** None; MNIST data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Packages:** numpy, matplotlib, sklearn, pytorch"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Credits and Acknowledgments:** We thank Ryan Lau and Melissa Graham for feedback on the notebook."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Get Support:**\n",
+ "Find DP0-related documentation and resources at dp0.lsst.io. Questions are welcome as new topics in the Support - Data Preview 0 Category of the Rubin Community Forum. Rubin staff will respond to all questions posted there."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 1. Introduction\n",
+ "\n",
+ "This Jupyter Notebook introduces artificial intelligence (AI)-based image classification. It demonstrates how to perform a few key steps:\n",
+ "1. examine and prepare data for classification;\n",
+ "2. train an AI algorithm;\n",
+ "3. plot diagnostics of the training performance;\n",
+ "4. initially assess those diagnostics.\n",
+ "\n",
+ "\n",
+ "In this section, you will find:\n",
+ "1. a general definition of AI;\n",
+ "3. commentary on terminology in AI;\n",
+ "4. a description of the software and data used in this tutorial;\n",
+ "4. package imports;\n",
+ "5. function definitions;\n",
+ "6. definition of paths for data and figures."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.1. Definition of AI\n",
+ "\n",
+ "AI is a class of algorithms for building statistical models. These algorithms primarily use data for training, as opposed to models that use analytic formulae or models that are based on physical reasoning. Machine learning is a subclass of algorithms -- e.g., random forests. Deep learning is a subclass of algorithms -- e.g., neural networks. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.2. AI is math, not magic.\n",
+ "\n",
+ "AI is firmly based in math, computer science, and statistics. Additionally, some of the approaches are inspired by concepts or notions in biology (e.g., the computational neuron) and in physics (e.g., the Reverse Boltzmann Machine). \n",
+ "\n",
+ "Much of the jargon in AI is anthropomorphic, which can make it appear that some other than math is happening. For example, consider the following list of terms that are very often used in AI -- and what these terms actually mean mathematically.\n",
+ "\n",
+ "1. `learn` $\\rightarrow$ fit\n",
+ "2. `hallucinate`/`lie` $\\rightarrow$ predict incorrectly\n",
+ "3. `understand` $\\rightarrow$ model fit has converged\n",
+ "4. `cheat` $\\rightarrow$ more efficiently guesses the best weight parameters of the model\n",
+ "5. `believe` $\\rightarrow$ predict/infer based on statistical priors\n",
+ "\n",
+ "When we over-anthropomorphize these mathematical concepts, we obfuscate how they actually work. That makes it harder to build and refine models. That is, AI models are not 'learning' or 'understanding'; they are merely large-parameter models that are being fit to data, and AI includes novel methods for that fitting process. The only learning that's happening is what humans do with these models.\n",
+ "\n",
+ "Many of the most useful AI-related terms are defined throughout this tutorial."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.3. Software and Data Description\n",
+ "\n",
+ "In this notebook, we use `pytorch`, which is currently the library most often used in deep learning studies. `pytorch` is among the state-of-the-art python libraries for tensor manipulation in general and neural network model development in particular. \n",
+ "\n",
+ "Instead of using DP0 data, this tutorial uses [handwritten digits AI benchmarking data from MNIST (Modified National Institute of Standards and Technology )](https://en.wikipedia.org/wiki/MNIST_database), a large database of handwritten digits that is commonly used for training and testing machine learning algorithms. The [`MNIST handwritten digits dataset`](https://ieeexplore.ieee.org/document/6296535) comprises 10 classes --- one for each digit --- where each image is a picture of the digit written by hand. This is a useful dataset for learning the basics of neural networks and other AI algorithms. MNIST is one of a few canonical AI benchmark data sets for image classification. \n",
+ "\n",
+ "Later tutorials in this series will use stars and galaxies drawn from DP0 data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.4. Import packages\n",
+ "\n",
+ "[`numpy`](https://numpy.org/) is used for computations and mathematical operations on multi-dimensional arrays.\n",
+ "\n",
+ "[`pandas`](https://pandas.pydata.org/) is used to organize and manage data.\n",
+ "\n",
+ "[`matplotlib`](https://matplotlib.org/) is a plotting library. \n",
+ "\n",
+ "[`seaborn`](https://seaborn.pydata.org/) is used for visualizations.\n",
+ "\n",
+ "[`sklearn`](https://scikit-learn.org/stable/) is a library for machine learning.\n",
+ "\n",
+ "[`torch`](https://www.pytorch.org) is used for fast tensor operations --- often used for building neural network models."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "JyaaGkFE8VOl"
+ },
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import time\n",
+ "import datetime\n",
+ "import os\n",
+ "\n",
+ "import matplotlib\n",
+ "import matplotlib.pyplot as plt\n",
+ "from matplotlib.pyplot import cm\n",
+ "from matplotlib.colors import LogNorm\n",
+ "import seaborn as sns\n",
+ "\n",
+ "from sklearn.metrics import confusion_matrix, RocCurveDisplay\n",
+ "from sklearn.preprocessing import LabelBinarizer\n",
+ "\n",
+ "import torch\n",
+ "import torch.nn as nn\n",
+ "import torch.optim as optim\n",
+ "import torch.nn.functional as F\n",
+ "import torchvision\n",
+ "from torch.utils.data import Dataset, DataLoader, Subset, random_split"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.5. Define functions"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The following functions are defined and used throughout this notebook. It is not necessary to understand exactly what every function does to proceed with this tutorial. Execute all cells and move on to Section 2."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def normalizeInputs(x_temp, input_minimum, input_maximum):\n",
+ " \"\"\"Normalize a datum that is an input to the neural network\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_temp: `numpy.array`\n",
+ " image data\n",
+ " input_minimum: `float`\n",
+ " minimum value for normalization\n",
+ " input_maximum: `float`\n",
+ " maximum value for normalization\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " x_temp_norm: `numpy.array`\n",
+ " normalized image data\n",
+ " \"\"\"\n",
+ " x_temp_norm = (x_temp - input_minimum)/input_maximum\n",
+ " return x_temp_norm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def createFileUidTimestamp():\n",
+ " \"\"\"Create a timestamp for a filename.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " None\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " file_uid_timestamp : `string`\n",
+ " String from date and time.\n",
+ " \"\"\"\n",
+ " file_uid_timestamp = datetime.datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
+ " return file_uid_timestamp"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def createFileName(file_prefix=\"\", file_location=\"Data/Sandbox/\",\n",
+ " file_suffix=\"\", useuid=True, verbose=True):\n",
+ " \"\"\"Create a file name.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " file_prefix: `string`\n",
+ " prefix of file name\n",
+ " file_location: `string`\n",
+ " path to file\n",
+ " file_suffix: `string`\n",
+ " suffix/extension of file name\n",
+ " useuid: 'bool'\n",
+ " choose to use a unique id\n",
+ " verbose: 'bool'\n",
+ " choose to print the file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " file_final: `string`\n",
+ " filename used for saving\n",
+ " \"\"\"\n",
+ " if useuid:\n",
+ " file_uid = createFileUidTimestamp()\n",
+ " else:\n",
+ " file_uid = \"\"\n",
+ "\n",
+ " file_final = file_location + file_prefix + \"_\" + file_uid + file_suffix\n",
+ "\n",
+ " if verbose:\n",
+ " print(file_final)\n",
+ "\n",
+ " return file_final"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotArrayImageExamples(subset_train,\n",
+ " num_row=3, num_col=3,\n",
+ " object_index_start=0,\n",
+ " figsize=(7, 7),\n",
+ " save_file=False,\n",
+ " file_prefix=\"ImageExamples\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot an array of examples of images and labels\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " subset_train: `numpy.ndarray`\n",
+ " training data images\n",
+ " num_row: `int`, optional\n",
+ " number of rows to plot\n",
+ " num_col: `int`, optional\n",
+ " number of columns to plot\n",
+ " figsize: `tuple`, optional\n",
+ " size of figure\n",
+ " object_index_start: `int`, optional\n",
+ " starting index for set of images to plot\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " From: https://pytorch.org/tutorials/beginner/basics/data_tutorial.html\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " labels_map = {\n",
+ " 0: \"0\",\n",
+ " 1: \"1\",\n",
+ " 2: \"2\",\n",
+ " 3: \"3\",\n",
+ " 4: \"4\",\n",
+ " 5: \"5\",\n",
+ " 6: \"6\",\n",
+ " 7: \"7\",\n",
+ " 8: \"8\",\n",
+ " 9: \"9\",\n",
+ " }\n",
+ "\n",
+ " figure = plt.figure(figsize=figsize)\n",
+ "\n",
+ " for i in range(0, num_row * num_col):\n",
+ " sample_idx = object_index_start + i\n",
+ " img, label = subset_train[sample_idx]\n",
+ " figure.add_subplot(num_row, num_col, i + 1)\n",
+ " plt.title(\"label (digit): \" + labels_map[label])\n",
+ " plt.axis(\"off\")\n",
+ " plt.imshow(img.squeeze(), cmap=\"gray\")\n",
+ "\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotArrayHistogramExamples(subset_train,\n",
+ " num_row=3, num_col=3,\n",
+ " n_bins=10,\n",
+ " object_index_start=0,\n",
+ " figsize=(7, 7),\n",
+ " save_file=False,\n",
+ " file_prefix=\"HistogramExamples\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histograms of image pixel values\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " subset_train: `numpy.ndarray`\n",
+ " training data images\n",
+ " num_row: `int`, optional\n",
+ " number of rows to plot\n",
+ " num_col: `int`, optional\n",
+ " number of columns to plot\n",
+ " n_bins: `int`, optional\n",
+ " number of bins in histogram \n",
+ " object_index_start: `int`, optional\n",
+ " starting index for set of images to plot\n",
+ " figsize: `tuple`, optional\n",
+ " size of figure\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " labels_map = {\n",
+ " 0: \"0\",\n",
+ " 1: \"1\",\n",
+ " 2: \"2\",\n",
+ " 3: \"3\",\n",
+ " 4: \"4\",\n",
+ " 5: \"5\",\n",
+ " 6: \"6\",\n",
+ " 7: \"7\",\n",
+ " 8: \"8\",\n",
+ " 9: \"9\",\n",
+ " }\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=figsize)\n",
+ "\n",
+ " for i in range(0, num_row * num_col):\n",
+ " sample_idx = object_index_start + i\n",
+ " img, label = subset_train[sample_idx]\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " img_temp = img[0, :, :]\n",
+ " img_temp = np.array(img_temp).flat\n",
+ " ax.hist(img_temp, bins=n_bins, color='gray')\n",
+ " ax.set_title(\"label (digit): \" + labels_map[label])\n",
+ " ax.set_xlabel(\"Pixel Values\")\n",
+ "\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def predict(dataloader, model, dataset_type):\n",
+ " \"\"\"Predict labels of inputs\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " dataloader: `numpy.ndarray`\n",
+ " training data images\n",
+ " model: `int`, optional\n",
+ " number of rows to plot\n",
+ " dataset_type: `int`, optional\n",
+ " number of columns to plot\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " y_prob_list: `numpy.ndarray`\n",
+ " probabilities for each class for each input\n",
+ " y_choice_list: `numpy.ndarray`\n",
+ " highest-probability class for each input\n",
+ " y_true_list: `numpy.ndarray`\n",
+ " true class for each input\n",
+ " x_list: `numpy.ndarray`\n",
+ " input\n",
+ " \"\"\"\n",
+ " size = len(dataloader.dataset)\n",
+ " num_batches = len(dataloader)\n",
+ " model.eval()\n",
+ "\n",
+ " y_prob_list = []\n",
+ " y_choice_list = []\n",
+ " y_true_list = []\n",
+ " x_list = []\n",
+ "\n",
+ " i = 0\n",
+ " loss, accuracy = 0, 0\n",
+ " with torch.no_grad():\n",
+ " for inputs, labels in dataloader:\n",
+ " inputs = inputs.to(device)\n",
+ " labels = labels.to(device)\n",
+ "\n",
+ " y = model(inputs)\n",
+ " y_prob = torch.softmax(y, dim=1)\n",
+ " y_choice = (torch.max(torch.exp(y), 1)[1]).data.cpu().numpy()\n",
+ "\n",
+ " loss += loss_fn(y, labels).item()\n",
+ " loss /= num_batches\n",
+ " accuracy_temp = y.argmax(1) == labels\n",
+ " accuracy += accuracy_temp.type(torch.float).sum().item()\n",
+ " accuracy /= size\n",
+ "\n",
+ " y_prob_list.append(y_prob.detach())\n",
+ " y_choice_list.append(y_choice)\n",
+ " y_true_list.append(labels)\n",
+ " x_list.append(inputs)\n",
+ " labels = labels.data.cpu().numpy()\n",
+ "\n",
+ " i += 1\n",
+ "\n",
+ " y_prob_list = np.array(y_prob_list)\n",
+ " y_choice_list = np.array(y_choice_list)\n",
+ " y_true_list = np.array(y_true_list)\n",
+ " x_list = np.array(x_list)\n",
+ "\n",
+ " y_prob_list = np.squeeze(y_prob_list)\n",
+ " y_choice_list = np.squeeze(y_choice_list)\n",
+ " y_true_list = np.squeeze(y_true_list)\n",
+ " x_list = np.squeeze(x_list)\n",
+ "\n",
+ " print(f\"{dataset_type : <10} data set ...\\\n",
+ " Accuracy: {(100*accuracy):>0.1f}%, Avg loss: {loss:>8f}\")\n",
+ "\n",
+ " return y_prob_list, y_choice_list, y_true_list, x_list"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotPredictionHistogram(y_prediction_a, y_prediction_b=None,\n",
+ " y_prediction_c=None, n_classes=None,\n",
+ " n_objects_a=None, n_colors=None,\n",
+ " title_a=None, title_b=None,\n",
+ " title_c=None, label_a=None,\n",
+ " label_b=None, label_c=None,\n",
+ " alpha=1.0, figsize=(12, 5),\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " xlabel_plot=\"Class label\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histogram of predicted labels\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " y_prediction_a: `numpy.ndarray`\n",
+ " y_prediction_b: `numpy.ndarray`, optional\n",
+ " y_prediction_c: `numpy.ndarray`, optional\n",
+ " n_classes: `int`, optional\n",
+ " n_objects_a: `int`, optional\n",
+ " n_colors: `int`, optional\n",
+ " title_a: `string`, optional\n",
+ " title_b: `string`, optional\n",
+ " title_c: `string`, optional\n",
+ " label_a: `string`, optional\n",
+ " label_b: `string`, optional\n",
+ " label_c: `string`, optional\n",
+ " alpha: `float`, optional\n",
+ " transparency\n",
+ " figsize: `tuple`, optional\n",
+ " figure size\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " ndim = y_prediction_a.ndim\n",
+ "\n",
+ " if ndim == 2:\n",
+ " fig, (axa, axb, axc) = plt.subplots(1, 3, figsize=figsize)\n",
+ " fig.subplots_adjust(wspace=0.35)\n",
+ " elif ndim == 1:\n",
+ " fig, ax = plt.subplots(figsize=figsize)\n",
+ "\n",
+ " shape_a = np.shape(y_prediction_a)\n",
+ "\n",
+ " if n_objects_a is None:\n",
+ " n_objects_a = shape_a[0]\n",
+ "\n",
+ " if ndim == 2:\n",
+ " if n_classes is None:\n",
+ " n_classes = shape_a[1]\n",
+ " if n_colors is None:\n",
+ " n_colors = n_classes\n",
+ " elif ndim == 1:\n",
+ " if n_colors is None:\n",
+ " n_colors = 1\n",
+ "\n",
+ " if ndim == 2:\n",
+ " colors = cm.Purples(np.linspace(0, 1, n_colors))\n",
+ " xlabel = \"Probability for Each Class\"\n",
+ "\n",
+ " axa.set_ylim(0, n_objects_a)\n",
+ " axa.set_xlabel(xlabel)\n",
+ " axa.set_title(title_a)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axa.hist(y_prediction_a[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " shape_b = np.shape(y_prediction_b)\n",
+ " axb.set_ylim(0, shape_b[0])\n",
+ " axb.set_xlabel(xlabel)\n",
+ " axb.set_title(title_b)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axb.hist(y_prediction_b[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " shape_c = np.shape(y_prediction_c)\n",
+ " axc.set_ylim(0, shape_c[0])\n",
+ " axc.set_xlabel(xlabel)\n",
+ " axc.set_title(title_c)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axc.hist(y_prediction_c[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " elif ndim == 1:\n",
+ " ya, xa, _ = plt.hist(y_prediction_a, alpha=alpha, color='orange',\n",
+ " label=label_a)\n",
+ " y_max_list = [max(ya)]\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " yb, xb, _ = plt.hist(y_prediction_b, alpha=alpha, color='green',\n",
+ " label=label_b)\n",
+ " y_max_list.append(max(yb))\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " yc, xc, _ = plt.hist(y_prediction_c, alpha=alpha, color='purple',\n",
+ " label=label_c)\n",
+ " y_max_list.append(max(yc))\n",
+ "\n",
+ " plt.ylim(0, np.max(y_max_list)*1.1)\n",
+ " plt.xlabel(xlabel_plot)\n",
+ "\n",
+ " plt.legend(loc='upper right')\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotTrueLabelHistogram(y_prediction_a, y_prediction_b=None,\n",
+ " y_prediction_c=None, n_classes=None,\n",
+ " n_objects_a=None, n_colors=None,\n",
+ " title_a=None, title_b=None,\n",
+ " title_c=None, label_a=None,\n",
+ " label_b=None, label_c=None,\n",
+ " alpha=1.0, figsize=(12, 5),\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " xlabel_plot=\"Class label\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histogram of predicted labels\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " y_prediction_a: `numpy.ndarray`\n",
+ " y_prediction_b: `numpy.ndarray`, optional\n",
+ " y_prediction_c: `numpy.ndarray`, optional\n",
+ " n_classes: `int`, optional\n",
+ " n_objects_a: `int`, optional\n",
+ " n_colors: `int`, optional\n",
+ " title_a: `string`, optional\n",
+ " title_b: `string`, optional\n",
+ " title_c: `string`, optional\n",
+ " label_a: `string`, optional\n",
+ " label_b: `string`, optional\n",
+ " label_c: `string`, optional\n",
+ " alpha: `float`, optional\n",
+ " transparency\n",
+ " figsize: `tuple`, optional\n",
+ " figure size\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ "\n",
+ " ndim = y_prediction_a.ndim\n",
+ "\n",
+ " if ndim == 2:\n",
+ " fig, (axa, axb, axc) = plt.subplots(1, 3, figsize=figsize)\n",
+ " fig.subplots_adjust(wspace=0.35)\n",
+ " elif ndim == 1:\n",
+ " fig, ax = plt.subplots(figsize=figsize)\n",
+ "\n",
+ " shape_a = np.shape(y_prediction_a)\n",
+ "\n",
+ " if n_objects_a is None:\n",
+ " n_objects_a = shape_a[0]\n",
+ "\n",
+ " if ndim == 2:\n",
+ " if n_classes is None:\n",
+ " n_classes = shape_a[1]\n",
+ " if n_colors is None:\n",
+ " n_colors = n_classes\n",
+ " elif ndim == 1:\n",
+ " if n_colors is None:\n",
+ " n_colors = 1\n",
+ "\n",
+ " if ndim == 2:\n",
+ " colors = cm.Purples(np.linspace(0, 1, n_colors))\n",
+ " xlabel = \"Probability for Each Class\"\n",
+ "\n",
+ " axa.set_ylim(0, n_objects_a)\n",
+ " axa.set_xlabel(xlabel)\n",
+ " axa.set_title(title_a)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axa.hist(y_prediction_a[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " shape_b = np.shape(y_prediction_b)\n",
+ " axb.set_ylim(0, shape_b[0])\n",
+ " axb.set_xlabel(xlabel)\n",
+ " axb.set_title(title_b)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axb.hist(y_prediction_b[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " shape_c = np.shape(y_prediction_c)\n",
+ " axc.set_ylim(0, shape_c[0])\n",
+ " axc.set_xlabel(xlabel)\n",
+ " axc.set_title(title_c)\n",
+ "\n",
+ " for i in np.arange(n_classes):\n",
+ " axc.hist(y_prediction_c[:, i], alpha=alpha,\n",
+ " color=colors[i], label=\"'\" + str(i) + \"'\")\n",
+ "\n",
+ " elif ndim == 1:\n",
+ " ya, xa, _ = plt.hist(y_prediction_a, alpha=alpha, color='orange',\n",
+ " label=label_a)\n",
+ " y_max_list = [max(ya)]\n",
+ "\n",
+ " if y_prediction_b is not None:\n",
+ " yb, xb, _ = plt.hist(y_prediction_b, alpha=alpha, color='green',\n",
+ " label=label_b)\n",
+ " y_max_list.append(max(yb))\n",
+ "\n",
+ " if y_prediction_c is not None:\n",
+ " yc, xc, _ = plt.hist(y_prediction_c, alpha=alpha, color='purple',\n",
+ " label=label_c)\n",
+ " y_max_list.append(max(yc))\n",
+ "\n",
+ " plt.ylim(0, np.max(y_max_list)*1.1)\n",
+ " plt.xlabel(xlabel_plot)\n",
+ "\n",
+ " plt.legend(loc='upper right')\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotLossHistory(history, figsize=(8, 5),\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot loss history of the model as function of epoch\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " history: `keras.src.callbacks.history.History`\n",
+ " keras callback history object containing the losses at each epoch\n",
+ " figsize: `tuple`, optional\n",
+ " figure size\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=figsize)\n",
+ "\n",
+ " loss_tra = np.array(history['loss'])\n",
+ " loss_val = np.array(history['val_loss'])\n",
+ " loss_dif = loss_val - loss_tra\n",
+ "\n",
+ " ax1.plot(loss_tra, label='Training')\n",
+ " ax1.plot(loss_val, label='Validation')\n",
+ " ax1.legend()\n",
+ "\n",
+ " ax2.plot(loss_dif, color='red', label='residual')\n",
+ " ax2.axhline(y=0, color='grey', linestyle='dashed', label='zero bias')\n",
+ " ax2.sharex(ax1)\n",
+ " ax2.legend()\n",
+ "\n",
+ " ax1.set_title('Loss History')\n",
+ " ax1.set_ylabel('Loss')\n",
+ " ax2.set_ylabel('Loss Residual')\n",
+ " ax2.set_xlabel('Epoch')\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotArrayImageConfusion(x_tra, y_tra, y_pred_tra_topchoice,\n",
+ " title_main=None, num=10,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot images of examples objects that are misclassified.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_tra: `numpy.ndarray`\n",
+ " training image data\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training label data\n",
+ " y_pred_tra_topchoice: `numpy.ndarray`\n",
+ " top choice of the predicted labels\n",
+ " title_main: `string`, optional\n",
+ " title for the plot\n",
+ " num: `int`, optional\n",
+ " number of examples\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " num_row = 2\n",
+ " num_col = 5\n",
+ " images = x_tra[:num]\n",
+ " labels_true = y_tra[:num]\n",
+ " labels_pred = y_pred_tra_topchoice[:num]\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ "\n",
+ " fig.patch.set_linewidth(5)\n",
+ " fig.patch.set_edgecolor('cornflowerblue')\n",
+ "\n",
+ " for i in range(num):\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " ax.imshow(images[i], cmap='gray')\n",
+ " ax.set_title(r'True: {}'.format(labels_true[i]) + '\\n'\n",
+ " + 'Pred: {}'.format(labels_pred[i]))\n",
+ "\n",
+ " fig.suptitle(title_main)\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotROCMulticlassOnevsrest(y_tra, y_tes, y_pred_tes,\n",
+ " figsize=(7, 7),\n",
+ " save_file=False,\n",
+ " file_prefix=\"ImageExamples\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot the one-vs-rest ROC curve\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training data true labels\n",
+ " y_tes: `numpy.ndarray`\n",
+ " testing data true labels\n",
+ " y_pred_tes: `numpy.ndarray`\n",
+ " testing data predicted labels\n",
+ " figsize: `tuple`, optional\n",
+ " size of figure\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " fig, ax = plt.subplots(figsize=figsize)\n",
+ " n_classes = len(y_prob_tes[0])\n",
+ " label_target_list = np.linspace(0, n_classes-1, num=n_classes)\n",
+ " color_list = cm.rainbow(np.linspace(0, 0.5, n_classes))\n",
+ "\n",
+ " for label_target, color in zip(label_target_list, color_list): \n",
+ " label_binarizer = LabelBinarizer().fit(y_tra)\n",
+ " y_onehot_tes = label_binarizer.transform(y_tes)\n",
+ " class_id = np.flatnonzero(label_binarizer.classes_ == label_target)[0]\n",
+ " display = RocCurveDisplay.from_predictions(\n",
+ " y_onehot_tes[:, class_id],\n",
+ " y_pred_tes[:, class_id],\n",
+ " name=f\"{int(label_target)} vs the rest\",\n",
+ " color=color,\n",
+ " ax=ax,\n",
+ " plot_chance_level=(class_id == 9)\n",
+ " )\n",
+ " \n",
+ " _ = display.ax_.set(\n",
+ " xlabel=\"False Positive Rate\",\n",
+ " ylabel=\"True Positive Rate\",\n",
+ " title=\"ROC: One-vs-Rest\",\n",
+ " )\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ " plt.savefig(file_final, bbox_inches='tight')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plotArrayHistogramConfusion(x_tra, y_tra, y_pred_tra_topchoice,\n",
+ " title_main=None, num=10,\n",
+ " save_file=False,\n",
+ " file_prefix=\"prediction_histogram\",\n",
+ " file_location=\"./\",\n",
+ " file_suffix=\".png\"):\n",
+ " \"\"\"Plot histograms of pixel values for images that are misclassified.\n",
+ "\n",
+ " Parameters\n",
+ " ----------\n",
+ " x_tra: `numpy.ndarray`\n",
+ " training image data\n",
+ " y_tra: `numpy.ndarray`\n",
+ " training label data\n",
+ " y_pred_tra_topchoice: `numpy.ndarray`\n",
+ " top choice of the predicted labels\n",
+ " title_main: `string`, optional\n",
+ " title of plot\n",
+ " num: `int`, optional\n",
+ " number of examples\n",
+ " file_prefix: `string`, optional\n",
+ " prefix of file name\n",
+ " file_location: `string`, optional\n",
+ " path to file\n",
+ " file_suffix: `string`, optional\n",
+ " suffix/extension of file name\n",
+ "\n",
+ " Returns\n",
+ " -------\n",
+ " None\n",
+ " \"\"\"\n",
+ " n_bins = 10\n",
+ " num_row = 2\n",
+ " num_col = 5\n",
+ " images = x_tra[:num]\n",
+ " labels_true = y_tra[:num]\n",
+ " labels_pred = y_pred_tra_topchoice[:num]\n",
+ "\n",
+ " fig, axes = plt.subplots(num_row, num_col,\n",
+ " figsize=(1.5*num_col, 2*num_row))\n",
+ "\n",
+ " fig.patch.set_linewidth(5)\n",
+ " fig.patch.set_edgecolor('cornflowerblue')\n",
+ "\n",
+ " for i in range(num):\n",
+ " ax = axes[i//num_col, i%num_col]\n",
+ " images_temp = images[i, :, :].flat\n",
+ " ax.hist(images_temp, bins=n_bins, color='gray')\n",
+ " ax.set_title(r'True: {}'.format(labels_true[i]) + '\\n'\n",
+ " + 'Pred: {}'.format(labels_pred[i]))\n",
+ " ax.set_xlabel('Pixel Values')\n",
+ "\n",
+ " fig.suptitle(title_main)\n",
+ " plt.tight_layout()\n",
+ "\n",
+ " if save_file:\n",
+ " file_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=file_location,\n",
+ " file_suffix=file_suffix,\n",
+ " useuid=True)\n",
+ "\n",
+ " plt.savefig(file_final, bbox_inches='tight')\n",
+ "\n",
+ " plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 1.6. Define paths for data and figures"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Neural network training (i.e., model fitting) typically requires many numerical experiments to achieve an ideal model. To facilitate the comparison of these experiments/models, it is helpful to organize data carefully. \n",
+ "\n",
+ "Set the variable `run_label` for each training run. \n",
+ "Set paths for the model weight parameters and diagnostic figures, and\n",
+ "save these paths in the dictionary `path_dict` to facilitate passing information to plotting functions.\n",
+ "Check whether the paths exist, and if not, create them."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "run_label = \"Run000\"\n",
+ "\n",
+ "path_temp = os.getenv(\"HOME\") + '/dp02_16a_temp'\n",
+ "path_dict = {'run_label': run_label,\n",
+ " 'dir_data_model': path_temp + \"/Models/\",\n",
+ " 'dir_data_figures': path_temp + \"/Figures/\",\n",
+ " 'dir_data_data': path_temp + \"/Data/\",\n",
+ " 'file_model_prefix': \"Model\",\n",
+ " 'file_figure_prefix': \"Figure\",\n",
+ " 'file_figure_suffix': \".png\",\n",
+ " 'file_model_suffix': \".pt\"\n",
+ " }\n",
+ "del path_temp\n",
+ "\n",
+ "if not os.path.exists(path_dict['dir_data_model']):\n",
+ " os.makedirs(path_dict['dir_data_model'])\n",
+ "\n",
+ "if not os.path.exists(path_dict['dir_data_figures']):\n",
+ " os.makedirs(path_dict['dir_data_figures'])\n",
+ "\n",
+ "if not os.path.exists(path_dict['dir_data_data']):\n",
+ " os.makedirs(path_dict['dir_data_data'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 2. Load and Prepare data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this section, you will encounter the following items regarding the dataset that we'll build a classification model for.\n",
+ "\n",
+ "1. obtaining the data: Normalizing the data and downloading the data;\n",
+ "5. splitting the data into different sets;\n",
+ "6. creating subsets of each of those with a smaller number of objects;\n",
+ "7. examining the raw data;\n",
+ "8. creating dataloaders for model training."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.1. Obtain the dataset"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`pytorch` has a simple function to download the MNIST data to your local server for free. While downloading, we use the `transforms` method to normalize the data; this makes the model training more efficient."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 2.1.1. Normalize data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Create a `transform` that is used to convert the data sets to tensors that can be used in `pytorch`. This also transforms all the data from the range $[0,255]$ to $[0.,1.]$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "kMzao03zcF5i",
+ "outputId": "0401d0af-d607-436a-908f-385ffc85812c"
+ },
+ "outputs": [],
+ "source": [
+ "transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 2.1.2. Download data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Download the data from a remote reserver."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%time\n",
+ "dataset = torchvision.datasets.MNIST(root=path_dict['dir_data_data'], train=True,\n",
+ " download=True, transform=transform)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.2. Split data into training, validation, and testing"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Split for a proper 'blind' analysis and optimization of an AI model.\n",
+ "\n",
+ "There are three primary data sets used in model development and optimization:\n",
+ "\n",
+ "* `Training` (with filename tag `_tra`) data is used directly by the algorithm to update the parameters of the AI model -- e.g., the weights of the computational neurons on the edges in neural networks.\n",
+ "* `Validation` (`_val`) data is used indirectly to update the hyperparameters of the AI model -- e.g., the batch size (`batchsize`), the learning rate, or the layers in the architecture of a neural network. Each time the neural network has completed training with the training data, the human looks at those diagnostics when run on the training and the validation data.\n",
+ "* `Test(ing)` (`_tes`) data is only used when the model is trained and validated and will no longer be update or further trained. This is the data that you would consider to be the new data that has not been examined before -- e.g., newly observed data that has not been previously characterized."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We use most of the data for training to maximize the accuracy and generalization of the model. We use a small amount of validation data, because only a little bit is needed to check the model optimization during training. We also use only a small amount of testing data, assuming that new data sets to examine are smaller than existing training data sets."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the fractions for the training, validation, and test sets."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fraction_tra = 0.8\n",
+ "fraction_val = 0.1\n",
+ "fraction_tes = 0.1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Split the data according to those fractions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fraction_list = [fraction_tra, fraction_val, fraction_tes]\n",
+ "\n",
+ "data_tra_full, data_val_full, data_tes_full = \\\n",
+ " torch.utils.data.random_split(dataset, fraction_list)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Print the data set sizes to check how much data you're using to optimize the model. Each problem has a unique requirement regarding the amount of training data. It typically depends on the complexity of shapes in the images and the variation across classes. Without enough data in each class, the model will likely be at least somewhat predictive but have a sub-optimal final loss (i.e., average error). If a problem requires neural networks, then it will likely require at least hundreds of images. Also, there is an interplay between the amount of data, the complexity of the images, and the complexity and size of the model."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"training:\", len(data_tra_full.indices))\n",
+ "print(\"validation:\", len(data_val_full.indices))\n",
+ "print(\"test\", len(data_tes_full.indices))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.3. Create a subset of the training data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use only a subset of each data to make the training faster for this tutorial. Consider increasing the sizes of these data sets in your exploration of the tutorial elements."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "subset_size = 5000\n",
+ "\n",
+ "subset_indices_tra = np.arange(subset_size)\n",
+ "subset_indices_val = np.arange(subset_size)\n",
+ "subset_indices_tes = np.arange(subset_size)\n",
+ "\n",
+ "data_tra = Subset(data_tra_full, subset_indices_tra)\n",
+ "data_val = Subset(data_val_full, subset_indices_val)\n",
+ "data_tes = Subset(data_tes_full, subset_indices_tes)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.4. Examine raw data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Review the raw data shapes by looking at a single datum in the training set. Each datum in the training set is an image-label pair. The image is a tensor, and the label is an integer. The image size in part determines the depth (number of layers) of the neural network. This will be discussed in a later section on model training."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sample_index = 0\n",
+ "image, label = data_tra[sample_index]\n",
+ "print(f\"The image shape is {image.shape}.\")\n",
+ "print(f\"The label for this image is {label}.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Print the image labels and their corresponding indices within a dataset object. This is useful for verifying that you understand your data set."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "{v: k for k, v in dataset.class_to_idx.items()}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot examples of the raw data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Example_Image_Array\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotArrayImageExamples(data_tra,\n",
+ " num_row=3, num_col=3,\n",
+ " save_file=False,\n",
+ " object_index_start=0,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 1: Three rows of three images, each a handwritten number in white on a black background."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot the distributions of pixel values to understand the data further. All pixel data has been normalized, and pixels have values between 0 and 1 only.\n",
+ "\n",
+ "The distribution of pixel values matches the images shown above: mostly black (values near 0) pixels, with some white (values near 1), and a few grey (values in between 0 and 1)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Example_Histogram_Array\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotArrayHistogramExamples(data_tra,\n",
+ " num_row=3, num_col=3,\n",
+ " save_file=False,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 2: Three rows of three histograms, each showing the distribution of pixel values (number of pixels of a given value) for the handwritten digit images shown in Figure 1."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-12-15T20:26:20.181221Z",
+ "iopub.status.busy": "2024-12-15T20:26:20.180895Z",
+ "iopub.status.idle": "2024-12-15T20:26:20.186166Z",
+ "shell.execute_reply": "2024-12-15T20:26:20.185452Z",
+ "shell.execute_reply.started": "2024-12-15T20:26:20.181199Z"
+ }
+ },
+ "source": [
+ "Examine the balance of classes in the data sets. If one class has more objects in the training set than other classes, the model will tend to be biased toward predicting that class. The classes don't have to be distributed perfectly uniformly, but a high degree of uniformity is preferable."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use the `plotPredictionHistogram` function to plot histograms of true label distributions by class."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_tra = []\n",
+ "y_val = []\n",
+ "y_tes = []\n",
+ "\n",
+ "for i in np.arange(subset_size):\n",
+ " image, label_tra = data_tra[i]\n",
+ " image, label_val = data_val[i]\n",
+ " image, label_tes = data_tes[i]\n",
+ " y_tra.append(label_tra)\n",
+ " y_val.append(label_val)\n",
+ " y_tes.append(label_tes)\n",
+ "\n",
+ "y_tra = np.array(y_tra)\n",
+ "y_val = np.array(y_val)\n",
+ "y_tes = np.array(y_tes)\n",
+ "\n",
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Histograms_true_class\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotPredictionHistogram(y_tra,\n",
+ " y_prediction_b=y_val,\n",
+ " y_prediction_c=y_tes,\n",
+ " label_a=\"Training Set\",\n",
+ " label_b=\"Validation Set\",\n",
+ " label_c=\"Testing Set\",\n",
+ " figsize=(12, 5),\n",
+ " alpha=0.5,\n",
+ " xlabel_plot=\"True class label\",\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Figure 3**: The histograms of true class labels for each data set. Each histogram is for a different data set used during model training --- training data, validation data, and test data. Note that these are overlapping histograms, not stacked. Please compare to Figure 4, which shows histograms of the predicted class labels."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 2.5. Create Dataloaders for training"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the batch size, which will be used in dataloaders and in training. To simplify data-handling, we set the batch size to the size of the subset that we select. This means that there is one batch used in training."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "batch_size = subset_size"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Create dataloaders for the training, validation, and test set data loaders."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trainloader = torch.utils.data.DataLoader(data_tra, batch_size=batch_size,\n",
+ " shuffle=False)\n",
+ "\n",
+ "validloader = torch.utils.data.DataLoader(data_val, batch_size=batch_size,\n",
+ " shuffle=False)\n",
+ "\n",
+ "testloader = torch.utils.data.DataLoader(data_tes, batch_size=batch_size,\n",
+ " shuffle=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 3. Train the model: Convolutional Neural Network"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this section, you will encounter the following major items for training a neural network:\n",
+ "\n",
+ "1. basics of `pytorch` model-building;\n",
+ "2. defining the neural network model -- setting model hyperparameters, a glossary of terms of model architecture elements, glossary of terms for a network model class, creating a model class;\n",
+ "3. training the model."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 3.1. Basics of pytorch"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-12-15T21:16:11.080821Z",
+ "iopub.status.busy": "2024-12-15T21:16:11.079938Z",
+ "iopub.status.idle": "2024-12-15T21:16:11.085835Z",
+ "shell.execute_reply": "2024-12-15T21:16:11.085097Z",
+ "shell.execute_reply.started": "2024-12-15T21:16:11.080794Z"
+ }
+ },
+ "source": [
+ "In `pytorch`, neural network models are defined as classes. This is slightly different than typical `tensorflow` usage, in which people build a `sequential` model or use a pre-built `model` class and add layers to that model. \n",
+ "\n",
+ "The other major difference between `pytorch` and `tensorflow` is the shape of the tensors and the inputs for each layer. \n",
+ "\n",
+ "In particular, in `pytorch` one has to explicitly match the output from one layer to the input of the next layer. Sometimes, this can be done with a calculation. But, more often, one must perform guess-and-check. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 3.2. Define the neural network model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.1. Define model hyperparameters"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the seed that for the random initial model weight values."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "Zsc_pqZtWftJ",
+ "outputId": "8238aa09-2afd-47ef-c93e-3910b342fe38"
+ },
+ "outputs": [],
+ "source": [
+ "seed = 1729\n",
+ "new = torch.manual_seed(seed)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Define the loss function. We choose cross-entropy, which is the standard loss function for classification of discrete labels."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "loss_fn = nn.CrossEntropyLoss()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.2. Glossary: model architecture elements"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Below is a list of important terms for elements of a neural network architecture.\n",
+ "\n",
+ " * `activation function`: a function within a neuron that takes inputs from a previous layer and produces an output -- usually, this function is non-linear. Examples include \"sigmoid,\" \"softmax,\" and \"reLu\" (rectified linear unit).\n",
+ " * `sigmoid`: an activation function that takes points from the Real line and maps them to the range [-1,1].\n",
+ " * `softmax`: an activation function that takes points from the Real line and maps them to the range [0,1]. This can be used to obtain a 'probability score.'\n",
+ " * `ReLU (rectified linear unit)`: an activation function that non-smoothly goes from 0 to some positive Real number when a threshold is reached for the input value. \n",
+ " * `weight`: the weight factor within an activation function.\n",
+ " * `bias`: the bias factor applied after an activation function.\n",
+ " * `layer`: one set of nodes/neurons that receive input data simultaneously.\n",
+ " * `linear (Dense) layer`: occurs due to the \"flattening\" of a higher-dimensional data vector, like an image. It only has an activation function -- as opposed to a convolutional layer which makes a convolution operation.\n",
+ " * `convolutional layer`: a layer that applies a convolution operation to an input sample."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.3. Glossary: class that defines a network model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Typically, there are two functions within this class.\n",
+ "\n",
+ "The constructor function (`__init__`) defines the available layers of the network. These layers require specific settings related to the data set shapes. \n",
+ "* `Conv2d`: defines a two-dimensional convolutional layer. Four inputs are considered here:\n",
+ " * `in_channels` (required): the number of input channels.\n",
+ " * `out_channels` (required): the number of output channels.\n",
+ " * `kernel_size` (required): the size on one dimension of the convolutional kernel.\n",
+ " * `stride` (optional): the stride of the convolution\n",
+ "* `Dropout`: defines a dropout layer. The fraction of neuron weights that are set to zero. Typically, this is used when the model is overfitting -- i.e., when the validation loss as a function of epoch is consistently higher than the training loss as a function of epoch (Please see Figure 6 as an example).\n",
+ "* `Linear`: defines a linear layer. Two inputs are considered here:\n",
+ " * `in_features` (required): the size of the sample input to the layer.\n",
+ " * `out_features` (required): the size of the sample output from the layer.\n",
+ "\n",
+ "The function `forward` defines the order of operations during a forward pass of the model. During training, the `forward` function is applied to the input data to make predictions. After each round of predictions (epoch), the optimizer is engaged to take the difference between the true labels and the predicted labels and then use that difference to update the model weights. \n",
+ "\n",
+ "The `forward` function uses the layers defined in the constructor, as well as other layers that don't require inputs that depend on the data. These layers are defined in the `torch.nn.functional` submodule, which contains predefined functions for layers that operate directly on the data and don't require an instance of that layer. These `functional` layers are \n",
+ "* `relu`: applies the `ReLU` activation function. It requires one input, the sample from the previous layer.\n",
+ "* `max_pool2d`: the max pooling function is applied to the sample from the previous layer. It requires the input sample and the size of the kernel of the pooling.\n",
+ "* `flatten`: reshapes the sample input into a one-dimensional tensor."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.4. Define the object class that represents the model "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class ConvNet(nn.Module):\n",
+ " def __init__(self):\n",
+ " super(ConvNet, self).__init__()\n",
+ " self.conv1 = nn.Conv2d(1, 32, 3, 1)\n",
+ " self.conv2 = nn.Conv2d(32, 64, 3, 1)\n",
+ " self.dropout1 = nn.Dropout(0.25)\n",
+ " self.dropout2 = nn.Dropout(0.5)\n",
+ " self.fc1 = nn.Linear(9216, 128)\n",
+ " self.fc2 = nn.Linear(128, 10)\n",
+ "\n",
+ " def forward(self, x):\n",
+ " x = self.conv1(x)\n",
+ " x = F.relu(x)\n",
+ " x = self.conv2(x)\n",
+ " x = F.relu(x)\n",
+ " x = F.max_pool2d(x, 2)\n",
+ " x = self.dropout1(x)\n",
+ " x = torch.flatten(x, 1)\n",
+ " x = self.fc1(x)\n",
+ " x = F.relu(x)\n",
+ " x = self.dropout2(x)\n",
+ " x = self.fc2(x)\n",
+ " output = x\n",
+ " return output"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Instantiate a neural network model object."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model = ConvNet()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Define the device. This is important especially when a GPU is available. This is necessary because the model and the data get moved to that device.\n",
+ "\n",
+ "In our case, the device is a CPU because that's what is currently available on the RSP."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "device = torch.device('cuda') if torch.cuda.is_available()\\\n",
+ " else torch.device('cpu')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Put the model on the device where the computations will be performed.\n",
+ "\n",
+ "When placing the model on the device, it also shows a summary of the network architecture. Examine the shapes of the layers and the number of parameters in each layer. Too few parameters may prevent the model from being flexible enough to model the data. Too many parameters could lead to overfitting of the model (e.g., 'memorizing' the training data) and an unnecessarily high computational cost. Typically, models range from thousands to millions of parameters. There is an interplay between model size (number of parameters), the amount of training data, and the complexity of the images in the training data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"Model Summary:\\n\")\n",
+ "model.to(device)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.5. Glossary: hyperparameters for the training schedule"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* `learning rate`: A multiplicative factor defining the amount that the model weights will change in response to the size of the error (loss) in the model prediction for that epoch. The lower the learning rate, the smaller the change to the weights, and usually the longer it will take to train the model. However, if the learning rate is too high, the weights can change too quickly: then, the loss can fluctuate significantly and not decrease quickly.\n",
+ "* `momentum`: A multiplicative factor on the aggregate of previous gradients. This aggregate term is combined with the weight gradient term to define the total change in the value of the weights. The smaller the momentum, the lesser the influence of the aggregated gradients, and usually the longer it will take train the model.\n",
+ "* `optimizer`: The method/algorithm used to update the network weights. Stochastic Gradient Descent (SGD) is the most commonly used method.\n",
+ "* `epoch`: One loop of training the model. Each loop includes the entire data set (all the batches) once, and it includes at least one round of weight updates.\n",
+ "* `n_epochs`: The number of epochs to train the network."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 3.2.6. Assign hyperparameters for the training schedule"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "learning_rate = 0.01\n",
+ "momentum = 0.9\n",
+ "optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=momentum)\n",
+ "n_epochs = 50"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 3.3. Train the model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set the model into a training context. This ensures that layers like \"batchnorm\" and \"dropout\" will be activated. In contrast, when the model is set to an evaluation context (later in this tutorial), those layers will be deactivated."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%capture\n",
+ "model.train()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use a loop over epochs to incrementally optimize the network weight parameters. \n",
+ "\n",
+ "Use lists to track the loss values on the training data, the loss values on the testing data, and the accuracy values on the testing data. Define the \"history\" dictionary to hold those lists. We will visualize these later to study the fitting efficacy and generalization capacity of the network.\n",
+ "\n",
+ "For this tutorial, 50 epochs on the medium-memory Rubin server required ~9 min of wall time and ~15min of CPU time."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "zB1OY3o8VWF_",
+ "outputId": "7bdd7e85-cef2-47af-f16b-5f8bbd66f67f"
+ },
+ "outputs": [],
+ "source": [
+ "%%time\n",
+ "time_start = time.time()\n",
+ "\n",
+ "loss_train_list = []\n",
+ "loss_test_list = []\n",
+ "accuracy_test_list = []\n",
+ "\n",
+ "for epoch in np.arange(n_epochs):\n",
+ "\n",
+ " loss_train = 0\n",
+ " for inputs, labels in trainloader:\n",
+ " inputs = inputs.to(device)\n",
+ " labels = labels.to(device)\n",
+ " y_pred = model(inputs)\n",
+ " loss = loss_fn(y_pred, labels)\n",
+ " optimizer.zero_grad()\n",
+ " loss.backward()\n",
+ " optimizer.step()\n",
+ " loss_train += loss.item()\n",
+ "\n",
+ " loss_train /= batch_size\n",
+ "\n",
+ " accuracy_test = 0\n",
+ " loss_test = 0\n",
+ " count_test = 0\n",
+ " for inputs, labels in testloader:\n",
+ " inputs = inputs.to(device)\n",
+ " labels = labels.to(device)\n",
+ " y_pred = model(inputs)\n",
+ " loss = loss_fn(y_pred, labels)\n",
+ " accuracy_test += (torch.argmax(y_pred, 1) == labels).float().sum()\n",
+ " loss_test += loss.item()\n",
+ " count_test += len(labels)\n",
+ "\n",
+ " accuracy_test /= count_test\n",
+ " loss_test /= batch_size\n",
+ "\n",
+ " loss_train_list.append(loss_train)\n",
+ " loss_test_list.append(loss_test)\n",
+ " accuracy_test_list.append(accuracy_test)\n",
+ "\n",
+ " # output = f\"Epoch ({epoch:3d}): accuracy ({accuracy_test*100:.2f} %),\\\n",
+ " output1 = f\"Epoch ({epoch:2d}): accuracy ({accuracy_test*50:.2f} %), \"\n",
+ " output2 = f\"train loss ({loss_train:.4f}), valid loss ({loss_test:.4f})\"\n",
+ " output = output1 + output2\n",
+ " print(output)\n",
+ "\n",
+ "time_end = time.time()\n",
+ "\n",
+ "time_difference = time_end - time_start\n",
+ "\n",
+ "history = {\"loss\": loss_train_list,\n",
+ " \"val_loss\": loss_test_list,\n",
+ " \"accuracy_test\": accuracy_test_list}\n",
+ "\n",
+ "print(f\"Total training time: {time_difference/60.:2.4f} min\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Save model to file: \"pt\" is the common suffix used for pytorch model files. This saves the architecture and weights of the model."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_model_prefix'] + \"_\" + path_dict['run_label']\n",
+ "file_name_final = createFileName(file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_model'],\n",
+ " file_suffix=path_dict['file_model_suffix'],\n",
+ " useuid=True,\n",
+ " verbose=True)\n",
+ "\n",
+ "torch.save(model.state_dict(), file_name_final)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Load the model from a \"pt\" file."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%capture\n",
+ "model.load_state_dict(torch.load(file_name_final, weights_only=False))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-01-14T23:05:09.388295Z",
+ "iopub.status.busy": "2025-01-14T23:05:09.387717Z",
+ "iopub.status.idle": "2025-01-14T23:05:09.481703Z",
+ "shell.execute_reply": "2025-01-14T23:05:09.481106Z",
+ "shell.execute_reply.started": "2025-01-14T23:05:09.388255Z"
+ }
+ },
+ "source": [
+ "Set the model to evaluation mode so that the \"batchnorm\" and \"dropout\" layers are deactivated. This is necessary for consistent inference."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%capture\n",
+ "model.eval()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 4. Diagnosing the Results of Model Training"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this section, you will encounter the following items:\n",
+ "\n",
+ "1. a glossary for diagnostics for model evaluation;\n",
+ "2. how to make predictions with the trained model;\n",
+ "3. basic bulk diagnostic: loss history;\n",
+ "4. basic bulk diagnostic: confusion matrix (CM);\n",
+ "5. basic bulk diagnostic: receiver operator characteristic (ROCH) curve;\n",
+ "6. investigating predictions of individual images."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.1. Glossary: diagnostics and model evaluation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use the following diagnostics to assess the status of the network optimization and efficacy. The [scikit-learn page on metrics and scoring](https://scikit-learn.org/stable/modules/model_evaluation.html) provides a good in-depth reference for these terms.\n",
+ "\n",
+ "Model Predictions:\n",
+ " * `Classification threshold`: The user-chosen value $[0,1]$ that sets the threshold for a positive classification. \n",
+ " * `Probability score`: The output from the classifier neural network. One typically uses the `softmax` activation function in the last layer of the NN to provide an output in the range $[0,1]$.\n",
+ " * `Classification score`: The predicted class label is the class that received the highest probability score.\n",
+ "\n",
+ "Metrics:\n",
+ " * `Loss`: A function of the difference between the true labels and predicted labels.\n",
+ " * `Accuracy`: A rough indicator of model training progress/convergence for balanced datasets. For model performance, use only in combination with other metrics. Avoid this metric when you have unbalanced training datasets. Consider using another metric.\n",
+ " * `True Positive Rate (TPR; \"Recall\")`: Use when false negatives are more expensive than false positives.\n",
+ " * `False Positive Rate (FPR)`: Use when false positives are more expensive than false negatives.\n",
+ " * `Precision`: Use when positive predictions need to be accurate.\n",
+ "\n",
+ "The `Generalization Error` (GE) is the difference in loss when the model is applied to training data versus when applied to validation and test data.\n",
+ "\n",
+ "The `Confusion Matrix` (CM) is a visual representation of the classification accuracy. Each row is the set of predictions for each true value (with one true value per column). Values along the diagonal indicate true positives (correct predictions). Values below the diagonal indicate false positives. Values above the diagonal indicate false negatives. The optimal scenario is one in which the off-diagonal values are all zero.\n",
+ "\n",
+ "The `Receiver Operator Characteristic (ROC) Curve` presents a comparison between the true positive rate (y-axis) and the false positive rate (x-axis) --- for a given false positive rate, the number of true positives that exist. Each point on the curve is for a distinct choice of the Classification threshold for the probability score $[0,1]$: the choice of classification threshold determines which objects are considered correctly classified. The optimal scenario is where the ROC curve is constant at a true positive rate $=1$. If the curve is along the diagonal (lower left to upper right), it indicates that the model performance is equivalent to 50-50 guessing."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.2. Predict classifications with the trained model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Predict classification probabilities on the training, validation, and test sets. Produce both the probabilities of each digit and the top choice for each prediction."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "y_prob_tes, y_choice_tes, y_true_tes, x_tes = predict(testloader, model,\n",
+ " \"test\")\n",
+ "y_prob_val, y_choice_val, y_true_val, x_val = predict(validloader, model,\n",
+ " \"validation\")\n",
+ "y_prob_tra, y_choice_tra, y_true_tra, x_tra = predict(trainloader, model,\n",
+ " \"training\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Print the shapes and verify that the shape of `y_prob_tes` matches the length of the input data `x_tes` and the number of classes. (as in Section 2.4)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f\"The input data has the shape {np.shape(x_tes)}: there the {subset_size}\\\n",
+ " images each image has 28 pixels on a side.\")\n",
+ "print(f\"The predicted probability score array has the shape\\\n",
+ " {np.shape(y_prob_tes)}: there are {subset_size} predictions,\\\n",
+ " with 10 probability scores predicted for each input image.\")\n",
+ "print(f\"The predicted classes array has has the shape {np.shape(y_choice_tes)}:\\\n",
+ " there is one top choice (highest probability score) for each prediction.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Use the `plotPredictionHistogram` function to plot histograms of prediction distributions by class."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Histograms_top_choice\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotPredictionHistogram(y_choice_tra,\n",
+ " y_prediction_b=y_choice_val,\n",
+ " y_prediction_c=y_choice_tes,\n",
+ " label_a=\"Training Set\",\n",
+ " label_b=\"Validation Set\",\n",
+ " label_c=\"Testing Set\",\n",
+ " figsize=(12, 5),\n",
+ " alpha=0.5,\n",
+ " xlabel_plot=\"Predicted class label\",\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 4: Histograms of the number of images for which the top-choice class was each number 0 through 9. Each histogram is for a different data set used during model training --- training data, validation data, and test data. Note that these are overlapping histograms, not stacked. Please compare to Figure 3, which shows the distributions of true class labels for each data set. Consider which classes are represented differently between the true labels and the predicted labels."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"Histograms_class_probabilities\"\\\n",
+ " + \"_\" + path_dict['run_label']\n",
+ "\n",
+ "plotPredictionHistogram(y_prob_tra,\n",
+ " y_prediction_b=y_prob_val,\n",
+ " y_prediction_c=y_prob_tes,\n",
+ " title_a='Training Set',\n",
+ " title_b='Validation Set',\n",
+ " title_c='Testing Set',\n",
+ " figsize=(15, 4),\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 5: Histograms of the number of images (y-axis) that had a probability (x-axis) of being each class 0 through 9 (light to dark shades)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In both of Figure 3 and 4, the histograms show very similar shapes across the classification categories.\n",
+ "This is a good sign because it indicates the model is not heavily biased toward a particular class."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.3. Loss History: History of Loss and Accuracy during Training"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The primary task in optimizing a network is to minimize the Generalization Error. Plot the loss history for the validation and training sets. We reserve the test set for a 'blind' analysis."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"LossHistory\"\\\n",
+ " + \"_\"\\\n",
+ " + path_dict['run_label']\n",
+ "\n",
+ "plotLossHistory(history,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 6: The loss histories for the training and validation data sets and the loss residual history between the training and the validation set. Top panel: the loss history as a function of epoch for the training and validation sets decreases with time, as it should as the model fit improves. There is slight difference between the validation and the training. Bottom panel: the loss residual (validation loss minus training loss) shows a minimum near epoch 34, indicating the model-fitting underwent a divergence between the classifications, but that this was rectified in later epochs. For epochs 10 to 44, the difference between validation and training data indicates that the validation data may not have been represeentative of the training data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Another pattern you may encounter is when the validation loss is consistently higher than the training loss. This typically indicates overfitting, which is when the model is complex enough to fit (sometimes, the term 'memorize' is used) all the details of the training data and not generalize enough to also fit the validation data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2024-10-26T18:50:41.751869Z",
+ "iopub.status.busy": "2024-10-26T18:50:41.751239Z",
+ "iopub.status.idle": "2024-10-26T18:50:41.757103Z",
+ "shell.execute_reply": "2024-10-26T18:50:41.756503Z",
+ "shell.execute_reply.started": "2024-10-26T18:50:41.751843Z"
+ }
+ },
+ "source": [
+ "### 4.4. Confusion Matrix: Bias in Trained Model?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Compute and plot the confusion matrices for the training, validation, and test samples (left, right, middle)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "classes = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')\n",
+ "figsize = (15, 3)\n",
+ "linewidths = 0.01\n",
+ "linecolor = 'white'\n",
+ "ylabel = \"Predicted Label\"\n",
+ "xlabel = \"True Label\"\n",
+ "\n",
+ "cm_tra = confusion_matrix(y_true_tra, y_choice_tra)\n",
+ "cm_val = confusion_matrix(y_true_val, y_choice_val)\n",
+ "cm_tes = confusion_matrix(y_true_tes, y_choice_tes)\n",
+ "\n",
+ "df_cm_tra = pd.DataFrame(cm_tra / np.sum(cm_tra, axis=1)[:, None],\n",
+ " index=[i for i in classes],\n",
+ " columns=[i for i in classes])\n",
+ "df_cm_val = pd.DataFrame(cm_val / np.sum(cm_val, axis=1)[:, None],\n",
+ " index=[i for i in classes],\n",
+ " columns=[i for i in classes])\n",
+ "df_cm_tes = pd.DataFrame(cm_tes / np.sum(cm_tes, axis=1)[:, None],\n",
+ " index=[i for i in classes],\n",
+ " columns=[i for i in classes])\n",
+ "\n",
+ "fig, (axa, axb, axc) = plt.subplots(1, 3, figsize=figsize)\n",
+ "fig.subplots_adjust(wspace=0.5)\n",
+ "\n",
+ "ax1 = sns.heatmap(df_cm_tra, annot=False, linewidths=linewidths,\n",
+ " linecolor=linecolor, square=True, ax=axa)\n",
+ "_ = ax1.set(xlabel=xlabel, ylabel=ylabel, title=\"Training Data\")\n",
+ "\n",
+ "ax2 = sns.heatmap(df_cm_val, annot=False, linewidths=linewidths,\n",
+ " linecolor=linecolor, square=True, ax=axb)\n",
+ "_ = ax2.set(xlabel=xlabel, ylabel=ylabel, title=\"Validation Data\")\n",
+ "\n",
+ "ax3 = sns.heatmap(df_cm_tes, annot=False, linewidths=linewidths,\n",
+ " linecolor=linecolor, square=True, ax=axc)\n",
+ "_ = ax3.set(xlabel=xlabel, ylabel=ylabel, title=\"Test Data\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 7: Confusion matrices for the training, validation, and test data sets (left to right). Each cell in the matrix shows the fraction (see the color bars) of the total objects with that true label that have been predicted to be a given label. The diagonal represents images that were correctly classified. All off-diagonal cells represent false positives (lower left) or false negatives (upper right). Consider some examples. First, the class \"0\" is almost always predicted to be \"0\" with a lighter color in the top-most, left-most cell; all the other cells in the column are completely dark. Second, consider the cell that represents a prediction \"4\", when the true label is \"9\": that cell is not completely dark. A \"4\" has a similar morphology or shape as a \"9.\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 4.5. Receiver Operator Characteristic (ROC) Curve: Trade-offs between Completeness and Purity"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The Receiver Operator Characteristic (ROC) Curve is a plot of the True Positive Rate (TPR; y axis) versus the False Positive Rate (FPR; x axis).\n",
+ "\n",
+ "For a given classification threshold on the probability (canonically, 0.5), the balance of true positives and false positives will change."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ROCCurve\"\\\n",
+ " + \"_\"\\\n",
+ " + path_dict['run_label']\n",
+ "\n",
+ "plotROCMulticlassOnevsrest(y_tra, y_tes, y_prob_tes,\n",
+ " save_file=True,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 8: ROC curve for classification of one digit (class) against the remaining nine digits (classes). All of the curves show a very high AUC, which means near-perfect classification. The black dashed line shows an ROC curve representing a 50-50 guess. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "vvAqrZwjVYBt"
+ },
+ "source": [
+ "### 4.5. Investigating predictions in detail"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 4.5.1. Glossary: classification metrics"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2025-01-26T21:19:35.897282Z",
+ "iopub.status.busy": "2025-01-26T21:19:35.896488Z",
+ "iopub.status.idle": "2025-01-26T21:19:36.705672Z",
+ "shell.execute_reply": "2025-01-26T21:19:36.705022Z",
+ "shell.execute_reply.started": "2025-01-26T21:19:35.897242Z"
+ }
+ },
+ "source": [
+ "Consider the example of true class label being \"2\". Then, we define the following metrics.\n",
+ "\n",
+ "* `True Positive (TP)`: correctly classified input digit image --- e.g., a \"2\" classified as \"2\".\n",
+ "* `False Positive (FP)`: another digit classified as \"2\".\n",
+ "* `True Negative (TN)`: another digit classified as another digit.\n",
+ "* `False Negative (FN)`: a \"2\" classified as something other than \"2\"."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 4.5.2. Explore the classification of the training data for an example class value"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Investigate the case in which the true digit label is \"2\"."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class_value = 2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Find all objects that have that class value. Obtain indices for the TP's, FP's, TN's, and FN's. Create subsets of the data according to those indices."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ind_class_tp_tra = np.where((y_true_tra == class_value)\n",
+ " & (y_choice_tra == class_value))[0]\n",
+ "\n",
+ "ind_class_fp_tra = np.where((y_true_tra != class_value)\n",
+ " & (y_choice_tra == class_value))[0]\n",
+ "\n",
+ "ind_class_tn_tra = np.where((y_true_tra != class_value)\n",
+ " & (y_choice_tra != class_value))[0]\n",
+ "\n",
+ "ind_class_fn_tra = np.where((y_true_tra == class_value)\n",
+ " & (y_choice_tra != class_value))[0]\n",
+ "\n",
+ "x_tra_tp = x_tra[ind_class_tp_tra]\n",
+ "y_true_tra_tp = y_true_tra[ind_class_tp_tra]\n",
+ "y_choice_tra_tp = y_choice_tra[ind_class_tp_tra]\n",
+ "\n",
+ "x_tra_fp = x_tra[ind_class_fp_tra]\n",
+ "y_true_tra_fp = y_true_tra[ind_class_fp_tra]\n",
+ "y_choice_tra_fp = y_choice_tra[ind_class_fp_tra]\n",
+ "\n",
+ "x_tra_tn = x_tra[ind_class_tn_tra]\n",
+ "y_true_tra_tn = y_true_tra[ind_class_tn_tra]\n",
+ "y_choice_tra_tn = y_choice_tra[ind_class_tn_tra]\n",
+ "\n",
+ "x_tra_fn = x_tra[ind_class_fn_tra]\n",
+ "y_true_tra_fn = y_true_tra[ind_class_fn_tra]\n",
+ "y_choice_tra_fn = y_choice_tra[ind_class_fn_tra]\n",
+ "\n",
+ "n_tp = len(ind_class_tp_tra)\n",
+ "n_fp = len(ind_class_fp_tra)\n",
+ "n_tn = len(ind_class_tn_tra)\n",
+ "n_fn = len(ind_class_fn_tra)\n",
+ "\n",
+ "print(f\"TP count: {n_tp:4d}\")\n",
+ "print(f\"FP count: {n_fp:4d}\")\n",
+ "print(f\"TN count: {n_tn:4d}\")\n",
+ "print(f\"FN count: {n_fn:4d}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if n_tp > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_TruePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayImageConfusion(x_tra_tp,\n",
+ " y_true_tra_tp,\n",
+ " y_choice_tra_tp,\n",
+ " title_main=\"True Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_fp > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_FalsePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayImageConfusion(x_tra_fp,\n",
+ " y_true_tra_fp,\n",
+ " y_choice_tra_fp,\n",
+ " title_main=\"False Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_tn > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_TrueNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayImageConfusion(x_tra_tn,\n",
+ " y_true_tra_tn,\n",
+ " y_choice_tra_tn,\n",
+ " title_main=\"True Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_fn > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix'] + \"_\"\\\n",
+ " + \"ExampleImages_FalseNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayImageConfusion(x_tra_fn,\n",
+ " y_true_tra_fn,\n",
+ " y_choice_tra_fn,\n",
+ " title_main=\"False Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 9: Four panels of 10 images each, representing true positives (top), false positives (second), true negatives (third), and false negatives (bottom), for classification category 2.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Plot histograms of images pixels of true positives, false positives, true negatives, and false negatives."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if n_tp > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_TruePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayHistogramConfusion(x_tra_tp,\n",
+ " y_true_tra_tp,\n",
+ " y_choice_tra_tp,\n",
+ " title_main=\"True Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_fp > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_FalsePostives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayHistogramConfusion(x_tra_fp,\n",
+ " y_true_tra_fp,\n",
+ " y_choice_tra_fp,\n",
+ " title_main=\"False Positives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_tn > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_TrueNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayHistogramConfusion(x_tra_tn,\n",
+ " y_true_tra_tn,\n",
+ " y_choice_tra_tn,\n",
+ " title_main=\"True Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])\n",
+ "\n",
+ "if n_fn > 0:\n",
+ " file_prefix = path_dict['file_figure_prefix']\\\n",
+ " + \"_\" + \"ExampleImages_FalseNegatives_on_class_\"\\\n",
+ " + str(class_value) + \"_\" + path_dict['run_label']\n",
+ " plotArrayHistogramConfusion(x_tra_fn,\n",
+ " y_true_tra_fn,\n",
+ " y_choice_tra_fn,\n",
+ " title_main=\"False Negatives\",\n",
+ " num=10,\n",
+ " file_prefix=file_prefix,\n",
+ " file_location=path_dict['dir_data_figures'],\n",
+ " file_suffix=path_dict['file_figure_suffix'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 10: Histograms of the pixel flux values for the images shown in Figure 8. Here, it is difficult to infer reasons for network classification errors like false positives and false negatives. If it is expected that a particular would have a particular distribution of pixel brightnesses, but the histogram for the predicted digit has a different distribution, that may help you identify a pattern. This may be a more useful diagnostic for physics-related data, like galaxy light profiles."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### 4.5.3. Investigate morphological features of images with feature maps"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The last diagnostic of this tutorial is the `feature map`, which shows how that one layer affects or processes the input image after the weights have been set during the model training. The morphological elements in the feature maps are the image regions that are highlighed by the earliest layers of convolution and activation functions.\n",
+ "\n",
+ "The feature map is obtained by passing an input image through one layer of the trained neural network model. More specifically, we first choose an input datum (image) by setting the array index of interest. Then, we make the image a `tensor` with the appropriate number of dimensions using `unsqueeze`. Then, we transfer it to the `device`. Next, we choose the `conv1` layer defined the section above where we defined the `model`. Finally, we use the number of convolutional kernels (32) that exist in the `conv1` layer of the model. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "index_input_image = 1\n",
+ "number_conv_kernels = 32\n",
+ "\n",
+ "input_image = dataset.data[index_input_image].type(torch.float32)\n",
+ "input_image = input_image.clone().detach()\n",
+ "input_image = input_image.unsqueeze(0)\n",
+ "input_image = input_image.to(device)\n",
+ "\n",
+ "with torch.no_grad():\n",
+ " feature_maps = model.conv1(input_image).cpu()\n",
+ "\n",
+ "fig, ax = plt.subplots(4, 8, sharex=True, sharey=True, figsize=(16, 8))\n",
+ "\n",
+ "for i in range(0, number_conv_kernels):\n",
+ " row, col = i//8, i%8\n",
+ " ax[row][col].imshow(feature_maps[i])\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> Figure 11: `Feature maps` of one input from the `conv1` layer of the `model`. The units on the x- and y-axes are the pixel indices. There are 32 images because there are 32 convolutional kernels in the `conv1` layer.\n",
+ ">\n",
+ "> The feature maps derived from the trained model show which morphological features --- e.g., lines and edges --- are favored by the model. When the model is accurate, these features and feature maps will accurately reflect the input image. In this example, the handwritten digit is \"0,\" and the feature maps all appear as \"0's\". Some maps have more clearly defined edges and \"0\"-like features than others, because each convolutional kernel has a distinct weight parameter associated with it. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 5. Exercises for the Learner"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Each time you train a new model, re-run all the diagnostic plots.\n",
+ "\n",
+ "1. How do the loss and accuracy histories change when batch size is small or large? Why?\n",
+ "2. Does the NN take more or less time (more or fewer epochs) to converge if the input image data are normalized or not normalized? Why?\n",
+ "3. How does the size of the training set affect the model's accuracy and loss -- keeping the number of epochs the same? Why?\n",
+ "3. How does the random seed for the weight initialization affect the model's accuracy and loss -- keeping the number of epochs the same?\n",
+ "5. Increase and then decrease the number of weights in the NN by an order of magnitude. Train the NN for each of those models and record the times. How does the number of weights in the neural network affect the training time and model loss and accuracy?\n",
+ "6. Increase and then decrease the number of layers in the NN. Train the NN for each of those models and record the times. How does the number of weights in the neural network affect the training time and model loss and accuracy?\n",
+ "7. Make new ROC curves using the validation data and the training data. Are the results consistent with those from the test data?\n",
+ "8. Change the pytorch random seed, and re-run the training and model evaluation. Have the results changed?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "accelerator": "GPU",
+ "colab": {
+ "gpuType": "T4",
+ "machine_shape": "hm",
+ "provenance": []
+ },
+ "kernelspec": {
+ "display_name": "LSST",
+ "language": "python",
+ "name": "lsst"
+ },
+ "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.12.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}