sklears_feature_selection/genetic_optimization/
costsensitiveobjective_traits.rs1use super::functions::*;
12use super::types::*;
13use scirs2_core::ndarray::{Array1, Array2};
14use sklears_core::error::{Result as SklResult, SklearsError};
15
16impl ObjectiveFunction for CostSensitiveObjective {
17 fn evaluate(
18 &self,
19 x: &Array2<f64>,
20 y_classif: Option<&Array1<i32>>,
21 y_regression: Option<&Array1<f64>>,
22 feature_mask: &[bool],
23 ) -> SklResult<f64> {
24 let selected_indices: Vec<usize> = feature_mask
25 .iter()
26 .enumerate()
27 .filter_map(|(i, &selected)| if selected { Some(i) } else { None })
28 .collect();
29 if selected_indices.is_empty() {
30 return Ok(0.0);
31 }
32 let total_cost: f64 = selected_indices
33 .iter()
34 .map(|&idx| self.feature_costs[idx])
35 .sum();
36 let max_cost: f64 = self.feature_costs.sum();
37 let normalized_cost = if max_cost > 0.0 {
38 total_cost / max_cost
39 } else {
40 0.0
41 };
42 let mut total_performance = 0.0;
43 if let Some(y) = y_classif {
44 for &idx in &selected_indices {
45 let feature = x.column(idx).to_owned();
46 let y_float = y.mapv(|v| v as f64);
47 let correlation = compute_pearson_correlation(&feature, &y_float).abs();
48 total_performance += correlation;
49 }
50 } else if let Some(y) = y_regression {
51 for &idx in &selected_indices {
52 let feature = x.column(idx).to_owned();
53 let correlation = compute_pearson_correlation(&feature, y).abs();
54 total_performance += correlation;
55 }
56 } else {
57 return Err(SklearsError::InvalidInput(
58 "Need either classification or regression target".to_string(),
59 ));
60 }
61 let avg_performance = total_performance / selected_indices.len() as f64;
62 let cost_sensitive_score =
63 (1.0 - self.cost_weight) * avg_performance + self.cost_weight * (1.0 - normalized_cost);
64 Ok(cost_sensitive_score)
65 }
66 fn name(&self) -> &str {
67 "cost_sensitive"
68 }
69 fn clone_box(&self) -> Box<dyn ObjectiveFunction> {
70 Box::new(self.clone())
71 }
72}