Skip to main content

Crate rustyml

Crate rustyml 

Source
Expand description

§RustyML: Machine Learning and Deep Learning in Pure Rust

RustyML is a machine learning and deep learning library written entirely in Rust. It implements classical ML algorithms, neural networks, and data-processing utilities

§Overview

The crate covers a full workflow: preprocessing, feature engineering, model training, and evaluation. It validates input and reports errors

Estimator defaults, score orientations, and metric conventions follow scikit-learn and are checked numerically against it, so a ported pipeline produces the same numbers. Where the crate departs from scikit-learn, the item’s own documentation says so. Known departures:

  • metrics panics instead of returning Result
  • roc_curve always returns the full threshold sweep
  • MeanShift has an opt-in Gaussian kernel

§Architecture

The crate splits into 5 modules. A feature flag gates each one:

§machine_learning

Classical machine learning algorithms for supervised and unsupervised learning:

  • Regression: Linear Regression with L1/L2 regularization, solved in closed form by default or by gradient descent
  • Classification: Logistic Regression, KNN, Decision Tree, SVC, Linear SVC, LDA
  • Clustering: KMeans, DBSCAN, MeanShift. All 3 label samples as Array1<isize>, with -1 for noise or unassigned points
  • Dimensionality Reduction: PCA, Kernel PCA, t-SNE
  • Anomaly Detection: Isolation Forest, scoring in [-1, 0) where lower is more anomalous and predicting -1 (outlier) / +1 (inlier)

§neural_network

Neural network framework built around a sequential model. Tensors are channels-last, and kernel shapes match Keras, so a layout carried over from Keras needs no permutation:

  • Layers: Dense, SimpleRNN, LSTM, GRU, Convolution, Pooling, Dropout
  • Optimizers: SGD, Adam, AdamW, RMSprop, AdaGrad
  • Loss Functions: MSE, MAE, Binary/Categorical/Sparse Categorical Cross-Entropy
  • Models: Sequential architecture for feed-forward networks. fit and fit_with_batches return a History of one loss per epoch. A hand-written loop can call the public train_batch instead, and evaluate scores the model without training it

§utils

Data preprocessing and dataset-splitting utilities:

  • Preprocessing: one-shot standardize / normalize, the stateful scaler family (StandardScaler, MinMaxScaler, MaxAbsScaler, RobustScaler, Normalizer) for reusing training statistics on later batches, and label encoding
  • Dataset Splitting: train/test split (optionally stratified)

§metrics

Evaluation metrics for model performance. Unlike the rest of the crate, these functions panic on a precondition violation instead of returning a Result, which keeps this leaf module dependency-light:

  • Regression: MSE, RMSE, MAE, R^2 score
  • Classification: Accuracy, Confusion Matrix, AUC-ROC, F1-score
  • Clustering: Adjusted Rand Index, Normalized/Adjusted Mutual Information, Silhouette Score. Every one of them takes isize labels, the type the clustering estimators return

§math

Low-level numeric primitives shared across modules:

  • Distance Metrics: Euclidean, Manhattan, Minkowski, plus the DistanceCalculationMetric dispatcher
  • Matrix Products: gemmkit-backed GEMM/GEMV with automatic parallelism
  • Reductions: deterministic blocked parallel reductions

§Quick Start

§Machine Learning Example

Add RustyML to your Cargo.toml:

[dependencies]
rustyml = "*"
# The default feature set is `full`. To slim the build, set `default-features = false` and
# list the features you need, e.g. `features = ["machine_learning"]`
# Add `"show_progress"` to show progress bars during training

In your Rust code, write:

use rustyml::machine_learning::LinearRegression;
use rustyml::machine_learning::linear_model::LeastSquaresSolver;
use ndarray::{Array1, Array2};

// Create a linear regression model
let mut model = LinearRegression::new(true).with_solver(LeastSquaresSolver::GradientDescent { learning_rate: 0.01, max_iter: 1000, tol: 1e-6 }).unwrap();

// Prepare training data
let raw_x = vec![vec![1.0, 2.0], vec![2.0, 3.0], vec![3.0, 4.0]];
let raw_y = vec![6.0, 9.0, 12.0];

// Convert Vec to ndarray types
let x = Array2::from_shape_vec((3, 2), raw_x.into_iter().flatten().collect()).unwrap();
let y = Array1::from_vec(raw_y);

// Train the model
model.fit(&x.view(), &y.view()).unwrap();

// Make predictions
let new_data = Array2::from_shape_vec((1, 2), vec![4.0, 5.0]).unwrap();
let _predictions = model.predict(&new_data.view());

// Save the trained model to a file
model.save_to_path("linear_regression_model.bin").unwrap();

// Load the model from the file
let loaded_model = LinearRegression::load_from_path("linear_regression_model.bin").unwrap();

// Use the loaded model for predictions
let _loaded_predictions = loaded_model.predict(&new_data.view());

// Clone is implemented
let _model_copy = model.clone();

// Debug is implemented
println!("{:?}", model);

§Neural Network Example

Add RustyML to your Cargo.toml:

[dependencies]
rustyml = "*"
# The default feature set is `full`. To slim the build, set `default-features = false` and
# list the features you need, e.g. `features = ["neural_network"]`
# Add `"show_progress"` to show progress bars during training

In your Rust code, write:

use rustyml::neural_network::{
    sequential::Sequential,
    layers::{Activation, Dense},
    optimizers::Adam,
    losses::CategoricalCrossEntropy,
};
use ndarray::Array;

// Create training data
let x = Array::ones((32, 784)).into_dyn(); // 32 samples, 784 features
let y = Array::ones((32, 10)).into_dyn();  // 32 samples, 10 classes

// Build a neural network
let mut model = Sequential::new();
model
    .add(Dense::new(784, 128, Activation::ReLU).unwrap())
    .add(Dense::new(128, 64, Activation::ReLU).unwrap())
    .add(Dense::new(64, 10, Activation::Softmax).unwrap())
    .compile(Adam::new(0.001, 0.9, 0.999, 1e-8, 0.0).unwrap(), CategoricalCrossEntropy::new(false));

// Display model structure
model.summary();

// Train the model
// The returned History holds one loss per epoch, measured during that epoch, not after it
let history = model.fit(&x, &y, 10).unwrap();
println!("Per-epoch loss: {:?}", history.loss());

// Score the model's current weights, an inference-mode pass that changes nothing
println!("Loss after training: {}", model.evaluate(&x, &y).unwrap());

// Save model weights to file
model.save_to_path("model.bin").unwrap();

// Create a new model with the same architecture
let mut new_model = Sequential::new();
new_model
    .add(Dense::new(784, 128, Activation::ReLU).unwrap())
    .add(Dense::new(128, 64, Activation::ReLU).unwrap())
    .add(Dense::new(64, 10, Activation::Softmax).unwrap());

// Load weights from file
new_model.load_from_path("model.bin").unwrap();

// Compile before using (required for training, optional for prediction)
new_model.compile(Adam::new(0.001, 0.9, 0.999, 1e-8, 0.0).unwrap(), CategoricalCrossEntropy::new(false));

// Make predictions with loaded model
let predictions = new_model.predict(&x).unwrap();
println!("Predictions shape: {:?}", predictions.shape());

§Feature Flags

The crate uses feature flags for modular compilation:

FeatureDescription
machine_learningClassical ML algorithms
neural_networkNeural network framework
utilsData preprocessing and dataset splitting
metricsEvaluation metrics
mathNumerical primitives (distances, matrix products, parallel reductions)
fullEnables all of the above
defaultEnables full
show_progressShow progress bars when training

machine_learning, neural_network, utils, and metrics each enable math.

The default enables everything. A scikit-learn workflow reaches across modules (utils::train_test_split -> machine_learning -> metrics), so a fresh cargo add rustyml should have all of it. Features are additive. Naming one does not turn the rest off, so to restrict a build, set default-features = false and list what you need.

Re-exports§

pub use random::clear_global_seed;
pub use random::set_global_seed;

Modules§

error
The crate’s unified error type (error::Error) and its result alias (error::RustymlResult) Error types for RustyML
machine_learning
Classical supervised and unsupervised estimators: regression, classification, clustering, dimensionality reduction, and anomaly detection Machine learning models for clustering, classification, regression, dimensionality reduction, and anomaly detection
math
Shared low-level numeric primitives: distance metrics, gemmkit-backed matrix products, and deterministic parallel reductions Shared low-level numeric primitives used across estimators and metrics
metrics
Model-evaluation metrics for regression, classification, and clustering Model-evaluation metrics for classification, clustering, and regression
neural_network
Neural-network framework: layers, optimizers, loss functions, and the sequential model Neural network primitives: layers, loss functions, optimizers, the sequential model, and the traits that tie them together
prelude
Single-import re-export of the crate’s most commonly used types, traits, and functions Prelude that re-exports the crate’s machine learning, metrics, neural network, and utility items
random
Crate-wide control of pseudo-random number generation for reproducibility Crate-wide control of pseudo-random number generation for reproducibility
traits
Every model and stateful transformer in the crate implements the shared estimator contract (Fit, Predict, Transform, FitTransform) Estimator traits shared by every model and stateful transformer in the crate
tuning
Runtime overrides for the crate’s parallel and serial gate thresholds Runtime overrides for the crate’s parallel and serial gate thresholds
utils
Data preprocessing (normalize, standardize, the stateful scaler family, label encoding) and train/test dataset splitting Utilities for preprocessing and dataset splitting