Skip to content

Commit c81f90f

Browse files
committed
Add normalized MSE sccore
1 parent 21bc18b commit c81f90f

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

pysteps/tests/test_detcontscores.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
(fct_data, obs_data, ('MAE'), None, None, [5.55]),
3737
# Mean Square Error
3838
(fct_data, obs_data, ('MSE'), None, None, [64.15]),
39+
# Normalized Mean Square Error
40+
(fct_data, obs_data, ('NMSE'), None, None, [0.113711]),
3941
# Root Mean Square Error
4042
(fct_data, obs_data, ('RMSE'), None, None, [8.009370]),
4143
# Beta

pysteps/verification/detcontscores.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ def det_cont_fct(pred, obs, scores="", axis=None, conditioning=None, thr=0.0):
5454
+------------+--------------------------------------------------------+
5555
| MSE | mean squared error |
5656
+------------+--------------------------------------------------------+
57+
| NMSE | normalized mean squared error |
58+
+------------+--------------------------------------------------------+
5759
| RMSE | root mean squared error |
5860
+------------+--------------------------------------------------------+
5961
| RV | reduction of variance |
@@ -94,14 +96,16 @@ def det_cont_fct(pred, obs, scores="", axis=None, conditioning=None, thr=0.0):
9496
9597
Multiplicative scores can be computed by passing log-tranformed values.
9698
Note that "scatter" is the only score that will be computed in dB units of
97-
the multiplicative error, i.e.: 10log10(pred/obs).
99+
the multiplicative error, i.e.: 10*log10(pred/obs).
100+
101+
The normalized MSE is computed as NMSE = E[(pred - obs)^2]/E[(pred + obs)^2].
98102
99-
The debiased RMSE is computed as DRMSE = sqrt(RMSE - ME^2)
103+
The debiased RMSE is computed as DRMSE = sqrt(RMSE - ME^2).
100104
101-
The reduction of variance score is computed as RV = 1 - MSE/Var(obs)
105+
The reduction of variance score is computed as RV = 1 - MSE/Var(obs).
102106
103107
Score names denoted by * can only be computed offline, meaning that the
104-
these cannot be update using _init, _accum and _compute methods of this
108+
these cannot be computed using _init, _accum and _compute methods of this
105109
module.
106110
107111
@@ -229,6 +233,7 @@ def det_cont_fct_init(axis=None, conditioning=None, thr=0.0):
229233
230234
out : dict
231235
The verification error object.
236+
232237
"""
233238

234239
err = {}
@@ -252,6 +257,7 @@ def get_iterable(x):
252257
err["mpred"] = None
253258
err["me"] = None
254259
err["mse"] = None
260+
err["mss"] = None # mean square sum, i.e. E[(pred + obs)^2]
255261
err["mae"] = None
256262
err["n"] = None
257263

@@ -314,6 +320,7 @@ def det_cont_fct_accum(err, pred, obs):
314320
err["mpred"] = np.zeros(nshape)
315321
err["me"] = np.zeros(nshape)
316322
err["mse"] = np.zeros(nshape)
323+
err["mss"] = np.zeros(nshape)
317324
err["mae"] = np.zeros(nshape)
318325
err["n"] = np.zeros(nshape)
319326

@@ -345,13 +352,15 @@ def det_cont_fct_accum(err, pred, obs):
345352

346353
# compute residuals
347354
res = pred - obs
355+
sum = pred + obs
348356
n = np.sum(np.isfinite(res), axis=axis)
349357

350358
# new means
351359
mobs = np.nanmean(obs, axis=axis)
352360
mpred = np.nanmean(pred, axis=axis)
353361
me = np.nanmean(res, axis=axis)
354362
mse = np.nanmean(res ** 2, axis=axis)
363+
mss = np.nanmean(sum ** 2, axis=axis)
355364
mae = np.nanmean(np.abs(res), axis=axis)
356365

357366
# expand axes for broadcasting
@@ -381,6 +390,7 @@ def det_cont_fct_accum(err, pred, obs):
381390
_parallel_mean(err["mpred"], err["n"], mpred, n)
382391
_parallel_mean(err["me"], err["n"], me, n)
383392
_parallel_mean(err["mse"], err["n"], mse, n)
393+
_parallel_mean(err["mss"], err["n"], mss, n)
384394
_parallel_mean(err["mae"], err["n"], mae, n)
385395

386396
# update number of samples
@@ -423,6 +433,8 @@ def det_cont_fct_compute(err, scores=""):
423433
+------------+--------------------------------------------------------+
424434
| MSE | mean squared error |
425435
+------------+--------------------------------------------------------+
436+
| NMSE | normalized mean squared error |
437+
+------------+--------------------------------------------------------+
426438
| RMSE | root mean squared error |
427439
+------------+--------------------------------------------------------+
428440
| RV | reduction of variance |
@@ -469,6 +481,11 @@ def get_iterable(x):
469481
MSE = err["mse"]
470482
result["MSE"] = MSE
471483

484+
# normalized mean squared error
485+
if score_ in ["nmse", ""]:
486+
NMSE = err["mse"] / err["mss"]
487+
result["NMSE"] = NMSE
488+
472489
# root mean squared error
473490
if score_ in ["rmse", ""]:
474491
RMSE = np.sqrt(err["mse"])

pysteps/verification/interface.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ def get_method(name, type="deterministic"):
6767
+------------+--------------------------------------------------------+
6868
| MSE | mean squared error |
6969
+------------+--------------------------------------------------------+
70+
| NMSE | normalized mean squared error |
71+
+------------+--------------------------------------------------------+
7072
| RMSE | root mean squared error |
7173
+------------+--------------------------------------------------------+
7274
| RV | reduction of variance |
@@ -178,10 +180,11 @@ def f(fct, obs, **kwargs):
178180
"beta",
179181
"corr_p",
180182
"corr_s",
183+
"drmse",
181184
"mae",
182185
"mse",
183186
"me",
184-
"drmse",
187+
"nrmse",
185188
"rmse",
186189
"rv",
187190
"scatter",

0 commit comments

Comments
 (0)