concision_neural/model/
mod.rs

1/*
2    Appellation: model <module>
3    Contrib: @FL03
4*/
5//! This module provides the scaffolding for creating models and layers in a neural network.
6
7#[doc(inline)]
8pub use self::{config::StandardModelConfig, layout::*, model_params::*, trainer::Trainer};
9
10pub mod config;
11pub mod layout;
12pub mod model_params;
13pub mod trainer;
14
15mod impls {
16    pub mod impl_model_params;
17    #[cfg(feature = "rand")]
18    pub mod impl_model_params_rand;
19}
20
21pub(crate) mod prelude {
22    #[doc(inline)]
23    pub use super::config::*;
24    #[doc(inline)]
25    pub use super::layout::*;
26    #[doc(inline)]
27    pub use super::model_params::*;
28    #[doc(inline)]
29    pub use super::trainer::*;
30    #[doc(inline)]
31    pub use super::{Model, ModelExt};
32}
33
34use crate::{NetworkConfig, Predict, Train};
35use concision_core::params::Params;
36use concision_data::DatasetBase;
37
38/// The base interface for all models; each model provides access to a configuration object
39/// defined as the associated type [`Config`](Model::Config). The configuration object is used
40/// to provide hyperparameters and other control related parameters. In addition, the model's
41/// layout is defined by the [`features`](Model::features) method which aptly returns a copy of
42/// its [ModelFeatures] object.
43pub trait Model<T = f32> {
44    /// The configuration type for the model
45    type Config: NetworkConfig<T>;
46    /// the type of layout used by the model
47    type Layout;
48    /// returns an immutable reference to the models configuration; this is typically used to
49    /// access the models hyperparameters (i.e. learning rate, momentum, etc.) and other
50    /// related control parameters.
51    fn config(&self) -> &Self::Config;
52    /// returns a mutable reference to the models configuration; useful for setting hyperparams
53    fn config_mut(&mut self) -> &mut Self::Config;
54    /// returns a copy of the model's current layout (features); a type providing the model
55    /// with a particular number of features for the various layers of a deep neural network.
56    ///
57    /// the layout is used in everything from creation and initialization routines to
58    /// validating the dimensionality of the model's inputs, outputs, training data, etc.
59    fn layout(&self) -> Self::Layout;
60    /// returns an immutable reference to the model parameters
61    fn params(&self) -> &ModelParams<T>;
62    /// returns a mutable reference to the model's parameters
63    fn params_mut(&mut self) -> &mut ModelParams<T>;
64    /// propagates the input through the model; each layer is applied in sequence meaning that
65    /// the output of each previous layer is the input to the next layer. This pattern
66    /// repeats until the output layer returns the final result.
67    ///
68    /// By default, the trait simply passes each output from one layer to the next, however,
69    /// custom models will likely override this method to inject activation methods and other
70    /// related logic
71    fn predict<U, V>(&self, inputs: &U) -> crate::NeuralResult<V>
72    where
73        Self: Predict<U, Output = V>,
74    {
75        Predict::predict(self, inputs)
76    }
77    /// a convience method that trains the model using the provided dataset; this method
78    /// requires that the model implements the [`Train`] trait and that the dataset
79    fn train<U, V, W>(&mut self, dataset: &DatasetBase<U, V>) -> crate::NeuralResult<W>
80    where
81        Self: Train<U, V, Output = W>,
82    {
83        Train::train(self, dataset.records(), dataset.targets())
84    }
85}
86
87pub trait ModelExt<T>: Model<T>
88where
89    Self::Layout: ModelLayout,
90{
91    /// [`replace`](core::mem::replace) the current configuration and returns the old one;
92    fn replace_config(&mut self, config: Self::Config) -> Self::Config {
93        core::mem::replace(self.config_mut(), config)
94    }
95    /// [`replace`](core::mem::replace) the current model parameters and returns the old one
96    fn replace_params(&mut self, params: ModelParams<T>) -> ModelParams<T> {
97        core::mem::replace(self.params_mut(), params)
98    }
99    /// overrides the current configuration and returns a mutable reference to the model
100    fn set_config(&mut self, config: Self::Config) -> &mut Self {
101        *self.config_mut() = config;
102        self
103    }
104    /// overrides the current model parameters and returns a mutable reference to the model
105    fn set_params(&mut self, params: ModelParams<T>) -> &mut Self {
106        *self.params_mut() = params;
107        self
108    }
109    /// returns an immutable reference to the input layer;
110    #[inline]
111    fn input_layer(&self) -> &Params<T> {
112        self.params().input()
113    }
114    /// returns a mutable reference to the input layer;
115    #[inline]
116    fn input_layer_mut(&mut self) -> &mut Params<T> {
117        self.params_mut().input_mut()
118    }
119    /// returns an immutable reference to the hidden layer(s);
120    #[inline]
121    fn hidden_layers(&self) -> &Vec<Params<T>> {
122        self.params().hidden()
123    }
124    /// returns a mutable reference to the hidden layer(s);
125    #[inline]
126    fn hidden_layers_mut(&mut self) -> &mut Vec<Params<T>> {
127        self.params_mut().hidden_mut()
128    }
129    /// returns an immutable reference to the output layer;
130    #[inline]
131    fn output_layer(&self) -> &Params<T> {
132        self.params().output()
133    }
134    /// returns a mutable reference to the output layer;
135    #[inline]
136    fn output_layer_mut(&mut self) -> &mut Params<T> {
137        self.params_mut().output_mut()
138    }
139    #[inline]
140    fn set_input_layer(&mut self, layer: Params<T>) -> &mut Self {
141        self.params_mut().set_input(layer);
142        self
143    }
144    #[inline]
145    fn set_hidden_layers(&mut self, layers: Vec<Params<T>>) -> &mut Self {
146        self.params_mut().set_hidden(layers);
147        self
148    }
149    #[inline]
150    fn set_output_layer(&mut self, layer: Params<T>) -> &mut Self {
151        self.params_mut().set_output(layer);
152        self
153    }
154    /// returns a 2-tuple representing the dimensions of the input layer; (input, hidden)
155    fn input_dim(&self) -> (usize, usize) {
156        self.layout().dim_input()
157    }
158    /// returns a 2-tuple representing the dimensions of the hidden layers; (hidden, hidden)
159    fn hidden_dim(&self) -> (usize, usize) {
160        self.layout().dim_hidden()
161    }
162    /// returns the total number of hidden layers in the model;
163    fn hidden_layers_count(&self) -> usize {
164        self.layout().layers()
165    }
166    /// returns a 2-tuple representing the dimensions of the output layer; (hidden, output)
167    fn output_dim(&self) -> (usize, usize) {
168        self.layout().dim_output()
169    }
170}
171
172impl<M, T> ModelExt<T> for M
173where
174    M: Model<T>,
175    M::Layout: ModelLayout,
176{
177}
178
179/// The [`DeepNeuralNetwork`] trait is a specialization of the [`Model`] trait that
180/// provides additional functionality for deep neural networks. This trait is
181pub trait DeepNeuralNetwork<T = f32>: Model<T> {}
182
183pub trait ModelTrainer<T> {
184    type Model: Model<T>;
185    /// returns a model trainer prepared to train the model; this is a convenience method
186    /// that creates a new trainer instance and returns it. Trainers are lazily evaluated
187    /// meaning that the training process won't begin until the user calls the `begin` method.
188    fn trainer<'a, U, V>(
189        &mut self,
190        dataset: DatasetBase<U, V>,
191        model: &'a mut Self::Model,
192    ) -> Trainer<'a, Self::Model, T, DatasetBase<U, V>>
193    where
194        Self: Sized,
195        T: Default,
196        for<'b> &'b mut Self::Model: Model<T>,
197    {
198        Trainer::new(model, dataset)
199    }
200}