繁体   English   中英

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

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

我需要(数值地)计算函数的一阶和二阶导数,我试图使用splrepUnivariateSpline来创建样条函数,以便插入函数来获取导数。

然而,对于大小为10 ^ -1或更低并且 (快速)振荡的函数,似乎在样条表示本身存在固有问题。

例如,考虑以下代码在区间(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)

下面是M的结果,A = 1.e0,A = 1.e-2

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

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

很明显,样条函数创建的插值函数完全不正确! 第二个图甚至没有振荡正确的频率。

有没有人对这个问题有任何见解? 或者知道在numpy / scipy中创建样条曲线的另一种方法?

干杯,罗里

我猜你的问题是由于别名造成的。

你的例子中 x是什么?

如果您插入的 x值与原始点之间的距离较小,则会固有地丢失频率信息。 这完全独立于任何类型的插值。 它是下采样中固有的。

没关系上面的别名。 它不适用于这种情况(虽然我仍然不知道你的例子中有什么x ...

我只是意识到,你原来的输入点,当你使用一个非零平滑因子(评估你的观点s )。

根据定义,平滑不会完全符合数据。 尝试改为使用s=0

作为一个简单的例子:

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()

在此输入图像描述

你只是清楚地看到低幅度平滑效果的原因是由于平滑因子的定义方式。 有关更多详细信息,请参阅scipy.interpolate.UnivariateSpline的文档。

即使幅度较高,如果使用平滑,插值数据也不会与原始数据匹配。

例如,如果我们只是在上面的代码示例中将幅度( A )更改为1.0 ,我们仍然会看到平滑的效果......

在此输入图像描述

问题在于为s参数选择合适的值。 其值取决于数据的缩放。

仔细阅读文档,可以推断出应该围绕s = len(y) * np.var(y)选择参数,即数据点数*方差。 例如, s = 0.05 * len(y) * np.var(y)给出平滑样条,其不依赖于数据的缩放或数据点的数量。

编辑s合理值当然也取决于数据中的噪声水平。 文档似乎建议选择范围内的s (m - sqrt(2*m)) * std**2 <= s <= (m + sqrt(2*m)) * std**2其中std是标准与您想要平滑的“噪音”相关的偏差。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM