PyBNF objective functions (pybnf.objective)¶
Classes defining various objective functions used for evaluating points in parameter space
- class pybnf.objective.AveNormSumOfSquaresObjective(ind_var_rounding=0)[source]¶
Sum of squares where each point is normalized by the average value of that variable, ((y-y’)/ybar)^2
- eval_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
Calculate the objective function for a single point in the data This evaluation is what differentiates the different objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param sim_row: The row number to look at in sim_data :param exp_row: The row number to look at in exp_data :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- class pybnf.objective.ChiSquareObjective(ind_var_rounding=0, overrides=None, noise=None, sigma_source=None, sigma_sources=None)[source]¶
Gaussian observation noise with sigma read per point from the data’s
_SDcolumn. Being fixed, the Gaussian normalizer is parameter-independent and dropped, leaving the chi-square data fit (ADR-0011/0021).- noise = <pybnf.noise.gaussian.Gaussian object>¶
The default per-observable noise model (applied to every column without an override): a NoiseModel plus its source(s). Subclasses set
noise/sigma_source(a single source) as class attributes; neg_bin setssigma_sourceper instance (its constant is a config value). A multi-parameter default (a whole-fit student_t line) is passed assigma_sources(the mapping) to the constructor;_default_sources()reconciles the two (ADR-0058).
- class pybnf.objective.ChiSquareObjective_Dynamic(ind_var_rounding=0, overrides=None, noise=None, sigma_source=None, sigma_sources=None)[source]¶
Gaussian observation noise with sigma a free parameter (
sigma__FREE). Being estimated, the Gaussian normalizer+log sigmais retained (ADR-0011).- noise = <pybnf.noise.gaussian.Gaussian object>¶
The default per-observable noise model (applied to every column without an override): a NoiseModel plus its source(s). Subclasses set
noise/sigma_source(a single source) as class attributes; neg_bin setssigma_sourceper instance (its constant is a config value). A multi-parameter default (a whole-fit student_t line) is passed assigma_sources(the mapping) to the constructor;_default_sources()reconciles the two (ADR-0058).
- class pybnf.objective.ColumnSummationObjective(ind_var_rounding=0)[source]¶
Represents a type of objective function in which we perform some kind of summation for one column at a time. The assumption is that the independent variable is the same for each row.
- eval_column(sim_data, exp_data, col_name)[source]¶
Calculate the objective function for a single column in the data This evaluation is what differentiates the different column based objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- class pybnf.objective.ConstraintCounter[source]¶
An objective function that just counts the numbered of failed constraints Used only in model checking
- class pybnf.objective.DirectPassObjective[source]¶
Passes through the score value directly from the simulated data.
Expects the simulated data to contain a single column ‘score’ with a single row. The experimental data is ignored: the analytical / bring-your-own objective IS the score, so there is nothing to compare against (ADR-0031/0059).
- evaluate_multiple(sim_data_dict, exp_data_dict, pset, constraints=(), show_warnings=True)[source]¶
Score straight off the model’s ‘score’ column, with no experimental-data pairing (ADR-0031/0059).
The base
ObjectiveFunction.evaluate_multiple()only scores a model-output suffix that has a matching experimental-data suffix – the right rule for a per-point objective, but fordirect_passthere is no exp column to compare to, so that rule forced an empty placeholder.expfile to exist purely to make the suffix match (the #425 discoverability footgun). This override drops the exp requirement: it sums the score of every output suffix the model emits (each read byevaluate(), which still requires ascorecolumn), so a closed-form / analytical target scores with no data file at all. Constraint penalties still apply, unchanged.
- class pybnf.objective.InformationCriteria(k, n, log_likelihood, aic, bic, aicc)¶
AIC/BIC/AICc for a fit, alongside the inputs (
kfree params,ndata points,log_likelihood) so a report can show the derivation.aiccisNonewhen the small-sample correction is undefined (n <= k + 1).- aic¶
Alias for field number 3
- aicc¶
Alias for field number 5
- bic¶
Alias for field number 4
- k¶
Alias for field number 0
- log_likelihood¶
Alias for field number 2
- n¶
Alias for field number 1
- class pybnf.objective.KLLikelihood(ind_var_rounding=0)[source]¶
The Kullback-Leibler likelihood. It should be more efficient in parameter fitting as numerical experiments suggest
- eval_column(sim_data, exp_data, col_name)[source]¶
Calculate the objective function for a single column in the data This evaluation is what differentiates the different column based objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- class pybnf.objective.LaplaceObjective(ind_var_rounding=0, overrides=None, noise=None, sigma_source=None, sigma_sources=None)[source]¶
Laplace observation noise with the scale
ba free parameter (b__FREE) – the heavy-tailed, outlier-robust likelihood behind least-absolute-deviation fitting (ADR-0021). Being estimated, thelog(2 b)normalizer is retained, which is what keeps the fit from drivingb -> inf. PEtab v2’snoiseDistribution = laplace; a fixed-scale Laplace is reachable per observable viaread_exp_file/fix_at.- noise = <pybnf.noise.laplace.Laplace object>¶
The default per-observable noise model (applied to every column without an override): a NoiseModel plus its source(s). Subclasses set
noise/sigma_source(a single source) as class attributes; neg_bin setssigma_sourceper instance (its constant is a config value). A multi-parameter default (a whole-fit student_t line) is passed assigma_sources(the mapping) to the constructor;_default_sources()reconciles the two (ADR-0058).
- class pybnf.objective.LikelihoodObjective(ind_var_rounding=0, overrides=None, noise=None, sigma_source=None, sigma_sources=None)[source]¶
A per-point likelihood: a distribution-family NoiseModel scored against the data with its noise parameter drawn from a SigmaSource, summed over points (ADR-0011, ADR-0021). The
(family, sigma_source)pair is selected per observable – the class-level default applies to every column, overridden for named observables byself.overrides. The five legacy likelihood objfuncs are exactly this object with a fixed default pair (chi_sq = Gaussian x the_SDdata column, chi_sq_dynamic = Gaussian x a free sigma, neg_bin = NegBinomial x a constant, …); per-observable selection is the new capability they all inherit.The whole family/normalizer choice collapses to one per-point expression: the family’s
data_fitalways, plus each noise parameter’sparam_normalizersentry iff that parameter’s source isestimated. That single rule reproduces every legacy objfunc – the data-fit-vs-nll split that used to be hard-coded per subclass now follows from whether each noise parameter is estimated (ADR-0011), and a two-parameter family (student_t’s sigma + df, ADR-0058) gates each independently.- data_fit_grad_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
d(data_fit)/d(prediction)for one scored point – the scalar-gradient seam an asymmetric family with no clean least-squares residual routes through (layer G, #454/#385): Laplace (its L1 data fit|z|/bis a cusp,sqrt(2 data_fit) ~ sqrt|z|has infinite slope atz=0, so it is inherently not least-squares, #459) and the count family (NegBinomial). A Gaussian or Student-t observable – whose data fit does reformulate as a smooth half-square – is routed throughresidual_pointinstead (has_least_squares_residual()decides).The assembly accumulates
sum_i w_i * data_fit_grad_point_i * d(prediction_i)/d thetadirectly into the scalar gradient and flags the result notleast_squares_exact– the universal form a quasi-Newton (L-BFGS) step consumes. Reads the prediction through the same_predictionseam and the noise through the same_noise_valuesmappingeval_pointuses, so it differentiates exactly the data fit PyBNF scores; the per-family slope isd_data_fit_d_prediction(). The per-point bootstrap weight is applied by the assembly, not here – mirroringresidual_point.
- eval_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
Calculate the objective function for a single point in the data This evaluation is what differentiates the different objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param sim_row: The row number to look at in sim_data :param exp_row: The row number to look at in exp_data :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- evaluate_pointwise(sim_data_dict, exp_data_dict, pset)[source]¶
The per-observation log-likelihoods this fit’s noise model assigns the data under
pset– the pointwise decomposition LOO/WAIC consume (ADR-0056).Returns
(ids, values):idsa list of stable per-point labels (model/suffix/observable@indvar=value),valuesthe matchingnp.ndarrayof genuine, unweighted log-densities. Each value is the family’s complete normalizedlog_density(the constant Gaussian/Jacobian termseval_pointdrops restored), NOT-eval_point: a predictive density needs the full normalization, and PyBNF’s per-pointweightsare a fitting device, not part of the generative model. So these do not sum to-score; they are the honest densitiesaz.loo/az.waicneed.Mirrors
evaluate_multiple’s per-evaluation setup – the{name: value}map aFreeParameterSigmareads, and the measurement-model observation layer – so the densities are scored against exactly the dataevaluatesaw. The emitted observation set is fixed by the experimental data (a point is skipped only on a NaN observation, never on anything draw-dependent), so every draw yields the same ids in the same order – the rectangularchain x draw x obsarray the bridge needs.
- classmethod from_config(config)[source]¶
Build this objective from the config dict (ADR-0011). The base takes no constructor args (e.g.
direct_pass); subclasses that read config keys override – the uniform construction entry point replacing the registry’s per-objfuncconfig_argsrecipe.
- has_least_squares_residual(col_name)[source]¶
Whether this observable contributes an exact least-squares residual/Jacobian (layer G, #454/#385; #459).
Truefor a family whose data fit reformulates as a smooth half-square – the Gaussian (data_fit = 1/2 rho**2) and, #459, the Student-t (the exact square-root-loss residualsign(z) sqrt(2 data_fit), smooth throughz=0) – on any scale and either location, so the assembly routes it throughresidual_pointand a fixed-scale fit isleast_squares_exact(#386’s LM/TRF consumes the residual form).Falsefor an asymmetric family with no clean residual – Laplace (its L1 data fit|z|/bgives the cuspsqrt|z|, infinite slope atz=0) and the count family – whose gradient goes through the scalardata_fit_grad_pointpath, so the result is notleast_squares_exact.
- noise = None¶
The default per-observable noise model (applied to every column without an override): a NoiseModel plus its source(s). Subclasses set
noise/sigma_source(a single source) as class attributes; neg_bin setssigma_sourceper instance (its constant is a config value). A multi-parameter default (a whole-fit student_t line) is passed assigma_sources(the mapping) to the constructor;_default_sources()reconciles the two (ADR-0058).
- noise_grad_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
The per-point gradient of the loss w.r.t. each estimated free noise parameter at one scored point –
{free_param_name: d loss/d param}(layer D/G, #451/#454/#385).Empty for a fixed-noise point (chi_sq’s data column, a constant, a relative scale): no noise parameter is estimated, so the loss carries no normalizer and the noise scale adds no gradient column. Otherwise each estimated noise parameter contributes
d(data_fit + its own normalizer)/d param, the column that keeps a free scale from running away. The per-parameter derivatives are the family’s own (d_nll_d_noise_params()):Gaussian’s single sigma:
(1 - rho**2)/sigma(the+log sigmanormalizer, layer D) –rhothe additive-space residual, so it composes with a log scale (#452); on the linear scale it is the historical closed form byte-for-byte.Laplace’s scale
b:-|residual|/b**2 + 1/b(thelog(2 b)normalizer).Student-t’s
sigmaanddf– the first multi-parameter estimated-noise gradient (ADR-0058); each independently sourced and gated.
Read through the same
_prediction/_noise_valuesseamseval_pointandresidual_pointuse, so the noise gradient differentiates exactly the loss PyBNF reports. Each free parameter is the noise parameter (factor 1), so the column maps straight to the source’s free-parameter name.Lives on the scalar-gradient (L-BFGS) path only: a normalizer like
+log sigmais not a sum of squares, so the trust-region residual form cannot represent it. The assembly adds this straight to the scalar gradient (and flags the residual form’s least-squares model inexact); the per-point bootstrap weight is applied there, not here – mirroringresidual_point.
- overrides¶
{col_name: (NoiseModel, {param: SigmaSource})} overriding the default per observable; empty -> every column uses the default, byte-identical to the pre-#410 single global objfunc.
- required_free_noise_params()[source]¶
The free-parameter names this objective’s noise sources estimate (default spec + every override) – what
_load_variableschecks have matching FreeParameters (ADR-0021). Iterates each spec’s per-parameter source mapping (one source for the single-parameter families, two for student_t; ADR-0058).
- residual_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
The least-squares residual
rand its derivatived r/d predfor one scored point (#449/#385/#452/#459).The residual a family whose data fit reformulates as a smooth half-square carries – the Gaussian (
data_fit = 1/2 rho**2, soris the standardized residualrho) and, layer-G follow-up #459, the Student-t (the exact square-root-loss residualr = sign(z) sqrt(2 data_fit), smooth throughz=0). The assembly routes such a column here, an asymmetric family with no clean residual (Laplace, whose L1 data fit is a cusp; the count family) throughdata_fit_grad_point()instead (has_least_squares_residual()decides). The pure family math lives on the noise model (residual()/d_residual_d_prediction()); this seam sources the prediction and the noise parameters and delegates, soris defined for the prediction as the MEDIAN or the MEAN (layer G, #454), additive on any scale (LINEAR, or a log scale: LOG10 / LN, #452). The residual lives in the additive (log) space,mu = forward(pred) - location offset, so its derivative picks up the scale’s chain factorforward'(pred)(1on the linear scale,1/(pred*ln10)for log10). The location offset is prediction-independent, so a MEDIAN (any scale) / a MEAN on the linear scale collapses to the historical Gaussian(pred-obs)/sigma/1/sigmabyte-for-byte; a MEAN on a log scale subtracts the family’s moment correction. Either way the family’sresidualsatisfies1/2 r**2 == data_fit, so this returns the same data-fit losseval_pointdoes in residual form, andr * d_residual_d_prediction == d_data_fit_d_prediction, so the residual-Jacobian reproduces the objective gradient.sigma(and Student-t’sdf) may be fixed (chi_sq/lognormal/student_t) or an estimated free parameter (chi_sq_dynamic); the residual is identical either way – an estimated scale’s own gradient column (its retained+log sigma/ df-block normalizer, which is not a square) is emitted separately bynoise_grad_point()(layer D/G, #451/#454). Any other per-observable configuration raisesGradientNotSupported(the capability gate); later layers extend it.Out-of-support points (log scale): match ``evaluate``. On a log scale
forward = log10requirespred > 0andobs > 0. PyBNF does not raise on a non-positive point here; it propagates a non-finiter(so the assembled gradient goes non-finite), exactly asevaluatereturns a non-finite score for the same point rather than raising – the optimizer’s existing signal to reject the step. Raising would diverge the gradient from the scalar objective it differentiates (a point the objective merely scoresinf/nanwould instead abort assembly); propagating keeps the two paths consistent.Reads the prediction through the same
_predictionseam and the noise through the same_noise_valuesmappingeval_pointuses, so the residual is the exact derivative of the loss PyBNF reports – same noise-weighting, same column selection. The per-point bootstrap weight is not applied here (the assembly foldssqrt(weight)into bothrand the Jacobian, exactly asevaluatemultiplieseval_pointby the weight).
- set_default_location(location)[source]¶
Apply a whole-fit default location interpretation (the global
noise_locationkey, ADR-0024; the modern-edition median default, ADR-0031) to the class-default noise model – the one used for every observable without a per-observablenoise_modeloverride (those already carry their own location). Mirrors the per-observablelocationfield via_apply_location; every family supports both mean and median (the neg_bin median is the per-point CDF inversion of issue #419).
- supports_pointwise_log_likelihood = True¶
A per-point likelihood can be left-one-out, so it supports LOO/WAIC (ADR-0056).
- class pybnf.objective.LogNormalObjective(ind_var_rounding=0, overrides=None, noise=None, sigma_source=None, sigma_sources=None)[source]¶
Lognormal observation noise: the Gaussian family additive on the log10 scale with the prediction interpreted as the median (ADR-0011, ADR-0022). sigma (the log10-scale standard deviation) comes from the data’s
_SDcolumn exactly as in chi_sq – being fixed, the Gaussian normalizer and the lognormal Jacobian are parameter-independent and dropped, leaving the log10-space squared residual(log10 sim - log10 exp)^2 / (2 sigma^2). log10 (not natural log) so sigma is a log10-scale standard deviation consistently with every other PyBNFlog(ADR-0022); the natural-log lognormal density isGaussian(LN, MEDIAN). Only the noise family differs from chi_sq – the seam proof that the scale and location axes compose. Observations and predictions must be positive (the lognormal support).- noise = <pybnf.noise.gaussian.Gaussian object>¶
The default per-observable noise model (applied to every column without an override): a NoiseModel plus its source(s). Subclasses set
noise/sigma_source(a single source) as class attributes; neg_bin setssigma_sourceper instance (its constant is a config value). A multi-parameter default (a whole-fit student_t line) is passed assigma_sources(the mapping) to the constructor;_default_sources()reconciles the two (ADR-0058).
- class pybnf.objective.NegBinLikelihood(r, ind_var_rounding=0, overrides=None)[source]¶
Negative-binomial likelihood with the dispersion
ra fixed config constant (neg_bin_r). Fixed and self-normalizing, so the objective is the NegBinomial data fit (ADR-0011).- classmethod from_config(config)[source]¶
Build this objective from the config dict (ADR-0011). The base takes no constructor args (e.g.
direct_pass); subclasses that read config keys override – the uniform construction entry point replacing the registry’s per-objfuncconfig_argsrecipe.
- noise = <pybnf.noise.negative_binomial.NegBinomial object>¶
The default per-observable noise model (applied to every column without an override): a NoiseModel plus its source(s). Subclasses set
noise/sigma_source(a single source) as class attributes; neg_bin setssigma_sourceper instance (its constant is a config value). A multi-parameter default (a whole-fit student_t line) is passed assigma_sources(the mapping) to the constructor;_default_sources()reconciles the two (ADR-0058).
- class pybnf.objective.NegBinLikelihood_Dynamic(ind_var_rounding=0, overrides=None, noise=None, sigma_source=None, sigma_sources=None)[source]¶
Negative-binomial likelihood with the dispersion
ra free parameter (r__FREE). NegBinomial’s PMF is self-normalizing, sonll == data_fit; the source is estimated but its normalizer is 0 (ADR-0011).- noise = <pybnf.noise.negative_binomial.NegBinomial object>¶
The default per-observable noise model (applied to every column without an override): a NoiseModel plus its source(s). Subclasses set
noise/sigma_source(a single source) as class attributes; neg_bin setssigma_sourceper instance (its constant is a config value). A multi-parameter default (a whole-fit student_t line) is passed assigma_sources(the mapping) to the constructor;_default_sources()reconciles the two (ADR-0058).
- class pybnf.objective.NormSumOfSquaresObjective(ind_var_rounding=0)[source]¶
Sum of squares where each point is normalized by the y value at that point, ((y-y’)/y)^2
- eval_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
Calculate the objective function for a single point in the data This evaluation is what differentiates the different objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param sim_row: The row number to look at in sim_data :param exp_row: The row number to look at in exp_data :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- class pybnf.objective.ObjectiveCalculator(objective, exp_data_dict, constraints)[source]¶
Wrapper for all of the objects needed for the workers to calculate the objective function value. Contains the objective function, exp_data_dict, and constraint tuple
- evaluate_objective(sim_data_dict, pset, show_warnings=True)[source]¶
Evaluate the objective using the input simulation data and the info contained in this object :param sim_data_dict: Dictionary of the form {modelname: {suffix1: Data1}} containing the simulated data objects :param show_warnings: If True, print warnings about unused data :type show_warnings: bool :return:
- class pybnf.objective.ObjectiveFunction[source]¶
Abstract class representing an objective function Subclasses customize how the objective value is calculated from the quantitative exp data The base class includes all the support we need for constraints.
- data_fit_grad_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
d(data_fit)/d(prediction)for one scored point – the scalar-gradient seam for an asymmetric family whose data fit is not a sum of squares (layer G, #454/#385). The base raisesGradientNotSupported(it is reached only whenhas_least_squares_residual()is False, which the base never reports). OnlyLikelihoodObjectiveoverrides it.
- evaluate_multiple(sim_data_dict, exp_data_dict, pset, constraints=(), show_warnings=True)[source]¶
Compute the value of the objective function on several data sets, and return the total. Optionally may pass an iterable of ConstraintSets whose penalties will be added to the total :param sim_data_dict: Dictionary of the form {modelname: {suffix1: Data1}} containing the simulated data objects :type sim_data_dict: dict :param exp_data_dict: Dictionary of the form {modelname: {suffix1: Data1}} containing experimental Data objects :type exp_data_dict: dict :param constraints: Iterable of ConstraintSet objects containing the constraints that we should evaluate using the simulated data :type constraints: Iterable of ConstraintSet :param show_warnings: If True, print warnings about unused data :type show_warnings: bool :return:
- evaluate_pointwise(sim_data_dict, exp_data_dict, pset)[source]¶
Per-observation log-likelihoods for one parameter set – the pointwise decomposition LOO/WAIC consume, as opposed to
evaluate_multiple’s scalar total (ADR-0056). Returns(ids, values)–idsa list of stable per-point labels,valuesthe matchingnp.ndarrayof genuine, unweighted log-densities – orNonefor an objective that is not a per-point likelihood. The base is that no-op;LikelihoodObjectiveoverrides it (and flipssupports_pointwise_log_likelihood).
- classmethod from_config(config)[source]¶
Build this objective from the config dict (ADR-0011). The base takes no constructor args (e.g.
direct_pass); subclasses that read config keys override – the uniform construction entry point replacing the registry’s per-objfuncconfig_argsrecipe.
- has_least_squares_residual(col_name)[source]¶
Whether one scored column contributes an exact least-squares residual/Jacobian (a Gaussian, whose
data_fitis1/2 rho**2) vs only the scalar data-fit gradient an asymmetric family carries (Laplace / Student-t, layer G of #385). The assembly routes a True column throughresidual_point()(the residual-Jacobian form) and a False one throughdata_fit_grad_point()(the scalar accumulator).Trueon the base, whereresidual_point()itself refuses an unsupported objective – so a non-likelihood / unsupported objective still raisesGradientNotSupportedthere rather than being silently routed elsewhere. OnlyLikelihoodObjectiveoverrides this to distinguish its families.
- measurement = None¶
The measurement-model observation layer (ADR-0036): a
MeasurementLayerthat materializes each expressionobservableFormula’s column into the simulated data (using the PSet) before the by-name objective match below.None(the default for every job without an expression measurement model) is an exact no-op, so the objective is byte-identical to its pre-#407 behavior. New-era PEtab/SBML (and the retrofitted new-era BNGL-expression) path attaches a populated layer inconfig.py.
- noise_grad_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
The per-point gradient of the loss w.r.t. each estimated free noise parameter –
{free_param: d loss/d param}(layer D, #451).Empty on the base: a non-likelihood objective (least-squares, distance, pass-through) estimates no noise parameter, so its scale contributes no gradient column. Only
LikelihoodObjectiveoverrides it, and only for the cut-1 Gaussian case with a free-parameter scale – the noise twin of the per-pointresidual_pointseam (whose base refuses, since the assembly reaches that first and gates the whole configuration there).
- required_free_noise_params()[source]¶
The free-parameter names this objective requires the fit to declare for its estimated noise sources – empty unless it is a likelihood with a free-parameter noise source (ADR-0021).
_load_variableschecks these against the declared free parameters, generalizing the old per-objfuncsigma__FREE/r__FREEhard-coded checks.
- residual_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
The standardized residual
rhoand its derivatived rho/d predictionfor one scored point – the per-point seam the gradient path differentiates (#449/#385).rhoandd rho/d predare defined so that this point’s contribution to the loss is1/2 rho**2andd(loss)/d pred = rho * d rho/d pred– the residual formscipy.least_squaresminimizes, agreeing with the scalar gradient by construction. The assembly multipliesd rho/d predby the forward sensitivityd pred/d theta(routed through #448’s chain-rule factor) to build the residual-Jacobian column.The base raises
GradientNotSupported: only a per-point likelihood (LikelihoodObjective) defines a residual, and only for the cut-1 Gaussian/MEDIAN configuration (the noise scale – linear or log – and a fixed-or-single-free sigma are admitted; #452/#451). Every other objective (least-squares, distance, pass-through) and every later layer raises until its support lands – so #386 can fall back to a gradient-free step.
- supports_pointwise_log_likelihood = False¶
Whether this objective can decompose its value into genuine per-observation log-likelihoods (ADR-0056) – the precondition for LOO/WAIC. True only for a per-point likelihood (
LikelihoodObjective); a least-squares / distance / pass-through objective has no normalized density to leave one out of, so it stays False andevaluate_pointwisereturns None (the LOO/WAIC no-op gate).
- class pybnf.objective.SumOfDiffsObjective(ind_var_rounding=0)[source]¶
- eval_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
Calculate the objective function for a single point in the data This evaluation is what differentiates the different objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param sim_row: The row number to look at in sim_data :param exp_row: The row number to look at in exp_data :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- class pybnf.objective.SumOfSquaresObjective(ind_var_rounding=0)[source]¶
- eval_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
Calculate the objective function for a single point in the data This evaluation is what differentiates the different objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param sim_row: The row number to look at in sim_data :param exp_row: The row number to look at in exp_data :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- class pybnf.objective.SummationObjective(ind_var_rounding=0)[source]¶
Represents a type of objective function in which we perform some kind of summation over all available experimental data points individually.
- eval_point(sim_data, exp_data, sim_row, exp_row, col_name)[source]¶
Calculate the objective function for a single point in the data This evaluation is what differentiates the different objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param sim_row: The row number to look at in sim_data :param exp_row: The row number to look at in exp_data :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- classmethod from_config(config)[source]¶
Build this objective from the config dict (ADR-0011). The base takes no constructor args (e.g.
direct_pass); subclasses that read config keys override – the uniform construction entry point replacing the registry’s per-objfuncconfig_argsrecipe.
- prediction_sensitivity(sim_data, sim_row, col_name, exp_data, exp_row, raw_sens, index)[source]¶
∂pred/∂θ(a native-space(n_param,)vector) for one matched point – the gradient seam mirroring_prediction()(#453/#385), branch for branch._predictionforms the scored value from the simulation through up to one trajectory transform; this returns that value’s parameter sensitivity, so the assembly differentiates exactly what it scores.raw_sens(column_name, row)is the sensitivity of a sim column as ``_prediction`` reads it – the #447 tensor with anyData-level normalization (ADR-0053) already folded in (so a normalized fit threads the normalizer’s own derivative, and the transforms below compose on top of it exactly as scoring applies normalize ->_prediction).indexmaps a free-parameter name to its column.Plain (the default, byte-identical to the raw observable):
raw_sens(col, row).Cumulative -> incident (ADR-0051): the prediction is
raw_i - raw_{i-1}(row 0 keeps its raw value), so∂pred_i/∂θ = raw_sens(col, i) - raw_sens(col, i-1)– a difference of sensitivity rows (row 0 keeps the plain value).Per-measurement scale/offset (ADR-0045): a general PEtab formula, so its sensitivity is the formula’s symbolic gradient chained through each referenced column’s
raw_sensplus any estimated placeholder/parameter it names (prediction_sensitivity()).
A per-measurement model takes priority and the two are mutually exclusive, exactly as in
_prediction(); both default off, so a plain job returns the raw observable’s sensitivity unchanged.
- class pybnf.objective.WassersteinObjective(ind_var_rounding=0)[source]¶
The 1-Wasserstein (earth-mover) distance between the simulated and experimental profiles, summed over observables (ADR-0031). Like
klit is a column-joint objective – it compares the shape of a whole column at once, not point by point – but whereklis the multinomial cross-entropy (a likelihood), this is a geometric distance: the minimal total mass-displacement to morph one normalized profile into the other. The two span theprofile_objectivefamily’s ends (statistical vs geometric), which is why the family is an objective, not a model (ADR-0031).Each column is normalized to a probability distribution over its row index, and the 1-Wasserstein distance on the (unit-spaced) index line is
sum_i |CDF_sim_i - CDF_exp_i|– the integral of the absolute CDF gap, which is the closed form of the 1-D earth-mover distance. The configurable support and spacing (placing the profile on real coordinates rather than the index) are the deferredprofile_objectivevalue grammar (ADR-0031); the default here is unit index spacing. A non-positive or negative simulated column cannot be normalized, so it scoresinf(the worst fit), mirroringkl’s degenerate-profile guard. Oracle:scipy.stats.wasserstein_distanceover the index with the normalized columns as weights.- eval_column(sim_data, exp_data, col_name)[source]¶
Calculate the objective function for a single column in the data This evaluation is what differentiates the different column based objective functions. :param sim_data: The simulation Data object :param exp_data: The experimental Data object :param col_name: The column name to look at (same for the sim_data and the exp_data) :return:
- pybnf.objective.build_named_objective(config, token)[source]¶
Build the objective for a modern
objective = <token>key (ADR-0031): the barescorepassthrough, or a legacy token desugared to the per-point engine. A profile-objective token (kl/wasserstein) is redirected to its own key rather than silently desugared, keeping one home per objective.
- pybnf.objective.build_profile_objective(config, token)[source]¶
Build the objective for a modern
profile_objective = <token>key – a column-joint (shape-comparison) objective (ADR-0031). A per-point token is redirected toobjective/noise_model.
- pybnf.objective.build_whole_fit_noise_objective(config)[source]¶
Build the objective for a whole-fit
noise_model = <family>, ...line – the no-observable('noise_model', None)key (ADR-0031). The named per-point noise model becomes the fit-wide default, with per-observablenoise_modellines overriding it.
- pybnf.objective.information_criteria(log_likelihood, k, n)[source]¶
AIC / BIC / AICc from a fit’s maximized log-likelihood (pure arithmetic).
- Parameters:
log_likelihood – the maximized log-likelihood
lnLat the best fit – the sum of the noise model’s complete per-pointlog_density, NOT the (constant-dropped)-scorethe optimizer minimizes.k – number of free (fitted) parameters, INCLUDING any estimated noise parameter – a fitted
sigma/b/ris itself a free parameter (ADR-0021), so counting the declared free parameters already includes it.n – number of scored data points.
- Returns:
an
InformationCriteria.aiccisNonewhenn <= k + 1(the correction2k(k+1)/(n-k-1)has a non-positive denominator there and is conventionally reported as undefined).
AIC = 2k - 2 lnL;BIC = k ln(n) - 2 lnL;AICc = AIC + 2k(k+1)/(n-k-1).
- pybnf.objective.likelihood_information_criteria(objective, sim_data_dict, exp_data_dict, pset, k)[source]¶
Information criteria for
objectivescored atpset, orNone.Returns
None– rather than a misleading number – when the objective is not a per-point likelihood (sos/sod/norm_sos/kl/wasserstein/direct_pass: no normalized density, so no AIC; the same gate LOO/WAIC use), when no point is scored, or when the log-likelihood is not finite. Otherwise the log-likelihood is the sum of the objective’s complete per-pointlog_densityover the scored data (evaluate_pointwise, ADR-0056),nis that point count, andkthe free-parameter count.