【Python】Python時間序列預測 | 經(jīng)典季節(jié)性分解
今天給大家分享一種方法,,時間序列預測之seasonal_decompose使用移動平均線對時間序列數(shù)據(jù)進行季節(jié)性分解,Python實現(xiàn)和原理介紹。這是我在學習時間序列異常檢測時遇到的一個問題,通過收集資料并整理出一文,希望能對大家有所幫助!

原理介紹

季節(jié)性分解原理
所謂分解就是將時序數(shù)據(jù)分離成不同的成分,分解有:長期趨勢Trend、季節(jié)性Seasonality和隨機殘差Residuals。
季節(jié)性分解是將時間序列抽象分解為系統(tǒng)和非系統(tǒng)組件。
系統(tǒng)組件 :具有一致性或重復性的時間序列的組成部分,可以進行描述和建模。 非系統(tǒng)組件 :無法直接建模的時間序列的組成部分。
給定的時間序列被認為包括三個系統(tǒng)組件,包括等級,趨勢,季節(jié)性和一個稱為噪聲的非系統(tǒng)組件。
這些組件定義如下:
等級Level:時間序列中的平均值。 趨勢Trend:時間序列中的增加或減少值。 季節(jié)性Seasonality:時間序列中重復的短期周期。 隨機殘差Residuals :時間序列中的隨機變化。
decompose數(shù)據(jù)分解模型主要有兩類:相加模型additive和相乘模型multiplicative。
官方解釋是:
相加模型?
相乘模型?
其中,是均值項,?是趨勢項,是季節(jié)性周期項,是殘值項。一般的,理想的分解模型中殘值項應該是一個均值為0的隨機變量。
兩種模型的分解思路一致,首先通過對數(shù)據(jù)應用卷積濾波器去除季節(jié)性成分。每個時期的平滑序列的平均值就是返回的季節(jié)性成分。
這里以相加模型(additive)為例介紹。
STEP1分解趨勢項,采用中心化移動均值的方法
當??為奇數(shù)時:
當??為偶數(shù)時:
其中??為趨勢項, 為時間序列頻率, 為時間序列長度。結果為長度為? 的時間序列,為便于后續(xù)的向量計算,當超過上述下標的定義域時,其值,如
STEP2分解季節(jié)性周期項
采用原始時間序列減去趨勢項
將各個周期內相同頻率下的值平均化,得到季節(jié)項 figure
將 figure中心化,得到中心化的季節(jié)項figure,代碼可表述為
STEP3?計算殘差項
函數(shù)解析
statsmodels.tsa.seasonal.seasonal_decompose(
??x,model?=?‘additive‘,
??filt?=?None,period?=?None,two_side?=?True,
??extrapolate_trend?=?0)
參數(shù):
x:array_like,被分解的數(shù)據(jù)。model:{“additive”, “multiplicative”}, optional
"additive"(加法模型)和"multiplicative"(乘法模型)
fil:tarray_like, optional
用于濾除季節(jié)性成分的濾除系數(shù)。濾波中使用的具體移動平均法由two_side確定。
period:int, optional?系列的時期。
如果x不是pandas對象或x的索引沒有頻率,則必須使用。
如果x是具有時間序列索引的pandas對象,則覆蓋x的默認周期性。
two_sided:bool, optional?濾波中使用的移動平均法。
如果為True(默認),則使用filt計算居中的移動平均線。
如果為False,則濾波器系數(shù)僅用于過去的值。
extrapolate_trend:int or ‘freq’, optional
如果設置為> 0,則考慮到許多(+1)最接近的點,由卷積產生的趨勢將在兩端外推線性最小二乘法(如果two_side為False,則為單一個最小二乘)。
如果設置為“頻率”,請使用頻率最近點。設置此參數(shù)將導致趨勢或殘油成分中沒有NaN值。
三種方法獲取三個值。
trend?=?decomposition.trend
seasonal?=?decomposition.seasonal
residual?=?decomposition.resid
舉例說明

生成數(shù)據(jù)
import?numpy?as?np
import?pandas?as?pd
from?statsmodels.tsa.seasonal?import?seasonal_decompose
import?matplotlib.pyplot?as?plt
df?=?pd.DataFrame(np.random.randint(1,?10,?
??????????????????size=(365,?1)),?
????????columns=['value'],
????????index=pd.date_range('2021-01-01',?
??????????????????periods=365,?freq='D'))??
乘法序列分解
乘法法序列 = Level * Trend * Seasonality * Error
result_mul?=?seasonal_decompose(df['value'],?
?????????????model='multiplicative',?
?????????????extrapolate_trend='freq')
plt.rcParams.update({'figure.figsize':?(10,?10)})
result_mul.plot().suptitle('Multiplicative?Decompose')
plt.show()

加法序列分解
加法序列 = Level + Trend + Seasonality + Error
result_add?=?seasonal_decompose(df['value'],?
?????????????model='additive',?
?????????????extrapolate_trend='freq')
plt.rcParams.update({'figure.figsize':?(10,?10)})
result_add.plot().suptitle('Additive?Decompose')
plt.show()

季節(jié)性分解工具的說明
季節(jié)性分解是一中工具,分解主要用于時間序列分析,作為分析工具,它可用于為問題提供預測模型。
它提供了一種思考時間序列預測問題的結構化方法,通常在建模復雜性方面,特別是在如何最佳地捕獲給定模型中的每個組件方面。
在數(shù)據(jù)準備,模型選擇和模型調整期間,可能需要考慮和解決每一個組件。可以在對趨勢進行建模并從數(shù)據(jù)中減去趨勢時明確地解決它,或者通過為算法提供足夠的歷史記錄來隱式地解決趨勢(如果趨勢可能存在)。
季節(jié)性分解中加法模型或乘法模型均可能會或可能無法將的特定時間序列干凈或完美地分解。因為現(xiàn)實世界的問題是混亂和嘈雜的。可能存在加法和乘法組件。可能會出現(xiàn)增長趨勢,隨后呈下降趨勢。可能存在與重復季節(jié)性成分混合的非重復循環(huán)。
應用案例
在時間序列異常檢測中,定義了這么一個函數(shù),用于季節(jié)性檢測,并輸出最佳趨勢,即用線性回歸擬合最好的那個趨勢線。
def?check_seasonality(self,?x,?probable_periods):
????"""
????????季節(jié)性檢測
????????:param?x:
????????:param?probable_periods:
????????:return:
????????"""
????#?先做個線性回歸
????series_r2,?slope,?reg_line?=?self.do_linear_regression(x)
????best_r2?=?series_r2
????seasonality?=?False
????best_trend?=?0
????for?model_type?in?['additive',?'multiplicative']:
????????#?乘法序列?=?Trend?*?Seasonality?*?Error
????????#?加法序列?=?Trend?+?Seasonality?+?Error
????????for?period?in?probable_periods:
????????????if?not?(2?*?period?>?len(x.index)):
????????????????result?=?seasonal_decompose(pd.DataFrame(x.values,?columns=['value']),?model=model_type,
????????????????????????????????????????????freq=period)
????????????????trend?=?result.trend.copy()
????????????????trend.dropna(inplace=True)
????????????????#?做個線性回歸,擬合斜率
????????????????trend_r2,?trend_slope,?reg_trend_line?=?self.do_linear_regression(trend)
????????????????#?選擇r2最大的那個趨勢,作為最佳趨勢
????????????????if?trend_r2?>?best_r2:
????????????????????best_r2?=?trend_r2
????????????????????seasonality?=?True
????????????????????best_trend?=?result.trend
????????????????????return?seasonality,?best_trend
參考資料
[1]https://blog.csdn.net/weixin_35757704/article/details/113039882
[2]https://www.jianshu.com/p/e2cc90e1c32d??
[3]https://machinelearningmastery.com/decompose-time-series-data-trend-seasonality/
往期精彩回顧 本站qq群554839127,加入微信群請掃碼:
