代码优化三次插值

时间:2014-03-07 12:04:13

标签: python optimization numpy

我已经阅读了很长一段时间Stack问题和答案,并找到了很多非常有用的优化。 我有点面临优化以下代码的瓶颈,这对于将笛卡尔地图转换为极坐标地图来说只是“公正”。但是具有增加角度点的密度的特殊性,半径意味着更大的半径用更多的点来描述。

有什么想加快这个过程吗?

Rbin=440
Angbin=440
def cart2pol_alt(data,center,Rfact):

"""
Cubic interpolation
Fastest implementation of the cubic interpolation so far
Faster than max(0,(x+1)**3) by 20% or any of the factorization by bool (x+2>0) by 60-65%
"""
def cubic(x):
    p0=lambda y: (y+2)**3 if (y+2>0) else 0
    p1=lambda y: (y+1)**3 if (y+1>0) else 0
    p2=lambda y: (y)**3 if (y>0) else 0
    p3=lambda y: (y-1)**3 if (y-1>0) else 0
    return (p0(x)-4*p1(x)+6*p2(x)-4*p3(x))/6.

"""
Adapt the  selected area size to polar basis size
"""

rad=Rfact*np.concatenate([r*np.ones(2*r+1) for r in np.arange(Rbin)])
theta=np.concatenate([np.pi*np.arange(t)/t for t in 2*np.arange(Rbin)+1])
x=rad*np.cos(theta) + center[1]
y=-rad*np.sin(theta) + center[0]
#Cubic interpolation
ix=x.astype('int')
iy=y.astype('int')
dx=x-ix
dy=y-iy
polar=np.zeros_like(rad)

nX,nY=data.shape
for index in np.arange(Rbin*Angbin):
    for i in np.arange(-1,3):
        for j in np.arange(-1,3):
            condx=np.logical_and((ix[index]+i)<nX,(ix[index]+i)>=0)
            condy=np.logical_and((iy[index]+j)<nY,(iy[index]+j)>=0)
            if np.logical_and(condx,condy):
                cub=cubic(i-dx[index])*cubic(dy[index]-j)
                polar[index]+=data.ravel()[(ix[index]+i)*nY+(iy[index]+j)]*cub    

return polar

EDIT。感谢你的帮助。矢量化并不容易,但我设法将执行时间从4分钟减少到2秒,但使用以下代码。我希望它可以帮助一些人。

Rbin=440
Angbin=440
def cart2pol(data,scale,center,Rfact):

"""
    Cubic interpolation
    Fastest implementation of the cubic interpolation so far for an array
"""
def cubic(y):
    p0=(y+2)**3
        p0[p0<0]=0
        p1 = (y+1)**3
        p1[p1<0]=0
        p2 = y**3
        p2[p2<0]=0
        p3 =(y-1)**3
        p3[p3<0]=0
        return (p0-4.*p1+6.*p2-4.*p3)/6.

rad=Rfact*np.concatenate([r*np.ones(2*r+1) for r in np.arange(Rbin)])
theta=np.concatenate([np.pi*np.arange(t)/t for t in 2*np.arange(Rbin)+1])
x=rad*np.cos(theta) + center[1]
y=-rad*np.sin(theta) + center[0]
#Cubic interpolation
ix=x.astype('int')
iy=y.astype('int')
dx=x-ix
dy=y-iy
polar=np.zeros_like(rad)

i,j=np.meshgrid(np.arange(-1,3),np.arange(-1,3))
i=i.ravel()
j=j.ravel()
I,IX=np.meshgrid(i,ix)
J,IY=np.meshgrid(i,iy)
IXI=IX+I
IYJ=IY+J
    nX,nY=data.shape
rule1=(IXI<nX) & (IXI>=0)
rule2=(IYJ<nY) & (IYJ>=0)
cub=cubic(I-dx.reshape((dx.shape[0],1)))*cubic(dy.reshape((dy.shape[0],1))-J)
dat=data.ravel()[(IXI*nY+IYJ).ravel()].reshape(IYJ.shape)
polar+=(dat*cub).sum(axis=1)
return polar

如果有人看到其他优化,请告诉我们!

2 个答案:

答案 0 :(得分:1)

你可以将for循环矢量化为:

nX,nY=data.shape
for i in np.arange(-1,3):
    for j in np.arange(-1,3):
        condx = np.logical_and((ix + i) < nX, (ix + i) >=0)
        condx = np.logical_and((iy + j) < nY, (iy + j) >=0)
        cub = cubic(i-dx) * cubic(dy - i)
        polar += data.ravel()[(ix + i) * nY + (iy + j)] * cub * \
                                     np.logical_and(condx, condy)

您也可以从三次函数中删除if语句

def cubic(x):
    p0 = (y+2)**3
    p0[p0 < 0] = 0
    p1 = (y+1)**3
    p1[p1 < 0] = 0
    p2 = (y)**3
    p2[p2 < 0] = 0
    p3 = (y-1)**3
    p3[p3 < 0] = 0
    return (p0 - 4*p1 + 6*p2 - 4*p3) /6.

答案 1 :(得分:0)

我无法验证它是否会产生与您的代码相同的结果,因为您没有提供任何数据。但我会先用矢量化操作替换一个for-cycle。

for i in np.arange(-1, 3):
    ixi = ix+i
    condx = (ixi < nX) & (ixi >= 0)
    for j in np.arange(-1, 3):
        iyj = iy+j
        cond = (iyj < nY) & (iyj >= 0) & condx
        if cond.any():
            cub = cubic(i-dx[cond])*cubic(dy[cond]-j)
            polar[cond] += data[ixi[cond], iyj[cond]]*cub