數據平滑處理-均值|中值|Savitzky-Golay濾波器

均值濾波器

均值濾波器是一種使用頻次較高的線性濾波器。它的實現原理很簡單,就是指定一個長度大小爲奇數的窗口,使用窗口中所有數據的平均值來替換中間位置的值,然後平移該窗口,平移步長爲 1,繼續重複上述操作,直至滑動到時序數據的末尾,如此一來,對時序數據的過濾操作就結束了。均值濾波器的思路簡單,計算速度快,但是它容易被窗口中的極值點或者峯值所左右,不能很好地保留序列的邊緣信息,在去噪的同時也對數據信號的細節特徵產生了一定的破壞,不能很好地去除噪聲點,這極大地影響了模型的預測精度。
均值濾波的公式

 

其中,m表示窗口大小,xi表示窗口中的第 i個數據,x表示窗口中所有數據的均值。
python代碼實現均值濾波
# 1. 均值濾波函數
def moving_average(data, window=5):
    size = window - 1
    arr_value = list(data.values)
    fill_left = arr_value[0]
    for i in range(size):
        arr_value.insert(0, fill_left)
    dat = pd.Series(arr_value)
    dat_roll = dat.rolling(window).mean()
    return dat_roll.dropna().reset_index(drop=True)

具體應用到數據上:高頻數據未完全擬合,其他數據也與源數據擬合程度一般

 

 中值濾波器

中值濾波是一種非線性的濾波算法,它是將指定長度大小爲奇數的窗口中的所有數據按從小到大的順序進行排列,並將排好序的數據的中值取代窗口中間的值。中值濾波克服了均值濾波所存在的問題,對窗口中的極端值不敏感,從而可以有效保留區域中的邊緣信息,並且能有效抑制椒鹽噪聲和脈衝噪聲,避免細節特徵的丟失。但是,在面對均勻分佈的高斯噪聲時,它表現很差。
中值濾波的公式見式

 

 具體的python實現代碼如下:

# 2. 中值濾波函數
def median_filter(data: pd.Series, window=5):
    return pd.Series(scipy.signal.medfilt(data, window))

應用到數據上:中值濾波將高頻擬合,其他數據也與源數據擬合程度一般

 

 SG濾波器

 對曲線進行平滑處理,通過Savitzky-Golay 濾波器,可以在scipy庫裏直接調用,不需要再定義函數。

python代碼實現:

from scipy.signal import savgol_filter
# 3. Savitzky-Golay濾波函數
newans = savgol_filter(data, 5, 3, mode= 'nearest')

plt.plot(index,data,label='源網絡流量',color='r',linestyle='-',marker='*')
plt.plot(index,newans,label='SG濾波網絡流量',color='b')#添加linestyle設置線條類型
plt.legend()
plt.show()

# 備註:
data:代表曲線點座標(x,y)中的y值數組
window_length:窗口長度,該值需爲正奇整數。例如:此處取值5
k值:polyorder爲對窗口內的數據點進行k階多項式擬合,k的值需要小於window_length。例如:此處取值3
mode:確定了要應用濾波器的填充信號的擴展類型。(This determines the type of extension to use for the padded signal to which the filter is applied. )

python原理手寫代碼實現:

# 3. Savitzky-Golay濾波函數
"""
  data - list格式的1×n緯數據
  window_size - 擬合的窗口大小
  rank - 擬合多項式階次
  ndata - 修正後的值
"""
def savgol(data: list, window_size: int, rank: int):
    m = int((window_size - 1) / 2)
    odata = data[:]
    # 處理邊緣數據,首尾增加m個首尾項
    for i in range(m):
        odata.insert(0, odata[0])
        odata.insert(len(odata), odata[len(odata)-1])
    # 創建X矩陣
    x = create_x(m, rank)
    # 計算加權係數矩陣B
    b = (x * (x.T * x).I) * x.T
    a0 = b[m]
    a0 = a0.T
    # 計算平滑修正後的值
    ndata = []
    for i in range(len(data)):
        y = [odata[i + j] for j in range(window_size)]
        y1 = np.mat(y) * a0
        y1 = float(y1)
        ndata.append(y1)
    return ndata

"""
  創建係數矩陣X
  size - 2×size+1 = window_size
  rank - 擬合多項式階次
  x - 創建的係數矩陣
"""
def create_x(size, rank):
    x = []
    for i in range(2 * size + 1):
        m = i - size
        row = [m**j for j in range(rank)]
        x.append(row)
    x = np.mat(x)
    return x

newans = savgol(list(data), 5, 3)

plt.plot(index,data,label='源網絡流量',color='r',linestyle='-',marker='*')
plt.plot(index,newans,label='SG濾波網絡流量',color='b')#添加linestyle設置線條類型
plt.legend()
plt.show()

應用到數據上效果:此圖更加接近源曲線,並且將高頻部分進行平滑處理,擬合低頻部分

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章