如何在Python中优化MAPE代码?

8

我需要一个MAPE函数,但是在标准包中找不到它...以下是我的实现。

def mape(actual, predict): 
    tmp, n = 0.0, 0
    for i in range(0, len(actual)):
        if actual[i] <> 0:
            tmp += math.fabs(actual[i]-predict[i])/actual[i]
            n += 1
    return (tmp/n)

我不喜欢这段代码,它在速度方面非常不理想。如何重写代码以更符合Python风格并提高速度?


对于那些感兴趣的人,自从0.24版本以来,MAPE已经在scikit-learn中可用(可以看看我在这里的答案)。 - Gonçalo Peres
2个回答

15

这里有一种利用掩码的向量化方法 -

def mape_vectorized(a, b): 
    mask = a <> 0
    return (np.fabs(a[mask] - b[mask])/a[mask]).mean()

在除法计算之后使用掩码可能会更快 - masking

def mape_vectorized_v2(a, b): 
    mask = a <> 0
    return (np.fabs(a - b)/a)[mask].mean() 

运行时测试 -

In [217]: a = np.random.randint(-10,10,(10000))
     ...: b = np.random.randint(-10,10,(10000))
     ...: 

In [218]: %timeit mape(a,b)
100 loops, best of 3: 11.7 ms per loop

In [219]: %timeit mape_vectorized(a,b)
1000 loops, best of 3: 273 µs per loop

In [220]: %timeit mape_vectorized_v2(a,b)
1000 loops, best of 3: 220 µs per loop

2
什么是 <> 操作? - panc
1
@panc 它与!=相同,它并不真正符合Pythonic风格,所以你可以忘记它。 - Nathan Furnal
@NathanFurnal 这意味着它是有效的Python代码,但我甚至无法让它工作(只是出于好奇)。 - SARose
1
@SARose 那是 Python 2!在任何 Python 3+ 代码中都无效。 - Nathan Furnal

0

使用masked_Arrays掩码零除时,另一种类似的方法是:

import numpy.ma as ma
masked_actual = ma.masked_array(actual, mask=actual==0)
MAPE = (np.fabs(masked_actual - predict)/masked_actual).mean()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接