发布时间:2024-01-24 19:00
目录
一、时间序列简要介绍
二、效应分解法分析时间序列
2.1 时间序列的效应分解
2.2 时间序列的组合方式
2.3 python中实现时间序列
2.3.1 加法模型案例及代码
2.3.2 乘法模型案例及代码
时间序列类型的数据是工作中最常见的一种数据类型,即指标随时间变化情况,比如一个公司每日的订单量、交易额、活跃用户数等指标都是时间序列,这些指标的波动一般都会呈现一定的规律性。了解这个规律,我们可以提前对未来的走势进行预测;也可以基于预测来进行异常检测、运营干预效果评估等。
商业中用来分析时间序列的方法有两类:一类为效应分解法,即把时间序列分解为趋势和周期性效应;另一类是ARIMA法,其可以针对数据产生的机理构建动态模型,实际上是根据数据扰动项之间的相关性结构构建预测模型。
本文主要介绍第一种方法即如何用python中的prophet包对时间序列进行效应分解并进行预测。
下图是2021年某品牌的每日销售量数据,观察该指标的波动具有明显的规律性。首先整体上数据走势较为平稳,其次按周呈现一定的周期性,在某些月份上升或下降呈现一定的季节性,另外也受传统节日的影响呈现一定的规律性。
根据效应拆解法可将其拆解为趋势性、周期性、季节性、节假日影响、随机性。
(1)趋势性:指数据在长时间范围内呈现上升、下降或保留在某一水平上的倾向。主要受客观因素的影响,如运营手段、业务扩展等影响。
(2)周期性:周期性通常指较长的时间周期,引起的波动,由于周期性不稳定,所以主要考虑季节性变动。
(3)季节性:指季度、月度、周度、日度的周期性变化,比如某些商品的销量在夏季较高冬季较低。
(4)节假日效应:指业务数据受传统或新兴节日的影响,呈现剧增或骤减的特征。比如月饼、粽子分别传统节中秋、端午传统节日的影响较大,而电商平台的销量则受618、双11等电商节日的影响较大。
(5)随机性:指数据受随机因素的影响呈小幅度波动。
(1)加法模型,即以上几种效应是累加的:
其中T是趋势效应,C是周期效应,S是季节效应,H是节日效应,I是随机效应。
(2)乘法模型,即几种效应是累积的:
fbprophet是facebook数据科学团队贡献的用来实现效应分解,效应的组合方式是加法模型,如果要实现乘法模型,可首先对数据取对数,进行建模预测,最后对预测结果求指数变换回去即可。
用该模型进行分析,首先需要将数据改为模型所需的格式,导入数据为两列,第一列必须为日期类
型,列名为\"ds\",第二列为数值类型,列名为\"y\"。如下是加法模型代码
(1)数据预处理及建模
%matplotlib inline
import os
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from fbprophet import Prophet # 时间序列效应分析包
df1 = pd.read_csv(\'./data/test_data.csv\')
df1[\'date\'] = pd.to_datetime(df1[\'date\']) # 将其转为日期类型
df1 = df1.rename(columns = {\'date\': \'ds\', \'value\': \'y\'}) # 修改列名使prophet包能够识别
# 第一步:建立模型
model = Prophet(growth = \'linear\'
, yearly_seasonality = True
, weekly_seasonality = True
, interval_width = 0.95)
model.add_country_holidays(country_name = \'CN\') # 添加传统节日效应
# 第二步:模型训练
model.fit(df1)
# 第三步:指定预测时间
future_dates = model.make_future_dataframe(periods = 90, freq = \'D\')
# 第四步:预测
pred = model.predict(future_dates)
(2)可以用模型自带的plot函数,画出实际值、预测值以及预测的置信区间:
fig5 = model.plot(pred)
(3)画出各部分效应,下图中分别是趋势效应、节假日效应、周季节性、年季节性。
能够看到整体呈增长趋势;业务受传统节假日的影响较大,在春节、中秋、十一、端午的影响最大;按周来看,周六、周日休息日业务下降也较明显;按年来看在不同的月份也有明显的淡旺季,如1月、11月、12月为旺季。
fig6 = model.plot_components(pred)
(4)计算预测误差
df1[\'ds_1\'] = [str(i.strftime(\'%Y-%m-%d\')) for i in df1[\'ds\']] # 创建字符串类型日期,用来关联
pred[\'ds_1\'] = [str(i.strftime(\'%Y-%m-%d\')) for i in pred[\'ds\']] # 创建字符串类型日期
df2 = df1.merge(pred[[\'ds_1\', \'yhat\']], on = \'ds_1\', how = \'left\') # 左关联1
df2.head()
# 计算预测 平均绝对误差
print(\"MAE\", abs(df2[\'y\'] - df2[\'yhat\']).sum()/df2.shape[0])
# 计算 均方误差
print(\"RMSE\", np.sqrt(sum((df2[\'y\'] - df2[\'yhat\'])**2)/df2.shape[0]))
该数据为1949年到1960年航空公司每月运量数据,点击如下链接可进行下载。航空公司每月运量时间序列数据-机器学习文档类资源-CSDN下载
(1)首先对其按照加法模型进行建模
df = pd.read_csv(\'./data/AirPassengers.csv\')
df = df.rename(columns = {\'DATE\': \'ds\', \'AIR\': \'y\'}) # 重命名
plt.figure(figsize = (18, 6))
plt.plot(df.ds, df.y)
# 建模
my_model = Prophet(yearly_seasonality = True
,growth = \'linear\'
, interval_width = 0.95)
my_model.fit(df)
future_dates = my_model.make_future_dataframe(periods = 36, freq = \'M\')
forecast = my_model.predict(future_dates)
forecast[[\'ds\', \'yhat\', \'yhat_lower\', \'yhat_upper\']].tail(5)
from fbprophet.plot import plot_plotly, plot_components_plotly
fig1 = model.plot(forecast)
可以看到随着时间的增长,季节性效应的影响在变大,可以用尝试用乘法模型进行预测。prophet中没有乘法模型,但可通过简单的转化来实现。首先对y取对数,对取完对数后的数据进行建模,而后再求其幂即可转化回来。
df[\'y\'] = np.log(df[\'y\']) # y赋值为原始数据的对数
my_model1 = Prophet(growth = \'linear\', interval_width = 0.95)
my_model1.fit(df)
future_dates = my_model1.make_future_dataframe(periods = 36, freq = \'M\')
forecast1 = my_model1.predict(future_dates)
fig3 = my_model1.plot(forecast1, uncertainty=True)
可以看到预测结果较加法模型有明显改进,预测数据较实际值偏离较上图有明显减小。
(2)将预测结果转化回去,如此即可实现乘法模型预测
forecast1[\'yhat\'] = np.power(math.e, forecast1[\'yhat\'])
forecast1[\'yhat_lower\'] = np.power(math.e, forecast1[\'yhat_lower\'])
forecast1[\'yhat_upper\'] = np.power(math.e, forecast1[\'yhat_upper\'])
fig4 = my_model1.plot(forecast1)