#[cfg(feature = "ml")]
use ndarray::{Array1, Array2};
#[cfg(feature = "ml")]
#[derive(Clone, Debug)]
pub struct DenseLayer {
pub weights: Array2<f32>,
pub bias: Array1<f32>,
}
#[cfg(feature = "ml")]
impl DenseLayer {
pub fn new(input_size: usize, output_size: usize) -> Self {
use ndarray_rand::RandomExt;
use rand_distr::Normal;
let dist = Normal::new(0.0, 0.1).expect("valid distribution");
let weights = Array2::random((input_size, output_size), dist);
let bias = Array1::zeros(output_size);
Self { weights, bias }
}
pub fn forward(&self, input: &Array1<f32>) -> Array1<f32> {
self.weights.t().dot(input) + &self.bias
}
pub fn relu(x: &Array1<f32>) -> Array1<f32> {
x.mapv(|v| v.max(0.0))
}
pub fn sigmoid(x: &Array1<f32>) -> Array1<f32> {
x.mapv(|v| 1.0 / (1.0 + (-v).exp()))
}
pub fn linear(x: &Array1<f32>) -> Array1<f32> {
x.clone()
}
}
#[cfg(feature = "ml")]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Activation {
ReLU,
Sigmoid,
Linear,
}
#[cfg(feature = "ml")]
impl Activation {
pub fn apply(&self, x: &Array1<f32>) -> Array1<f32> {
match self {
Activation::ReLU => DenseLayer::relu(x),
Activation::Sigmoid => DenseLayer::sigmoid(x),
Activation::Linear => DenseLayer::linear(x),
}
}
}
pub mod network_utils {
use std::collections::HashMap;
pub fn normalize_prices(prices: &HashMap<String, f64>) -> Vec<f32> {
let mut price_values: Vec<f32> = prices
.values()
.map(|&p| (p.ln()) as f32) .collect();
if price_values.is_empty() {
return vec![0.0];
}
let mean = price_values.iter().sum::<f32>() / price_values.len() as f32;
let variance = price_values.iter()
.map(|x| (x - mean).powi(2))
.sum::<f32>() / price_values.len() as f32;
let std = variance.sqrt();
if std > 0.0 {
price_values.iter_mut().for_each(|x| {
*x = (*x - mean) / std;
});
}
price_values
}
}