afor-optimizer 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,194 @@
1
+ """
2
+ AFOR: Adaptive Forgetting Optimizer.
3
+
4
+ Usage:
5
+ from AFOR import afor
6
+
7
+ optimizer = afor(
8
+ model.parameters(),
9
+ lr=0.001,
10
+ betas=(0.9, 0.999),
11
+ beta2_min=0.99,
12
+ weight_decay=1e-4,
13
+ )
14
+ """
15
+
16
+ import math
17
+
18
+ import torch
19
+ from torch.optim import Optimizer
20
+
21
+
22
+ class afor(Optimizer):
23
+ """Tensor-wise adaptive forgetting optimizer."""
24
+
25
+ def __init__(
26
+ self,
27
+ params,
28
+ lr,
29
+ betas=(0.9, 0.999),
30
+ beta2_min=0.99,
31
+ dir_weight=1.0,
32
+ eps=1e-8,
33
+ weight_decay=0,
34
+ fast_ref=True,
35
+ ):
36
+ defaults = dict(
37
+ lr=lr,
38
+ betas=betas,
39
+ beta2_min=beta2_min,
40
+ dir_weight=dir_weight,
41
+ eps=eps,
42
+ weight_decay=weight_decay,
43
+ fast_ref=fast_ref,
44
+ )
45
+ super().__init__(params, defaults)
46
+
47
+ @torch.no_grad()
48
+ def step(self, closure=None):
49
+ loss = None
50
+ if closure is not None:
51
+ with torch.enable_grad():
52
+ loss = closure()
53
+
54
+ for group in self.param_groups:
55
+ lr = group["lr"]
56
+ beta1, beta2_init = group["betas"]
57
+ beta2_min = group["beta2_min"]
58
+ dir_weight = group["dir_weight"]
59
+ eps = group["eps"]
60
+ weight_decay = group["weight_decay"]
61
+ fast_ref = group["fast_ref"]
62
+
63
+ # beta2 is adapted within [beta2_min, beta2_init].
64
+ beta2_max = beta2_init
65
+ beta_fast = beta1
66
+ beta_slow = beta2_init
67
+ gate_warmup = 100
68
+
69
+ for p in group["params"]:
70
+ if p.grad is None:
71
+ continue
72
+
73
+ grad = p.grad
74
+ if grad.is_sparse:
75
+ raise RuntimeError("afor does not support sparse gradients")
76
+
77
+ # Apply decoupled weight decay before the adaptive update.
78
+ if weight_decay != 0:
79
+ p.mul_(1 - lr * weight_decay)
80
+
81
+ state = self.state[p]
82
+
83
+ # Initialize tensor-wise optimizer states.
84
+ if len(state) == 0:
85
+ state["step"] = 0
86
+ state["exp_avg"] = torch.zeros_like(p)
87
+ state["exp_avg_sq"] = torch.zeros_like(p)
88
+ state["noise_fast"] = torch.tensor(0.0, device=p.device)
89
+ state["noise_slow"] = torch.tensor(0.0, device=p.device)
90
+ state["dir_ema"] = torch.tensor(1.0, device=p.device)
91
+ state["beta2_cumprod"] = torch.tensor(1.0, device=p.device)
92
+ state["snr_ema"] = torch.tensor(0.0, device=p.device)
93
+ state["snr_var_ema"] = torch.tensor(1.0, device=p.device)
94
+
95
+ # These values are exposed for visualization and diagnostics.
96
+ state["snr_mag_t"] = torch.tensor(0.0, device=p.device)
97
+ state["snr_t"] = torch.tensor(0.0, device=p.device)
98
+ state["z_t"] = torch.tensor(0.0, device=p.device)
99
+ state["beta2_t"] = torch.tensor(1.0, device=p.device)
100
+
101
+ exp_avg = state["exp_avg"]
102
+ exp_avg_sq = state["exp_avg_sq"]
103
+ state["step"] += 1
104
+ step = state["step"]
105
+
106
+ # The residual uses the previous first-moment estimate.
107
+ noise_inst = (grad - exp_avg).abs().mean()
108
+ state["noise_fast"].mul_(beta_fast).add_(
109
+ noise_inst, alpha=1 - beta_fast
110
+ )
111
+ state["noise_slow"].mul_(beta_slow).add_(
112
+ noise_inst, alpha=1 - beta_slow
113
+ )
114
+
115
+ # the previous momentum direction.
116
+ dot = (grad * exp_avg).sum()
117
+ ng, nm = grad.norm(), exp_avg.norm()
118
+ if ng > eps and nm > eps:
119
+ cos = (dot / (ng * nm)).clamp(min=0.0)
120
+ else:
121
+ cos = torch.tensor(1.0, device=p.device)
122
+ state["dir_ema"].mul_(0.9).add_(cos, alpha=0.1)
123
+
124
+ # momentum-to-noise signal ratio.
125
+ exp_avg.mul_(beta1).add_(grad, alpha=1 - beta1)
126
+
127
+ # combine relative momentum magnitude and direction
128
+ # consistency into a non-negative tensor-wise signal score.
129
+ if fast_ref:
130
+ noise_ref = torch.max(
131
+ state["noise_fast"], state["noise_slow"]
132
+ )
133
+ else:
134
+ noise_ref = state["noise_slow"]
135
+
136
+ mag_snr = exp_avg.abs().mean() / (noise_ref + eps)
137
+ snr = mag_snr * (
138
+ 1.0 + dir_weight * (state["dir_ema"] - 1.0)
139
+ )
140
+ snr = snr.clamp(min=0.0)
141
+
142
+ # This avoids fixed, model-specific SNR thresholds.
143
+ snr_val = snr.item()
144
+ state["snr_ema"].mul_(beta_slow).add_(
145
+ snr_val, alpha=1 - beta_slow
146
+ )
147
+ delta_t = snr_val - state["snr_ema"]
148
+ state["snr_var_ema"].mul_(beta_slow).addcmul_(
149
+ delta_t, delta_t, value=1 - beta_slow
150
+ )
151
+
152
+ var_clamped = max(state["snr_var_ema"].item(), 1e-8)
153
+ z_score = delta_t / (math.sqrt(var_clamped) + eps)
154
+ z_score = torch.clamp(z_score, -5.0, 5.0)
155
+
156
+ beta2_raw = beta2_min + (
157
+ beta2_max - beta2_min
158
+ ) * torch.sigmoid(z_score)
159
+
160
+ # keep beta2 close to its initial value during the
161
+ # warm-up period while the online statistics become reliable.
162
+ gate = min(1.0, step / gate_warmup)
163
+ beta2_t = gate * beta2_raw + (1.0 - gate) * beta2_init
164
+
165
+ # Save observability values without changing the update rule.
166
+ state["snr_mag_t"] = mag_snr
167
+ state["snr_t"] = snr
168
+ state["z_t"] = z_score
169
+ state["beta2_t"] = beta2_t
170
+
171
+ # update the second moment with time-varying beta2.
172
+ state["beta2_cumprod"].mul_(beta2_t)
173
+ beta2_value = beta2_t.item()
174
+ exp_avg_sq.mul_(beta2_value).addcmul_(
175
+ grad, grad, value=1 - beta2_value
176
+ )
177
+
178
+ # corrections, using the cumulative product for time-varying
179
+ # beta2, then update the parameters.
180
+ bias_correction1 = 1.0 - beta1**step
181
+ bias_correction2 = max(
182
+ 1.0 - state["beta2_cumprod"].item(), 1e-12
183
+ )
184
+
185
+ denom = (
186
+ exp_avg_sq.sqrt() / math.sqrt(bias_correction2)
187
+ ).add_(eps)
188
+ p.addcdiv_(
189
+ exp_avg,
190
+ denom,
191
+ value=-(lr / bias_correction1),
192
+ )
193
+
194
+ return loss
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AFOR Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,73 @@
1
+ Metadata-Version: 2.4
2
+ Name: afor-optimizer
3
+ Version: 0.1.0
4
+ Summary: Adaptive Forgetting Optimizer for PyTorch
5
+ Author: AFOR Contributors
6
+ License-Expression: MIT
7
+ Keywords: pytorch,optimizer,deep-learning,adaptive-optimization,machine-learning
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: torch>=2.0
21
+ Dynamic: license-file
22
+
23
+ # AFOR
24
+
25
+ AFOR is a tensor-wise adaptive forgetting optimizer for PyTorch. It adapts
26
+ the second-moment decay coefficient from local gradient residuals, direction
27
+ consistency, and online Z-score normalization.
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ pip install afor-optimizer
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ import torch
39
+ from AFOR import afor
40
+
41
+ model = torch.nn.Linear(10, 2)
42
+ optimizer = afor(
43
+ model.parameters(),
44
+ lr=1e-3,
45
+ betas=(0.9, 0.999),
46
+ beta2_min=0.99,
47
+ dir_weight=1.0,
48
+ weight_decay=1e-4,
49
+ )
50
+
51
+ inputs = torch.randn(16, 10)
52
+ targets = torch.randint(0, 2, (16,))
53
+ loss = torch.nn.functional.cross_entropy(model(inputs), targets)
54
+ loss.backward()
55
+ optimizer.step()
56
+ optimizer.zero_grad()
57
+ ```
58
+
59
+ ## Main Parameters
60
+
61
+ - `lr`: learning rate.
62
+ - `betas`: first-moment and initial second-moment coefficients.
63
+ - `beta2_min`: lower bound for the adaptive second-moment coefficient.
64
+ - `dir_weight`: weight of gradient-direction consistency.
65
+ - `eps`: numerical stability term.
66
+ - `weight_decay`: decoupled weight decay.
67
+ - `fast_ref`: use the larger fast/slow noise estimate as the noise reference.
68
+
69
+ AFOR currently supports dense gradients only.
70
+
71
+ ## License
72
+
73
+ Released under the MIT License. See `LICENSE`.
@@ -0,0 +1,51 @@
1
+ # AFOR
2
+
3
+ AFOR is a tensor-wise adaptive forgetting optimizer for PyTorch. It adapts
4
+ the second-moment decay coefficient from local gradient residuals, direction
5
+ consistency, and online Z-score normalization.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install afor-optimizer
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```python
16
+ import torch
17
+ from AFOR import afor
18
+
19
+ model = torch.nn.Linear(10, 2)
20
+ optimizer = afor(
21
+ model.parameters(),
22
+ lr=1e-3,
23
+ betas=(0.9, 0.999),
24
+ beta2_min=0.99,
25
+ dir_weight=1.0,
26
+ weight_decay=1e-4,
27
+ )
28
+
29
+ inputs = torch.randn(16, 10)
30
+ targets = torch.randint(0, 2, (16,))
31
+ loss = torch.nn.functional.cross_entropy(model(inputs), targets)
32
+ loss.backward()
33
+ optimizer.step()
34
+ optimizer.zero_grad()
35
+ ```
36
+
37
+ ## Main Parameters
38
+
39
+ - `lr`: learning rate.
40
+ - `betas`: first-moment and initial second-moment coefficients.
41
+ - `beta2_min`: lower bound for the adaptive second-moment coefficient.
42
+ - `dir_weight`: weight of gradient-direction consistency.
43
+ - `eps`: numerical stability term.
44
+ - `weight_decay`: decoupled weight decay.
45
+ - `fast_ref`: use the larger fast/slow noise estimate as the noise reference.
46
+
47
+ AFOR currently supports dense gradients only.
48
+
49
+ ## License
50
+
51
+ Released under the MIT License. See `LICENSE`.
@@ -0,0 +1,73 @@
1
+ Metadata-Version: 2.4
2
+ Name: afor-optimizer
3
+ Version: 0.1.0
4
+ Summary: Adaptive Forgetting Optimizer for PyTorch
5
+ Author: AFOR Contributors
6
+ License-Expression: MIT
7
+ Keywords: pytorch,optimizer,deep-learning,adaptive-optimization,machine-learning
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: torch>=2.0
21
+ Dynamic: license-file
22
+
23
+ # AFOR
24
+
25
+ AFOR is a tensor-wise adaptive forgetting optimizer for PyTorch. It adapts
26
+ the second-moment decay coefficient from local gradient residuals, direction
27
+ consistency, and online Z-score normalization.
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ pip install afor-optimizer
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ import torch
39
+ from AFOR import afor
40
+
41
+ model = torch.nn.Linear(10, 2)
42
+ optimizer = afor(
43
+ model.parameters(),
44
+ lr=1e-3,
45
+ betas=(0.9, 0.999),
46
+ beta2_min=0.99,
47
+ dir_weight=1.0,
48
+ weight_decay=1e-4,
49
+ )
50
+
51
+ inputs = torch.randn(16, 10)
52
+ targets = torch.randint(0, 2, (16,))
53
+ loss = torch.nn.functional.cross_entropy(model(inputs), targets)
54
+ loss.backward()
55
+ optimizer.step()
56
+ optimizer.zero_grad()
57
+ ```
58
+
59
+ ## Main Parameters
60
+
61
+ - `lr`: learning rate.
62
+ - `betas`: first-moment and initial second-moment coefficients.
63
+ - `beta2_min`: lower bound for the adaptive second-moment coefficient.
64
+ - `dir_weight`: weight of gradient-direction consistency.
65
+ - `eps`: numerical stability term.
66
+ - `weight_decay`: decoupled weight decay.
67
+ - `fast_ref`: use the larger fast/slow noise estimate as the noise reference.
68
+
69
+ AFOR currently supports dense gradients only.
70
+
71
+ ## License
72
+
73
+ Released under the MIT License. See `LICENSE`.
@@ -0,0 +1,9 @@
1
+ AFOR.py
2
+ LICENSE
3
+ README.md
4
+ pyproject.toml
5
+ afor_optimizer.egg-info/PKG-INFO
6
+ afor_optimizer.egg-info/SOURCES.txt
7
+ afor_optimizer.egg-info/dependency_links.txt
8
+ afor_optimizer.egg-info/requires.txt
9
+ afor_optimizer.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ torch>=2.0
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.3", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "afor-optimizer"
7
+ version = "0.1.0"
8
+ description = "Adaptive Forgetting Optimizer for PyTorch"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "AFOR Contributors" }
14
+ ]
15
+ keywords = [
16
+ "pytorch",
17
+ "optimizer",
18
+ "deep-learning",
19
+ "adaptive-optimization",
20
+ "machine-learning"
21
+ ]
22
+ classifiers = [
23
+ "Development Status :: 3 - Alpha",
24
+ "Intended Audience :: Science/Research",
25
+ "Intended Audience :: Developers",
26
+ "Programming Language :: Python :: 3",
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ "Programming Language :: Python :: 3.12",
30
+ "Programming Language :: Python :: 3.13",
31
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
32
+ ]
33
+ dependencies = [
34
+ "torch>=2.0"
35
+ ]
36
+
37
+ [tool.setuptools]
38
+ py-modules = ["AFOR"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+