multimodalart's picture
multimodalart HF Staff
Upload folder using huggingface_hub
93c14fa verified
Raw
History Blame Contribute Delete
4.95 kB
import os, torch
from tqdm import tqdm
from accelerate import Accelerator
from .training_module import DiffusionTrainingModule
from src.training_module import MetaViewTrainingModule
from .logger import ModelLogger
from PIL import Image
def collate_fn(batch):
if len(batch) == 0:
return {}
collated = {}
keys = batch[0].keys()
for key in keys:
values = [sample[key] for sample in batch]
first_val = values[0]
if isinstance(first_val, torch.Tensor):
# 对于 Tensor,使用 torch.stack 沿第0维堆叠(要求所有张量形状相同)
collated[key] = torch.stack(values, dim=0)
elif isinstance(first_val, Image.Image):
collated[key] = values
elif isinstance(first_val, str):
collated[key] = values
else:
collated[key] = values
return collated
def launch_training_task(
accelerator: Accelerator,
dataset: torch.utils.data.Dataset,
model: MetaViewTrainingModule,
model_logger: ModelLogger,
learning_rate: float = 1e-5,
weight_decay: float = 1e-2,
num_workers: int = 1,
save_steps: int = None,
num_epochs: int = 1,
batch_size: int = 1,
args = None,
):
if args is not None:
learning_rate = args.learning_rate
weight_decay = args.weight_decay
num_workers = args.dataset_num_workers
save_steps = args.save_steps
num_epochs = args.num_epochs
optimizer = torch.optim.AdamW(model.trainable_modules(), lr=learning_rate, weight_decay=weight_decay)
scheduler = torch.optim.lr_scheduler.ConstantLR(optimizer)
# dataloader = torch.utils.data.DataLoader(dataset, shuffle=False, collate_fn=lambda x: x[0], num_workers=num_workers)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True, collate_fn=collate_fn, num_workers=num_workers)
model, optimizer, dataloader, scheduler = accelerator.prepare(model, optimizer, dataloader, scheduler)
def grad_hook(name):
def hook(grad):
# # print(f"{name} gradient norm:{grad.norm().item():.6f}")
# if grad.norm().item() > 1:
# print(f" gradient over 1: {name} {grad.norm().item():.6f}")
if torch.isnan(grad).any():
print(f"!!! NaN gradient: {name}")
if torch.isinf(grad).any():
print(f"!!! Inf gradient: {name}")
return grad
return hook
for name, param in model.named_parameters():
if param.requires_grad:
param.register_hook(grad_hook(name))
NaN_step = 0
for epoch_id in range(num_epochs):
for data in tqdm(dataloader):
with accelerator.accumulate(model):
# print(type(data))
# print(data["prompt"])
optimizer.zero_grad()
if dataset.load_from_cache:
loss = model({}, inputs=data)
else:
loss = model(data)
if torch.isnan(loss).any():
print(f"!!! Loss is NaN at step {model_logger.num_steps}! Skipping...")
NaN_step += 1
print(data["name"])
exit(0)
accelerator.backward(loss)
max_norm = 5.0
if accelerator.sync_gradients:
grad_norm = accelerator.clip_grad_norm_(model.parameters(), max_norm=max_norm)
if accelerator.is_main_process:
if grad_norm > 5.0:
print(f"gradient over 5: {grad_norm:.4f}")
optimizer.step()
model_logger.on_step_end(accelerator, model, save_steps)
scheduler.step()
if save_steps is None:
model_logger.on_epoch_end(accelerator, model, epoch_id)
model_logger.on_training_end(accelerator, model, save_steps)
def launch_data_process_task(
accelerator: Accelerator,
dataset: torch.utils.data.Dataset,
model: DiffusionTrainingModule,
model_logger: ModelLogger,
num_workers: int = 8,
args = None,
):
if args is not None:
num_workers = args.dataset_num_workers
dataloader = torch.utils.data.DataLoader(dataset, shuffle=False, collate_fn=lambda x: x[0], num_workers=num_workers)
model, dataloader = accelerator.prepare(model, dataloader)
for data_id, data in enumerate(tqdm(dataloader)):
with accelerator.accumulate(model):
with torch.no_grad():
folder = os.path.join(model_logger.output_path, str(accelerator.process_index))
os.makedirs(folder, exist_ok=True)
save_path = os.path.join(model_logger.output_path, str(accelerator.process_index), f"{data_id}.pth")
data = model(data)
torch.save(data, save_path)