Numpy Root-Mean-Squared(RMS)信号平滑

hel*_*ker 9 iteration numpy scipy smoothing moving-average

我有一个肌电数据的信号,我认为(科学论文的明确推荐),以平滑使用RMS.

我有以下工作代码,产生所需的输出,但它比我想象的要慢.

#!/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
Run Code Online (Sandbox Code Playgroud)

我已经看到了关于移动窗口循环优化的一些dequeitertools建议,也convolve来自numpy,但我无法弄清楚如何使用它们完成我想要的东西.

此外,我不在乎避免边界问题,因为我最终拥有大型阵列和相对较小的滑动窗口.

谢谢阅读

mat*_*hat 13

可以使用卷积来执行你指的操作.我也做了几次处理EEG信号.

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'))
Run Code Online (Sandbox Code Playgroud)

将其分解,该np.power(a, 2)部分创建一个具有相同维度的新数组a,但每个值都是平方的.np.ones(window_size)/float(window_size)生成window_size每个元素所在的数组或长度1/window_size.因此卷积有效地产生了一个新的数组,其中每个元素i都相等

(a[i]^2 + a[i+1]^2 + … + a[i+window_size]^2)/window_size
Run Code Online (Sandbox Code Playgroud)

这是移动窗口内数组元素的RMS值.它应该以这种方式表现得非常好.

但请注意,它np.power(a, 2)会生成一个具有相同维度的数组.如果a大,我的意思是足够大的,它不能装入内存的两倍,你可能需要有一个策略,其中每个元素都在发生改变.此外,'valid'参数指定丢弃边框效果,从而产生较小的数组np.convolve().您可以通过指定'same'来保留所有内容(请参阅文档).