From 70515ed788670c1db53769041fe1dc4925a972d0 Mon Sep 17 00:00:00 2001
From: Phillip Cloud <417981+cpcloud@users.noreply.github.com>
Date: Thu, 31 Aug 2023 07:05:17 -0400
Subject: [PATCH] docs(blog): embed the torch youtube video directly
---
.../torch/index/execute-results/html.json | 4 ++--
.../index/figure-html/cell-11-output-1.png | Bin 80459 -> 80134 bytes
docs/posts/torch/index.qmd | 4 +++-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/docs/_freeze/posts/torch/index/execute-results/html.json b/docs/_freeze/posts/torch/index/execute-results/html.json
index 95533563a084..a9f18b90cbd5 100644
--- a/docs/_freeze/posts/torch/index/execute-results/html.json
+++ b/docs/_freeze/posts/torch/index/execute-results/html.json
@@ -1,7 +1,7 @@
{
- "hash": "5c4026e2ed388cf5f5eb5e0333ec2001",
+ "hash": "04f3b3449ad4f530e5dc73c36b32c14e",
"result": {
- "markdown": "---\ntitle: \"Ibis on 🔥: Supercharge Your Workflow with DuckDB and PyTorch\"\nauthor: \"Phillip Cloud\"\ndate: \"2023-06-27\"\ncategories:\n - blog\n---\n\nIn this blog post we show how to leverage ecosystem tools to build an end-to-end ML pipeline using Ibis, DuckDB and PyTorch.\n\nCheck out the live stream of this notebook here: https://www.youtube.com/live/L4_deAdStKs?feature=share\n\nLet's get started!\n\n::: {#6ffa986b .cell execution_count=1}\n``` {.python .cell-code}\nimport ibis\nimport ibis.expr.datatypes as dt\n\nfrom ibis import _, selectors as s, udf\n\nibis.options.interactive = True\n```\n:::\n\n\n## Define a Function to Clean Inputs\n\nLet's define a function to clean the data in a few different ways:\n\n- Remove outliers (Z-score based)\n- Remove negative trip distances and negative fare amounts\n- Cast inputs to `float32`, since that's what PyTorch wants\n\nWe use a function here to ensure that we can run the same code on the test data set before prediction.\n\n::: {#f686359d .cell execution_count=2}\n``` {.python .cell-code}\ndef clean_input(path):\n return (\n # load parquet\n ibis.read_parquet(path)\n # compute fare_amount_zscore and trip_distance_zscore\n .mutate(s.across([\"fare_amount\", \"trip_distance\"], dict(zscore=(_ - _.mean()) / _.std())))\n # filter out negative trip distance and bizarre transactions\n .filter([_.trip_distance > 0.0, _.fare_amount >= 0.0])\n # keep values that within 2 standard deviations\n .filter(s.if_all(s.endswith(\"_zscore\"), _.abs() <= 2))\n # drop columns that aren't necessary for further analysis\n .drop(s.endswith(\"_zscore\"))\n # select the columns we care about\n .select(s.across([\"fare_amount\", \"trip_distance\"], _.cast(\"float32\")))\n )\n```\n:::\n\n\n::: {#cf3b1176 .cell execution_count=3}\n``` {.python .cell-code}\ntraining_data = clean_input(\"https://storage.googleapis.com/ibis-tutorial-data/nyctaxi/yellow/yellow_tripdata_2016-01.parquet\")\ntraining_data\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```{=html}\n
┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓\n┃ trip_distance ┃ fare_amount ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩\n│ float32 │ float32 │\n├───────────────┼─────────────┤\n│ 3.20 │ 14.0 │\n│ 1.00 │ 9.5 │\n│ 0.90 │ 6.0 │\n│ 0.80 │ 5.0 │\n│ 1.80 │ 11.0 │\n│ 2.30 │ 11.0 │\n│ 13.80 │ 43.0 │\n│ 3.46 │ 20.0 │\n│ 0.83 │ 5.5 │\n│ 0.87 │ 7.0 │\n│ … │ … │\n└───────────────┴─────────────┘\n \n```\n:::\n:::\n\n\n## Execute the Query and Convert to Torch Tensors\n\nNew in Ibis 6.0 is the `to_torch` method, which executes a query and returns the results as a dictionary of `torch.Tensor`s keyed by column names.\n\nWe'll use that to get our input data for training.\n\n::: {#eaa5a821 .cell execution_count=4}\n``` {.python .cell-code}\nimport torch\n\ntorch_training_data: dict[str, torch.Tensor] = training_data.to_torch()\ntorch_training_data\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n{'trip_distance': tensor([3.2000, 1.0000, 0.9000, ..., 5.6300, 0.7700, 1.2600]),\n 'fare_amount': tensor([14.0000, 9.5000, 6.0000, ..., 18.5000, 5.0000, 6.5000])}\n```\n:::\n:::\n\n\n## Train the Model\n\nLet's assume for now we don't have access to the model code. Maybe your co-worker wrote the model or it's part of an API that you don't control. Either way, it's a black box to us.\n\nThe API looks like this:\n\n::: {#63f52310 .cell execution_count=5}\n``` {.python .cell-code}\nimport pyarrow\n\n\nclass PredictCabFare:\n def __init__(self, data: dict[str, torch.Tensor]) -> None:\n \"\"\"Initialize the model with training data.\"\"\"\n\n def train(self) -> None:\n \"\"\"Train the model.\"\"\"\n\n def __call__(self, input: pyarrow.ChunkedArray) -> pyarrow.Array:\n \"\"\"Invoke the trained model on unseen input.\"\"\"\n```\n:::\n\n\n::: {#ab041996 .cell execution_count=6}\n``` {.python .cell-code}\nfrom model import PredictCabFare\n\n\nmodel = PredictCabFare(torch_training_data)\nmodel.train()\n```\n:::\n\n\n## Define an Ibis UDF that predicts fares\n\nNow we get to the meaty part: defining an Ibis UDF (user-defined function) that invokes our model on unseen data!\n\n::: {#df851080 .cell execution_count=7}\n``` {.python .cell-code}\nfrom ibis.expr.operations import udf\n\n\n@udf.scalar.pyarrow\ndef predict_fare(distance: dt.float64) -> dt.float32:\n return model(distance)\n```\n:::\n\n\nLet's run our UDF\n\n::: {#2e98bd40 .cell execution_count=8}\n``` {.python .cell-code}\nprediction = (\n clean_input(\"https://storage.googleapis.com/ibis-tutorial-data/nyctaxi/yellow/yellow_tripdata_2016-02.parquet\")\n .limit(10_000)\n .mutate(predicted_fare=lambda t: predict_fare(t.trip_distance.cast(\"float32\")))\n)\nprediction\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓\n┃ trip_distance ┃ fare_amount ┃ predicted_fare ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩\n│ float32 │ float32 │ float32 │\n├───────────────┼─────────────┼────────────────┤\n│ 9.1 │ 27.0 │ 28.976849 │\n│ 3.3 │ 11.5 │ 12.836579 │\n│ 0.5 │ 4.0 │ 5.044726 │\n│ 7.4 │ 26.5 │ 24.246078 │\n│ 1.6 │ 7.5 │ 8.105812 │\n│ 3.8 │ 16.0 │ 14.227982 │\n│ 1.1 │ 6.0 │ 6.714409 │\n│ 6.8 │ 21.0 │ 22.576397 │\n│ 2.9 │ 12.0 │ 11.723458 │\n│ 1.2 │ 6.5 │ 6.992690 │\n│ … │ … │ … │\n└───────────────┴─────────────┴────────────────┘\n \n```\n:::\n:::\n\n\n## Prepare the Data for Plotting\n\nHere we [tidy up our data](https://r4ds.had.co.nz/tidy-data.html) to make it easier to adjust plotting style based on the data.\n\nIn this case, we're interested in visually distinguishing the model's **predicted** fare amount from the **actual** fare amount so we\npivot the data into a [longer form](https://r4ds.had.co.nz/tidy-data.html#longer) which adds a string column `metric`\nthat indicates the kind of fare a given row contains.\n\n::: {#f470f30e .cell execution_count=9}\n``` {.python .cell-code}\npivoted_prediction = prediction.pivot_longer(\n s.contains(\"fare\"),\n values_to=\"fare\",\n names_to=\"metric\",\n)\npivoted_prediction\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓\n┃ trip_distance ┃ metric ┃ fare ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩\n│ float32 │ string │ float32 │\n├───────────────┼────────────────┼───────────┤\n│ 9.1 │ fare_amount │ 27.000000 │\n│ 9.1 │ predicted_fare │ 28.976849 │\n│ 3.3 │ fare_amount │ 11.500000 │\n│ 3.3 │ predicted_fare │ 12.836579 │\n│ 0.5 │ fare_amount │ 4.000000 │\n│ 0.5 │ predicted_fare │ 5.044726 │\n│ 7.4 │ fare_amount │ 26.500000 │\n│ 7.4 │ predicted_fare │ 24.246078 │\n│ 1.6 │ fare_amount │ 7.500000 │\n│ 1.6 │ predicted_fare │ 8.105812 │\n│ … │ … │ … │\n└───────────────┴────────────────┴───────────┘\n \n```\n:::\n:::\n\n\n## Plot the Results\n\nThere are a bunch of strange and interesting data points and observations that don't have an obvious explanation:\n\n- There seem to be a good number of \\\\$50-ish rides regardless of distance. What's going on there?\n- What's going on with the extreme outliers? For instance, the 50 mile ride that only cost about \\\\$60 or the 25 mile ride that cost about \\\\$140.\n\n::: {#a73af875 .cell execution_count=10}\n``` {.python .cell-code}\nfrom plotnine import aes, ggtitle, ggplot, geom_point, xlab, ylab\n\n(\n ggplot(pivoted_prediction, aes(x=\"trip_distance\", y=\"fare\", color=\"metric\"))\n + geom_point()\n + xlab(\"Trip Distance\")\n + ylab(\"Fare\")\n + ggtitle(\"Predicted Fare vs Actual Fare by Trip Distance\")\n)\n```\n\n::: {.cell-output .cell-output-display}\n![](index_files/figure-html/cell-11-output-1.png){}\n:::\n\n::: {.cell-output .cell-output-display execution_count=10}\n```\n\n```\n:::\n:::\n\n\n# Appendix: `model.py`\n\n```python\n\"\"\"Linear regression model for predicting cab fares using PyTorch.\n\nAdapted from https://gist.github.com/pdet/e8d38734232c08e6c15aba79b4eb8368#file-taxi_prediction_example-py.\n\"\"\"\nfrom __future__ import annotations\n\nimport pyarrow as pa\nimport torch\nimport tqdm\nfrom torch import nn\n\n\nclass LinearRegression(nn.Module):\n def __init__(self, input_dim, output_dim):\n super().__init__()\n self.linear = nn.Linear(input_dim, output_dim)\n\n def forward(self, distances):\n return self.linear(distances)\n\n\nclass PredictCabFare:\n def __init__(self, data, learning_rate: float = 0.01, epochs: int = 100) -> None:\n # Define the input and output dimensions\n input_dim = 1\n output_dim = 1\n\n # Create a linear regression model instance\n self.data = data\n self.model = LinearRegression(input_dim, output_dim)\n self.learning_rate = learning_rate\n self.epochs = epochs\n\n def train(self):\n distances = self.data[\"trip_distance\"].reshape(-1, 1)\n fares = self.data[\"fare_amount\"].reshape(-1, 1)\n\n # Define the loss function\n criterion = nn.MSELoss()\n\n # Define the optimizer\n optimizer = torch.optim.SGD(self.model.parameters(), lr=self.learning_rate)\n\n # Train the model\n for _ in tqdm.trange(self.epochs):\n # Forward pass\n y_pred = self.model(distances)\n\n # Compute loss\n loss = criterion(y_pred, fares)\n\n # Backward pass and optimize\n optimizer.zero_grad()\n loss.backward()\n optimizer.step()\n\n def predict(self, input):\n with torch.no_grad():\n return self.model(input)\n\n def __call__(self, input: pa.ChunkedArray):\n # Convert the input to numpy so it can be fed to the model\n #\n # .copy() to avoid the warning about undefined behavior from torch\n input = torch.from_numpy(input.to_numpy().copy())[:, None]\n predicted = self.predict(input).ravel()\n return pa.array(predicted.numpy())\n\n```\n\n\n",
+ "markdown": "---\ntitle: \"Ibis on 🔥: Supercharge Your Workflow with DuckDB and PyTorch\"\nauthor: \"Phillip Cloud\"\ndate: \"2023-06-27\"\ncategories:\n - blog\n---\n\nIn this blog post we show how to leverage ecosystem tools to build an end-to-end ML pipeline using Ibis, DuckDB and PyTorch.\n\nCheck out the live stream of this notebook below!\n\n\n{{< video https://www.youtube.com/embed/L4_deAdStKs >}}\n\n\n\nLet's get started!\n\n::: {#95a23c4a .cell execution_count=1}\n``` {.python .cell-code}\nimport ibis\nimport ibis.expr.datatypes as dt\n\nfrom ibis import _, selectors as s, udf\n\nibis.options.interactive = True\n```\n:::\n\n\n## Define a Function to Clean Inputs\n\nLet's define a function to clean the data in a few different ways:\n\n- Remove outliers (Z-score based)\n- Remove negative trip distances and negative fare amounts\n- Cast inputs to `float32`, since that's what PyTorch wants\n\nWe use a function here to ensure that we can run the same code on the test data set before prediction.\n\n::: {#751665de .cell execution_count=2}\n``` {.python .cell-code}\ndef clean_input(path):\n return (\n # load parquet\n ibis.read_parquet(path)\n # compute fare_amount_zscore and trip_distance_zscore\n .mutate(s.across([\"fare_amount\", \"trip_distance\"], dict(zscore=(_ - _.mean()) / _.std())))\n # filter out negative trip distance and bizarre transactions\n .filter([_.trip_distance > 0.0, _.fare_amount >= 0.0])\n # keep values that within 2 standard deviations\n .filter(s.if_all(s.endswith(\"_zscore\"), _.abs() <= 2))\n # drop columns that aren't necessary for further analysis\n .drop(s.endswith(\"_zscore\"))\n # select the columns we care about\n .select(s.across([\"fare_amount\", \"trip_distance\"], _.cast(\"float32\")))\n )\n```\n:::\n\n\n::: {#eba29231 .cell execution_count=3}\n``` {.python .cell-code}\ntraining_data = clean_input(\"https://storage.googleapis.com/ibis-tutorial-data/nyctaxi/yellow/yellow_tripdata_2016-01.parquet\")\ntraining_data\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```{=html}\n┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓\n┃ trip_distance ┃ fare_amount ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩\n│ float32 │ float32 │\n├───────────────┼─────────────┤\n│ 3.20 │ 14.0 │\n│ 1.00 │ 9.5 │\n│ 0.90 │ 6.0 │\n│ 0.80 │ 5.0 │\n│ 1.80 │ 11.0 │\n│ 2.30 │ 11.0 │\n│ 13.80 │ 43.0 │\n│ 3.46 │ 20.0 │\n│ 0.83 │ 5.5 │\n│ 0.87 │ 7.0 │\n│ … │ … │\n└───────────────┴─────────────┘\n \n```\n:::\n:::\n\n\n## Execute the Query and Convert to Torch Tensors\n\nNew in Ibis 6.0 is the `to_torch` method, which executes a query and returns the results as a dictionary of `torch.Tensor`s keyed by column names.\n\nWe'll use that to get our input data for training.\n\n::: {#ca27c5b3 .cell execution_count=4}\n``` {.python .cell-code}\nimport torch\n\ntorch_training_data: dict[str, torch.Tensor] = training_data.to_torch()\ntorch_training_data\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n{'trip_distance': tensor([3.2000, 1.0000, 0.9000, ..., 5.6300, 0.7700, 1.2600]),\n 'fare_amount': tensor([14.0000, 9.5000, 6.0000, ..., 18.5000, 5.0000, 6.5000])}\n```\n:::\n:::\n\n\n## Train the Model\n\nLet's assume for now we don't have access to the model code. Maybe your co-worker wrote the model or it's part of an API that you don't control. Either way, it's a black box to us.\n\nThe API looks like this:\n\n::: {#f5c5984b .cell execution_count=5}\n``` {.python .cell-code}\nimport pyarrow\n\n\nclass PredictCabFare:\n def __init__(self, data: dict[str, torch.Tensor]) -> None:\n \"\"\"Initialize the model with training data.\"\"\"\n\n def train(self) -> None:\n \"\"\"Train the model.\"\"\"\n\n def __call__(self, input: pyarrow.ChunkedArray) -> pyarrow.Array:\n \"\"\"Invoke the trained model on unseen input.\"\"\"\n```\n:::\n\n\n::: {#09151f0a .cell execution_count=6}\n``` {.python .cell-code}\nfrom model import PredictCabFare\n\n\nmodel = PredictCabFare(torch_training_data)\nmodel.train()\n```\n:::\n\n\n## Define an Ibis UDF that predicts fares\n\nNow we get to the meaty part: defining an Ibis UDF (user-defined function) that invokes our model on unseen data!\n\n::: {#f287ca26 .cell execution_count=7}\n``` {.python .cell-code}\nfrom ibis.expr.operations import udf\n\n\n@udf.scalar.pyarrow\ndef predict_fare(distance: dt.float64) -> dt.float32:\n return model(distance)\n```\n:::\n\n\nLet's run our UDF\n\n::: {#ac959189 .cell execution_count=8}\n``` {.python .cell-code}\nprediction = (\n clean_input(\"https://storage.googleapis.com/ibis-tutorial-data/nyctaxi/yellow/yellow_tripdata_2016-02.parquet\")\n .limit(10_000)\n .mutate(predicted_fare=lambda t: predict_fare(t.trip_distance.cast(\"float32\")))\n)\nprediction\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓\n┃ trip_distance ┃ fare_amount ┃ predicted_fare ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩\n│ float32 │ float32 │ float32 │\n├───────────────┼─────────────┼────────────────┤\n│ 9.1 │ 27.0 │ 29.090069 │\n│ 3.3 │ 11.5 │ 12.618828 │\n│ 0.5 │ 4.0 │ 4.667196 │\n│ 7.4 │ 26.5 │ 24.262291 │\n│ 1.6 │ 7.5 │ 7.791052 │\n│ 3.8 │ 16.0 │ 14.038762 │\n│ 1.1 │ 6.0 │ 6.371117 │\n│ 6.8 │ 21.0 │ 22.558369 │\n│ 2.9 │ 12.0 │ 11.482881 │\n│ 1.2 │ 6.5 │ 6.655104 │\n│ … │ … │ … │\n└───────────────┴─────────────┴────────────────┘\n \n```\n:::\n:::\n\n\n## Prepare the Data for Plotting\n\nHere we [tidy up our data](https://r4ds.had.co.nz/tidy-data.html) to make it easier to adjust plotting style based on the data.\n\nIn this case, we're interested in visually distinguishing the model's **predicted** fare amount from the **actual** fare amount so we\npivot the data into a [longer form](https://r4ds.had.co.nz/tidy-data.html#longer) which adds a string column `metric`\nthat indicates the kind of fare a given row contains.\n\n::: {#a499e7db .cell execution_count=9}\n``` {.python .cell-code}\npivoted_prediction = prediction.pivot_longer(\n s.contains(\"fare\"),\n values_to=\"fare\",\n names_to=\"metric\",\n)\npivoted_prediction\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓\n┃ trip_distance ┃ metric ┃ fare ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩\n│ float32 │ string │ float32 │\n├───────────────┼────────────────┼───────────┤\n│ 9.1 │ fare_amount │ 27.000000 │\n│ 9.1 │ predicted_fare │ 29.090069 │\n│ 3.3 │ fare_amount │ 11.500000 │\n│ 3.3 │ predicted_fare │ 12.618828 │\n│ 0.5 │ fare_amount │ 4.000000 │\n│ 0.5 │ predicted_fare │ 4.667196 │\n│ 7.4 │ fare_amount │ 26.500000 │\n│ 7.4 │ predicted_fare │ 24.262291 │\n│ 1.6 │ fare_amount │ 7.500000 │\n│ 1.6 │ predicted_fare │ 7.791052 │\n│ … │ … │ … │\n└───────────────┴────────────────┴───────────┘\n \n```\n:::\n:::\n\n\n## Plot the Results\n\nThere are a bunch of strange and interesting data points and observations that don't have an obvious explanation:\n\n- There seem to be a good number of \\\\$50-ish rides regardless of distance. What's going on there?\n- What's going on with the extreme outliers? For instance, the 50 mile ride that only cost about \\\\$60 or the 25 mile ride that cost about \\\\$140.\n\n::: {#c41ee3d5 .cell execution_count=10}\n``` {.python .cell-code}\nfrom plotnine import aes, ggtitle, ggplot, geom_point, xlab, ylab\n\n(\n ggplot(pivoted_prediction, aes(x=\"trip_distance\", y=\"fare\", color=\"metric\"))\n + geom_point()\n + xlab(\"Trip Distance\")\n + ylab(\"Fare\")\n + ggtitle(\"Predicted Fare vs Actual Fare by Trip Distance\")\n)\n```\n\n::: {.cell-output .cell-output-display}\n![](index_files/figure-html/cell-11-output-1.png){}\n:::\n\n::: {.cell-output .cell-output-display execution_count=10}\n```\n\n```\n:::\n:::\n\n\n# Appendix: `model.py`\n\n```python\n\"\"\"Linear regression model for predicting cab fares using PyTorch.\n\nAdapted from https://gist.github.com/pdet/e8d38734232c08e6c15aba79b4eb8368#file-taxi_prediction_example-py.\n\"\"\"\nfrom __future__ import annotations\n\nimport pyarrow as pa\nimport torch\nimport tqdm\nfrom torch import nn\n\n\nclass LinearRegression(nn.Module):\n def __init__(self, input_dim, output_dim):\n super().__init__()\n self.linear = nn.Linear(input_dim, output_dim)\n\n def forward(self, distances):\n return self.linear(distances)\n\n\nclass PredictCabFare:\n def __init__(self, data, learning_rate: float = 0.01, epochs: int = 100) -> None:\n # Define the input and output dimensions\n input_dim = 1\n output_dim = 1\n\n # Create a linear regression model instance\n self.data = data\n self.model = LinearRegression(input_dim, output_dim)\n self.learning_rate = learning_rate\n self.epochs = epochs\n\n def train(self):\n distances = self.data[\"trip_distance\"].reshape(-1, 1)\n fares = self.data[\"fare_amount\"].reshape(-1, 1)\n\n # Define the loss function\n criterion = nn.MSELoss()\n\n # Define the optimizer\n optimizer = torch.optim.SGD(self.model.parameters(), lr=self.learning_rate)\n\n # Train the model\n for _ in tqdm.trange(self.epochs):\n # Forward pass\n y_pred = self.model(distances)\n\n # Compute loss\n loss = criterion(y_pred, fares)\n\n # Backward pass and optimize\n optimizer.zero_grad()\n loss.backward()\n optimizer.step()\n\n def predict(self, input):\n with torch.no_grad():\n return self.model(input)\n\n def __call__(self, input: pa.ChunkedArray):\n # Convert the input to numpy so it can be fed to the model\n #\n # .copy() to avoid the warning about undefined behavior from torch\n input = torch.from_numpy(input.to_numpy().copy())[:, None]\n predicted = self.predict(input).ravel()\n return pa.array(predicted.numpy())\n\n```\n\n\n",
"supporting": [
"index_files"
],
diff --git a/docs/_freeze/posts/torch/index/figure-html/cell-11-output-1.png b/docs/_freeze/posts/torch/index/figure-html/cell-11-output-1.png
index 39f2da5caf9d9d3508e3ac9e2660a387dab3bb56..f04d1173a23e3e1f2937b28fd98df85be67b81e7 100644
GIT binary patch
literal 80134
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