MamaPearl's picture
Update train.py
a341645 verified
Raw
History Blame Contribute Delete
4.21 kB
import os
import torch as pt
from torch.amp import autocast, GradScaler
from torch.optim.lr_scheduler import LinearLR, CosineAnnealingLR, SequentialLR
from tqdm.auto import tqdm
from configuration_nula import NulaConfig
from modeling_nula import NulaForImageClassification
from dataset_nula import get_loaders, get_device
NUM_EPOCHS = 50
LR = 1e-3
WEIGHT_DECAY = 0.01
WARMUP_STEPS = 5
GRAD_CLIP = 1.0
SAVE_EVERY = 5
CHECKPOINT_DIR = "./checkpoints"
BEST_MODEL_DIR = "./nula-best-model"
FINAL_MODEL_DIR = "./nula-final-model"
def train_epoch(model, loader, optimizer, scaler, device, epoch):
model.train()
total_loss, total_correct, total_examples = 0.0, 0, 0
pbar = tqdm(loader, desc=f"epoch {epoch}", leave=False)
use_amp = "cuda" in str(device)
for batch in pbar:
x = batch["pixel_values"].to(device, non_blocking=True)
y = batch["labels"].to(device, non_blocking=True)
optimizer.zero_grad(set_to_none=True)
with autocast("cuda", enabled=use_amp):
out = model(pixel_values=x, labels=y)
loss = out.loss
scaler.scale(loss).backward()
scaler.unscale_(optimizer)
pt.nn.utils.clip_grad_norm_(model.parameters(), max_norm=GRAD_CLIP)
scaler.step(optimizer)
scaler.update()
total_loss += loss.item() * y.size(0)
total_correct += (out.logits.argmax(dim=1) == y).sum().item()
total_examples += y.size(0)
pbar.set_postfix(loss=f"{loss.item():.4f}", acc=f"{100 * total_correct / total_examples:.2f}%")
return total_loss / total_examples, total_correct / total_examples
@pt.no_grad()
def evaluate(model, loader, device):
model.eval()
total_loss, total_correct, total_examples = 0.0, 0, 0
for batch in loader:
x = batch["pixel_values"].to(device, non_blocking=True)
y = batch["labels"].to(device, non_blocking=True)
out = model(pixel_values=x, labels=y)
total_loss += out.loss.item() * y.size(0)
total_correct += (out.logits.argmax(dim=1) == y).sum().item()
total_examples += y.size(0)
return total_loss / total_examples, total_correct / total_examples
def train_model(model, train_loader, test_loader, optimizer, scheduler, scaler, device):
best_val_acc = 0.0
os.makedirs(CHECKPOINT_DIR, exist_ok=True)
print(f"training on {device}")
for epoch in range(1, NUM_EPOCHS + 1):
train_loss, train_acc = train_epoch(model, train_loader, optimizer, scaler, device, epoch)
val_loss, val_acc = evaluate(model, test_loader, device)
scheduler.step()
if epoch % SAVE_EVERY == 0:
save_path = f"{CHECKPOINT_DIR}/epoch{epoch}"
model.save_pretrained(save_path)
if val_acc > best_val_acc:
best_val_acc = val_acc
model.save_pretrained(BEST_MODEL_DIR)
print(f"new best: {100 * best_val_acc:.2f}%")
current_lr = optimizer.param_groups[0]["lr"]
print(f"|{'—'*60}|")
print(f"epoch [{epoch}/{NUM_EPOCHS}]")
print(f"lr: {current_lr:.6f}")
print(f"train_loss: {train_loss:.4f}")
print(f"train_acc: {train_acc*100:.2f}%")
print(f"val loss: {val_loss:.4f}")
print(f"val_acc: {val_acc*100:.2f}%")
print(f"best: {best_val_acc*100:.2f}%")
model.save_pretrained(FINAL_MODEL_DIR)
print("final model saved")
if __name__ == "__main__":
DEVICE = get_device()
train_loader, test_loader = get_loaders()
cfg = NulaConfig(block_channels=(128, 256, 512), classifier_hidden_dim=512, use_se=True)
model = NulaForImageClassification(cfg).to(DEVICE)
optimizer = pt.optim.AdamW(model.parameters(), lr=LR, weight_decay=WEIGHT_DECAY)
warmup = LinearLR(optimizer, start_factor=0.1, end_factor=1.0, total_iters=WARMUP_STEPS)
cosine = CosineAnnealingLR(optimizer, T_max=NUM_EPOCHS - WARMUP_STEPS)
scheduler = SequentialLR(optimizer, schedulers=[warmup, cosine], milestones=[WARMUP_STEPS])
scaler = GradScaler("cuda")
print("enjoy <3\n")
train_model(model, train_loader, test_loader, optimizer, scheduler, scaler, DEVICE)