diff --git a/lab1/PT_Part1_Intro.ipynb b/lab1/PT_Part1_Intro.ipynb index db97d067..c3701bf7 100644 --- a/lab1/PT_Part1_Intro.ipynb +++ b/lab1/PT_Part1_Intro.ipynb @@ -21,7 +21,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "id": "3eI6DUic-6jo" }, @@ -60,11 +60,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "id": "LkaimNJfYZ2w" }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\lucas\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "Gym has been unmaintained since 2022 and does not support NumPy 2.0 amongst other critical functionality.\n", + "Please upgrade to Gymnasium, the maintained drop-in replacement of Gym, or contact the authors of your software and request that they upgrade.\n", + "Users of this version of Gym should be able to simply replace 'import gym' with 'import gymnasium as gym' in the vast majority of cases.\n", + "See the migration guide at https://gymnasium.farama.org/introduction/migration_guide/ for additional information.\n" + ] + } + ], "source": [ "import torch\n", "import torch.nn as nn\n", @@ -94,11 +107,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "id": "tFxztZQInlAB" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "`integer` is a 0-d Tensor: 1234\n", + "`decimal` is a 0-d Tensor: 3.1415927410125732\n" + ] + } + ], "source": [ "integer = torch.tensor(1234)\n", "decimal = torch.tensor(3.14159265359)\n", @@ -118,11 +140,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "id": "oaHXABe8oPcO" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "`fibonacci` is a 1-d Tensor with shape: torch.Size([6])\n", + "`count_to_100` is a 1-d Tensor with shape: torch.Size([100])\n" + ] + } + ], "source": [ "fibonacci = torch.tensor([1, 1, 2, 3, 5, 8])\n", "count_to_100 = torch.tensor(range(100))\n", @@ -142,16 +173,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "id": "tFeBBe1IouS3" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "images is a 4-d Tensor with shape: torch.Size([10, 3, 256, 256])\n" + ] + } + ], "source": [ "### Defining higher-order Tensors ###\n", "\n", "'''TODO: Define a 2-d Tensor'''\n", - "matrix = # TODO\n", + "matrix = torch.tensor([[1,2,3],[4,5,6]])\n", "\n", "assert isinstance(matrix, torch.Tensor), \"matrix must be a torch Tensor object\"\n", "assert matrix.ndim == 2\n", @@ -159,7 +198,7 @@ "'''TODO: Define a 4-d Tensor.'''\n", "# Use torch.zeros to initialize a 4-d Tensor of zeros with size 10 x 3 x 256 x 256.\n", "# You can think of this as 10 images where each image is RGB 256 x 256.\n", - "images = # TODO\n", + "images = torch.zeros([10,3,256,256])\n", "\n", "assert isinstance(images, torch.Tensor), \"images must be a torch Tensor object\"\n", "assert images.ndim == 4, \"images must have 4 dimensions\"\n", @@ -178,11 +217,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "id": "FhaufyObuLEG" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "`row_vector`: tensor([4, 5, 6])\n", + "`column_vector`: tensor([2, 5])\n", + "`scalar`: 2\n" + ] + } + ], "source": [ "row_vector = matrix[1]\n", "column_vector = matrix[:, 1]\n", @@ -208,11 +257,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "id": "X_YJrZsxYZ2z" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c1: 76\n", + "c2: 76\n" + ] + } + ], "source": [ "# Create the nodes in the graph and initialize values\n", "a = torch.tensor(15)\n", @@ -244,7 +302,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": { "id": "PJnfzpWyYZ23", "scrolled": true @@ -256,9 +314,9 @@ "# Construct a simple computation function\n", "def func(a, b):\n", " '''TODO: Define the operation for c, d, e.'''\n", - " c = # TODO\n", - " d = # TODO\n", - " e = # TODO\n", + " c = torch.add(a,b)\n", + " d = torch.subtract(b,1)\n", + " e = torch.multiply(c,d)\n", " return e\n" ] }, @@ -273,11 +331,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": { "id": "pnwsf8w2uF7p" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "e_out: 6.0\n" + ] + } + ], "source": [ "# Consider example values for a,b\n", "a, b = 1.5, 2.5\n", @@ -315,7 +381,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "id": "HutbJk-1kHPh" }, @@ -337,10 +403,10 @@ "\n", " def forward(self, x):\n", " '''TODO: define the operation for z (hint: use torch.matmul).'''\n", - " z = # TODO\n", + " z = torch.matmul(x, self.W)\n", "\n", " '''TODO: define the operation for out (hint: use torch.sigmoid).'''\n", - " y = # TODO\n", + " y = torch.sigmoid(z)\n", " return y\n" ] }, @@ -355,11 +421,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": { "id": "2yxjCPa69hV_" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "input shape: torch.Size([1, 2])\n", + "output shape: torch.Size([1, 3])\n", + "output result: tensor([[0.5341, 0.9590, 0.0504]], grad_fn=)\n" + ] + } + ], "source": [ "# Define a layer and test the output!\n", "num_inputs = 2\n", @@ -386,7 +462,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "id": "7WXTpmoL6TDz" }, @@ -401,7 +477,9 @@ "# Define the model\n", "'''TODO: Use the Sequential API to define a neural network with a\n", " single linear (dense!) layer, followed by non-linearity to compute z'''\n", - "model = nn.Sequential( ''' TODO ''' )\n" + "model = nn.Sequential(\n", + " nn.Linear(n_input_nodes, n_output_nodes),\n", + " nn.Sigmoid())\n" ] }, { @@ -415,11 +493,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "id": "zKhp6XqCFFa0" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "input shape: torch.Size([1, 2])\n", + "output shape: torch.Size([1, 3])\n", + "output result: tensor([[0.5341, 0.9590, 0.0504]], grad_fn=)\n" + ] + } + ], "source": [ "# Test the model with example input\n", "x_input = torch.tensor([[1, 2.]])\n", @@ -442,7 +530,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": { "id": "K4aCflPVyViD" }, @@ -454,8 +542,8 @@ " def __init__(self, num_inputs, num_outputs):\n", " super(LinearWithSigmoidActivation, self).__init__()\n", " '''TODO: define a model with a single Linear layer and sigmoid activation.'''\n", - " self.linear = '''TODO: linear layer'''\n", - " self.activation = '''TODO: sigmoid activation'''\n", + " self.linear = nn.Linear(num_inputs, num_outputs)\n", + " self.activation = nn.Sigmoid()\n", "\n", " def forward(self, inputs):\n", " linear_output = self.linear(inputs)\n", @@ -474,11 +562,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "id": "V-eNhSyRG6hl" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "input shape: torch.Size([1, 2])\n", + "output shape: torch.Size([1, 3])\n", + "output result: tensor([[0.3185, 0.5937, 0.8650]], grad_fn=)\n" + ] + } + ], "source": [ "n_input_nodes = 2\n", "n_output_nodes = 3\n", @@ -501,7 +599,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "id": "P7jzGX5D1xT5" }, @@ -517,7 +615,7 @@ " '''TODO: Implement the behavior where the network outputs the input, unchanged,\n", " under control of the isidentity argument.'''\n", " def forward(self, inputs, isidentity=False):\n", - " ''' TODO '''\n" + " return inputs if isidentity else self.linear(inputs)\n" ] }, { @@ -531,20 +629,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": { "id": "NzC0mgbk5dp2" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "input: tensor([[1., 2.]])\n", + "Network linear output: tensor([[-0.1452, 0.3877, -0.0137]], grad_fn=); network identity output: tensor([[1., 2.]])\n" + ] + } + ], "source": [ "# Test the IdentityModel\n", "model = LinearButSometimesIdentity(num_inputs=2, num_outputs=3)\n", "x_input = torch.tensor([[1, 2.]])\n", "\n", "'''TODO: pass the input into the model and call with and without the input identity option.'''\n", - "out_with_linear = # TODO\n", + "out_with_linear = model(x_input)\n", "\n", - "out_with_identity = # TODO\n", + "out_with_identity = model(x_input, isidentity = True)\n", "\n", "print(f\"input: {x_input}\")\n", "print(\"Network linear output: {}; network identity output: {}\".format(out_with_linear, out_with_identity))" @@ -576,11 +683,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": { "id": "tdkqk8pw5yJM" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dy_dx of y=x^2 at x=3.0 is: tensor(6.)\n" + ] + } + ], "source": [ "### Gradient computation ###\n", "\n", @@ -606,7 +721,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 29, "metadata": { "attributes": { "classes": [ @@ -616,7 +731,25 @@ }, "id": "7g1yWiSXqEf-" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initializing x=-0.05343540012836456\n" + ] + }, + { + "data": { + "image/png": "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w1KqOFgVEKuVGHv37i1vvPGGng1177336ufHjRunFyNS18tQpkyZopeQnjVrlowYMUIWLVqkp8a9++67Bv8kAAAjGTz5F070OzQ83Kip3efOndOXe1dFwWpK94oVK6xFw2oxIrUqo0W/fv1k4cKF8swzz+ipberCYGqmVKdOnQz8KQAARvHz89O36tID6krYcF1qFrWiSlZcep0bR6vLVDIAgGtQK/eqJUSaNm2qlxjxUpdfgEtRZSlnzpzRYVUt+3Ll77Au39+G99wAANBQlkklNa1uD9egRmqqCzZ1RbgBALg89WXYrFkz3XNT+WKScC1qolHlUpT6ItwAANyGqtVoaL0GXJ/hF84EAACwJcINAABwK4QbAADgVjyu5sYy811NKQMAAK7B8r1dmxVsPC7c5Obm6tvExESjmwIAAOrxPa7Wu7kWj1vEz7JIUFhYmM0XeVKpUoWmtLQ0Fgi0I86zY3CeHYPz7Dica9c+zyquqGATFxd33eniHtdzo05IQkKCXT9D/TL5P479cZ4dg/PsGJxnx+Fcu+55vl6PjQUFxQAAwK0QbgAAgFsh3NhQQECAPPfcc/oW9sN5dgzOs2Nwnh2Hc+0559njCooBAIB7o+cGAAC4FcINAABwK4QbAADgVgg3AADArRBubOTtt9+Wli1bSmBgoNx0002ydetWo5vkUtavXy8jR47UK0+qlaOXLFlS5XlV9/7ss89Ks2bNJCgoSAYNGiRHjx6tcszFixflrrvu0otGRUZGyoQJEyQvL8/BP4lzmz59utx44416he6mTZvK6NGj5fDhw1WOKSwslEmTJknjxo0lNDRUfvOb38jZs2erHJOamiojRoyQ4OBg/T6PP/64lJaWOvincV5z5syRLl26WBcx69u3ryxfvtz6POfYPmbMmKH//Zg6dap1H+faNp5//nl9bitv7dq1c97zrGZLoWEWLVpk9vf3N7/33nvmAwcOmCdOnGiOjIw0nz171uimuYxvvvnG/Ne//tX85Zdfqtl75sWLF1d5fsaMGeaIiAjzkiVLzHv27DH/6le/MiclJZkvX75sPeb22283d+3a1bx582bzf//7X3NycrJ57NixBvw0zmvo0KHm999/37x//37z7t27zcOHDzc3b97cnJeXZz3mwQcfNCcmJppXr15t3r59u7lPnz7mfv36WZ8vLS01d+rUyTxo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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "### Function minimization with autograd and gradient descent ###\n", "\n", @@ -635,7 +768,7 @@ " x = torch.tensor([x], requires_grad=True)\n", "\n", " # TODO: Compute the loss as the square of the difference between x and x_f\n", - " loss = # TODO\n", + " loss = torch.square(torch.subtract(x,x_f))\n", "\n", " # Backpropagate through the loss to compute gradients\n", " loss.backward()\n", @@ -688,7 +821,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.13.7" }, "vscode": { "interpreter": { diff --git a/lab1/TF_Part1_Intro.ipynb b/lab1/TF_Part1_Intro.ipynb index b79e04df..b92e3bcf 100644 --- a/lab1/TF_Part1_Intro.ipynb +++ b/lab1/TF_Part1_Intro.ipynb @@ -58,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "id": "LkaimNJfYZ2w" }, @@ -67,7 +67,8 @@ "import tensorflow as tf\n", "\n", "# Download and import the MIT Introduction to Deep Learning package\n", - "!pip install mitdeeplearning --quiet\n", + "#!pip install mitdeeplearning --quiet\n", + "#!pip install opencv-python\n", "import mitdeeplearning as mdl\n", "\n", "import numpy as np\n", @@ -91,11 +92,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "id": "tFxztZQInlAB" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "`sport` is a 0-d Tensor\n", + "`number` is a 0-d Tensor\n" + ] + } + ], "source": [ "sport = tf.constant(\"Tennis\", tf.string)\n", "number = tf.constant(1.41421356237, tf.float64)\n", @@ -115,11 +125,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "id": "oaHXABe8oPcO" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "`sports` is a 1-d Tensor with shape: [2]\n", + "`numbers` is a 1-d Tensor with shape: [3]\n" + ] + } + ], "source": [ "sports = tf.constant([\"Tennis\", \"Basketball\"], tf.string)\n", "numbers = tf.constant([3.141592, 1.414213, 2.71821], tf.float64)\n", @@ -139,7 +158,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "id": "tFeBBe1IouS3" }, @@ -148,7 +167,7 @@ "### Defining higher-order Tensors ###\n", "\n", "'''TODO: Define a 2-d Tensor'''\n", - "matrix = # TODO\n", + "matrix = tf.constant([[1,2],[3,4]], tf.int64)\n", "\n", "assert isinstance(matrix, tf.Tensor), \"matrix must be a tf Tensor object\"\n", "assert tf.rank(matrix).numpy() == 2" @@ -156,7 +175,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "id": "Zv1fTn_Ya_cz" }, @@ -165,7 +184,7 @@ "'''TODO: Define a 4-d Tensor.'''\n", "# Use tf.zeros to initialize a 4-d Tensor of zeros with size 10 x 256 x 256 x 3.\n", "# You can think of this as 10 images where each image is RGB 256 x 256.\n", - "images = # TODO\n", + "images = tf.zeros([10,256,256,3], tf.int64)\n", "\n", "assert isinstance(images, tf.Tensor), \"matrix must be a tf Tensor object\"\n", "assert tf.rank(images).numpy() == 4, \"matrix must be of rank 4\"\n", @@ -183,11 +202,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "id": "FhaufyObuLEG" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "`row_vector`: [3 4]\n", + "`column_vector`: [2 4]\n", + "`scalar`: 2\n" + ] + } + ], "source": [ "row_vector = matrix[1]\n", "column_vector = matrix[:,1]\n", @@ -213,11 +242,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "id": "X_YJrZsxYZ2z" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tf.Tensor(76, shape=(), dtype=int32)\n", + "tf.Tensor(76, shape=(), dtype=int32)\n" + ] + } + ], "source": [ "# Create the nodes in the graph, and initialize values\n", "a = tf.constant(15)\n", @@ -249,7 +287,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "id": "PJnfzpWyYZ23", "scrolled": true @@ -261,9 +299,9 @@ "# Construct a simple computation function\n", "def func(a,b):\n", " '''TODO: Define the operation for c, d, e (use tf.add, tf.subtract, tf.multiply).'''\n", - " c = # TODO\n", - " d = # TODO\n", - " e = # TODO\n", + " c = tf.add(a,b)\n", + " d = tf.subtract(b, 1)\n", + " e = tf.multiply(c,d)\n", " return e" ] }, @@ -278,11 +316,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "id": "pnwsf8w2uF7p" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tf.Tensor(6.0, shape=(), dtype=float32)\n" + ] + } + ], "source": [ "# Consider example values for a,b\n", "a, b = 1.5, 2.5\n", @@ -318,11 +364,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "id": "HutbJk-1kHPh" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0.27064407 0.18269512 0.50374055]]\n", + "[PASS] test_custom_dense_layer_output\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "### Defining a network Layer ###\n", "\n", @@ -330,6 +395,9 @@ "# input_shape: shape of the input\n", "# x: input to the layer\n", "\n", + "from mitdeeplearning import lab1\n", + "\n", + "\n", "class OurDenseLayer(tf.keras.layers.Layer):\n", " def __init__(self, n_output_nodes):\n", " super(OurDenseLayer, self).__init__()\n", @@ -339,15 +407,15 @@ " d = int(input_shape[-1])\n", " # Define and initialize parameters: a weight matrix W and bias b\n", " # Note that parameter initialization is random!\n", - " self.W = self.add_weight(\"weight\", shape=[d, self.n_output_nodes]) # note the dimensionality\n", - " self.b = self.add_weight(\"bias\", shape=[1, self.n_output_nodes]) # note the dimensionality\n", + " self.W = self.add_weight(name = \"weight\", shape=[d, self.n_output_nodes]) # note the dimensionality\n", + " self.b = self.add_weight(name = \"bias\", shape=[1, self.n_output_nodes]) # note the dimensionality\n", "\n", " def call(self, x):\n", " '''TODO: define the operation for z (hint: use tf.matmul)'''\n", - " z = # TODO\n", + " z = tf.add(tf.matmul(x, self.W), self.b)\n", "\n", " '''TODO: define the operation for out (hint: use tf.sigmoid)'''\n", - " y = # TODO\n", + " y = tf.sigmoid(z)\n", " return y\n", "\n", "# Since layer parameters are initialized randomly, we will set a random seed for reproducibility\n", @@ -359,7 +427,7 @@ "\n", "# test the output!\n", "print(y.numpy())\n", - "mdl.lab1.test_custom_dense_layer_output(y)" + "lab1.test_custom_dense_layer_output(y)" ] }, { @@ -373,7 +441,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "metadata": { "id": "7WXTpmoL6TDz" }, @@ -395,7 +463,7 @@ "# Remember: dense layers are defined by the parameters W and b!\n", "# You can read more about the initialization of W and b in the TF documentation :)\n", "# https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense?version=stable\n", - "dense_layer = # TODO\n", + "dense_layer = Dense(n_output_nodes, activation='sigmoid')\n", "\n", "# Add the dense layer to the model\n", "model.add(dense_layer)\n" @@ -412,17 +480,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 49, "metadata": { "id": "sg23OczByRDb" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 64ms/step\n", + "[[0.3137059 0.09264623 0.23160182]]\n" + ] + } + ], "source": [ "# Test model with example input\n", "x_input = tf.constant([[1,2.]], shape=(1,2))\n", "\n", "'''TODO: feed input into the model and predict the output!'''\n", - "model_output = # TODO\n", + "model_output = model.predict(x_input)\n", "print(model_output)" ] }, @@ -437,7 +514,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 50, "metadata": { "id": "K4aCflPVyViD" }, @@ -454,7 +531,7 @@ " def __init__(self, n_output_nodes):\n", " super(SubclassModel, self).__init__()\n", " '''TODO: Our model consists of a single Dense layer. Define this layer.'''\n", - " self.dense_layer = '''TODO: Dense Layer'''\n", + " self.dense_layer = Dense(n_output_nodes)\n", "\n", " # In the call function, we define the Model's forward pass.\n", " def call(self, inputs):\n", @@ -473,11 +550,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 51, "metadata": { "id": "LhB34RA-4gXb" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tf.Tensor([[ 0.3973893 -0.4299295 -0.85902894]], shape=(1, 3), dtype=float32)\n" + ] + } + ], "source": [ "n_output_nodes = 3\n", "model = SubclassModel(n_output_nodes)\n", @@ -498,7 +583,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 52, "metadata": { "id": "P7jzGX5D1xT5" }, @@ -519,7 +604,7 @@ "\n", " '''TODO: Implement the behavior where the network outputs the input, unchanged, under control of the isidentity argument.'''\n", " def call(self, inputs, isidentity=False):\n", - " ### TODO" + " return inputs if isidentity else self.dense_layer(inputs)" ] }, { @@ -533,19 +618,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 54, "metadata": { "id": "NzC0mgbk5dp2" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Network output with activation: [[0.80413926 0.40394166 0.36478916]]; network identity output: [[1. 2.]]\n" + ] + } + ], "source": [ "n_output_nodes = 3\n", "model = IdentityModel(n_output_nodes)\n", "\n", "x_input = tf.constant([[1,2.]], shape=(1,2))\n", "'''TODO: pass the input into the model and call with and without the input identity option.'''\n", - "out_activate = # TODO\n", - "out_identity = # TODO\n", + "out_activate = model.call(x_input)\n", + "out_identity = model.call(x_input, isidentity=True)\n", "\n", "print(\"Network output with activation: {}; network identity output: {}\".format(out_activate.numpy(), out_identity.numpy()))" ] @@ -579,7 +672,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 55, "metadata": { "id": "tdkqk8pw5yJM" }, @@ -612,7 +705,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 56, "metadata": { "attributes": { "classes": [ @@ -622,7 +715,35 @@ }, "id": "7g1yWiSXqEf-" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initializing x=[[-1.1012203]]\n" + ] + }, + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'x value')" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjUAAAGwCAYAAABRgJRuAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAOvVJREFUeJzt3Ql4lNW9x/F/9j0hISELBAKyyyKrBVuhiCxaC9qqVVS0Vq8KFlwrbd1aNbS2XpGqcN1Qq4IXBb0qKiKLWGQP+06AAIGQQHayzcx9zpnMmECALDPzzjvz/TzPdN5ZMnN4J838POd/zgmw2Ww2AQAAMLlAoxsAAADgCoQaAADgEwg1AADAJxBqAACATyDUAAAAn0CoAQAAPoFQAwAAfEKw+BGr1SpHjx6VmJgYCQgIMLo5AACgEdSSeiUlJZKWliaBgefuj/GrUKMCTXp6utHNAAAAzZCTkyPt2rU75+N+FWpUD43jpMTGxhrdHAAA0AjFxcW6U8LxPX4ufhVqHENOKtAQagAAMJcLlY5QKAwAAHwCoQYAAPgEQg0AAPAJhBoAAOATCDUAAMAnEGoAAIBPINQAAACfQKgBAAA+gVADAAB8AqEGAAD4BNOGmunTp+vlkqdOnWp0UwAAgBcwZahZu3atzJ49W/r06WN0UwAAgJcw3YaWpaWlMmHCBHnttdfkmWeeMbo5IjabSHW50a0AAFyATf29rv2zra/PvL/ecx3Pqf8z53q8Ma/rfI3m/Gxj/n1ygWe17OFGPSkmPFgio2LVzpNiBNOFmkmTJsnVV18tI0eOvGCoqays1Je6W5e7nAo0z6W5/nUBAC7l+Jo15uvWj/zxqEholCFvbapQM3fuXNmwYYMefmqMzMxMefrpp93eLgAAYDzThJqcnByZMmWKLF68WMLDwxv1M9OmTZMHH3ywXk9Nenq6axsWEmlPpQBapKrGKsUV1VJaaZGS09VSUlkjJRXVtRdL7XWNlFRWS/HpGimtqJHSqho5XWWRcnVdra4tYrE2qhPdrUKCAiQkKFCCAwMkODBQgoPs16HB9vuCggJ/fE6Aulb32Z+jjgPVcwICJCgwQAID1G2xH8uP96nrH4+l9nn2n9PXdY8DRF8C6t1X+/P6NVTvRe21vqhbqkvj7PvU+6jb+rr23+s4Vq+lrvVz9WvaH1MH+vrMn699juP5ztepvV3bhB+Pa9/vx9v1H3D2wNTpinE858xeGvWeDb1mg68b0PSfPXP05cw2n/ma53tdx/2mERJp2FsH2BwDd15u4cKFcu2110pQUJDzPovFoj/swMBAPcxU97GGqFATFxcnRUVFEhsb64FWA/5J/VkprqiREyUVUlBaJafKq+RkWXXtdZWcKquSk+V1r1WYqXFpG1SAiAwNksiQIIkMC7Yf60uwRIQGSXhwkISFBDqvw4LVJch+HVLnWN+uc1z7/NAg++1gFUyCAvRtHVjUF7vZvoQAL9fY72/T9NRcccUVsmXLlnr33XHHHdK9e3f5wx/+cMFAA8A1yipr5EjhaTleXCHHiyslr6RC8updV+rHKmuszXr96LBgiQ0PlpjwEImNqL0+63aILkiMDg+WqND6gSUyzB5kVNgA4F9ME2piYmKkV69e9e6LioqS1q1bn3U/gOZTQ0A5J8vlyKnTcvjUaR1g9HGh/b5T5dWNfi0VPBKjwyQ+MkQSokIlPjJUEqJDJSEyVOKj6lzrx1RQCdE9HQDg06EGgOtUVFvkYEG5ZOeXyv78Msk+USbZ+WVyoKBM8kurLvjzquckNS5C2sSGSVJMmCTHhkubmDBpExOu70uOCdf3q2EeAPAUU4eaZcuWGd0EwOuLb/fnl8quYyWy81iJvlaXo0Wnz1p3o67WUaHSLj5C2qpLqwhpFx+pr/Xt+Ag9/AMA3sbUoQZA/VqXrUeKZPPhItl6tEh25pboQFNtsZ1zaKhTUrR0SoySjNZR0jEpyn6cGKXrWgDAbPjLBZi0B2ZHbrFsPlwomw6rIFMoe/NKpaHZzDFhwdI1JUa6pcRId3WdHCOd20TrOhZm6QDwJYQawATUWiwbD52S1dknZU32SdmYc0oqqs+eXZQSGy592sXpS4/UWB1k1LAR4QWAPyDUAF6ossYi6w+eku/25MsP+wtky+EiqTmjG6ZVZIj0bddK+raLk961121iG7cwJQD4IkIN4CWL1anZRyt2n5AVtUFGrY5bV2pcuAzumKAvl3ZMkIuSoumBAYA6CDWAQWosVll38JR8te2YfLPjuOScPF3vcbW+y+VdEuWyzok6yKjZSIQYADg3Qg3g4fVhVu7J10Fmyc48vWWAg1pmf2BGvFzeNUku75IkPVJjCDEA0ASEGsDN1AaLq/cXyMKsI7Jo6zG9KWPdupgruifL6IuT5addEvUy/wCA5uEvKOAm248W6yDzadZROVZcUW+Gkgoxoy9O0cNK7FEEAK5BqAFcqLyqRv5v01F5f/UhvX5M3W0Fru6TKuMuaSuDMxIkkP2NAMDlCDWAC6iF8FSQWbjxiJRU2oeXQoICZGSPZB1kft49ScKC2QcJANyJUAM0k9Vq08W+r323Xy+I59ChdaTcNLi9/HpAOz2DCQDgGYQaoBmr+3604bC8uTJb73CtBAcGyKiLk+XmwR1k6EWtGV4CAAMQaoAmbBj57g8H5bUV+6Wgdiq22hRywqUd5PahGZISx2q+AGAkQg1wAaWVNfLOqgPy+nfZznVl1EJ4v72so9wwKJ0drQHAS/DXGDjPQnnvrjooryzbK6fKq/V9Ga0j5f4RXWTcJWlMxQYAL0OoARooAP6/zUfl71/ukiOF9q0LOiZGyeSfdybMAIAXI9QAdaiNJJ/7Yodsrl1jJjk2TB66sptc178tYQYAvByhBhCRvOIKeebzHfLppqP6tqqTuWdYJ7nzp50kIpT1ZQDADAg1EH/fKfudVQflhcW7dUGwmol986XtZerIrqwxAwAmQ6iB38rKKZRpH2/RqwErfdNbybPje0mvtnFGNw0A0AyEGvidyhqLzPhmj8xavk+sNpG4iBD5w5ju8ptB6SyaBwAmRqiBX9l6pEge+nCT7Dpeom+r2UxP/KKntGaoCQBMj1ADv6mdmfntXvnX0r1isdqkdVSoPHttbxnTK8XopgEAXIRQA5+XW3Rafv/BRll74JS+fXXvVPnLuIvpnQEAH0OogU/7dudxPdykVgSOCQuWZ6/rLb/sm2Z0swAAbkCogU+qtljl+a92yf+s2K9v924bJ/+6uZ90aB1ldNMAAG5CqIHPyS+tlHv/vd453KR20J52VXcJC2YRPQDwZYQa+NzsprvfWSdHiyr0cNPz1/eRMb1SjW4WAMADCDXwGf+36ag8Mn+TVFRbpVNilPzPbQOlc5too5sFAPAQQg1Mz2azyctL98o/vt6tbw/rmiQv3dRPL6oHAPAfhBqYfv2Zxz/ZJh+sOaRv3315J706cBArAwOA3yHUwLTKq2rk/vc3ypKdeXojyqd/ebHcOiTD6GYBAAxCqIEpFZVXy8S31uhNKcOCA2XmTf1k1MWsDgwA/oxQA9MpKK2UW95Yo3fXbhUZIm9MHCQDOsQb3SwAgMEINTCV48UVMuH11bI3r1QSo8Pkvd9dKt1SYoxuFgDACxBqYBpHCk/Lza/9IAcLyiU1LlwHmk5JTNkGANgRamCaHhpHoElPiJD3f/cTSU+INLpZAAAvQqiBKbY9qBtoPvyvIZIaF2F0swAAXibQ6AYA51NYXiW3vL5a9p0o00NOqoeGQAMAaAihBl6rrLJGJr65RnYeK5GkmDB5/y6GnAAA50aogVeqtljl3vc2yKbDRRIfGaKLgjsmRhndLACAFyPUwCv3cpr28RZZsfuERIQEyVt3DJauyUzbBgCcH6EGXue/F++W+esP660P/nVzP7kkvZXRTQIAmAChBl5l7ppD8tK3e/Xxs9f2lit6JBvdJACASRBq4DV+2F8gf164VR///oouctPg9kY3CQBgIoQaeIWck+Vy33sbpMZqk2v6pskDI7sY3SQAgMkQauAVU7fvemednCyrkl5tY+Xvv+ojAQEBRjcLAGAyhBoYymq1yUMfbtJr0agNKv/n1oESERpkdLMAACZEqIGhZq3YJ19uOyahQYEy+9b+ktaK1YIBAM1DqIFhVu8vkH9+vVsfPz3uYhnQIcHoJgEATIxQA8M2qbz/g41isdrk2n5t5TeD0o1uEgDA5Ag18DgVZB6YlyV5JZXSuU20PDO+F4XBAIAWI9TA415Zule+25Ovt0B4ZUJ/iQoLNrpJAAAfQKiBR204dEr++xt7Hc1fx/diTycAgMsQauDR9WgenJclVpvI+EvS5NcD2hndJACADyHUwGOe+XyHHCgol7S4cHl6XC+jmwMA8DGmCTWvvvqq9OnTR2JjY/VlyJAhsmjRIqObhUZasuO4fLDmkD7+xw19JS4ixOgmAQB8jGlCTbt27WT69Omyfv16WbdunYwYMULGjRsn27ZtM7ppuICC0kr5w0eb9fHvftpRhl6UaHSTAAA+KMBms9nEpBISEuT555+XO++8s8HHKysr9cWhuLhY0tPTpaioSPf2wDMmvbdBPt+SK92SY+STyZdJeAjbIAAAGk99f8fFxV3w+9s0PTV1WSwWmTt3rpSVlelhqHPJzMzUJ8FxUYEGnvX1tmM60AQFBsg/b+hLoAEAuI2pQs2WLVskOjpawsLC5J577pEFCxZIz549z/n8adOm6VTnuOTk5Hi0vf6uuKJaHv9kqz6+62edpFfbOKObBADwYaZa9axbt26SlZWlA8r8+fNl4sSJsnz58nMGGxV+1AXG+NuinXK8uFIyWkfK1JFdjG4OAMDHmSrUhIaGSufOnfXxgAEDZO3atTJjxgyZPXu20U3DGdZkn5T3VttnOz13XW+GnQAAbmeq4aczWa3WeoXA8A6VNRZ57GP7bCe1USWznQAAnmCanhpVHzN27Fhp3769lJSUyPvvvy/Lli2Tr776yuim4Qyvf5ct+0+USVJMmEy7qofRzQEA+AnThJq8vDy57bbbJDc3V89kUgvxqUBz5ZVXGt001HGk8LTM/HaPPv7z1T1YZA8A4DGmCTVvvPGG0U1AIzz3+Q6pqLbK4IwE+WXfNKObAwDwI6auqYF3+X5vvl6TJjBA5KlfXiwBAQFGNwkA4EcINXCJaotVnvrUvmXFrT/pID3TWLEZAOBZhBq4xNv/OSB78kolISpUHryym9HNAQD4IUINWuxUWZXMWGIvDn5kdDeJi6Q4GADgeYQatNjLS/dKSUWNdE+JkRsGsr8WAMAYhBq0SM7Jcnln1UF9/NjY7nrjSgAAjECoQYv84+tdUmWxymWdW8uwrklGNwcA4McINWi2rUeK5JOso/p42tgeTOEGABiKUINmsdls8twXO/Tx+EvSpFfbOKObBADwc4QaNMuKPfnyn30FEhoUKA+NYgo3AMB4hBo0q5fmhcW79fEtP+kg6QmRRjcJAABCDZpu2a4TsimnUMJDAuXe4RcZ3RwAADRCDZrcS/Pf39h7aW4bkiFJMWFGNwkAAI1Qgyb5dmeebD5cJBEhQXL35Z2Mbg4AAE6EGjSpl+bFb+zbIdw2tIMkRtNLAwDwHoQaNNo3O/Jky5EiiQwNkv+6nFoaAIB3IdSgCb009lqaiUMz9G7cAAB4E0INGmX57hOy7Wix7qW562fU0gAAvA+hBo0ya/k+fX3T4Pb00gAAvBKhBheUlVMoP+w/KcGBAXLnTzsa3RwAABpEqMEFzVpm76UZd0lbSWsVYXRzAABoEKEG57XvRKl8tf2YPr5nGLU0AADvRajBeb22Yr/YbCIje7SRLskxRjcHAIBzItTgnPKKK+TjDUf08T3DWJcGAODdCDU4p7f+c0CqLFYZ2CFeBmYkGN0cAADOi1CDBp2ussgHaw7pY/Z4AgCYAaEGDfok64gUlldLu/gIuaJHstHNAQDgggg1aHBLhDn/OaCPJw7JkKDAAKObBADABRFqcJbV2Sdl57ESiQgJkhsGphvdHAAAGoVQg7PM+d7eS3Nt/7YSFxlidHMAAGgUQg3qOVJ4Wr6uXWzv9qEZRjcHAIBGI9SgnndXHRSrTeSyzq2lK4vtAQBMhFADp4pqi8xda5/GfftQNq4EAJgLoQZOn23OdU7jHtG9jdHNAQCgSQg1cJpbu9jeTYPbM40bAGA6hBpoe46XyLqDp3SYuX5AO6ObAwBAkxFqoH2wJkdfq2GnNrHhRjcHAIAmI9RAFwh/vPGwPr55cHujmwMAQLMQaiBfbTumC4TT4sLl8q5JRjcHAIBmIdTAuRv39QPTKRAGAJgWocbPZeeXyQ/7T0pAgMgNg9jnCQBgXoQaP+dYbG941yRp2yrC6OYAANBshBo/VmOxykfrj+jjGwdRIAwAMDdCjR/7bm++5JdWSkJUKCsIAwBMj1DjxxZssPfSXNMnVUKD+VUAAJgb32R+qrSyRr7efkwfX9efFYQBAOZHqPFTi7bkSkW1VTolRUmfdnFGNwcAgBYj1Pipj2uHnq7r11YC1HxuAABMjlDjh44WnpYfsgv08fh+bY1uDgAALkGo8UMLs46IzSZyaccEaRcfaXRzAABwCUKNn7HZbM5ZT9f1p5cGAOA7CDV+ZuuRYtmTVyphwYEytneq0c0BAMBlCDV+5tNN9l6akT2TJTY8xOjmAADgMoQaPxt6+nxzrj7+Zd80o5sDAIBLEWr8yMacQjlaVCFRoUEyrGuS0c0BAMClCDV+5LNN9l6aK3smS3hIkNHNAQDAP0NNZmamDBo0SGJiYqRNmzYyfvx42bVrl9HNMg2r1SZfbLGHmqv7MPQEAPA9pgk1y5cvl0mTJskPP/wgixcvlurqahk1apSUlZUZ3TRT2HDolBwrrpCYsGD5WZdEo5sDAIDLBYtJfPnll/Vuz5kzR/fYrF+/Xi6//PIGf6ayslJfHIqLi8VffVZbIMzQEwDAV5mmp+ZMRUVF+johIeG8Q1ZxcXHOS3p6uvij+kNPrE0DAPBNpgw1VqtVpk6dKpdddpn06tXrnM+bNm2aDj+OS05OjvijdQdPSV5JpcSEB8tPGXoCAPgo0ww/1aVqa7Zu3SorV6487/PCwsL0xd99tvmovh7VM0XCghl6AgD4JtOFmsmTJ8tnn30mK1askHbt2hndHK9n0UNPx/TxLxh6AgD4sGAzrYZ7//33y4IFC2TZsmXSsWNHo5tkChsPnZL8UvvQ02WdGXoCAPiuYDMNOb3//vvyySef6LVqjh2z9z6oAuCIiAijm+e1Fm8/rq9HdG8jocGmLKECAKBRTPMt9+qrr+pi3+HDh0tqaqrzMm/ePKOb5tW9W1/Xhho1lRsAAF8WbKYvaDTNvhOlkp1fJqFBgez1BADweabpqUHTfbXN3ksz5KLWEhMeYnRzAABwK0KNH9TTjLqYoScAgO8j1PiovOIKycop1McjexBqAAC+r1mh5t1339Wr+aalpcnBgwf1fS+++KKemQTvsHiHvZfmkvRWkhwbbnRzAADwvlCjZiE9+OCDctVVV0lhYaFYLBZ9f6tWrXSwgXcNPTHrCQDgL5ocambOnCmvvfaa/OlPf5KgoB+X3B84cKBs2bLF1e1DM5RW1sh/9hbo41GEGgCAn2hyqMnOzpZ+/fqddb/aY6msrMxV7UILLN91QqosVumYGCWd20Qb3RwAALwz1KjtCbKyss66/8svv5QePXq4ql1ogW92/Dj0FBAQYHRzAADwzsX3VD2N2rKgoqJCL4i3Zs0a+eCDDyQzM1Nef/1197QSjWa12mT57hPOrREAAPAXTQ41v/vd7/ReS3/+85+lvLxcbr75Zj0LasaMGfKb3/zGPa1Eo20+UiQny6okJixYBnSIN7o5AAB49zYJEyZM0BcVakpLS6VNG3oEvMXSnXn6+qddEiUkiGWIAAD+o0V7P0VGRuoLvMey2qGn4d3Y6wkA4F+Cm1MofL7i0/3797e0TWimgtJK2XzYvorw8G70ngEA/EuTQ83UqVPr3a6urpaNGzfq2U+PPPKIK9uGJvpuT76ozcx7pMayijAAwO80OdRMmTKlwftffvllWbdunSvahGZausteT8PQEwDAH7msknTs2LHy0Ucfuerl0EQWq01WOOppuhJqAAD+x2WhZv78+ZKQkOCql0MTqVqaU+XVEhMeLP2Zyg0A8ENNHn5SWyTULRRWC/AdO3ZMTpw4Ia+88oqr24dGWrbL3kvzM6ZyAwD8VJNDzfjx4+vdDgwMlKSkJBk+fLh0797dlW1DEyxz1NN0ZdYTAMA/NTnUPPnkk+5pCVo2lftIkT4eRpEwAMBPNSrUFBcXN/oFY2NjW9IeNMPKvUzlBgCgUaGmVatWF9ztWdXWqOdYLBZXtQ2N9P3efGc9DQAA/qpRoWbp0qXubwmaRYXJ7/cW6OOhF7U2ujkAAHh3qBk2bJj7W4JmOVhQLkcKT0tIUIAM7siUegCA/2r2hpZqh+5Dhw5JVVVVvfv79OnjinahCfU0Sv/28RIZ2qL9SQEAMLUmfwuq9WjuuOMOWbRoUYOPU1PjWf/ZZw81l3WmngYA4N8Cm7OhZWFhoaxevVoiIiL0RpZvv/22dOnSRT799FP3tBINslpt8p999noaQg0AwN81uafm22+/lU8++UQGDhyoF97r0KGDXHnllXoqd2Zmplx99dXuaSnOsj23WArLqyU6LFj6toszujkAAJirp6asrEzatLGvWhsfH6+Ho5TevXvLhg0bXN9CXLCe5iedEiSYrREAAH6uyd+E3bp1k127dunjvn37yuzZs+XIkSMya9YsSU1NdUcbcYH1aYZexNATAABNHn6aMmWK5ObmOrdMGDNmjLz33nsSGhoqc+bMcUcb0YCKaousPXBSH/+URfcAAGh6qLnlllucxwMGDJCDBw/Kzp07pX379pKYyJerp2w4dEoqqq2SFBMmXdpEG90cAADMN/y0cuXKercjIyOlf//+BBoP+0/tKsKXXdT6gltYAADgD5ocakaMGCEdO3aUP/7xj7J9+3b3tAqNLhJmKjcAAM0MNUePHpWHHnpIli9fLr169ZJLLrlEnn/+eTl8+HBTXwrNVFZZI1uOFOnjIez3BABA80KNGmaaPHmyfP/997Jv3z65/vrr9eJ7GRkZuhcHnqmnsVht0rZVhLSLjzS6OQAAeIUWLW6ihqEee+wxmT59ul6nRvXewP1W77fPerqUDSwBAGh5qFE9Nffdd59em+bmm2/WQ1Gff/55c18OTbAmuzbUdCLUAADQ7Cnd06ZNk7lz5+raGrU9wowZM2TcuHF6FhQ8sz5NVk6hPh7ckXoaAACaHWpWrFghjzzyiNxwww1M4zaACjRVFvv6NBmtCZIAADQ71KhhJ3jB0FPHBNanAQCgDnZBNJnV2fZF9ygSBgCgPkKNiVTVWGX9wVP6mHoaAADqI9SYyNajRXq/p/jIEPZ7AgDgDIQaE65PMygjQQIDqacBAKBFoWbp0qXnfGz27NlNfTk0wZraeprB1NMAANDyUDNmzBg9pbu6utp5X35+vlxzzTV6dWG4h9oWYd0Bez3NTzpRTwMAgEt6ahYsWCCDBg3Su3SrVYTVasLFxcWSlZXV1JdDI+3ILZaSyhqJDguWHqmxRjcHAADzh5qhQ4fq8KKCTP/+/eXaa6+VBx54QJYtWyYdOnRwTyshq2vXpxmYES9B1NMAAOCaQuHdu3fLunXrpF27dhIcHCy7du2S8vLy5rwUGmlD7VRuVSQMAABcEGrUjtxDhgzR+z5t3bpV1qxZIxs3bpQ+ffrIqlWrmvpyaKQNh+yhpn/7eKObAgCAb4QatYHlwoULZebMmRIeHq6HoVSwue6662T48OHuaaWfO1p4WnKLKvSwU9/0OKObAwCAb+z9tGXLlrM2sgwJCZHnn39efvGLX7iybTijl6ZHaoxEhjb5IwMAwC80uafmfDtzDxs2rKXtQQMcWyMw9AQAwLmxorAJbDhUqK8HdCDUAABwLoQaL1dRbZFtR4r0MT01AAD4SKhZsWKFXrk4LS1NAgICdMGyr9typEhqrDZJigmTdvERRjcHAACvZapQU1ZWJn379pWXX35Z/K+eppUOcgAAoGGmmkozduxYffHHRfeopwEAwIdCTVNVVlbqi4Pan8pMbDabs0iYehoAAHxo+KmpMjMzJS4uznlJT08XM8k5eVrySyslJChAerVl0T0AAPw21EybNk2Kioqcl5ycHDHjonsXp8VJeEiQ0c0BAMCr+fTwU1hYmL6YvUiYehoAAPy8p8bs2MQSAAAf7akpLS2VvXv3Om9nZ2dLVlaWJCQkSPv27cWXlFfVyI5ce2Fz/w6tjG4OAABez1ShZt26dfLzn//cefvBBx/U1xMnTpQ5c+aIL9l6pFisNpGU2HBJjWPRPQAAfCrUDB8+XE9z9gebD9uncvdpx6wnAAAag5oaL7XpsH2/p77pDD0BANAYhBovRU8NAABNQ6jxQoXlVXKwoFwf92lLTw0AAI1BqPFCm2uHnjJaR0pcZIjRzQEAwBQINV499EQvDQAAjUWo8UJZOfaeGuppAABoPEKNF/fUMPMJAIDGI9R4mWNFFZJXUimBAWojy1ijmwMAgGkQarzMptpemq7JMRIZaqq1EQEAMBShxsuwPg0AAM1DqPHS6dzMfAIAoGkINV5E7WvlCDV9CTUAADQJocaLqFWEi05XS2hQoHRLiTG6OQAAmAqhxguLhHukxUpoMB8NAABNwTenF/lx6IkiYQAAmopQ40W2HLGHmt5tCTUAADQVocZLWK022XG0WB/3ItQAANBkhBovkXOqXEoqa3QtTec20UY3BwAA0yHUeIlttb003ZJjJCSIjwUAgKbi29NLbDtqr6dhvycAAJqHUONlPTWEGgAAmodQ4yW214aanoQaAACahVDjBU6UVEpeSaUEBIh0TyHUAADQHIQaL6qn6ZgYJVFhwUY3BwAAUyLUeFU9DevTAADQXIQaL6qnoUgYAIDmI9R4AaZzAwDQcoQag5VUVMuBgnJ9zPATAADNR6gx2I7cEn2dGhcuCVGhRjcHAADTItQYjKEnAABcg1DjJTOfejL0BABAixBqDMb2CAAAuAahxkCVNRbZc9xeU0OoAQCgZQg1BtpzvFRqrDaJiwiRtq0ijG4OAACmRqgx0PZc+9BTj9QYCVAbPwEAgGYj1Bho1zH70BObWAIA0HKEGq8INTFGNwUAANMj1BhoZ22o6UaoAQCgxQg1BikorZT80kp93DWZUAMAQEsRagweemqfEClRYcFGNwcAANMj1Bg89EQ9DQAArkGoMQhFwgAAuBahxiA7j9nXqOnGdG4AAFyCUGMAq9Umu4+X6mNmPgEA4BqEGgMcOlkup6stEhocKBmtI41uDgAAPoFQY2CRcJc20RIcxEcAAIAr8I1qYJEwQ08AALgOocYAu47bi4SZ+QQAgOsQagxdo4aZTwAAuAqhxsMqqi1yIL9MH9NTAwCA6xBqPGxvXqlYbSLxkSGSFBNmdHMAAPAZhBoDd+YOCAgwujkAAPgMQo2H7cx1FAlTTwMAgCsRajxs13GmcwMA4A6EGg9jjRoAANyDUONBRaerJa+k0rmaMAAA8ONQ8/LLL0tGRoaEh4fLpZdeKmvWrBEzzXxSUuPCJSY8xOjmAADgU0wVaubNmycPPvigPPnkk7Jhwwbp27evjB49WvLy8sQM9ubZh54600sDAIB/h5oXXnhB7rrrLrnjjjukZ8+eMmvWLImMjJQ333xTzGDPcXtPDaEGAAA/DjVVVVWyfv16GTlypPO+wMBAfXvVqlUN/kxlZaUUFxfXuxhp7wl7qOnShiJhAAD8NtTk5+eLxWKR5OTkever28eOHWvwZzIzMyUuLs55SU9PFyPRUwMAgPuYJtQ0x7Rp06SoqMh5ycnJMawtZZU1cqTwtD5m5hMAAK4XLCaRmJgoQUFBcvz48Xr3q9spKSkN/kxYWJi+eIP9J+ybWLaOCpX4qFCjmwMAgM8xTU9NaGioDBgwQJYsWeK8z2q16ttDhgwRb7eHmU8AALiVaXpqFDWde+LEiTJw4EAZPHiwvPjii1JWVqZnQ5lljZouyYQaAADE30PNjTfeKCdOnJAnnnhCFwdfcskl8uWXX55VPOyN9tSGms5JhBoAAMTfQ40yefJkfTGbH3tqmM4NAIBf19SYWWWNRQ4W2AuFmfkEAIB7EGo8IDu/TKw2kZjwYEmK8Y7ZWAAA+BpCjQcX3VO9NAEBAUY3BwAAn0So8WA9DdO5AQBwH0KNJ4uE2fMJAAC3IdR4sqeGNWoAAHAbQo2b1Vissj+fNWoAAHA3Qo2bHTxZLtUWm0SEBEnbVhFGNwcAAJ9FqPHQ0NNFbaIkMJCZTwAAuAuhxlP1NAw9AQDgVoQaN9t3guncAAB4AqHGA6sJKx0TCTUAALgTocZDoaZTUpTRTQEAwKcRatzoZFmVFJZX6+OM1oQaAADciVDjRtm169OkxYVLRGiQ0c0BAMCnEWrcaN8Jx9AT9TQAALgbocYjRcIMPQEA4G6EGjfKdvbUEGoAAHA3Qo0bOfZ8oqcGAAD3I9S4icVqkwMF5fq4E2vUAADgdoQaNzlaeFqqaqwSGhQobePZyBIAAHcj1LjJ/toi4Q6tIyWIjSwBAHA7Qo2bZNfu+UQ9DQAAnhHsoffx254a1qgBAPezWCxSXW1fwR3mExISIkFBLV+kllDj7j2f6KkBALex2Wxy7NgxKSwsNLopaKFWrVpJSkqKBAQ0v2SDUOMm+1mjBgDczhFo2rRpI5GRkS36QoRxwbS8vFzy8vL07dTU1Ga/FqHGDSqqLXK06LQ+pqYGANw35OQINK1btza6OWiBiAj7LGEVbNTn2dyhKAqF3eBAQZnYbCKx4cGSEBVqdHMAwCc5amhUDw3Mz/E5tqQ2ilDj1qGnaLpCAcDN+DvrGwJc8DkSatyAImEAADyPUOPGnhrqaQAARrr99ttl/PjxztvDhw+XqVOnerwdy5Yt0z0x7p6lRqhx40aWrFEDADhX2FBf8uoSGhoqnTt3lr/85S9SU1Pj1vf9+OOP5a9//atXBRFXYvaTG4ef6KkBAJzLmDFj5K233pLKykr54osvZNKkSXoRumnTptV7XlVVlQ4+rpCQkCC+jJ4aFztVViWF5fbKbUINABiw5klVjSEX9d5NERYWpheb69Chg9x7770ycuRI+fTTT51DRs8++6ykpaVJt27d9PNzcnLkhhtu0IvUqXAybtw4OXDgQL0p7g8++KB+XE1xf/TRR89q05nDTypQ/eEPf5D09HTdHtVj9MYbb+jX/fnPf66fEx8fr3tsVLsUq9UqmZmZ0rFjRz0Vu2/fvjJ//vx676NCWteuXfXj6nXqttOd6KlxsewCey9NSmy4RIS2fMlnAEDjna62SM8nvjLkvbf/ZbREhjb/a1UFgIKCAn28ZMkSiY2NlcWLFzunOY8ePVqGDBki3333nQQHB8szzzyje3s2b96se3L++c9/ypw5c+TNN9+UHj166NsLFiyQESNGnPM9b7vtNlm1apW89NJLOpxkZ2dLfn6+DjkfffSR/OpXv5Jdu3bptjjWklGB5t///rfMmjVLunTpIitWrJBbbrlFkpKSZNiwYTp8XXfddbrn6e6775Z169bJQw89JJ5AqHGxQwXlzt25AQC4ENWbokLMV199Jffff7+cOHFCoqKi5PXXX3cOO6kQoXpI1H2Oqc9q6Er1yqjal1GjRsmLL76oh65UoFBU6FCveS67d++WDz/8UAcn1UukdOrU6ayhKrUYnnofR8/Oc889J998840OWI6fWblypcyePVuHmldffVUuuugiHaoU1dO0ZcsW+dvf/ibuRqhxsYOEGgAwTERIkO4xMeq9m+Kzzz6T6Oho3QujAsvNN98sTz31lO7h6N27d706mk2bNsnevXslJiam3mtUVFTIvn37pKioSHJzc+XSSy91PqZ6cwYOHHjOYbGsrCy9cq8KIo2l2qC2NLjyyivPqvvp16+fPt6xY0e9diiOAORuhBoXO1g7/NShNfU0AOBpqhejJUNAnqRqTVSvhgovqnZGhRAH1VNTV2lpqQwYMEDee++9s15HDfs0R0TtcFJTqHYon3/+ubRt27beY6omx2jm+ORN5OBJemoAABemgosqzG2M/v37y7x58/RQkKpvaUhqaqqsXr1aLr/8cn1bTQ9fv369/tmGqN4g1UO0fPly5/BTXY6eIlWA7NCzZ08dXg4dOnTOHh5Vz6MKnuv64YcfxBOY/eSunpoEemoAAK4xYcIESUxM1DOeVKGwKuhVtTS///3v5fDhw/o5U6ZMkenTp8vChQtl586dct999513jZmMjAyZOHGi/Pa3v9U/43hNVWejqFlZqudLDZOpOh/VS6OGvx5++GF54IEH5O2339ZDXxs2bJCZM2fq28o999wje/bskUceeUQXGb///vu6gNkTCDUuVFpZI/mlVfq4PT01AAAXbvaoZhm1b99eFwKr3pA777xT19Q4em4eeughufXWW3VQUTUsKoBce+21531dNfz161//Wgeg7t27y1133SVlZfb/OFfDS08//bQ89thjkpycLJMnT9b3q8X7Hn/8cT0LSrVDzcBSw1Fqirei2qhmTqmgpGZUqYJlVVzsCQG2pk6sN7Hi4mKJi4vTBVXn6r5rie1Hi+Wql76T+MgQ2fjEKJe/PgDgR+oLXfUuqC/T8PBwo5sDN36ejf3+pqfGhSgSBgDAOIQaF6JIGAAA4xBq3LFGTQKhBgAATyPUuBDDTwAAGIdQ40KsJgwAgHEINS5SWWORo0Wn9TE9NQAAeB6hxkUOnzotanJ8ZGiQJEb/uF8HAADwDEKNy3fnjnLuoAoAADyHUOMiB5zbI1BPAwCAEQg1LkKRMAAAxiLUuAjTuQEAjaFKFM53eeqpp4xuomkFG90AX8FqwgCAxsjNzXUez5s3T5544gm9m7VDdHS081htz2ixWCQ4mK/rxqCnxgUsVpscPumYzk2oAQDDqGmoVWXGXBq5P3RKSorzojZpVL0zjts7d+7Uu2svWrRIBgwYIGFhYbJy5Uq5/fbbZfz48fVeZ+rUqTJ8+HDnbavVqnfOVhtCRkRE6B2y58+fL/6E6OcCuUWnpcpilZCgAEmNizC6OQDgv6rLRZ5LM+a9/3hUJNQ1JQiPPfaY/OMf/5BOnTpJfHx8o34mMzNT/v3vf8usWbOkS5cusmLFCrnlllskKSlJhg0bJv7ANKHm2Weflc8//1yysrIkNDRUCgsLxdumc6fHR0pQINO5AQAt85e//EWuvPLKRj+/srJSnnvuOfnmm29kyJAh+j4ViFQvz+zZswk13qaqqkquv/56/WG98cYb4k0OMPMJALxDSKS9x8So93aRgQMHNun5e/fulfLy8rOCkPru7Nevn/gL04Sap59+Wl/PmTNHvM3Bk8x8AgCvoBY/ddEQkJGiour/GwIDA3XRcF3V1dXO49LSUn2tRjTatm1b73mqLsdfmCbUNIfqjlMXh+LiYjevJkxPDQDA9VRdzNatW+vdp8oxQkJC9HHPnj11eDl06JDfDDX53ewnVTSlKssdl/T0dLe8T1WNVdfSEGoAAO4wYsQIWbdunbzzzjuyZ88eefLJJ+uFHDVj6uGHH5YHHnhA3n77bdm3b59s2LBBZs6cqW/7C0NDjaruvtAiRGp6W3NNmzZNioqKnJecnBxxhzduHyQ7/zpGftYlyS2vDwDwb6NHj5bHH39cHn30URk0aJCUlJTIbbfdVu85f/3rX/Vz1H/Q9+jRQ8aMGaOHo9QUb38RYDtzkM6DTpw4IQUFBed9jqreVrOdHFRNjZqb35zZT2r4SfXYqIATGxvbrDYDALxDRUWFZGdn6y/t8PBwo5sDN36ejf3+DjZ6jFBdAAAA/KZQWBU/nTx5Ul+rJaNVgZTSuXPnektKAwAA/2SaUKP2xqhb7OSYd7906dJ6y0QDAAD/ZJrZT6qWRpX/nHkh0AAAAFOFGgAAGmLgfBd42edIqAEAmJJj4Tm1PQDMz/E5Oj5Xn66pAQCgrqCgIGnVqpXk5eXp25GRkXp9M5ivh0YFGvU5qs9Tfa7NRagBAJhWSkqKvnYEG5iXCjSOz7O5CDUAANNSPTOpqanSpk2behs8wlzUkFNLemgcCDUAANNTX4iu+FKEuVEoDAAAfAKhBgAA+ARCDQAA8AnB/riwj9rtEwAAmIPje/tCC/T5VagpKSnR1+np6UY3BQAANON7PC4u7pyPB9j8aH1pq9UqR48elZiYGJcu0KQSpApKOTk5Ehsb67LXxdk4157BefYMzrNncJ7Nf55VVFGBJi0tTQIDz10541c9NepEtGvXzm2vrz5E/g/jGZxrz+A8ewbn2TM4z+Y+z+froXGgUBgAAPgEQg0AAPAJhBoXCAsLkyeffFJfw704157BefYMzrNncJ795zz7VaEwAADwXfTUAAAAn0CoAQAAPoFQAwAAfAKhBgAA+ARCjQu8/PLLkpGRIeHh4XLppZfKmjVrjG6SqaxYsUKuueYavVKkWul54cKF9R5XtexPPPGEpKamSkREhIwcOVL27NlT7zknT56UCRMm6AWfWrVqJXfeeaeUlpZ6+F/i3TIzM2XQoEF6Re02bdrI+PHjZdeuXfWeU1FRIZMmTZLWrVtLdHS0/OpXv5Ljx4/Xe86hQ4fk6quvlsjISP06jzzyiNTU1Hj4X+O9Xn31VenTp49zAbIhQ4bIokWLnI9zjt1j+vTp+u/H1KlTnfdxrlvuqaee0ue17qV79+7ee47V7Cc039y5c22hoaG2N99807Zt2zbbXXfdZWvVqpXt+PHjRjfNNL744gvbn/70J9vHH3+sZuLZFixYUO/x6dOn2+Li4mwLFy60bdq0yfbLX/7S1rFjR9vp06edzxkzZoytb9++th9++MH23Xff2Tp37my76aabDPjXeK/Ro0fb3nrrLdvWrVttWVlZtquuusrWvn17W2lpqfM599xzjy09Pd22ZMkS27p162w/+clPbEOHDnU+XlNTY+vVq5dt5MiRto0bN+rPLjEx0TZt2jSD/lXe59NPP7V9/vnntt27d9t27dpl++Mf/2gLCQnR513hHLvemjVrbBkZGbY+ffrYpkyZ4ryfc91yTz75pO3iiy+25ebmOi8nTpzw2nNMqGmhwYMH2yZNmuS8bbFYbGlpabbMzExD22VWZ4Yaq9VqS0lJsT3//PPO+woLC21hYWG2Dz74QN/evn27/rm1a9c6n7No0SJbQECA7ciRIx7+F5hHXl6ePm/Lly93nlf15fu///u/zufs2LFDP2fVqlX6tvqDFBgYaDt27JjzOa+++qotNjbWVllZacC/whzi4+Ntr7/+OufYDUpKSmxdunSxLV682DZs2DBnqOFcuy7UqP9gbIg3nmOGn1qgqqpK1q9fr4dD6u4vpW6vWrXK0Lb5iuzsbDl27Fi9c6z2/1DDfI5zrK7VkNPAgQOdz1HPV5/F6tWrDWm3GRQVFenrhIQEfa1+l6urq+uda9XN3L59+3rnunfv3pKcnOx8zujRo/VGdtu2bfP4v8HbWSwWmTt3rpSVlelhKM6x66mhDzW0UfecKpxr11HD/ao8oFOnTnqYXw0nees59qsNLV0tPz9f/9Gq+2Ep6vbOnTsNa5cvUYFGaegcOx5T12qctq7g4GD9Ze14Ds7esV7VHlx22WXSq1cvfZ86V6GhoTognu9cN/RZOB6D3ZYtW3SIUfUGqs5gwYIF0rNnT8nKyuIcu5AKjBs2bJC1a9ee9Ri/z66h/gNyzpw50q1bN8nNzZWnn35afvazn8nWrVu98hwTagA//a9b9Udp5cqVRjfFJ6kvABVgVG/Y/PnzZeLEibJ8+XKjm+VTcnJyZMqUKbJ48WI9SQPuMXbsWOexKoBXIadDhw7y4Ycf6okb3obhpxZITEyUoKCgsyq91e2UlBTD2uVLHOfxfOdYXefl5dV7XFXWqxlRfA5nmzx5snz22WeydOlSadeunfN+da7UkGphYeF5z3VDn4XjMdip/3rt3LmzDBgwQM8669u3r8yYMYNz7EJq6EP9/75///66Z1ZdVHB86aWX9LHqDeBcu57qlenatavs3bvXK3+fCTUt/MOl/mgtWbKkXre+uq26ntFyHTt21L/4dc+xGotVtTKOc6yu1f+p1B85h2+//VZ/Fuq/KmCn6rBVoFFDIer8qHNbl/pdDgkJqXeu1ZRvNX5e91yroZW6IVL9l7KauqyGV9Aw9btYWVnJOXahK664Qp8n1SPmuKi6OlXz4TjmXLueWipj3759eokNr/x9dnnpsR9O6VYzcebMmaNn4dx99916SnfdSm9cePaCmuqnLupX8oUXXtDHBw8edE7pVuf0k08+sW3evNk2bty4Bqd09+vXz7Z69WrbypUr9WwIpnTXd++99+qp8cuWLas3PbO8vLze9Ew1zfvbb7/V0zOHDBmiL2dOzxw1apSeFv7ll1/akpKSmAJbx2OPPaZnlGVnZ+vfV3VbzcT7+uuv9eOcY/epO/tJ4Vy33EMPPaT/Zqjf5++//15PzVZTstXsSW88x4QaF5g5c6b+UNV6NWqKt1orBY23dOlSHWbOvEycONE5rfvxxx+3JScn6wB5xRVX6PU/6iooKNAhJjo6Wk8VvOOOO3RYwo8aOsfqotaucVBB8b777tNTkCMjI23XXnutDj51HThwwDZ27FhbRESE/uOm/uhVV1cb8C/yTr/97W9tHTp00H8P1B9v9fvqCDQK59hzoYZz3XI33nijLTU1Vf8+t23bVt/eu3ev157jAPU/ru//AQAA8CxqagAAgE8g1AAAAJ9AqAEAAD6BUAMAAHwCoQYAAPgEQg0AAPAJhBoAAOATCDUAAMAnEGoA+JWMjAx58cUXjW4GADcg1ABwm9tvv13Gjx+vj4cPHy5Tp0712HvPmTNH7yh8prVr18rdd9/tsXYA8JxgD74XALRYVVWVhIaGNvvnk5KSXNoeAN6DnhoAHumxWb58ucyYMUMCAgL05cCBA/qxrVu3ytixYyU6OlqSk5Pl1ltvlfz8fOfPqh6eyZMn616exMREGT16tL7/hRdekN69e0tUVJSkp6fLfffdJ6WlpfqxZcuWyR133CFFRUXO93vqqacaHH46dOiQjBs3Tr9/bGys3HDDDXL8+HHn4+rnLrnkEnn33Xf1z8bFxclvfvMbKSkp8dj5A9A4hBoAbqfCzJAhQ+Suu+6S3NxcfVFBpLCwUEaMGCH9+vWTdevWyZdffqkDhQoWdb399tu6d+b777+XWbNm6fsCAwPlpZdekm3btunHv/32W3n00Uf1Y0OHDtXBRYUUx/s9/PDDZ7XLarXqQHPy5EkduhYvXiz79++XG2+8sd7z9u3bJwsXLpTPPvtMX9Rzp0+f7tZzBqDpGH4C4Haqd0OFksjISElJSXHe/69//UsHmueee85535tvvqkDz+7du6Vr1676vi5dusjf//73eq9Ztz5H9aA888wzcs8998grr7yi30u9p+qhqft+Z1qyZIls2bJFsrOz9Xsq77zzjlx88cW69mbQoEHO8KNqdGJiYvRt1ZukfvbZZ5912TkC0HL01AAwzKZNm2Tp0qV66Mdx6d69u7N3xGHAgAFn/ew333wjV1xxhbRt21aHDRU0CgoKpLy8vNHvv2PHDh1mHIFG6dmzpy4wVo/VDU2OQKOkpqZKXl5es/7NANyHnhoAhlE1MNdcc4387W9/O+sxFRwcVN1MXaoe5xe/+IXce++9urckISFBVq5cKXfeeacuJFY9Qq4UEhJS77bqAVK9NwC8C6EGgEeoISGLxVLvvv79+8tHH32ke0KCgxv/52j9+vU6VPzzn//UtTXKhx9+eMH3O1OPHj0kJydHXxy9Ndu3b9e1PqrHBoC5MPwEwCNUcFm9erXuZVGzm1QomTRpki7Svemmm3QNixpy+uqrr/TMpfMFks6dO0t1dbXMnDlTF/aqmUmOAuK676d6glTti3q/hoalRo4cqWdQTZgwQTZs2CBr1qyR2267TYYNGyYDBw50y3kA4D6EGgAeoWYfBQUF6R4QtVaMmkqdlpamZzSpADNq1CgdMFQBsKppcfTANKRv3756SrcaturVq5e89957kpmZWe85agaUKhxWM5nU+51ZaOwYRvrkk08kPj5eLr/8ch1yOnXqJPPmzXPLOQDgXgE2m83m5vcAAABwO3pqAACATyDUAAAAn0CoAQAAPoFQAwAAfAKhBgAA+ARCDQAA8AmEGgAA4BMINQAAwCcQagAAgE8g1AAAAJ9AqAEAAOIL/h+oixiePn6U0QAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "### Function minimization with automatic differentiation and SGD ###\n", "\n", @@ -640,7 +761,7 @@ "for i in range(500):\n", " with tf.GradientTape() as tape:\n", " '''TODO: define the loss as described above'''\n", - " loss = # TODO\n", + " loss = tf.square(x-x_f)\n", "\n", " # loss minimization using gradient tape\n", " grad = tape.gradient(loss, x) # compute the derivative of the loss with respect to x\n", @@ -681,8 +802,16 @@ "name": "python3" }, "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.9.6" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.7" }, "vscode": { "interpreter": { diff --git a/lab1/TF_Part2_Music_Generation.ipynb b/lab1/TF_Part2_Music_Generation.ipynb index 63941f0c..276a3c48 100644 --- a/lab1/TF_Part2_Music_Generation.ipynb +++ b/lab1/TF_Part2_Music_Generation.ipynb @@ -70,12 +70,172 @@ "metadata": { "id": "riVZCVK65QTH" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting comet_ml\n", + " Downloading comet_ml-3.54.1-py3-none-any.whl.metadata (4.0 kB)\n", + "Collecting dulwich!=0.20.33,>=0.20.6 (from comet_ml)\n", + " Downloading dulwich-0.24.10-cp313-cp313-win_amd64.whl.metadata (5.5 kB)\n", + "Collecting everett<3.2.0,>=1.0.1 (from everett[ini]<3.2.0,>=1.0.1->comet_ml)\n", + " Downloading everett-3.1.0-py2.py3-none-any.whl.metadata (17 kB)\n", + "Requirement already satisfied: jsonschema!=3.1.0,>=2.6.0 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from comet_ml) (4.25.1)\n", + "Requirement already satisfied: psutil>=5.6.3 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from comet_ml) (7.1.0)\n", + "Collecting python-box<7.0.0 (from comet_ml)\n", + " Downloading python_box-6.1.0-py3-none-any.whl.metadata (7.8 kB)\n", + "Collecting requests-toolbelt>=0.8.0 (from comet_ml)\n", + " Using cached requests_toolbelt-1.0.0-py2.py3-none-any.whl.metadata (14 kB)\n", + "Requirement already satisfied: requests>=2.18.4 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from comet_ml) (2.32.5)\n", + "Requirement already satisfied: rich>=13.3.2 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from comet_ml) (14.1.0)\n", + "Collecting semantic-version>=2.8.0 (from comet_ml)\n", + " Downloading semantic_version-2.10.0-py2.py3-none-any.whl.metadata (9.7 kB)\n", + "Requirement already satisfied: sentry-sdk>=1.1.0 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from comet_ml) (2.44.0)\n", + "Requirement already satisfied: setuptools in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from comet_ml) (80.9.0)\n", + "Collecting simplejson (from comet_ml)\n", + " Downloading simplejson-3.20.2-cp313-cp313-win_amd64.whl.metadata (3.4 kB)\n", + "Requirement already satisfied: urllib3>=1.26.8 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from comet_ml) (2.5.0)\n", + "Requirement already satisfied: wrapt>=1.11.2 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from comet_ml) (1.17.3)\n", + "Collecting wurlitzer>=1.0.2 (from comet_ml)\n", + " Downloading wurlitzer-3.1.1-py3-none-any.whl.metadata (2.5 kB)\n", + "Collecting configobj (from everett[ini]<3.2.0,>=1.0.1->comet_ml)\n", + " Downloading configobj-5.0.9-py2.py3-none-any.whl.metadata (3.2 kB)\n", + "Requirement already satisfied: attrs>=22.2.0 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from jsonschema!=3.1.0,>=2.6.0->comet_ml) (25.3.0)\n", + "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from jsonschema!=3.1.0,>=2.6.0->comet_ml) (2025.9.1)\n", + "Requirement already satisfied: referencing>=0.28.4 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from jsonschema!=3.1.0,>=2.6.0->comet_ml) (0.37.0)\n", + "Requirement already satisfied: rpds-py>=0.7.1 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from jsonschema!=3.1.0,>=2.6.0->comet_ml) (0.29.0)\n", + "Requirement already satisfied: charset_normalizer<4,>=2 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from requests>=2.18.4->comet_ml) (3.4.3)\n", + "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from requests>=2.18.4->comet_ml) (3.10)\n", + "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from requests>=2.18.4->comet_ml) (2025.8.3)\n", + "Requirement already satisfied: markdown-it-py>=2.2.0 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from rich>=13.3.2->comet_ml) (4.0.0)\n", + "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from rich>=13.3.2->comet_ml) (2.19.2)\n", + "Requirement already satisfied: mdurl~=0.1 in c:\\users\\lucas\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from markdown-it-py>=2.2.0->rich>=13.3.2->comet_ml) (0.1.2)\n", + "Downloading comet_ml-3.54.1-py3-none-any.whl (775 kB)\n", + " ---------------------------------------- 0.0/775.1 kB ? eta -:--:--\n", + " --------------------------- ------------ 524.3/775.1 kB 4.8 MB/s eta 0:00:01\n", + " ---------------------------------------- 775.1/775.1 kB 4.5 MB/s 0:00:00\n", + "Downloading everett-3.1.0-py2.py3-none-any.whl (35 kB)\n", + "Downloading python_box-6.1.0-py3-none-any.whl (27 kB)\n", + "Downloading dulwich-0.24.10-cp313-cp313-win_amd64.whl (919 kB)\n", + " ---------------------------------------- 0.0/919.4 kB ? eta -:--:--\n", + " ---------------------------------- ----- 786.4/919.4 kB 4.0 MB/s eta 0:00:01\n", + " ---------------------------------------- 919.4/919.4 kB 3.1 MB/s 0:00:00\n", + "Using cached requests_toolbelt-1.0.0-py2.py3-none-any.whl (54 kB)\n", + "Downloading semantic_version-2.10.0-py2.py3-none-any.whl (15 kB)\n", + "Downloading wurlitzer-3.1.1-py3-none-any.whl (8.6 kB)\n", + "Downloading configobj-5.0.9-py2.py3-none-any.whl (35 kB)\n", + "Downloading simplejson-3.20.2-cp313-cp313-win_amd64.whl (75 kB)\n", + "Installing collected packages: everett, wurlitzer, simplejson, semantic-version, python-box, dulwich, configobj, requests-toolbelt, comet_ml\n", + "\n", + " ---- ----------------------------------- 1/9 [wurlitzer]\n", + " -------- ------------------------------- 2/9 [simplejson]\n", + " -------- ------------------------------- 2/9 [simplejson]\n", + " -------- ------------------------------- 2/9 [simplejson]\n", + " -------- ------------------------------- 2/9 [simplejson]\n", + " -------- ------------------------------- 2/9 [simplejson]\n", + " -------- ------------------------------- 2/9 [simplejson]\n", + " ----------------- ---------------------- 4/9 [python-box]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " ---------------------- ----------------- 5/9 [dulwich]\n", + " -------------------------- ------------- 6/9 [configobj]\n", + " ------------------------------- -------- 7/9 [requests-toolbelt]\n", + " ------------------------------- -------- 7/9 [requests-toolbelt]\n", + " ------------------------------- -------- 7/9 [requests-toolbelt]\n", + " ------------------------------- -------- 7/9 [requests-toolbelt]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ----------------------------------- ---- 8/9 [comet_ml]\n", + " ---------------------------------------- 9/9 [comet_ml]\n", + "\n", + "Successfully installed comet_ml-3.54.1 configobj-5.0.9 dulwich-0.24.10 everett-3.1.0 python-box-6.1.0 requests-toolbelt-1.0.0 semantic-version-2.10.0 simplejson-3.20.2 wurlitzer-3.1.1\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\lucas\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "Gym has been unmaintained since 2022 and does not support NumPy 2.0 amongst other critical functionality.\n", + "Please upgrade to Gymnasium, the maintained drop-in replacement of Gym, or contact the authors of your software and request that they upgrade.\n", + "Users of this version of Gym should be able to simply replace 'import gym' with 'import gymnasium as gym' in the vast majority of cases.\n", + "See the migration guide at https://gymnasium.farama.org/introduction/migration_guide/ for additional information.\n", + "'apt-get' n�o � reconhecido como um comando interno\n", + "ou externo, um programa oper�vel ou um arquivo em lotes.\n" + ] + } + ], "source": [ - "!pip install comet_ml > /dev/null 2>&1\n", + "!pip install comet_ml\n", "import comet_ml\n", "# TODO: ENTER YOUR API KEY HERE!! instructions above\n", - "COMET_API_KEY = \"\"\n", + "COMET_API_KEY = input(\"Enter your Comet API key: \")\n", "\n", "# Import Tensorflow 2.0\n", "import tensorflow as tf\n", @@ -92,7 +252,7 @@ "from IPython import display as ipythondisplay\n", "from tqdm import tqdm\n", "from scipy.io.wavfile import write\n", - "!apt-get install abcmidi timidity > /dev/null 2>&1\n", + "!apt-get install abcmidi timidity\n", "\n", "\n", "# Check that we are using a GPU, if not switch runtimes\n", @@ -116,11 +276,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "id": "P7dFnP5q3Jve" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found 817 songs in text\n", + "\n", + "Example song: \n", + "X:1\n", + "T:Alexander's\n", + "Z: id:dc-hornpipe-1\n", + "M:C|\n", + "L:1/8\n", + "K:D Major\n", + "(3ABc|dAFA DFAd|fdcd FAdf|gfge fefd|(3efe (3dcB A2 (3ABc|!\n", + "dAFA DFAd|fdcd FAdf|gfge fefd|(3efe dc d2:|!\n", + "AG|FAdA FAdA|GBdB GBdB|Acec Acec|dfaf gecA|!\n", + "FAdA FAdA|GBdB GBdB|Aceg fefd|(3efe dc d2:|!\n" + ] + } + ], "source": [ "# Download the dataset\n", "songs = mdl.lab1.load_training_data()\n", @@ -142,7 +322,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "id": "11toYzhEEKDz" }, @@ -163,11 +343,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "id": "IlCgQBRVymwR" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "There are 83 unique characters in the dataset\n" + ] + } + ], "source": [ "# Join our list of song strings into a single string containing all songs\n", "songs_joined = \"\\n\\n\".join(songs)\n", @@ -205,7 +393,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "id": "IalZLbvOzf-F" }, @@ -235,11 +423,41 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "id": "FYyNlCNXymwY" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " '\\n': 0,\n", + " ' ' : 1,\n", + " '!' : 2,\n", + " '\"' : 3,\n", + " '#' : 4,\n", + " \"'\" : 5,\n", + " '(' : 6,\n", + " ')' : 7,\n", + " ',' : 8,\n", + " '-' : 9,\n", + " '.' : 10,\n", + " '/' : 11,\n", + " '0' : 12,\n", + " '1' : 13,\n", + " '2' : 14,\n", + " '3' : 15,\n", + " '4' : 16,\n", + " '5' : 17,\n", + " '6' : 18,\n", + " '7' : 19,\n", + " ...\n", + "}\n" + ] + } + ], "source": [ "print('{')\n", "for char,_ in zip(char2idx, range(20)):\n", @@ -249,7 +467,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "id": "g-LnKyu4dczc" }, @@ -266,7 +484,8 @@ " the number of characters in the input string\n", "'''\n", "def vectorize_string(string):\n", - " '''TODO'''\n", + " return np.array([char2idx[c] for c in string])\n", + "\n", "\n", "vectorized_songs = vectorize_string(songs_joined)" ] @@ -282,11 +501,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "id": "l1VKcQHcymwb" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "'X:1\\nT:Alex' ---- characters mapped to int ----> [49 22 13 0 45 22 26 67 60 79]\n" + ] + } + ], "source": [ "print ('{} ---- characters mapped to int ----> {}'.format(repr(songs_joined[:10]), vectorized_songs[:10]))\n", "# check that vectorized_songs is a numpy array\n", @@ -310,11 +537,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "metadata": { "id": "LF-N8F7BoDRi" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[PASS] test_batch_func_types\n", + "[PASS] test_batch_func_shapes\n", + "[PASS] test_batch_func_next_step\n", + "======\n", + "[PASS] passed all tests!\n" + ] + } + ], "source": [ "### Batch definition to create training examples ###\n", "\n", @@ -325,10 +564,10 @@ " idx = np.random.choice(n-seq_length, batch_size)\n", "\n", " '''TODO: construct a list of input sequences for the training batch'''\n", - " input_batch = # TODO\n", + " input_batch = [vectorized_songs[id:id+seq_length] for id in idx]\n", "\n", " '''TODO: construct a list of output sequences for the training batch'''\n", - " output_batch = # TODO\n", + " output_batch = [vectorized_songs[id+1:id+seq_length+1] for id in idx]\n", "\n", " # x_batch, y_batch provide the true inputs and targets for network training\n", " x_batch = np.reshape(input_batch, [batch_size, seq_length])\n", @@ -359,11 +598,33 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": { "id": "0eBu9WZG84i0" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Step 0\n", + " input: 26 (np.str_('A'))\n", + " expected output: 1 (np.str_(' '))\n", + "Step 1\n", + " input: 1 (np.str_(' '))\n", + " expected output: 26 (np.str_('A'))\n", + "Step 2\n", + " input: 26 (np.str_('A'))\n", + " expected output: 26 (np.str_('A'))\n", + "Step 3\n", + " input: 26 (np.str_('A'))\n", + " expected output: 11 (np.str_('/'))\n", + "Step 4\n", + " input: 11 (np.str_('/'))\n", + " expected output: 27 (np.str_('B'))\n" + ] + } + ], "source": [ "x_batch, y_batch = get_batch(vectorized_songs, seq_length=5, batch_size=1)\n", "\n", @@ -415,7 +676,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "metadata": { "id": "8DsWzojvkbc7" }, @@ -442,7 +703,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "metadata": { "id": "MtCrdfzEI2N0" }, @@ -459,12 +720,12 @@ "\n", " # Layer 2: LSTM with `rnn_units` number of units.\n", " # TODO: Call the LSTM function defined above to add this layer.\n", - " LSTM('''TODO'''),\n", + " LSTM(rnn_units),\n", "\n", " # Layer 3: Dense (fully-connected) layer that transforms the LSTM output\n", " # into the vocabulary size.\n", " # TODO: Add the Dense layer.\n", - " '''TODO: DENSE LAYER HERE'''\n", + " tf.keras.layers.Dense(vocab_size)\n", " ])\n", "\n", " return model\n", @@ -490,11 +751,93 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "metadata": { "id": "RwG1DD6rDrRM" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Model: \"sequential\"\n",
+              "
\n" + ], + "text/plain": [ + "\u001b[1mModel: \"sequential\"\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
+              "┃ Layer (type)                     Output Shape                  Param # ┃\n",
+              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
+              "│ embedding (Embedding)           │ (32, 100, 256)         │        21,248 │\n",
+              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+              "│ lstm (LSTM)                     │ (32, 100, 1024)        │     5,246,976 │\n",
+              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+              "│ dense (Dense)                   │ (32, 100, 83)          │        85,075 │\n",
+              "└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
+              "
\n" + ], + "text/plain": [ + "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n", + "┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n", + "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n", + "│ embedding (\u001b[38;5;33mEmbedding\u001b[0m) │ (\u001b[38;5;34m32\u001b[0m, \u001b[38;5;34m100\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m21,248\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ lstm (\u001b[38;5;33mLSTM\u001b[0m) │ (\u001b[38;5;34m32\u001b[0m, \u001b[38;5;34m100\u001b[0m, \u001b[38;5;34m1024\u001b[0m) │ \u001b[38;5;34m5,246,976\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;34m32\u001b[0m, \u001b[38;5;34m100\u001b[0m, \u001b[38;5;34m83\u001b[0m) │ \u001b[38;5;34m85,075\u001b[0m │\n", + "└─────────────────────────────────┴────────────────────────┴───────────────┘\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
 Total params: 5,353,299 (20.42 MB)\n",
+              "
\n" + ], + "text/plain": [ + "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m5,353,299\u001b[0m (20.42 MB)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
 Trainable params: 5,353,299 (20.42 MB)\n",
+              "
\n" + ], + "text/plain": [ + "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m5,353,299\u001b[0m (20.42 MB)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
 Non-trainable params: 0 (0.00 B)\n",
+              "
\n" + ], + "text/plain": [ + "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "model.summary()" ] @@ -510,11 +853,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "metadata": { "id": "C-_70kKAPrPU" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Input shape: (32, 100) # (batch_size, sequence_length)\n", + "Prediction shape: (32, 100, 83) # (batch_size, sequence_length, vocab_size)\n" + ] + } + ], "source": [ "x, y = get_batch(vectorized_songs, seq_length=100, batch_size=32)\n", "pred = model(x)\n", @@ -541,11 +893,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "metadata": { "id": "4V4MfFg0RQJg" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "array([12, 41, 80, 53, 72, 4, 4, 82, 4, 18, 43, 20, 81, 70, 64, 7, 27,\n", + " 69, 16, 66, 70, 14, 42, 42, 32, 42, 24, 38, 50, 82, 40, 32, 0, 43,\n", + " 38, 42, 63, 27, 38, 67, 18, 64, 47, 6, 5, 39, 58, 30, 28, 25, 33,\n", + " 18, 36, 64, 63, 52, 58, 4, 82, 30, 13, 75, 39, 80, 62, 79, 58, 75,\n", + " 55, 66, 58, 39, 39, 31, 31, 34, 39, 35, 9, 19, 8, 77, 25, 61, 0,\n", + " 67, 10, 24, 47, 58, 23, 64, 58, 26, 12, 58, 54, 54, 57, 31])" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "sampled_indices = tf.random.categorical(pred[0], num_samples=1)\n", "sampled_indices = tf.squeeze(sampled_indices,axis=-1).numpy()\n", @@ -563,11 +931,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "metadata": { "id": "xWcFwPwLSo05" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Input: \n", + " 're\\nZ: id:dc-ocarolan-18\\nM:4/4\\nL:1/8\\nK:F Major\\nC2FE F2DE|F2ED C2A,2|B2BG A/B/ccA|F2A2 c2f2|!\\nfefg fef'\n", + "\n", + "Next Char Predictions: \n", + " \"0Py]q##|#6R8zoi)Bn4ko2QQGQ=MY|OG\\nRMQhBMl6iV('NcEC>H6Kih[c#|E1tNygxct_kcNNFFINJ-7,v>f\\nl.=Vc" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 3000/3000 [27:37<00:00, 1.81it/s]\n", + "\u001b[1;38;5;39mCOMET INFO:\u001b[0m Uploading 4 metrics, params and output messages\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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cqRE27Hq3LlzhvdWv379Yu5YjRgxQpo2beqbsK1t27Yyfvz4yHpP6agfpBs9erSnQIECnk8//dSzcuVKz3333ecpVaqUZ+/evZ5Y8vzzz3saNWrk2b17t++yf/9+3+P9+vXzVKtWzTN58mTPwoULPW3atPFcdtllvsfPnDnjady4sadr166eP//80/Prr796ypUr5xk4cKAn0unP8uyzz3p+/PFHHTHnGTNmjN/jw4YN85QsWdIzduxYz9KlSz3XXXedp1atWp4TJ074tunevbunWbNmnrlz53pmzpzpqVOnjqdPnz6+xxMTEz0VK1b09O3b17NixQrP119/7SlcuLDngw8+8ETTsbrjjjvMsbC+zw4dOuS3Tawcq6uuusrz2WefmZ9hyZIlnquvvtpTvXp1z9GjR3P0727Tpk2eIkWKeB599FHPqlWrPO+8844nISHBM2HCBE80HatOnTqZf7+t7y19r8Tasfrpp588v/zyi2fdunWetWvXep555hlP/vz5zbGLlPcUQSVAq1atPP379/fdTk1N9VSpUsUzdOhQT6wFFT052Dly5Ih5o3/33Xe++1avXm1ORHPmzDG39c0cHx/v2bNnj2+bESNGeEqUKOFJSUnxRIvAk29aWpqnUqVKntdee83veBUsWNCcQJX+Iev3LViwwLfN+PHjPXFxcZ6dO3ea2++9956ndOnSfsfqqaee8tSvX98TqYIFlV69egX9nlg9Vmrfvn3mZ58+fXqO/t09+eST5kOI1c0332xO/tFyrLxB5eGHHw76PbF6rJT+vXz88ccR856i68fi1KlTsmjRItNUb11PSG/PmTNHYo12V2iTfe3atU3Tuzb/KT1Gp0+f9jtO2i1UvXp133HSr02aNJGKFSv6trnqqqvMAlcrV66UaLV582bZs2eP37HR9Sy0C9F6bLQL49JLL/Vto9vre23evHm+bTp27CgFChTwO37avH348GGJJtpkrM3J9evXlwceeEAOHjzoeyyWj1ViYqL5WqZMmRz9u9NtrM/h3SaS/40LPFZeo0aNknLlyknjxo1l4MCBcvz4cd9jsXisUlNTZfTo0XLs2DHTBRQp76mIXpQwpx04cMD8Iq2/EKW316xZI7FET6zax6gnj927d8sLL7xgagBWrFhhTsR6UtATSOBx0seUfrU7jt7HopX3Z7P72a3HRk/MVvny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HxpObrrpJvnoo4/k8OHD2TgaAHIDQQVAtmlNybXXXitLlizxu6xfv146duzo207rUKy0vuWaa66Rpk2byg8//CCLFi2S4cOH+4ptc1r+/Pn9bmtLjbayqISEBNNlNH78eBNy3nnnHalfv75ppQHgPIIKgLBod0xqaqrffS1atDA1JtpiUadOHb9LYDix0mCiQeH111+XNm3amC6iXbt2hXy9QBdddJFs377dXLxWrVplamc0dIRLg0u7du3khRdekD///NO89pgxY8L+fgC5h6ACICwaRubNm2daQ3RUjwaN/v37m0JWLUbVmhDt7vntt9/MiJ3MQoYGmdOnT5vWCy1+1RE53iJb6+tpi43Wkujr2XUJ6egc7bLp27evLF68WObPny+33367dOrUSS699NKwfi79mbTGRouBdQTRjz/+KPv37zchCIDzCCoAwqKjbrSbRFsqdC4TPalXqVLFjOTRUNKtWzcTGrRIVmtEdFRPMFoXosOTX3nlFWncuLGMGjVKhg4d6reNjvzR4lodwaOvF1iM620JGTdunJQuXdp0NWlwqV27tnzzzTdh/1w6smjGjBly9dVXm5ad5557zrT06JBrAM6L8zAGDwAAuBQtKgAAwLUIKgAAwLUIKgAAwLUIKgAAwLUIKgAAwLUIKgAAwLUIKgAAwLUIKgAAwLUIKgAAwLUIKgAAwLUIKgAAQNzq/wGL3y2oO8a8aQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "### Define optimizer and training operation ###\n", "\n", "'''TODO: instantiate a new model for training using the `build_model`\n", " function and the hyperparameters created above.'''\n", - "model = build_model('''TODO: arguments''')\n", + "model = build_model(vocab_size = vocab_size, \n", + " embedding_dim=params['embedding_dim'],\n", + " rnn_units=params['rnn_units'],\n", + " batch_size=params['batch_size'])\n", "\n", "'''TODO: instantiate an optimizer with its learning rate.\n", " Checkout the tensorflow website for a list of supported optimizers.\n", " https://www.tensorflow.org/api_docs/python/tf/keras/optimizers/\n", " Try using the Adam optimizer to start.'''\n", - "optimizer = # TODO\n", + "optimizer = tf.optimizers.Adam(params['learning_rate'])\n", "\n", "@tf.function\n", "def train_step(x, y):\n", @@ -737,10 +1168,10 @@ " with tf.GradientTape() as tape:\n", "\n", " '''TODO: feed the current input into the model and generate predictions'''\n", - " y_hat = model('''TODO''')\n", + " y_hat = model(x)\n", "\n", " '''TODO: compute the loss!'''\n", - " loss = compute_loss('''TODO''', '''TODO''')\n", + " loss = compute_loss(y, y_hat)\n", "\n", " # Now, compute the gradients\n", " '''TODO: complete the function call for gradient computation.\n", @@ -748,7 +1179,7 @@ " of the model parameters.\n", " HINT: use `model.trainable_variables` to get a list of all model\n", " parameters.'''\n", - " grads = tape.gradient('''TODO''', '''TODO''')\n", + " grads = tape.gradient(loss,model.trainable_variables)\n", "\n", " # Apply the gradients to the optimizer so it can update the model accordingly\n", " optimizer.apply_gradients(zip(grads, model.trainable_variables))\n", @@ -815,14 +1246,99 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 49, "metadata": { "id": "LycQ-ot_jjyu" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Model: \"sequential_3\"\n",
+              "
\n" + ], + "text/plain": [ + "\u001b[1mModel: \"sequential_3\"\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
+              "┃ Layer (type)                     Output Shape                  Param # ┃\n",
+              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
+              "│ embedding_3 (Embedding)         │ (1, None, 256)         │        21,248 │\n",
+              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+              "│ lstm_3 (LSTM)                   │ (1, None, 1024)        │     5,246,976 │\n",
+              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+              "│ dense_3 (Dense)                 │ (1, None, 83)          │        85,075 │\n",
+              "└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
+              "
\n" + ], + "text/plain": [ + "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n", + "┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n", + "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n", + "│ embedding_3 (\u001b[38;5;33mEmbedding\u001b[0m) │ (\u001b[38;5;34m1\u001b[0m, \u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m21,248\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ lstm_3 (\u001b[38;5;33mLSTM\u001b[0m) │ (\u001b[38;5;34m1\u001b[0m, \u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1024\u001b[0m) │ \u001b[38;5;34m5,246,976\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_3 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;34m1\u001b[0m, \u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m83\u001b[0m) │ \u001b[38;5;34m85,075\u001b[0m │\n", + "└─────────────────────────────────┴────────────────────────┴───────────────┘\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
 Total params: 5,353,299 (20.42 MB)\n",
+              "
\n" + ], + "text/plain": [ + "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m5,353,299\u001b[0m (20.42 MB)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
 Trainable params: 5,353,299 (20.42 MB)\n",
+              "
\n" + ], + "text/plain": [ + "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m5,353,299\u001b[0m (20.42 MB)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
 Non-trainable params: 0 (0.00 B)\n",
+              "
\n" + ], + "text/plain": [ + "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "'''TODO: Rebuild the model using a batch_size=1'''\n", - "model = build_model('''TODO''', '''TODO''', '''TODO''', batch_size=1)\n", + "model = build_model(vocab_size = vocab_size, \n", + " embedding_dim=params['embedding_dim'],\n", + " rnn_units=params['rnn_units'],\n", + " batch_size=1)\n", "\n", "# Restore the model weights for the last checkpoint after training\n", "model.build(tf.TensorShape([1, None]))\n", @@ -865,7 +1381,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 57, "metadata": { "id": "WvuwZBX5Ogfd" }, @@ -877,25 +1393,25 @@ " # Evaluation step (generating ABC text using the learned RNN model)\n", "\n", " '''TODO: convert the start string to numbers (vectorize)'''\n", - " input_eval = ['''TODO''']\n", + " input_eval = [char2idx[c] for c in start_string]\n", " input_eval = tf.expand_dims(input_eval, 0)\n", "\n", " # Empty string to store our results\n", " text_generated = []\n", "\n", " # Here batch size == 1\n", - " model.reset_states()\n", + " #model.reset_states()\n", " tqdm._instances.clear()\n", "\n", " for i in tqdm(range(generation_length)):\n", " '''TODO: evaluate the inputs and generate the next character predictions'''\n", - " predictions = model('''TODO''')\n", + " predictions = model(input_eval)\n", "\n", " # Remove the batch dimension\n", " predictions = tf.squeeze(predictions, 0)\n", "\n", " '''TODO: use a multinomial distribution to sample'''\n", - " predicted_id = tf.random.categorical('''TODO''', num_samples=1)[-1,0].numpy()\n", + " predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy()\n", "\n", " # Pass the prediction along with the previous hidden state\n", " # as the next inputs to the model\n", @@ -903,22 +1419,30 @@ "\n", " '''TODO: add the predicted character to the generated text!'''\n", " # Hint: consider what format the prediction is in vs. the output\n", - " text_generated.append('''TODO''')\n", + " text_generated.append(idx2char[predicted_id])\n", "\n", " return (start_string + ''.join(text_generated))" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 58, "metadata": { "id": "ktovv0RFhrkn" }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 1000/1000 [00:11<00:00, 83.68it/s]\n" + ] + } + ], "source": [ "'''TODO: Use the model and the function defined above to generate ABC format text of length 1000!\n", " As you may notice, ABC files start with \"X\" - this may be a good start string.'''\n", - "generated_text = generate_text('''TODO''', start_string=\"X\", generation_length=1000)" + "generated_text = generate_text(model, start_string=\"X\", generation_length=1000)" ] }, { @@ -936,11 +1460,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 72, "metadata": { "id": "LrOtG64bfLto" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found 1 songs in text\n", + "XN!d edB|AGF G2:|!\n", + "[2 AG|FDFA G2:|!\n", + "Bc|dggf gd|(3efe d2Bc|dBBA BcdA|BAGF DEFA|GBdB cBAG|Add2 c2dB|cBAG FGAd|BdAF DEFE|DFF2 DFFAF|dFGA BAFA|BGAG FDD:|!\n", + "B|GEEF G2ea|geed efge|dBAc BGG:|!\n", + "B|d2fd Adfd|eaag eafd|eaac acgc|edcB Adfe|!\n", + "dceg acAE|FDDE F2GF|!\n", + "Add2 fede|!\n", + "dgg2 bgde|g2bg dgbg|Adfd Add|gdB c2A|BAG AFD|FDD D2:|!\n" + ] + } + ], "source": [ "### Play back generated songs ###\n", "\n", @@ -948,6 +1488,7 @@ "\n", "for i, song in enumerate(generated_songs):\n", " # Synthesize the waveform from a song\n", + " print(song)\n", " waveform = mdl.lab1.play_song(song)\n", "\n", " # If its a valid song (correct syntax), lets play it!\n", @@ -1031,7 +1572,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.11" + "version": "3.13.7" } }, "nbformat": 4, diff --git a/lab1/tmp.abc b/lab1/tmp.abc new file mode 100644 index 00000000..37c62da4 --- /dev/null +++ b/lab1/tmp.abc @@ -0,0 +1,2 @@ +X:6/BGF f G cEE D2A Ma2:dcAc-1 +cef|B| \ No newline at end of file diff --git a/lab1/training_checkpoints/my_ckpt b/lab1/training_checkpoints/my_ckpt new file mode 100644 index 00000000..ed57b5b8 Binary files /dev/null and b/lab1/training_checkpoints/my_ckpt differ