一个复杂的Numpy脚本的矢量化实现

时间:2017-05-12 19:29:08

标签: python numpy vectorization

我正在开展一个涉及预测雷达天气模式运动的个人项目。我有三个n个m numpy数组;一个具有降水强度值,一个具有该降水的X方向上的移动(以像素为单位),一个具有该降水的Y方向上的移动(以像素为单位)。我想使用这三个数组来确定沉淀像素的位置,使用其他两个数组中的偏移量。

xMax = currentReflectivity.shape[0]
yMax = currentReflectivity.shape[1]                            
for x in xrange(currentReflectivity.shape[0]):
    for y in xrange(currentReflectivity.shape[1]):
        targetPixelX = xOffsetArray[x,y] + x
        targetPixelY = yOffsetArray[x,y] + y
        targetPixelX = int(targetPixelX)
        targetPixelY = int(targetPixelY)
        if targetPixelX < xMax and targetPixelY < yMax:
            interpolatedReflectivity[targetPixelX,targetPixelY] = currentReflectivity[x,y]

我无法想出一种对此进行矢量化的方法;任何想法?

2 个答案:

答案 0 :(得分:3)

这是一个利用broadcasting -

的矢量化方法
x_arr = np.arange(currentReflectivity.shape[0])[:,None]
y_arr = np.arange(currentReflectivity.shape[1])

targetPixelX_arr = (xOffsetArray[x_arr, y_arr] + x_arr).astype(int)
targetPixelY_arr = (yOffsetArray[x_arr, y_arr] + y_arr).astype(int)

valid_mask = (targetPixelX_arr < xMax) & (targetPixelY_arr < yMax)

R = targetPixelX_arr[valid_mask]
C = targetPixelY_arr[valid_mask]
interpolatedReflectivity[R,C] = currentReflectivity[valid_mask]

运行时测试

方法 -

def org_app(currentReflectivity, xOffsetArray, yOffsetArray):
    m,n = currentReflectivity.shape
    interpolatedReflectivity = np.zeros((m,n))

    xMax = currentReflectivity.shape[0]
    yMax = currentReflectivity.shape[1]                            
    for x in xrange(currentReflectivity.shape[0]):
        for y in xrange(currentReflectivity.shape[1]):
            targetPixelX = xOffsetArray[x,y] + x
            targetPixelY = yOffsetArray[x,y] + y
            targetPixelX = int(targetPixelX)
            targetPixelY = int(targetPixelY)

            if targetPixelX < xMax and targetPixelY < yMax:
                interpolatedReflectivity[targetPixelX,targetPixelY] = \
                currentReflectivity[x,y]
    return interpolatedReflectivity

def broadcasting_app(currentReflectivity, xOffsetArray, yOffsetArray):
    m,n = currentReflectivity.shape
    interpolatedReflectivity = np.zeros((m,n))

    xMax, yMax = m,n        
    x_arr = np.arange(currentReflectivity.shape[0])[:,None]
    y_arr = np.arange(currentReflectivity.shape[1])

    targetPixelX_arr = (xOffsetArray[x_arr, y_arr] + x_arr).astype(int)
    targetPixelY_arr = (yOffsetArray[x_arr, y_arr] + y_arr).astype(int)

    valid_mask = (targetPixelX_arr < xMax) & (targetPixelY_arr < yMax)     
    R = targetPixelX_arr[valid_mask]
    C = targetPixelY_arr[valid_mask]
    interpolatedReflectivity[R,C] = currentReflectivity[valid_mask]
    return interpolatedReflectivity

计时和验证 -

In [276]: # Setup inputs
     ...: m,n = 100,110  # currentReflectivity.shape
     ...: max_r = 120  # xOffsetArray's extent
     ...: max_c = 130  # yOffsetArray's extent
     ...: 
     ...: currentReflectivity = np.random.rand(m, n)
     ...: xOffsetArray = np.random.randint(0,max_r,(m, n))
     ...: yOffsetArray = np.random.randint(0,max_c,(m, n))
     ...: 

In [277]: out1 = org_app(currentReflectivity, xOffsetArray, yOffsetArray)
     ...: out2 = broadcasting_app(currentReflectivity, xOffsetArray, yOffsetArray)
     ...: print np.allclose(out1, out2)
     ...: 
True

In [278]: %timeit org_app(currentReflectivity, xOffsetArray, yOffsetArray)
100 loops, best of 3: 6.86 ms per loop

In [279]: %timeit broadcasting_app(currentReflectivity, xOffsetArray, yOffsetArray)
1000 loops, best of 3: 212 µs per loop

In [280]: 6860.0/212        # Speedup number
Out[280]: 32.35849056603774

答案 1 :(得分:1)

我很确定你可以通过将所有内容从循环中取出来进行矢量化:

targetPixelX = (xOffsetArray + np.arange(xMax).reshape(xMax, 1)).astype(np.int)
targetPixelY = (yOffsetArray + np.arange(yMax)).astype(np.int)
mask = ((targetPixelX < xMax) & (targetPixelY < yMax))
interpolatedReflectivity[mask] = currentReflectivity[mask]

这将更快但内存更密集。基本上,targetPixelXtargetPixelY现在是包含每个像素的值的数组,这些值是在每次迭代的基础上计算出来的。

interpolatedReflectivity中只设置了屏蔽值,与if语句在循环中的操作类似。