7
7
8
8
9
9
def _brier_score_ndarray (forecast , observations ):
10
- """ Computes the brier score
10
+ """ Computes the brier (binary) score for spatial-magnitude cells
11
+ using the formula:
12
+
13
+ Q(Lambda, Sigma) = 1/N sum_{i=1}^N (Lambda_i - Ind(Sigma_i > 0 ))^2
14
+
15
+ where Lambda is the forecast array, Sigma is the observed catalog, N the
16
+ number of spatial-magnitude cells and Ind is the indicator function, which
17
+ is 1 if Sigma_i > 0 and 0 otherwise.
18
+
19
+ Args:
20
+ forecast: 2d array of forecasted rates
21
+ observations: 2d array of observed counts
22
+ Returns
23
+ brier: float, brier score
11
24
"""
25
+
12
26
prob_success = 1 - poisson .cdf (0 , forecast )
13
27
brier_cell = np .square (prob_success .ravel () - (observations .ravel () > 0 ))
14
28
brier = - 2 * brier_cell .sum ()
@@ -19,6 +33,18 @@ def _brier_score_ndarray(forecast, observations):
19
33
20
34
21
35
def _simulate_catalog (sim_cells , sampling_weights , random_numbers = None ):
36
+ """
37
+ Simulates a catalog by sampling from the sampling_weights array.
38
+ Identical to binomial_evaluations._simulate_catalog
39
+
40
+ Args:
41
+ sim_cells:
42
+ sampling_weights:
43
+ random_numbers:
44
+
45
+ Returns:
46
+
47
+ """
22
48
sim_fore = numpy .zeros (sampling_weights .shape )
23
49
24
50
if random_numbers is None :
@@ -46,10 +72,19 @@ def _simulate_catalog(sim_cells, sampling_weights, random_numbers=None):
46
72
47
73
def _brier_score_test (forecast_data , observed_data , num_simulations = 1000 ,
48
74
random_numbers = None , seed = None , verbose = True ):
49
- """ Computes binary conditional-likelihood test from CSEP using an
50
- efficient simulation based approach.
75
+ """ Computes the Brier consistency test conditional on the total observed
76
+ number of events
51
77
52
78
Args:
79
+ forecast_data: 2d array of forecasted rates for spatial_magnitude cells
80
+ observed_data: 2d array of a catalog resampled to spatial_magnitude
81
+ cells
82
+ num_simulations: number of synthetic catalog simulations
83
+ random_numbers: numpy array of random numbers to use for simulation
84
+ seed: seed for random number generator
85
+ verbose: print status updates
86
+
87
+
53
88
54
89
"""
55
90
# Array-masking that avoids log singularities:
@@ -58,8 +93,6 @@ def _brier_score_test(forecast_data, observed_data, num_simulations=1000,
58
93
# set seed for the likelihood test
59
94
if seed is not None :
60
95
numpy .random .seed (seed )
61
- import time
62
- start = time .process_time ()
63
96
64
97
# used to determine where simulated earthquake should
65
98
# be placed, by definition of cumsum these are sorted
@@ -93,7 +126,6 @@ def _brier_score_test(forecast_data, observed_data, num_simulations=1000,
93
126
print (f'... { idx + 1 } catalogs simulated.' )
94
127
95
128
obs_brier = _brier_score_ndarray (forecast_data .data , observed_data )
96
-
97
129
# quantile score
98
130
qs = numpy .sum (simulated_brier <= obs_brier ) / num_simulations
99
131
@@ -107,13 +139,11 @@ def brier_score_test(gridded_forecast,
107
139
seed = None ,
108
140
random_numbers = None ,
109
141
verbose = False ):
110
- """ Performs the Brier conditional test on Gridded Forecast using an
111
- Observed Catalog.
112
- Normalizes the forecast so the forecasted rate are consistent with the
113
- observations. This modification
114
- eliminates the strong impact differences in the number distribution
115
- have on the forecasted rates.
116
-
142
+ """
143
+ Performs the Brier conditional test on a Gridded Forecast using an
144
+ Observed Catalog. Normalizes the forecast so the forecasted rate are
145
+ consistent with the observations. This modification eliminates the strong
146
+ impact differences in the number distribution have on the forecasted rates.
117
147
"""
118
148
119
149
# grid catalog onto spatial grid
0 commit comments