Vspark / train.py
AyaanAhmed123's picture
VSpark 0.5B base — full arch, scratch init, fully trainable
278133d verified
Raw
History Blame Contribute Delete
3.12 kB
#!/usr/bin/env python3
# train.py — VSpark 0.5B basic training script
# For the memory-efficient Colab version use train_colab.py
import argparse, json, torch, torch.nn.functional as F
from pathlib import Path
from torch.utils.data import Dataset, DataLoader
from torch.optim import AdamW
from torch.optim.lr_scheduler import CosineAnnealingLR
try:
from vspark_model import VSparkModel, VSparkConfig, DDPMScheduler
except ImportError:
from vspark_build_fixed import VSparkModel, VSparkConfig, DDPMScheduler
class DummyVideoDataset(Dataset):
def __init__(self, cfg, size=200):
self.cfg = cfg
self.size = size
def __len__(self):
return self.size
def __getitem__(self, _):
cfg = self.cfg
Hl = cfg.latent_size
return dict(
video_latents = torch.randn(cfg.num_frames, cfg.in_channels, Hl, Hl),
input_ids = torch.randint(0, 49408, (cfg.max_text_len,)),
audio_mel = torch.randn(cfg.mel_frames, cfg.n_mels),
)
def train(args):
device = "cuda" if torch.cuda.is_available() else "cpu"
cfg = VSparkConfig()
model = VSparkModel(cfg).to(device)
scheduler = DDPMScheduler(cfg).to(device)
dataset = DummyVideoDataset(cfg)
loader = DataLoader(dataset, batch_size=args.batch_size, shuffle=True, num_workers=0)
optim = AdamW(model.parameters(), lr=args.lr, weight_decay=1e-2)
lr_sched = CosineAnnealingLR(optim, T_max=args.epochs * len(loader), eta_min=1e-6)
out_dir = Path(args.output_dir); out_dir.mkdir(parents=True, exist_ok=True)
step = 0
for epoch in range(args.epochs):
model.train()
for batch in loader:
lat = batch["video_latents"].to(device)
ids = batch["input_ids"].to(device)
mel = batch["audio_mel"].to(device)
B = lat.shape[0]
t = torch.randint(0, cfg.num_timesteps, (B,), device=device)
noisy_lat, noise_lat = scheduler.add_noise(lat, t)
noisy_mel, noise_mel = scheduler.add_noise(mel, t)
pred_lat = model(noisy_lat, t, ids)
pred_mel = model.predict_audio(noisy_mel, t, ids)
loss = F.mse_loss(pred_lat, noise_lat) + 0.5 * F.mse_loss(pred_mel, noise_mel)
optim.zero_grad()
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
optim.step(); lr_sched.step()
step += 1
if step % args.log_every == 0:
print(f" step={step} loss={loss.item():.4f}")
ckpt = out_dir / f"ckpt_epoch{epoch+1:03d}.pt"
torch.save({"model_state_dict": model.state_dict(), "epoch": epoch + 1}, ckpt)
if __name__ == "__main__":
p = argparse.ArgumentParser()
p.add_argument("--output_dir", default="./checkpoints")
p.add_argument("--epochs", type=int, default=100)
p.add_argument("--batch_size", type=int, default=1)
p.add_argument("--lr", type=float, default=1e-4)
p.add_argument("--log_every", type=int, default=10)
train(p.parse_args())