Python透過Scipy的convolve實踐Sliding Window Detrend
一般數位訊號如果出現某種逐漸遞增、遞減的趨勢
通常都需要做一個所謂去趨勢化(detrend)的前置處理。
scipy內建的detrend函數(scipy.signal.detrend)
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.detrend.html
是採用「簡單迴歸法」(最小平方法的線性迴歸)的移除趨勢方法
從時間序列資料中移除趨勢成分的函數,透過執行線性迴歸(嚴格來說是簡單迴歸)來移除趨勢。
演算法步驟
步驟 1:計算線性趨勢
針對資料使用最小平方法執行線性迴歸,也就是以直線近似資料的趨勢。
透過線性迴歸,可取得表示資料趨勢之直線的斜率與截距。
步驟 2:移除趨勢
將計算出的線性趨勢(直線)從原始資料中扣除。
如此一來,便可從資料中移除長期變動成分,僅保留雜訊成分。
和這次要實作的sliding window 方法不同
以下是藉由scipy.signal內建的convolve函數實作的滑動視窗去趨勢法
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve.html#scipy.signal.convolve
import numpy as np import matplotlib.pyplot as plt from scipy.signal import convolve # ========================================== # 1. 產生模擬訊號 (弦波 + 向上飄移的趨勢 + 雜訊) # ========================================== t = np.linspace(0, 10, 150) original_trend = 0.5 * t # 緩慢向上的線性趨勢 signal_data = np.sin(2 * np.pi * 1.0 * t) + original_trend + np.random.normal(0, 0.2, 150) # 2. 執行滑動視窗去趨勢 (使用卷積法) # ========================================== # 設置視窗大小為 15 window_size = 15 # 建立平均權重 Kernel kernel = np.ones(window_size) / window_size # 算出每個視窗內的平均值 (即抓出低頻趨勢) rolling_mean = convolve(signal_data, kernel, mode='same') # 原訊號減去平均值,完成去趨勢 (Detrend) detrended_signal = signal_data - rolling_mean # ========================================== plt.figure(figsize=(10, 6)) # 畫出原始訊號與抓出來的趨勢 plt.subplot(2, 1, 1) plt.plot(signal_data, label="Original Signal (with upward trend)", color='lightgray') plt.plot(rolling_mean, label=f"Rolling Mean (Trend, window={window_size})", color='red') plt.title("Original Signal vs Trend") plt.legend() # 畫出去趨勢後的結果 plt.subplot(2, 1, 2) plt.plot(detrended_signal, label="Detrended Signal", color='blue') plt.axhline(0, color='red', linestyle='--') # 畫出水平基準線 0 plt.title("After Sliding Window Detrending") plt.legend() plt.tight_layout() plt.show()
留言
張貼留言