1+ import numpy as np
12import string
23import torch
34
45
56torch ._dynamo .config .cache_size_limit = 1_000_000
67
78try :
8- torch .backends .opt_einsum .strategy = ' dynamic-programming'
9+ torch .backends .opt_einsum .strategy = " dynamic-programming"
910except AttributeError :
1011 # opt_einsum backend is not available, so we'll skip setting the strategy
1112 pass
1213
1314
1415def precond_update_prob_schedule (
15- max_prob = 1.0 , min_prob = 0.03 , decay = 0.001 , flat_start = 200
16+ max_prob = 1.0 , min_prob = 0.03 , decay = 0.001 , flat_start = 250
1617):
1718 """Anneal preconditioner update probability during beginning of training.
1819
@@ -45,21 +46,24 @@ class Kron(torch.optim.Optimizer):
4546 Args:
4647 params (iterable): Iterable of parameters to optimize or dicts defining
4748 parameter groups.
48- lr (float, optional ): Learning rate (default: 0.001) .
49- b1 (float, optional ): Momentum parameter (default: 0.9) .
50- weight_decay (float, optional ): Weight decay (L2 penalty) (default: 0.0 ).
49+ lr (float): Learning rate.
50+ b1 (float): Momentum parameter.
51+ weight_decay (float): Weight decay (L2 penalty).
5152 preconditioner_update_probability (callable or float, optional): Probability of
5253 updating the preconditioner. If None, defaults to a schedule that anneals
5354 from 1.0 to 0.03 by 4000 steps.
54- max_size_triangular (int, optional): Max size for dim's preconditioner to be
55- triangular (default: 8192).
56- max_skew_triangular (float, optional): Max skew for dim's preconditioner to be
57- triangular (default: inf).
58- min_ndim_triangular (int, optional): Minimum number of dimensions a layer needs
59- to have triangular preconditioners (default: 2).
60- mu_dtype (torch.dtype, optional): Dtype of the momentum accumulator. Defaults
61- to the same dtype as the parameters.
62- precond_dtype (torch.dtype, optional): Dtype of the preconditioner (default: None).
55+ max_size_triangular (int): Max size for dim's preconditioner to be triangular.
56+ min_ndim_triangular (int): Minimum number of dimensions a layer needs
57+ to have triangular preconditioners.
58+ memory_save_mode: (string, optional), None, 'one_diag', or 'all_diag', None is default
59+ to set all preconditioners to be triangular, 'one_diag' sets the largest
60+ or last dim to be diagonal per layer, and 'all_diag' sets all preconditioners
61+ to be diagonal.
62+ mu_dtype (torch.dtype, optional): Dtype of the momentum accumulator.
63+ precond_dtype (torch.dtype, optional): Dtype of the preconditioner.
64+ trust_region_scale (float): Trust region on preconditioned grads. Normally this
65+ doesn't need to be changed but if things seem unstable you can try reducing
66+ this to 1.5.
6367 """
6468
6569 def __init__ (
@@ -70,10 +74,11 @@ def __init__(
7074 weight_decay = 0.0 ,
7175 preconditioner_update_probability = None ,
7276 max_size_triangular = 8192 ,
73- max_skew_triangular = float ("inf" ),
7477 min_ndim_triangular = 2 ,
78+ memory_save_mode = None ,
7579 mu_dtype = None ,
7680 precond_dtype = None ,
81+ trust_region_scale = 2.0 ,
7782 ):
7883 if not 0.0 <= lr :
7984 raise ValueError (f"Invalid learning rate: { lr } " )
@@ -91,26 +96,17 @@ def __init__(
9196 weight_decay = weight_decay ,
9297 preconditioner_update_probability = preconditioner_update_probability ,
9398 max_size_triangular = max_size_triangular ,
94- max_skew_triangular = max_skew_triangular ,
9599 min_ndim_triangular = min_ndim_triangular ,
100+ memory_save_mode = memory_save_mode ,
96101 precond_lr = 0.1 , # precond lr hardcoded to 0.1
97102 precond_init_scale = 1.0 , # precond init scale hardcoded to 1.0
98103 mu_dtype = mu_dtype ,
99104 precond_dtype = precond_dtype ,
105+ trust_region_scale = trust_region_scale ,
100106 )
101107 super (Kron , self ).__init__ (params , defaults )
102108
103- self ._global_clip = (
104- sum (
105- p .numel ()
106- for group in self .param_groups
107- for p in group ["params" ]
108- if p .requires_grad
109- )
110- ** 0.5
111- )
112- self ._element_clip = 1.0
113- self ._tiny = 1e-30
109+ self ._tiny = torch .finfo (torch .bfloat16 ).tiny
114110 self ._prob_step = 0
115111
116112 @torch .no_grad ()
@@ -132,7 +128,7 @@ def step(self, closure=None):
132128 device = self .param_groups [0 ]["params" ][0 ].device
133129 do_update = torch .rand ([], device = device ) < update_prob
134130 self ._prob_step += 1
135-
131+
136132 balance = torch .rand ([], device = device ) < 0.01 and do_update
137133
138134 for group in self .param_groups :
@@ -155,8 +151,8 @@ def step(self, closure=None):
155151 p ,
156152 group ["precond_init_scale" ],
157153 group ["max_size_triangular" ],
158- group ["max_skew_triangular" ],
159154 group ["min_ndim_triangular" ],
155+ group ["memory_save_mode" ],
160156 dtype = precond_dtype ,
161157 )
162158
@@ -206,8 +202,10 @@ def step(self, closure=None):
206202 ).to (dtype = p .dtype , non_blocking = True )
207203
208204 # Apply trust region
209- torch .nn .utils .clip_grad_norm_ (pre_grad , self ._global_clip )
210- pre_grad .clamp_ (- self ._element_clip , self ._element_clip )
205+ pre_grad = (
206+ torch .tanh (pre_grad / group ["trust_region_scale" ])
207+ * group ["trust_region_scale" ]
208+ )
211209
212210 # Apply weight decay and update parameters
213211 if group ["weight_decay" ] != 0 and p .dim () >= 2 :
@@ -231,7 +229,7 @@ def step(self, closure=None):
231229 return loss
232230
233231
234- def init_Q_exprs (t , scale , max_size , max_skew , min_ndim_triangular , dtype = None ):
232+ def init_Q_exprs (t , scale , max_size , min_ndim_triangular , memory_save_mode , dtype = None ):
235233 """For a scalar or tensor t, we initialize its preconditioner Q and
236234 reusable einsum expressions for updating Q and preconditioning gradient.
237235 """
@@ -242,30 +240,40 @@ def init_Q_exprs(t, scale, max_size, max_skew, min_ndim_triangular, dtype=None):
242240 if len (shape ) == 0 : # scalar
243241 Q = [scale * torch .ones_like (t , dtype = dtype )]
244242 exprA = ",->,"
245- exprP = ",,->,"
246243 exprGs = [",->" ]
244+ exprP = ",,->,"
247245 else : # tensor
248246 if len (shape ) > 13 :
249247 raise ValueError (
250248 f"Got tensor with dim { len (t .shape )} ; Einstein runs out of letters!"
251249 )
252250
253251 scale = scale ** (1 / len (shape ))
254- if len (shape ) == 1 :
255- beta_size = 1 # 2nd largest size
252+
253+ if memory_save_mode is None :
254+ dim_diag = [False for _ in shape ]
255+ elif memory_save_mode == "one_diag" :
256+ rev_sorted_dims = np .argsort (shape )[::- 1 ]
257+ dim_diag = [False for _ in shape ]
258+ dim_diag [rev_sorted_dims [0 ]] = True
259+ elif memory_save_mode == "all_diag" :
260+ dim_diag = [True for _ in shape ]
256261 else :
257- beta_size = sorted (list (shape ))[- 2 ]
262+ raise ValueError (
263+ f"Invalid memory_save_mode: { memory_save_mode } , must be one of "
264+ "[None, 'one_diag', 'all_diag']"
265+ )
258266
259267 Q = []
260- exprGs = []
261268 piece1A , piece2A , piece3A = ([], "" , "" )
269+ exprGs = []
262270 piece1P , piece2P , piece3P , piece4P = ([], [], "" , "" )
263- for i , size in enumerate (shape ):
271+ for i , ( size , dim_d ) in enumerate (zip ( shape , dim_diag ) ):
264272 if (
265273 size == 1
266274 or size > max_size
267- or size > max_skew * beta_size
268275 or len (shape ) < min_ndim_triangular
276+ or dim_d
269277 ):
270278 # use diagonal matrix as preconditioner for this dim
271279 Q .append (scale * torch .ones (size , dtype = dtype , device = t .device ))
@@ -274,19 +282,19 @@ def init_Q_exprs(t, scale, max_size, max_skew, min_ndim_triangular, dtype=None):
274282 piece2A = piece2A + letters [i ]
275283 piece3A = piece3A + letters [i ]
276284
277- piece1P .append (letters [i + 13 ])
278- piece2P .append (letters [i + 13 ])
279- piece3P = piece3P + letters [i + 13 ]
280- piece4P = piece4P + letters [i + 13 ]
281-
282285 piece1 = "" .join (
283286 [
284- (letters [j + 13 ] if j == i else letters [j ])
287+ (letters [i + 13 ] if j == i else letters [j ])
285288 for j in range (len (shape ))
286289 ]
287290 )
288291 subscripts = piece1 + "," + piece1 + "->" + letters [i + 13 ]
289292 exprGs .append (subscripts )
293+
294+ piece1P .append (letters [i + 13 ])
295+ piece2P .append (letters [i + 13 ])
296+ piece3P = piece3P + letters [i + 13 ]
297+ piece4P = piece4P + letters [i + 13 ]
290298 else :
291299 # use triangular matrix as preconditioner for this dim
292300 Q .append (scale * torch .eye (size , dtype = dtype , device = t .device ))
@@ -295,21 +303,15 @@ def init_Q_exprs(t, scale, max_size, max_skew, min_ndim_triangular, dtype=None):
295303 piece2A = piece2A + letters [i + 13 ]
296304 piece3A = piece3A + letters [i ]
297305
298- a , b , c = (letters [i ], letters [i + 13 ], letters [i + 26 ])
299- piece1P .append (a + b )
300- piece2P .append (a + c )
301- piece3P = piece3P + c
302- piece4P = piece4P + b
303-
304306 piece1 = "" .join (
305307 [
306- (letters [j + 13 ] if j == i else letters [j ])
308+ (letters [i + 13 ] if j == i else letters [j ])
307309 for j in range (len (shape ))
308310 ]
309311 )
310312 piece2 = "" .join (
311313 [
312- (letters [j + 26 ] if j == i else letters [j ])
314+ (letters [i + 26 ] if j == i else letters [j ])
313315 for j in range (len (shape ))
314316 ]
315317 )
@@ -318,6 +320,12 @@ def init_Q_exprs(t, scale, max_size, max_skew, min_ndim_triangular, dtype=None):
318320 )
319321 exprGs .append (subscripts )
320322
323+ a , b , c = (letters [i ], letters [i + 13 ], letters [i + 26 ])
324+ piece1P .append (a + b )
325+ piece2P .append (a + c )
326+ piece3P = piece3P + c
327+ piece4P = piece4P + b
328+
321329 exprA = "," .join (piece1A ) + "," + piece2A + "->" + piece3A
322330 exprP = (
323331 "," .join (piece1P ) + "," + "," .join (piece2P ) + "," + piece3P + "->" + piece4P
0 commit comments