Permalink
Browse files

added simple version of a weighted MAPE

  • Loading branch information...
T-002 committed Mar 15, 2013
1 parent 0a4211d commit 564916a0550bee0a55861d5254ffc7eea80b2206
View
@@ -22,17 +22,24 @@
#OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
#WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+## the mother of all errors
from baseerrormeasure import BaseErrorMeasure
+## absolute errors
from meansquarederror import MeanSquaredError, MSE
-from symmetricmeanabsolutepercentageerror import SymmetricMeanAbsolutePercentageError, SMAPE
+
+
+## scaled errors that can be used to compare prediction accuracy on different TimeSeries
from meanabsolutedeviationerror import MeanAbsoluteDeviationError, MAD
-#from meaneconomicerror import MeanEconomicError, MEE, MeanSignedEconomicError, MSEE
-from meanabsolutepercentageerror import MeanAbsolutePercentageError, MAPE, GeometricMeanAbsolutePercentageError, GMAPE, MeanSignedPercentageError, MSPE
-#from weightedmeanabsolutepercentageerror import WeightedMeanAbsolutePercentageError, WMAPE
-from medianabsolutepercentageerror import MedianAbsolutePercentageError, MdAPE
+from meanabsolutepercentageerror import MeanAbsolutePercentageError, MAPE, GeometricMeanAbsolutePercentageError, GMAPE, MeanSignedPercentageError, MSPE
+from symmetricmeanabsolutepercentageerror import SymmetricMeanAbsolutePercentageError, SMAPE
+from medianabsolutepercentageerror import MedianAbsolutePercentageError, MdAPE
+from weightedmeanabsolutepercentageerror import WeightedMeanAbsolutePercentageError, WMAPE
+
+
+#from meaneconomicerror import MeanEconomicError, MEE, MeanSignedEconomicError, MSEE
#from meanabsolutescalederror import MeanAbsoluteScaledError, MASE
-#from meansigneddifferenceerror import MeanSignedDifferenceError, MSD
+#from meansigneddifferenceerror import MeanSignedDifferenceError, MSD
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+#Copyright (c) 2012-2013 Christian Schwarz
+#
+#Permission is hereby granted, free of charge, to any person obtaining
+#a copy of this software and associated documentation files (the
+#"Software"), to deal in the Software without restriction, including
+#without limitation the rights to use, copy, modify, merge, publish,
+#distribute, sublicense, and/or sell copies of the Software, and to
+#permit persons to whom the Software is furnished to do so, subject to
+#the following conditions:
+#
+#The above copyright notice and this permission notice shall be
+#included in all copies or substantial portions of the Software.
+#
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+#LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+#OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import math
+from pycast.errors import MeanAbsolutePercentageError
+
+class WeightedMeanAbsolutePercentageError(MeanAbsolutePercentageError):
+ """Implements a weighted alternative of the MeanAbsolutePercentageError."""
+
+ def local_error(self, originalValue, calculatedValue):
+ """Calculates the error between the two given values.
+
+ :param List originalValue: List containing the values of the original data.
+ :param List calculatedValue: List containing the values of the calculated TimeSeries that
+ corresponds to originalValue.
+
+ :return: Returns the error measure of the two given values.
+ :rtype: Numeric
+ """
+ originalValue = originalValue[0]
+ calculatedValue = calculatedValue[0]
+
+ if 0 == originalValue:
+ return None
+
+ signed_mape = (calculatedValue - originalValue) / float(originalValue) * 100.0
+ if signed_mape < 0:
+ signed_mape *= 2
+
+ return math.fabs(signed_mape)
+
+WMAPE = WeightedMeanAbsolutePercentageError
View
@@ -41,7 +41,7 @@
## error measure tests
from errormeasuretest import BaseErrorMeasureTest, MeanSquaredErrorTest, SymmetricMeanAbsolutePercentageErrorTest, MeanAbsoluteDeviationErrorTest, MedianAbsolutePercentageErrorTest#, MeanAbsoluteScaledErrorTest#, MeanSignedDifferenceErrorTest
from mapetest import MeanAbsolutePercentageErrorTest, GeometricMeanAbsolutePercentageErrorTest
-#from weightedmapetest import WeightedMeanAbsolutePercentageErrorTest
+from weightedmapetest import WeightedMeanAbsolutePercentageErrorTest
#from meetest import MeanEconomicErrorTest
## optimization method
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+#Copyright (c) 2012-2013 Christian Schwarz
+#
+#Permission is hereby granted, free of charge, to any person obtaining
+#a copy of this software and associated documentation files (the
+#"Software"), to deal in the Software without restriction, including
+#without limitation the rights to use, copy, modify, merge, publish,
+#distribute, sublicense, and/or sell copies of the Software, and to
+#permit persons to whom the Software is furnished to do so, subject to
+#the following conditions:
+#
+#The above copyright notice and this permission notice shall be
+#included in all copies or substantial portions of the Software.
+#
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+#NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+#LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+#OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+#WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+## required external modules
+import unittest
+
+## required modules from pycast
+from pycast.errors import WeightedMeanAbsolutePercentageError
+from pycast.common.timeseries import TimeSeries
+
+class WeightedMeanAbsolutePercentageErrorTest(unittest.TestCase):
+ """Test class containing all tests for WeightedMeanAbsolutePercentageError."""
+ def local_error_test(self):
+ orgValues = [11, 33.1, 2.3, 6.54, 123.1, 12.54, 12.9]
+ calValues = [24, 1.23, 342, 1.21, 4.112, 9.543, 3.54]
+ resValues = ['118.181', '192.567', '14769.5', '162.996', '193.319', '47.7990', '145.116']
+
+ wmape = WeightedMeanAbsolutePercentageError()
+ for idx in xrange(len(orgValues)):
+ localError = wmape.local_error([orgValues[idx]], [calValues[idx]])
+ assert str(resValues[idx]) == str(localError)[:7], str(resValues[idx]) + '!=' + str(localError)[:7]
+
+ def error_calculation_test(self):
+ """Test the calculation of the MeanAbsolutePercentageError."""
+ dataOrg = [[1,1], [2,2], [3,3], [4,4], [5,5], [6,6], [7,8], [7.3, 5], [8, 0], [9,10]]
+ dataCalc = [[1,3], [2,5], [3,0], [4,3], [5,5], [6.1,6], [7,3], [7.3, 5], [8, 0], [9,9]]
+ # abs difference: 2 3 3 1 0 NA 5 0 NA 1
+ # local errors: 200 150 200 50 0 NA 125 0 NA 20
+ # sum: 745
+
+ tsOrg = TimeSeries.from_twodim_list(dataOrg)
+ tsCalc = TimeSeries.from_twodim_list(dataCalc)
+
+ wmape = WeightedMeanAbsolutePercentageError()
+ wmape.initialize(tsOrg, tsCalc)
+ assert str(wmape.get_error())[:6] == "93.125"

0 comments on commit 564916a

Please sign in to comment.