Switching to ndarray
Rust’s standard library does not include built-in numerical computing tools. The ndarray crate provides efficient n-dimensional arrays and vectorized operations.
This example uses:
Array1<f64>for 1D arrays.mean(),.dot(), and.mapv()for basic mathematical operations- Broadcasting (
x * beta) for scalar–array multiplication
Fit function
The impl of the fit function is shown below. As you can see, we essentially replaced Vec<f64> by Array1<f64> here and there. This allows us to rely on .mean, dot, or mapv to perform basic linear algebra. Given that self.beta is defined as an Option<f64>, we return Some(num / denom), from which Rust can infer the type Some(f64).
#![allow(unused)] fn main() { impl RidgeEstimator { /// Creates a new, unfitted Ridge estimator. /// /// # Returns /// A `RidgeEstimator` with `beta` set to `None`. pub fn new() -> Self { Self { beta: None } } /// Fits the Ridge regression model using 1D input and output arrays. /// /// This function computes the coefficient `beta` using the closed-form /// solution with L2 regularization. /// /// # Arguments /// - `x`: Input features as a 1D `Array1<f64>`. /// - `y`: Target values as a 1D `Array1<f64>`. /// - `lambda2`: The regularization strength (λ²). pub fn fit(&mut self, x: &Array1<f64>, y: &Array1<f64>, lambda2: f64) { let n: usize = x.len(); assert!(n > 0); assert_eq!(x.len(), y.len(), "x and y must have the same length"); // mean returns None if the array is empty, so we need to unwrap it let x_mean: f64 = x.mean().unwrap(); let y_mean: f64 = y.mean().unwrap(); let num: f64 = (x - x_mean).dot(&(y - y_mean)); let denom: f64 = (x - x_mean).mapv(|z| z.powi(2)).sum() + lambda2 * (n as f64); self.beta = Some(num / denom); } } }