Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
# for the math-heavy paths)
# - `cargo doc --no-deps` — `RUSTDOCFLAGS=-D warnings` catches
# broken doc links + missing docs
# errors before they ship to docs.rs
# errors before they ship to docs.rs.
# Runs with `--document-private-items`
# so private docs are also gated.
#
# Jobs are independent so a failure in one (e.g. fmt drift) doesn't gate
# the others — you see all the breakages in one CI run instead of
Expand Down Expand Up @@ -94,6 +96,8 @@ jobs:
doc:
name: cargo doc --no-deps
runs-on: ubuntu-latest
env:
RUSTDOCFLAGS: -D warnings
steps:
- uses: actions/checkout@v4
- name: Install Rust stable
Expand All @@ -102,9 +106,4 @@ jobs:
uses: Swatinem/rust-cache@v2
with:
shared-key: doc
# Builds docs without strict warnings — the workspace currently has
# several broken intra-doc links (`FerroError::*` variants, etc.)
# that should be cleaned up as a follow-up PR. Tighten to
# `RUSTDOCFLAGS: -D warnings` once those land. For now, this catches
# syntax-level doc errors that would break the docs.rs build.
- run: cargo doc --workspace --no-deps --document-private-items
4 changes: 2 additions & 2 deletions ferrolearn-bayes/src/conjugate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ const MIN_OBS_VAR: f64 = 1e-12;
///
/// # Edge cases
///
/// - `prior_var ≤ 0` is clipped to [`MIN_OBS_VAR`] (the prior is effectively
/// - `prior_var ≤ 0` is clipped to an internal `MIN_OBS_VAR` floor (the prior is effectively
/// improper but the math still produces a defined posterior dominated by
/// the data).
/// - Any `obs_var_i ≤ 0` is clipped to [`MIN_OBS_VAR`] (degenerate
/// - Any `obs_var_i ≤ 0` is clipped to an internal `MIN_OBS_VAR` floor (degenerate
/// observations get extremely high weight but do not produce NaN).
/// - Empty `observations` returns the prior unchanged.
///
Expand Down
4 changes: 2 additions & 2 deletions ferrolearn-cluster/src/spectral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! 4. **Row-normalize** the embedding matrix so each row has unit L2 norm.
//! 5. **K-Means** clustering on the embedded points with `n_init` restarts.
//!
//! Spectral Clustering does **not** implement [`Predict`](ferrolearn_core::Predict)
//! Spectral Clustering does **not** implement [`ferrolearn_core::Predict`]
//! because there is no simple way to embed new points into the learned eigenspace
//! without refitting.
//!
Expand Down Expand Up @@ -123,7 +123,7 @@ impl<F: Float> SpectralClustering<F> {
///
/// Stores the cluster labels for the training data.
///
/// Spectral Clustering does **not** implement [`Predict`](ferrolearn_core::Predict).
/// Spectral Clustering does **not** implement [`ferrolearn_core::Predict`].
#[derive(Debug, Clone)]
pub struct FittedSpectralClustering<F> {
/// Cluster label for each training sample (0-indexed).
Expand Down
30 changes: 15 additions & 15 deletions ferrolearn-core/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ pub trait Backend: Send + Sync + 'static {
///
/// # Errors
///
/// Returns [`FerroError::ShapeMismatch`] if the inner dimensions of `A`
/// and `B` do not match (i.e., `A.ncols() != B.nrows()`).
/// Returns [`crate::FerroError::ShapeMismatch`] if the inner dimensions
/// of `A` and `B` do not match (i.e., `A.ncols() != B.nrows()`).
fn gemm(a: &Array2<f64>, b: &Array2<f64>) -> FerroResult<Array2<f64>>;

/// Singular Value Decomposition: `A = U * diag(S) * Vt`.
Expand All @@ -53,7 +53,7 @@ pub trait Backend: Send + Sync + 'static {
///
/// # Errors
///
/// Returns [`FerroError::NumericalInstability`] if the SVD fails to converge.
/// Returns [`crate::FerroError::NumericalInstability`] if the SVD fails to converge.
fn svd(a: &Array2<f64>) -> FerroResult<(Array2<f64>, Array1<f64>, Array2<f64>)>;

/// QR decomposition: `A = Q * R`.
Expand All @@ -64,7 +64,7 @@ pub trait Backend: Send + Sync + 'static {
///
/// # Errors
///
/// Returns [`FerroError::NumericalInstability`] if the decomposition fails.
/// Returns [`crate::FerroError::NumericalInstability`] if the decomposition fails.
fn qr(a: &Array2<f64>) -> FerroResult<(Array2<f64>, Array2<f64>)>;

/// Cholesky decomposition: `A = L * L^T` (lower triangular).
Expand All @@ -73,8 +73,8 @@ pub trait Backend: Send + Sync + 'static {
///
/// # Errors
///
/// Returns [`FerroError::NumericalInstability`] if the matrix is not
/// positive definite.
/// Returns [`crate::FerroError::NumericalInstability`] if the matrix is
/// not positive definite.
fn cholesky(a: &Array2<f64>) -> FerroResult<Array2<f64>>;

/// Solve linear system: `A * x = b`.
Expand All @@ -83,9 +83,9 @@ pub trait Backend: Send + Sync + 'static {
///
/// # Errors
///
/// Returns [`FerroError::ShapeMismatch`] if `A` is not square or if
/// `b.len() != A.nrows()`.
/// Returns [`FerroError::NumericalInstability`] if `A` is singular.
/// Returns [`crate::FerroError::ShapeMismatch`] if `A` is not square or
/// if `b.len() != A.nrows()`.
/// Returns [`crate::FerroError::NumericalInstability`] if `A` is singular.
fn solve(a: &Array2<f64>, b: &Array1<f64>) -> FerroResult<Array1<f64>>;

/// Symmetric eigendecomposition: `A = V * diag(eigenvalues) * V^T`.
Expand All @@ -97,9 +97,9 @@ pub trait Backend: Send + Sync + 'static {
///
/// # Errors
///
/// Returns [`FerroError::ShapeMismatch`] if `A` is not square.
/// Returns [`FerroError::NumericalInstability`] if the decomposition fails
/// to converge.
/// Returns [`crate::FerroError::ShapeMismatch`] if `A` is not square.
/// Returns [`crate::FerroError::NumericalInstability`] if the
/// decomposition fails to converge.
fn eigh(a: &Array2<f64>) -> FerroResult<(Array1<f64>, Array2<f64>)>;

/// Matrix determinant.
Expand All @@ -108,7 +108,7 @@ pub trait Backend: Send + Sync + 'static {
///
/// # Errors
///
/// Returns [`FerroError::ShapeMismatch`] if `A` is not square.
/// Returns [`crate::FerroError::ShapeMismatch`] if `A` is not square.
fn det(a: &Array2<f64>) -> FerroResult<f64>;

/// Matrix inverse.
Expand All @@ -117,7 +117,7 @@ pub trait Backend: Send + Sync + 'static {
///
/// # Errors
///
/// Returns [`FerroError::ShapeMismatch`] if `A` is not square.
/// Returns [`FerroError::NumericalInstability`] if `A` is singular.
/// Returns [`crate::FerroError::ShapeMismatch`] if `A` is not square.
/// Returns [`crate::FerroError::NumericalInstability`] if `A` is singular.
fn inv(a: &Array2<f64>) -> FerroResult<Array2<f64>>;
}
4 changes: 2 additions & 2 deletions ferrolearn-core/src/backend_faer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Default backend implementation using `faer` for linear algebra.
//!
//! [`NdarrayFaerBackend`] implements the [`Backend`](crate::backend::Backend)
//! trait by converting between `ndarray::Array2<f64>` and `faer::Mat<f64>`,
//! [`NdarrayFaerBackend`] implements the [`crate::backend::Backend`] trait by
//! converting between `ndarray::Array2<f64>` and `faer::Mat<f64>`,
//! then delegating to `faer`'s high-performance decomposition routines.
//!
//! - **gemm**: uses `ndarray`'s `dot` (which may use optimized BLAS internally).
Expand Down
4 changes: 2 additions & 2 deletions ferrolearn-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
//! pipelines, `std::error::Error` impls).
//! - `faer` (default) -- Enables the [`NdarrayFaerBackend`] using the `faer`
//! crate for pure-Rust linear algebra.
//! - `blas` -- Enables the [`BLASBackend`](backend_blas::BLASBackend) using
//! system BLAS/LAPACK via `ndarray-linalg`.
//! - `blas` -- Enables the `BLASBackend` (feature-gated) using system
//! BLAS/LAPACK via `ndarray-linalg`.
//!
//! # Design Principles
//!
Expand Down
4 changes: 2 additions & 2 deletions ferrolearn-core/src/streaming.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Streaming data adapter for incremental learning.
//!
//! The [`StreamingFitter`] feeds batches from an iterator to a
//! [`PartialFit`](crate::PartialFit) model, enabling online/streaming
//! learning workflows where the full dataset does not fit in memory.
//! [`crate::PartialFit`] model, enabling online/streaming learning workflows
//! where the full dataset does not fit in memory.
//!
//! # Example
//!
Expand Down
2 changes: 1 addition & 1 deletion ferrolearn-covariance/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
//! - [`ledoit_wolf_shrinkage`] — return only the shrinkage coefficient.
//! - [`oas`] — return `(cov, shrinkage)`.
//! - [`log_likelihood`] — Gaussian log-likelihood under a covariance.
//! - [`graphical_lasso`] — one-shot graphical-lasso fit.
//! - [`fn@graphical_lasso`] — one-shot graphical-lasso fit.
//! - [`fast_mcd`] — robust MCD location/cov estimate.

pub mod covariance;
Expand Down
4 changes: 2 additions & 2 deletions ferrolearn-datasets/src/svmlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
//!
//! For simplicity this module returns dense [`ndarray::Array2<F>`] feature
//! matrices, which is adequate for small/medium datasets. For very large
//! sparse data, prefer streaming directly into a [`ferrolearn_sparse`]
//! matrix (out of scope here).
//! sparse data, prefer streaming directly into a `ferrolearn_sparse` matrix
//! (out of scope here).

use ferrolearn_core::FerroError;
use ndarray::{Array1, Array2};
Expand Down
12 changes: 7 additions & 5 deletions ferrolearn-io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
//!
//! ## Feature Flags
//!
//! - **`onnx`** — Enables ONNX protobuf model export via the [`onnx`] module.
//! - **`pmml`** — Enables PMML 4.4 XML model export via the [`pmml`] module.
//! - **`onnx`** — Enables ONNX protobuf model export via the `onnx` module
//! (feature-gated).
//! - **`pmml`** — Enables PMML 4.4 XML model export via the `pmml` module
//! (feature-gated).
//!
//! # Example
//!
Expand Down Expand Up @@ -69,8 +71,8 @@ struct ModelEnvelope {
checksum: u32,
}

/// Serialize `model` to MessagePack bytes, wrap in a [`ModelEnvelope`], and
/// write the envelope to `path`.
/// Serialize `model` to MessagePack bytes, wrap in a private `ModelEnvelope`,
/// and write the envelope to `path`.
///
/// # Errors
///
Expand All @@ -85,7 +87,7 @@ pub fn save_model<T: Serialize>(model: &T, path: impl AsRef<Path>) -> Result<(),
///
/// Validation checks:
/// - Magic bytes must equal `FLRN`.
/// - Schema version must equal [`SCHEMA_VERSION`].
/// - Schema version must equal the internal `SCHEMA_VERSION` constant.
/// - CRC32 of the payload must match the stored checksum.
///
/// # Errors
Expand Down
2 changes: 1 addition & 1 deletion ferrolearn-kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
//! Williams Algorithm 3.2 predictions and `log_marginal_likelihood()` for
//! hyperparameter selection.
//! - **GP Kernels** — RBF, Matern (0.5/1.5/2.5), Constant, White, DotProduct,
//! plus Sum and Product kernel composition via the [`GPKernel`](gp_kernels::GPKernel) trait.
//! plus Sum and Product kernel composition via the [`gp_kernels::GPKernel`] trait.
//! - **[`KernelRidge`]** — Kernel ridge regression in dual form
//! `(K + αI) c = y` with RBF / Polynomial / Linear / Sigmoid / Laplacian
//! / Cosine kernels.
Expand Down
2 changes: 1 addition & 1 deletion ferrolearn-linear/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
//! - The unfitted struct (e.g., `LinearRegression<F>`) holds hyperparameters
//! and implements [`Fit`](ferrolearn_core::Fit).
//! - Calling `fit()` produces a new fitted type (e.g., `FittedLinearRegression<F>`)
//! that implements [`Predict`](ferrolearn_core::Predict).
//! that implements [`ferrolearn_core::Predict`].
//! - Calling `predict()` on an unfitted model is a compile-time error.
//!
//! # Pipeline Integration
Expand Down
8 changes: 4 additions & 4 deletions ferrolearn-linear/src/nu_svm.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
//! Nu-parameterized Support Vector Machines.
//!
//! This module provides [`NuSVC`] (classification) and [`NuSVR`] (regression),
//! which are nu-parameterized variants of [`SVC`](super::svm::SVC) and
//! [`SVR`](super::svm::SVR). Instead of setting the penalty parameter `C`
//! which are nu-parameterized variants of [`super::svm::SVC`] and
//! [`super::svm::SVR`]. Instead of setting the penalty parameter `C`
//! directly, the user specifies `nu` in `(0, 1]`, which is an upper bound on
//! the fraction of training errors and a lower bound on the fraction of
//! support vectors.
//!
//! # Internals
//!
//! `NuSVC` converts `nu` to an equivalent `C = 1 / (nu * n_samples)` and
//! delegates to [`SVC`](super::svm::SVC). `NuSVR` converts `nu` to
//! delegates to [`super::svm::SVC`]. `NuSVR` converts `nu` to
//! `epsilon = 0` and `C = 1 / (nu * n_samples)`, delegating to
//! [`SVR`](super::svm::SVR).
//! [`super::svm::SVR`].
//!
//! # Examples
//!
Expand Down
2 changes: 1 addition & 1 deletion ferrolearn-metrics/src/clustering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ fn entropy_from_counts(counts: &[u64], n: f64) -> f64 {
/// Expected Mutual Information under random permutations.
///
/// Uses the exact combinatorial formula:
/// E[MI] = sum_{i,j} sum_{n_ij} p(n_ij) * (n_ij/n) * log((n * n_ij) / (a_i * b_j))
/// `E[MI] = sum_{i,j} sum_{n_ij} p(n_ij) * (n_ij/n) * log((n * n_ij) / (a_i * b_j))`
///
/// where the sum over n_ij runs from max(1, a_i + b_j - n) to min(a_i, b_j).
fn expected_mutual_info(a: &[u64], b: &[u64], n: u64) -> f64 {
Expand Down
2 changes: 1 addition & 1 deletion ferrolearn-metrics/src/pairwise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ where
fn pairwise(&self, x: &Array2<F>, y: &Array2<F>) -> Result<Array2<F>, FerroError>;

/// Convenience: compute the distance from a single point `a` to a single
/// point `b`. Default implementation calls [`pairwise`] on `1 × d`
/// point `b`. Default implementation calls [`Self::pairwise`] on `1 × d`
/// matrices and returns the single entry.
fn distance(&self, a: &ndarray::Array1<F>, b: &ndarray::Array1<F>) -> Result<F, FerroError> {
let mut x = Array2::<F>::zeros((1, a.len()));
Expand Down
3 changes: 2 additions & 1 deletion ferrolearn-model-sel/src/grid_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ use crate::param_grid::ParamSet;
// CvResults
// ---------------------------------------------------------------------------

/// Results collected during a [`GridSearchCV`] or [`RandomizedSearchCV`] run.
/// Results collected during a [`GridSearchCV`] or
/// [`crate::RandomizedSearchCV`] run.
///
/// Each entry corresponds to one parameter combination that was evaluated.
#[derive(Debug, Clone)]
Expand Down
6 changes: 3 additions & 3 deletions ferrolearn-model-sel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
//! - [`cross_validate`] — like `cross_val_score` but with timing and optional
//! training scores.
//! - [`cross_val_predict`] — generate out-of-fold predictions for every sample.
//! - [`learning_curve`] — train/test scores for varying training set sizes.
//! - [`validation_curve`] — train/test scores for varying hyperparameter values.
//! - [`learning_curve()`] — train/test scores for varying training set sizes.
//! - [`validation_curve()`] — train/test scores for varying hyperparameter values.
//! - [`GridSearchCV`] — exhaustive hyperparameter search over a parameter grid.
//! - [`RandomizedSearchCV`] — randomized hyperparameter search over distributions.
//! - [`TimeSeriesSplit`] — time-series aware cross-validation splitter.
//! - [`HalvingGridSearchCV`] — successive-halving hyperparameter search.
//! - [`HalvingRandomSearchCV`] — successive-halving search with random sampling.
//! - [`param_grid!`] — macro for building Cartesian-product parameter grids.
//! - [`macro@param_grid`] — macro for building Cartesian-product parameter grids.
//! - [`ParamValue`] / [`ParamSet`] — hyperparameter value and set types.
//! - [`distributions`] — sampling distributions for [`RandomizedSearchCV`].
//! - [`CalibratedClassifierCV`] — probability calibration via cross-validation.
Expand Down
8 changes: 4 additions & 4 deletions ferrolearn-model-sel/src/param_grid.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Parameter grid types and the [`param_grid!`] macro.
//! Parameter grid types and the [`macro@crate::param_grid`] macro.
//!
//! This module defines:
//!
//! - [`ParamValue`] — a dynamically-typed hyperparameter value.
//! - [`ParamSet`] — a single parameter configuration (`HashMap<String, ParamValue>`).
//! - [`param_grid!`] — a macro that builds the Cartesian product of parameter
//! lists as `Vec<ParamSet>`.
//! - [`macro@crate::param_grid`] — a macro that builds the Cartesian product
//! of parameter lists as `Vec<ParamSet>`.
//!
//! # Example
//!
Expand Down Expand Up @@ -50,7 +50,7 @@ impl std::fmt::Display for ParamValue {

/// A single set of hyperparameter name–value pairs.
///
/// Created by [`param_grid!`] or built manually.
/// Created by [`macro@crate::param_grid`] or built manually.
pub type ParamSet = HashMap<String, ParamValue>;

// ---------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion ferrolearn-model-sel/src/random_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! [`RandomizedSearchCV`] samples `n_iter` random parameter combinations from
//! the supplied distributions, evaluates each using cross-validation, and
//! records the results in a [`CvResults`] struct (re-exported from
//! [`grid_search`]).
//! [`crate::grid_search`]).
//!
//! # Example
//!
Expand Down
2 changes: 1 addition & 1 deletion ferrolearn-model-sel/src/self_training.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! [`SelfTrainingClassifier`] is a meta-estimator that wraps a supervised
//! classifier and iteratively assigns pseudo-labels to unlabeled samples
//! whose predicted probabilities exceed a confidence [`threshold`].
//! whose predicted probabilities exceed a confidence `threshold`.
//!
//! # Algorithm
//!
Expand Down
2 changes: 1 addition & 1 deletion ferrolearn-neighbors/src/knn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ impl<F: Float + Send + Sync + 'static> FittedKNeighborsClassifier<F> {
///
/// # Errors
///
/// As [`kneighbors_impl`].
/// As the internal `kneighbors_impl`.
pub fn kneighbors(
&self,
x: &Array2<F>,
Expand Down
4 changes: 2 additions & 2 deletions ferrolearn-neighbors/src/local_outlier_factor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ impl<F: Float + Send + Sync + 'static> FittedLocalOutlierFactor<F> {
///
/// # Errors
///
/// As [`compute_lof`](Self::compute_lof).
/// As the internal `compute_lof`.
pub fn score_samples(&self, x: &Array2<F>) -> Result<Array1<F>, FerroError> {
let lof = self.compute_lof(x)?;
Ok(Array1::from_iter(lof.into_iter().map(|v| -v)))
Expand All @@ -483,7 +483,7 @@ impl<F: Float + Send + Sync + 'static> FittedLocalOutlierFactor<F> {
///
/// # Errors
///
/// As [`compute_lof`](Self::compute_lof).
/// As the internal `compute_lof`.
pub fn decision_function(&self, x: &Array2<F>) -> Result<Array1<F>, FerroError> {
let lof = self.compute_lof(x)?;
Ok(Array1::from_iter(
Expand Down
Loading
Loading