Skip to content

Commit

Permalink
Merge pull request #158 from Srinidhi-Patil/master
Browse files Browse the repository at this point in the history
GMAE Metric
  • Loading branch information
deatinor committed Mar 25, 2020
2 parents d08a80b + bb6964d commit ce9d6b3
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 2 deletions.
4 changes: 3 additions & 1 deletion gtime/metrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
The :mod:`gtime.metrics` module contains a collection of different metrics.
"""

from .metrics import smape, max_error, mse, log_mse, r_square, mae, mape, rmse, rmsle
from .metrics import (smape, max_error, mse, log_mse,
r_square, mae, mape, rmse, rmsle, gmae)

__all__ = [
"smape",
Expand All @@ -14,4 +15,5 @@
"r_square",
"mae",
"mape",
"gmae",
]
39 changes: 38 additions & 1 deletion gtime/metrics/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import numpy as np
import pandas as pd
from scipy.stats import gmean


def _check_input(y_true: np.ndarray, y_pred: np.ndarray) -> None:
Expand Down Expand Up @@ -305,7 +306,8 @@ def mae(
y_true: Union[pd.DataFrame, List, np.ndarray],
y_pred: Union[pd.DataFrame, List, np.ndarray],
) -> float:
"""Compute the Mean Absolute Error(also called, Mean Absolute Deviation(MAD)) between two vectors.
"""Compute the Mean Absolute Error(also called, Mean Absolute Deviation(MAD) or Mean Ratio)
between two vectors.
Parameters
----------
Expand Down Expand Up @@ -371,3 +373,38 @@ def mape(
if np.isnan(mape_value):
raise ValueError("MAPE can not be calculated due to Zero/Zero")
return mape_value * 100


def gmae(
y_true: Union[pd.DataFrame, List, np.ndarray],
y_pred: Union[pd.DataFrame, List, np.ndarray],
) -> float:
"""Compute the Geometric Mean Absolute Error between two vectors.
Parameters
----------
y_true : array-like, shape (length, 1), required
The first vector.
y_pred : array-like, shape (length, 1), required
The second vector.
Returns
-------
gmae_value : float
The geometric mean absolute error between the two vectors.
Examples
--------
>>> from gtime.metrics import gmae
>>> y_true = [0, 1, 2, 3, 6, 5]
>>> y_pred = [-1, 4, 5, 10, 4, 1]
>>> gmae(y_true, y_pred)
2.82
"""
y_true, y_pred = _convert_to_ndarray(y_true, y_pred)
_check_input(y_true, y_pred)

absolute_difference = np.abs(y_pred - y_true)
return 0 if 0 in absolute_difference else gmean(absolute_difference)
82 changes: 82 additions & 0 deletions gtime/metrics/tests/test_loss_functions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np
import pandas as pd
import pytest
from scipy.stats import gmean
from hypothesis import given
from hypothesis.extra.numpy import arrays
from hypothesis.strategies import floats
Expand All @@ -15,6 +16,7 @@
mape,
rmse,
rmsle,
gmae,
)


Expand Down Expand Up @@ -812,3 +814,83 @@ def test_mape_random_arrays_finite_values(self, y_true, y_pred):
print(y_pred)

assert expected_mape == mape_value


class TestGMAE:
def _correct_gmae(self, y_true, y_pred):
y_true = np.array(y_true)
y_pred = np.array(y_pred)

absolute_difference = np.abs(y_true - y_pred)
return 0 if 0 in absolute_difference else gmean(absolute_difference)

def test_wrong_vector_length(self):
y_true = np.random.random(5)
y_pred = np.random.random(4)

with pytest.raises(ValueError):
gmae(y_true, y_pred)

def test_nan_values(self):
y_true = [np.nan, 1, 2, 3]
y_pred = np.random.random(4)

with pytest.raises(ValueError):
gmae(y_true, y_pred)

def test_infinite_values(self):
y_true = np.random.random(4)
y_pred = [0, np.inf, 2, 3]

with pytest.raises(ValueError):
gmae(y_true, y_pred)

def test_gmae_list(self):
y_true = [0, 1, 2, 3, 6, 5]
y_pred = [-1, 4, 5, 10, 4, 1]

gmae_value = np.round(gmae(y_true, y_pred), decimals=2)
expected_gmae = 2.82

assert expected_gmae == gmae_value

def test_gmae_array(self):
y_true = np.array([0, 1, 2, 3, 6, 5])
y_pred = np.array([-1, 4, 5, 10, 4, 1])

gmae_value = np.round(gmae(y_true, y_pred), decimals=2)
expected_gmae = 2.82

assert expected_gmae == gmae_value

def test_gmae_dataframe(self):
y_true = pd.DataFrame([0, 1, 2, 3, 6, 5])
y_pred = pd.DataFrame([-1, 4, 5, 10, 4, 1])

gmae_value = np.round(gmae(y_true, y_pred), decimals=2)
expected_gmae = 2.82

assert expected_gmae == gmae_value

def test_zero_in_difference_gmae(self):
#if absolute difference is zero then GMAE is zero
y_true = pd.DataFrame([0, 1, 2, 3, 4, 5])
y_pred = pd.DataFrame([-1, 4, 5, 10, 4, 1])

gmae_value = np.round(gmae(y_true, y_pred), decimals=2)
expected_gmae = 0

assert expected_gmae == gmae_value

@given(
arrays(float, shape=30, elements=floats(allow_nan=False, allow_infinity=False)),
arrays(float, shape=30, elements=floats(allow_nan=False, allow_infinity=False)),
)
def test_gmae_random_arrays_finite_values(self, y_true, y_pred):
gmae_value = gmae(y_true, y_pred)
expected_gmae = self._correct_gmae(y_true, y_pred)
print(y_true)
print(y_pred)

assert expected_gmae == gmae_value

0 comments on commit ce9d6b3

Please sign in to comment.