Python 代码优化三次插值

Python 代码优化三次插值,python,optimization,numpy,Python,Optimization,Numpy,我已经阅读了相当长一段时间的问题和答案,发现了很多非常有用的优化。 我在优化下面的代码时遇到了一个瓶颈,它“只是”用于将笛卡尔地图转换为极坐标地图。但由于半径增加角点密度的特殊性,意味着半径越大,描述的点就越多 有没有加快这一进程的想法 Rbin=440 Angbin=440 def cart2pol_alt(data,center,Rfact): """ Cubic interpolation Fastest implementation of the cubic interpolation

我已经阅读了相当长一段时间的问题和答案,发现了很多非常有用的优化。 我在优化下面的代码时遇到了一个瓶颈,它“只是”用于将笛卡尔地图转换为极坐标地图。但由于半径增加角点密度的特殊性,意味着半径越大,描述的点就越多

有没有加快这一进程的想法

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
Rbin=440
Angbin=440
def cart2pol_alt(数据、中心、Rfact):
"""
三次插值
到目前为止最快的三次插值实现
比max(0,(x+1)**3)快20%,或比bool(x+2>0)的任何因式分解快60-65%
"""
def立方(x):
p0=λy:(y+2)**3如果(y+2>0)否则0
p1=λy:(y+1)**3如果(y+1>0)否则为0
p2=λy:(y)**3如果(y>0)否则0
p3=λy:(y-1)**3如果(y-1>0)否则0
返回值(p0(x)-4*p1(x)+6*p2(x)-4*p3(x))/6。
"""
将所选区域大小调整为极坐标基准大小
"""
rad=Rfact*np.连接([r*np.one(2*r+1)表示np.arange(Rbin)])
θ=np.连接([np.pi*np.arange(t)/t表示2*np.arange(Rbin)+1]中的t)
x=rad*np.cos(θ)+中心[1]
y=-rad*np.sin(θ)+中心[0]
#三次插值
ix=x.astype('int')
iy=y.astype('int')
dx=x-ix
dy=y-iy
极坐标=np.类零(rad)
nX,nY=data.shape
对于np.arange中的索引(Rbin*Angbin):
对于np.arange中的i(-1,3):
对于np.arange中的j(-1,3):
condx=np.logical_和((ix[索引]+i)=0)
condy=np.logical_和((iy[index]+j)=0)
如果np.逻辑_和(condx,condy):
立方=立方(i-dx[index])*立方(dy[index]-j)
polar[index]+=data.ravel()[(ix[index]+i)*nY+(iy[index]+j)]*cub
返回极轴
编辑。谢谢大家的帮助。矢量化并不容易,但我设法将执行时间从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
Rbin=440
Angbin=440
def cart2pol(数据、比例、中心、Rfact):
"""
三次插值
迄今为止最快的阵列三次插值实现
"""
def立方(y):
p0=(y+2)**3

p0[p0由于您没有提供任何数据,我无法验证它是否会产生与您的代码相同的结果。但我将首先用矢量化操作替换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
np.arange(-1,3)中的i的
:
ixi=ix+i
condx=(ixi=0)
对于np.arange中的j(-1,3):
iyj=iy+j
cond=(iyj=0)&condx
如果条件为any():
立方=立方(i-dx[cond])*立方(dy[cond]-j)
极坐标[cond]+=数据[ixi[cond],iyj[cond]]*cub

您可能可以将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)
nX,nY=data.shape
对于np.arange中的i(-1,3):
对于np.arange中的j(-1,3):
condx=np.逻辑_和((ix+i)=0)
condx=np.logical_和((iy+j)=0)
立方=立方(i-dx)*立方(dy-i)
polar+=data.ravel()[(ix+i)*nY+(iy+j)]*cub*\
np.logical_和(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.
def立方(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
返回(p0-4*p1+6*p2-4*p3)/6。

欢迎作为用户使用StackOverflow!优化您的代码可能更好。但作为起点,我总是尝试避免for循环。您不能将函数立方统一列在有用范围上吗?在这里使用lambda有什么好处?还请注意,您的插值方案是可分离的。感谢此立方插值对于阵列,on确实比前一种更快生成数据的简单方法:X,Y=np.meshgrid(np.arange(-250250),np.arange(-250250)),然后是data=np.exp(-(sqrt(X2+Y2)-80)**2/50)。这应该会给你打电话。是的,对。如果我能理解你的数据,我可以制作它们。但是,你应该在发布时提供一个最低限度的工作示例,这样所有想帮助你的人就不必提供相同(甚至更糟的是,不同)的数据。我很高兴你找到了解决方案。