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
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
* [Linear Regression](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/linear_regression.rs)
* Loss Function
* [Hinge Loss](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/loss_function/hinge_loss.rs)
* [Huber Loss](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/loss_function/huber_loss.rs)
* [Kl Divergence Loss](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/loss_function/kl_divergence_loss.rs)
* [Mean Absolute Error Loss](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/loss_function/mean_absolute_error_loss.rs)
* [Mean Squared Error Loss](https://github.com/TheAlgorithms/Rust/blob/master/src/machine_learning/loss_function/mean_squared_error_loss.rs)
Expand Down
74 changes: 74 additions & 0 deletions src/machine_learning/loss_function/huber_loss.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/// Computes the Huber loss between arrays of true and predicted values.
///
/// # Arguments
///
/// * `y_true` - An array of true values.
/// * `y_pred` - An array of predicted values.
/// * `delta` - The threshold parameter that controls the linear behavior of the loss function.
///
/// # Returns
///
/// The average Huber loss for all pairs of true and predicted values.
pub fn huber_loss(y_true: &[f64], y_pred: &[f64], delta: f64) -> Option<f64> {
if y_true.len() != y_pred.len() || y_pred.is_empty() {
return None;
}

let loss: f64 = y_true
.iter()
.zip(y_pred.iter())
.map(|(&true_val, &pred_val)| {
let residual = (true_val - pred_val).abs();
match residual {
r if r <= delta => 0.5 * r.powi(2),
_ => delta * residual - 0.5 * delta.powi(2),
Comment thread
sozelfist marked this conversation as resolved.
Resolved
}
})
.sum();

Some(loss / (y_pred.len() as f64))
}

#[cfg(test)]
mod tests {
use super::*;

macro_rules! huber_loss_tests {
($($name:ident: $test_case:expr,)*) => {
$(
#[test]
fn $name() {
let (y_true, y_pred, delta, expected_loss) = $test_case;
assert_eq!(huber_loss(&y_true, &y_pred, delta), expected_loss);
}
)*
};
}

huber_loss_tests! {
test_huber_loss_residual_less_than_delta: (
vec![10.0, 8.0, 12.0],
vec![9.0, 7.0, 11.0],
1.0,
Some(0.5)
),
test_huber_loss_residual_greater_than_delta: (
vec![3.0, 5.0, 7.0],
vec![2.0, 4.0, 8.0],
0.5,
Some(0.375)
),
test_huber_loss_invalid_length: (
vec![10.0, 8.0, 12.0],
vec![7.0, 6.0],
1.0,
None
),
test_huber_loss_empty_prediction: (
vec![10.0, 8.0, 12.0],
vec![],
1.0,
None
),
}
}
2 changes: 2 additions & 0 deletions src/machine_learning/loss_function/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod hinge_loss;
mod huber_loss;
mod kl_divergence_loss;
mod mean_absolute_error_loss;
mod mean_squared_error_loss;

pub use self::hinge_loss::hng_loss;
pub use self::huber_loss::huber_loss;
pub use self::kl_divergence_loss::kld_loss;
pub use self::mean_absolute_error_loss::mae_loss;
pub use self::mean_squared_error_loss::mse_loss;
1 change: 1 addition & 0 deletions src/machine_learning/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub use self::cholesky::cholesky;
pub use self::k_means::k_means;
pub use self::linear_regression::linear_regression;
pub use self::loss_function::hng_loss;
pub use self::loss_function::huber_loss;
pub use self::loss_function::kld_loss;
pub use self::loss_function::mae_loss;
pub use self::loss_function::mse_loss;
Expand Down