pytorch-optimizer 3.3.3__tar.gz → 3.3.4__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.
Files changed (117) hide show
  1. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/PKG-INFO +6 -4
  2. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/README.md +4 -2
  3. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pyproject.toml +4 -4
  4. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/__init__.py +3 -0
  5. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/base/scheduler.py +4 -3
  6. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/base/types.py +1 -0
  7. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/cosine_anealing.py +3 -4
  8. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/rex.py +3 -4
  9. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/__init__.py +18 -8
  10. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adafactor.py +2 -2
  11. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adamp.py +4 -3
  12. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adamw.py +1 -2
  13. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/experimental/ranger25.py +17 -26
  14. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/fp16.py +31 -36
  15. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/lookahead.py +13 -5
  16. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/nero.py +4 -4
  17. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/orthograd.py +25 -7
  18. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/pcgrad.py +5 -5
  19. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/sam.py +4 -3
  20. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/sgd.py +2 -2
  21. pytorch_optimizer-3.3.4/pytorch_optimizer/optimizer/spam.py +269 -0
  22. pytorch_optimizer-3.3.4/pytorch_optimizer/optimizer/tam.py +221 -0
  23. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/trac.py +13 -5
  24. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/LICENSE +0 -0
  25. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/base/__init__.py +0 -0
  26. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/base/exception.py +0 -0
  27. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/base/optimizer.py +0 -0
  28. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/__init__.py +0 -0
  29. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/bi_tempered.py +0 -0
  30. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/cross_entropy.py +0 -0
  31. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/dice.py +0 -0
  32. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/f1.py +0 -0
  33. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/focal.py +0 -0
  34. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/jaccard.py +0 -0
  35. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/ldam.py +0 -0
  36. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/lovasz.py +0 -0
  37. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/loss/tversky.py +0 -0
  38. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/__init__.py +0 -0
  39. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/chebyshev.py +0 -0
  40. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/experimental/__init__.py +0 -0
  41. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/experimental/deberta_v3_lr_scheduler.py +0 -0
  42. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/linear_warmup.py +0 -0
  43. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/proportion.py +0 -0
  44. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/lr_scheduler/wsd.py +0 -0
  45. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/a2grad.py +0 -0
  46. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adabelief.py +0 -0
  47. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adabound.py +0 -0
  48. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adadelta.py +0 -0
  49. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adahessian.py +0 -0
  50. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adai.py +0 -0
  51. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adalite.py +0 -0
  52. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adam_mini.py +0 -0
  53. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adamax.py +0 -0
  54. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adamg.py +0 -0
  55. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adamod.py +0 -0
  56. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adams.py +0 -0
  57. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adan.py +0 -0
  58. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adanorm.py +0 -0
  59. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adapnm.py +0 -0
  60. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adashift.py +0 -0
  61. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adasmooth.py +0 -0
  62. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/ademamix.py +0 -0
  63. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/adopt.py +0 -0
  64. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/agc.py +0 -0
  65. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/aggmo.py +0 -0
  66. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/aida.py +0 -0
  67. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/alig.py +0 -0
  68. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/amos.py +0 -0
  69. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/apollo.py +0 -0
  70. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/avagrad.py +0 -0
  71. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/came.py +0 -0
  72. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/dadapt.py +0 -0
  73. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/demo.py +0 -0
  74. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/diffgrad.py +0 -0
  75. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/experimental/__init__.py +0 -0
  76. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/fadam.py +0 -0
  77. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/fromage.py +0 -0
  78. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/ftrl.py +0 -0
  79. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/galore.py +0 -0
  80. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/galore_utils.py +0 -0
  81. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/gc.py +0 -0
  82. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/grams.py +0 -0
  83. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/gravity.py +0 -0
  84. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/grokfast.py +0 -0
  85. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/kate.py +0 -0
  86. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/lamb.py +0 -0
  87. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/laprop.py +0 -0
  88. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/lars.py +0 -0
  89. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/lion.py +0 -0
  90. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/lomo.py +0 -0
  91. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/madgrad.py +0 -0
  92. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/mars.py +0 -0
  93. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/msvag.py +0 -0
  94. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/muon.py +0 -0
  95. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/novograd.py +0 -0
  96. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/padam.py +0 -0
  97. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/pid.py +0 -0
  98. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/pnm.py +0 -0
  99. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/prodigy.py +0 -0
  100. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/qhadam.py +0 -0
  101. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/qhm.py +0 -0
  102. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/radam.py +0 -0
  103. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/ranger.py +0 -0
  104. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/ranger21.py +0 -0
  105. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/rotograd.py +0 -0
  106. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/schedulefree.py +0 -0
  107. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/sgdp.py +0 -0
  108. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/shampoo.py +0 -0
  109. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/shampoo_utils.py +0 -0
  110. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/sm3.py +0 -0
  111. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/soap.py +0 -0
  112. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/sophia.py +0 -0
  113. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/srmm.py +0 -0
  114. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/swats.py +0 -0
  115. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/tiger.py +0 -0
  116. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/utils.py +0 -0
  117. {pytorch_optimizer-3.3.3 → pytorch_optimizer-3.3.4}/pytorch_optimizer/optimizer/yogi.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pytorch_optimizer
3
- Version: 3.3.3
3
+ Version: 3.3.4
4
4
  Summary: optimizer & lr scheduler & objective function collections in PyTorch
5
5
  License: Apache-2.0
6
- Keywords: pytorch,deep-learning,optimizer,lr scheduler,A2Grad,ASGD,AccSGD,AdaBelief,AdaBound,AdaDelta,AdaFactor,AdaMax,AdamG,AdaMod,AdaNorm,AdaPNM,AdaSmooth,AdEMAMix,ADOPT,AdaHessian,Adai,Adalite,AdaLomo,AdamMini,AdamP,AdamS,Adan,AggMo,Aida,AliG,Amos,Apollo,APOLLO,AvaGrad,bSAM,CAME,DAdaptAdaGrad,DAdaptAdam,DAdaptAdan,DAdaptSGD,DAdaptLion,DeMo,DiffGrad,FAdam,Fromage,FTRL,GaLore,Grams,Gravity,GrokFast,GSAM,Kate,Lamb,LaProp,LARS,Lion,LOMO,Lookahead,MADGRAD,MARS,MSVAG,Muno,Nero,NovoGrad,OrthoGrad,PAdam,PCGrad,PID,PNM,Prodigy,QHAdam,QHM,RAdam,Ranger,Ranger21,RotoGrad,SAM,ScheduleFreeSGD,ScheduleFreeAdamW,ScheduleFreeRAdam,SGDP,Shampoo,ScalableShampoo,SGDW,SignSGD,SM3,SOAP,SopihaH,SRMM,StableAdamW,SWATS,Tiger,TRAC,WSAM,Yogi,BCE,BCEFocal,Focal,FocalCosine,SoftF1,Dice,LDAM,Jaccard,Bi-Tempered,Tversky,FocalTversky,LovaszHinge,bitsandbytes,WSD,QGaLore
6
+ Keywords: pytorch,deep-learning,optimizer,lr scheduler,A2Grad,ASGD,AccSGD,AdaBelief,AdaBound,AdaDelta,AdaFactor,AdaMax,AdamG,AdaMod,AdaNorm,AdaPNM,AdaSmooth,AdEMAMix,ADOPT,AdaHessian,Adai,Adalite,AdaLomo,AdamMini,AdamP,AdamS,Adan,AggMo,Aida,AliG,Amos,Apollo,APOLLO,AvaGrad,bSAM,CAME,DAdaptAdaGrad,DAdaptAdam,DAdaptAdan,DAdaptSGD,DAdaptLion,DeMo,DiffGrad,FAdam,Fromage,FTRL,GaLore,Grams,Gravity,GrokFast,GSAM,Kate,Lamb,LaProp,LARS,Lion,LOMO,Lookahead,MADGRAD,MARS,MSVAG,Muno,Nero,NovoGrad,OrthoGrad,PAdam,PCGrad,PID,PNM,Prodigy,QHAdam,QHM,RAdam,Ranger,Ranger21,RotoGrad,SAM,ScheduleFreeSGD,ScheduleFreeAdamW,ScheduleFreeRAdam,SGDP,Shampoo,ScalableShampoo,SGDW,SignSGD,SM3,SOAP,SopihaH,SPAM,SRMM,StableAdamW,SWATS,TAM,Tiger,TRAC,WSAM,Yogi,BCE,BCEFocal,Focal,FocalCosine,SoftF1,Dice,LDAM,Jaccard,Bi-Tempered,Tversky,FocalTversky,LovaszHinge,bitsandbytes,WSD,QGaLore
7
7
  Author: kozistr
8
8
  Author-email: kozistr@gmail.com
9
9
  Maintainer: kozistr
@@ -51,8 +51,8 @@ Description-Content-Type: text/markdown
51
51
 
52
52
  ## The reasons why you use `pytorch-optimizer`.
53
53
 
54
- * Wide range of supported optimizers. Currently, **89 optimizers (+ `bitsandbytes`, `qgalore`, `torchao`)**, **16 lr schedulers**, and **13 loss functions** are supported!
55
- * Including many variants such as `Cautious`, `AdamD`, `Gradient Centrailiaztion`
54
+ * Wide range of supported optimizers. Currently, **92 optimizers (+ `bitsandbytes`, `qgalore`, `torchao`)**, **16 lr schedulers**, and **13 loss functions** are supported!
55
+ * Including many variants such as `ADOPT`, `Cautious`, `AdamD`, `StableAdamW`, and `Gradient Centrailiaztion`
56
56
  * Easy to use, clean, and tested codes
57
57
  * Active maintenance
58
58
  * Somewhat a bit more optimized compared to the original implementation
@@ -239,6 +239,8 @@ get_supported_optimizers(['adam*', 'ranger*'])
239
239
  | Grams | *Gradient Descent with Adaptive Momentum Scaling* | | <https://arxiv.org/abs/2412.17107> | [cite](https://ui.adsabs.harvard.edu/abs/2024arXiv241217107C/exportcitation) |
240
240
  | OrthoGrad | *Grokking at the Edge of Numerical Stability* | [github](https://github.com/LucasPrietoAl/grokking-at-the-edge-of-numerical-stability) | <https://arxiv.org/abs/2501.04697> | [cite](https://github.com/LucasPrietoAl/grokking-at-the-edge-of-numerical-stability?tab=readme-ov-file#citation) |
241
241
  | Adam-ATAN2 | *Scaling Exponents Across Parameterizations and Optimizers* | | <https://arxiv.org/abs/2407.05872> | [cite](https://ui.adsabs.harvard.edu/abs/2024arXiv240705872E/exportcitation) |
242
+ | SPAM | *Spike-Aware Adam with Momentum Reset for Stable LLM Training* | [github](https://github.com/TianjinYellow/SPAM-Optimizer) | <https://arxiv.org/abs/2501.06842> | [cite](https://ui.adsabs.harvard.edu/abs/2025arXiv250106842H/exportcitation) |
243
+ | TAM | *Torque-Aware Momentum* | | <https://arxiv.org/abs/2412.18790> | [cite](https://ui.adsabs.harvard.edu/abs/2024arXiv241218790M/exportcitation) |
242
244
 
243
245
  ## Supported LR Scheduler
244
246
 
@@ -10,8 +10,8 @@
10
10
 
11
11
  ## The reasons why you use `pytorch-optimizer`.
12
12
 
13
- * Wide range of supported optimizers. Currently, **89 optimizers (+ `bitsandbytes`, `qgalore`, `torchao`)**, **16 lr schedulers**, and **13 loss functions** are supported!
14
- * Including many variants such as `Cautious`, `AdamD`, `Gradient Centrailiaztion`
13
+ * Wide range of supported optimizers. Currently, **92 optimizers (+ `bitsandbytes`, `qgalore`, `torchao`)**, **16 lr schedulers**, and **13 loss functions** are supported!
14
+ * Including many variants such as `ADOPT`, `Cautious`, `AdamD`, `StableAdamW`, and `Gradient Centrailiaztion`
15
15
  * Easy to use, clean, and tested codes
16
16
  * Active maintenance
17
17
  * Somewhat a bit more optimized compared to the original implementation
@@ -198,6 +198,8 @@ get_supported_optimizers(['adam*', 'ranger*'])
198
198
  | Grams | *Gradient Descent with Adaptive Momentum Scaling* | | <https://arxiv.org/abs/2412.17107> | [cite](https://ui.adsabs.harvard.edu/abs/2024arXiv241217107C/exportcitation) |
199
199
  | OrthoGrad | *Grokking at the Edge of Numerical Stability* | [github](https://github.com/LucasPrietoAl/grokking-at-the-edge-of-numerical-stability) | <https://arxiv.org/abs/2501.04697> | [cite](https://github.com/LucasPrietoAl/grokking-at-the-edge-of-numerical-stability?tab=readme-ov-file#citation) |
200
200
  | Adam-ATAN2 | *Scaling Exponents Across Parameterizations and Optimizers* | | <https://arxiv.org/abs/2407.05872> | [cite](https://ui.adsabs.harvard.edu/abs/2024arXiv240705872E/exportcitation) |
201
+ | SPAM | *Spike-Aware Adam with Momentum Reset for Stable LLM Training* | [github](https://github.com/TianjinYellow/SPAM-Optimizer) | <https://arxiv.org/abs/2501.06842> | [cite](https://ui.adsabs.harvard.edu/abs/2025arXiv250106842H/exportcitation) |
202
+ | TAM | *Torque-Aware Momentum* | | <https://arxiv.org/abs/2412.18790> | [cite](https://ui.adsabs.harvard.edu/abs/2024arXiv241218790M/exportcitation) |
201
203
 
202
204
  ## Supported LR Scheduler
203
205
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pytorch_optimizer"
3
- version = "3.3.3"
3
+ version = "3.3.4"
4
4
  description = "optimizer & lr scheduler & objective function collections in PyTorch"
5
5
  license = "Apache-2.0"
6
6
  authors = ["kozistr <kozistr@gmail.com>"]
@@ -18,9 +18,9 @@ keywords = [
18
18
  "Kate", "Lamb", "LaProp", "LARS", "Lion", "LOMO", "Lookahead", "MADGRAD", "MARS", "MSVAG", "Muno", "Nero",
19
19
  "NovoGrad", "OrthoGrad", "PAdam", "PCGrad", "PID", "PNM", "Prodigy", "QHAdam", "QHM", "RAdam", "Ranger",
20
20
  "Ranger21", "RotoGrad", "SAM", "ScheduleFreeSGD", "ScheduleFreeAdamW", "ScheduleFreeRAdam", "SGDP", "Shampoo",
21
- "ScalableShampoo", "SGDW", "SignSGD", "SM3", "SOAP", "SopihaH", "SRMM", "StableAdamW", "SWATS", "Tiger", "TRAC",
22
- "WSAM", "Yogi", "BCE", "BCEFocal", "Focal", "FocalCosine", "SoftF1", "Dice", "LDAM", "Jaccard", "Bi-Tempered",
23
- "Tversky", "FocalTversky", "LovaszHinge", "bitsandbytes", "WSD", "QGaLore",
21
+ "ScalableShampoo", "SGDW", "SignSGD", "SM3", "SOAP", "SopihaH", "SPAM", "SRMM", "StableAdamW", "SWATS", "TAM",
22
+ "Tiger", "TRAC", "WSAM", "Yogi", "BCE", "BCEFocal", "Focal", "FocalCosine", "SoftF1", "Dice", "LDAM", "Jaccard",
23
+ "Bi-Tempered", "Tversky", "FocalTversky", "LovaszHinge", "bitsandbytes", "WSD", "QGaLore",
24
24
  ]
25
25
  classifiers = [
26
26
  "License :: OSI Approved :: Apache Software License",
@@ -61,8 +61,10 @@ from pytorch_optimizer.optimizer import (
61
61
  SGDW,
62
62
  SM3,
63
63
  SOAP,
64
+ SPAM,
64
65
  SRMM,
65
66
  SWATS,
67
+ TAM,
66
68
  TRAC,
67
69
  WSAM,
68
70
  A2Grad,
@@ -87,6 +89,7 @@ from pytorch_optimizer.optimizer import (
87
89
  AdaPNM,
88
90
  AdaShift,
89
91
  AdaSmooth,
92
+ AdaTAM,
90
93
  AdEMAMix,
91
94
  AggMo,
92
95
  Aida,
@@ -1,8 +1,9 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from typing import List
3
3
 
4
+ from torch.optim import Optimizer
5
+
4
6
  from pytorch_optimizer.base.exception import NegativeLRError, NegativeStepError
5
- from pytorch_optimizer.base.types import OPTIMIZER
6
7
 
7
8
 
8
9
  class BaseLinearWarmupScheduler(ABC):
@@ -10,7 +11,7 @@ class BaseLinearWarmupScheduler(ABC):
10
11
 
11
12
  The LR Scheduler class based on this class has linear warmup strategy.
12
13
 
13
- :param optimizer: Optimizer. OPTIMIZER. It will set learning rate to all trainable parameters in optimizer.
14
+ :param optimizer: Optimizer. It will set learning rate to all trainable parameters in optimizer.
14
15
  :param t_max: int. total steps to train.
15
16
  :param max_lr: float. maximum lr.
16
17
  :param min_lr: float. minimum lr.
@@ -20,7 +21,7 @@ class BaseLinearWarmupScheduler(ABC):
20
21
 
21
22
  def __init__(
22
23
  self,
23
- optimizer: OPTIMIZER,
24
+ optimizer: Optimizer,
24
25
  t_max: int,
25
26
  max_lr: float,
26
27
  min_lr: float = 0.0,
@@ -11,6 +11,7 @@ DEFAULTS = Dict
11
11
  PARAMETERS = Optional[Union[Iterable[Dict], Iterable[torch.Tensor]]]
12
12
  STATE = Dict
13
13
  OPTIMIZER = Type[Optimizer]
14
+ OPTIMIZER_INSTANCE_OR_CLASS = Union[OPTIMIZER, Optimizer]
14
15
  SCHEDULER = Type[LRScheduler]
15
16
 
16
17
  HUTCHINSON_G = Literal['gaussian', 'rademacher']
@@ -1,10 +1,9 @@
1
1
  import math
2
2
  from typing import List, Optional
3
3
 
4
+ from torch.optim import Optimizer
4
5
  from torch.optim.lr_scheduler import LRScheduler
5
6
 
6
- from pytorch_optimizer.base.types import OPTIMIZER
7
-
8
7
 
9
8
  class CosineAnnealingWarmupRestarts(LRScheduler):
10
9
  r"""CosineAnnealingWarmupRestarts.
@@ -21,7 +20,7 @@ class CosineAnnealingWarmupRestarts(LRScheduler):
21
20
 
22
21
  def __init__(
23
22
  self,
24
- optimizer: OPTIMIZER,
23
+ optimizer: Optimizer,
25
24
  first_cycle_steps: int,
26
25
  cycle_mult: float = 1.0,
27
26
  max_lr: float = 1e-4,
@@ -53,7 +52,7 @@ class CosineAnnealingWarmupRestarts(LRScheduler):
53
52
 
54
53
  self.init_lr()
55
54
 
56
- def init_lr(self):
55
+ def init_lr(self) -> None:
57
56
  self.base_lrs = []
58
57
  for param_group in self.optimizer.param_groups:
59
58
  param_group['lr'] = self.min_lr
@@ -1,9 +1,8 @@
1
1
  from typing import List, Optional
2
2
 
3
+ from torch.optim import Optimizer
3
4
  from torch.optim.lr_scheduler import LRScheduler
4
5
 
5
- from pytorch_optimizer.base.types import OPTIMIZER
6
-
7
6
 
8
7
  class REXScheduler(LRScheduler):
9
8
  r"""Revisiting Budgeted Training with an Improved Schedule.
@@ -16,7 +15,7 @@ class REXScheduler(LRScheduler):
16
15
 
17
16
  def __init__(
18
17
  self,
19
- optimizer: OPTIMIZER,
18
+ optimizer: Optimizer,
20
19
  total_steps: int,
21
20
  max_lr: float = 1.0,
22
21
  min_lr: float = 0.0,
@@ -35,7 +34,7 @@ class REXScheduler(LRScheduler):
35
34
 
36
35
  self.init_lr()
37
36
 
38
- def init_lr(self):
37
+ def init_lr(self) -> None:
39
38
  self.base_lrs = []
40
39
  for param_group in self.optimizer.param_groups:
41
40
  param_group['lr'] = self.min_lr
@@ -1,10 +1,10 @@
1
1
  import fnmatch
2
2
  from importlib.util import find_spec
3
- from typing import Dict, List, Optional, Sequence, Set, Union
3
+ from typing import Dict, List, Optional, Sequence, Set, Type, Union
4
4
 
5
5
  import torch
6
6
  from torch import nn
7
- from torch.optim import AdamW
7
+ from torch.optim import AdamW, Optimizer
8
8
 
9
9
  from pytorch_optimizer.base.types import OPTIMIZER, PARAMETERS
10
10
  from pytorch_optimizer.optimizer.a2grad import A2Grad
@@ -83,8 +83,10 @@ from pytorch_optimizer.optimizer.shampoo import ScalableShampoo, Shampoo
83
83
  from pytorch_optimizer.optimizer.sm3 import SM3
84
84
  from pytorch_optimizer.optimizer.soap import SOAP
85
85
  from pytorch_optimizer.optimizer.sophia import SophiaH
86
+ from pytorch_optimizer.optimizer.spam import SPAM
86
87
  from pytorch_optimizer.optimizer.srmm import SRMM
87
88
  from pytorch_optimizer.optimizer.swats import SWATS
89
+ from pytorch_optimizer.optimizer.tam import TAM, AdaTAM
88
90
  from pytorch_optimizer.optimizer.tiger import Tiger
89
91
  from pytorch_optimizer.optimizer.trac import TRAC
90
92
  from pytorch_optimizer.optimizer.yogi import Yogi
@@ -251,6 +253,8 @@ OPTIMIZER_LIST: List[OPTIMIZER] = [
251
253
  SRMM,
252
254
  AvaGrad,
253
255
  AdaShift,
256
+ TAM,
257
+ AdaTAM,
254
258
  AdaDelta,
255
259
  Amos,
256
260
  AdaHessian,
@@ -286,6 +290,7 @@ OPTIMIZER_LIST: List[OPTIMIZER] = [
286
290
  MARS,
287
291
  SGDSaI,
288
292
  Grams,
293
+ SPAM,
289
294
  Ranger25,
290
295
  ]
291
296
  OPTIMIZERS: Dict[str, OPTIMIZER] = {str(optimizer.__name__).lower(): optimizer for optimizer in OPTIMIZER_LIST}
@@ -298,8 +303,9 @@ def create_optimizer(
298
303
  weight_decay: float = 0.0,
299
304
  wd_ban_list: List[str] = ('bias', 'LayerNorm.bias', 'LayerNorm.weight'),
300
305
  use_lookahead: bool = False,
306
+ use_orthograd: bool = False,
301
307
  **kwargs,
302
- ):
308
+ ) -> Optimizer:
303
309
  r"""Build optimizer.
304
310
 
305
311
  :param model: nn.Module. model.
@@ -307,7 +313,8 @@ def create_optimizer(
307
313
  :param lr: float. learning rate.
308
314
  :param weight_decay: float. weight decay.
309
315
  :param wd_ban_list: List[str]. weight decay ban list by layer.
310
- :param use_lookahead: bool. use lookahead.
316
+ :param use_lookahead: bool. use Lookahead.
317
+ :param use_orthograd: bool. use OrthoGrad.
311
318
  """
312
319
  optimizer_name = optimizer_name.lower()
313
320
 
@@ -315,14 +322,17 @@ def create_optimizer(
315
322
  get_optimizer_parameters(model, weight_decay, wd_ban_list) if weight_decay > 0.0 else model.parameters()
316
323
  )
317
324
 
318
- optimizer = load_optimizer(optimizer_name)
325
+ optimizer_class: OPTIMIZER = load_optimizer(optimizer_name)
319
326
 
320
327
  if optimizer_name == 'alig':
321
- optimizer = optimizer(parameters, max_lr=lr, **kwargs)
328
+ optimizer = optimizer_class(parameters, max_lr=lr, **kwargs)
322
329
  elif optimizer_name in {'lomo', 'adalomo', 'adammini'}:
323
- optimizer = optimizer(model, lr=lr, **kwargs)
330
+ optimizer = optimizer_class(model, lr=lr, **kwargs)
324
331
  else:
325
- optimizer = optimizer(parameters, lr=lr, **kwargs)
332
+ optimizer = optimizer_class(parameters, lr=lr, **kwargs)
333
+
334
+ if use_orthograd:
335
+ optimizer = OrthoGrad(optimizer, **kwargs)
326
336
 
327
337
  if use_lookahead:
328
338
  optimizer = Lookahead(
@@ -13,8 +13,8 @@ class AdaFactor(BaseOptimizer):
13
13
 
14
14
  :param params: PARAMETERS. iterable of parameters to optimize or dicts defining parameter groups.
15
15
  :param lr: float. learning rate.
16
- :param betas: BETAS. coefficients used for computing running averages of gradient and the squared
17
- hessian trace. if beta1 is None, first momentum will be skipped.
16
+ :param betas: BETAS. coefficients used for computing running averages of gradient and the squared hessian trace.
17
+ if beta1 is None, first momentum will be skipped.
18
18
  :param decay_rate: float. coefficient used to compute running averages of square gradient.
19
19
  :param weight_decay: float. weight decay (L2 penalty).
20
20
  :param weight_decouple: bool. the optimizer uses decoupled weight decay as in AdamW.
@@ -141,6 +141,10 @@ class AdamP(BaseOptimizer):
141
141
  inv_de_nom = exp_avg_sq.rsqrt().add_(group['eps']).mul_(bias_correction2_sq)
142
142
 
143
143
  perturb = exp_avg.clone()
144
+
145
+ if self.cautious:
146
+ self.apply_cautious(perturb, grad)
147
+
144
148
  if group['nesterov']:
145
149
  perturb.mul_(beta1).addcmul_(grad, inv_de_nom, value=1.0 - beta1)
146
150
  else:
@@ -173,9 +177,6 @@ class AdamP(BaseOptimizer):
173
177
  bias_correction1=bias_correction1,
174
178
  )
175
179
 
176
- if self.cautious:
177
- self.apply_cautious(perturb, grad)
178
-
179
180
  p.add_(perturb, alpha=-step_size)
180
181
 
181
182
  return loss
@@ -107,8 +107,7 @@ class StableAdamW(BaseOptimizer):
107
107
  exp_avg.lerp_(grad, weight=beta1_comp)
108
108
  exp_avg_sq.mul_(beta2_hat).addcmul_(grad, grad, value=1.0 - beta2_hat)
109
109
 
110
- rms = self.get_stable_adamw_rms(grad, exp_avg_sq, eps=eps_p2)
111
- lr = group['lr'] / rms
110
+ lr: float = group['lr'] / self.get_stable_adamw_rms(grad, exp_avg_sq, eps=eps_p2)
112
111
 
113
112
  self.apply_weight_decay(
114
113
  p,
@@ -11,6 +11,8 @@ from pytorch_optimizer.base.types import BETAS, CLOSURE, DEFAULTS, LOSS, PARAMET
11
11
  class Ranger25(BaseOptimizer):
12
12
  r"""Mixin' every fancy optimizer hacks.
13
13
 
14
+ ADOPT + AdEMAMix + Cautious + StableAdamW + Adam-Atan2
15
+
14
16
  :param params: PARAMETERS. iterable of parameters to optimize or dicts defining parameter groups.
15
17
  :param lr: float. learning rate.
16
18
  :param betas: BETAS. coefficients used for computing running averages of gradient and the squared hessian trace.
@@ -19,10 +21,10 @@ class Ranger25(BaseOptimizer):
19
21
  :param fixed_decay: bool. fix weight decay.
20
22
  :param alpha: float. usually between 4 and 10 would work well.
21
23
  :param t_alpha_beta3: Optional[float]. total number of iterations is preferred when needed.
22
- :param n_sma_threshold: number of SMA threshold (recommended is 5).
23
24
  :param cautious: bool. whether to use the Cautious variant.
24
25
  :param stable_adamw: bool. whether to use stable AdamW variant.
25
- :param eps: float. term added to the denominator to improve numerical stability.
26
+ :param eps: Optional[float]. term added to the denominator to improve numerical stability. when eps is None and
27
+ stable_adamw is False, adam-atan2 feature will be used.
26
28
  """
27
29
 
28
30
  def __init__(
@@ -35,10 +37,9 @@ class Ranger25(BaseOptimizer):
35
37
  fixed_decay: bool = False,
36
38
  alpha: float = 5.0,
37
39
  t_alpha_beta3: Optional[float] = None,
38
- n_sma_threshold: int = 5,
39
40
  cautious: bool = True,
40
41
  stable_adamw: bool = True,
41
- eps: float = 1e-8,
42
+ eps: Optional[float] = 1e-8,
42
43
  **kwargs,
43
44
  ):
44
45
  self.validate_learning_rate(lr)
@@ -48,9 +49,8 @@ class Ranger25(BaseOptimizer):
48
49
  self.validate_non_negative(weight_decay, 'weight_decay')
49
50
  self.validate_non_negative(eps, 'eps')
50
51
 
51
- self.n_sma_threshold = n_sma_threshold
52
52
  self.cautious = cautious
53
- self.stable_adamw = stable_adamw
53
+ self.stable_adamw: bool = stable_adamw if isinstance(eps, float) else False
54
54
 
55
55
  defaults: DEFAULTS = {
56
56
  'lr': lr,
@@ -60,7 +60,7 @@ class Ranger25(BaseOptimizer):
60
60
  'fixed_decay': fixed_decay,
61
61
  'alpha': alpha,
62
62
  't_alpha_beta3': t_alpha_beta3,
63
- 'eps': eps,
63
+ 'eps': eps if (eps is not None) or (eps is None and not stable_adamw) else 1e-8,
64
64
  }
65
65
 
66
66
  super().__init__(params, defaults)
@@ -147,16 +147,14 @@ class Ranger25(BaseOptimizer):
147
147
 
148
148
  exp_avg, exp_avg_sq, exp_avg_slow = state['exp_avg'], state['exp_avg_sq'], state['exp_avg_slow']
149
149
 
150
- de_nom = exp_avg_sq.sqrt().clamp_(min=group['eps'])
151
-
152
- normed_grad = grad.div(de_nom).clamp_(-clip, clip)
150
+ normed_grad = grad.div(
151
+ exp_avg_sq.sqrt().clamp_(min=group['eps'] if group['eps'] is not None else 1e-8)
152
+ ).clamp_(-clip, clip)
153
153
 
154
154
  exp_avg.mul_(beta1).add_(normed_grad, alpha=1.0 - beta1)
155
155
  exp_avg_sq.mul_(beta2).addcmul_(grad, grad, value=1.0 - beta2)
156
156
  exp_avg_slow.mul_(beta3_t).add_(normed_grad, alpha=1.0 - beta3_t)
157
157
 
158
- de_nom = exp_avg_sq.sqrt().div_(bias_correction2_sq).add_(group['eps'])
159
-
160
158
  update = exp_avg.clone()
161
159
  if self.cautious:
162
160
  self.apply_cautious(update, grad)
@@ -164,21 +162,14 @@ class Ranger25(BaseOptimizer):
164
162
  if self.stable_adamw:
165
163
  step_size /= self.get_stable_adamw_rms(grad, exp_avg_sq)
166
164
 
167
- step_size, n_sma = self.get_rectify_step_size(
168
- is_rectify=True,
169
- step=group['step'],
170
- lr=step_size,
171
- beta2=beta2,
172
- n_sma_threshold=self.n_sma_threshold,
173
- degenerated_to_sgd=False,
174
- )
165
+ update.add_(exp_avg_slow, alpha=alpha_t)
166
+
167
+ de_nom = exp_avg_sq.sqrt().div_(bias_correction2_sq)
175
168
 
176
- update.add_(exp_avg_slow, alpha=alpha_t).div_(de_nom)
169
+ if group['eps'] is not None:
170
+ p.addcdiv_(update, de_nom.add_(group['eps']), value=-step_size)
171
+ continue
177
172
 
178
- if n_sma >= self.n_sma_threshold:
179
- de_nom = exp_avg_sq.sqrt().add_(group['eps'])
180
- p.addcdiv_(update, de_nom, value=-step_size)
181
- else:
182
- p.add_(update, alpha=-step_size)
173
+ p.add_(update.atan2_(de_nom), alpha=-step_size)
183
174
 
184
175
  return loss
@@ -4,7 +4,7 @@ import torch
4
4
  from torch import nn
5
5
  from torch.optim import Optimizer
6
6
 
7
- from pytorch_optimizer.base.types import CLOSURE, OPTIMIZER, PARAMETERS
7
+ from pytorch_optimizer.base.types import CLOSURE, PARAMETERS
8
8
  from pytorch_optimizer.optimizer.utils import clip_grad_norm, has_overflow
9
9
 
10
10
 
@@ -100,7 +100,7 @@ class SafeFP16Optimizer(Optimizer): # pragma: no cover
100
100
 
101
101
  def __init__(
102
102
  self,
103
- optimizer: OPTIMIZER,
103
+ optimizer: Optimizer,
104
104
  aggregate_g_norms: bool = False,
105
105
  min_loss_scale: float = 2 ** -5,
106
106
  ): # fmt: skip
@@ -113,10 +113,9 @@ class SafeFP16Optimizer(Optimizer): # pragma: no cover
113
113
 
114
114
  # we want the optimizer to be tracking the fp32 parameters
115
115
  if len(optimizer.param_groups) != 1:
116
- # future implementers: this should hopefully be a matter of just
117
- # iterating through the param groups and keeping track of the pointer
118
- # through the fp32_params
119
- raise NotImplementedError('[-] Need to implement the parameter group transfer.')
116
+ # future implementers: this should hopefully be a matter of just iterating through the param groups and
117
+ # keeping track of the pointer through the fp32_params
118
+ raise NotImplementedError('Need to implement the parameter group transfer.')
120
119
 
121
120
  optimizer.param_groups[0]['params'] = self.fp32_params
122
121
 
@@ -124,17 +123,16 @@ class SafeFP16Optimizer(Optimizer): # pragma: no cover
124
123
  self.needs_sync: bool = True
125
124
 
126
125
  @classmethod
127
- def get_parameters(cls, optimizer: OPTIMIZER):
126
+ def get_parameters(cls, optimizer: Optimizer) -> List:
128
127
  params: List = []
129
- for pg in optimizer.param_groups:
130
- params += list(pg['params'])
128
+ for group in optimizer.param_groups:
129
+ params += list(group['params'])
131
130
  return params
132
131
 
133
132
  @classmethod
134
133
  def build_fp32_params(
135
134
  cls, parameters: PARAMETERS, flatten: bool = True
136
135
  ) -> Union[torch.Tensor, List[torch.Tensor]]:
137
- # create FP32 copy of parameters and grads
138
136
  if flatten:
139
137
  total_param_size: int = sum(p.numel() for p in parameters)
140
138
  fp32_params = torch.zeros(total_param_size, dtype=torch.float, device=parameters[0].device)
@@ -142,7 +140,7 @@ class SafeFP16Optimizer(Optimizer): # pragma: no cover
142
140
  offset: int = 0
143
141
  for p in parameters:
144
142
  p_num_el = p.numel()
145
- fp32_params[offset : offset + p_num_el].copy_(p.view(-1))
143
+ fp32_params[offset:offset + p_num_el].copy_(p.view(-1)) # fmt: skip
146
144
  offset += p_num_el
147
145
 
148
146
  fp32_params = nn.Parameter(fp32_params)
@@ -168,9 +166,9 @@ class SafeFP16Optimizer(Optimizer): # pragma: no cover
168
166
  def load_state_dict(self, state_dict: Dict):
169
167
  r"""Load an optimizer state dict.
170
168
 
171
- In general, we should prefer the configuration of the existing optimizer instance
172
- (e.g., learning rate) over that found in the state_dict. This allows us to
173
- resume training from a checkpoint using a new set of optimizer args.
169
+ In general, we should prefer the configuration of the existing optimizer instance (e.g., learning rate)
170
+ over that found in the state_dict. This allows us to resume training from a checkpoint using a new set of
171
+ optimizer args.
174
172
 
175
173
  :param state_dict: Dict. state_dict.
176
174
  """
@@ -196,35 +194,34 @@ class SafeFP16Optimizer(Optimizer): # pragma: no cover
196
194
  if update_main_grads:
197
195
  self.update_main_grads()
198
196
 
199
- def sync_fp16_grads_to_fp32(self, multiply_grads: float = 1.0):
197
+ def sync_fp16_grads_to_fp32(self, multiply_grads: float = 1.0) -> None:
200
198
  r"""Sync fp16 to fp32 gradients."""
201
199
  if self.needs_sync:
202
200
  if self.scaler is not None:
203
- # correct for dynamic loss scaler
204
201
  multiply_grads /= self.scaler.loss_scale
205
202
 
206
- # copy FP16 grads to FP32
207
- for p, p32 in zip(self.fp16_params, self.fp32_params):
208
- if not p.requires_grad:
203
+ for p16, p32 in zip(self.fp16_params, self.fp32_params):
204
+ if not p16.requires_grad:
209
205
  continue
210
206
 
211
- if p.grad is not None:
212
- p32.grad.copy_(p.grad)
207
+ if p16.grad is not None:
208
+ p32.grad.copy_(p16.grad)
213
209
  p32.grad.mul_(multiply_grads)
214
210
  else:
215
- p32.grad = torch.zeros_like(p, dtype=torch.float)
211
+ p32.grad = torch.zeros_like(p16, dtype=torch.float)
216
212
 
217
213
  self.needs_sync = False
218
214
 
219
- def multiply_grads(self, c: float):
215
+ def multiply_grads(self, c: float) -> None:
220
216
  r"""Multiply grads by a constant c."""
221
217
  if self.needs_sync:
222
218
  self.sync_fp16_grads_to_fp32(c)
223
- else:
224
- for p32 in self.fp32_params:
225
- p32.grad.mul_(c)
219
+ return
226
220
 
227
- def update_main_grads(self):
221
+ for p32 in self.fp32_params:
222
+ p32.grad.mul_(c)
223
+
224
+ def update_main_grads(self) -> None:
228
225
  self.sync_fp16_grads_to_fp32()
229
226
 
230
227
  def clip_main_grads(self, max_norm: float):
@@ -249,8 +246,7 @@ class SafeFP16Optimizer(Optimizer): # pragma: no cover
249
246
 
250
247
  raise FloatingPointError(
251
248
  f'Minimum loss scale reached ({self.min_loss_scale}). Your loss is probably exploding. '
252
- 'Try lowering the learning rate, using gradient clipping or '
253
- 'increasing the batch size.\n'
249
+ 'Try lowering the learning rate, using gradient clipping or increasing the batch size.\n'
254
250
  f'Overflow: setting loss scale to {self.scaler.loss_scale}'
255
251
  )
256
252
 
@@ -261,16 +257,15 @@ class SafeFP16Optimizer(Optimizer): # pragma: no cover
261
257
  self.sync_fp16_grads_to_fp32()
262
258
  self.optimizer.step(closure)
263
259
 
264
- # copy FP32 params back into FP16 model
265
- for p, p32 in zip(self.fp16_params, self.fp32_params):
266
- if not p.requires_grad:
260
+ for p16, p32 in zip(self.fp16_params, self.fp32_params):
261
+ if not p16.requires_grad:
267
262
  continue
268
- p.data.copy_(p32)
263
+ p16.data.copy_(p32)
269
264
 
270
- def zero_grad(self):
265
+ def zero_grad(self) -> None:
271
266
  r"""Clear the gradients of all optimized parameters."""
272
- for p in self.fp16_params:
273
- p.grad = None
267
+ for p16 in self.fp16_params:
268
+ p16.grad = None
274
269
  for p32 in self.fp32_params:
275
270
  p32.grad.zero_()
276
271
  self.needs_sync = False
@@ -2,15 +2,16 @@ from collections import defaultdict
2
2
  from typing import Callable, Dict
3
3
 
4
4
  import torch
5
+ from torch.optim import Optimizer
5
6
 
6
7
  from pytorch_optimizer.base.optimizer import BaseOptimizer
7
- from pytorch_optimizer.base.types import CLOSURE, DEFAULTS, LOSS, OPTIMIZER, STATE
8
+ from pytorch_optimizer.base.types import CLOSURE, DEFAULTS, LOSS, OPTIMIZER_INSTANCE_OR_CLASS, STATE
8
9
 
9
10
 
10
11
  class Lookahead(BaseOptimizer):
11
12
  r"""k steps forward, 1 step back.
12
13
 
13
- :param optimizer: OPTIMIZER. base optimizer.
14
+ :param optimizer: OPTIMIZER_INSTANCE_OR_CLASS. base optimizer.
14
15
  :param k: int. number of lookahead steps.
15
16
  :param alpha: float. linear interpolation factor.
16
17
  :param pullback_momentum: str. change to inner optimizer momentum on interpolation update.
@@ -18,7 +19,7 @@ class Lookahead(BaseOptimizer):
18
19
 
19
20
  def __init__(
20
21
  self,
21
- optimizer: OPTIMIZER,
22
+ optimizer: OPTIMIZER_INSTANCE_OR_CLASS,
22
23
  k: int = 5,
23
24
  alpha: float = 0.5,
24
25
  pullback_momentum: str = 'none',
@@ -28,10 +29,17 @@ class Lookahead(BaseOptimizer):
28
29
  self.validate_range(alpha, 'alpha', 0.0, 1.0)
29
30
  self.validate_options(pullback_momentum, 'pullback_momentum', ['none', 'reset', 'pullback'])
30
31
 
32
+ if isinstance(optimizer, Optimizer):
33
+ self.optimizer = optimizer
34
+ elif 'params' in kwargs:
35
+ params = kwargs.pop('params')
36
+ self.optimizer = optimizer(params, **kwargs)
37
+ else:
38
+ raise ValueError('Need to pass `params` when you pass the torch.optim.Optimizer instance.')
39
+
31
40
  self._optimizer_step_pre_hooks: Dict[int, Callable] = {}
32
41
  self._optimizer_step_post_hooks: Dict[int, Callable] = {}
33
42
 
34
- self.optimizer = optimizer
35
43
  self.alpha = alpha
36
44
  self.k = k
37
45
  self.pullback_momentum = pullback_momentum
@@ -53,7 +61,7 @@ class Lookahead(BaseOptimizer):
53
61
  'lookahead_alpha': alpha,
54
62
  'lookahead_k': k,
55
63
  'lookahead_pullback_momentum': pullback_momentum,
56
- **optimizer.defaults,
64
+ **self.optimizer.defaults,
57
65
  }
58
66
 
59
67
  @property