use rand_chacha::ChaCha8Rng;
use rand_chacha::rand_core::{RngCore, SeedableRng};
use crate::util::functions::Optimiser::{Adam, SGD};
use crate::util::precision::PrecisionType;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Regularisation {
None,
L1Regular(f32),
L2Regular(f32),
}
impl Regularisation {
pub(crate) fn ordinal(&self) -> usize {
match self {
Regularisation::None => 0,
Regularisation::L1Regular(_) => 1,
Regularisation::L2Regular(_) => 2,
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Normalisation {
Disabled,
RMSNorm,
LayerNorm,
BatchNorm
}
impl Normalisation {
pub(crate) fn ordinal(&self) -> usize {
match self {
Normalisation::Disabled => 0,
Normalisation::RMSNorm => 1,
Normalisation::LayerNorm => 2,
Normalisation::BatchNorm => 3
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Optimiser {
SGD(f32, bool),
Adam(f32, f32, f32)
}
impl Optimiser {
pub(crate) fn ordinal(&self) -> usize {
match self {
SGD(_, _) => 0,
Adam(_, _, _) => 1,
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Activation {
Identity,
Sigmoid,
ReLU,
LeakyReLU(f32),
Tanh,
Softmax,
SiLU,
Mish
}
impl Activation {
pub fn ordinal(&self) -> usize {
match self {
Activation::Identity => 0,
Activation::Sigmoid => 1,
Activation::ReLU => 2,
Activation::LeakyReLU(_) => 3,
Activation::Tanh => 4,
Activation::Softmax => 5,
Activation::SiLU => 6,
Activation::Mish => 7
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum LossFunc {
MeanSquareLoss,
CrossEntropyLoss,
BinaryCrossEntropy,
}
pub trait InitFunc {
fn new<T: PrecisionType>(seed: u64, mul: f32) -> Self;
fn init<T: PrecisionType>(&mut self, fan_in: usize, fan_out: usize) -> Vec<T>;
}
pub struct InitXavierUniformFunc {
rng: ChaCha8Rng,
factor: f32
}
pub struct InitXavierNormalFunc {
rng: ChaCha8Rng,
factor: f32
}
pub struct InitHeUniformFunc {
rng: ChaCha8Rng,
factor: f32
}
pub struct InitHeNormalFunc {
rng: ChaCha8Rng,
factor: f32
}
pub struct InitZeroFunc {}
fn normal_dist<T: PrecisionType>(total: usize, rng: &mut ChaCha8Rng, factor: f32, std: f32) -> Vec<T> {
(0..total)
.map(|_| {
let u1 = (rng.next_u32() as f32 + 1.0) / (u32::MAX as f32 + 1.0);
let u2 = rng.next_u32() as f32 / u32::MAX as f32;
let z = (-2.0 * u1.ln()).sqrt() * (2.0 * std::f32::consts::PI * u2).cos();
T::from_f32(factor * z * std)
})
.collect()
}
fn uniform_dist<T: PrecisionType>(total: usize, rng: &mut ChaCha8Rng, factor: f32, limit: f32) -> Vec<T> {
(0..total)
.map(|_| {
let raw = rng.next_u32() as f32 / u32::MAX as f32;
T::from_f32(factor * (-limit + raw * (2.0 * limit)))
})
.collect()
}
impl InitFunc for InitXavierUniformFunc {
fn new<T: PrecisionType>(seed: u64, factor: f32) -> Self {
Self {
rng: ChaCha8Rng::seed_from_u64(seed),
factor
}
}
fn init<T: PrecisionType>(&mut self, fan_in: usize, fan_out: usize) -> Vec<T> {
let total = fan_in * fan_out;
let limit = (6.0 / (fan_in + fan_out) as f32).sqrt();
uniform_dist(total, &mut self.rng, self.factor, limit)
}
}
impl InitFunc for InitXavierNormalFunc {
fn new<T: PrecisionType>(seed: u64, factor: f32) -> Self {
Self {
rng: ChaCha8Rng::seed_from_u64(seed),
factor
}
}
fn init<T: PrecisionType>(&mut self, fan_in: usize, fan_out: usize) -> Vec<T> {
let total = fan_in * fan_out;
let std = (2.0 / (fan_in + fan_out) as f32).sqrt();
normal_dist(total, &mut self.rng, self.factor, std)
}
}
impl InitFunc for InitHeUniformFunc {
fn new<T: PrecisionType>(seed: u64, factor: f32) -> Self {
Self {
rng: ChaCha8Rng::seed_from_u64(seed),
factor
}
}
fn init<T: PrecisionType>(&mut self, fan_in: usize, fan_out: usize) -> Vec<T> {
let total = fan_in * fan_out;
let limit = (6.0 / fan_in as f32).sqrt();
uniform_dist(total, &mut self.rng, self.factor, limit)
}
}
impl InitFunc for InitHeNormalFunc {
fn new<T: PrecisionType>(seed: u64, factor: f32) -> Self {
Self {
rng: ChaCha8Rng::seed_from_u64(seed),
factor
}
}
fn init<T: PrecisionType>(&mut self, fan_in: usize, fan_out: usize) -> Vec<T> {
let total = fan_in * fan_out;
let std = (2.0 / fan_in as f32).sqrt();
normal_dist(total, &mut self.rng, self.factor, std)
}
}
impl InitFunc for InitZeroFunc {
fn new<T: PrecisionType>(_seed: u64, _factor: f32) -> Self {
Self {}
}
fn init<T: PrecisionType>(&mut self, fan_in: usize, fan_out: usize) -> Vec<T> {
vec![T::zero(); fan_in * fan_out]
}
}