Python Savitzky-Golay过滤器打印错误的值

Python Savitzky-Golay过滤器打印错误的值,python,matplotlib,plot,Python,Matplotlib,Plot,我正在使用Savitzky-Golay过滤器平滑我的数据。我遇到了一个值列表,这些值很快下降到接近0.0的值。下图为原始数据: 应用Savitzky-Golay过滤器后,我得到以下结果: 我们可以看到,它绘制的值低于0.0,这是错误的 以下是我使用的函数: def savitzky_golay(y, window_size, order, deriv=0, rate=1): r"""Smooth (and optionally differentiate) data with a S

我正在使用Savitzky-Golay过滤器平滑我的数据。我遇到了一个值列表,这些值很快下降到接近0.0的值。下图为原始数据:

应用Savitzky-Golay过滤器后,我得到以下结果:

我们可以看到,它绘制的值低于0.0,这是错误的

以下是我使用的函数:

def savitzky_golay(y, window_size, order, deriv=0, rate=1):
    r"""Smooth (and optionally differentiate) data with a Savitzky-Golay filter.
    The Savitzky-Golay filter removes high frequency noise from data.
    It has the advantage of preserving the original shape and
    features of the signal better than other types of filtering
    approaches, such as moving averages techniques.
    Parameters
    ----------
    y : array_like, shape (N,)
        the values of the time history of the signal.
    window_size : int
        the length of the window. Must be an odd integer number.
    order : int
        the order of the polynomial used in the filtering.
        Must be less then `window_size` - 1.
    deriv: int
        the order of the derivative to compute (default = 0 means only smoothing)
    Returns
    -------
    ys : ndarray, shape (N)
        the smoothed signal (or it's n-th derivative).
    Notes
    -----
    The Savitzky-Golay is a type of low-pass filter, particularly
    suited for smoothing noisy data. The main idea behind this
    approach is to make for each point a least-square fit with a
    polynomial of high order over a odd-sized window centered at
    the point.
    Examples
    --------
    t = np.linspace(-4, 4, 500)
    y = np.exp( -t**2 ) + np.random.normal(0, 0.05, t.shape)
    ysg = savitzky_golay(y, window_size=31, order=4)
    import matplotlib.pyplot as plt
    plt.plot(t, y, label='Noisy signal')
    plt.plot(t, np.exp(-t**2), 'k', lw=1.5, label='Original signal')
    plt.plot(t, ysg, 'r', label='Filtered signal')
    plt.legend()
    plt.show()
    References
    ----------
    .. [1] A. Savitzky, M. J. E. Golay, Smoothing and Differentiation of
       Data by Simplified Least Squares Procedures. Analytical
       Chemistry, 1964, 36 (8), pp 1627-1639.
    .. [2] Numerical Recipes 3rd Edition: The Art of Scientific Computing
       W.H. Press, S.A. Teukolsky, W.T. Vetterling, B.P. Flannery
       Cambridge University Press ISBN-13: 9780521880688
    """
    import numpy as np
    from math import factorial

    try:
        window_size = np.abs(np.int(window_size))
        order = np.abs(np.int(order))
    except ValueError, msg:
        raise ValueError("window_size and order have to be of type int")
    if window_size % 2 != 1 or window_size < 1:
        raise TypeError("window_size size must be a positive odd number")
    if window_size < order + 2:
        raise TypeError("window_size is too small for the polynomials order")
    order_range = range(order+1)
    half_window = (window_size -1) // 2
    # precompute coefficients
    b = np.mat([[k**i for i in order_range] for k in range(-half_window, half_window+1)])
    m = np.linalg.pinv(b).A[deriv] * rate**deriv * factorial(deriv)
    # pad the signal at the extremes with
    # values taken from the signal itself
    firstvals = y[0] - np.abs( y[1:half_window+1][::-1] - y[0] )
    lastvals = y[-1] + np.abs(y[-half_window-1:-1][::-1] - y[-1])
    y = np.concatenate((firstvals, y, lastvals))
    return np.convolve( m[::-1], y, mode='valid')
def savitzky_golay(y,窗口大小,订单,利率=0,利率=1):
使用Savitzky-Golay过滤器使数据平滑(并可选择性地进行区分)。
Savitzky-Golay滤波器从数据中去除高频噪声。
它的优点是保留了原始的形状和形状
信号的特性优于其他类型的滤波
方法,如移动平均技术。
参数
----------
y:数组_-like,形状(N,)
信号的时间历史值。
窗口大小:int
窗口的长度。必须是奇数整数。
订单:int
滤波中使用的多项式的阶数。
必须小于“窗口大小”-1。
德里夫:int
要计算的导数顺序(默认值=0表示仅平滑)
退换商品
-------
ys:ndarray,形状(N)
平滑信号(或其第n阶导数)。
笔记
-----
Savitzky-Golay是一种低通滤波器,特别是
适用于平滑噪声数据。其主要思想是
这种方法是用一个最小二乘法对每个点进行拟合
以中心为中心的奇数窗口上的高阶多项式
重点。
例子
--------
t=np.linspace(-4500)
y=np.exp(-t**2)+np.random.normal(0,0.05,t.shape)
ysg=savitzky_golay(y,窗口尺寸=31,订单=4)
将matplotlib.pyplot作为plt导入
plt.绘图(t,y,label='noise signal')
plt.plot(t,np.exp(-t**2),'k',lw=1.5,标签='原始信号')
plt.plot(t,ysg,'r',label='Filtered signal')
plt.legend()
plt.show()
工具书类
----------
[1]A.Savitzky,M.J.E.Golay,光滑与微分
简化最小二乘法数据.分析法
《化学》,1964年,第36(8)页,第1627-1639页。
…[2]数字配方第3版:科学计算的艺术
W.H.出版社,S.A.Teukolsky,W.T.Vetterling,B.P.弗兰纳里
剑桥大学出版社ISBN-13:9780521880688
"""
将numpy作为np导入
从数学导入阶乘
尝试:
窗口大小=np.abs(np.int(窗口大小))
订单=np.abs(np.int(订单))
除了ValueError,msg:
raise VALUE ERROR(“窗口大小和顺序必须为int类型”)
如果窗口大小为%2!=1或窗口大小<1:
raise TypeError(“窗口大小必须为正奇数”)
如果窗口大小<订单+2:
raise TypeError(“窗口大小对于多项式顺序来说太小”)
订单\范围=范围(订单+1)
半窗口=(窗口大小-1)//2
#预计算系数
b=np.mat([[k**i表示顺序范围内的i]表示范围内的k(-half_窗口,half_窗口+1)])
m=np.linalg.pinv(b.A[deriv]*速率**deriv*阶乘(deriv)
#在极端情况下,使用
#从信号本身获取的值
firstvals=y[0]-np.abs(y[1:half_window+1][::-1]-y[0])
lastvals=y[-1]+np.abs(y[-half_window-1:-1][:-1]-y[-1])
y=np.连接((第一个VAL,y,最后一个VAL))
返回np.convolve(m[:-1],y,mode='valid')

有人知道为什么以及如何修复它吗?

这样的事情对于几种基于多项式的插值/平滑技术来说是典型的。(我没有计算你这里是否有一个实际的1/x函数。)近似像1/x这样的函数可能会使你过冲到负值(频率和程度取决于你使用的多项式的阶数:n阶可能会使你在符号上有n-1的变化)。 “修复”方法是使用optimize.curve_fit()而不是过滤器,并将函数定义为

def f(x, a, b, c, d): 
     return a/(x-b)**c + d

此过滤器在
scipy.signal.savgol\u过滤器中实现。您使用的是统一采样数据吗?否则它将不起作用(即,您需要在均匀采样的栅格上对其进行插值)。否则,尝试降低多项式的阶数。