简体   繁体   English

使用scipy.interpolate进行样条曲线表示:低振幅,快速振荡函数的插值不良

[英]Spline representation with scipy.interpolate: Poor interpolation for low-amplitude, rapidly oscillating functions

I need to (numerically) calculate the first and second derivative of a function for which I've attempted to use both splrep and UnivariateSpline to create splines for the purpose of interpolation the function to take the derivatives. 我需要(数值地)计算函数的一阶和二阶导数,我试图使用splrepUnivariateSpline来创建样条函数,以便插入函数来获取导数。

However, it seems that there's an inherent problem in the spline representation itself for functions who's magnitude is order 10^-1 or lower and are (rapidly) oscillating. 然而,对于大小为10 ^ -1或更低并且 (快速)振荡的函数,似乎在样条表示本身存在固有问题。

As an example, consider the following code to create a spline representation of the sine function over the interval (0,6*pi) (so the function oscillates three times only): 例如,考虑以下代码在区间(0,6 * pi)上创建正弦函数的样条曲线表示(因此函数仅振荡三次):

import scipy
from scipy import interpolate
import numpy
from numpy import linspace
import math
from math import sin

k = linspace(0, 6.*pi, num=10000) #interval (0,6*pi) in 10'000 steps
y=[]
A = 1.e0 # Amplitude of sine function

for i in range(len(k)):

  y.append(A*sin(k[i]))

tck =interpolate.UnivariateSpline(x, y, w=None, bbox=[None, None], k=5, s=2)
M=tck(k)

Below are the results for M for A = 1.e0 and A = 1.e-2 下面是M的结果,A = 1.e0,A = 1.e-2

http://i.imgur.com/uEIxq.png Amplitude = 1 http://i.imgur.com/uEIxq.png幅度= 1

http://i.imgur.com/zFfK0.png Amplitude = 1/100 http://i.imgur.com/zFfK0.png振幅= 1/100

Clearly the interpolated function created by the splines is totally incorrect! 很明显,样条函数创建的插值函数完全不正确! The 2nd graph does not even oscillate the correct frequency. 第二个图甚至没有振荡正确的频率。

Does anyone have any insight into this problem? 有没有人对这个问题有任何见解? Or know of another way to create splines within numpy/scipy? 或者知道在numpy / scipy中创建样条曲线的另一种方法?

Cheers, Rory 干杯,罗里

I'm guessing that your problem is due to aliasing. 我猜你的问题是由于别名造成的。

What is x in your example? 你的例子中 x是什么?

If the x values that you're interpolating at are less closely spaced than your original points, you'll inherently lose frequency information. 如果您插入的 x值与原始点之间的距离较小,则会固有地丢失频率信息。 This is completely independent from any type of interpolation. 这完全独立于任何类型的插值。 It's inherent in downsampling. 它是下采样中固有的。

Nevermind the above bit about aliasing. 没关系上面的别名。 It doesn't apply in this case (though I still have no idea what x is in your example... 它不适用于这种情况(虽然我仍然不知道你的例子中有什么x ...

I just realized that you're evaluating your points at the original input points when you're using a non-zero smoothing factor ( s ). 我只是意识到,你原来的输入点,当你使用一个非零平滑因子(评估你的观点s )。

By definition, smoothing won't fit the data exactly. 根据定义,平滑不会完全符合数据。 Try putting s=0 in instead. 尝试改为使用s=0

As a quick example: 作为一个简单的例子:

import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate

x = np.linspace(0, 6.*np.pi, num=100) #interval (0,6*pi) in 10'000 steps
A = 1.e-4 # Amplitude of sine function
y = A*np.sin(x)

fig, axes = plt.subplots(nrows=2)
for ax, s, title in zip(axes, [2, 0], ['With', 'Without']):
    yinterp = interpolate.UnivariateSpline(x, y, s=s)(x)
    ax.plot(x, yinterp, label='Interpolated')
    ax.plot(x, y, 'bo',label='Original')
    ax.legend()
    ax.set_title(title + ' Smoothing')

plt.show()

在此输入图像描述

The reason that you're only clearly seeing the effects of smoothing with a low amplitude is due to the way the smoothing factor is defined. 你只是清楚地看到低幅度平滑效果的原因是由于平滑因子的定义方式。 See the documentation for scipy.interpolate.UnivariateSpline for more details. 有关更多详细信息,请参阅scipy.interpolate.UnivariateSpline的文档。

Even with a higher amplitude, the interpolated data won't match the original data if you use smoothing. 即使幅度较高,如果使用平滑,插值数据也不会与原始数据匹配。

For example, if we just change the amplitude ( A ) to 1.0 in the code example above, we'll still see the effects of smoothing... 例如,如果我们只是在上面的代码示例中将幅度( A )更改为1.0 ,我们仍然会看到平滑的效果......

在此输入图像描述

The problem is in choosing suitable values for the s parameter. 问题在于为s参数选择合适的值。 Its values depend on the scaling of the data. 其值取决于数据的缩放。

Reading the documentation carefully, one can deduce that the parameter should be chosen around s = len(y) * np.var(y) , ie # of data points * variance. 仔细阅读文档,可以推断出应该围绕s = len(y) * np.var(y)选择参数,即数据点数*方差。 Taking for example s = 0.05 * len(y) * np.var(y) gives a smoothing spline that does not depend on the scaling of the data or the number of data points. 例如, s = 0.05 * len(y) * np.var(y)给出平滑样条,其不依赖于数据的缩放或数据点的数量。

EDIT : sensible values for s depend of course also on the noise level in the data. 编辑s合理值当然也取决于数据中的噪声水平。 The docs seem to recommend choosing s in the range (m - sqrt(2*m)) * std**2 <= s <= (m + sqrt(2*m)) * std**2 where std is the standard deviation associated with the "noise" you want to smooth over. 文档似乎建议选择范围内的s (m - sqrt(2*m)) * std**2 <= s <= (m + sqrt(2*m)) * std**2其中std是标准与您想要平滑的“噪音”相关的偏差。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 scipy.interpolate 中设置三次样条插值的第一个和最后一个斜率? - How to set first and last slope of cubic spline interpolation in scipy.interpolate? scipy.interpolate中的三次样条函数返回numpy.ndarray - Cubic Spline function in scipy.interpolate returns a numpy.ndarray AttributeError: 模块 &#39;scipy.interpolate&#39; 没有属性 &#39;spline&#39; - AttributeError: module 'scipy.interpolate' has no attribute 'spline' 如何使用scipy.interpolate获得顺序点插值? - How to use scipy.interpolate to get sequential point interpolation? Python:SciPy.interpolate分段多项式 - Python: SciPy.interpolate PiecewisePolynomial 使用 scipy.interpolate 具有固定起点和终点的平滑样条近似 - Smooth spline approximation with fixed start and end points using scipy.interpolate 如何使用 from scipy.interpolate import make_interp_spline 在 Python 中平滑此图 - How to smooth this Figure in Python with from scipy.interpolate import make_interp_spline scipy.interpolate导致ImportError - scipy.interpolate leads to ImportError 线性插值和存储输出永远使用 python scipy.interpolate interp1d 和 for 循环 - linear interpolation and storing outputs taking forever using python scipy.interpolate interp1d and for loop 使用 scipy.interpolate.splrep 沿样条线插值点 - Interpolation of points along the spline using scipy.interpolate.splrep
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM