{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## How does a neural net really work\n", "\n", "In this notebook I'm exploring fast.ai's Kaggle notebook on [\"How does a neural net really work\"](https://www.kaggle.com/code/jhoward/how-does-a-neural-net-really-work). This relates to [Lesson 3 of the fast.ai Deep Learning course](https://course.fast.ai/Lessons/lesson3.html). While the video provides a solid explanation, the enigmatic imports and variables can be difficult to comprehend. I'm reimplementing some sections to see if if sticks. In a nutshell, this is what is happening in this notebook:\n", "\n", "1. Revising Regressions \n", " - Plot a generic quadratic function ($ax^2 + bx + c$) \n", " - Generate some random data points \n", " - Learn the step-by-step process to find the values of `a`, `b`, and `c` that make our function represent the random data generated in `2` \n", " - Use the [mean absolute error](https://docs.fast.ai/metrics.html#mae) to manually adjust `a`, `b`, and `c`. \n", "2. Understand and break down the Gradient Descent algorithm\n", "3. The Basics of a Neural-Network\n", " - Understand what is a ReLU\n", " - Create the simplest neural-network possible" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2025-02-26T21:17:08.144649Z", "iopub.status.busy": "2025-02-26T21:17:08.144181Z", "iopub.status.idle": "2025-02-26T21:17:09.907835Z", "shell.execute_reply": "2025-02-26T21:17:09.907012Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Note: you may need to restart the kernel to use updated packages.\n" ] } ], "source": [ "# Installing the dependencies within the notebook to make it easier to run on colab\n", "%pip install -Uqq fastai ipywidgets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Revising Regressions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.1 Plot a generic quadratic function ($ax^2+bx+c$)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2025-02-26T21:17:09.941482Z", "iopub.status.busy": "2025-02-26T21:17:09.941171Z", "iopub.status.idle": "2025-02-26T21:17:11.643434Z", "shell.execute_reply": "2025-02-26T21:17:11.643073Z" } }, "outputs": [], "source": [ "from fastai.basics import torch, plt\n", "\n", "# Set the figure DPI to 90 for better resolution\n", "plt.rc('figure', dpi=90)\n", "\n", "# Function to plot a mathematical function over a range\n", "def plot_function(f, title=None, min=-2.1, max=2.1, color='r', ylim=None):\n", " # Create evenly spaced x values as a column vector\n", " x = torch.linspace(min,max, 100)[:,None]\n", " # Set y-axis limits if specified\n", " if ylim: plt.ylim(ylim)\n", " # Plot the function\n", " plt.plot(x, f(x), color)\n", " # Add title if provided\n", " if title is not None: plt.title(title)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2025-02-26T21:17:11.645196Z", "iopub.status.busy": "2025-02-26T21:17:11.645028Z", "iopub.status.idle": "2025-02-26T21:17:11.771311Z", "shell.execute_reply": "2025-02-26T21:17:11.770998Z" } }, "outputs": [ { "data": { "image/png": "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WWd5B4/Vrl1bEydOVLQhqOeCnSg3cOBArVu3TqtXr1bx4sXVrl07v4cVN/Lnz69rr71WM2fO9HsocWXo0KGaP3++Vq5cqRUrVmjevHnemQ2IDHsRO2jQIC+wIPLS09NVvnx5zZkzRzt37tSkSZN033336YMPPlA0YZ96GHz11Vdq2LCh90quQIGwttPHCVimvmzZMjVo0MDvoQSenaI4evRob2bKTJs2TQMGDNDatWv9HlpcSUpK8maneFHrv9atW+vcc8/VkCFDFC3I1MPg448/9g6mIaAjqLZt2+YtMR354snup6SkeDNXQLzZu3evFi9erHr16imaENSPcf3113vZX3bXmjVrjnq8ZYl24pxlMIj89x+RkZqa6t2WLFny0Psy7+/atcu3cQF+yMjI8I4KP/vss71sPZqQWh7jtddeU1paWrb/bgVCmb7++mu1bNnSK2C55pprIjTCYMvJ9x+Rk5iY6N1aVn766acfum+saAiIp4Deu3dvrVq1yltftxqfaEJQP4YVvYXCAvrVV1+t4cOHe2fBI7Lff0SWVbxXrFjRW8utXr269z67b+vsJUqU8Ht4QMQC+t13363PPvtMc+fOjcrf/eh6iREjrPLXArpVA3ft2tXv4cTtepZdxjJ7u3/w4EG/hxVo9ruenJysjRs3epdVvtsUJCJXfW2/53Zrv+t2/3izWgg/29K5YMECzZ4923uhG42ofs/lk9srr7yiIkWKHPV+2+pTuXJl38YVT2x9/VgffvihmjVr5st44mWf+j333OMtkRibobJaEgpEI1f1Pnjw4KPed/nll+ujjz7ybUzxZO3atapatarXJ+DI33n7Oxg/fryiBUEdAICAYPodAICAIKgDABAQBHUAAAKCoA4AQEAQ1AEACAiCOgAAAUFQBwAgIAjqAAAEBEEdAICAIKgDAKBg+D8ekl9LtSjtiwAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Function with quadratic expression ax^2 + bx + c\n", "def quad(a, b, c, x): return a*x**2 + b*x + c\n", "\n", "from functools import partial\n", "# Creates a new function with fixed a,b,c parameters, leaving only x variable\n", "# This allows us to create specific quadratic functions by \"fixing\" the coefficients\n", "def mk_quad(a,b,c): return partial(quad, a,b,c)\n", "\n", "def demo_plot_basic_quadratic():\n", " a = 3\n", " b = 2\n", " c = 1\n", " f = mk_quad(a, b ,c)\n", " plot_function(f, title=f'${a}x^2 + {b}x + {c}$')\n", "\n", "demo_plot_basic_quadratic()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.2. Generate some random data points" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2025-02-26T21:17:11.772794Z", "iopub.status.busy": "2025-02-26T21:17:11.772676Z", "iopub.status.idle": "2025-02-26T21:17:11.822864Z", "shell.execute_reply": "2025-02-26T21:17:11.822595Z" } }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Add both multiplicative and additive noise to input x\n", "def add_noise(x, mult, add): return x * (1+torch.randn(x.shape) * mult) + torch.randn(x.shape) * add\n", "\n", "def generate_noisy_data(f, x_start=-2, x_end=2, num_datapoints=20, noise_mult=0.15, noise_add=0.15, seed=42):\n", " # Define a static seed, so that the random data is always the same every time we run this\n", " torch.manual_seed(seed)\n", " # Create evenly spaced x values and add a dimension of size 1 at position 1,\n", " # transforming shape from (20,) to (20,1) to make it a column vector\n", " # Example: tensor([1,2,3]) shape=(3,) -> tensor([[1],[2],[3]]) shape=(3,1)\n", " x = torch.linspace(x_start, x_end, steps=num_datapoints).unsqueeze(1) \n", " # Generate noisy y values by applying noise to function output\n", " # mult=0.15 for multiplicative noise, add=1.5 for additive noise\n", " y = add_noise(f(x), noise_mult, noise_add)\n", " return x, y\n", "\n", "def demp_plot_random_data():\n", " x,y = generate_noisy_data(mk_quad(3,2,1))\n", " plt.scatter(x,y);\n", "\n", "demp_plot_random_data()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.3. Fit the function to the data\n", "\n", "In this section, we will explore the step-by-step process to find the values of `a`, `b`, and `c` that allow our function to accurately reflect the random data generated in `1.2`. The interactive plot below, shows how adjustments to `a`, `b`, and `c` influence the function's shape to better align with our data layout." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2025-02-26T21:17:11.824384Z", "iopub.status.busy": "2025-02-26T21:17:11.824261Z", "iopub.status.idle": "2025-02-26T21:17:11.900687Z", "shell.execute_reply": "2025-02-26T21:17:11.900408Z" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "52dcc224eb5f498a860d45227c52bf68", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(FloatSlider(value=1.5, description='a', max=4.5, min=-1.5), FloatSlider(value=1.5, descr…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from ipywidgets import interact\n", "@interact(a=1.5, b=1.5, c=1.5)\n", "def demo_interactive_plot_quad(a, b, c):\n", " plt.close('all') # Close all existing figures\n", " plt.figure() # Create a new figure\n", " x,y = generate_noisy_data(mk_quad(3,2,1))\n", " \n", " plt.scatter(x,y)\n", " plot_function(mk_quad(a,b,c), ylim=(0,13))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.4 Measure the error\n", "\n", "This is cool and works, but we need to know how close we are to our ideal solution. In regression, we can use fun ways to estimate this, like the \"Mean Absolute Error,\" which averages the distance between predicted and actual values.\n", "\n", "The [fastai library has a wrapper for some of the most common methods](https://docs.fast.ai/metrics.html#regression) (from [scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_absolute_error.html)).\n", "\n", "Here's a quick demo where we can see how it is calculated." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2025-02-26T21:17:11.903408Z", "iopub.status.busy": "2025-02-26T21:17:11.903326Z", "iopub.status.idle": "2025-02-26T21:17:11.906820Z", "shell.execute_reply": "2025-02-26T21:17:11.906569Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mean Absolute Error: 0.150\n", "\n", "Absolute differences between predictions and actuals:\n", "Prediction: 1.0, Actual: 1.1, Absolute Difference: 0.100\n", "Prediction: 2.0, Actual: 2.1, Absolute Difference: 0.100\n", "Prediction: 3.0, Actual: 2.8, Absolute Difference: 0.200\n", "Prediction: 4.0, Actual: 4.2, Absolute Difference: 0.200\n" ] } ], "source": [ "def mean_absolute_error(preds, acts): return (torch.abs(preds-acts)).mean()\n", "\n", "def demo_mean_absolute_error():\n", " # Create some example predictions and actual values\n", " preds = torch.tensor([1.0, 2.0, 3.0, 4.0])\n", " actuals = torch.tensor([1.1, 2.1, 2.8, 4.2])\n", "\n", " # Calculate and print the mean absolute error\n", " error = mean_absolute_error(preds, actuals)\n", " print(f\"Mean Absolute Error: {error:.3f}\")\n", "\n", " # Let's break down what's happening:\n", " print(\"\\nAbsolute differences between predictions and actuals:\")\n", " abs_diffs = torch.abs(preds-actuals)\n", " for i, (p, a, d) in enumerate(zip(preds, actuals, abs_diffs)):\n", " print(f\"Prediction: {p:.1f}, Actual: {a:.1f}, Absolute Difference: {d:.3f}\")\n", "\n", "demo_mean_absolute_error()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2025-02-26T21:17:11.908071Z", "iopub.status.busy": "2025-02-26T21:17:11.907979Z", "iopub.status.idle": "2025-02-26T21:17:11.956174Z", "shell.execute_reply": "2025-02-26T21:17:11.955905Z" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e6814ad990f24ac191751b113096e580", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(FloatSlider(value=1.5, description='a', max=4.5, min=-1.5), FloatSlider(value=1.5, descr…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@interact(a=1.5, b=1.5, c=1.5)\n", "def plot_quad(a, b, c):\n", " x,y = generate_noisy_data(mk_quad(3,2,1))\n", "\n", " f = mk_quad(a, b ,c)\n", " plt.scatter(x,y)\n", " loss = mean_absolute_error(f(x), y)\n", " plot_function(f, ylim=(0,13), title=f\"MAE: {loss:.2f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Understand and break down the Gradient Descent algorithm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we can calculate the mean absolute error, the next step is to understand how to adjust our parameters `a`, `b`, and `c` to *reduce* this error. To do this, we can think about the *gradients* of the error with respect to each of the `a,b,c` parameters.\n", "\n", "👉 If you were walking on a hill (representing the error surface), the partial derivative with respect to one direction (say, the 'a' direction) tells you the slope of the hill in *that specific direction*. A steep *slope/gradient* means a large change in error for a small change in 'a'.\n", "\n", "For example, if we consider the partial derivative of the mean absolute error with respect to `a` (while keeping `b` and `c` fixed), a negative value would indicate that increasing `a` will lead to a *decrease* in the error (like walking forward-downhill in the 'a' direction). Conversely, a positive value would suggest that decreasing `a` would reduce the error (ackwardly walking backwards-downhill in the 'a' direction 😄). \n", "\n", "\n", "---\n", "\n", "With PyTorch we can use the `require_grad=True` on tensors and it automatically handles the differentiation and the calculation of the *gradients* for us. Which tbh looks a bit like dark magic. Let's use AI to understand how it works by doing two Example on a function like $f(x) = m*x + b$ , and two different inputs (`x1` and `x2`)🕵️‍♂️" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Example 1 | x: tensor([1., 2., 3.]), m: 2.0, b: 1.0\n", "Example 1 | Gradient with respect to m1 (m1.grad): tensor(6.)\n", "Example 1 | Gradient with respect to b1 (b1.grad): tensor(3.)\n", "--------------\n", "Example 2 | x: tensor([1., 4.]), m: 2.0, b: 1.0\n", "Example 2 | Gradient with respect to m2 (m2.grad): tensor(5.)\n", "Example 2 | Gradient with respect to b2 (b2.grad): tensor(2.)\n", "--------------\n", "\n", "Explanation:\n", "- **Example 1:**\n", " - We start with a list of numbers: x1 = [1.0, 2.0, 3.0].\n", " - We plug each number into our function, which means we multiply it by m (let's say m = 2) and then add b (let's say b = 1):\n", " - For 1.0: f(1.0) = 2 * 1 + 1 = 3\n", " - For 2.0: f(2.0) = 2 * 2 + 1 = 5\n", " - For 3.0: f(3.0) = 2 * 3 + 1 = 7\n", " - So, we end up with y1 = [3.0, 5.0, 7.0].\n", " - Then, we add these numbers together: 3 + 5 + 7 = 15.\n", " - If we look at our equation, we can say: total1 = m1*(1.0+2.0+3.0) + b1*3 = 6 * m1 + 3 * b1.\n", " - Now, when we want to see how changing m1 and b1 affects total1, we find:\n", " - Changing m1 gives us a \"gradient\" of 6.\n", " - Changing b1 gives us a \"gradient\" of 3.\n", " - So, m1.grad = 6.0 and b1.grad = 3.\n", "\n", "- **Example 2:**\n", " - Now we have a different list: x2 = [1.0, 4.0].\n", " - We use the same m and b:\n", " - For 1.0: f(1.0) = 3 (same as before).\n", " - For 4.0: f(4.0) = 2 * 4 + 1 = 9.\n", " - So, now we have y2 = [3.0, 9.0].\n", " - We add these: 3 + 9 = 12.\n", " - In terms of our equation, total2 = m2*(1.0+4.0) + b2*2 = 5 * m2 + 2 * b2.\n", " - For the gradients:\n", " - Changing m2 gives us a \"gradient\" of 5.\n", " - Changing b2 gives us a \"gradient\" of 2.\n", " - So, m2.grad = 5.0 and b2.grad = 2.\n", "\n" ] } ], "source": [ "#########################################\n", "# Example 1: Using x1 = [1.0, 2.0, 3.0]\n", "#########################################\n", "x1 = torch.tensor([1.0, 2.0, 3.0])\n", "m1 = torch.tensor(2.0, requires_grad=True)\n", "b1 = torch.tensor(1.0, requires_grad=True)\n", "\n", "# Compute f(x1) = m1 * x1 + b1\n", "y1 = m1 * x1 + b1\n", "total1 = y1.sum() # total1 = m1*(1+2+3) + b1*3 = 6*m1 + 3*b1\n", "\n", "# Compute gradients for m1 and b1.\n", "total1.backward()\n", "\n", "print(f'Example 1 | x: {x1}, m: {m1}, b: {b1}')\n", "print(\"Example 1 | Gradient with respect to m1 (m1.grad):\", m1.grad) # Expected: sum(x1) = 6.0\n", "print(\"Example 1 | Gradient with respect to b1 (b1.grad):\", b1.grad) # Expected: len(x1) = 3\n", "print(\"--------------\")\n", "\n", "#########################################\n", "# Example 2: Using x2 = [1.0, 4.0] (different size and values)\n", "#########################################\n", "x2 = torch.tensor([1.0, 4.0])\n", "m2 = torch.tensor(2.0, requires_grad=True)\n", "b2 = torch.tensor(1.0, requires_grad=True)\n", "\n", "# Compute f(x2) = m2 * x2 + b2\n", "y2 = m2 * x2 + b2\n", "total2 = y2.sum() # total2 = m2*(1+4) + b2*2 = 5*m2 + 2*b2\n", "\n", "# Compute gradients for m2 and b2.\n", "total2.backward()\n", "\n", "print(f'Example 2 | x: {x2}, m: {m2}, b: {b2}')\n", "print(\"Example 2 | Gradient with respect to m2 (m2.grad):\", m2.grad) # Expected: sum(x2) = 5.0\n", "print(\"Example 2 | Gradient with respect to b2 (b2.grad):\", b2.grad) # Expected: len(x2) = 2\n", "print(\"--------------\")\n", "\n", "# Print an explanation that details the differentiation steps.\n", "explanation = \"\"\"\n", "Explanation:\n", "- **Example 1:**\n", " - We start with a list of numbers: x1 = [1.0, 2.0, 3.0].\n", " - We plug each number into our function, which means we multiply it by m (let's say m = 2) and then add b (let's say b = 1):\n", " - For 1.0: f(1.0) = 2 * 1 + 1 = 3\n", " - For 2.0: f(2.0) = 2 * 2 + 1 = 5\n", " - For 3.0: f(3.0) = 2 * 3 + 1 = 7\n", " - So, we end up with y1 = [3.0, 5.0, 7.0].\n", " - Then, we add these numbers together: 3 + 5 + 7 = 15.\n", " - If we look at our equation, we can say: total1 = m1*(1.0+2.0+3.0) + b1*3 = 6 * m1 + 3 * b1.\n", " - Now, when we want to see how changing m1 and b1 affects total1, we find:\n", " - Changing m1 gives us a \"gradient\" of 6.\n", " - Changing b1 gives us a \"gradient\" of 3.\n", " - So, m1.grad = 6.0 and b1.grad = 3.\n", "\n", "- **Example 2:**\n", " - Now we have a different list: x2 = [1.0, 4.0].\n", " - We use the same m and b:\n", " - For 1.0: f(1.0) = 3 (same as before).\n", " - For 4.0: f(4.0) = 2 * 4 + 1 = 9.\n", " - So, now we have y2 = [3.0, 9.0].\n", " - We add these: 3 + 9 = 12.\n", " - In terms of our equation, total2 = m2*(1.0+4.0) + b2*2 = 5 * m2 + 2 * b2.\n", " - For the gradients:\n", " - Changing m2 gives us a \"gradient\" of 5.\n", " - Changing b2 gives us a \"gradient\" of 2.\n", " - So, m2.grad = 5.0 and b2.grad = 2.\n", "\"\"\"\n", "print(explanation)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can create an interactive plot where we show the gradient on `a`, `b` and `c`. \n", "If the slope is negative we want to move forward (or downhill)." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "cb8257556c124f118636a3e179c48b41", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(FloatSlider(value=1.5, description='a', max=4.5, min=-1.5), FloatSlider(value=1.5, descr…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@interact(a=1.5, b=1.5, c=1.5)\n", "def demo_quadratic_plot_with_gradients(a, b, c):\n", " x,y = generate_noisy_data(mk_quad(3,2,1))\n", " plt.scatter(x,y)\n", "\n", " a_tensor = torch.tensor([float(a)], requires_grad=True)\n", " b_tensor = torch.tensor([float(b)], requires_grad=True)\n", " c_tensor = torch.tensor([float(c)], requires_grad=True)\n", "\n", " f = mk_quad(a_tensor, b_tensor, c_tensor)\n", "\n", " loss = torch.abs(f(x) - y).mean() \n", " loss.backward()\n", "\n", " a_grad = a_tensor.grad.item()\n", " b_grad = b_tensor.grad.item()\n", " c_grad = c_tensor.grad.item()\n", "\n", " plot_function(lambda x: f(x).detach(), ylim=(0,13), title=f\"MAE: {loss:.2f}, dLoss/da: {a_grad:.2f}, dLoss/db: {b_grad:.2f}, dLoss/dc: {c_grad:.2f}\")" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "step=0; loss=3.15; abc=tensor([1.1463, 1.0042, 1.0800], requires_grad=True)\n", "step=1; loss=2.87; abc=tensor([1.2925, 1.0084, 1.1600], requires_grad=True)\n", "step=2; loss=2.59; abc=tensor([1.4388, 1.0126, 1.2400], requires_grad=True)\n", "step=3; loss=2.32; abc=tensor([1.5634, 1.0347, 1.2900], requires_grad=True)\n", "step=4; loss=2.14; abc=tensor([1.6881, 1.0568, 1.3400], requires_grad=True)\n", "step=5; loss=1.96; abc=tensor([1.7993, 1.0905, 1.3800], requires_grad=True)\n", "step=6; loss=1.81; abc=tensor([1.9016, 1.1337, 1.4100], requires_grad=True)\n", "step=7; loss=1.69; abc=tensor([1.9975, 1.1811, 1.4200], requires_grad=True)\n", "step=8; loss=1.57; abc=tensor([2.0933, 1.2284, 1.4300], requires_grad=True)\n", "step=9; loss=1.46; abc=tensor([2.1864, 1.2705, 1.4300], requires_grad=True)\n", "step=10; loss=1.36; abc=tensor([2.2794, 1.3126, 1.4300], requires_grad=True)\n", "step=11; loss=1.26; abc=tensor([2.3725, 1.3547, 1.4300], requires_grad=True)\n", "step=12; loss=1.15; abc=tensor([2.4656, 1.3968, 1.4300], requires_grad=True)\n", "step=13; loss=1.05; abc=tensor([2.5587, 1.4389, 1.4300], requires_grad=True)\n", "step=14; loss=0.94; abc=tensor([2.6517, 1.4811, 1.4300], requires_grad=True)\n", "step=15; loss=0.84; abc=tensor([2.7448, 1.5232, 1.4300], requires_grad=True)\n", "step=16; loss=0.76; abc=tensor([2.7889, 1.5358, 1.4100], requires_grad=True)\n", "step=17; loss=0.74; abc=tensor([2.8330, 1.5484, 1.3900], requires_grad=True)\n", "step=18; loss=0.71; abc=tensor([2.8771, 1.5611, 1.3700], requires_grad=True)\n", "step=19; loss=0.69; abc=tensor([2.9212, 1.5737, 1.3500], requires_grad=True)\n", "step=20; loss=0.68; abc=tensor([2.9155, 1.5863, 1.3100], requires_grad=True)\n", "step=21; loss=0.66; abc=tensor([2.9346, 1.5832, 1.2800], requires_grad=True)\n", "step=22; loss=0.65; abc=tensor([2.9289, 1.5958, 1.2400], requires_grad=True)\n", "step=23; loss=0.64; abc=tensor([2.9480, 1.5926, 1.2100], requires_grad=True)\n", "step=24; loss=0.62; abc=tensor([2.9672, 1.5895, 1.1800], requires_grad=True)\n", "step=25; loss=0.61; abc=tensor([2.9864, 1.5863, 1.1500], requires_grad=True)\n", "step=26; loss=0.60; abc=tensor([2.9807, 1.6000, 1.1200], requires_grad=True)\n", "step=27; loss=0.60; abc=tensor([3.0064, 1.5937, 1.1200], requires_grad=True)\n", "step=28; loss=0.59; abc=tensor([3.0018, 1.6105, 1.1000], requires_grad=True)\n", "step=29; loss=0.59; abc=tensor([3.0275, 1.6042, 1.1000], requires_grad=True)\n", "step=30; loss=0.59; abc=tensor([3.0283, 1.6137, 1.0900], requires_grad=True)\n", "step=31; loss=0.58; abc=tensor([3.0290, 1.6232, 1.0800], requires_grad=True)\n", "step=32; loss=0.58; abc=tensor([3.0547, 1.6168, 1.0800], requires_grad=True)\n", "step=33; loss=0.58; abc=tensor([3.0555, 1.6263, 1.0700], requires_grad=True)\n", "step=34; loss=0.58; abc=tensor([3.0563, 1.6358, 1.0600], requires_grad=True)\n", "step=35; loss=0.58; abc=tensor([3.0571, 1.6453, 1.0500], requires_grad=True)\n", "step=36; loss=0.58; abc=tensor([3.0828, 1.6389, 1.0500], requires_grad=True)\n", "step=37; loss=0.58; abc=tensor([3.0835, 1.6484, 1.0400], requires_grad=True)\n", "step=38; loss=0.58; abc=tensor([3.0843, 1.6579, 1.0300], requires_grad=True)\n", "step=39; loss=0.57; abc=tensor([3.0851, 1.6674, 1.0200], requires_grad=True)\n", "step=40; loss=0.57; abc=tensor([3.1136, 1.6558, 1.0300], requires_grad=True)\n", "step=41; loss=0.58; abc=tensor([3.0956, 1.6516, 1.0100], requires_grad=True)\n", "step=42; loss=0.57; abc=tensor([3.0992, 1.6558, 1.0100], requires_grad=True)\n", "step=43; loss=0.57; abc=tensor([3.1027, 1.6600, 1.0100], requires_grad=True)\n", "step=44; loss=0.57; abc=tensor([3.1063, 1.6642, 1.0100], requires_grad=True)\n", "step=45; loss=0.57; abc=tensor([3.0911, 1.6547, 1.0000], requires_grad=True)\n", "step=46; loss=0.57; abc=tensor([3.0946, 1.6589, 1.0000], requires_grad=True)\n", "step=47; loss=0.57; abc=tensor([3.0982, 1.6632, 1.0000], requires_grad=True)\n", "step=48; loss=0.57; abc=tensor([3.1017, 1.6674, 1.0000], requires_grad=True)\n", "step=49; loss=0.57; abc=tensor([3.1053, 1.6716, 1.0000], requires_grad=True)\n", "Best abc parameters: tensor([3.1053, 1.6716, 1.0000])\n" ] } ], "source": [ "from fastai.metrics import mae\n", "\n", "def demo_auto_fit(steps=50):\n", " x, y = generate_noisy_data(mk_quad(3,2,1))\n", "\n", " abc = torch.tensor([1.0,1.0,1.0], requires_grad=True)\n", " min_loss = float('inf')\n", " best_abc = abc.clone().detach() # Initialize best_abc with the initial abc\n", "\n", " for i in range(steps):\n", " f = mk_quad(*abc)\n", " loss = mae(f(x), y)\n", " loss.backward()\n", "\n", " with torch.no_grad():\n", " abc -= abc.grad*0.1\n", " abc.grad.zero_() # Clear gradients after update\n", "\n", " print(f'step={i}; loss={loss.item():.2f}; abc={abc}')\n", "\n", " if loss < min_loss:\n", " min_loss = loss\n", " best_abc = abc.clone().detach() # Update best_abc when a lower loss is found\n", "\n", " return best_abc\n", "\n", "best_abc_params = demo_auto_fit()\n", "print(f\"Best abc parameters: {best_abc_params}\")" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "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.10.16" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": { "0363ed04965849e9ba9ac84840f53aa9": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "05cea0acdefd4a3a9d07c89aad6f18fc": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "321c6e25d6c1469393077b48f599ac80": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "3a6cb362843644dea22fe24e70e1ffb9": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "c", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_548bccf6f2e64f639da9e99aadf4b011", "max": 3.3000000000000003, "min": -1.1, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.1, "style": "IPY_MODEL_65564a7d02a840b7b978d18acb045631", "tabbable": null, "tooltip": null, "value": 1.1 } }, "4429d264f29d497fb60af0b1d6ed52a7": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "a", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_912f33f722c54a90ac3f5fc43a08edfb", "max": 3.3000000000000003, "min": -1.1, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.1, "style": "IPY_MODEL_05cea0acdefd4a3a9d07c89aad6f18fc", "tabbable": null, "tooltip": null, "value": 1.1 } }, "463bafc74b2c4e1abfe644763ca84d30": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "491653f696a2408e8a8f62e50f7b571f": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "b", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_fcb22dd6b63b4c0cabe19648cdef049d", "max": 3.3000000000000003, "min": -1.1, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.1, "style": "IPY_MODEL_321c6e25d6c1469393077b48f599ac80", "tabbable": null, "tooltip": null, "value": 1.1 } }, "548bccf6f2e64f639da9e99aadf4b011": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "594a1ead46ac4e78ad9e66447cb4c560": { "model_module": "@jupyter-widgets/output", "model_module_version": "1.0.0", "model_name": "OutputModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/output", "_model_module_version": "1.0.0", "_model_name": "OutputModel", "_view_count": null, "_view_module": "@jupyter-widgets/output", "_view_module_version": "1.0.0", "_view_name": "OutputView", "layout": "IPY_MODEL_fe3097341cf74549bc3a8067d41f4bbc", "msg_id": "", "outputs": [ { "name": "stderr", "output_type": "stream", "text": "/var/folders/cw/6t1pfkgn3c5_3l_gc40ch3kr0000gn/T/ipykernel_9562/81275562.py:8: DeprecationWarning: __array_wrap__ must accept context and return_scalar arguments (positionally) in the future. (Deprecated NumPy 2.0)\n def add_noise(x, mult, add): return x * (1+noise(x,mult)) + noise(x,add)\n" }, { "data": { "image/png": "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", "text/plain": "
" }, "metadata": {}, "output_type": "display_data" } ], "tabbable": null, "tooltip": null } }, "61b1a60553064335b727665c2af4adaa": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "b", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_b2ef5c10de0344b3b299a5ed341c2f6d", "max": 3.3000000000000003, "min": -1.1, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.1, "style": "IPY_MODEL_0363ed04965849e9ba9ac84840f53aa9", "tabbable": null, "tooltip": null, "value": 1.1 } }, "65564a7d02a840b7b978d18acb045631": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "67508c117c834df9b8d69f0b7d69ca65": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "c", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_463bafc74b2c4e1abfe644763ca84d30", "max": 3.3000000000000003, "min": -1.1, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.1, "style": "IPY_MODEL_7cea5bf13f6746c3a55e03a2537f79a0", "tabbable": null, "tooltip": null, "value": 1.1 } }, "6c2aa70352d844b2947251e8bf0fa56a": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "VBoxModel", "state": { "_dom_classes": [ "widget-interact" ], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "VBoxModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "VBoxView", "box_style": "", "children": [ "IPY_MODEL_ea0046057c4344cc93342bfcbab546a0", "IPY_MODEL_491653f696a2408e8a8f62e50f7b571f", "IPY_MODEL_3a6cb362843644dea22fe24e70e1ffb9", "IPY_MODEL_594a1ead46ac4e78ad9e66447cb4c560" ], "layout": "IPY_MODEL_b7c38ee42c294e22b52d0a114055416a", "tabbable": null, "tooltip": null } }, "6c8dd3e12674415d9f2286c393e8d8ad": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "VBoxModel", "state": { "_dom_classes": [ "widget-interact" ], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "VBoxModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "VBoxView", "box_style": "", "children": [ "IPY_MODEL_4429d264f29d497fb60af0b1d6ed52a7", "IPY_MODEL_61b1a60553064335b727665c2af4adaa", "IPY_MODEL_67508c117c834df9b8d69f0b7d69ca65", "IPY_MODEL_a81622b41a6c49f6b90c25c1380e64e5" ], "layout": "IPY_MODEL_c6466c422ef44bc9baf0511dd2700d31", "tabbable": null, "tooltip": null } }, "7cea5bf13f6746c3a55e03a2537f79a0": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "81d8ecb827ae49199a164f493eade1cf": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "StyleView", "description_width": "", "handle_color": null } }, "912f33f722c54a90ac3f5fc43a08edfb": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "a81622b41a6c49f6b90c25c1380e64e5": { "model_module": "@jupyter-widgets/output", "model_module_version": "1.0.0", "model_name": "OutputModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/output", "_model_module_version": "1.0.0", "_model_name": "OutputModel", "_view_count": null, "_view_module": "@jupyter-widgets/output", "_view_module_version": "1.0.0", "_view_name": "OutputView", "layout": "IPY_MODEL_c6396dd928734d0bb99f4306c245c689", "msg_id": "", "outputs": [ { "name": "stderr", "output_type": "stream", "text": "/var/folders/cw/6t1pfkgn3c5_3l_gc40ch3kr0000gn/T/ipykernel_9562/81275562.py:8: DeprecationWarning: __array_wrap__ must accept context and return_scalar arguments (positionally) in the future. (Deprecated NumPy 2.0)\n def add_noise(x, mult, add): return x * (1+noise(x,mult)) + noise(x,add)\n" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAekAAAGHCAYAAACUMKq9AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAN1wAADdcBQiibeAAAMsBJREFUeJzt3Ql4VOXZxvE7YZOEHUSFCCIVRWQVBcSNioAWMCKLiGBVcAFDrbjRokYEam2tC4h8rigqKnVDrciiWKWAsqqgiC2LLAIKIQJhTb7rOS8JiwkEMplzZs7/d11zzcyZwLwsmTvv9rwJOTk5OQIAAIGT6HcDAABA/ghpAAACipAGACCgCGkAAAKKkAYAIKAIaQAAAoqQBgAgoAhpAAACipAGoig9PV0JCQk65ZRT8n3drtvr9nX5qVOnjvf6999//6vXpk+f7r2W361v375H1M61a9fqjjvuUOPGjVWuXDmdeOKJuuaaa7RmzZrD/trRo0erefPmqly5spKSktSwYUPv2qHqJl1++eVeO0eNGnVE7QTiXUm/GwCEzTHHHKNly5Zpzpw5Xpjl+uKLL7R8+XLv9fzMnDnTe92MHz9e99xzT75f9/LLL+vkk08+4Fr16tWPqI1z587VW2+95YV7ixYttG7dOu8Hh3POOUdff/21F9wF2bRpkxe6jRo18kJ62rRpuuWWW7Rt2zbdfvvtv/r6yZMne382AL9GSANRlpycrGbNmunVV189IKTt+W9/+1svIPNjwWy/9owzzjhkSFs42tcUxbnnnqtvv/1WJUvu+4iwNp966ql64403vF51Qf785z8f8Pyiiy7SihUr9OKLL/4qpHft2qU//OEPGj58+BH39oEwYLgb8MGVV16p119/PW8I2O7tuV3Pz549e7zXO3furOuuu07ffPONFi5cWGztq1Sp0gEBberVq+f1jAsz5H2wqlWraufOnb+6/thjj6ls2bK69tpri9ReIF4R0oAPunTp4g0hf/bZZ97zTz/9VBs2bPCu5+fjjz/2vt5CvGvXripVqpTXmy4o0Hfv3n3Abf/54Nx58SP15ZdfekPWFtaFYe+7ZcsWffDBB14vesCAAQe8/uOPP+qBBx7Qo48+qsREPoqA/PCdAfjAeqodOnTwhriN3dvzihUr5vv1Fsi5v6ZKlSpq166d92vyW4zVpEkTL8T3v73wwgt5r1sglihR4ojam52d7Q1L28I2680fjgWwvW/58uV16aWXKi0tzbvt784771T79u11/vnnH1FbgDBhThrwifWKb731Vv3jH//QP//5Tz3++OP5fp0NE7/55pveYqzSpUvn/drevXt7C65sMdf+LLzr1q37q1Xhue69917vdiQGDx7svdcnn3zihe/hVKtWzVsIZz1pW3X+4IMPeoFtwWzs97I/sw3bAygYIQ34xHqktljKFlpt3bpVnTp1yvfrbLg4IyPD65HavbnwwgtVpkwZr4d9cEg3aNCgyAvH9mfbp/72t79572UrvQvD5rNzF8VZW633ft9993mrvG1e2344ufHGG72Rg9w/k8nKytLmzZsLHFEAwobhbsAntlK7Y8eOeuSRR7yAtuf5yZ177tatm7f32G62b3nHjh2aMGGCNwddXGwltw1TP/TQQ+rRo8dR/z62Mnz79u15i86WLFnizUXn/nnsZqynbYvMADj0pAEf3XzzzV7Y3nTTTfm+bj3sd999Vz179tQNN9xwwGvz58/Xbbfdpo8++kgXX3xxxNtmw9S9evXyQjq//c1HYsaMGV7Pv0aNGt7z9957z1tYtr82bdpo4MCBBS6eA8KIkAZ8ZEPBdivIO++8462otkVbBw81t27d2ttfbD3t/UPaVmHbXPD+bPi4fv363uOhQ4d6t4NDcn82V5yamqrTTjvN60HPmjUr77Vjjz02b87b5qhtH7QVLLngggu8a2eddZa3j9r2VNs+6ClTpniVxAYNGuQNdefuw86PLUzL/X0AENJAoFkAW3DlNxdsC7i6d++uV155RU8++WTedev9HsyCdOrUqXkrtQ83RD579mxvbtj2Yh88520BPHbsWO+xrS6332v/Vea2utwWwa1atcoLZWv/888/n2+7ABxaQs6hCuoCAADfsHAMAICAIqQBAAgoQhoAgIAipAEACChCGgCAgCKkAQAIqMDskz6ao/MAAIhlh9sFHZiQNmzZBgCERUIhOqcMdwMAEFCENAAAAUVIAwAQUIQ0AAABRUgDABBQhDQAAAFFSAMAEFCENAAAAUVIAwAQUIQ0AAABRUgDABBQhDQAAAFFSAMAEFCENAAAAUVIAwAQUIQ0AAABRUgDABBQhDQAAAFV0u8GAABwONnZOZq4cI3GzVyuVRlZSqlUVr1bnaTOjWsoMTFB8SohJycnRwGQ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", "text/plain": "
" }, "metadata": {}, "output_type": "display_data" } ], "tabbable": null, "tooltip": null } }, "b2ef5c10de0344b3b299a5ed341c2f6d": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "b7c38ee42c294e22b52d0a114055416a": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "c6396dd928734d0bb99f4306c245c689": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "c6466c422ef44bc9baf0511dd2700d31": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "d7773e30a1a44581b659162a725f5633": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "ea0046057c4344cc93342bfcbab546a0": { "model_module": "@jupyter-widgets/controls", "model_module_version": "2.0.0", "model_name": "FloatSliderModel", "state": { "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "2.0.0", "_view_name": "FloatSliderView", "behavior": "drag-tap", "continuous_update": true, "description": "a", "description_allow_html": false, "disabled": false, "layout": "IPY_MODEL_d7773e30a1a44581b659162a725f5633", "max": 3.3000000000000003, "min": -1.1, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.1, "style": "IPY_MODEL_81d8ecb827ae49199a164f493eade1cf", "tabbable": null, "tooltip": null, "value": 1.1 } }, "fcb22dd6b63b4c0cabe19648cdef049d": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } }, "fe3097341cf74549bc3a8067d41f4bbc": { "model_module": "@jupyter-widgets/base", "model_module_version": "2.0.0", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "2.0.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border_bottom": null, "border_left": null, "border_right": null, "border_top": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } } }, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 2 }