Spaces:
Running
Running
from tqdm import tqdm | |
from romatch.utils.utils import to_cuda | |
import romatch | |
import torch | |
import wandb | |
def log_param_statistics(named_parameters, norm_type = 2): | |
named_parameters = list(named_parameters) | |
grads = [p.grad for n, p in named_parameters if p.grad is not None] | |
weight_norms = [p.norm(p=norm_type) for n, p in named_parameters if p.grad is not None] | |
names = [n for n,p in named_parameters if p.grad is not None] | |
param_norm = torch.stack(weight_norms).norm(p=norm_type) | |
device = grads[0].device | |
grad_norms = torch.stack([torch.norm(g.detach(), norm_type).to(device) for g in grads]) | |
nans_or_infs = torch.isinf(grad_norms) | torch.isnan(grad_norms) | |
nan_inf_names = [name for name, naninf in zip(names, nans_or_infs) if naninf] | |
total_grad_norm = torch.norm(grad_norms, norm_type) | |
if torch.any(nans_or_infs): | |
print(f"These params have nan or inf grads: {nan_inf_names}") | |
wandb.log({"grad_norm": total_grad_norm.item()}, step = romatch.GLOBAL_STEP) | |
wandb.log({"param_norm": param_norm.item()}, step = romatch.GLOBAL_STEP) | |
def train_step(train_batch, model, objective, optimizer, grad_scaler, grad_clip_norm = 1.,**kwargs): | |
optimizer.zero_grad() | |
out = model(train_batch) | |
l = objective(out, train_batch) | |
grad_scaler.scale(l).backward() | |
grad_scaler.unscale_(optimizer) | |
log_param_statistics(model.named_parameters()) | |
torch.nn.utils.clip_grad_norm_(model.parameters(), grad_clip_norm) # what should max norm be? | |
grad_scaler.step(optimizer) | |
grad_scaler.update() | |
wandb.log({"grad_scale": grad_scaler._scale.item()}, step = romatch.GLOBAL_STEP) | |
if grad_scaler._scale < 1.: | |
grad_scaler._scale = torch.tensor(1.).to(grad_scaler._scale) | |
romatch.GLOBAL_STEP = romatch.GLOBAL_STEP + romatch.STEP_SIZE # increment global step | |
return {"train_out": out, "train_loss": l.item()} | |
def train_k_steps( | |
n_0, k, dataloader, model, objective, optimizer, lr_scheduler, grad_scaler, progress_bar=True, grad_clip_norm = 1., warmup = None, ema_model = None, pbar_n_seconds = 1, | |
): | |
for n in tqdm(range(n_0, n_0 + k), disable=(not progress_bar) or romatch.RANK > 0, mininterval=pbar_n_seconds): | |
batch = next(dataloader) | |
model.train(True) | |
batch = to_cuda(batch) | |
train_step( | |
train_batch=batch, | |
model=model, | |
objective=objective, | |
optimizer=optimizer, | |
lr_scheduler=lr_scheduler, | |
grad_scaler=grad_scaler, | |
n=n, | |
grad_clip_norm = grad_clip_norm, | |
) | |
if ema_model is not None: | |
ema_model.update() | |
if warmup is not None: | |
with warmup.dampening(): | |
lr_scheduler.step() | |
else: | |
lr_scheduler.step() | |
[wandb.log({f"lr_group_{grp}": lr}) for grp, lr in enumerate(lr_scheduler.get_last_lr())] | |
def train_epoch( | |
dataloader=None, | |
model=None, | |
objective=None, | |
optimizer=None, | |
lr_scheduler=None, | |
epoch=None, | |
): | |
model.train(True) | |
print(f"At epoch {epoch}") | |
for batch in tqdm(dataloader, mininterval=5.0): | |
batch = to_cuda(batch) | |
train_step( | |
train_batch=batch, model=model, objective=objective, optimizer=optimizer | |
) | |
lr_scheduler.step() | |
return { | |
"model": model, | |
"optimizer": optimizer, | |
"lr_scheduler": lr_scheduler, | |
"epoch": epoch, | |
} | |
def train_k_epochs( | |
start_epoch, end_epoch, dataloader, model, objective, optimizer, lr_scheduler | |
): | |
for epoch in range(start_epoch, end_epoch + 1): | |
train_epoch( | |
dataloader=dataloader, | |
model=model, | |
objective=objective, | |
optimizer=optimizer, | |
lr_scheduler=lr_scheduler, | |
epoch=epoch, | |
) | |