Model Fitting
This module uses the JAX library for high-performance, gradient-based optimization to fit the parameters of a FosterNetwork
to thermal impedance data.
fit_foster_network()
Section titled “fit_foster_network()”fit_foster_network( time_data, impedance_data, n_layers, config=None, random_seed=0, tau_floor=None)
Fits an N-layer Foster network to thermal impedance data.
time_data
:array-like
- Array of time points.impedance_data
:array-like
- Array of corresponding thermal impedance values.n_layers
:int
- The number of RC layers to fit.config
:OptimizationConfig
, optional - Configuration for the optimization process (e.g., optimizer, learning rate, tolerances). IfNone
, default settings are used.random_seed
:int
- Seed for randomizing the initial guess.tau_floor
:float
, optional - If set, guarantees the smallest time constant will be greater than this value. IfNone
, it’s fully free.- Returns:
FittingResult
- An object containing the fittedFosterNetwork
and metadata about the optimization.
fit_optimal_foster_network()
Section titled “fit_optimal_foster_network()”fit_optimal_foster_network( time_data, impedance_data, max_layers=10, selection_criterion='bic', config=None, random_seed=0, tau_floor=None)
Fits models with 1 to max_layers
and selects the best one using a model selection criterion (AIC or BIC). This is useful for automatically determining the required complexity of the model.
time_data
:array-like
- Array of time points.impedance_data
:array-like
- Array of corresponding thermal impedance values.max_layers
:int
- The maximum number of layers to test.selection_criterion
:str
-'aic'
or'bic'
. The criterion used for model selection.config
:OptimizationConfig
, optional - Configuration for the optimization process.random_seed
:int
- Seed for randomizing the initial guess.tau_floor
:float
, optional - If set, guarantees the smallest time constant will be greater than this value. IfNone
, it’s fully free.- Returns:
ModelSelectionResult
- The best model found, including its selection criteria scores.
trim_steady_state()
Section titled “trim_steady_state()”trim_steady_state( time_data, impedance_data, min_points=5, p_value_tol=0.1, noise_std_multiplier=2.0)
Detects the steady-state region at the end of thermal impedance data and retains only the first point of that region.
time_data
:array-like
- Array of time points.impedance_data
:array-like
- Array of corresponding thermal impedance values.min_points
:int
- Minimum number of points required for a steady-state region.p_value_tol
:float
- p-value threshold for the null hypothesis “slope = 0” (set higher for stricter flatness).noise_std_multiplier
:float
- Multiplier for the noise standard deviation used as residual tolerance for the linear regression (set lower for stricter fit).- Returns:
tuple
- A tuple containing the trimmed time and impedance arrays.
OptimizationConfig
Section titled “OptimizationConfig”A data class for configuring the fitting process.
optimizer
:str
-'lbfgs'
or'adam'
.n_steps
:int
- Maximum number of optimization steps. Defaults to100000
for Adam and20000
for L-BFGS.learning_rate
:float
- Learning rate for the Adam optimizer.loss_tol
:float
- Convergence tolerance for the change in loss value.gradient_tol
:float
- Convergence tolerance for the gradient norm.params_rtol
:float
- Relative tolerance for parameter change.params_atol
:float
- Absolute tolerance for parameter change.randomize_guess_strength
:float
- Stddev of multiplicative noise for randomizing the initial guess. 0 implies a deterministic initial guess.
Example: Automatic Model Selection
Section titled “Example: Automatic Model Selection”-
Generate Synthetic Data
First, we create a “true” 3-layer network and generate noisy impedance data from it, simulating a real-world measurement.
import numpy as npfrom thermal_network.networks import FosterNetworkfrom thermal_network.impedance import foster_impedance_time_domain# Define a true 3-layer networktrue_network = FosterNetwork(r=[0.2, 0.8, 0.5], c=[15.0, 1.0, 4.0])time_vec = np.logspace(-1, 2, 200)true_impedance = foster_impedance_time_domain(true_network, time_vec)# Add noisenp.random.seed(42)noise_level = 0.015 * np.max(true_impedance)noisy_impedance = true_impedance + noise_level * np.random.randn(true_impedance.shape[0]) -
Find the Optimal Model
We use
fit_optimal_foster_network
to test models from 1 to 10 layers and let it choose the best one based on the Bayesian Information Criterion (BIC).from thermal_network.fitting import fit_optimal_foster_network# Find the optimal model up to 10 layersresult = fit_optimal_foster_network(time_vec,noisy_impedance,max_layers=10,selection_criterion='bic',)optimal_model = result.best_modelprint(f"Optimal model found with {optimal_model.n_layers} layers.")print(f"BIC Score: {result.selection_criteria['bic']:.2f}")print("Fitted Network:", optimal_model.network)