1.1. What is RustyML
RustyML is a machine learning and deep learning library written entirely in Rust. It covers the full workflow a data-science project needs — data preprocessing, feature engineering, model training, and evaluation. It provides classical machine-learning estimators (linear models, decision trees, SVMs, clustering, dimensionality reduction, anomaly detection) as well as a Keras-style neural-network framework.
This guide documents version 0.14. The API is stabilizing, but minor releases can still introduce breaking changes, so pin a concrete version in Cargo.toml for production rather than tracking *. The authoritative API reference is at docs.rs/rustyml, and the source at github.com/SomeB1oody/RustyML.
1.1.1. Pure Rust, end to end
RustyML contains no C or C++ code: no BLAS to link, no LAPACK, no CUDA. That makes it highly portable, spares you from configuring a complicated environment by hand, and keeps you from hitting inscrutable errors at build time — which suits both production and newcomers. Most of the code is written in safe Rust, so its memory safety is guaranteed.
For performance, matrix multiplication goes through the pure-Rust gemmkit crate (reaching ndarray via the zero-copy gemmkit-ndarray adapter). It dispatches at run time to the widest SIMD the current CPU actually supports (AVX-512F, AVX2+FMA, NEON, wasm simd128, with a scalar fallback), and decides on its own whether a given product is worth threading and across how many workers — so you get excellent performance across very different hardware.
1.1.2. Parallelism
RustyML parallelizes its compute-heavy kernels with Rayon, but never blindly. Below a certain size the overhead of multithreading makes the parallel path slower than the serial one, so every kernel class has a calibrated size threshold and switches to the parallel path only once parallel is measurably faster. Those thresholds are not hardcoded constants: rustyml::tuning lets you override them at run time without a recompile, which matters most when you deploy the same binary to machines with very different core counts. See Performance Tuning and Parallelism for the details.
What the design buys you:
- Parallel reductions are deterministic: the blocked fold sums in a fixed order no matter how many threads run it, so results do not drift as you scale cores.
- Performance is predictable: no garbage-collection pauses, no JIT warmup, and no global interpreter lock serializing your threads.
- Nearly every randomized component honors a global seed (see Reproducibility and Random Seeds), so a run reproduces across machines. The dimensionality reducers’ iterative eigensolvers are deliberately left out, because they converge to the same result whatever the seed is.
1.1.3. Features and modules
RustyML is split into five modules, each controlled by a Cargo feature (prelude is shared). Naming features lets you compile only the parts you use. machine_learning, neural_network, utils, and metrics all enable math automatically.
| Feature / module | What lives in it |
|---|---|
machine_learning | Classical machine-learning estimators |
neural_network | The Sequential model plus layers (Dense, convolution, pooling, recurrent, dropout, normalization), activations, optimizers (SGD, Adam, AdamW, RMSprop, AdaGrad), and losses |
utils | Preprocessing (the StandardScaler family of scalers, label helpers such as to_categorical) and dataset splitting (train_test_split, train_test_split_stratified) |
metrics | Evaluation metrics for regression, classification (ConfusionMatrix, ROC AUC, log loss, …), and clustering (ARI, silhouette, …) |
math | Numeric computation and gemmkit-backed matrix products |
The default feature turns everything on. There is also a separate show_progress feature that draws training progress bars; see Installation and Feature Flags.
1.1.4. An API modeled on scikit-learn and Keras
Classical estimators follow scikit-learn, exposing methods like fit and predict; the neural network follows Keras’s Sequential model with its add / compile / fit / predict flow — which makes it easier to pick up if you know the Python data-science ecosystem. What changes is that data is ndarray arrays rather than NumPy (see Working with ndarray), and fallible calls return Result instead of raising exceptions.
Here is a classical machine-learning example; you can see the API shape follows scikit-learn:
use rustyml::prelude::machine_learning::*;
use ndarray::array;
fn main() {
// new(fit_intercept); the default solver is the exact closed form
let mut model = LinearRegression::new(true);
let x = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0]];
let y = array![6.0, 9.0, 12.0];
model.fit(&x, &y).unwrap();
let predictions = model.predict(&x).unwrap();
println!("predictions: {:?}", predictions);
}
And here is neural-network code, whose architecture follows Keras:
use rustyml::prelude::neural_network::*;
use ndarray::Array;
fn main() {
// 4 samples, 8 input features, 1 output
let x = Array::ones((4, 8)).into_dyn();
let y = Array::ones((4, 1)).into_dyn();
let mut model = Sequential::new();
model
.add(Dense::new(8, 16, Activation::ReLU).unwrap())
.add(Dense::new(16, 1, Activation::Linear).unwrap())
.compile(
Adam::new(0.001, 0.9, 0.999, 1e-8, 0.0).unwrap(),
MeanSquaredError::new(),
);
model.summary(); // prints the architecture, just like Keras
model.fit(&x, &y, 5).unwrap();
let predictions = model.predict(&x).unwrap();
println!("prediction shape: {:?}", predictions.shape());
}
The metrics keep the same design as scikit-learn too (every metric takes its arguments in (y_true, y_pred) order):
use rustyml::metrics::*;
use ndarray::array;
fn main() {
let y_true = array![1.0, 0.0, 0.0, 1.0, 1.0];
let y_pred = array![1.0, 0.0, 1.0, 1.0, 0.0];
let cm = ConfusionMatrix::new(&y_true, &y_pred);
println!("accuracy: {:.3}", cm.accuracy());
println!("f1 score: {:.3}", cm.f1_score());
}
Unlike Python, RustyML’s error propagation wraps the result of a fallible call in Result<T, Error>, and you can match on it to handle each outcome separately (either it succeeded and gives you T, or it failed and gives you an Error). See Error Handling.
Hyperparameters are validated at the point they are supplied, and an illegal value is rejected on the spot. Configuration uses the builder pattern: an estimator names its essential hyperparameters in new, then layers optional settings through chained with_* methods, each validating what it receives (for example LinearRegression::new(true).with_regularization(..)?).
1.1.5. What pure Rust buys you
A RustyML program compiles to a single self-contained binary. There is no extra toolchain to install and no complicated environment to configure. Trained classical models and neural-network weights serialize to binary through save_to_path / load_from_path; see Model Persistence in Depth. And because there is no GC, no interpreter, and no warmup, latency is predictable.
1.1.6. Notes on scope
RustyML is CPU-only. There is no GPU or CUDA backend. The neural-network framework suits small-to-medium models and deep learning that sits close to classical ML; it is not for training large vision or language models. The classical machine_learning and utils estimators all take an f64 feature matrix, but the element type of what predict gives back varies by model, see the table in Working with ndarray. The neural-network stack works in f32, and its tensor type is Tensor = ArrayD<f32>. The framework does not build a dynamic autodiff graph the way PyTorch does.