Spaces:
Running on Zero
Running on Zero
| import os, sys, re | |
| import torch | |
| import torch.nn as nn | |
| import logging | |
| logger = logging.getLogger(__name__) | |
| _rank_env = os.environ.get("RANK") or os.environ.get("LOCAL_RANK") or os.environ.get("ACCELERATE_PROCESS_INDEX") or "0" | |
| _rank = int(str(_rank_env)) | |
| _level = logging.INFO if _rank == 0 else logging.WARNING | |
| logging.basicConfig( | |
| level=_level, | |
| format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", | |
| datefmt="%Y-%m-%d %H:%M:%S", | |
| force=True, | |
| ) | |
| logger.setLevel(_level) | |
| current_file_abs = os.path.abspath(__file__) | |
| project_root = os.path.dirname(os.path.dirname(os.path.dirname(current_file_abs))) | |
| if project_root not in sys.path: | |
| sys.path.insert(0, project_root) | |
| from src.model_training.transformers_compat import patch_transformers_hybrid_cache | |
| patch_transformers_hybrid_cache() | |
| from diffsynth.trainers.utils import VideoDataset, CamVideoDataset, wan_parser | |
| import diffsynth.trainers.utils as utils_module | |
| utils_file = utils_module.__file__ | |
| if 'site-packages' in utils_file: | |
| logger.warning(f"Using INSTALLED diffsynth package from: {utils_file}") | |
| else: | |
| logger.info(f"[VERIFIED] Using LOCAL diffsynth code from: {utils_file}") | |
| import random | |
| import numpy as np | |
| os.environ["TOKENIZERS_PARALLELISM"] = "false" | |
| from safetensors.torch import load_file as safe_load_file | |
| from src.model_training.fov_retrieval import setup_fov_retriever_for_training | |
| from src.model_training.training_modules import DiTBlock_w_Action, WanTrainingModule | |
| def set_seed(seed=42): | |
| """Set random seeds for reproducible training.""" | |
| random.seed(seed) | |
| np.random.seed(seed) | |
| torch.manual_seed(seed) | |
| torch.cuda.manual_seed(seed) | |
| torch.cuda.manual_seed_all(seed) | |
| torch.backends.cudnn.deterministic = True | |
| torch.backends.cudnn.benchmark = False | |
| os.environ['PYTHONHASHSEED'] = str(seed) | |
| os.environ['CUBLAS_WORKSPACE_CONFIG'] = ':4096:8' | |
| logger.info(f"Random seed set to {seed}") | |
| def _log_dit_freeze_summary(dit: torch.nn.Module) -> None: | |
| by_module: dict[str, tuple[int, bool]] = {} | |
| for name, p in dit.named_parameters(): | |
| numel = p.numel() | |
| trainable = p.requires_grad | |
| parts = name.split(".") | |
| prefix = ".".join(parts[:-1]) if len(parts) > 1 else name | |
| if prefix not in by_module: | |
| by_module[prefix] = (0, False) | |
| prev_numel, prev_trainable = by_module[prefix] | |
| by_module[prefix] = (prev_numel + numel, prev_trainable or trainable) | |
| trainable_list = [(k, v[0]) for k, v in by_module.items() if v[1]] | |
| frozen_list = [(k, v[0]) for k, v in by_module.items() if not v[1]] | |
| trainable_list.sort(key=lambda x: x[0]) | |
| frozen_list.sort(key=lambda x: x[0]) | |
| total_trainable = sum(n for _, n in trainable_list) | |
| total_frozen = sum(n for _, n in frozen_list) | |
| examples = ", ".join(name for name, _ in trainable_list[:8]) | |
| logger.info( | |
| f"[DiT freeze] trainable={total_trainable:,} ({len(trainable_list)} groups), " | |
| f"frozen={total_frozen:,} ({len(frozen_list)} groups), examples=[{examples}]" | |
| ) | |
| set_seed(42) | |
| from src.model_training.training_modules.model_logger import ModelLogger | |
| from src.model_training.training_modules.training_loop import launch_training_task | |
| if __name__ == "__main__": | |
| parser = wan_parser() | |
| def _add_arg_if_missing(*args, **kwargs): | |
| if args and args[0] in parser._option_string_actions: | |
| return | |
| parser.add_argument(*args, **kwargs) | |
| for name, kwargs in [ | |
| ("--tokenizer_path", dict(type=str, default=None, help="Local tokenizer path.")), | |
| ("--wandb_run_name", dict(type=str, default=None)), | |
| ("--ckpt_interval", dict(type=int, default=None)), | |
| ("--trainable_dit_modules", dict(type=str, default=None, help="Comma-separated DiT modules to unfreeze.")), | |
| ("--num_workers", dict(type=int, default=0, help="DataLoader workers.")), | |
| ("--max_train_steps", dict(type=int, default=0, help="Stop after N optimizer steps.")), | |
| ("--progress_total_steps", dict(type=int, default=0, help="tqdm total steps override.")), | |
| ("--resume_from_checkpoint", dict(type=str, default=None)), | |
| ("--context_memory_frames", dict(type=int, default=8)), | |
| ("--training_mode", dict(type=str, default="predict", choices=["predict", "context", "condition"])), | |
| ("--context_drop_prob", dict(type=float, default=0.0)), | |
| ("--retrieval_method", dict(type=str, default="fov", choices=["fov", "latent_sim"])), | |
| ("--latent_retrieval_dir", dict(type=str, default=None)), | |
| ("--fov_top_k", dict(type=int, default=4)), | |
| ("--context_attention_weight", dict(type=float, default=1.0)), | |
| ("--context_temporal_decay", dict(type=float, default=1.0)), | |
| ("--spike_threshold", dict(type=float, default=5.0)), | |
| ("--spatial_memory_tokens", dict(type=int, default=64)), | |
| ("--spatial_memory_grid", dict(type=int, default=8)), | |
| ("--spatial_memory_inject_mode", dict(type=str, default="concat_text", choices=["concat_text", "none", "cross_attn_readout"])), | |
| ("--framepack_ratio", dict(type=int, default=2)), | |
| ("--framepack_length_strategy", dict(type=str, default="distance_merge", choices=["distance_merge", "mean", "uniform", "recent_weighted", "weighted_recent", "packed_multiscale"])), | |
| ("--framepack_recent_keep_ratio", dict(type=float, default=0.5)), | |
| ("--framepack_multiscale_w2", dict(type=float, default=0.25)), | |
| ("--framepack_multiscale_w4", dict(type=float, default=0.15)), | |
| ("--context_source", dict(type=str, default="fov", choices=["fov", "replay", "prev_chunk_tail"])), | |
| ("--ssm_num_blocks_hint", dict(type=int, default=21)), | |
| ("--ssm_every_n_blocks", dict(type=int, default=4)), | |
| ("--videossm_kernel_size", dict(type=int, default=3)), | |
| ("--videossm_expand", dict(type=int, default=2)), | |
| ("--videossm_every_n_blocks", dict(type=int, default=4)), | |
| ("--sampling_interval_steps", dict(type=int, default=0)), | |
| ("--sampling_negative_prompt", dict(type=str, default="oversaturated colors, overexposed, static, blurry details")), | |
| ("--sampling_height", dict(type=int, default=352)), | |
| ("--sampling_width", dict(type=int, default=640)), | |
| ("--sampling_num_frames", dict(type=int, default=81)), | |
| ("--sampling_num_inference_steps", dict(type=int, default=50)), | |
| ("--sampling_action_path", dict(type=str, default=None)), | |
| ("--sampling_two_chunk_action_path", dict(type=str, default=None)), | |
| ("--sampling_eval_dataset_base", dict(type=str, default=None)), | |
| ("--sampling_eval_metadata_path", dict(type=str, default=None)), | |
| ("--samples_per_epoch", dict(type=int, default=0)), | |
| ("--camera_encoder_scale", dict(type=float, default=1.0)), | |
| ("--camera_inject_mode", dict(type=str, default="post", choices=["post", "pre_norm", "pre_qkv", "pre_qkv_post", "pre_modulate", "pre_qkv_gated"])), | |
| ]: | |
| _add_arg_if_missing(name, **kwargs) | |
| for name in [ | |
| "--save_full_model", "--add_action_attn", "--action_use_temporal_attention", | |
| "--action_inject_after_spatial_attn", "--use_camera_encoder", "--camera_encoder_shallow", | |
| "--camera_encoder_separate_t_r", "--camera_encoder_explicit_yaw", "--yaw_flip_aug", | |
| "--camera_encoder_sincos_yaw", "--camera_encoder_r_mlp_no_layernorm", | |
| "--add_camera_outside_gate", "--no_camera_encoder_zero_init", | |
| "--camera_encoder_full_zero_init", "--enable_context_memory", "--context_per_frame_vae", | |
| "--cfg_target_only", "--enable_fov_retrieval", "--use_rt_relative", | |
| "--strict_overlap_context", "--use_anchor_frame", "--use_spatial_memory", | |
| "--use_spatial_memory_legacy", "--use_framepack_memory", "--use_framepack_length_compress", | |
| "--use_block_wise_ssm", "--use_videossm_hybrid", "--sampling_two_chunk_memory", | |
| ]: | |
| _add_arg_if_missing(name, action="store_true") | |
| for name, kwargs in [ | |
| ("--per_device_train_batch_size", dict(type=int, default=None)), | |
| ("--timestep_shift", dict(type=float, default=1.0)), | |
| ("--action_base_path", dict(type=str, default=None)), | |
| ("--ckpt_path", dict(type=str, default=None)), | |
| ("--cam_position_scale", dict(type=float, default=0.01)), | |
| ("--resume_from", dict(type=str, default=None)), | |
| ("--verify_ckpt_step", dict(type=int, default=0)), | |
| ("--verify_high_noise_first_steps", dict(type=int, default=0)), | |
| ("--moc_temperature", dict(type=float, default=1.0)), | |
| ("--moc_top_k", dict(type=int, default=0)), | |
| ("--prev_chunk_frames", dict(type=int, default=81)), | |
| ("--implicit_type", dict(type=str, default="summary")), | |
| ("--context_compressor_ratio", dict(type=int, default=2)), | |
| ("--episodic_buffer_size", dict(type=int, default=0)), | |
| ("--episodic_replay_interval", dict(type=int, default=0)), | |
| ("--episodic_replay_weight", dict(type=float, default=0.0)), | |
| ]: | |
| _add_arg_if_missing(name, **kwargs) | |
| for name in [ | |
| "--enable_video_sampling", "--sampling_atomic_left_right", "--sampling_four_prompts", | |
| "--sampling_two_prompts", "--train_action_module", "--train_cam_pose", | |
| "--action_module_only", "--use_moc", "--unified_implicit", "--use_implicit_memory", | |
| "--use_memory_v2v_compressor", "--use_slow_fast_memory", "--use_entity_memory", | |
| "--use_episodic_memory", | |
| ]: | |
| _add_arg_if_missing(name, action="store_true") | |
| args = parser.parse_args() | |
| def _arg(name, default=None): | |
| return getattr(args, name, default) | |
| def _normalize_and_validate_args(): | |
| # Backward-compat mappings | |
| if _arg("per_device_train_batch_size", None) is None: | |
| args.per_device_train_batch_size = int(_arg("batch_size", 1)) | |
| if _arg("sampling_atomic_left_right", False) and not _arg("sampling_two_chunk_memory", False): | |
| # Legacy monitor intent maps to current two-chunk monitor. | |
| args.sampling_two_chunk_memory = True | |
| if _arg("enable_video_sampling", False) and int(_arg("sampling_interval_steps", 0)) <= 0: | |
| args.sampling_interval_steps = 1000 | |
| # Keep paper-style block-wise SSM and legacy VideoSSM hybrid explicitly separated. | |
| if _arg("use_block_wise_ssm", False) and _arg("use_videossm_hybrid", False): | |
| raise ValueError( | |
| "--use_block_wise_ssm and --use_videossm_hybrid are mutually exclusive; " | |
| "use block-wise SSM for paper-aligned runs or VideoSSM hybrid for legacy baselines." | |
| ) | |
| # Explicit retrieval strategy visibility: default fov, latent_sim degrades to fov when cache dir is absent. | |
| if _arg("retrieval_method", "fov") == "latent_sim": | |
| if not _arg("latent_retrieval_dir", None): | |
| logger.warning("retrieval_method=latent_sim but latent_retrieval_dir is empty; runtime will fallback to fov retrieval.") | |
| else: | |
| logger.info(f"retrieval_method=latent_sim latent_retrieval_dir={args.latent_retrieval_dir}") | |
| else: | |
| logger.info("retrieval_method=fov") | |
| # 2-chunk sampling defaults: keep left/right_45 semantics compatible with existing shell wrappers. | |
| if _arg("sampling_two_chunk_action_path", None) in (None, ""): | |
| args.sampling_two_chunk_action_path = _arg("sampling_action_path", None) | |
| _normalize_and_validate_args() | |
| resume_step_count = 0 | |
| if args.resume_from_checkpoint is not None: | |
| if (_arg('trainable_dit_modules', None) or "").strip() or _arg('resume_weights_only', False): | |
| logger.info("resume_from_checkpoint used for weights only (trainable_dit_modules set or resume_weights_only), step count starts from 0, no skip data") | |
| resume_step_count = 0 | |
| else: | |
| checkpoint_filename = os.path.basename(args.resume_from_checkpoint) | |
| step_match = re.search(r'Step-(\d+)', checkpoint_filename) | |
| epoch_match = re.search(r'epoch-(\d+)', checkpoint_filename) | |
| if step_match: | |
| resume_step_count = int(step_match.group(1)) | |
| logger.info(f"Resuming from step {resume_step_count} (extracted from checkpoint filename)") | |
| elif epoch_match: | |
| logger.info(f"Resuming from epoch checkpoint (epoch-{epoch_match.group(1)}), step count will start from 0") | |
| resume_step_count = 0 | |
| else: | |
| logger.warning("Could not extract step count from checkpoint filename, starting from step 0") | |
| set_seed(42) | |
| args.enable_icl = False | |
| args.icl_num_examples = 2 | |
| args.icl_context_frames = 8 | |
| if _arg('train_cam_pose', False): | |
| dataset = CamVideoDataset(args=args) | |
| else: | |
| dataset = VideoDataset(args=args, action_base_path=args.action_base_path) | |
| def _log_dataset_validation(ds): | |
| ds_size = len(ds) | |
| ds_repeat = _arg('dataset_repeat', 1) | |
| logger.info( | |
| f"[Dataset] size={ds_size}, repeat={ds_repeat}, " | |
| f"epochs={args.num_epochs}, total_samples={ds_size * ds_repeat * args.num_epochs}" | |
| ) | |
| _log_dataset_validation(dataset) | |
| model = WanTrainingModule( | |
| model_paths=args.model_paths, | |
| model_id_with_origin_paths=args.model_id_with_origin_paths, | |
| tokenizer_path=_arg('tokenizer_path', None), | |
| trainable_models=_arg('trainable_models', None), | |
| lora_base_model=args.lora_base_model, | |
| lora_target_modules=args.lora_target_modules, | |
| lora_rank=args.lora_rank, | |
| use_gradient_checkpointing_offload=args.use_gradient_checkpointing_offload, | |
| extra_inputs=args.extra_inputs, | |
| resume_from_checkpoint=args.resume_from_checkpoint, | |
| dataset_base_path=_arg('dataset_base_path', None), | |
| enable_context_memory=_arg('enable_context_memory', False), | |
| context_drop_prob=_arg('context_drop_prob', 0.0), | |
| context_drop_seed=42, | |
| omit_context_actions=_arg('omit_context_actions', False) or (_arg('context_memory_frames', 8) == 1), # ctx=1: no context action injection | |
| context_noise_prob=_arg('context_noise_prob', 0.0), | |
| context_noise_std=_arg('context_noise_std', 0.02), | |
| context_fixed_noise_std=_arg('context_fixed_noise_std', None), | |
| context_memory_frames=_arg('context_memory_frames', 8), | |
| context_per_frame_vae=_arg('context_per_frame_vae', False), | |
| training_mode=_arg('training_mode', 'predict'), | |
| teacher_forcing_prob=_arg('teacher_forcing_prob', 0.0), | |
| yaw_flip_aug=_arg('yaw_flip_aug', False), | |
| context_source=_arg('context_source', 'fov'), | |
| use_framepack_memory=_arg('use_framepack_memory', False), | |
| context_temporal_decay=_arg('context_temporal_decay', 1.0), | |
| context_attention_weight=_arg('context_attention_weight', 1.0), | |
| use_framepack_length_compress=_arg('use_framepack_length_compress', False), | |
| framepack_ratio=_arg('framepack_ratio', 2), | |
| framepack_length_strategy=_arg('framepack_length_strategy', 'distance_merge'), | |
| framepack_recent_keep_ratio=_arg('framepack_recent_keep_ratio', 0.5), | |
| framepack_multiscale_w2=_arg('framepack_multiscale_w2', 0.25), | |
| framepack_multiscale_w4=_arg('framepack_multiscale_w4', 0.15), | |
| use_spatial_memory=_arg('use_spatial_memory', False), | |
| use_spatial_memory_legacy=_arg('use_spatial_memory_legacy', False), | |
| spatial_memory_tokens=_arg('spatial_memory_tokens', 64), | |
| spatial_memory_grid=_arg('spatial_memory_grid', 8), | |
| spatial_memory_inject_mode=_arg('spatial_memory_inject_mode', 'concat_text'), | |
| timestep_shift=float(_arg('timestep_shift', 1.0)), | |
| ) | |
| # ── VWM-style: Replace DiT blocks with DiTBlock_w_Action ── | |
| _use_cam_pose = bool(_arg('train_cam_pose', False)) | |
| if _arg('train_action_module', False) or _use_cam_pose: | |
| dit = model.pipe.dit | |
| old_blocks = dit.blocks | |
| has_image_input = dit.has_image_input | |
| dim = dit.dim | |
| num_heads = dit.num_heads | |
| ffn_dim = dit.ffn_dim | |
| eps = 1e-6 | |
| block_dtype = next(old_blocks[0].parameters()).dtype | |
| use_block_wise_ssm = bool(_arg('use_block_wise_ssm', False)) | |
| use_videossm_hybrid = bool(_arg('use_videossm_hybrid', False)) | |
| ssm_every_n = max(int(_arg('ssm_every_n_blocks', 4)), 1) | |
| videossm_every_n = max(int(_arg('videossm_every_n_blocks', 4)), 1) | |
| new_blocks = nn.ModuleList() | |
| for block_id, old_block in enumerate(old_blocks): | |
| attach_block_ssm = use_block_wise_ssm and (block_id % ssm_every_n == 0) | |
| attach_videossm = use_videossm_hybrid and (block_id % videossm_every_n == 0) | |
| new_block = DiTBlock_w_Action( | |
| has_image_input=has_image_input, | |
| dim=dim, num_heads=num_heads, ffn_dim=ffn_dim, eps=eps, | |
| add_action_attn=_arg('add_action_attn', False), | |
| action_use_temporal_attention=_arg('action_use_temporal_attention', False), | |
| use_cam_pose=_use_cam_pose, | |
| use_block_wise_ssm=attach_block_ssm, | |
| use_videossm_hybrid=attach_videossm, | |
| videossm_kernel_size=int(_arg('videossm_kernel_size', 3)), | |
| videossm_expand=int(_arg('videossm_expand', 2)), | |
| ) | |
| new_block = new_block.to(dtype=block_dtype, device=next(old_block.parameters()).device) | |
| for attr in ("self_attn", "cross_attn", "norm1", "norm2", "norm3", "ffn"): | |
| getattr(new_block, attr).load_state_dict(getattr(old_block, attr).state_dict()) | |
| with torch.no_grad(): | |
| new_block.modulation.copy_(old_block.modulation.to(dtype=block_dtype)) | |
| new_blocks.append(new_block) | |
| dit.blocks = new_blocks | |
| _mlp_type = "MLP_CamPose" if _use_cam_pose else "MLP_Action" | |
| logger.info(f"[VWM-style] Replaced {len(new_blocks)} DiT blocks with DiTBlock_w_Action ({_mlp_type}, zero-init)") | |
| if use_block_wise_ssm: | |
| logger.info(f"[Block-wise SSM] attached to every {ssm_every_n} DiT block(s)") | |
| if use_videossm_hybrid: | |
| logger.info(f"[VideoSSM hybrid] attached to every {videossm_every_n} DiT block(s)") | |
| device = next(dit.parameters()).device | |
| _ckpt_path = _arg('ckpt_path', None) or _arg('resume_from_checkpoint', None) | |
| if _ckpt_path is not None: | |
| ckpt = safe_load_file(_ckpt_path) | |
| missing, unexpected = dit.load_state_dict(ckpt, strict=False) | |
| dit.to(device=device) | |
| logger.info(f"[VWM-style] Loaded ckpt: {len(ckpt)} keys, missing={len(missing)}, unexpected={len(unexpected)}") | |
| if _arg('action_module_only', False): | |
| if _arg('add_action_attn', False): | |
| for block in dit.blocks: | |
| for name, param in block.named_parameters(): | |
| if ("action_mlp" in name) or ("self_attn_with_action" in name) or ("block_wise_ssm" in name) or ("videossm_hybrid" in name): | |
| param.requires_grad = True | |
| else: | |
| param.requires_grad = False | |
| else: | |
| for block in dit.blocks: | |
| for name, param in block.named_parameters(): | |
| if "action_mlp" in name or "self_attn" in name or "block_wise_ssm" in name or "videossm_hybrid" in name: | |
| param.requires_grad = True | |
| else: | |
| param.requires_grad = False | |
| else: | |
| for block in dit.blocks: | |
| for name, param in block.named_parameters(): | |
| if "action_mlp" in name or "self_attn_with_action" in name or "block_wise_ssm" in name or "videossm_hybrid" in name: | |
| param.requires_grad = True | |
| else: | |
| param.requires_grad = False | |
| _log_dit_freeze_summary(dit) | |
| _resume_from = _arg('resume_from', None) | |
| if _resume_from: | |
| logger.info(f"Loading full resume checkpoint: {_resume_from}") | |
| ckpt = safe_load_file(_resume_from) | |
| model.pipe.dit.load_state_dict(ckpt, strict=False) | |
| logger.info(f"Checkpoint loaded, resuming from step {resume_step_count}") | |
| model_logger = ModelLogger( | |
| args.output_path, | |
| remove_prefix_in_ckpt=args.remove_prefix_in_ckpt, | |
| wandb_run_name=args.wandb_run_name, | |
| ckpt_interval=args.ckpt_interval, | |
| resume_step_count=resume_step_count, | |
| save_full_model=_arg('save_full_model', False), | |
| context_drop_prob=float(_arg("context_drop_prob", 0.0)), | |
| enable_video_sampling=_arg("enable_video_sampling", False), | |
| sampling_interval_steps=int(_arg("sampling_interval_steps", 0)), | |
| sampling_two_chunk_memory=_arg("sampling_two_chunk_memory", False), | |
| sampling_action_path=_arg("sampling_action_path", None), | |
| sampling_two_chunk_action_path=_arg("sampling_two_chunk_action_path", None), | |
| sampling_negative_prompt=_arg("sampling_negative_prompt", ""), | |
| sampling_height=int(_arg("sampling_height", 352)), | |
| sampling_width=int(_arg("sampling_width", 640)), | |
| sampling_num_frames=int(_arg("sampling_num_frames", 81)), | |
| sampling_num_inference_steps=int(_arg("sampling_num_inference_steps", 50)), | |
| context_memory_frames=int(_arg("context_memory_frames", 1)), | |
| context_source=_arg("context_source", "replay"), | |
| context_per_frame_vae=_arg("context_per_frame_vae", False), | |
| ) | |
| optimizer = torch.optim.AdamW(model.trainable_modules(), lr=args.learning_rate) | |
| scheduler = torch.optim.lr_scheduler.ConstantLR(optimizer) | |
| # Setup FOV retriever for context-based memory training (also for ModelLogger sampling) | |
| enable_fov_retrieval = _arg('enable_fov_retrieval', False) | |
| fov_retriever = None | |
| dataset_base_path = _arg('dataset_base_path', None) | |
| if enable_fov_retrieval: | |
| fov_retriever = setup_fov_retriever_for_training( | |
| dataset_base_path=dataset_base_path, | |
| enable_fov_retrieval=True | |
| ) | |
| launch_training_task( | |
| dataset, model, model_logger, optimizer, scheduler, | |
| num_epochs=args.num_epochs, | |
| gradient_accumulation_steps=args.gradient_accumulation_steps, | |
| per_device_train_batch_size=int(_arg("per_device_train_batch_size", 1)), | |
| spike_threshold=_arg('spike_threshold', 5.0), | |
| resume_step_count=resume_step_count, | |
| enable_fov_retrieval=enable_fov_retrieval, | |
| retrieval_method=_arg('retrieval_method', 'fov'), | |
| latent_retrieval_dir=_arg('latent_retrieval_dir', None), | |
| dataset_base_path=_arg('dataset_base_path', None), | |
| fov_retriever=fov_retriever, | |
| context_memory_frames=_arg('context_memory_frames', 8), | |
| prev_chunk_frames=int(_arg('prev_chunk_frames', 81)), | |
| fov_top_k=_arg('fov_top_k', 4), # Number of overlap frames (4), GT frame 0 added automatically | |
| use_rt_relative=_arg('use_rt_relative', False), # Experiment 1_4_2: RT relative conversion | |
| strict_overlap_context=_arg('strict_overlap_context', False), | |
| dataset_repeat=_arg('dataset_repeat', 1), # Pass dataset_repeat for step calculation | |
| use_camera_encoder=_arg('use_camera_encoder', False), # exp1_4_3: DDP find_unused_parameters | |
| num_workers=_arg('num_workers', 0), | |
| context_source=_arg('context_source', 'fov'), | |
| max_train_steps=int(_arg('max_train_steps', 0)), | |
| progress_total_steps=int(_arg('progress_total_steps', 0)), | |
| ) | |
| model_logger.finish() |