Source code for sequifier.io.sequifier_dataset_from_folder_pt_lazy

import os
from collections import Counter
from collections.abc import Iterator
from typing import Any

from loguru import logger
from torch.utils.data import get_worker_info

from sequifier.config.depth_layout import DepthLayoutRegistryModel
from sequifier.helpers import validate_stored_window_width
from sequifier.io.batch import SequifierBatch
from sequifier.io.folder_dataset import LazyFolderChunk, LazyFolderDataset
from sequifier.io.pt_payload import load_pt_payload
from sequifier.io.sample_order import curriculum_sample_positions
from sequifier.io.window_sampling import (
    target_valid_from_offsets,
    validate_split_bounds_available,
)
from sequifier.typechecking import beartype


[docs]class SequifierDatasetFromFolderPtLazy(LazyFolderDataset): """Streams PT chunks into rank/worker-aligned batches.""" chunk_format = "PT" @beartype def __init__(self, data_path: str, config: Any, shuffle: bool = True): super().__init__(data_path, config, shuffle, "write_format: pt") metadata = self.metadata self.payload_n_classes = metadata.get("n_classes") or config.n_classes self.depth_layouts = DepthLayoutRegistryModel.model_validate( metadata.get("depth_layouts", {}) ) selected_layouts: DepthLayoutRegistryModel | None = getattr( config, "depth_layouts", None ) if selected_layouts is None: selected_layouts = DepthLayoutRegistryModel() if self.depth_layouts.compatibility_signature( config.input_columns ) != selected_layouts.compatibility_signature(config.input_columns): raise ValueError( "PT folder depth layouts are incompatible with the selected interface" ) self._initialize_window_layout() self.batch_files_info = [] raw_file_infos = list(metadata["batch_files"]) if self.file_order == "name": raw_file_infos.sort(key=lambda item: item["path"]) for raw_file_info in raw_file_infos: file_info = dict(raw_file_info) file_info["stored_samples"] = int(raw_file_info["samples"]) histogram = raw_file_info.get("target_valid_from_histogram") if histogram is None and not self.sampling_plan.legacy_single_window: file_path = os.path.join(self.data_dir, file_info["path"]) payload = load_pt_payload( file_path, layouts=self.depth_layouts, n_classes=self.payload_n_classes, ) valid_from = target_valid_from_offsets( payload.left_pad_lengths, payload.start_item_positions, payload.split_start_item_positions, ) histogram = { str(value): count for value, count in Counter(valid_from.tolist()).items() } if self.sampling_plan.legacy_single_window: file_info["samples"] = file_info["stored_samples"] else: assert histogram is not None file_info["samples"] = ( self.sampling_plan.sample_count_from_target_valid_from_histogram( histogram ) ) if file_info["samples"] > 0: self.batch_files_info.append(file_info) self.total_samples = sum(info["samples"] for info in self.batch_files_info) if self.total_samples == 0: raise ValueError("No usable model windows were found in the dataset.") self.target_samples = self._get_target_samples() self.total_batches = self._calculate_total_batches(self.target_samples) logger.info( f"Lazy Dataset loaded into RAM with {self.target_samples} samples and {self.total_batches} batches." ) @beartype def __iter__(self) -> Iterator[SequifierBatch]: yield from self._iter_batches(get_worker_info()) def _read_chunk(self, file_path: str) -> LazyFolderChunk: payload = load_pt_payload( file_path, layouts=self.depth_layouts, n_classes=self.payload_n_classes, ) validate_split_bounds_available( payload.start_item_positions, payload.split_start_item_positions, payload.split_end_item_positions, file_path, ) for tensor in payload.sequences.values(): validate_stored_window_width(tensor, self.folder_layout.window_length) sample_index = self.sampling_plan.build_index( payload.left_pad_lengths, target_valid_from_offsets( payload.left_pad_lengths, payload.start_item_positions, payload.split_start_item_positions, ), ) return LazyFolderChunk( sequences=payload.sequences, sample_index=sample_index, sample_positions=curriculum_sample_positions( self.config, payload.sample_positions, file_path, payload.curriculum_columns, ), depth_valid_masks={ name: payload.depth_valid_masks[name] for name in self.config.depth_layouts.root }, start_item_positions=payload.start_item_positions, split_start_item_positions=payload.split_start_item_positions, split_end_item_positions=payload.split_end_item_positions, )