nabla_ml/
nabla.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use crate::nab_array::NDArray;

impl NDArray {
    /// Calculates the gradients (nabla) for linear regression with multiple features
    ///
    /// # Arguments
    ///
    /// * `X` - The input feature matrix
    /// * `y` - The actual target values
    /// * `y_pred` - The predicted values
    /// * `N` - The number of samples
    ///
    /// # Returns
    ///
    /// A vector containing the gradients for each parameter
    #[allow(non_snake_case)]
    #[allow(dead_code)]
    pub fn nabla(X: &NDArray, y: &NDArray, y_pred: &NDArray, N: usize) -> Vec<f64> {
        let mut gradients = vec![0.0; X.shape()[1] + 1]; // +1 for the intercept
        let errors: Vec<f64> = y.data().iter().zip(y_pred.data().iter()).map(|(&t, &p)| t - p).collect();

        // Gradient for the intercept
        gradients[0] = -(2.0 / N as f64) * errors.iter().sum::<f64>();

        // Gradients for the features
        for j in 0..X.shape()[1] {
            gradients[j + 1] = -(2.0 / N as f64) * X.data().iter().skip(j).step_by(X.shape()[1]).zip(errors.iter()).map(|(&x, &e)| x * e).sum::<f64>();
        }

        gradients
    }
}