Team Ai
Apppublic

JimmyChin1998/Pytorch-Learning-File

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
PyTorch_Workflow_Fundamentals.ipynb1206 linesDownload Raw Back to root
1{2 "cells": [3  {4   "cell_type": "code",5   "execution_count": 1,6   "id": "45547673-e5ba-47a1-949f-ded91159e841",7   "metadata": {},8   "outputs": [],9   "source": [10    "what_were_covering = {1: \"data (prepare and load)\",\n",11    "    2: \"build model\",\n",12    "    3: \"fitting the model to data (training)\",\n",13    "    4: \"making predictions and evaluating a model (inference)\",\n",14    "    5: \"saving and loading a model\",\n",15    "    6: \"putting it all together\"\n",16    "}"17   ]18  },19  {20   "cell_type": "code",21   "execution_count": 2,22   "id": "c64a4d1c-31fc-40a8-b788-da0a30eb417a",23   "metadata": {},24   "outputs": [25    {26     "data": {27      "text/plain": [28       "{1: 'data (prepare and load)',\n",29       " 2: 'build model',\n",30       " 3: 'fitting the model to data (training)',\n",31       " 4: 'making predictions and evaluating a model (inference)',\n",32       " 5: 'saving and loading a model',\n",33       " 6: 'putting it all together'}"34      ]35     },36     "execution_count": 2,37     "metadata": {},38     "output_type": "execute_result"39    }40   ],41   "source": [42    "what_were_covering"43   ]44  },45  {46   "cell_type": "code",47   "execution_count": 3,48   "id": "62cdd39c-6a35-49e2-a271-22e1ddcf5207",49   "metadata": {},50   "outputs": [51    {52     "data": {53      "text/plain": [54       "'2.5.0'"55      ]56     },57     "execution_count": 3,58     "metadata": {},59     "output_type": "execute_result"60    }61   ],62   "source": [63    "import torch\n",64    "from torch import nn # nn contains all of PyTorch's building blocks for neural networks\n",65    "import matplotlib.pyplot as plt\n",66    "\n",67    "# Check PyTorch version\n",68    "torch.__version__"69   ]70  },71  {72   "cell_type": "code",73   "execution_count": 5,74   "id": "cda3e90c-9c67-4c0f-a59e-cf5fcc6b9c04",75   "metadata": {},76   "outputs": [77    {78     "data": {79      "text/plain": [80       "(tensor([[0.0000],\n",81       "         [0.0200],\n",82       "         [0.0400],\n",83       "         [0.0600],\n",84       "         [0.0800],\n",85       "         [0.1000],\n",86       "         [0.1200],\n",87       "         [0.1400],\n",88       "         [0.1600],\n",89       "         [0.1800]]),\n",90       " tensor([[0.3000],\n",91       "         [0.3140],\n",92       "         [0.3280],\n",93       "         [0.3420],\n",94       "         [0.3560],\n",95       "         [0.3700],\n",96       "         [0.3840],\n",97       "         [0.3980],\n",98       "         [0.4120],\n",99       "         [0.4260]]),\n",100       " tensor([[0.0000, 0.0200, 0.0400, 0.0600, 0.0800, 0.1000, 0.1200, 0.1400, 0.1600,\n",101       "          0.1800, 0.2000, 0.2200, 0.2400, 0.2600, 0.2800, 0.3000, 0.3200, 0.3400,\n",102       "          0.3600, 0.3800, 0.4000, 0.4200, 0.4400, 0.4600, 0.4800, 0.5000, 0.5200,\n",103       "          0.5400, 0.5600, 0.5800, 0.6000, 0.6200, 0.6400, 0.6600, 0.6800, 0.7000,\n",104       "          0.7200, 0.7400, 0.7600, 0.7800, 0.8000, 0.8200, 0.8400, 0.8600, 0.8800,\n",105       "          0.9000, 0.9200, 0.9400, 0.9600, 0.9800]]))"106      ]107     },108     "execution_count": 5,109     "metadata": {},110     "output_type": "execute_result"111    }112   ],113   "source": [114    "# Create *known* parameters\n",115    "weight = 0.7\n",116    "bias = 0.3\n",117    "\n",118    "# Create data\n",119    "start = 0\n",120    "end = 1\n",121    "step = 0.02\n",122    "X = torch.arange(start, end, step).unsqueeze(dim=1)\n",123    "y = weight * X + bias\n",124    "z = torch.arange(start, end, step).unsqueeze(dim=0)\n",125    "# 50行1列 (0,1,2)\n",126    "X[:10], y[:10], z[:10] # 1行50列"127   ]128  },129  {130   "cell_type": "code",131   "execution_count": 6,132   "id": "172d6c95-b789-4c1b-a636-4ca371e4e9ec",133   "metadata": {},134   "outputs": [135    {136     "data": {137      "text/plain": [138       "(40, 40, 10, 10)"139      ]140     },141     "execution_count": 6,142     "metadata": {},143     "output_type": "execute_result"144    }145   ],146   "source": [147    "# Create train/test split\n",148    "train_split = int(0.8 * len(X)) # 80% of data used for training set, 20% for testing \n",149    "X_train, y_train = X[:train_split], y[:train_split] # 最初到train_split\n",150    "X_test, y_test = X[train_split:], y[train_split:]   # train_split到最底\n",151    "\n",152    "len(X_train), len(y_train), len(X_test), len(y_test)"153   ]154  },155  {156   "cell_type": "code",157   "execution_count": 46,158   "id": "772dd17b-bafc-49ab-a2ed-cf9815d0eb1d",159   "metadata": {},160   "outputs": [],161   "source": [162    "def plot_predictions(train_data=X_train, \n",163    "                     train_labels=y_train, \n",164    "                     test_data=X_test, \n",165    "                     test_labels=y_test, \n",166    "                     predictions=None):\n",167    "  \"\"\"\n",168    "  Plots training data, test data and compares predictions.\n",169    "  \"\"\"\n",170    "  plt.figure(figsize=(10, 7))\n",171    "\n",172    "  # Plot training data in blue\n",173    "  plt.scatter(train_data, train_labels, c=\"b\", s=4, label=\"Training data\")\n",174    "  \n",175    "  # Plot test data in green\n",176    "  plt.scatter(test_data, test_labels, c=\"g\", s=4, label=\"Testing data\")\n",177    "\n",178    "  if predictions is not None:\n",179    "    # Plot the predictions in red (predictions were made on the test data)\n",180    "    plt.scatter(test_data, predictions, c=\"r\", s=4, label=\"Predictions\")\n",181    "\n",182    "  # Show the legend\n",183    "  plt.legend(prop={\"size\": 14});"184   ]185  },186  {187   "cell_type": "code",188   "execution_count": 47,189   "id": "c92e5766-433d-461a-ae10-be2073055e8d",190   "metadata": {},191   "outputs": [192    {193     "data": {194      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAzoAAAJGCAYAAACTJvC6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABK0ElEQVR4nO3de3xU9Z3/8fcwIQm3DItIDBCTaBGpKC1JQUDqjNKwaD3DWkusW7yhK9sqDyarrixVLtWmVkvRUahWkLpeoAo6x5a6xjrhqqtQ7CooVQiGSyAGNUHBAMP5/TG/TJwmQCYkmZkzr+fjMY8x3znnzGfwhMe8+X7P+Tgsy7IEAAAAADbSJd4FAAAAAEB7I+gAAAAAsB2CDgAAAADbIegAAAAAsB2CDgAAAADbIegAAAAAsB2CDgAAAADbSYt3Aa1x7Ngx7dmzR7169ZLD4Yh3OQAAAADixLIsHThwQP3791eXLseft0mKoLNnzx7l5ubGuwwAAAAACWLnzp0aOHDgcV9PiqDTq1cvSeEPk5WVFedqAAAAAMRLfX29cnNzIxnheJIi6DQuV8vKyiLoAAAAADjpJS3cjAAAAACA7RB0AAAAANgOQQcAAACA7RB0AAAAANgOQQcAAACA7RB0AAAAANhOUtxeui1CoZCOHDkS7zKAuOjataucTme8ywAAAIgb2wUdy7K0d+9e1dXVybKseJcDxIXD4ZDL5dIZZ5xx0nvMAwAA2FHMQWf16tV64IEHtHHjRlVXV+vFF1/UxIkTT7jPqlWrVFpaqs2bN6t///668847NXXq1LbWfEJ1dXX6/PPPdfrpp6tHjx58yUPKsSxLX375pT755BN169ZNvXv3jndJAAAAnS7moPPll19q2LBhuuGGG/SDH/zgpNtXVlbqsssu080336ynn35a69at009+8hOdfvrprdo/FpZlqaamRllZWerbt2+7HhtIJt26dVNDQ4NqamrkcrkI/AAAIOXEHHQmTJigCRMmtHr73/72tzrzzDM1f/58SdKQIUO0YcMGPfjgg+0edEKhkEKhkLKystr1uEAyysrKUn19vUKhkNLSbLdKFQAA4IQ6/K5rb7zxhoqLi6PGxo8frw0bNhz3ZgENDQ2qr6+PerTG0aNHJYkvdYCafg8afy8AAABSSYcHnb179yo7OztqLDs7W0ePHlVtbW2L+5SVlcnlckUeubm5Mb0ny3QAfg8AAEBq65Q+Ov/4havxbmjH+yI2Y8YM1dXVRR47d+7s8BoBAAAA2EeHr/E644wztHfv3qixmpoapaWl6bTTTmtxn4yMDGVkZHR0aQAAAABsqsNndEaNGqXy8vKosVdffVVFRUXq2rVrR789OoHD4ZDb7T6lY1RUVMjhcGj27NntUlNHa4/PDAAAgI4Tc9D54osv9M477+idd96RFL599DvvvKOqqipJ4WVn1157bWT7qVOn6uOPP1Zpaanef/99LV68WIsWLdLtt9/ePp8AksJfvGN5IP7y8/OVn58f7zIAAABsKealaxs2bJDH44n8XFpaKkm67rrrtGTJElVXV0dCjyQVFBRo5cqV8vl8evTRR9W/f389/PDD7X5r6VQ3a9asZmNz5syRy+XS9OnTO/S933//fXXv3v2UjjFixAi9//779D8CAABAu3BYjXcGSGD19fVyuVyqq6s7YY+cr776SpWVlSooKFBmZmYnVpiYHA6H8vLytGPHjniXYjsOh0MXX3yxKioq2nyMxtmcjvr/w+8DAACwo9Zmg0656xoSx44dO+RwOHT99dfrgw8+0JVXXqm+ffvK4XBEvnC/+OKL+tGPfqRvfOMb6t69u1wul8aOHavly5e3eMyWrle5/vrrI8dcsGCBhgwZoszMTOXl5WnOnDk6duxY1PbHu0ancXnXl19+qdLSUg0YMEAZGRm64IIL9MILLxz3M5aUlKhPnz7q2bOnLr74Yq1evVqzZ8+Ww+GIKZw88cQTGjp0qDIzM5Wbm6s777xTX331VYvbbty4UbfeequGDh0ql8ulbt266fzzz9cvf/nLqJ5Rjf8PPv74Y3388cdRSwobP//hw4fl9/s1fvx45ebmKiMjQ/369dOVV16pTZs2tbp+AACAVEVnzRT10Ucf6cILL9R5552n6667Tp9++qnS09Mlha+zSk9P10UXXaScnBx98sknMk1TV111lR5++GHddtttrX6fO+64QxUVFfr+97+v4uJivfTSS5o9e7YOHz6s++67r1XHOHLkiIqLi/Xpp5/qyiuv1MGDB7V06VJNmjRJr7zySlRD2t27d2v06NGqrq7WZZddpmHDhmnr1q0qLi6OWnLZGj//+c91zz33KDs7WzfffLO6du2qZcuW6f33329x+9/97nd6+eWX9d3vfleXXXaZDh48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vhVTTRs2bNADDzwgt9utW265RZs2bdJLL72kd999V++9954yMzMj2y5evFhTpkxR7969de2118rlcmnlypX63ve+pyNHjqhr166tes+DBw/K7Xbr3Xff1ahRo3TxxRdr586dKikpUXFxcYv7/PSnP9WwYcM0btw4nX766dq9e7deeukljRs3TitWrJDX65Ukud1u7dixQ7///e918cUXy+12R47Ru3dvSeGwtmjRInk8Hrndbh07dkxvvvmm7r//fq1atUqrV69u9WcBAABAC6wkUFdXZ0my6urqTrjdoUOHrC1btliHDh3qpMoSmyQrLy8vauzxxx+3JFlTpkyxjhw5EhlvaGiwrrjiCkuStWHDBsuyLOvzzz+3HA6HVVRUZB09ejTqOEePHrU+++yzyM9PPvmkJcl68sknW6zluuuusyRZlZWVkbFgMGhJsiRZS5cujdp+8uTJliTrueeei4x99tlnVs+ePa1evXpZ27Zti4wfOXLEGjduXIuf93hmzZplSbJuvvnmqPH/+Z//idT0j59l+/btzY6zZ88eq3///tagQYOixhs/26xZs1p8/127dlkNDQ3NxufMmWNJsp5++ulWfY4T4fcBAIDEFfggYE3/83Qr8EEg3qUkndZmA5autZG51ZTvFV/SdaN95JFH1KNHDz3yyCNKS2ua0EtPT9d9990nSXruueckhe/kZlmWMjIy5HQ6o47jdDojsxOn6rvf/a5KSkqixm688UZJ0ttvvx0ZCwQC+uKLL3TTTTfprLPOioynpaXp5z//eUzv+dRTTyk9PV1z586NGi8uLtall17a4j4FBQXNxnJycvSDH/xAH374oT7++ONWv/+AAQOUnp7ebPzWW2+VJL322mutPhYAAEgu5lZT3qVe+d/yy7vUm3TfJ5MFS9faoPHkdDqcmv+/85PmHuYHDx7Uu+++q/79++uXv/xls9ePHDkiSfrggw8kSVlZWfrnf/5nvfLKKxo+fLiuuuoqjR07ViNHjmzxS3pbDR8+vNnYwIEDJUmff/55ZOxvf/ubJGn06NHNth8xYkRUcDuRAwcOqLKyUt/85jd1xhlnNHt97Nix+stf/tJsfPv27SorK9Prr7+u3bt3q6GhIer1PXv2KC8vr1U1WJalJ598UkuWLNF7772nuro6HTt2LOpYAADAnoKVwUjDT6fDqYodFUnxXTLZEHTaIFlPzs8++0yWZWn37t2aM2fOcbf78ssvI//9wgsv6Be/+IWee+45zZw5U5LUq1cv3XjjjfrFL36h7t27n3JdLper2VhjaAmFQpGx+vp6SdLpp5/ebPsuXbqob9++rXq/uro6SVK/fv1afD07O7vZ2EcffaQRI0aovr5eHo9HV1xxhbKystSlSxdVVFRo1apVzYLPiUybNk2PPPKIcnNzZRiGcnJylJGRISl8A4NYjgUAAJKLp8Cj+f87P/J90p3vjndJtkTQaYNkPTmzsrIkSYWFhdqwYUOr9unRo4fuu+8+3XfffaqsrFQwGNRvf/tbPfTQQzp06JAee+yxjiw5SmP9n3zySbPXjh07ptra2lb16Wk8Tk1NTYuv79u3r9nYb37zG3322Wd6+umn9a//+q9Rr02dOlWrVq066fs2qqmp0aOPPqoLLrhAb7zxRlRY3Lt37wlDKAAASH7GYEOBqwOq2FEhd747Kf7BPBlxjU4bNJ6c00ZOS5pla1J4JmbIkCF6//33o5aEtVZBQYFuvPFGrVq1Sj179pRpNq0nbbyG5+szMO1t2LBhkqT169c3e+2tt97S0aNHW3WcrKwsFRQU6KOPPtLevXubvb5mzZpmY9u2bZMkGUb0/+tjx45p3bp1zbY/0Z/H9u3bZVmWxo0b12xGrKX3BgAA9mMMNjRv/Lyk+R6ZjAg6bZSsJ+e0adN08OBB3XzzzVFL1BpVVlZGer188skneuutt5pt89lnn6mhoUHdunWLjPXp00eStGvXro4pXJLX61XPnj31xBNPqLKyMjJ+9OhR3X333TEda/LkyTp8+LDuueeeqPFXX321xetzGq+9Wbt2bdT4/fffr/fee6/Z9if682g81vr166Ouy9m1a5fuuuuumD4HAAAAWsbStRRzyy236M0339Tvf/97rVu3TuPGjVP//v21b98+ffDBB/rf//1fPfvss8rPz9fu3bs1cuRInXfeeRo+fLgGDBig/fv3KxAI6MiRI7rzzjsjxx01apS6deum+fPnq76+PnIdTXt+ce/du7fmzZunf/u3f9Pw4cNVUlIS6aOTkZGh/v37q0uX1mX3O++8UytWrNDvfvc7bd68Wd/97ne1c+dO/eEPf9Dll1+uP/3pT1HbT506VU8++aSuvPJKlZSU6LTTTtObb76pv/71ry1uf+6556p///5aunSpunfvroEDB8rhcOjf//3fI3dqW758uYqKinTppZdq3759+uMf/6hLLrlE27dvb7c/MwAAgFRF0EkxDodDS5Ys0WWXXabf/e53+uMf/6gvvvhC/fr106BBg/Tggw9q3LhxkqT8/HzNnj1br7/+ul577TXt379fffv21fDhw+Xz+aIaa/bp00cvvPCCZs+erYULF+rQoUOS2jfoSNLNN9+sf/qnf9IvfvELLVmyRC6XS4Zh6P7771deXp7OPvvsVh2nR48eWrVqlWbMmKEXX3xRf/3rX3Xeeedp2bJlqquraxZcvv3tb+vVV1/Vz372M61YsUJOp1OjR4/WunXrZJpms+2dTqdWrFih//zP/9R///d/68CBA5Kkq6++Wi6XS0uWLFF+fr6WL18uv9+vM888U6WlpfrP//zPdr2jHQAAQKpyWJZlxbuIk6mvr5fL5VJdXV3kQvKWfPXVV6qsrFRBQYEyMzM7sULE20cffaRBgwZp0qRJWrZsWbzLSQj8PgAAADtqbTbgGh0klcbrg77u0KFD8vl8kqSJEyfGoSoAAJCqkrWJfCpg6RqSyqpVqzRlyhQVFxfrzDPPVG1trV5//XXt2LFDl1xyiUpKSuJdIgAASBHJ2kQ+VTCjg6Ry3nnn6Xvf+57WrVunhx9+WM8++6x69uypn//85/rTn/7U6psRAAAAnKqWmsgjcTCjg6QyaNAgLV26NN5lAAAAJG0T+VRB0AEAAADaoLGJfMWOCrnz3SxbSzAEHQAAAKCNjMEGASdB2fKChiS4YzbQ4fg9AAAAqcxWQSctLTxBdfTo0ThXAsRf4+9B4+8FAABAKrFV0HE6nXI6naqvr493KUDc1dfXR34nAAAAUo2t/qnX4XCoX79+qq6uVkZGhnr06CGHwxHvsoBOZVmWvvzyS9XX1ysnJ4ffAQAAkJJsFXQkyeVy6dChQ6qtrdUnn3wS73KAuHA4HOrdu7dcLle8SwEAICmYW00FK4PyFHi4uYBNOKwkuGK5vr5eLpdLdXV1ysrKatU+oVBIR44c6eDKgMTUtWtXlqwBANBK5lZT3qXeSD+cwNUBwk4Ca202sN2MTiOuTQAAAEBrBCuDkZDjdDhVsaOCoGMDtroZAQAAABArT4EnEnJCVkjufHe8S0I7sO2MDgAAANAaxmBDgasDqthRIXe+m9kcm7DtNToAAAAA7Ke12YClawAAAABsh6ADAAAAwHYIOgAAAABsp01BZ8GCBSooKFBmZqYKCwu1Zs2aE27/6KOPasiQIerWrZsGDx6sp556qk3FAgAAAEBrxBx0li1bpunTp2vmzJnatGmTxo4dqwkTJqiqqqrF7RcuXKgZM2Zo9uzZ2rx5s+bMmaOf/vSnevnll0+5eAAAAKCRudWU7xWfzK1mvEtBAoj5rmsjR47U8OHDtXDhwsjYkCFDNHHiRJWVlTXbfvTo0RozZoweeOCByNj06dO1YcMGrV27tlXvyV3XAAAAcCLmVlPepd5IL5zA1QFuE21THXLXtcOHD2vjxo0qLi6OGi8uLtb69etb3KehoUGZmZlRY926ddNbb72lI0eOHHef+vr6qAcAAABwPMHKYCTkOB1OVeyoiHdJiLOYgk5tba1CoZCys7OjxrOzs7V3794W9xk/fryeeOIJbdy4UZZlacOGDVq8eLGOHDmi2traFvcpKyuTy+WKPHJzc2MpEwAAACnGU+CJhJyQFZI73x3vkhBnbboZgcPhiPrZsqxmY43uvvtuTZgwQRdeeKG6du0qr9er66+/XpLkdDpb3GfGjBmqq6uLPHbu3NmWMgEAAJAijMGGAlcHNG3kNJatQVKMQadv375yOp3NZm9qamqazfI06tatmxYvXqyDBw9qx44dqqqqUn5+vnr16qW+ffu2uE9GRoaysrKiHgAAAMCJGIMNzRs/j5ADSTEGnfT0dBUWFqq8vDxqvLy8XKNHjz7hvl27dtXAgQPldDq1dOlSff/731eXLrTxAQAAAND+0mLdobS0VJMnT1ZRUZFGjRqlxx9/XFVVVZo6daqk8LKz3bt3R3rl/P3vf9dbb72lkSNH6rPPPtO8efP03nvv6fe//337fhIAAAAA+P9iDjolJSXav3+/5s6dq+rqag0dOlQrV65UXl6eJKm6ujqqp04oFNKvf/1rbd26VV27dpXH49H69euVn5/fbh8CAAAAAL4u5j468UAfHQAAAABSB/XRAQAAADqaudWU7xWfzK1mvEtBEiPoAAAAIGGYW015l3rlf8sv71IvYQdtRtABAABAwghWBiNNP50Opyp2VMS7JCQpgg4AAAAShqfAEwk5ISskd7473iUhScV81zUAAACgoxiDDQWuDqhiR4Xc+W6af6LNuOsaAAAAgKTBXdcAAAAApCyCDgAAAADbIegAAAAAsB2CDgAAAADbIegAAACgQ5hbTfle8dH0E3FB0AEAAEC7M7ea8i71yv+WX96lXsIOOh1BBwAAAO0uWBmMNP10Opyq2FER75KQYgg6AAAAaHeeAk8k5ISskNz57niXhBSTFu8CAAAAYD/GYEOBqwOq2FEhd75bxmAj3iUhxTgsy7LiXcTJtLb7KQAAAAB7a202YOkaAAAAANsh6AAAAACwHYIOAAAAANsh6AAAAACwHYIOAAAAjsvcasr3io+Gn0g6BB0AAAC0yNxqyrvUK/9bfnmXegk7SCoEHQAAALQoWBmMNPx0Opyq2FER75KAViPoAAAAoEWeAk8k5ISskNz57niXBLRaWrwLAAAAQGIyBhsKXB1QxY4KufPdMgYb8S4JaDWHZVlWvIs4mdZ2PwUAAABgb63NBixdAwAAAGA7BB0AAAAAtkPQAQAAAGA7BB0AAAAAtkPQAQAASAGmKfl84WcgFRB0AAAAbM40Ja9X8vvDz4QdpAKCDgAAgM0Fg5LTKYVC4eeKinhXBHQ8gg4AAIDNeTxNIScUktzueFcEdLy0eBcAAACAjmUYUiAQnslxu8M/A3ZH0AEAAEgBhkHAQWph6RoAAAAA2yHoAAAAALAdgg4AAAAA2yHoAAAAALAdgg4AAECSME3J56PhJ9AaBB0AAIAkYJqS1yv5/eFnwg5wYgQdAACAJBAMNjX8dDrDPXEAHB9BBwAAIAl4PE0hJxQKN/4EcHw0DAUAAEgChiEFAuGZHLeb5p/AyRB0AAAAkoRhEHCA1mLpGgAAAADbIegAAAAAsB2CDgAAAADbIegAAAAAsB2CDgAAQCczTcnno+kn0JEIOgAAAJ3INCWvV/L7w8+EHaBjEHQAAAA6UTDY1PTT6Qz3xQHQ/gg6AAAAncjjaQo5oVC4+SeA9kfDUAAAgE5kGFIgEJ7JcbtpAAp0FIIOAABAJzMMAg7Q0Vi6BgAAAMB2CDoAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAA0EamKfl8NP0EElGbgs6CBQtUUFCgzMxMFRYWas2aNSfc/plnntGwYcPUvXt35eTk6IYbbtD+/fvbVDAAAEAiME3J65X8/vAzYQdILDEHnWXLlmn69OmaOXOmNm3apLFjx2rChAmqqqpqcfu1a9fq2muv1ZQpU7R582Y9//zzevvtt3XTTTedcvEAAADxEgw2Nf10OsN9cQAkjpiDzrx58zRlyhTddNNNGjJkiObPn6/c3FwtXLiwxe3ffPNN5efna9q0aSooKNBFF12kW265RRs2bDjl4gEAAOLF42kKOaFQuPkngMQRU9A5fPiwNm7cqOLi4qjx4uJirV+/vsV9Ro8erV27dmnlypWyLEv79u3TCy+8oMsvv/y479PQ0KD6+vqoBwAAQCIxDCkQkKZNCz/TABRILDEFndraWoVCIWVnZ0eNZ2dna+/evS3uM3r0aD3zzDMqKSlRenq6zjjjDPXu3Vt+v/+471NWViaXyxV55ObmxlImAABApzAMad48Qg6QiNp0MwKHwxH1s2VZzcYabdmyRdOmTdM999yjjRs36pVXXlFlZaWmTp163OPPmDFDdXV1kcfOnTvbUiYAAACAFJUWy8Z9+/aV0+lsNntTU1PTbJanUVlZmcaMGaM77rhDknTBBReoR48eGjt2rO69917l5OQ02ycjI0MZGRmxlAYAAAAAETHN6KSnp6uwsFDl5eVR4+Xl5Ro9enSL+xw8eFBdukS/jdPplBSeCQIAAACA9hbz0rXS0lI98cQTWrx4sd5//335fD5VVVVFlqLNmDFD1157bWT7K664QitWrNDChQu1fft2rVu3TtOmTdOIESPUv3//9vskAAAAAPD/xbR0TZJKSkq0f/9+zZ07V9XV1Ro6dKhWrlypvLw8SVJ1dXVUT53rr79eBw4c0COPPKL/+I//UO/evXXJJZfo/vvvb79PAQAA0EamGe6J4/FwUwHAThxWEqwfq6+vl8vlUl1dnbKysuJdDgAAsAnTlLzepl443CYaSHytzQZtuusaAACAHQSDTSHH6ZQqKuJdEYD2QtABAAApy+NpCjmhkOR2x7siAO0l5mt0AAAA7MIwwsvVKirCIYdla4B9EHQAAEBKMwwCDmBHLF0DAAAAYDsEHQAAAAC2Q9ABAAAAYDsEHQAAAAC2Q9ABAAC2YJqSzxd+BgCCDgAASHqmKXm9kt8ffibsACDoAACApBcMNjX9dDrDfXEApDaCDgAASHoeT1PICYXCzT8BpDYahgIAgKRnGFIgEJ7JcbtpAAqAoAMAAGzCMAg4AJqwdA0AAACA7RB0AAAAANgOQQcAAACA7RB0AAAAANgOQQcAACQU05R8Ppp+Ajg1BB0AAJAwTFPyeiW/P/xM2AHQVgQdAACQMILBpqafTme4Lw4AtAVBBwAAJAyPpynkhELh5p8A0BY0DAUAAAnDMKRAIDyT43bTABRA2xF0AABAQjEMAg6AU8fSNQAAAAC2Q9ABAAAAYDsEHQAAAAC2Q9ABAAAAYDsEHQAA0O5MU/L5aPgJIH4IOgAAoF2ZpuT1Sn5/+JmwAyAeCDoAAKBdBYNNDT+dznBPHADobAQdAADQrjyeppATCoUbfwJAZ6NhKAAAaFeGIQUC4Zkct5vmnwDig6ADAADanWEQcADEF0vXAAAAANgOQQcAAACA7RB0AAAAANgOQQcAAACA7RB0AADAcZmm5PPR9BNA8iHoAACAFpmm5PVKfn/4mbADIJkQdAAAQIuCwaamn05nuC8OACQLgg4AAGiRx9MUckKhcPNPAEgWNAwFAAAtMgwpEAjP5LjdNAAFkFwIOgAA4LgMg4ADIDmxdA0AAACA7RB0AAAAANgOQQcAAACA7RB0AAAAANgOQQcAAJszTcnno+EngNRC0AEAwMZMU/J6Jb8//EzYAZAqCDoAANhYMNjU8NPpDPfEAYBUQNABAMDGPJ6mkBMKhRt/AkAqoGEoAAA2ZhhSIBCeyXG7af4JIHUQdAAAsDnDIOAASD0sXQMAAABgOwQdAAAAALZD0AEAAABgOwQdAAAAALZD0AEAIEmYpuTz0fQTAFqDoAMAQBIwTcnrlfz+8DNhBwBOrE1BZ8GCBSooKFBmZqYKCwu1Zs2a4257/fXXy+FwNHucd955bS4aAIBUEww2Nf10OsN9cQAAxxdz0Fm2bJmmT5+umTNnatOmTRo7dqwmTJigqqqqFrd/6KGHVF1dHXns3LlTffr00Q9/+MNTLh4AgFTh8TSFnFAo3PwTAHB8DsuyrFh2GDlypIYPH66FCxdGxoYMGaKJEyeqrKzspPu/9NJLuvLKK1VZWam8vLxWvWd9fb1cLpfq6uqUlZUVS7kAANiGaYZnctxuGoACSF2tzQZpsRz08OHD2rhxo+66666o8eLiYq1fv75Vx1i0aJHGjRt3wpDT0NCghoaGyM/19fWxlAkAgC0ZBgEHAForpqVrtbW1CoVCys7OjhrPzs7W3r17T7p/dXW1/vznP+umm2464XZlZWVyuVyRR25ubixlAgAAAEhxbboZgcPhiPrZsqxmYy1ZsmSJevfurYkTJ55wuxkzZqiuri7y2LlzZ1vKBAAAAJCiYlq61rdvXzmdzmazNzU1Nc1mef6RZVlavHixJk+erPT09BNum5GRoYyMjFhKAwAAAICImGZ00tPTVVhYqPLy8qjx8vJyjR49+oT7rlq1Sh999JGmTJkSe5UAAAAAEIOYZnQkqbS0VJMnT1ZRUZFGjRqlxx9/XFVVVZo6daqk8LKz3bt366mnnorab9GiRRo5cqSGDh3aPpUDAJCkTDPcF8fj4eYCANBRYg46JSUl2r9/v+bOnavq6moNHTpUK1eujNxFrbq6ullPnbq6Oi1fvlwPPfRQ+1QNAECSMk3J6w33w5k/XwoECDsA0BFi7qMTD/TRAQDYhc8n+f1NzT+nTZPmzYt3VQCQPFqbDdp01zUAANA2Hk9TyAmFws0/AQDtL+alawAAoO0MI7xcraIiHHJYtgYAHYOgAwBAJzMMAg4AdDSWrgEAAACwHYIOAAAAANsh6AAAAACwHYIOAAAAANsh6AAA0AamGe6JY5rxrgQA0BKCDgAAMTJNyesNN/70egk7AJCICDoAAMQoGGxq+Ol0hnviAAASC0EHAIAYeTxNIScUCjf+BAAkFhqGAgAQI8OQAoHwTI7bTfNPAEhEBB0AANrAMAg4AJDIWLoGAAAAwHYIOgAAAABsh6ADAAAAwHYIOgAAAABsh6ADAEhppin5fDT9BAC7IegAAFKWaUper+T3h58JOwBgHwQdAEDKCgabmn46neG+OAAAeyDoAABSlsfTFHJCoXDzTwCAPdAwFACQsgxDCgTCMzluNw1AAcBOCDoAgJRmGAQcALAjlq4BAAAAsB2CDgAAAADbIegAAAAAsB2CDgAAAADbIegAAGzBNCWfj6afAIAwgg4AIOmZpuT1Sn5/+JmwAwAg6AAAkl4w2NT00+kM98UBAKQ2gg4AIOl5PE0hJxQKN/8EAKQ2GoYCAJKeYUiBQHgmx+2mASgAgKADALAJwyDgAACasHQNAAAAgO0QdAAAAADYDkEHAAAAgO0QdAAAAADYDkEHAJAwTFPy+Wj4CQA4dQQdAEBCME3J65X8/vAzYQcAcCoIOgCAhBAMNjX8dDrDPXEAAGgrgg4AICF4PE0hJxQKN/4EAKCtaBgKAEgIhiEFAuGZHLeb5p8AgFND0AEAJAzDIOAAANoHS9cAAAAA2A5BBwAAAIDtEHQAAAAA2A5BBwAAAIDtEHQAAO3ONCWfj6afAID4IegAANqVaUper+T3h58JOwCAeCDoAADaVTDY1PTT6Qz3xQEAoLMRdAAA7crjaQo5oVC4+ScAAJ2NhqEAgHZlGFIgEJ7JcbtpAAoAiA+CDgCg3RkGAQcAEF8sXQMAAABgOwQdAAAAALZD0AEAAABgOwQdAAAAALZD0AEAtMg0JZ+Php8AgORE0AEANGOaktcr+f3hZ8IOACDZEHQAAM0Eg00NP53OcE8cAACSCUEHANCMx9MUckKhcONPAACSSZuCzoIFC1RQUKDMzEwVFhZqzZo1J9y+oaFBM2fOVF5enjIyMnT22Wdr8eLFbSoYANDxDEMKBKRp08LPNP8EACSbtFh3WLZsmaZPn64FCxZozJgxeuyxxzRhwgRt2bJFZ555Zov7TJo0Sfv27dOiRYv0jW98QzU1NTp69OgpFw8A6DiGQcABACQvh2VZViw7jBw5UsOHD9fChQsjY0OGDNHEiRNVVlbWbPtXXnlFV199tbZv364+ffq06j0aGhrU0NAQ+bm+vl65ubmqq6tTVlZWLOUCAAAAsJH6+nq5XK6TZoOYlq4dPnxYGzduVHFxcdR4cXGx1q9f3+I+pmmqqKhIv/rVrzRgwACdc845uv3223Xo0KHjvk9ZWZlcLlfkkZubG0uZAAAAAFJcTEvXamtrFQqFlJ2dHTWenZ2tvXv3trjP9u3btXbtWmVmZurFF19UbW2tfvKTn+jTTz897nU6M2bMUGlpaeTnxhkdAAAAAGiNmK/RkSSHwxH1s2VZzcYaHTt2TA6HQ88884xcLpckad68ebrqqqv06KOPqlu3bs32ycjIUEZGRltKAwAAAIDYlq717dtXTqez2exNTU1Ns1meRjk5ORowYEAk5Ejha3osy9KuXbvaUDIAIBamKfl8NP0EAKSWmIJOenq6CgsLVV5eHjVeXl6u0aNHt7jPmDFjtGfPHn3xxReRsb///e/q0qWLBg4c2IaSAQCtZZqS1yv5/eFnwg4AIFXE3EentLRUTzzxhBYvXqz3339fPp9PVVVVmjp1qqTw9TXXXnttZPtrrrlGp512mm644QZt2bJFq1ev1h133KEbb7yxxWVrAID2Eww2Nf10OqWKinhXBABA54j5Gp2SkhLt379fc+fOVXV1tYYOHaqVK1cqLy9PklRdXa2qqqrI9j179lR5ebluu+02FRUV6bTTTtOkSZN07733tt+nAAC0yOOR5s9vCjtud7wrAgCgc8TcRyceWnuvbABAc6YZnslxu2kACgBIfq3NBm266xoAIHkYBgEHAJB6Yr5GBwAAAAASHUEHAAAAgO0QdAAAAADYDkEHAAAAgO0QdAAgSZim5PPR9BMAgNYg6ABAEjBNyeuV/P7wM2EHAIATI+gAQBIIBpuafjqd4b44AADg+Ag6AJAEPJ6mkBMKhZt/AgCA46NhKAAkAcOQAoHwTI7bTQNQAABOhqADAEnCMAg4AAC0FkvXAAAAANgOQQcAAACA7RB0AAAAANgOQQcAAACA7RB0AKATmabk89HwEwCAjkbQAYBOYpqS1yv5/eFnwg4AAB2HoAMAnSQYbGr46XSGe+IAAICOQdABgE7i8TSFnFAo3PgTAAB0DBqGAkAnMQwpEAjP5LjdNP8EAKAjEXQAoBMZBgEHAIDOwNI1AAAAALZD0AEAAABgOwQdAAAAALZD0AEAAABgOwQdAGgD05R8Ppp+AgCQqAg6ABAj05S8XsnvDz8TdgAASDwEHQCIUTDY1PTT6Qz3xQEAAImFoAMAMfJ4mkJOKBRu/gkAABILDUMBIEaGIQUC4Zkct5sGoAAAJCKCDgC0gWEQcAAASGQsXQMAAABgOwQdAAAAALZD0AEAAABgOwQdAAAAALZD0AGQ0kxT8vlo+gkAgN0QdACkLNOUvF7J7w8/E3YAALAPgg6AlBUMNjX9dDrDfXEAAIA9EHQApCyPpynkhELh5p8AAMAeaBgKIGUZhhQIhGdy3G4agAIAYCcEHQApzTAIOAAA2BFL1wAAAADYDkEHAAAAgO0QdAAAAADYDkEHAAAAgO0QdAAkPdOUfD4afgIAgCYEHQBJzTQlr1fy+8PPhB0AACARdAAkuWCwqeGn0xnuiQMAAEDQAZDUPJ6mkBMKhRt/AgAA0DAUQFIzDCkQCM/kuN00/wQAAGEEHQBJzzAIOAAAIBpL1wAAAADYDkEHAAAAgO0QdAAAAADYDkEHAAAAgO0QdAAkDNOUfD6afgIAgFNH0AGQEExT8nolvz/8TNgBAACngqADICEEg01NP53OcF8cAACAtiLoAEgIHk9TyAmFws0/AQAA2oqGoQASgmFIgUB4JsftpgEoAAA4NW2a0VmwYIEKCgqUmZmpwsJCrVmz5rjbVlRUyOFwNHt88MEHbS4agD0ZhjRvHiEHAACcupiDzrJlyzR9+nTNnDlTmzZt0tixYzVhwgRVVVWdcL+tW7equro68hg0aFCbiwYAAACAE4k56MybN09TpkzRTTfdpCFDhmj+/PnKzc3VwoULT7hfv379dMYZZ0QeTqezzUUDAAAAwInEFHQOHz6sjRs3qri4OGq8uLhY69evP+G+3/72t5WTk6NLL71UwWDwhNs2NDSovr4+6gEAAAAArRVT0KmtrVUoFFJ2dnbUeHZ2tvbu3dviPjk5OXr88ce1fPlyrVixQoMHD9all16q1atXH/d9ysrK5HK5Io/c3NxYygQAAACQ4tp01zWHwxH1s2VZzcYaDR48WIMHD478PGrUKO3cuVMPPvigvvvd77a4z4wZM1RaWhr5ub6+nrADJAnTDPfE8Xi4qQAAAIifmGZ0+vbtK6fT2Wz2pqamptksz4lceOGF+vDDD4/7ekZGhrKysqIeABKfaUper+T3h59NM94VAQCAVBVT0ElPT1dhYaHKy8ujxsvLyzV69OhWH2fTpk3KycmJ5a0BJIFgsKnhp9MZ7okDAAAQDzEvXSstLdXkyZNVVFSkUaNG6fHHH1dVVZWmTp0qKbzsbPfu3XrqqackSfPnz1d+fr7OO+88HT58WE8//bSWL1+u5cuXt+8nARB3Ho80f35T2HG7410RAABIVTEHnZKSEu3fv19z585VdXW1hg4dqpUrVyovL0+SVF1dHdVT5/Dhw7r99tu1e/dudevWTeedd57+9Kc/6bLLLmu/TwEgIRiGFAiEZ3Lcbq7RAQAA8eOwLMuKdxEnU19fL5fLpbq6Oq7XAQAAAFJYa7NBzA1DAQAAACDREXQAAAAA2A5BBwAAAIDtEHQAAAAA2A5BB0CLTFPy+Wj6CQAAkhNBB0Azpil5vZLfH34m7AAAgGRD0AHQTDDY1PTT6Qz3xQEAAEgmBB0AzXg8TSEnFAo3/wQAAEgmafEuAEDiMQwpEAjP5Ljd4Z8BAACSCUEHQIsMg4ADAACSF0vXAAAAANgOQQcAAACA7RB0AAAAANgOQQcAAACA7RB0AJszTcnno+knAABILQQdwMZMU/J6Jb8//EzYAQAAqYKgA9hYMNjU9NPpDPfFAQAASAUEHcDGPJ6mkBMKhZt/AgAApAIahgI2ZhhSIBCeyXG7aQAKAABSB0EHsDnDIOAAAIDUw9I1AAAAALZD0AEAAABgOwQdAAAAALZD0AEAAABgOwQdIAmYpuTz0fATAACgtQg6QIIzTcnrlfz+8DNhBwAA4OQIOkCCCwabGn46neGeOAAAADgxgg6Q4DyeppATCoUbfwIAAODEaBgKJDjDkAKB8EyO203zTwAAgNYg6ABJwDAIOAAAALFg6RoAAAAA2yHoAAAAALAdgg4AAAAA2yHoAAAAALAdgg7QiUxT8vlo+gkAANDRCDpAJzFNyeuV/P7wM2EHAACg4xB0gE4SDDY1/XQ6w31xAAAA0DEIOkAn8XiaQk4oFG7+CQAAgI5Bw1CgkxiGFAiEZ3LcbhqAAgAAdCSCDtCJDIOAAwAA0BlYugYAAADAdgg6AAAAAGyHoAMAAADAdgg6AAAAAGyHoAPEyDQln4+GnwAAAImMoAPEwDQlr1fy+8PPhB0AAIDERNABYhAMNjX8dDrDPXEAAACQeAg6QAw8nqaQEwqFG38CAAAg8dAwFIiBYUiBQHgmx+2m+ScAAECiIugAMTIMAg4AAECiY+kaAAAAANsh6AAAAACwHYIOAAAAANsh6AAAAACwHYIOUpZpSj4fTT8BAADsiKCDlGSaktcr+f3hZ8IOAACAvRB0kJKCwaamn05nuC8OAAAA7IOgg5Tk8TSFnFAo3PwTAAAA9kHDUKQkw5ACgfBMjttNA1AAAAC7IeggZRkGAQcAAMCuWLoGAAAAwHbaFHQWLFiggoICZWZmqrCwUGvWrGnVfuvWrVNaWpq+9a1vteVtAQAAAKBVYg46y5Yt0/Tp0zVz5kxt2rRJY8eO1YQJE1RVVXXC/erq6nTttdfq0ksvbXOxAAAAANAaDsuyrFh2GDlypIYPH66FCxdGxoYMGaKJEyeqrKzsuPtdffXVGjRokJxOp1566SW98847x922oaFBDQ0NkZ/r6+uVm5ururo6ZWVlxVIuAAAAABupr6+Xy+U6aTaIaUbn8OHD2rhxo4qLi6PGi4uLtX79+uPu9+STT2rbtm2aNWtWq96nrKxMLpcr8sjNzY2lTKQY05R8Ppp+AgAAoElMQae2tlahUEjZ2dlR49nZ2dq7d2+L+3z44Ye666679MwzzygtrXU3eZsxY4bq6uoij507d8ZSJlKIaUper+T3h58JOwAAAJDaeDMCh8MR9bNlWc3GJCkUCumaa67RnDlzdM4557T6+BkZGcrKyop6AC0JBpuafjqd4b44AAAAQExBp2/fvnI6nc1mb2pqaprN8kjSgQMHtGHDBt16661KS0tTWlqa5s6dq7/97W9KS0vT66+/fmrVI+V5PE0hJxQKN/8EAAAAYmoYmp6ersLCQpWXl+tf/uVfIuPl5eXyer3Nts/KytK7774bNbZgwQK9/vrreuGFF1RQUNDGsoEww5ACgfBMjttNA1AAAACExRR0JKm0tFSTJ09WUVGRRo0apccff1xVVVWaOnWqpPD1Nbt379ZTTz2lLl26aOjQoVH79+vXT5mZmc3GgbYyDAIOAAAAosUcdEpKSrR//37NnTtX1dXVGjp0qFauXKm8vDxJUnV19Ul76gAAAABAR4q5j048tPZe2QAAAADsrUP66AAAAABAMiDoAAAAALAdgg4SgmlKPh8NPwEAANA+CDqIO9OUvF7J7w8/E3YAAABwqgg6iLtgsKnhp9MZ7okDAAAAnAqCDuLO42kKOaFQuPEnAAAAcCpi7qMDtDfDkAKB8EyO203zTwAAAJw6gg4SgmEQcAAAANB+WLoGAAAAwHYIOgAAAABsh6ADAAAAwHYIOgAAAABsh6CDdmWaks9H008AAADEF0EH7cY0Ja9X8vvDz4QdAAAAxAtBB+0mGGxq+ul0hvviAAAAAPFA0EG78XiaQk4oFG7+CQAAAMQDDUPRbgxDCgTCMzluNw1AAQAAED8EHbQrwyDgAAAAIP5YugYAAADAdgg6AAAAAGyHoAMAAADAdgg6AAAAAGyHoIMWmabk89H0EwAAAMmJoINmTFPyeiW/P/xM2AEAAECyIeigmWCwqemn0xnuiwMAAAAkE4IOmvF4mkJOKBRu/gkAAAAkExqGohnDkAKB8EyO200DUAAAACQfgg5aZBgEHAAAACQvlq4BAAAAsB2CDgAAAADbIegAAAAAsB2CDgAAAADbIejYmGlKPh8NPwEAAJB6CDo2ZZqS1yv5/eFnwg4AAABSCUHHpoLBpoafTme4Jw4AAACQKgg6NuXxNIWcUCjc+BMAAABIFTQMtSnDkAKB8EyO203zTwAAAKQWgo6NGQYBBwAAAKmJpWsAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAAAMB2CDpJwDQln4+mnwAAAEBrEXQSnGlKXq/k94efCTsAAADAyRF0Elww2NT00+kM98UBAAAAcGIEnQTn8TSFnFAo3PwTAAAAwInRMDTBGYYUCIRnctxuGoACAAAArUHQSQKGQcABAAAAYsHSNQAAAAC2Q9ABAAAAYDsEHQAAAAC2Q9ABAAAAYDsEnU5impLPR8NPAAAAoDMQdDqBaUper+T3h58JOwAAAEDHIuh0gmCwqeGn0xnuiQMAAACg4xB0OoHH0xRyQqFw408AAAAAHYeGoZ3AMKRAIDyT43bT/BMAAADoaASdTmIYBBwAAACgs7B0DQAAAIDtEHQAAAAA2E6bgs6CBQtUUFCgzMxMFRYWas2aNcfddu3atRozZoxOO+00devWTeeee65+85vftLlgAAAAADiZmK/RWbZsmaZPn64FCxZozJgxeuyxxzRhwgRt2bJFZ555ZrPte/TooVtvvVUXXHCBevToobVr1+qWW25Rjx499G//9m/t8iEAAAAA4OsclmVZsewwcuRIDR8+XAsXLoyMDRkyRBMnTlRZWVmrjnHllVeqR48e+u///u9WbV9fXy+Xy6W6ujplZWXFUm67M81wXxyPh5sLAAAAAJ2ttdkgpqVrhw8f1saNG1VcXBw1XlxcrPXr17fqGJs2bdL69et18cUXH3ebhoYG1dfXRz0SgWlKXq/k94efTTPeFQEAAABoSUxBp7a2VqFQSNnZ2VHj2dnZ2rt37wn3HThwoDIyMlRUVKSf/vSnuummm467bVlZmVwuV+SRm5sbS5kdJhhsavrpdIb74gAAAABIPG26GYHD4Yj62bKsZmP/aM2aNdqwYYN++9vfav78+XruueeOu+2MGTNUV1cXeezcubMtZbY7j6cp5IRC4eafAAAAABJPTDcj6Nu3r5xOZ7PZm5qammazPP+ooKBAknT++edr3759mj17tn70ox+1uG1GRoYyMjJiKa1TGIYUCIRnctxurtEBAAAAElVMMzrp6ekqLCxUeXl51Hh5eblGjx7d6uNYlqWGhoZY3jphGIY0bx4hBwAAAEhkMd9eurS0VJMnT1ZRUZFGjRqlxx9/XFVVVZo6daqk8LKz3bt366mnnpIkPfroozrzzDN17rnnSgr31XnwwQd12223tePHAAAAAIAmMQedkpIS7d+/X3PnzlV1dbWGDh2qlStXKi8vT5JUXV2tqqqqyPbHjh3TjBkzVFlZqbS0NJ199tn65S9/qVtuuaX9PgUAAAAAfE3MfXTiIZH66AAAAACInw7powMAAAAAyYCgAwAAAMB2CDoAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAAAMB20uJdQGtYliVJqq+vj3MlAAAAAOKpMRM0ZoTjSYqgc+DAAUlSbm5unCsBAAAAkAgOHDggl8t13Ncd1smiUAI4duyY9uzZo169esnhcMS1lvr6euXm5mrnzp3KysqKay1IPpw/OBWcP2grzh2cCs4fnIqOOH8sy9KBAwfUv39/dely/CtxkmJGp0uXLho4cGC8y4iSlZXFLzvajPMHp4LzB23FuYNTwfmDU9He58+JZnIacTMCAAAAALZD0AEAAABgOwSdGGVkZGjWrFnKyMiIdylIQpw/OBWcP2grzh2cCs4fnIp4nj9JcTMCAAAAAIgFMzoAAAAAbIegAwAAAMB2CDoAAAAAbIegAwAAAMB2CDoAAAAAbIeg04IFCxaooKBAmZmZKiws1Jo1a064/apVq1RYWKjMzEydddZZ+u1vf9tJlSIRxXL+rFixQt/73vd0+umnKysrS6NGjdL//M//dGK1SCSx/t3TaN26dUpLS9O3vvWtji0QCS3W86ehoUEzZ85UXl6eMjIydPbZZ2vx4sWdVC0STaznzzPPPKNhw4ape/fuysnJ0Q033KD9+/d3UrVIFKtXr9YVV1yh/v37y+Fw6KWXXjrpPp35vZmg8w+WLVum6dOna+bMmdq0aZPGjh2rCRMmqKqqqsXtKysrddlll2ns2LHatGmT/uu//kvTpk3T8uXLO7lyJIJYz5/Vq1fre9/7nlauXKmNGzfK4/Hoiiuu0KZNmzq5csRbrOdOo7q6Ol177bW69NJLO6lSJKK2nD+TJk3SX/7yFy1atEhbt27Vc889p3PPPbcTq0aiiPX8Wbt2ra699lpNmTJFmzdv1vPPP6+3335bN910UydXjnj78ssvNWzYMD3yyCOt2r7TvzdbiDJixAhr6tSpUWPnnnuuddddd7W4/Z133mmde+65UWO33HKLdeGFF3ZYjUhcsZ4/LfnmN79pzZkzp71LQ4Jr67lTUlJi/exnP7NmzZplDRs2rAMrRCKL9fz585//bLlcLmv//v2dUR4SXKznzwMPPGCdddZZUWMPP/ywNXDgwA6rEYlPkvXiiy+ecJvO/t7MjM7XHD58WBs3blRxcXHUeHFxsdavX9/iPm+88Uaz7cePH68NGzboyJEjHVYrEk9bzp9/dOzYMR04cEB9+vTpiBKRoNp67jz55JPatm2bZs2a1dElIoG15fwxTVNFRUX61a9+pQEDBuicc87R7bffrkOHDnVGyUggbTl/Ro8erV27dmnlypWyLEv79u3TCy+8oMsvv7wzSkYS6+zvzWntfsQkVltbq1AopOzs7Kjx7Oxs7d27t8V99u7d2+L2R48eVW1trXJycjqsXiSWtpw//+jXv/61vvzyS02aNKkjSkSCasu58+GHH+quu+7SmjVrlJbGX+WprC3nz/bt27V27VplZmbqxRdfVG1trX7yk5/o008/5TqdFNOW82f06NF65plnVFJSoq+++kpHjx6VYRjy+/2dUTKSWGd/b2ZGpwUOhyPqZ8uymo2dbPuWxpEaYj1/Gj333HOaPXu2li1bpn79+nVUeUhgrT13QqGQrrnmGs2ZM0fnnHNOZ5WHBBfL3z3Hjh2Tw+HQM888oxEjRuiyyy7TvHnztGTJEmZ1UlQs58+WLVs0bdo03XPPPdq4caNeeeUVVVZWaurUqZ1RKpJcZ35v5p8Bv6Zv375yOp3N/gWjpqamWfpsdMYZZ7S4fVpamk477bQOqxWJpy3nT6Nly5ZpypQpev755zVu3LiOLBMJKNZz58CBA9qwYYM2bdqkW2+9VVL4i6tlWUpLS9Orr76qSy65pFNqR/y15e+enJwcDRgwQC6XKzI2ZMgQWZalXbt2adCgQR1aMxJHW86fsrIyjRkzRnfccYck6YILLlCPHj00duxY3XvvvaxmwXF19vdmZnS+Jj09XYWFhSovL48aLy8v1+jRo1vcZ9SoUc22f/XVV1VUVKSuXbt2WK1IPG05f6TwTM7111+vZ599lvXNKSrWcycrK0vvvvuu3nnnnchj6tSpGjx4sN555x2NHDmys0pHAmjL3z1jxozRnj179MUXX0TG/v73v6tLly4aOHBgh9aLxNKW8+fgwYPq0iX6K6TT6ZTU9K/zQEs6/Xtzh9ziIIktXbrU6tq1q7Vo0SJry5Yt1vTp060ePXpYO3bssCzLsu666y5r8uTJke23b99ude/e3fL5fNaWLVusRYsWWV27drVeeOGFeH0ExFGs58+zzz5rpaWlWY8++qhVXV0deXz++efx+giIk1jPnX/EXddSW6znz4EDB6yBAwdaV111lbV582Zr1apV1qBBg6ybbropXh8BcRTr+fPkk09aaWlp1oIFC6xt27ZZa9eutYqKiqwRI0bE6yMgTg4cOGBt2rTJ2rRpkyXJmjdvnrVp0ybr448/tiwr/t+bCTotePTRR628vDwrPT3dGj58uLVq1arIa9ddd5118cUXR21fUVFhffvb37bS09Ot/Px8a+HChZ1cMRJJLOfPxRdfbElq9rjuuus6v3DEXax/93wdQQexnj/vv/++NW7cOKtbt27WwIEDrdLSUuvgwYOdXDUSRaznz8MPP2x985vftLp162bl5ORY//qv/2rt2rWrk6tGvAWDwRN+j4n392aHZTHHCAAAAMBeuEYHAAAAgO0QdAAAAADYDkEHAAAAgO0QdAAAAADYDkEHAAAAgO0QdAAAAADYDkEHAAAAgO0QdAAAAADYDkEHAAAAgO0QdAAAAADYDkEHAAAAgO38PzUOv4hLfafPAAAAAElFTkSuQmCC",195      "text/plain": [196       "<Figure size 1000x700 with 1 Axes>"197      ]198     },199     "metadata": {},200     "output_type": "display_data"201    }202   ],203   "source": [204    "plot_predictions(); # 預設最理想狀況"205   ]206  },207  {208   "cell_type": "code",209   "execution_count": 10,210   "id": "c552bbc9-f3bb-40e0-9eb4-707b96102777",211   "metadata": {},212   "outputs": [],213   "source": [214    "# Create a Linear Regression model class\n",215    "class LinearRegressionModel(nn.Module): # <- almost everything in PyTorch is a nn.Module (think of this as neural network lego blocks)\n",216    "    def __init__(self):\n",217    "        super().__init__()\n",218    "        self.weights = nn.Parameter(torch.randn(1, # <- start with random weights (this will get adjusted as the model learns)\n",219    "                       dtype=torch.float), # <- PyTorch loves float32 by default\n",220    "                       requires_grad=True) # <- can we update this value with gradient descent?)\n",221    "\n",222    "        self.bias = nn.Parameter(torch.randn(1, # <- start with random bias (this will get adjusted as the model learns)\n",223    "                      dtype=torch.float), # <- PyTorch loves float32 by default\n",224    "                      requires_grad=True) # <- can we update this value with gradient descent?))\n",225    "\n",226    "    # Forward defines the computation in the model\n",227    "    def forward(self, x: torch.Tensor) -> torch.Tensor: # <- \"x\" is the input data (e.g. training/testing features)\n",228    "        return self.weights * x + self.bias # <- this is the linear regression formula (y = m*x + b)"229   ]230  },231  {232   "cell_type": "code",233   "execution_count": 12,234   "id": "39fa2ec7-095e-4f7f-8efb-9ded8d831480",235   "metadata": {},236   "outputs": [],237   "source": [238    "class LinearRegressionModel(nn.Module): #繼承類別nn.Module\n",239    "    def __init__(self):\n",240    "        super().__init__()    #繼承類別nn.Module的初始化並使用\n",241    "        self.weights = nn.Parameter(torch.randn(1,\n",242    "                       dtype=torch.float),\n",243    "                       requires_grad=True)\n",244    "\n",245    "        self.bias = nn.Parameter(torch.randn(1,\n",246    "                      dtype=torch.float),\n",247    "                      requires_grad=True)\n",248    "    # forward方法是使用nn.Module時要自行建立 (類似C#的interface?)\n",249    "    def forward(self, x: torch.Tensor) -> torch.Tensor: # -> torch.Tensor這並非必要 (表示回傳值的型態類別)\n",250    "        return self.weights * x + self.bias"251   ]252  },253  {254   "cell_type": "code",255   "execution_count": 15,256   "id": "c66d0bc3-7ed8-471e-9e6b-e2eacf072701",257   "metadata": {},258   "outputs": [259    {260     "name": "stdout",261     "output_type": "stream",262     "text": [263      "Weights: -0.866369903087616\n",264      "Bias: -0.3100593686103821\n",265      "tensor([-1.1764, -2.0428, -2.9092], grad_fn=<AddBackward0>)\n"266     ]267    }268   ],269   "source": [270    "model = LinearRegressionModel()\n",271    "x = torch.tensor([1.0, 2.0, 3.0])\n",272    "output = model(x)  # 等同於 model.forward(x)\n",273    "print(\"Weights:\", model.weights.item())\n",274    "print(\"Bias:\", model.bias.item())\n",275    "print(output)      # 這會輸出 forward 的結果"276   ]277  },278  {279   "cell_type": "code",280   "execution_count": 20,281   "id": "2d203a3b-c03a-40b3-b178-37d3e868a354",282   "metadata": {},283   "outputs": [284    {285     "data": {286      "text/plain": [287       "[Parameter containing:\n",288       " tensor([0.3367], requires_grad=True),\n",289       " Parameter containing:\n",290       " tensor([0.1288], requires_grad=True)]"291      ]292     },293     "execution_count": 20,294     "metadata": {},295     "output_type": "execute_result"296    }297   ],298   "source": [299    "# Set manual seed since nn.Parameter are randomly initialized\n",300    "torch.manual_seed(42)\n",301    "\n",302    "# Create an instance of the model (this is a subclass of nn.Module that contains nn.Parameter(s))\n",303    "model_0 = LinearRegressionModel()\n",304    "\n",305    "# Check the nn.Parameter(s) within the nn.Module subclass we created\n",306    "list(model_0.parameters())"307   ]308  },309  {310   "cell_type": "code",311   "execution_count": 17,312   "id": "bb48f9e7-a6da-40b1-8efb-6603baa80040",313   "metadata": {},314   "outputs": [315    {316     "data": {317      "text/plain": [318       "OrderedDict([('weights', tensor([0.3367])), ('bias', tensor([0.1288]))])"319      ]320     },321     "execution_count": 17,322     "metadata": {},323     "output_type": "execute_result"324    }325   ],326   "source": [327    "# List named parameters\n",328    "model_0.state_dict()"329   ]330  },331  {332   "cell_type": "code",333   "execution_count": 21,334   "id": "0659243d-2ded-4694-bc20-f1d68b60e2b0",335   "metadata": {},336   "outputs": [],337   "source": [338    "# Make predictions with model\n",339    "# with 語句是一種上下文管理器,表示在這段程式碼塊內部會啟用 torch.inference_mode(),一旦退出這段程式碼塊,inference_mode 的效果就會結束。\n",340    "with torch.inference_mode():\n",341    "    y_preds = model_0(X_test)"342   ]343  },344  {345   "cell_type": "code",346   "execution_count": 22,347   "id": "770fd457-d1f4-40fa-a2a9-55cad32c0b92",348   "metadata": {},349   "outputs": [350    {351     "data": {352      "text/plain": [353       "tensor([[0.3982],\n",354       "        [0.4049],\n",355       "        [0.4116],\n",356       "        [0.4184],\n",357       "        [0.4251],\n",358       "        [0.4318],\n",359       "        [0.4386],\n",360       "        [0.4453],\n",361       "        [0.4520],\n",362       "        [0.4588]])"363      ]364     },365     "execution_count": 22,366     "metadata": {},367     "output_type": "execute_result"368    }369   ],370   "source": [371    "y_preds"372   ]373  },374  {375   "cell_type": "code",376   "execution_count": 23,377   "id": "0400c895-8071-4d2d-afb5-1a944cdb2ffa",378   "metadata": {},379   "outputs": [380    {381     "name": "stdout",382     "output_type": "stream",383     "text": [384      "Number of testing samples: 10\n",385      "Number of predictions made: 10\n",386      "Predicted values:\n",387      "tensor([[0.3982],\n",388      "        [0.4049],\n",389      "        [0.4116],\n",390      "        [0.4184],\n",391      "        [0.4251],\n",392      "        [0.4318],\n",393      "        [0.4386],\n",394      "        [0.4453],\n",395      "        [0.4520],\n",396      "        [0.4588]])\n"397     ]398    }399   ],400   "source": [401    "# Check the predictions\n",402    "print(f\"Number of testing samples: {len(X_test)}\")\n",403    "print(f\"Number of predictions made: {len(y_preds)}\")\n",404    "print(f\"Predicted values:\\n{y_preds}\")"405   ]406  },407  {408   "cell_type": "markdown",409   "id": "714fe43e-9985-43ce-9ca6-e582be2bede6",410   "metadata": {},411   "source": [412    "## Train model\n",413    "MAE (mean absolute error) loss function for regression problems (predicting a number) \n",414    " => loss function and optimizer"415   ]416  },417  {418   "cell_type": "code",419   "execution_count": 25,420   "id": "9760d31e-e967-473f-a0a6-fc60a0f28926",421   "metadata": {},422   "outputs": [],423   "source": [424    "# Create the loss function\n",425    "loss_fn = nn.L1Loss() # MAE loss is same as L1Loss\n",426    "\n",427    "# Create the optimizer\n",428    "optimizer = torch.optim.SGD(params=model_0.parameters(), # parameters of target model to optimize\n",429    "                            lr=0.01) # learning rate (how much the optimizer should change parameters at each step, higher=more (less stable), lower=less (might take a long time))"430   ]431  },432  {433   "cell_type": "code",434   "execution_count": 26,435   "id": "4548a3b7-4ed4-4339-8132-8d1edd7d6629",436   "metadata": {},437   "outputs": [438    {439     "name": "stdout",440     "output_type": "stream",441     "text": [442      "Epoch: 0 | MAE Train Loss: 0.31288138031959534 | MAE Test Loss: 0.48106518387794495 \n",443      "Epoch: 10 | MAE Train Loss: 0.1976713240146637 | MAE Test Loss: 0.3463551998138428 \n",444      "Epoch: 20 | MAE Train Loss: 0.08908725529909134 | MAE Test Loss: 0.21729660034179688 \n",445      "Epoch: 30 | MAE Train Loss: 0.053148526698350906 | MAE Test Loss: 0.14464017748832703 \n",446      "Epoch: 40 | MAE Train Loss: 0.04543796554207802 | MAE Test Loss: 0.11360953003168106 \n",447      "Epoch: 50 | MAE Train Loss: 0.04167863354086876 | MAE Test Loss: 0.09919948130846024 \n",448      "Epoch: 60 | MAE Train Loss: 0.03818932920694351 | MAE Test Loss: 0.08886633068323135 \n",449      "Epoch: 70 | MAE Train Loss: 0.03476089984178543 | MAE Test Loss: 0.0805937647819519 \n",450      "Epoch: 80 | MAE Train Loss: 0.03132382780313492 | MAE Test Loss: 0.07232122868299484 \n",451      "Epoch: 90 | MAE Train Loss: 0.02788739837706089 | MAE Test Loss: 0.06473556160926819 \n"452     ]453    }454   ],455   "source": [456    "torch.manual_seed(42)\n",457    "\n",458    "# Set the number of epochs (how many times the model will pass over the training data)\n",459    "epochs = 100\n",460    "\n",461    "# Create empty loss lists to track values\n",462    "train_loss_values = []\n",463    "test_loss_values = []\n",464    "epoch_count = []\n",465    "\n",466    "for epoch in range(epochs):\n",467    "    ### Training\n",468    "\n",469    "    # Put model in training mode (this is the default state of a model)\n",470    "    model_0.train()\n",471    "\n",472    "    # 1. Forward pass on train data using the forward() method inside \n",473    "    y_pred = model_0(X_train)\n",474    "    # print(y_pred)\n",475    "\n",476    "    # 2. Calculate the loss (how different are our models predictions to the ground truth)\n",477    "    loss = loss_fn(y_pred, y_train)\n",478    "\n",479    "    # 3. Zero grad of the optimizer\n",480    "    optimizer.zero_grad()\n",481    "\n",482    "    # 4. Loss backwards\n",483    "    loss.backward()\n",484    "\n",485    "    # 5. Progress the optimizer\n",486    "    optimizer.step()\n",487    "\n",488    "    ### Testing\n",489    "\n",490    "    # Put the model in evaluation mode\n",491    "    model_0.eval()\n",492    "\n",493    "    with torch.inference_mode():\n",494    "      # 1. Forward pass on test data\n",495    "      test_pred = model_0(X_test)\n",496    "\n",497    "      # 2. Caculate loss on test data\n",498    "      test_loss = loss_fn(test_pred, y_test.type(torch.float)) # predictions come in torch.float datatype, so comparisons need to be done with tensors of the same type\n",499    "\n",500    "      # Print out what's happening\n",501    "      if epoch % 10 == 0:\n",502    "            epoch_count.append(epoch)\n",503    "            train_loss_values.append(loss.detach().numpy())\n",504    "            test_loss_values.append(test_loss.detach().numpy())\n",505    "            print(f\"Epoch: {epoch} | MAE Train Loss: {loss} | MAE Test Loss: {test_loss} \")"506   ]507  },508  {509   "cell_type": "markdown",510   "id": "288361ab-65a7-40c8-853f-9073fc987509",511   "metadata": {},512   "source": [513    "## Create Full Training Model Code"514   ]515  },516  {517   "cell_type": "code",518   "execution_count": 58,519   "id": "bb6dd8cd-3172-487f-a504-7777cc9436de",520   "metadata": {},521   "outputs": [522    {523     "name": "stdout",524     "output_type": "stream",525     "text": [526      "Epoch: 0 | MAE Train Loss: 0.31288138031959534 | MAE Test Loss: 0.48106518387794495 \n",527      "Epoch: 10 | MAE Train Loss: 0.1976713240146637 | MAE Test Loss: 0.3463551998138428 \n",528      "Epoch: 20 | MAE Train Loss: 0.08908725529909134 | MAE Test Loss: 0.21729660034179688 \n",529      "Epoch: 30 | MAE Train Loss: 0.053148526698350906 | MAE Test Loss: 0.14464017748832703 \n",530      "Epoch: 40 | MAE Train Loss: 0.04543796554207802 | MAE Test Loss: 0.11360953003168106 \n",531      "Epoch: 50 | MAE Train Loss: 0.04167863354086876 | MAE Test Loss: 0.09919948130846024 \n",532      "Epoch: 60 | MAE Train Loss: 0.03818932920694351 | MAE Test Loss: 0.08886633068323135 \n",533      "Epoch: 70 | MAE Train Loss: 0.03476089984178543 | MAE Test Loss: 0.0805937647819519 \n",534      "Epoch: 80 | MAE Train Loss: 0.03132382780313492 | MAE Test Loss: 0.07232122868299484 \n",535      "Epoch: 90 | MAE Train Loss: 0.02788739837706089 | MAE Test Loss: 0.06473556160926819 \n"536     ]537    }538   ],539   "source": [540    "import torch\n",541    "from torch import nn\n",542    "\n",543    "class LinearRegressionModel(nn.Module): \n",544    "    def __init__(self):\n",545    "        super().__init__()   \n",546    "        self.weights = nn.Parameter(torch.randn(1,\n",547    "                       dtype=torch.float),\n",548    "                       requires_grad=True)\n",549    "\n",550    "        self.bias = nn.Parameter(torch.randn(1,\n",551    "                      dtype=torch.float),\n",552    "                      requires_grad=True)\n",553    "\n",554    "    def forward(self, x: torch.Tensor) -> torch.Tensor:\n",555    "        return self.weights * x + self.bias\n",556    "\n",557    "torch.manual_seed(42)\n",558    "\n",559    "model_0 = LinearRegressionModel()\n",560    "\n",561    "loss_fn = nn.L1Loss() \n",562    "optimizer = torch.optim.SGD(params=model_0.parameters(),\n",563    "                            lr=0.01)\n",564    "\n",565    "epochs = 100\n",566    "# epochs = 190\n",567    "train_loss_values = []\n",568    "test_loss_values = []\n",569    "epoch_count = []\n",570    "\n",571    "for epoch in range(epochs):\n",572    "    model_0.train()\n",573    "    y_pred = model_0(X_train)\n",574    "    loss = loss_fn(y_pred, y_train)\n",575    "    optimizer.zero_grad()\n",576    "    loss.backward()\n",577    "    optimizer.step()\n",578    "    model_0.eval()\n",579    "    with torch.inference_mode():\n",580    "      test_pred = model_0(X_test)\n",581    "      test_loss = loss_fn(test_pred, y_test.type(torch.float)) \n",582    "      if epoch % 10 == 0:\n",583    "            epoch_count.append(epoch)\n",584    "            train_loss_values.append(loss.detach().numpy())\n",585    "            test_loss_values.append(test_loss.detach().numpy())\n",586    "            print(f\"Epoch: {epoch} | MAE Train Loss: {loss} | MAE Test Loss: {test_loss} \")"587   ]588  },589  {590   "cell_type": "code",591   "execution_count": 59,592   "id": "0a0e6738-406e-4195-9907-c73c20bfa79c",593   "metadata": {},594   "outputs": [595    {596     "data": {597      "image/png": "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",598      "text/plain": [599       "<Figure size 640x480 with 1 Axes>"600      ]601     },602     "metadata": {},603     "output_type": "display_data"604    }605   ],606   "source": [607    "# Plot the loss curves\n",608    "plt.plot(epoch_count, train_loss_values, label=\"Train loss\")\n",609    "plt.plot(epoch_count, test_loss_values, label=\"Test loss\")\n",610    "plt.title(\"Training and test loss curves\")\n",611    "plt.ylabel(\"Loss\")\n",612    "plt.xlabel(\"Epochs\")\n",613    "plt.legend();"614   ]615  },616  {617   "cell_type": "code",618   "execution_count": 60,619   "id": "64f2c722-8e40-4e49-a8f2-f994f788fd7b",620   "metadata": {},621   "outputs": [622    {623     "name": "stdout",624     "output_type": "stream",625     "text": [626      "The model learned the following values for weights and bias:\n",627      "OrderedDict({'weights': tensor([0.5784]), 'bias': tensor([0.3513])})\n",628      "\n",629      "And the original values for weights and bias are:\n",630      "weights: 0.7, bias: 0.3\n"631     ]632    }633   ],634   "source": [635    "# Find our model's learned parameters\n",636    "print(\"The model learned the following values for weights and bias:\")\n",637    "print(model_0.state_dict())\n",638    "print(\"\\nAnd the original values for weights and bias are:\")\n",639    "print(f\"weights: {weight}, bias: {bias}\")"640   ]641  },642  {643   "cell_type": "code",644   "execution_count": 61,645   "id": "7c0ba150-7dd7-4bcf-9a23-47df80b3af94",646   "metadata": {},647   "outputs": [648    {649     "data": {650      "text/plain": [651       "tensor([[0.8141],\n",652       "        [0.8256],\n",653       "        [0.8372],\n",654       "        [0.8488],\n",655       "        [0.8603],\n",656       "        [0.8719],\n",657       "        [0.8835],\n",658       "        [0.8950],\n",659       "        [0.9066],\n",660       "        [0.9182]])"661      ]662     },663     "execution_count": 61,664     "metadata": {},665     "output_type": "execute_result"666    }667   ],668   "source": [669    "# 1. Set the model in evaluation mode\n",670    "model_0.eval()\n",671    "\n",672    "# 2. Setup the inference mode context manager\n",673    "with torch.inference_mode():\n",674    "  # 3. Make sure the calculations are done with the model and data on the same device\n",675    "  # in our case, we haven't setup device-agnostic code yet so our data and model are\n",676    "  # on the CPU by default.\n",677    "  # model_0.to(device)\n",678    "  # X_test = X_test.to(device)\n",679    "  y_preds = model_0(X_test)\n",680    "y_preds"681   ]682  },683  {684   "cell_type": "code",685   "execution_count": 63,686   "id": "3fc2c6e2-2750-4b93-89e8-9d30c175fd1b",687   "metadata": {},688   "outputs": [689    {690     "data": {691      "image/png": "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ffvtt3r88cfD+r1t3LhR11xzjSQpMzNTHTp0UNOmTWWz2fTGG2/oo48+Cut4AAAA1eXu5Jb3Jq9y9+bKme6MmWt0CDrV4PMFQo7fH3jOzY29oFNZ09AXXnhB+fn5evDBBzVt2rSQ1x5++GF5vd66KK9aSm8v+NVXX1X4+qFDh6p8rNJwVVhYqLS0tLMe54MPPtCbb76pQYMG6e233w5ZwrZp0yY9/vjjVX5vSXrooYdUUlKi9evX68orrwx5bdOmTcEZJwAAgLrg7uSOmYBTiqVr1eBylYUcv1/6yZ2VY9ru3bslSe4Kktu6devqupywdOrUSQkJCdq6datOnDgR8pppmtq0aVOVj9WtWzdJFX/misZKf2/XXXdduet0Kvu92e32Sme1du/erRYtWpQLOceOHdO//vWvs38AAACAeo6gUw1ud2C52oQJsbls7UxKZy/Wr18fMv7yyy9r5cqVkSipyhISEnTjjTfq4MGDeuKJJ0JeW7JkSaW3ha7IyJEjZbfbNXfuXBUWFgbHi4uL9eCDD5bbvrLf2/bt25WdnV3he7Ro0UKHDx+usC9PWlqavvnmG23fvj045vf7dc8991Q6YwUAAIAyLF2rJrfbWgGn1KhRozR79mzdfffd8vl8SktL0//93//p3Xff1Q033KAVK1ZEusQzys7O1rvvvqt7771XPp9Pl112mXbt2qW33npLv/zlL7Vq1So1aHD2fH/RRRfpgQce0PTp03XppZdq+PDhiouL0/Lly3XJJZeUu2Ncr1691KtXL/3tb39TQUGBrrjiCuXn58swDF133XUVNje95pprtGXLFg0dOlT9+vUL9i666qqrdPfdd+udd97RVVddpeHDhysxMVG5ubk6cOCAnE5nWE1PAQAA6iNmdBCiXbt2WrNmjQYMGKB3331XzzzzjEpKSvTOO+9o6NChkS7vrFJTU/X+++/r17/+tTZs2KB58+apsLBQ77zzji666CJJZdfynM0DDzyg5557Ti1bttQzzzyjV199VcOHD9err75ablu73a633npLt956q3bv3q2cnBzt2LFDc+bM0SOPPFLh8e+//37ddttt2r59u2bOnKmpU6cGb0H9q1/9Sq+99pouuOACvfjii3r55ZfVuXNnbd68udw1QwAAACjPZpqmGekizqa4uFgOh0NFRUVn/JL6ww8/KC8vTxkZGUpMTKzDChELrrrqKr3//vsqKipS06ZNI11OrePvAQAA/Jixy5AvzydXhivmbizwY1XNBszowHIKCgrKjb300kvasGGDBg4cWC9CDgAAwI8Zuwx5lnqUszlHnqUeGbtitBlkGLhGB5bTtWtXXX755fr5z38e7P+Tm5urZs2aac6cOZEuDwAAoM758nzBhp92m125e3NjelanKpjRgeWMHz9ehYWFWrJkiZ588knt2rVLI0eO1ObNm3XJJZdEujwAAIA658pwBUOO3/TLme6MdEm1jmt0AIvi7wEAAPyYsctQ7t5cOdOdMT2bU9VswNI1AAAAoB5wd3LHdMAJF0vXAAAAAFgOQQcAAACA5RB0AAAAAFgOQQcAAACA5RB0AAAAgBhi7DKUtSqrXjT9PBcEHQAAACBGGLsMeZZ6lLM5R56lHsLOGRB0AAAAgBjhy/MFm37abXbl7s2NdElRi6ADAAAAxAhXhisYcvymX850Z6RLiloEHdSJMWPGyGazae/evZEu5awWL14sm82mxYsXR7oUAACAEO5Obnlv8mpC7wny3uStVw1Aw0XQsQibzRbWo6YRDkLl5ubKZrNpxowZkS4FAABYjLuTW3MHzSXknEVcpAtAzZg+fXq5sZkzZ8rhcGjixIl1X9BPZGdna8qUKWrbtm2kSwEAAEA9QNCxiIpmDmbOnKnmzZtHxaxCSkqKUlJSIl0GAAAA6gmWrtVDpmlq4cKFuvLKK5WUlKTGjRurZ8+eWrhwYbltf/jhB/35z39Wt27d5HA41LRpU1144YX6zW9+o48//lhS4PqbW265RZJ0yy23VLhErqJrdH68vOtf//qXBg0apGbNmsnhcOj666+v9HqeFStWqGfPnmrUqJGSk5N122236ZtvvlF6errS09Or/Hv4+uuvNX78eCUnJ6tx48b6xS9+oddff73S7RcuXCiPx6P09HQlJiaqRYsWGjRokHw+X8h2M2bMkMvlkhQImz/+fZR+pn//+9+aPHmyunfvrpYtWyoxMVEdO3bUlClT9N1331X5MwAAAKBizOjUM6Zp6ne/+51efvlldezYUSNHjlR8fLxWr16tsWPHaseOHZozZ05w+9GjR+tvf/ubLr30Ut1yyy1KSEhQfn6+fD6fBg0apEsuuUTDhg3Tt99+K6/XK4/Ho8suuyysmrZs2aJHH31UTqdTt99+u7Zt26Y33nhDH3/8sT755BMlJiYGt124cKHGjh2r5s2b6+abb5bD4dDKlSt17bXX6uTJk2rYsGGV3vPYsWNyOp36+OOP1adPH/Xv31/79u3TiBEjlJmZWeE+d955p7p166aBAwfqvPPO04EDB/TGG29o4MCBWrFihTwejyTJ6XRq7969+stf/qL+/fvL6XQGj9G8eXNJgbD2wgsvyOVyyel06vTp09q0aZNmz56tNWvWaO3atVX+LAAAAKiAGQOKiopMSWZRUdEZtzt+/Li5Y8cO8/jx43VUWXSTZKalpYWMPfvss6Ykc+zYsebJkyeD4yUlJebQoUNNSeaWLVtM0zTNb7/91rTZbGbPnj3NU6dOhRzn1KlT5jfffBP8edGiRaYkc9GiRRXWMnr0aFOSmZeXFxzz+XymJFOSuXTp0pDtR40aZUoyX3nlleDYN998YzZt2tRs1qyZuXv37uD4yZMnzYEDB1b4eSszffp0U5J52223hYz/4x//CNb008+yZ8+ecsf58ssvzTZt2pgdOnQIGS/9bNOnT6/w/ffv32+WlJSUG585c6YpyXzxxRer9DnOhL8HAACil/dTrznx7xNN76feSJcSc6qaDVi6Vk3GLkNZq7Jirhvtk08+qSZNmujJJ59UXFzZhF58fLweeughSdIrr7wiKXAnN9M0lZCQILvdHnIcu90enJ04V1dffbVGjBgRMnbrrbdKkj744IPgmNfr1Xfffadx48bpggsuCI7HxcXpj3/8Y1jvuWTJEsXHx2vWrFkh45mZmRowYECF+2RkZJQbS0lJ0X/8x3/os88+0xdffFHl92/btq3i4+PLjd91112SpHfffbfKxwIAALHF2GXIs9SjnM058iz1xNz3yVjB0rVqKD057Ta75v3vvJi5h/mxY8f08ccfq02bNnr44YfLvX7y5ElJ0qeffipJSkpK0i9/+UutWrVK3bt314033qh+/fqpd+/eFX5Jr67u3buXG2vXrp0k6dtvvw2OffTRR5Kkvn37ltu+V69eIcHtTI4ePaq8vDz9/Oc/1/nnn1/u9X79+umf//xnufE9e/YoOztb7733ng4cOKCSkpKQ17/88kulpaVVqQbTNLVo0SItXrxYn3zyiYqKinT69OmQYwEAAGvy5fmCDT/tNrty9+bGxHfJWEPQqYZYPTm/+eYbmaapAwcOaObMmZVu9/333wf/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mSqrp3S8dLvqsNlsGjdunLZs2aKvvvpKr7/+um644QYZhqHrrrsuJBQBAICa48pwBUOO3/TLme6MdEmIsGr9b/Offjk2TbPSL8z333+/Bg8erCuuuEINGzaUx+PRmDFjJKncdSGlpk6dqqKiouBj37591Smz9tSDNY69e/eWVLaE7Wy6desmSVq3bl251yoaq0yvXr1UUlKiNWvWnHXb0vOnquEhKSlJF1xwgT7//HMdOHCg3Oul73nZZZdVud4zadmypYYNG6Zly5bpmmuu0c6dO/X555/XyLEBAEAodye3vDd5NaH3BJatQVKYQadVq1ay2+3lZm8KCwsrXQ7UqFEjLVy4UMeOHdPevXuVn5+v9PR0NWvWrMJlTpKUkJCgpKSkkEfUcbuluXMtGXIk6Y477lBcXJzuvvvuCoPmt99+q23btgV/vvnmmyVJs2bN0vfffx8cP3DggB5//PEqv++dd94pKXDxf+nyuVKnTp0KmY0pvUnC/v37q3z80aNH6+TJk5o6dWrIjNQnn3yiRYsWyeFwnNMtoP/xj3/o1KlTIWMnT54MfpZGjRpV+9gAAODM3J3cmjtorvVDTpTfFCtahHWNTnx8vHr06KHVq1fr+uuvD46vXr1aHo/njPs2bNgwePH20qVL9atf/apWrsNAzejatavmz5+v//zP/1SnTp00ZMgQXXjhhcEL+tesWaMxY8bo6aeflhS4kP+WW27RokWLdMkll+j6669XSUmJli1bpiuuuEJvvfVWld53yJAhuueeezRnzhx16NBB119/vVq3bq0DBw7on//8p+655x5NnDhRknTNNddozpw5uv322/XrX/9aTZo0Ufv27TVy5MhKjz958mS9/fbb+utf/6qdO3dqwIAB+uqrr7Rs2TKdPHlSS5YsUbNmzar9exsxYoQaN26sq666SmlpaTp58qRWr16tHTt2aMSIEWrfvn21jw0AABALN8WKFmHfdW3SpEkaNWqUevbsqT59+ujZZ59Vfn6+xo8fLymw7OzAgQPB2w3/+9//1ubNm9W7d2998803mjt3rj755JNgV3tEr9tuu02XXXaZ5s6dq7Vr18owDDkcDrVv315ZWVkaPXp0yPbPPfecOnbsqOeee05PPvmk2rVrp0mTJmn48OFVDjqS9Oijj6pPnz568skn9dprr+mHH35QSkqKrrnmGl177bXB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AKLB0aNH5XA4Kn3dZp4tCkWB06dP68svv1SzZs1ks9kiWktxcbFSU1O1b98+JSUlRbQWxB7OH5wLzh9UF+cOzgXnD85FbZw/pmnq6NGjatOmjRo0qPxKnJiY0WnQoIHatWsX6TJCJCUl8ceOauP8wbng/EF1ce7gXHD+4FzU9PlzppmcUtyMAAAAAIDlEHQAAAAAWA5BJ0wJCQmaPn26EhISIl0KYhDnD84F5w+qi3MH54LzB+cikudPTNyMAAAAAADCwYwOAAAAAMsh6AAAAACwHIIOAAAAAMsh6AAAAACwHIIOAAAAAMsh6FRg/vz5ysjIUGJionr06KF169adcfs1a9aoR48eSkxM1AUXXKCnn366jipFNArn/FmxYoWuvfZanXfeeUpKSlKfPn30j3/8ow6rRTQJ9789pTZs2KC4uDhddtlltVsgolq4509JSYmmTZumtLQ0JSQk6MILL9TChQvrqFpEm3DPn5deekndunVT48aNlZKSoltuuUVHjhypo2oRLdauXauhQ4eqTZs2stlseuONN866T11+bybo/MSyZcs0ceJETZs2Tdu2bVO/fv00ePBg5efnV7h9Xl6ehgwZon79+mnbtm36n//5H02YMEHLly+v48oRDcI9f9auXatrr71WK1eu1NatW+VyuTR06FBt27atjitHpIV77pQqKirSzTffrAEDBtRRpYhG1Tl/hg8frn/+85964YUXtGvXLr3yyivq3LlzHVaNaBHu+bN+/XrdfPPNGjt2rLZv365XX31VH3zwgcaNG1fHlSPSvv/+e3Xr1k1PPvlklbav8+/NJkL06tXLHD9+fMhY586dzSlTplS4/eTJk83OnTuHjN1+++3mFVdcUWs1InqFe/5U5Oc//7k5c+bMmi4NUa66586IESPM++67z5w+fbrZrVu3WqwQ0Szc8+fvf/+76XA4zCNHjtRFeYhy4Z4/jz76qHnBBReEjD3xxBNmu3btaq1GRD9J5uuvv37Gber6ezMzOj9y4sQJbd26VZmZmSHjmZmZ2rhxY4X7vP/+++W2HzRokLZs2aKTJ0/WWq2IPtU5f37q9OnTOnr0qFq0aFEbJSJKVffcWbRokXbv3q3p06fXdomIYtU5fwzDUM+ePfXII4+obdu26tixo+655x4dP368LkpGFKnO+dO3b1/t379fK1eulGmaOnTokF577TVdd911dVEyYlhdf2+Oq/EjxrDDhw/L7/crOTk5ZDw5OVkHDx6scJ+DBw9WuP2pU6d0+PBhpaSk1Fq9iC7VOX9+6s9//rO+//57DR8+vDZKRJSqzrnz2WefacqUKVq3bp3i4vhPeX1WnfNnz549Wr9+vRITE/X666/r8OHDuuOOO/T1119znU49U53zp2/fvnrppZc0YsQI/fDDDzp16pTcbrdycnLqomTEsLr+3syMTgVsNlvIz6Zplhs72/YVjaN+CPf8KfXKK69oxowZWrZsmVq3bl1b5SGKVfXc8fv9GjlypGbOnKmOHTvWVXmIcuH8t+f06dOy2Wx66aWX1KtXLw0ZMkRz587V4sWLmdWpp8I5f3bs2KEJEybogQce0NatW7Vq1Srl5eVp/PjxdVEqYlxdfm/mfwP+SKtWrWS328v9H4zCwsJy6bPU+eefX+H2cXFxatmyZa3ViuhTnfOn1LJlyzR27Fi9+uqrGjhwYG2WiSgU7rlz9OhRbdmyRdu2bdNdd90lKfDF1TRNxcXF6Z133tE111xTJ7Uj8qrz356UlBS1bdtWDocjONalSxeZpqn9+/erQ4cOtVozokd1zp/s7GxdeeWVuvfeeyVJl156qZo0aaJ+/frpwQcfZDULKlXX35uZ0fmR+Ph49ejRQ6tXrw4ZX716tfr27VvhPn369Cm3/TvvvKOePXuqYcOGtVYrok91zh8pMJMzZswYvfzyy6xvrqfCPXeSkpL08ccf68MPPww+xo8fr06dOunDDz9U796966p0RIHq/Lfnyiuv1JdffqnvvvsuOPbvf/9bDRo0ULt27Wq1XkSX6pw/x44dU4MGoV8h7Xa7pLL/Ow9UpM6/N9fKLQ5i2NKlS82GDRuaL7zwgrljxw5z4sSJZpMmTcy9e/eapmmaU6ZMMUeNGhXcfs+ePWbjxo3NrKwsc8eOHeYLL7xgNmzY0Hzttdci9REQQeGePy+//LIZFxdnPvXUU2ZBQUHw8e2330bqIyBCwj13foq7rtVv4Z4/R48eNdu1a2feeOON5vbt2801a9aYHTp0MMeNGxepj4AICvf8WbRokRkXF2fOnz/f3L17t7l+/XqzZ8+eZq9evSL1ERAhR48eNbdt22Zu27bNlGTOnTvX3LZtm/nFF1+Yphn5780EnQo89dRTZlpamhkfH292797dXLNmTfC10aNHm/379w/ZPjc317z88svN+Ph4Mz093VywYEEdV4xoEs75079/f1NSucfo0aPrvnBEXLj/7fkxgg7CPX927txpDhw40GzUqJHZrl07c9KkSeaxY8fquGpEi3DPnyeeeML8+c9/bjZq1MhMSUkxf/vb35r79++v46oRaT6f74zfYyL9vdlmmswxAgAAALAWrtEBAAAAYDkEHQAAAACWQ9ABAAAAYDkEHQAAAACWQ9ABAAAAYDkEHQAAAACWQ9ABAAAAYDkEHQAAAACWQ9ABAAAAYDkEHQAAAACWQ9ABAAAAYDn/D11pxiOOmLqMAAAAAElFTkSuQmCC",692      "text/plain": [693       "<Figure size 1000x700 with 1 Axes>"694      ]695     },696     "metadata": {},697     "output_type": "display_data"698    }699   ],700   "source": [701    "plot_predictions(predictions=y_preds)"702   ]703  },704  {705   "cell_type": "code",706   "execution_count": 64,707   "id": "f8e6a67a-5496-4cf0-b8bb-e93d8282d162",708   "metadata": {},709   "outputs": [710    {711     "name": "stdout",712     "output_type": "stream",713     "text": [714      "Saving model to: models\\01_pytorch_workflow_model_0.pth\n"715     ]716    }717   ],718   "source": [719    "from pathlib import Path\n",720    "\n",721    "# 1. Create models directory \n",722    "MODEL_PATH = Path(\"models\")\n",723    "MODEL_PATH.mkdir(parents=True, exist_ok=True)\n",724    "\n",725    "# 2. Create model save path \n",726    "MODEL_NAME = \"01_pytorch_workflow_model_0.pth\"\n",727    "MODEL_SAVE_PATH = MODEL_PATH / MODEL_NAME\n",728    "\n",729    "# 3. Save the model state dict \n",730    "print(f\"Saving model to: {MODEL_SAVE_PATH}\")\n",731    "torch.save(obj=model_0.state_dict(), # only saving the state_dict() only saves the models learned parameters\n",732    "           f=MODEL_SAVE_PATH) "733   ]734  },735  {736   "cell_type": "code",737   "execution_count": 66,738   "id": "bccb5513-b08e-4e5b-b029-8a6bac306f5b",739   "metadata": {},740   "outputs": [741    {742     "name": "stderr",743     "output_type": "stream",744     "text": [745      "C:\\Users\\User\\AppData\\Local\\Temp\\ipykernel_10048\\1296048670.py:5: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",746      "  loaded_model_0.load_state_dict(torch.load(f=MODEL_SAVE_PATH))\n"747     ]748    },749    {750     "data": {751      "text/plain": [752       "<All keys matched successfully>"753      ]754     },755     "execution_count": 66,756     "metadata": {},757     "output_type": "execute_result"758    }759   ],760   "source": [761    "# Instantiate a new instance of our model (this will be instantiated with random weights)\n",762    "loaded_model_0 = LinearRegressionModel()\n",763    "\n",764    "# Load the state_dict of our saved model (this will update the new instance of our model with trained weights)\n",765    "loaded_model_0.load_state_dict(torch.load(f=MODEL_SAVE_PATH))"766   ]767  },768  {769   "cell_type": "code",770   "execution_count": 67,771   "id": "ca3ae66b-8512-4f18-a504-b3485d7dd922",772   "metadata": {},773   "outputs": [],774   "source": [775    "# 1. Put the loaded model into evaluation mode\n",776    "loaded_model_0.eval()\n",777    "\n",778    "# 2. Use the inference mode context manager to make predictions\n",779    "with torch.inference_mode():\n",780    "    loaded_model_preds = loaded_model_0(X_test) # perform a forward pass on the test data with the loaded model"781   ]782  },783  {784   "cell_type": "code",785   "execution_count": 68,786   "id": "241284a9-85de-42c1-8eae-c0da161f5cce",787   "metadata": {},788   "outputs": [789    {790     "data": {791      "text/plain": [792       "tensor([[True],\n",793       "        [True],\n",794       "        [True],\n",795       "        [True],\n",796       "        [True],\n",797       "        [True],\n",798       "        [True],\n",799       "        [True],\n",800       "        [True],\n",801       "        [True]])"802      ]803     },804     "execution_count": 68,805     "metadata": {},806     "output_type": "execute_result"807    }808   ],809   "source": [810    "# Compare previous model predictions with loaded model predictions (these should be the same)\n",811    "y_preds == loaded_model_preds"812   ]813  },814  {815   "cell_type": "code",816   "execution_count": 69,817   "id": "da18d672-bedb-4dd8-bbe8-37096362d3ea",818   "metadata": {},819   "outputs": [820    {821     "data": {822      "text/plain": [823       "(LinearRegressionModelV2(\n",824       "   (linear_layer): Linear(in_features=1, out_features=1, bias=True)\n",825       " ),\n",826       " OrderedDict([('linear_layer.weight', tensor([[0.7645]])),\n",827       "              ('linear_layer.bias', tensor([0.8300]))]))"828      ]829     },830     "execution_count": 69,831     "metadata": {},832     "output_type": "execute_result"833    }834   ],835   "source": [836    "# 以 linear_layer 取代 nn.Parameter\n",837    "# Subclass nn.Module to make our model\n",838    "class LinearRegressionModelV2(nn.Module):\n",839    "    def __init__(self):\n",840    "        super().__init__()\n",841    "        # Use nn.Linear() for creating the model parameters\n",842    "        self.linear_layer = nn.Linear(in_features=1, \n",843    "                                      out_features=1)\n",844    "    \n",845    "    # Define the forward computation (input data x flows through nn.Linear())\n",846    "    def forward(self, x: torch.Tensor) -> torch.Tensor:\n",847    "        return self.linear_layer(x)\n",848    "\n",849    "# Set the manual seed when creating the model (this isn't always needed but is used for demonstrative purposes, try commenting it out and seeing what happens)\n",850    "torch.manual_seed(42)\n",851    "model_1 = LinearRegressionModelV2()\n",852    "model_1, model_1.state_dict()"853   ]854  },855  {856   "cell_type": "code",857   "execution_count": 71,858   "id": "06f1a2f9-b29a-46e5-b2c5-41124dd4f78b",859   "metadata": {},860   "outputs": [861    {862     "name": "stdout",863     "output_type": "stream",864     "text": [865      "Using device: cuda\n"866     ]867    }868   ],869   "source": [870    "# 檢查是否有可用的 GPU\n",871    "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",872    "print(f\"Using device: {device}\")"873   ]874  },875  {876   "cell_type": "code",877   "execution_count": 72,878   "id": "dc739a00-102b-4e2f-aff6-65447b7a7f3d",879   "metadata": {},880   "outputs": [881    {882     "data": {883      "text/plain": [884       "device(type='cuda', index=0)"885      ]886     },887     "execution_count": 72,888     "metadata": {},889     "output_type": "execute_result"890    }891   ],892   "source": [893    "# Set model to GPU if it's available, otherwise it'll default to CPU\n",894    "model_1.to(device) # the device variable was set above to be \"cuda\" if available or \"cpu\" if not\n",895    "next(model_1.parameters()).device"896   ]897  },898  {899   "cell_type": "code",900   "execution_count": 73,901   "id": "fa6d9a0f-dccb-4c56-8e65-b3a20c76ff21",902   "metadata": {},903   "outputs": [],904   "source": [905    "# Create loss function\n",906    "loss_fn = nn.L1Loss()\n",907    "\n",908    "# Create optimizer\n",909    "optimizer = torch.optim.SGD(params=model_1.parameters(), # optimize newly created model's parameters\n",910    "                            lr=0.01)"911   ]912  },913  {914   "cell_type": "code",915   "execution_count": 74,916   "id": "6f439bd9-8669-42ee-9fc3-f94f185aa941",917   "metadata": {},918   "outputs": [919    {920     "name": "stdout",921     "output_type": "stream",922     "text": [923      "Epoch: 0 | Train loss: 0.5551779866218567 | Test loss: 0.5739762187004089\n",924      "Epoch: 100 | Train loss: 0.006215683650225401 | Test loss: 0.014086711220443249\n",925      "Epoch: 200 | Train loss: 0.0012645035749301314 | Test loss: 0.013801801018416882\n",926      "Epoch: 300 | Train loss: 0.0012645035749301314 | Test loss: 0.013801801018416882\n",927      "Epoch: 400 | Train loss: 0.0012645035749301314 | Test loss: 0.013801801018416882\n",928      "Epoch: 500 | Train loss: 0.0012645035749301314 | Test loss: 0.013801801018416882\n",929      "Epoch: 600 | Train loss: 0.0012645035749301314 | Test loss: 0.013801801018416882\n",930      "Epoch: 700 | Train loss: 0.0012645035749301314 | Test loss: 0.013801801018416882\n",931      "Epoch: 800 | Train loss: 0.0012645035749301314 | Test loss: 0.013801801018416882\n",932      "Epoch: 900 | Train loss: 0.0012645035749301314 | Test loss: 0.013801801018416882\n"933     ]934    }935   ],936   "source": [937    "torch.manual_seed(42)\n",938    "\n",939    "# Set the number of epochs \n",940    "epochs = 1000 \n",941    "\n",942    "# Put data on the available device\n",943    "# Without this, error will happen (not all model/data on device)\n",944    "X_train = X_train.to(device)\n",945    "X_test = X_test.to(device)\n",946    "y_train = y_train.to(device)\n",947    "y_test = y_test.to(device)\n",948    "\n",949    "for epoch in range(epochs):\n",950    "    ### Training\n",951    "    model_1.train() # train mode is on by default after construction\n",952    "\n",953    "    # 1. Forward pass\n",954    "    y_pred = model_1(X_train)\n",955    "\n",956    "    # 2. Calculate loss\n",957    "    loss = loss_fn(y_pred, y_train)\n",958    "\n",959    "    # 3. Zero grad optimizer\n",960    "    optimizer.zero_grad()\n",961    "\n",962    "    # 4. Loss backward\n",963    "    loss.backward()\n",964    "\n",965    "    # 5. Step the optimizer\n",966    "    optimizer.step()\n",967    "\n",968    "    ### Testing\n",969    "    model_1.eval() # put the model in evaluation mode for testing (inference)\n",970    "    # 1. Forward pass\n",971    "    with torch.inference_mode():\n",972    "        test_pred = model_1(X_test)\n",973    "    \n",974    "        # 2. Calculate the loss\n",975    "        test_loss = loss_fn(test_pred, y_test)\n",976    "\n",977    "    if epoch % 100 == 0:\n",978    "        print(f\"Epoch: {epoch} | Train loss: {loss} | Test loss: {test_loss}\")"979   ]980  },981  {982   "cell_type": "code",983   "execution_count": 75,984   "id": "5c47fc3b-78e2-4c5a-a3d8-7ebb00b81413",985   "metadata": {},986   "outputs": [987    {988     "name": "stdout",989     "output_type": "stream",990     "text": [991      "The model learned the following values for weights and bias:\n",992      "OrderedDict([('linear_layer.weight', tensor([[0.6968]], device='cuda:0')),\n",993      "             ('linear_layer.bias', tensor([0.3025], device='cuda:0'))])\n",994      "\n",995      "And the original values for weights and bias are:\n",996      "weights: 0.7, bias: 0.3\n"997     ]998    }999   ],1000   "source": [1001    "# Find our model's learned parameters\n",1002    "from pprint import pprint # pprint = pretty print, see: https://docs.python.org/3/library/pprint.html \n",1003    "print(\"The model learned the following values for weights and bias:\")\n",1004    "pprint(model_1.state_dict())\n",1005    "print(\"\\nAnd the original values for weights and bias are:\")\n",1006    "print(f\"weights: {weight}, bias: {bias}\")"1007   ]1008  },1009  {1010   "cell_type": "code",1011   "execution_count": 76,1012   "id": "2a98f85c-ffec-414f-8836-a1587559eead",1013   "metadata": {},1014   "outputs": [1015    {1016     "data": {1017      "text/plain": [1018       "tensor([[0.8600],\n",1019       "        [0.8739],\n",1020       "        [0.8878],\n",1021       "        [0.9018],\n",1022       "        [0.9157],\n",1023       "        [0.9296],\n",1024       "        [0.9436],\n",1025       "        [0.9575],\n",1026       "        [0.9714],\n",1027       "        [0.9854]], device='cuda:0')"1028      ]1029     },1030     "execution_count": 76,1031     "metadata": {},1032     "output_type": "execute_result"1033    }1034   ],1035   "source": [1036    "# Turn model into evaluation mode\n",1037    "model_1.eval()\n",1038    "\n",1039    "# Make predictions on the test data\n",1040    "with torch.inference_mode():\n",1041    "    y_preds = model_1(X_test)\n",1042    "y_preds"1043   ]1044  },1045  {1046   "cell_type": "code",1047   "execution_count": 77,1048   "id": "bad9fc8c-8af0-4405-b5c8-90c49dd8f54e",1049   "metadata": {},1050   "outputs": [1051    {1052     "data": {1053      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAzoAAAJGCAYAAACTJvC6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABUTElEQVR4nO3de3yT9f3//2dI6YFDwwCpBUqpCsJE0cKogEgqUARHgn4c3dgQFJx4YpSP8gWrcphYUYZolXoExjwxBWlUZNQZzoLCqh8FdMrBAhYqqC0KFAjX74/8mhrbQlPaJrn6uN9uuWV957quvNJd9ZYn7/d1vSyGYRgCAAAAABNpFOwCAAAAAKC2EXQAAAAAmA5BBwAAAIDpEHQAAAAAmA5BBwAAAIDpEHQAAAAAmA5BBwAAAIDpRAS7gOo4ffq0vvnmGzVv3lwWiyXY5QAAAAAIEsMwdOTIEbVt21aNGlU9bxMWQeebb75RQkJCsMsAAAAAECL27t2r9u3bV/l6WASd5s2bS/J+mNjY2CBXAwAAACBYSkpKlJCQ4MsIVQmLoFO2XC02NpagAwAAAOCsl7RwMwIAAAAApkPQAQAAAGA6BB0AAAAApkPQAQAAAGA6BB0AAAAApkPQAQAAAGA6YXF76ZrweDw6efJksMsAgqJx48ayWq3BLgMAACBoTBd0DMPQgQMHVFxcLMMwgl0OEBQWi0U2m03nn3/+We8xDwAAYEYBB521a9fqscce09atW1VYWKg333xTw4cPP+M+a9as0aRJk7Rt2za1bdtWkydP1vjx42ta8xkVFxfrhx9+0HnnnaemTZvyJQ8NjmEY+umnn/Ttt98qJiZGLVq0CHZJAAAA9S7goPPTTz+pe/fuuvnmm/U///M/Z91+9+7dGjp0qG699Va99NJL2rBhg+644w6dd9551do/EIZhqKioSLGxsWrdunWtHhsIJzExMSotLVVRUZFsNhuBHwAANDgBB50hQ4ZoyJAh1d7+mWeeUYcOHTRv3jxJUteuXbVlyxbNmTOn1oOOx+ORx+NRbGxsrR4XCEexsbEqKSmRx+NRRITpVqkCAACcUZ3fde2DDz5QWlqa39jgwYO1ZcuWKm8WUFpaqpKSEr9HdZw6dUqS+FIHqPzvoOzvAgAAoCGp86Bz4MABxcXF+Y3FxcXp1KlTOnToUKX7ZGVlyWaz+R4JCQkBvSfLdAD+DgAAQMNWL310fvmFq+xuaFV9EZs6daqKi4t9j71799Z5jQAAAADMo87XeJ1//vk6cOCA31hRUZEiIiLUqlWrSveJiopSVFRUXZcGAAAAwKTqfEand+/eysvL8xtbtWqVevbsqcaNG9f126MeWCwW2e32czrG6tWrZbFYNH369Fqpqa7VxmcGAABA3Qk46Pz444/6+OOP9fHHH0vy3j76448/VkFBgSTvsrObbrrJt/348eP19ddfa9KkSdqxY4cWLFigF198Uffcc0/tfAJI8n7xDuSB4OvYsaM6duwY7DIAAABMKeCla1u2bFFqaqrv50mTJkmSRo8erUWLFqmwsNAXeiQpKSlJK1asUEZGhp5++mm1bdtWTz75ZK3fWrqhmzZtWoWxGTNmyGazaeLEiXX63jt27FCTJk3O6Ri9evXSjh076H8EAACAWmExyu4MEMJKSkpks9lUXFx8xh45x48f1+7du5WUlKTo6Oh6rDA0WSwWJSYmas+ePcEuxXQsFov69++v1atX1/gYZbM5dfX/D38PAADAjKqbDerlrmsIHXv27JHFYtGYMWP0+eef64YbblDr1q1lsVh8X7jffPNN/eEPf9BFF12kJk2ayGazqV+/flq6dGmlx6zsepUxY8b4jjl//nx17dpV0dHRSkxM1IwZM3T69Gm/7au6RqdseddPP/2kSZMmqV27doqKitJll12mN954o8rPmJ6erpYtW6pZs2bq37+/1q5dq+nTp8tisQQUTl544QV169ZN0dHRSkhI0OTJk3X8+PFKt926davuuusudevWTTabTTExMbr00kv1yCOP+PWMKvv/4Ouvv9bXX3/tt6Sw7POfOHFC2dnZGjx4sBISEhQVFaU2bdrohhtuUH5+frXrBwAAaKjorNlAffXVV7ryyit1ySWXaPTo0fruu+8UGRkpyXudVWRkpK666irFx8fr22+/lcvl0o033qgnn3xSd999d7Xf595779Xq1av129/+VmlpaVq+fLmmT5+uEydOaNasWdU6xsmTJ5WWlqbvvvtON9xwg44eParXXntNI0aM0MqVK/0a0u7fv199+vRRYWGhhg4dqu7du+uLL75QWlqa35LL6vjrX/+qBx98UHFxcbr11lvVuHFjLVmyRDt27Kh0++eff15vvfWWrr76ag0dOlRHjx7V6tWrNXXqVH300Ue+oNiiRQtNmzZN8+bNkyS/pYVlgfG7777TxIkT1a9fPw0dOlS/+tWvtGvXLrlcLr377rtau3atfvOb3wT0eQAAAGpqc06mjq96V9FpQ5Rye/W+wwWdEQaKi4sNSUZxcfEZtzt27Jixfft249ixY/VUWWiTZCQmJvqN7d6925BkSDIeeOCBSvfbuXNnhbEjR44Yl156qWGz2Yyffvqpwvv079/fb2z06NGGJCMpKcn45ptvfOPffvut0aJFC6N58+ZGaWmpb9ztdhuSjGnTpvkdJzEx0ZBkOJ1Ov+3fe+89Q5IxePBgv+3/9Kc/GZKMxx57zG984cKFvs/tdrsr/dw/9+WXXxoRERFGu3btjIMHD/rGi4uLjYsvvrjSz7xnzx7j1KlTfmOnT582brnlFkOSsX79+gqf7Zf//5Q5fvy4sW/fvgrjn332mdGsWTNj4MCBZ/0M/D0AAIDasGn+fYYhGSctMgzJ+3MQVTcbsHStgTr//PN1//33V/raBRdcUGGsWbNmGjNmjIqLi/XRRx9V+30eeOABxcfH+35u3bq1nE6njhw5oi+++KLax3n88cd9M06SNGDAACUmJvrVUlpaqtdff11xcXGaMGGC3/6jR49Wly5dqv1+r7zyik6dOqVJkyapTZs2vvHY2Ngqf2+JiYmyWq1+YxaLRXfeeack6b333qv2+0dFRaldu3YVxi+55BKlpqZq7dq1fsvhAAAA6srxVe/qlEWKMKRTFulY3spgl1QtBJ0acrmkjAzvczjq3r27X3D4uaKiIk2aNEldu3ZVkyZNfNeP/O///q8k6Ztvvqn2+yQnJ1cYa9++vSTphx9+qNYxWrRooaSkpEqP8/NjfPHFFyotLVXPnj0rfDaLxaLevXtXu+5PPvlEktSvX78Kr1U2Jnmvq5k7d6569eql2NhYNWrUSBaLRT169JAU2O9Nkj7++GONHDlSHTp0UGRkpO//h7feeksnTpzQoUOHAjoeAABATUSnDfGFnAhDihl0bbBLqhau0akBl0tyOiWrVZo3T8rNlRyOYFcVmLi4uErHv/vuO/3mN79RQUGB+vbtq4EDB6pFixayWq36+OOPlZubq9LS0mq/j81mqzAWEeE97TweT42PUXacn9/UoKSkRJJ03nnnVbp9VZ+5MsXFxZLkN5tztuPceOONeuutt9S5c2elp6erTZs2aty4sX744Qc98cQTAf3eNm7cqGuuuUaSlJaWpk6dOqlZs2ayWCxavny5Pvnkk4COBwAAUFMpt8/SZnlncmIGXRs21+gQdGrA7faGHI/H+7x6dfgFnaqahr744osqKCjQQw89pMzMTL/XHnnkEeXm5tZHeTVSdnvBb7/9ttLXDx48WO1jlYWroqIiJSYmnvU4H330kd566y0NHjxY77zzjt8Stk2bNumJJ56o9ntL0qxZs1RaWqr169erb9++fq9t2rTJN+MEAABQH1JunyWFScApw9K1GkhNLQ85Ho/0izsrh7WdO3dKkhyVJLd169bVdzkBufjiixUVFaWtW7fqxIkTfq8ZhqFNmzZV+1jdu3eXVPlnrmys7Pd23XXXVbhOp6rfm9VqrXJWa+fOnWrZsmWFkHP06FH95z//OfsHAAAAaOAIOjXgcHiXq02YEJ7L1s6kbPZi/fr1fuOvvPKKVqxYEYySqi0qKko33nijDhw4oCeffNLvtcWLF1d5W+jKjBw5UlarVXPnzlVRUZFvvKSkRA899FCF7av6vW3btk1ZWVmVvkfLli116NChSvvyJCYm6vvvv9e2bdt8Yx6PR/fcc0+VM1YAAAAox9K1GnI4zBVwyowaNUqzZ8/W3XffLbfbrcTERP3f//2f3nvvPd1www1atmxZsEs8o6ysLL333nu699575Xa7dfnll+uLL77Q22+/rWuvvVYrV65Uo0Znz/cXXXSRHnzwQU2bNk2XXXaZRowYoYiICC1dulSXXnpphTvG9erVS7169dI///lPFRYW6sorr1RBQYFcLpeuu+66SpubXnPNNdqyZYuGDRumfv36+XoXXXXVVbr77ru1atUqXXXVVRoxYoSio6O1evVq7d+/X3a7PaCmpwAAAA0RMzrw0759e61Zs0YDBgzQe++9p2effValpaVatWqVhg0bFuzyziohIUEffPCBfve732nDhg2aN2+eioqKtGrVKl100UWSyq/lOZsHH3xQzz//vFq1aqVnn31Wr7/+ukaMGKHXX3+9wrZWq1Vvv/22brnlFu3cuVPZ2dnavn275syZo0cffbTS4z/wwAO69dZbtW3bNs2YMUNTp0713YL6t7/9rd544w1dcMEFeumll/TKK6+oS5cu+vDDDytcMwQAAICKLIZhGMEu4mxKSkpks9lUXFx8xi+px48f1+7du5WUlKTo6Oh6rBDh4KqrrtIHH3yg4uJiNWvWLNjl1Dn+HgAAwM9tzsnU8VXvKjptSNjcOa0y1c0GLF2D6RQWFvo1KZWkl19+WRs2bFBaWlqDCDkAAAA/tzknUyl3POzthbM8X5ulsA471UHQgel069ZNV1xxhX7961/7+v+sXr1azZs315w5c4JdHgAAQL07vupdX8PPUxZvT5xwu110oLhGB6Yzfvx4FRUVafHixXrqqaf0xRdfaOTIkfrwww916aWXBrs8AACAehedNsQXciIMKWbQtcEuqc4xowPTmTVrlmbNMve/UAAAAAQi5fZZ2izvTE7MoGtNv2xNIugAAAAADULK7bNMv1zt51i6BgAAAMB0CDoAAAAATIegAwAAAMB0CDoAAAAATIegAwAAAISRzTmZWnN9sjbnZAa7lJDGXdcAAACAMLE5J1Mpdzzs7YezPF+bpQZxq+iaYEYHAAAACBPHV73ra/p5yuLti4PKEXQAAACAMBGdNsQXciIMKWbQtcEuKWQRdFAvxowZI4vFoj179gS7lLNatGiRLBaLFi1aFOxSAAAA/KTcPkub59+n9cOTtXn+fSxbOwOCjklYLJaAHrWNcOBv9erVslgsmj59erBLAQAAJpNy+yzZl20l5JwFNyMwiWnTplUYmzFjhmw2myZOnFj/Bf1CVlaWpkyZonbt2gW7FAAAADQABB2TqGzmYMaMGWrRokVIzCrEx8crPj4+2GUAAACggWDpWgNkGIYWLFigvn37KjY2Vk2aNFHPnj21YMGCCtseP35cf/vb39S9e3fZbDY1a9ZMF154of7whz/o008/leS9/ubmm2+WJN18882VLpGr7Bqdny/v+s9//qPBgwerefPmstlsuv7666u8nmfZsmXq2bOnYmJiFBcXp1tvvVXff/+9OnbsqI4dO1b79/Ddd99p/PjxiouLU5MmTfSb3/xGb775ZpXbL1iwQE6nUx07dlR0dLRatmypwYMHy+12+203ffp0paamSvKGzZ//Pso+03//+19NnjxZycnJatWqlaKjo9W5c2dNmTJFP/74Y7U/AwAAACrHjE4DYxiG/vSnP+mVV15R586dNXLkSEVGRiovL09jx47V9u3bNWfOHN/2o0eP1j//+U9ddtlluvnmmxUVFaWCggK53W4NHjxYl156qYYPH64ffvhBubm5cjqduvzyywOqacuWLXrsscdkt9t12223KT8/X8uXL9enn36qzz77TNHR0b5tFyxYoLFjx6pFixa66aabZLPZtGLFCg0aNEgnT55U48aNq/WeR48eld1u16effqrevXurf//+2rt3r9LT05WWllbpPnfeeae6d++ugQMH6rzzztP+/fu1fPlyDRw4UMuWLZPT6ZQk2e127dmzR3//+9/Vv39/2e123zFatGghyRvWXnzxRaWmpsput+v06dPatGmTZs+erTVr1mjt2rXV/iwAAACohBEGiouLDUlGcXHxGbc7duyYsX37duPYsWP1VFlok2QkJib6jT333HOGJGPs2LHGyZMnfeOlpaXGsGHDDEnGli1bDMMwjB9++MGwWCxGz549jVOnTvkd59SpU8b333/v+3nhwoWGJGPhwoWV1jJ69GhDkrF7927fmNvtNiQZkozXXnvNb/tRo0YZkoxXX33VN/b9998bzZo1M5o3b27s3LnTN37y5Elj4MCBlX7eqkybNs2QZNx6661+4//61798Nf3ys+zatavCcb755hujbdu2RqdOnfzGyz7btGnTKn3/ffv2GaWlpRXGZ8yYYUgyXnrppWp9jjPh7wEAgNC1af59xurhVxib5t8X7FLCTnWzAUvXasj1hUsZKzPk+sIV7FIC8tRTT6lp06Z66qmnFBFRPqEXGRmpWbO8d+549dVXJXnv5GYYhqKiomS1Wv2OY7VafbMT5+rqq69Wenq639gtt9wiSfroo498Y7m5ufrxxx81btw4XXDBBb7xiIgI/fWvfw3oPRcvXqzIyEjNnDnTbzwtLU0DBgyodJ+kpKQKY/Hx8fqf//kfffnll/r666+r/f7t2rVTZGRkhfG77rpLkvTee+9V+1gAACC8bM7JVModD6tvbr5S7nhYm3Myg12SKbF0rQZcX7jkfM0pq8WqeZvnKff3uXJc7Ah2WWd19OhRffrpp2rbtq0eeeSRCq+fPHlSkvT5559LkmJjY3Xttddq5cqVSk5O1o033qh+/fopJSWl0i/pNZWcnFxhrH379pKkH374wTf2ySefSJL69OlTYftevXr5BbczOXLkiHbv3q1f//rXOv/88yu83q9fP/373/+uML5r1y5lZWXp/fff1/79+1VaWur3+jfffKPExMRq1WAYhhYuXKhFixbps88+U3FxsU6fPu13LAAAYE7HV73ra/h5yiIdy1spcavoWkfQqQH3bresFqs8hkdWi1Wr96wOi6Dz/fffyzAM7d+/XzNmzKhyu59++sn3v9944w09/PDDevXVV5WZ6f3XhubNm+uWW27Rww8/rCZNmpxzXTabrcJYWWjxeDy+sZKSEknSeeedV2H7Ro0aqXXr1tV6v+LiYklSmzZtKn09Li6uwthXX32lXr16qaSkRKmpqRo2bJhiY2PVqFEjrV69WmvWrKkQfM5kwoQJeuqpp5SQkCCHw6H4+HhFRUVJ8t7AIJBjAQCA8BKdNkQRy/N9YSdm0LXBLsmUCDo1kJqUqnmb5/nCjr2jPdglVUtsbKwkqUePHtqyZUu19mnatKlmzZqlWbNmaffu3XK73XrmmWf0xBNP6NixY3r22WfrsmQ/ZfV/++23FV47ffq0Dh06VK0+PWXHKSoqqvT1gwcPVhh7/PHH9f333+ull17SH//4R7/Xxo8frzVr1pz1fcsUFRXp6aef1mWXXaYPPvjALyweOHDgjCEUAACEv5TbZ2mzvDM5MYOupfFnHeEanRpwXOxQ7u9zNSFlQtgsW5O8MzFdu3bVjh07/JaEVVdSUpJuueUWrVmzRs2aNZPLVX59Utk1PD+fgalt3bt3lyRt3LixwmsffvihTp06Va3jxMbGKikpSV999ZUOHDhQ4fV169ZVGNu5c6ckyeHw///69OnT2rBhQ4Xtz/T72LVrlwzD0MCBAyvMiFX23gAAwHxSbp8l+7KthJw6RNCpIcfFDs0dPDdsQk6ZCRMm6OjRo7r11lv9lqiV2b17t6/Xy7fffqsPP/ywwjbff/+9SktLFRMT4xtr2bKlJGnfvn11U7gkp9OpZs2a6YUXXtDu3bt946dOndIDDzwQ0LFGjRqlEydO6MEHH/QbX7VqVaXX55Rde7N+/Xq/8dmzZ+uzzz6rsP2Zfh9lx9q4caPfdTn79u3TlClTAvocAAAAqBxL1xqY2267TZs2bdLf//53bdiwQQMHDlTbtm118OBBff7559q8ebNeeeUVdezYUfv371dKSoouueQSJScnq127djp8+LByc3N18uRJTZ482Xfc3r17KyYmRvPmzVNJSYnvOpra/OLeokULzZ07V3/+85+VnJys9PR0Xx+dqKgotW3bVo0aVS+7T548WcuWLdPzzz+vbdu26eqrr9bevXv1z3/+U9ddd53eeecdv+3Hjx+vhQsX6oYbblB6erpatWqlTZs26T//+U+l23fp0kVt27bVa6+9piZNmqh9+/ayWCy6/fbbfXdqW7p0qXr27KkBAwbo4MGDevvtt3XNNddo165dtfY7AwAAaKgIOg2MxWLRokWLNHToUD3//PN6++239eOPP6pNmzbq1KmT5syZo4EDB0qSOnbsqOnTp+v999/Xe++9p8OHD6t169ZKTk5WRkaGX2PNli1b6o033tD06dOVk5OjY8eOSardoCNJt956q371q1/p4Ycf1qJFi2Sz2eRwODR79mwlJibqwgsvrNZxmjZtqjVr1mjq1Kl688039Z///EeXXHKJlixZouLi4grB5YorrtCqVat0//33a9myZbJarerTp482bNggl8tVYXur1aply5bp//2//6d//OMfOnLkiCTp97//vWw2mxYtWqSOHTtq6dKlys7OVocOHTRp0iT9v//3/2r1jnYAAAANlcUwDCPYRZxNSUmJbDabiouLfReSV+b48ePavXu3kpKSFB0dXY8VIti++uorderUSSNGjNCSJUuCXU5I4O8BAACYUXWzAdfoIKyUXR/0c8eOHVNGRoYkafjw4UGoCgAANFSbczK15vpkmn6GIJauIaysWbNGY8eOVVpamjp06KBDhw7p/fff1549e3TNNdcoPT092CUCAIAGYnNOplLueNjbD2d5vjZL3EUthDCjg7ByySWXaNCgQdqwYYOefPJJvfLKK2rWrJn++te/6p133qn2zQgAAADO1fFV7/qafp6yePviIHQwo4Ow0qlTJ7322mvBLgMAAEDRaUMUsTzfF3ZiBl0b7JLwMwQdAAAAoAZSbp+lzfLO5MQMupZlayGGoAMAAADUUMrtsyQCTkjiggYAAAAApkPQAQAAAGA6BB0AAAAApkPQAQAAAGA6BB0AAAA0eJtzMrXm+mRtzskMdimoJdx1DQAAAA3a5pxMpdzxsLcfzvJ8bZa4VbQJMKMDAACABu34qnd9TT9PWbx9cRD+CDqoc3v27JHFYtGYMWP8xu12uywWS529b8eOHdWxY8c6Oz4AADCH6LQhvpATYUgxg64NdkmoBQQdkykLFT9/REZGKiEhQSNHjtT//d//BbvEWjNmzBhZLBbt2bMn2KUAAIAwlnL7LG2ef5/WD0/W5vn3sWzNJLhGx6QuvPBC/elPf5Ik/fjjj9q0aZNeffVVLVu2TO+//7769OkT5AqlxYsX6+jRo3V2/H//+991dmwAAGAuKbfPkgg4pkLQMamLLrpI06dP9xu7//77NWvWLGVmZsrtdgensJ/p0KFDnR7/wgsvrNPjAwAAIHSxdK0BufvuuyVJH330kSTJYrHIbrdr//79GjNmjM4//3w1atRIq1ev9u2zdu1aDRs2TK1bt1ZUVJQ6deqk+++/v9KZGI/Ho9mzZ+uiiy5SdHS0LrroImVlZen06dOV1nOma3RcLpcGDx6sVq1aKTo6Wh07dtSoUaP02WefSfJef/P3v/9dkpSUlORbpme3233HqOoanaNHj2r69Onq0qWLoqOj1bJlS1133XXauHFjhW2nT58ui8Wi1atX65///KeSk5MVExOj+Ph4TZgwQceOHauwz9KlS9W/f3+1adNG0dHRSkhI0LXXXqvly5dX+lkBAABQ+5jRaUAqCxWHDx9W79691bJlS6Wnp+vEiROKjY2VJD3zzDO644479Ktf/UrDhg3Teeedp48++kizZs2S2+2W2+1WZGSk71h//vOftWDBAiUlJenOO+/U8ePHNXfu3EoDxJlMnjxZjz32mFq2bKnhw4erTZs22rt3r9577z316NFD3bp108SJE7Vo0SJ98skn+stf/qIWLVpI0llvPlBaWqoBAwZo06ZNSk5O1sSJE1VUVKQlS5Zo1apVWrJkiW644YYK+z399NN699135XQ6ZbfbtXLlSmVnZ+vw4cN6+eWXfdvl5OTojjvuUHx8vK6//nq1atVKhYWF+vDDD7V8+XINHz48oN8FAAAAasiogaefftro2LGjERUVZSQnJxtr16494/ZPPfWU0aVLFyM6Otro3Lmz8fe//z2g9ysuLjYkGcXFxWfc7tixY8b27duNY8eOBXR8M9m9e7chyRg8eHCF1zIzMw1Jht1uNwzDMCQZkoybb77ZOHXqlN+227ZtMyIiIowrrrjCOHz4sN9rWVlZhiRjzpw5vjG3221IMrp37278+OOPvvF9+/YZrVu3NiQZo0eP9jtO//79jV+egu+8844hybj00kuNQ4cO+b128uRJ48CBA76fR48ebUgydu/eXenvIjEx0UhMTPQbmzlzpiHJ+OMf/2icPn3aN/7JJ58YUVFRxq9+9SujpKTENz5t2jRDkmGz2YzPP//cN3706FGjc+fOhsViMfbv3+8bT05O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hmj79u3q0KFDhe2bNm2qu+66S5dddpmaNm2q9evX67bbblPTpk315z//uVY+BAAAAAD8nMUwDCOQHVJSUpScnKycnBzfWNeuXTV8+HBlZWVV6xg33HCDmjZtqn/84x/V2r6kpEQ2m03FxcWKjY0NpNxa53J5++KkpnJzAQAAAKC+VTcbBLR07cSJE9q6davS0tL8xtPS0rRx48ZqHSM/P18bN25U//79q9ymtLRUJSUlfo9Q4HJJTqeUne19drmCXREAAACAygQUdA4dOiSPx6O4uDi/8bi4OB04cOCM+7Zv315RUVHq2bOn7rzzTo0bN67KbbOysmSz2XyPhISEQMqsM253edNPq9XbFwcAAABA6KnRzQgsFovfz4ZhVBj7pXXr1mnLli165plnNG/ePL366qtVbjt16lQVFxf7Hnv37q1JmbUuNbU85Hg83uafAAAAAEJPQDcjaN26taxWa4XZm6KiogqzPL+UlJQkSbr00kt18OBBTZ8+XX/4wx8q3TYqKkpRUVGBlFYvHA4pN9c7k2O3c40OAAAAEKoCmtGJjIxUjx49lJeX5zeel5enPn36VPs4hmGotLQ0kLcOGQ6HNHcuIQcAAAAIZQHfXnrSpEkaNWqUevbsqd69e+u5555TQUGBxo8fL8m77Gz//v1avHixJOnpp59Whw4d1KVLF0nevjpz5szR3XffXYsfAwAAAADKBRx00tPTdfjwYc2cOVOFhYXq1q2bVqxYocTERElSYWGhCgoKfNufPn1aU6dO1e7duxUREaELL7xQjzzyiG677bba+xQAAAAA8DMB99EJhlDqowMAAAAgeOqkjw4AAAAAhAOCDgAAAADTIegAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTiQh2AdVhGIYkqaSkJMiVAAAAAAimskxQlhGqEhZB58iRI5KkhISEIFcCAAAAIBQcOXJENputytctxtmiUAg4ffq0vvnmGzVv3lwWiyWotZSUlCghIUF79+5VbGxsUGtB+OH8wbng/EFNce7gXHD+4FzUxfljGIaOHDmitm3bqlGjqq/ECYsZnUaNGql9+/bBLsNPbGwsf+yoMc4fnAvOH9QU5w7OBecPzkVtnz9nmskpw80IAAAAAJgOQQcAAACA6RB0AhQVFaVp06YpKioq2KUgDHH+4Fxw/qCmOHdwLjh/cC6Cef6Exc0IAAAAACAQzOgAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTIegAAAAAMB2CTiXmz5+vpKQkRUdHq0ePHlq3bt0Zt1+zZo169Oih6OhoXXDBBXrmmWfqqVKEokDOn2XLlmnQoEE677zzFBsbq969e+tf//pXPVaLUBLof3vKbNiwQREREbr88svrtkCEtEDPn9LSUmVmZioxMVFRUVG68MILtWDBgnqqFqEm0PPn5ZdfVvfu3dWkSRPFx8fr5ptv1uHDh+upWoSKtWvXatiwYWrbtq0sFouWL19+1n3q83szQecXlixZookTJyozM1P5+fnq16+fhgwZooKCgkq33717t4YOHap+/fopPz9f9913nyZMmKClS5fWc+UIBYGeP2vXrtWgQYO0YsUKbd26VampqRo2bJjy8/PruXIEW6DnTpni4mLddNNNGjBgQD1VilBUk/NnxIgR+ve//60XX3xRX3zxhV599VV16dKlHqtGqAj0/Fm/fr1uuukmjR07Vtu2bdPrr7+ujz76SOPGjavnyhFsP/30k7p3766nnnqqWtvX+/dmA3569epljB8/3m+sS5cuxpQpUyrdfvLkyUaXLl38xm677TbjyiuvrLMaEboCPX8q8+tf/9qYMWNGbZeGEFfTcyc9Pd24//77jWnTphndu3evwwoRygI9f959913DZrMZhw8fro/yEOICPX8ee+wx44ILLvAbe/LJJ4327dvXWY0IfZKMN99884zb1Pf3ZmZ0fubEiRPaunWr0tLS/MbT0tK0cePGSvf54IMPKmw/ePBgbdmyRSdPnqyzWhF6anL+/NLp06d15MgRtWzZsi5KRIiq6bmzcOFC7dy5U9OmTavrEhHCanL+uFwu9ezZU48++qjatWunzp0765577tGxY8fqo2SEkJqcP3369NG+ffu0YsUKGYahgwcP6o033tB1111XHyUjjNX39+aIWj9iGDt06JA8Ho/i4uL8xuPi4nTgwIFK9zlw4ECl2586dUqHDh1SfHx8ndWL0FKT8+eX/va3v+mnn37SiBEj6qJEhKianDtffvmlpkyZonXr1ikigv+UN2Q1OX927dql9evXKzo6Wm+++aYOHTqkO+64Q9999x3X6TQwNTl/+vTpo5dfflnp6ek6fvy4Tp06JYfDoezs7PooGWGsvr83M6NTCYvF4vezYRgVxs62fWXjaBgCPX/KvPrqq5o+fbqWLFmiNm3a1FV5CGHVPXc8Ho9GjhypGTNmqHPnzvVVHkJcIP/tOX36tCwWi15++WX16tVLQ4cO1dy5c7Vo0SJmdRqoQM6f7du3a8KECXrwwQe1detWrVy5Urt379b48ePro1SEufr83sw/A/5M69atZbVaK/wLRlFRUYX0Web888+vdPuIiAi1atWqzmpF6KnJ+VNmyZIlGjt2rF5//XUNHDiwLstECAr03Dly5Ii2bNmi/Px83XXXXZK8X1wNw1BERIRWrVqla665pl5qR/DV5L898fHxateunWw2m2+sa9euMgxD+/btU6dOneq0ZoSOmpw/WVlZ6tu3r+69915J0mWXXaamTZuqX79+euihh1jNgirV9/dmZnR+JjIyUj169FBeXp7feF5envr06VPpPr17966w/apVq9SzZ081bty4zmpF6KnJ+SN5Z3LGjBmjV155hfXNDVSg505sbKw+/fRTffzxx77H+PHjdfHFF+vjjz9WSkpKfZWOEFCT//b07dtX33zzjX788Uff2H//+181atRI7du3r9N6EVpqcv4cPXpUjRr5f4W0Wq2Syv91HqhMvX9vrpNbHISx1157zWjcuLHx4osvGtu3bzcmTpxoNG3a1NizZ49hGIYxZcoUY9SoUb7td+3aZTRp0sTIyMgwtm/fbrz44otG48aNjTfeeCNYHwFBFOj588orrxgRERHG008/bRQWFvoeP/zwQ7A+AoIk0HPnl7jrWsMW6Plz5MgRo3379saNN95obNu2zVizZo3RqVMnY9y4ccH6CAiiQM+fhQsXGhEREcb8+fONnTt3GuvXrzd69uxp9OrVK1gfAUFy5MgRIz8/38jPzzckGXPnzjXy8/ONr7/+2jCM4H9vJuhU4umnnzYSExONyMhIIzk52VizZo3vtdGjRxv9+/f323716tXGFVdcYURGRhodO3Y0cnJy6rlihJJAzp/+/fsbkio8Ro8eXf+FI+gC/W/PzxF0EOj5s2PHDmPgwIFGTEyM0b59e2PSpEnG0aNH67lqhIpAz58nn3zS+PWvf23ExMQY8fHxxh//+Edj37599Vw1gs3tdp/xe0ywvzdbDIM5RgAAAADmwjU6AAAAAEyHoAMAAADAdAg6AAAAAEyHoAMAAADAdAg6AAAAAEyHoAMAAADAdAg6AAAAAEyHoAMAAADAdAg6AAAAAEyHoAMAAADAdAg6AAAAAEzn/wMrl02beMB4GQAAAABJRU5ErkJggg==",1054      "text/plain": [1055       "<Figure size 1000x700 with 1 Axes>"1056      ]1057     },1058     "metadata": {},1059     "output_type": "display_data"1060    }1061   ],1062   "source": [1063    "# plot_predictions(predictions=y_preds) # -> won't work... data not on CPU\n",1064    "\n",1065    "# Put data on the CPU and plot it\n",1066    "plot_predictions(predictions=y_preds.cpu())"1067   ]1068  },1069  {1070   "cell_type": "code",1071   "execution_count": 78,1072   "id": "6e182caf-6495-42c9-89f7-99de9f6d3055",1073   "metadata": {},1074   "outputs": [1075    {1076     "name": "stdout",1077     "output_type": "stream",1078     "text": [1079      "Saving model to: models\\01_pytorch_workflow_model_1.pth\n"1080     ]1081    }1082   ],1083   "source": [1084    "from pathlib import Path\n",1085    "\n",1086    "# 1. Create models directory \n",1087    "MODEL_PATH = Path(\"models\")\n",1088    "MODEL_PATH.mkdir(parents=True, exist_ok=True)\n",1089    "\n",1090    "# 2. Create model save path \n",1091    "MODEL_NAME = \"01_pytorch_workflow_model_1.pth\"\n",1092    "MODEL_SAVE_PATH = MODEL_PATH / MODEL_NAME\n",1093    "\n",1094    "# 3. Save the model state dict \n",1095    "print(f\"Saving model to: {MODEL_SAVE_PATH}\")\n",1096    "torch.save(obj=model_1.state_dict(), # only saving the state_dict() only saves the models learned parameters\n",1097    "           f=MODEL_SAVE_PATH) "1098   ]1099  },1100  {1101   "cell_type": "code",1102   "execution_count": 80,1103   "id": "6f3a7b33-2a75-4532-a469-28d78ee48673",1104   "metadata": {},1105   "outputs": [1106    {1107     "name": "stdout",1108     "output_type": "stream",1109     "text": [1110      "Loaded model:\n",1111      "LinearRegressionModelV2(\n",1112      "  (linear_layer): Linear(in_features=1, out_features=1, bias=True)\n",1113      ")\n",1114      "Model on device:\n",1115      "cuda:0\n"1116     ]1117    },1118    {1119     "name": "stderr",1120     "output_type": "stream",1121     "text": [1122      "C:\\Users\\User\\AppData\\Local\\Temp\\ipykernel_10048\\2631515358.py:5: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",1123      "  loaded_model_1.load_state_dict(torch.load(MODEL_SAVE_PATH))\n"1124     ]1125    }1126   ],1127   "source": [1128    "# Instantiate a fresh instance of LinearRegressionModelV2\n",1129    "loaded_model_1 = LinearRegressionModelV2()\n",1130    "\n",1131    "# Load model state dict \n",1132    "loaded_model_1.load_state_dict(torch.load(MODEL_SAVE_PATH))\n",1133    "\n",1134    "# Put model to target device (if your data is on GPU, model will have to be on GPU to make predictions)\n",1135    "loaded_model_1.to(device)\n",1136    "\n",1137    "print(f\"Loaded model:\\n{loaded_model_1}\")\n",1138    "print(f\"Model on device:\\n{next(loaded_model_1.parameters()).device}\")"1139   ]1140  },1141  {1142   "cell_type": "code",1143   "execution_count": 81,1144   "id": "c0cb6338-e54c-42b7-9c8a-ff147e244a37",1145   "metadata": {},1146   "outputs": [1147    {1148     "data": {1149      "text/plain": [1150       "tensor([[True],\n",1151       "        [True],\n",1152       "        [True],\n",1153       "        [True],\n",1154       "        [True],\n",1155       "        [True],\n",1156       "        [True],\n",1157       "        [True],\n",1158       "        [True],\n",1159       "        [True]], device='cuda:0')"1160      ]1161     },1162     "execution_count": 81,1163     "metadata": {},1164     "output_type": "execute_result"1165    }1166   ],1167   "source": [1168    "# Evaluate loaded model\n",1169    "loaded_model_1.eval()\n",1170    "with torch.inference_mode():\n",1171    "    loaded_model_1_preds = loaded_model_1(X_test)\n",1172    "y_preds == loaded_model_1_preds"1173   ]1174  },1175  {1176   "cell_type": "code",1177   "execution_count": null,1178   "id": "dab92270-dd02-4959-b9c1-3b275fba6d3a",1179   "metadata": {},1180   "outputs": [],1181   "source": []1182  }1183 ],1184 "metadata": {1185  "kernelspec": {1186   "display_name": "Python 3 (ipykernel)",1187   "language": "python",1188   "name": "python3"1189  },1190  "language_info": {1191   "codemirror_mode": {1192    "name": "ipython",1193    "version": 31194   },1195   "file_extension": ".py",1196   "mimetype": "text/x-python",1197   "name": "python",1198   "nbconvert_exporter": "python",1199   "pygments_lexer": "ipython3",1200   "version": "3.12.7"

Showing the first 1,200 of 1206 lines. Download the file for the rest.