Python 将高斯滤波器应用于一维数据”;亲手;使用Numpy
我有一个非均匀采样的数据,我正试图应用高斯滤波器。我正在使用python的numpy库来解决这个问题。数据为XY类型,如下所示: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
[[ -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轴,使其围绕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
?关于你的解决方案:1half_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
。查看我的最新帖子。