Python 中的多线程一维中值滤波
Multithreading 1D Median Filtering in Python
我已尝试对时间序列信号进行以下python中值滤波,以找到最快和更有效的函数。
sig
是一个大小为 80×188
的 numpy
数组,其中包含由 80 个传感器测量的 188 个样本。
import numpy as np
from scipy.ndimage import median_filter
from scipy.signal import medfilt
from scipy.signal import medfilt2d
import time
sig = np.random.rand(80,188).astype('f')
print(type(sig))
print(type(sig[0][0]))
window_length = 181
t = time.time()
sigFiltered = medfilt2d(sig, (1,window_length))
elapsed = time.time() - t
print('scipy.signal.medfilt2d: %g seconds' % elapsed)
t = time.time()
sigFiltered = median_filter(sig, (1,window_length))
elapsed = time.time() - t
print('scipy.ndimage.median_filter: %g seconds' % elapsed)
t = time.time()
sigFiltered = medfilt(sig, (1,window_length))
elapsed = time.time() - t
print('scipy.signal.medfilt: %g seconds' % elapsed)
代码可以试一下here。
过滤器的结果是另一个大小为 80×188
的时间序列数组,每个传感器都有平滑的时间点。
MATLAB medfilt1
(sig, 181, [], 2)
performs the filtering on the same data 10 times faster compared to scipy.signal.medfilt2d
,这是其他函数中最快的。在我的机器上,MATLAB=2ms vs Python=20 ms。我认为 MATLAB 执行多线程处理而 python 没有。
有没有什么方法可以执行多线程中值过滤来加快进程并将传感器分配给不同的线程? python 中是否有更有效的中值过滤?我能否达到 MATLAB win python 或至少接近它的性能?
我想知道为什么您对 188 的数据长度使用 181 点的中值滤波器?过滤器太长了,以至于您实际上只是丢弃了所有数据,并用传感器输出的全局中值代替了它。典型的中值滤波器长度是几个样本,具体取决于您要滤除的瞬变类型。
过滤器长度也解释了为什么它这么慢。在我的机器上,您的 median_filter
示例需要 46 毫秒。 运行 3 个样本的更正常的过滤器大小需要 0.7 毫秒。
对于相对于输入的如此长的过滤器,使用标准 medfilt 的大多数输出将是相同的。如果这是一个卷积,这将是一个 "full" 卷积。如果您只为 "valid" 卷积提供输出,在这种情况下会快得多:
t = time.time()
medians = []
for i in range(188-181):
sig2 = sig[:, i:i+window_length]
f = np.median(sig2, axis=1)
medians.append(f)
sigFiltered = np.stack(medians).T
elapsed = time.time() - t
print('numpy.median: %g seconds' % elapsed)
numpy.median: 0.0015518 seconds
这在每 188 个样本大小所请求的 1 毫秒运行时间的大致范围内。
考虑到即使是这里的每个唯一值也会随着新的输入样本发生很大的变化 slowly/rarely。因此,您可以通过使用大于 1 的跃点来大大加快速度。
我已尝试对时间序列信号进行以下python中值滤波,以找到最快和更有效的函数。
sig
是一个大小为 80×188
的 numpy
数组,其中包含由 80 个传感器测量的 188 个样本。
import numpy as np
from scipy.ndimage import median_filter
from scipy.signal import medfilt
from scipy.signal import medfilt2d
import time
sig = np.random.rand(80,188).astype('f')
print(type(sig))
print(type(sig[0][0]))
window_length = 181
t = time.time()
sigFiltered = medfilt2d(sig, (1,window_length))
elapsed = time.time() - t
print('scipy.signal.medfilt2d: %g seconds' % elapsed)
t = time.time()
sigFiltered = median_filter(sig, (1,window_length))
elapsed = time.time() - t
print('scipy.ndimage.median_filter: %g seconds' % elapsed)
t = time.time()
sigFiltered = medfilt(sig, (1,window_length))
elapsed = time.time() - t
print('scipy.signal.medfilt: %g seconds' % elapsed)
代码可以试一下here。
过滤器的结果是另一个大小为 80×188
的时间序列数组,每个传感器都有平滑的时间点。
MATLAB medfilt1
(sig, 181, [], 2)
performs the filtering on the same data 10 times faster compared to scipy.signal.medfilt2d
,这是其他函数中最快的。在我的机器上,MATLAB=2ms vs Python=20 ms。我认为 MATLAB 执行多线程处理而 python 没有。
有没有什么方法可以执行多线程中值过滤来加快进程并将传感器分配给不同的线程? python 中是否有更有效的中值过滤?我能否达到 MATLAB win python 或至少接近它的性能?
我想知道为什么您对 188 的数据长度使用 181 点的中值滤波器?过滤器太长了,以至于您实际上只是丢弃了所有数据,并用传感器输出的全局中值代替了它。典型的中值滤波器长度是几个样本,具体取决于您要滤除的瞬变类型。
过滤器长度也解释了为什么它这么慢。在我的机器上,您的 median_filter
示例需要 46 毫秒。 运行 3 个样本的更正常的过滤器大小需要 0.7 毫秒。
对于相对于输入的如此长的过滤器,使用标准 medfilt 的大多数输出将是相同的。如果这是一个卷积,这将是一个 "full" 卷积。如果您只为 "valid" 卷积提供输出,在这种情况下会快得多:
t = time.time()
medians = []
for i in range(188-181):
sig2 = sig[:, i:i+window_length]
f = np.median(sig2, axis=1)
medians.append(f)
sigFiltered = np.stack(medians).T
elapsed = time.time() - t
print('numpy.median: %g seconds' % elapsed)
numpy.median: 0.0015518 seconds
这在每 188 个样本大小所请求的 1 毫秒运行时间的大致范围内。
考虑到即使是这里的每个唯一值也会随着新的输入样本发生很大的变化 slowly/rarely。因此,您可以通过使用大于 1 的跃点来大大加快速度。