meuron/cost/
binary_cross_entropy.rs1use crate::backend::Backend;
2use crate::backend::unary_ops;
3use crate::cost::Cost;
4use ndarray::Dimension;
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Copy, Serialize, Deserialize)]
8pub struct BinaryCrossEntropy;
9
10impl<B: Backend> Cost<B> for BinaryCrossEntropy {
11 fn loss<D: Dimension>(&self, predicted: &B::Tensor<D>, target: &B::Tensor<D>) -> f32 {
12 let eps = 1e-15_f32;
13 let c = B::clamp(predicted, eps, 1.0 - eps);
14 let ln_c = B::unary(&c, unary_ops::LN);
15 let ln_1mc = B::unary(&B::scalar_sub(1.0, &c), unary_ops::LN);
16 let loss = B::add(
17 &B::mul(target, &ln_c),
18 &B::mul(&B::scalar_sub(1.0, target), &ln_1mc),
19 );
20 -B::mean(&loss).unwrap_or(0.0)
21 }
22
23 fn gradient<D: Dimension>(
24 &self,
25 predicted: &B::Tensor<D>,
26 target: &B::Tensor<D>,
27 ) -> B::Tensor<D> {
28 let eps = 1e-15_f32;
29 let c = B::clamp(predicted, eps, 1.0 - eps);
30 let c1mc = B::mul(&c, &B::scalar_sub(1.0, &c));
31 B::div(&B::sub(&c, target), &c1mc)
32 }
33}