A workshop demo project that builds an Iris flower classifier in Rust using Linfa, demonstrating the "vibe coding" workflow -- where AI assistants handle syntax while you focus on intent, and the Rust compiler acts as your safety net.
flowchart LR
A["π¦ Load Dataset"] --> B["βοΈ Train/Test Split"]
B --> C["π§ Train Models"]
C --> D["π Evaluate"]
D --> E["π₯οΈ Terminal Output"]
style A fill:#e1f5fe
style C fill:#fff3e0
style D fill:#e8f5e9
- Loads the classic Iris dataset (150 samples, 4 features, 3 classes)
- Trains two Decision Tree classifiers (participant model from lib.rs + built-in Entropy tree)
- Evaluates both models and displays results in formatted terminal tables
- Rust toolchain (1.93+ stable): Install via rustup
- Git (to navigate workshop checkpoints)
git clone https://github.com/Tony363/vibe-rust-ml-workshop.git
cd vibe-rust-ml-workshop
cargo run --releaseThe project is built incrementally. Each Git tag represents a compilable, runnable checkpoint:
flowchart LR
S1["step-1-scaffold\nποΈ Project Setup"]
S2["step-2-data\nπ¦ Data Loading"]
S3["step-3-training\nπ§ Model Training"]
S4["step-4-complete\nπ Evaluation"]
S1 --> S2 --> S3 --> S4
style S1 fill:#e3f2fd
style S2 fill:#e8f5e9
style S3 fill:#fff3e0
style S4 fill:#fce4ec
git checkout step-1-scaffold
cargo run
# Output: "Vibe Rust ML Workshop"Minimal project setup with dependencies in Cargo.toml: linfa, linfa-trees, linfa-datasets, ndarray, comfy-table, rand.
git checkout step-2-data
cargo runLoads Iris dataset via linfa_datasets::iris(), displays a dataset info table, and splits 80/20 for training/testing.
git checkout step-3-training
cargo runTrains two Decision Tree classifiers:
- Tree 1 (lib.rs): Entropy, max depth = 10
- Tree 2 (main.rs): Entropy, unlimited depth
git checkout step-4-complete
cargo run --releaseFull pipeline with predictions, accuracy comparison, confusion matrix, and sample predictions table.
To return to the final version:
git checkout master Vibe Rust ML Workshop -- Iris Classification
βββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Property β Value β
βββββββββββββββββͺβββββββββββββββββββββββββββββββββββββββββββββββββββββββ‘
β Dataset β Iris β
βββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Samples β 150 β
βββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Features β 4 β
βββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Classes β 3 (Setosa, Versicolor, Virginica) β
βββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Feature Names β sepal length, sepal width, petal length, petal width β
βββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Train/Test split: 120 training, 30 testing samples
Training Model 1: DecisionTree (Entropy, depth=10)...
-> Trained in ~130Β΅s
Training Model 2: Decision Tree (Entropy, unlimited depth)...
-> Trained in ~150Β΅s
Model Comparison
ββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββ
β Model β Split Quality β Max Depth β Accuracy β Train Time β
ββββββββββββββββββββββββββββββββββββͺββββββββββββββββͺββββββββββββͺβββββββββββͺβββββββββββββ‘
β DecisionTree (Entropy, depth=10) β - β - β ~93-100% β ~130Β΅s β
ββββββββββββββββββββββββββββββββββββΌββββββββββββββββΌββββββββββββΌβββββββββββΌβββββββββββββ€
β Tree 2 β Entropy β None β ~93-100% β ~150Β΅s β
ββββββββββββββββββββββββββββββββββββ΄ββββββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββ
Confusion Matrix (DecisionTree (Entropy, depth=10))
ββββββββββββββββββββββ¬βββββββββ¬βββββββββββββ¬ββββββββββββ
β Actual \ Predicted β Setosa β Versicolor β Virginica β
ββββββββββββββββββββββͺβββββββββͺβββββββββββββͺββββββββββββ‘
β Setosa β ~10 β 0 β 0 β
ββββββββββββββββββββββΌβββββββββΌβββββββββββββΌββββββββββββ€
β Versicolor β 0 β ~10 β 0-1 β
ββββββββββββββββββββββΌβββββββββΌβββββββββββββΌββββββββββββ€
β Virginica β 0 β 0-1 β ~10 β
ββββββββββββββββββββββ΄βββββββββ΄βββββββββββββ΄ββββββββββββ
Sample Predictions (first 10 test samples)
ββββββ¬ββββββββββ¬ββββββββββ¬ββββββββββ¬ββββββββββ¬βββββββββββββ¬βββββββββββββ
β # β Sepal L β Sepal W β Petal L β Petal W β Actual β Predicted β
ββββββͺββββββββββͺββββββββββͺββββββββββͺββββββββββͺβββββββββββββͺβββββββββββββ‘
β 1 β 5.0 β 3.4 β 1.5 β 0.2 β Setosa β Setosa β
ββββββΌββββββββββΌββββββββββΌββββββββββΌββββββββββΌβββββββββββββΌβββββββββββββ€
β 2 β 6.8 β 3.2 β 5.9 β 2.3 β Virginica β Virginica β
ββββββΌββββββββββΌββββββββββΌββββββββββΌββββββββββΌβββββββββββββΌβββββββββββββ€
β .. β ... β ... β ... β ... β ... β ... β
ββββββΌββββββββββΌββββββββββΌββββββββββΌββββββββββΌβββββββββββββΌβββββββββββββ€
β 10 β 6.9 β 3.1 β 5.4 β 2.1 β Virginica β Virginica β
ββββββ΄ββββββββββ΄ββββββββββ΄ββββββββββ΄ββββββββββ΄βββββββββββββ΄βββββββββββββ
Note: the demo uses seed 42; the CI scorer (src/bin/score.rs) uses seed 1 for fair leaderboard comparison.
graph LR
subgraph "Source Code"
lib["src/lib.rs\nβοΈ Participant Models"]
main["src/main.rs\nDemo Binary"]
score["src/bin/score.rs\nπΈ Iris Scorer"]
wine["src/bin/score_wine.rs\nπ· Wine Scorer"]
end
subgraph "CI / Leaderboard"
lb["leaderboard.yml\nScore PRs"]
ulb["update-leaderboard.yml\nUpdate Rankings"]
cs["check-steps.yml\nVerify Tags"]
end
subgraph "Docs"
ws["WORKSHOP.md"]
rules["LEADERBOARD_RULES.md"]
lead["LEADERBOARD.md"]
end
lib --> main
lib --> score
lib --> wine
score --> lb
wine --> lb
lb --> lead
ulb --> lead
| Crate | Purpose |
|---|---|
| linfa | ML framework (scikit-learn for Rust) |
| linfa-trees | Decision Tree classifier |
| linfa-datasets | Built-in datasets (Iris, Wine Quality) |
| ndarray | N-dimensional arrays |
| comfy-table | Pretty terminal tables |
| rand | Random number generation (shuffling) |
Think you can beat the baseline? Two challenges, pick one or both!
xychart-beta horizontal
title "Baseline Accuracy β Can You Beat It?"
x-axis ["πΈ Iris (Easy)", "π· Wine Quality (Hard)"]
bar [93.3, 53.9]
| Challenge | Dataset | Baseline | Beat this! |
|---|---|---|---|
| Iris (Easy) | 150 samples, 4 features, 3 classes | 93.3% | Can you hit 100%? |
| Wine Quality (Hard) | 1599 samples, 11 features, 6 classes | 53.9% | Can you break 65%? |
git checkout submissions
git checkout -b my-submission
# edit src/lib.rs -- change build_and_predict() and/or build_and_predict_wine()
cargo run --bin score --release # check Iris score locally
cargo run --bin score_wine --release # check Wine Quality score locally
git add -A && git commit -m "my submission"
git push -u origin my-submission
# open a PR targeting the 'submissions' branch- Only modify
src/lib.rsandCargo.toml - Must use linfa algorithms
- CI scores both challenges with a fixed seed for fairness
- CI will automatically post a combined leaderboard on your PR
See LEADERBOARD.md for current standings and LEADERBOARD_RULES.md for full rules.
- Linfa Documentation
- Linfa GitHub -- scikit-learn-like ML in Rust
- Burn -- Deep learning framework for Rust
- Candle -- Hugging Face's minimalist ML framework for Rust
- Are We Learning Yet? -- Rust ML ecosystem tracker
MIT