trustformers_optim/second_order/
self_scaled.rs1use std::collections::VecDeque;
2use trustformers_core::errors::{Result, TrustformersError};
3use trustformers_core::tensor::Tensor;
4use trustformers_core::traits::Optimizer;
5
6#[derive(Debug)]
18pub struct SSBFGS {
19 pub learning_rate: f32,
20 pub history_size: usize,
21 pub scaling_factor: f32,
22 pub momentum: f32,
23
24 pub step: usize,
26 pub scale_history: VecDeque<f32>,
27}
28
29#[derive(Debug, Clone)]
30pub struct SSBFGSConfig {
31 pub learning_rate: f32,
32 pub history_size: usize,
33 pub scaling_factor: f32,
34 pub momentum: f32,
35}
36
37impl Default for SSBFGSConfig {
38 fn default() -> Self {
39 Self {
40 learning_rate: 1.0,
41 history_size: 10,
42 scaling_factor: 1.0,
43 momentum: 0.9,
44 }
45 }
46}
47
48impl Default for SSBFGS {
49 fn default() -> Self {
50 Self::new()
51 }
52}
53
54impl SSBFGS {
55 pub fn new() -> Self {
56 Self::from_config(SSBFGSConfig::default())
57 }
58
59 pub fn from_config(config: SSBFGSConfig) -> Self {
60 Self {
61 learning_rate: config.learning_rate,
62 history_size: config.history_size,
63 scaling_factor: config.scaling_factor,
64 momentum: config.momentum,
65 step: 0,
66 scale_history: VecDeque::new(),
67 }
68 }
69
70 pub fn for_physics_informed() -> Self {
72 Self::from_config(SSBFGSConfig {
73 learning_rate: 0.8,
74 history_size: 15,
75 scaling_factor: 1.2,
76 momentum: 0.95,
77 })
78 }
79
80 pub fn for_non_convex() -> Self {
82 Self::from_config(SSBFGSConfig {
83 learning_rate: 0.5,
84 history_size: 20,
85 scaling_factor: 0.8,
86 momentum: 0.85,
87 })
88 }
89
90 fn compute_self_scaling_factor(&mut self, grad_norm: f32) -> f32 {
92 let mut scale = self.scaling_factor;
93
94 if !self.scale_history.is_empty() {
95 let mean_scale: f32 =
96 self.scale_history.iter().sum::<f32>() / self.scale_history.len() as f32;
97 let adaptation_factor = 1.0 + 0.1 * grad_norm.tanh();
98 scale = self.momentum * mean_scale + (1.0 - self.momentum) * adaptation_factor;
99 }
100
101 scale = scale.clamp(0.1, 10.0);
102
103 self.scale_history.push_back(scale);
104 if self.scale_history.len() > self.history_size {
105 self.scale_history.pop_front();
106 }
107
108 scale
109 }
110
111 pub fn get_stats(&self) -> SSBFGSStats {
113 SSBFGSStats {
114 step: self.step,
115 current_scaling_factor: self.scale_history.back().copied().unwrap_or(1.0),
116 average_scaling_factor: if !self.scale_history.is_empty() {
117 self.scale_history.iter().sum::<f32>() / self.scale_history.len() as f32
118 } else {
119 1.0
120 },
121 }
122 }
123}
124
125#[derive(Debug, Clone)]
126pub struct SSBFGSStats {
127 pub step: usize,
128 pub current_scaling_factor: f32,
129 pub average_scaling_factor: f32,
130}
131
132impl Optimizer for SSBFGS {
133 fn update(&mut self, parameter: &mut Tensor, grad: &Tensor) -> Result<()> {
134 match (parameter, grad) {
135 (Tensor::F32(param), Tensor::F32(grad_arr)) => {
136 self.step += 1;
137
138 let grad_norm: f32 = grad_arr.iter().map(|g| g * g).sum::<f32>().sqrt();
140
141 let scale = self.compute_self_scaling_factor(grad_norm);
143
144 let scaled_lr = self.learning_rate * scale;
146 *param = &*param - &(grad_arr.clone() * scaled_lr);
147
148 Ok(())
149 },
150 _ => Err(TrustformersError::tensor_op_error(
151 "Unsupported tensor types for SSBFGS",
152 "ssbfgs_update",
153 )),
154 }
155 }
156
157 fn zero_grad(&mut self) {
158 }
160
161 fn step(&mut self) {
162 }
164
165 fn get_lr(&self) -> f32 {
166 self.learning_rate
167 }
168
169 fn set_lr(&mut self, lr: f32) {
170 self.learning_rate = lr;
171 }
172}
173
174#[derive(Debug)]
180pub struct SSBroyden {
181 pub learning_rate: f32,
182 pub history_size: usize,
183 pub scaling_factor: f32,
184 pub momentum: f32,
185
186 pub step: usize,
188 pub scale_history: VecDeque<f32>,
189}
190
191#[derive(Debug, Clone)]
192pub struct SSBroydenConfig {
193 pub learning_rate: f32,
194 pub history_size: usize,
195 pub scaling_factor: f32,
196 pub momentum: f32,
197}
198
199impl Default for SSBroydenConfig {
200 fn default() -> Self {
201 Self {
202 learning_rate: 1.0,
203 history_size: 15,
204 scaling_factor: 1.0,
205 momentum: 0.9,
206 }
207 }
208}
209
210impl Default for SSBroyden {
211 fn default() -> Self {
212 Self::new()
213 }
214}
215
216impl SSBroyden {
217 pub fn new() -> Self {
218 Self::from_config(SSBroydenConfig::default())
219 }
220
221 pub fn from_config(config: SSBroydenConfig) -> Self {
222 Self {
223 learning_rate: config.learning_rate,
224 history_size: config.history_size,
225 scaling_factor: config.scaling_factor,
226 momentum: config.momentum,
227 step: 0,
228 scale_history: VecDeque::new(),
229 }
230 }
231
232 pub fn for_physics_informed() -> Self {
234 Self::from_config(SSBroydenConfig {
235 learning_rate: 0.7,
236 history_size: 20,
237 scaling_factor: 1.1,
238 momentum: 0.95,
239 })
240 }
241
242 fn compute_self_scaling_factor(&mut self, grad_norm: f32) -> f32 {
244 let mut scale = self.scaling_factor;
245
246 if !self.scale_history.is_empty() {
247 let mean_scale: f32 =
248 self.scale_history.iter().sum::<f32>() / self.scale_history.len() as f32;
249 let adaptation_factor = 1.0 + 0.1 * grad_norm.tanh();
250 scale = self.momentum * mean_scale + (1.0 - self.momentum) * adaptation_factor;
251 }
252
253 scale = scale.clamp(0.1, 5.0);
254
255 self.scale_history.push_back(scale);
256 if self.scale_history.len() > self.history_size {
257 self.scale_history.pop_front();
258 }
259
260 scale
261 }
262}
263
264impl Optimizer for SSBroyden {
265 fn update(&mut self, parameter: &mut Tensor, grad: &Tensor) -> Result<()> {
266 match (parameter, grad) {
267 (Tensor::F32(param), Tensor::F32(grad_arr)) => {
268 self.step += 1;
269
270 let grad_norm: f32 = grad_arr.iter().map(|g| g * g).sum::<f32>().sqrt();
272
273 let scale = self.compute_self_scaling_factor(grad_norm);
275
276 let scaled_lr = self.learning_rate * scale;
278 *param = &*param - &(grad_arr.clone() * scaled_lr);
279
280 Ok(())
281 },
282 _ => Err(TrustformersError::tensor_op_error(
283 "Unsupported tensor types for SSBroyden",
284 "ssbroyden_update",
285 )),
286 }
287 }
288
289 fn zero_grad(&mut self) {
290 }
292
293 fn step(&mut self) {
294 }
296
297 fn get_lr(&self) -> f32 {
298 self.learning_rate
299 }
300
301 fn set_lr(&mut self, lr: f32) {
302 self.learning_rate = lr;
303 }
304}