python中的多个1d插值
我正在研究模拟CCD阵列中的陷阱。目前我正在使用NumPy和Scipy,我已经能够对大多数调用进行矢量化,这给了我一些加速。 目前,代码中的瓶颈是我必须从代码内部循环中的大量不同插值中检索一个数字。这一特定步骤占用了约97%的计算时间 我在这里举了一个简单的例子来说明我的问题:python中的多个1d插值,python,numpy,scipy,linear-interpolation,Python,Numpy,Scipy,Linear Interpolation,我正在研究模拟CCD阵列中的陷阱。目前我正在使用NumPy和Scipy,我已经能够对大多数调用进行矢量化,这给了我一些加速。 目前,代码中的瓶颈是我必须从代码内部循环中的大量不同插值中检索一个数字。这一特定步骤占用了约97%的计算时间 我在这里举了一个简单的例子来说明我的问题: import numpy as np from scipy.interpolate import interp1d # the CCD array containing values from 0-100 array
import numpy as np
from scipy.interpolate import interp1d
# the CCD array containing values from 0-100
array = np.random.random(200)*100
# a number of traps at different positions in the CCD array
n_traps = 100
trap_positions = np.random.randint(0,200,n_traps)
# xvalues for the interpolations
xval = [0,10,100]
# each trap has y values corresponding to the x values
trap_yvals = [np.random.random(3)*100 for _ in range(n_traps)]
# The xval-to-yval interpolation is made for each trap
yval_interps = [interp1d(xval,yval) for yval in trap_yvals]
# moving the trap positions down over the array
for i in range(len(array)):
# calculating new trap position
new_trap_pos = trap_positions+i
# omitting traps that are outside array
trap_inside_array = new_trap_pos < len(array)
# finding the array_vals (corresponding to the xvalues in the interpolations)
array_vals = array[new_trap_pos[trap_inside_array]]
# retrieving the interpolated y-values (this is the bottleneck)
yvals = np.array([yval_interps[trap_inside_array[t]](array_vals[t])
for t in range(len(array_vals))])
# some more operations using yvals
将numpy导入为np
从scipy.interpolate导入interp1d
#包含0-100之间的值的CCD阵列
数组=np.随机.随机(200)*100
#CCD阵列中不同位置的多个陷阱
n_陷阱=100
陷阱位置=np.random.randint(0200,n个陷阱)
#xx插值的值
xval=[0,10100]
#每个陷阱都有对应于x值的y值
trap_yvals=[np.random.random(3)*100用于范围内的u陷阱(n_陷阱)]
#对每个陷阱进行xval到yval插值
yval_interps=[陷阱中yval的interp1d(xval,yval)]
#在阵列上向下移动陷阱位置
对于范围内的i(len(数组)):
#计算新的陷阱位置
新陷阱位置=陷阱位置+i
#忽略阵列外部的陷阱
陷阱\u内部\u阵列=新陷阱\u位置
有没有一种方法可以优化它,可能是使用Cython或类似的工具?我已经仔细考虑了一下,我想我已经找到了一个非常好的解决方案,我想与大家分享,尽管这意味着我将回答我自己的问题 首先,我意识到,不用使用scipy.interpolation函数,我只需要找到两个值之间的插值。这可以通过这个小功能来完成
from bisect import bisect_left
def two_value_interpolation(x,y,val):
index = bisect_left(x,val)
_xrange = x[index] - x[index-1]
xdiff = val - x[index-1]
modolo = xdiff/_xrange
ydiff = y[index] - y[index-1]
return y[index-1] + modolo*ydiff
这给了我一些速度,但我想看看是否可以做得更好,因此我将函数移植到Cython,并在所有陷阱上添加了循环,因此我不必在python代码中这样做:
# cython: boundscheck=False
# cython: wraparound=False
# cython: cdivision=True
import numpy as np
cimport numpy as np
def two_value_interpolation_c(np.ndarray[np.float64_t] x,
np.ndarray[np.float64_t, ndim=2] y,
np.ndarray[np.float64_t] val_array):
cdef unsigned int index, trap
cdef unsigned int ntraps=val_array.size
cdef long double val, _xrange, xdiff, modolo, ydiff
cdef np.ndarray y_interp = np.zeros(ntraps, dtype=np.float64)
for trap in range(ntraps):
index = 0
val = val_array[trap]
while x[index] <= val:
index += 1
_xrange = x[index] - x[index-1]
xdiff = val - x[index-1]
modolo = xdiff/_xrange
ydiff = y[trap,index] - y[trap,index-1]
y_interp[trap] = y[trap,index-1] + modolo*ydiff
return y_interp
#cython:boundscheck=False
#cython:wrapparound=False
#cython:cdivision=True
将numpy作为np导入
cimport numpy作为np
定义二值插值(np.ndarray[np.float64_t]x,
np.ndarray[np.float64_t,ndim=2]y,
np.ndarray[np.float64\u t]val\u数组):
cdef无符号整数索引,陷阱
cdef unsigned int ntraps=val_array.size
cdef长双val,X量程,xdiff,modolo,ydiff
cdef np.ndarray y_interp=np.zero(ntraps,dtype=np.float64)
对于范围内的陷阱(ntraps):
索引=0
val=val_数组[trap]
当x[index]参见时,请使用InterpolateUnivariateSpline,而不是Interpole1d。将性能提高几个数量级另一个显著改进是将数组作为参数传递给interp1d/InterpolateUnivariateSpline,而不是在以下情况下循环单个值possible@M.T:感谢您提供有关使用InterpolatedUnivariateSpline进行加速的提示。我之所以在单个值上循环,是因为每个值都需要从不同的插值中提取,我没有找到解决这个问题的方法。