Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Architecture

How datarust is organized and the design decisions behind it.

Design philosophy

  1. Zero external dependencies by default. cargo add datarust pulls in nothing. All linear algebra — Jacobi eigendecomposition, one-sided Jacobi SVD, Cholesky factorization, coordinate descent, IRLS — is pure Rust. Feature flags (serde, rayon, matrixmultiply) opt in to extras.

  2. sklearn-inspired but Rust-native. The familiar fit/transform/predict API, but using Result (panic-free), builder-pattern config, and enum-based parameters (Norm::L2, ImputeStrategy::Median) instead of strings.

  3. Type-safe modality separation. Four traits enforce that numeric, categorical, target, and label data go to the right transformer. The compiler catches misuse.

  4. Composability via type-erased enums. TransformerKind, CategoricalTransformerKind, and TargetTransformerKind allow heterogeneous pipelines that are still serializable.

Module layout

src/
├── lib.rs                 # Crate root: re-exports + module declarations
├── error.rs               # DatarustError enum + Result alias
├── traits.rs              # Estimator, Predictor, Regressor, Classifier, transformers, FeatureNames
├── matrix.rs              # Matrix (f64 flat), StrMatrix, SparseMatrix (CSR)
├── stats.rs               # Column statistics, covariance/correlation
├── pipeline.rs            # Sequential and supervised Pipeline
├── transformer_kind.rs    # TransformerKind enum (type erasure)
├── categorical_kind.rs    # CategoricalTransformerKind enum
├── target_kind.rs         # TargetTransformerKind enum
├── function_transformer.rs
├── polynomial.rs          # PolynomialFeatures
├── serialize.rs           # JSON save/load (serde feature)
├── datasets/              # Iris, Breast Cancer, Wine, Diabetes (datasets feature)
├── linalg/
│   └── cholesky.rs        # Cholesky decomposition + SPD solver
├── scaler/                # 9 transformers (standard, minmax, robust, ...)
├── encoder/               # 5 encoders (onehot, ordinal, label, target, frequency)
├── imputer/               # SimpleImputer, KnnImputer
├── selection/             # VarianceThreshold, SelectKBest
├── decomposition/         # PCA, TruncatedSVD, Jacobi, randomized_svd
├── linear_model/          # LinearRegression, Ridge, Lasso, LogisticRegression
├── metrics/
│   ├── regression.rs      # MSE, MAE, R², max_error, explained_variance
│   └── classification.rs  # accuracy, precision, recall, F1, confusion_matrix, log_loss
├── model_selection/
│   ├── split.rs           # train_test_split
│   ├── kfold.rs           # KFold, StratifiedKFold
│   ├── cross_val.rs       # cross_val_score
│   └── rng.rs             # shared xorshift64 PRNG
└── compose/
    ├── column_transformer.rs
    └── output.rs

Trait hierarchy

TraitData flowImplementors
TransformerMatrix → Matrixall scalers, PCA, TruncatedSVD, PolynomialFeatures, VarianceThreshold, SelectKBest, imputers, FunctionTransformer
Predictorfit(X, y) + predict(X) → Vec<f64>all linear models and supervised pipelines
Regressorcontinuous-prediction semanticsLinearRegression, Ridge, Lasso
Classifierclass-label prediction semanticsLogisticRegression
CategoricalTransformerStrMatrix → MatrixOneHotEncoder, OrdinalEncoder, FrequencyEncoder
TargetTransformerfit(StrMatrix, y)TargetEncoder
LabelTransformer&[String] ↔ Vec<usize>LabelEncoder
FeatureNamesoutput column namesevery output-producing transformer

Solver infrastructure

Three distinct solver families, all pure-Rust, in linalg/:

  1. Cholesky (linalg::cholesky) — symmetric positive-definite system solver. Used by LinearRegression, Ridge, and LogisticRegression (per IRLS iteration).
  2. Coordinate descent (Lasso) — soft-thresholding iteration for L1-regularized problems.
  3. IRLS (LogisticRegression) — Newton-Raphson on the logistic loss, solving a weighted least-squares system each iteration.

All three are backed by the shared Matrix::matmul for forming Gram matrices, which dispatches to a tuned GEMM under the matrixmultiply feature.

Error handling

Hand-rolled DatarustError enum (no anyhow/thiserror, consistent with the zero-dependency ethos). Every fallible public API returns Result<T, DatarustError>. The variant set is ML-domain-specific (NotFitted, UnknownCategory, Singular, etc.), more informative than a generic error blob.