From 294a319557812aadceff3b3f937c1d4156e4e7cd Mon Sep 17 00:00:00 2001 From: Dilshod Tadjibaev <939125+antimora@users.noreply.github.com> Date: Wed, 16 Aug 2023 17:17:12 -0500 Subject: [PATCH] Add Jupyter notebook examples (#651) --- Cargo.toml | 4 + examples/notebook/README.md | 47 +++++++ examples/notebook/basic-tensor-op.ipynb | 173 ++++++++++++++++++++++++ examples/notebook/plots.ipynb | 113 ++++++++++++++++ 4 files changed, 337 insertions(+) create mode 100644 examples/notebook/README.md create mode 100644 examples/notebook/basic-tensor-op.ipynb create mode 100644 examples/notebook/plots.ipynb diff --git a/Cargo.toml b/Cargo.toml index b80df0513..e9da016dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,10 @@ members = [ "examples/*", ] +exclude = [ + "examples/notebook", +] + [workspace.dependencies] bytemuck = "1.13" const-random = "0.1.15" diff --git a/examples/notebook/README.md b/examples/notebook/README.md new file mode 100644 index 000000000..c141aa7b8 --- /dev/null +++ b/examples/notebook/README.md @@ -0,0 +1,47 @@ +# Jupyter Notebook Examples with Burn + +This directory includes Jupyter Notebook examples showcasing the usage of the Burn deep learning +framework in Rust through +[Evcxr Jupyter](https://github.com/evcxr/evcxr/blob/main/evcxr_jupyter/README.md). The examples are +systematically organized based on the specific Burn features they illustrate. + +## Viewing Options + +You can explore the examples in different ways: + +- **Notebook Viewer:** If you prefer not to set up the entire crate package, you can view the + examples in a notebook viewer or run them to see images and other media outputs. + +- **Visual Studio Code (vscode):** If you're using vscode, you already have access to a built-in + notebook viewer, enabling you to open and interact with the notebook files directly. + +For other editors, you can utilize the [Jupyter Notebook Viewer](https://nbviewer.jupyter.org/). + +## Getting Started with Rust and Evcxr + +To execute the Rust code within the notebooks, you must install the Evcxr kernel. Here's how to get +started: + +### Install Evcxr Kernel + +1. **Build Evcxr Kernel:** Install the required package with the following command: + + ```shell + cargo install evcxr_jupyter + ``` + +2. **Install and Register the Kernel to Jupyter:** + ```shell + evcxr_jupyter --install + ``` + +### Open and Run Notebooks + +Once the kernel is installed, you can open the notebook files in your preferred editor and run the +code. Ensure that the kernel is set to `Rust` within the notebook for proper execution. + +## Additional Reading Resources + +- [Notebook Special Commands for Evcxr](https://github.com/evcxr/evcxr/blob/main/COMMON.md): Learn + about the unique commands and functionalities offered by Evcxr for a more efficient workflow with + Jupyter Notebooks. diff --git a/examples/notebook/basic-tensor-op.ipynb b/examples/notebook/basic-tensor-op.ipynb new file mode 100644 index 000000000..11e3eda08 --- /dev/null +++ b/examples/notebook/basic-tensor-op.ipynb @@ -0,0 +1,173 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# This notebook demonstrates basic tensor operations in Burn." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, + "outputs": [], + "source": [ + "// Dependency declarations for the notebook. WARNING: It may take a while to compile the first time.\n", + "\n", + "// The syntax is similar to the one used in the Cargo.toml file. Just prefix with :dep\n", + "// See: https://github.com/evcxr/evcxr/blob/main/COMMON.md\n", + "\n", + ":dep burn = {path = \"../../burn\"}\n", + ":dep burn-ndarray = {path = \"../../burn-ndarray\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, + "outputs": [], + "source": [ + "// Import packages\n", + "use burn::tensor::Tensor;\n", + "use burn_ndarray::NdArrayBackend;\n", + "\n", + "// Type alias for the backend\n", + "type B = NdArrayBackend;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tensor creation" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Empty tensor: Tensor {\n", + " data: [[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]],\n", + " shape: [1, 2, 3],\n", + " device: Cpu,\n", + " backend: \"ndarray\",\n", + " kind: \"Float\",\n", + " dtype: \"f32\",\n", + "}\n", + "Tensor from slice: Tensor {\n", + " data: [[1.0, 2.0], [3.0, 4.0]],\n", + " shape: [2, 2],\n", + " device: Cpu,\n", + " backend: \"ndarray\",\n", + " kind: \"Float\",\n", + " dtype: \"f32\",\n", + "}\n", + "Random tensor: Tensor {\n", + " data: [0.16685265, 0.7217095, 0.35741878, 0.49403405, 0.27360022],\n", + " shape: [5],\n", + " device: Cpu,\n", + " backend: \"ndarray\",\n", + " kind: \"Float\",\n", + " dtype: \"f32\",\n", + "}\n" + ] + } + ], + "source": [ + "// Create an empty tensor for a given shape\n", + "let tensor: Tensor = Tensor::empty([1, 2, 3]);\n", + "println!(\"Empty tensor: {}\", tensor);\n", + "\n", + "// Create a tensor from a slice of floats\n", + "let tensor: Tensor = Tensor::from_floats([1.0, 2.0, 3.0, 4.0]).reshape([2, 2]);\n", + "println!(\"Tensor from slice: {}\", tensor);\n", + "\n", + "// Create a random tensor\n", + "use burn::tensor::Distribution;\n", + "let tensor: Tensor = Tensor::random([5], Distribution::Default);\n", + "println!(\"Random tensor: {}\", tensor);\n", + "\n", + "// Create a tensor using fill values, zeros, or ones\n", + "let tensor: Tensor = Tensor::full([2, 2], 7.0);\n", + "let tensor: Tensor = Tensor::zeros([2, 2]);\n", + "let tensor: Tensor = Tensor::ones([2, 2]);\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tensor Operations\n" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x3 = Tensor {\n", + " data: [[8.0, 8.0], [8.0, 8.0]],\n", + " shape: [2, 2],\n", + " device: Cpu,\n", + " backend: \"ndarray\",\n", + " kind: \"Float\",\n", + " dtype: \"f32\",\n", + "}\n" + ] + } + ], + "source": [ + "let x1: Tensor = Tensor::ones([2, 2]);\n", + "let x2: Tensor = Tensor::full([2, 2], 7.0);\n", + "\n", + "let x3 = x1 + x2;\n", + "\n", + "println!(\"x3 = {}\", x3);" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Rust", + "language": "rust", + "name": "rust" + }, + "language_info": { + "codemirror_mode": "rust", + "file_extension": ".rs", + "mimetype": "text/rust", + "name": "Rust", + "pygment_lexer": "rust", + "version": "" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/notebook/plots.ipynb b/examples/notebook/plots.ipynb new file mode 100644 index 000000000..f24dca24e --- /dev/null +++ b/examples/notebook/plots.ipynb @@ -0,0 +1,113 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# This notebook demonstrates basic tensor operations in Burn." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, + "outputs": [], + "source": [ + "// Dependency declarations for the notebook. WARNING: It may take a while to compile the first time.\n", + "\n", + "// The syntax is similar to the one used in the Cargo.toml file. Just prefix with :dep\n", + "// See: https://github.com/evcxr/evcxr/blob/main/COMMON.md\n", + "\n", + ":dep burn = {path = \"../../burn\"}\n", + ":dep burn-ndarray = {path = \"../../burn-ndarray\"}\n", + "\n", + "// The following dependencies are used for plotting\n", + ":dep image = \"0.23\"\n", + ":dep evcxr_image = \"1.1\"" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, + "outputs": [], + "source": [ + "// Import packages\n", + "use burn::tensor::Tensor;\n", + "use burn_ndarray::NdArrayBackend;\n", + "\n", + "// Import plotting library\n", + "use evcxr_image::ImageDisplay;\n", + "\n", + "// Type alias for the backend\n", + "type B = NdArrayBackend;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Image from tensor" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, + "outputs": [ + { + "data": { + "image/png": "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" + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "// Create a random tensor\n", + "use burn::tensor::Distribution;\n", + "let tensor: Tensor = Tensor::random([3, 256, 256], Distribution::Default);\n", + "\n", + "// TODO Use tenso to display plots\n", + "image::ImageBuffer::from_fn(256, 256, |x, y| {\n", + " if (x as i32 - y as i32).abs() < 3 {\n", + " image::Rgb([0, 0, 255])\n", + " } else {\n", + " image::Rgb([0, 0, 0])\n", + " }\n", + "})\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Rust", + "language": "rust", + "name": "rust" + }, + "language_info": { + "codemirror_mode": "rust", + "file_extension": ".rs", + "mimetype": "text/rust", + "name": "Rust", + "pygment_lexer": "rust", + "version": "" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +}