Python 将高斯滤波器应用于一维数据”;亲手;使用Numpy

Python 将高斯滤波器应用于一维数据”;亲手;使用Numpy,python,numpy,convolution,Python,Numpy,Convolution,我有一个非均匀采样的数据,我正试图应用高斯滤波器。我正在使用python的numpy库来解决这个问题。数据为XY类型,如下所示: [[ -0.96 390.63523024] [ -1.085 390.68523024] [ -1.21 390.44023023] ... [-76.695 390.86023024] [-77.105 392.51023024] [-77.155 392.10023024]] import num

我有一个非均匀采样的数据,我正试图应用高斯滤波器。我正在使用python的numpy库来解决这个问题。数据为XY类型,如下所示:

[[ -0.96       390.63523024]
[ -1.085      390.68523024]
[ -1.21       390.44023023]
...
[-76.695      390.86023024]
[-77.105      392.51023024]
[-77.155      392.10023024]]
import numpy as np
import matplotlib.pyplot as plt

xy = np.load('1D_data.npz')['arr_0']

def g_func(xx, w=1.0):
    a = 0.47 * w
    return (1 / a) * np.exp((xx / a) ** 2 * (-np.pi))

x, y, x_, y_ = xy[:, 0], xy[:, 1], [], []

counter, xi, ww = 0, x[0], 1.0
while xi > np.amin(x):

    curr_x = x[(x < xi) & (x >= xi - 2 * ww)]
    g, ysel = [], []
    for i, els in enumerate(curr_x):
        xil = els - curr_x[0] + abs(curr_x[0] - curr_x[-1]) / 2
        g.append(g_func(xil, ww))
        ysel.append(y[counter + i])

    y_.append(np.sum(np.multiply(g, ysel)) / len(g))
    x_.append(xi)

    counter += 1
    xi = x[counter]

plt.plot(x, y, '-k')
plt.plot(x_, y_, '-r')
plt.show()
并且是指向整个*.npz文件的链接

我的做法如下:

  • 我从定义高斯函数开始
  • 然后我开始沿着X轴用while循环扫描数据
  • 在循环的每个步骤中:
    • 我选择两个截止长度内的一部分数据
    • 移动选定数据部分的X轴,使其围绕0对称
    • 计算每个点的高斯函数,乘以相应的Y值,求和并除以元素数
  • 转到下一点
  • 下面是代码的外观:

    [[ -0.96       390.63523024]
    [ -1.085      390.68523024]
    [ -1.21       390.44023023]
    ...
    [-76.695      390.86023024]
    [-77.105      392.51023024]
    [-77.155      392.10023024]]
    
    import numpy as np
    import matplotlib.pyplot as plt
    
    xy = np.load('1D_data.npz')['arr_0']
    
    def g_func(xx, w=1.0):
        a = 0.47 * w
        return (1 / a) * np.exp((xx / a) ** 2 * (-np.pi))
    
    x, y, x_, y_ = xy[:, 0], xy[:, 1], [], []
    
    counter, xi, ww = 0, x[0], 1.0
    while xi > np.amin(x):
    
        curr_x = x[(x < xi) & (x >= xi - 2 * ww)]
        g, ysel = [], []
        for i, els in enumerate(curr_x):
            xil = els - curr_x[0] + abs(curr_x[0] - curr_x[-1]) / 2
            g.append(g_func(xil, ww))
            ysel.append(y[counter + i])
    
        y_.append(np.sum(np.multiply(g, ysel)) / len(g))
        x_.append(xi)
    
        counter += 1
        xi = x[counter]
    
    plt.plot(x, y, '-k')
    plt.plot(x_, y_, '-r')
    plt.show()
    
    将numpy导入为np
    将matplotlib.pyplot作为plt导入
    xy=np.load('1D_data.npz')['arr_0']
    def g_func(xx,w=1.0):
    a=0.47*w
    报税表(1/a)*np.exp((xx/a)**2*(-np.pi))
    x、 y,x,y=xy[:,0],xy[:,1],[]
    计数器,席,WW=0,X〔0〕,1
    席奚NP .阿明(X):
    Currxx= x[(x<席)和(x>=席2×Ww)]
    g、 ysel=[],[]
    对于i,枚举中的els(curr_x):
    xil=els-curr\ux[0]+abs(curr\ux[0]-curr\ux[-1])/2
    g、 附加(g_func(xil,ww))
    ysel.append(y[计数器+i])
    追加(np.sum(np.multiply(g,ysel))/len(g))
    附加(xi)
    计数器+=1
    席= X [计数器]
    plt.绘图(x,y,'-k')
    plt.plot(x_u,y_u,'-r')
    plt.show()
    
    但是输出看起来不正确。(参见下图)即使丢弃边缘,卷积也是非常嘈杂的,并且值似乎与数据不对应。我可能做错了什么


    您在代码中犯了一个错误:

    在将
    g
    y_sel
    相乘之前,
    y_sel
    未居中。

    y_sel
    应该居中的原因是,我们希望将高斯加权的相对差值添加到中心的条目中。如果将
    g
    y_sel
    直接相乘,则不仅窗口内相邻项的值,而且中心项的值将通过高斯函数进行加权。这肯定会极大地改变函数值

    下面是我使用
    numpy

    def g_func(xx, w=1.0):
        mean = np.mean(xx)
        a = 0.47 * w
        return (1 / a) * np.exp(((xx-mean) / a) ** 2 * (-np.pi))
    
    
    def get_convolution(array,half_window_size):
        
        array = np.concatenate((np.repeat(array[0],half_window_size),
                                array,
                                np.repeat(array[-1],half_window_size)))
        window_inds = [list(range(ind-half_window_size,ind+half_window_size+1)) \
                       for ind in range(half_window_size,len(array)-half_window_size)]
        
        return np.take(array,window_inds)
    
    xy = np.load('1D_data.npz')['arr_0']
    x, y = xy[:, 0], xy[:, 1]
    
    half_window_size = 4
    x_conv = np.apply_along_axis(g_func,axis=1,arr=get_convolution(x,half_window_size=half_window_size))
    y_conv = get_convolution(y,half_window_size=half_window_size)
    y_mean = np.mean(y_conv,axis=1)
    y_centered = y_conv - y_mean[:,None]
    smoothed = np.sum(x_conv*y_centered,axis=1) / (half_window_size*2) + y_mean
    
    fig,ax = plt.subplots(figsize=(10,6))
    ax.plot(x, y, '-k')
    ax.plot(x, smoothed, '-r')
    
    运行代码时,输出为


    更新

    为了将
    w
    half_window_size
    统一起来,这里有一种可能性,其想法是让高斯的标准偏差为
    2*half_window_size

    def g_func(xx):
        
        std = len(xx)
        mean = np.mean(xx)
        return 1 / (std*np.sqrt(2*np.pi)) * np.exp(-1/2*((xx-mean)/std)**2)
    
    
    def get_convolution(array,half_window_size):
        
        array = np.concatenate((np.repeat(array[0],half_window_size),
                                array,
                                np.repeat(array[-1],half_window_size)))
        window_inds = [list(range(ind-half_window_size,ind+half_window_size+1)) \
                       for ind in range(half_window_size,len(array)-half_window_size)]
        
        return np.take(array,window_inds)
    
    xy = np.load('1D_data.npz')['arr_0']
    x, y = xy[:, 0], xy[:, 1]
    
    half_window_size = 4
    x_conv = np.apply_along_axis(g_func,axis=1,arr=get_convolution(x,half_window_size=half_window_size))
    y_conv = get_convolution(y,half_window_size=half_window_size)
    y_mean = np.mean(y_conv,axis=1)
    y_centered = y_conv - y_mean[:,None]
    smoothed = np.sum(x_conv*y_centered,axis=1) / (half_window_size*2) + y_mean
    
    fig,ax = plt.subplots(figsize=(10,6))
    ax.plot(x, y, '-k')
    ax.plot(x, smoothed, '-r')
    

    我知道这可能是一个愚蠢的问题,但有没有具体的原因让你不简单地使用scipy的
    gaussian\u filter1d()
    ?@Asmus我想用我自己的解决方案来调整窗口函数的形状。而且这看起来不是一个非常复杂的任务。。不知道我做错了什么。无论如何,谢谢你的评论!那么,您是想手工编写所有内容,还是使用带有“手动”过滤功能的
    np.convolve()
    也可以?是的,我正在考虑完全手动编写。你是想说这是一项太难的任务吗?不,不一定。我认为,在这一过程中,您将学到很多关于python/numpy/编码的有用知识,但最终也可能会得到一个效率不高/兼容性不强的解决方案;-)明天我会再看一遍,但到目前为止,我承认很难理解你的代码(这不一定是你的错!)。你能评论一下
    np.sum(np.multiply(g,ysel))/len(g)
    这行应该做什么吗?@meTchaikovsky感谢你的反馈和努力!我将在两个评论中反映,使其更有条理。首先,关于对我的解决方案的反馈:1。实际上,我减去平均值,我在循环的每个循环中进行:
    xil=els-curr\ux[0]+abs(curr\ux[0]-curr\ux[-1])/2
    2。这一部分我不明白,为什么我需要在与高斯相乘之前居中
    ysel
    ?关于你的解决方案:1
    half_window_size
    实际上,窗口大小由高斯宽度定义,即
    w
    参数。否则,过滤有点奇怪:它取决于主程序中定义的两个参数“半窗口大小”和函数定义2中定义的“w”
    y_居中
    我仍然不明白为什么在与高斯贝尔相乘之前需要将选定的y值居中。你能再多评论一下吗?同时,我喜欢您引入
    get\u卷积
    函数进行数据选择的方法。很好@不客气,我很高兴我帮了忙。对不起,我的第一个错误在我原来的帖子,我已经删除了它在我的更新后的帖子。至于
    y_sel
    应该居中的原因,有两个原因:1。如果不减去平均值,中心值也将由高斯分布加权。2.我们想要的是将高斯加权的相对差值添加到中心。感谢更新!关于第二条评论。我考虑了如何使代码中的
    half\u window\u size
    参数依赖于高斯分布的宽度。这里有一个建议:1。在代码2中的某个位置定义
    w
    的值。将行
    half_window_size=4
    替换为
    half_window_size=int(x.shape[0]/(abs(x[0]-x[-1])/ww))
    3。将相应的
    w
    参数定义添加到带有
    np的行中。沿\u轴应用\u
    。你觉得怎么样?@Bulat不客气:)我想你可以简单地去掉
    w
    ,换成
    half\u window\u size
    。查看我的最新帖子。