[開發技巧]·Python極簡實現滑動平均濾波(基於Numpy.convolve)

[開發技巧]·Python極簡實現滑動平均濾波(基於Numpy.convolve)


1.滑動平均概念

滑動平均濾波法(又稱遞推平均濾波法),時把連續取N個採樣值當作一個隊列 ,隊列的長度固定爲N ,每次採樣到一個新數據放入隊尾,並扔掉原來隊首的一次數據.(先進先出原則)  把隊列中的N個數據進行算術平均運算,就可得到新的濾波結果。N值的選取:流量,N=12;壓力:N=4;液麪,N=4~12;溫度,N=1~4 python

優勢:  對週期性干擾有良好的抑制做用,平滑度高  適用於高頻振盪的系統  算法

缺點:  靈敏度低  對偶然出現的脈衝性干擾的抑制做用較差  不易消除因爲脈衝干擾所引發的採樣值誤差  不適用於脈衝干擾比較嚴重的場合  比較浪費RAM  數組

 

2.解決思路

能夠發現滑動平均濾波法計算很相似與一維卷積的工做原理,滑動平均的N就對應一維卷積核大小(長度)。app

步長會有些區別,滑動平均濾波法滑動步長爲1,而一維卷積步長能夠自定義。還有區別就是一維卷積的核參數是須要更新迭代的,而滑動平均濾波法核參數都是一。框架

咱們應該怎麼利用這個類似性呢?其實也很簡單,只須要把一維卷積核大小(長度)和N相等,步長設置爲1,核參數都初始爲1就能夠了。因爲一維卷積具有速度快,而後咱們就可使用一維卷積來實現這個功能了,快速高效。學習

使用深度學習框架實現這個功能是否有些大材小用了?是有些大材小用了,由於這裏使用卷積的核參數不用更新,其實不必使用複雜的深度學習框架,若是Numpy中能夠實現這些功能就更簡單方便了。spa

說幹就幹,通過查找發現Numpy.convolve能夠實現咱們想要的功能。code

 

3.Numpy.convolve介紹

numpy.convolve(a, v, mode=‘full’)
參數:
    a:(N,)輸入的一維數組
    v:(M,)輸入的第二個一維數組
    mode:{‘full’, ‘valid’, ‘same’}參數可選
      ‘full’ 默認值,返回每個卷積值,長度是N+M-1,在卷積的邊緣處,信號不重疊,存在邊際效應。
      ‘same’ 返回的數組長度爲max(M, N),邊際效應依舊存在。
      ‘valid’  返回的數組長度爲max(M,N)-min(M,N)+1,此時返回的是徹底重疊的點。邊緣的點無效。blog

和一維卷積參數相似,a就是被卷積數據,v是卷積核大小。隊列

 

4.算法實現

def np_move_avg(a,n,mode="same"):
    return(np.convolve(a, np.ones((n,))/n, mode=mode))

原理說明

運行平均值是卷積數學運算的一個例子。對於運行平均值,沿着輸入滑動窗口並計算窗口內容的平均值。對於離散的1D信號,卷積是相同的,除了代替計算任意線性組合的平均值,即將每一個元素乘以相應的係數並將結果相加。那些係數,一個用於窗口中的每一個位置,有時稱爲卷積。如今,N值的算術平均值是(x_1 + x_2 + ... + x_N) / N,因此相應的內核是(1/N, 1/N, ..., 1/N),這正是咱們經過使用獲得的np.ones((N,))/N

邊緣處理

mode的參數np.convolve指定如何處理邊緣。在這裏選擇了same模式,這樣能夠保證輸出長度一種,但你可能還有其餘優先事項。這是一個說明模式之間差別的圖:

import numpy as np
import matplotlib.pyplot as plt

def np_move_avg(a,n,mode="same"):
    return(np.convolve(a, np.ones((n,))/n, mode=mode))

modes = ['full', 'same', 'valid']
for m in modes:
    plt.plot(np_move_avg(np.ones((200,)), 50, mode=m));

plt.axis([-10, 251, -.1, 1.1]);

plt.legend(modes, loc='lower center');

plt.show()

5.參考

1.https://stackoverflow.com/questions/13728392/moving-average-or-running-mean

相關文章
相關標籤/搜索