1

我正在尝试评估卡方函数,即将任意(黑盒)函数与数据的 numpy 向量数组进行比较。目前我正在循环遍历python中的数组,但是这样的事情非常慢:

n=len(array)
sigma=1.0
chisq=0.0
for i in range(n):
    data = array[i]
    model = f(i,a,b,c)
    chisq += 0.5*((data-model)/sigma)**2.0
return chisq

array 是一维 numpy 数组, a,b,c 是标量。有没有办法通过使用 numpy.sum() 或某种 lambda 函数等来加快速度?我可以看到如何像这样删除一个循环(通过 chisq):

numpy.sum(((array-model_vec)/sigma)**2.0)

但是我仍然需要显式地填充数组 model_vec,这可能会很慢;如果没有这样的显式循环,我该怎么做:

model_vec=numpy.zeros(len(data))
for i in range(n):
    model_vec[i] = f(i,a,b,c)
return numpy.sum(((array-model_vec)/sigma)**2.0)

?

谢谢!

4

2 回答 2

1

如果您无法控制其定义,则可以使用np.vectorize“矢量化”您的函数:f

g = np.vectorize(f)

但这不如自己手动对函数进行矢量化以支持数组,因为它实际上并没有做更多的事情,只是将循环内部化,而且它可能不适用于某些函数。事实上,从文档中:

注意提供 该vectorize功能主要是为了方便,而不是为了性能。该实现本质上是一个 for 循环。

相反,您应该专注于f接受向量而不是i

def f(i, a, b, x):
    return a*x[i] + b

def g(a, b, x):
    x = np.asarray(x)
    return a*x + b

然后,如果你只想要th,而不是调用f(i, a, b, x),调用,但是对于整个函数的操作,使用它会快得多。g(a,b,x)[i]ig(a, b, x)

model_vec = g(a, b, x)
return numpy.sum(((array-model_vec)/sigma)**2.0)
于 2013-04-26T15:14:51.397 回答
0

您的代码似乎很慢,因为循环中执行的内容很慢(您的模型生成)。把它变成单线不会加快速度。如果您可以访问具有多于 CPU 的现代计算机,您可以尝试并行运行此循环 - 例如使用multiprocessing模块;

from multiprocessing import Pool

if __name__ == '__main__':

    # snip set up code

    pool = Pool(processes=4)              # start 4 worker processes
    inputs = [(i,a,b,c) for i in range(n)]
    model_array = pool.map(model, inputs)

    for i in range(n):
        data = array[i]
        model = model_array[i]
        chisq += 0.5*((data-model)/sigma)**2.0
于 2013-04-26T12:20:23.827 回答