加速计算大数组邻居平均值的程序

2 投票
3 回答
1477 浏览
提问于 2025-04-16 10:47

我遇到了一个程序速度的问题。我想在一个很大的数组中计算四个邻居的平均值。这是我代码的一部分。你们有什么建议可以改进最后一行吗?或者我应该使用另一个数组吗?

for a in np.arange(100000):
    for x in np.arange(size):
        for y in np.arange(size):
            if unchangeableflag[x*size+y] == 0:
                vnew[x*size+y] = (v[(x+1)*size+y] + v[(x-1)*size+y] + v[x*size+y+1] + v[x*size+y-1]) / 4.0

3 个回答

1

我不太确定,但你可以去掉一些不变的东西。

for a in np.arange(100000):
    for x in np.arange(size):
        for y in np.arange(size):
            t = x*size+y
            if unchangeableflag[t] == 0:
                vnew[t] = (v[t+size] + v[t-size] + v[t+1] + v[t-1]) / 4.0
3

你可以考虑使用SciPy里的卷积滤波器或者通用滤波器。虽然这些方法计算起来还是比较复杂,但比起一个一个循环处理要快得多。通常在进行这种平均计算时,中心的元素也是会被包含在内的。需要注意的是,这些方法同样适用于多维数组。

from scipy import ndimage
footprint = scipy.array([[0,0.25,0],[0.25,0,0.25],[0,0.25,0]])
filtered_array = scipy.convolve(array, footprint)

或者

from scipy import ndimage
def myfunction(window):
    return (window[0,1] + window[1,0] + window[1,2] + window[2,1]) / 4
filtered_array = scipy.generic_filter(array, myfunction, size=3)
4

你根本不需要用到循环。假设 vvnewunchangeableflag 是一维数组,每个数组都有 size*size 个元素,你可以这样做:

v = v.reshape(size, size)
vnew = vnew.reshape(size, size)
unchangeableflag = unchangeableflag.reshape(size, size)
average = v[1:-1, 2:]
average += v[1:-1, :-2] 
average += v[2:, 1:-1]
average += v[-2:, 1:-1]
average /= 4.0
vnew[1:-1, 1:-1][unchangeableflag[1:-1, 1:-1] == 0] = average

不过,你实际上想要实现什么呢?这看起来有点像你可以用离散拉普拉斯算子来解决的问题。

(注意,这里假设 v 里面是浮点数。如果 v 的数据类型是某种整数类型,你需要稍微修改一下。)

撰写回答