1+ import typing as tp
2+
3+ from scoringrules .backend import backends
4+ from scoringrules .core import error_spread
5+
6+ if tp .TYPE_CHECKING :
7+ from scoringrules .core .typing import Array , ArrayLike , Backend
8+
9+
10+ def error_spread_score (
11+ forecasts : "Array" ,
12+ observations : "ArrayLike" ,
13+ / ,
14+ axis : int = - 1 ,
15+ * ,
16+ backend : "Backend" = None ,
17+ ) -> "Array" :
18+ r"""Compute the error-spread score (ESS) for a finite ensemble.
19+
20+ The error spread score [(Christensen et al., 2015)](https://doi.org/10.1002/qj.2375) is given by:
21+
22+ $$ESS = \left(s^2 - e^2 - e \cdot s \cdot g\right)^2$$
23+
24+ where the mean $m$, variance $s^2$, and skewness $g$ of the ensemble forecast of size $F$ are computed as follows:
25+
26+ $$m = \frac{1}{F} \sum_{f=1}^{F} X_f, \quad s^2 = \frac{1}{F-1} \sum_{f=1}^{F} (X_f - m)^2, \quad g = \frac{F}{(F-1)(F-2)} \sum_{f=1}^{F} \left(\frac{X_f - m}{s}\right)^3$$
27+
28+ The error in the ensemble mean $e$ is calculated as $e = m - y$, where $y$ is the observed value.
29+
30+ Parameters
31+ ----------
32+ forecasts: Array
33+ The predicted forecast ensemble, where the ensemble dimension is by default
34+ represented by the last axis.
35+ observations: ArrayLike
36+ The observed values.
37+ axis: int
38+ The axis corresponding to the ensemble. Default is the last axis.
39+ backend: str
40+ The name of the backend used for computations. Defaults to 'numba' if available, else 'numpy'.
41+
42+ Returns
43+ -------
44+ - Array
45+ An array of error spread scores for each ensemble forecast, which should be averaged to get meaningful values.
46+ """
47+ B = backends .active if backend is None else backends [backend ]
48+ forecasts , observations = map (B .asarray , (forecasts , observations ))
49+
50+ if axis != - 1 :
51+ forecasts = B .moveaxis (forecasts , axis , - 1 )
52+
53+ if B .name == "numba" :
54+ return error_spread ._ess_gufunc (forecasts , observations )
55+
56+ return error_spread .ess (forecasts , observations , backend = backend )
57+
58+
59+
60+ # \[
61+ # ESS = \left(s^2 - e^2 - e \cdot s \cdot g\right)^2
62+ # \]
0 commit comments