fit.identifiability¶
Parameter identifiability by profile likelihood.
A fit gives the parameters which describe the data best. Identifiability asks how well the data determines every one of them: a parameter is identifiable if the data constrains it to a finite interval, and non-identifiable if it can be changed without the model describing the data worse.
The profile likelihood answers this by scanning every parameter around the optimum. The scanned parameter is fixed at a value and all other parameters are optimized again, so the profile is the best cost the model reaches with the parameter at that value (Raue et al. 2009):
PL(θi) = min over θj≠i of cost(θ)
The cost of sbmlsim is the cost of scipy.optimize.least_squares, i.e., half
the sum of the squared weighted residuals, cost = 0.5 * Σ r². With residuals
which are standardized by the errors of the data, 2 * cost is the negative
log-likelihood up to a constant, and the profile is compared with the threshold
of the likelihood ratio test (Raue et al. 2009, Kreutz et al. 2013):
cost_threshold = cost_min + chi2.ppf(alpha, df) / 2
with df = 1 for the pointwise confidence intervals of single parameters, i.e.,
a threshold of 1.92 above the minimal cost at 95% confidence, and
df = #parameters for simultaneous intervals. The values of a parameter at
which the profile crosses the threshold are the bounds of its confidence
interval. The intervals are invariant under a transformation of the parameters
and may be asymmetric, which is where the intervals of the Fisher information
matrix fail for the non-linear models of systems biology (Wieland et al. 2021).
The shape of the profile classifies the parameter (Raue et al. 2009):
- identifiable: the profile crosses the threshold on both sides of the optimum, the confidence interval is finite,
- practically non-identifiable: the profile has a minimum but stays below the threshold on one or both sides, i.e., up to the bound of the parameter. The data does not determine the parameter towards small and/or large values,
- structurally non-identifiable: the profile is flat over the whole scanned range, the parameter is compensated by the other parameters and the data carries no information about it.
The scans run in logarithmic parameter space, as the optimization does. The
step along a profile is adaptive (Schälte et al. 2023): a step which raises the
cost by more than a fraction of the threshold is halved and repeated, a step
which raises it by little is enlarged, so the profile is resolved where it
changes. The other parameters start from the previous point of the profile
(Simpson & Maclaren 2023) and their paths are stored, so a parameter which is
coupled to the scanned one is seen in its path (Maiwald et al. 2016). A scan
stops when the profile crosses the threshold, at the bound of the parameter or
after max_points; a bound which is reached below the threshold is an open
interval (Borisov & Metelkin 2020). A scan which finds a lower cost than the
optimum reports it: the fit did not converge, and the threshold is taken
relative to the lowest cost of all profiles.
The scans are independent, so they run in the worker pool of the fit runner,
two scans per parameter. A parallel analysis needs the same
if __name__ == "__main__": guard as a parallel fit.
References
Raue A, Kreutz C, Maiwald T, Bachmann J, Schilling M, Klingmüller U, Timmer J. Structural and practical identifiability analysis of partially observed dynamical models by exploiting the profile likelihood. Bioinformatics. 2009;25(15):1923-1929. doi:10.1093/bioinformatics/btp358
Kreutz C, Raue A, Kaschek D, Timmer J. Profile likelihood in systems biology. FEBS J. 2013;280(11):2564-2571. doi:10.1111/febs.12276
Maiwald T, Hass H, Steiert B, Vanlier J, Engesser R, Raue A, Kipkeew F, Bock HH, Kaschek D, Kreutz C, Timmer J. Driving the model to its limit: profile likelihood based model reduction. PLoS ONE. 2016;11(9):e0162366. doi:10.1371/journal.pone.0162366
Wieland FG, Hauber AL, Rosenblatt M, Tönsing C, Timmer J. On structural and practical identifiability. Curr Opin Syst Biol. 2021;25:60-69. doi:10.1016/j.coisb.2021.03.005
Borisov I, Metelkin E. Confidence intervals by constrained optimization, an algorithm and software package for practical identifiability analysis in systems biology. PLoS Comput Biol. 2020;16(12):e1008495. doi:10.1371/journal.pcbi.1008495
Simpson MJ, Maclaren OJ. Profile-wise analysis: a profile likelihood-based workflow for identifiability analysis, estimation, and prediction with mechanistic mathematical models. PLoS Comput Biol. 2023;19(9):e1011515. doi:10.1371/journal.pcbi.1011515
Schälte Y, Fröhlich F, Jost PJ, Vanhoefer J, Pathirana D, Stapor P, Lakrisenko P, Wang D, Raimúndez E, Merkt S, Schmiester L, Städter P, Grein S, Dudkin E, Doresic D, Weindl D, Hasenauer J. pyPESTO: a modular and scalable tool for parameter estimation for dynamic models. Bioinformatics. 2023;39(11):btad711. doi:10.1093/bioinformatics/btad711
Identifiability
¶
Bases: StrEnum
Identifiability of a parameter, read from the shape of its profile.
The classification follows Raue et al. 2009: a parameter is identifiable if its profile crosses the threshold on both sides of the optimum, practically non-identifiable if the profile stays below the threshold up to a bound of the parameter, on one or both sides, and structurally non-identifiable if the profile is flat on both sides.
ProfileSettings
dataclass
¶
ProfileSettings(
alpha=0.95,
degrees_of_freedom=1,
initial_step=0.1,
min_step=0.01,
max_step=1.0,
step_factor=2.0,
max_cost_fraction=0.2,
max_points=50,
flatness=0.05,
reoptimize=True,
optimizer_kwargs=(lambda: {"diff_step": 0.05})(),
)
Settings of a profile likelihood analysis.
The steps are in logarithmic parameter space, i.e., in decades of the parameter, because the scans run in the space the optimization runs in.
Attributes:
| Name | Type | Description |
|---|---|---|
alpha |
float
|
confidence level of the intervals. |
degrees_of_freedom |
int
|
degrees of freedom of the chi-square threshold,
|
initial_step |
float
|
first step of a scan in decades of the parameter. |
min_step |
float
|
smallest step in decades, a step is not halved below it. |
max_step |
float
|
largest step in decades. |
step_factor |
float
|
factor a step is reduced or enlarged by. |
max_cost_fraction |
float
|
largest increase of the cost a single step may
cause, as a fraction of the distance between the minimal cost and
the threshold. A step with a larger increase is reduced and
repeated, so a profile has at least |
max_points |
int
|
largest number of points of a scan in one direction. |
flatness |
float
|
a profile which rises by less than this fraction of the distance between the minimal cost and the threshold, on both sides, is flat, i.e., the parameter is structurally non-identifiable. |
reoptimize |
bool
|
optimize the other parameters at every point of a scan, which is the profile likelihood. Without it the other parameters stay at the optimum, which is a plain scan of the cost and a lower bound of the profile: it is faster and finds the non-identifiable parameters, but its intervals are too narrow for coupled parameters. |
optimizer_kwargs |
Mapping[str, Any]
|
arguments of |
delta
property
¶
Get the chi-square quantile of the confidence level.
This is the threshold on -2 log L, i.e., on twice the cost.
threshold
¶
Get the threshold on the cost for a minimal cost.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cost
|
float
|
minimal cost. |
required |
Returns:
| Type | Description |
|---|---|
float
|
The cost at which the profile crosses the confidence level, |
float
|
|
from_dict
staticmethod
¶
Create settings from a dictionary, i.e., from the stored JSON.
ParameterProfile
dataclass
¶
ParameterProfile(
pid,
values,
costs,
paths,
converged,
index_optimum,
ci_lower=None,
ci_upper=None,
identifiability=None,
)
Profile likelihood of a single parameter.
The points are sorted by the value of the parameter, the optimum is one of them. Every point carries the full parameter vector the cost was reached with, so the paths of the other parameters along the profile are known.
Attributes:
| Name | Type | Description |
|---|---|---|
pid |
str
|
id of the profiled parameter. |
values |
ndarray
|
values of the parameter at the points, ascending. |
costs |
ndarray
|
cost at every point. |
paths |
ndarray
|
values of all parameters at every point, one row per point in the order of the parameters of the problem. |
converged |
ndarray
|
whether the optimization of the other parameters converged at every point. |
index_optimum |
int
|
index of the optimum in the points. |
ci_lower |
float | None
|
lower bound of the confidence interval, |
ci_upper |
float | None
|
upper bound of the confidence interval, |
identifiability |
Identifiability | None
|
classification of the parameter, set by |
side
¶
Get the points on one side of the optimum, from the optimum outward.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
direction
|
int
|
|
required |
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray]
|
The values and the costs, the optimum first. |
crossing
¶
Get the value at which the profile crosses the threshold.
The crossing is interpolated between the last point below and the first point above the threshold, in logarithmic space where the two values are positive, i.e. where the scan ran on a logarithmic scale, and linearly otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
float
|
threshold on the cost. |
required |
direction
|
int
|
|
required |
Returns:
| Type | Description |
|---|---|
float | None
|
The value of the parameter at the crossing, |
float | None
|
does not reach the threshold on that side. |
rise
¶
Get how far the profile rises above its minimum on one side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
direction
|
int
|
|
required |
Returns:
| Type | Description |
|---|---|
float
|
The largest cost on the side minus the lowest cost of the profile. |
evaluate
¶
Set the confidence interval and the classification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
float
|
threshold on the cost of the confidence intervals. |
required |
flatness_cost
|
float
|
rise of the cost below which a side is flat. |
required |
from_dict
staticmethod
¶
Create a profile from a dictionary, i.e., from the stored JSON.
IdentifiabilityResult
dataclass
¶
IdentifiabilityResult(
opid,
parameter_set,
parameters,
settings,
fit_settings,
cost,
profiles,
duration=0.0,
)
Result of a profile likelihood analysis.
Attributes:
| Name | Type | Description |
|---|---|---|
opid |
str
|
id of the optimization problem. |
parameter_set |
ParameterSet
|
parameters the profiles were computed around. |
parameters |
list[FitParameter]
|
fit parameters of the problem, with their bounds and units. |
settings |
ProfileSettings
|
settings of the analysis. |
fit_settings |
FitSettings
|
settings of the fit, which define the cost. |
cost |
float
|
cost of the parameter set. |
profiles |
dict[str, ParameterProfile]
|
profile of every analysed parameter by parameter id. |
duration |
float
|
duration of the analysis in seconds. |
better_optimum
property
¶
Check whether a profile found a lower cost than the parameter set.
The threshold is relative to the lowest cost, so the intervals are still valid, but the fit did not converge to the optimum.
parameter
¶
Get the fit parameter of an id.
Raises:
| Type | Description |
|---|---|
KeyError
|
if the problem has no parameter with the id. |
summary_df
¶
Get the table of the analysis, one row per profiled parameter.
Returns:
| Type | Description |
|---|---|
DataFrame
|
Table with the parameter, its value, unit and bounds, the |
DataFrame
|
confidence interval ( |
DataFrame
|
the number of points of the profile and its lowest cost. |
report
¶
Get the text report of the analysis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path | None
|
file to write the report to. |
None
|
print_output
|
bool
|
print the report. |
False
|
Returns:
| Type | Description |
|---|---|
str
|
The report. |
from_dict
staticmethod
¶
Create a result from a dictionary, i.e., from the stored JSON.
to_json
¶
Store the result as JSON.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path | None
|
file to write, the JSON string is returned if it is |
None
|
Returns:
| Type | Description |
|---|---|
str | Path
|
The path or the JSON string. |
from_json
staticmethod
¶
Load a result from a JSON file or string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
json_info
|
str | Path
|
path of the file or the JSON string. |
required |
Returns:
| Type | Description |
|---|---|
IdentifiabilityResult
|
The result. |
cost_threshold
¶
Get the threshold on the cost of a likelihood ratio test.
The cost is 0.5 * Σ r², so the threshold is half the chi-square quantile
above the minimal cost; at 95% and one degree of freedom it is 1.92.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cost
|
float
|
minimal cost. |
required |
alpha
|
float
|
confidence level. |
0.95
|
df
|
int
|
degrees of freedom. |
1
|
Returns:
| Type | Description |
|---|---|
float
|
The threshold on the cost. |
profile_likelihood
¶
profile_likelihood(
problem,
settings,
parameter_set,
profile_settings=None,
pids=None,
n_cores=1,
serial=False,
show_progress=True,
)
Analyse the identifiability of the parameters of a fit.
Computes the profile likelihood of every parameter around the parameter set and classifies the parameters, see the module documentation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
problem
|
OptimizationProblem
|
optimization problem, initialized with the settings. |
required |
settings
|
FitSettings
|
settings of the fit, which define the cost. |
required |
parameter_set
|
ParameterSet
|
optimal parameters, e.g., the best run of a fit. |
required |
profile_settings
|
ProfileSettings | None
|
settings of the analysis, the defaults if |
None
|
pids
|
Sequence[str] | None
|
parameters to profile, all parameters of the problem by default. |
None
|
n_cores
|
int
|
number of worker processes, the scans of the parameters run
in parallel. A parallel analysis needs the
|
1
|
serial
|
bool
|
run the scans in this process, whatever |
False
|
show_progress
|
bool
|
show the progress of the scans on the console. |
True
|
Returns:
| Type | Description |
|---|---|
IdentifiabilityResult
|
The profiles with the confidence intervals and the classification. |
Raises:
| Type | Description |
|---|---|
KeyError
|
if a parameter id is not a parameter of the problem. |
ValueError
|
if the parameter set is outside of the bounds of the problem. |
plot_profiles
¶
Plot the profiles of all parameters, one panel per parameter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
IdentifiabilityResult
|
result of the analysis. |
required |
path
|
Path | None
|
file to save the figure to, the figure is returned otherwise. |
None
|
ncols
|
int
|
number of panels per row. |
3
|
Returns:
| Type | Description |
|---|---|
Any
|
The figure. |
plot_profile
¶
Plot the profile of a parameter with the paths of the other parameters.
The upper panel is the profile, the lower panel the other parameters along it, relative to their values at the optimum. A parameter which changes along the profile is coupled to the scanned one (Maiwald et al. 2016).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
IdentifiabilityResult
|
result of the analysis. |
required |
pid
|
str
|
id of the parameter. |
required |
path
|
Path | None
|
file to save the figure to, the figure is returned otherwise. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
The figure. |
plot_all
¶
Write the overview figure and the figure of every profile.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
IdentifiabilityResult
|
result of the analysis. |
required |
output_dir
|
Path
|
directory of the figures. |
required |
image_format
|
str
|
format of the figures. |
'svg'
|
Returns:
| Type | Description |
|---|---|
list[Path]
|
The paths of the figures, the overview first. |