Skip to content

Commit 61f2773

Browse files
authored
Add relative error option to error calculation methods (#273)
* Add relative error option to error calculation methods
1 parent a9dc5cf commit 61f2773

1 file changed

Lines changed: 122 additions & 7 deletions

File tree

‎ezyrb/reducedordermodel.py‎

Lines changed: 122 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def load(fname):
411411

412412
return rom
413413

414-
def test_error(self, test, norm=np.linalg.norm):
414+
def test_error(self, test, norm=np.linalg.norm, relative=True):
415415
"""
416416
Compute the mean norm of the relative error vectors of predicted
417417
test snapshots.
@@ -420,16 +420,24 @@ def test_error(self, test, norm=np.linalg.norm):
420420
:param function norm: the function used to assign at the vector of
421421
errors a float number. It has to take as input a 'numpy.ndarray'
422422
and returns a float. Default value is the L2 norm.
423+
:param relative: True if the error computed is relative. Default is
424+
True.
423425
:return: the mean L2 norm of the relative errors of the estimated
424426
test snapshots.
425427
:rtype: numpy.ndarray
426428
"""
427429
predicted_test = self.predict(test.parameters_matrix)
428-
return np.mean(
429-
norm(predicted_test - test.snapshots_matrix,
430-
axis=1) / norm(test.snapshots_matrix, axis=1))
430+
if relative:
431+
return np.mean(
432+
norm(predicted_test - test.snapshots_matrix,
433+
axis=1) / norm(test.snapshots_matrix, axis=1))
434+
else:
435+
return np.mean(
436+
norm(predicted_test - test.snapshots_matrix,
437+
axis=1))
431438

432-
def kfold_cv_error(self, n_splits, *args, norm=np.linalg.norm, **kwargs):
439+
def kfold_cv_error(self, n_splits, *args, norm=np.linalg.norm, relative=True,
440+
**kwargs):
433441
r"""
434442
Split the database into k consecutive folds (no shuffling by default).
435443
Each fold is used once as a validation while the k - 1 remaining folds
@@ -441,6 +449,8 @@ def kfold_cv_error(self, n_splits, *args, norm=np.linalg.norm, **kwargs):
441449
:param function norm: function to apply to compute the relative error
442450
between the true snapshot and the predicted one.
443451
Default value is the L2 norm.
452+
:param relative: True if the error computed is relative. Default is
453+
True.
444454
:param \*args: additional parameters to pass to the `fit` method.
445455
:param \**kwargs: additional parameters to pass to the `fit` method.
446456
:return: the vector containing the errors corresponding to each fold.
@@ -455,7 +465,7 @@ def kfold_cv_error(self, n_splits, *args, norm=np.linalg.norm, **kwargs):
455465
plugins=[copy.deepcopy(p) for p in self.plugins]).fit(
456466
*args, **kwargs)
457467

458-
error.append(rom.test_error(self.database[test_index], norm))
468+
error.append(rom.test_error(self.database[test_index], norm, relative))
459469

460470
return np.array(error)
461471

@@ -548,6 +558,111 @@ def _simplex_volume(self, vertices):
548558
return np.abs(
549559
np.linalg.det(distance) / math.factorial(vertices.shape[1]))
550560

561+
def reduction_error(self, db=None, relative=True, eps=1e-12):
562+
"""
563+
Calculate the reconstruction error between the original snapshots and
564+
the ones reconstructed by the ROM.
565+
566+
:param database.Database db: the database to use to compute the error.
567+
If None, the error is computed on the training database.
568+
Default is None.
569+
:param bool relative: True if the error computed is relative. Default is
570+
True.
571+
:param float eps: small number to avoid division by zero in relative
572+
error computation. Default is 1e-12.
573+
:return: the vector containing the reconstruction errors.
574+
575+
Esempio:
576+
>>> from ezyrb import ReducedOrderModel as ROM
577+
>>> from ezyrb import POD, RBF, Database
578+
>>> db = Database(param, snapshots) # param and snapshots are assumed
579+
to be declared
580+
>>> db_train = db[:10] # training database
581+
>>> db_test = db[10:] # test database
582+
>>> pod = POD()
583+
>>> rbf = RBF()
584+
>>> rom = ROM(db_train, pod, rbf)
585+
>>> rom.fit()
586+
>>> err_train_reduct = rom.reconstruction_error(relative=True)
587+
>>> err_test_reduct = rom.reconstruction_error(db_test, relative=True)
588+
"""
589+
590+
errs = []
591+
if db is None:
592+
db = self.database
593+
snap = db.snapshots_matrix
594+
snap_red = self.reduction.transform(snap.T)
595+
snap_full = self.reduction.inverse_transform(snap_red).T
596+
597+
E = snap - snap_full
598+
599+
if relative:
600+
num = np.linalg.norm(E, axis=1)
601+
den = np.linalg.norm(snap, axis=1) + eps
602+
603+
err = float(np.mean(num/den))
604+
else:
605+
err = float(np.mean(np.linalg.norm(E, axis=1)))
606+
errs.append(err)
607+
608+
return np.array(errs)
609+
610+
def approximation_error(self, db=None, relative=True, eps=1e-12):
611+
"""
612+
Calculate the approximation error between the true modal coefficients
613+
and the approximated ones.
614+
615+
:param database.Database db: the database to use to compute the error.
616+
If None, the error is computed on the training database.
617+
Default is None.
618+
:param bool relative: True if the error computed is relative. Default is
619+
True.
620+
:param float eps: small number to avoid division by zero in relative
621+
error computation. Default is 1e-12.
622+
623+
:return: the vector containing the approximation errors.
624+
625+
Esempio:
626+
>>> from ezyrb import ReducedOrderModel as ROM
627+
>>> from ezyrb import POD, RBF, Database
628+
>>> db = Database(param, snapshots) # param and snapshots are assumed
629+
to be declared
630+
>>> db_train = db[:10] # training database
631+
>>> db_test = db[10:] # test database
632+
>>> pod = POD()
633+
>>> rbf = RBF()
634+
>>> rom = ROM(db_train, pod, rbf)
635+
>>> rom.fit()
636+
>>> err_train_approx = rom.approximation_error(relative=True)
637+
>>> err_test_approx = rom.approximation_error(db_test, relative=True)
638+
639+
"""
640+
errs = []
641+
if db is None:
642+
db = self.database
643+
644+
snap = db.snapshots_matrix
645+
params_true = self.reduction.transform(snap.T).T
646+
647+
params = db.parameters_matrix
648+
649+
params_approx = self.approximation.predict(params)
650+
651+
E = params_true - params_approx
652+
653+
if relative:
654+
num = np.linalg.norm(E, axis=1)
655+
den = np.linalg.norm(params_true, axis=1) + eps
656+
657+
err = float(np.mean(num/den))
658+
else:
659+
err = float(np.mean(np.linalg.norm(E, axis=1)))
660+
errs.append(err)
661+
662+
return np.array(errs)
663+
664+
665+
551666
class MultiReducedOrderModel(ReducedOrderModelInterface):
552667
"""
553668
Multiple Reduced Order Model class.
@@ -960,7 +1075,7 @@ def _simplex_volume(self, vertices):
9601075
return np.abs(
9611076
np.linalg.det(distance) / math.factorial(vertices.shape[1]))
9621077

963-
def reconstruction_error(self, db=None, relative=True, eps=1e-12):
1078+
def reduction_error(self, db=None, relative=True, eps=1e-12):
9641079
"""
9651080
Calculate the reconstruction error between the original snapshots and
9661081
the ones reconstructed by the ROM.

0 commit comments

Comments
 (0)