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)。这应该会给你打电话。是的,对。如果我能理解你的数据,我可以制作它们。但是,你应该在发布时提供一个最低限度的工作示例,这样所有想帮助你的人就不必提供相同(甚至更糟的是,不同)的数据。我很高兴你找到了解决方案。