T

Diffusers
Safetensors
T
File size: 7,055 Bytes
964f845
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
"""
Progress Tracking Utilities with tqdm

Provides:
- Epoch-level progress bars
- Step-level metrics display
- ETA calculation
- Formatted logging
"""

import time
from typing import Dict, Optional
from tqdm import tqdm


class TrainingProgressTracker:
    """
    Manages training progress with tqdm bars and ETA.
    """
    def __init__(
        self,
        total_epochs: int,
        steps_per_epoch: int,
        log_interval: int = 100,
        val_interval: int = 2000,
    ):
        self.total_epochs = total_epochs
        self.steps_per_epoch = steps_per_epoch
        self.log_interval = log_interval
        self.val_interval = val_interval
        
        # Progress bars
        self.epoch_bar = None
        self.step_bar = None
        
        # Timing
        self.epoch_start_time = None
        self.training_start_time = time.time()
        
        # Metrics
        self.current_epoch = 0
        self.global_step = 0
    
    def start_epoch(self, epoch: int):
        """Start a new epoch"""
        self.current_epoch = epoch
        self.epoch_start_time = time.time()
        
        # Create epoch-level progress bar
        if self.epoch_bar is not None:
            self.epoch_bar.close()
        
        self.epoch_bar = tqdm(
            total=self.steps_per_epoch,
            desc=f"Epoch {epoch}/{self.total_epochs}",
            position=0,
            leave=True,
            bar_format="{desc}: {percentage:3.0f}%|{bar}| {n}/{total} [{elapsed}<{remaining}, {rate_fmt}]"
        )
    
    def update_step(
        self,
        metrics: Dict[str, float],
        global_step: int,
    ):
        """
        Update progress for a single step.
        
        Args:
            metrics: Dict of metrics to display (loss, lr, etc.)
            global_step: Global training step
        """
        self.global_step = global_step
        
        # Format metrics for display
        metric_str = {}
        for key, value in metrics.items():
            if 'loss' in key.lower():
                metric_str[key] = f"{value:.4f}"
            elif 'lr' in key.lower():
                metric_str[key] = f"{value:.2e}"
            elif 'scale' in key.lower():
                metric_str[key] = f"{value:.2f}"
            else:
                metric_str[key] = f"{value:.4f}"
        
        # Add global step
        metric_str['step'] = f"{global_step}"
        
        # Update epoch bar
        if self.epoch_bar is not None:
            self.epoch_bar.set_postfix(metric_str)
            self.epoch_bar.update(1)
    
    def end_epoch(self):
        """End current epoch"""
        if self.epoch_bar is not None:
            self.epoch_bar.close()
            self.epoch_bar = None
        
        # Print epoch summary
        epoch_time = time.time() - self.epoch_start_time
        total_time = time.time() - self.training_start_time
        
        print(f"\n{'='*60}")
        print(f"Epoch {self.current_epoch} complete!")
        print(f"  Epoch time: {self.format_time(epoch_time)}")
        print(f"  Total training time: {self.format_time(total_time)}")
        print(f"  Global step: {self.global_step}")
        print(f"{'='*60}\n")
    
    def close(self):
        """Close all progress bars"""
        if self.epoch_bar is not None:
            self.epoch_bar.close()
        
        total_time = time.time() - self.training_start_time
        print(f"\n{'='*60}")
        print(f"Training complete!")
        print(f"  Total time: {self.format_time(total_time)}")
        print(f"  Total steps: {self.global_step}")
        print(f"  Average steps/sec: {self.global_step / total_time:.2f}")
        print(f"{'='*60}\n")
    
    @staticmethod
    def format_time(seconds: float) -> str:
        """Format seconds into human-readable string"""
        if seconds < 60:
            return f"{seconds:.1f}s"
        elif seconds < 3600:
            minutes = int(seconds // 60)
            secs = int(seconds % 60)
            return f"{minutes}m {secs}s"
        else:
            hours = int(seconds // 3600)
            minutes = int((seconds % 3600) // 60)
            return f"{hours}h {minutes}m"
    
    def get_eta(self, current_step: int, total_steps: int) -> str:
        """Calculate ETA for remaining steps"""
        if current_step == 0:
            return "calculating..."
        
        elapsed = time.time() - self.training_start_time
        steps_per_sec = current_step / elapsed
        remaining_steps = total_steps - current_step
        eta_seconds = remaining_steps / steps_per_sec
        
        return self.format_time(eta_seconds)


def format_metrics_for_wandb(metrics: Dict[str, float], prefix: str = "") -> Dict[str, float]:
    """
    Format metrics for W&B logging.
    
    Args:
        metrics: Raw metrics dict
        prefix: Prefix to add to keys (e.g., "train/", "val/")
    
    Returns:
        formatted_metrics: Formatted for W&B
    """
    formatted = {}
    for key, value in metrics.items():
        if isinstance(value, (int, float)):
            formatted[f"{prefix}{key}"] = value
    return formatted


def print_training_header(config: Dict):
    """Print formatted training configuration"""
    print("\n" + "="*80)
    print("FROZEN VLM-IP2P TRAINING".center(80))
    print("="*80)
    print("\nConfiguration:")
    print("-" * 80)
    
    # Group configs
    groups = {
        "Data": ["data_path", "image_folder", "batch_size", "num_workers"],
        "Model": ["resolution", "num_vlm_tokens", "resampler_depth"],
        "Training": ["num_epochs", "lr_perceiver", "lr_adapter", "weight_decay"],
        "CFG": ["cfg_dropout", "image_guidance_scale", "text_guidance_scale", "vlm_guidance_scale"],
        "Validation": ["val_interval", "num_val_samples", "val_scheduler", "num_inference_steps"],
        "Output": ["output_dir", "save_interval", "log_interval"],
    }
    
    for group_name, keys in groups.items():
        print(f"\n{group_name}:")
        for key in keys:
            if key in config:
                value = config[key]
                print(f"  {key:30s}: {value}")
    
    print("\n" + "="*80 + "\n")


if __name__ == "__main__":
    # Test progress tracker
    print("Testing progress tracker...")
    
    tracker = TrainingProgressTracker(
        total_epochs=3,
        steps_per_epoch=100,
        log_interval=10,
    )
    
    # Simulate training
    import random
    
    for epoch in range(1, 4):
        tracker.start_epoch(epoch)
        
        for step in range(100):
            global_step = (epoch - 1) * 100 + step
            
            # Simulate metrics
            metrics = {
                'loss': random.uniform(0.1, 0.5),
                'lr': 1e-4 * (0.99 ** global_step),
                'ema_decay': 0.9999,
            }
            
            tracker.update_step(metrics, global_step)
            time.sleep(0.01)  # Simulate training time
        
        tracker.end_epoch()
    
    tracker.close()
    
    print("\n✓ Progress tracker test complete!")