sklears_compose/plugin_architecture/
exampleregressor_traits.rs1use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ArrayView2};
13use sklears_core::{
14 error::{Result as SklResult, SklearsError},
15 traits::Estimator,
16 types::Float,
17};
18use std::any::Any;
19
20use super::functions::{PluginComponent, PluginEstimator};
21use super::types::{ComponentConfig, ComponentContext, ExampleRegressor};
22
23impl PluginComponent for ExampleRegressor {
24 fn component_type(&self) -> &'static str {
25 "example_regressor"
26 }
27 fn config(&self) -> &ComponentConfig {
28 &self.config
29 }
30 fn initialize(&mut self, _context: &ComponentContext) -> SklResult<()> {
31 Ok(())
32 }
33 fn clone_component(&self) -> Box<dyn PluginComponent> {
34 Box::new(self.clone())
35 }
36 fn as_any(&self) -> &dyn Any {
37 self
38 }
39 fn as_any_mut(&mut self) -> &mut dyn Any {
40 self
41 }
42}
43
44impl PluginEstimator for ExampleRegressor {
45 fn fit(&mut self, x: &ArrayView2<'_, Float>, y: &ArrayView1<'_, Float>) -> SklResult<()> {
46 let n_features = x.ncols();
47 let mut coefficients = Array1::zeros(n_features);
48 let y_f64 = y.mapv(|v| v);
49 for _ in 0..1000 {
50 let predictions = x.dot(&coefficients);
51 let errors = &predictions - &y_f64;
52 let gradient = x.t().dot(&errors) / x.nrows() as f64;
53 coefficients = coefficients - self.learning_rate * gradient;
54 }
55 self.coefficients = Some(coefficients);
56 self.fitted = true;
57 Ok(())
58 }
59 fn predict(&self, x: &ArrayView2<'_, Float>) -> SklResult<Array1<f64>> {
60 if !self.fitted {
61 return Err(SklearsError::InvalidOperation(
62 "Estimator must be fitted before predict".to_string(),
63 ));
64 }
65 let coefficients = self.coefficients.as_ref().ok_or_else(|| {
66 SklearsError::InvalidOperation("Coefficients not initialized".to_string())
67 })?;
68 Ok(x.dot(coefficients))
69 }
70 fn score(&self, x: &ArrayView2<'_, Float>, y: &ArrayView1<'_, Float>) -> SklResult<f64> {
71 let predictions = self.predict(x)?;
72 let y_f64 = y.mapv(|v: Float| v);
73 let y_mean = y_f64.mean().ok_or_else(|| {
74 SklearsError::InvalidOperation("Cannot compute mean of empty array".to_string())
75 })?;
76 let ss_res = (&predictions - &y_f64).mapv(|x: f64| x.powi(2)).sum();
77 let ss_tot = y_f64.mapv(|x: f64| (x - y_mean).powi(2)).sum();
78 Ok(1.0 - ss_res / ss_tot)
79 }
80 fn is_fitted(&self) -> bool {
81 self.fitted
82 }
83 fn feature_importances(&self) -> Option<Array1<f64>> {
84 self.coefficients
85 .as_ref()
86 .map(|coefs: &Array1<f64>| coefs.mapv(f64::abs))
87 }
88}