Files
mrdbourke--pytorch-deep-lea…/extras/exercises/02_pytorch_classification_exercises.ipynb
T
wehub-resource-sync 37c25cd088
make_docs / deploy (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:27:58 +08:00

641 lines
58 KiB
Plaintext

{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "02_pytorch_classification_exercises.ipynb",
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyNloicnciRwCXd2bJo6F2iS",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/mrdbourke/pytorch-deep-learning/blob/main/extras/exercises/02_pytorch_classification_exercises.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"# 02. PyTorch Classification Exercises\n",
"\n",
"The following is a template for 02. PyTorch Classification exercises.\n",
"\n",
"It's only starter code and it's your job to fill in the blanks.\n",
"\n",
"Because of the flexibility of PyTorch, there may be more than one way to answer the question.\n",
"\n",
"Don't worry about trying to be *right* just try writing code that suffices the question.\n",
"\n",
"## Resources\n",
"* These exercises are based on [notebook 02 of the learn PyTorch course](https://www.learnpytorch.io/02_pytorch_classification/).\n",
"* You can see one form of [solutions on GitHub](https://github.com/mrdbourke/pytorch-deep-learning/tree/main/extras/solutions) (but try the exercises below yourself first!)."
],
"metadata": {
"id": "ZKJFt7YxH8yl"
}
},
{
"cell_type": "code",
"source": [
"# Import torch\n",
"import torch\n",
"\n",
"# Setup device agnostic code\n",
"\n",
"\n",
"# Setup random seed\n",
"RANDOM_SEED = 42"
],
"metadata": {
"id": "CSrUPgapO0tf"
},
"execution_count": 1,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## 1. Make a binary classification dataset with Scikit-Learn's [`make_moons()`](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_moons.html) function.\n",
" * For consistency, the dataset should have 1000 samples and a `random_state=42`.\n",
" * Turn the data into PyTorch tensors. \n",
" * Split the data into training and test sets using `train_test_split` with 80% training and 20% testing."
],
"metadata": {
"id": "pH7jIZ2SPFee"
}
},
{
"cell_type": "code",
"source": [
"# Create a dataset with Scikit-Learn's make_moons()\n",
"from sklearn.datasets import make_moons"
],
"metadata": {
"id": "5t4VhPV1PX1X"
},
"execution_count": 2,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Turn data into a DataFrame\n",
"import pandas as pd\n"
],
"metadata": {
"id": "SUeHZ3-3P9C7"
},
"execution_count": 3,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Visualize the data on a scatter plot\n",
"import matplotlib.pyplot as plt\n"
],
"metadata": {
"id": "owrkPSFvQPFI"
},
"execution_count": 4,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Turn data into tensors of dtype float\n",
"\n",
"\n",
"# Split the data into train and test sets (80% train, 20% test)\n",
"from sklearn.model_selection import train_test_split\n"
],
"metadata": {
"id": "bDhyHn9fR4dq"
},
"execution_count": 5,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## 2. Build a model by subclassing `nn.Module` that incorporates non-linear activation functions and is capable of fitting the data you created in 1.\n",
" * Feel free to use any combination of PyTorch layers (linear and non-linear) you want."
],
"metadata": {
"id": "cMIjxZdzQfPz"
}
},
{
"cell_type": "code",
"source": [
"import torch\n",
"from torch import nn\n",
"\n",
"# Inherit from nn.Module to make a model capable of fitting the mooon data\n",
"class MoonModelV0(nn.Module):\n",
" ## Your code here ##\n",
"\n",
" def forward(self, x):\n",
" ## Your code here ##\n",
" return \n",
"\n",
"# Instantiate the model\n",
"## Your code here ##"
],
"metadata": {
"id": "hwtyvm34Ri6Q"
},
"execution_count": 6,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## 3. Setup a binary classification compatible loss function and optimizer to use when training the model built in 2."
],
"metadata": {
"id": "DSj97RwyVeFE"
}
},
{
"cell_type": "code",
"source": [
"# Setup loss function\n",
"\n",
"# Setup optimizer to optimize model's parameters"
],
"metadata": {
"id": "whSGw5qgVvxU"
},
"execution_count": 7,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## 4. Create a training and testing loop to fit the model you created in 2 to the data you created in 1.\n",
" * Do a forward pass of the model to see what's coming out in the form of logits, prediction probabilities and labels.\n",
" * To measure model accuray, you can create your own accuracy function or use the accuracy function in [TorchMetrics](https://torchmetrics.readthedocs.io/en/latest/).\n",
" * Train the model for long enough for it to reach over 96% accuracy.\n",
" * The training loop should output progress every 10 epochs of the model's training and test set loss and accuracy."
],
"metadata": {
"id": "nvk4PfNTWUAt"
}
},
{
"cell_type": "code",
"source": [
"# What's coming out of our model?\n",
"\n",
"# logits (raw outputs of model)\n",
"print(\"Logits:\")\n",
"## Your code here ##\n",
"\n",
"# Prediction probabilities\n",
"print(\"Pred probs:\")\n",
"## Your code here ##\n",
"\n",
"# Prediction labels\n",
"print(\"Pred labels:\")\n",
"## Your code here ##"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AgnFdlamd2-D",
"outputId": "627d8c33-071e-4925-f18b-5d5ba6126729"
},
"execution_count": 8,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Logits:\n",
"Pred probs:\n",
"Pred labels:\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"# Let's calculuate the accuracy using accuracy from TorchMetrics\n",
"!pip -q install torchmetrics # Colab doesn't come with torchmetrics\n",
"from torchmetrics import Accuracy\n",
"\n",
"## TODO: Uncomment this code to use the Accuracy function\n",
"# acc_fn = Accuracy(task=\"multiclass\", num_classes=2).to(device) # send accuracy function to device\n",
"# acc_fn"
],
"metadata": {
"id": "rUSDNHB4euoJ"
},
"execution_count": 9,
"outputs": []
},
{
"cell_type": "code",
"source": [
"## TODO: Uncomment this to set the seed\n",
"# torch.manual_seed(RANDOM_SEED)\n",
"\n",
"# Setup epochs\n",
"\n",
"\n",
"# Send data to the device\n",
"\n",
"\n",
"# Loop through the data\n",
"# for epoch in range(epochs):\n",
" ### Training\n",
" \n",
"\n",
" # 1. Forward pass (logits output)\n",
" \n",
" # Turn logits into prediction probabilities\n",
" \n",
"\n",
" # Turn prediction probabilities into prediction labels\n",
" \n",
"\n",
" # 2. Calculaute the loss\n",
" # loss = loss_fn(y_logits, y_train) # loss = compare model raw outputs to desired model outputs\n",
"\n",
" # Calculate the accuracy\n",
" # acc = acc_fn(y_pred, y_train.int()) # the accuracy function needs to compare pred labels (not logits) with actual labels\n",
"\n",
" # 3. Zero the gradients\n",
" \n",
"\n",
" # 4. Loss backward (perform backpropagation) - https://brilliant.org/wiki/backpropagation/#:~:text=Backpropagation%2C%20short%20for%20%22backward%20propagation,to%20the%20neural%20network's%20weights.\n",
" \n",
" # 5. Step the optimizer (gradient descent) - https://towardsdatascience.com/gradient-descent-algorithm-a-deep-dive-cf04e8115f21#:~:text=Gradient%20descent%20(GD)%20is%20an,e.g.%20in%20a%20linear%20regression) \n",
" \n",
"\n",
" ### Testing\n",
" # model_0.eval() \n",
" # with torch.inference_mode():\n",
" # 1. Forward pass (to get the logits)\n",
" \n",
" # Turn the test logits into prediction labels\n",
" \n",
"\n",
" # 2. Caculate the test loss/acc\n",
" \n",
"\n",
" # Print out what's happening every 100 epochs\n",
" # if epoch % 100 == 0:\n",
" "
],
"metadata": {
"id": "SHBY3h7XXnxt"
},
"execution_count": 10,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## 5. Make predictions with your trained model and plot them using the `plot_decision_boundary()` function created in this notebook."
],
"metadata": {
"id": "8Nwihtomj9JO"
}
},
{
"cell_type": "code",
"source": [
"# Plot the model predictions\n",
"import numpy as np\n",
"\n",
"def plot_decision_boundary(model, X, y):\n",
" \n",
" # Put everything to CPU (works better with NumPy + Matplotlib)\n",
" model.to(\"cpu\")\n",
" X, y = X.to(\"cpu\"), y.to(\"cpu\")\n",
"\n",
" # Source - https://madewithml.com/courses/foundations/neural-networks/ \n",
" # (with modifications)\n",
" x_min, x_max = X[:, 0].min() - 0.1, X[:, 0].max() + 0.1\n",
" y_min, y_max = X[:, 1].min() - 0.1, X[:, 1].max() + 0.1\n",
" xx, yy = np.meshgrid(np.linspace(x_min, x_max, 101), \n",
" np.linspace(y_min, y_max, 101))\n",
"\n",
" # Make features\n",
" X_to_pred_on = torch.from_numpy(np.column_stack((xx.ravel(), yy.ravel()))).float()\n",
"\n",
" # Make predictions\n",
" model.eval()\n",
" with torch.inference_mode():\n",
" y_logits = model(X_to_pred_on)\n",
"\n",
" # Test for multi-class or binary and adjust logits to prediction labels\n",
" if len(torch.unique(y)) > 2:\n",
" y_pred = torch.softmax(y_logits, dim=1).argmax(dim=1) # mutli-class\n",
" else: \n",
" y_pred = torch.round(torch.sigmoid(y_logits)) # binary\n",
" \n",
" # Reshape preds and plot\n",
" y_pred = y_pred.reshape(xx.shape).detach().numpy()\n",
" plt.contourf(xx, yy, y_pred, cmap=plt.cm.RdYlBu, alpha=0.7)\n",
" plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.RdYlBu)\n",
" plt.xlim(xx.min(), xx.max())\n",
" plt.ylim(yy.min(), yy.max())"
],
"metadata": {
"id": "0YRzatb8a1P2"
},
"execution_count": 11,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Plot decision boundaries for training and test sets\n"
],
"metadata": {
"id": "PMrcpyirig1d"
},
"execution_count": 12,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## 6. Replicate the Tanh (hyperbolic tangent) activation function in pure PyTorch.\n",
" * Feel free to reference the [ML cheatsheet website](https://ml-cheatsheet.readthedocs.io/en/latest/activation_functions.html#tanh) for the formula."
],
"metadata": {
"id": "EtMYBvtciiAU"
}
},
{
"cell_type": "code",
"source": [
"# Create a straight line tensor\n"
],
"metadata": {
"id": "BlXaWC5TkEUE"
},
"execution_count": 13,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Test torch.tanh() on the tensor and plot it\n"
],
"metadata": {
"id": "vZPCcQmIkZjO"
},
"execution_count": 14,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Replicate torch.tanh() and plot it\n"
],
"metadata": {
"id": "J-ne__Kjkdc1"
},
"execution_count": 15,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## 7. Create a multi-class dataset using the [spirals data creation function from CS231n](https://cs231n.github.io/neural-networks-case-study/) (see below for the code).\n",
" * Split the data into training and test sets (80% train, 20% test) as well as turn it into PyTorch tensors.\n",
" * Construct a model capable of fitting the data (you may need a combination of linear and non-linear layers).\n",
" * Build a loss function and optimizer capable of handling multi-class data (optional extension: use the Adam optimizer instead of SGD, you may have to experiment with different values of the learning rate to get it working).\n",
" * Make a training and testing loop for the multi-class data and train a model on it to reach over 95% testing accuracy (you can use any accuracy measuring function here that you like) - 1000 epochs should be plenty.\n",
" * Plot the decision boundaries on the spirals dataset from your model predictions, the `plot_decision_boundary()` function should work for this dataset too."
],
"metadata": {
"id": "Lbt1bNcWk5G9"
}
},
{
"cell_type": "code",
"source": [
"# Code for creating a spiral dataset from CS231n\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"RANDOM_SEED = 42\n",
"np.random.seed(RANDOM_SEED)\n",
"N = 100 # number of points per class\n",
"D = 2 # dimensionality\n",
"K = 3 # number of classes\n",
"X = np.zeros((N*K,D)) # data matrix (each row = single example)\n",
"y = np.zeros(N*K, dtype='uint8') # class labels\n",
"for j in range(K):\n",
" ix = range(N*j,N*(j+1))\n",
" r = np.linspace(0.0,1,N) # radius\n",
" t = np.linspace(j*4,(j+1)*4,N) + np.random.randn(N)*0.2 # theta\n",
" X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]\n",
" y[ix] = j\n",
"# lets visualize the data\n",
"plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.RdYlBu)\n",
"plt.show()"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 265
},
"id": "tU-UNZsKlJls",
"outputId": "8b7b745a-070d-4ecb-c639-c4ee4d8eae06"
},
"execution_count": 16,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"source": [
"# Turn data into tensors\n",
"import torch\n",
"X = torch.from_numpy(X).type(torch.float) # features as float32\n",
"y = torch.from_numpy(y).type(torch.LongTensor) # labels need to be of type long\n",
"\n",
"# Create train and test splits\n",
"from sklearn.model_selection import train_test_split\n"
],
"metadata": {
"id": "OWVrmkEyl0VP"
},
"execution_count": 17,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Let's calculuate the accuracy for when we fit our model\n",
"!pip -q install torchmetrics # colab doesn't come with torchmetrics\n",
"from torchmetrics import Accuracy\n",
"\n",
"## TODO: uncomment the two lines below to send the accuracy function to the device\n",
"# acc_fn = Accuracy(task=\"multiclass\", num_classes=4).to(device)\n",
"# acc_fn"
],
"metadata": {
"id": "a-v-7f0op0tG"
},
"execution_count": 18,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Prepare device agnostic code\n",
"# device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
"\n",
"# Create model by subclassing nn.Module\n",
"\n",
"\n",
"\n",
"# Instantiate model and send it to device\n"
],
"metadata": {
"id": "DB3u3ldumapf"
},
"execution_count": 19,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Setup data to be device agnostic\n",
"\n",
"\n",
"# Print out first 10 untrained model outputs (forward pass)\n",
"print(\"Logits:\")\n",
"## Your code here ##\n",
"\n",
"print(\"Pred probs:\")\n",
"## Your code here ##\n",
"\n",
"print(\"Pred labels:\")\n",
"## Your code here ##"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "QE7XWSSunMTS",
"outputId": "00b31909-87c9-41e3-9dbb-fb4c4bd3aabd"
},
"execution_count": 20,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Logits:\n",
"Pred probs:\n",
"Pred labels:\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"# Setup loss function and optimizer\n",
"# loss_fn =\n",
"# optimizer = "
],
"metadata": {
"id": "54EqLRKLo0AW"
},
"execution_count": 21,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Build a training loop for the model\n",
"\n",
"# Loop over data\n",
"\n",
"\n",
" ## Training\n",
" \n",
" # 1. Forward pass\n",
" \n",
"\n",
" # 2. Calculate the loss\n",
" \n",
" \n",
" # 3. Optimizer zero grad\n",
" \n",
"\n",
" # 4. Loss backward\n",
" \n",
"\n",
" # 5. Optimizer step\n",
" \n",
"\n",
" ## Testing\n",
" \n",
"\n",
" # 1. Forward pass\n",
" \n",
" # 2. Caculate loss and acc\n",
" \n",
" # Print out what's happening every 100 epochs\n",
" "
],
"metadata": {
"id": "vIlExkUHnmxi"
},
"execution_count": 22,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Plot decision boundaries for training and test sets\n"
],
"metadata": {
"id": "JrwVRbaE0keT"
},
"execution_count": 23,
"outputs": []
}
]
}