Skip to content

uncertainty.testing

Probability statements about predictions, robust to the number of draws.

The question "how probable is it that an output satisfies a hypothesis H, given everything that is uncertain?" is answered from the draws of a propagation: the estimate is the fraction of the draws which satisfy H, an estimate of the posterior predictive probability P(H) (Gelman et al. 2013). P(H) is a property of the model and of what is uncertain, not of the number of draws: more draws estimate it more precisely and change nothing else.

Anytime-valid inference. More draws can always be simulated, so a statement must stay valid whenever one looks at it and adds draws (optional stopping). A confidence interval of a fixed number of draws, e.g. the Wilson interval, does not: looked at after every batch, it misses the true probability far more often than its level says. The statements use the confidence sequence of the beta-binomial mixture instead (Robbins 1970; Lai 1976; Howard et al. 2021): with the mixture of the likelihood ratios of the first m draws, M_m(p) = B(a + k_m, b + m - k_m) / B(a, b) / (p^k_m (1 - p)^(m - k_m)) with the Jeffreys mixture a = b = 1/2, a nonnegative martingale of mean 1 under the true probability, the set {p: M_m(p) < 1 / alpha} contains the true probability at every m at once with probability at least 1 - alpha (Ville's inequality, alpha = 1 - level). The sequence is intersected over the numbers of draws, so it is nested: it only shrinks with more draws (should the sets of two numbers of draws exclude each other, which happens with probability at most alpha, it stays the last set which is not empty). Its anytime-valid p-value of a probability p0 is min(1, 1 / max_m M_m(p0)) over the numbers of draws whose estimate is on the side of the alternative, valid for the composite null of that side.

Decisions. A statement with a threshold (at_least=p0) is decided by the p-values at alpha after every number of draws: accepted when P(H) >= p0 is shown, rejected when P(H) < p0 is shown, equivalent when P(H) is shown to be within the margin of the threshold (two one-sided tests, Schuirmann 1987), undecided otherwise, with the number of draws which would decide it at the current estimate (n_needed). More draws only make a statement more precise: an undecided one becomes decided, an equivalence becomes the direction which is shown later, and a direction once shown is kept (the direction shown first, at n_decided draws): a decision is never reversed. Every wrong decision of a statement is an event of the martingale of its true probability, so a statement is wrong with probability at most alpha. The margin is the difference of a probability which does not matter, 0.05 by default; it makes every statement decidable with a bounded number of draws, also one whose probability is the threshold.

Several statements. A TestReport decides m statements at the level of Bonferroni, alpha / m each (and gives their simultaneous intervals at that level), so the probability that any of them is wrong is at most alpha (the mean alpha of statements of other levels, TestReport.family_error), whatever the dependence between them, which share their draws: every statement with a threshold has a true null (both directions at the threshold, one direction and the equivalence elsewhere), so a correct decision of one statement must not relax the level of the others. The decisions of a report are the decisions of single statements at a fixed level, so they are never reversed by more draws either; the conservative level costs draws only, about log(m) times the information per statement, which more draws provide.

The draws which are NaN (failed points) are excluded and counted, infinite values are values. The validity assumes independent draws, which design="random" of a propagation gives; the counts of quasi-random draws fluctuate less, for which the sequence is conservative in practice but not by a theorem. A probability statement is about the predictive distribution, i.e. about the uncertainty of the inputs, not a test of observed data: the draws are not subjects of a study.

Robbins H (1970). Statistical methods related to the law of the iterated logarithm. Ann Math Stat 41:1397-1409. Lai TL (1976). On confidence sequences. Ann Stat 4:265-280. Howard SR, Ramdas A, McAuliffe J, Sekhon J (2021). Time-uniform, nonparametric, nonasymptotic confidence sequences. Ann Stat 49:1055-1080. Schuirmann DJ (1987). A comparison of the two one-sided tests procedure and the power approach for assessing the equivalence of average bioavailability. J Pharmacokinet Biopharm 15:657-680. Gelman A, Carlin JB, Stern HS, Dunson DB, Vehtari A, Rubin DB (2013). Bayesian Data Analysis, 3rd ed. CRC Press.

TestResult dataclass

TestResult(
    hypothesis,
    estimate,
    low,
    high,
    n,
    n_failed,
    k,
    threshold,
    decision,
    n_needed=None,
    n_decided=None,
    level=0.95,
    margin=None,
    p_greater=nan,
    p_less=nan,
    p_equivalent=nan,
    satisfied=None,
    method="fraction of the draws, beta-binomial confidence sequence",
    references=REFERENCES,
)

A probability statement about a prediction, see the module.

Attributes:

Name Type Description
hypothesis str

the hypothesis in words.

estimate float

the fraction of the draws which satisfy it.

low float

the lower end of the confidence sequence.

high float

the upper end of the confidence sequence.

n int

the number of draws which are not NaN.

n_failed int

the number of draws which are NaN.

k int

the number of draws which satisfy the hypothesis.

threshold float | None

the probability of the decision, None for an estimate.

decision Decision

accepted, rejected, equivalent, undecided or estimate.

n_needed int | None

the draws an undecided statement needs at its estimate, None otherwise.

n_decided int | None

the number of draws at which the decision was first shown, None for an undecided statement.

level float

the level of the confidence sequence and of the decisions.

margin float | None

the margin of the threshold of an equivalence, None for an estimate.

p_greater float

the anytime-valid p-value of P >= threshold.

p_less float

the anytime-valid p-value of P < threshold.

p_equivalent float

the anytime-valid p-value of the equivalence.

satisfied ndarray | None

whether every draw satisfies the hypothesis, in the order of the draws, which a statement at another level needs.

method str

the method.

references tuple[str, ...]

the references of the method.

p_value

p_value()

Get the p-value of the decision, the smallest one of an undecided statement.

nan for an estimate.

at_level

at_level(level)

Get the statement at another level, e.g. of a TestReport.

Raises:

Type Description
ValueError

for a statement without its draws.

Hypothesis dataclass

Hypothesis(
    output,
    greater=None,
    less=None,
    between=None,
    at_least=None,
    scenario=None,
    contrast=None,
    kind="ratio",
    margin=MARGIN,
    level=0.95,
)

A hypothesis about an output of a propagation, which it can draw until decided.

Attributes:

Name Type Description
output str

the output, one value per draw, e.g. pk.auc_last.

greater Any

the hypothesis output > greater.

less Any

the hypothesis output < less.

between tuple[Any, Any] | None

the hypothesis low <= output <= high.

at_least float | None

the threshold of the decision, None for an estimate.

scenario str | None

the scenario of the output, the only one by default.

contrast tuple[str, str] | None

the scenarios (a, b) of a paired contrast of the output instead of a scenario.

kind Literal['ratio', 'difference']

the kind of the contrast, ratio or difference.

margin float

the margin of the threshold of an equivalence, see probability.

level float

the level of the decision.

evaluate

evaluate(values, level=None)

Get the statement of the hypothesis about the values of its output.

Parameters:

Name Type Description Default
values DataArray

the values of its output.

required
level float | None

the level of the statement, the one of the hypothesis by default, e.g. family_level of a report.

None

to_dict

to_dict()

Get the hypothesis as a dictionary of JSON types.

TestReport dataclass

TestReport(tests=list(), adjust='bonferroni')

Probability statements with their decisions adjusted for multiplicity.

Attributes:

Name Type Description
tests Sequence[TestResult]

the statements.

adjust Literal['bonferroni', 'none']

bonferroni (the family-wise error of the decisions, see the module) or none.

m property

m

Get the number of statements with a threshold, the family of the decisions.

family_error property

family_error

Get the bound of the probability that any decision is wrong.

The mean alpha of the statements with a threshold, each decided at its own alpha / m; the alpha of the statement without adjustment.

adjusted

adjusted()

Get the statements at the level of Bonferroni, see the module.

table

table()

Get the table of the statements with their adjusted decisions.

The interval, the decision and the draws are the ones of the adjusted level, p_adjusted is the p-value of the decision times m.

confidence_sequence

confidence_sequence(satisfied, level=0.95)

Get the confidence sequence of a probability after the draws, see the module.

Parameters:

Name Type Description Default
satisfied ArrayLike

whether every draw satisfies the hypothesis, in the order of the draws.

required
level float

the level of the sequence, its coverage at every number of draws at once.

0.95

Returns:

Type Description
float

The lower and the upper end, the intersection of the confidence sets

float

of every number of draws; (0, 1) without draws.

probability

probability(
    values,
    *,
    greater=None,
    less=None,
    between=None,
    at_least=None,
    margin=MARGIN,
    level=0.95,
)

Get the probability that values satisfy a hypothesis, see the module.

Parameters:

Name Type Description Default
values DataArray

the draws of an output in their order, one value per draw, with its unit in attrs["units"].

required
greater Any

the hypothesis values > greater.

None
less Any

the hypothesis values < less.

None
between tuple[Any, Any] | None

the hypothesis low <= values <= high.

None
at_least float | None

the threshold of a decision.

None
margin float

the margin of the threshold of an equivalence, in [0, 0.5).

MARGIN
level float

the level of the confidence sequence and of the decision.

0.95

Returns:

Type Description
TestResult

The statement.

Raises:

Type Description
ValueError

unless exactly one hypothesis is given, for values which are not one value per draw, a threshold outside (0, 1), a margin outside [0, 0.5), bounds whose units do not fit, or no draw.

family_level

family_level(level, m, adjust='bonferroni')

Get the level of a statement with a threshold in a report of m of them.