为什么 SciPy 的 interp1d 需要一分钟多的时间来构建一个插值器?
Why would SciPy's interp1d take over a minute to build an interpolator?
我想在 1d 中对一长串浮点数(或向量)进行四边形或立方体插值,其中长可以是 1E+05 或 1E+06(或更多)。出于某种原因,SciPi 方便 interp1d()
准备插值器的时间开销对于二次和三次样条几乎为 n^3,几千点需要一分钟。
根据评论 (我将删除一个问题,我暂时将其保留在那里以供评论访问)在其他计算机上需要一毫秒,因此这里显然存在病态错误。
我的安装有点旧,但是 SciPy 的 .interp1d()
已经存在了很长一段时间。
np.__version__ '1.13.0'
scipy.__version__ '0.17.0'
我该怎么做才能弄清楚插值的这种令人难以置信的缓慢?
import time
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
times = []
for n in np.logspace(1, 3.5, 6).astype(int):
x = np.arange(n, dtype=float)
y = np.vstack((np.cos(x), np.sin(x)))
start = time.clock()
bob = interp1d(x, y, kind='quadratic', assume_sorted=True)
times.append((n, time.clock() - start))
n, tim = zip(*times)
plt.figure()
plt.plot(n, tim)
plt.xscale('log')
plt.yscale('log')
plt.show()
简短回答:更新您的 scipy 安装。
更长的答案:0.19 之前,interp1d
基于 splmake
,它使用具有完整矩阵的线性代数。在 scipy 0.19 中,它被重构为使用带状线性代数。结果,(下面是 scipy 0.19.1)
In [14]: rndm = np.random.RandomState(1234)
In [15]: for n in [100, 1000, 10000, int(1e6)]:
...: x = np.sort(rndm.uniform(size=n))
...: y = np.sin(x)
...: %timeit interp1d(x, y, kind='quadratic', assume_sorted=True)
...:
...:
244 µs ± 4.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
422 µs ± 4.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.17 ms ± 50.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
227 ms ± 4.45 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [16]:
In [16]: for n in [100, 1000, 10000, int(1e6)]:
...: x = np.sort(rndm.uniform(size=n))
...: y = np.sin(x)
...: %timeit interp1d(x, y, kind='cubic', assume_sorted=True)
...:
...:
241 µs ± 4.67 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
462 µs ± 4.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.64 ms ± 37.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
276 ms ± 1.91 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
如果你特别想要三次样条曲线(这是 scipy 0.18 中的新功能),你的其他选项是 CubicSpline
或 make_interp_spline
如果你还想要二次样条曲线([=22 中的新功能) =] 0.19;这就是 interp1d
在后台使用的内容)。
我想在 1d 中对一长串浮点数(或向量)进行四边形或立方体插值,其中长可以是 1E+05 或 1E+06(或更多)。出于某种原因,SciPi 方便 interp1d()
准备插值器的时间开销对于二次和三次样条几乎为 n^3,几千点需要一分钟。
根据评论
我的安装有点旧,但是 SciPy 的 .interp1d()
已经存在了很长一段时间。
np.__version__ '1.13.0'
scipy.__version__ '0.17.0'
我该怎么做才能弄清楚插值的这种令人难以置信的缓慢?
import time
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
times = []
for n in np.logspace(1, 3.5, 6).astype(int):
x = np.arange(n, dtype=float)
y = np.vstack((np.cos(x), np.sin(x)))
start = time.clock()
bob = interp1d(x, y, kind='quadratic', assume_sorted=True)
times.append((n, time.clock() - start))
n, tim = zip(*times)
plt.figure()
plt.plot(n, tim)
plt.xscale('log')
plt.yscale('log')
plt.show()
简短回答:更新您的 scipy 安装。
更长的答案:0.19 之前,interp1d
基于 splmake
,它使用具有完整矩阵的线性代数。在 scipy 0.19 中,它被重构为使用带状线性代数。结果,(下面是 scipy 0.19.1)
In [14]: rndm = np.random.RandomState(1234)
In [15]: for n in [100, 1000, 10000, int(1e6)]:
...: x = np.sort(rndm.uniform(size=n))
...: y = np.sin(x)
...: %timeit interp1d(x, y, kind='quadratic', assume_sorted=True)
...:
...:
244 µs ± 4.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
422 µs ± 4.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.17 ms ± 50.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
227 ms ± 4.45 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [16]:
In [16]: for n in [100, 1000, 10000, int(1e6)]:
...: x = np.sort(rndm.uniform(size=n))
...: y = np.sin(x)
...: %timeit interp1d(x, y, kind='cubic', assume_sorted=True)
...:
...:
241 µs ± 4.67 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
462 µs ± 4.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.64 ms ± 37.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
276 ms ± 1.91 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
如果你特别想要三次样条曲线(这是 scipy 0.18 中的新功能),你的其他选项是 CubicSpline
或 make_interp_spline
如果你还想要二次样条曲线([=22 中的新功能) =] 0.19;这就是 interp1d
在后台使用的内容)。