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)
├── rng.rs                 # public xorshift64* Rng (foundation module)
├── 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)
├── label_space.rs         # Label vocabulary (fit/encode/decode)
├── 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
├── tree/                  # CART kernel: estimators, splitter, node arena
├── ensemble.rs            # RandomForestClassifier / RandomForestRegressor
├── cluster/               # KMeans
├── 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 re-exported from src/rng.rs)
└── 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, decision trees, random forests, and supervised pipelines
Regressorcontinuous-prediction semanticsLinearRegression, Ridge, Lasso, DecisionTreeRegressor, RandomForestRegressor
Classifierclass-label prediction semanticsLogisticRegression, DecisionTreeClassifier, RandomForestClassifier
PredictProbapredict_proba(X) → MatrixLogisticRegression, DecisionTreeClassifier, RandomForestClassifier
CategoricalTransformerStrMatrix → MatrixOneHotEncoder, OrdinalEncoder, FrequencyEncoder
TargetTransformerfit(StrMatrix, y)TargetEncoder
LabelTransformer&[String] ↔ Vec<usize>LabelEncoder
FeatureNamesoutput column namesevery output-producing transformer

Solver infrastructure

Four distinct solver families, all pure-Rust:

  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.
  4. CART splitter + forest seeding (tree/splitter.rs, ensemble.rs) — an exact transliteration of sklearn’s BestSplitter/DensePartitioner criterion accumulation, plus a local MT19937 “legacy RandomState” clone that seeds bootstrap samples identically to sklearn’s forests.

The first three are backed by the shared Matrix::matmul for forming Gram matrices, which dispatches to a tuned GEMM under the matrixmultiply feature; the tree kernel is allocation-light comparison sort + prefix accumulation and needs no BLAS at all.

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.