天天看點

時間序列異常值檢測——Prophet算法

作者:青銅算法進階之路

Prophet算法概述

Prophet由facebook開源的基于python和R語言的資料預測工具,基于時間和變量值結合時間序列分解和機器學習的拟合來做的;可以解決大部分的實際場景中的對單項值的預測,也可以用于時間序列資料的異常值檢測以及缺失值填充;

一般會把時間序列拆分成幾個部分,分别是s(t)季節項:表示周期項,或者稱為季節項,一般以周者年為機關;趨勢項g(t):表示時間序列在非周期上面的變化趨勢;假期項h(t):表示在當天是否存在節假日;剩餘項εt:表示誤差項或者稱為剩餘項;

時間序列異常值檢測——Prophet算法

Prophet算法就是通過拟合這幾項,最後把它們累加起來就得到時間序列的預測值;

Prophet算法實戰

Prophet需要導入包

from fbprophet import Prophet
import pandas as pd
import numpy as np
import warnings
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['KaiTi']
mpl.rcParams['font.serif'] = ['KaiTi']
mpl.rcParams['axes.unicode_minus']=False #用來正常顯示負号
warnings.filterwarnings('ignore')           

模型需要導入的資料格式如下圖,資料列名要保持一緻,時間列為ds,對應資料為y;

時間序列異常值檢測——Prophet算法

加入假期分量,時間可以根據實際需求适當擴充,代碼部分如下:

#端午假期
duanwu = pd.DataFrame({
    'holiday': 'duanwu',
    'ds':pd.date_range('2022-06-01', periods =7 , freq = 'D')})
#中秋假期
zhongqiu = pd.DataFrame({
    'holiday': 'zhongqiu',
    'ds':pd.date_range('2022-09-08', periods =7 , freq = 'D')})
#國慶
guoqing = pd.DataFrame({
    'holiday':'guoqing',
    'ds':pd.date_range('2022-09-28', periods =11 , freq = 'D'),
    })
#元旦
yuandan = pd.DataFrame({
    'holiday': 'yuandan',
    'ds': pd.date_range('2022-12-29', periods =7 , freq = 'D'),
})
#春節假期
chunjie = pd.DataFrame({
    'holiday': 'chunjie',
    'ds':pd.date_range('2023-01-19', periods =11 , freq = 'D')})
#合并假期資料
holidays = pd.concat((chunjie,duanwu,zhongqiu,yuandan,guoqing))            

模型訓練、預測以及輸出結果,0.95的置信區間;

m = Prophet(
            holidays=holidays,
            yearly_seasonality=8,
            weekly_seasonality=8,
            daily_seasonality=20,
            changepoint_prior_scale=0.04,
            growth='linear',
            interval_width = 0.95
            )
#指定節假日參數,
#對過去資料進行訓練
m.fit(df)  
forecast = m.predict(df)
forecast["y"] = df["y"].reset_index(drop = True)
forecast[["ds","y","yhat","yhat_lower","yhat_upper"]].head()           
時間序列異常值檢測——Prophet算法

模型自帶畫圖,畫出趨勢分量、周期分量、假期分量以及剩餘項;

m.plot_components(forecast)
plt.show()           
時間序列異常值檢測——Prophet算法
時間序列異常值檢測——Prophet算法
時間序列異常值檢測——Prophet算法

模型自帶畫圖,畫出模型的預測結果、置信區間、原始散點圖;

m.plot(forecast)
plt.show()           
時間序列異常值檢測——Prophet算法

Prophet異常資料檢測

對于原始資料落于置信區間之外的點可以認為是時間序列的異常值,異常值檢測代碼如下:

#異常值索引
def outlier_detection(forecast):
    index = np.where((forecast["y"] <= forecast["yhat_lower"])|
                     (forecast["y"] >= forecast["yhat_upper"]),True,False)
    return index
outlier_index = outlier_detection(forecast)
outlier_df = df[outlier_index]
print(outlier_df)
print("異常值的數量為:",np.sum(outlier_index))           
時間序列異常值檢測——Prophet算法

異常檢測資料可視化代碼如下:

# 可視化異常值的結果
fig, ax = plt.subplots()
## 可視化預測值
forecast.plot(x = "ds",y = "yhat",style = "b-",figsize=(14,7),
              label = "預測值",ax=ax)
## 可視化出置信區間
ax.fill_between(forecast["ds"].values, forecast["yhat_lower"].values,
                forecast["yhat_upper"].values,color='b',alpha=.2,
                label = "95%置信區間")
forecast.plot(kind = "scatter",x = "ds",y = "y",c = "k",
              s = 20,label = "原始資料",ax = ax)
## 可視化出異常值的點
outlier_df.plot(kind = "scatter",x = "ds",y = "y",ax = ax,
                c = "red",label = "異常值")
plt.grid()
plt.title("時間序列異常點檢測")
plt.show()           
時間序列異常值檢測——Prophet算法

對于異常檢測的資料模型預測出的結果進行回填,時間序列原始資料、與異常檢測後資料進行對比,代碼如下:

dfnew = df.copy()
dfnew['y'][outlier_index] =forecast["yhat"][outlier_index]
fig, ax = plt.subplots()
plt.plot(df['y'],label='原始資料')
plt.plot(dfnew['y'],label='處理後')
plt.legend(loc = 2)
plt.grid()
plt.title("時間序列處理對比圖")
plt.show()           
時間序列異常值檢測——Prophet算法

Prophet缺失值填充

對于時間序列的缺失值,同樣可采用上述方式,缺失值用預測值進行回填,代碼如下:

#空值索引
def null_detection(forecast):
    index = np.where(pd.isna(forecast["y"]),True,False)
    return index
null_index = null_detection(forecast)
dfnew = df.copy()
dfnew['y'][null_index] =forecast["yhat"][null_index]           
時間序列異常值檢測——Prophet算法

繼續閱讀