信号的 Numpy 均方根 (RMS) 平滑
问题描述
我有一个肌电数据信号,我应该(科学论文的明确建议)使用 RMS 进行平滑处理.
I have a signal of electromyographical data that I am supposed (scientific papers' explicit recommendation) to smooth using RMS.
我有以下工作代码,产生所需的输出,但它比我想象的要慢.
I have the following working code, producing the desired output, but it is way slower than I think it's possible.
#!/usr/bin/python
import numpy
def rms(interval, halfwindow):
""" performs the moving-window smoothing of a signal using RMS """
n = len(interval)
rms_signal = numpy.zeros(n)
for i in range(n):
small_index = max(0, i - halfwindow) # intended to avoid boundary effect
big_index = min(n, i + halfwindow) # intended to avoid boundary effect
window_samples = interval[small_index:big_index]
# here is the RMS of the window, being attributed to rms_signal 'i'th sample:
rms_signal[i] = sqrt(sum([s**2 for s in window_samples])/len(window_samples))
return rms_signal
我已经看到了一些关于移动窗口循环优化的 deque
和 itertools
建议,以及来自 numpy 的 convolve
,但我不能弄清楚如何使用它们来完成我想要的.
I have seen some deque
and itertools
suggestions regarding optimization of moving window loops, and also convolve
from numpy, but I couldn't figure it out how to accomplish what I want using them.
此外,我不再关心避免边界问题,因为我最终得到了大数组和相对较小的滑动窗口.
Also, I do not care to avoid boundary problems anymore, because I end up having large arrays and relatively small sliding windows.
感谢阅读
解决方案
可以使用卷积来执行您所指的操作.为了处理脑电信号,我也做了几次.
It is possible to use convolution to perform the operation you are referring to. I did it a few times for processing EEG signals as well.
import numpy as np
def window_rms(a, window_size):
a2 = np.power(a,2)
window = np.ones(window_size)/float(window_size)
return np.sqrt(np.convolve(a2, window, 'valid'))
分解后,np.power(a, 2)
部分创建了一个与 a
维度相同的新数组,但每个值都是平方的.np.ones(window_size)/float(window_size)
产生一个数组或长度window_size
,其中每个元素是1/window_size
.所以卷积有效地产生了一个新数组,其中每个元素 i
等于
Breaking it down, the np.power(a, 2)
part makes a new array with the same dimension as a
, but where each value is squared. np.ones(window_size)/float(window_size)
produces an array or length window_size
where each element is 1/window_size
. So the convolution effectively produces a new array where each element i
is equal to
(a[i]^2 + a[i+1]^2 + … + a[i+window_size]^2)/window_size
这是移动窗口内数组元素的 RMS 值.它应该以这种方式表现得非常好.
which is the RMS value of the array elements within the moving window. It should perform really well this way.
但是请注意,np.power(a, 2)
会生成一个相同维度的 new 数组.如果 a
是 really 大,我的意思是足够大以至于它不能在内存中容纳两次,您可能需要一个策略来修改每个元素.此外,'valid'
参数指定丢弃边框效果,从而生成由 np.convolve()
生成的较小数组.您可以通过指定 'same'
来保留所有内容(请参阅 文档).
Note, though, that np.power(a, 2)
produces a new array of same dimension. If a
is really large, I mean sufficiently large that it cannot fit twice in memory, you might need a strategy where each element are modified in place. Also, the 'valid'
argument specifies to discard border effects, resulting in a smaller array produced by np.convolve()
. You could keep it all by specifying 'same'
instead (see documentation).
相关文章