diff --git a/_images/cnn_10_1.png b/_images/cnn_10_1.png
deleted file mode 100644
index b3d6c3a8af..0000000000
Binary files a/_images/cnn_10_1.png and /dev/null differ
diff --git a/_images/cnn_11_1.png b/_images/cnn_11_1.png
index eec7cc23bb..b3d6c3a8af 100644
Binary files a/_images/cnn_11_1.png and b/_images/cnn_11_1.png differ
diff --git a/_images/cnn_12_1.png b/_images/cnn_12_1.png
new file mode 100644
index 0000000000..eec7cc23bb
Binary files /dev/null and b/_images/cnn_12_1.png differ
diff --git a/_images/cnn_11_2.png b/_images/cnn_12_2.png
similarity index 100%
rename from _images/cnn_11_2.png
rename to _images/cnn_12_2.png
diff --git a/_images/cnn_11_4.png b/_images/cnn_12_4.png
similarity index 100%
rename from _images/cnn_11_4.png
rename to _images/cnn_12_4.png
diff --git a/_images/gradient-descent_19_1.png b/_images/gradient-descent_19_1.png
index e224f2e1e4..3f81b0867c 100644
Binary files a/_images/gradient-descent_19_1.png and b/_images/gradient-descent_19_1.png differ
diff --git a/_images/kernel-method_32_0.png b/_images/kernel-method_32_0.png
index 0068095f20..ab10cc25f0 100644
Binary files a/_images/kernel-method_32_0.png and b/_images/kernel-method_32_0.png differ
diff --git a/_images/kernel-method_39_1.png b/_images/kernel-method_39_1.png
index 0341d935c7..abd7482f24 100644
Binary files a/_images/kernel-method_39_1.png and b/_images/kernel-method_39_1.png differ
diff --git a/_images/rnn_17_0.png b/_images/rnn_17_0.png
new file mode 100644
index 0000000000..41277722ff
Binary files /dev/null and b/_images/rnn_17_0.png differ
diff --git a/_images/rnn_17_1.png b/_images/rnn_17_1.png
new file mode 100644
index 0000000000..71c224f423
Binary files /dev/null and b/_images/rnn_17_1.png differ
diff --git a/_images/rnn_7_3.png b/_images/rnn_7_3.png
deleted file mode 100644
index ff15035929..0000000000
Binary files a/_images/rnn_7_3.png and /dev/null differ
diff --git a/_images/rnn_7_4.png b/_images/rnn_7_4.png
deleted file mode 100644
index 1db25e6f3e..0000000000
Binary files a/_images/rnn_7_4.png and /dev/null differ
diff --git a/_images/tools-of-the-trade_29_0.png b/_images/tools-of-the-trade_29_0.png
index 2771a6fcb9..caa9f81586 100644
Binary files a/_images/tools-of-the-trade_29_0.png and b/_images/tools-of-the-trade_29_0.png differ
diff --git a/_images/visualization-relationships_12_0.png b/_images/visualization-relationships_12_0.png
index e39c9ece95..1e673d453e 100644
Binary files a/_images/visualization-relationships_12_0.png and b/_images/visualization-relationships_12_0.png differ
diff --git a/_images/visualization-relationships_16_0.png b/_images/visualization-relationships_16_0.png
index 51768453b5..5661ce4a96 100644
Binary files a/_images/visualization-relationships_16_0.png and b/_images/visualization-relationships_16_0.png differ
diff --git a/_images/visualization-relationships_18_1.png b/_images/visualization-relationships_18_1.png
index a66c1f92ca..32c99efd7d 100644
Binary files a/_images/visualization-relationships_18_1.png and b/_images/visualization-relationships_18_1.png differ
diff --git a/_images/visualization-relationships_20_0.png b/_images/visualization-relationships_20_0.png
index 541bbf0884..612f86593e 100644
Binary files a/_images/visualization-relationships_20_0.png and b/_images/visualization-relationships_20_0.png differ
diff --git a/_sources/assignments/deep-learning/cnn/image-classification.ipynb b/_sources/assignments/deep-learning/cnn/image-classification.ipynb
new file mode 100644
index 0000000000..7f3a631caf
--- /dev/null
+++ b/_sources/assignments/deep-learning/cnn/image-classification.ipynb
@@ -0,0 +1,1396 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": [
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "# Install the necessary dependencies\n",
+ "\n",
+ "import os\n",
+ "import sys\n",
+ "!{sys.executable} -m pip install --quiet seaborn pandas scikit-learn numpy matplotlib jupyterlab_myst ipython"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "tags": [
+ "remove-cell"
+ ]
+ },
+ "source": [
+ "---\n",
+ "license:\n",
+ " code: MIT\n",
+ " content: CC-BY-4.0\n",
+ "github: https://github.com/ocademy-ai/machine-learning\n",
+ "venue: By Ocademy\n",
+ "open_access: true\n",
+ "bibliography:\n",
+ " - https://raw.githubusercontent.com/ocademy-ai/machine-learning/main/open-machine-learning-jupyter-book/references.bib\n",
+ "---"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "FE7KNzPPVrVV"
+ },
+ "source": [
+ "# Image classification"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "gN7G9GFmVrVY"
+ },
+ "source": [
+ "This tutorial shows how to classify images of flowers using a `tf.keras.Sequential` model and load data using `tf.keras.utils.image_dataset_from_directory`. It demonstrates the following concepts:\n",
+ "\n",
+ "\n",
+ "* Efficiently loading a dataset off disk.\n",
+ "* Identifying overfitting and applying techniques to mitigate it, including data augmentation and dropout.\n",
+ "\n",
+ "This tutorial follows a basic machine learning workflow:\n",
+ "\n",
+ "1. Examine and understand data\n",
+ "2. Build an input pipeline\n",
+ "3. Build the model\n",
+ "4. Train the model\n",
+ "5. Test the model\n",
+ "6. Improve the model and repeat the process\n",
+ "\n",
+ "In addition, the notebook demonstrates how to convert a saved model to a TensorFlow Lite model for on-device machine learning on mobile, embedded, and IoT devices."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "zF9uvbXNVrVY"
+ },
+ "source": [
+ "## Setup\n",
+ "\n",
+ "Import TensorFlow and other necessary libraries:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:37.838594Z",
+ "iopub.status.busy": "2023-10-27T06:06:37.838012Z",
+ "iopub.status.idle": "2023-10-27T06:06:40.429734Z",
+ "shell.execute_reply": "2023-10-27T06:06:40.429024Z"
+ },
+ "id": "L1WtoaOHVrVh"
+ },
+ "outputs": [],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "import PIL\n",
+ "import tensorflow as tf\n",
+ "\n",
+ "from tensorflow import keras\n",
+ "from tensorflow.keras import layers\n",
+ "from tensorflow.keras.models import Sequential"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "UZZI6lNkVrVm"
+ },
+ "source": [
+ "## Download and explore the dataset"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "DPHx8-t-VrVo"
+ },
+ "source": [
+ "This tutorial uses a dataset of about 3,700 photos of flowers. The dataset contains five sub-directories, one per class:\n",
+ "\n",
+ "```\n",
+ "flower_photo/\n",
+ " daisy/\n",
+ " dandelion/\n",
+ " roses/\n",
+ " sunflowers/\n",
+ " tulips/\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:40.434690Z",
+ "iopub.status.busy": "2023-10-27T06:06:40.433828Z",
+ "iopub.status.idle": "2023-10-27T06:06:43.613076Z",
+ "shell.execute_reply": "2023-10-27T06:06:43.612374Z"
+ },
+ "id": "57CcilYSG0zv"
+ },
+ "outputs": [],
+ "source": [
+ "import pathlib\n",
+ "\n",
+ "dataset_url = \"https://static-1300131294.cos.ap-shanghai.myqcloud.com/images/deep-learning/CNN/flower_photos.tgz\"\n",
+ "data_dir = tf.keras.utils.get_file('flower_photos.tar', origin=dataset_url, extract=True)\n",
+ "data_dir = pathlib.Path(data_dir).with_suffix('')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "VpmywIlsVrVx"
+ },
+ "source": [
+ "After downloading, you should now have a copy of the dataset available. There are 3,670 total images:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:43.617178Z",
+ "iopub.status.busy": "2023-10-27T06:06:43.616929Z",
+ "iopub.status.idle": "2023-10-27T06:06:43.630586Z",
+ "shell.execute_reply": "2023-10-27T06:06:43.629991Z"
+ },
+ "id": "SbtTDYhOHZb6"
+ },
+ "outputs": [],
+ "source": [
+ "image_count = len(list(data_dir.glob('*/*.jpg')))\n",
+ "print(image_count)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "PVmwkOSdHZ5A"
+ },
+ "source": [
+ "Here are some roses:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:43.633873Z",
+ "iopub.status.busy": "2023-10-27T06:06:43.633337Z",
+ "iopub.status.idle": "2023-10-27T06:06:43.663732Z",
+ "shell.execute_reply": "2023-10-27T06:06:43.663159Z"
+ },
+ "id": "N1loMlbYHeiJ"
+ },
+ "outputs": [],
+ "source": [
+ "roses = list(data_dir.glob('roses/*'))\n",
+ "PIL.Image.open(str(roses[0]))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:43.669205Z",
+ "iopub.status.busy": "2023-10-27T06:06:43.668553Z",
+ "iopub.status.idle": "2023-10-27T06:06:43.706526Z",
+ "shell.execute_reply": "2023-10-27T06:06:43.705970Z"
+ },
+ "id": "RQbZBOTLHiUP"
+ },
+ "outputs": [],
+ "source": [
+ "PIL.Image.open(str(roses[1]))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "DGEqiBbRHnyI"
+ },
+ "source": [
+ "And some tulips:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:43.713651Z",
+ "iopub.status.busy": "2023-10-27T06:06:43.712988Z",
+ "iopub.status.idle": "2023-10-27T06:06:43.732316Z",
+ "shell.execute_reply": "2023-10-27T06:06:43.731754Z"
+ },
+ "id": "HyQkfPGdHilw"
+ },
+ "outputs": [],
+ "source": [
+ "tulips = list(data_dir.glob('tulips/*'))\n",
+ "PIL.Image.open(str(tulips[0]))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:43.736431Z",
+ "iopub.status.busy": "2023-10-27T06:06:43.735919Z",
+ "iopub.status.idle": "2023-10-27T06:06:43.758890Z",
+ "shell.execute_reply": "2023-10-27T06:06:43.758290Z"
+ },
+ "id": "wtlhWJPAHivf"
+ },
+ "outputs": [],
+ "source": [
+ "PIL.Image.open(str(tulips[1]))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "gIjgz7_JIo_m"
+ },
+ "source": [
+ "## Load data using a Keras utility\n",
+ "\n",
+ "Next, load these images off disk using the helpful `tf.keras.utils.image_dataset_from_directory` utility. This will take you from a directory of images on disk to a `tf.data.Dataset` in just a couple lines of code. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "xyDNn9MbIzfT"
+ },
+ "source": [
+ "### Create a dataset"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "anqiK_AGI086"
+ },
+ "source": [
+ "Define some parameters for the loader:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:43.764214Z",
+ "iopub.status.busy": "2023-10-27T06:06:43.763806Z",
+ "iopub.status.idle": "2023-10-27T06:06:43.766863Z",
+ "shell.execute_reply": "2023-10-27T06:06:43.766310Z"
+ },
+ "id": "H74l2DoDI2XD"
+ },
+ "outputs": [],
+ "source": [
+ "batch_size = 32\n",
+ "img_height = 180\n",
+ "img_width = 180"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "pFBhRrrEI49z"
+ },
+ "source": [
+ "It's good practice to use a validation split when developing your model. Use 80% of the images for training and 20% for validation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:43.770270Z",
+ "iopub.status.busy": "2023-10-27T06:06:43.769868Z",
+ "iopub.status.idle": "2023-10-27T06:06:47.127119Z",
+ "shell.execute_reply": "2023-10-27T06:06:47.126368Z"
+ },
+ "id": "fIR0kRZiI_AT"
+ },
+ "outputs": [],
+ "source": [
+ "train_ds = tf.keras.utils.image_dataset_from_directory(\n",
+ " data_dir,\n",
+ " validation_split=0.2,\n",
+ " subset=\"training\",\n",
+ " seed=123,\n",
+ " image_size=(img_height, img_width),\n",
+ " batch_size=batch_size)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:47.131037Z",
+ "iopub.status.busy": "2023-10-27T06:06:47.130765Z",
+ "iopub.status.idle": "2023-10-27T06:06:47.287395Z",
+ "shell.execute_reply": "2023-10-27T06:06:47.286778Z"
+ },
+ "id": "iscU3UoVJBXj"
+ },
+ "outputs": [],
+ "source": [
+ "val_ds = tf.keras.utils.image_dataset_from_directory(\n",
+ " data_dir,\n",
+ " validation_split=0.2,\n",
+ " subset=\"validation\",\n",
+ " seed=123,\n",
+ " image_size=(img_height, img_width),\n",
+ " batch_size=batch_size)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "WLQULyAvJC3X"
+ },
+ "source": [
+ "You can find the class names in the `class_names` attribute on these datasets. These correspond to the directory names in alphabetical order."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:47.291072Z",
+ "iopub.status.busy": "2023-10-27T06:06:47.290824Z",
+ "iopub.status.idle": "2023-10-27T06:06:47.294420Z",
+ "shell.execute_reply": "2023-10-27T06:06:47.293799Z"
+ },
+ "id": "ZHAxkHX5JD3k"
+ },
+ "outputs": [],
+ "source": [
+ "class_names = train_ds.class_names\n",
+ "print(class_names)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "_uoVvxSLJW9m"
+ },
+ "source": [
+ "## Visualize the data\n",
+ "\n",
+ "Here are the first nine images from the training dataset:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:47.297749Z",
+ "iopub.status.busy": "2023-10-27T06:06:47.297476Z",
+ "iopub.status.idle": "2023-10-27T06:06:48.298425Z",
+ "shell.execute_reply": "2023-10-27T06:06:48.297546Z"
+ },
+ "id": "wBmEA9c0JYes"
+ },
+ "outputs": [],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "plt.figure(figsize=(10, 10))\n",
+ "for images, labels in train_ds.take(1):\n",
+ " for i in range(9):\n",
+ " ax = plt.subplot(3, 3, i + 1)\n",
+ " plt.imshow(images[i].numpy().astype(\"uint8\"))\n",
+ " plt.title(class_names[labels[i]])\n",
+ " plt.axis(\"off\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "5M6BXtXFJdW0"
+ },
+ "source": [
+ "You will pass these datasets to the Keras `Model.fit` method for training later in this tutorial. If you like, you can also manually iterate over the dataset and retrieve batches of images:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:48.314518Z",
+ "iopub.status.busy": "2023-10-27T06:06:48.314267Z",
+ "iopub.status.idle": "2023-10-27T06:06:48.383826Z",
+ "shell.execute_reply": "2023-10-27T06:06:48.383086Z"
+ },
+ "id": "2-MfMoenJi8s"
+ },
+ "outputs": [],
+ "source": [
+ "for image_batch, labels_batch in train_ds:\n",
+ " print(image_batch.shape)\n",
+ " print(labels_batch.shape)\n",
+ " break"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Wj4FrKxxJkoW"
+ },
+ "source": [
+ "The `image_batch` is a tensor of the shape `(32, 180, 180, 3)`. This is a batch of 32 images of shape `180x180x3` (the last dimension refers to color channels RGB). The `label_batch` is a tensor of the shape `(32,)`, these are corresponding labels to the 32 images.\n",
+ "\n",
+ "You can call `.numpy()` on the `image_batch` and `labels_batch` tensors to convert them to a `numpy.ndarray`.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "4Dr0at41KcAU"
+ },
+ "source": [
+ "## Configure the dataset for performance\n",
+ "\n",
+ "Make sure to use buffered prefetching, so you can yield data from disk without having I/O become blocking. These are two important methods you should use when loading data:\n",
+ "\n",
+ "- `Dataset.cache` keeps the images in memory after they're loaded off disk during the first epoch. This will ensure the dataset does not become a bottleneck while training your model. If your dataset is too large to fit into memory, you can also use this method to create a performant on-disk cache.\n",
+ "- `Dataset.prefetch` overlaps data preprocessing and model execution while training.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:48.387326Z",
+ "iopub.status.busy": "2023-10-27T06:06:48.387053Z",
+ "iopub.status.idle": "2023-10-27T06:06:48.399552Z",
+ "shell.execute_reply": "2023-10-27T06:06:48.398861Z"
+ },
+ "id": "nOjJSm7DKoZA"
+ },
+ "outputs": [],
+ "source": [
+ "AUTOTUNE = tf.data.AUTOTUNE\n",
+ "\n",
+ "train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)\n",
+ "val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "8GUnmPF4JvEf"
+ },
+ "source": [
+ "## Standardize the data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "e56VXHMWJxYT"
+ },
+ "source": [
+ "The RGB channel values are in the `[0, 255]` range. This is not ideal for a neural network; in general you should seek to make your input values small.\n",
+ "\n",
+ "Here, you will standardize values to be in the `[0, 1]` range by using `tf.keras.layers.Rescaling`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:48.403081Z",
+ "iopub.status.busy": "2023-10-27T06:06:48.402855Z",
+ "iopub.status.idle": "2023-10-27T06:06:48.409847Z",
+ "shell.execute_reply": "2023-10-27T06:06:48.409235Z"
+ },
+ "id": "PEYxo2CTJvY9"
+ },
+ "outputs": [],
+ "source": [
+ "normalization_layer = layers.Rescaling(1./255)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Bl4RmanbJ4g0"
+ },
+ "source": [
+ "There are two ways to use this layer. You can apply it to the dataset by calling `Dataset.map`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:48.413451Z",
+ "iopub.status.busy": "2023-10-27T06:06:48.412874Z",
+ "iopub.status.idle": "2023-10-27T06:06:48.874337Z",
+ "shell.execute_reply": "2023-10-27T06:06:48.873622Z"
+ },
+ "id": "X9o9ESaJJ502"
+ },
+ "outputs": [],
+ "source": [
+ "normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))\n",
+ "image_batch, labels_batch = next(iter(normalized_ds))\n",
+ "first_image = image_batch[0]\n",
+ "# Notice the pixel values are now in `[0,1]`.\n",
+ "print(np.min(first_image), np.max(first_image))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "XWEOmRSBJ9J8"
+ },
+ "source": [
+ "Or, you can include the layer inside your model definition, which can simplify deployment. Use the second approach here."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "XsRk1xCwKZR4"
+ },
+ "source": [
+ "Note: You previously resized images using the `image_size` argument of `tf.keras.utils.image_dataset_from_directory`. If you want to include the resizing logic in your model as well, you can use the `tf.keras.layers.Resizing` layer."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "WcUTyDOPKucd"
+ },
+ "source": [
+ "## A basic Keras model\n",
+ "\n",
+ "### Create the model\n",
+ "\n",
+ "The Keras [Sequential](https://www.tensorflow.org/guide/keras/sequential_model) model consists of three convolution blocks (`tf.keras.layers.Conv2D`) with a max pooling layer (`tf.keras.layers.MaxPooling2D`) in each of them. There's a fully-connected layer (`tf.keras.layers.Dense`) with 128 units on top of it that is activated by a ReLU activation function (`'relu'`). This model has not been tuned for high accuracy; the goal of this tutorial is to show a standard approach."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:48.878528Z",
+ "iopub.status.busy": "2023-10-27T06:06:48.878247Z",
+ "iopub.status.idle": "2023-10-27T06:06:48.977446Z",
+ "shell.execute_reply": "2023-10-27T06:06:48.976699Z"
+ },
+ "id": "QR6argA1K074"
+ },
+ "outputs": [],
+ "source": [
+ "num_classes = len(class_names)\n",
+ "\n",
+ "model = Sequential([\n",
+ " layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)),\n",
+ " layers.Conv2D(16, 3, padding='same', activation='relu'),\n",
+ " layers.MaxPooling2D(),\n",
+ " layers.Conv2D(32, 3, padding='same', activation='relu'),\n",
+ " layers.MaxPooling2D(),\n",
+ " layers.Conv2D(64, 3, padding='same', activation='relu'),\n",
+ " layers.MaxPooling2D(),\n",
+ " layers.Flatten(),\n",
+ " layers.Dense(128, activation='relu'),\n",
+ " layers.Dense(num_classes)\n",
+ "])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "EaKFzz72Lqpg"
+ },
+ "source": [
+ "### Compile the model\n",
+ "\n",
+ "For this tutorial, choose the `tf.keras.optimizers.Adam` optimizer and `tf.keras.losses.SparseCategoricalCrossentropy` loss function. To view training and validation accuracy for each training epoch, pass the `metrics` argument to `Model.compile`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:48.981686Z",
+ "iopub.status.busy": "2023-10-27T06:06:48.981407Z",
+ "iopub.status.idle": "2023-10-27T06:06:49.130037Z",
+ "shell.execute_reply": "2023-10-27T06:06:49.129313Z"
+ },
+ "id": "jloGNS1MLx3A"
+ },
+ "outputs": [],
+ "source": [
+ "model.compile(optimizer='adam',\n",
+ " loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n",
+ " metrics=['accuracy'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "aMJ4DnuJL55A"
+ },
+ "source": [
+ "### Model summary\n",
+ "\n",
+ "View all the layers of the network using the Keras `Model.summary` method:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:49.134092Z",
+ "iopub.status.busy": "2023-10-27T06:06:49.133829Z",
+ "iopub.status.idle": "2023-10-27T06:06:49.152889Z",
+ "shell.execute_reply": "2023-10-27T06:06:49.152297Z"
+ },
+ "id": "llLYH-BXL7Xe"
+ },
+ "outputs": [],
+ "source": [
+ "model.summary()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "NiYHcbvaL9H-"
+ },
+ "source": [
+ "### Train the model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "j30F69T4sIVN"
+ },
+ "source": [
+ "Train the model for 10 epochs with the Keras `Model.fit` method:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:06:49.166383Z",
+ "iopub.status.busy": "2023-10-27T06:06:49.166146Z",
+ "iopub.status.idle": "2023-10-27T06:07:12.242819Z",
+ "shell.execute_reply": "2023-10-27T06:07:12.242097Z"
+ },
+ "id": "5fWToCqYMErH"
+ },
+ "outputs": [],
+ "source": [
+ "epochs=10\n",
+ "history = model.fit(\n",
+ " train_ds,\n",
+ " validation_data=val_ds,\n",
+ " epochs=epochs\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "SyFKdQpXMJT4"
+ },
+ "source": [
+ "## Visualize training results"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "dFvOvmAmMK9w"
+ },
+ "source": [
+ "Create plots of the loss and accuracy on the training and validation sets:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:12.247018Z",
+ "iopub.status.busy": "2023-10-27T06:07:12.246357Z",
+ "iopub.status.idle": "2023-10-27T06:07:12.534186Z",
+ "shell.execute_reply": "2023-10-27T06:07:12.533543Z"
+ },
+ "id": "jWnopEChMMCn"
+ },
+ "outputs": [],
+ "source": [
+ "acc = history.history['accuracy']\n",
+ "val_acc = history.history['val_accuracy']\n",
+ "\n",
+ "loss = history.history['loss']\n",
+ "val_loss = history.history['val_loss']\n",
+ "\n",
+ "epochs_range = range(epochs)\n",
+ "\n",
+ "plt.figure(figsize=(8, 8))\n",
+ "plt.subplot(1, 2, 1)\n",
+ "plt.plot(epochs_range, acc, label='Training Accuracy')\n",
+ "plt.plot(epochs_range, val_acc, label='Validation Accuracy')\n",
+ "plt.legend(loc='lower right')\n",
+ "plt.title('Training and Validation Accuracy')\n",
+ "\n",
+ "plt.subplot(1, 2, 2)\n",
+ "plt.plot(epochs_range, loss, label='Training Loss')\n",
+ "plt.plot(epochs_range, val_loss, label='Validation Loss')\n",
+ "plt.legend(loc='upper right')\n",
+ "plt.title('Training and Validation Loss')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "hO_jT7HwMrEn"
+ },
+ "source": [
+ "The plots show that training accuracy and validation accuracy are off by large margins, and the model has achieved only around 60% accuracy on the validation set.\n",
+ "\n",
+ "The following tutorial sections show how to inspect what went wrong and try to increase the overall performance of the model."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "hqtyGodAMvNV"
+ },
+ "source": [
+ "## Overfitting"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "ixsz9XFfMxcu"
+ },
+ "source": [
+ "In the plots above, the training accuracy is increasing linearly over time, whereas validation accuracy stalls around 60% in the training process. Also, the difference in accuracy between training and validation accuracy is noticeable—a sign of [overfitting](https://www.tensorflow.org/tutorials/keras/overfit_and_underfit).\n",
+ "\n",
+ "When there are a small number of training examples, the model sometimes learns from noises or unwanted details from training examples—to an extent that it negatively impacts the performance of the model on new examples. This phenomenon is known as overfitting. It means that the model will have a difficult time generalizing on a new dataset.\n",
+ "\n",
+ "There are multiple ways to fight overfitting in the training process. In this tutorial, you'll use *data augmentation* and add *dropout* to your model."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "BDMfYqwmM1C-"
+ },
+ "source": [
+ "## Data augmentation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "GxYwix81M2YO"
+ },
+ "source": [
+ "Overfitting generally occurs when there are a small number of training examples. **Data augmentation** takes the approach of generating additional training data from your existing examples by augmenting them using random transformations that yield believable-looking images. This helps expose the model to more aspects of the data and generalize better.\n",
+ "\n",
+ "You will implement data augmentation using the following Keras preprocessing layers: `tf.keras.layers.RandomFlip`, `tf.keras.layers.RandomRotation`, and `tf.keras.layers.RandomZoom`. These can be included inside your model like other layers, and run on the GPU."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:12.537963Z",
+ "iopub.status.busy": "2023-10-27T06:07:12.537729Z",
+ "iopub.status.idle": "2023-10-27T06:07:12.684248Z",
+ "shell.execute_reply": "2023-10-27T06:07:12.683621Z"
+ },
+ "id": "9J80BAbIMs21"
+ },
+ "outputs": [],
+ "source": [
+ "data_augmentation = keras.Sequential(\n",
+ " [\n",
+ " layers.RandomFlip(\"horizontal\",\n",
+ " input_shape=(img_height,\n",
+ " img_width,\n",
+ " 3)),\n",
+ " layers.RandomRotation(0.1),\n",
+ " layers.RandomZoom(0.1),\n",
+ " ]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "PN4k1dK3S6eV"
+ },
+ "source": [
+ "Visualize a few augmented examples by applying data augmentation to the same image several times:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:12.687482Z",
+ "iopub.status.busy": "2023-10-27T06:07:12.687256Z",
+ "iopub.status.idle": "2023-10-27T06:07:13.738634Z",
+ "shell.execute_reply": "2023-10-27T06:07:13.737939Z"
+ },
+ "id": "7Z90k539S838"
+ },
+ "outputs": [],
+ "source": [
+ "plt.figure(figsize=(10, 10))\n",
+ "for images, _ in train_ds.take(1):\n",
+ " for i in range(9):\n",
+ " augmented_images = data_augmentation(images)\n",
+ " ax = plt.subplot(3, 3, i + 1)\n",
+ " plt.imshow(augmented_images[0].numpy().astype(\"uint8\"))\n",
+ " plt.axis(\"off\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "tsjXCBLYYNs5"
+ },
+ "source": [
+ "You will add data augmentation to your model before training in the next step."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "ZeD3bXepYKXs"
+ },
+ "source": [
+ "## Dropout\n",
+ "\n",
+ "Another technique to reduce overfitting is to introduce [dropout](https://developers.google.com/machine-learning/glossary#dropout_regularization) regularization to the network.\n",
+ "\n",
+ "When you apply dropout to a layer, it randomly drops out (by setting the activation to zero) a number of output units from the layer during the training process. Dropout takes a fractional number as its input value, in the form such as 0.1, 0.2, 0.4, etc. This means dropping out 10%, 20% or 40% of the output units randomly from the applied layer.\n",
+ "\n",
+ "Create a new neural network with `tf.keras.layers.Dropout` before training it using the augmented images:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:13.750960Z",
+ "iopub.status.busy": "2023-10-27T06:07:13.750684Z",
+ "iopub.status.idle": "2023-10-27T06:07:13.952738Z",
+ "shell.execute_reply": "2023-10-27T06:07:13.952076Z"
+ },
+ "id": "2Zeg8zsqXCsm"
+ },
+ "outputs": [],
+ "source": [
+ "model = Sequential([\n",
+ " data_augmentation,\n",
+ " layers.Rescaling(1./255),\n",
+ " layers.Conv2D(16, 3, padding='same', activation='relu'),\n",
+ " layers.MaxPooling2D(),\n",
+ " layers.Conv2D(32, 3, padding='same', activation='relu'),\n",
+ " layers.MaxPooling2D(),\n",
+ " layers.Conv2D(64, 3, padding='same', activation='relu'),\n",
+ " layers.MaxPooling2D(),\n",
+ " layers.Dropout(0.2),\n",
+ " layers.Flatten(),\n",
+ " layers.Dense(128, activation='relu'),\n",
+ " layers.Dense(num_classes, name=\"outputs\")\n",
+ "])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "L4nEcuqgZLbi"
+ },
+ "source": [
+ "## Compile and train the model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:13.956252Z",
+ "iopub.status.busy": "2023-10-27T06:07:13.955872Z",
+ "iopub.status.idle": "2023-10-27T06:07:13.965125Z",
+ "shell.execute_reply": "2023-10-27T06:07:13.964525Z"
+ },
+ "id": "EvyAINs9ZOmJ"
+ },
+ "outputs": [],
+ "source": [
+ "model.compile(optimizer='adam',\n",
+ " loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n",
+ " metrics=['accuracy'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:13.968257Z",
+ "iopub.status.busy": "2023-10-27T06:07:13.967902Z",
+ "iopub.status.idle": "2023-10-27T06:07:13.987989Z",
+ "shell.execute_reply": "2023-10-27T06:07:13.987423Z"
+ },
+ "id": "wWLkKoKjZSoC"
+ },
+ "outputs": [],
+ "source": [
+ "model.summary()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:14.004029Z",
+ "iopub.status.busy": "2023-10-27T06:07:14.003575Z",
+ "iopub.status.idle": "2023-10-27T06:07:55.642484Z",
+ "shell.execute_reply": "2023-10-27T06:07:55.641736Z"
+ },
+ "id": "LWS-vvNaZDag"
+ },
+ "outputs": [],
+ "source": [
+ "epochs = 15\n",
+ "history = model.fit(\n",
+ " train_ds,\n",
+ " validation_data=val_ds,\n",
+ " epochs=epochs\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Lkdl8VsBbZOu"
+ },
+ "source": [
+ "## Visualize training results\n",
+ "\n",
+ "After applying data augmentation and `tf.keras.layers.Dropout`, there is less overfitting than before, and training and validation accuracy are closer aligned:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:55.646327Z",
+ "iopub.status.busy": "2023-10-27T06:07:55.646069Z",
+ "iopub.status.idle": "2023-10-27T06:07:55.930762Z",
+ "shell.execute_reply": "2023-10-27T06:07:55.930040Z"
+ },
+ "id": "dduoLfKsZVIA"
+ },
+ "outputs": [],
+ "source": [
+ "acc = history.history['accuracy']\n",
+ "val_acc = history.history['val_accuracy']\n",
+ "\n",
+ "loss = history.history['loss']\n",
+ "val_loss = history.history['val_loss']\n",
+ "\n",
+ "epochs_range = range(epochs)\n",
+ "\n",
+ "plt.figure(figsize=(8, 8))\n",
+ "plt.subplot(1, 2, 1)\n",
+ "plt.plot(epochs_range, acc, label='Training Accuracy')\n",
+ "plt.plot(epochs_range, val_acc, label='Validation Accuracy')\n",
+ "plt.legend(loc='lower right')\n",
+ "plt.title('Training and Validation Accuracy')\n",
+ "\n",
+ "plt.subplot(1, 2, 2)\n",
+ "plt.plot(epochs_range, loss, label='Training Loss')\n",
+ "plt.plot(epochs_range, val_loss, label='Validation Loss')\n",
+ "plt.legend(loc='upper right')\n",
+ "plt.title('Training and Validation Loss')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "dtv5VbaVb-3W"
+ },
+ "source": [
+ "## Predict on new data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "10buWpJbcCQz"
+ },
+ "source": [
+ "Use your model to classify an image that wasn't included in the training or validation sets."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "NKgMZ4bDcHf7"
+ },
+ "source": [
+ "Note: Data augmentation and dropout layers are inactive at inference time."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:55.935151Z",
+ "iopub.status.busy": "2023-10-27T06:07:55.934521Z",
+ "iopub.status.idle": "2023-10-27T06:07:56.295539Z",
+ "shell.execute_reply": "2023-10-27T06:07:56.294784Z"
+ },
+ "id": "dC40sRITBSsQ"
+ },
+ "outputs": [],
+ "source": [
+ "sunflower_url = \"https://static-1300131294.cos.ap-shanghai.myqcloud.com/images/deep-learning/CNN/592px-Red_sunflower.jpg\"\n",
+ "sunflower_path = tf.keras.utils.get_file('Red_sunflower', origin=sunflower_url)\n",
+ "\n",
+ "img = tf.keras.utils.load_img(\n",
+ " sunflower_path, target_size=(img_height, img_width)\n",
+ ")\n",
+ "img_array = tf.keras.utils.img_to_array(img)\n",
+ "img_array = tf.expand_dims(img_array, 0) # Create a batch\n",
+ "\n",
+ "predictions = model.predict(img_array)\n",
+ "score = tf.nn.softmax(predictions[0])\n",
+ "\n",
+ "print(\n",
+ " \"This image most likely belongs to {} with a {:.2f} percent confidence.\"\n",
+ " .format(class_names[np.argmax(score)], 100 * np.max(score))\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "aOc3PZ2N2r18"
+ },
+ "source": [
+ "## Use TensorFlow Lite\n",
+ "\n",
+ "TensorFlow Lite is a set of tools that enables on-device machine learning by helping developers run their models on mobile, embedded, and edge devices."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "cThu25rh4LPP"
+ },
+ "source": [
+ "### Convert the Keras Sequential model to a TensorFlow Lite model\n",
+ "\n",
+ "To use the trained model with on-device applications, first [convert it](https://www.tensorflow.org/lite/models/convert) to a smaller and more efficient model format called a [TensorFlow Lite](https://www.tensorflow.org/lite/) model.\n",
+ "\n",
+ "In this example, take the trained Keras Sequential model and use `tf.lite.TFLiteConverter.from_keras_model` to generate a [TensorFlow Lite](https://www.tensorflow.org/lite/) model:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:56.299091Z",
+ "iopub.status.busy": "2023-10-27T06:07:56.298832Z",
+ "iopub.status.idle": "2023-10-27T06:07:59.418375Z",
+ "shell.execute_reply": "2023-10-27T06:07:59.417577Z"
+ },
+ "id": "mXo6ftuL2ufx"
+ },
+ "outputs": [],
+ "source": [
+ "# Convert the model.\n",
+ "converter = tf.lite.TFLiteConverter.from_keras_model(model)\n",
+ "tflite_model = converter.convert()\n",
+ "\n",
+ "# Save the model.\n",
+ "with open('model.tflite', 'wb') as f:\n",
+ " f.write(tflite_model)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "4R26OU4gGKhh"
+ },
+ "source": [
+ "The TensorFlow Lite model you saved in the previous step can contain several function signatures. The Keras model converter API uses the default signature automatically. Learn more about [TensorFlow Lite signatures](https://www.tensorflow.org/lite/guide/signatures)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "7fjQfXaV2l-5"
+ },
+ "source": [
+ "### Run the TensorFlow Lite model\n",
+ "\n",
+ "You can access the TensorFlow Lite saved model signatures in Python via the `tf.lite.Interpreter` class.\n",
+ "\n",
+ "Load the model with the `Interpreter`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:59.422492Z",
+ "iopub.status.busy": "2023-10-27T06:07:59.421837Z",
+ "iopub.status.idle": "2023-10-27T06:07:59.426824Z",
+ "shell.execute_reply": "2023-10-27T06:07:59.426189Z"
+ },
+ "id": "cHYcip_FOaHq"
+ },
+ "outputs": [],
+ "source": [
+ "TF_MODEL_FILE_PATH = 'model.tflite' # The default path to the saved TensorFlow Lite model\n",
+ "\n",
+ "interpreter = tf.lite.Interpreter(model_path=TF_MODEL_FILE_PATH)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "nPUXY6BdHDHo"
+ },
+ "source": [
+ "Print the signatures from the converted model to obtain the names of the inputs (and outputs):\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:59.430202Z",
+ "iopub.status.busy": "2023-10-27T06:07:59.429564Z",
+ "iopub.status.idle": "2023-10-27T06:07:59.434156Z",
+ "shell.execute_reply": "2023-10-27T06:07:59.433471Z"
+ },
+ "id": "ZdDl00E2OaHq"
+ },
+ "outputs": [],
+ "source": [
+ "interpreter.get_signature_list()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "4eVFqT0je3YG"
+ },
+ "source": [
+ "In this example, you have one default signature called `serving_default`. In addition, the name of the `'inputs'` is `'sequential_1_input'`, while the `'outputs'` are called `'outputs'`. You can look up these first and last Keras layer names when running `Model.summary`, as demonstrated earlier in this tutorial.\n",
+ "\n",
+ "Now you can test the loaded TensorFlow Model by performing inference on a sample image with `tf.lite.Interpreter.get_signature_runner` by passing the signature name as follows:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:59.437162Z",
+ "iopub.status.busy": "2023-10-27T06:07:59.436928Z",
+ "iopub.status.idle": "2023-10-27T06:07:59.441228Z",
+ "shell.execute_reply": "2023-10-27T06:07:59.440621Z"
+ },
+ "id": "yFoT_7W_OaHq"
+ },
+ "outputs": [],
+ "source": [
+ "classify_lite = interpreter.get_signature_runner('serving_default')\n",
+ "classify_lite"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "b1mfRcBOnEx0"
+ },
+ "source": [
+ "Similar to what you did earlier in the tutorial, you can use the TensorFlow Lite model to classify images that weren't included in the training or validation sets.\n",
+ "\n",
+ "You have already tensorized that image and saved it as `img_array`. Now, pass it to the first argument (the name of the `'inputs'`) of the loaded TensorFlow Lite model (`predictions_lite`), compute softmax activations, and then print the prediction for the class with the highest computed probability."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:59.444546Z",
+ "iopub.status.busy": "2023-10-27T06:07:59.444034Z",
+ "iopub.status.idle": "2023-10-27T06:07:59.455152Z",
+ "shell.execute_reply": "2023-10-27T06:07:59.454445Z"
+ },
+ "id": "sEqR27YcnFvc"
+ },
+ "outputs": [],
+ "source": [
+ "predictions_lite = classify_lite(sequential_1_input=img_array)['outputs']\n",
+ "score_lite = tf.nn.softmax(predictions_lite)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:59.458120Z",
+ "iopub.status.busy": "2023-10-27T06:07:59.457878Z",
+ "iopub.status.idle": "2023-10-27T06:07:59.462008Z",
+ "shell.execute_reply": "2023-10-27T06:07:59.461371Z"
+ },
+ "id": "ZKP_GFeKUWb5"
+ },
+ "outputs": [],
+ "source": [
+ "print(\n",
+ " \"This image most likely belongs to {} with a {:.2f} percent confidence.\"\n",
+ " .format(class_names[np.argmax(score_lite)], 100 * np.max(score_lite))\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Poz_iYgeUg_U"
+ },
+ "source": [
+ "The prediction generated by the lite model should be almost identical to the predictions generated by the original model:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2023-10-27T06:07:59.465227Z",
+ "iopub.status.busy": "2023-10-27T06:07:59.464844Z",
+ "iopub.status.idle": "2023-10-27T06:07:59.468274Z",
+ "shell.execute_reply": "2023-10-27T06:07:59.467738Z"
+ },
+ "id": "InXXDJL8UYC1"
+ },
+ "outputs": [],
+ "source": [
+ "print(np.max(np.abs(predictions - predictions_lite)))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "5hJzY8XijM7N"
+ },
+ "source": [
+ "Of the five classes—`'daisy'`, `'dandelion'`, `'roses'`, `'sunflowers'`, and `'tulips'`—the model should predict the image belongs to sunflowers, which is the same result as before the TensorFlow Lite conversion.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "1RlfCY9v2_ir"
+ },
+ "source": [
+ "## Acknowledgments\n",
+ "\n",
+ "Thanks to Tensorflow for creating the tutorial notebook [Image classification](https://www.tensorflow.org/tutorials/images/classification). It inspires the majority of the content in this chapter."
+ ]
+ }
+ ],
+ "metadata": {
+ "accelerator": "GPU",
+ "colab": {
+ "collapsed_sections": [],
+ "name": "classification.ipynb",
+ "toc_visible": true
+ },
+ "kernelspec": {
+ "display_name": "Python 3",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.18"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
diff --git a/_sources/assignments/deep-learning/image-segmentation/comparing-edge-based-and-region-based-segmentation.ipynb b/_sources/assignments/deep-learning/image-segmentation/comparing-edge-based-and-region-based-segmentation.ipynb
new file mode 100644
index 0000000000..3fe2073a9c
--- /dev/null
+++ b/_sources/assignments/deep-learning/image-segmentation/comparing-edge-based-and-region-based-segmentation.ipynb
@@ -0,0 +1,332 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "tags": [
+ "hide-input"
+ ]
+ },
+ "outputs": [],
+ "source": [
+ "# Install the necessary dependencies\n",
+ "\n",
+ "import os\n",
+ "import sys\n",
+ "!{sys.executable} -m pip install --quiet seaborn pandas scikit-learn numpy matplotlib jupyterlab_myst ipython skimage"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "tags": [
+ "remove-cell"
+ ]
+ },
+ "source": [
+ "---\n",
+ "license:\n",
+ " code: MIT\n",
+ " content: CC-BY-4.0\n",
+ "github: https://github.com/ocademy-ai/machine-learning\n",
+ "venue: By Ocademy\n",
+ "open_access: true\n",
+ "bibliography:\n",
+ " - https://raw.githubusercontent.com/ocademy-ai/machine-learning/main/open-machine-learning-jupyter-book/references.bib\n",
+ "---"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Comparing edge-based and region-based segmentation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this example, we will try how to segment objects from a background. We use the coins image from skimage.data, which shows several coins outlined against a darker background."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "from skimage import data\n",
+ "from skimage.exposure import histogram\n",
+ "\n",
+ "coins = data.coins()\n",
+ "hist, hist_centers = histogram(coins)\n",
+ "\n",
+ "fig, axes = plt.subplots(1, 2, figsize=(8, 3))\n",
+ "axes[0].imshow(coins, cmap=plt.cm.gray)\n",
+ "axes[0].axis('off')\n",
+ "axes[1].plot(hist_centers, hist, lw=2)\n",
+ "axes[1].set_title('histogram of gray values')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Thresholding"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "A simple way to segment the coins is to choose a threshold based on the histogram of gray values. Unfortunately, thresholding this image gives a binary image that either misses significant parts of the coins or merges parts of the background with the coins:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fig, axes = plt.subplots(1, 2, figsize=(8, 3), sharey=True)\n",
+ "\n",
+ "axes[0].imshow(coins > 100, cmap=plt.cm.gray)\n",
+ "axes[0].set_title('coins > 100')\n",
+ "\n",
+ "axes[1].imshow(coins > 150, cmap=plt.cm.gray)\n",
+ "axes[1].set_title('coins > 150')\n",
+ "\n",
+ "for a in axes:\n",
+ " a.axis('off')\n",
+ "\n",
+ "plt.tight_layout()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Edge-based segmentation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next, we try to delineate the contours of the coins using edge-based segmentation. To do this, we first get the edges of features using the Canny edge-detector."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from skimage.feature import canny\n",
+ "\n",
+ "edges = canny(coins)\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(4, 3))\n",
+ "ax.imshow(edges, cmap=plt.cm.gray)\n",
+ "ax.set_title('Canny detector')\n",
+ "ax.axis('off')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "These contours are then filled using mathematical morphology."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from scipy import ndimage as ndi\n",
+ "\n",
+ "fill_coins = ndi.binary_fill_holes(edges)\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(4, 3))\n",
+ "ax.imshow(fill_coins, cmap=plt.cm.gray)\n",
+ "ax.set_title('filling the holes')\n",
+ "ax.axis('off')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Small spurious objects are easily removed by setting a minimum size for valid objects."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from skimage import morphology\n",
+ "\n",
+ "coins_cleaned = morphology.remove_small_objects(fill_coins, 21)\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(4, 3))\n",
+ "ax.imshow(coins_cleaned, cmap=plt.cm.gray)\n",
+ "ax.set_title('removing small objects')\n",
+ "ax.axis('off')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "However, this method is not very robust, since contours that are not perfectly closed are not filled correctly, as is the case for one unfilled coin above."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Region-based segmentation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We therefore try a region-based method using the watershed transform. First, we find an elevation map using the Sobel gradient of the image."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from skimage.filters import sobel\n",
+ "\n",
+ "elevation_map = sobel(coins)\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(4, 3))\n",
+ "ax.imshow(elevation_map, cmap=plt.cm.gray)\n",
+ "ax.set_title('elevation map')\n",
+ "ax.axis('off')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next we find markers of the background and the coins based on the extreme parts of the histogram of gray values."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "markers = np.zeros_like(coins)\n",
+ "markers[coins < 30] = 1\n",
+ "markers[coins > 150] = 2\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(4, 3))\n",
+ "ax.imshow(markers, cmap=plt.cm.nipy_spectral)\n",
+ "ax.set_title('markers')\n",
+ "ax.axis('off')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Finally, we use the watershed transform to fill regions of the elevation map starting from the markers determined above:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from skimage import segmentation\n",
+ "\n",
+ "segmentation_coins = segmentation.watershed(elevation_map, markers)\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(4, 3))\n",
+ "ax.imshow(segmentation_coins, cmap=plt.cm.gray)\n",
+ "ax.set_title('segmentation')\n",
+ "ax.axis('off')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This last method works even better, and the coins can be segmented and labeled individually."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from skimage.color import label2rgb\n",
+ "\n",
+ "segmentation_coins = ndi.binary_fill_holes(segmentation_coins - 1)\n",
+ "labeled_coins, _ = ndi.label(segmentation_coins)\n",
+ "image_label_overlay = label2rgb(labeled_coins, image=coins, bg_label=0)\n",
+ "\n",
+ "fig, axes = plt.subplots(1, 2, figsize=(8, 3), sharey=True)\n",
+ "axes[0].imshow(coins, cmap=plt.cm.gray)\n",
+ "axes[0].contour(segmentation_coins, [0.5], linewidths=1.2, colors='y')\n",
+ "axes[1].imshow(image_label_overlay)\n",
+ "\n",
+ "for a in axes:\n",
+ " a.axis('off')\n",
+ "\n",
+ "plt.tight_layout()\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Acknowledgments\n",
+ "\n",
+ "Thanks to [Scikit-image](https://scikit-image.org/) for creating the open-source project [Comparing edge-based and region-based segmentation](https://scikit-image.org/docs/stable/auto_examples/applications/plot_coins_segmentation.html). This inspires the majority of the content in this chapter."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "open-machine-learning-jupyter-book",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.18"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/_sources/assignments/deep-learning/nlp/getting-start-nlp-with-classification-task.ipynb b/_sources/assignments/deep-learning/nlp/getting-start-nlp-with-classification-task.ipynb
new file mode 100644
index 0000000000..457d84b138
--- /dev/null
+++ b/_sources/assignments/deep-learning/nlp/getting-start-nlp-with-classification-task.ipynb
@@ -0,0 +1,1152 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "6e14052d-5eec-449a-b6d5-bcc100456aba",
+ "metadata": {},
+ "source": [
+ "# Getting Start NLP with classification task"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "259d0ecc-b734-44ef-b989-49a6e127a944",
+ "metadata": {},
+ "source": [
+ "One area where deep learning has dramatically improved in the last couple of years is natural language processing (NLP). Computers can now generate text, translate automatically from one language to another, analyze comments, label words in sentences, and much more.\n",
+ "\n",
+ "Perhaps the most widely practically useful application of NLP is classification -- that is, classifying a document automatically into some category. This can be used, for instance, for:\n",
+ "\n",
+ "- Sentiment analysis (e.g are people saying positive or negative things about your product)\n",
+ "- Author identification (what author most likely wrote some document)\n",
+ "- Legal discovery (which documents are in scope for a trial)\n",
+ "- Organizing documents by topic\n",
+ "- Triaging inbound emails\n",
+ "- ...and much more!\n",
+ "\n",
+ "Today, we are tasked with comparing two words or short phrases, and scoring them based on whether they're similar or not, based on which patent class they were used in. With a score of 1 it is considered that the two inputs have identical meaning, and 0 means they have totally different meaning. For instance, abatement and eliminating process have a score of 0.5, meaning they're somewhat similar, but not identical.\n",
+ "\n",
+ "It turns out that this can be represented as a classification problem. How? By representing the question like this:\n",
+ "\n",
+ "> For the following text...: \"TEXT1: abatement; TEXT2: eliminating process\" ...chose a category of meaning similarity: \"Different; Similar; Identical\".\n",
+ "\n",
+ "In this assignment section we'll see how to solve the Patent Phrase Matching problem by treating it as a classification task, by representing it in a very similar way to that shown above."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "12389d2f-c08d-4941-a759-d8bbd8fa44ba",
+ "metadata": {},
+ "source": [
+ "## Import and EDA"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "id": "4e4e3c06-4292-40a7-bb1a-66207159c604",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "from datasets import Dataset,DatasetDict\n",
+ "from transformers import AutoModelForSequenceClassification, AutoTokenizer, TrainingArguments, Trainer\n",
+ "import warnings\n",
+ "\n",
+ "warnings.filterwarnings(\"ignore\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f3085076-3dbc-4eab-941c-9c7e2a4b740e",
+ "metadata": {},
+ "source": [
+ "First of all, let's import the dataset."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "cbd450f6-31dd-46c9-918e-e0f3984d1436",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " id \n",
+ " anchor \n",
+ " target \n",
+ " context \n",
+ " score \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 \n",
+ " 37d61fd2272659b1 \n",
+ " abatement \n",
+ " abatement of pollution \n",
+ " A47 \n",
+ " 0.50 \n",
+ " \n",
+ " \n",
+ " 1 \n",
+ " 7b9652b17b68b7a4 \n",
+ " abatement \n",
+ " act of abating \n",
+ " A47 \n",
+ " 0.75 \n",
+ " \n",
+ " \n",
+ " 2 \n",
+ " 36d72442aefd8232 \n",
+ " abatement \n",
+ " active catalyst \n",
+ " A47 \n",
+ " 0.25 \n",
+ " \n",
+ " \n",
+ " 3 \n",
+ " 5296b0c19e1ce60e \n",
+ " abatement \n",
+ " eliminating process \n",
+ " A47 \n",
+ " 0.50 \n",
+ " \n",
+ " \n",
+ " 4 \n",
+ " 54c1e3b9184cb5b6 \n",
+ " abatement \n",
+ " forest region \n",
+ " A47 \n",
+ " 0.00 \n",
+ " \n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id anchor target context score\n",
+ "0 37d61fd2272659b1 abatement abatement of pollution A47 0.50\n",
+ "1 7b9652b17b68b7a4 abatement act of abating A47 0.75\n",
+ "2 36d72442aefd8232 abatement active catalyst A47 0.25\n",
+ "3 5296b0c19e1ce60e abatement eliminating process A47 0.50\n",
+ "4 54c1e3b9184cb5b6 abatement forest region A47 0.00"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.read_csv('https://static-1300131294.cos.ap-shanghai.myqcloud.com/data/deep-learning/nlp/phrase_matching_train.csv')\n",
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8c3283b2-2a18-447f-8400-f6d6efc95f4d",
+ "metadata": {},
+ "source": [
+ "As you see, there are 5 columns, where **anchor** and **target** are a pair phrases, **context** is the common context they are in, **score** is the similarity score of anchor and target."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "69b58088-6d15-4b11-85dd-bf5b86d9df64",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " id \n",
+ " anchor \n",
+ " target \n",
+ " context \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " count \n",
+ " 36473 \n",
+ " 36473 \n",
+ " 36473 \n",
+ " 36473 \n",
+ " \n",
+ " \n",
+ " unique \n",
+ " 36473 \n",
+ " 733 \n",
+ " 29340 \n",
+ " 106 \n",
+ " \n",
+ " \n",
+ " top \n",
+ " 37d61fd2272659b1 \n",
+ " component composite coating \n",
+ " composition \n",
+ " H01 \n",
+ " \n",
+ " \n",
+ " freq \n",
+ " 1 \n",
+ " 152 \n",
+ " 24 \n",
+ " 2186 \n",
+ " \n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id anchor target context\n",
+ "count 36473 36473 36473 36473\n",
+ "unique 36473 733 29340 106\n",
+ "top 37d61fd2272659b1 component composite coating composition H01\n",
+ "freq 1 152 24 2186"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df.describe(include='object')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "00f5b5c7-bcb7-4bf0-875e-45fbf8a2ba65",
+ "metadata": {},
+ "source": [
+ "We can see that in the 36473 rows, there are 733 unique anchors, 106 contexts, and nearly 30000 targets. Some anchors are very common, with \"component composite coating\" for instance appearing 152 times.\n",
+ "\n",
+ "Earlier, I suggested we could represent the input to the model as something like \"TEXT1: abatement; TEXT2: eliminating process\". We'll need to add the context to this too. In Pandas, we just use + to concatenate, like so:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "a89091d6-771a-4b7e-a540-b20d6f03e9aa",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " id \n",
+ " anchor \n",
+ " target \n",
+ " context \n",
+ " score \n",
+ " input \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 \n",
+ " 37d61fd2272659b1 \n",
+ " abatement \n",
+ " abatement of pollution \n",
+ " A47 \n",
+ " 0.50 \n",
+ " TEXT1: A47; TEXT2: abatement of pollution; ANC... \n",
+ " \n",
+ " \n",
+ " 1 \n",
+ " 7b9652b17b68b7a4 \n",
+ " abatement \n",
+ " act of abating \n",
+ " A47 \n",
+ " 0.75 \n",
+ " TEXT1: A47; TEXT2: act of abating; ANC1: abate... \n",
+ " \n",
+ " \n",
+ " 2 \n",
+ " 36d72442aefd8232 \n",
+ " abatement \n",
+ " active catalyst \n",
+ " A47 \n",
+ " 0.25 \n",
+ " TEXT1: A47; TEXT2: active catalyst; ANC1: abat... \n",
+ " \n",
+ " \n",
+ " 3 \n",
+ " 5296b0c19e1ce60e \n",
+ " abatement \n",
+ " eliminating process \n",
+ " A47 \n",
+ " 0.50 \n",
+ " TEXT1: A47; TEXT2: eliminating process; ANC1: ... \n",
+ " \n",
+ " \n",
+ " 4 \n",
+ " 54c1e3b9184cb5b6 \n",
+ " abatement \n",
+ " forest region \n",
+ " A47 \n",
+ " 0.00 \n",
+ " TEXT1: A47; TEXT2: forest region; ANC1: abatement \n",
+ " \n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " id anchor target context score \\\n",
+ "0 37d61fd2272659b1 abatement abatement of pollution A47 0.50 \n",
+ "1 7b9652b17b68b7a4 abatement act of abating A47 0.75 \n",
+ "2 36d72442aefd8232 abatement active catalyst A47 0.25 \n",
+ "3 5296b0c19e1ce60e abatement eliminating process A47 0.50 \n",
+ "4 54c1e3b9184cb5b6 abatement forest region A47 0.00 \n",
+ "\n",
+ " input \n",
+ "0 TEXT1: A47; TEXT2: abatement of pollution; ANC... \n",
+ "1 TEXT1: A47; TEXT2: act of abating; ANC1: abate... \n",
+ "2 TEXT1: A47; TEXT2: active catalyst; ANC1: abat... \n",
+ "3 TEXT1: A47; TEXT2: eliminating process; ANC1: ... \n",
+ "4 TEXT1: A47; TEXT2: forest region; ANC1: abatement "
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df['input'] = 'TEXT1: ' + df.context + '; TEXT2: ' + df.target + '; ANC1: ' + df.anchor\n",
+ "df.head(5)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0fc9e71f-aed8-40b0-821d-c352331f4a89",
+ "metadata": {},
+ "source": [
+ "## Tokenization"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0d9c20bb-a146-497b-a503-edfc6372c084",
+ "metadata": {},
+ "source": [
+ "Transformers uses a `Dataset` object for storing their dataset, of course! We can create one like so:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "a3dcc05b-e170-43ed-92f5-8805d3dbac7f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Dataset({\n",
+ " features: ['id', 'anchor', 'target', 'context', 'score', 'input'],\n",
+ " num_rows: 36473\n",
+ "})"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ds = Dataset.from_pandas(df)\n",
+ "ds"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "107fe0be-b9a4-4c30-a141-41fcfb3beab4",
+ "metadata": {},
+ "source": [
+ "But we can't pass the texts directly into a model. A deep learning model expects numbers as inputs, not English sentences! So we need to do two things:\n",
+ "\n",
+ "- Tokenization: Split each text up into words (or actually, as we'll see, into tokens)\n",
+ "- Numericalization: Convert each word (or token) into a number.\n",
+ "\n",
+ "The details about how this is done actually depend on the particular model we use. So first we'll need to pick a model. There are thousands of models available, but a reasonable starting point for nearly any NLP problem is to use this (replace \"small\" with \"large\" for a slower but more accurate model, once you've finished exploring):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "9bd4fdd3-f881-486b-9d75-ccbb6286b525",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model_nm = 'microsoft/deberta-v3-small'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3f60c3b5-a0a5-4dd5-b512-549cb4242579",
+ "metadata": {},
+ "source": [
+ "`AutoTokenizer` will create a tokenizer appropriate for a given model:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "96aca66f-0663-4dfd-97f6-169f8a0fcb1d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tokz = AutoTokenizer.from_pretrained(model_nm)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5335cfec-7a71-481a-8c18-e934a90194ad",
+ "metadata": {},
+ "source": [
+ "Here's an example of how the tokenizer splits a text into \"tokens\" (which are like words, but can be sub-word pieces, as you see below):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "6fd61beb-a5a8-4f89-9659-8470faf62fb4",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['▁G',\n",
+ " \"'\",\n",
+ " 'day',\n",
+ " '▁folks',\n",
+ " ',',\n",
+ " '▁I',\n",
+ " \"'\",\n",
+ " 'm',\n",
+ " '▁Jeremy',\n",
+ " '▁from',\n",
+ " '▁fast',\n",
+ " '.',\n",
+ " 'ai',\n",
+ " '!']"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tokz.tokenize(\"G'day folks, I'm Jeremy from fast.ai!\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0a2a6a56-2e10-403a-9533-b65afb974425",
+ "metadata": {},
+ "source": [
+ "Uncommon words will be split into pieces just like `ornithorhynchus`. The start of a new word is represented by `▁`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "92e0189f-c8f1-405f-83fb-bd01c483710c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['▁A',\n",
+ " '▁platypus',\n",
+ " '▁is',\n",
+ " '▁an',\n",
+ " '▁or',\n",
+ " 'ni',\n",
+ " 'tho',\n",
+ " 'rhynch',\n",
+ " 'us',\n",
+ " '▁an',\n",
+ " 'at',\n",
+ " 'inus',\n",
+ " '.']"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tokz.tokenize(\"A platypus is an ornithorhynchus anatinus.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a4e253e5-e098-4253-b401-57f0cf753325",
+ "metadata": {},
+ "source": [
+ "## Numericalization"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "83ee57e9-54d7-45cb-a23d-68156b0350f8",
+ "metadata": {},
+ "source": [
+ "After completing Tokenization, we need to convert each token into a number, because the model only accepts numbers as input. But ... how to do it?\n",
+ "We need a large token dictionary to map each token to a number!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "7d56000f-9137-4f7f-b3b6-93624efddc50",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "vocab = tokz.get_vocab()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f062775c-83b5-48cb-be62-70d9e1355d05",
+ "metadata": {},
+ "source": [
+ "The above is the token dictionary that comes with the `deberta-v3-small` model. You can print it out to check."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "dd749eeb-17da-4bd9-b229-c96270a0d415",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'input_ids': [1, 336, 114224, 269, 299, 289, 4840, 34765, 102530, 1867, 299, 2401, 26835, 260, 2], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tokz(\"A platypus is an ornithorhynchus anatinus.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "95028988-a530-46d2-96a9-b11c2e9ab3d7",
+ "metadata": {},
+ "source": [
+ "According to this token dictionary, we can convert the original token sequence into a digital sequence. Input_ids is the number we need, token_type_ids represents whether all tokens belong to the same sentence, and attention_mask represents whether the token exists in the token dictionary.\n",
+ "\n",
+ "Here's a simple function which tokenizes our inputs:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "8c6da089-a612-499b-8a00-e448a0eee212",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def tok_func(x): return tokz(x[\"input\"])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "681d176d-f055-42fd-87de-88dcee8ec18a",
+ "metadata": {},
+ "source": [
+ "To run this quickly in parallel on every row in our dataset, use map:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "fec0c346-3726-42d2-87c6-2260b7d4c80c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "42f7bd84ff414f0cb23b9b1bb44b8ad5",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "Map: 0%| | 0/36473 [00:00, ? examples/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "Dataset({\n",
+ " features: ['id', 'anchor', 'target', 'context', 'score', 'input', 'input_ids', 'token_type_ids', 'attention_mask'],\n",
+ " num_rows: 36473\n",
+ "})"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tok_ds = ds.map(tok_func, batched=True)\n",
+ "tok_ds"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ad41633c-b609-4c71-b51e-7be9861fa05e",
+ "metadata": {},
+ "source": [
+ "This adds a new item to our dataset called input_ids. For instance, here is the input and IDs for the first row of our data:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "7fad8274-4847-49f2-83ab-c3ae6abe6313",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "('TEXT1: A47; TEXT2: abatement of pollution; ANC1: abatement',\n",
+ " [1,\n",
+ " 54453,\n",
+ " 435,\n",
+ " 294,\n",
+ " 336,\n",
+ " 5753,\n",
+ " 346,\n",
+ " 54453,\n",
+ " 445,\n",
+ " 294,\n",
+ " 47284,\n",
+ " 265,\n",
+ " 6435,\n",
+ " 346,\n",
+ " 23702,\n",
+ " 435,\n",
+ " 294,\n",
+ " 47284,\n",
+ " 2])"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "row = tok_ds[0]\n",
+ "row['input'], row['input_ids']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f5fcd90d-f60b-4ca7-9101-e788bb3be03e",
+ "metadata": {},
+ "source": [
+ "Finally, we need to prepare our labels. Transformers always assumes that your labels has the column name labels, but in our dataset it's currently score. Therefore, we need to rename it:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "bb8e3ef2-0574-411f-ab17-3b35af0d7519",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Dataset({\n",
+ " features: ['id', 'anchor', 'target', 'context', 'labels', 'input', 'input_ids', 'token_type_ids', 'attention_mask'],\n",
+ " num_rows: 36473\n",
+ "})"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tok_ds = tok_ds.rename_columns({'score':'labels'})\n",
+ "tok_ds"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "17dc8f85-fc53-425f-ae26-fe9c1429a667",
+ "metadata": {},
+ "source": [
+ "Now that we've prepared our tokens and labels, we need to create our validation set."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c124199a-7978-4c01-9924-c47fb63ca2fb",
+ "metadata": {},
+ "source": [
+ "## Test and validation sets"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "ad9891e8-9f0e-46da-a9e2-7c357673f337",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "9feb595356464f7597d8bc8907474a2a",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "Map: 0%| | 0/36 [00:00, ? examples/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "Dataset({\n",
+ " features: ['id', 'anchor', 'target', 'context', 'input', 'input_ids', 'token_type_ids', 'attention_mask'],\n",
+ " num_rows: 36\n",
+ "})"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "eval_df = pd.read_csv('https://static-1300131294.cos.ap-shanghai.myqcloud.com/data/deep-learning/nlp/phrase_matching_test.csv')\n",
+ "eval_df['input'] = 'TEXT1: ' + eval_df.context + '; TEXT2: ' + eval_df.target + '; ANC1: ' + eval_df.anchor\n",
+ "eval_ds = Dataset.from_pandas(eval_df).map(tok_func, batched=True)\n",
+ "eval_ds"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ddaad27f-c72f-4867-bc54-b6b3e83329ea",
+ "metadata": {},
+ "source": [
+ "This is the test set. Possibly the most important idea in machine learning is that of having separate training, validation, and test data sets."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "263cec95-5e4b-4fec-bc06-7e55a3a9e25f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "DatasetDict({\n",
+ " train: Dataset({\n",
+ " features: ['id', 'anchor', 'target', 'context', 'labels', 'input', 'input_ids', 'token_type_ids', 'attention_mask'],\n",
+ " num_rows: 27354\n",
+ " })\n",
+ " test: Dataset({\n",
+ " features: ['id', 'anchor', 'target', 'context', 'labels', 'input', 'input_ids', 'token_type_ids', 'attention_mask'],\n",
+ " num_rows: 9119\n",
+ " })\n",
+ "})"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dds = tok_ds.train_test_split(0.25, seed=42)\n",
+ "dds"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fae92113-59e2-475d-b472-4f4f7c338f39",
+ "metadata": {},
+ "source": [
+ "This is the validation set. We use train_test_split to separate it from the training set with a separation ratio of 25%."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c23e0df9-6feb-451a-8d26-7515cc21e6d9",
+ "metadata": {},
+ "source": [
+ "## Training our model"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c8294281-4b31-4446-a4a4-2c99ba4bd593",
+ "metadata": {},
+ "source": [
+ "Before starting training, we need to set some hyperparameters for our model. Here's a concise explanation:\n",
+ "\n",
+ "- **Batch Size (`bs`):** 128 examples processed in each iteration.\n",
+ "- **Epochs (`epochs`):** The model will be trained through the entire dataset 4 times.\n",
+ "- **Learning Rate (`lr`):** The step size for adjusting model weights during optimization is set to 8e-5.\n",
+ "- **TrainingArguments (`args`):**\n",
+ " - **Warmup Ratio:** 10% of training steps used for learning rate warm-up.\n",
+ " - **Learning Rate Scheduler:** Cosine learning rate scheduler.\n",
+ " - **Mixed Precision (`fp16`):** Training with mixed-precision for faster computation.\n",
+ " - **Evaluation Strategy:** Model evaluation after each epoch.\n",
+ " - **Batch Sizes:** 128 examples per training device, 256 for evaluation.\n",
+ " - **Number of Training Epochs:** Training for 4 epochs.\n",
+ " - **Weight Decay:** L2 regularization with a rate of 0.01.\n",
+ " - **Report To:** No reports sent during training (set to 'none'). to 'none')."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "a0134c74-63b1-472f-8a8e-ad9eefae0a2b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bs = 128\n",
+ "epochs = 4\n",
+ "lr = 8e-5\n",
+ "args = TrainingArguments('outputs', learning_rate=lr, warmup_ratio=0.1, lr_scheduler_type='cosine', fp16=True,\n",
+ " evaluation_strategy=\"epoch\", per_device_train_batch_size=bs, per_device_eval_batch_size=bs*2,\n",
+ " num_train_epochs=epochs, weight_decay=0.01, report_to='none')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d0458916-7686-4833-84ec-c66823ad6fdf",
+ "metadata": {},
+ "source": [
+ "Now, we can initialize a pre-trained sequence classification model and sets up a training environment using Hugging Face's Trainer. The model is loaded with `AutoModelForSequenceClassification.from_pretrained` and configured with training parameters in the `Trainer` object.\n",
+ "\r\n",
+ "\r\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "id": "32d7e88e-d163-47b8-9b7b-8f910e500fa2",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Some weights of DebertaV2ForSequenceClassification were not initialized from the model checkpoint at deberta-v3-small and are newly initialized: ['classifier.bias', 'classifier.weight', 'pooler.dense.bias', 'pooler.dense.weight']\n",
+ "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
+ ]
+ }
+ ],
+ "source": [
+ "model = AutoModelForSequenceClassification.from_pretrained(model_nm, num_labels=1)\n",
+ "trainer = Trainer(model, args, train_dataset=dds['train'], eval_dataset=dds['test'],\n",
+ " tokenizer=tokz)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "664277e2-2771-44aa-8695-d448c38e86f6",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ " \n",
+ " \n",
+ "
\n",
+ " [856/856 00:53, Epoch 4/4]\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " Epoch \n",
+ " Training Loss \n",
+ " Validation Loss \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " 1 \n",
+ " No log \n",
+ " 0.026275 \n",
+ " \n",
+ " \n",
+ " 2 \n",
+ " No log \n",
+ " 0.021973 \n",
+ " \n",
+ " \n",
+ " 3 \n",
+ " 0.039600 \n",
+ " 0.022443 \n",
+ " \n",
+ " \n",
+ " 4 \n",
+ " 0.039600 \n",
+ " 0.023286 \n",
+ " \n",
+ " \n",
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "trainer.train();"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "id": "3c35b83e-0320-4ea6-89df-342f9d3fb36e",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "array([[-1.50489807e-03],\n",
+ " [ 4.90570068e-03],\n",
+ " [-5.05447388e-04],\n",
+ " [ 2.69412994e-04],\n",
+ " [-1.44767761e-03],\n",
+ " [ 4.85897064e-04],\n",
+ " [-1.81484222e-03],\n",
+ " [ 8.22067261e-04],\n",
+ " [ 4.36019897e-03],\n",
+ " [ 4.40216064e-03],\n",
+ " [-6.16550446e-04],\n",
+ " [-4.18424606e-05],\n",
+ " [-1.20639801e-03],\n",
+ " [ 3.18288803e-04],\n",
+ " [-6.15119934e-04],\n",
+ " [-8.05377960e-04],\n",
+ " [-2.66265869e-03],\n",
+ " [ 2.60114670e-04],\n",
+ " [ 3.48281860e-03],\n",
+ " [ 1.68323517e-03],\n",
+ " [ 1.38378143e-03],\n",
+ " [-2.48527527e-03],\n",
+ " [ 7.53879547e-04],\n",
+ " [ 8.55922699e-04],\n",
+ " [-2.27355957e-03],\n",
+ " [-2.88581848e-03],\n",
+ " [ 3.29780579e-03],\n",
+ " [ 9.42707062e-04],\n",
+ " [ 4.26769257e-04],\n",
+ " [-1.19447708e-04],\n",
+ " [-2.77519226e-03],\n",
+ " [ 5.27381897e-04],\n",
+ " [-8.44001770e-04],\n",
+ " [ 4.88281250e-04],\n",
+ " [-2.11715698e-04],\n",
+ " [-1.00421906e-03]])"
+ ]
+ },
+ "execution_count": 24,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "preds = trainer.predict(eval_ds).predictions.astype(float)\n",
+ "preds"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "138c6cd1-e0cb-405e-8b15-952e90c6a954",
+ "metadata": {},
+ "source": [
+ "Look out - some of our predictions are <0, or >1! Let's fix those out-of-bounds predictions:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "id": "d6cfff69-3178-4afb-858e-5653a938e3af",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([[0. ],\n",
+ " [0.0049057 ],\n",
+ " [0. ],\n",
+ " [0.00026941],\n",
+ " [0. ],\n",
+ " [0.0004859 ],\n",
+ " [0. ],\n",
+ " [0.00082207],\n",
+ " [0.0043602 ],\n",
+ " [0.00440216],\n",
+ " [0. ],\n",
+ " [0. ],\n",
+ " [0. ],\n",
+ " [0.00031829],\n",
+ " [0. ],\n",
+ " [0. ],\n",
+ " [0. ],\n",
+ " [0.00026011],\n",
+ " [0.00348282],\n",
+ " [0.00168324],\n",
+ " [0.00138378],\n",
+ " [0. ],\n",
+ " [0.00075388],\n",
+ " [0.00085592],\n",
+ " [0. ],\n",
+ " [0. ],\n",
+ " [0.00329781],\n",
+ " [0.00094271],\n",
+ " [0.00042677],\n",
+ " [0. ],\n",
+ " [0. ],\n",
+ " [0.00052738],\n",
+ " [0. ],\n",
+ " [0.00048828],\n",
+ " [0. ],\n",
+ " [0. ]])"
+ ]
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "preds = np.clip(preds, 0, 1)\n",
+ "preds"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "464c75ad-e4c3-4c6a-a776-c98011ed5eba",
+ "metadata": {
+ "jp-MarkdownHeadingCollapsed": true
+ },
+ "source": [
+ "# Acknowledgments\n",
+ "\n",
+ "Thanks to [Jeremy Howard](https://www.kaggle.com/jhoward) for creating [Getting started with NLP for absolute beginners](https://www.kaggle.com/code/jhoward/getting-started-with-nlp-for-absolute-beginners). It inspires the majority of the content in this chapter."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "vmamba",
+ "language": "python",
+ "name": "vmamba"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/_sources/assignments/machine-learning-productionization/random-forest-classifier.ipynb b/_sources/assignments/machine-learning-productionization/random-forest-classifier.ipynb
new file mode 100644
index 0000000000..16f232bd58
--- /dev/null
+++ b/_sources/assignments/machine-learning-productionization/random-forest-classifier.ipynb
@@ -0,0 +1 @@
+{"cells":[{"cell_type":"markdown","metadata":{},"source":["LICENSE \n","\n","Copyright 2018 Google LLC.\n","\n","Licensed under the Apache License, Version 2.0 (the \"License\");\n","you may not use this file except in compliance with the License.\n","You may obtain a copy of the License at\n","\n","https://www.apache.org/licenses/LICENSE-2.0\n","\n","Unless required by applicable law or agreed to in writing, software\n","distributed under the License is distributed on an \"AS IS\" BASIS,\n","WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n","See the License for the specific language governing permissions and\n","limitations under the License.\n"," "]},{"cell_type":"markdown","metadata":{},"source":["# Introduction"]},{"cell_type":"markdown","metadata":{},"source":["Climate Prediction-Random Forest is a model that uses a combination of climate variables and machine learning algorithms to predict future climate conditions. The model is trained on a large dataset of climate observations and uses a random forest approach to generate predictions. The predictions are based on the relationships between the climate variables and the random forest algorithm is able to capture complex patterns in the data."]},{"cell_type":"markdown","metadata":{},"source":["## Importing Libraries"]},{"cell_type":"code","execution_count":1,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:09.977471Z","iopub.status.busy":"2021-09-12T07:42:09.976692Z","iopub.status.idle":"2021-09-12T07:42:11.175857Z","shell.execute_reply":"2021-09-12T07:42:11.174872Z","shell.execute_reply.started":"2021-09-12T07:42:09.977341Z"},"hideCode":false,"hidePrompt":false,"id":"d4a2uASN7jbm","outputId":"a31fc9d2-6d41-4f32-f935-4de1392fb75d","trusted":true},"outputs":[],"source":["# Pandas is used for data manipulation\n","import pandas as pd\n","\n","# Use numpy to convert to arrays\n","import numpy as np\n","\n","# Import tools needed for visualization\n","\n","import matplotlib.pyplot as plt\n","%matplotlib inline"]},{"cell_type":"markdown","metadata":{"execution":{"iopub.execute_input":"2021-06-05T03:15:54.659441Z","iopub.status.busy":"2021-06-05T03:15:54.658886Z","iopub.status.idle":"2021-06-05T03:15:54.679235Z","shell.execute_reply":"2021-06-05T03:15:54.677744Z","shell.execute_reply.started":"2021-06-05T03:15:54.659396Z"}},"source":["## Data Exploration"]},{"cell_type":"code","execution_count":2,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.178015Z","iopub.status.busy":"2021-09-12T07:42:11.177625Z","iopub.status.idle":"2021-09-12T07:42:11.198022Z","shell.execute_reply":"2021-09-12T07:42:11.197162Z","shell.execute_reply.started":"2021-09-12T07:42:11.177971Z"},"trusted":true},"outputs":[],"source":["# Reading the data to a dataframe \n","df = pd.read_csv('https://static-1300131294.cos.ap-shanghai.myqcloud.com/data/classification/temps.csv')"]},{"cell_type":"code","execution_count":3,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.201049Z","iopub.status.busy":"2021-09-12T07:42:11.200281Z","iopub.status.idle":"2021-09-12T07:42:11.230628Z","shell.execute_reply":"2021-09-12T07:42:11.229917Z","shell.execute_reply.started":"2021-09-12T07:42:11.200999Z"},"trusted":true},"outputs":[{"data":{"text/html":["\n","\n","
\n"," \n"," \n"," \n"," year \n"," month \n"," day \n"," week \n"," temp_2 \n"," temp_1 \n"," average \n"," actual \n"," friend \n"," \n"," \n"," \n"," \n"," 0 \n"," 2019 \n"," 1 \n"," 1 \n"," Fri \n"," 45 \n"," 45 \n"," 45.6 \n"," 45 \n"," 29 \n"," \n"," \n"," 1 \n"," 2019 \n"," 1 \n"," 2 \n"," Sat \n"," 44 \n"," 45 \n"," 45.7 \n"," 44 \n"," 61 \n"," \n"," \n"," 2 \n"," 2019 \n"," 1 \n"," 3 \n"," Sun \n"," 45 \n"," 44 \n"," 45.8 \n"," 41 \n"," 56 \n"," \n"," \n"," 3 \n"," 2019 \n"," 1 \n"," 4 \n"," Mon \n"," 44 \n"," 41 \n"," 45.9 \n"," 40 \n"," 53 \n"," \n"," \n"," 4 \n"," 2019 \n"," 1 \n"," 5 \n"," Tues \n"," 41 \n"," 40 \n"," 46.0 \n"," 44 \n"," 41 \n"," \n"," \n","
\n","
"],"text/plain":[" year month day week temp_2 temp_1 average actual friend\n","0 2019 1 1 Fri 45 45 45.6 45 29\n","1 2019 1 2 Sat 44 45 45.7 44 61\n","2 2019 1 3 Sun 45 44 45.8 41 56\n","3 2019 1 4 Mon 44 41 45.9 40 53\n","4 2019 1 5 Tues 41 40 46.0 44 41"]},"execution_count":3,"metadata":{},"output_type":"execute_result"}],"source":["# displaying first 5 rows\n","df.head(5)"]},{"cell_type":"code","execution_count":4,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.232535Z","iopub.status.busy":"2021-09-12T07:42:11.232032Z","iopub.status.idle":"2021-09-12T07:42:11.237917Z","shell.execute_reply":"2021-09-12T07:42:11.236766Z","shell.execute_reply.started":"2021-09-12T07:42:11.232503Z"},"hideCode":false,"hidePrompt":false,"id":"5aXM1w987jbq","outputId":"c9eabdf4-30d9-4df4-b890-b28df3c5287b","trusted":true},"outputs":[{"data":{"text/plain":["(348, 9)"]},"execution_count":4,"metadata":{},"output_type":"execute_result"}],"source":["# the shape of our features\n","df.shape"]},{"cell_type":"code","execution_count":5,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.239954Z","iopub.status.busy":"2021-09-12T07:42:11.239514Z","iopub.status.idle":"2021-09-12T07:42:11.253434Z","shell.execute_reply":"2021-09-12T07:42:11.252149Z","shell.execute_reply.started":"2021-09-12T07:42:11.239913Z"},"trusted":true},"outputs":[{"data":{"text/plain":["Index(['year', 'month', 'day', 'week', 'temp_2', 'temp_1', 'average', 'actual',\n"," 'friend'],\n"," dtype='object')"]},"execution_count":5,"metadata":{},"output_type":"execute_result"}],"source":["# column names\n","df.columns"]},{"cell_type":"code","execution_count":6,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.256082Z","iopub.status.busy":"2021-09-12T07:42:11.255489Z","iopub.status.idle":"2021-09-12T07:42:11.271869Z","shell.execute_reply":"2021-09-12T07:42:11.270748Z","shell.execute_reply.started":"2021-09-12T07:42:11.256038Z"},"trusted":true},"outputs":[{"data":{"text/plain":["year 0\n","month 0\n","day 0\n","week 0\n","temp_2 0\n","temp_1 0\n","average 0\n","actual 0\n","friend 0\n","dtype: int64"]},"execution_count":6,"metadata":{},"output_type":"execute_result"}],"source":["# checking for null values\n","df.isnull().sum()"]},{"cell_type":"markdown","metadata":{},"source":["There are no null values"]},{"cell_type":"markdown","metadata":{"id":"Nzu0v5mQ7jbs"},"source":["## One-Hot Encoding"]},{"cell_type":"markdown","metadata":{"execution":{"iopub.execute_input":"2021-06-05T03:26:04.246284Z","iopub.status.busy":"2021-06-05T03:26:04.245896Z","iopub.status.idle":"2021-06-05T03:26:04.252279Z","shell.execute_reply":"2021-06-05T03:26:04.250937Z","shell.execute_reply.started":"2021-06-05T03:26:04.246247Z"}},"source":["A one hot encoding allows the representation of categorical data to be more expressive. "]},{"cell_type":"code","execution_count":7,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.273448Z","iopub.status.busy":"2021-09-12T07:42:11.273117Z","iopub.status.idle":"2021-09-12T07:42:11.308893Z","shell.execute_reply":"2021-09-12T07:42:11.307365Z","shell.execute_reply.started":"2021-09-12T07:42:11.273418Z"},"hideCode":false,"hidePrompt":false,"id":"VURjcTE27jbu","outputId":"12cc15a3-072a-4e40-89c8-009ea27c2622","trusted":true},"outputs":[{"data":{"text/html":["\n","\n","
\n"," \n"," \n"," \n"," year \n"," month \n"," day \n"," temp_2 \n"," temp_1 \n"," average \n"," actual \n"," friend \n"," week_Fri \n"," week_Mon \n"," week_Sat \n"," week_Sun \n"," week_Thurs \n"," week_Tues \n"," week_Wed \n"," \n"," \n"," \n"," \n"," 0 \n"," 2019 \n"," 1 \n"," 1 \n"," 45 \n"," 45 \n"," 45.6 \n"," 45 \n"," 29 \n"," True \n"," False \n"," False \n"," False \n"," False \n"," False \n"," False \n"," \n"," \n"," 1 \n"," 2019 \n"," 1 \n"," 2 \n"," 44 \n"," 45 \n"," 45.7 \n"," 44 \n"," 61 \n"," False \n"," False \n"," True \n"," False \n"," False \n"," False \n"," False \n"," \n"," \n"," 2 \n"," 2019 \n"," 1 \n"," 3 \n"," 45 \n"," 44 \n"," 45.8 \n"," 41 \n"," 56 \n"," False \n"," False \n"," False \n"," True \n"," False \n"," False \n"," False \n"," \n"," \n"," 3 \n"," 2019 \n"," 1 \n"," 4 \n"," 44 \n"," 41 \n"," 45.9 \n"," 40 \n"," 53 \n"," False \n"," True \n"," False \n"," False \n"," False \n"," False \n"," False \n"," \n"," \n"," 4 \n"," 2019 \n"," 1 \n"," 5 \n"," 41 \n"," 40 \n"," 46.0 \n"," 44 \n"," 41 \n"," False \n"," False \n"," False \n"," False \n"," False \n"," True \n"," False \n"," \n"," \n","
\n","
"],"text/plain":[" year month day temp_2 temp_1 average actual friend week_Fri \\\n","0 2019 1 1 45 45 45.6 45 29 True \n","1 2019 1 2 44 45 45.7 44 61 False \n","2 2019 1 3 45 44 45.8 41 56 False \n","3 2019 1 4 44 41 45.9 40 53 False \n","4 2019 1 5 41 40 46.0 44 41 False \n","\n"," week_Mon week_Sat week_Sun week_Thurs week_Tues week_Wed \n","0 False False False False False False \n","1 False True False False False False \n","2 False False True False False False \n","3 True False False False False False \n","4 False False False False True False "]},"execution_count":7,"metadata":{},"output_type":"execute_result"}],"source":["# One-hot encode categorical features\n","df = pd.get_dummies(df)\n","df.head(5)"]},{"cell_type":"code","execution_count":8,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.312525Z","iopub.status.busy":"2021-09-12T07:42:11.312019Z","iopub.status.idle":"2021-09-12T07:42:11.320042Z","shell.execute_reply":"2021-09-12T07:42:11.318836Z","shell.execute_reply.started":"2021-09-12T07:42:11.312458Z"},"id":"zgYBtUrr7jbv","outputId":"69df322f-2e24-4576-9fd2-d34773ac406c","trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Shape of features after one-hot encoding: (348, 15)\n"]}],"source":["print('Shape of features after one-hot encoding:', df.shape)"]},{"cell_type":"markdown","metadata":{"id":"mtd7DqrQ7jbw"},"source":["## Features and Labels"]},{"cell_type":"code","execution_count":9,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.322293Z","iopub.status.busy":"2021-09-12T07:42:11.321937Z","iopub.status.idle":"2021-09-12T07:42:11.33496Z","shell.execute_reply":"2021-09-12T07:42:11.333645Z","shell.execute_reply.started":"2021-09-12T07:42:11.322261Z"},"id":"2rYCVrfV7jbx","trusted":true},"outputs":[],"source":["# Labels are the values we want to predict\n","labels = df['actual']\n","\n","# Remove the labels from the features\n","df = df.drop('actual', axis = 1)\n","\n","# Saving feature names for later use\n","feature_list = list(df.columns)"]},{"cell_type":"markdown","metadata":{"id":"Q6SSjx5p7jb0"},"source":["## Train Test Split"]},{"cell_type":"code","execution_count":10,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.336918Z","iopub.status.busy":"2021-09-12T07:42:11.336569Z","iopub.status.idle":"2021-09-12T07:42:11.348348Z","shell.execute_reply":"2021-09-12T07:42:11.347294Z","shell.execute_reply.started":"2021-09-12T07:42:11.336886Z"},"id":"11BJUq0s7jb0","trusted":true},"outputs":[],"source":["# Using Skicit-learn to split data into training and testing sets\n","from sklearn.model_selection import train_test_split\n","\n","# Split the data into training and testing sets\n","train_features, test_features, train_labels, test_labels = train_test_split(df,\n"," labels,\n"," test_size = 0.20,\n"," random_state = 42)"]},{"cell_type":"code","execution_count":11,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.350455Z","iopub.status.busy":"2021-09-12T07:42:11.350066Z","iopub.status.idle":"2021-09-12T07:42:11.358556Z","shell.execute_reply":"2021-09-12T07:42:11.357489Z","shell.execute_reply.started":"2021-09-12T07:42:11.350426Z"},"id":"KkVnZf4H7jb2","outputId":"3c0a9db7-0f71-44be-bd0a-946fddc7d048","trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Training Features Shape: (278, 14)\n","Training Labels Shape: (278,)\n","Testing Features Shape: (70, 14)\n","Testing Labels Shape: (70,)\n"]}],"source":["print('Training Features Shape:', train_features.shape)\n","print('Training Labels Shape:', train_labels.shape)\n","print('Testing Features Shape:', test_features.shape)\n","print('Testing Labels Shape:', test_labels.shape)"]},{"cell_type":"markdown","metadata":{"id":"ny3qdq-i7jb4"},"source":["## Training the Forest"]},{"cell_type":"code","execution_count":12,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:11.360258Z","iopub.status.busy":"2021-09-12T07:42:11.359962Z","iopub.status.idle":"2021-09-12T07:42:13.842601Z","shell.execute_reply":"2021-09-12T07:42:13.841175Z","shell.execute_reply.started":"2021-09-12T07:42:11.360229Z"},"hideCode":false,"hidePrompt":false,"id":"d_Vboxs77jb5","trusted":true},"outputs":[],"source":["# Import the model we are using\n","from sklearn.ensemble import RandomForestRegressor\n","\n","# Instantiate model \n","rf = RandomForestRegressor(n_estimators= 1000, random_state=42)\n","\n","# Train the model on training data\n","rf.fit(train_features, train_labels);"]},{"cell_type":"markdown","metadata":{"id":"rJz8X7b77jb6"},"source":["## Make Predictions on Test Data"]},{"cell_type":"code","execution_count":13,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:13.844914Z","iopub.status.busy":"2021-09-12T07:42:13.844471Z","iopub.status.idle":"2021-09-12T07:42:13.975596Z","shell.execute_reply":"2021-09-12T07:42:13.974317Z","shell.execute_reply.started":"2021-09-12T07:42:13.84487Z"},"id":"pssgaBC67jb6","outputId":"5a3a9029-c98b-4ac8-c081-2f7e17c3ca86","trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Mean Absolute Error: 3.78 degrees.\n"]}],"source":["# Use the forest's predict method on the test data\n","predictions = rf.predict(test_features)\n","\n","# Calculate the absolute errors\n","errors = abs(predictions - test_labels)\n","\n","# Print out the mean absolute error (mae)\n","print('Mean Absolute Error:', round(np.mean(errors), 2), 'degrees.')\n"]},{"cell_type":"code","execution_count":14,"metadata":{"execution":{"iopub.execute_input":"2021-09-12T07:42:13.978583Z","iopub.status.busy":"2021-09-12T07:42:13.97822Z","iopub.status.idle":"2021-09-12T07:42:13.985832Z","shell.execute_reply":"2021-09-12T07:42:13.984493Z","shell.execute_reply.started":"2021-09-12T07:42:13.978549Z"},"id":"fDaM3Z677jb7","outputId":"2307bab3-cb96-4a7a-f57d-3a9d80cec129","trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Accuracy: 94.02 %.\n"]}],"source":["# Calculate mean absolute percentage error (MAPE)\n","mape = 100 * (errors / test_labels)\n","\n","# Calculate and display accuracy\n","accuracy = 100 - np.mean(mape)\n","print('Accuracy:', round(accuracy, 2), '%.')"]},{"cell_type":"markdown","metadata":{"id":"9U2KQYmS7jb7"},"source":["## Visualizing a Single Decision Tree"]},{"cell_type":"markdown","metadata":{"id":"Cnbb-pTt7jb9"},"source":["![Decision Tree](https://static-1300131294.cos.ap-shanghai.myqcloud.com/images/assignment/deep-learning/nn/tree.png)"]},{"cell_type":"markdown","metadata":{},"source":["## Your turn! 🚀\n","You can practice your random-forest skills by following the assignment [Climate Prediction-Random Forest](../../assignments/machine-learning-productionization/random-forest-classifier.ipynb)."]},{"cell_type":"markdown","metadata":{},"source":["## Acknowledgments\n","\n","Thanks to Kaggle for creating the open source course [Climate Prediction-Random Forest](https://www.kaggle.com/code/anandhuh/climate-prediction-random-forest-94-accuracy?scriptVersionId=74560159&cellId=26). It contributes some of the content in this chapter."]}],"metadata":{"kaggle":{"accelerator":"none","dataSources":[{"datasetId":1018620,"sourceId":1717426,"sourceType":"datasetVersion"}],"dockerImageVersionId":30096,"isGpuEnabled":false,"isInternetEnabled":false,"language":"python","sourceType":"notebook"},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.11.5"}},"nbformat":4,"nbformat_minor":4}
diff --git a/_sources/assignments/ml-fundamentals/create-a-regression-model.ipynb b/_sources/assignments/ml-fundamentals/create-a-regression-model.ipynb
index a5ecb1db0a..5b96cb622c 100644
--- a/_sources/assignments/ml-fundamentals/create-a-regression-model.ipynb
+++ b/_sources/assignments/ml-fundamentals/create-a-regression-model.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "ee2af449",
+ "id": "6e4ad8e0",
"metadata": {},
"source": [
"# Create a regression model\n",
diff --git a/_sources/assignments/ml-fundamentals/exploring-visualizations.ipynb b/_sources/assignments/ml-fundamentals/exploring-visualizations.ipynb
index 1f287345e2..2b91d3a104 100644
--- a/_sources/assignments/ml-fundamentals/exploring-visualizations.ipynb
+++ b/_sources/assignments/ml-fundamentals/exploring-visualizations.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "70c3fb3a",
+ "id": "8633a20a",
"metadata": {},
"source": [
"# Exploring visualizations\n",
diff --git a/_sources/assignments/ml-fundamentals/parameter-play.ipynb b/_sources/assignments/ml-fundamentals/parameter-play.ipynb
index 7290324945..8c808e78eb 100644
--- a/_sources/assignments/ml-fundamentals/parameter-play.ipynb
+++ b/_sources/assignments/ml-fundamentals/parameter-play.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "b62869bf",
+ "id": "ccc592ea",
"metadata": {},
"source": [
"# Parameter play\n",
diff --git a/_sources/assignments/ml-fundamentals/regression-with-scikit-learn.ipynb b/_sources/assignments/ml-fundamentals/regression-with-scikit-learn.ipynb
index 4b58aa3f21..48bcd3b714 100644
--- a/_sources/assignments/ml-fundamentals/regression-with-scikit-learn.ipynb
+++ b/_sources/assignments/ml-fundamentals/regression-with-scikit-learn.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "2812ba9a",
+ "id": "d5e8515c",
"metadata": {},
"source": [
"# Regression with Scikit-learn\n",
diff --git a/_sources/assignments/ml-fundamentals/retrying-some-regression.ipynb b/_sources/assignments/ml-fundamentals/retrying-some-regression.ipynb
index 7db5432d06..1c55b67f0e 100644
--- a/_sources/assignments/ml-fundamentals/retrying-some-regression.ipynb
+++ b/_sources/assignments/ml-fundamentals/retrying-some-regression.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "4e729fc1",
+ "id": "441cd1b1",
"metadata": {},
"source": [
"# Retrying some regression\n",
diff --git a/_sources/data-science/working-with-data/numpy.ipynb b/_sources/data-science/working-with-data/numpy.ipynb
index 13cc19f4b8..26b6ec9650 100644
--- a/_sources/data-science/working-with-data/numpy.ipynb
+++ b/_sources/data-science/working-with-data/numpy.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "1816b909",
+ "id": "1824344d",
"metadata": {},
"source": [
"# NumPy\n",
@@ -19,7 +19,7 @@
{
"cell_type": "code",
"execution_count": 1,
- "id": "16db2570",
+ "id": "524f2024",
"metadata": {},
"outputs": [
{
@@ -40,7 +40,7 @@
},
{
"cell_type": "markdown",
- "id": "0ea8e4d9",
+ "id": "0ecaa4a1",
"metadata": {},
"source": [
"### Create a basic array\n",
@@ -53,7 +53,7 @@
{
"cell_type": "code",
"execution_count": 2,
- "id": "f3a97a93",
+ "id": "fdbbbc0b",
"metadata": {},
"outputs": [
{
@@ -75,7 +75,7 @@
},
{
"cell_type": "markdown",
- "id": "db97ae62",
+ "id": "52e94fbd",
"metadata": {},
"source": [
"Besides creating an array from a sequence of elements, you can easily create an array filled with `0`’s:"
@@ -84,7 +84,7 @@
{
"cell_type": "code",
"execution_count": 3,
- "id": "03b948d2",
+ "id": "e00c2e09",
"metadata": {},
"outputs": [
{
@@ -104,7 +104,7 @@
},
{
"cell_type": "markdown",
- "id": "9d11a2b8",
+ "id": "754873dd",
"metadata": {},
"source": [
"Or an array filled with 1’s:"
@@ -113,7 +113,7 @@
{
"cell_type": "code",
"execution_count": 4,
- "id": "f31d9d52",
+ "id": "a4fcd2e2",
"metadata": {},
"outputs": [
{
@@ -133,7 +133,7 @@
},
{
"cell_type": "markdown",
- "id": "a44b0e87",
+ "id": "4c6327c9",
"metadata": {},
"source": [
"Or even an empty array! The function `empty` creates an array whose initial content is random and depends on the state of the memory. The reason to use `empty` over `zeros` (or something similar) is speed - just make sure to fill every element afterwards!"
@@ -142,7 +142,7 @@
{
"cell_type": "code",
"execution_count": 5,
- "id": "d02a7123",
+ "id": "453ab575",
"metadata": {},
"outputs": [
{
@@ -162,7 +162,7 @@
},
{
"cell_type": "markdown",
- "id": "c4546a55",
+ "id": "ef83f671",
"metadata": {},
"source": [
"You can create an array with a range of elements:"
@@ -171,7 +171,7 @@
{
"cell_type": "code",
"execution_count": 6,
- "id": "cbad5e9e",
+ "id": "a3d25666",
"metadata": {},
"outputs": [
{
@@ -191,7 +191,7 @@
},
{
"cell_type": "markdown",
- "id": "c4ae3281",
+ "id": "a1e4a408",
"metadata": {},
"source": [
"And even an array that contains a range of evenly spaced intervals. To do this, you will specify the **first number**, **last number**, and the **step size**."
@@ -200,7 +200,7 @@
{
"cell_type": "code",
"execution_count": 7,
- "id": "796953a0",
+ "id": "6851463b",
"metadata": {},
"outputs": [
{
@@ -220,7 +220,7 @@
},
{
"cell_type": "markdown",
- "id": "41299cfe",
+ "id": "214052a9",
"metadata": {},
"source": [
"You can also use `np.linspace()` to create an array with values that are spaced linearly in a specified interval:"
@@ -229,7 +229,7 @@
{
"cell_type": "code",
"execution_count": 8,
- "id": "411e39bd",
+ "id": "392ba480",
"metadata": {},
"outputs": [
{
@@ -249,7 +249,7 @@
},
{
"cell_type": "markdown",
- "id": "d416d0be",
+ "id": "758d340d",
"metadata": {},
"source": [
"While the default data type is floating point (`np.float64`), you can explicitly specify which data type you want using the `dtype` keyword."
@@ -258,7 +258,7 @@
{
"cell_type": "code",
"execution_count": 9,
- "id": "0cfcf49d",
+ "id": "4956e399",
"metadata": {},
"outputs": [
{
@@ -278,7 +278,7 @@
},
{
"cell_type": "markdown",
- "id": "58557c57",
+ "id": "424fc3cf",
"metadata": {},
"source": [
"### Adding, removing, and sorting elements\n",
@@ -291,7 +291,7 @@
{
"cell_type": "code",
"execution_count": 10,
- "id": "c5680f41",
+ "id": "82acaac3",
"metadata": {},
"outputs": [],
"source": [
@@ -300,7 +300,7 @@
},
{
"cell_type": "markdown",
- "id": "03ca1110",
+ "id": "d1b1a4a4",
"metadata": {},
"source": [
"You can quickly sort the numbers in ascending order with:"
@@ -309,7 +309,7 @@
{
"cell_type": "code",
"execution_count": 11,
- "id": "6bfee14a",
+ "id": "33f1d0f9",
"metadata": {},
"outputs": [
{
@@ -329,7 +329,7 @@
},
{
"cell_type": "markdown",
- "id": "312788c4",
+ "id": "290dc695",
"metadata": {},
"source": [
"In addition to sort, which returns a sorted copy of an array, you can use:\n",
@@ -345,7 +345,7 @@
{
"cell_type": "code",
"execution_count": 12,
- "id": "3b8ccf7d",
+ "id": "59a365e9",
"metadata": {},
"outputs": [],
"source": [
@@ -355,7 +355,7 @@
},
{
"cell_type": "markdown",
- "id": "e0b12155",
+ "id": "abfb3a12",
"metadata": {},
"source": [
"You can concatenate them with `np.concatenate()`."
@@ -364,7 +364,7 @@
{
"cell_type": "code",
"execution_count": 13,
- "id": "47e4d2d7",
+ "id": "178dc1a9",
"metadata": {},
"outputs": [
{
@@ -384,7 +384,7 @@
},
{
"cell_type": "markdown",
- "id": "14f32192",
+ "id": "81c2d2cc",
"metadata": {},
"source": [
"Or, if you start with these arrays:"
@@ -393,7 +393,7 @@
{
"cell_type": "code",
"execution_count": 14,
- "id": "03035494",
+ "id": "0041f9cb",
"metadata": {},
"outputs": [],
"source": [
@@ -403,7 +403,7 @@
},
{
"cell_type": "markdown",
- "id": "f1177f1f",
+ "id": "62a5fda3",
"metadata": {},
"source": [
"You can concatenate them with:"
@@ -412,7 +412,7 @@
{
"cell_type": "code",
"execution_count": 15,
- "id": "b55eb0c6",
+ "id": "c5b2ad7f",
"metadata": {},
"outputs": [
{
@@ -434,7 +434,7 @@
},
{
"cell_type": "markdown",
- "id": "bebaef59",
+ "id": "023eed3d",
"metadata": {},
"source": [
"In order to remove elements from an array, it’s simple to use indexing to select the elements that you want to keep.\n",
@@ -450,7 +450,7 @@
{
"cell_type": "code",
"execution_count": 16,
- "id": "e0ae6518",
+ "id": "7e0508c9",
"metadata": {},
"outputs": [
{
@@ -475,7 +475,7 @@
{
"cell_type": "code",
"execution_count": 17,
- "id": "d88c14eb",
+ "id": "72bcb260",
"metadata": {},
"outputs": [
{
@@ -495,7 +495,7 @@
},
{
"cell_type": "markdown",
- "id": "42651f1a",
+ "id": "a64eea9d",
"metadata": {},
"source": [
"- ndarray.shape\n",
@@ -505,7 +505,7 @@
{
"cell_type": "code",
"execution_count": 18,
- "id": "034505ee",
+ "id": "6f45f950",
"metadata": {},
"outputs": [
{
@@ -525,7 +525,7 @@
},
{
"cell_type": "markdown",
- "id": "6319a33f",
+ "id": "68585758",
"metadata": {},
"source": [
"- ndarray.size\n",
@@ -535,7 +535,7 @@
{
"cell_type": "code",
"execution_count": 19,
- "id": "b02dad23",
+ "id": "7e313856",
"metadata": {},
"outputs": [
{
@@ -555,7 +555,7 @@
},
{
"cell_type": "markdown",
- "id": "40df55da",
+ "id": "3a2d0042",
"metadata": {},
"source": [
"- ndarray.dtype\n",
@@ -565,7 +565,7 @@
{
"cell_type": "code",
"execution_count": 20,
- "id": "d0ee25cc",
+ "id": "a23efb5c",
"metadata": {},
"outputs": [
{
@@ -586,7 +586,7 @@
{
"cell_type": "code",
"execution_count": 21,
- "id": "ce5388d2",
+ "id": "587a63a9",
"metadata": {},
"outputs": [
{
@@ -606,7 +606,7 @@
},
{
"cell_type": "markdown",
- "id": "13f9ecb1",
+ "id": "5c23cb2e",
"metadata": {},
"source": [
"- ndarray.itemsize\n",
@@ -616,7 +616,7 @@
{
"cell_type": "code",
"execution_count": 22,
- "id": "a37e6226",
+ "id": "00a5ec05",
"metadata": {},
"outputs": [
{
@@ -636,7 +636,7 @@
},
{
"cell_type": "markdown",
- "id": "2f645661",
+ "id": "021373f2",
"metadata": {},
"source": [
"- ndarray.data\n",
@@ -646,13 +646,13 @@
{
"cell_type": "code",
"execution_count": 23,
- "id": "230eb0a8",
+ "id": "246a9ae5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 23,
@@ -666,7 +666,7 @@
},
{
"cell_type": "markdown",
- "id": "c1391da9",
+ "id": "c8c621a6",
"metadata": {},
"source": [
"### Reshape an array\n",
@@ -679,7 +679,7 @@
{
"cell_type": "code",
"execution_count": 24,
- "id": "eb269161",
+ "id": "f303592f",
"metadata": {},
"outputs": [
{
@@ -700,7 +700,7 @@
},
{
"cell_type": "markdown",
- "id": "e1799fdd",
+ "id": "9966b1c7",
"metadata": {},
"source": [
"You can use `reshape()` to reshape your array. For example, you can reshape this array to an array with three rows and two columns:"
@@ -709,7 +709,7 @@
{
"cell_type": "code",
"execution_count": 25,
- "id": "474b905b",
+ "id": "ca2f6ae0",
"metadata": {},
"outputs": [
{
@@ -732,7 +732,7 @@
},
{
"cell_type": "markdown",
- "id": "b652bd10",
+ "id": "3cba7acb",
"metadata": {},
"source": [
"With `np.reshape`, you can specify a few optional parameters:"
@@ -741,7 +741,7 @@
{
"cell_type": "code",
"execution_count": 26,
- "id": "2111b540",
+ "id": "91843f24",
"metadata": {},
"outputs": [
{
@@ -761,7 +761,7 @@
},
{
"cell_type": "markdown",
- "id": "3fe6825e",
+ "id": "1a0a17fc",
"metadata": {},
"source": [
"`a` is the array to be reshaped.\n",
@@ -782,7 +782,7 @@
{
"cell_type": "code",
"execution_count": 27,
- "id": "9c7d4be6",
+ "id": "dc26bcaa",
"metadata": {},
"outputs": [
{
@@ -803,7 +803,7 @@
},
{
"cell_type": "markdown",
- "id": "b8f5cdba",
+ "id": "c9c3ad13",
"metadata": {},
"source": [
"You can use `np.newaxis` to add a new axis:"
@@ -812,7 +812,7 @@
{
"cell_type": "code",
"execution_count": 28,
- "id": "ecc8a5a1",
+ "id": "222e3bbc",
"metadata": {},
"outputs": [
{
@@ -833,7 +833,7 @@
},
{
"cell_type": "markdown",
- "id": "2136fbc5",
+ "id": "5aca6723",
"metadata": {},
"source": [
"You can explicitly convert a 1D array with either a row vector or a column vector using `np.newaxis`. For example, you can convert a 1D array to a row vector by inserting an axis along the first dimension:"
@@ -842,7 +842,7 @@
{
"cell_type": "code",
"execution_count": 29,
- "id": "5f5c0256",
+ "id": "78686b80",
"metadata": {},
"outputs": [
{
@@ -863,7 +863,7 @@
},
{
"cell_type": "markdown",
- "id": "f446042c",
+ "id": "1880a2bc",
"metadata": {},
"source": [
"Or, for a column vector, you can insert an axis along the second dimension:"
@@ -872,7 +872,7 @@
{
"cell_type": "code",
"execution_count": 30,
- "id": "085bcaea",
+ "id": "79e0afad",
"metadata": {},
"outputs": [
{
@@ -893,7 +893,7 @@
},
{
"cell_type": "markdown",
- "id": "e14b2290",
+ "id": "39c555ff",
"metadata": {},
"source": [
"You can also expand an array by inserting a new axis at a specified position with `np.expand_dims`.\n",
@@ -904,7 +904,7 @@
{
"cell_type": "code",
"execution_count": 31,
- "id": "43063c3a",
+ "id": "2702b9e5",
"metadata": {},
"outputs": [
{
@@ -925,7 +925,7 @@
},
{
"cell_type": "markdown",
- "id": "f1ca9224",
+ "id": "02d4d8ad",
"metadata": {},
"source": [
"You can use np.expand_dims to add an axis at index position 1 with:"
@@ -934,7 +934,7 @@
{
"cell_type": "code",
"execution_count": 32,
- "id": "54426fa5",
+ "id": "f399bc85",
"metadata": {},
"outputs": [
{
@@ -955,7 +955,7 @@
},
{
"cell_type": "markdown",
- "id": "ad62b973",
+ "id": "1d3afbaa",
"metadata": {},
"source": [
"You can add an axis at index position 0 with:"
@@ -964,7 +964,7 @@
{
"cell_type": "code",
"execution_count": 33,
- "id": "e5b4e1db",
+ "id": "8b5f3d80",
"metadata": {},
"outputs": [
{
@@ -985,7 +985,7 @@
},
{
"cell_type": "markdown",
- "id": "a7d628d0",
+ "id": "f5643a8d",
"metadata": {},
"source": [
"### Indexing and slicing\n",
@@ -996,7 +996,7 @@
{
"cell_type": "code",
"execution_count": 34,
- "id": "7744b04c",
+ "id": "989b5895",
"metadata": {},
"outputs": [],
"source": [
@@ -1006,7 +1006,7 @@
{
"cell_type": "code",
"execution_count": 35,
- "id": "e57b89ed",
+ "id": "5b691c28",
"metadata": {},
"outputs": [
{
@@ -1027,7 +1027,7 @@
{
"cell_type": "code",
"execution_count": 36,
- "id": "871490cb",
+ "id": "0215274d",
"metadata": {},
"outputs": [
{
@@ -1048,7 +1048,7 @@
{
"cell_type": "code",
"execution_count": 37,
- "id": "b1edf739",
+ "id": "bf45b2af",
"metadata": {},
"outputs": [
{
@@ -1069,7 +1069,7 @@
{
"cell_type": "code",
"execution_count": 38,
- "id": "4f445c63",
+ "id": "e7bdb1d6",
"metadata": {},
"outputs": [
{
@@ -1089,7 +1089,7 @@
},
{
"cell_type": "markdown",
- "id": "abe25bce",
+ "id": "b6be28c4",
"metadata": {},
"source": [
"You may want to take a section of your array or specific array elements to use in further analysis or additional operations. To do that, you’ll need to subset, slice, and/or index your arrays.\n",
@@ -1102,7 +1102,7 @@
{
"cell_type": "code",
"execution_count": 39,
- "id": "4ff5af74",
+ "id": "6c11e978",
"metadata": {},
"outputs": [],
"source": [
@@ -1111,7 +1111,7 @@
},
{
"cell_type": "markdown",
- "id": "46e9a9e4",
+ "id": "71c0d6dd",
"metadata": {},
"source": [
"You can easily print all of the values in the array that are less than 5."
@@ -1120,7 +1120,7 @@
{
"cell_type": "code",
"execution_count": 40,
- "id": "315c2a6d",
+ "id": "d8a5e5b6",
"metadata": {},
"outputs": [
{
@@ -1140,7 +1140,7 @@
},
{
"cell_type": "markdown",
- "id": "48eb2ce0",
+ "id": "62ca2bd5",
"metadata": {},
"source": [
"You can also select, for example, numbers that are equal to or greater than 5, and use that condition to index an array."
@@ -1149,7 +1149,7 @@
{
"cell_type": "code",
"execution_count": 41,
- "id": "72f77806",
+ "id": "88160ef6",
"metadata": {},
"outputs": [
{
@@ -1170,7 +1170,7 @@
},
{
"cell_type": "markdown",
- "id": "a9d85724",
+ "id": "93c0082f",
"metadata": {},
"source": [
"You can select elements that are divisible by 2:"
@@ -1179,7 +1179,7 @@
{
"cell_type": "code",
"execution_count": 42,
- "id": "2eb963d0",
+ "id": "bd315251",
"metadata": {},
"outputs": [
{
@@ -1200,7 +1200,7 @@
},
{
"cell_type": "markdown",
- "id": "e413ed52",
+ "id": "f0317012",
"metadata": {},
"source": [
"Or you can select elements that satisfy two conditions using the `&` and `|` operators:"
@@ -1209,7 +1209,7 @@
{
"cell_type": "code",
"execution_count": 43,
- "id": "3cbbcb78",
+ "id": "b232c963",
"metadata": {},
"outputs": [
{
@@ -1230,7 +1230,7 @@
},
{
"cell_type": "markdown",
- "id": "15d9f972",
+ "id": "c19ab5ad",
"metadata": {},
"source": [
"You can also make use of the logical operators `&` and `|` in order to return boolean values that specify whether or not the values in an array fulfill a certain condition. This can be useful with arrays that contain names or other categorical values."
@@ -1239,7 +1239,7 @@
{
"cell_type": "code",
"execution_count": 44,
- "id": "71107b1d",
+ "id": "cc3ee644",
"metadata": {},
"outputs": [
{
@@ -1262,7 +1262,7 @@
},
{
"cell_type": "markdown",
- "id": "f33cf954",
+ "id": "c1edf600",
"metadata": {},
"source": [
"You can also use `np.nonzero()` to select elements or indices from an array.\n",
@@ -1273,7 +1273,7 @@
{
"cell_type": "code",
"execution_count": 45,
- "id": "4c70a74d",
+ "id": "cfa0a483",
"metadata": {},
"outputs": [],
"source": [
@@ -1282,7 +1282,7 @@
},
{
"cell_type": "markdown",
- "id": "ffe2a170",
+ "id": "8af96f8e",
"metadata": {},
"source": [
"You can use `np.nonzero()` to print the indices of elements that are, for example, less than 5:"
@@ -1291,7 +1291,7 @@
{
"cell_type": "code",
"execution_count": 46,
- "id": "8b4b45b8",
+ "id": "f27a3cb8",
"metadata": {},
"outputs": [
{
@@ -1312,7 +1312,7 @@
},
{
"cell_type": "markdown",
- "id": "55e88a39",
+ "id": "2334c12d",
"metadata": {},
"source": [
"In this example, a tuple of arrays was returned: one for each dimension. The first array represents the row indices where these values are found, and the second array represents the column indices where the values are found.\n",
@@ -1323,7 +1323,7 @@
{
"cell_type": "code",
"execution_count": 47,
- "id": "b66242da",
+ "id": "8b52d868",
"metadata": {},
"outputs": [
{
@@ -1345,7 +1345,7 @@
},
{
"cell_type": "markdown",
- "id": "0b59a31e",
+ "id": "97416f45",
"metadata": {},
"source": [
"You can also use `np.nonzero()` to print the elements in an array that are less than 5 with:"
@@ -1354,7 +1354,7 @@
{
"cell_type": "code",
"execution_count": 48,
- "id": "dbb5def2",
+ "id": "7f6736f7",
"metadata": {},
"outputs": [
{
@@ -1374,7 +1374,7 @@
},
{
"cell_type": "markdown",
- "id": "e8e58650",
+ "id": "fa8447ee",
"metadata": {},
"source": [
"If the element you’re looking for doesn’t exist in the array, then the returned array of indices will be empty. For example:"
@@ -1383,7 +1383,7 @@
{
"cell_type": "code",
"execution_count": 49,
- "id": "9c70546d",
+ "id": "30f0472b",
"metadata": {},
"outputs": [
{
@@ -1404,7 +1404,7 @@
},
{
"cell_type": "markdown",
- "id": "9453b1a1",
+ "id": "dabfad61",
"metadata": {},
"source": [
"### Create an array from existing data\n",
@@ -1417,7 +1417,7 @@
{
"cell_type": "code",
"execution_count": 50,
- "id": "e78ed6f3",
+ "id": "a6842649",
"metadata": {},
"outputs": [],
"source": [
@@ -1426,7 +1426,7 @@
},
{
"cell_type": "markdown",
- "id": "acda1ab2",
+ "id": "8b614389",
"metadata": {},
"source": [
"You can create a new array from a section of your array any time by specifying where you want to slice your array."
@@ -1435,7 +1435,7 @@
{
"cell_type": "code",
"execution_count": 51,
- "id": "94e882ca",
+ "id": "6989fa4f",
"metadata": {},
"outputs": [
{
@@ -1456,7 +1456,7 @@
},
{
"cell_type": "markdown",
- "id": "2f306341",
+ "id": "f289eda6",
"metadata": {},
"source": [
"Here, you grabbed a section of your array from index position 3 through index position 8.\n",
@@ -1467,7 +1467,7 @@
{
"cell_type": "code",
"execution_count": 52,
- "id": "da7cf18e",
+ "id": "e210134f",
"metadata": {},
"outputs": [],
"source": [
@@ -1479,7 +1479,7 @@
},
{
"cell_type": "markdown",
- "id": "defa57a1",
+ "id": "2afdac4f",
"metadata": {},
"source": [
"You can stack them vertically with `vstack`:"
@@ -1488,7 +1488,7 @@
{
"cell_type": "code",
"execution_count": 53,
- "id": "c5e69457",
+ "id": "26755e66",
"metadata": {},
"outputs": [
{
@@ -1511,7 +1511,7 @@
},
{
"cell_type": "markdown",
- "id": "012e163b",
+ "id": "fef26743",
"metadata": {},
"source": [
"Or stack them horizontally with hstack:"
@@ -1520,7 +1520,7 @@
{
"cell_type": "code",
"execution_count": 54,
- "id": "570dc433",
+ "id": "6644a131",
"metadata": {},
"outputs": [
{
@@ -1541,7 +1541,7 @@
},
{
"cell_type": "markdown",
- "id": "4ff18130",
+ "id": "9c076954",
"metadata": {},
"source": [
"You can split an array into several smaller arrays using `hsplit`. You can specify either the number of equally shaped arrays to return or the columns after which the division should occur.\n",
@@ -1552,7 +1552,7 @@
{
"cell_type": "code",
"execution_count": 55,
- "id": "1347c4a4",
+ "id": "bc4467b4",
"metadata": {},
"outputs": [
{
@@ -1574,7 +1574,7 @@
},
{
"cell_type": "markdown",
- "id": "0191a5a0",
+ "id": "0c66f90e",
"metadata": {},
"source": [
"If you wanted to split this array into three equally shaped arrays, you would run:"
@@ -1583,7 +1583,7 @@
{
"cell_type": "code",
"execution_count": 56,
- "id": "c5c5352f",
+ "id": "c085a4c4",
"metadata": {},
"outputs": [
{
@@ -1608,7 +1608,7 @@
},
{
"cell_type": "markdown",
- "id": "4553dec2",
+ "id": "09d10de4",
"metadata": {},
"source": [
"If you wanted to split your array after the third and fourth column, you’d run:"
@@ -1617,7 +1617,7 @@
{
"cell_type": "code",
"execution_count": 57,
- "id": "bff5cc21",
+ "id": "6f735a83",
"metadata": {},
"outputs": [
{
@@ -1642,7 +1642,7 @@
},
{
"cell_type": "markdown",
- "id": "6672a1d9",
+ "id": "10d069a1",
"metadata": {},
"source": [
"You can use the `view` method to create a new array object that looks at the same data as the original array (a shallow copy).\n",
@@ -1655,7 +1655,7 @@
{
"cell_type": "code",
"execution_count": 58,
- "id": "84d6807a",
+ "id": "681e767a",
"metadata": {},
"outputs": [],
"source": [
@@ -1664,7 +1664,7 @@
},
{
"cell_type": "markdown",
- "id": "7743a4b6",
+ "id": "d793698b",
"metadata": {},
"source": [
"Now we create an array `b1` by slicing `a` and modify the first element of `b1`. This will modify the corresponding element in `a` as well!"
@@ -1673,7 +1673,7 @@
{
"cell_type": "code",
"execution_count": 59,
- "id": "fb7cea7e",
+ "id": "03f7af11",
"metadata": {},
"outputs": [
{
@@ -1695,7 +1695,7 @@
{
"cell_type": "code",
"execution_count": 60,
- "id": "a14c10fa",
+ "id": "29abfd98",
"metadata": {},
"outputs": [
{
@@ -1717,7 +1717,7 @@
{
"cell_type": "code",
"execution_count": 61,
- "id": "e21fbebe",
+ "id": "1cb28f3b",
"metadata": {},
"outputs": [
{
@@ -1739,7 +1739,7 @@
},
{
"cell_type": "markdown",
- "id": "2fa50f1c",
+ "id": "6fa60f89",
"metadata": {},
"source": [
"Using the `copy` method will make a complete copy of the array and its data (a deep copy). To use this on your array, you could run:"
@@ -1748,7 +1748,7 @@
{
"cell_type": "code",
"execution_count": 62,
- "id": "ab07c948",
+ "id": "8dd1dbb7",
"metadata": {},
"outputs": [],
"source": [
@@ -1757,7 +1757,7 @@
},
{
"cell_type": "markdown",
- "id": "5bfb0e9a",
+ "id": "3c1bf5b9",
"metadata": {},
"source": [
"## Array operations\n",
@@ -1770,7 +1770,7 @@
{
"cell_type": "code",
"execution_count": 63,
- "id": "f63f7a98",
+ "id": "0df0d146",
"metadata": {},
"outputs": [],
"source": [
@@ -1780,7 +1780,7 @@
},
{
"cell_type": "markdown",
- "id": "edb26bed",
+ "id": "6096c489",
"metadata": {},
"source": [
"You can add the arrays together with the plus sign."
@@ -1789,7 +1789,7 @@
{
"cell_type": "code",
"execution_count": 64,
- "id": "a12628ca",
+ "id": "a3da3376",
"metadata": {},
"outputs": [
{
@@ -1809,7 +1809,7 @@
},
{
"cell_type": "markdown",
- "id": "10a78453",
+ "id": "857ceeca",
"metadata": {},
"source": [
"You can, of course, do more than just addition!"
@@ -1818,7 +1818,7 @@
{
"cell_type": "code",
"execution_count": 65,
- "id": "0a1ab57e",
+ "id": "c34fbb3d",
"metadata": {},
"outputs": [
{
@@ -1839,7 +1839,7 @@
},
{
"cell_type": "markdown",
- "id": "3a7fe8c5",
+ "id": "db7b0009",
"metadata": {},
"source": [
"Basic operations are simple with NumPy. If you want to find the sum of the elements in an array, you’d use `sum()`. This works for 1D arrays, 2D arrays, and arrays in higher dimensions."
@@ -1848,7 +1848,7 @@
{
"cell_type": "code",
"execution_count": 66,
- "id": "4765fbea",
+ "id": "3ccef6f8",
"metadata": {},
"outputs": [
{
@@ -1869,7 +1869,7 @@
},
{
"cell_type": "markdown",
- "id": "c795d2ae",
+ "id": "92cbcee9",
"metadata": {},
"source": [
"To add the rows or the columns in a 2D array, you would specify the axis.\n",
@@ -1880,7 +1880,7 @@
{
"cell_type": "code",
"execution_count": 67,
- "id": "22774bc3",
+ "id": "c97288df",
"metadata": {},
"outputs": [],
"source": [
@@ -1889,7 +1889,7 @@
},
{
"cell_type": "markdown",
- "id": "ca4b6372",
+ "id": "17f5f516",
"metadata": {},
"source": [
"You can sum over the axis of rows with:"
@@ -1898,7 +1898,7 @@
{
"cell_type": "code",
"execution_count": 68,
- "id": "8547d72c",
+ "id": "4eea7e0a",
"metadata": {},
"outputs": [
{
@@ -1918,7 +1918,7 @@
},
{
"cell_type": "markdown",
- "id": "0ac60ab0",
+ "id": "be1de269",
"metadata": {},
"source": [
"You can sum over the axis of columns with:"
@@ -1927,7 +1927,7 @@
{
"cell_type": "code",
"execution_count": 69,
- "id": "85ac759f",
+ "id": "3a987410",
"metadata": {},
"outputs": [
{
@@ -1947,7 +1947,7 @@
},
{
"cell_type": "markdown",
- "id": "25b5d4f4",
+ "id": "369fb67d",
"metadata": {},
"source": [
"### Universal functions(ufunc)\n",
@@ -2038,7 +2038,7 @@
{
"cell_type": "code",
"execution_count": 70,
- "id": "e169b883",
+ "id": "bf6e23ee",
"metadata": {},
"outputs": [
{
@@ -2060,7 +2060,7 @@
},
{
"cell_type": "markdown",
- "id": "2cc7a971",
+ "id": "434fd9bf",
"metadata": {},
"source": [
"NumPy’s broadcasting rule relaxes this constraint when the arrays’ shapes meet certain constraints. The simplest broadcasting example occurs when an array and a scalar value are combined in an operation:"
@@ -2069,7 +2069,7 @@
{
"cell_type": "code",
"execution_count": 71,
- "id": "3741d36a",
+ "id": "a469d37a",
"metadata": {},
"outputs": [
{
@@ -2091,7 +2091,7 @@
},
{
"cell_type": "markdown",
- "id": "c0dac40e",
+ "id": "1ee6b52f",
"metadata": {},
"source": [
"The result is equivalent to the previous example where `b` was an array. NumPy is smart enough to use the original scalar value without actually making copies so that broadcasting operations are as memory and computationally efficient as possible.\n",
@@ -2133,7 +2133,7 @@
{
"cell_type": "code",
"execution_count": 72,
- "id": "76014f7f",
+ "id": "35e1c26c",
"metadata": {},
"outputs": [
{
@@ -2154,7 +2154,7 @@
{
"cell_type": "code",
"execution_count": 73,
- "id": "12e9b800",
+ "id": "26aefd82",
"metadata": {},
"outputs": [
{
@@ -2175,7 +2175,7 @@
{
"cell_type": "code",
"execution_count": 74,
- "id": "538e8b0f",
+ "id": "d37ad687",
"metadata": {},
"outputs": [
{
@@ -2195,7 +2195,7 @@
},
{
"cell_type": "markdown",
- "id": "6c450279",
+ "id": "273886fa",
"metadata": {},
"source": [
"Let’s start with this array, called “a”."
@@ -2204,7 +2204,7 @@
{
"cell_type": "code",
"execution_count": 75,
- "id": "df7e5735",
+ "id": "34183eda",
"metadata": {},
"outputs": [],
"source": [
@@ -2215,7 +2215,7 @@
},
{
"cell_type": "markdown",
- "id": "80b524b9",
+ "id": "c0f61cfa",
"metadata": {},
"source": [
"It’s very common to want to aggregate along a row or column. By default, every NumPy aggregation function will return the aggregate of the entire array. To find the sum or the minimum of the elements in your array, run:"
@@ -2224,7 +2224,7 @@
{
"cell_type": "code",
"execution_count": 76,
- "id": "66c67ac4",
+ "id": "cb0a6d59",
"metadata": {},
"outputs": [
{
@@ -2244,7 +2244,7 @@
},
{
"cell_type": "markdown",
- "id": "5c440ff4",
+ "id": "9e3b702e",
"metadata": {},
"source": [
"Or:"
@@ -2253,7 +2253,7 @@
{
"cell_type": "code",
"execution_count": 77,
- "id": "0064a683",
+ "id": "ab98f982",
"metadata": {},
"outputs": [
{
@@ -2273,7 +2273,7 @@
},
{
"cell_type": "markdown",
- "id": "77adcfae",
+ "id": "e4b23885",
"metadata": {},
"source": [
"You can specify on which axis you want the aggregation function to be computed. For example, you can find the minimum value within each column by specifying `axis=0`."
@@ -2282,7 +2282,7 @@
{
"cell_type": "code",
"execution_count": 78,
- "id": "406f149a",
+ "id": "555a5494",
"metadata": {},
"outputs": [
{
@@ -2302,7 +2302,7 @@
},
{
"cell_type": "markdown",
- "id": "c6150b00",
+ "id": "3cf31cb7",
"metadata": {},
"source": [
"The four values listed above correspond to the number of columns in your array. With a four-column array, you will get four values as your result.\n",
@@ -2325,7 +2325,7 @@
{
"cell_type": "code",
"execution_count": 79,
- "id": "c82893ba",
+ "id": "b8db9ba4",
"metadata": {},
"outputs": [],
"source": [
@@ -2335,7 +2335,7 @@
{
"cell_type": "code",
"execution_count": 80,
- "id": "5bbf1fa8",
+ "id": "c38ea3cb",
"metadata": {},
"outputs": [
{
@@ -2356,7 +2356,7 @@
{
"cell_type": "code",
"execution_count": 81,
- "id": "046bdefe",
+ "id": "6ff1d893",
"metadata": {},
"outputs": [
{
@@ -2376,7 +2376,7 @@
},
{
"cell_type": "markdown",
- "id": "a5569c55",
+ "id": "d7c505e0",
"metadata": {},
"source": [
"It is not necessary to separate each dimension’s index into its own set of square brackets."
@@ -2385,7 +2385,7 @@
{
"cell_type": "code",
"execution_count": 82,
- "id": "6d2ddea2",
+ "id": "73771785",
"metadata": {},
"outputs": [],
"source": [
@@ -2395,7 +2395,7 @@
{
"cell_type": "code",
"execution_count": 83,
- "id": "94aa2b0d",
+ "id": "c087f055",
"metadata": {},
"outputs": [
{
@@ -2416,7 +2416,7 @@
{
"cell_type": "code",
"execution_count": 84,
- "id": "8f19e665",
+ "id": "55e3a5ae",
"metadata": {},
"outputs": [
{
@@ -2436,7 +2436,7 @@
},
{
"cell_type": "markdown",
- "id": "b5948b7d",
+ "id": "254c4056",
"metadata": {},
"source": [
"Note that If one indexes a multidimensional array with fewer indices than dimensions, one gets a subdimensional array. For example:"
@@ -2445,7 +2445,7 @@
{
"cell_type": "code",
"execution_count": 85,
- "id": "707ba14b",
+ "id": "bc3f0df1",
"metadata": {},
"outputs": [
{
@@ -2465,7 +2465,7 @@
},
{
"cell_type": "markdown",
- "id": "03ccae92",
+ "id": "60e0fea3",
"metadata": {},
"source": [
"That is, each index specified selects the array corresponding to the rest of the dimensions selected. In the above example, choosing 0 means that the remaining dimension of length 5 is being left unspecified, and that what is returned is an array of that dimensionality and size. It must be noted that the returned array is a view, i.e., it is not a copy of the original, but points to the same values in memory as does the original array. In this case, the 1-D array at the first position (0) is returned. So using a single index on the returned array, results in a single element being returned. That is:"
@@ -2474,7 +2474,7 @@
{
"cell_type": "code",
"execution_count": 86,
- "id": "0d7943d1",
+ "id": "17ca9933",
"metadata": {},
"outputs": [
{
@@ -2494,7 +2494,7 @@
},
{
"cell_type": "markdown",
- "id": "9bfe60fd",
+ "id": "b1540b46",
"metadata": {},
"source": [
"So note that `x[0, 2] == x[0][2]` though the second case is more inefficient as a new temporary array is created after the first index that is subsequently indexed by 2.\n",
@@ -2521,7 +2521,7 @@
{
"cell_type": "code",
"execution_count": 87,
- "id": "39736de3",
+ "id": "5d59ce09",
"metadata": {},
"outputs": [
{
@@ -2542,7 +2542,7 @@
},
{
"cell_type": "markdown",
- "id": "cae23acf",
+ "id": "0ad4af78",
"metadata": {},
"source": [
"- Negative *i* and *j* are interpreted as *n + i* and *n + j* where *n* is the number of elements in the corresponding dimension. Negative *k* makes stepping go towards smaller indices. From the above example:"
@@ -2551,7 +2551,7 @@
{
"cell_type": "code",
"execution_count": 88,
- "id": "9b7f09b1",
+ "id": "0b8d903a",
"metadata": {},
"outputs": [
{
@@ -2572,7 +2572,7 @@
{
"cell_type": "code",
"execution_count": 89,
- "id": "a917329c",
+ "id": "0dccd35c",
"metadata": {},
"outputs": [
{
@@ -2592,7 +2592,7 @@
},
{
"cell_type": "markdown",
- "id": "817f1318",
+ "id": "fdf27673",
"metadata": {},
"source": [
"- Assume *n* is the number of elements in the dimension being sliced. Then, if *i* is not given it defaults to 0 for *k > 0* and *n - 1* for *k < 0*. If *j* is not given it defaults to *n* for *k > 0* and *-n-1* for *k < 0*. If *k* is not given it defaults to 1. Note that `::` is the same as : and means select all indices along this axis. From the above example:"
@@ -2601,7 +2601,7 @@
{
"cell_type": "code",
"execution_count": 90,
- "id": "aa2480ef",
+ "id": "9c58ff87",
"metadata": {},
"outputs": [
{
@@ -2621,7 +2621,7 @@
},
{
"cell_type": "markdown",
- "id": "cdb21dd3",
+ "id": "36552e98",
"metadata": {},
"source": [
"- If the number of objects in the selection tuple is less than N, then `:` is assumed for any subsequent dimensions. For example:"
@@ -2630,7 +2630,7 @@
{
"cell_type": "code",
"execution_count": 91,
- "id": "c3dcf26b",
+ "id": "a50bd245",
"metadata": {},
"outputs": [
{
@@ -2652,7 +2652,7 @@
{
"cell_type": "code",
"execution_count": 92,
- "id": "e3dc5a91",
+ "id": "0486952f",
"metadata": {},
"outputs": [
{
@@ -2674,7 +2674,7 @@
},
{
"cell_type": "markdown",
- "id": "24d6064c",
+ "id": "fddbb9d3",
"metadata": {},
"source": [
"- An integer, *i*, returns the same values as `i:i+1` **except** the dimensionality of the returned object is reduced by 1. In particular, a selection tuple with the *p*-th element an integer (and all other entries *:*) returns the corresponding sub-array with dimension *N - 1*. If *N = 1* then the returned object is an array scalar.\n",
@@ -2699,7 +2699,7 @@
{
"cell_type": "code",
"execution_count": 93,
- "id": "d93749f7",
+ "id": "12c63082",
"metadata": {},
"outputs": [
{
@@ -2720,7 +2720,7 @@
},
{
"cell_type": "markdown",
- "id": "ca8798f4",
+ "id": "0078053e",
"metadata": {},
"source": [
"This is equivalent to:"
@@ -2729,7 +2729,7 @@
{
"cell_type": "code",
"execution_count": 94,
- "id": "cd4c7a2e",
+ "id": "340be6f0",
"metadata": {},
"outputs": [
{
@@ -2750,7 +2750,7 @@
},
{
"cell_type": "markdown",
- "id": "32625800",
+ "id": "9d18f154",
"metadata": {},
"source": [
"Each `newaxis` object in the selection tuple serves to expand the dimensions of the resulting selection by one unit-length dimension. The added dimension is the position of the `newaxis` object in the selection tuple. `newaxis` is an alias for `None`, and `None` can be used in place of this with the same result. From the above example:"
@@ -2759,7 +2759,7 @@
{
"cell_type": "code",
"execution_count": 95,
- "id": "20fe2be5",
+ "id": "6d7c70b3",
"metadata": {},
"outputs": [
{
@@ -2780,7 +2780,7 @@
{
"cell_type": "code",
"execution_count": 96,
- "id": "63240821",
+ "id": "2ac0fede",
"metadata": {},
"outputs": [
{
@@ -2800,7 +2800,7 @@
},
{
"cell_type": "markdown",
- "id": "0a220928",
+ "id": "c33c4d8f",
"metadata": {},
"source": [
"This can be handy to combine two arrays in a way that otherwise would require explicit reshaping operations. For example:"
@@ -2809,7 +2809,7 @@
{
"cell_type": "code",
"execution_count": 97,
- "id": "20ae9d4b",
+ "id": "af1e4760",
"metadata": {},
"outputs": [
{
@@ -2834,7 +2834,7 @@
},
{
"cell_type": "markdown",
- "id": "8616dbbc",
+ "id": "a682dfca",
"metadata": {},
"source": [
"### Advanced indexing\n",
@@ -2857,7 +2857,7 @@
{
"cell_type": "code",
"execution_count": 98,
- "id": "4cade501",
+ "id": "09f60290",
"metadata": {},
"outputs": [],
"source": [
@@ -2867,7 +2867,7 @@
{
"cell_type": "code",
"execution_count": 99,
- "id": "8cb265f3",
+ "id": "c6215f55",
"metadata": {},
"outputs": [
{
@@ -2888,7 +2888,7 @@
{
"cell_type": "code",
"execution_count": 100,
- "id": "6a678867",
+ "id": "4c78bcbf",
"metadata": {},
"outputs": [
{
@@ -2909,7 +2909,7 @@
{
"cell_type": "code",
"execution_count": 101,
- "id": "76ffa3ab",
+ "id": "712d9208",
"metadata": {},
"outputs": [
{
@@ -2929,7 +2929,7 @@
},
{
"cell_type": "markdown",
- "id": "3046f1aa",
+ "id": "e5d75aa2",
"metadata": {},
"source": [
"If the index values are out of bounds then an `IndexError` is thrown:"
@@ -2938,7 +2938,7 @@
{
"cell_type": "code",
"execution_count": 102,
- "id": "69ad05d6",
+ "id": "3f885a84",
"metadata": {},
"outputs": [],
"source": [
@@ -2948,7 +2948,7 @@
{
"cell_type": "code",
"execution_count": 103,
- "id": "a94a5db2",
+ "id": "eed86f9e",
"metadata": {},
"outputs": [
{
@@ -2969,7 +2969,7 @@
},
{
"cell_type": "markdown",
- "id": "fe1eb07f",
+ "id": "6dd9de97",
"metadata": {},
"source": [
"```py\n",
@@ -2999,7 +2999,7 @@
{
"cell_type": "code",
"execution_count": 104,
- "id": "534eaca5",
+ "id": "804a6e1c",
"metadata": {},
"outputs": [],
"source": [
@@ -3009,7 +3009,7 @@
{
"cell_type": "code",
"execution_count": 105,
- "id": "48bf6028",
+ "id": "2a4c6d27",
"metadata": {},
"outputs": [
{
@@ -3034,7 +3034,7 @@
{
"cell_type": "code",
"execution_count": 106,
- "id": "3d30a489",
+ "id": "34937c0b",
"metadata": {},
"outputs": [
{
@@ -3054,7 +3054,7 @@
},
{
"cell_type": "markdown",
- "id": "237662eb",
+ "id": "72afe642",
"metadata": {},
"source": [
"In this case, if the index arrays have a matching shape, and there is an index array for each dimension of the array being indexed, the resultant array has the same shape as the index arrays, and the values correspond to the index set for each position in the index arrays. In this example, the first index value is 0 for both index arrays, and thus the first value of the resultant array is `y[0, 0]`. The next value is `y[2, 1]`, and the last is `y[4, 2]`.\n",
@@ -3077,7 +3077,7 @@
{
"cell_type": "code",
"execution_count": 107,
- "id": "4af2f4e9",
+ "id": "746a8a2a",
"metadata": {},
"outputs": [
{
@@ -3097,7 +3097,7 @@
},
{
"cell_type": "markdown",
- "id": "cfb6a961",
+ "id": "c806293b",
"metadata": {},
"source": [
"Jumping to the next level of complexity, it is possible to only partially index an array with index arrays. It takes a bit of thought to understand what happens in such cases. For example if we just use one index array with y:"
@@ -3106,7 +3106,7 @@
{
"cell_type": "code",
"execution_count": 108,
- "id": "970c577f",
+ "id": "8d24f98b",
"metadata": {},
"outputs": [
{
@@ -3128,7 +3128,7 @@
},
{
"cell_type": "markdown",
- "id": "8f83cd68",
+ "id": "75a6a88c",
"metadata": {},
"source": [
"It results in the construction of a new array where each value of the index array selects one row from the array being indexed and the resultant array has the resulting shape (number of index elements, size of row).\n",
@@ -3143,7 +3143,7 @@
{
"cell_type": "code",
"execution_count": 109,
- "id": "7845e084",
+ "id": "843d2d9d",
"metadata": {},
"outputs": [
{
@@ -3164,7 +3164,7 @@
},
{
"cell_type": "markdown",
- "id": "9d716b3d",
+ "id": "b53bec85",
"metadata": {},
"source": [
"To achieve a behaviour similar to the basic slicing above, broadcasting can be used. The function `ix_` can help with this broadcasting. This is best understood with an example.\n",
@@ -3177,7 +3177,7 @@
{
"cell_type": "code",
"execution_count": 110,
- "id": "9d028c17",
+ "id": "8b3486a3",
"metadata": {},
"outputs": [
{
@@ -3206,7 +3206,7 @@
},
{
"cell_type": "markdown",
- "id": "758b4a35",
+ "id": "6b649b71",
"metadata": {},
"source": [
"However, since the indexing arrays above just repeat themselves, broadcasting can be used (compare operations such as `rows[:, np.newaxis] + columns`) to simplify this:"
@@ -3215,7 +3215,7 @@
{
"cell_type": "code",
"execution_count": 111,
- "id": "ec7b51df",
+ "id": "e499d3c0",
"metadata": {},
"outputs": [],
"source": [
@@ -3226,7 +3226,7 @@
{
"cell_type": "code",
"execution_count": 112,
- "id": "edbf9768",
+ "id": "8c259488",
"metadata": {},
"outputs": [
{
@@ -3248,7 +3248,7 @@
{
"cell_type": "code",
"execution_count": 113,
- "id": "eb31dd1f",
+ "id": "162b4cf4",
"metadata": {},
"outputs": [
{
@@ -3269,7 +3269,7 @@
},
{
"cell_type": "markdown",
- "id": "7ff7c435",
+ "id": "6804676b",
"metadata": {},
"source": [
"This broadcasting can also be achieved using the function `ix_`:"
@@ -3278,7 +3278,7 @@
{
"cell_type": "code",
"execution_count": 114,
- "id": "b5b937a5",
+ "id": "9be46052",
"metadata": {},
"outputs": [
{
@@ -3299,7 +3299,7 @@
},
{
"cell_type": "markdown",
- "id": "0a8f070c",
+ "id": "e9ff09f5",
"metadata": {},
"source": [
"Note that without the `np.ix_` call, only the diagonal elements would be selected:"
@@ -3308,7 +3308,7 @@
{
"cell_type": "code",
"execution_count": 115,
- "id": "05619cd7",
+ "id": "e796de41",
"metadata": {},
"outputs": [
{
@@ -3328,7 +3328,7 @@
},
{
"cell_type": "markdown",
- "id": "9d77ccdb",
+ "id": "12406154",
"metadata": {},
"source": [
"This difference is the most important thing to remember about indexing with multiple advanced indices.\n",
@@ -3349,7 +3349,7 @@
{
"cell_type": "code",
"execution_count": 116,
- "id": "d73844ae",
+ "id": "0c1a1859",
"metadata": {},
"outputs": [
{
@@ -3370,7 +3370,7 @@
},
{
"cell_type": "markdown",
- "id": "985d5493",
+ "id": "cfda58c9",
"metadata": {},
"source": [
"Or wish to add a constant to all negative elements:"
@@ -3379,7 +3379,7 @@
{
"cell_type": "code",
"execution_count": 117,
- "id": "75ee7fe3",
+ "id": "84b58448",
"metadata": {},
"outputs": [
{
@@ -3401,7 +3401,7 @@
},
{
"cell_type": "markdown",
- "id": "d9247246",
+ "id": "ac73a2b4",
"metadata": {},
"source": [
"In general if an index includes a Boolean array, the result will be identical to inserting `obj.nonzero()` into the same position and using the integer array indexing mechanism described above. `x[ind_1, boolean_array, ind_2]` is equivalent to `x[(ind_1,) + boolean_array.nonzero() + (ind_2,)]`.\n",
@@ -3414,7 +3414,7 @@
{
"cell_type": "code",
"execution_count": 118,
- "id": "e691a204",
+ "id": "030806a6",
"metadata": {},
"outputs": [],
"source": [
@@ -3425,7 +3425,7 @@
{
"cell_type": "code",
"execution_count": 119,
- "id": "6730d9e8",
+ "id": "419f7088",
"metadata": {},
"outputs": [
{
@@ -3446,7 +3446,7 @@
{
"cell_type": "code",
"execution_count": 120,
- "id": "716092f9",
+ "id": "356547dd",
"metadata": {},
"outputs": [
{
@@ -3467,7 +3467,7 @@
},
{
"cell_type": "markdown",
- "id": "657b732f",
+ "id": "5ead70ba",
"metadata": {},
"source": [
"Here the 4th and 5th rows are selected from the indexed array and combined to make a 2-D array.\n",
@@ -3480,7 +3480,7 @@
{
"cell_type": "code",
"execution_count": 121,
- "id": "24e80f01",
+ "id": "59f2584c",
"metadata": {},
"outputs": [
{
@@ -3503,7 +3503,7 @@
},
{
"cell_type": "markdown",
- "id": "2e9c7a50",
+ "id": "fde47f24",
"metadata": {},
"source": [
"Combining multiple Boolean indexing arrays or a Boolean with an integer indexing array can best be understood with the `obj.nonzero()` analogy. The function `ix_` also supports boolean arrays and will work without any surprises.\n",
@@ -3516,7 +3516,7 @@
{
"cell_type": "code",
"execution_count": 122,
- "id": "0aee987f",
+ "id": "ad475641",
"metadata": {},
"outputs": [],
"source": [
@@ -3530,7 +3530,7 @@
{
"cell_type": "code",
"execution_count": 123,
- "id": "43d73458",
+ "id": "57e1caef",
"metadata": {},
"outputs": [
{
@@ -3551,7 +3551,7 @@
{
"cell_type": "code",
"execution_count": 124,
- "id": "4544e60c",
+ "id": "f711ea9e",
"metadata": {},
"outputs": [],
"source": [
@@ -3561,7 +3561,7 @@
{
"cell_type": "code",
"execution_count": 125,
- "id": "084a72fa",
+ "id": "afb6793d",
"metadata": {},
"outputs": [
{
@@ -3582,7 +3582,7 @@
},
{
"cell_type": "markdown",
- "id": "54d115d4",
+ "id": "20bb0f03",
"metadata": {},
"source": [
"Without the n`p.ix_` call, only the diagonal elements would be selected.\n",
@@ -3593,7 +3593,7 @@
{
"cell_type": "code",
"execution_count": 126,
- "id": "492e0749",
+ "id": "fec999aa",
"metadata": {},
"outputs": [
{
@@ -3615,7 +3615,7 @@
},
{
"cell_type": "markdown",
- "id": "9794683e",
+ "id": "5f069d0e",
"metadata": {},
"source": [
"##### Example 3\n",
@@ -3626,7 +3626,7 @@
{
"cell_type": "code",
"execution_count": 127,
- "id": "27a94206",
+ "id": "78014573",
"metadata": {},
"outputs": [
{
@@ -3654,7 +3654,7 @@
{
"cell_type": "code",
"execution_count": 128,
- "id": "602decb2",
+ "id": "5f18d1f1",
"metadata": {},
"outputs": [
{
@@ -3678,7 +3678,7 @@
},
{
"cell_type": "markdown",
- "id": "822f10a9",
+ "id": "a0d3b147",
"metadata": {},
"source": [
"#### Combining advanced and basic indexing\n",
@@ -3691,7 +3691,7 @@
{
"cell_type": "code",
"execution_count": 129,
- "id": "2fd94f53",
+ "id": "9313ab71",
"metadata": {},
"outputs": [
{
@@ -3714,7 +3714,7 @@
},
{
"cell_type": "markdown",
- "id": "61fb52dd",
+ "id": "2ae88709",
"metadata": {},
"source": [
"In effect, the slice and index array operation are independent. The slice operation extracts columns with index 1 and 2, (i.e. the 2nd and 3rd columns), followed by the index array operation which extracts rows with index 0, 2 and 4 (i.e the first, third and fifth rows). This is equivalent to:"
@@ -3723,7 +3723,7 @@
{
"cell_type": "code",
"execution_count": 130,
- "id": "6b417598",
+ "id": "56b1f695",
"metadata": {},
"outputs": [
{
@@ -3745,7 +3745,7 @@
},
{
"cell_type": "markdown",
- "id": "e1c85d79",
+ "id": "0e6dddf9",
"metadata": {},
"source": [
"A single advanced index can, for example, replace a slice and the result array will be the same. However, it is a copy and may have a different memory layout. A slice is preferable when it is possible. For example:"
@@ -3754,7 +3754,7 @@
{
"cell_type": "code",
"execution_count": 131,
- "id": "0ff42fd8",
+ "id": "607ce968",
"metadata": {},
"outputs": [],
"source": [
@@ -3767,7 +3767,7 @@
{
"cell_type": "code",
"execution_count": 132,
- "id": "58013488",
+ "id": "f04d4d21",
"metadata": {},
"outputs": [
{
@@ -3788,7 +3788,7 @@
{
"cell_type": "code",
"execution_count": 133,
- "id": "5e4c2001",
+ "id": "7bdee1ce",
"metadata": {},
"outputs": [
{
@@ -3808,7 +3808,7 @@
},
{
"cell_type": "markdown",
- "id": "381fc0be",
+ "id": "df8272ed",
"metadata": {},
"source": [
"The easiest way to understand a combination of multiple advanced indices may be to think in terms of the resulting shape. There are two parts to the indexing operation, the subspace defined by the basic indexing (excluding integers) and the subspace from the advanced indexing part. Two cases of index combination need to be distinguished:\n",
@@ -3834,7 +3834,7 @@
{
"cell_type": "code",
"execution_count": 134,
- "id": "1731247e",
+ "id": "e665163b",
"metadata": {},
"outputs": [],
"source": [
@@ -3845,7 +3845,7 @@
{
"cell_type": "code",
"execution_count": 135,
- "id": "baefc549",
+ "id": "8a0eeb3f",
"metadata": {},
"outputs": [
{
@@ -3870,7 +3870,7 @@
{
"cell_type": "code",
"execution_count": 136,
- "id": "e6e1c108",
+ "id": "211ae299",
"metadata": {},
"outputs": [
{
@@ -3891,7 +3891,7 @@
},
{
"cell_type": "markdown",
- "id": "eaa10183",
+ "id": "ac489faf",
"metadata": {},
"source": [
"### Field access\n",
@@ -3908,7 +3908,7 @@
{
"cell_type": "code",
"execution_count": 137,
- "id": "8c715588",
+ "id": "87082d2b",
"metadata": {},
"outputs": [],
"source": [
@@ -3918,7 +3918,7 @@
{
"cell_type": "code",
"execution_count": 138,
- "id": "7b5d745d",
+ "id": "25797dbf",
"metadata": {},
"outputs": [
{
@@ -3939,7 +3939,7 @@
{
"cell_type": "code",
"execution_count": 139,
- "id": "473385a9",
+ "id": "d362383b",
"metadata": {},
"outputs": [
{
@@ -3960,7 +3960,7 @@
{
"cell_type": "code",
"execution_count": 140,
- "id": "38df66f1",
+ "id": "d277a47b",
"metadata": {},
"outputs": [
{
@@ -3981,7 +3981,7 @@
{
"cell_type": "code",
"execution_count": 141,
- "id": "6b405005",
+ "id": "bb59101a",
"metadata": {},
"outputs": [
{
@@ -4001,7 +4001,7 @@
},
{
"cell_type": "markdown",
- "id": "ceaa6265",
+ "id": "81e86d2a",
"metadata": {},
"source": [
"### Flat Iterator indexing\n",
@@ -4016,7 +4016,7 @@
{
"cell_type": "code",
"execution_count": 142,
- "id": "60df60bc",
+ "id": "651d8796",
"metadata": {},
"outputs": [],
"source": [
@@ -4026,7 +4026,7 @@
},
{
"cell_type": "markdown",
- "id": "e35ad0a7",
+ "id": "f0bf23cc",
"metadata": {},
"source": [
"Or an array of the right size:"
@@ -4035,7 +4035,7 @@
{
"cell_type": "code",
"execution_count": 143,
- "id": "36c7a028",
+ "id": "3f734843",
"metadata": {},
"outputs": [],
"source": [
@@ -4044,7 +4044,7 @@
},
{
"cell_type": "markdown",
- "id": "d6bb68ea",
+ "id": "7577483a",
"metadata": {},
"source": [
"Note that assignments may result in changes if assigning higher types to lower types (like floats to ints) or even exceptions (assigning complex to floats or ints):"
@@ -4053,7 +4053,7 @@
{
"cell_type": "code",
"execution_count": 144,
- "id": "9f3a644a",
+ "id": "4a2f112c",
"metadata": {},
"outputs": [
{
@@ -4074,7 +4074,7 @@
},
{
"cell_type": "markdown",
- "id": "a9daf9ca",
+ "id": "47e09f84",
"metadata": {},
"source": [
"```py\n",
@@ -4093,7 +4093,7 @@
{
"cell_type": "code",
"execution_count": 145,
- "id": "152f86ff",
+ "id": "b1b83b6d",
"metadata": {},
"outputs": [
{
@@ -4115,7 +4115,7 @@
{
"cell_type": "code",
"execution_count": 146,
- "id": "8a4b69d7",
+ "id": "c2ed584e",
"metadata": {},
"outputs": [
{
@@ -4136,7 +4136,7 @@
},
{
"cell_type": "markdown",
- "id": "94071121",
+ "id": "26367fa1",
"metadata": {},
"source": [
"Where people expect that the 1st location will be incremented by 3. In fact, it will only be incremented by 1. The reason is that a new array is extracted from the original (as a temporary) containing the values at 1, 1, 3, 1, then the value 1 is added to the temporary, and then the temporary is assigned back to the original array. Thus the value of the array at `x[1] + 1` is assigned to `x[1]` three times, rather than being incremented 3 times.\n",
@@ -4149,7 +4149,7 @@
{
"cell_type": "code",
"execution_count": 147,
- "id": "f8f02799",
+ "id": "361dad28",
"metadata": {},
"outputs": [
{
@@ -4171,7 +4171,7 @@
},
{
"cell_type": "markdown",
- "id": "0c35b2c7",
+ "id": "e214f199",
"metadata": {},
"source": [
"So one can use code to construct tuples of any number of indices and then use these within an index.\n",
@@ -4182,7 +4182,7 @@
{
"cell_type": "code",
"execution_count": 148,
- "id": "b05c46a5",
+ "id": "956f5a69",
"metadata": {},
"outputs": [
{
@@ -4203,7 +4203,7 @@
},
{
"cell_type": "markdown",
- "id": "32f2990f",
+ "id": "7d68302b",
"metadata": {},
"source": [
"Likewise, ellipsis can be specified by code by using the Ellipsis object:"
@@ -4212,7 +4212,7 @@
{
"cell_type": "code",
"execution_count": 149,
- "id": "0c52b1c9",
+ "id": "8e19d081",
"metadata": {},
"outputs": [
{
@@ -4235,7 +4235,7 @@
},
{
"cell_type": "markdown",
- "id": "2cf9e8ae",
+ "id": "30b1c106",
"metadata": {},
"source": [
"For this reason, it is possible to use the output from the `np.nonzero()` function directly as an index since it always returns a tuple of index arrays.\n",
@@ -4246,7 +4246,7 @@
{
"cell_type": "code",
"execution_count": 150,
- "id": "0e5cedd0",
+ "id": "bc878720",
"metadata": {},
"outputs": [
{
@@ -4316,7 +4316,7 @@
{
"cell_type": "code",
"execution_count": 151,
- "id": "93461eca",
+ "id": "8d0c8879",
"metadata": {},
"outputs": [
{
@@ -4336,7 +4336,7 @@
},
{
"cell_type": "markdown",
- "id": "860ceada",
+ "id": "b900ab4b",
"metadata": {},
"source": [
"## Structured arrays\n",
@@ -4349,7 +4349,7 @@
{
"cell_type": "code",
"execution_count": 152,
- "id": "bbccc513",
+ "id": "731cfdd6",
"metadata": {},
"outputs": [
{
@@ -4372,7 +4372,7 @@
},
{
"cell_type": "markdown",
- "id": "599c24ca",
+ "id": "148197cf",
"metadata": {},
"source": [
"Here `x` is a one-dimensional array of length two whose datatype is a structure with three fields: 1. A string of length 10 or less named `'name'`, 2. a 32-bit integer named `'age'`, and 3. a 32-bit float named `'weight'`.\n",
@@ -4383,7 +4383,7 @@
{
"cell_type": "code",
"execution_count": 153,
- "id": "745967eb",
+ "id": "9616caaa",
"metadata": {},
"outputs": [
{
@@ -4403,7 +4403,7 @@
},
{
"cell_type": "markdown",
- "id": "d2f00026",
+ "id": "de516267",
"metadata": {},
"source": [
"You can access and modify individual fields of a structured array by indexing with the field name:"
@@ -4412,7 +4412,7 @@
{
"cell_type": "code",
"execution_count": 154,
- "id": "fec68e48",
+ "id": "d43c6311",
"metadata": {},
"outputs": [
{
@@ -4433,7 +4433,7 @@
{
"cell_type": "code",
"execution_count": 155,
- "id": "25eb0464",
+ "id": "0be2975e",
"metadata": {},
"outputs": [
{
@@ -4454,7 +4454,7 @@
{
"cell_type": "code",
"execution_count": 156,
- "id": "d1f77685",
+ "id": "80a499fb",
"metadata": {},
"outputs": [
{
@@ -4475,7 +4475,7 @@
},
{
"cell_type": "markdown",
- "id": "d8d5a893",
+ "id": "3b028ec2",
"metadata": {},
"source": [
"Structured datatypes are designed to be able to mimic 'structs' in the C language, and share a similar memory layout. They are meant for interfacing with C code and for low-level manipulation of structured buffers, for example for interpreting binary blobs. For these purposes they support specialized features such as subarrays, nested datatypes, and unions, and allow control over the memory layout of the structure.\n",
@@ -4498,7 +4498,7 @@
{
"cell_type": "code",
"execution_count": 157,
- "id": "797dd050",
+ "id": "74ebd158",
"metadata": {},
"outputs": [
{
@@ -4518,7 +4518,7 @@
},
{
"cell_type": "markdown",
- "id": "32712a39",
+ "id": "e34b6ce2",
"metadata": {},
"source": [
"If `fieldname` is the empty string `''`, the field will be given a default name of the form `f#`, where `#` is the integer index of the field, counting from 0 from the left:"
@@ -4527,7 +4527,7 @@
{
"cell_type": "code",
"execution_count": 158,
- "id": "09d05c4f",
+ "id": "0f6e526b",
"metadata": {},
"outputs": [
{
@@ -4547,7 +4547,7 @@
},
{
"cell_type": "markdown",
- "id": "4f6bb0fd",
+ "id": "53d95bbc",
"metadata": {},
"source": [
"The byte offsets of the fields within the structure and the total structure itemsize are determined automatically.\n",
@@ -4560,7 +4560,7 @@
{
"cell_type": "code",
"execution_count": 159,
- "id": "28c8a822",
+ "id": "b2287306",
"metadata": {},
"outputs": [
{
@@ -4581,7 +4581,7 @@
{
"cell_type": "code",
"execution_count": 160,
- "id": "f7b83bcf",
+ "id": "79eff3e6",
"metadata": {},
"outputs": [
{
@@ -4601,7 +4601,7 @@
},
{
"cell_type": "markdown",
- "id": "5c960b91",
+ "id": "257bd476",
"metadata": {},
"source": [
"- A dictionary of field parameter arrays\n",
@@ -4614,7 +4614,7 @@
{
"cell_type": "code",
"execution_count": 161,
- "id": "434ca05a",
+ "id": "ab42e01a",
"metadata": {},
"outputs": [
{
@@ -4635,7 +4635,7 @@
{
"cell_type": "code",
"execution_count": 162,
- "id": "e2a4528d",
+ "id": "9fd55ad4",
"metadata": {},
"outputs": [
{
@@ -4658,7 +4658,7 @@
},
{
"cell_type": "markdown",
- "id": "36a35aeb",
+ "id": "64c2856f",
"metadata": {},
"source": [
"Offsets may be chosen such that the fields overlap, though this will mean that assigning to one field may clobber any overlapping field’s data. As an exception, fields of `numpy.object_` type cannot overlap with other fields, because of the risk of clobbering the internal object pointer and then dereferencing it.\n",
@@ -4673,7 +4673,7 @@
{
"cell_type": "code",
"execution_count": 163,
- "id": "d9f02eba",
+ "id": "d9c1f88a",
"metadata": {},
"outputs": [
{
@@ -4693,7 +4693,7 @@
},
{
"cell_type": "markdown",
- "id": "a436abe7",
+ "id": "86448c29",
"metadata": {},
"source": [
"#### Manipulating and Displaying Structured Datatypes\n",
@@ -4704,7 +4704,7 @@
{
"cell_type": "code",
"execution_count": 164,
- "id": "f69590d4",
+ "id": "b9033bda",
"metadata": {},
"outputs": [
{
@@ -4725,7 +4725,7 @@
},
{
"cell_type": "markdown",
- "id": "4e7b9a5d",
+ "id": "178065ea",
"metadata": {},
"source": [
"The field names may be modified by assigning to the `names` attribute using a sequence of strings of the same length.\n",
@@ -4736,7 +4736,7 @@
{
"cell_type": "code",
"execution_count": 165,
- "id": "43f8a0f5",
+ "id": "2ab6061b",
"metadata": {},
"outputs": [
{
@@ -4756,7 +4756,7 @@
},
{
"cell_type": "markdown",
- "id": "1232b323",
+ "id": "ec92a2d5",
"metadata": {},
"source": [
"Both the `names` and `fields` attributes will equal `None` for unstructured arrays. The recommended way to test if a dtype is structured is with `if dt.names is not None` rather than `if dt.names`, to account for dtypes with 0 fields.\n",
@@ -4773,7 +4773,7 @@
{
"cell_type": "code",
"execution_count": 166,
- "id": "a0ed1548",
+ "id": "655b8383",
"metadata": {},
"outputs": [
{
@@ -4793,7 +4793,7 @@
},
{
"cell_type": "markdown",
- "id": "7828e2b3",
+ "id": "6ff6765b",
"metadata": {},
"source": [
"When using the first form of dictionary-based specification, the titles may be supplied as an extra `'titles'` key as described above. When using the second (discouraged) dictionary-based specification, the title can be supplied by providing a 3-element tuple `(datatype, offset, title)` instead of the usual 2-element tuple:"
@@ -4802,7 +4802,7 @@
{
"cell_type": "code",
"execution_count": 167,
- "id": "a92fe7b9",
+ "id": "054229c3",
"metadata": {},
"outputs": [
{
@@ -4822,7 +4822,7 @@
},
{
"cell_type": "markdown",
- "id": "a03df07f",
+ "id": "8cb7b0c3",
"metadata": {},
"source": [
"The `dtype.fields` dictionary will contain titles as keys, if any titles are used. This means effectively that a field with a title will be represented twice in the fields dictionary. The tuple values for these fields will also have a third element, the field title. Because of this, and because the `names` attribute preserves the field order while the `fields` attribute may not, it is recommended to iterate through the fields of a dtype using the `names` attribute of the dtype, which will not list titles, as in:"
@@ -4831,7 +4831,7 @@
{
"cell_type": "code",
"execution_count": 168,
- "id": "7d79d449",
+ "id": "46fa0789",
"metadata": {},
"outputs": [
{
@@ -4850,7 +4850,7 @@
},
{
"cell_type": "markdown",
- "id": "f326f48c",
+ "id": "90027ceb",
"metadata": {},
"source": [
"### Indexing and Assignment to Structured arrays\n",
@@ -4867,7 +4867,7 @@
{
"cell_type": "code",
"execution_count": 169,
- "id": "0bcff25e",
+ "id": "3acd25ac",
"metadata": {},
"outputs": [
{
@@ -4890,7 +4890,7 @@
},
{
"cell_type": "markdown",
- "id": "c6036a27",
+ "id": "71abc223",
"metadata": {},
"source": [
"##### Assignment from Scalars\n",
@@ -4901,7 +4901,7 @@
{
"cell_type": "code",
"execution_count": 170,
- "id": "5f8180c1",
+ "id": "09ad3720",
"metadata": {},
"outputs": [],
"source": [
@@ -4911,7 +4911,7 @@
{
"cell_type": "code",
"execution_count": 171,
- "id": "1d2f184e",
+ "id": "b4e9d99e",
"metadata": {},
"outputs": [
{
@@ -4934,7 +4934,7 @@
{
"cell_type": "code",
"execution_count": 172,
- "id": "38fa378b",
+ "id": "17e3e19a",
"metadata": {},
"outputs": [
{
@@ -4956,7 +4956,7 @@
},
{
"cell_type": "markdown",
- "id": "31872854",
+ "id": "bfc7d2c2",
"metadata": {},
"source": [
"Structured arrays can also be assigned to unstructured arrays, but only if the structured datatype has just a single field:"
@@ -4965,7 +4965,7 @@
{
"cell_type": "code",
"execution_count": 173,
- "id": "2ad8f17d",
+ "id": "e27b36d3",
"metadata": {},
"outputs": [],
"source": [
@@ -4976,7 +4976,7 @@
{
"cell_type": "code",
"execution_count": 174,
- "id": "59d06d12",
+ "id": "bbda13b9",
"metadata": {},
"outputs": [],
"source": [
@@ -4985,7 +4985,7 @@
},
{
"cell_type": "markdown",
- "id": "254ad34d",
+ "id": "ce6b3e7e",
"metadata": {},
"source": [
"```py\n",
@@ -5006,7 +5006,7 @@
{
"cell_type": "code",
"execution_count": 175,
- "id": "a1e63a89",
+ "id": "4c1918c7",
"metadata": {},
"outputs": [],
"source": [
@@ -5017,7 +5017,7 @@
{
"cell_type": "code",
"execution_count": 176,
- "id": "ac4e538d",
+ "id": "00d0a5f3",
"metadata": {},
"outputs": [
{
@@ -5039,7 +5039,7 @@
},
{
"cell_type": "markdown",
- "id": "695a3ae3",
+ "id": "2c3d7598",
"metadata": {},
"source": [
"##### Assignment involving subarrays\n",
@@ -5056,7 +5056,7 @@
{
"cell_type": "code",
"execution_count": 177,
- "id": "78eb2d91",
+ "id": "095efc01",
"metadata": {},
"outputs": [
{
@@ -5078,7 +5078,7 @@
{
"cell_type": "code",
"execution_count": 178,
- "id": "bd39cd14",
+ "id": "4aba895c",
"metadata": {},
"outputs": [
{
@@ -5099,7 +5099,7 @@
},
{
"cell_type": "markdown",
- "id": "65aa6b1c",
+ "id": "b41a3c7a",
"metadata": {},
"source": [
"The resulting array is a view into the original array. It shares the same memory locations and writing to the view will modify the original array."
@@ -5108,7 +5108,7 @@
{
"cell_type": "code",
"execution_count": 179,
- "id": "98b4398f",
+ "id": "748ea7c0",
"metadata": {},
"outputs": [
{
@@ -5130,7 +5130,7 @@
},
{
"cell_type": "markdown",
- "id": "eb5964c9",
+ "id": "dd634134",
"metadata": {},
"source": [
"This view has the same dtype and itemsize as the indexed field, so it is typically a non-structured array, except in the case of nested structures."
@@ -5139,7 +5139,7 @@
{
"cell_type": "code",
"execution_count": 180,
- "id": "f1fc17d5",
+ "id": "da053c07",
"metadata": {},
"outputs": [
{
@@ -5159,7 +5159,7 @@
},
{
"cell_type": "markdown",
- "id": "2ce4b583",
+ "id": "527b2bfe",
"metadata": {},
"source": [
"If the accessed field is a subarray, the dimensions of the subarray are appended to the shape of the result:"
@@ -5168,7 +5168,7 @@
{
"cell_type": "code",
"execution_count": 181,
- "id": "511e4a07",
+ "id": "4aab2047",
"metadata": {},
"outputs": [],
"source": [
@@ -5178,7 +5178,7 @@
{
"cell_type": "code",
"execution_count": 182,
- "id": "6a2b3394",
+ "id": "aa1fe97d",
"metadata": {},
"outputs": [
{
@@ -5199,7 +5199,7 @@
{
"cell_type": "code",
"execution_count": 183,
- "id": "13a0bed3",
+ "id": "347a151d",
"metadata": {},
"outputs": [
{
@@ -5219,7 +5219,7 @@
},
{
"cell_type": "markdown",
- "id": "2fcb6413",
+ "id": "16ef12a4",
"metadata": {},
"source": [
"##### Accessing multiple fields\n",
@@ -5232,7 +5232,7 @@
{
"cell_type": "code",
"execution_count": 184,
- "id": "1fbf406d",
+ "id": "7d571104",
"metadata": {},
"outputs": [
{
@@ -5254,7 +5254,7 @@
},
{
"cell_type": "markdown",
- "id": "446cb17a",
+ "id": "fd414843",
"metadata": {},
"source": [
"Assignment to the view modifies the original array. The view’s fields will be in the order they were indexed. Note that unlike for single-field indexing, the dtype of the view has the same itemsize as the original array, and has fields at the same offsets as in the original array, and unindexed fields are merely missing.\n",
@@ -5265,7 +5265,7 @@
{
"cell_type": "code",
"execution_count": 185,
- "id": "9b1533fb",
+ "id": "63fc9305",
"metadata": {},
"outputs": [
{
@@ -5287,7 +5287,7 @@
},
{
"cell_type": "markdown",
- "id": "1ab777da",
+ "id": "3bebf5bb",
"metadata": {},
"source": [
"This obeys the structured array assignment rules described above. For example, this means that one can swap the values of two fields using appropriate multi-field indexes:"
@@ -5296,7 +5296,7 @@
{
"cell_type": "code",
"execution_count": 186,
- "id": "92f9299f",
+ "id": "d012c47a",
"metadata": {},
"outputs": [],
"source": [
@@ -5305,7 +5305,7 @@
},
{
"cell_type": "markdown",
- "id": "ff11badf",
+ "id": "3a06e1be",
"metadata": {},
"source": [
"##### Indexing with an integer to get a structured scalar\n",
@@ -5316,7 +5316,7 @@
{
"cell_type": "code",
"execution_count": 187,
- "id": "3c4458fb",
+ "id": "57a2317e",
"metadata": {},
"outputs": [
{
@@ -5339,7 +5339,7 @@
{
"cell_type": "code",
"execution_count": 188,
- "id": "9d02156e",
+ "id": "68e825bd",
"metadata": {},
"outputs": [
{
@@ -5359,7 +5359,7 @@
},
{
"cell_type": "markdown",
- "id": "091a49db",
+ "id": "76996871",
"metadata": {},
"source": [
"Unlike other numpy scalars, structured scalars are mutable and act like views into the original array, such that modifying the scalar will modify the original array. Structured scalars also support access and assignment by field name:"
@@ -5368,7 +5368,7 @@
{
"cell_type": "code",
"execution_count": 189,
- "id": "fce3539a",
+ "id": "7717de35",
"metadata": {},
"outputs": [
{
@@ -5391,7 +5391,7 @@
},
{
"cell_type": "markdown",
- "id": "ec2ee51b",
+ "id": "0c60396e",
"metadata": {},
"source": [
"Similarly to tuples, structured scalars can also be indexed with an integer:"
@@ -5400,7 +5400,7 @@
{
"cell_type": "code",
"execution_count": 190,
- "id": "7892151e",
+ "id": "f15636e2",
"metadata": {},
"outputs": [
{
@@ -5422,7 +5422,7 @@
{
"cell_type": "code",
"execution_count": 191,
- "id": "1f5b258b",
+ "id": "f36c37e1",
"metadata": {},
"outputs": [],
"source": [
@@ -5431,7 +5431,7 @@
},
{
"cell_type": "markdown",
- "id": "fc2974b3",
+ "id": "902b6b77",
"metadata": {},
"source": [
"Thus, tuples might be thought of as the native Python equivalent to numpy’s structured types, much like native python integers are the equivalent to numpy’s integer types. Structured scalars may be converted to a tuple by calling `numpy.ndarray.item`:"
@@ -5440,7 +5440,7 @@
{
"cell_type": "code",
"execution_count": 192,
- "id": "75900109",
+ "id": "501e7ddc",
"metadata": {},
"outputs": [
{
@@ -5460,7 +5460,7 @@
},
{
"cell_type": "markdown",
- "id": "675d25e0",
+ "id": "701d3646",
"metadata": {},
"source": [
"#### Viewing structured arrays containing objects\n",
@@ -5475,7 +5475,7 @@
{
"cell_type": "code",
"execution_count": 193,
- "id": "4e0d5322",
+ "id": "3a2ffa4c",
"metadata": {},
"outputs": [
{
@@ -5497,7 +5497,7 @@
},
{
"cell_type": "markdown",
- "id": "bf1f00b0",
+ "id": "bd9211ed",
"metadata": {},
"source": [
"NumPy will promote individual field datatypes to perform the comparison. So the following is also valid (note the `'f4'` dtype for the `'a'` field):"
@@ -5506,7 +5506,7 @@
{
"cell_type": "code",
"execution_count": 194,
- "id": "afc92f87",
+ "id": "06be69c9",
"metadata": {},
"outputs": [
{
@@ -5527,7 +5527,7 @@
},
{
"cell_type": "markdown",
- "id": "580de1f6",
+ "id": "b6da70a8",
"metadata": {},
"source": [
"To compare two structured arrays, it must be possible to promote them to a common dtype as returned by `numpy.result_type` and `np.promote_types`. This enforces that the number of fields, the field names, and the field titles must match precisely. When promotion is not possible, for example due to mismatching field names, NumPy will raise an error. Promotion between two structured dtypes results in a canonical dtype that ensures native byte-order for all fields:"
@@ -5536,7 +5536,7 @@
{
"cell_type": "code",
"execution_count": 195,
- "id": "ca2a66a5",
+ "id": "337df658",
"metadata": {},
"outputs": [
{
@@ -5557,7 +5557,7 @@
{
"cell_type": "code",
"execution_count": 196,
- "id": "ef7f384f",
+ "id": "51141e9f",
"metadata": {},
"outputs": [
{
@@ -5577,7 +5577,7 @@
},
{
"cell_type": "markdown",
- "id": "93698d5e",
+ "id": "04f4a521",
"metadata": {},
"source": [
"The resulting dtype from promotion is also guaranteed to be packed, meaning that all fields are ordered contiguously and any unnecessary padding is removed:"
@@ -5586,7 +5586,7 @@
{
"cell_type": "code",
"execution_count": 197,
- "id": "fb8d6547",
+ "id": "a4837e21",
"metadata": {},
"outputs": [
{
@@ -5608,7 +5608,7 @@
{
"cell_type": "code",
"execution_count": 198,
- "id": "76a68ed4",
+ "id": "b4e5acc1",
"metadata": {},
"outputs": [
{
@@ -5628,7 +5628,7 @@
},
{
"cell_type": "markdown",
- "id": "3c61f81d",
+ "id": "2635d41b",
"metadata": {},
"source": [
"Note that the result prints without `offsets` or `itemsize` indicating no additional padding. If a structured dtype is created with `align=True` ensuring that `dtype.isalignedstruct` is true, this property is preserved:"
@@ -5637,7 +5637,7 @@
{
"cell_type": "code",
"execution_count": 199,
- "id": "c471ee7c",
+ "id": "ec117194",
"metadata": {},
"outputs": [
{
@@ -5659,7 +5659,7 @@
{
"cell_type": "code",
"execution_count": 200,
- "id": "cf6d9f72",
+ "id": "c20a5317",
"metadata": {},
"outputs": [
{
@@ -5680,7 +5680,7 @@
{
"cell_type": "code",
"execution_count": 201,
- "id": "77b637fe",
+ "id": "0648deaa",
"metadata": {},
"outputs": [
{
@@ -5700,7 +5700,7 @@
},
{
"cell_type": "markdown",
- "id": "f7bae0a4",
+ "id": "462d8b57",
"metadata": {},
"source": [
"When promoting multiple dtypes, the result is aligned if any of the inputs is:"
@@ -5709,7 +5709,7 @@
{
"cell_type": "code",
"execution_count": 202,
- "id": "56b42f94",
+ "id": "53ca495a",
"metadata": {},
"outputs": [
{
@@ -5729,7 +5729,7 @@
},
{
"cell_type": "markdown",
- "id": "7253081d",
+ "id": "fab01908",
"metadata": {},
"source": [
"The `<` and `>` operators always return `False` when comparing void structured arrays, and arithmetic and bitwise operations are not supported.\n",
@@ -5816,7 +5816,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.18"
+ "version": "3.9.19"
},
"source_map": [
14,
diff --git a/_sources/deep-learning/cnn/cnn-deepdream.ipynb b/_sources/deep-learning/cnn/cnn-deepdream.ipynb
index 49ef8353bf..bc578fe39e 100644
--- a/_sources/deep-learning/cnn/cnn-deepdream.ipynb
+++ b/_sources/deep-learning/cnn/cnn-deepdream.ipynb
@@ -352,7 +352,7 @@
"source": [
"## Your turn! 🚀\n",
"\n",
- "TBD."
+ "You can practice your cnn skills by following the assignment [sign language digits classification with cnn](../../assignments/deep-learning/cnn/sign-language-digits-classification-with-cnn.ipynb)"
]
},
{
diff --git a/_sources/deep-learning/cnn/cnn-vgg.ipynb b/_sources/deep-learning/cnn/cnn-vgg.ipynb
index 4e67c7e724..188b31cdbd 100644
--- a/_sources/deep-learning/cnn/cnn-vgg.ipynb
+++ b/_sources/deep-learning/cnn/cnn-vgg.ipynb
@@ -440,8 +440,7 @@
"metadata": {},
"source": [
"## Your turn! 🚀\n",
- "\n",
- "TBD."
+ "You can practice your cnn skills by following the assignment [object recognition in images using cnn](../../assignments/deep-learning/cnn/object-recognition-in-images-using-cnn.ipynb)."
]
},
{
diff --git a/_sources/deep-learning/cnn/cnn.ipynb b/_sources/deep-learning/cnn/cnn.ipynb
index 29bb544d7b..5ac8402b46 100644
--- a/_sources/deep-learning/cnn/cnn.ipynb
+++ b/_sources/deep-learning/cnn/cnn.ipynb
@@ -162,6 +162,42 @@
"\"\"\"))"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "\n",
+ "A demo of CNN. [source] \n",
+ "
\n"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "from IPython.display import HTML\n",
+ "display(HTML(\"\"\"\n",
+ "\n",
+ "\n",
+ "A demo of CNN. [source] \n",
+ "
\n",
+ "\"\"\"))"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 4,
@@ -861,8 +897,7 @@
"metadata": {},
"source": [
"## Your turn! 🚀\n",
- "\n",
- "TBD."
+ "You can practice your cnn skills by following the assignment [how to choose cnn architecture mnist](../../assignments/deep-learning/cnn/how-to-choose-cnn-architecture-mnist.ipynb)."
]
},
{
diff --git a/_sources/deep-learning/image-classification.ipynb b/_sources/deep-learning/image-classification.ipynb
index 56f4d51c5e..2486078d3d 100644
--- a/_sources/deep-learning/image-classification.ipynb
+++ b/_sources/deep-learning/image-classification.ipynb
@@ -219,8 +219,8 @@
"source": [
"- Using small 3×3 filters to replace large convolutional kernels.\n",
"- After replacing the convolution kernel, the convolution layers have the same perceptual field. \n",
- "- Each layer is trained by Re LU activation function and batch gradient descent after convolution operation.\n",
- "- It is verified that increasing the network depth can improve the model performance Although, VGG has achieved good results in image classification and localization problems in 2014 due to its deeper network structure and low computational complexity, it uses 140 million parameters and is computationally intensive, which is its shortcoming."
+ "- Each layer is trained by ReLU activation function and batch gradient descent after convolution operation.\n",
+ "- It is verified that increasing the network depth can improve the model performance. Although, VGG has achieved good results in image classification and localization problems in 2014 due to its deeper network structure and low computational complexity, it uses 140 million parameters and is computationally intensive, which is its shortcoming."
]
},
{
@@ -1156,7 +1156,7 @@
"id": "b4552758",
"metadata": {},
"source": [
- "TBD."
+ "Assignment - [Image classification](../../assignments/deep-learning/cnn/image-classification.ipynb)"
]
},
{
diff --git a/_sources/deep-learning/image-segmentation.ipynb b/_sources/deep-learning/image-segmentation.ipynb
index 7c2d3556dc..abbe6c89a3 100644
--- a/_sources/deep-learning/image-segmentation.ipynb
+++ b/_sources/deep-learning/image-segmentation.ipynb
@@ -2045,7 +2045,7 @@
"id": "a0994ed1",
"metadata": {},
"source": [
- "TBD."
+ "Assignment - [Comparing edge-based and region-based segmentation](../../assignments/deep-learning/image-segmentation/comparing-edge-based-and-region-based-segmentation.ipynb)"
]
},
{
diff --git a/_sources/deep-learning/lstm.ipynb b/_sources/deep-learning/lstm.ipynb
index c920b28b04..6ea5b6e8f9 100644
--- a/_sources/deep-learning/lstm.ipynb
+++ b/_sources/deep-learning/lstm.ipynb
@@ -4770,7 +4770,7 @@
"source": [
"## Your turn! 🚀\n",
"\n",
- "Practice the Long-Short Term Memory Networks by following this TBD.\n",
+ "Assignment - [Bitcoin lstm model with tweet volume and sentiment](../../assignments/deep-learning/lstm/bitcoin-lstm-model-with-tweet-volume-and-sentiment.ipynb)\n",
"\n",
"## Acknowledgments\n",
"\n",
diff --git a/_sources/deep-learning/nlp.ipynb b/_sources/deep-learning/nlp.ipynb
index 839b75e674..efcff10fd5 100644
--- a/_sources/deep-learning/nlp.ipynb
+++ b/_sources/deep-learning/nlp.ipynb
@@ -786,8 +786,7 @@
},
"source": [
"## Your turn! 🚀\n",
- "\n",
- "TBD."
+ "You can practice your nlp skills by following the assignment [getting start nlp with classification task](../assignments/deep-learning/nlp/getting-start-nlp-with-classification-task.ipynb)."
]
},
{
diff --git a/_sources/deep-learning/rnn.ipynb b/_sources/deep-learning/rnn.ipynb
index d436b6048b..7c1bf555d2 100644
--- a/_sources/deep-learning/rnn.ipynb
+++ b/_sources/deep-learning/rnn.ipynb
@@ -2,14 +2,23 @@
"cells": [
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"id": "4f92eda8",
"metadata": {
"tags": [
"hide-input"
]
},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "WARNING: Ignoring invalid distribution -fds-nightly (c:\\users\\16111\\.conda\\envs\\open-machine-learning-jupyter-book\\lib\\site-packages)\n",
+ "WARNING: Ignoring invalid distribution -fds-nightly (c:\\users\\16111\\.conda\\envs\\open-machine-learning-jupyter-book\\lib\\site-packages)\n"
+ ]
+ }
+ ],
"source": [
"# Install the necessary dependencies\n",
"\n",
@@ -159,9 +168,21 @@
"## Code"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "6b52f47d",
+ "metadata": {},
+ "source": [
+ "A text classifier implemented in TensorFlow to classify SMS spam messages.\n",
+ "Code first downloads and processes the SMS Spam Collection dataset from the UCI Machine Learning Repository and then builds a basic Recurrent neural network (RNN) for text classification using TensorFlow.\n",
+ "The code first cleans and preprocesses the text, then splits it into training and test sets, followed by tokenizing and padding the training set. Next, the code uses an embedding layer to convert the tokenized text into a vector representation, which is then fed into a recurrent neural network and finally classified using a Softmax loss function.\n",
+ "The output of the # code is the accuracy of the classifier along with some statistics\n",
+ "We implement an RNN in TensorFlow to predict spam/ham from texts"
+ ]
+ },
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 2,
"id": "b8241ee1",
"metadata": {
"attributes": {
@@ -171,294 +192,303 @@
"id": ""
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['go until jurong point crazy available only in bugis n great world la e buffet cine there got amore wat', 'ok lar joking wif u oni', 'free entry in a wkly comp to win fa cup final tkts st may text fa to to receive entry questionstd txt ratetcs apply overs', 'u dun say so early hor u c already then say', 'nah i dont think he goes to usf he lives around here though']\n",
- "(5574, 25)\n",
- "[[ 191 3 17 ... 2725 0 0]\n",
- " [ 365 1206 41 ... 0 0 0]\n",
- " [ 81 40 4 ... 0 0 0]\n",
- " ...\n",
- " [7814 7815 533 ... 0 0 0]\n",
- " [ 2 28 1439 ... 7 161 3]\n",
- " [ 51 20 3 ... 0 0 0]]\n",
- "Vocabulary Size: 8629\n",
- "80-20 Train Test split: 4459 -- 1115\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "C:\\Users\\fuqiongying\\AppData\\Local\\Temp\\ipykernel_1816\\2116000173.py:115: UserWarning: `tf.nn.rnn_cell.BasicRNNCell` is deprecated and will be removed in a future version. This class is equivalent as `tf.keras.layers.SimpleRNNCell`, and will be replaced by that in Tensorflow 2.0.\n",
- " cell = tf.nn.rnn_cell.BasicRNNCell(num_units=rnn_size)\n"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Tensor(\"Mean:0\", shape=(), dtype=float32)\n",
- "Tensor(\"Mean_1:0\", shape=(), dtype=float32)\n",
- "Epoch: 1, Test Loss: 0.69, Test Acc: 0.81\n",
- "Epoch: 2, Test Loss: 0.65, Test Acc: 0.82\n",
- "Epoch: 3, Test Loss: 0.6, Test Acc: 0.82\n",
- "Epoch: 4, Test Loss: 0.55, Test Acc: 0.82\n",
- "Epoch: 5, Test Loss: 0.51, Test Acc: 0.83\n",
- "Epoch: 6, Test Loss: 0.47, Test Acc: 0.83\n",
- "Epoch: 7, Test Loss: 0.45, Test Acc: 0.83\n",
- "Epoch: 8, Test Loss: 0.43, Test Acc: 0.84\n",
- "Epoch: 9, Test Loss: 0.42, Test Acc: 0.84\n",
- "Epoch: 10, Test Loss: 0.41, Test Acc: 0.84\n",
- "Epoch: 11, Test Loss: 0.41, Test Acc: 0.84\n",
- "Epoch: 12, Test Loss: 0.4, Test Acc: 0.85\n",
- "Epoch: 13, Test Loss: 0.4, Test Acc: 0.85\n",
- "Epoch: 14, Test Loss: 0.4, Test Acc: 0.85\n",
- "Epoch: 15, Test Loss: 0.4, Test Acc: 0.86\n",
- "Epoch: 16, Test Loss: 0.39, Test Acc: 0.86\n",
- "Epoch: 17, Test Loss: 0.39, Test Acc: 0.87\n",
- "Epoch: 18, Test Loss: 0.38, Test Acc: 0.87\n",
- "Epoch: 19, Test Loss: 0.38, Test Acc: 0.87\n",
- "Epoch: 20, Test Loss: 0.37, Test Acc: 0.87\n"
- ]
- },
- {
- "data": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHHCAYAAABXx+fLAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB2IklEQVR4nO3dd3gU1dvG8e+mNyBASAECCaF3aRFBEUEDKIKKgCJNFEWKvogUC8VCUBFRpChK94cIdqUIURAhFCnSO6Gm0EIKpJDM+8ea1SUJkMam3J/rmovszJnZZ1jj3pyZOcdkGIaBiIiISAliZ+sCRERERG43BSAREREpcRSAREREpMRRABIREZESRwFIREREShwFIBERESlxFIBERESkxFEAEhERkRJHAUhERERKHAUgEbnt3n//fapVq4a9vT2NGze2dTkiUgIpAInIDe3evZtu3bpRtWpVXFxcqFSpEvfffz/Tpk3L1fF+/fVXRo4cSatWrZg7dy4TJ07k7NmzjB8/np07d+Zv8bdJREQEJpOJyZMn27oUEblFDrYuQEQKr40bN9K2bVuqVKnCs88+i6+vL6dOnWLTpk189NFHDB06NMfH/O2337Czs+OLL77AyckJgL/++osJEyYQEBCgHiERuS0UgEQkW++88w5lypRh69ateHp6Wm2LiYnJ1TFjYmJwdXW1hB8REVvQJTARydbRo0epV69epvAD4O3tbfX62rVrvPXWWwQFBeHs7ExAQACvvvoqycnJljYmk4m5c+eSmJiIyWTCZDIxb948mjdvDkD//v2t1gPce++91K9fn127dtGmTRvc3NyoXr06y5YtA2DdunUEBwfj6upKrVq1WLNmjVVdJ06c4IUXXqBWrVq4urpSvnx5Hn/8cSIiIixtDMOgbdu2VKhQwSrYpaSk0KBBA4KCgkhMTMzLXyVgDn8DBgzAx8cHFxcXGjVqxPz58zO1++qrr2jatCmlSpWidOnSNGjQgI8++siyPTU1lQkTJlCjRg1cXFwoX748rVu3ZvXq1XmuUaSkUAASkWxVrVqVbdu2sWfPnpu2feaZZxg7dixNmjThww8/pE2bNoSGhtKzZ09Lm4ULF3L33Xfj7OzMwoULWbhwIXXq1OHNN98EYODAgZb199xzj2W/S5cu8dBDDxEcHMx7772Hs7MzPXv2ZMmSJfTs2ZNOnToxadIkEhMT6datG/Hx8ZZ9t27dysaNG+nZsycff/wxzz//PGFhYdx7771cuXIFMAezOXPmkJSUxPPPP2/Zd9y4cezdu5e5c+fi7u6ep7/Lq1evcu+997Jw4UJ69erF+++/T5kyZejXr59VuFm9ejVPPPEEZcuW5d1332XSpEnce++9bNiwwdJm/PjxTJgwgbZt2/LJJ5/w2muvUaVKFbZv356nGkVKFENEJBu//vqrYW9vb9jb2xstW7Y0Ro4caaxatcpISUmxardz504DMJ555hmr9SNGjDAA47fffrOs69u3r+Hu7m7VbuvWrQZgzJ07N1MNbdq0MQDjf//7n2XdgQMHDMCws7MzNm3aZFm/atWqTMe5cuVKpmOGh4cbgLFgwQKr9Z9++qkBGIsWLTI2bdpk2NvbGy+99FL2f0H/OH78uAEY77//frZtpk6dajl2hpSUFKNly5aGh4eHERcXZxiGYbz44otG6dKljWvXrmV7rEaNGhkPPvjgTesSkeypB0hEsnX//fcTHh7Oww8/zN9//817771HSEgIlSpV4scff7S0W758OQDDhw+32v/ll18G4JdffslTHR4eHlY9SbVq1cLT05M6deoQHBxsWZ/x87FjxyzrXF1dLT+npqZy4cIFqlevjqenZ6Yek4EDBxISEsLQoUPp3bs3QUFBTJw4MU+1Z1i+fDm+vr488cQTlnWOjo4MGzaMhIQE1q1bB4CnpyeJiYk3vJzl6enJ3r17OXz4cL7UJlISKQCJyA01b96cb7/9lkuXLrFlyxbGjBlDfHw83bp1Y9++fYD5Phs7OzuqV69uta+vry+enp6cOHEiTzVUrlwZk8lkta5MmTL4+/tnWgfmS2YZrl69ytixY/H398fZ2RkvLy8qVKhAbGwsly9fzvReX3zxBVeuXOHw4cPMmzfPKkDlxYkTJ6hRowZ2dtb/261Tp45lO8ALL7xAzZo16dixI5UrV+bpp59m5cqVVvu8+eabxMbGUrNmTRo0aMArr7zCrl278qVOkZJCAUhEbomTkxPNmzdn4sSJzJw5k9TUVJYuXWrV5vqQkl/s7e1ztN4wDMvPQ4cO5Z133qF79+58/fXX/Prrr6xevZry5cuTnp6ead+1a9dabtzevXt3PlSfM97e3uzcuZMff/yRhx9+mN9//52OHTvSt29fS5t77rmHo0ePMmfOHOrXr8/nn39OkyZN+Pzzz297vSJFlQKQiORYs2bNAIiMjATMN0unp6dnuiQTHR1NbGwsVatWveHxCio4ASxbtoy+ffvywQcf0K1bN+6//35at25NbGxspraRkZEMHTqUBx54gIceeogRI0bkufcqQ9WqVTl8+HCm0HXgwAHL9gxOTk507tyZGTNmcPToUZ577jkWLFjAkSNHLG3KlStH//79Wbx4MadOnaJhw4aMHz8+X2oVKQkUgEQkW7///rtVb0qGjHt+atWqBUCnTp0AmDp1qlW7KVOmAPDggw/e8H0ynrDKKpTklb29faZzmDZtGmlpaZnaPvvss6Snp/PFF1/w2Wef4eDgwIABA7L8O8ipTp06ERUVxZIlSyzrrl27xrRp0/Dw8KBNmzYAXLhwwWo/Ozs7GjZsCGDpmbq+jYeHB9WrV7cackBEbkwDIYpItoYOHcqVK1d45JFHqF27NikpKWzcuJElS5YQEBBA//79AWjUqBF9+/bls88+IzY2ljZt2rBlyxbmz59P165dadu27Q3fJygoCE9PT2bNmkWpUqVwd3cnODiYwMDAPJ/DQw89xMKFCylTpgx169YlPDycNWvWUL58eat2c+fO5ZdffmHevHlUrlwZMAelp556ipkzZ/LCCy/c9L3CwsJISkrKtL5r164MHDiQTz/9lH79+rFt2zYCAgJYtmwZGzZsYOrUqZQqVQowDydw8eJF7rvvPipXrsyJEyeYNm0ajRs3ttwvVLduXe69916aNm1KuXLl+Ouvv1i2bBlDhgzJ61+XSMlh24fQRKQwW7FihfH0008btWvXNjw8PAwnJyejevXqxtChQ43o6GirtqmpqcaECROMwMBAw9HR0fD39zfGjBljJCUlWbXL6jF4wzCMH374wahbt67h4OBg9Sh7mzZtjHr16mVqX7Vq1SwfBQeMwYMHW15funTJ6N+/v+Hl5WV4eHgYISEhxoEDB4yqVasaffv2NQzDME6dOmWUKVPG6Ny5c6bjPfLII4a7u7tx7NixbP+eMh6Dz25ZuHChYRiGER0dbanFycnJaNCgQaZH/5ctW2Y88MADhre3t+Hk5GRUqVLFeO6554zIyEhLm7ffftto0aKF4enpabi6uhq1a9c23nnnnUzDE4hI9kyGkQ99uyIiIiJFiO4BEhERkRJHAUhERERKHAUgERERKXEUgERERKTEUQAS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LVu2FNAZ5MyNzjc1NZVRo0bRoEED3N3dqVixIn369OHs2bM3PGZufhduh5t9tv369ctUd4cOHW563ML42d7sXLP6/TWZTLz//vvZHrOwfq638l2TlJTE4MGDKV++PB4eHjz22GNER0ff8Li5/V3PCQWgYmrdunUMHjyYTZs2sXr1alJTU3nggQdITEy84X6lS5cmMjLSspw4ceI2VZx39erVs6r9zz//zLbtxo0beeKJJxgwYAA7duyga9eudO3alT179tzGinNn69atVue5evVqAB5//PFs9ykqn2tiYiKNGjVi+vTpWW5/7733+Pjjj5k1axabN2/G3d2dkJAQkpKSsj3mkiVLGD58OOPGjWP79u00atSIkJAQYmJiCuo0btmNzvfKlSts376dN954g+3bt/Ptt99y8OBBHn744ZseNye/C7fLzT5bgA4dOljVvXjx4hses7B+tjc71/+eY2RkJHPmzMFkMvHYY4/d8LiF8XO9le+a//u//+Onn35i6dKlrFu3jrNnz/Loo4/e8Li5+V3PMUNKhJiYGAMw1q1bl22buXPnGmXKlLl9ReWjcePGGY0aNbrl9t27dzcefPBBq3XBwcHGc889l8+VFbwXX3zRCAoKMtLT07PcXlQ/V8D47rvvLK/T09MNX19f4/3337esi42NNZydnY3Fixdne5wWLVoYgwcPtrxOS0szKlasaISGhhZI3bl1/flmZcuWLQZgnDhxIts2Of1dsIWszrVv375Gly5dcnScovDZ3srn2qVLF+O+++67YZui8LkaRubvmtjYWMPR0dFYunSppc3+/fsNwAgPD8/yGLn9Xc8p9QCVEJcvXwagXLlyN2yXkJBA1apV8ff3p0uXLuzdu/d2lJcvDh8+TMWKFalWrRq9evXi5MmT2bYNDw+nffv2VutCQkIIDw8v6DLzVUpKCosWLeLpp5++4cS9RflzzXD8+HGioqKsPrcyZcoQHByc7eeWkpLCtm3brPaxs7Ojffv2Re6zBvPvsclkwtPT84btcvK7UJisXbsWb29vatWqxaBBg7hw4UK2bYvLZxsdHc0vv/zCgAEDbtq2KHyu13/XbNu2jdTUVKvPqXbt2lSpUiXbzyk3v+u5oQBUAqSnp/PSSy/RqlUr6tevn227WrVqMWfOHH744QcWLVpEeno6d911F6dPn76N1eZOcHAw8+bN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",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "image/png": "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5QoVKlCwYEFmz57N2LFjE7vMD1K3bl3T86JFi+Lh4UGuXLn4/fff3+svq5Rq3rx51K1bl6xZs8a6TUo+r0ITHh5Oy5YtUUoxc+bMt26bUn8XWrdubXpepEgRihYtSt68edm1axfVq1fXsbLENX/+fNq1a/fOGxNSwnl93++a5EJagFK53r17s2HDBnbu3En27Nnj9F4rKytKlCjB1atXE6m6xOPi4sLHH38ca+2ZM2eOdhfCo0ePyJw5c1KUlyBu3brF9u3b6datW5zel1LP6+tzE5fz5urqiqWlZYo+16/Dz61bt9i2bdtbW39i8q7fheQqT548uLq6xlp3aji3e/fu5dKlS3H+HYbkd15j+67JnDkzYWFhPH/+PMr2bztP8fldjw8JQKmUUorevXuzZs0aduzYQe7cueO8j8jISM6cOUOWLFkSocLEFRQUxLVr12KtvXz58vj6+kZZt23btigtJcndggULyJQpE/Xr14/T+1Lqec2dOzeZM2eOct4CAwM5fPhwrOfN2tqaUqVKRXmP0WjE19c3RZzr1+HnypUrbN++nQwZMsR5H+/6XUiu7t69y5MnT2KtO6WfW9BacEuVKkWxYsXi/N7kcl7f9V1TqlQprKysopynS5cucfv27VjPU3x+1+NbvEiFevbsqZydndWuXbvUgwcPTI+XL1+atmnfvr0aPHiwaXn06NFq69at6tq1a+r48eOqdevWytbWVp07d06PQ4iTAQMGqF27dqkbN26o/fv3qxo1aihXV1fl5+enlIp+rPv371dp0qRRP/zwg7pw4YLy9vZWVlZW6syZM3odQpxERkaqnDlzqkGDBkV7LSWf1xcvXqiTJ0+qkydPKkBNnjxZnTx50nTX08SJE5WLi4tat26d+vvvv1WjRo1U7ty51atXr0z7qFatmpo6dappecWKFcrGxkYtXLhQnT9/XnXv3l25uLiohw8fJvnx/dfbjjcsLEw1bNhQZc+eXZ06dSrK73FoaKhpH/893nf9Lujlbcf64sULNXDgQHXw4EF148YNtX37dlWyZEmVL18+FRISYtpHSjm37/r/WCmlAgIClL29vZo5c2aM+0gp5/V9vmt69OihcubMqXbs2KGOHTumypcvr8qXLx9lP/nz51erV682Lb/P7/qHkgCUSgExPhYsWGDapmrVqqpjx46m5a+//lrlzJlTWVtbKzc3N1WvXj114sSJpC8+Hlq1aqWyZMmirK2tVbZs2VSrVq3U1atXTa//91iVUur3339XH3/8sbK2tlaFCxdWGzduTOKq42/r1q0KUJcuXYr2Wko+rzt37ozx/9vXx2M0GtWIESOUm5ubsrGxUdWrV4/2M8iVK5fy9vaOsm7q1Kmmn0HZsmXVoUOHkuiI3u5tx3vjxo1Yf4937txp2sd/j/ddvwt6eduxvnz5UtWqVUtlzJhRWVlZqVy5cqkvvvgiWpBJKef2Xf8fK6XU7NmzlZ2dnXr+/HmM+0gp5/V9vmtevXqlevXqpdKlS6fs7e1VkyZN1IMHD6Lt59/veZ/f9Q9l+OeDhRBCCCHMhvQBEkIIIYTZkQAkhBBCCLMjAUgIIYQQZkcCkBBCCCHMjgQgIYQQQpgdCUBCCCGEMDsSgIQQQghhdiQACSFELAwGA2vXrtW7DCFEIpAAJIRIljp16oTBYIj2qFOnjt6lCSFSgTR6FyCEELGpU6cOCxYsiLLOxsZGp2qEEKmJtAAJIZItGxsbMmfOHOWRLl06QLs8NXPmTOrWrYudnR158uRh1apVUd5/5swZqlWrhp2dHRkyZKB79+4EBQVF2Wb+/PkULlwYGxsbsmTJQu/evaO87u/vT5MmTbC3tydfvnysX7/e9NqzZ89o164dGTNmxM7Ojnz58kULbEKI5EkCkBAixRoxYgTNmjXj9OnTtGvXjtatW3PhwgUAgoODqV27NunSpePo0aOsXLmS7du3Rwk4M2fOxMvLi+7du3PmzBnWr1/PRx99FOUzRo8eTcuWLfn777+pV68e7dq14+nTp6bPP3/+PJs3b+bChQvMnDkTV1fXpPsBCCHiL0GnVhVCiATSsWNHZWlpqRwcHKI8xo0bp5TSZo/u0aNHlPd4eHionj17KqWUmjNnjkqXLp0KCgoyvb5x40ZlYWFhmmU8a9asatiwYbHWAKjhw4ebloOCghSgNm/erJRSytPTU3Xu3DlhDlgIkaSkD5AQItn67LPPmDlzZpR16dOnNz0vX758lNfKly/PqVOnALhw4QLFihXDwcHB9HrFihUxGo1cunQJg8HA/fv3qV69+ltrKFq0qOm5g4MDTk5O+Pn5AdCzZ0+aNWvGiRMnqFWrFo0bN6ZChQrxOlYhRNKSACSESLYcHByiXZJKKHZ2du+1nZWVVZRlg8GA0WgEoG7duty6dYtNmzaxbds2qlevjpeXFz/88EOC1yuESFjSB0gIkWIdOnQo2nLBggUBKFiwIKdPnyY4ONj0+v79+7GwsCB//vw4Ojri7u6Or6/vB9WQMWNGOnbsyJIlS5gyZQpz5sz5oP0JIZKGtAAJIZKt0NBQHj58GGVdmjRpTB2NV65cSenSpalUqRJLly7lyJEjzJs3D4B27drh7e1Nx44dGTVqFI8fP6ZPnz60b98eNzc3AEaNGkWPHj3IlCkTdevW5cWLF+zfv58+ffq8V30jR46kVKlSFC5cmNDQUDZs2GAKYEKI5E0CkBAi2dqyZQtZsmSJsi5//vxcvHgR0O7QWrFiBb169SJLliwsX76cQoUKAWBvb8/WrVvp27cvZcqUwd7enmbNmjF58mTTvjp27EhISAg//fQTAwcOxNXVlebNm793fdbW1gwZMoSbN29iZ2dH5cqVWbFiRQIcuRAisRmUUkrvIoQQIq4MBgNr1qyhcePGepcihEiBpA+QEEIIIcyOBCAhhBBCmB3pAySESJHk6r0Q4kNIC5AQQgghzI4EICGEEEKYHQlAQgghhDA7EoCEEEIIYXYkAAkhhBDC7EgAEkIIIYTZkQAkhBBCCLMjAUgIIYQQZkcCkBBCCCHMzv8BHMFwk67OIgIAAAAASUVORK5CYII=",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
- "# A text classifier implemented in TensorFlow to classify SMS spam messages.\n",
- "\n",
- "# Code first downloads and processes the SMS Spam Collection dataset from the UCI Machine Learning Repository and then builds a basic Recurrent neural network (RNN) for text classification using TensorFlow.\n",
- "\n",
- "# The code first cleans and preprocesses the text, then splits it into training and test sets, followed by tokenizing and padding the training set. Next, the code uses an embedding layer to convert the tokenized text into a vector representation, which is then fed into a recurrent neural network and finally classified using a Softmax loss function.\n",
- "\n",
- "#The output of the # code is the accuracy of the classifier along with some statistics\n",
- "\n",
- "# We implement an RNN in TensorFlow to predict spam/ham from texts\n",
- "\n",
"import os\n",
"import re\n",
"import io\n",
"import requests\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
- "import tensorflow.compat.v1 as tf\n",
+ "import tensorflow as tf\n",
"from zipfile import ZipFile\n",
- "from tensorflow.python.framework import ops\n",
- "tf.disable_v2_behavior()\n",
- "ops.reset_default_graph()\n",
- "\n",
- "# Start a graph\n",
- "sess = tf.Session()\n",
- "\n",
- "# Set RNN parameters\n",
- "epochs = 20\n",
- "batch_size = 250\n",
- "max_sequence_length =25 \n",
- "rnn_size = 10\n",
- "embedding_size = 50\n",
- "min_word_frequency = 10\n",
- "learning_rate = 0.0005\n",
- "dropout_keep_prob = tf.placeholder(tf.float32,name='dropout_keep_prob')\n",
- "\n",
+ "from tensorflow.keras.preprocessing.text import Tokenizer\n",
+ "from tensorflow.keras.preprocessing.sequence import pad_sequences"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "b3fa5d09",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Set random seed for reproducibility\n",
+ "tf.random.set_seed(42)\n",
"\n",
"# Download or open data\n",
- "data_dir = 'tmp'\n",
- "data_file = 'text_data.txt'\n",
+ "data_dir = \"tmp\"\n",
+ "data_file = \"text_data.txt\"\n",
"if not os.path.exists(data_dir):\n",
" os.makedirs(data_dir)\n",
"\n",
"if not os.path.isfile(os.path.join(data_dir, data_file)):\n",
- " zip_url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/00228/smsspamcollection.zip'\n",
+ " zip_url = \"http://archive.ics.uci.edu/ml/machine-learning-databases/00228/smsspamcollection.zip\"\n",
" r = requests.get(zip_url)\n",
" z = ZipFile(io.BytesIO(r.content))\n",
- " file = z.read('SMSSpamCollection')\n",
+ " file = z.read(\"SMSSpamCollection\")\n",
" # Format Data\n",
" text_data = file.decode()\n",
- " text_data = text_data.encode('ascii', errors='ignore')\n",
- " text_data = text_data.decode().split('\\n')\n",
+ " text_data = text_data.encode(\"ascii\", errors=\"ignore\")\n",
+ " text_data = text_data.decode().split(\"\\n\")\n",
"\n",
" # Save data to text file\n",
- " with open(os.path.join(data_dir, data_file), 'w') as file_conn:\n",
+ " with open(os.path.join(data_dir, data_file), \"w\") as file_conn:\n",
" for text in text_data:\n",
" file_conn.write(\"{}\\n\".format(text))\n",
"else:\n",
" # Open data from text file\n",
" text_data = []\n",
- " with open(os.path.join(data_dir, data_file), 'r') as file_conn:\n",
+ " with open(os.path.join(data_dir, data_file), \"r\") as file_conn:\n",
" for row in file_conn:\n",
" text_data.append(row)\n",
" text_data = text_data[:-1]\n",
"\n",
- "text_data = [x.split('\\t') for x in text_data if len(x) >= 1]\n",
- "[text_data_target, text_data_train] = [list(x) for x in zip(*text_data)]\n",
- "\n",
- "\n",
+ "text_data = [x.split(\"\\t\") for x in text_data if len(x) >= 1]\n",
+ "[text_data_target, text_data_train] = [list(x) for x in zip(*text_data)]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "d2d94450",
+ "metadata": {},
+ "outputs": [],
+ "source": [
"# Create a text cleaning function\n",
"def clean_text(text_string):\n",
- " text_string = re.sub(r'([^\\s\\w]|_|[0-9])+', '', text_string)\n",
+ " text_string = re.sub(r\"([^\\s\\w]|_|[0-9])+\", \"\", text_string)\n",
" text_string = \" \".join(text_string.split())\n",
" text_string = text_string.lower()\n",
- " return text_string\n",
- "\n",
+ " return text_string"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "7c01c5b9",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "['go until jurong point crazy available only in bugis n great world la e buffet cine there got amore wat', 'ok lar joking wif u oni', 'free entry in a wkly comp to win fa cup final tkts st may text fa to to receive entry questionstd txt ratetcs apply overs', 'u dun say so early hor u c already then say', 'nah i dont think he goes to usf he lives around here though']\n",
+ "(5574, 25)\n"
+ ]
+ }
+ ],
+ "source": [
"# Clean texts\n",
"text_data_train = [clean_text(x) for x in text_data_train]\n",
- "#print(text_data[:5])\n",
"print(text_data_train[:5])\n",
"\n",
"# Tokenize and pad sequences\n",
- "vocab_processor = tf.keras.preprocessing.text.Tokenizer()\n",
- "vocab_processor.fit_on_texts(text_data_train)\n",
- "text_processed = vocab_processor.texts_to_sequences(text_data_train)\n",
- "max_document_length = max([len(x) for x in text_processed])\n",
- "#pads the text data to ensure all sequences have the same length (max_sequence_length).\n",
- "text_processed = tf.keras.preprocessing.sequence.pad_sequences(text_processed, maxlen=max_sequence_length, padding='post')\n",
- "print(text_processed.shape)\n",
+ "tokenizer = Tokenizer()\n",
+ "tokenizer.fit_on_texts(text_data_train)\n",
+ "text_processed = tokenizer.texts_to_sequences(text_data_train)\n",
+ "max_sequence_length = 25\n",
+ "text_processed = pad_sequences(\n",
+ " text_processed, maxlen=max_sequence_length, padding=\"post\"\n",
+ ")\n",
+ "print(text_processed.shape)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "fe65852c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
"# Shuffle and split data\n",
"text_processed = np.array(text_processed)\n",
- "text_data_target = np.array([1 if x == 'ham' else 0 for x in text_data_target])\n",
+ "text_data_target = np.array([1 if x == \"ham\" else 0 for x in text_data_target])\n",
"shuffled_ix = np.random.permutation(np.arange(len(text_data_target)))\n",
"x_shuffled = text_processed[shuffled_ix]\n",
- "y_shuffled = text_data_target[shuffled_ix]\n",
- "\n",
+ "y_shuffled = text_data_target[shuffled_ix]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "b107bb0b",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Vocabulary Size: 8630\n",
+ "80-20 Train Test split: 4459 -- 1115\n"
+ ]
+ }
+ ],
+ "source": [
"# Split train/test set\n",
- "ix_cutoff = int(len(y_shuffled)*0.80)\n",
+ "ix_cutoff = int(len(y_shuffled) * 0.80)\n",
"x_train, x_test = x_shuffled[:ix_cutoff], x_shuffled[ix_cutoff:]\n",
- "print(x_train)\n",
"y_train, y_test = y_shuffled[:ix_cutoff], y_shuffled[ix_cutoff:]\n",
- "vocab_size = len(vocab_processor.word_counts)\n",
+ "vocab_size = len(tokenizer.word_index) + 1\n",
"print(\"Vocabulary Size: {:d}\".format(vocab_size))\n",
- "print(\"80-20 Train Test split: {:d} -- {:d}\".format(len(y_train), len(y_test)))\n",
- "\n",
- "# Create placeholders\n",
- "x_data = tf.placeholder(tf.int32, [None, max_sequence_length])\n",
- "y_output = tf.placeholder(tf.int32, [None])\n",
- "\n",
- "# Create embedding\n",
- "embedding_mat = tf.Variable(tf.random_uniform([vocab_size+1, embedding_size], -1.0, 1.0))\n",
- "embedding_output = tf.nn.embedding_lookup(embedding_mat, x_data)\n",
- "\n",
- "# Define the RNN cell\n",
- "# tensorflow change >= 1.0, rnn is put into tensorflow.contrib directory. Prior version not test.\n",
- "cell = tf.nn.rnn_cell.BasicRNNCell(num_units=rnn_size)\n",
- "\n",
- "output, state = tf.nn.dynamic_rnn(cell, embedding_output, dtype=tf.float32)\n",
- "output = tf.nn.dropout(output, dropout_keep_prob)\n",
- "\n",
- "# Get output of RNN sequence\n",
- "output = tf.transpose(output, [1, 0, 2])\n",
- "last = tf.gather(output, int(output.get_shape()[0]) - 1)\n",
- "\n",
- "weight = tf.Variable(tf.truncated_normal([rnn_size, 2], stddev=0.1))\n",
- "bias = tf.Variable(tf.constant(0.1, shape=[2]))\n",
- "logits_out = tf.matmul(last, weight) + bias\n",
- "\n",
- "\n",
- "# Loss function\n",
- "losses = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits_out, labels=y_output)\n",
- "loss = tf.reduce_mean(losses)\n",
- "print(loss)\n",
- "accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(logits_out, 1), tf.cast(y_output, tf.int64)), tf.float32))\n",
- "print(accuracy)\n",
- "optimizer = tf.train.RMSPropOptimizer(learning_rate)\n",
- "train_step = optimizer.minimize(loss)\n",
- "init = tf.global_variables_initializer()\n",
- "sess.run(init)\n",
- "\n",
- "train_loss = []\n",
- "test_loss = []\n",
- "train_accuracy = []\n",
- "test_accuracy = []\n",
- "# Start training\n",
- "for epoch in range(epochs):\n",
- " # Shuffle training data\n",
- " shuffled_ix = np.random.permutation(np.arange(len(x_train)))\n",
- " x_train = x_train[shuffled_ix]\n",
- " y_train = y_train[shuffled_ix]\n",
- " num_batches = int(len(x_train)/batch_size) + 1\n",
- " # TO DO CALCULATE GENERATIONS ExACTLY\n",
- " for i in range(num_batches):\n",
- " # Select train data\n",
- " min_ix = i * batch_size\n",
- " max_ix = np.min([len(x_train), ((i+1) * batch_size)])\n",
- " x_train_batch = x_train[min_ix:max_ix]\n",
- " y_train_batch = y_train[min_ix:max_ix]\n",
- " max_len = max([len(x) for x in x_train_batch])\n",
- " x_train_batch = np.array([np.pad(x, (0, max_len - len(x)), 'constant') for x in x_train_batch])\n",
- " # Run train step\n",
- " train_dict = {x_data: x_train_batch, y_output: y_train_batch, dropout_keep_prob:0.5}\n",
- " sess.run(train_step, feed_dict=train_dict)\n",
- " # Run loss and accuracy for training\n",
- " train_dict = {x_data: x_train, y_output: y_train, dropout_keep_prob:1.0}\n",
- " temp_train_loss, temp_train_acc = sess.run([loss, accuracy], feed_dict=train_dict)\n",
- " train_loss.append(temp_train_loss)\n",
- " train_accuracy.append(temp_train_acc)\n",
- " # Run Eval Step\n",
- " test_dict = {x_data: x_test, y_output: y_test, dropout_keep_prob:1.0}\n",
- " temp_test_loss, temp_test_acc = sess.run([loss, accuracy], feed_dict=test_dict)\n",
- " test_loss.append(temp_test_loss)\n",
- " test_accuracy.append(temp_test_acc)\n",
- " print('Epoch: {}, Test Loss: {:.2}, Test Acc: {:.2}'.format(epoch+1, temp_test_loss, temp_test_acc))\n",
- " \n",
- "# Plot loss over time\n",
- "epoch_seq = np.arange(1, epochs+1)\n",
- "plt.plot(epoch_seq, train_loss, 'k--', label='Train Set')\n",
- "plt.plot(epoch_seq, test_loss, 'r-', label='Test Set')\n",
- "plt.title('Softmax Loss')\n",
- "plt.xlabel('Epochs')\n",
- "plt.ylabel('Softmax Loss')\n",
- "plt.legend(loc='upper left')\n",
- "plt.show()\n",
+ "print(\"80-20 Train Test split: {:d} -- {:d}\".format(len(y_train), len(y_test)))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "fdd3ca65",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create the model using the Sequential API\n",
+ "embedding_size = 50\n",
+ "model = tf.keras.Sequential(\n",
+ " [\n",
+ " tf.keras.layers.Embedding(\n",
+ " input_dim=vocab_size,\n",
+ " output_dim=embedding_size,\n",
+ " input_length=max_sequence_length,\n",
+ " ),\n",
+ " tf.keras.layers.SimpleRNN(units=10),\n",
+ " tf.keras.layers.Dropout(0.5),\n",
+ " tf.keras.layers.Dense(units=2, activation=\"softmax\"),\n",
+ " ]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "34b221e2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Compile the model\n",
+ "model.compile(\n",
+ " optimizer=tf.keras.optimizers.RMSprop(learning_rate=0.0005),\n",
+ " loss=\"sparse_categorical_crossentropy\",\n",
+ " metrics=[\"accuracy\"],\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "e7bef8d5",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch 1/20\n",
+ "15/15 [==============================] - 3s 65ms/step - loss: 0.5753 - accuracy: 0.7575 - val_loss: 0.4707 - val_accuracy: 0.8756\n",
+ "Epoch 2/20\n",
+ "15/15 [==============================] - 0s 33ms/step - loss: 0.4656 - accuracy: 0.8433 - val_loss: 0.3906 - val_accuracy: 0.9283\n",
+ "Epoch 3/20\n",
+ "15/15 [==============================] - 0s 24ms/step - loss: 0.3762 - accuracy: 0.9162 - val_loss: 0.3093 - val_accuracy: 0.9574\n",
+ "Epoch 4/20\n",
+ "15/15 [==============================] - 0s 9ms/step - loss: 0.3103 - accuracy: 0.9422 - val_loss: 0.2595 - val_accuracy: 0.9652\n",
+ "Epoch 5/20\n",
+ "15/15 [==============================] - 0s 10ms/step - loss: 0.2693 - accuracy: 0.9498 - val_loss: 0.2225 - val_accuracy: 0.9664\n",
+ "Epoch 6/20\n",
+ "15/15 [==============================] - 0s 10ms/step - loss: 0.2285 - accuracy: 0.9686 - val_loss: 0.1987 - val_accuracy: 0.9664\n",
+ "Epoch 7/20\n",
+ "15/15 [==============================] - 0s 10ms/step - loss: 0.2024 - accuracy: 0.9795 - val_loss: 0.1820 - val_accuracy: 0.9619\n",
+ "Epoch 8/20\n",
+ "15/15 [==============================] - 0s 10ms/step - loss: 0.1825 - accuracy: 0.9748 - val_loss: 0.1675 - val_accuracy: 0.9630\n",
+ "Epoch 9/20\n",
+ "15/15 [==============================] - 0s 9ms/step - loss: 0.1647 - accuracy: 0.9821 - val_loss: 0.1631 - val_accuracy: 0.9608\n",
+ "Epoch 10/20\n",
+ "15/15 [==============================] - 0s 14ms/step - loss: 0.1546 - accuracy: 0.9837 - val_loss: 0.1623 - val_accuracy: 0.9574\n",
+ "Epoch 11/20\n",
+ "15/15 [==============================] - 0s 12ms/step - loss: 0.1400 - accuracy: 0.9865 - val_loss: 0.1622 - val_accuracy: 0.9552\n",
+ "Epoch 12/20\n",
+ "15/15 [==============================] - 0s 13ms/step - loss: 0.1302 - accuracy: 0.9868 - val_loss: 0.1632 - val_accuracy: 0.9552\n",
+ "Epoch 13/20\n",
+ "15/15 [==============================] - 0s 14ms/step - loss: 0.1285 - accuracy: 0.9865 - val_loss: 0.1640 - val_accuracy: 0.9540\n",
+ "Epoch 14/20\n",
+ "15/15 [==============================] - 0s 17ms/step - loss: 0.1194 - accuracy: 0.9871 - val_loss: 0.1579 - val_accuracy: 0.9552\n",
+ "Epoch 15/20\n",
+ "15/15 [==============================] - 0s 15ms/step - loss: 0.1190 - accuracy: 0.9874 - val_loss: 0.1647 - val_accuracy: 0.9518\n",
+ "Epoch 16/20\n",
+ "15/15 [==============================] - 0s 17ms/step - loss: 0.1103 - accuracy: 0.9874 - val_loss: 0.1596 - val_accuracy: 0.9563\n",
+ "Epoch 17/20\n",
+ "15/15 [==============================] - 0s 11ms/step - loss: 0.1033 - accuracy: 0.9879 - val_loss: 0.1530 - val_accuracy: 0.9585\n",
+ "Epoch 18/20\n",
+ "15/15 [==============================] - 0s 11ms/step - loss: 0.0954 - accuracy: 0.9905 - val_loss: 0.1611 - val_accuracy: 0.9552\n",
+ "Epoch 19/20\n",
+ "15/15 [==============================] - 0s 17ms/step - loss: 0.0937 - accuracy: 0.9896 - val_loss: 0.1640 - val_accuracy: 0.9552\n",
+ "Epoch 20/20\n",
+ "15/15 [==============================] - 0s 10ms/step - loss: 0.0924 - accuracy: 0.9907 - val_loss: 0.1848 - val_accuracy: 0.9484\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Train the model\n",
+ "epochs = 20\n",
+ "batch_size = 250\n",
"\n",
- "# Plot accuracy over time\n",
- "plt.plot(epoch_seq, train_accuracy, 'k--', label='Train Set')\n",
- "plt.plot(epoch_seq, test_accuracy, 'r-', label='Test Set')\n",
- "plt.title('Test Accuracy')\n",
- "plt.xlabel('Epochs')\n",
- "plt.ylabel('Accuracy')\n",
- "plt.legend(loc='upper left')\n",
- "plt.show()"
+ "history = model.fit(\n",
+ " x_train, y_train, epochs=epochs, batch_size=batch_size, validation_split=0.2\n",
+ ")"
]
},
{
- "cell_type": "markdown",
- "id": "3bc90f40",
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "e8d94dcc",
"metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHHCAYAAABDUnkqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABwoElEQVR4nO3dd3hUVeLG8e9Meg8hkIQQCL0ThEAERYpIURFUFFlWiihWLMiq/FxFdFd0bYhYsFCUVVGsawEBwUKRJr230BNqKmkz9/fHJSOhhITcSX0/zzNPZu7cOedMJiEv555iMwzDQERERKSSsJd1A0RERESspHAjIiIilYrCjYiIiFQqCjciIiJSqSjciIiISKWicCMiIiKVisKNiIiIVCoKNyIiIlKpKNyIiIhIpaJwIyKWeumll6hfvz4eHh60adOmrJsjIlWQwo1IFbZ+/XoGDBhA3bp18fX1JTo6mmuuuYY33njjksr76aefeOyxx7jiiiuYNm0azz//PAcPHuSZZ55hzZo11ja+lOzZswebzcbLL79c1k0RkSLyLOsGiEjZWLJkCd26daNOnTrcddddREZGsm/fPpYtW8brr7/OqFGjil3mzz//jN1u54MPPsDb2xuAlStXMn78eGJjY9WTIyKlQuFGpIr697//TUhICCtWrCA0NLTAc8nJyZdUZnJyMn5+fq5gIyJSFnRZSqSK2rlzJy1atDgn2ADUrFmzwOO8vDyee+45GjRogI+PD7Gxsfzf//0f2dnZrnNsNhvTpk0jIyMDm82GzWZj+vTptG/fHoDhw4cXOA7QtWtXWrZsybp16+jSpQv+/v40bNiQ2bNnA/DLL7+QkJCAn58fTZo0Yf78+QXalZiYyH333UeTJk3w8/OjevXq3HLLLezZs8d1jmEYdOvWjRo1ahQIbTk5ObRq1YoGDRqQkZFRkm8lYAa7ESNGEBERga+vL3FxccyYMeOc8z799FPatWtHUFAQwcHBtGrVitdff931fG5uLuPHj6dRo0b4+vpSvXp1rrzySubNm1fiNopUFQo3IlVU3bp1WbVqFRs2bLjouXfeeSdPP/00bdu25bXXXqNLly5MmDCB2267zXXORx99ROfOnfHx8eGjjz7io48+olmzZjz77LMAjBw50nX8qquucr3uxIkTXH/99SQkJPCf//wHHx8fbrvtNmbNmsVtt93GtddeywsvvEBGRgYDBgwgLS3N9doVK1awZMkSbrvtNiZNmsQ999zDggUL6Nq1K5mZmYAZuqZOnUpWVhb33HOP67Xjxo1j48aNTJs2jYCAgBJ9L0+dOkXXrl356KOPGDx4MC+99BIhISEMGzasQHCZN28egwYNolq1arz44ou88MILdO3alcWLF7vOeeaZZxg/fjzdunVj8uTJPPnkk9SpU4fVq1eXqI0iVYohIlXSTz/9ZHh4eBgeHh5Gx44djccee8yYO3eukZOTU+C8NWvWGIBx5513Fjg+ZswYAzB+/vln17GhQ4caAQEBBc5bsWKFARjTpk07pw1dunQxAOPjjz92HduyZYsBGHa73Vi2bJnr+Ny5c88pJzMz85wyly5dagDGhx9+WOD4lClTDMCYOXOmsWzZMsPDw8N4+OGHL/wNOm337t0GYLz00ksXPGfixImusvPl5OQYHTt2NAIDA43U1FTDMAzjoYceMoKDg428vLwLlhUXF2dcd911F22XiFyYem5EqqhrrrmGpUuXcsMNN7B27Vr+85//0KtXL6Kjo/n2229d5/3www8AjB49usDrH330UQC+//77ErUjMDCwQA9QkyZNCA0NpVmzZiQkJLiO59/ftWuX65ifn5/rfm5uLseOHaNhw4aEhoae09MxcuRIevXqxahRo7j99ttp0KABzz//fInanu+HH34gMjKSQYMGuY55eXnx4IMPkp6ezi+//AJAaGgoGRkZhV5iCg0NZePGjWzfvt2StolURQo3IlVY+/bt+fLLLzlx4gTLly9n7NixpKWlMWDAADZt2gSY41rsdjsNGzYs8NrIyEhCQ0NJTEwsURtq166NzWYrcCwkJISYmJhzjoF5GSvfqVOnePrpp4mJicHHx4fw8HBq1KjByZMnSUlJOaeuDz74gMzMTLZv38706dMLhKOSSExMpFGjRtjtBf9Jbdasmet5gPvuu4/GjRvTp08fateuzR133MGcOXMKvObZZ5/l5MmTNG7cmFatWvGPf/yDdevWWdJOkapC4UZE8Pb2pn379jz//PO8/fbb5Obm8vnnnxc45+wAYhUPD49iHTcMw3V/1KhR/Pvf/+bWW2/ls88+46effmLevHlUr14dp9N5zmsXLVrkGgS9fv16C1pfPDVr1mTNmjV8++233HDDDSxcuJA+ffowdOhQ1zlXXXUVO3fu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lD8lPDMnjzyHtVsbiIiIyPkp3LiRt6cdPy8PDCA1q/xfmuratSsPP/yw63FsbCwTJ04s9DU2m42vv/66xHVbVY6IiIjCjZuVxqWpvn370rt37/M+99tvv2Gz2Vi3bl2xy12xYgUjR44safMKeOaZZ2jTps05xw8dOkSfPn0sretsDoeDF154gaZNm+Ln50dYWBgJCQm8//77RS5j0aJF2Gw2Tp486b6GiohIiXiWdQMqu2BfL5JSs0jPzsPpNLDbbZbXMWLECG6++Wb2799P7dq1Czw3bdo04uPjad26dbHLrVGjhlVNvKjIyEi31zF+/HimTJnC5MmTiY+PJzU1lZUrV3LixAm31y0iIqVHPTdu5utlx9vDjtMwSMt2z6Wp66+/nho1ajB9+vQCx9PT0/n8888ZMWIEx44dY9CgQURHR+Pv70+rVq345JNPCi337MtS27dv56qrrsLX15fmzZszb968c17z+OOP07hxY/z9/alfvz5PPfUUublmr9X06dMZP348a9euxWazYbPZXG0++7LU+vXr6d69O35+flSvXp2RI0eSnp7uen7YsGH079+fl19+maioKKpXr87999/vqut8vv32W+677z5uueUW6tWrR1xcHCNGjGDMmDGuc5xOJxMmTKBevXr4+fkRFxfH7NmzAdizZw/dunUDoFq1athsNoYNG1bo91BEREqfem4uxjAgN/OSX24DQjxzOJqVQ1pqHiEefkV/sZc/2C7e0+Pp6cmQIUOYPn06Tz75JLbTr/n8889xOBwMGjSI9PR02rVrx+OPP05wcDDff/89t99+Ow0aNKBDhw4XrcPpdHLTTTcRERHBH3/8QUpKSoHxOfmCgoKYPn06tWrVYv369dx1110EBQXx2GOPMXDgQDZs2MCcOXOYP38+ACEhIeeUkZGRQa9evejYsSMrVqwgOTmZO++8kwceeKBAgFu4cCFRUVEsXLiQHTt2MHDgQNq0acNdd9113vcQGRnJzz//zH333XfBXqkJEyYwc+ZM3nnnHRo1asSvv/7K3//+d2rUqMGVV17JF198wc0338zWrVsJDg7Gz68Yn6eIiJQKhZuLyc2E52uVqIio07di+7+D4B1QpFPvuOMOXnrpJX755Re6du0KmJekbr75ZkJCQggJCSnQQzFq1Cjmzp3LZ599VqRwM3/+fLZs2cLcuXOpVcv8fjz//PPnjJP55z//6bofGxvLmDFj+PTTT3nsscfw8/MjMDAQT0/PQi9Dffzxx2RlZfHhhx8SEGC+/8mTJ9O3b19efPFFIiIiALP3ZPLkyXh4eNC0aVOuu+46FixYcMFw8+qrrzJgwAAiIyNp0aIFnTp1ol+/fq73kJ2dzfPPP8/8+fPp2LEjAPXr1+f3339nypQpdOnShbCwMABq1qxJaGjoRb9vIiJS+nRZqpJo2rQpnTp1YurUqQDs2LGD3377jREjRgDmYNrnnnuOVq1aERYWRmBgIHPnzmXv3r1FKn/z5s3ExMS4gg3gCgBnmjVrFldccQWRkZEEBgbyz3/+s8h1nFlXXFycK9gAXHHFFTidTrZu3eo61qJFCzw8PFyPo6KiSE5OvmC5zZs3Z8OGDSxbtow77riD5ORk+vbty5133gmY37PMzEyuueYaAgMDXbcPP/yQnTt3Fus9iIhI2VHPzcV4+Zs9KCW0/8QpTmTmEB7oTVRIES9lePkXq44RI0YwatQo3nzzTaZNm0aDBg3o0qULAC+99BKvv/46EydOpFWrVgQEBPDwww+Tk5NT3LdyQUuXLmXw4MGMHz+eXr16ERISwqeffsorr7xiWR1n8vLyKvDYZrPhdBa+npDdbqd9+/a0b9+ehx9+mJkzZ3L77bfz5JNPusb0fP/990RHRxd4nY+Pj7WNFxERt1G4uRibrciXhgoTFOzN8dwMUhx2Ir38XeNirHTrrbfy0EMP8fHHH/Phhx9y7733uupZvHgx/fr14+9//ztgjqHZtm0bzZs3L1LZzZo1Y9++fRw6dIioKPMi27Jlywqcs2TJEurWrcuTTz7pOpaYmFjgHG9vbxyOwvfaatasGdOnTycjI8PVe7N48WLsdjtNmjQpUnuLKv/9Z2Rk0Lx5c3x8fNi7d68rFJ7N29sb4KLvQUREyo4uS5WSQB9P7DYbOXlOsnLds1pxYGAgAwcOZOzYsRw6dKjATJ5GjRoxb948lixZwubNm7n77rtJSkoqctk9evSgcePGDB06lLVr1/Lbb78VCDH5dezdu5dPP/2UnTt3MmnSJL766qsC58TGxrJ7927WrFnD0aNHyc7OPqeuwYMH4+vry9ChQ9mwYQMLFy5k1KhR3H777a7xNpdiwIABvPbaa/zxxx8kJiayaNEi7r//fho3bkzTpk0JCgpizJgxPPLII8yYMYOdO3eyevVq3njjDWbMmAFA3bp1sdlsfPfddxw5cqTADC4RESkfFG5KiYfdRqCP2VGWmuW+Bf1GjBjBiRMn6NWrV4HxMf/85z9p27YtvXr1omvXrkRGRtK/f/8il2u32/nqq684deoUHTp04M477+Tf//53gXNuuOEGHnnkER544AHatGnDkiVLeOqppwqcc/PNN9O7d2+6detGjRo1zjsd3d/fn7lz53L8+HHat2/PgAEDuPrqq5k8eXLxvhln6dWrF//73//o27evK6g1bdqUn376CU9P87N57rnneOqpp5gwYQLNmjWjd+/efP/999SrVw+A6Ohoxo8fzxNPPEFERAQPPPBAidokIiLWsxmGYZR1I0pTamoqISEhpKSkEBwcXOC5rKwsdu/eTb169fD19bW87uMZOew/kYmflweNIoIsL1/KB3f/HImIVEWF/f0+m3puSlGwryc24FSug5w8baQpIiLiDgo3pcjTw46/t/svTYmIiFRlCjelrDQ20hQREanKFG5KWbCv2XOTke0gz6FLUyIiIlZTuDkPd46x9vHywNfLAwP3baQpZauKjdEXESl3FG7OkL/ibWbmpW+UWRTBvro0VZnl//ycvYKyiIiUDq1QfAYPDw9CQ0Nd+xP5+7tnJWEfWx5GXg4p6blk+tmx262vQ0qfYRhkZmaSnJxMaGhogX2vRESk9CjcnCV/t+rCNmC0wrGULBxOA0eKN75e+iNYmYSGhha667mIiLiXws1ZbDYbUVFR1KxZk9xc9102+nb+Nr5de5DrWkUxumdDt9UjpcvLy0s9NiIiZUzh5gI8PDzc+keqU5Mo3v59H1+uO8IT17fWpSkRERGLaEBxGUmoV50gH0+Opmfz576TZd0cERGRSkPhpox4e9rp1rQmAPM2FX13bhERESmcwk0ZuqZ5BAA/bTpcxi0RERGpPBRuylDXJjXw8rCx60gGO5LTy7o5IiIilYLCTRkK8vWiU4NwQJemRERErKJwU8Z0aUpERMRaCjdlLD/c/Ln3JMmpWWXcGhERkYpP4aaMRQT70iYmFID5m927KrKIiEhVoHBTDujSlIiIiHXKRbh58803iY2NxdfXl4SEBJYvX37Bc6dPn47NZitw8/X1LcXWWq9XCzPcLNlxjPTsvDJujYiISMVW5uFm1qxZjB49mnHjxrF69Wri4uLo1atX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hRsRqZJsNhtff/11WTdDRNxA4UZESt2wYcOw2Wzn3Hr37l3WTRORSsCzrBsgIlVT7969mTZtWoFjPj4+ZdQaEalM1HMjImXCx8eHyMjIArdq1aoB5iWjt99+mz59+uDn50f9+vWZPXt2gdevX7+e7t274+fnR/Xq1Rk5ciTp6ekFzpk6dSotWrTAx8eHqKgoHnjggQLPHz16lBtvvBF/f38aNWrEt99+63ruxIkTDB48mBo1auDn50ejRo3OCWMiUj4p3IhIufTUU09x8803s3btWgYPHsxtt93G5s2bAcjIyKBXr15Uq1aNFStW8PnnnzN//vwC4eXtt9/m/vvvZ+TIkaxfv55vv/2Whg0bFqhj/Pjx3Hrrraxbt45rr72WwYMHc/z4cVf9mzZt4scff2Tz5s28/fbbhIeHl943QEQuXVnv3CkiVc/QoUMNDw8PIyAgoMDt3//+t2EY5s7099xzT4HXJCQkGPfee69hGIbx7rvvGtWqVTPS09Ndz3///feG3W537QZdq1Yt48knn7xgGwDjn//8p+txenq6ARg//vijYRiG0bdvX2P48OHWvGERKVUacyMiZaJbt268/fbbBY6FhYW57nfs2LHAcx07dmTNmjUAbN68mbi4OAICAlzPX3HFFTidTrZu3YrNZuPgwYNcffXVhbahdevWrvsBAQEEBweTnJwMwL333svNN9/M6tWr6dmzJ/3796dTp06X9F5FpHQp3IhImQgICDjnMpFV/Pz8inSel5dXgcc2mw2n0wlAnz59SExM5IcffmDevHlcffXV3H///bz88suWt1dErKUxNyJSLi1btuycx82aNQOgWbNmrF27loyMDNfzixcvxm6306RJE4KCgoiNjWXBggUlakONGjUYOnQoM2fOZOLEibz77rslKk9ESod6bkSkTGRnZ3P48OECxzw9PV2Ddj///HPi4+O58sor+e9//8vy5cv54IMPABg8eDDjxo1j6NChPPPMMxw5coRRo0Zx++23ExERAcAzzzzDPffcQ82aNenTpw9paWksXryYUaNGFal9Tz/9NO3ataNFixZkZ2fz3XffucKViJRvCjciUibmzJlDVFRUgWNNmjRhy5YtgDmT6dNPP+W+++4jKiqKTz75hObNmwPg7+/P3Llzeeihh2jfvj3+/v7cfPPNvPrqq66yhg4dSlZWFq+99hpjxowhPDycAQMGFLl93t7ejB07lj179uDn50fnzp359NNPLXjnIuJuNsMwjLJuhIjImWw2G1999RX9+/cv66aISAWkMTciIiJSqSjciIiISKWiMTciUu7oarmIlIR6bkRERKRSUbgRERGRSkXhRkRERCoVhRsRERGpVBRuREREpFJRuBEREZFKReFGREREKhWFGxEREalUFG5ERESkUvl/si3q3HgHsLMAAAAASUVORK5CYII=",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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+uorHD16FI6OjoiKikJJSUmV+zT0b95UqjvX4uJiHD9+HHPnzsXx48exefNmJCQk4Nlnn33ofg35WzClh322ANCvXz+92tevX1/tPi3xswWgd47p6elYtWoVJBIJhg4dWu1+zfWzrTcCGVXXrl2FqVOn6l6rVCrBz89PiImJqXT9YcOGCU8//bTesoiICOGll16q1zqNLSsrSwAg/PXXX1Wus3r1asHV1dV0RRnJ/PnzhfDw8Bqv31A+U63XX39daNasmaBWqyt931I/VwDCli1bdK/VarXg4+MjLF68WLcsNzdXkMvlwvr166vcj6F/82J48Fwrc+zYMQGAcO3atSrXMfRvQSyVne/YsWOFgQMHGrSfhvLZDhw4UHjyySerXcdSPltjYguQEZWVlSE+Ph6RkZG6ZVKpFJGRkTh8+HCl2xw+fFhvfQCIioqqcn1zlZeXBwBwd3evdr3CwkIEBgYiICAAAwcOxLlz50xRXp0lJibCz88PISEhGDVqFFJSUqpct6F8poDmd/qHH37AhAkTqr0xsKV+rvdLTk5GRkaG3mfn6uqKiIiIKj+72vzNm6u8vDxIJBK4ublVu54hfwvmZu/evfDy8kJoaCimTJmCmzdvVrluQ/lsMzMzsW3bNkycOPGh61ryZ1sbDEBGlJOTA5VKBW9vb73l3t7eyMjIqHSbjIwMg9Y3R2q1GtOnT0ePHj3wyCOPVLleaGgoVq1ahf/973/44YcfoFar0b17d9y4ccOE1RouIiICa9aswY4dO7BixQokJyejV69eKCgoqHT9hvCZam3duhW5ubkYN25cletY6uf6IO3nY8hnV5u/eXNUUlKCt956CyNHjqz2RpmG/i2Yk379+uG7775DXFwcPvzwQ/z111/o378/VCpVpes3lM927dq1cHZ2xpAhQ6pdz5I/29ri3eCpzqZOnYqzZ88+tL+4W7du6Natm+519+7d0apVK3z99dd477336rvMWuvfv7/uebt27RAREYHAwED89NNPNfq/Kku2cuVK9O/fH35+flWuY6mfK2kolUoMGzYMgiBgxYoV1a5ryX8LI0aM0D1v27Yt2rVrh2bNmmHv3r146qmnRKysfq1atQqjRo166IUJlvzZ1hZbgIzIw8MDMpkMmZmZesszMzPh4+NT6TY+Pj4GrW9upk2bht9//x179uxBkyZNDNrW1tYW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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
"source": [
- "## Your turn! 🚀\n",
+ "# Plot loss and accuracy over time\n",
+ "plt.plot(history.history[\"loss\"], label=\"Train Set\")\n",
+ "plt.plot(history.history[\"val_loss\"], label=\"Validation Set\")\n",
+ "plt.title(\"Softmax Loss\")\n",
+ "plt.xlabel(\"Epochs\")\n",
+ "plt.ylabel(\"Softmax Loss\")\n",
+ "plt.legend(loc=\"upper left\")\n",
+ "plt.show()\n",
"\n",
- "Practice the Recurrent Neural Networks by following this TBD."
+ "plt.plot(history.history[\"accuracy\"], label=\"Train Set\")\n",
+ "plt.plot(history.history[\"val_accuracy\"], label=\"Validation Set\")\n",
+ "plt.title(\"Test Accuracy\")\n",
+ "plt.xlabel(\"Epochs\")\n",
+ "plt.ylabel(\"Accuracy\")\n",
+ "plt.legend(loc=\"upper left\")\n",
+ "plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "863d18f5",
+ "id": "3bc90f40",
"metadata": {},
"source": [
- "## Self study\n",
+ "## Your turn! 🚀\n",
"\n",
- "TBD"
+ "You can practice your rnn skills by following the assignment [google stock price prediction rnn](../assignments/deep-learning/rnn/google-stock-price-prediction-rnn.ipynb)"
]
},
{
@@ -488,7 +518,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.13"
+ "version": "3.9.18"
}
},
"nbformat": 4,
diff --git a/_sources/deep-learning/time-series.ipynb b/_sources/deep-learning/time-series.ipynb
index 2947c75e1b..35bd8f304b 100644
--- a/_sources/deep-learning/time-series.ipynb
+++ b/_sources/deep-learning/time-series.ipynb
@@ -1700,12 +1700,18 @@
"\n",
"## Your turn! 🚀\n",
"\n",
- "TBD.\n",
+ "You can practice your time series skills by following the assignment [time series forecasting assignment](../assignments/deep-learning/time-series-forecasting-assignment.ipynb)\n",
"\n",
"## Acknowledgments\n",
"\n",
"Thanks to [kaggle](https://www.kaggle.com/) for creating the open-source course [Time Series](https://www.kaggle.com/learn/time-series). It inspires the majority of the content in this chapter.\n"
]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f258c933",
+ "metadata": {},
+ "source": []
}
],
"metadata": {
diff --git a/assignments/README.html b/assignments/README.html
index 96b07d8a02..91b898373f 100644
--- a/assignments/README.html
+++ b/assignments/README.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/analyzing-COVID-19-papers.html b/assignments/data-science/analyzing-COVID-19-papers.html
index 6453757aca..1aa79f0cf0 100644
--- a/assignments/data-science/analyzing-COVID-19-papers.html
+++ b/assignments/data-science/analyzing-COVID-19-papers.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/analyzing-data.html b/assignments/data-science/analyzing-data.html
index 77a97545c8..17478978d9 100644
--- a/assignments/data-science/analyzing-data.html
+++ b/assignments/data-science/analyzing-data.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/analyzing-text-about-data-science.html b/assignments/data-science/analyzing-text-about-data-science.html
index 3ce31fb077..96c3b63814 100644
--- a/assignments/data-science/analyzing-text-about-data-science.html
+++ b/assignments/data-science/analyzing-text-about-data-science.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/apply-your-skills.html b/assignments/data-science/apply-your-skills.html
index 8300aa9569..4117ee79bb 100644
--- a/assignments/data-science/apply-your-skills.html
+++ b/assignments/data-science/apply-your-skills.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/build-your-own-custom-vis.html b/assignments/data-science/build-your-own-custom-vis.html
index 702a95fe68..a5e53858c3 100644
--- a/assignments/data-science/build-your-own-custom-vis.html
+++ b/assignments/data-science/build-your-own-custom-vis.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/classifying-datasets.html b/assignments/data-science/classifying-datasets.html
index 505dca5f30..c9860e3f46 100644
--- a/assignments/data-science/classifying-datasets.html
+++ b/assignments/data-science/classifying-datasets.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/data-preparation.html b/assignments/data-science/data-preparation.html
index 196b614e7e..e8501dbc15 100644
--- a/assignments/data-science/data-preparation.html
+++ b/assignments/data-science/data-preparation.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/data-processing-in-python.html b/assignments/data-science/data-processing-in-python.html
index 66f846f4cc..bf225e8b7d 100644
--- a/assignments/data-science/data-processing-in-python.html
+++ b/assignments/data-science/data-processing-in-python.html
@@ -27,8 +27,8 @@
-
+
@@ -1112,114 +1112,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/data-science-in-the-cloud-the-azure-ml-sdk-way.html b/assignments/data-science/data-science-in-the-cloud-the-azure-ml-sdk-way.html
index e2b91df6a4..3bded09c9a 100644
--- a/assignments/data-science/data-science-in-the-cloud-the-azure-ml-sdk-way.html
+++ b/assignments/data-science/data-science-in-the-cloud-the-azure-ml-sdk-way.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/data-science-project-using-azure-ml-sdk.html b/assignments/data-science/data-science-project-using-azure-ml-sdk.html
index 8b6f850f49..ea2aa35f57 100644
--- a/assignments/data-science/data-science-project-using-azure-ml-sdk.html
+++ b/assignments/data-science/data-science-project-using-azure-ml-sdk.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/data-science-scenarios.html b/assignments/data-science/data-science-scenarios.html
index cde8054331..46e17dc79c 100644
--- a/assignments/data-science/data-science-scenarios.html
+++ b/assignments/data-science/data-science-scenarios.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/displaying-airport-data.html b/assignments/data-science/displaying-airport-data.html
index d4111b697b..6192f3ae34 100644
--- a/assignments/data-science/displaying-airport-data.html
+++ b/assignments/data-science/displaying-airport-data.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/dive-into-the-beehive.html b/assignments/data-science/dive-into-the-beehive.html
index a111204f8e..a49b073d70 100644
--- a/assignments/data-science/dive-into-the-beehive.html
+++ b/assignments/data-science/dive-into-the-beehive.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/estimation-of-COVID-19-pandemic.html b/assignments/data-science/estimation-of-COVID-19-pandemic.html
index e23cbfe4fe..210cd96cba 100644
--- a/assignments/data-science/estimation-of-COVID-19-pandemic.html
+++ b/assignments/data-science/estimation-of-COVID-19-pandemic.html
@@ -27,8 +27,8 @@
-
+
@@ -1112,114 +1112,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/evaluating-data-from-a-form.html b/assignments/data-science/evaluating-data-from-a-form.html
index 452a1ef790..3808cbebf7 100644
--- a/assignments/data-science/evaluating-data-from-a-form.html
+++ b/assignments/data-science/evaluating-data-from-a-form.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/explore-a-planetary-computer-dataset.html b/assignments/data-science/explore-a-planetary-computer-dataset.html
index 4037597907..940ddfa9d9 100644
--- a/assignments/data-science/explore-a-planetary-computer-dataset.html
+++ b/assignments/data-science/explore-a-planetary-computer-dataset.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/exploring-for-anwser.html b/assignments/data-science/exploring-for-anwser.html
index f3b9503a79..fb2cf956ff 100644
--- a/assignments/data-science/exploring-for-anwser.html
+++ b/assignments/data-science/exploring-for-anwser.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/introduction-to-statistics-and-probability.html b/assignments/data-science/introduction-to-statistics-and-probability.html
index f7feddab58..ac31c813a9 100644
--- a/assignments/data-science/introduction-to-statistics-and-probability.html
+++ b/assignments/data-science/introduction-to-statistics-and-probability.html
@@ -27,8 +27,8 @@
-
+
@@ -1112,114 +1112,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/lines-scatters-and-bars.html b/assignments/data-science/lines-scatters-and-bars.html
index d157d06026..7a0c566b42 100644
--- a/assignments/data-science/lines-scatters-and-bars.html
+++ b/assignments/data-science/lines-scatters-and-bars.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/low-code-no-code-data-science-project-on-azure-ml.html b/assignments/data-science/low-code-no-code-data-science-project-on-azure-ml.html
index 1f7222a1b0..1645c2560b 100644
--- a/assignments/data-science/low-code-no-code-data-science-project-on-azure-ml.html
+++ b/assignments/data-science/low-code-no-code-data-science-project-on-azure-ml.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/market-research.html b/assignments/data-science/market-research.html
index fae414a259..fad34f25f6 100644
--- a/assignments/data-science/market-research.html
+++ b/assignments/data-science/market-research.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/matplotlib-applied.html b/assignments/data-science/matplotlib-applied.html
index 772e3ae76a..450d44a205 100644
--- a/assignments/data-science/matplotlib-applied.html
+++ b/assignments/data-science/matplotlib-applied.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/nyc-taxi-data-in-winter-and-summer.html b/assignments/data-science/nyc-taxi-data-in-winter-and-summer.html
index 09e96c6e8c..c9a1a493aa 100644
--- a/assignments/data-science/nyc-taxi-data-in-winter-and-summer.html
+++ b/assignments/data-science/nyc-taxi-data-in-winter-and-summer.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/small-diabetes-study.html b/assignments/data-science/small-diabetes-study.html
index 393a1a7bfb..d89a37a0e2 100644
--- a/assignments/data-science/small-diabetes-study.html
+++ b/assignments/data-science/small-diabetes-study.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/soda-profits.html b/assignments/data-science/soda-profits.html
index 781f096a1d..5732e0d8d7 100644
--- a/assignments/data-science/soda-profits.html
+++ b/assignments/data-science/soda-profits.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/tell-a-story.html b/assignments/data-science/tell-a-story.html
index 92afd1d949..e89a7530ca 100644
--- a/assignments/data-science/tell-a-story.html
+++ b/assignments/data-science/tell-a-story.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/try-it-in-excel.html b/assignments/data-science/try-it-in-excel.html
index 8f741a6da6..03bafa4f22 100644
--- a/assignments/data-science/try-it-in-excel.html
+++ b/assignments/data-science/try-it-in-excel.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/data-science/write-a-data-ethics-case-study.html b/assignments/data-science/write-a-data-ethics-case-study.html
index 17e93fcf77..7e819dfdc0 100644
--- a/assignments/data-science/write-a-data-ethics-case-study.html
+++ b/assignments/data-science/write-a-data-ethics-case-study.html
@@ -27,8 +27,8 @@
-
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
diff --git a/assignments/deep-learning/autoencoder/autoencoder.html b/assignments/deep-learning/autoencoder/autoencoder.html
index e42ae9eeeb..f81f57c752 100644
--- a/assignments/deep-learning/autoencoder/autoencoder.html
+++ b/assignments/deep-learning/autoencoder/autoencoder.html
@@ -6,7 +6,7 @@
- 40.104. Intro to Autoencoders — Ocademy Open Machine Learning Book
+ 40.106. Intro to Autoencoders — Ocademy Open Machine Learning Book
@@ -27,8 +27,8 @@
-
+
@@ -98,8 +98,8 @@
-
-
+
+
@@ -1110,114 +1110,134 @@ Ocademy Open Machine Learning Book
40.88. Case Study: Debugging in Regression
+
+
+ 40.89. Introduction
+
+
- 40.89. Study the solvers
+ 40.90. Study the solvers
- 40.90. Build classification models
+ 40.91. Build classification models
- 40.91. Build Classification Model
+ 40.92. Build Classification Model
- 40.92. Parameter play
+ 40.93. Parameter play
- 40.93. How to choose cnn architecture mnist
+ 40.94. How to choose cnn architecture mnist
- 40.95. Sign Language Digits Classification with CNN
+ 40.96. Sign Language Digits Classification with CNN
- 40.97. Object Recognition in Images using CNN
+ 40.98. Object Recognition in Images using CNN
+
+
+
+
+ 40.99. Image classification
- 40.98. Intro to TensorFlow for Deep Learning
+ 40.100. Intro to TensorFlow for Deep Learning
- 40.100. Bitcoin LSTM Model with Tweet Volume and Sentiment
+ 40.102. Bitcoin LSTM Model with Tweet Volume and Sentiment
- 40.102. Google Stock Price Prediction RNN
+ 40.104. Google Stock Price Prediction RNN
- 40.104. Intro to Autoencoders
+ 40.106. Intro to Autoencoders
- 40.105. Base/Denoising Autoencoder & Dimension Reduction
+ 40.107. Base/Denoising Autoencoder & Dimension Reduction
- 40.106. Fun with Variational Autoencoders
+ 40.108. Fun with Variational Autoencoders
- 40.107. Time Series Forecasting Assignment
+ 40.109. Time Series Forecasting Assignment
- 40.109. Neural Networks for Classification with TensorFlow
+ 40.111. Neural Networks for Classification with TensorFlow
- 40.110. NN Classify 15 Fruits Assignment
+ 40.112. NN Classify 15 Fruits Assignment
- 40.115. DQN On Foreign Exchange Market
+ 40.117. DQN On Foreign Exchange Market
- 40.116. Art by gan
+ 40.118. Art by gan
- 40.118. Generative Adversarial Networks (GANs)
+ 40.120. Generative Adversarial Networks (GANs)
+
+
+
+
+ 40.121. Comparing edge-based and region-based segmentation
- 40.119. Summary
+ 40.122. Summary
- 40.120. Car Object Detection
+ 40.123. Car Object Detection
- 40.122. Basic classification: Classify images of clothing
+ 40.125. Basic classification: Classify images of clothing
+
+
+
+
+ 40.126. Getting Start NLP with classification task
@@ -1600,71 +1620,71 @@ Ocademy Open Machine Learning Book
@@ -1688,71 +1708,71 @@ Contents
@@ -1766,12 +1786,12 @@ Contents