1use crate::{
4 array,
5 linear_algebra::{FixDimension, Vector},
6 Model,
7};
8use serde_derive::{Deserialize, Serialize};
9
10impl Model for f64 {
11 type Features = ();
12 type Target = f64;
13
14 fn num_coefficients(&self) -> usize {
15 1
16 }
17
18 fn coefficient(&mut self, coefficient: usize) -> &mut f64 {
19 match coefficient {
20 0 => self,
21 _ => panic!("coefficient index out of range"),
22 }
23 }
24
25 fn predict(&self, _: &()) -> f64 {
26 *self
27 }
28
29 fn gradient(&self, coefficient: usize, _: &()) -> f64 {
30 match coefficient {
31 0 => 1.0,
32 _ => panic!("coefficient index out of range"),
33 }
34 }
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct Linear<V> {
40 pub m: V,
42 pub c: f64,
44}
45
46impl<V: Vector> Linear<V> {
47 pub fn with_feature_dimension(dimension: usize) -> Self {
50 Linear {
51 m: V::zero_from_dimension(dimension),
52 c: 0f64,
53 }
54 }
55}
56
57impl<V> Default for Linear<V>
58where
59 V: FixDimension,
60{
61 fn default() -> Self {
62 Linear {
63 m: V::zero(),
64 c: 0f64,
65 }
66 }
67}
68
69impl<V> Model for Linear<V>
70where
71 V: Vector,
72{
73 type Features = V;
74 type Target = f64;
75
76 fn num_coefficients(&self) -> usize {
77 self.m.dimension() + 1
78 }
79
80 fn coefficient(&mut self, coefficient: usize) -> &mut f64 {
81 if coefficient == self.m.dimension() {
82 &mut self.c
83 } else {
84 self.m.at_mut(coefficient)
85 }
86 }
87
88 fn predict(&self, input: &V) -> f64 {
89 self.m.dot(input) + self.c
90 }
91
92 fn gradient(&self, coefficient: usize, input: &V) -> f64 {
93 if coefficient == self.m.dimension() {
94 1.0 } else {
96 input.at(coefficient) }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct Logistic<V>(Linear<V>);
104
105impl<V: Vector> Logistic<V> {
106 pub fn with_feature_dimension(dimension: usize) -> Self {
109 Logistic(Linear::with_feature_dimension(dimension))
110 }
111}
112
113impl<V> Default for Logistic<V>
114where
115 V: FixDimension,
116{
117 fn default() -> Self {
118 Logistic(Linear::default())
119 }
120}
121
122impl<V> Model for Logistic<V>
123where
124 Linear<V>: Model<Features = V, Target = f64>,
125{
126 type Features = V;
127 type Target = f64;
128
129 fn num_coefficients(&self) -> usize {
130 self.0.num_coefficients()
131 }
132
133 fn coefficient(&mut self, coefficient: usize) -> &mut f64 {
134 self.0.coefficient(coefficient)
135 }
136
137 fn predict(&self, input: &V) -> f64 {
138 1.0 / (1.0 + self.0.predict(input).exp())
139 }
140
141 fn gradient(&self, coefficient: usize, input: &V) -> f64 {
142 let p = self.predict(input);
143 -p * (1.0 - p) * self.0.gradient(coefficient, input)
144 }
145}
146
147#[derive(Clone)]
168pub struct GeneralizedLinearModel<V, G, Dg> {
169 pub linear: Linear<V>,
171 pub g: G,
173 pub g_derivate: Dg,
175}
176
177impl<V, G, Dg> GeneralizedLinearModel<V, G, Dg>
178where
179 G: Fn(f64) -> f64,
180 Dg: Fn(f64) -> f64,
181{
182 pub fn new(g: G, g_derivate: Dg) -> GeneralizedLinearModel<V, G, Dg>
184 where
185 V: FixDimension,
186 {
187 GeneralizedLinearModel {
188 linear: Linear::default(),
189 g,
190 g_derivate,
191 }
192 }
193}
194
195impl<V, F, Df> Model for GeneralizedLinearModel<V, F, Df>
196where
197 F: Fn(f64) -> f64,
198 Df: Fn(f64) -> f64,
199 Linear<V>: Model<Features = V, Target = f64>,
200{
201 type Features = V;
202 type Target = f64;
203
204 fn num_coefficients(&self) -> usize {
205 self.linear.num_coefficients()
206 }
207
208 fn coefficient(&mut self, coefficient: usize) -> &mut f64 {
209 self.linear.coefficient(coefficient)
210 }
211
212 fn predict(&self, input: &V) -> f64 {
213 let f = &self.g;
214 f(self.linear.predict(&input))
215 }
216
217 fn gradient(&self, coefficient: usize, input: &V) -> f64 {
218 let f = &self.g_derivate;
219 f(self.linear.predict(&input)) * self.linear.gradient(coefficient, input)
220 }
221}
222
223#[derive(Debug, Clone, Default, Serialize, Deserialize)]
229pub struct OneVsRest<T>(T);
230
231impl<T> OneVsRest<T> {
232 pub fn new(t: T) -> Self {
234 OneVsRest(t)
235 }
236}
237
238impl<T> Model for OneVsRest<T>
239where
240 T: array::Array,
241 T::Element: Model<Target = f64>,
242{
243 type Features = <T::Element as Model>::Features;
244 type Target = T::Vector;
245
246 fn num_coefficients(&self) -> usize {
247 let models = &self.0;
248 models.length() * models.at_ref(0).num_coefficients()
249 }
250
251 fn coefficient(&mut self, index: usize) -> &mut f64 {
252 let models = &mut self.0;
255 let class = index % models.length();
256 let n = index / models.length();
257 models.at_mut(class).coefficient(n)
258 }
259
260 fn predict(&self, input: &Self::Features) -> Self::Target {
261 let models = &self.0;
262 let mut result = Self::Target::zero_from_dimension(models.length());
263 for i in 0..models.length() {
264 *result.at_mut(i) = models.at_ref(i).predict(input);
265 }
266 result
267 }
268
269 fn gradient(&self, coefficient: usize, input: &Self::Features) -> Self::Target {
270 let models = &self.0;
271 let class = coefficient % models.length();
272 let mut result = Self::Target::zero_from_dimension(models.length());
273 *result.at_mut(class) = models
274 .at_ref(class)
275 .gradient(coefficient / models.length(), input);
276 result
277 }
278}