641 lines
58 KiB
Plaintext
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": []
|
|
}
|
|
]
|
|
}
|