diff --git a/generated.tf b/generated.tf index 7670a987d4..476aca9e43 100644 --- a/generated.tf +++ b/generated.tf @@ -1233,11 +1233,6 @@ module "pytorch" { target_repository = "${var.target_repository}/pytorch" } -module "pytorch-cuda12" { - source = "./images/pytorch-cuda12" - target_repository = "${var.target_repository}/pytorch-cuda12" -} - module "qdrant" { source = "./images/qdrant" target_repository = "${var.target_repository}/qdrant" @@ -2603,10 +2598,6 @@ output "summary_pytorch" { value = module.pytorch.summary } -output "summary_pytorch-cuda12" { - value = module.pytorch-cuda12.summary -} - output "summary_qdrant" { value = module.qdrant.summary } diff --git a/images/jenkins/tests/controller/main.tf b/images/jenkins/tests/controller/main.tf index 3cf2b0f3e3..fd2cebc711 100644 --- a/images/jenkins/tests/controller/main.tf +++ b/images/jenkins/tests/controller/main.tf @@ -24,12 +24,18 @@ variable "values" { } } +variable "helm_chart_version" { + type = string + default = "" +} + module "helm" { source = "../../../../tflib/imagetest/helm" - namespace = "jenkins" - chart = "jenkins" - repo = "https://charts.jenkins.io" + namespace = "jenkins" + chart = "jenkins" + repo = "https://charts.jenkins.io" + chart_version = var.helm_chart_version values = var.values } diff --git a/images/jenkins/tests/main.tf b/images/jenkins/tests/main.tf index b18a8cfb65..cc1a75d78d 100644 --- a/images/jenkins/tests/main.tf +++ b/images/jenkins/tests/main.tf @@ -13,6 +13,11 @@ variable "digest" { description = "The image digest to run tests over." } +variable "helm_chart_version" { + type = string + default = "" +} + locals { parsed = provider::oci::parse(var.digest) } data "imagetest_inventory" "this" {} @@ -32,7 +37,8 @@ resource "imagetest_harness_k3s" "this" { } module "helm_controller" { - source = "./controller" + source = "./controller" + helm_chart_version = var.helm_chart_version values = { namespace = local.namespace fullnameOverride = local.namespace diff --git a/images/pytorch-cuda12/README.md b/images/pytorch-cuda12/README.md deleted file mode 100644 index e5b0a141f1..0000000000 --- a/images/pytorch-cuda12/README.md +++ /dev/null @@ -1,128 +0,0 @@ - -# pytorch-cuda12 -| | | -| - | - | -| **OCI Reference** | `cgr.dev/chainguard/pytorch-cuda12` | - - -* [View Image in the Chainguard Images Directory](https://images.chainguard.dev/directory/image/pytorch-cuda12/overview). -* [View the Image Catalog](https://console.chainguard.dev/images/catalog) for a full list of available tags. -* [Contact Chainguard](https://www.chainguard.dev/chainguard-images) for enterprise support, SLAs, and access to older tags. - ---- - - - -# Chainguard Image for pytorch-cuda12 - -A minimal, [wolfi](https://github.com/wolfi-dev)-based image for pytorch, a Python package that provides two high-level features: Tensor computation with strong GPU acceleration and Deep neural networks built on a tape-based autograd system. - - -Chainguard Images are regularly-updated, minimal container images with low-to-zero CVEs. - - - -## Download this Image -This image is available on `cgr.dev`: - -``` -docker pull cgr.dev/ORGANIZATION/pytorch-cuda12:latest -``` - -Be sure to replace the `ORGANIZATION` placeholder with the name used for your organization's private repository within the Chainguard registry. - - - - -## Running pytorch-cuda12 - -PyTorch has some prerequisites which need to be configured in the environment -prior to running with GPUs. For examples, please refer to [TESTING.md](https://github.com/chainguard-images/images/blob/main/images/pytorch-cuda12/TESTING.md). - -Additionally, please refer to the [upstream documentation](https://github.com/pytorch/pytorch) -for more information on configuring and using PyTorch. - -Assuming the environment prerequisites have been met, below demonstrates how -to launch the container: - -```bash -docker run --rm -i -t \ - --privileged \ - --gpus all \ - cgr.dev/chainguard/pytorch:latest -``` - -## Testing GPU Access - -If your environment has connected GPUs, you can check that PyTorch has access with the following: - -```bash -docker run --rm -it --gpus all cgr.dev/chainguard/pytorch-cuda12:latest -Python 3.11.9 (main, Apr 2 2024, 15:40:32) [GCC 13.2.0] on linux -Type "help", "copyright", "credits" or "license" for more information. ->>> import torch ->>> torch.cuda.is_available() -True ->>> torch.cuda.device_count() -1 ->>> torch.cuda.get_device_name(0) -'Tesla V100-SXM2-16GB' -``` - -## Testing PyTorch - -As a quick intro, we will use PyTorch to create a very simple deep learning model with two linear layers and an activation function. We’ll create an instance of it and ask it to report on its parameters. Running the below will fetch a [model_builder.py](https://github.com/chainguard-images/images/blob/main/images/pytorch-cuda12/model_builder.py) script from the Chainguard Images repository, place it in a folder on your host machine, and run the script in a pytorch-cuda12 container from a volume. - -```bash -mkdir pytorch-test &&\ - curl https://raw.githubusercontent.com/chainguard-images/images/main/images/pytorch-cuda12/model_builder.py > pytorch-test/model_builder.py &&\ - docker run --rm -it -v "$PWD/pytorch-test:/tmp/pytorch-test" --gpus all cgr.dev/chainguard/pytorch-cuda12:latest -c "python /tmp/pytorch-test/model_builder.py" -``` - -You may also consider running this [quickstart script](https://github.com/chainguard-images/images/blob/main/images/pytorch-cuda12/tests/quickstart.py) based on the [official PyTorch quickstart tutorial](https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html) using the same approach as above. - -### Using Helm charts - -As a place to get started, you may also use this Helm chart to get PyTorch running -```bash - helm install pytorch \ - --namespace pytorch-space --create-namespace \ - --set image.registry="cgr.dev" \ - --set image.repository="chainguard/pytorch-cuda12" \ - --set image.tag=latest \ - --set containerSecurityContext.runAsUser=0 \ - --set containerSecurityContext.runAsNonRoot=false \ - --set containerSecurityContext.allowPrivilegeEscalation=true \ - --wait oci://registry-1.docker.io/bitnamicharts/pytorch -``` - - -## Contact Support - -If you have a Zendesk account (typically set up for you by your Customer Success Manager) you can reach out to Chainguard's Customer Success team through our [Zendesk portal](https://support.chainguard.dev/hc/en-us). - -## What are Chainguard Images? - -[Chainguard Images](https://www.chainguard.dev/chainguard-images?utm_source=readmes) are a collection of container images designed for security and minimalism. - -Many Chainguard Images are [distroless](https://edu.chainguard.dev/chainguard/chainguard-images/getting-started-distroless/); they contain only an open-source application and its runtime dependencies. These images do not even contain a shell or package manager. Chainguard Images are built with [Wolfi](https://edu.chainguard.dev/open-source/wolfi/overview), our Linux _undistro_ designed to produce container images that meet the requirements of a secure software supply chain. - -The main features of Chainguard Images include: - -* Minimal design, with no unnecessary software bloat -* Automated nightly builds to ensure Images are completely up-to-date and contain all available security patches -* [High quality build-time SBOMs](https://edu.chainguard.dev/chainguard/chainguard-images/working-with-images/retrieve-image-sboms/) (software bills of materials) attesting the provenance of all artifacts within the Image -* [Verifiable signatures](https://edu.chainguard.dev/chainguard/chainguard-images/working-with-images/retrieve-image-sboms/) provided by [Sigstore](https://edu.chainguard.dev/open-source/sigstore/cosign/an-introduction-to-cosign/) -* Reproducible builds with Cosign and apko ([read more about reproducibility](https://www.chainguard.dev/unchained/reproducing-chainguards-reproducible-image-builds)) - -### `-dev` Variants - -As mentioned previously, Chainguard’s distroless Images have no shell or package manager by default. This is great for security, but sometimes you need these things, especially in builder images. For those cases, most (but not all) Chainguard Images come paired with a `-dev` variant which does include a shell and package manager. - -Although the `-dev` image variants have similar security features as their distroless versions, such as complete SBOMs and signatures, they feature additional software that is typically not necessary in production environments. The general recommendation is to use the `-dev` variants only to build the application and then copy all application artifacts into a distroless image, which will result in a final container image that has a minimal attack surface and won’t allow package installations or logins. - -That being said, it’s worth noting that `-dev` variants of Chainguard Images are completely fine to run in production environments. After all, the `-dev` variants are still **more secure** than many popular container images based on fully-featured operating systems such as Debian and Ubuntu since they carry less software, follow a more frequent patch cadence, and offer attestations for what they include. - -## Learn More - -To better understand how to work with Chainguard Images, we encourage you to visit [Chainguard Academy](https://edu.chainguard.dev/), our documentation and education platform. \ No newline at end of file diff --git a/images/pytorch-cuda12/TESTING.md b/images/pytorch-cuda12/TESTING.md deleted file mode 100644 index 8b99353117..0000000000 --- a/images/pytorch-cuda12/TESTING.md +++ /dev/null @@ -1,97 +0,0 @@ -# Testing the PyTorch-CUDA Image - -While some functionality in PyTorch will run on CPU, full testing of -this image requires an environment with connected GPUs. Previous -testing has used a [Google Cloud deep learning -instance](https://cloud.google.com/deep-learning-vm) with connected -GPU, CUDA toolkit, and required NVIDIA drivers. - -## Creating a Deep Learning VM - -1. If you haven't already, install the [gcloud CLI](https://cloud.google.com/sdk/docs/install). -2. In GCP, create a project and grab the project ID or find the ID of - your existing project. The ID is a descriptive string, not a - number. -3. Run `gcloud init` in the terminal to authenticate to GCP. You may - want to add the ID above at this step. You can set the project - later with `gcloud config set project `. -4. Once you're authenticated, review and set these environment - variables as below. GPU aren't available in all zones and this - changes. You can [review availability using gcloud - cli](https://cloud.google.com/compute/docs/gpus/gpu-regions-zones), - or you can [sneak a look at the GCP docs on creating an instance to - see what their current default - is](https://cloud.google.com/deep-learning-vm/docs/pytorch_start_instance) - since it's pretty likely to work. You can also set the pytorch-cuda - version if needed (see the above GCP docs) and name the instance. - - ```bash - export IMAGE_FAMILY="pytorch-latest-gpu" - export ZONE="us-west1-b" - export INSTANCE_NAME="" - ``` - -5. Run the following to create the instance: - -``` bash -gcloud compute instances create $INSTANCE_NAME \ - --zone=$ZONE \ - --image-family=$IMAGE_FAMILY \ - --image-project=deeplearning-platform-release \ - --maintenance-policy=TERMINATE \ - --accelerator="type=nvidia-tesla-v100,count=1" \ - --metadata="install-nvidia-driver=True" -``` - -Some notes: - -- If the above instructions aren't working, [check the GCP docs for an - update](https://cloud.google.com/deep-learning-vm/docs/pytorch_start_instance). -- Using the above instructions, the CUDA drivers should be installed - during image creation (that's the metadata tag). -- The maintenance policy needs to be set because GPU instances can't - be moved live. If the realm changes or other maintenance occurs, the - image will be shut down. - -## Check CUDA and GPU Availability - -```bash -$ nvcc --version -nvcc: NVIDIA (R) Cuda compiler driver -Copyright (c) 2005-2023 NVIDIA Corporation -Built on Mon_Apr__3_17:16:06_PDT_2023 -Cuda compilation tools, release 12.1, V12.1.105 -Build cuda_12.1.r12.1/compiler.32688072_0 -``` - -Check that CUDA is available as a device: - -```bash -$ echo "import torch;print(torch.cuda.is_available())"| python -True -``` - -Check the specific connected GPU. If more than one is connected, this will show the first. - -```bash -$ echo "import torch;print(torch.cuda.get_device_name(0))" | python -Tesla V100-SXM2-16GB -``` - -## Run Image - -Install [Docker Engine](https://docs.docker.com/engine/install/ubuntu/). - -Run the image: - -```bash -docker run --rm -i -t \ - --gpus all \ - cgr.dev/chainguard/pytorch-cuda12:latest -``` - -## Documentation and Resources - -- [Deep Learning VM Docs](https://cloud.google.com/deep-learning-vm/docs) -- [PyTorch-Specific instructions](https://cloud.google.com/deep-learning-vm/docs/pytorch_start_instance) - (TF on same page) diff --git a/images/pytorch-cuda12/config/main.tf b/images/pytorch-cuda12/config/main.tf deleted file mode 100644 index aa6feadf43..0000000000 --- a/images/pytorch-cuda12/config/main.tf +++ /dev/null @@ -1,51 +0,0 @@ -terraform { - required_providers { - apko = { source = "chainguard-dev/apko" } - } -} - -variable "extra_packages" { - default = ["torchvision-cuda12"] - description = "Additional packages to install." - type = list(string) -} - -variable "extra_repositories" { - default = ["https://packages.cgr.dev/extras"] - description = "The additional repositores to install from (e.g. extras)." -} - -variable "extra_keyring" { - default = ["https://packages.cgr.dev/extras/chainguard-extras.rsa.pub"] - description = "The additional keys to use (e.g. extras)." -} - -variable "environment" { - default = {} -} - -module "accts" { - source = "../../../tflib/accts" -} - -output "config" { - value = jsonencode({ - contents = { - packages = var.extra_packages - repositories = var.extra_repositories - keyring = var.extra_keyring - } - accounts = module.accts.block - environment = merge({ - "PATH" : "/work:/usr/share/torchvision/.venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin", - "CUDA_VERSION" : "12.3", - "LD_LIBRARY_PATH" : "/usr/local/cuda-12.3/lib:/usr/local/cudnn-8.9/lib64", - }, var.environment) - entrypoint = { - command = "/usr/share/torchvision/.venv/bin/python3" - } - archs = ["x86_64"] - work-dir = "/work" - }) -} - diff --git a/images/pytorch-cuda12/generated.tf b/images/pytorch-cuda12/generated.tf deleted file mode 100644 index fdbe7e4d9a..0000000000 --- a/images/pytorch-cuda12/generated.tf +++ /dev/null @@ -1,8 +0,0 @@ -# DO NOT EDIT - this file is autogenerated by tfgen - -output "summary" { - value = { - "tags" = merge(module.tagger.imagetags) - } -} - diff --git a/images/pytorch-cuda12/main.tf b/images/pytorch-cuda12/main.tf deleted file mode 100644 index 5a38ae24d2..0000000000 --- a/images/pytorch-cuda12/main.tf +++ /dev/null @@ -1,40 +0,0 @@ -locals { - versions = [ - "py3.11-pytorch-cuda-12.3", - ] -} - -variable "target_repository" { - description = "The docker repo into which the image and attestations should be published." -} - -module "config" { - extra_packages = [each.key, "py3.11-torchvision-cuda-12.3"] - for_each = toset(local.versions) - source = "./config" -} - -module "versioned" { - build-dev = true - check-sbom = false - config = module.config[each.key].config - extra_dev_packages = ["cuda-toolkit-12.3-dev", "bash"] - for_each = toset(local.versions) - main_package = each.key - name = basename(path.module) - source = "../../tflib/publisher" - target_repository = var.target_repository -} - -module "test" { - digest = module.versioned[each.key].image_ref - for_each = toset(local.versions) - source = "./tests" -} - -module "tagger" { - depends_on = [module.test] - source = "../../tflib/tagger" - tags = merge([for v in local.versions : module.versioned[v].latest_tag_map]...) -} - diff --git a/images/pytorch-cuda12/metadata.yaml b/images/pytorch-cuda12/metadata.yaml deleted file mode 100644 index 585fdf9c01..0000000000 --- a/images/pytorch-cuda12/metadata.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: pytorch-cuda12 -image: cgr.dev/chainguard/pytorch-cuda12 -logo: https://storage.googleapis.com/chainguard-academy/logos/pytorch.svg -endoflife: "" -console_summary: "" -short_description: | - A minimal, [wolfi](https://github.com/wolfi-dev)-based image for pytorch, a Python package that provides two high-level features: Tensor computation with strong GPU acceleration and Deep neural networks built on a tape-based autograd system. -compatibility_notes: "" -readme_file: README.md -upstream_url: https://www.pytorch.org/ -keywords: - - ai - - base -public: true -tier: AI -aliases: - - pytorch/pytorch:latest diff --git a/images/pytorch-cuda12/model_builder.py b/images/pytorch-cuda12/model_builder.py deleted file mode 100644 index 70968a2f36..0000000000 --- a/images/pytorch-cuda12/model_builder.py +++ /dev/null @@ -1,34 +0,0 @@ -import torch - -class TinyModel(torch.nn.Module): - - def __init__(self): - super(TinyModel, self).__init__() - - self.linear1 = torch.nn.Linear(100, 200) - self.activation = torch.nn.ReLU() - self.linear2 = torch.nn.Linear(200, 10) - self.softmax = torch.nn.Softmax() - - def forward(self, x): - x = self.linear1(x) - x = self.activation(x) - x = self.linear2(x) - x = self.softmax(x) - return x - -tinymodel = TinyModel() - -print('The model:') -print(tinymodel) - -print('\n\nJust one layer:') -print(tinymodel.linear2) - -print('\n\nModel params:') -for param in tinymodel.parameters(): - print(param) - -print('\n\nLayer params:') -for param in tinymodel.linear2.parameters(): - print(param) diff --git a/images/pytorch-cuda12/tests/check-pytorch.sh b/images/pytorch-cuda12/tests/check-pytorch.sh deleted file mode 100755 index 3c53747c8f..0000000000 --- a/images/pytorch-cuda12/tests/check-pytorch.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - - -set -o errexit -o nounset -o errtrace -o pipefail -x - -my_d=$(cd "${0%/*}" && pwd) -exit_code=1 - -run_scripts() { - pod_name=$(kubectl get pods -n pytorch -l "app.kubernetes.io/instance=pytorch" -o custom-columns=:metadata.name --no-headers | head -n 1) - kubectl cp "${my_d}/quickstart.py" "$pod_name":/tmp/pytorch.py -n pytorch - kubectl exec "$pod_name" -n pytorch -- python /tmp/pytorch.py - exit_code=$? - if [ $exit_code -eq 0 ]; then - printf "Test ran successfully" - return 0 - fi - echo "FAILED: Unable to run test scripts" - exit 1 -} - -run_scripts diff --git a/images/pytorch-cuda12/tests/main.tf b/images/pytorch-cuda12/tests/main.tf deleted file mode 100644 index da89427213..0000000000 --- a/images/pytorch-cuda12/tests/main.tf +++ /dev/null @@ -1,36 +0,0 @@ -terraform { - required_providers { - imagetest = { source = "chainguard-dev/imagetest" } - oci = { source = "chainguard-dev/oci" } - } -} - -variable "digest" { - description = "The image digest to run tests over." -} - -data "imagetest_inventory" "this" { -} - -resource "imagetest_harness_docker" "this" { - inventory = data.imagetest_inventory.this - name = "pytorch" -} - -resource "imagetest_feature" "basic" { - description = "Placeholder" - harness = imagetest_harness_docker.this - labels = { - type = "container" - # Group this image into a pytorch only shard - "shard::group" = "pytorch" - } - name = "Placeholder" - steps = [ - { - name = "Placeholder" - cmd = "exit 0" - }, - ] -} - diff --git a/images/pytorch-cuda12/tests/quickstart.py b/images/pytorch-cuda12/tests/quickstart.py deleted file mode 100644 index efab39b7e4..0000000000 --- a/images/pytorch-cuda12/tests/quickstart.py +++ /dev/null @@ -1,113 +0,0 @@ -import torch -from torch import nn -from torch.utils.data import DataLoader -from torchvision import datasets -from torchvision.transforms import ToTensor - -# Download training data from open datasets. -training_data = datasets.FashionMNIST( - root="data", - train=True, - download=True, - transform=ToTensor(), -) - -# Download test data from open datasets. -test_data = datasets.FashionMNIST( - root="data", - train=False, - download=True, - transform=ToTensor(), -) - -batch_size = 128 - -# Create data loaders. -train_dataloader = DataLoader(training_data, batch_size=batch_size) -test_dataloader = DataLoader(test_data, batch_size=batch_size) - -for X, y in test_dataloader: - print(f"Shape of X [N, C, H, W]: {X.shape}") - print(f"Shape of y: {y.shape} {y.dtype}") - break - -# Get cpu, gpu or mps device for training. -device = ( - "cuda" - if torch.cuda.is_available() - else "mps" - if torch.backends.mps.is_available() - else "cpu" -) -print(f"Using {device} device") - - -# Define model -class NeuralNetwork(nn.Module): - def __init__(self): - super().__init__() - self.flatten = nn.Flatten() - self.linear_relu_stack = nn.Sequential( - nn.Linear(28 * 28, 256), - nn.ReLU(), - nn.Linear(256, 10), - ) - - def forward(self, x): - x = self.flatten(x) - logits = self.linear_relu_stack(x) - return logits - - -model = NeuralNetwork().to(device) -print(model) - - -loss_fn = nn.CrossEntropyLoss() -optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) - - -def train(dataloader, model, loss_fn, optimizer): - size = len(dataloader.dataset) - model.train() - for batch, (X, y) in enumerate(dataloader): - X, y = X.to(device), y.to(device) - - # Compute prediction error - pred = model(X) - loss = loss_fn(pred, y) - - # Backpropagation - loss.backward() - optimizer.step() - optimizer.zero_grad() - - if batch % 100 == 0: - loss, current = loss.item(), (batch + 1) * len(X) - print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]") - - -def test(dataloader, model, loss_fn): - size = len(dataloader.dataset) - num_batches = len(dataloader) - model.eval() - test_loss, correct = 0, 0 - with torch.no_grad(): - for X, y in dataloader: - X, y = X.to(device), y.to(device) - pred = model(X) - test_loss += loss_fn(pred, y).item() - correct += (pred.argmax(1) == y).type(torch.float).sum().item() - test_loss /= num_batches - correct /= size - print( - f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n" - ) - - -epochs = 2 -for t in range(epochs): - print(f"Epoch {t+1}\n-------------------------------") - train(train_dataloader, model, loss_fn, optimizer) - test(test_dataloader, model, loss_fn) -print("Done!") diff --git a/images/pytorch-cuda12/tests/torch_optim.py b/images/pytorch-cuda12/tests/torch_optim.py deleted file mode 100644 index a79c57fbde..0000000000 --- a/images/pytorch-cuda12/tests/torch_optim.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -import torch -import math - - -# Create Tensors to hold input and outputs. -x = torch.linspace(-math.pi, math.pi, 2000) -y = torch.sin(x) - -# Prepare the input tensor (x, x^2, x^3). -p = torch.tensor([1, 2, 3]) -xx = x.unsqueeze(-1).pow(p) - -# Use the nn package to define our model and loss function. -model = torch.nn.Sequential( - torch.nn.Linear(3, 1), - torch.nn.Flatten(0, 1) -) -loss_fn = torch.nn.MSELoss(reduction='sum') - -# Use the optim package to define an Optimizer that will update the weights of -# the model for us. Here we will use RMSprop; the optim package contains many other -# optimization algorithms. The first argument to the RMSprop constructor tells the -# optimizer which Tensors it should update. -learning_rate = 1e-3 -optimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate) -for t in range(2000): - # Forward pass: compute predicted y by passing x to the model. - y_pred = model(xx) - - # Compute and print loss. - loss = loss_fn(y_pred, y) - if t % 100 == 99: - print(t, loss.item()) - - # Before the backward pass, use the optimizer object to zero all of the - # gradients for the variables it will update (which are the learnable - # weights of the model). This is because by default, gradients are - # accumulated in buffers( i.e, not overwritten) whenever .backward() - # is called. Checkout docs of torch.autograd.backward for more details. - optimizer.zero_grad() - - # Backward pass: compute gradient of the loss with respect to model - # parameters - loss.backward() - - # Calling the step function on an Optimizer makes an update to its - # parameters - optimizer.step() - - -linear_layer = model[0] -print(f'Result: y = {linear_layer.bias.item()} + {linear_layer.weight[:, 0].item()} x + {linear_layer.weight[:, 1].item()} x^2 + {linear_layer.weight[:, 2].item()} x^3')