python中的MAPE计算
Posted
技术标签:
【中文标题】python中的MAPE计算【英文标题】:MAPE calculation in python 【发布时间】:2018-05-18 18:58:06 【问题描述】:我想计算预测值和真实值的平均绝对百分比误差 (MAPE)。我从here 找到了一个解决方案,但这会产生错误并在mask = a <> 0
行中显示无效语法
def mape_vectorized_v2(a, b):
mask = a <> 0
return (np.fabs(a - b)/a)[mask].mean()
def mape_vectorized_v2(a, b):
File "<ipython-input-5-afa5c1162e83>", line 1
def mape_vectorized_v2(a, b):
^
SyntaxError: unexpected EOF while parsing
我正在使用 spyder3。我的预测值是 np.array 类型,真实值是数据帧
type(predicted)
Out[7]: numpy.ndarray
type(y_test)
Out[8]: pandas.core.frame.DataFrame
如何清除此错误并继续进行 MAPE 计算?
编辑:
predicted.head()
Out[22]:
Total_kWh
0 7.163627
1 6.584960
2 6.638057
3 7.785487
4 6.994427
y_test.head()
Out[23]:
Total_kWh
79 7.2
148 6.7
143 6.7
189 7.2
17 6.4
np.abs(y_test[['Total_kWh']] - predicted[['Total_kWh']]).head()
Out[24]:
Total_kWh
0 NaN
1 NaN
2 NaN
3 NaN
4 0.094427
【问题讨论】:
你需要mask = a != 0
【参考方案1】:
在 python 中比较需要!=
,而不是<>
。
所以需要:
def mape_vectorized_v2(a, b):
mask = a != 0
return (np.fabs(a - b)/a)[mask].mean()
来自stats.stackexchange的另一个解决方案:
def mean_absolute_percentage_error(y_true, y_pred):
y_true, y_pred = np.array(y_true), np.array(y_pred)
return np.mean(np.abs((y_true - y_pred) / y_true)) * 100
【讨论】:
这给了我一个 nan。你知道它什么时候会产生这样的价值吗?我的第二个数组包含的值为 0,如何修改后一种解决方案以包含此类情况? 对于a
中的负值,第一个函数不会导致负 MAPE 值吗?计算不应该是(np.fabs((a - b))/a)[mask].mean()
,分母也是绝对的吗?【参考方案2】:
这两种解决方案都不适用于零值。这是我的工作方式:
def percentage_error(actual, predicted):
res = np.empty(actual.shape)
for j in range(actual.shape[0]):
if actual[j] != 0:
res[j] = (actual[j] - predicted[j]) / actual[j]
else:
res[j] = predicted[j] / np.mean(actual)
return res
def mean_absolute_percentage_error(y_true, y_pred):
return np.mean(np.abs(percentage_error(np.asarray(y_true), np.asarray(y_pred)))) * 100
希望对你有帮助。
【讨论】:
np.mean(actual) 可以替换为非常小的浮点数等其他标准。【参考方案3】:新版本的 scikit-learn (v0.24) 具有计算 MAPE 的功能。
sklearn.metrics.mean_absolute_percentage_error
您只需要两个类似数组的变量:y_true
存储实际/真实值,y_pred
存储预测值。
可以参考官方文档here。
【讨论】:
sklearn mean_absolute_percentage_error 给出了错误的值,即使在这个文档上,如果你看到给出的例子,结果是 112589990684262.48 的大值。【参考方案4】:由于实际值也可以为零,因此我取分母中实际值的平均值,而不是实际值:
Error = np.sum(np.abs(np.subtract(data_4['y'],data_4['pred'])))
Average = np.sum(data_4['y'])
MAPE = Error/Average
【讨论】:
【参考方案5】:这是一个注意零的改进版本:
#Mean Absolute Percentage error
def mape(y_true, y_pred,sample_weight=None,multioutput='uniform_average'):
y_type, y_true, y_pred, multioutput = _check_reg_targets(y_true, y_pred, multioutput)
epsilon = np.finfo(np.float64).eps
mape = np.abs(y_pred - y_true) / np.maximum(np.abs(y_true), epsilon)
output_errors = np.average(mape,weights=sample_weight, axis=0)
if isinstance(multioutput, str):
if multioutput == 'raw_values':
return output_errors
elif multioutput == 'uniform_average':
# pass None as weights to np.average: uniform mean
multioutput = None
return np.average(output_errors, weights=multioutput)
def _check_reg_targets(y_true, y_pred, multioutput, dtype="numeric"):
if y_true.ndim == 1:
y_true = y_true.reshape((-1, 1))
if y_pred.ndim == 1:
y_pred = y_pred.reshape((-1, 1))
if y_true.shape[1] != y_pred.shape[1]:
raise ValueError("y_true and y_pred have different number of output "
"(0!=1)".format(y_true.shape[1], y_pred.shape[1]))
n_outputs = y_true.shape[1]
allowed_multioutput_str = ('raw_values', 'uniform_average',
'variance_weighted')
if isinstance(multioutput, str):
if multioutput not in allowed_multioutput_str:
raise ValueError("Allowed 'multioutput' string values are . "
"You provided multioutput=!r".format(
allowed_multioutput_str,
multioutput))
elif multioutput is not None:
multioutput = check_array(multioutput, ensure_2d=False)
if n_outputs == 1:
raise ValueError("Custom weights are useful only in "
"multi-output cases.")
elif n_outputs != len(multioutput):
raise ValueError(("There must be equally many custom weights "
"(%d) as outputs (%d).") %
(len(multioutput), n_outputs))
y_type = 'continuous' if n_outputs == 1 else 'continuous-multioutput'
return y_type, y_true, y_pred, multioutput
【讨论】:
【参考方案6】:这是另一种计算 MAPE 的方法,它可以处理“0”分母,而且速度很快。
def mod_my_MAPE(y, pred):
y = y[:][y[:]!=0]
pred = pred[:][y[:]!=0]
summ = np.sum(abs((y[:] - pred[:])/y[:]))
return summ/len(y)
【讨论】:
【参考方案7】:从scikit-learn
0.24 版开始。可以使用sklearn.metrics.mean_absolute_percentage_error
。
Here 是其 GitHub 存储库上的实现链接。
我刚刚在本地尝试了最新版本(1.0.2)。
这是一个例子 (Source)
>>> from sklearn.metrics import mean_absolute_percentage_error
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> mean_absolute_percentage_error(y_true, y_pred)
0.5515...
注意:如果 y_true 的值之一为零,则 MAPE 可能会出现问题。在 Scikit-learn 中,这将导致任意高的数字。
查看此示例 (Source)
>>> from sklearn.metrics import mean_absolute_percentage_error
>>> y_true = [1., 0., 2.4, 7.]
>>> y_pred = [1.2, 0.1, 2.4, 8.]
>>> mean_absolute_percentage_error(y_true, y_pred)
112589990684262.48
【讨论】:
以上是关于python中的MAPE计算的主要内容,如果未能解决你的问题,请参考以下文章
回归模型和时间序列模型中的MAPE指标是什么?MAPE指标解读MAPE越大越好还是越小越好使用MAPE指标的注意事项
XGBoost:是不是可以预测多个标签并计算它们的 MAPE?