From e86e768102a997e5de53aadd440b0e3d3ca7db4f Mon Sep 17 00:00:00 2001 From: Emil Date: Sat, 4 Jul 2026 21:14:40 +0300 Subject: [PATCH] new commit. --- .../00_pytorch_fundamentals.ipynb | 407 ++++---- .../PyTorch_Course/01_pytorch_workflow.ipynb | 954 ++++++++++++++++++ My_Experiments/pytorch.ipynb | 2 +- My_Experiments/pytorch2.ipynb | 2 +- My_Experiments/pytorch3.ipynb | 240 ++++- micrograd_from_scratch.ipynb | 2 +- 6 files changed, 1382 insertions(+), 225 deletions(-) create mode 100644 My_Experiments/PyTorch_Course/01_pytorch_workflow.ipynb diff --git a/My_Experiments/PyTorch_Course/00_pytorch_fundamentals.ipynb b/My_Experiments/PyTorch_Course/00_pytorch_fundamentals.ipynb index d177936..923f29c 100644 --- a/My_Experiments/PyTorch_Course/00_pytorch_fundamentals.ipynb +++ b/My_Experiments/PyTorch_Course/00_pytorch_fundamentals.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 63, + "execution_count": 2, "id": "4138ee2e", "metadata": {}, "outputs": [ @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 3, "id": "fa46b5f3", "metadata": {}, "outputs": [ @@ -43,7 +43,7 @@ "tensor(7)" ] }, - "execution_count": 64, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -56,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": 4, "id": "80146c19", "metadata": {}, "outputs": [ @@ -66,7 +66,7 @@ "0" ] }, - "execution_count": 65, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -77,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 5, "id": "8ebd6387", "metadata": {}, "outputs": [ @@ -87,7 +87,7 @@ "7" ] }, - "execution_count": 66, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -98,7 +98,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 6, "id": "975ba0ba", "metadata": {}, "outputs": [ @@ -108,7 +108,7 @@ "tensor([7, 7])" ] }, - "execution_count": 67, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -120,7 +120,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 7, "id": "adc95f24", "metadata": {}, "outputs": [ @@ -130,7 +130,7 @@ "1" ] }, - "execution_count": 68, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -141,7 +141,7 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": 8, "id": "1364d5be", "metadata": {}, "outputs": [ @@ -151,7 +151,7 @@ "torch.Size([2])" ] }, - "execution_count": 69, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -162,7 +162,7 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": 9, "id": "3d811521", "metadata": {}, "outputs": [ @@ -173,7 +173,7 @@ " [ 9, 10]])" ] }, - "execution_count": 70, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -186,7 +186,7 @@ }, { "cell_type": "code", - "execution_count": 71, + "execution_count": 10, "id": "e9acf917", "metadata": {}, "outputs": [ @@ -196,7 +196,7 @@ "2" ] }, - "execution_count": 71, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -207,7 +207,7 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": 11, "id": "40bd74ac", "metadata": {}, "outputs": [ @@ -217,7 +217,7 @@ "tensor([7, 8])" ] }, - "execution_count": 72, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -228,7 +228,7 @@ }, { "cell_type": "code", - "execution_count": 73, + "execution_count": 12, "id": "8093f799", "metadata": {}, "outputs": [ @@ -238,7 +238,7 @@ "tensor([ 9, 10])" ] }, - "execution_count": 73, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -249,7 +249,7 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": 13, "id": "85b1d000", "metadata": {}, "outputs": [ @@ -259,7 +259,7 @@ "torch.Size([2, 2])" ] }, - "execution_count": 74, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -270,7 +270,7 @@ }, { "cell_type": "code", - "execution_count": 75, + "execution_count": 14, "id": "2ff8b7c4", "metadata": {}, "outputs": [], @@ -290,7 +290,7 @@ }, { "cell_type": "code", - "execution_count": 76, + "execution_count": 15, "id": "1e12a399", "metadata": {}, "outputs": [ @@ -300,7 +300,7 @@ "3" ] }, - "execution_count": 76, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -311,7 +311,7 @@ }, { "cell_type": "code", - "execution_count": 77, + "execution_count": 16, "id": "32e5193a", "metadata": {}, "outputs": [ @@ -321,7 +321,7 @@ "torch.Size([3, 3, 3])" ] }, - "execution_count": 77, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -332,7 +332,7 @@ }, { "cell_type": "code", - "execution_count": 78, + "execution_count": 17, "id": "3a25ca11", "metadata": {}, "outputs": [ @@ -344,7 +344,7 @@ " [7, 8, 9]])" ] }, - "execution_count": 78, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -363,19 +363,19 @@ }, { "cell_type": "code", - "execution_count": 79, + "execution_count": 18, "id": "7526c1ee", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "tensor([[0.1109, 0.4425, 0.1133, 0.9341],\n", - " [0.7576, 0.9063, 0.7243, 0.5338],\n", - " [0.3031, 0.8889, 0.0658, 0.3763]])" + "tensor([[0.4974, 0.9957, 0.6890, 0.7849],\n", + " [0.9054, 0.1436, 0.6384, 0.8741],\n", + " [0.8593, 0.0899, 0.3280, 0.3293]])" ] }, - "execution_count": 79, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -388,7 +388,7 @@ }, { "cell_type": "code", - "execution_count": 80, + "execution_count": 19, "id": "26cc4026", "metadata": {}, "outputs": [ @@ -398,7 +398,7 @@ "2" ] }, - "execution_count": 80, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -409,7 +409,7 @@ }, { "cell_type": "code", - "execution_count": 81, + "execution_count": 20, "id": "bda29746", "metadata": {}, "outputs": [ @@ -419,7 +419,7 @@ "(torch.Size([3, 224, 224]), 3)" ] }, - "execution_count": 81, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -440,7 +440,7 @@ }, { "cell_type": "code", - "execution_count": 82, + "execution_count": 21, "id": "9583ab83", "metadata": {}, "outputs": [ @@ -452,7 +452,7 @@ " [0., 0., 0., 0.]])" ] }, - "execution_count": 82, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -464,7 +464,7 @@ }, { "cell_type": "code", - "execution_count": 83, + "execution_count": 22, "id": "18cc934f", "metadata": {}, "outputs": [ @@ -476,7 +476,7 @@ " [1., 1., 1., 1.]])" ] }, - "execution_count": 83, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -488,7 +488,7 @@ }, { "cell_type": "code", - "execution_count": 84, + "execution_count": 23, "id": "fc494597", "metadata": {}, "outputs": [ @@ -498,7 +498,7 @@ "torch.float32" ] }, - "execution_count": 84, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -517,7 +517,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 24, "id": "01ff10a6", "metadata": {}, "outputs": [ @@ -529,7 +529,7 @@ " 9.0000, 9.5000, 10.0000, 10.5000])" ] }, - "execution_count": 85, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -542,7 +542,7 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 25, "id": "00fcd1b0", "metadata": {}, "outputs": [ @@ -552,7 +552,7 @@ "tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])" ] }, - "execution_count": 86, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -573,7 +573,7 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 26, "id": "f9fbb1f3", "metadata": {}, "outputs": [ @@ -583,7 +583,7 @@ "tensor([3., 6., 9.])" ] }, - "execution_count": 87, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -599,7 +599,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 27, "id": "661203f0", "metadata": {}, "outputs": [ @@ -609,7 +609,7 @@ "torch.float32" ] }, - "execution_count": 88, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -620,7 +620,7 @@ }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 28, "id": "931e8a6b", "metadata": {}, "outputs": [ @@ -630,7 +630,7 @@ "tensor([3., 6., 9.], dtype=torch.float16)" ] }, - "execution_count": 89, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -642,7 +642,7 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 29, "id": "79935a92", "metadata": {}, "outputs": [ @@ -652,7 +652,7 @@ "torch.float32" ] }, - "execution_count": 90, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -663,19 +663,19 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": 30, "id": "b80e8014", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "tensor([[0.6552, 0.8326, 0.2693, 0.4535],\n", - " [0.4237, 0.0072, 0.9796, 0.4627],\n", - " [0.7492, 0.4209, 0.5884, 0.7448]])" + "tensor([[0.5581, 0.7143, 0.7689, 0.4654],\n", + " [0.1519, 0.5226, 0.5498, 0.6938],\n", + " [0.1794, 0.2392, 0.3715, 0.4167]])" ] }, - "execution_count": 91, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } @@ -689,7 +689,7 @@ }, { "cell_type": "code", - "execution_count": 92, + "execution_count": 31, "id": "81a5af8e", "metadata": {}, "outputs": [ @@ -697,9 +697,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "tensor([[0.6552, 0.8326, 0.2693, 0.4535],\n", - " [0.4237, 0.0072, 0.9796, 0.4627],\n", - " [0.7492, 0.4209, 0.5884, 0.7448]])\n", + "tensor([[0.5581, 0.7143, 0.7689, 0.4654],\n", + " [0.1519, 0.5226, 0.5498, 0.6938],\n", + " [0.1794, 0.2392, 0.3715, 0.4167]])\n", "Datatype of tensor: torch.float32\n", "Shape of tensor: torch.Size([3, 4])\n", "Device of tensor: cpu\n" @@ -725,7 +725,7 @@ }, { "cell_type": "code", - "execution_count": 93, + "execution_count": 32, "id": "05fadd99", "metadata": {}, "outputs": [ @@ -735,7 +735,7 @@ "tensor([101, 102, 103])" ] }, - "execution_count": 93, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -748,7 +748,7 @@ }, { "cell_type": "code", - "execution_count": 94, + "execution_count": 33, "id": "cced037e", "metadata": {}, "outputs": [ @@ -758,7 +758,7 @@ "tensor([202, 204, 206])" ] }, - "execution_count": 94, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } @@ -778,7 +778,7 @@ }, { "cell_type": "code", - "execution_count": 95, + "execution_count": 34, "id": "dae43f89", "metadata": {}, "outputs": [ @@ -795,7 +795,7 @@ "tensor([1, 4, 9])" ] }, - "execution_count": 95, + "execution_count": 34, "metadata": {}, "output_type": "execute_result" } @@ -809,7 +809,7 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 35, "id": "5335eb6a", "metadata": {}, "outputs": [ @@ -819,7 +819,7 @@ "tensor(14)" ] }, - "execution_count": 96, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } @@ -831,7 +831,7 @@ }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 36, "id": "96214e1c", "metadata": {}, "outputs": [ @@ -841,7 +841,7 @@ "14" ] }, - "execution_count": 97, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } @@ -853,7 +853,7 @@ }, { "cell_type": "code", - "execution_count": 98, + "execution_count": 37, "id": "839afbd2", "metadata": {}, "outputs": [ @@ -861,8 +861,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 1.87 ms, sys: 993 μs, total: 2.86 ms\n", - "Wall time: 1.7 ms\n" + "CPU times: user 971 μs, sys: 769 μs, total: 1.74 ms\n", + "Wall time: 885 μs\n" ] }, { @@ -871,7 +871,7 @@ "tensor(14)" ] }, - "execution_count": 98, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -886,7 +886,7 @@ }, { "cell_type": "code", - "execution_count": 99, + "execution_count": 38, "id": "1c1c93ce", "metadata": {}, "outputs": [ @@ -894,8 +894,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 718 μs, sys: 0 ns, total: 718 μs\n", - "Wall time: 541 μs\n" + "CPU times: user 204 μs, sys: 58 μs, total: 262 μs\n", + "Wall time: 170 μs\n" ] }, { @@ -904,7 +904,7 @@ "tensor(14)" ] }, - "execution_count": 99, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } @@ -924,7 +924,7 @@ }, { "cell_type": "code", - "execution_count": 100, + "execution_count": 39, "id": "837697b0", "metadata": {}, "outputs": [ @@ -932,8 +932,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 733 μs, sys: 0 ns, total: 733 μs\n", - "Wall time: 608 μs\n" + "CPU times: user 872 μs, sys: 0 ns, total: 872 μs\n", + "Wall time: 876 μs\n" ] }, { @@ -942,7 +942,7 @@ "tensor(14)" ] }, - "execution_count": 100, + "execution_count": 39, "metadata": {}, "output_type": "execute_result" } @@ -955,19 +955,19 @@ }, { "cell_type": "code", - "execution_count": 101, + "execution_count": 40, "id": "12f61493", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(tensor([[0.9213, 0.9373],\n", - " [0.9613, 1.0427]]),\n", + "(tensor([[0.1963, 0.6142],\n", + " [0.1970, 0.4875]]),\n", " torch.Size([2, 2]))" ] }, - "execution_count": 101, + "execution_count": 40, "metadata": {}, "output_type": "execute_result" } @@ -979,7 +979,7 @@ }, { "cell_type": "code", - "execution_count": 102, + "execution_count": 41, "id": "bef98c6b", "metadata": {}, "outputs": [ @@ -1024,7 +1024,7 @@ }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 42, "id": "4b0c4fe3", "metadata": {}, "outputs": [ @@ -1034,7 +1034,7 @@ "tensor([ 0., 10., 20., 30., 40., 50., 60., 70., 80., 90.])" ] }, - "execution_count": 103, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" } @@ -1046,7 +1046,7 @@ }, { "cell_type": "code", - "execution_count": 104, + "execution_count": 43, "id": "013597a9", "metadata": {}, "outputs": [ @@ -1056,7 +1056,7 @@ "(tensor(0.), tensor(0.))" ] }, - "execution_count": 104, + "execution_count": 43, "metadata": {}, "output_type": "execute_result" } @@ -1067,7 +1067,7 @@ }, { "cell_type": "code", - "execution_count": 105, + "execution_count": 44, "id": "c071479e", "metadata": {}, "outputs": [ @@ -1077,7 +1077,7 @@ "(tensor(90.), tensor(90.))" ] }, - "execution_count": 105, + "execution_count": 44, "metadata": {}, "output_type": "execute_result" } @@ -1088,7 +1088,7 @@ }, { "cell_type": "code", - "execution_count": 106, + "execution_count": 45, "id": "9bb59339", "metadata": {}, "outputs": [ @@ -1098,7 +1098,7 @@ "(tensor(45.), tensor(45.))" ] }, - "execution_count": 106, + "execution_count": 45, "metadata": {}, "output_type": "execute_result" } @@ -1109,7 +1109,7 @@ }, { "cell_type": "code", - "execution_count": 107, + "execution_count": 46, "id": "a4896145", "metadata": {}, "outputs": [ @@ -1119,7 +1119,7 @@ "(tensor(450.), tensor(450.))" ] }, - "execution_count": 107, + "execution_count": 46, "metadata": {}, "output_type": "execute_result" } @@ -1138,7 +1138,7 @@ }, { "cell_type": "code", - "execution_count": 108, + "execution_count": 47, "id": "abe4c14d", "metadata": {}, "outputs": [ @@ -1148,7 +1148,7 @@ "tensor([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])" ] }, - "execution_count": 108, + "execution_count": 47, "metadata": {}, "output_type": "execute_result" } @@ -1160,7 +1160,7 @@ }, { "cell_type": "code", - "execution_count": 109, + "execution_count": 48, "id": "7ef986e5", "metadata": {}, "outputs": [ @@ -1170,7 +1170,7 @@ "(tensor(0), tensor(9))" ] }, - "execution_count": 109, + "execution_count": 48, "metadata": {}, "output_type": "execute_result" } @@ -1181,7 +1181,7 @@ }, { "cell_type": "code", - "execution_count": 110, + "execution_count": 49, "id": "7ad63bda", "metadata": {}, "outputs": [ @@ -1191,7 +1191,7 @@ "tensor(0)" ] }, - "execution_count": 110, + "execution_count": 49, "metadata": {}, "output_type": "execute_result" } @@ -1210,7 +1210,7 @@ }, { "cell_type": "code", - "execution_count": 111, + "execution_count": 50, "id": "f0a1909b", "metadata": {}, "outputs": [ @@ -1220,7 +1220,7 @@ "(tensor([1., 2., 3., 4., 5., 6., 7., 8., 9.]), torch.Size([9]))" ] }, - "execution_count": 111, + "execution_count": 50, "metadata": {}, "output_type": "execute_result" } @@ -1233,7 +1233,7 @@ }, { "cell_type": "code", - "execution_count": 112, + "execution_count": 51, "id": "ba064450", "metadata": {}, "outputs": [ @@ -1252,7 +1252,7 @@ " torch.Size([9, 1]))" ] }, - "execution_count": 112, + "execution_count": 51, "metadata": {}, "output_type": "execute_result" } @@ -1265,7 +1265,7 @@ }, { "cell_type": "code", - "execution_count": 113, + "execution_count": 52, "id": "ed78b429", "metadata": {}, "outputs": [ @@ -1275,7 +1275,7 @@ "(tensor([[1., 2., 3., 4., 5., 6., 7., 8., 9.]]), torch.Size([1, 9]))" ] }, - "execution_count": 113, + "execution_count": 52, "metadata": {}, "output_type": "execute_result" } @@ -1288,7 +1288,7 @@ }, { "cell_type": "code", - "execution_count": 114, + "execution_count": 53, "id": "cf403167", "metadata": {}, "outputs": [ @@ -1299,7 +1299,7 @@ " tensor([5., 2., 3., 4., 5., 6., 7., 8., 9.]))" ] }, - "execution_count": 114, + "execution_count": 53, "metadata": {}, "output_type": "execute_result" } @@ -1312,7 +1312,7 @@ }, { "cell_type": "code", - "execution_count": 115, + "execution_count": 54, "id": "ca8cb352", "metadata": {}, "outputs": [ @@ -1330,7 +1330,7 @@ " [9., 9., 9., 9.]])" ] }, - "execution_count": 115, + "execution_count": 54, "metadata": {}, "output_type": "execute_result" } @@ -1343,7 +1343,7 @@ }, { "cell_type": "code", - "execution_count": 116, + "execution_count": 55, "id": "cdb0b28c", "metadata": {}, "outputs": [ @@ -1366,7 +1366,7 @@ }, { "cell_type": "code", - "execution_count": 117, + "execution_count": 56, "id": "5f036e71", "metadata": {}, "outputs": [ @@ -1403,6 +1403,55 @@ "print(x_reshaped.unsqueeze(dim=2).shape)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "22fcea9f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(torch.Size([224, 224, 3]), torch.Size([3, 224, 224]))" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Permuting dimensions\n", + "x_original = torch.rand(size=(224, 224, 3)) # [height, width, colour_channels]\n", + "x_original.shape\n", + "\n", + "x_permuted = x_original.permute(2, 0, 1) # [colour_channels, height, width]\n", + "\n", + "x_original.shape, x_permuted.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "013fd834", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(tensor(12345.), tensor(12345.))" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x_original[0, 0, 0] = 12345\n", + "x_original[0, 0, 0], x_permuted[0, 0, 0] # they share memory" + ] + }, { "cell_type": "markdown", "id": "57a63474", @@ -1413,7 +1462,7 @@ }, { "cell_type": "code", - "execution_count": 121, + "execution_count": 57, "id": "bb3e71e7", "metadata": {}, "outputs": [ @@ -1426,7 +1475,7 @@ " torch.Size([1, 3, 3]))" ] }, - "execution_count": 121, + "execution_count": 57, "metadata": {}, "output_type": "execute_result" } @@ -1438,7 +1487,7 @@ }, { "cell_type": "code", - "execution_count": 123, + "execution_count": 58, "id": "8c42f28e", "metadata": {}, "outputs": [ @@ -1466,7 +1515,7 @@ }, { "cell_type": "code", - "execution_count": 126, + "execution_count": 59, "id": "ab0376d9", "metadata": {}, "outputs": [ @@ -1476,7 +1525,7 @@ "tensor([[1, 2, 3]])" ] }, - "execution_count": 126, + "execution_count": 59, "metadata": {}, "output_type": "execute_result" } @@ -1487,7 +1536,7 @@ }, { "cell_type": "code", - "execution_count": 127, + "execution_count": 60, "id": "c7ecdc4d", "metadata": {}, "outputs": [ @@ -1497,7 +1546,7 @@ "tensor([[2, 5, 8]])" ] }, - "execution_count": 127, + "execution_count": 60, "metadata": {}, "output_type": "execute_result" } @@ -1508,7 +1557,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 61, "id": "cc2c0da2", "metadata": {}, "outputs": [ @@ -1518,7 +1567,7 @@ "tensor([5])" ] }, - "execution_count": 133, + "execution_count": 61, "metadata": {}, "output_type": "execute_result" } @@ -1529,7 +1578,7 @@ }, { "cell_type": "code", - "execution_count": 134, + "execution_count": 62, "id": "20b11409", "metadata": {}, "outputs": [ @@ -1539,7 +1588,7 @@ "tensor([1, 2, 3])" ] }, - "execution_count": 134, + "execution_count": 62, "metadata": {}, "output_type": "execute_result" } @@ -1558,7 +1607,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 63, "id": "e7bb6813", "metadata": {}, "outputs": [ @@ -1569,7 +1618,7 @@ " tensor([1., 2., 3., 4., 5., 6., 7.], dtype=torch.float64))" ] }, - "execution_count": 14, + "execution_count": 63, "metadata": {}, "output_type": "execute_result" } @@ -1584,7 +1633,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 64, "id": "61b93491", "metadata": {}, "outputs": [ @@ -1595,7 +1644,7 @@ " tensor([1., 2., 3., 4., 5., 6., 7.], dtype=torch.float64))" ] }, - "execution_count": 15, + "execution_count": 64, "metadata": {}, "output_type": "execute_result" } @@ -1607,7 +1656,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 65, "id": "41d9fd3a", "metadata": {}, "outputs": [ @@ -1618,7 +1667,7 @@ " array([1., 1., 1., 1., 1., 1., 1.], dtype=float32))" ] }, - "execution_count": 17, + "execution_count": 65, "metadata": {}, "output_type": "execute_result" } @@ -1631,7 +1680,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 66, "id": "8ada9db6", "metadata": {}, "outputs": [ @@ -1642,7 +1691,7 @@ " array([1., 1., 1., 1., 1., 1., 1.], dtype=float32))" ] }, - "execution_count": 18, + "execution_count": 66, "metadata": {}, "output_type": "execute_result" } @@ -1663,7 +1712,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 67, "id": "0a00667b", "metadata": {}, "outputs": [ @@ -1671,12 +1720,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "A: tensor([[4.2700e-01, 8.9671e-01, 4.1658e-01, 2.9154e-01],\n", - " [3.4190e-02, 3.4361e-01, 3.1516e-01, 2.7454e-04],\n", - " [9.2615e-01, 1.6299e-02, 1.7206e-01, 1.8269e-01]])\n", - "B: tensor([[0.9275, 0.7377, 0.7251, 0.2588],\n", - " [0.4665, 0.1228, 0.1004, 0.6401],\n", - " [0.3025, 0.1982, 0.0094, 0.3338]])\n" + "A: tensor([[0.6495, 0.6435, 0.2537, 0.5257],\n", + " [0.1518, 0.1355, 0.5372, 0.0834],\n", + " [0.4902, 0.8733, 0.4010, 0.1388]])\n", + "B: tensor([[0.6869, 0.5879, 0.5750, 0.9675],\n", + " [0.0820, 0.5819, 0.2359, 0.6734],\n", + " [0.5958, 0.0518, 0.6173, 0.6183]])\n" ] }, { @@ -1687,7 +1736,7 @@ " [False, False, False, False]])" ] }, - "execution_count": 25, + "execution_count": 67, "metadata": {}, "output_type": "execute_result" } @@ -1703,7 +1752,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 68, "id": "ab5c361b", "metadata": {}, "outputs": [ @@ -1715,7 +1764,7 @@ " [True, True, True, True]])" ] }, - "execution_count": 37, + "execution_count": 68, "metadata": {}, "output_type": "execute_result" } @@ -1743,7 +1792,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 69, "id": "30165071", "metadata": {}, "outputs": [ @@ -1751,16 +1800,16 @@ "name": "stdout", "output_type": "stream", "text": [ - "Sat Jul 4 03:48:48 2026 \n", + "Sat Jul 4 14:33:15 2026 \n", "+-----------------------------------------------------------------------------------------+\n", - "| NVIDIA-SMI 580.159.03 Driver Version: 580.159.03 CUDA Version: 13.0 |\n", + "| NVIDIA-SMI 595.71.05 Driver Version: 595.71.05 CUDA Version: 13.2 |\n", "+-----------------------------------------+------------------------+----------------------+\n", "| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |\n", "| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |\n", "| | | MIG M. |\n", "|=========================================+========================+======================|\n", - "| 0 NVIDIA GeForce RTX 3050 ... Off | 00000000:01:00.0 Off | N/A |\n", - "| N/A 38C P0 8W / 74W | 15MiB / 4096MiB | 0% Default |\n", + "| 0 NVIDIA GeForce RTX 2080 Ti Off | 00000000:26:00.0 On | N/A |\n", + "| 35% 54C P0 71W / 250W | 4490MiB / 11264MiB | 11% Default |\n", "| | | N/A |\n", "+-----------------------------------------+------------------------+----------------------+\n", "\n", @@ -1769,7 +1818,25 @@ "| GPU GI CI PID Type Process name GPU Memory |\n", "| ID ID Usage |\n", "|=========================================================================================|\n", - "| 0 N/A N/A 1997 G /usr/lib/xorg/Xorg 4MiB |\n", + "| 0 N/A N/A 2538 G /usr/bin/ksecretd 2MiB |\n", + "| 0 N/A N/A 2697 G /usr/bin/kwin_wayland 126MiB |\n", + "| 0 N/A N/A 2742 G /usr/bin/Xwayland 3MiB |\n", + "| 0 N/A N/A 2781 G /usr/bin/ksmserver 2MiB |\n", + "| 0 N/A N/A 2783 G /usr/bin/kded6 2MiB |\n", + "| 0 N/A N/A 2801 G /usr/bin/plasmashell 165MiB |\n", + "| 0 N/A N/A 2816 G /usr/bin/kaccess 2MiB |\n", + "| 0 N/A N/A 2817 G ...it-kde-authentication-agent-1 2MiB |\n", + "| 0 N/A N/A 2929 G /usr/bin/kdeconnectd 2MiB |\n", + "| 0 N/A N/A 2957 G ...-gnu/libexec/DiscoverNotifier 2MiB |\n", + "| 0 N/A N/A 3064 G ...ibexec/xdg-desktop-portal-kde 2MiB |\n", + "| 0 N/A N/A 3825 G ...docker-desktop/Docker Desktop 44MiB |\n", + "| 0 N/A N/A 4019 C+G ...7014/usr/bin/telegram-desktop 65MiB |\n", + "| 0 N/A N/A 4967 G /opt/google/chrome/chrome 2MiB |\n", + "| 0 N/A N/A 5015 C+G ...rack-uuid=3190708988185955192 324MiB |\n", + "| 0 N/A N/A 5109 G /usr/bin/kwalletd6 2MiB |\n", + "| 0 N/A N/A 19293 G ...linux-gnu/libexec/baloorunner 2MiB |\n", + "| 0 N/A N/A 19415 C+G ...rack-uuid=3190708988185955192 202MiB |\n", + "| 0 N/A N/A 27150 C ...local/lib/ollama/llama-server 3294MiB |\n", "+-----------------------------------------------------------------------------------------+\n" ] } @@ -1780,7 +1847,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 70, "id": "0ef09aeb", "metadata": {}, "outputs": [ @@ -1790,7 +1857,7 @@ "True" ] }, - "execution_count": 39, + "execution_count": 70, "metadata": {}, "output_type": "execute_result" } @@ -1802,7 +1869,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 71, "id": "cfae87dd", "metadata": {}, "outputs": [ @@ -1812,7 +1879,7 @@ "'cuda'" ] }, - "execution_count": 40, + "execution_count": 71, "metadata": {}, "output_type": "execute_result" } @@ -1824,7 +1891,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 72, "id": "50a4a450", "metadata": {}, "outputs": [ @@ -1834,7 +1901,7 @@ "1" ] }, - "execution_count": 41, + "execution_count": 72, "metadata": {}, "output_type": "execute_result" } @@ -1845,7 +1912,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 73, "id": "212ef7c7", "metadata": {}, "outputs": [ @@ -1862,7 +1929,7 @@ "tensor([1, 2, 3], device='cuda:0')" ] }, - "execution_count": 43, + "execution_count": 73, "metadata": {}, "output_type": "execute_result" } @@ -1877,7 +1944,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 74, "id": "7e7b30a8", "metadata": {}, "outputs": [ @@ -1887,7 +1954,7 @@ "array([1, 2, 3])" ] }, - "execution_count": 44, + "execution_count": 74, "metadata": {}, "output_type": "execute_result" } @@ -1899,7 +1966,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 75, "id": "4a8a7c7f", "metadata": {}, "outputs": [ @@ -1909,7 +1976,7 @@ "tensor([1, 2, 3], device='cuda:0')" ] }, - "execution_count": 45, + "execution_count": 75, "metadata": {}, "output_type": "execute_result" } @@ -1929,7 +1996,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv (3.13.7)", + "display_name": ".venv (3.11.15.final.0)", "language": "python", "name": "python3" }, @@ -1943,7 +2010,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.13.7" + "version": "3.11.15" } }, "nbformat": 4, diff --git a/My_Experiments/PyTorch_Course/01_pytorch_workflow.ipynb b/My_Experiments/PyTorch_Course/01_pytorch_workflow.ipynb new file mode 100644 index 0000000..caa8963 --- /dev/null +++ b/My_Experiments/PyTorch_Course/01_pytorch_workflow.ipynb @@ -0,0 +1,954 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9c98ad95", + "metadata": {}, + "source": [ + "# Pytorch Workflow" + ] + }, + { + "cell_type": "code", + "execution_count": 266, + "id": "87dce210", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{1: 'data (prepare and load)',\n", + " 2: 'build model',\n", + " 3: 'fitting the model to data (training)',\n", + " 4: 'making predicions and evaluating a model (inference)',\n", + " 5: 'saving and loading a model',\n", + " 6: 'putting it all together'}" + ] + }, + "execution_count": 266, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "what_were_covering = {1: \"data (prepare and load)\",\n", + " 2: \"build model\",\n", + " 3: \"fitting the model to data (training)\",\n", + " 4: \"making predicions and evaluating a model (inference)\",\n", + " 5: \"saving and loading a model\",\n", + " 6: \"putting it all together\"}\n", + "what_were_covering" + ] + }, + { + "cell_type": "code", + "execution_count": 267, + "id": "e90c8379", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'2.12.1+cu130'" + ] + }, + "execution_count": 267, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import torch\n", + "from torch import nn\n", + "import matplotlib.pyplot as plt\n", + "\n", + "torch.__version__" + ] + }, + { + "cell_type": "markdown", + "id": "12ff616c", + "metadata": {}, + "source": [ + "## 1. Data (preparing and loading)" + ] + }, + { + "cell_type": "code", + "execution_count": 268, + "id": "a5b9b36a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(tensor([[0.0000],\n", + " [0.0200],\n", + " [0.0400],\n", + " [0.0600],\n", + " [0.0800],\n", + " [0.1000],\n", + " [0.1200],\n", + " [0.1400],\n", + " [0.1600],\n", + " [0.1800]]),\n", + " tensor([[0.3000],\n", + " [0.3140],\n", + " [0.3280],\n", + " [0.3420],\n", + " [0.3560],\n", + " [0.3700],\n", + " [0.3840],\n", + " [0.3980],\n", + " [0.4120],\n", + " [0.4260]]))" + ] + }, + "execution_count": 268, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create *known* parameters\n", + "weight = 0.7 \n", + "bias = 0.3\n", + "\n", + "# Create\n", + "start = 0\n", + "end = 1\n", + "step = 0.02\n", + "X = torch.arange(start, end, step).unsqueeze(dim=1)\n", + "y = weight * X + bias\n", + "\n", + "X[:10], y[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": 269, + "id": "41f90d81", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(50, 50)" + ] + }, + "execution_count": 269, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(X), len(y)" + ] + }, + { + "cell_type": "markdown", + "id": "1f10e890", + "metadata": {}, + "source": [ + "### Splitting data into training and test sets" + ] + }, + { + "cell_type": "code", + "execution_count": 270, + "id": "b2c8b4d9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(40, 40, 10, 10)" + ] + }, + "execution_count": 270, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create train/test split\n", + "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:] \n", + "\n", + "len(X_train), len(y_train), len(X_test), len(y_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 271, + "id": "8cd57e5c", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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JsHOzg45OTkoKipCTEwMvvvuO1MPTa/w8HDs2rULISEhqKysRE5ODjp06IBt27ZJySFyntDeq1cv7N69G6GhodBqtcjJyYG3tze2bNkiBaZ7GXq+unXrhsWLF8PJyQlXr15FZmYmLl261Ki+iBrDHB9PYwwKYQGT+XIeLV5aWopLly6hS5cu0k2xtiw/Px83b95Ehw4ddG78rSnv1KkTHB0d621fXl6O3377DV5eXlK9zMxMODo6ws/PT6qnVqtx/fp1+Pr6SokY+o5R89n999+Ptm3bNlsf97p+/Tq0Wi18fHxQVlaGwMBAlJWV4datWwacwersycrKSvj4+MDOzg43b95Efn4+AgICaj3hWu75qlFZWYmrV6+itLQUbdq0QefOnRvd1+/xt0D6zNk1BytTVkpJI7P6zULssFhTD0sWObGgBoMbWY233noLkydPRkBAAIDqXfxnzpyJrVu3YvLkyfjyyy9NPMKWwd8C6XNvur9WaC1qbY3BjT9om+Tr64tr167Bzc0Nbdu2lfaDdHV1xYkTJ+Dv72/iEbYM/haoIQmZCWb1eBq5DAluXHMjq7F48WJ069YNhYWFuH79Ouzs7DBgwADs37/fZgIbUQ1bSBrRh/e5kdWYNGkSJk2ahOLiYty4cQOenp6yb+AmsibWtNNIY/HKjayOo6MjunTpwsBGNsvSHk9jDAYHt3379mHo0KHo1q0bRo0ahWPHjumtX1FRgY8++giPPfYYunfvjvHjx+PcuXONHjAREekX1SVKCmyWvtNIYxkU3I4cOYLhw4fjkUcewebNmxEQEICBAwciKyur3javvPIKli1bhr/85S/YunUrOnXqhEceeUR6rhURETUva9pppLEMypYcPXo0SkpKkJiYKJX16NEDjz76KFavXl2rfnl5OZydnfHpp5/ipZdekspDQ0MxevRoLF68WNZxmS1JJB9/C7ZB36NprJXRsiX/+9//YtiwYTplw4cPR3Jycp31S0tLUVFRUevpwW5ubti3b58hhyYiov9nK7uMNIXs4FZUVAS1Wo0OHTrolHfo0AHXrl2rs42rqyseeughrFixAgUFBQCAXbt24fDhw7h69Wq9xyorK4NGo9F5ERFRNSaMNEx2cKt5RMfvN591cHDQeVrw733zzTdo3bo17rvvPnh6euKNN97As88+q/cRHkuWLIFKpZJecrYc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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Visualize\n", + "def plot_predictions(train_data=X_train,\n", + " train_labels=y_train,\n", + " test_data=X_test,\n", + " test_labels=y_test,\n", + " predictions=None):\n", + "\n", + " plt.figure(figsize=(5, 3.5))\n", + "\n", + " plt.scatter(train_data, train_labels, c=\"b\", s=4, label=\"Training data\")\n", + "\n", + " plt.scatter(test_data, test_labels, c=\"g\", s=4, label=\"Testing data\")\n", + "\n", + " if predictions is not None:\n", + " plt.scatter(test_data, predictions, c=\"r\", s=4, label=\"Predictions\")\n", + "\n", + " plt.legend(prop={\"size\": 14})\n", + "plot_predictions()\n" + ] + }, + { + "cell_type": "markdown", + "id": "bbcb4887", + "metadata": {}, + "source": [ + "## 2. Build model" + ] + }, + { + "cell_type": "code", + "execution_count": 272, + "id": "aa9f92c3", + "metadata": {}, + "outputs": [], + "source": [ + "from torch import nn\n", + "# Create a linear regression model class\n", + "class LinearRegressionModel(nn.Module): # <- almost everything in PyTorch inherits from nn.Module\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.weights = nn.Parameter(torch.randn(1,\n", + " requires_grad=True, \n", + " dtype=torch.float))\n", + " self.bias = nn.Parameter(torch.randn(1,\n", + " requires_grad=True,\n", + " dtype=torch.float))\n", + " # Forward method to define the computation in the model\n", + " def forward(self, x: torch.Tensor) -> torch.Tensor:\n", + " return self.weights * x + self.bias # linear regression formula" + ] + }, + { + "cell_type": "markdown", + "id": "9bfd38aa", + "metadata": {}, + "source": [ + "### PyTorch model building essentials" + ] + }, + { + "cell_type": "markdown", + "id": "44777cd3", + "metadata": {}, + "source": [ + "### Checking the contence of our PyTorch model" + ] + }, + { + "cell_type": "code", + "execution_count": 273, + "id": "c97c753c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Parameter containing:\n", + " tensor([0.3367], requires_grad=True),\n", + " Parameter containing:\n", + " tensor([0.1288], requires_grad=True)]" + ] + }, + "execution_count": 273, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create a random seed\n", + "torch.manual_seed(42)\n", + "\n", + "#Create an instance on the model we created\n", + "model_0 = LinearRegressionModel()\n", + "\n", + "# Check out the parameters\n", + "list(model_0.parameters())" + ] + }, + { + "cell_type": "code", + "execution_count": 274, + "id": "f38d41c0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "OrderedDict([('weights', tensor([0.3367])), ('bias', tensor([0.1288]))])" + ] + }, + "execution_count": 274, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# List name parameters\n", + "model_0.state_dict()" + ] + }, + { + "cell_type": "markdown", + "id": "c5f259ae", + "metadata": {}, + "source": [ + "### Making prediction using `torch.inference_mode()`" + ] + }, + { + "cell_type": "code", + "execution_count": 275, + "id": "5263fef5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(tensor([[0.8000],\n", + " [0.8200],\n", + " [0.8400],\n", + " [0.8600],\n", + " [0.8800],\n", + " [0.9000],\n", + " [0.9200],\n", + " [0.9400],\n", + " [0.9600],\n", + " [0.9800]]),\n", + " tensor([[0.8600],\n", + " [0.8740],\n", + " [0.8880],\n", + " [0.9020],\n", + " [0.9160],\n", + " [0.9300],\n", + " [0.9440],\n", + " [0.9580],\n", + " [0.9720],\n", + " [0.9860]]))" + ] + }, + "execution_count": 275, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X_test, y_test" + ] + }, + { + "cell_type": "code", + "execution_count": 276, + "id": "01a46c08", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[0.3982],\n", + " [0.4049],\n", + " [0.4116],\n", + " [0.4184],\n", + " [0.4251],\n", + " [0.4318],\n", + " [0.4386],\n", + " [0.4453],\n", + " [0.4520],\n", + " [0.4588]])" + ] + }, + "execution_count": 276, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Make predictions with model\n", + "with torch.inference_mode():\n", + " y_preds = model_0(X_test)\n", + "y_preds" + ] + }, + { + "cell_type": "code", + "execution_count": 277, + "id": "e27f6f66", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_predictions(predictions=y_preds)" + ] + }, + { + "cell_type": "markdown", + "id": "f4a7052e", + "metadata": {}, + "source": [ + "## 3. Train model" + ] + }, + { + "cell_type": "code", + "execution_count": 278, + "id": "cfe9b6be", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(L1Loss(),\n", + " SGD (\n", + " Parameter Group 0\n", + " dampening: 0\n", + " differentiable: False\n", + " foreach: None\n", + " fused: None\n", + " lr: 0.01\n", + " maximize: False\n", + " momentum: 0\n", + " nesterov: False\n", + " weight_decay: 0\n", + " ))" + ] + }, + "execution_count": 278, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Setup a loss functions\n", + "\n", + "loss_fn = nn.L1Loss()\n", + "\n", + "# Setup an optimizer (stochastic gradient descent)\n", + "\n", + "optimizer = torch.optim.SGD(model_0.parameters(), lr=0.01) # lr = learning rate\n", + "\n", + "loss_fn, optimizer" + ] + }, + { + "cell_type": "markdown", + "id": "ee9243ec", + "metadata": {}, + "source": [ + "### Building a training loop (and a testing loop) in PyTorch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7942336a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 279, + "id": "c678f976", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch: 0 | loss: 0.31288138031959534 | Test loss: 0.48106518387794495\n", + "OrderedDict([('weights', tensor([0.3406])), ('bias', tensor([0.1388]))])\n", + "Epoch: 10 | loss: 0.1976713240146637 | Test loss: 0.3463551998138428\n", + "OrderedDict([('weights', tensor([0.3796])), ('bias', tensor([0.2388]))])\n", + "Epoch: 20 | loss: 0.08908725529909134 | Test loss: 0.21729660034179688\n", + "OrderedDict([('weights', tensor([0.4184])), ('bias', tensor([0.3333]))])\n", + "Epoch: 30 | loss: 0.053148526698350906 | Test loss: 0.14464017748832703\n", + "OrderedDict([('weights', tensor([0.4512])), ('bias', tensor([0.3768]))])\n", + "Epoch: 40 | loss: 0.04543796554207802 | Test loss: 0.11360953003168106\n", + "OrderedDict([('weights', tensor([0.4748])), ('bias', tensor([0.3868]))])\n", + "Epoch: 50 | loss: 0.04167863354086876 | Test loss: 0.09919948130846024\n", + "OrderedDict([('weights', tensor([0.4938])), ('bias', tensor([0.3843]))])\n", + "Epoch: 60 | loss: 0.03818932920694351 | Test loss: 0.08886633068323135\n", + "OrderedDict([('weights', tensor([0.5116])), ('bias', tensor([0.3788]))])\n", + "Epoch: 70 | loss: 0.03476089984178543 | Test loss: 0.0805937647819519\n", + "OrderedDict([('weights', tensor([0.5288])), ('bias', tensor([0.3718]))])\n", + "Epoch: 80 | loss: 0.03132382780313492 | Test loss: 0.07232122868299484\n", + "OrderedDict([('weights', tensor([0.5459])), ('bias', tensor([0.3648]))])\n", + "Epoch: 90 | loss: 0.02788739837706089 | Test loss: 0.06473556160926819\n", + "OrderedDict([('weights', tensor([0.5629])), ('bias', tensor([0.3573]))])\n", + "Epoch: 100 | loss: 0.024458957836031914 | Test loss: 0.05646304413676262\n", + "OrderedDict([('weights', tensor([0.5800])), ('bias', tensor([0.3503]))])\n", + "Epoch: 110 | loss: 0.021020207554101944 | Test loss: 0.04819049686193466\n", + "OrderedDict([('weights', tensor([0.5972])), ('bias', tensor([0.3433]))])\n", + "Epoch: 120 | loss: 0.01758546568453312 | Test loss: 0.04060482233762741\n", + "OrderedDict([('weights', tensor([0.6141])), ('bias', tensor([0.3358]))])\n", + "Epoch: 130 | loss: 0.014155393466353416 | Test loss: 0.03233227878808975\n", + "OrderedDict([('weights', tensor([0.6313])), ('bias', tensor([0.3288]))])\n", + "Epoch: 140 | loss: 0.010716589167714119 | Test loss: 0.024059748277068138\n", + "OrderedDict([('weights', tensor([0.6485])), ('bias', tensor([0.3218]))])\n", + "Epoch: 150 | loss: 0.0072835334576666355 | Test loss: 0.016474086791276932\n", + "OrderedDict([('weights', tensor([0.6654])), ('bias', tensor([0.3143]))])\n", + "Epoch: 160 | loss: 0.0038517764769494534 | Test loss: 0.008201557211577892\n", + "OrderedDict([('weights', tensor([0.6826])), ('bias', tensor([0.3073]))])\n", + "Epoch: 170 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 180 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 190 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 200 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 210 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 220 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 230 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 240 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 250 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 260 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 270 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 280 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 290 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 300 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 310 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 320 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 330 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 340 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 350 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 360 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 370 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 380 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 390 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 400 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 410 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 420 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 430 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 440 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 450 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 460 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 470 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 480 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n", + "Epoch: 490 | loss: 0.008932482451200485 | Test loss: 0.005023092031478882\n", + "OrderedDict([('weights', tensor([0.6951])), ('bias', tensor([0.2993]))])\n" + ] + } + ], + "source": [ + "# An epoch is one loop through the data...\n", + "epochs = 500\n", + "# Traking values\n", + "epoch_count = []\n", + "loss_values = []\n", + "test_loss_values = []\n", + "### Training\n", + "# 0. Loop through the data\n", + "for epoch in range(epochs):\n", + " # Set the model to training mode\n", + " model_0.train() # turn on gradient tracking\n", + " \n", + " # 1. Forward pass\n", + " y_pred = model_0(X_train)\n", + "\n", + " # 2. Calculate the loss\n", + " loss = loss_fn(y_pred, y_train)\n", + "\n", + " # 3. Optimizer zero grad\n", + " optimizer.zero_grad()\n", + "\n", + " # 4. Perform backpropagation on the loss with respect to the parameters of the model\n", + " loss.backward()\n", + " \n", + " # 5. Step the optimizer (perform gradient descent)\n", + " optimizer.step()\n", + " \n", + "\n", + " model_0.eval() # turn off gradient tracking \n", + " with torch.inference_mode():\n", + " # 1. Do the forward pass\n", + " test_pred = model_0(X_test)\n", + " # 2. Calculate the loss\n", + " test_loss = loss_fn(test_pred, y_test)\n", + " if epoch % 10 == 0:\n", + " epoch_count.append(epoch)\n", + " loss_values.append(loss.item())\n", + " test_loss_values.append(test_loss.item())\n", + " print(f\"Epoch: {epoch} | loss: {loss} | Test loss: {test_loss}\")\n", + " print(model_0.state_dict())\n" + ] + }, + { + "cell_type": "code", + "execution_count": 280, + "id": "90cf11b7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "([0,\n", + " 10,\n", + " 20,\n", + " 30,\n", + " 40,\n", + " 50,\n", + " 60,\n", + " 70,\n", + " 80,\n", + " 90,\n", + " 100,\n", + " 110,\n", + " 120,\n", + " 130,\n", + " 140,\n", + " 150,\n", + " 160,\n", + " 170,\n", + " 180,\n", + " 190,\n", + " 200,\n", + " 210,\n", + " 220,\n", + " 230,\n", + " 240,\n", + " 250,\n", + " 260,\n", + " 270,\n", + " 280,\n", + " 290,\n", + " 300,\n", + " 310,\n", + " 320,\n", + " 330,\n", + " 340,\n", + " 350,\n", + " 360,\n", + " 370,\n", + " 380,\n", + " 390,\n", + " 400,\n", + " 410,\n", + " 420,\n", + " 430,\n", + " 440,\n", + " 450,\n", + " 460,\n", + " 470,\n", + " 480,\n", + " 490],\n", + " [0.31288138031959534,\n", + " 0.1976713240146637,\n", + " 0.08908725529909134,\n", + " 0.053148526698350906,\n", + " 0.04543796554207802,\n", + " 0.04167863354086876,\n", + " 0.03818932920694351,\n", + " 0.03476089984178543,\n", + " 0.03132382780313492,\n", + " 0.02788739837706089,\n", + " 0.024458957836031914,\n", + " 0.021020207554101944,\n", + " 0.01758546568453312,\n", + " 0.014155393466353416,\n", + " 0.010716589167714119,\n", + " 0.0072835334576666355,\n", + " 0.0038517764769494534,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485,\n", + " 0.008932482451200485],\n", + " [0.48106518387794495,\n", + " 0.3463551998138428,\n", + " 0.21729660034179688,\n", + " 0.14464017748832703,\n", + " 0.11360953003168106,\n", + " 0.09919948130846024,\n", + " 0.08886633068323135,\n", + " 0.0805937647819519,\n", + " 0.07232122868299484,\n", + " 0.06473556160926819,\n", + " 0.05646304413676262,\n", + " 0.04819049686193466,\n", + " 0.04060482233762741,\n", + " 0.03233227878808975,\n", + " 0.024059748277068138,\n", + " 0.016474086791276932,\n", + " 0.008201557211577892,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882,\n", + " 0.005023092031478882])" + ] + }, + "execution_count": 280, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "epoch_count, loss_values, test_loss_values" + ] + }, + { + "cell_type": "code", + "execution_count": 281, + "id": "2d17ee65", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 281, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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io8++siZj0qXLl1YsGCBw+csHlN0Plf/jkRKo54bkTK4++67+fDDD+nduze33347qampLFu2jMcff5wHHnjA2+XZtWvXjpdffpnHH3+cnTt30rFjR9auXUvfvn0JDg6+ZM+EOz5n27ZteeWVV3jsscfYvXs3nTp1YvXq1fTv3/+Ct7XKwt/fn3nz5nHjjTfSokULhg4dSt26dUlMTGTZsmXcdNNNdOzYkfXr1zNgwAB69epF8+bNyc7O5r///S8tW7bkrrvusl/vpptu4oUXXmDChAnExMSUeZ2b0NBQpk6dyp/+9Ce6du3KoEGDOHz4MF988QUjRoywf4fO1ONszRfTp08fGjduzKuvvkpQUBAjRoxweH3AgAH06NGDMWPG8Je//AWTycQPP/zAo48+WmLV7gt5/vnnueqqq+jZsycDBw5k69atxMbGlhiH5erfkUhpFG6kxrvtttscngcFBfHggw+WGAwKULt2bbZs2cLXX39NYmIiLVu25PnnnycpKYkHH3yQBg0aABfePqG06952221ERUXZn1f0fIBHH32Ua665hrlz55Kfn89TTz1Fly5deOSRRy4ZJpz9nGWtacKECVxzzTXMmTOH/Px8nn76aXr06MGJEydo27ZtqTWdLzY2lgcffNDhH9DLLruM7du3M3/+fDZu3EhmZiZXXnklTz31lH0Q82233cYNN9zA3Llz2blzJwEBAbz++usMGDDAYTzQU089RatWrdiwYQMHDhy45LYOY8eOLTF4+/rrr2fv3r1899137Nu3j0aNGvHjjz/aeyGcrcfZmi/GZDLxr3/9ixUrVtCmTZsSv3uLxcLSpUv59ttv2bp1KxEREcydO5fg4GAefPBBh4G8F/qcV1xxBZs3b2batGlkZWVxxx13cP311/P222+XqMWVvyOR0mjjTJEaZMeOHbRq1YoPPviAu+++29vliIi4hcbciFRTf9xFu6ioiIkTJ+Lv78+QIUO8VJWIiPvptpRINTV37ly+/PJLrr32WqxWK4sWLWL9+vV8/PHHDgsSiohUN7otJVKN/frrryxbtoyjR49Sv359hgwZUmJqsohIdaNwIyIiItWKxtyIiIhIteL1MTfHjx9n9erV+Pv707NnT4KCgi7atqCggKlTp5Y43q1bN2JjY91ZpoiIiFQRXg03U6dO5c477+SKK64gLS2N48ePM3/+fDp06HDB9jk5OYwZM4a+ffsSGRlpP964cWOnw01RURFHjx4lJCQEk8nkio8hIiIibmYYBpmZmdSvX//SW6QYXnLixAkjKCjIeP311w3DMIyioiJj2LBhRrt27S56TmZmpgEYP//8c7nf99ChQwaghx566KGHHnpUwcehQ4cu+W+913puZs6cSWFhoX0hMZPJxEMPPcRVV13F1q1bSyzdfb5169Zx5MgR4uLiaN++fZl6YEJCQgA4dOgQoaGhFfsQIiIi4hEZGRk0bNjQ/u94abwWbrZs2UJsbCyBgYH2Y8XLr2/ZsuWi4cZkMvH5558THR3NmjVraNasGdOmTSMmJuaC7XNzcx12HM7MzARse78o3IiIiFQtznRoeG22VHp6OrVq1XI4FhYWhsViIT09/YLn+Pr6smzZMtavX8+cOXPYvXs32dnZpW6mNmnSJMLCwuyPP+6LIiIiItWL18JNQEAAp0+fdjiWnZ1NYWEhAQEBFzzHarXSs2dP+/Pw8HAefvhhFi9e7NA7c74nn3yS9PR0++PQoUOu+xAiIiJS6Xgt3MTGxnLo0CGH3XYTExPtrzkrKCiIgoIC0tLSLvi61Wq134LSrSgREZHqz2tjbgYOHMjjjz/Ojz/+SJ8+fQDb1PCIiAi6dOkCQH5+Pv/973/t69gcPXqU6Ohoh/tt06dPp3HjxtStW9crn0NERLyjqKiIvLw8b5chLuLr64vFYnHJtbwWbi677DLuvfdeRo8ezSOPPMKpU6d44403+Pjjj/Hz8wMgKyuLMWPG8NlnnxEbG8uiRYuYPHkyAwcOJDw8nB9++IFly5bx7bffeutjiIiIF+Tl5bF//36H3n+p+sLDw6lXr16F16Hz6iJ+7777Lj179mTJkiVYrVaWLFlCjx497K/7+fkxatQo4uLiALjtttvo0KED3333HVu2bOHqq6/mo48+Ijo62lsfQUREPMwwDJKSkrBYLDRs2PDSC7pJpWcYBmfOnOHEiRMAFf53vcZtnJmRkUFYWBjp6ekafyMiUgXl5+ezZ88e6tevT1hYmLfLERdKSUnhxIkTNG/evMQtqrL8+624KyIiVUphYSGAfQiDVB/Fa9/l5+dX6DoKNyIiUiVpf8Dqx1W/U4UbERGRKuyVV15h9uzZ3i6jUvHqgGIREZHq7vTp0zz00EOltunTpw8jRowo1/XnzJlDdnY2N9xwQ7nOB3jnnXfw9fXlnnvuKfc1KhOFGxERETfy9fUlISHB/nzhwoXMnTuXt99+236scePG5b7+E088Qf369StU4//+9z/8/f0VbuQP0o/A4V/AGgLNrvN2NSIiUklYrVbuvPNO+/O0tDQWLlzocOyFF14gIyODnJwclixZQsuWLbnnnnv44IMPWL9+PSaTiTp16tCzZ0/69evncP1t27ZRVFREx44d7ddKSEigsLCQ5cuX4+Pjw8iRI2ndunW5P4NhGMyaNYulS5fi4+ND3759uf766x3a7N69m2+++YZTp07Rrl07Ro8ebR/0Xdpr7qAxN66SuBKm3Q6r3vJ2JSIiUsXMmDGDsWPH8vbbbxMbG0t8fDwA8fHxJCQk0KVLF/z8/Bg7dizPPPOMw7lz5sxh48aNDte64447ePvtt6lbty779u3jiiuuYN++feWub/z48dx1111ERETg7+/P0KFD+fvf/25/fevWrXTo0IGkpCTi4uJYu3YtgwYNuuRr7qKeG1cJObv9Q+Zx79YhIlLDGIZBdn6hV947wNfishk+0dHRLFq0yOF61157rUObfv360bNnT5544gmCg4Mveq24uDjmz59vf96uXTumTJnCs88+W+a6Nm3axOTJk1m9erX99trll1/OqFGjGDt2LI0aNWLevHl07NiR999/337e4cOHAUp9zV0UblwluJ7tz9PHvFuHiEgNk51fSOu//c8r7739hb4E+rnmn9J+/fqVCEoFBQXMmDGDjRs3kpKSQn5+Pvn5+ezdu5f27dtf9FrXXec4PKJFixblDhQ//fQTjRs3dhg3NGzYMMaMGcPPP/9Mo0aNaN26NS+++CIff/wxQ4YMoU6dOsTExACU+pq76LaUqxT33OSkQ362d2sREZEqJzw83OG5YRgMHDiQ5557joCAADp16kTnzp0ByMzMLPVaAQEBDs8tFot98cOyOnHiBJGRkQ7HTCYTERERHD9uu1sxePBgJk+ezNSpU2nSpAmXX365fd/H0l5zF/XcuIp/OFisUJgLp49DrSberkhEpEYI8LWw/YW+Xntvd9m7dy8LFy4kMTHRPptqx44dbnu/i2nYsCEHDx7EMAx7z1JOTg7Hjx+nUaNG9na33HILt9xyC7m5uXz88ceMHDmSTp06ERcXV+pr7qCeG1cxmc713pw+4d1aRERqEJPJRKCfj1ce7lwluXjrx+JeGsMweOWVV9z2fhczcOBAMjIymDJliv3YW2+9RWhoKL169QJg6dKlnDx5ErDNDhs0aBBFRUWkpaWV+pq7qOfGlYLrQtpByNS4GxERqZj4+Hj+9Kc/cc0113Ddddexfft2rFar295vw4YNDtPTAbp27cq4ceN4/fXXueuuu/jmm2/Izc1l9erVfPHFF/ZbaZmZmSQkJBAXF0edOnVYunQpw4cP5/LLL2fu3LkXfc1dtCu4K00dBTvmwoB/Que7XHttEREBbLdE9u/fT9OmTfH39/d2OWW2ZcsWfv31V8aMGWM/9v3339OsWTPatm1bov3y5cvtt6a6devG559/zuDBg6lb13a3YO7cudSvX9++zs2FrrV06VJ8fX3p0aPHBWtauHAhBw8eLHG8WbNm9t6ZQ4cOsXLlSiwWC1dffbX9/YtlZWWxevVqUlJSaN26Ne3atXPqtfOV9rsty7/fCjeuNO//YN3HcNUEuLbs0+1EROTSqnq4kYtzVbjRmBtX0nRwERERr1O4cSUt5CciIuJ1CjeuZO+5UbgRERHxFoUbV7JPBVe4ERER8RaFG1cKPhtusk5CkXf2OREREanpFG5cKagOmMxgFNkCjoiIiHicwo0rmS22gANayE9ERMRLFG5cLVjjbkRERLxJ4cbVQjRjSkRExJu0t5SrBWutGxEROScvL4/Zs2eX2iY+Pp727duX6/q5ubnMmTOH66+//qIr9xqGwXfffUfnzp0ddvKurhRuXM1+W0pjbkRExBY+pk6dan++a9cuduzYwQ033GA/NmjQoHKHm9TUVG6++Wa2bNlCmzZtLtimsLCQm2++mS+//JLRo0eX632qEoUbVyu+LaUBxSIiAoSEhDB9+nT783/+859MnDjR4RjA6dOnWbt2LQDt2rWjTp06Dq8XFBSwbt06MjIyaNeuHdHR0RiGwdy5cwFYtGgRO3bsIDIy0r7ZZVnt2rWLnTt3EhUVxZVXXonZ7Dh6JT09nY0bN2IymejUqRMhISFOveZpCjeupgHFIiJSRjNnzmTcuHG0bNmSwMBA1q1bx8svv8w999wDwNGjR+nVqxcWi4XY2Fi2bdvGXXfdxZNPPsmsWbMAmD9/PqGhobRq1arM4cYwDMaOHcuMGTPo0qULO3bsICIigvnz5xMdHQ3A4sWLufnmm2nVqhVBQUHs3buX9957j/79+5f6mjco3LiavedG4UZExCMMA/LPeOe9fQPBZKrQJRITExk9ejSzZs3i2muvBeCXX37h6quv5pprrqF58+Z8/PHHREZGsmrVKkwmE0VFRcycOROz2cxHH31EdHQ0r7/++kVvS13KV199xfTp09m4cSPNmzcnKyuLXr168eijj/LVV18B8NJLL3HPPfcwadIkANLS0li3bt0lX/MGhRtXO7/nxjAq/JdeREQuIf8MvFTfO+/91FHwC6rQJb755hsiIiLIzMzk+++/xzAMAGrXrs1PP/1E8+bNsVqtpKamcvz4cerVq4fZbGbo0KGu+AT2GoYPH07z5s0BCAoK4v/+7/+49dZb+fzzz7FYLFitVhITE8nOziYgIIDw8HD69OkDUOpr3qCp4K5WHG4KcyEnzauliIhI5bd//35yc3P56quvmDJlCl9//TVff/01Xbt2pXbt2gCMHz+etm3b0rRpUxISEnj22Wc5dsx1YzsTExOJjY11ONasWTPy8/M5evQoYBsrtG/fPqKioujXrx/vvvsuubm5l3zNG9Rz42q+/uAfBjnptltTAbW8XZGISPXmG2jrQfHWe1dQSEgItWvXLjHA+HyhoaF8++23ZGZmsmLFCt599106derE7t27K/z+ABEREaSlpTkcO3XqFIA9YF122WWsXbuWo0ePsmTJEv7xj3+wePFiZs6cWepr3qCeG3cILl7ITzOmRETczmSy3RryxsMFQw/69u3L77//zooVKxyOZ2VlkZmZCUBSUhJgC0IDBgzgvffe4+jRoyQmJhIcHAxQoZ6SHj16MGfOHAoLz236PGPGDDp06EBQUJBDDfXr12f06NE89thjrF69+pKveYN6btwhpC4k79SgYhERuaTrr7+eO+64g4EDB/LQQw8RFxfHzp07mT59OgsWLCAkJIR33nmHDRs2MGDAAMLDw/nqq69o06YNzZs3x8fHh+bNm/Pqq68ybNgwoqKiLjpbat26dfj7+zsc69q1K4899hhfffUV/fr1Y+TIkWzYsIHPPvuMBQsW2Nv9+c9/JjY2lu7du5Ofn88bb7zBsGHDLvmaNyjcuIN6bkRE5CJatGjBkCFDHI598sknDB06lHnz5nHgwAFat27NihUrqFvXNo7zpZdeYtGiRcybN4/09HQGDBjA2LFj8fGx/TM+Z84cPvzwQ2bMmEF8fHyJcGM2mxk2bBhHjhxxWFAQICYmhoSEBDZu3Mj777/P4sWLiYqKYu3atXTo0MHe7scff2TKlCmsXLkSi8XC888/z/Dhwy/5mjeYjOJh2TVERkYGYWFhpKenX3SZ6gpb+Aysfge63g99/+Ge9xARqaFycnLYv38/TZs2LdELIVVbab/bsvz7rTE37hCsVYpFRES8ReHGHbQzuIiIiNco3LhDcJTtT/XciIiIeJzCjTsEq+dGRETEWxRu3CHk7CrFuRmQ56X9TkRERGoohRt3sIaCT4DtZ/XeiIi4RQ2b7FsjuOp3qnDjDibTud4bhRsREZeyWCwA5OXlebkScbUzZ2x3O3x9fSt0HS3i5y7B9SA1UYOKRURczMfHh8DAQE6ePImvry9ms/47vaozDIMzZ85w4sQJwsPD7QG2vBRu3KV4xpR6bkREXMpkMhEdHc3+/fs5cOCAt8sRFwoPD6devXoVvo7CjbuEaCE/ERF38fPzIz4+XremqhFfX98K99gUU7hxl2CNuRERcSez2aztF+SCdKPSXbRKsYiIiFco3LiLfX8phRsRERFPUrhxF/tUcI25ERER8SSFG3cpHnOTlQyFBd6tRUREpAZRuHGXwEgwWQADsk54uxoREZEaQ+HGXcxm7Q4uIiLiBQo37mSfDq6eGxEREU9RuHEn+3Rw9dyIiIh4isKNOxX33Gg6uIiIiMco3LiTem5EREQ8TuHGnewDitVzIyIi4ikKN+4UrJ4bERERT/NquDl27Bi33HILdevWpXHjxjz22GNO7/B66tQp4uPjCQ4O5ujRo26utJzst6U0W0pERMRTvLYreFFREQMHDiQsLIyffvqJ1NRUhg8fTmZmJu+///4lzx83bhxNmzZlz549FBUVeaDicjh/Z3DDAJPJu/WIiIjUAF7ruVm4cCEbN27ko48+omXLlnTt2pV//OMffPzxx6SkpJR67jvvvENqaioTJkzwULXlVBxuCvMgO9W7tYiIiNQQXgs3K1eupHHjxsTFxdmP9enTh4KCAtasWXPR83777TdeeuklvvjiC8zmSj5kyMcPAmrbftYqxSIiIh7htXRw9OhRoqKiHI7VqVMHk8lEUlLSBc/JyspixIgRvPnmmzRq1Mip98nNzSUjI8Ph4VHB2h1cRETEk7za9fHHnhfT2TEphmFcsP0DDzxA586dGTFihNPvMWnSJMLCwuyPhg0blr/g8gjRQn4iIiKe5LVwExUVxcmTJx2OpaSkYBhGiR6dYj/++CPTpk0jODiY4OBgBg8eDECLFi14/PHHL3jOk08+SXp6uv1x6NAh136QS7FPB1e4ERER8QSvzZbq2rUrr776KocPHyYmJgaApUuXYjab6dy58wXP2b59u8PMqGXLljF48GA2bdpEkyZNLniO1WrFarW6vH6nhZw3Y0pERETczms9N/379yc+Pp4HHniA1NRU9u/fz/PPP8/w4cOJjo4GID09neDgYKZMmQJAYGCgvdcmODgYf39/+3E/Pz9vfZTSFffcaECxiIiIR3gt3Pj5+TFv3jxSU1OJioqiVatWXHHFFUyePNnexjAMsrKyyM/P91aZFaeeGxEREY/y2m0pgGbNmrF06VIKCgqwWCz2AcXFwsPDyczMtPfQ/FHv3r3JzMwkKCjIE+WWj31ncPXciIiIeIJXw00xH5+LlxEcHHzR1ywWS6mvVwoaUCwiIuJRlXwVvGqg+LZU3mnIPe3dWkRERGoAhRt3s4aA79nbZuq9ERERcTuFG0/QoGIRERGPUbjxBE0HFxER8RiFG09Qz42IiIjHKNx4gqaDi4iIeIzCjSfYdwY/4d06REREagCFG08IKV7rRj03IiIi7qZw4wn221IacyMiIuJuCjeeoJ4bERERj1G48YTiqeBnUqAgz7u1iIiIVHMKN54QUAvMZ/fPytKgYhEREXdSuPEEs/m8GVMadyMiIuJOCjeeokHFIiIiHqFw4ykaVCwiIuIRCjeeop4bERERj1C48RT13IiIiHiEwo2nBEfZ/lTPjYiIiFsp3HhK8Vo3mi0lIiLiVgo3nhKiqeAiIiKeoHDjKef33BQVebcWERGRakzhxlOCowATFBVA9ilvVyMiIlJtKdx4isUXAiNsP2dqxpSIiIi7KNx4kn0LBoUbERERd1G48ST7oGJtnikiIuIuCjeeVDyoWLelRERE3EbhxpM0HVxERMTtFG48ST03IiIibqdw40nquREREXE7hRtPUs+NiIiI2ynceNL5PTeG4d1aREREqimFG08q7rnJPwO5md6tRUREpJpSuPEkv0Cwhtl+1q0pERERt1C48bSQ4nE3Sd6tQ0REpJpSuPG0EA0qFhERcSeFG08Libb9qZ4bERERt1C48TT13IiIiLiVwo2nqedGRETErRRuPK2450arFIuIiLiFwo2nqedGRETErRRuPO38MTdapVhERMTlFG48rTjcFORATppXSxEREamOFG48zccKAbVtP2vGlIiIiMsp3HiDxt2IiIi4jcKNN2itGxEREbdRuPEG9dyIiIi4jcKNN4TUtf2pnhsRERGXU7jxBvXciIiIuI3CjTdozI2IiIjbKNx4g73nRuFGRETE1RRuvOH8npuiIu/WIiIiUs0o3HhD8NkBxUX5kH3Ku7WIiIhUMwo3LlZU5MR+URZfCKpj+1m3pkRERFxK4cZF5m1OotOLi7j7qw3OnaBBxSIiIm6hcOMi/r5mUrLyOJqW7dwJmg4uIiLiFgo3LhIdFgBAUnqOcyeo50ZERMQtFG5cpH64PwCnsvLIyS+89AnquREREXELhRsXCQvwJcDXAjjZe6OeGxEREbfw8XYBy5cv58cff8Tf35+bbrqJli1blto+Pz+f2bNns2XLFsLDw+nfvz8tWrTwULUXZzKZiA73Z9/JLJLSsmkaGVT6Ceq5ERERcQuv9tw8//zzDBo0iPT0dHbs2EH79u2ZM2fORdsfPnyYDh06MH36dCwWC5s2baJdu3a8//77Hqz64uqfHXdz1Jmem2BtnikiIuIOXuu52bt3LxMnTuS///0vw4YNA6B27dqMHz+eAQMGYLFYSpwTEBDA4sWLiY6Oth9r0KABEydOZPz48R6r/WKiw2zjbpKcmTFV3HNz+jgUFYK55OcVERGRsvNaz82cOXMIDg5myJAh9mO33347R44cYf369Rc8JyIiwiHYAOTk5BAeHu7OUp0WHV6GnpugOmAyg1EIWclurkxERKTm8FrPzc6dO2nUqBE+PudKiIuLA2DXrl106dLloudOnjyZHTt2sGvXLpKTk5kyZcpF2+bm5pKbm2t/npGR4YLqL6x+cc9NuhM9NxYfCIqC08ds425C6rqtLhERkZrEaz03Z86cITQ01OFYcHAwFouFrKysUs+tVasWderUISwsjP3797Njx46Ltp00aRJhYWH2R8OGDV1S/4UU99wkpWmtGxEREW/xWs9NcHAwaWlpDscyMzMpLCwkJCSk1HNvvvlm+89vvfUWd9xxB/369bvg7aknn3ySRx55xP48IyPDbQGnuOfmqDM9N2Abd5P0q2ZMiYiIuJDXem5at27NgQMHHG4ZFffAtGrVyunrdOvWjezsbBITEy/4utVqJTQ01OHhLsU9N5k5BZzOLbj0Ceq5ERERcTmvhZshQ4aQl5fnMF7mgw8+oFmzZlx++eWAbbDwhAkT7AOMN27cyOnTpx2u8/333xMcHEyzZs08V/xFBFt9CPG3dYaVbcaUwo2IiIireO22VExMDP/617+4//77WbRoEadOneLnn39m7ty5mEwmwBZu/vWvf9GmTRuuuOIKkpKSGD16NG3atCEyMpJff/2VnTt38tlnnxEcHOytj+KgflgAO3MyOZqeQ3zd0m+vqedGRETE9by6QvH999/Ptddey7Jly7BarXz++efUq1fP/npAQACvvfYaV155JQADBw6kR48eLFmyhGPHjtG/f3969+5daYIN2PaY2nk8s2w9NxpzIyIi4jJe336hVatWFx1jY7VamTBhgsOxsLAwbrrpJk+UVi5lWutGPTciIiIup40zXax+uVYpPgGFTgxAFhERkUtSuHGx6LP7Szm1M3hgBJh9AAOyTri3MBERkRpC4cbFosPLsNaN2QzBxbemNO5GRETEFRRuXMy+M3haNoZhXPqEEO0OLiIi4koKNy5W7+yYm5z8ItLO5F/6BM2YEhERcSmFGxfz97UQEeQHOHlrSjOmREREXErhxg2Kx904tYFmiMbciIiIuJLCjRucmzFVloX81HMjIiLiCgo3bnBud3At5CciIuJpCjduULxKsbZgEBER8TyFGzeILlPPzdlwcyYFCvLcWJWIiEjNoHDjBvXDyzDmJqAWWGyzqzh93I1ViYiI1AwKN25Q3HNzLD2HoqJLLORnMmncjYiIiAsp3LhB3VB/TCbILzRIzsq99AkadyMiIuIyCjdu4GsxExViBcq61o16bkRERCpK4cZNyrfWjXpuREREKkrhxk3qF+8Orp4bERERj1K4cZMy9dwEawsGERERV3FJuElKSmLNmjXk5WmdlmJlW+tGPTciIiKuUq5wM2rUKNasWQPAL7/8QlxcHF27dqVnz57k5+e7tMCqqr5WKRYREfGKMoebVatWceTIERISEgB4/fXX+ctf/sKJEyfIy8tj5syZrq6xSiruuUkqS89NThrkOxGGRERE5KJ8ynrC5s2badOmDQCGYfDjjz+yevVq6tSpw4033sj27dtdXmRVVNxzczwjh4LCInwspeRI/zDwCYCCbNutqdpNPVSliIhI9VPmnpvatWuzbds2wNaL4+/v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BQUZd9999wXbffDBB0ZgYKD9+x40aJCRlZVV5jY13ZIlS4wrr7zSqFevntG+fXsjICDAePDBB42ioiKHdh999JERGBhotGjRwggKCjL69+9vnD59usxtarpDhw4Zw4cPNyIjI42OHTsaISEhxlVXXWUcOXLEod0XX3xhBAcHG82bNzeCg4ON6667zkhPTy9zGzln1qxZhtlsNqxWa4nXpkyZYoSEhBjNmzc3QkJCjN69extpaWllblPT/f777wZgXHnllUb37t3tj3Xr1jm0mzZtmhEWFmbEx8cboaGhRo8ePYyUlJQyt7kUhZsKWrdunWEymYwZM2YYhmEYSUlJRkxMjPHoo496ubKqZ+vWrcakSZOM48ePG927d79guNm0aZNhMpmMb7/91jAMwzh+/LjRqFEj4+GHHy5TGzGMyZMnG+vXr7c/37RpkxEUFGS899579mObN282zGaz8fXXXxuGYRgnTpwwmjRpYvz1r38tUxsxjFWrVhnz5s2zP8/IyDDat29vjBgxwn5sx44dho+Pj/Hpp58ahmEYp06dMuLj44277rqrTG3knEOHDhkxMTHGX//61xLhZvfu3Yavr68xefJkwzBs/4HVokULY+zYsWVqI+fCzaFDhy7a5sCBA4bVajXefvttwzBs/xto06aNMXLkyDK1cYbCTQXde++9Rps2bRyOPf/880ZkZGSJ/wIW510s3DzwwANGy5YtHY5NnDjRqFWrllFYWOh0G7mw6667zuH/RB555BGjWbNmDm1efvllIywszCgoKHC6jVzYHXfcYfTo0cP+/KmnnjJiYmIc2rz55ptGYGCgkZOT43QbsSkoKDB69uxpvPvuu8b7779fItz87W9/M6Kjox3+v/rdd981/P397b3vzrSRc+Fm+fLlxsaNG42MjIwSbV566SUjIiLC4f8XPv74Y8PX19fe8+hMG2doQHEFbdq0iU6dOjkc69y5M8nJyRw+fNhLVVVfF/u+U1NTOXDggNNtpKTs7Gy2bt3qcH/7Yt9leno6+/btc7qNnLNu3TqWLl3K66+/zuzZs3n66aftr13suzxz5gy7du1yuo3YvPDCCwQHB3Pfffdd8PVNmzbRsWNHh02UO3fuTE5ODjt27HC6jZwzcuRIRo8eTUREBPfccw+5ubn21zZt2kSHDh2wWCz2Y507dyY/P59t27Y53cYZCjcVdOrUKSIiIhyOFT8/deqUN0qq1pz5vvU7KZ+HH36Y/Px8xo8fbz+m79v1Jk2axKOPPspzzz1H37596dKli/01fd+u89NPP/HRRx/x6aefXrSNvm/XCQ4OZu7cuRw+fJht27axbt06vv32W/72t7/Z23jy+1a4qSBfX19ycnIcjmVnZwPg5+fnjZKqNWe+b/1Oyu7vf/87X331FTNnziQ6Otp+XN+3682YMYP169dz6NAhEhMTGT58uP01fd+uYRgGo0aN4vbbb2f37t2sXLmSvXv3YhgGK1euJCkpCdD37UoxMTEMHDjQ/rx9+/bce++9TJ061X7Mk9+3wk0FNW7cmCNHjjgcO3LkCCaTiYYNG3qpqurrYt83YP++nWkj50ycOJHXXnuNefPm0aNHD4fXSvsui5c8cKaNlBQeHs5dd93Fjz/+SF5eHqDv21WKiopo0qQJy5cv54knnuCJJ57g+++/Jz8/nyeeeIKff/4Z0PftbnXr1nX47jz5fSvcVFCfPn1YsmQJWVlZ9mOzZs0iISGB4OBgL1ZWPfXp04dly5aRmZlpPzZr1iyuvPJKwsPDnW4jNi+99BKTJk1i7ty5XH311SVe79OnD8uXLyc9Pd1+bNasWVx++eX2rmJn2ggO/x9RbM+ePYSFheHr6wvYvsvVq1eTnJxsbzNr1ixatWpFgwYNnG5T01ksFlauXOnwmDBhAn5+fqxcuZKhQ4cCtu9y7dq1nDhxwn7urFmziI+Pt6+N5UwbufDf70WLFtGmTRv78z59+rBp0yaH8aizZs2iUaNGNG/e3Ok2Tin30GgxDMMwTp8+bcTHxxvXXnutMXPmTOPJJ580fHx8jCVLlni7tCqnqKjIWLFihbFixQqjbdu2xpAhQ4wVK1YYGzZssLfJysoyWrRoYfTu3duYOXOm8cwzzxgWi8VYuHBhmdqIYbz11lsGYEycONH+va9YscLYvHmzvU12drbRunVro2fPnsbMmTONv/3tb4bFYjHmz59fpjZim1l5//33G9OnTzd++OEH46mnnjL8/PyMN954w94mNzfXaN++vdGtWzfj+++/N1544QXDYrEYM2fOLFMbKelCs6Xy8/ONjh07GgkJCcaMGTOMf/zjH4bFYjGmT59epjZiGI8//rhx5513Gt9++60xe/ZsY/To0Yafn5/D/w8UFBQYCQkJRqdOnYzvvvvOeOWVVwwfHx9jypQpZWrjDO0K7gInTpzg5Zdf5rfffiMqKop7772Xq666yttlVTl5eXlcc801JY43btyYKVOm2J+fPHmSl19+mV9//ZU6deowfvz4Er0OzrSp6SZMmMCaNWtKHL/88st555137M+Tk5N55ZVX2LRpk30GRO/evR3OcaZNTVdYWMiXX37J/PnzycjIoGnTptx2220OA4oBUlNTeeWVV1i/fj21a9fmrrvuok+fPmVuI45mzZrF22+/zY8//uhwPC0tjVdeeYV169ZRq1Yt7rzzTvr27VvmNjWdYRh88803zJkzh4yMDFq0aMF9991XYpX5jIwMXnvtNX7++WfCwsIYO3YsgwYNKnObS1G4ERERkWpFY25ERESkWlG4ERERkWpF4UZERESqFYUbERERqVYUbkRERKRaUbgRERGRakXhRkRERKoVhRsRqZHy8/OZOnUqqamp3i5FRFxMi/iJiEd999135Ofnlzjepk0bh31o3C0tLY1atWqxbt06rrjiCo+9r4i4n4+3CxCRmuW2226jRYsWxMfHOxz38fHxaLgRkepL4UZEPG7s2LHcf//9F3wtPz+f7777jr59+5Kamsr27dupX78+HTt2LNH25MmTrFmzBh8fH7p160ZYWFiJNmfOnGHNmjXk5eWRkJBwwZ3hDxw4wNatW6lXrx6dOnVyeK2wsJC1a9dy6tQp2rRpQ5MmTcr1mUXEcxRuRKRSycrKYuTIkfTv35/ff/+dli1bsmrVKoYOHcp//vMfe7vPP/+c8ePHc8UVV5Cbm8uOHTuYMmWKwwZ78+fPZ8yYMdSrV4+GDRty33338dFHHzls0Pr3v/+d3bt3Ex8fz8qVKxk8eDBffPEFYNsQ9Oqrr6awsJAWLVrw+++/M3jwYP71r3957PsQkbJTuBERj9u4cSNTp051ONarVy/q1atnf17caxMQEMC2bdvo2LEjw4YNY/DgwRw9epR7772XN954g7vvvhuAZ599lnHjxrFnzx5CQkJISkri5ptv5tFHH+W5556zX3Pr1q0O72u1Wtm2bRsWi4XffvuNDh068Oijj9K2bVumTJmC2Wxmy5YtmM22+RczZ8504zcjIq6g2VIi4nG//fYbM2fOdHgcP37coc39999PQEAAAJdddhmDBg3i22+/BWDOnDkEBgZy11132ds/8cQTpKSksHTpUgCmT5+On58fTz31lL1NrVq1uOqqqxze5y9/+QsWiwWA9u3bEx4ezs6dOwEICAggPT2dAwcO2NvfeOONLvoWRMRd1HMjIh5X2pibYn8c29K0aVN++eUXwDZGpkmTJvbeFICgoCDq1atnDyIHDx6kadOm+Pr6lvo+tWvXdnhutVrJyckB4NZbb2XNmjW0adOG+Ph4+vTpw7333kvTpk2d+pwi4h3quRGRSumP68+kpqYSGRkJQGRkJKdOnbrgOcVtwsPDSUlJqVAN/v7+fPrppyQnJ/PGG29w8OBBOnbsWOHrioh7KdyISKV0/tiWnJwcfvjhB7p37w5Ajx492L9/P7/++qu9zbx588jLy6NLly4AXH/99Rw4cIDly5c7XPfkyZNO13DkyBHAdnuqd+/efPDBB6SlpdlvW4lI5aTbUiLicRcaUNy0aVN7MAGYNWsWPj4+XH755XzxxRcEBgYyfvx4ADp37szo0aMZOHAgEyZMIDc3l1deeYVHHnmE2NhYAK688koeeOABBg0axIMPPkhMTAzz58+nb9++9utcyjfffMPMmTO54YYbqFOnDtOnT6dZs2Z06NDBNV+EiLiFVigWEY+6/fbb7WNaznf11Vczfvx4+8rBy5YtY8OGDWzbto369evzwAMPUKdOHXv7wsJCvv76a5YtW4bFYqFfv34MHTq0xHV/+OEH5s2bh2EY9O/fn8GDBwO29W/uuOMOXnrpJXsgArjnnnsYPXo0PXr0AODnn39m5syZpKSk0Lp1a26//fYS43REpHJRuBGRSkXbIohIRWnMjYiIiFQrCjciUqn4+fkxYsQI3foRkXLTbSkRERGpVtRzIyIiItWKwo2IiIhUKwo3IiIiUq0o3IiIiEi1onAjIiIi1YrCjYiIiFQrCjciIiJSrSjciIiISLWicCMiIiLVyv8DK+Jq7QdofBIAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(epoch_count, loss_values, label=\"Train Loss\")\n", + "plt.plot(epoch_count, test_loss_values, label=\"Test Loss\")\n", + "plt.title(\"Training and Test loss values\")\n", + "plt.ylabel(\"Loss\")\n", + "plt.xlabel(\"Epochs\")\n", + "plt.legend()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 282, + "id": "6aa42ea1", + "metadata": {}, + "outputs": [], + "source": [ + "with torch.inference_mode():\n", + " y_preds_new = model_0(X_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 283, + "id": "04ce6868", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "OrderedDict([('weights', tensor([0.6990])), ('bias', tensor([0.3093]))])" + ] + }, + "execution_count": 283, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "model_0.state_dict()" + ] + }, + { + "cell_type": "code", + "execution_count": 284, + "id": "f1a4db10", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.7, 0.3)" + ] + }, + "execution_count": 284, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "weight, bias" + ] + }, + { + "cell_type": "code", + "execution_count": 285, + "id": "94cdacb6", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_predictions(predictions=y_preds_new)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70ce0795", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.11.15.final.0)", + "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 +} diff --git a/My_Experiments/pytorch.ipynb b/My_Experiments/pytorch.ipynb index dba0e77..df197f3 100644 --- a/My_Experiments/pytorch.ipynb +++ b/My_Experiments/pytorch.ipynb @@ -133,7 +133,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv (3.11.15)", + "display_name": ".venv (3.11.15.final.0)", "language": "python", "name": "python3" }, diff --git a/My_Experiments/pytorch2.ipynb b/My_Experiments/pytorch2.ipynb index 6f90ea4..746e574 100644 --- a/My_Experiments/pytorch2.ipynb +++ b/My_Experiments/pytorch2.ipynb @@ -79,7 +79,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv (3.11.15)", + "display_name": ".venv (3.11.15.final.0)", "language": "python", "name": "python3" }, diff --git a/My_Experiments/pytorch3.ipynb b/My_Experiments/pytorch3.ipynb index 8e953e0..c465d0a 100644 --- a/My_Experiments/pytorch3.ipynb +++ b/My_Experiments/pytorch3.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 22, "id": "3163fb75", "metadata": {}, "outputs": [], @@ -23,7 +23,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 23, "id": "64a02514", "metadata": {}, "outputs": [], @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 24, "id": "35200e59", "metadata": {}, "outputs": [ @@ -42,36 +42,36 @@ "name": "stdout", "output_type": "stream", "text": [ - "Epoch 0: Loss = 42.0600\n", - "Epoch 400: Loss = 24.6847\n", - "Epoch 800: Loss = 14.4873\n", - "Epoch 1200: Loss = 8.5024\n", - "Epoch 1600: Loss = 4.9900\n", - "Epoch 2000: Loss = 2.9286\n", - "Epoch 2400: Loss = 1.7188\n", - "Epoch 2800: Loss = 1.0087\n", - "Epoch 3200: Loss = 0.5920\n", - "Epoch 3600: Loss = 0.3474\n", - "Epoch 4000: Loss = 0.2039\n", - "Epoch 4400: Loss = 0.1197\n", - "Epoch 4800: Loss = 0.0702\n", - "Epoch 5200: Loss = 0.0412\n", - "Epoch 5600: Loss = 0.0242\n", - "Epoch 6000: Loss = 0.0142\n", - "Epoch 6400: Loss = 0.0083\n", - "Epoch 6800: Loss = 0.0049\n", - "Epoch 7200: Loss = 0.0029\n", - "Epoch 7600: Loss = 0.0017\n", - "Epoch 8000: Loss = 0.0010\n", - "Epoch 8400: Loss = 0.0006\n", - "Epoch 8800: Loss = 0.0003\n", - "Epoch 9200: Loss = 0.0002\n", - "Epoch 9600: Loss = 0.0001\n", - "Epoch 10000: Loss = 0.0001\n", - "Epoch 10400: Loss = 0.0000\n", - "Epoch 10800: Loss = 0.0000\n", - "Epoch 11200: Loss = 0.0000\n", - "Epoch 11600: Loss = 0.0000\n", + "Epoch 0: Loss = 10481.2871\n", + "Epoch 400: Loss = 207.9038\n", + "Epoch 800: Loss = 122.0165\n", + "Epoch 1200: Loss = 71.6102\n", + "Epoch 1600: Loss = 42.0273\n", + "Epoch 2000: Loss = 24.6654\n", + "Epoch 2400: Loss = 14.4759\n", + "Epoch 2800: Loss = 8.4958\n", + "Epoch 3200: Loss = 4.9861\n", + "Epoch 3600: Loss = 2.9263\n", + "Epoch 4000: Loss = 1.7174\n", + "Epoch 4400: Loss = 1.0079\n", + "Epoch 4800: Loss = 0.5916\n", + "Epoch 5200: Loss = 0.3472\n", + "Epoch 5600: Loss = 0.2038\n", + "Epoch 6000: Loss = 0.1196\n", + "Epoch 6400: Loss = 0.0702\n", + "Epoch 6800: Loss = 0.0412\n", + "Epoch 7200: Loss = 0.0242\n", + "Epoch 7600: Loss = 0.0142\n", + "Epoch 8000: Loss = 0.0083\n", + "Epoch 8400: Loss = 0.0049\n", + "Epoch 8800: Loss = 0.0029\n", + "Epoch 9200: Loss = 0.0017\n", + "Epoch 9600: Loss = 0.0010\n", + "Epoch 10000: Loss = 0.0006\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", @@ -117,7 +117,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 25, "id": "be1eb1bd", "metadata": {}, "outputs": [ @@ -127,9 +127,9 @@ "text": [ "\n", "--- Результаты обучения ---\n", - "Предсказание для 100°C: 211.99°F (Ожидалось: 212.00)\n", - "Итоговый вес W: 1.7999 (Ожидалось: 1.8)\n", - "Итоговое смещение B: 32.0029 (Ожидалось: 32.0)\n" + "Предсказание для 100°C: 212.00°F (Ожидалось: 212.00)\n", + "Итоговый вес W: 1.8000 (Ожидалось: 1.8)\n", + "Итоговое смещение B: 31.9986 (Ожидалось: 32.0)\n" ] } ], @@ -153,7 +153,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 26, "id": "fa3c1e81", "metadata": {}, "outputs": [], @@ -168,7 +168,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 27, "id": "8860a027", "metadata": {}, "outputs": [], @@ -178,7 +178,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 28, "id": "b1213a8a", "metadata": {}, "outputs": [], @@ -189,7 +189,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 29, "id": "27d203c4", "metadata": {}, "outputs": [ @@ -197,11 +197,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "Epoch 0: loss = 6039.51318359375\n", - "Epoch 400: loss = 199.59164428710938\n", - "Epoch 800: loss = 117.13835144042969\n", - "Epoch 1200: loss = 68.74734497070312\n", - "Epoch 1600: loss = 40.34719467163086\n" + "Epoch 0: loss = 5640.71875\n", + "Epoch 400: loss = 197.63983154296875\n", + "Epoch 800: loss = 115.99267578125\n", + "Epoch 1200: loss = 68.0748291015625\n", + "Epoch 1600: loss = 39.95244598388672\n" ] } ], @@ -223,7 +223,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 30, "id": "024b4276", "metadata": {}, "outputs": [ @@ -233,9 +233,9 @@ "text": [ "\n", "--- Результаты обучения ---\n", - "Предсказание для 100°C: 231.68°F\n", - "Итоговый вес W: 2.0811\n", - "Итоговое смещение B: 23.5716\n" + "Предсказание для 100°C: 231.59°F\n", + "Итоговый вес W: 2.0797\n", + "Итоговое смещение B: 23.6129\n" ] } ], @@ -253,16 +253,152 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "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.3642\n", + "Epoch [2/5], Loss: 2.0382\n", + "Epoch [3/5], Loss: 1.7581\n", + "Epoch [4/5], Loss: 1.5167\n", + "Epoch [5/5], Loss: 1.3047\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": 32, + "id": "98166324", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "from torch import nn\n", + "from matplotlib import pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef1351a0", + "metadata": {}, + "outputs": [], + "source": [ + "X_test = torch.tensor(" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9f7783b", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "class Model(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90874c3d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7b808533", + "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { - "display_name": ".venv (3.11.15)", + "display_name": ".venv (3.11.15.final.0)", "language": "python", "name": "python3" }, diff --git a/micrograd_from_scratch.ipynb b/micrograd_from_scratch.ipynb index d44fda1..db143f4 100644 --- a/micrograd_from_scratch.ipynb +++ b/micrograd_from_scratch.ipynb @@ -776,7 +776,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv (3.11.15)", + "display_name": ".venv (3.11.15.final.0)", "language": "python", "name": "python3" },