Computes pointwise scores for two probabilistic forecasters and compares them sequentially using confidence sequences and, when valid finite-sample bounds are available, e-processes.
Usage
compare_forecasts(
p,
q,
y,
scoring_rule = c("brier", "spherical", "log"),
alpha = 0.05,
cs_type = NULL,
compute_cs = TRUE,
compute_e = TRUE,
v_opt = 10,
boundary = "mixture",
lcb_only = FALSE,
ucb_only = FALSE,
eps = 1e-15,
clip_max = 1e+07
)Arguments
- p
Forecasts from forecaster 1. For binary outcomes, a numeric vector of probabilities for event
y = 1. For categorical outcomes, a numeric matrix whose rows are probability vectors.- q
Forecasts from forecaster 2, in the same format as
p.- y
Outcomes. For binary vector forecasts, a numeric vector in
{0, 1}. For categorical matrix forecasts, integer class labels in{1, ..., K}.- scoring_rule
Character. Scoring rule used to compare forecasts. Currently supports
"brier","spherical", and"log".- alpha
Numeric in
(0, 1). Significance level. Default is0.05.- cs_type
Character or
NULL. Confidence sequence type:"bernstein","hoeffding","asymptotic", or"none". IfNULL, the wrapper uses"bernstein"for bounded scoring rules ("brier"and"spherical") and"asymptotic"for"log".- compute_cs
Logical. If
TRUE, compute a confidence sequence. Default isTRUE.- compute_e
Logical. If
TRUE, compute two one-sided e-processes. Default isTRUE. This is only allowed for bounded score differences under the current wrapper, namely"brier"and"spherical".- v_opt
Numeric > 0. Intrinsic time at which the mixture boundary or e-process is tuned to be tightest. Default is
10.- boundary
Character. Boundary type passed to
cs_hoeffding()orcs_bernstein(). Default is"mixture".- lcb_only
Logical. If
TRUE, compute a lower one-sided empirical Bernstein CS. Only used whencs_type = "bernstein".- ucb_only
Logical. If
TRUE, compute an upper one-sided empirical Bernstein CS. Only used whencs_type = "bernstein".- eps
Numeric. Probability floor passed to
log_score()whenscoring_rule = "log". Default is1e-15.- clip_max
Numeric. Maximum e-process value before clipping. Passed to
eprocess(). Default is1e7.
Value
A data.frame with one row per time point and columns:
tTime index.
score_pPointwise score of forecaster
p.score_qPointwise score of forecaster
q.deltaPointwise score difference,
score_p - score_q.estimateRunning mean score difference. Positive values favour forecaster
p; negative values favour forecasterq.lower,upperConfidence sequence bounds. These are
NAifcompute_cs = FALSEorcs_type = "none".e_pq,e_qpOne-sided e-processes.
e_pqtests whether forecasterpoutperformsq;e_qptests the reverse direction. These areNAifcompute_e = FALSE.
Details
This is a convenience wrapper around brier_score(), spherical_score(),
log_score(), cs_hoeffding(), cs_bernstein(), cs_asymptotic(), and
eprocess(). It is designed for the common workflow where the user has two
forecast streams p and q, an outcome stream y, and wants a single tidy
output object.
All scoring rules in seqcomp are positively oriented: higher scores are
better. Therefore
$$\hat{\delta}_t = S(p_t, y_t) - S(q_t, y_t)$$
is positive when forecaster p performs better than forecaster q at time
t.
For "brier" and "spherical", score differences are bounded in [-1, 1].
The wrapper therefore uses c = 1 for Hoeffding-style confidence sequences
and c = 2 for empirical Bernstein confidence sequences and e-processes.
For "log", score differences are unbounded. The wrapper therefore defaults
to cs_asymptotic() and refuses to compute finite-sample e-processes. For
binary log-score comparisons where the Winkler construction is appropriate,
use winkler_compare() instead.
Interpretation
The confidence sequence estimates the running average score advantage of
p over q. If the whole interval lies above zero, the data favour p;
if the whole interval lies below zero, the data favour q.
The e-processes are evidence processes for one-sided null hypotheses. At
level alpha, the two-sided rejection threshold used by eprocess() is
2 / alpha.
Examples
set.seed(1)
y <- rbinom(200, 1, 0.5)
p <- rep(0.5, 200)
q <- runif(200)
out <- compare_forecasts(p, q, y, scoring_rule = "brier")
tail(out)
#> t score_p score_q delta estimate lower upper
#> 195 195 -0.25 -0.02397884 -0.2260212 0.04786789 -0.05978248 0.1555182
#> 196 196 -0.25 -0.42471022 0.1747102 0.04851504 -0.05862231 0.1556524
#> 197 197 -0.25 -0.43536379 0.1853638 0.04920970 -0.05742572 0.1558451
#> 198 198 -0.25 -0.47365726 0.2236573 0.05009075 -0.05607385 0.1562554
#> 199 199 -0.25 -0.12360386 -0.1263961 0.04920388 -0.05649615 0.1549039
#> 200 200 -0.25 -0.72616694 0.4761669 0.05133870 -0.05423303 0.1569104
#> e_pq e_qp
#> 195 1.047987 2.220446e-16
#> 196 1.096365 2.220446e-16
#> 197 1.150311 2.220446e-16
#> 198 1.218612 2.220446e-16
#> 199 1.174685 2.220446e-16
#> 200 1.315716 2.220446e-16