tensorlogic_train/loss/
hingeloss_traits.rs1use crate::{TrainError, TrainResult};
11use scirs2_core::ndarray::{Array, ArrayView, Ix2};
12
13use super::functions::Loss;
14use super::types::HingeLoss;
15
16impl Default for HingeLoss {
17 fn default() -> Self {
18 Self { margin: 1.0 }
19 }
20}
21
22impl Loss for HingeLoss {
23 fn compute(
24 &self,
25 predictions: &ArrayView<f64, Ix2>,
26 targets: &ArrayView<f64, Ix2>,
27 ) -> TrainResult<f64> {
28 if predictions.shape() != targets.shape() {
29 return Err(TrainError::LossError(format!(
30 "Shape mismatch: predictions {:?} vs targets {:?}",
31 predictions.shape(),
32 targets.shape()
33 )));
34 }
35 let mut total_loss = 0.0;
36 let n = predictions.nrows() as f64;
37 for i in 0..predictions.nrows() {
38 for j in 0..predictions.ncols() {
39 let pred = predictions[[i, j]];
40 let target = targets[[i, j]];
41 let loss = (self.margin - target * pred).max(0.0);
42 total_loss += loss;
43 }
44 }
45 Ok(total_loss / n)
46 }
47 fn gradient(
48 &self,
49 predictions: &ArrayView<f64, Ix2>,
50 targets: &ArrayView<f64, Ix2>,
51 ) -> TrainResult<Array<f64, Ix2>> {
52 let mut grad = Array::zeros(predictions.raw_dim());
53 let n = predictions.nrows() as f64;
54 for i in 0..predictions.nrows() {
55 for j in 0..predictions.ncols() {
56 let pred = predictions[[i, j]];
57 let target = targets[[i, j]];
58 if self.margin - target * pred > 0.0 {
59 grad[[i, j]] = -target / n;
60 }
61 }
62 }
63 Ok(grad)
64 }
65}