Files
Karpathy_ZtH_Learning/My_Experiments/pytorch3.ipynb
T

502 lines
68 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "a11ebdff",
"metadata": {},
"source": [
"## Manual approach"
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "3163fb75",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"\n",
"X = torch.tensor([[0.0],[10.0], [20.0], [30.0], [40.0]])\n",
"Y = torch.tensor([[32.0], [50.0], [68.0], [86.0], [104.0]])"
]
},
{
"cell_type": "code",
"execution_count": 59,
"id": "64a02514",
"metadata": {},
"outputs": [],
"source": [
"W = torch.randn((1, 1), requires_grad=True)\n",
"B = torch.randn((1, 1), requires_grad=True)"
]
},
{
"cell_type": "code",
"execution_count": 60,
"id": "35200e59",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 0: Loss = 2051.0815\n",
"Epoch 400: Loss = 181.1680\n",
"Epoch 800: Loss = 106.3257\n",
"Epoch 1200: Loss = 62.4014\n",
"Epoch 1600: Loss = 36.6228\n",
"Epoch 2000: Loss = 21.4935\n",
"Epoch 2400: Loss = 12.6143\n",
"Epoch 2800: Loss = 7.4032\n",
"Epoch 3200: Loss = 4.3449\n",
"Epoch 3600: Loss = 2.5500\n",
"Epoch 4000: Loss = 1.4965\n",
"Epoch 4400: Loss = 0.8783\n",
"Epoch 4800: Loss = 0.5155\n",
"Epoch 5200: Loss = 0.3025\n",
"Epoch 5600: Loss = 0.1775\n",
"Epoch 6000: Loss = 0.1042\n",
"Epoch 6400: Loss = 0.0612\n",
"Epoch 6800: Loss = 0.0359\n",
"Epoch 7200: Loss = 0.0211\n",
"Epoch 7600: Loss = 0.0124\n",
"Epoch 8000: Loss = 0.0073\n",
"Epoch 8400: Loss = 0.0043\n",
"Epoch 8800: Loss = 0.0025\n",
"Epoch 9200: Loss = 0.0015\n",
"Epoch 9600: Loss = 0.0009\n",
"Epoch 10000: Loss = 0.0005\n",
"Epoch 10400: Loss = 0.0003\n",
"Epoch 10800: Loss = 0.0002\n",
"Epoch 11200: Loss = 0.0001\n",
"Epoch 11600: Loss = 0.0001\n",
"Epoch 12000: Loss = 0.0000\n",
"Epoch 12400: Loss = 0.0000\n",
"Epoch 12800: Loss = 0.0000\n",
"Epoch 13200: Loss = 0.0000\n",
"Epoch 13600: Loss = 0.0000\n",
"Epoch 14000: Loss = 0.0000\n",
"Epoch 14400: Loss = 0.0000\n",
"Epoch 14800: Loss = 0.0000\n",
"Epoch 15200: Loss = 0.0000\n",
"Epoch 15600: Loss = 0.0000\n",
"Epoch 16000: Loss = 0.0000\n",
"Epoch 16400: Loss = 0.0000\n",
"Epoch 16800: Loss = 0.0000\n",
"Epoch 17200: Loss = 0.0000\n",
"Epoch 17600: Loss = 0.0000\n",
"Epoch 18000: Loss = 0.0000\n",
"Epoch 18400: Loss = 0.0000\n",
"Epoch 18800: Loss = 0.0000\n",
"Epoch 19200: Loss = 0.0000\n",
"Epoch 19600: Loss = 0.0000\n"
]
}
],
"source": [
"learning_rate = 0.001\n",
"\n",
"for epoch in range(20000):\n",
" Y_pred = X.matmul(W) + B\n",
"\n",
" loss = ((Y_pred - Y)**2).mean()\n",
"\n",
" loss.backward()\n",
" with torch.no_grad():\n",
" W -= learning_rate * W.grad\n",
" B -= learning_rate * B.grad\n",
"\n",
" W.grad.zero_()\n",
" B.grad.zero_()\n",
"\n",
" if epoch % 400 == 0:\n",
" print(f\"Epoch {epoch}: Loss = {loss.item():.4f}\")"
]
},
{
"cell_type": "code",
"execution_count": 61,
"id": "be1eb1bd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"--- Результаты обучения ---\n",
"Предсказание для 100°C: 212.00°F (Ожидалось: 212.00)\n",
"Итоговый вес W: 1.8000 (Ожидалось: 1.8)\n",
"Итоговое смещение B: 31.9986 (Ожидалось: 32.0)\n"
]
}
],
"source": [
"with torch.no_grad():\n",
" X_test = torch.tensor([[100.0]])\n",
" Y_test_pred = X_test.matmul(W) + B\n",
" print(\"\\n--- Результаты обучения ---\")\n",
" print(f\"Предсказание для 100°C: {Y_test_pred.item():.2f}°F (Ожидалось: 212.00)\")\n",
" print(f\"Итоговый вес W: {W.item():.4f} (Ожидалось: 1.8)\")\n",
" print(f\"Итоговое смещение B: {B.item():.4f} (Ожидалось: 32.0)\")"
]
},
{
"cell_type": "markdown",
"id": "1a066894",
"metadata": {},
"source": [
"## Professional approach"
]
},
{
"cell_type": "code",
"execution_count": 62,
"id": "fa3c1e81",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"\n",
"X = torch.tensor([[0.0],[10.0], [20.0], [30.0], [40.0]])\n",
"Y = torch.tensor([[32.0], [50.0], [68.0], [86.0], [104.0]])"
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "8860a027",
"metadata": {},
"outputs": [],
"source": [
"model = nn.Linear(in_features=1, out_features=1)"
]
},
{
"cell_type": "code",
"execution_count": 64,
"id": "b1213a8a",
"metadata": {},
"outputs": [],
"source": [
"criterion = nn.MSELoss()\n",
"optimizer = optim.SGD(model.parameters(), lr=0.001)"
]
},
{
"cell_type": "code",
"execution_count": 65,
"id": "27d203c4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 0: loss = 5002.43408203125\n",
"Epoch 400: loss = 189.92440795898438\n",
"Epoch 800: loss = 111.46468353271484\n",
"Epoch 1200: loss = 65.41755676269531\n",
"Epoch 1600: loss = 38.39296340942383\n"
]
}
],
"source": [
"for epoch in range(2000):\n",
" Y_pred = model(X)\n",
"\n",
" loss = criterion(Y_pred, Y)\n",
"\n",
" optimizer.zero_grad()\n",
"\n",
" loss.backward()\n",
"\n",
" optimizer.step()\n",
"\n",
" if epoch % 400 == 0:\n",
" print(f\"Epoch {epoch}: loss = {loss.item()}\")"
]
},
{
"cell_type": "code",
"execution_count": 66,
"id": "024b4276",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"--- Результаты обучения ---\n",
"Предсказание для 100°C: 231.20°F\n",
"Итоговый вес W: 2.0742\n",
"Итоговое смещение B: 23.7783\n"
]
}
],
"source": [
"with torch.no_grad():\n",
" X_test = torch.tensor([[100.0]])\n",
" Y_test_pred = model(X_test)\n",
" print(\"\\n--- Результаты обучения ---\")\n",
" print(f\"Предсказание для 100°C: {Y_test_pred.item():.2f}°F\")\n",
" \n",
" # Доступ к обученным весам внутри слоя\n",
" print(f\"Итоговый вес W: {model.weight.item():.4f}\")\n",
" print(f\"Итоговое смещение B: {model.bias.item():.4f}\")"
]
},
{
"cell_type": "code",
"execution_count": 67,
"id": "df8942cd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- MLP Model Architecture ---\n",
"SimpleMLP(\n",
" (fc1): Linear(in_features=784, out_features=128, bias=True)\n",
" (fc2): Linear(in_features=128, out_features=10, bias=True)\n",
")\n",
"\n",
"--- Starting Training Simulation ---\n",
"Epoch [1/5], Loss: 2.3632\n",
"Epoch [2/5], Loss: 2.0220\n",
"Epoch [3/5], Loss: 1.7251\n",
"Epoch [4/5], Loss: 1.4678\n",
"Epoch [5/5], Loss: 1.2423\n",
"\n",
"MLP Example successfully defined and simulated training steps.\n"
]
}
],
"source": [
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"\n",
"# 1. Define the MLP model\n",
"class SimpleMLP(nn.Module):\n",
" def __init__(self, input_size, hidden_size, output_size):\n",
" super(SimpleMLP, self).__init__()\n",
" # First linear layer: input to hidden layer\n",
" self.fc1 = nn.Linear(input_size, hidden_size)\n",
" # Second linear layer: hidden layer to output layer\n",
" self.fc2 = nn.Linear(hidden_size, output_size)\n",
"\n",
" def forward(self, x):\n",
" # Apply ReLU activation function\n",
" x = torch.relu(self.fc1(x))\n",
" # Output layer (no activation for regression or logits)\n",
" x = self.fc2(x)\n",
" return x\n",
"\n",
"# 2. Setup parameters\n",
"input_size = 784 # Example: Flattened MNIST image (28*28)\n",
"hidden_size = 128\n",
"output_size = 10 # Example: Number of classes for classification\n",
"\n",
"# Initialize the model\n",
"model = SimpleMLP(input_size, hidden_size, output_size)\n",
"print(\"--- MLP Model Architecture ---\")\n",
"print(model)\n",
"\n",
"# 3. Create dummy data for demonstration (In a real scenario, you would load a dataset like MNIST)\n",
"# Batch size and input features\n",
"batch_size = 64\n",
"dummy_input = torch.randn(batch_size, input_size)\n",
"# Dummy labels\n",
"dummy_target = torch.randint(0, output_size, (batch_size,))\n",
"\n",
"# 4. Setup Loss Function and Optimizer\n",
"criterion = nn.CrossEntropyLoss() # Suitable for multi-class classification\n",
"optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
"print(\"\\n--- Starting Training Simulation ---\")\n",
"\n",
"# 5. Training Loop (Simulation)\n",
"num_epochs = 5\n",
"\n",
"for epoch in range(num_epochs):\n",
" # Forward pass\n",
" outputs = model(dummy_input)\n",
" \n",
" # Calculate loss\n",
" loss = criterion(outputs, dummy_target)\n",
" \n",
" # Backward pass and optimization\n",
" optimizer.zero_grad()\n",
" loss.backward()\n",
" optimizer.step()\n",
" \n",
" print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')\n",
"\n",
"print(\"\\nMLP Example successfully defined and simulated training steps.\")"
]
},
{
"cell_type": "code",
"execution_count": 68,
"id": "98166324",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"from torch import nn\n",
"from matplotlib import pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 69,
"id": "ef1351a0",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x704a3989d750>]"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"w = 0.7\n",
"b = 0.3\n",
"\n",
"X = torch.arange(10, 100, 5).unsqueeze(dim=1)\n",
"y = X * w + b\n",
"\n",
"plt.plot(X, y)"
]
},
{
"cell_type": "code",
"execution_count": 70,
"id": "e452da62",
"metadata": {},
"outputs": [],
"source": [
"train_split = int(0.8 * len(X))\n",
"X_train, y_train = X[:train_split], y[:train_split]\n",
"X_test, y_test = X[train_split:], y[train_split:]"
]
},
{
"cell_type": "code",
"execution_count": 71,
"id": "b9f7783b",
"metadata": {},
"outputs": [],
"source": [
"\n",
"\n",
"class Model(nn.Module):\n",
" def __init__(self):\n",
" super().__init__()\n",
" self.w = nn.Parameter(torch.randn(1))\n",
" self.b = nn.Parameter(torch.randn(1))\n",
" def forward(self, x):\n",
" return x * self.w + self.b"
]
},
{
"cell_type": "code",
"execution_count": 78,
"id": "90874c3d",
"metadata": {},
"outputs": [
{
"ename": "RuntimeError",
"evalue": "Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.",
"output_type": "error",
"traceback": [
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
"\u001b[31mRuntimeError\u001b[39m Traceback (most recent call last)",
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[78]\u001b[39m\u001b[32m, line 17\u001b[39m\n\u001b[32m 13\u001b[39m optimizer.step()\n\u001b[32m 14\u001b[39m epochs.append(epoch)\n\u001b[32m 15\u001b[39m losses.append(loss.item())\n\u001b[32m 16\u001b[39m plt.plot(X, y)\n\u001b[32m---> \u001b[39m\u001b[32m17\u001b[39m plt.plot(X_train, y_pred)\n",
"\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/Karpathy_ZtH_Learning/.venv/lib/python3.11/site-packages/matplotlib/pyplot.py:4043\u001b[39m, in \u001b[36mplot\u001b[39m\u001b[34m(scalex, scaley, data, *args, **kwargs)\u001b[39m\n\u001b[32m 4035\u001b[39m \u001b[38;5;129m@_copy_docstring_and_deprecators\u001b[39m(Axes.plot)\n\u001b[32m 4036\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mplot\u001b[39m(\n\u001b[32m 4037\u001b[39m *args: \u001b[38;5;28mfloat\u001b[39m | ArrayLike | \u001b[38;5;28mstr\u001b[39m,\n\u001b[32m (...)\u001b[39m\u001b[32m 4041\u001b[39m **kwargs,\n\u001b[32m 4042\u001b[39m ) -> \u001b[38;5;28mlist\u001b[39m[Line2D]:\n\u001b[32m-> \u001b[39m\u001b[32m4043\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[30;43mgca\u001b[39;49m\u001b[30;43m(\u001b[39;49m\u001b[30;43m)\u001b[39;49m\u001b[30;43m.\u001b[39;49m\u001b[30;43mplot\u001b[39;49m\u001b[30;43m(\u001b[39;49m\n\u001b[32m 4044\u001b[39m \u001b[30;43m \u001b[39;49m\u001b[30;43m*\u001b[39;49m\u001b[30;43margs\u001b[39;49m\u001b[30;43m,\u001b[39;49m\n\u001b[32m 4045\u001b[39m \u001b[30;43m \u001b[39;49m\u001b[30;43mscalex\u001b[39;49m\u001b[30;43m=\u001b[39;49m\u001b[30;43mscalex\u001b[39;49m\u001b[30;43m,\u001b[39;49m\n\u001b[32m 4046\u001b[39m \u001b[30;43m \u001b[39;49m\u001b[30;43mscaley\u001b[39;49m\u001b[30;43m=\u001b[39;49m\u001b[30;43mscaley\u001b[39;49m\u001b[30;43m,\u001b[39;49m\n\u001b[32m 4047\u001b[39m \u001b[30;43m \u001b[39;49m\u001b[30;43m*\u001b[39;49m\u001b[30;43m*\u001b[39;49m\u001b[30;43m(\u001b[39;49m\u001b[30;43m{\u001b[39;49m\u001b[30;43m\"\u001b[39;49m\u001b[30;43mdata\u001b[39;49m\u001b[30;43m\"\u001b[39;49m\u001b[30;43m:\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43mdata\u001b[39;49m\u001b[30;43m}\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43;01mif\u001b[39;49;00m\u001b[30;43m \u001b[39;49m\u001b[30;43mdata\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43;01mis\u001b[39;49;00m\u001b[30;43m \u001b[39;49m\u001b[30;43;01mnot\u001b[39;49;00m\u001b[30;43m \u001b[39;49m\u001b[30;43;01mNone\u001b[39;49;00m\u001b[30;43m \u001b[39;49m\u001b[30;43;01melse\u001b[39;49;00m\u001b[30;43m \u001b[39;49m\u001b[30;43m{\u001b[39;49m\u001b[30;43m}\u001b[39;49m\u001b[30;43m)\u001b[39;49m\u001b[30;43m,\u001b[39;49m\n\u001b[32m 4048\u001b[39m \u001b[30;43m \u001b[39;49m\u001b[30;43m*\u001b[39;49m\u001b[30;43m*\u001b[39;49m\u001b[30;43mkwargs\u001b[39;49m\u001b[30;43m,\u001b[39;49m\n\u001b[32m 4049\u001b[39m \u001b[30;43m \u001b[39;49m\u001b[30;43m)\u001b[39;49m\n",
"\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/Karpathy_ZtH_Learning/.venv/lib/python3.11/site-packages/matplotlib/axes/_axes.py:1792\u001b[39m, in \u001b[36mAxes.plot\u001b[39m\u001b[34m(self, scalex, scaley, data, *args, **kwargs)\u001b[39m\n\u001b[32m 1549\u001b[39m \u001b[38;5;250m\u001b[39m\u001b[33;03m\"\"\"\u001b[39;00m\n\u001b[32m 1550\u001b[39m \u001b[33;03mPlot y versus x as lines and/or markers.\u001b[39;00m\n\u001b[32m 1551\u001b[39m \n\u001b[32m (...)\u001b[39m\u001b[32m 1789\u001b[39m \u001b[33;03m(``'green'``) or hex strings (``'#008000'``).\u001b[39;00m\n\u001b[32m 1790\u001b[39m \u001b[33;03m\"\"\"\u001b[39;00m\n\u001b[32m 1791\u001b[39m kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)\n\u001b[32m-> \u001b[39m\u001b[32m1792\u001b[39m lines = [*\u001b[38;5;28mself\u001b[39m._get_lines(\u001b[38;5;28mself\u001b[39m, *args, data=data, **kwargs)]\n\u001b[32m 1793\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m line \u001b[38;5;129;01min\u001b[39;00m lines:\n\u001b[32m 1794\u001b[39m \u001b[38;5;28mself\u001b[39m.add_line(line)\n",
"\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/Karpathy_ZtH_Learning/.venv/lib/python3.11/site-packages/matplotlib/axes/_base.py:331\u001b[39m, in \u001b[36m_process_plot_var_args.__call__\u001b[39m\u001b[34m(self, axes, data, return_kwargs, *args, **kwargs)\u001b[39m\n\u001b[32m 329\u001b[39m this += args[\u001b[32m0\u001b[39m],\n\u001b[32m 330\u001b[39m args = args[\u001b[32m1\u001b[39m:]\n\u001b[32m--> \u001b[39m\u001b[32m331\u001b[39m \u001b[38;5;28;01myield from\u001b[39;00m \u001b[30;43mself\u001b[39;49m\u001b[30;43m.\u001b[39;49m\u001b[30;43m_plot_args\u001b[39;49m\u001b[30;43m(\u001b[39;49m\n\u001b[32m 332\u001b[39m \u001b[30;43m \u001b[39;49m\u001b[30;43maxes\u001b[39;49m\u001b[30;43m,\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43mthis\u001b[39;49m\u001b[30;43m,\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43mkwargs\u001b[39;49m\u001b[30;43m,\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43mambiguous_fmt_datakey\u001b[39;49m\u001b[30;43m=\u001b[39;49m\u001b[30;43mambiguous_fmt_datakey\u001b[39;49m\u001b[30;43m,\u001b[39;49m\n\u001b[32m 333\u001b[39m \u001b[30;43m \u001b[39;49m\u001b[30;43mreturn_kwargs\u001b[39;49m\u001b[30;43m=\u001b[39;49m\u001b[30;43mreturn_kwargs\u001b[39;49m\n\u001b[32m 334\u001b[39m \u001b[30;43m\u001b[39;49m\u001b[30;43m)\u001b[39;49m\n",
"\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/Karpathy_ZtH_Learning/.venv/lib/python3.11/site-packages/matplotlib/axes/_base.py:499\u001b[39m, in \u001b[36m_process_plot_var_args._plot_args\u001b[39m\u001b[34m(self, axes, tup, kwargs, return_kwargs, ambiguous_fmt_datakey)\u001b[39m\n\u001b[32m 497\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(xy) == \u001b[32m2\u001b[39m:\n\u001b[32m 498\u001b[39m x = _check_1d(xy[\u001b[32m0\u001b[39m])\n\u001b[32m--> \u001b[39m\u001b[32m499\u001b[39m y = \u001b[30;43m_check_1d\u001b[39;49m\u001b[30;43m(\u001b[39;49m\u001b[30;43mxy\u001b[39;49m\u001b[30;43m[\u001b[39;49m\u001b[30;43m1\u001b[39;49m\u001b[30;43m]\u001b[39;49m\u001b[30;43m)\u001b[39;49m\n\u001b[32m 500\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 501\u001b[39m x, y = index_of(xy[-\u001b[32m1\u001b[39m])\n",
"\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/Karpathy_ZtH_Learning/.venv/lib/python3.11/site-packages/matplotlib/cbook.py:1413\u001b[39m, in \u001b[36m_check_1d\u001b[39m\u001b[34m(x)\u001b[39m\n\u001b[32m 1411\u001b[39m \u001b[38;5;250m\u001b[39m\u001b[33;03m\"\"\"Convert scalars to 1D arrays; pass-through arrays as is.\"\"\"\u001b[39;00m\n\u001b[32m 1412\u001b[39m \u001b[38;5;66;03m# Unpack in case of e.g. Pandas or xarray object\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m1413\u001b[39m x = \u001b[30;43m_unpack_to_numpy\u001b[39;49m\u001b[30;43m(\u001b[39;49m\u001b[30;43mx\u001b[39;49m\u001b[30;43m)\u001b[39;49m\n\u001b[32m 1414\u001b[39m \u001b[38;5;66;03m# plot requires `shape` and `ndim`. If passed an\u001b[39;00m\n\u001b[32m 1415\u001b[39m \u001b[38;5;66;03m# object that doesn't provide them, then force to numpy array.\u001b[39;00m\n\u001b[32m 1416\u001b[39m \u001b[38;5;66;03m# Note this will strip unit information.\u001b[39;00m\n\u001b[32m 1417\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(x, \u001b[33m'\u001b[39m\u001b[33mshape\u001b[39m\u001b[33m'\u001b[39m) \u001b[38;5;129;01mor\u001b[39;00m\n\u001b[32m 1418\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(x, \u001b[33m'\u001b[39m\u001b[33mndim\u001b[39m\u001b[33m'\u001b[39m) \u001b[38;5;129;01mor\u001b[39;00m\n\u001b[32m 1419\u001b[39m \u001b[38;5;28mlen\u001b[39m(x.shape) < \u001b[32m1\u001b[39m):\n",
"\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/Karpathy_ZtH_Learning/.venv/lib/python3.11/site-packages/matplotlib/cbook.py:2517\u001b[39m, in \u001b[36m_unpack_to_numpy\u001b[39m\u001b[34m(x)\u001b[39m\n\u001b[32m 2508\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m xtmp\n\u001b[32m 2509\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m _is_torch_array(x) \\\n\u001b[32m 2510\u001b[39m \u001b[38;5;129;01mor\u001b[39;00m _is_jax_array(x) \\\n\u001b[32m 2511\u001b[39m \u001b[38;5;129;01mor\u001b[39;00m _is_tensorflow_array(x) \\\n\u001b[32m (...)\u001b[39m\u001b[32m 2515\u001b[39m \u001b[38;5;66;03m# https://numpy.org/devdocs/user/basics.interoperability.html#using-arbitrary-objects-in-numpy\u001b[39;00m\n\u001b[32m 2516\u001b[39m \u001b[38;5;66;03m# therefore, let arrays do better if they can\u001b[39;00m\n\u001b[32m-> \u001b[39m\u001b[32m2517\u001b[39m xtmp = np.asarray(x)\n\u001b[32m 2519\u001b[39m \u001b[38;5;66;03m# In case np.asarray method does not return a numpy array in future\u001b[39;00m\n\u001b[32m 2520\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(xtmp, np.ndarray):\n",
"\u001b[36mFile \u001b[39m\u001b[32m~/Desktop/Karpathy_ZtH_Learning/.venv/lib/python3.11/site-packages/torch/_tensor.py:1253\u001b[39m, in \u001b[36mTensor.__array__\u001b[39m\u001b[34m(self, dtype)\u001b[39m\n\u001b[32m 1251\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m handle_torch_function(Tensor.__array__, (\u001b[38;5;28mself\u001b[39m,), \u001b[38;5;28mself\u001b[39m, dtype=dtype)\n\u001b[32m 1252\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m dtype \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m-> \u001b[39m\u001b[32m1253\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[30;43mself\u001b[39;49m\u001b[30;43m.\u001b[39;49m\u001b[30;43mnumpy\u001b[39;49m\u001b[30;43m(\u001b[39;49m\u001b[30;43m)\u001b[39;49m\n\u001b[32m 1254\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m 1255\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m.numpy().astype(dtype, copy=\u001b[38;5;28;01mFalse\u001b[39;00m)\n",
"\u001b[31mRuntimeError\u001b[39m: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead."
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAAGdCAYAAACyzRGfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjExLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlcelbwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAQetJREFUeJzt3Xd0VAX+///npE16QhIgQEIPLYEUAyrFLtIERGnxs7vuWlalKVbWtaCu6CIqCLrr+vmsNaCAKCgqoqI0UUmB0IuU0EOZ9GTK/f3hb/PdCGgCYe5M5vU4J+cw996ZeXFuknnlvu/csRiGYSAiIiLiJn5mBxARERHfovIhIiIibqXyISIiIm6l8iEiIiJupfIhIiIibqXyISIiIm6l8iEiIiJupfIhIiIibhVgdoAzcblcHDx4kIiICCwWi9lxREREpA4Mw6CkpISWLVvi53f24xseWT4OHjxIYmKi2TFERETkHOzfv5+EhISzrvfI8hEREQH8HD4yMtLkNCIiIlIXxcXFJCYm1ryOn41Hlo//jFoiIyNVPkRERLzMb50yoRNORURExK1UPkRERMStVD5ERETErVQ+RERExK1UPkRERMStVD5ERETErVQ+RERExK1UPkRERMStVD5ERETErVQ+RERExK1UPkRERMStVD5ERETErVQ+REREfMj6vSeYumQThmGYlsEjP9VWREREGpbLZfDayt1M/3wbTpdBSssobrwowZQsKh8iIiKN3PHSKu6bn8+KbccAGJbWkutS4k3Lo/IhIiLSiK3bfZyJ83I5UlyFNcCPJ4clMyozEYvFYlomlQ8REZFGyOkyeOXrnby4fDsuAzo2C2dOVgad4yPMjqbyISIi0tgcK6ni3vfyWLWzCIAbMxJ4angyoUGe8bLvGSlERESkQazZWcSk9/I4VlJFSKA/Tw1P4SaTTiw9G5UPERGRRsDpMpj55Q5e/moHhgGdm0cw5+Z0OjYzf8zySyofIiIiXu5IcSWT5uXy3e4TAIzpmcjj1ycTEuRvcrIzU/kQERHxYt9uP8a97+VxvKyasCB/nhnRnWFprcyO9atUPkRERLyQw+nixeXbeWXFLgwDuraIZE5WOu2bhpsd7TepfIiIiHiZQ7YKJs7N5Yc9JwH43SVteGRwV4IDPXPM8ksqHyIiIl7k661Hmfx+HifL7URYA3j2xh4M7tHC7Fj1ovIhIiLiBexOF89/vo1/frsbgO6topidlU6b2DCTk9WfyoeIiIiHKzxZzoS5ueTuOwXALb3bMmVQF6wB3jFm+SWVDxEREQ+2bNNhHliwAVuFncjgAKaPTOW6ZPM+FK4hqHyIiIh4oGqHi2mfbuHfq/cAkJYYzctj00mMCTU3WANQ+RAREfEw+46XM35uDhsKbQDc3q8dD1zXhaAAP5OTNQyVDxEREQ/y6cZDPLhgAyVVDqJDA5kxMpWruzY3O1aDUvkQERHxAJV2J88s3cJba/cCkNmmCbPGptMyOsTkZA1P5UNERMRkPxWVMT47h00HiwG4+4oO3HttJwL9G8eY5ZdUPkREREy0OP8gUxZuoKzaSUxYEC+OTuPyTk3NjnVBqXyIiIiYoNLuZOqSzcz9fh8AvdrFMGtMOvFRwSYnu/BUPkRERNxs59FSxmfnsPVwCRYLTLiyIxOvTiKgkY5ZfknlQ0RExI0+yCnkrx8WUF7tJC7cykuj0+ibFGd2LLdS+RAREXGD8moHj320iQXrCwHo0zGWF0en0Syi8Y9ZfknlQ0RE5ALbfqSEce/msONoKX4WuOeaToy7siP+fhazo5lC5UNEROQCMQyD+T8W8tjiAirtLppFWJk1Np1L2seaHc1UKh8iIiIXQFmVg0cWbeTDvIMAXNapKS+MSiUu3GpyMvOpfIiIiDSwzQeLGZ+dw+6iMvz9LNzXvxN3XtYBPx8ds/ySyoeIiEgDMQyD7O/3MXXJZqodLlpEBTNrbDo928aYHc2jqHyIiIg0gJJKOw9/sJFPNhwC4KouzZgxMpUmYUEmJ/M8Kh8iIiLnqeCAjXHZOew9Xk6An4WHBnTh1r7tNGY5C5UPERGRc2QYBm+t3cvfPtlCtdNFq+gQXs5KJ6N1E7OjeTSVDxERkXNgq7Dz0IINfLbpMAD9uzVn+k2pRIUGmpzM89W7fLhcLt555x2WLl2KxWIhKyuL66+/vtY227ZtY+bMmezdu5ekpCTuu+8+EhMTGyy0iIiImfL2n2J8dg6FJysI9Lfwl0FduaV3WywWjVnqol6fYON0Ohk6dChPPPEE11xzDWPGjOGNN95g8eLFNdts376dXr16UVZWxi233MJPP/1Er169OHz4cIOHFxERcSfDMHh95W5G/mMNhScraB0TysK7evPHPu1UPOrBYhiGUdeNX3nlFe6//342b95M27Zta5aXlpYSHh4OwP/8z/+wY8cO1q1bB4DdbicpKYmRI0cyffr0Oj1PcXExUVFR2Gw2IiMj6/HfERERuTBOlVdz//x8lm85CsCg7vE8e2MPIoM1ZvmPur5+1+vIxxtvvMHQoUNrFQ+gpngALFu2jGHDhtXcDgwMZMiQISxbtqw+TyUiIuIx1u89waCZK1m+5ShBAX48NTyFOVkZKh7nqF7nfBQUFDBy5EheeOEFvv76a5o1a8ZNN93EwIEDASgvL+fYsWMkJCTUul9CQgJ79uw56+NWVVVRVVVVc7u4uLg+sURERC4Il8vgtZW7mf75Npwug3ZxYczOSie5ZZTZ0bxanY98GIZBZWUlf//739m6dSu33XYbHTt2ZMSIEcycOROA6upqAEJCQmrdNzQ0tGbdmUybNo2oqKiaL52cKiIiZjteWsWf3vyBZz/ditNlMDS1JUsm9FXxaAB1PvJhsViIjo6mY8eOvPbaawAMGzaM4uJipk+fzqRJkwgPDycgIIATJ07Uuu/x48dp0uTs73meMmUKkydPrrldXFysAiIiIqZZt/s4E+flcqS4CmuAH08MTWZMz0SdVNpA6jV2ycjIIC4urtay1q1bc/z4cQzDICAggJSUFHJycmptk5OTQ1pa2lkf12q1YrXqU/5ERMRcTpfBK1/v5MXl23EZ0KFpGHNuzqBLvN780JDqdcLprbfeyvLly9m/fz8AlZWVzJ07l8suu6ymDd5yyy3Mnz+fnTt3AvDjjz+ybNkybrnlloZNLiIi0oCOlVTxh//7nhlf/Fw8RmS0YvH4vioeF0C9jnyMHTuW3NxckpOTSUlJYffu3bRt25Z33nmnZpvx48eTk5NDamoqXbp0YfPmzYwbN45Ro0Y1eHgREZGGsGZnEZPey+NYSRUhgf48OSyZkZka/18o9brOx38cPnyYnTt30qJFC9q3b3/GGdjevXvZt28fHTp0oGXLlvV6fF3nQ0RE3MHpMpj55Q5e/moHhgGdmoczJyuDpOYRZkfzSnV9/T6nz3aJj48nPj7+V7dp06YNbdq0OZeHFxERueCOFFcyaV4u3+3++U0SozMTeWJoMiFB/iYna/z0wXIiIuJzvt1+jHvfy+N4WTWhQf48c0N3hqe3MjuWz1D5EBERn+Fwunhx+XZeWbELw4CuLSKZk5VO+6bhv31naTAqHyIi4hMO2SqYODeXH/acBODmi1vz6JBuBAdqzOJuKh8iItLofb31KJPfz+NkuZ1wawDP3tidIT3q92YIaTgqHyIi0mjZnS6e/3wb//x2NwAprSKZPTaDtnFhJifzbSofIiLSKBWeLGfC3Fxy950C4JbebZkyqAvWAI1ZzKbyISIijc6yTYd5YMEGbBV2IoIDmH5TDwaktDA7lvz/VD5ERKTRqHa4mPbpFv69eg8AqQlRzM7KIDEm1NxgUovKh4iINAr7jpczfm4OGwptANzWtx0PDuhCUEC9PsZM3EDlQ0REvN7SjYd4aMEGSqocRIUEMmNkKtd0a252LDkLlQ8REfFalXYnf/tkC29/txeAjNbRvJyVQavoEJOTya9R+RAREa/0U1EZ47Nz2HSwGIA7L+/Aff07EeivMYunU/kQERGvszj/IFMWbqCs2klMWBAzRqVyZedmZseSOlL5EBERr1FpdzJ1yWbmfr8PgF5tY5g1Np34qGCTk0l9qHyIiIhX2Hm0lPHZOWw9XILFAuOu6Mg91yQRoDGL11H5EBERj/dBTiF//bCA8monceFBvDg6jX5JTc2OJedI5UNERDxWebWDxz/axPz1hQBc2j6WmWPSaBapMYs3U/kQERGPtP1ICePezWHH0VL8LDDp6k6Mv6oj/n4Ws6PJeVL5EBERj2IYBvN/LOSxxQVU2l00jbAya0w6l3aINTuaNBCVDxER8RhlVQ4eWbSRD/MOAtAvKY4XR6cRF241OZk0JJUPERHxCJsPFjM+O4fdRWX4WeC+/p256/IO+GnM0uiofIiIiKkMwyD7+31MXbKZaoeL+MhgZo1Np1e7GLOjyQWi8iEiIqYpqbQz5YONfLzhEABXdm7KjFFpxIQFmZxMLiSVDxERMUXBARvjsnPYe7ycAD8LD1zXmdv7tdeYxQeofIiIiFsZhsFba/fyt0+2UO100So6hFlj07moTROzo4mbqHyIiIjb2CrsPLRgA59tOgzANV2b8/zIHkSHasziS1Q+RETELfL2n2J8dg6FJysI9Lfw8MCu/KlPWywWjVl8jcqHiIhcUIZh8L+rfuK5z7ZidxokxoQwe2wGqYnRZkcTk6h8iIjIBXOqvJr7529g+ZYjAAxMiefZG3sQFRJocjIxk8qHiIhcEOv3nmRCdg4HbZUE+fvx1yFd+d0lbTRmEZUPERFpWC6XwWsrdzP98204XQZtY0OZnZVBSqsos6OJh1D5EBGRBnOirJrJ7+exYtsxAK5PbckzN6QQEawxi/w/Kh8iItIgvv/pBBPn5nK4uBJrgB+PX5/M2F6JGrPIaVQ+RETkvLhcBq+s2MkLX2zHZUD7pmHMycqga4tIs6OJh1L5EBGRc3aspIrJ7+exckcRADekt+Lp4SmEWfXyImen7w4RETkna3YVMWleHsdKqggO9OPJYSmMvChBYxb5TSofIiJSL06Xwctf7WDWlztwGZDULJw5N2fQqXmE2dHES6h8iIhInR0trmTSvDzW7j4OwKjMBKYOTSEkyN/kZOJNVD5ERKROVu44xr3v5VFUWk1okD9PD09hREaC2bHEC6l8iIjIr3I4Xby0fAdzVuzEMKBLfASzszLo2Czc7GjipVQ+RETkrA7ZKpg0N4/v95wAIOvi1jw2pBvBgRqzyLlT+RARkTP6eutRJr+fx8lyO+HWAJ4Z0Z2hqS3NjiWNgMqHiIjUYne6eP7zbfzz290AJLeMZE5WBm3jwkxOJo2FyoeIiNQ4cKqCCdk55Ow7BcAfLm3DlEFdNWaRBlWv8rFnzx527txZa1lgYCCXX375advu3buXffv20bFjR1q0aHF+KUVE5IL7YvMR7p+fj63CTkRwAH+/sQcDu+v3tzS8epWPd955h+nTp9OzZ8+aZeHh4bXKh9Pp5E9/+hMLFiygS5cubN68mbvvvpsZM2Y0XGoREWkw1Q4Xz322lf9d9RMAqQlRzM7KIDEm1ORk0ljVe+zStWtXli9fftb1s2fPZvHixeTn59OxY0d+/PFH+vTpw8UXX8yoUaPOK6yIiDSs/SfKGZ+dQ36hDYBb+7bjoQFdCArwMzmZNGb1/u6qrq5m3bp15OfnU1lZedr6N954g1GjRtGxY0cAMjMz6d+/P2+88cZ5hxURkYbzWcEhBs1aSX6hjaiQQP71+0weHdJNxUMuuHp/hxUUFHD33XczYsQI4uPjef3112vWORwOCgoKyMjIqHWfjIwM8vLyzvqYVVVVFBcX1/oSEZELo8rh5PGPCrjznRxKKh1ktI7mk4l9ubZbc7OjiY+o19jl0ksvZc+ePbRs+fP7vF999VXuuOMOunTpQt++fSktLcXhcBATE1PrfrGxsZw8efKsjztt2jSmTp16DvFFRKQ+9hSVMX5uDgUHfv4j78+Xt+f+/p0J9NfRDnGfen23XX311TXFA+Cuu+6ia9euLFy4EICgoCAAKioqat2vvLy8Zt2ZTJkyBZvNVvO1f//++sQSEZE6WJJ/kCEvr6LgQDFNQgP59y09mTKwq4qHuN15X+cjLi6OQ4cOARAaGkrTpk0pLCystU1hYSFt27Y962NYrVasVuv5RhERkTOotDt58uPNZK/bB0CvtjHMHJtGi6gQk5OJr6pX3bXZbLVuHz58mNzcXFJTU2uW9e/fn48++qjmtt1u5+OPP6Z///7nGVVEROpr17FShs9ZTfa6fVgsMP7KjmTffrGKh5jKYhiGUdeNe/XqxYABA0hPT6eoqIgZM2bg5+fHmjVriI6OBmDbtm306tWL4cOHM2TIEN59913WrVtHbm4u8fHxdXqe4uJioqKisNlsREZGntN/TETE1y3KLeSRRQWUVzuJCw/ixdFp9EtqanYsacTq+vpdryMfX375JREREbz77rusXLmS8ePHk5ubW1M8ADp37sy6desIDQ3ljTfeoG3btqxbt67OxUNERM5PRbWTBxfkc+97+ZRXO7m0fSxLJ/ZT8RCPUa8jH+6iIx8iIudmx5ESxmXnsP1IKRYLTLo6iQlXJeHvZzE7mviAur5+64PlREQaAcMwmL++kMc+KqDS7qJphJWZY9Lo3SHO7Ggip1H5EBHxcmVVDh79sIAPcg8A0C8pjhdHpxEXrncRimdS+RAR8WJbDhUzPjuHXcfK8LPAff07c9flHfDTmEU8mMqHiIgXMgyDud/vZ+qSTVQ5XMRHBjNrbDq92sX89p1FTKbyISLiZUoq7fxlUQFL8g8CcEXnprwwKo2YsLNfSVrEk6h8iIh4kYIDNsZn57DneDn+fhYevK4zt/drrzGLeBWVDxERL2AYBu98t5enPt5CtdNFq+gQZo1N56I2TcyOJlJvKh8iIh6uuNLOwws3sHTjYQCu6dqc50f2IDpUYxbxTiofIiIeLH//KcbPzWH/iQoC/S08PLArf+rTFotFYxbxXiofIiIeyDAM/r16D9M+3YLdaZDQJIQ5WRmkJkabHU3kvKl8iIh4mFPl1TywYANfbD4CwIDkeJ67qQdRIYEmJxNpGCofIiIeJGffSSZk53LgVAVB/n78dUhXfndJG41ZpFFR+RAR8QAul8Hrq3bz98+24XAZtIkNZU5WBimtosyOJtLgVD5EREx2oqya++fn89XWowAM6dGCaSO6ExGsMYs0TiofIiIm+mHPCSbOzeWQrZKgAD+euD6Zsb0SNWaRRk3lQ0TEBC6Xwavf7OKFL7bjdBm0jwtjzs0ZdG0RaXY0kQtO5UNExM2KSquY/H4+324/BsAN6a14engKYVb9ShbfoO90ERE3WrvrOJPm5XK0pIrgQD+eHJrCyMwEjVnEp6h8iIi4gdNlMPurncz8cjsuA5KahTM7K4PO8RFmRxNxO5UPEZEL7GhJJffMy2PNruMAjLwoganDkgkN0q9g8U36zhcRuYBW7SjinvdyKSqtJjTIn6eHpzAiI8HsWCKmUvkQEbkAHE4XM7/cweyvd2IY0CU+gtlZGXRsFm52NBHTqXyIiDSww7ZKJs7L5fufTgAwtldrHr++G8GB/iYnE/EMKh8iIg1oxbajTH4/nxNl1YQF+TPtxh4MTW1pdiwRj6LyISLSAOxOFzOWbecf3+wCILllJLOzMmgXF2ZyMhHPo/IhInKeDpyqYOLcXNbvPQnA7y9tw18GddWYReQsVD5ERM7D8s1HuH9BPqfK7UQEB/D3G3swsHsLs2OJeDSVDxGRc1DtcPH3z7by+qqfAEhNiOLlsRm0jg01OZmI51P5EBGpp/0nyhk/N5f8/acA+FOfdjw8sAtBAX7mBhPxEiofIiL18FnBIR5YsIGSSgeRwQE8PzKV/snxZscS8SoqHyIidVDlcPLMJ1t4c+1eANJbR/Py2HQSmmjMIlJfKh8iIr9hT1EZ4+fmUHCgGIA/X96e+/t3JtBfYxaRc6HyISLyKz7ecJCHF26ktMpBk9BAXhiVxpVdmpkdS8SrqXyIiJxBpd3JUx9v5t11+wDo2bYJs8am0yIqxORkIt5P5UNE5Bd2HStl3Ls5bD1cgsUCd1/RgXuv6USAxiwiDULlQ0Tkv3yYe4C/LNpIebWT2LAgXhydxmWdmpodS6RRUfkQEQEqqp08sXgT7/24H4BL2scwa0w6zSKDTU4m0viofIiIz9txpIRx2TlsP1KKxQITr0pi4tVJ+PtZzI4m0iipfIiIT5v/434e+2gTFXYnTSOszBydRu+OcWbHEmnUVD5ExCeVVTl49KMCPsg5AEC/pDheGJVG0wiryclEGj+VDxHxOVsPFzPu3Rx2HSvDzwKTr+3E3Vd0xE9jFhG3UPkQEZ9hGAbzftjPE4s3UeVw0TzSyqwx6VzcPtbsaCI+ReVDRHxCaZWDv3ywkcX5BwG4onNTZoxMJTZcYxYRd1P5EJFGr+CAjfHZOew5Xo6/n4UHruvMHf3aa8wiYhKVDxFptAzD4J3v9vLUJ1uodrhoGRXMy1npXNQmxuxoIj7tnK8V/Nlnn5GZmclDDz102rr169eTlZVFnz59uOWWW9i2bdt5hRQRqa/iSjvjsnN49KNNVDtcXNO1GUsn9VPxEPEA51Q+Dh06xB133EFJSQm7du2qtW7jxo3069ePuLg4nnjiCZxOJ71792b//v0NElhE5LdsKDzF4FkrWbrxMIH+Fv46uCv/+n0m0aFBZkcTEcBiGIZRnzu4XC6uvfZahg0bxrJlywgODmbBggU160eNGsXhw4f59ttva7bv3LkzgwYNYubMmXV6juLiYqKiorDZbERGRtYnnoj4MMMw+PfqPUz7dAt2p0FCkxBmZ2WQlhhtdjQRn1DX1+96H/mYNm0agYGBTJgw4Yzrv/zySwYPHvz/nsDPj0GDBvHll1/W96lEROrMVm7nz2+v58mPN2N3GgxIjueTif1UPEQ8UL1OOF2zZg2zZ88mJycHi+X0s8TLyso4ceIELVu2rLW8ZcuW7Nu376yPW1VVRVVVVc3t4uLi+sQSER+Xs+8kE7JzOXCqgiB/Px4Z3JXfX9rmjL+nRMR8dS4fJ0+eJCsri1dffZUWLVqccRu73Q6A1Vr7ffMhISE1685k2rRpTJ06ta5RREQAcLkMXl+1m79/tg2Hy6BNbCizx2bQPSHK7Ggi8ivqPHb55ptvOHToEE8//TSZmZlkZmayatUqvvrqKzIzMzl06BAREREEBgZy/PjxWvctKioiNvbsVxCcMmUKNput5ksnp4rIbzlZVs1tb/3IM0u34nAZDO7Rgo8n9FXxEPECdT7yccUVV7B69epay+69916CgoJ47rnniI2Nxd/fn9TUVH744Qfuuuuumu3WrVtHRkbGWR/barWedrRERORsfthzgolzczlkqyQowI/Hr+9GVq/WGrOIeIk6l4/o6GgyMzNrLYuKiiI4OLjW8ttuu40HHniAe++9l+7du/PNN9/w1VdfsXDhwoZLLSI+yeUyePWbXbzwxXacLoP2cWHMzsqgW0u9K07EmzT4FU7vuOMONm/eTGZmJgkJCRw4cIBHH32UoUOHNvRTiYgPKSqtYvL7+Xy7/RgAw9Na8vQN3Qm36kLNIt6m3tf5+G87d+7Ez8+P9u3bn7buxIkTHDhwgNatWxMVVb8ZrK7zISL/7bvdx5k4N5ejJVUEB/rx5NAURmYmaMwi4mHq+vp9Xn8ydOzY8azrYmJiiInRZYxF5Nw5XQazv9rJzC+34zKgY7Nw5mRl0Dk+wuxoInIedLxSRDzS0ZJK7n0vj9U7f3733E0XJfDksGRCg/RrS8Tb6adYRDzOqh1F3PNeHkWlVYQE+vO3G1IYkZFgdiwRaSAqHyLiMRxOFzO/3MHsr3diGNAlPoLZWRl0bBZudjQRaUAqHyLiEQ7bKpk4L5fvfzoBwNheiTx+fTLBgf4mJxORhqbyISKmW7HtKJPfz+dEWTVhQf48M6I7w9JamR1LRC4QlQ8RMY3d6eKFL7bz6opdAHRrEcmcmzNoFxdmcjIRuZBUPkTEFAdPVTBhbi7r954E4PeXtuEvg7pqzCLiA1Q+RMTtvtxyhPvm53Oq3E6ENYDnburBoO5n/rRsEWl8VD5ExG2qHS7+/tlWXl/1EwA9EqKYPTaD1rGhJicTEXdS+RARt9h/opzxc3PJ338KgD/1acdDAztjDdCYRcTXqHyIyAX3WcFhHlyQT3Glg8jgAJ4fmUr/5HizY4mISVQ+ROSCqXI4mbZ0K2+s2QNAeutoXh6bTkITjVlEfJnKh4hcEHuPlzE+O5eNB2wA/Pmy9tx/XWcC/f1MTiYiZlP5EJEG98mGQzy8cAMlVQ6ahAYyY1QqV3VpbnYsEfEQKh8i0mAq7U6e/mQz73y3D4CebZswa2w6LaJCTE4mIp5E5UNEGsTuY6WMy85ly6FiAO6+ogOTr+1EgMYsIvILKh8ict4+zD3AXxZtpLzaSWxYEC+MTuPyTk3NjiUiHkrlQ0TOWUW1kycWb+K9H/cDcEn7GGaOSad5ZLDJyUTEk6l8iMg52Xm0hHHv5rLtSAkWC0y8KomJVyfh72cxO5qIeDiVDxGptwXrC3n0wwIq7E6aRliZOTqN3h3jzI4lIl5C5UNE6qy82sFfPyzgg5wDAPTtGMeLo9NoGmE1OZmIeBOVDxGpk62Hixn3bg67jpXhZ4HJ13biris6aswiIvWm8iEiv8owDN77YT+PL95ElcNF80grs8akc3H7WLOjiYiXUvkQkbMqrXLwyKKNfJR3EIDLOzXlhVGpxIZrzCIi507lQ0TOaNNBG+Ozc/mpqAx/Pwv39+/Mny9rj5/GLCJynlQ+RKQWwzB4Z90+nvp4M9UOFy2jgnk5K52L2sSYHU1EGgmVDxGpUVxpZ8rCjXyy8RAA13RtxvSbUmkSFmRyMhFpTFQ+RASADYWnGJ+dy74T5QT4WXh4YBdu7dsOi0VjFhFpWCofIj7OMAzeWLOHZ5Zuwe40SGgSwuysDNISo82OJiKNlMqHiA+zldt5YEE+yzYfAeC65Ob8/aZUokICTU4mIo2ZyoeIj8rdd5Lx2bkcOFVBkL8fjwzuyu8vbaMxi4hccCofIj7GMAxeX/kTz322FYfLoE1sKLPHZtA9IcrsaCLiI1Q+RHzIybJq7p+fz5dbjwIwuEcLpo3oTmSwxiwi4j4qHyI+4sc9J5gwN5dDtkqCAvx4bEg3br64tcYsIuJ2Kh8ijZzLZfCPb3cxY9l2nC6D9nFhzM7KoFvLSLOjiYiPUvkQacSOl1Yx+f18vtl+DIDhaS15+obuhFv1oy8i5tFvIJFG6rvdx5k0L5cjxVUEB/oxdWgyozITNWYREdOpfIg0Mk6XwZyvd/LS8u24DOjYLJw5WRl0jo8wO5qICKDyIdKoHC2pZPJ7+azaWQTATRcl8OSwZEKD9KMuIp5Dv5FEGonVO4uYNC+PotIqQgL9eXp4CjdelGB2LBGR06h8iHg5p8tg5pc7ePmrHRgGdG4ewZyb0+nYTGMWEfFMKh8iXuxIcSUT5+ay7qcTAIztlcjj1ycTHOhvcjIRkbNT+RDxUt9sP8a97+VxoqyasCB/nhnRnWFprcyOJSLym1Q+RLyMw+lixhfbeXXFLgC6tohkTlY67ZuGm5xMRKRu6l0+7HY7+fn5FBUVkZSURIcOHc643YYNG9i7dy9JSUl06dLlvIOKCBw8VcHEubn8uPckAL+7pA2PDO6qMYuIeJV6lY8lS5Zw//33ExMTQ2RkJGvWrOHaa69l7ty5WK1WAKqrqxk1ahQrV64kLS2NH374gZEjR/L666/r4kYi5+GrrUeY/H4+p8rtRFgDePbGHgzu0cLsWCIi9VbvIx8rV66kWbNmAOzfv5/OnTvz73//mzvvvBOAl156idWrV5Ofn09CQgKbNm0iMzOTK664gt/97ncNm17EB1Q7XEz/fCv/WvkTAN1bRTE7K502sWEmJxMROTd+9dn4+uuvrykeAK1atSIqKgqbzVaz7O2332b06NEkJPx8fYHk5GQGDhzI22+/3UCRRXzH/hPljPrn2pri8cc+bVlw16UqHiLi1ep95KO4uJhly5ZRVlbGBx98QLt27bj99tsBcDgcbNmyhQkTJtS6T48ePfjHP/5x1sesqqqiqqqq1nOI+LrPNx3mgfn5FFc6iAwOYPrIVK5Ljjc7lojIeat3+bDZbMybN49Tp06Rl5fHrbfeSkTEzxczKi0txel00qRJk1r3iY2N5dSpU2d9zGnTpjF16tT6RhFplKocTqYt3coba/YAkJYYzctj00mMCTU3mIhIA6l3+UhMTGTBggXAz+d89OzZk9DQUB5//PGak07Ly8tr3ae0tJTg4OCzPuaUKVOYPHlyze3i4mISExPrG03E6+09Xsb47Fw2Hvh5lHl7v3Y8cF0XggLqNSEVEfFo53Wdj8TERK6++mq++eYbAEJCQoiPj2ffvn21ttu3bx/t27c/6+NYrdaa4iLiqz7ZcIiHF26gpMpBdGggM0amcnXX5mbHEhFpcPX6c+ro0aO1bjscDjZu3FhzcinAwIED+eCDD3C5XABUVlayZMkSBg4c2ABxRRqfSruTv364kXHZOZRUOchs04SlE/upeIhIo2UxDMOo68a9evWid+/epKamUlFRwXvvvceWLVv49ttvay4ktmfPHnr27Enfvn0ZNGgQ8+bNY9euXaxfv57Y2Ng6PU9xcXHNu2giIyPP7X8m4gV2HytlXHYuWw79fJL13Vd04N5rOxHorzGLiHifur5+1+s33MqVK0lOTmb16tVs3LiRkSNHsmvXrlpXMG3bti05OTl06dKFFStW0K9fP3744Yc6Fw8RX/FR3gGuf3kVWw4VExMWxJt/6sWDA7qoeIhIo1evIx/uoiMf0phVVDuZumQT837YD8DF7WKYNTad5pFnPylbRMQb1PX1Wx8sJ+JGO4+WMO7dXLYdKcFigQlXdmTi1UkE6GiHiPgQlQ8RN1mwvpBHPyygwu4kLtzKS6PT6JsUZ3YsERG3U/kQucDKqx08+uEmFuYUAtCnYywvjk6jWYTGLCLim1Q+RC6gbYdLuPvd9ew6VoafBe65phPjruyIv58+4VlEfJfKh8gFYBgG7/2wn8cXb6LK4aJZhJVZY9O5pL3e9SUiovIh0sBKqxw8smgjH+UdBOCyTk15YVQqceG6iq+ICKh8iDSoTQdtTMjOZXdRGf5+Fu7r34k7L+uAn8YsIiI1VD5EGoBhGLyzbh9PfbyZaoeLFlHBzBqbTs+2MWZHExHxOCofIuepuNLOlA828smGQwBc1aUZM0am0iQsyORkIiKeSeVD5DxsLLQxLjuHfSfKCfCz8NCALtzat53GLCIiv0LlQ+QcGIbBm2v28MzSrVQ7XbSKDuHlrHQyWjcxO5qIiMdT+RCpJ1u5nQcX5vP5piMA9O/WnOk3pRIVGmhyMhER76DyIVIPuftOMmFuLoUnKwj0t/CXQV25pXdbLBaNWURE6krlQ6QODMPgf1f9xLOfbsXhMmgdE8rsrHR6JESbHU1ExOuofIj8hpNl1dw/P58vtx4FYFD3eJ69sQeRwRqziIicC5UPkV+xfu8JJmTnctBWSVCAH48O6cb/XNxaYxYRkfOg8iFyBi6XwT+/3c3zy7bhdBm0iwtjdlY6yS2jzI4mIuL1VD5EfuF4aRWT38/nm+3HABia2pJnRnQn3KofFxGRhqDfpiL/Zd3u40ycl8uR4iqsAX5MHZrM6J6JGrOIiDQglQ8RwOkyeOXrnby4fDsuAzo0DWPOzRl0iY80O5qISKOj8iE+71hJFfe8l8vqnccBGJHRiqeGpRCmMYuIyAWh367i09bsLGLivDyKSqsICfTnyWHJjMxMNDuWiEijpvIhPsnpMpj55Q5e/moHhgGdmoczJyuDpOYRZkcTEWn0VD7E5xwprmTSvFy+230CgNGZiTwxNJmQIH+Tk4mI+AaVD/Ep32w/xuT38jheVk1okD/P3NCd4emtzI4lIuJTVD7EJzicLl74YjuvrNgFQNcWkczJSqd903CTk4mI+B6VD2n0DtkqmDg3lx/2nATg5otb8+iQbgQHaswiImIGlQ9p1L7aeoT73s/nZLmdcGsAz97YnSE9WpodS0TEp6l8SKNkd7qY/vk2Xvt2NwAprSKZPTaDtnFhJicTERGVD2l0Ck+WM2FuLrn7TgFwS++2TBnUBWuAxiwiIp5A5UMalWWbDnP//HyKKx1EBAcw/aYeDEhpYXYsERH5Lyof0ihUO1xM+3QL/169B4DUxGhmj00nMSbU3GAiInIalQ/xevuOlzN+bg4bCm0A3Na3HQ8O6EJQgJ/JyURE5ExUPsSrLd14iIcWbKCkykFUSCAzRqZyTbfmZscSEZFfofIhXqnS7uRvn2zh7e/2AnBRmybMGptOq+gQk5OJiMhvUfkQr/NTURnjs3PYdLAYgDsv78B9/TsR6K8xi4iIN1D5EK/yUd4B/vLBRsqqncSEBTFjVCpXdm5mdiwREakHlQ/xCpV2J1OXbGLu9/sB6NU2hllj04mPCjY5mYiI1JfKh3i8nUdLGZ+dw9bDJVgsMP7Kjky6OokAjVlERLySyod4tIXrC/nrhwVU2J3EhQfx4ug0+iU1NTuWiIicB5UP8Ujl1Q4e+2gTC9YXAnBp+1hmjkmjWaTGLCIi3k7lQzzO9iMljHs3hx1HS/GzwKSrOzH+qo74+1nMjiYiIg1A5UM8hmEYzP+xkMcWF1Bpd9E0wsqsMelc2iHW7GgiItKAVD7EI5RVOXhk0UY+zDsIQL+kOF4cnUZcuNXkZCIi0tBUPsR0mw8WMz47h91FZfj7WZh8bSfuurwDfhqziIg0SvV6r+KRI0d45JFH6Nu3LxdffDHjx4/nwIEDp233zTffMGjQIJKTkxk+fDg5OTkNFlgaD8MweHfdXoa/sprdRWXERwYz745LGHdlRxUPEZFGrF7l4/rrryc8PJxnn32Wl156iZ07d9KnTx9OnDhRs80PP/xA//79yczM5I033qBVq1ZcccUV7Nq1q8HDi/cqqbQzYW4ujywqoNrh4srOTVk6qR8928aYHU1ERC4wi2EYRl03ttvtBAYG1twuLi6mSZMmvP3222RlZQEwfPhwysrK+OKLL2q269atG5dffjmvvvpqnZ6nuLiYqKgobDYbkZGRdY0nXqLggI1x2TnsPV5OgJ+FBwd05ra+7XW0Q0TEy9X19bteRz7+u3jAz4fNLRYLFsv/e9FYsWIF1113Xa3tBg4cyIoVK+rzVNIIGYbBm2v2MOKVNew9Xk6r6BDev/NS7rhM53eIiPiS8zrh9IknniAyMpL+/fsDUFJSgs1mIz4+vtZ28fHxFBYWnvVxqqqqqKqqqrldXFx8PrHEA9kq7Dy0YAOfbToMwLXdmjP9ph5EhwaZnExERNztnMvH66+/zuzZs1m0aBGxsT9fh8HlcgGnHyEJCgrC6XSe9bGmTZvG1KlTzzWKeLi8/acYn51D4ckKAv0tTBnYlT/2aVvriJmIiPiOc/pkrjfffJO7776bd955hyFDhtQsj4iIwGq1cvz48VrbFxUVERcXd9bHmzJlCjabreZr//795xJLPIxhGLy+cjcj/7GGwpMVJMaEsODO3vypbzsVDxERH1bvIx9vv/02d9xxB2+99RajR4+utc7Pz4+MjAzWrl3L3XffXbN81apVZGZmnvUxrVYrVqsuJtWYnCqv5v75G1i+5QgAg7rH8+yNPYgMDvyNe4qISGNXryMf2dnZ3Hbbbbz55puMGTPmjNvceeedLFy4kDVr1gCwZMkSVq5cyV133XX+acUrrN97kkEzV7J8yxGC/P14algyc7IyVDxERASo51ttw8LCcLlctGrVqtbyiRMnMnHixJrbjz/+ONOnTyckJAS73c7TTz9da/1v0VttvZPLZfDayt1M/3wbTpdB29hQZmdlkNIqyuxoIiLiBnV9/a5X+di9e3fNSaX/LSYmhpiY2heHqqys5NixYzRv3pygoPq9o0Hlw/scL63ivvn5rNh2DIChqS15ZkR3wq26gr+IiK+o6+t3vV4Z2rdvX+dtg4ODSUxMrM/Di5f6/qcTTJibw5HiKqwBfjwxNJkxPRN1UqmIiJyR/iyVc+ZyGbyyYicvfLEdlwEdmoYx5+YMusTraJWIiJydyoeck2MlVUx+P4+VO4oAGJHRiqeGpRCmMYuIiPwGvVJIva3ZWcSk9/I4VlJFSKA/Tw5LZmSmRmwiIlI3Kh9SZ06XwawvdzDrqx0YBnRqHs6crAySmkeYHU1ERLyIyofUydHiSibNy2Pt7p+vXjumZyKPX59MSJC/yclERMTbqHzIb1q54xj3vpdHUWk1YUH+PDOiO8PSWv32HUVERM5A5UPOyuF08dLyHcxZsRPDgK4tIpmdlU6HpuFmRxMRES+m8iFndMhWwaS5eXy/5wQAN1/cmkeHdCM4UGMWERE5Pyofcpqvtx5l8vt5nCy3E24N4NkbuzOkR0uzY4mISCOh8iE17E4Xz3++jX9+uxuAlFaRzMnKoE1smMnJRESkMVH5EAAOnKpgQnYOOftOAXBL77ZMGdQFa4DGLCIi0rBUPoQvNh/h/vn52CrsRAQHMP2mHgxIaWF2LBERaaRUPnxYtcPFs59u5f9W/wRAamI0s8emkxgTanIyERFpzFQ+fNT+E+WMz84hv9AGwG192/HggC4EBfiZnExERBo7lQ8f9OnGQzy4cAMllQ6iQgKZMTKVa7o1NzuWiIj4CJUPH1Jpd/LM0i28tXYvABe1acKssem0ig4xOZmIiPgSlQ8fsaeojHHZOWw6WAzAnZd34L7+nQj015hFRETcS+XDByzOP8hfPthIaZWDmLAgXhiVyhWdm5kdS0REfJTKRyNWaXcydclm5n6/D4Be7WKYNSad+Khgk5OJiIgvU/lopHYeLWV8dg5bD5dgscD4Kzsy6eokAjRmERERk6l8NEIf5BTy1w8LKK92EhcexEuj0+mbFGd2LBEREUDlo1Epr3bw+EebmL++EIDeHWJ5aXQazSI1ZhEREc+h8tFIbD9Swrh3c9hxtBQ/C0y6uhPjr+qIv5/F7GgiIiK1qHx4OcMwmL++kMc+KqDS7qJZhJWZY9K5tEOs2dFERETOSOXDi5VVOfjrhwUsyj0AQL+kOF4cnUZcuNXkZCIiImen8uGlthwqZty7OewuKsPfz8Lkaztx1+Ud8NOYRUREPJzKh5cxDIPs7/cxdclmqh0u4iODeTkrnZ5tY8yOJiIiUicqH16kpNLOlA828vGGQwBc2bkpM0alERMWZHIyERGRulP58BIFB2yMz85hz/FyAvwsPDigM7f1ba8xi4iIeB2VDw9nGAZvrd3L3z7ZQrXTRavoEGaNTeeiNk3MjiYiInJOVD48mK3CzsMLN/BpwWEArunanOdH9iA6VGMWERHxXiofHipv/ynGZ+dQeLKCQH8LUwZ25Y992mKxaMwiIiLeTeXDwxiGwf+u+onnPtuK3WmQGBPC7LEZpCZGmx1NRESkQah8eJBT5dXcP38Dy7ccAWBgSjzP3tiDqJBAk5OJiIg0HJUPD7F+70kmZOdw0FZJkL8ffx3Sld9d0kZjFhERaXRUPkzmchm8tnI30z/fhtNl0DY2lNlZGaS0ijI7moiIyAWh8mGiE2XVTH4/jxXbjgFwfWpLnrkhhYhgjVlERKTxUvkwyfc/nWDi3FwOF1diDfDjiaHJjOmZqDGLiIg0eiofbuZyGbyyYicvfLEdlwHtm4YxJyuDri0izY4mIiLiFiofbnSspIrJ7+exckcRACPSW/HU8BTCrNoNIiLiO/Sq5yZrdhYx6b08jpVUERzox5PDUhh5UYLGLCIi4nNUPi4wp8tg1pc7mPXVDgwDkpqF88rNGSQ1jzA7moiIiClUPi6go8WVTJqXx9rdxwEYlZnA1KEphAT5m5xMRETEPCofF8jKHce49708ikqrCQ3y5283pHBDeoLZsUREREx3TuUjPz+f3NxcLrvsMtq3b3/aesMwWLt2LXv37iUpKYnMzMzzDuotHE4XLy7fzisrdmEY0CU+gtlZGXRsFm52NBEREY9Qr/Lx3Xffcd9991FcXExBQQFvv/32aeWjsrKS66+/noKCAnr16sWqVau45ppryM7Oxt+/cY8bDtkqmDQ3j+/3nABgbK/WPH59N4IDG/f/W0REpD7qVT6qqqp47rnn6Nu371nfpfH8889TUFBAXl4ezZs3Z8eOHaSlpfHGG29w6623NkhoT/T11qNMfj+Pk+V2wq0BPDOiO0NTW5odS0RExOPUq3xcfvnlv7lNdnY2o0ePpnnz5gAkJSUxaNAgsrOzG2X5sDtdPP/5Nv757W4AkltGMicrg7ZxYSYnExER8Ux+Dflgdrudbdu2kZycXGt5SkoKBQUFZ71fVVUVxcXFtb68wYFTFYz+59qa4vGHS9uw8K7eKh4iIiK/okHf7VJaWorL5SI6OrrW8piYGGw221nvN23aNKZOndqQUS64LzYf4f75+dgq7EQEB/D3G3swsHsLs2OJiIh4vAY98hESEgJAWVlZreUlJSU1685kypQp2Gy2mq/9+/c3ZKwGVe1w8eSSzdz+1o/YKuykJkTxyYR+Kh4iIiJ11KBHPoKDg2nZsiV79uyptXzPnj106NDhrPezWq1YrdaGjHJB7D9RzvjsHPILfz6Kc2vfdjw0oAtBAQ3a4URERBq1Bn/VHDJkCAsXLsThcAA/HwVZsmQJQ4YMaeincqtPNx5i0KyV5BfaiAoJ5F+/z+TRId1UPEREROqpXkc+Dh06xOeff15ze+XKlTgcDjp16kTv3r0BePTRR+nVqxeDBw9mwIABzJ8/n4iICO65554GDe4ulXYnzyzdwltr9wKQ0TqaWWPTSWgSanIyERER71Sv8nHy5ElWrFgBwB/+8AeqqqpYsWIFhmHUlI+EhARyc3N5/fXX2bp1KyNGjOD2228nKiqqwcNfaHuKyhiXncOmgz+/++bPl7fn/v6dCfTX0Q4REZFzZTEMwzA7xC8VFxcTFRWFzWYjMjLSlAyL8w/ylw82UlrloEloIC+MSuPKLs1MySIiIuIN6vr6rQ+W+4VKu5OpSzYz9/t9APRs24RZY9NpEXX2d+uIiIhI3al8/Jddx0oZ924OWw+XYLHAuCs6cs81SQRozCIiItJgVD7+f4tyC3lkUQHl1U5iw4J4aUwa/ZKamh1LRESk0fH58lFR7eSxjwqYv74QgEvbxzJzTBrNIoNNTiYiItI4+XT52H6khHHv5rDjaCkWC0y6OokJVyXh73fmT+wVERGR8+eT5cMwDOavL+SxjwqotLtoGmFl5pg0eneIMzuaiIhIo+dz5aOsysFfPyxgUe4BAPolxfHCqDSaRnj+5d1FREQaA58qH1sOFTMuO4fdx8rws8B9/Ttz1+Ud8NOYRURExG18pnxUVDv5n9fXcbysmvjIYGaNTadXuxizY4mIiPgcnykfIUH+PDqkGx/mHeCFUWnEhAWZHUlERMQn+Uz5ABie3ophaS2xWDRmERERMYvPXbpTxUNERMRcPlc+RERExFwqHyIiIuJWKh8iIiLiViofIiIi4lYqHyIiIuJWKh8iIiLiViofIiIi4lYqHyIiIuJWKh8iIiLiViofIiIi4lYqHyIiIuJWKh8iIiLiVh75qbaGYQBQXFxschIRERGpq/+8bv/ndfxsPLJ8lJSUAJCYmGhyEhEREamvkpISoqKizrreYvxWPTGBy+Xi4MGDREREYLFYzI7j0YqLi0lMTGT//v1ERkaaHUfOQvvJe2hfeQftJ89kGAYlJSW0bNkSP7+zn9nhkUc+/Pz8SEhIMDuGV4mMjNQPoBfQfvIe2lfeQfvJ8/zaEY//0AmnIiIi4lYqHyIiIuJWKh9ezmq18vjjj2O1Ws2OIr9C+8l7aF95B+0n7+aRJ5yKiIhI46UjHyIiIuJWKh8iIiLiViofIiIi4lYeeZ0POZ3T6WTDhg0cOHCADh060LVr1zNuV1hYyPr164mOjqZ3794EBga6Oan8x/LlyykqKmLEiBEEBQXVWnf06FG+++47wsLC6NOnD8HBwSal9G1bt25l27ZtdOvWjaSkpNPWnzp1itWrV+Pv70/fvn0JDw83IaVvO3z4MBs2bMDhcJCcnEybNm1O26asrIxVq1bhcDjo3bs3TZo0MSGp1IshHm/p0qVG586djfT0dGPIkCFGTEyMMWDAAKOsrKzWdi+99JIREhJiXHnllUb79u2NLl26GIWFhSal9m2fffaZYbVaDcA4duxYrXXvvPOOERYWZvTr18/o2rWrkZiYaGzevNmkpL7JZrMZgwcPNmJiYoyhQ4caaWlpxj333FNrm88//9yIiooyLr74YiM9Pd2IjY01Vq1aZVJi3zRt2jQjODjYuOqqq4wBAwYYISEhxrhx42pt8/333xvNmjUzUlNTjUsvvdSIiIgwlixZYlJiqSuVDy+wePFiY9euXTW3jxw5YrRo0cKYMmVKzbKCggLDz8/PmD9/vmEYhlFZWWn06tXLGD58uNvz+rpDhw4ZiYmJxtNPP31a+Th48KAREhJivPzyy4ZhGIbT6TQGDRpkXHLJJWbF9Uk33HCDkZycbBw/frxm2UcffVTz77KyMqNp06bGQw89VLPs1ltvNdq2bWvY7Xa3ZvVVR44cMQDj//7v/2qWffHFFwZgfP/994Zh/Pzzk5SUZPzhD3+o2eaRRx4xYmJijOLiYndHlnpQ+fBSI0eONAYOHFhz+5FHHjESExNrbfPWW28Z/v7+xqlTp9wdz2c5nU7jmmuuMZ5//nljyZIlp5WPl19+2QgPDzcqKytrli1btswAjB07dpgR2eds2bLFAIzFixefdZtFixYZFovFOHToUM2yzZs3G4CxYsUKd8T0efv27TMA46uvvqpZtmvXLgOoOQK1du1aAzDy8/Nrtjl69Kjh7+9vzJs3z+2Zpe50wqkXqqioYM2aNaSkpNQs27hxY63bAN27d8fpdLJlyxZ3R/RZzz77LIZhMHny5DOu37hxI0lJSbUujNS9e3cACgoK3JLR13377bf4+/tz5ZVXsnr1aj755BP27NlTa5uNGzcSFxdHfHx8zbKuXbsSGBjIxo0b3ZzYNyUmJjJ16lQmTJjA7Nmzee211xgzZgx33nknffr0AX7eTxaLheTk5Jr7NW3alPj4eO0nD6cTTr3Q3Xffjd1ur/UCZ7PZTvswvtjYWODnk+bkwlu7di0zZ84kJyfnrJ/GbLPZiImJqbVM+8m9jh49SkREBDfeeCM2m40mTZrwzTffcNtttzFr1izgzPsJoEmTJtpPbpSWlkZ2djYLFizAarVy7NgxevbsWbPeZrMRGRmJv79/rfvFxsZqP3k4lQ8v8+CDD7Jo0SKWL19e668yq9VKaWlprW3/c1vvpHCP22+/nf79+7Ny5UoAcnNzAVi0aBEXX3wxPXr00H7yAMHBwZw6dYo+ffrw2GOPAfDdd9/Ru3dvrrvuOgYPHnzG/QQ/7yvtJ/fYsmULI0aMYO7cuYwcORKAdevW0bt3b9q0acPVV1+N1WqlrKzstPtqP3k+jV28yJQpU/jnP//J559/TmZmZq11HTp0YN++fbWW7d27F4D27du7LaMv69u3L3a7nQ8//JAPP/yQtWvXAvDpp5+yadMmQPvJE3To0AGAG2+8sWbZJZdcQqtWrVi/fn3NNseOHaOysrJmm6KiIsrLy7Wf3GTVqlUAjBgxombZxRdfTGJiIl9//TXw835yOBwcPHiwZpvq6moOHz6s/eTpzD7pROpmypQpRmRkpLF27dozrl+yZIlhsViM7du31yy75ZZbjJSUFHdFlF840wmnP/zwQ60T5gzDMB5++GEjPj7ecDgcZsT0OTabzQgNDTUWLFhQs6yoqMiwWq0176zYv3+/ERAQUOukxdmzZxshISHGyZMn3R3ZJ3366acGYGzZsqVm2fHjx42QkBDj1VdfNQzDMEpKSozw8HDjpZdeqtlmwYIFhp+fX613CIrn0djFC7zwwgtMmzaNe+65hz179tScHNekSROuu+46AAYPHlxzyHjChAls27aNd955h6VLl5qYXH4pMzOT3//+94wePZr77ruPI0eOMGPGDN58883T5tZyYURGRvLcc89x5513snPnTqKjo3nttdfo0qULY8aMASAhIYEHH3yQP//5z/z000/Y7XamTZvGk08+SXR0tLn/AR9xzTXXcOmllzJ48GAmTpxIUFAQ//rXv2jZsiVZWVkAhIeH88wzz/Dggw9y8uRJQkNDefbZZ7n33nt15MPD6VNtvcCsWbNYs2bNacvbtm3Ls88+W3Pbbrfz+uuvs27dOqKjo/nDH/5Aenq6O6PKf8nNzeW5557jX//6FxERETXLXS4Xb7/9Nt988w2hoaGMGTOGvn37mpjUN3311VcsXLgQu91Oeno6f/zjH087T2DRokUsXboUPz8/hg8fzsCBA01K65uqq6t5++23ycnJweFwkJKSwh//+MfTrjS7bNkyPvjgAxwOB9ddd13NOSLiuVQ+RERExK10wqmIiIi4lcqHiIiIuJXKh4iIiLiVyoeIiIi4lcqHiIiIuJXKh4iIiLiVyoeIiIi4lcqHiIiIuJXKh4iIiLiVyoeIiIi4lcqHiIiIuJXKh4iIiLjV/wdVs+N0M7Q+1AAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"model = Model()\n",
"loss_fn = nn.L1Loss()\n",
"optimizer = torch.optim.SGD(model.parameters(), lr=0.0001)\n",
"epochs_num = 100\n",
"epochs = []\n",
"losses = []\n",
"for epoch in range(epochs_num):\n",
" model.train()\n",
" y_pred = model(X_train)\n",
" loss = loss_fn(y_pred, y_train)\n",
" optimizer.zero_grad()\n",
" loss.backward()\n",
" optimizer.step()\n",
" epochs.append(epoch)\n",
" losses.append(loss.item())\n",
"plt.plot(X, y)\n",
"plt.plot(X_train, y_pred)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv (3.11.15)",
"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.15"
}
},
"nbformat": 4,
"nbformat_minor": 5
}