Spaces:
Running
on
Zero
Running
on
Zero
from typing import * | |
import fnmatch | |
import sympy | |
import torch | |
import torch.nn as nn | |
def any_match(s: str, patterns: List[str]) -> bool: | |
return any(fnmatch.fnmatch(s, pat) for pat in patterns) | |
def build_optimizer(model: nn.Module, optimizer_config: Dict[str, Any]) -> torch.optim.Optimizer: | |
named_param_groups = [ | |
{ | |
k: p for k, p in model.named_parameters() if any_match(k, param_group_config['params']['include']) and not any_match(k, param_group_config['params'].get('exclude', [])) | |
} for param_group_config in optimizer_config['params'] | |
] | |
excluded_params = [k for k, p in model.named_parameters() if p.requires_grad and not any(k in named_params for named_params in named_param_groups)] | |
assert len(excluded_params) == 0, f'The following parameters require grad but are excluded from the optimizer: {excluded_params}' | |
optimizer_cls = getattr(torch.optim, optimizer_config['type']) | |
optimizer = optimizer_cls([ | |
{ | |
**param_group_config, | |
'params': list(params.values()), | |
} for param_group_config, params in zip(optimizer_config['params'], named_param_groups) | |
]) | |
return optimizer | |
def parse_lr_lambda(s: str) -> Callable[[int], float]: | |
epoch = sympy.symbols('epoch') | |
lr_lambda = sympy.sympify(s) | |
return sympy.lambdify(epoch, lr_lambda, 'math') | |
def build_lr_scheduler(optimizer: torch.optim.Optimizer, scheduler_config: Dict[str, Any]) -> torch.optim.lr_scheduler._LRScheduler: | |
if scheduler_config['type'] == "SequentialLR": | |
child_schedulers = [ | |
build_lr_scheduler(optimizer, child_scheduler_config) | |
for child_scheduler_config in scheduler_config['params']['schedulers'] | |
] | |
return torch.optim.lr_scheduler.SequentialLR(optimizer, schedulers=child_schedulers, milestones=scheduler_config['params']['milestones']) | |
elif scheduler_config['type'] == "LambdaLR": | |
lr_lambda = scheduler_config['params']['lr_lambda'] | |
if isinstance(lr_lambda, str): | |
lr_lambda = parse_lr_lambda(lr_lambda) | |
elif isinstance(lr_lambda, list): | |
lr_lambda = [parse_lr_lambda(l) for l in lr_lambda] | |
return torch.optim.lr_scheduler.LambdaLR( | |
optimizer, | |
lr_lambda=lr_lambda, | |
) | |
else: | |
scheduler_cls = getattr(torch.optim.lr_scheduler, scheduler_config['type']) | |
scheduler = scheduler_cls(optimizer, **scheduler_config.get('params', {})) | |
return scheduler |