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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//! Loss functions for neural networks
//!
//! This module provides common loss functions used in neural networks for training.
//! Loss functions measure how well the model's predictions match the target values,
//! providing a signal for optimization during training.
//! # Overview
//! Loss functions serve two main purposes in neural networks:
//! 1. **Forward pass**: Calculate the scalar loss value between predictions and targets
//! 2. **Backward pass**: Calculate gradients needed for backpropagation
//! The choice of loss function depends on your task type and requirements.
//! # Available Loss Functions
//! - **MeanSquaredError**: For regression tasks, measures squared differences
//! - **CrossEntropyLoss**: For classification tasks, combines softmax and negative log-likelihood
//! - **FocalLoss**: For imbalanced classification, focuses on hard examples
//! - **ContrastiveLoss**: For learning embeddings, brings similar items closer
//! - **TripletLoss**: For metric learning, enforces relative distances
//! # Examples
//! ## Regression with Mean Squared Error
//! ```rust
//! use scirs2_neural::losses::{Loss, MeanSquaredError};
//! use scirs2_core::ndarray::Array;
//! # fn example() -> scirs2_neural::error::Result<()> {
//! let mse = MeanSquaredError::new();
//! // Predictions and targets for regression
//! let predictions = Array::from_vec(vec![1.5, 2.3, 0.8]).into_dyn();
//! let targets = Array::from_vec(vec![1.0, 2.0, 1.0]).into_dyn();
//! // Calculate loss
//! let loss_value = mse.forward(&predictions, &targets)?;
//! println!("MSE Loss: {:.4}", loss_value);
//! // Calculate gradients for backpropagation
//! let gradients = mse.backward(&predictions, &targets)?;
//! println!("Gradients: {:?}", gradients);
//! # Ok(())
//! # }
//! ```
//! ## Classification with Cross Entropy
//! use scirs2_neural::losses::{Loss, CrossEntropyLoss};
//! let ce_loss = CrossEntropyLoss::default();
//! // Logits (raw predictions) for 3-class classification
//! let logits = Array::from_shape_vec((2, 3), vec![
//! 1.0, 2.0, 0.5, // Sample 1
//! 0.8, 0.2, 1.5, // Sample 2
//! ])?.into_dyn();
//! // One-hot encoded targets
//! let targets = Array::from_shape_vec((2, 3), vec![
//! 0.0, 1.0, 0.0, // Sample 1: class 1
//! 0.0, 0.0, 1.0, // Sample 2: class 2
//! // Calculate cross-entropy loss
//! let loss_value = ce_loss.forward(&logits, &targets)?;
//! println!("Cross-Entropy Loss: {:.4}", loss_value);
//! // Get gradients for backpropagation
//! let gradients = ce_loss.backward(&logits, &targets)?;
//! ## Handling Class Imbalance with Focal Loss
//! use scirs2_neural::losses::{Loss, FocalLoss};
//! // Focal loss with gamma=2.0, alpha=0.25 (typical values)
//! let focal_loss = FocalLoss::new(2.0, Some(0.25), 1e-10);
//! let predictions = Array::from_shape_vec((2, 2), vec![
//! 0.9, 0.1, // High confidence prediction
//! 0.6, 0.4, // Lower confidence prediction
//! let targets = Array::from_shape_vec((2, 2), vec![
//! 1.0, 0.0, // Correct prediction
//! 1.0, 0.0, // Incorrect prediction (will get higher loss)
//! let loss_value = focal_loss.forward(&predictions, &targets)?;
//! // Focal loss will be higher for the incorrect, hard example
//! println!("Focal Loss: {:.4}", loss_value);
//! ## Metric Learning with Triplet Loss
//! use scirs2_neural::losses::{Loss, TripletLoss};
//! let triplet_loss = TripletLoss::new(1.0); // margin = 1.0
//! // Embeddings: [anchor, positive, negative]
//! let anchor = Array::from_vec(vec![1.0, 0.0, 0.0]).into_dyn();
//! let positive = Array::from_vec(vec![0.9, 0.1, 0.0]).into_dyn(); // Similar to anchor
//! let negative = Array::from_vec(vec![0.0, 0.0, 1.0]).into_dyn(); // Different from anchor
//! // Stack into batch format
//! let embeddings = Array::from_shape_vec((3, 3), vec![
//! 1.0, 0.0, 0.0, // anchor
//! 0.9, 0.1, 0.0, // positive
//! 0.0, 0.0, 1.0, // negative
//! // Dummy targets (not used in triplet loss)
//! let targets = Array::zeros((3,)).into_dyn();
//! let loss_value = triplet_loss.forward(&embeddings, &targets)?;
//! println!("Triplet Loss: {:.4}", loss_value);
//! # Choosing the Right Loss Function
//! ## For Regression:
//! - **MeanSquaredError**: Most common, penalizes large errors heavily
//! - **Mean Absolute Error**: More robust to outliers (implement if needed)
//! - **Huber Loss**: Combines benefits of MSE and MAE (implement if needed)
//! ## For Classification:
//! - **CrossEntropyLoss**: Standard choice for balanced multi-class problems
//! - **FocalLoss**: Better for imbalanced datasets, focuses on hard examples
//! - **Binary Cross-Entropy**: For binary classification (implement if needed)
//! ## For Similarity Learning:
//! - **ContrastiveLoss**: For learning embeddings with positive/negative pairs
//! - **TripletLoss**: For learning relative similarities with triplets
//! # Training Tips
//! 1. **Scale your loss**: If loss values are too large/small, consider scaling
//! 2. **Monitor gradients**: Use backward() to check gradient magnitudes
//! 3. **Combine losses**: You can combine multiple loss functions for complex objectives
//! 4. **Loss scheduling**: Consider changing loss function or parameters during training
use crateResult;
use Array;
use ;
use Debug;
/// Trait for loss functions used in neural networks
///
/// Loss functions compute the error between model predictions and target values,
/// providing both the scalar loss value and gradients needed for training.
/// # Examples
/// ```rust
/// use scirs2_neural::losses::{Loss, MeanSquaredError};
/// use scirs2_core::ndarray::Array;
/// # fn example() -> scirs2_neural::error::Result<()> {
/// let loss_fn = MeanSquaredError::new();
/// let predictions = Array::from_vec(vec![1.0, 2.0, 3.0]).into_dyn();
/// let targets = Array::from_vec(vec![1.1, 1.9, 3.2]).into_dyn();
/// // Forward pass: compute loss value
/// let loss_value = loss_fn.forward(&predictions, &targets)?;
/// assert!(loss_value >= 0.0); // Loss is non-negative
/// // Backward pass: compute gradients
/// let gradients = loss_fn.backward(&predictions, &targets)?;
/// assert_eq!(gradients.shape(), predictions.shape());
/// # Ok(())
/// # }
/// ```
pub use ContrastiveLoss;
pub use CrossEntropyLoss;
pub use FocalLoss;
pub use ;
pub use MeanAbsoluteError;
pub use MeanSquaredError;
pub use TripletLoss;