首頁 > 軟體

python庫Tsmoothie模組資料平滑化異常點抓取

2022-06-10 22:04:06

前言

在處理資料的時候,我們經常會遇到一些非連續的散點時間序列資料:

有些時候,這樣的散點資料是不利於我們進行資料的聚類和預測的。因此我們需要把它們平滑化,如下圖所示:

如果我們將散點及其範圍區間都去除,平滑後的效果如下:

這樣的時序資料是不是看起來舒服多了?此外,使用平滑後的時序資料去做聚類或預測或許有令人驚豔的效果,因為它去除了一些偏差值並細化了資料的分佈範圍。

如果我們自己開發一個這樣的平滑工具,會耗費不少的時間。因為平滑的技術有很多種,你需要一個個地去研究,找到最合適的技術並編寫程式碼,這是一個非常耗時的過程。平滑技術包括但不限於:

  • 指數平滑
  • 具有各種視窗型別(常數、漢寧、漢明、巴特利特、布萊克曼)的折積平滑
  • 傅立葉變換的頻譜平滑
  • 多項式平滑
  • 各種樣條平滑(線性、三次、自然三次)
  • 高斯平滑
  • 二進位制平滑

所幸,有大佬已經為我們實現好了時間序列的這些平滑技術,並在GitHub上開源了這份模組的程式碼——它就是 Tsmoothie 模組。

1.準備

開始之前,你要確保Python和pip已經成功安裝在電腦上。

(可選1) 如果你用Python的目的是資料分析,可以直接安裝Anaconda,它內建了Python和pip.

(可選2) 此外,推薦大家用VSCode編輯器,它有許多的優點。

請選擇以下任一種方式輸入命令安裝依賴:

  • Windows 環境 開啟 Cmd (開始-執行-CMD)。
  • MacOS 環境 開啟 Terminal (command+空格輸入Terminal)。
  • 如果你用的是 VSCode編輯器 或 Pycharm,可以直接使用介面下方的Terminal.
pip install tsmoothie

(PS) Tsmoothie 僅支援Python 3.6 及以上的版本。

2.Tsmoothie 基本使用

為了嘗試Tsmoothie的效果,我們需要生成亂資料:

import numpy as np
import matplotlib.pyplot as plt
from tsmoothie.utils_func import sim_randomwalk
from tsmoothie.smoother import LowessSmoother
# 生成 3 個長度為200的亂資料組
np.random.seed(123)
data = sim_randomwalk(n_series=3, timesteps=200,
                      process_noise=10, measure_noise=30)

然後使用Tsmoothie執行平滑化:

# 平滑
smoother = LowessSmoother(smooth_fraction=0.1, iterations=1)
smoother.smooth(data)

通過 smoother.smooth_data 你就可以獲取平滑後的資料:

print(smoother.smooth_data)
# [[ 5.21462928 3.07898076 0.93933646 -1.19847767 -3.32294934
# -5.40678762 -7.42425709 -9.36150892 -11.23591897 -13.05271523
# ....... ....... ....... ....... ....... ]]

繪製效果圖:

3.基於Tsmoothie的極端異常值檢測

事實上,基於smoother生成的範圍區域,我們可以進行異常值的檢測:

可以看到,在藍色範圍以外的點,都屬於異常值。我們可以輕易地將這些異常值標紅或記錄,以便後續的處理。

_low, _up = smoother.get_intervals('sigma_interval', n_sigma=2)
series['low'] = np.hstack([series['low'], _low[:,[-1]]])
series['up'] = np.hstack([series['up'], _up[:,[-1]]])
is_anomaly = np.logical_or(
    series['original'][:,-1] > series['up'][:,-1],
    series['original'][:,-1] < series['low'][:,-1]
).reshape(-1,1)

假設藍色範圍interval的最大值為up、最小值為low,如果存在 data > up 或 data < low 則表明此資料是異常點。

使用以下程式碼通過捲動資料點進行平滑化和異常檢測,就能儲存得到上方的GIF動圖。

上滑檢視更多程式碼

# Origin: https://github.com/cerlymarco/MEDIUM_NoteBook/blob/master/Anomaly_Detection_RealTime/Anomaly_Detection_RealTime.ipynb
import numpy as np
import matplotlib.pyplot as plt
from celluloid import Camera
from collections import defaultdict
from functools import partial
from tqdm import tqdm
from tsmoothie.utils_func import sim_randomwalk, sim_seasonal_data
from tsmoothie.smoother import *
def plot_history(ax, i, is_anomaly, window_len, color='blue', **pltargs):
    posrange = np.arange(0,i)
    ax.fill_between(posrange[window_len:],
                    pltargs['low'][1:], pltargs['up'][1:],
                    color=color, alpha=0.2)
    if is_anomaly:
        ax.scatter(i-1, pltargs['original'][-1], c='red')
    else:
        ax.scatter(i-1, pltargs['original'][-1], c='black')
    ax.scatter(i-1, pltargs['smooth'][-1], c=color)
    ax.plot(posrange, pltargs['original'][1:], '.k')
    ax.plot(posrange[window_len:],
            pltargs['smooth'][1:], color=color, linewidth=3)
    if 'ano_id' in pltargs.keys():
        if pltargs['ano_id'].sum()>0:
            not_zeros = pltargs['ano_id'][pltargs['ano_id']!=0] -1
            ax.scatter(not_zeros, pltargs['original'][1:][not_zeros],
                       c='red', alpha=1.)
np.random.seed(42)
n_series, timesteps = 3, 200
data = sim_randomwalk(n_series=n_series, timesteps=timesteps,
                      process_noise=10, measure_noise=30)
window_len = 20
fig = plt.figure(figsize=(18,10))
camera = Camera(fig)
axes = [plt.subplot(n_series,1,ax+1) for ax in range(n_series)]
series = defaultdict(partial(np.ndarray, shape=(n_series,1), dtype='float32'))
for i in tqdm(range(timesteps+1), total=(timesteps+1)):
    if i>window_len:
        smoother = ConvolutionSmoother(window_len=window_len, window_type='ones')
        smoother.smooth(series['original'][:,-window_len:])
        series['smooth'] = np.hstack([series['smooth'], smoother.smooth_data[:,[-1]]])
        _low, _up = smoother.get_intervals('sigma_interval', n_sigma=2)
        series['low'] = np.hstack([series['low'], _low[:,[-1]]])
        series['up'] = np.hstack([series['up'], _up[:,[-1]]])
        is_anomaly = np.logical_or(
            series['original'][:,-1] > series['up'][:,-1],
            series['original'][:,-1] < series['low'][:,-1]
        ).reshape(-1,1)
        if is_anomaly.any():
            series['ano_id'] = np.hstack([series['ano_id'], is_anomaly*i]).astype(int)
        for s in range(n_series):
            pltargs = {k:v[s,:] for k,v in series.items()}
            plot_history(axes[s], i, is_anomaly[s], window_len,
                         **pltargs)
        camera.snap()
    if i>=timesteps:
        continue
    series['original'] = np.hstack([series['original'], data[:,[i]]])
print('CREATING GIF...') # it may take a few seconds
camera._photos = [camera._photos[-1]] + camera._photos
animation = camera.animate()
animation.save('animation1.gif', codec="gif", writer='imagemagick')
plt.close(fig)
print('DONE')

注意,異常點並非都是負面作用,在不同的應用場景下,它們可能代表了不同的意義。

比如在股票中,它或許可以代表著震盪行情中某種趨勢反轉的訊號。

或者在家庭用電量分析中,它可能代表著某個時刻的用電峰值,根據這個峰值我們可以此時此刻開啟了什麼樣的電器。

所以異常點的作用需要根據不同應用場景進行不同的分析,才能找到它真正的價值。

總而言之,Tsmoothie 不僅可以使用多種平滑技術平滑化我們的時序資料,讓我們的模型訓練更加有效,還可以根據平滑結果找出資料中的離群點,是我們做資料分析和研究的一個好幫手,非常有價值。

以上就是python庫Tsmoothie模組資料平滑化異常點抓取的詳細內容,更多關於python Tsmoothie異常點抓取的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com