时间序列分析就是发现时间序列的变动规律并使用该规律来预测的统计技术。时间序列分析基于以下三个假设:
- 假设事物发展规律趋势会延续到未来。
- 预测所依据的数据没有不规则性。
- 不考虑事物发展之间的因果关系。
时间序列分析主要包括两方面内容:第一是 序列分解;第二是 序列预测。
代码及数据地址:https://github.com/SeafyLiang/machine_learning_study/tree/master/time_series
时间序列基础-序列分解与序列预测
*
– 一、时间序列分解
–
+ 1.1 非季节性时间序列分解
+
* MA(Moving Average)
* SMA(Simple Moving Average)
* WMA(Weighted Moving Average)
+ 1.2 季节性时间序列
– 二、序列预测
–
+ 2.1 不平稳时间序列转换成平稳的时间序列
+
* 差分(Integrated)
* 单位根检验法
+ 2.2 自回归模型-AR
+ 2.3 移动平均模型-MA
+ 2.4 自回归移动平均模型-ARMA
+ 2.5 时序预测代码-AR, MA, ARMA
一、时间序列分解
一个时间序列包含三种影响因素:
- 长期趋势:在一个相当长的时间内表现为一种近似直线的持续向上、向下或平稳的趋势。
- 季节变动:受季节变化影响所形成的一种长度和幅度固定的短期周期波动,”季节”指的是周期,可以是周、月、年等。
- 不规则变动:受偶然因素的影响所形成的不规则波动,如股票市场受利好或者利空信息的影响,使得股票价格产生的波动。
时间序列按照季节性来分类,分为季节性时间序列和非季节性时间序列。
1.1 非季节性时间序列分解
MA(Moving Average)
移动平均是一种简单平滑技术,它通过在时间序列上逐项推移取一定项数的均值,来表现指标的长期变化和发展趋势。
SMA(Simple Moving Average)
简单移动平均将时间序列上前n个数值做简单的算术平均。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data = pd.read_csv('data/非季节性时间序列.csv', encoding='utf8', engine='python')
original_data = data['公司A']
def sma_demo():
sma_data = original_data.rolling(3).mean()
plt.plot(
data.index, original_data, 'k-',
data.index, sma_data, 'g-'
)
plt.show()
random_error = original_data - sma_data
plt.plot(
data.index, original_data, 'k-',
data.index, sma_data, 'g-',
data.index, random_error, 'r-'
)
plt.show()
if __name__ == '__main__':
sma_demo()
WMA(Weighted Moving Average)
加权移动平均在基于简单移动平均的基础上,对时间序列上前n期的每一期数值赋予对应的权重。
它的基本思想是,提升近期的数据并减弱远期数据对当前预测值的影响,使平滑值更贴近最近的变化趋势。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data = pd.read_csv('data/非季节性时间序列.csv', encoding='utf8', engine='python')
original_data = data['公司A']
def wma_demo():
wl = 3
ww = [1 / 6, 2 / 6, 3 / 6]
def wma(window):
return np.sum(window * ww)
sma_data = original_data.rolling(wl).aggregate(wma)
random_error = original_data - sma_data
plt.plot(
data.index, original_data, 'k-',
data.index, sma_data, 'g-',
data.index, random_error, 'r-'
)
plt.show()
if __name__ == '__main__':
wma_demo()
1.2 季节性时间序列
季节性时间序列,是指在一个时间序列中,若经过n个时间间隔后,呈现出相似的波动,则称该序列具有以n为周期的季节性特性。
import pandas as pd
import statsmodels.api
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
data = pd.read_csv('data/季节性时间序列.csv', encoding='utf8', engine='python')
total_sales = data['总销量'].values
'''
statsmodels.api.tsa.seasonal_decompose(x, freq=None)
x:要分解的季节性时间序列
freq:时间序列的周期,需要自己根据业务来判断数据的周期
'''
tsr = statsmodels.api.tsa.seasonal_decompose(
total_sales, period=7
)
trend = tsr.trend
seasonal = tsr.seasonal
random_error = tsr.resid
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
ax1.set_title('总销量')
ax1.plot(
data.index, total_sales, 'k-'
)
ax2.set_title('趋势部分')
ax2.plot(
data.index, trend, 'g-'
)
ax3.set_title('季节性部分')
ax3.plot(
data.index, seasonal, 'r-'
)
ax4.set_title('随机误差')
ax4.plot(
data.index, random_error, 'b-'
)
plt.show()
二、序列预测
时间序列预测,是根据时间序列反映出来的 发展过程、方向和趋势,进行类推或延伸,借以预测下一段时间或以后若干周期内可能达到的水平。
时间序列预测使用时间序列的 均值、方差和协方差这三个统计量来刻画时间序列的本质特征。若这些统计量的值在过去和未来仍保持不变,则为平稳的时间序列。
2.1 不平稳时间序列转换成平稳的时间序列
如果时间序列不平稳,则需要通过差分等技术手段,把它转换成平稳的时间序列,然后再进行预测。
差分(Integrated)
在pandas模块中,使用diff函数,即可对数据进行差分。
单位根检验法
可以使用单位根检验法来检验一个时间序列的平稳性。其中的p-value代表有多大的概率不是一个平稳的时间序列。
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.tsa.stattools as ts
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
'''
一个平稳的时间序列指的是,未来的时间序列,它的均值、方差和协方差必定与现在的时间序列相等。
若时间序列不平稳,则需要通过差分等技术手段,把它转换成平稳的时间序列,然后再进行预测。
'''
data = pd.read_csv('data/时间序列预测.csv', encoding='utf8', engine='python')
data.index = pd.to_datetime(data.date, format='%Y%m%d')
del data['date']
plt.figure()
plt.plot(data, 'r')
plt.show()
def tagADF(t):
result = pd.DataFrame(index=[
"Test Statistic Value",
"p-value", "Lags Used",
"Number of Observations Used",
"Critical Value(1%)",
"Critical Value(5%)",
"Critical Value(10%)"
], columns=['value']
)
result['value']['Test Statistic Value'] = t[0]
result['value']['p-value'] = t[1]
result['value']['Lags Used'] = t[2]
result['value']['Number of Observations Used'] = t[3]
result['value']['Critical Value(1%)'] = t[4]['1%']
result['value']['Critical Value(5%)'] = t[4]['5%']
result['value']['Critical Value(10%)'] = t[4]['10%']
return result
adf_data = ts.adfuller(data.value)
adfResult = tagADF(adf_data)
print(adfResult)
diff = data.value.diff(1).dropna()
plt.figure()
plt.plot(diff, 'r')
plt.show()
adf_diff = ts.adfuller(diff)
adfResult = tagADF(adf_diff)
print(adfResult)
2.2 自回归模型-AR
自回归模型本质是一个线性回归模型,”自”描述的是当前值与历史值之间的关系。通过一个超参数p,把时间序列格式的样本转换为线性回归模型的样本。
2.3 移动平均模型-MA
移动平均模型描述的是自回归模型部分的累计误差。
移动平均模型的意义在于,找到较少参数的移动平均模型,来替代较多参数的自回归模型。
2.4 自回归移动平均模型-ARMA
ARMA模型就是AR模型和MA模型的组合,将因变量仅对它的滞后值以及随机误差项的现值和滞后值进行回归所建立的模型。
; 2.5 时序预测代码-AR, MA, ARMA
import statsmodels.api as sm
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
data = pd.read_csv('data/时间序列预测.csv', encoding='utf8', engine='python')
data.index = pd.to_datetime(data.date, format='%Y%m%d')
del data['date']
diff = data.value.diff(1).dropna()
plt.figure()
plt.plot(diff, 'r')
plt.show()
def ar_demo():
'''
自回归
:return:
'''
arModel = sm.tsa.AR(
diff
)
p = arModel.select_order(
maxlag=30,
ic='aic'
)
print(p)
arModel = arModel.fit(maxlag=p)
delta = arModel.fittedvalues - diff
score = 1 - delta.var() / diff.var()
print(score)
def sma_demo():
'''
简单移动平均
:return:
'''
sma_data = diff.rolling(3).mean()
plt.plot(
diff.index, diff, 'k-',
diff.index, sma_data, 'g-'
)
plt.show()
def arma_demo():
order = (6, 6)
armaModel = sm.tsa.ARMA(
diff, order
).fit()
delta = armaModel.fittedvalues - diff
score = 1 - delta.var() / diff.var()
print(score)
p = armaModel.predict(
start='2016-03-31',
end='2016-04-10'
)
def revert(diffValues, *lastValue):
for i in range(len(lastValue)):
result = []
lv = lastValue[i]
for dv in diffValues:
lv = dv + lv
result.append(lv)
diffValues = result
return diffValues
r = revert(p, 10395)
plt.figure()
plt.plot(
diff, 'r',
label='Raw'
)
plt.plot(
armaModel.fittedvalues, 'g',
label='ARMA Model'
)
plt.plot(
p, 'b', label='ARMA Predict'
)
plt.legend()
plt.show()
r = pd.DataFrame({
'value': r
}, index=p.index
)
plt.figure()
plt.plot(
data.value, c='r',
label='Raw'
)
plt.plot(
r, c='g',
label='ARMA Model'
)
plt.legend()
plt.show()
if __name__ == '__main__':
ar_demo()
sma_demo()
arma_demo()
Original: https://blog.csdn.net/SeafyLiang/article/details/124160665
Author: SeafyLiang
Title: 时间序列基础-序列分解与序列预测
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/639998/
转载文章受原作者版权保护。转载请注明原作者出处!