"""
.. versionadded:: 0.7
Implemented functions:
* **Mean absolute error** (MAE, also known as MAD - mean absolute deviation)
:math:`\\textrm{MAE}=\\frac{1}{n} \sum _{i=1}^{n}(e_{i})`.
* **Mean squared error** (MSE, also known as MSD)
:math:`\\textrm{MSE}=\\frac{1}{n} \sum _{i=1}^{n}(e_{i})^{2}`.
* **Root-mean-square error** (RMSE, also known as RMSD)
:math:`\\textrm{RMSE} = \\sqrt{\\textrm{MSE}}`.
* **Logarithmic squared error** (returns a vector of values in dB!)
:math:`\\textbf{logSE} = 10 \log_{10} (\\textbf{e}^{2})`
all functions are often used for evaluation of an error rather than just
the error itself or its mean value.
Usage instructions
====================
For MAE evaluation from two time series use
.. code-block:: python
mse = pa.misc.MAE(x1, x2)
If you have the error already calculated, then just
.. code-block:: python
mse = pa.misc.MAE(e)
The same instructions apply for the MSE, RMSE a logarithmic squared error
.. code-block:: python
mse = pa.misc.MSE(x1, x2)
rmse = pa.misc.RMSE(x1, x2)
logse = pa.misc.logSE(x1, x2)
and from error
.. code-block:: python
mse = pa.misc.MSE(e)
rmse = pa.misc.RMSE(e)
logse = pa.misc.logSE(e)
Minimal working examples
==========================
In the following example is estimated MSE for two series
(:code:`x1` and :code:`x1`):
.. code-block:: python
import numpy as np
import padasip as pa
x1 = np.array([1, 2, 3, 4, 5])
x2 = np.array([5, 4, 3, 2, 1])
mse = pa.misc.MSE(x1, x2)
print(mse)
You can easily check that the printed result :code:`8.0` is correct MSE for
given series.
The following example displays, that you can use directly the error series
:code:`e` if you already have it.
.. code-block:: python
import numpy as np
import padasip as pa
# somewhere else in your project
x1 = np.array([1, 2, 3, 4, 5])
x2 = np.array([5, 4, 3, 2, 1])
e = x1 - x2
# you have just the error - e
mse = pa.misc.MSE(e)
print(mse)
Again, you can check the correctness of the answer easily.
Code Explanation
====================
"""
import numpy as np
[docs]def get_valid_error(x1, x2=-1):
"""
Function that validates:
* x1 is possible to convert to numpy array
* x2 is possible to convert to numpy array (if exists)
* x1 and x2 have the same length (if both exist)
"""
# just error
if isinstance(x2, int) and x2 == -1:
try:
e = np.array(x1)
except:
raise ValueError('Impossible to convert series to a numpy array')
# two series
else:
try:
x1 = np.array(x1)
x2 = np.array(x2)
except:
raise ValueError('Impossible to convert one of series to a numpy array')
if not len(x1) == len(x2):
raise ValueError('The length of both series must agree.')
e = x1 - x2
return e
[docs]def logSE(x1, x2=-1):
"""
10 * log10(e**2)
This function accepts two series of data or directly
one series with error.
**Args:**
* `x1` - first data series or error (1d array)
**Kwargs:**
* `x2` - second series (1d array) if first series was not error directly,
then this should be the second series
**Returns:**
* `e` - logSE of error (1d array) obtained directly from `x1`,
or as a difference of `x1` and `x2`. The values are in dB!
"""
e = get_valid_error(x1, x2)
return 10*np.log10(e**2)
[docs]def MAE(x1, x2=-1):
"""
Mean absolute error - this function accepts two series of data or directly
one series with error.
**Args:**
* `x1` - first data series or error (1d array)
**Kwargs:**
* `x2` - second series (1d array) if first series was not error directly,
then this should be the second series
**Returns:**
* `e` - MAE of error (float) obtained directly from `x1`,
or as a difference of `x1` and `x2`
"""
e = get_valid_error(x1, x2)
return np.sum(np.abs(e)) / float(len(e))
[docs]def MSE(x1, x2=-1):
"""
Mean squared error - this function accepts two series of data or directly
one series with error.
**Args:**
* `x1` - first data series or error (1d array)
**Kwargs:**
* `x2` - second series (1d array) if first series was not error directly,
then this should be the second series
**Returns:**
* `e` - MSE of error (float) obtained directly from `x1`,
or as a difference of `x1` and `x2`
"""
e = get_valid_error(x1, x2)
return np.dot(e, e) / float(len(e))
[docs]def RMSE(x1, x2=-1):
"""
Root-mean-square error - this function accepts two series of data
or directly one series with error.
**Args:**
* `x1` - first data series or error (1d array)
**Kwargs:**
* `x2` - second series (1d array) if first series was not error directly,
then this should be the second series
**Returns:**
* `e` - RMSE of error (float) obtained directly from `x1`,
or as a difference of `x1` and `x2`
"""
e = get_valid_error(x1, x2)
return np.sqrt(np.dot(e, e) / float(len(e)))
[docs]def get_mean_error(x1, x2=-1, function="MSE"):
"""
This function returns desired mean error. Options are: MSE, MAE, RMSE
**Args:**
* `x1` - first data series or error (1d array)
**Kwargs:**
* `x2` - second series (1d array) if first series was not error directly,
then this should be the second series
**Returns:**
* `e` - mean error value (float) obtained directly from `x1`,
or as a difference of `x1` and `x2`
"""
if function == "MSE":
return MSE(x1, x2)
if function == "MAE":
return MAE(x1, x2)
if function == "RMSE":
return RMSE(x1, x2)
raise ValueError('The provided error function is not known')