clean up to baseline

This commit is contained in:
pikaliov
2026-04-29 14:45:31 +03:00
parent 6b928634f4
commit d42ef94821
6 changed files with 0 additions and 343 deletions

View File

@@ -1,62 +0,0 @@
from __future__ import annotations
import logging
from pathlib import Path
from typing import Any
import gin
from src.conf.hardware_conf import HardwareConfig
from src.conf.models_conf import ModelsConfig
from src.conf.pipeline_conf import PipelineConfig
from src.conf.tracking_conf import TrackingConfig
from src.conf.training_conf import TrainingConfig
logger = logging.getLogger(__name__)
def load_all_configs(path2cfg: str) -> dict[str, Any]:
"""Parse ALL .gin files in path2cfg and return all config objects.
This is the PRODUCTION entry point — main() calls this once. Individual
get_*_cfg() loaders exist only for unit tests / notebooks.
Args:
path2cfg: Path to config directory (WITH trailing slash).
Returns:
Dict with config objects keyed by name:
{
"pipeline": PipelineConfig,
"hardware": HardwareConfig,
"models": ModelsConfig,
"training": TrainingConfig,
"tracking": TrackingConfig,
}
Raises:
FileNotFoundError: If path2cfg contains no .gin files.
"""
cfg_dir = Path(path2cfg)
gin_files = sorted(cfg_dir.glob("*.gin"))
if not gin_files:
raise FileNotFoundError(f"No .gin files found in {cfg_dir}")
# MANDATORY: reset gin global state before parsing — without clear_config(),
# parameters from previous parses accumulate (gin holds global bindings).
gin.clear_config()
gin.parse_config_files_and_bindings(
config_files=[str(f) for f in gin_files],
bindings=[],
)
logger.info("Loaded %d gin files from %s", len(gin_files), cfg_dir)
# Instantiate AFTER all bindings are parsed.
return {
"pipeline": PipelineConfig(),
"hardware": HardwareConfig(),
"models": ModelsConfig(),
"training": TrainingConfig(),
"tracking": TrackingConfig(),
}

View File

@@ -1,43 +0,0 @@
from __future__ import annotations
import gin
@gin.configurable
class HardwareConfig:
"""GPU profile + memory/compute optimisation flags.
Everything that changes when you switch hardware (4090 → A100 → Jetson)
lives here. batch_size and grad_accum_steps are hardware-bound: they
determine VRAM footprint, not the training recipe.
"""
def __init__(
self,
device: str = "cuda",
batch_size: int = 8,
grad_accum_steps: int = 1,
num_workers: int = 4,
use_amp: bool = True,
gradient_checkpointing: bool = True,
reserve_gb: float = 2.0,
) -> None:
self.device = device
self.batch_size = batch_size
self.grad_accum_steps = grad_accum_steps
self.num_workers = num_workers
self.use_amp = use_amp
self.gradient_checkpointing = gradient_checkpointing
self.reserve_gb = reserve_gb
# Derived (RTX 4090 default; override per profile):
self.total_vram_gb = 24.0
self.available_vram_gb = self.total_vram_gb - self.reserve_gb
self.effective_batch_size = self.batch_size * self.grad_accum_steps
def get_hardware_cfg(path2cfg: str) -> HardwareConfig:
"""Load ONLY hardware config (TESTING ONLY — use load_all_configs in production)."""
gin.clear_config()
gin.parse_config_file(f"{path2cfg}hardware.gin")
return HardwareConfig()

View File

@@ -1,54 +0,0 @@
from __future__ import annotations
import gin
@gin.configurable
class ModelsConfig:
"""Model checkpoints + architecture switches.
Default checkpoint paths are relative to the project root (matching the
repository layout: nn_models/DINO_WEB/, nn_models/DINO_SAT/, etc.).
These are gitignored and must be downloaded separately — see README.
"""
def __init__(
self,
# Checkpoints — relative to project root, defaults match repo layout.
dino_web_path: str = "nn_models/DINO_WEB/dinov3-vitl16-pretrain-lvd1689m.pth",
dino_sat_path: str = "nn_models/DINO_SAT/model.safetensors",
lrsclip_path: str = "nn_models/LRSCLIP/DGTRS-CLIP-ViT-L-14.pt",
stripnet_path: str = "nn_models/STRIPNET/stripnet_s.pth",
# Backbone selection.
backbone: str = "dinov3",
shared_encoder: bool = True,
baseline_mode: bool = False,
# Fusion.
init_gate: float = 0.7,
# MONA (DINOv3).
mona_bottleneck: int = 64,
mona_last_n_blocks: int = 12,
# StripNet-specific.
stripnet_freeze: bool = True,
stripnet_mona_last_n_stages: int = 2,
) -> None:
self.dino_web_path = dino_web_path
self.dino_sat_path = dino_sat_path
self.lrsclip_path = lrsclip_path
self.stripnet_path = stripnet_path
self.backbone = backbone
self.shared_encoder = shared_encoder
self.baseline_mode = baseline_mode
self.init_gate = init_gate
self.mona_bottleneck = mona_bottleneck
self.mona_last_n_blocks = mona_last_n_blocks
self.stripnet_freeze = stripnet_freeze
self.stripnet_mona_last_n_stages = stripnet_mona_last_n_stages
def get_models_cfg(path2cfg: str) -> ModelsConfig:
"""Load ONLY models config (TESTING ONLY — use load_all_configs in production)."""
gin.clear_config()
gin.parse_config_file(f"{path2cfg}models.gin")
return ModelsConfig()

View File

@@ -1,57 +0,0 @@
from __future__ import annotations
import gin
@gin.configurable
class PipelineConfig:
"""Pipeline orchestration: data IO, training schedule, output, resume.
Defaults match the current `belka_refactor` HEAD: hardcoded servml paths
are preserved verbatim. To switch to a different machine, override in
pipeline.gin — never edit defaults here.
"""
def __init__(
self,
# Data paths (defaults match servml workstation).
train_json: str = "meta/train_80.json",
test_json: str = "meta/test_20.json",
rgb_root: str = "/home/servml/Документы/datasets/GTA-UAV-LR",
caption_root: str = "/home/servml/Документы/datasets/GTA-UAV-LR-captions",
filter_meta: str | None = None,
# Training schedule.
epochs: int = 10,
warmup_epochs: int = 2,
eval_every: int = 1,
# Reproducibility & output.
seed: int = 42,
output_dir: str = "out/gtauav/with_text",
resume_from: str | None = None,
) -> None:
self.train_json = train_json
self.test_json = test_json
self.rgb_root = rgb_root
self.caption_root = caption_root
self.filter_meta = filter_meta
self.epochs = epochs
self.warmup_epochs = warmup_epochs
self.eval_every = eval_every
self.seed = seed
self.output_dir = output_dir
self.resume_from = resume_from
def get_pipeline_cfg(path2cfg: str) -> PipelineConfig:
"""Load ONLY pipeline config (TESTING ONLY — use load_all_configs in production).
Args:
path2cfg: Path to config directory (with trailing slash).
Returns:
Instantiated PipelineConfig.
"""
gin.clear_config()
gin.parse_config_file(f"{path2cfg}pipeline.gin")
return PipelineConfig()

View File

@@ -1,48 +0,0 @@
from __future__ import annotations
import gin
@gin.configurable
class TrackingConfig:
"""Experiment tracking + diagnostics.
Independent axis: changing these flags does not affect training results,
only what is observed/recorded.
"""
def __init__(
self,
use_wandb: bool = False,
use_tb: bool = True,
wandb_project: str = "caption-test-gtauav",
wandb_run_name: str | None = None,
wandb_entity: str | None = None,
log_grad_norms: bool = True,
use_gradcam: bool = False,
gradcam_every: int = 5,
gradcam_samples: int = 8,
use_profiler: bool = False,
profiler_warmup: int = 3,
profiler_active: int = 5,
) -> None:
self.use_wandb = use_wandb
self.use_tb = use_tb
self.wandb_project = wandb_project
self.wandb_run_name = wandb_run_name
self.wandb_entity = wandb_entity
self.log_grad_norms = log_grad_norms
self.use_gradcam = use_gradcam
self.gradcam_every = gradcam_every
self.gradcam_samples = gradcam_samples
self.use_profiler = use_profiler
self.profiler_warmup = profiler_warmup
self.profiler_active = profiler_active
def get_tracking_cfg(path2cfg: str) -> TrackingConfig:
"""Load ONLY tracking config (TESTING ONLY — use load_all_configs in production)."""
gin.clear_config()
gin.parse_config_file(f"{path2cfg}tracking.gin")
return TrackingConfig()

View File

@@ -1,79 +0,0 @@
from __future__ import annotations
import gin
@gin.configurable
class TrainingConfig:
"""Training recipe: loss + optimizer + sampler.
These three move together when you tune learning. Changing tau usually
pairs with changing lr; switching sampler_type usually pairs with
re-tuning loss weights. Keeping them in one config matches the actual
workflow of running ablations.
"""
def __init__(
self,
# --- Loss ---
loss_type: str = "symmetric",
tau_init: float = 0.07,
tau_min: float = 0.01,
tau_max: float = 0.1,
learnable_temperature: bool = True,
label_smoothing: float = 0.1,
weight_q2g: float = 0.6,
weight_g2q: float = 0.4,
hard_mining_k: int = 0,
neg_bank_size: int = 0,
# --- Optimizer ---
learning_rate: float = 1e-4,
text_lr_factor: float = 0.1,
stripnet_backbone_lr_factor: float = 0.1,
weight_decay: float = 1e-4,
grad_clip: float = 1.0,
# --- Sampler ---
sampler_type: str = "mutex",
dss_warmup_epochs: int = 1,
dss_reembed_every: int = 1,
dss_knn_device: str = "cuda",
dss_use_lsh: bool = False,
dss_lsh_num_tables: int = 8,
dss_lsh_num_bits: int = 14,
dss_cache_dir: str | None = None,
) -> None:
# Loss.
self.loss_type = loss_type
self.tau_init = tau_init
self.tau_min = tau_min
self.tau_max = tau_max
self.learnable_temperature = learnable_temperature
self.label_smoothing = label_smoothing
self.weight_q2g = weight_q2g
self.weight_g2q = weight_g2q
self.hard_mining_k = hard_mining_k
self.neg_bank_size = neg_bank_size
# Optimizer.
self.learning_rate = learning_rate
self.text_lr_factor = text_lr_factor
self.stripnet_backbone_lr_factor = stripnet_backbone_lr_factor
self.weight_decay = weight_decay
self.grad_clip = grad_clip
# Sampler.
self.sampler_type = sampler_type
self.dss_warmup_epochs = dss_warmup_epochs
self.dss_reembed_every = dss_reembed_every
self.dss_knn_device = dss_knn_device
self.dss_use_lsh = dss_use_lsh
self.dss_lsh_num_tables = dss_lsh_num_tables
self.dss_lsh_num_bits = dss_lsh_num_bits
self.dss_cache_dir = dss_cache_dir
def get_training_cfg(path2cfg: str) -> TrainingConfig:
"""Load ONLY training config (TESTING ONLY — use load_all_configs in production)."""
gin.clear_config()
gin.parse_config_file(f"{path2cfg}training.gin")
return TrainingConfig()