Source code for padasip.misc.error_evaluation

"""
.. 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')