Source code for nlsq.streaming.hybrid_config

"""Configuration for adaptive hybrid streaming optimizer.

This module provides configuration options for the four-phase hybrid optimizer
that combines parameter normalization, L-BFGS warmup, streaming Gauss-Newton, and
exact covariance computation.
"""

from dataclasses import dataclass
from typing import Literal

from nlsq.streaming.validators import (
    validate_cg_config,
    validate_defense_layer_config,
    validate_gauss_newton_config,
    validate_gradient_clip,
    validate_group_variance_config,
    validate_lbfgs_config,
    validate_loop_strategy,
    validate_lr_schedule_config,
    validate_multistart_config,
    validate_normalization_strategy,
    validate_residual_weighting_config,
    validate_streaming_config,
    validate_warmup_config,
)


[docs] @dataclass(slots=True) class HybridStreamingConfig: """Configuration for adaptive hybrid streaming optimizer. This configuration class controls all aspects of the four-phase hybrid optimizer: - Phase 0: Parameter normalization setup - Phase 1: L-BFGS warmup with adaptive switching - Phase 2: Streaming Gauss-Newton with exact J^T J accumulation - Phase 3: Denormalization and covariance transform Parameters ---------- normalize : bool, default=True Enable parameter normalization. When True, parameters are normalized to similar scales to improve gradient signal quality and convergence speed. normalization_strategy : str, default='auto' Strategy for parameter normalization. Options: - **'auto'**: Use bounds-based if bounds provided, else p0-based - **'bounds'**: Normalize to [0, 1] using parameter bounds - **'p0'**: Scale by initial parameter magnitudes - **'none'**: Identity transform (no normalization) warmup_iterations : int, default=200 Number of L-BFGS warmup iterations before checking switch criteria. With L-BFGS, typical values are 20-50 (5-10x fewer than Adam). More iterations allow better initial convergence before switching to Gauss-Newton. max_warmup_iterations : int, default=500 Maximum L-BFGS warmup iterations before forced switch to Phase 2. Safety limit to prevent indefinite warmup when loss plateaus slowly. warmup_learning_rate : float, default=0.001 Legacy warmup step size retained for backward compatibility. L-BFGS warmup uses ``lbfgs_initial_step_size`` and adaptive step sizes. loss_plateau_threshold : float, default=1e-4 Relative loss improvement threshold for plateau detection. Switch to Phase 2 if: abs(loss - prev_loss) / (abs(prev_loss) + eps) < threshold. Smaller values = stricter plateau detection = later switching. gradient_norm_threshold : float, default=1e-3 Gradient norm threshold for early Phase 2 switch. Switch to Phase 2 if: ||gradient|| < threshold. Indicates optimization is close to optimum and Gauss-Newton will be effective. active_switching_criteria : list, default=['plateau', 'gradient', 'max_iter'] List of active switching criteria for Phase 1 -> Phase 2 transition. Available criteria: - **'plateau'**: Loss plateau detection (loss_plateau_threshold) - **'gradient'**: Gradient norm below threshold (gradient_norm_threshold) - **'max_iter'**: Maximum iterations reached (max_warmup_iterations) Switch occurs when ANY active criterion is met. lbfgs_history_size : int, default=10 Number of previous gradients and updates to store for L-BFGS Hessian approximation. Standard default from SciPy, PyTorch, and Nocedal & Wright. Larger values give better Hessian approximation but use more memory. lbfgs_initial_step_size : float, default=0.1 Initial step size for L-BFGS during cold start (first m iterations while history buffer fills). Small value prevents overshooting when Hessian approximation is poor (identity matrix initially). lbfgs_line_search : str, default='wolfe' Line search method for L-BFGS step acceptance. Options: - **'wolfe'**: Standard Wolfe conditions (default) - **'strong_wolfe'**: Strong Wolfe conditions (stricter) - **'backtracking'**: Simple backtracking line search lbfgs_exploration_step_size : float, default=0.1 L-BFGS initial step size for exploration mode (high relative loss). Small value prevents first "Hessian=Identity" step from overshooting. lbfgs_refinement_step_size : float, default=1.0 L-BFGS initial step size for refinement mode (low relative loss). Larger value leverages L-BFGS's near-Newton convergence speed when close to optimum. gauss_newton_max_iterations : int, default=100 Maximum iterations for Phase 2 Gauss-Newton optimization. Typical values: 50-200. gauss_newton_tol : float, default=1e-8 Convergence tolerance for Phase 2 (gradient norm threshold). Optimization stops if: ||gradient|| < tol. trust_region_initial : float, default=1.0 Initial trust region radius for Gauss-Newton step control. Radius is adapted based on actual vs predicted reduction ratio. regularization_factor : float, default=1e-10 Regularization factor for rank-deficient J^T J matrices. Added to diagonal: J^T J + regularization_factor * I. cg_max_iterations : int, default=100 Maximum iterations for Conjugate Gradient solver in Phase 2. Used when parameter count exceeds cg_param_threshold. Higher values allow better convergence but more computation. cg_relative_tolerance : float, default=1e-4 Relative tolerance for CG solver convergence. Convergence check: ||r|| < cg_relative_tolerance * ||J^T r_0||. Implements Inexact Newton strategy for efficiency. cg_absolute_tolerance : float, default=1e-10 Absolute tolerance floor for CG solver convergence. Safety floor to prevent over-iteration on well-conditioned systems. cg_param_threshold : int, default=2000 Parameter count threshold for auto-selecting CG vs materialized solver. - **p < threshold**: Use materialized J^T J with SVD solve (faster for small p) - **p >= threshold**: Use CG with implicit matvec (O(p) memory vs O(p^2)) Threshold balances memory savings vs additional data passes for CG. enable_group_variance_regularization : bool, default=False Enable variance regularization for parameter groups. When enabled, adds a penalty term to the loss function that penalizes variance within specified parameter groups. This is essential for preventing per-group parameter absorption in multi-component fitting. The regularized loss becomes ``L = MSE + group_variance_lambda * sum(Var(group_i))`` where each group_i is a slice of parameters defined by group_variance_indices. group_variance_lambda : float, default=0.01 Regularization strength for group variance penalty. Larger values more strongly penalize variance within parameter groups. Use 0.001-0.01 for light regularization (allows moderate group variation), 0.1-1.0 for moderate regularization (constrains groups to be similar), or 10-1000 for strong regularization (forces groups to be nearly uniform). For multi-component fits with per-group parameters, use ``lambda ~ 0.1 * n_data / (n_groups * sigma^2)`` where sigma is the expected experimental variation (~0.05 for 5%). group_variance_indices : list of tuple, default=None List of (start, end) tuples defining parameter groups for variance regularization. Each tuple specifies a slice [start:end] of the parameter vector that should have low internal variance. Example for 23 independent groups: ``group_variance_indices = [(0, 23), (23, 46)]`` constrains contrast params [0:23] and offset params [23:46] to each have low variance, preventing them from absorbing group-dependent physical signals. If None when enable_group_variance_regularization=True, no groups are regularized (effectively disabling the feature). chunk_size : int, default=10000 Size of data chunks for streaming J^T J accumulation. Larger chunks = faster but more memory. Typical: 5000-50000. gc_chunk_interval : int, default=10 Chunks between gc.collect() calls (FR-007). Controls how often garbage collection runs during chunked processing. Higher values reduce GC overhead but may increase memory usage. Default of 10 balances memory reclamation with performance. enable_checkpoints : bool, default=True Enable checkpoint save/resume for fault tolerance. checkpoint_frequency : int, default=100 Save checkpoint every N iterations (across all phases). validate_numerics : bool, default=True Enable NaN/Inf validation at gradient, parameter, and loss computation points. enable_multi_device : bool, default=False Enable multi-GPU/TPU parallelism for Jacobian computation. Uses JAX pmap for data-parallel computation across devices. callback_frequency : int, default=10 Call progress callback every N iterations (if callback provided). enable_multistart : bool, default=False Enable multi-start optimization with tournament selection during Phase 1. When enabled, generates multiple starting points using LHS sampling and uses tournament elimination to select the best candidate for Phase 2. n_starts : int, default=10 Number of starting points for multi-start optimization. Only used when enable_multistart=True. multistart_sampler : str, default='lhs' Sampling method for generating starting points. Options: 'lhs' (Latin Hypercube), 'sobol', 'halton'. elimination_rounds : int, default=3 Number of tournament elimination rounds. Each round eliminates elimination_fraction of candidates. elimination_fraction : float, default=0.5 Fraction of candidates to eliminate per round. Must be in (0, 1). Default 0.5 = eliminate half each round. batches_per_round : int, default=50 Number of data batches to use for evaluation in each tournament round. More batches = more reliable selection but slower. Examples -------- Default configuration: >>> from nlsq import HybridStreamingConfig >>> config = HybridStreamingConfig() >>> config.warmup_iterations 200 Aggressive profile (faster convergence with L-BFGS): >>> config = HybridStreamingConfig.aggressive() >>> config.warmup_iterations 50 Conservative profile (higher quality): >>> config = HybridStreamingConfig.conservative() >>> config.gauss_newton_tol < 1e-8 True Memory-optimized profile: >>> config = HybridStreamingConfig.memory_optimized() >>> config.chunk_size < 10000 True Custom configuration: >>> config = HybridStreamingConfig( ... warmup_iterations=50, ... lbfgs_history_size=15, ... chunk_size=5000, ... ) With multi-start tournament selection: >>> config = HybridStreamingConfig( ... enable_multistart=True, ... n_starts=20, ... elimination_rounds=3, ... batches_per_round=50, ... ) See Also -------- AdaptiveHybridStreamingOptimizer : Optimizer that uses this configuration curve_fit : High-level interface with method='hybrid_streaming' TournamentSelector : Tournament selection for multi-start optimization Notes ----- Based on Adaptive Hybrid Streaming Optimizer specification: ``agent-os/specs/2025-12-18-adaptive-hybrid-streaming-optimizer/spec.md`` L-BFGS replaces Adam for warmup, providing 5-10x faster convergence to the basin of attraction through approximate Hessian information. """ # Phase 0: Parameter normalization normalize: bool = True normalization_strategy: str = "auto" # Phase 1: L-BFGS warmup warmup_iterations: int = 200 max_warmup_iterations: int = 500 warmup_learning_rate: float = 0.001 loss_plateau_threshold: float = 1e-4 gradient_norm_threshold: float = 1e-3 active_switching_criteria: list[str] | None = None # L-BFGS configuration parameters lbfgs_history_size: int = 10 # Standard default (SciPy, PyTorch, Nocedal & Wright) lbfgs_initial_step_size: float = 0.1 # Cold start scaffolding lbfgs_line_search: Literal["wolfe", "strong_wolfe", "backtracking"] = "wolfe" lbfgs_exploration_step_size: float = 0.1 # For high relative loss (exploration) lbfgs_refinement_step_size: float = 1.0 # For low relative loss (refinement) # Optax enhancements use_learning_rate_schedule: bool = False lr_schedule_warmup_steps: int = 50 lr_schedule_decay_steps: int = 450 lr_schedule_end_value: float = 0.0001 gradient_clip_value: float | None = ( None # None = no clipping, e.g., 1.0 for clipping ) # 4-Layer Defense Strategy for Warmup Divergence Prevention # Layer 1: Warm Start Detection - skip warmup if already near optimum enable_warm_start_detection: bool = True warm_start_threshold: float = 0.01 # Skip if relative_loss < this # Layer 2: Adaptive Step Size - scale step size based on initial loss quality enable_adaptive_warmup_lr: bool = True warmup_lr_refinement: float = 1e-6 # For relative_loss < 0.1 (excellent) warmup_lr_careful: float = 1e-5 # For relative_loss < 1.0 (good) # warmup_learning_rate (0.001) used for relative_loss >= 1.0 (poor) # Layer 3: Cost-Increase Guard - abort if loss increases during warmup enable_cost_guard: bool = True cost_increase_tolerance: float = 0.05 # Abort if loss > initial * 1.05 # Layer 4: Trust Region Constraint - clip update magnitude enable_step_clipping: bool = True max_warmup_step_size: float = 0.1 # Max L2 norm of parameter update # Phase 2: Gauss-Newton gauss_newton_max_iterations: int = 100 gauss_newton_tol: float = 1e-8 trust_region_initial: float = 1.0 regularization_factor: float = 1e-10 # CG-based Gauss-Newton solver configuration # These parameters control the Conjugate Gradient solver used when # the parameter count exceeds cg_param_threshold cg_max_iterations: int = 100 # Cap for high-p problems cg_relative_tolerance: float = 1e-4 # Multiplier for ||J^T r|| (Inexact Newton) cg_absolute_tolerance: float = 1e-10 # Safety floor cg_param_threshold: int = 2000 # Auto-select threshold: p < this -> materialized # Group variance regularization (for per-group parameter absorption prevention) enable_group_variance_regularization: bool = False group_variance_lambda: float = 0.01 group_variance_indices: list[tuple[int, int]] | None = None # Residual weighting for weighted least squares optimization # When enabled, residuals are weighted during loss computation: # wMSE = sum(w[group_idx] * residuals^2) / sum(w[group_idx]) # This is useful for: # - Heteroscedastic data (varying noise levels across groups) # - Emphasizing certain regions or groups of data # - Domain-specific weighting (e.g., group-dependent weights) # The weights are looked up using the first column of x_data as group index. enable_residual_weighting: bool = False residual_weights: list[float] | None = None # Per-group weights, shape (n_groups,) # Streaming configuration chunk_size: int = 10000 # Garbage collection interval for chunked processing (FR-007) gc_chunk_interval: int = 10 # Chunks between gc.collect() calls # Loop strategy for chunk accumulation # 'auto': Use scan on GPU/TPU (better fusion), Python loops on CPU (lower overhead) # 'scan': Always use JAX lax.scan (best for GPU/TPU) # 'loop': Always use Python loops (best for CPU) loop_strategy: Literal["auto", "scan", "loop"] = "auto" # Fault tolerance enable_checkpoints: bool = True checkpoint_frequency: int = 100 checkpoint_dir: str | None = None resume_from_checkpoint: str | None = None validate_numerics: bool = True enable_fault_tolerance: bool = True max_retries_per_batch: int = 2 min_success_rate: float = 0.5 # Multi-device support enable_multi_device: bool = False # Progress monitoring callback_frequency: int = 10 verbose: int = 1 # Verbosity level: 0=silent, 1=progress, 2=debug log_frequency: int = 1 # Log every N iterations in Phase 2 # Multi-start optimization with tournament selection enable_multistart: bool = False n_starts: int = 10 multistart_sampler: Literal["lhs", "sobol", "halton"] = "lhs" elimination_rounds: int = 3 elimination_fraction: float = 0.5 batches_per_round: int = 50 center_on_p0: bool = True scale_factor: float = 1.0
[docs] def __post_init__(self): """Validate configuration after initialization. Delegates to specialized validator functions for each configuration group. ConfigValidationError from validators is re-raised as ValueError for backwards compatibility. """ from nlsq.streaming.validators import ConfigValidationError # Set default for mutable default (list) if self.active_switching_criteria is None: self.active_switching_criteria = ["plateau", "gradient", "max_iter"] try: # Validate enum-like parameters validate_normalization_strategy(self.normalization_strategy) validate_loop_strategy(self.loop_strategy) # Validate Phase 1 warmup configuration validate_warmup_config( warmup_iterations=self.warmup_iterations, max_warmup_iterations=self.max_warmup_iterations, warmup_learning_rate=self.warmup_learning_rate, loss_plateau_threshold=self.loss_plateau_threshold, gradient_norm_threshold=self.gradient_norm_threshold, ) # Validate L-BFGS configuration validate_lbfgs_config( history_size=self.lbfgs_history_size, initial_step_size=self.lbfgs_initial_step_size, line_search=self.lbfgs_line_search, exploration_step_size=self.lbfgs_exploration_step_size, refinement_step_size=self.lbfgs_refinement_step_size, ) # Validate Phase 2 Gauss-Newton configuration validate_gauss_newton_config( max_iterations=self.gauss_newton_max_iterations, tol=self.gauss_newton_tol, trust_region_initial=self.trust_region_initial, regularization_factor=self.regularization_factor, ) # Validate CG solver configuration validate_cg_config( max_iterations=self.cg_max_iterations, relative_tolerance=self.cg_relative_tolerance, absolute_tolerance=self.cg_absolute_tolerance, param_threshold=self.cg_param_threshold, ) # Validate group variance regularization validate_group_variance_config( enabled=self.enable_group_variance_regularization, lambda_val=self.group_variance_lambda, indices=self.group_variance_indices, ) # Validate residual weighting configuration validate_residual_weighting_config( enabled=self.enable_residual_weighting, weights=self.residual_weights, ) # Validate streaming configuration validate_streaming_config( chunk_size=self.chunk_size, checkpoint_frequency=self.checkpoint_frequency, callback_frequency=self.callback_frequency, ) # Validate learning rate schedule validate_lr_schedule_config( enabled=self.use_learning_rate_schedule, warmup_steps=self.lr_schedule_warmup_steps, decay_steps=self.lr_schedule_decay_steps, end_value=self.lr_schedule_end_value, ) # Validate gradient clipping validate_gradient_clip(self.gradient_clip_value) # Validate 4-layer defense strategy validate_defense_layer_config( enable_warm_start=self.enable_warm_start_detection, warm_start_threshold=self.warm_start_threshold, enable_adaptive_lr=self.enable_adaptive_warmup_lr, lr_refinement=self.warmup_lr_refinement, lr_careful=self.warmup_lr_careful, lr_default=self.warmup_learning_rate, enable_cost_guard=self.enable_cost_guard, cost_tolerance=self.cost_increase_tolerance, enable_step_clipping=self.enable_step_clipping, max_step_size=self.max_warmup_step_size, ) # Validate multi-start configuration validate_multistart_config( enabled=self.enable_multistart, n_starts=self.n_starts, sampler=self.multistart_sampler, elimination_fraction=self.elimination_fraction, elimination_rounds=self.elimination_rounds, batches_per_round=self.batches_per_round, scale_factor=self.scale_factor, ) # Validate gc_chunk_interval (FR-007) if self.gc_chunk_interval < 1: raise ValueError( f"gc_chunk_interval must be >= 1, got {self.gc_chunk_interval}" ) except ConfigValidationError as e: # Re-raise as ValueError for backwards compatibility raise ValueError(str(e)) from e
[docs] @classmethod def aggressive(cls): """Create aggressive profile: faster convergence with L-BFGS, looser tolerances. This preset prioritizes speed over robustness: - L-BFGS warmup with reduced iterations (50 vs 300 with Adam) - Higher learning rate for faster progress - Looser tolerances for earlier Phase 2 switching - Larger chunks for better throughput Returns ------- HybridStreamingConfig Configuration with aggressive settings. Examples -------- >>> config = HybridStreamingConfig.aggressive() >>> config.warmup_learning_rate 0.003 >>> config.warmup_iterations 50 """ return cls( # L-BFGS warmup with reduced iterations (5-10x fewer than Adam) warmup_iterations=50, max_warmup_iterations=100, # Higher learning rate for faster progress warmup_learning_rate=0.003, # Looser tolerances for faster switching loss_plateau_threshold=5e-4, gradient_norm_threshold=5e-3, gauss_newton_tol=1e-7, # Larger chunks for throughput chunk_size=20000, # Keep other defaults )
[docs] @classmethod def conservative(cls): """Create conservative profile: slower but robust, tighter tolerances. This preset prioritizes solution quality over speed: - L-BFGS warmup with conservative iterations - Lower learning rate for stability - Tighter tolerances for higher quality - More Gauss-Newton iterations Returns ------- HybridStreamingConfig Configuration with conservative settings. Examples -------- >>> config = HybridStreamingConfig.conservative() >>> config.gauss_newton_tol 1e-10 >>> config.warmup_iterations 30 """ return cls( # L-BFGS warmup with reduced iterations, rely on Gauss-Newton warmup_iterations=30, max_warmup_iterations=80, # Lower learning rate for stability warmup_learning_rate=0.0003, # Tighter tolerances for quality loss_plateau_threshold=1e-5, gradient_norm_threshold=1e-4, gauss_newton_tol=1e-10, # More Gauss-Newton iterations gauss_newton_max_iterations=200, # Smaller trust region for safety trust_region_initial=0.5, # Keep other defaults )
[docs] @classmethod def memory_optimized(cls): """Create memory-optimized profile: smaller chunks, efficient settings. This preset minimizes memory footprint: - Smaller chunks to reduce memory usage - L-BFGS warmup with reduced iterations - Enable checkpoints for recovery (important when memory is tight) - Lower CG threshold for more aggressive CG usage (avoids O(p^2) J^T J) Returns ------- HybridStreamingConfig Configuration with memory-optimized settings. Examples -------- >>> config = HybridStreamingConfig.memory_optimized() >>> config.chunk_size 5000 >>> config.warmup_iterations 40 >>> config.cg_param_threshold 1000 """ return cls( # Smaller chunks for memory efficiency chunk_size=5000, # L-BFGS warmup with reduced iterations warmup_iterations=40, max_warmup_iterations=100, # Enable checkpoints (important when memory tight) enable_checkpoints=True, checkpoint_frequency=50, # More frequent saves # More aggressive CG usage to avoid O(p^2) J^T J storage cg_param_threshold=1000, # Lower threshold for memory savings # Keep other defaults )
[docs] @classmethod def with_multistart(cls, n_starts: int = 10, **kwargs): """Create configuration with multi-start tournament selection enabled. This preset enables multi-start optimization for finding global optima: - Tournament selection during Phase 1 warmup - LHS sampling for generating starting points - Progressive elimination to select best candidate Parameters ---------- n_starts : int, default=10 Number of starting points to generate. **kwargs Additional configuration parameters to override. Returns ------- HybridStreamingConfig Configuration with multi-start enabled. Examples -------- >>> config = HybridStreamingConfig.with_multistart(n_starts=20) >>> config.enable_multistart True >>> config.n_starts 20 """ return cls( enable_multistart=True, n_starts=n_starts, **kwargs, )
# ========================================================================= # Defense Layer Sensitivity Presets # =========================================================================
[docs] @classmethod def defense_strict(cls): """Create strict defense layer profile for near-optimal scenarios. This preset maximizes protection against divergence when initial parameters are expected to be close to optimal (warm starts, refinement): - Very low warm start threshold (triggers at 1% relative loss) - Ultra-conservative learning rates for refinement - Very tight cost guard tolerance (5% increase aborts) - Very small step clipping for stability Use this when: - Continuing optimization from a previous fit - Refining parameters that are already close to optimal - Dealing with ill-conditioned problems - Prioritizing stability over speed Returns ------- HybridStreamingConfig Configuration with strict defense layer settings. Examples -------- >>> config = HybridStreamingConfig.defense_strict() >>> config.warm_start_threshold 0.01 >>> config.cost_increase_tolerance 0.05 >>> config.warmup_iterations 25 """ return cls( # All defense layers enabled enable_warm_start_detection=True, enable_adaptive_warmup_lr=True, enable_cost_guard=True, enable_step_clipping=True, # Layer 1: Very low threshold (1% relative loss triggers warm start) warm_start_threshold=0.01, # Layer 2: Ultra-conservative LR progression warmup_lr_refinement=1e-7, warmup_lr_careful=1e-6, warmup_learning_rate=0.0005, # Layer 3: Very tight cost guard (5% increase aborts) cost_increase_tolerance=0.05, # Layer 4: Very small steps max_warmup_step_size=0.05, # L-BFGS warmup with reduced iterations warmup_iterations=25, max_warmup_iterations=60, )
[docs] @classmethod def defense_relaxed(cls): """Create relaxed defense layer profile for exploration-heavy scenarios. This preset reduces defense layer sensitivity for problems where significant parameter exploration is needed: - Higher warm start threshold (50% relative loss needed to skip) - More aggressive learning rates for exploration - Generous cost guard tolerance (50% increase allowed) - Larger step clipping for faster exploration Use this when: - Starting from a rough initial guess - Exploring a wide parameter space - Problems with multiple local minima - Speed is more important than robustness Returns ------- HybridStreamingConfig Configuration with relaxed defense layer settings. Examples -------- >>> config = HybridStreamingConfig.defense_relaxed() >>> config.warm_start_threshold 0.5 >>> config.cost_increase_tolerance 0.5 >>> config.warmup_iterations 50 """ return cls( # All defense layers enabled but relaxed enable_warm_start_detection=True, enable_adaptive_warmup_lr=True, enable_cost_guard=True, enable_step_clipping=True, # Layer 1: High threshold (50% relative loss triggers warm start) warm_start_threshold=0.5, # Layer 2: Aggressive LR progression warmup_lr_refinement=1e-5, warmup_lr_careful=1e-4, warmup_learning_rate=0.003, # Layer 3: Generous cost guard (50% increase allowed) cost_increase_tolerance=0.5, # Layer 4: Larger steps for exploration max_warmup_step_size=0.5, # L-BFGS warmup with reduced iterations warmup_iterations=50, max_warmup_iterations=120, )
[docs] @classmethod def defense_disabled(cls): """Create profile with all defense layers disabled. This preset completely disables the 4-layer defense strategy, reverting to pre-0.3.6 behavior. Use with caution as this removes protection against warmup divergence. Use this when: - Debugging to isolate defense layer effects - Benchmarking without defense overhead - Backward compatibility with older code is required Returns ------- HybridStreamingConfig Configuration with all defense layers disabled. Examples -------- >>> config = HybridStreamingConfig.defense_disabled() >>> config.enable_warm_start_detection False """ return cls( enable_warm_start_detection=False, enable_adaptive_warmup_lr=False, enable_cost_guard=False, enable_step_clipping=False, )
[docs] @classmethod def scientific_default(cls): """Create profile optimized for scientific computing workflows. This preset is tuned for scientific fitting scenarios like spectroscopy, decay curves, and other physics-based models: - Balanced defense layers that protect without being too aggressive - L-BFGS warmup with moderate iterations - Enabled checkpoints for long-running fits Use this when: - Fitting physics-based models (spectroscopy, decay curves) - Numerical precision is important - Parameters may have multiple scales - Reproducibility is required Returns ------- HybridStreamingConfig Configuration optimized for scientific computing. Examples -------- >>> config = HybridStreamingConfig.scientific_default() >>> config.warmup_iterations 35 """ return cls( # All defense layers enabled with balanced settings enable_warm_start_detection=True, enable_adaptive_warmup_lr=True, enable_cost_guard=True, enable_step_clipping=True, # Layer 1: Moderate threshold warm_start_threshold=0.05, # Layer 2: Balanced LR progression warmup_lr_refinement=1e-6, warmup_lr_careful=1e-5, warmup_learning_rate=0.001, # Layer 3: Moderate cost guard cost_increase_tolerance=0.2, # Layer 4: Moderate step clipping max_warmup_step_size=0.1, # L-BFGS warmup with reduced iterations warmup_iterations=35, max_warmup_iterations=100, # Scientific computing settings gauss_newton_tol=1e-10, gauss_newton_max_iterations=200, # Enable checkpoints for long jobs enable_checkpoints=True, checkpoint_frequency=100, )