From 1f8b5d3efbda58853a1a89ce6c94755942b616fa Mon Sep 17 00:00:00 2001 From: Sylvain Benner Date: Fri, 26 Apr 2024 15:42:02 -0400 Subject: [PATCH] [guide] Remove ambiguity lib vs. executable (#1649) --- burn-book/book.toml | 1 + burn-book/src/basic-workflow/README.md | 10 ++- burn-book/src/basic-workflow/backend.md | 67 +++---------------- burn-book/src/basic-workflow/inference.md | 15 +++++ burn-book/src/basic-workflow/model.md | 9 +++ burn-book/src/getting-started.md | 78 ++++++++++++++++++++++- examples/guide/examples/guide.rs | 36 ++++------- examples/guide/src/lib.rs | 6 ++ examples/guide/src/main.rs | 31 +++++++++ 9 files changed, 169 insertions(+), 84 deletions(-) create mode 100644 examples/guide/src/main.rs diff --git a/burn-book/book.toml b/burn-book/book.toml index d259a439c9..c3819d8826 100644 --- a/burn-book/book.toml +++ b/burn-book/book.toml @@ -5,6 +5,7 @@ authors = [ "Louis Fortier-Dubois", "Dilshod Tadjibaev", "Guillaume Lagrange", + "Sylvain Benner", ] language = "en" multilingual = false diff --git a/burn-book/src/basic-workflow/README.md b/burn-book/src/basic-workflow/README.md index 97e802113a..4350df82fa 100644 --- a/burn-book/src/basic-workflow/README.md +++ b/burn-book/src/basic-workflow/README.md @@ -6,9 +6,17 @@ train a simple convolutional neural network model on the MNIST dataset and prepa For clarity, we sometimes omit imports in our code snippets. For more details, please refer to the corresponding code in the `examples/guide` [directory](https://github.com/tracel-ai/burn/tree/main/examples/guide). We reproduce this example in a step-by-step fashion, from dataset creation to modeling and training -in the following sections. It is recommended to use the capabilities of your IDE or editor to +in the following sections. It is recommended to use the capabilities of your IDE or text editor to automatically add the missing imports as you add the code snippets to your code. +
+ +Be sure to checkout the git branch corresponding to the version of Burn you are using to follow +this guide. + +The current version of Burn is `0.14` and the corresponding branch to checkout is `main`. +
+ The code for this demo can be executed from Burn's base directory using the command: ```bash diff --git a/burn-book/src/basic-workflow/backend.md b/burn-book/src/basic-workflow/backend.md index 0761199575..2734f8b09d 100644 --- a/burn-book/src/basic-workflow/backend.md +++ b/burn-book/src/basic-workflow/backend.md @@ -7,74 +7,21 @@ entrypoint of our program, namely the `main` function defined in `src/main.rs`. ```rust , ignore use burn::optim::AdamConfig; use burn::backend::{Autodiff, Wgpu, wgpu::AutoGraphicsApi}; -use guide::model::ModelConfig; +use crate::model::ModelConfig; fn main() { type MyBackend = Wgpu; type MyAutodiffBackend = Autodiff; let device = burn::backend::wgpu::WgpuDevice::default(); - guide::training::train::( + crate::training::train::( "/tmp/guide", - guide::training::TrainingConfig::new(ModelConfig::new(10, 512), AdamConfig::new()), + crate::training::TrainingConfig::new(ModelConfig::new(10, 512), AdamConfig::new()), device, ); } ``` -
-🦀 Packages, Crates and Modules - -You might be wondering why we use the `guide` prefix to bring the different modules we just -implemented into scope. Instead of including the code in the current guide in a single file, we -separated it into different files which group related code into _modules_. The `guide` is simply the -name we gave to our _crate_, which contains the different files. Below is a brief explanation of the -different parts of the Rust module system. - -A **package** is a bundle of one or more crates that provides a set of functionality. A package -contains a `Cargo.toml` file that describes how to build those crates. Burn is a package. - -A **crate** is a compilation unit in Rust. It could be a single file, but it is often easier to -split up crates into multiple _modules_ and possibly multiple files. A crate can come in one of two -forms: a binary crate or a library crate. When compiling a crate, the compiler first looks in the -crate root file (usually `src/lib.rs` for a library crate or `src/main.rs` for a binary crate). Any -module declared in the crate root file will be inserted in the crate for compilation. For this demo -example, we will define a library crate where all the individual modules (model, data, training, -etc.) are listed inside `src/lib.rs` as follows: - -``` -pub mod data; -pub mod inference; -pub mod model; -pub mod training; -``` - -A **module** lets us organize code within a crate for readability and easy reuse. Modules also allow -us to control the _privacy_ of items. The `pub` keyword used above, for example, is employed to make -a module publicly available inside the crate. - -The entry point of our program is the `main` function, defined in the `examples/guide.rs` file. The -file structure for this example is illustrated below: - -``` -guide -├── Cargo.toml -├── examples -│ └── guide.rs -└── src - ├── data.rs - ├── inference.rs - ├── lib.rs - ├── model.rs - └── training.rs -``` - -The source for this guide can be found in our -[GitHub repository](https://github.com/tracel-ai/burn/tree/main/examples/guide) which can be used to -run this basic workflow example end-to-end.\ - -

- In this example, we use the `Wgpu` backend which is compatible with any operating system and will use the GPU. For other options, see the Burn README. This backend type takes the graphics api, the float type and the int type as generic arguments that will be used during the training. By leaving @@ -87,6 +34,12 @@ the model (the number of digit classes is 10 and the hidden dimension is 512), t configuration which in our case will be the default Adam configuration, and the device which can be obtained from the backend. -When running the example, we can see the training progression through a basic CLI dashboard: +You can now train your freshly created model with the command: + +```console +cargo run --release +``` + +When running the example, you should see the training progression through a basic CLI dashboard: Alt text diff --git a/burn-book/src/basic-workflow/inference.md b/burn-book/src/basic-workflow/inference.md index 8f422d7f45..4c170414ff 100644 --- a/burn-book/src/basic-workflow/inference.md +++ b/burn-book/src/basic-workflow/inference.md @@ -35,3 +35,18 @@ Finally we can init the model with the configuration and the record. For simplic same batcher used during the training to pass from a MnistItem to a tensor. By running the infer function, you should see the predictions of your model! + +Add the call to `infer` to the `main.rs` file after the `train` function call: + +```rust , ignore + crate::inference::infer::( + artifact_dir, + device, + burn::data::dataset::vision::MnistDataset::test() + .get(42) + .unwrap(), + ); +``` + +The number `42` is the index of the image in the MNIST dataset. You can explore and verify them using +this [MNIST viewer](https://observablehq.com/@davidalber/mnist-viewer). diff --git a/burn-book/src/basic-workflow/model.md b/burn-book/src/basic-workflow/model.md index 7b5fab5c71..73088c789e 100644 --- a/burn-book/src/basic-workflow/model.md +++ b/burn-book/src/basic-workflow/model.md @@ -11,6 +11,7 @@ As [mentioned previously](../getting-started.md#creating-a-burn-application), th your `guide` project directory with a `Cargo.toml` and a `src/main.rs` file. In the `Cargo.toml` file, add the `burn` dependency with `train`, `wgpu` and `vision` features. +Then run `cargo build` to build the project and import all the dependencies. ```toml [package] @@ -158,6 +159,14 @@ There are two major things going on in this code sample.
+Note that each time you create a new file in the `src` directory you also need to add explicitly this +module to the `main.rs` file. For instance after creating the `model.rs`, you need to add the following +at the top of the main file: + +```rust , ignore +mod model; +``` + Next, we need to instantiate the model for training. ```rust , ignore diff --git a/burn-book/src/getting-started.md b/burn-book/src/getting-started.md index 6db75852fe..eb8d6005db 100644 --- a/burn-book/src/getting-started.md +++ b/burn-book/src/getting-started.md @@ -199,14 +199,86 @@ For the sake of simplicity, the subsequent chapters of this book will all use th -## Running examples +## Explore examples + +In the [next chapter](./basic-workflow) you'll have the opportunity to implement the whole Burn +`guide` example yourself in a step by step manner. Many additional Burn examples are available in the -[examples](https://github.com/tracel-ai/burn/tree/main/examples) directory. To run an example, please refer -to its README.md for the specific command to execute. +[examples](https://github.com/tracel-ai/burn/tree/main/examples) directory. Burn examples are +organized as library crates with one or more examples that are executable binaries. An example +can then be executed using the following cargo command line in the root of the Burn repository: + +```bash +cargo run --example +``` + +To learn more about crates and examples, read the Rust section below. + +
+🦀 About Rust crates + +Each Burn example is a **package** which are subdirectories of the `examples` directory. A package +is composed of one or more **crates**. + +A package is a bundle of one or more crates that provides a set of functionality. A package +contains a `Cargo.toml` file that describes how to build those crates. + +A crate is a compilation unit in Rust. It could be a single file, but it is often easier to +split up crates into multiple **modules**. + +A module lets us organize code within a crate for readability and easy reuse. Modules also allow +us to control the _privacy_ of items. For instance the `pub(crate)` keyword is employed to make +a module publicly available inside the crate. In the snippet below there are four modules declared, +two of them are public and visible to the users of the crates, one of them is public inside the crate +only and crate users cannot see it, at last one is private when there is no keyword. +These modules can be single files or a directory with a `mod.rs` file inside. + +```rust, ignore +pub mod data; +pub mod inference; +pub(crate) mod model; +mod training; +``` + +A crate can come in one of two forms: a **binary crate** or a **library crate**. When compiling a crate, +the compiler first looks in the crate root file (`src/lib.rs` for a library crate and `src/main.rs` +for a binary crate). Any module declared in the crate root file will be inserted in the crate for +compilation. + +All Burn examples are library crates and they can contain one or more executable examples that +uses the library. We even have some Burn examples that uses the library crate of other examples. + +The examples are unique files under the `examples` directory. Each file produces an executable file +with the same name. Each example can then be executed with `cargo run --example `. + +Below is an file tree of a typical Burn example package: + +``` +examples/burn-example +├── Cargo.toml +├── examples +│ ├── example1.rs +│ ├── example2.rs +│ └── ... +└── src + ├── lib.rs + ├── module1.rs + ├── module2.rs + └── ... +``` + +

+ +For more information on each example, see their respective `README.md` file. + +
Note that some examples use the [`datasets` library by HuggingFace](https://huggingface.co/docs/datasets/index) to download the datasets required in the examples. This is a Python library, which means that you will need to install Python before running these examples. This requirement will be clearly indicated in the example's README when applicable. + +
+ diff --git a/examples/guide/examples/guide.rs b/examples/guide/examples/guide.rs index f00610e1af..0ddc70e460 100644 --- a/examples/guide/examples/guide.rs +++ b/examples/guide/examples/guide.rs @@ -1,26 +1,16 @@ -use burn::{ - backend::{wgpu::AutoGraphicsApi, Autodiff, Wgpu}, - data::dataset::Dataset, - optim::AdamConfig, -}; -use guide::{model::ModelConfig, training::TrainingConfig}; +// +// Note: If you are following the Burn Book guide this file can be ignored. +// +// This example file is added only for convenience and consistency so that +// the guide example can be executed like any other examples using: +// +// cargo run --release --example guide +// +use std::process::Command; fn main() { - type MyBackend = Wgpu; - type MyAutodiffBackend = Autodiff; - - let device = burn::backend::wgpu::WgpuDevice::default(); - let artifact_dir = "/tmp/guide"; - guide::training::train::( - artifact_dir, - TrainingConfig::new(ModelConfig::new(10, 512), AdamConfig::new()), - device.clone(), - ); - guide::inference::infer::( - artifact_dir, - device, - burn::data::dataset::vision::MnistDataset::test() - .get(42) - .unwrap(), - ); + Command::new("cargo") + .args(["run", "--bin", "guide"]) + .status() + .expect("guide example should run"); } diff --git a/examples/guide/src/lib.rs b/examples/guide/src/lib.rs index 36d4df05b0..a56bdbe0fe 100644 --- a/examples/guide/src/lib.rs +++ b/examples/guide/src/lib.rs @@ -1,3 +1,9 @@ +// +// Note: If you are following the Burn Book guide this file can be ignored. +// +// This lib.rs file is added only for convenience so that the code in this +// guide can be reused. +// pub mod data; pub mod inference; pub mod model; diff --git a/examples/guide/src/main.rs b/examples/guide/src/main.rs new file mode 100644 index 0000000000..22cee5f72f --- /dev/null +++ b/examples/guide/src/main.rs @@ -0,0 +1,31 @@ +mod data; +mod inference; +mod model; +mod training; + +use crate::{model::ModelConfig, training::TrainingConfig}; +use burn::{ + backend::{wgpu::AutoGraphicsApi, Autodiff, Wgpu}, + data::dataset::Dataset, + optim::AdamConfig, +}; + +fn main() { + type MyBackend = Wgpu; + type MyAutodiffBackend = Autodiff; + + let device = burn::backend::wgpu::WgpuDevice::default(); + let artifact_dir = "/tmp/guide"; + crate::training::train::( + artifact_dir, + TrainingConfig::new(ModelConfig::new(10, 512), AdamConfig::new()), + device.clone(), + ); + crate::inference::infer::( + artifact_dir, + device, + burn::data::dataset::vision::MnistDataset::test() + .get(42) + .unwrap(), + ); +}