forked from NVlabs/FastGen
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathct_schedule.py
More file actions
83 lines (68 loc) · 2.82 KB
/
Copy pathct_schedule.py
File metadata and controls
83 lines (68 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
from typing import Callable, TYPE_CHECKING
import wandb
import torch
from fastgen.callbacks.callback import Callback
import fastgen.utils.logging_utils as logger
from fastgen.utils.basic_utils import get_batch_size_total
from fastgen.utils.distributed import is_rank0
if TYPE_CHECKING:
from fastgen.methods import FastGenModel
from fastgen.configs.config import BaseConfig
class CTScheduleCallback(Callback):
config: "BaseConfig"
def __init__(
self,
q: float = 2.0,
ratio_limit: float = 0.999,
kimg_per_stage: int = 12500,
batch_size: int = 1,
):
self.q = q
self.ratio_limit = ratio_limit
self.kimg_per_stage = kimg_per_stage
self.batch_size = batch_size
self.stage = 0
self.ratio = 0.0
def _get_cur_stage(self, model, iteration):
# Start from the saved iteration of the first-stage model in TCM
if hasattr(model, "resume_iter"):
assert isinstance(model.resume_iter, int)
iteration = iteration + model.resume_iter
batch_size = self.batch_size
if hasattr(self, "config"):
# override the batch_size using self.config
batch_size = get_batch_size_total(self.config)
cur_nimg = iteration * batch_size
stage = cur_nimg // (self.kimg_per_stage * 1000)
return stage, cur_nimg
def _update_schedule(self, stage):
self.stage = stage
self.ratio = 1 - 1 / self.q ** (stage + 1)
if self.ratio > self.ratio_limit:
logger.info(f"Clipping ratio from {self.ratio} -> {self.ratio_limit}")
self.ratio = self.ratio_limit
def on_train_begin(self, model: FastGenModel, iteration: int = 0) -> None:
stage, _ = self._get_cur_stage(model, iteration)
self._update_schedule(stage)
setattr(model, "ratio", self.ratio)
def on_training_step_end(
self,
model: FastGenModel,
data_batch: dict[str, torch.Tensor],
output_batch: dict[str, torch.Tensor | Callable],
loss_dict: dict[str, torch.Tensor],
iteration: int = 0,
) -> None:
del data_batch, output_batch, loss_dict
new_stage, cur_nimg = self._get_cur_stage(model, iteration)
if new_stage > self.stage:
self._update_schedule(new_stage)
setattr(model, "ratio", self.ratio)
if hasattr(self, "config"):
# only wandb log when config exists
if iteration % self.config.trainer.logging_iter == 0 and is_rank0():
if wandb.run:
wandb.log({"ct_schedule/kimg": cur_nimg / 1e3, "ct_schedule/ratio": self.ratio}, step=iteration)