立即注册找回密码

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

手机动态码快速登录

手机号快速注册登录

搜索

图文播报

查看: 222|回复: 0

[分享] 每天都和时间序列打交道,我总结了这篇文章!

[复制链接]
发表于 2025-3-31 06:24 | 显示全部楼层 |阅读模式

登陆有奖并可浏览互动!

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录 手机动态码快速登录

×
Datawhale干货

作者:戳戳龍,上海交通大学,量化算法工程师

前言

<hr/>   平时工作中每天都在和时间序列打交道,对时间序列分析进行研究是有必要的
   分享和交流一些自己的在时序处理方面的心得,提供一些思路
   介绍时序的发展情况,以及目前业界常用的方法
   代码希望能模板化,能直接复制过去使用
时序方法发展

<hr/>



时间序列特征

<hr/>
series = trend + seasons + dependence+ error
趋势

  时间序列的趋势分量表示该序列均值持续的、长期的变化




Df[&#39;ma20&#39;] = Df[&#39;amt&#39;].rolling(20).mean()
周期性(季节性)



季节时序图

def plot_season(Df):
    df = Df.copy()
    # 计算每周属于哪一年
    df[&#39;year&#39;] = df[&#39;date&#39;].dt.year
    # 计算每周为一年当中的第几周
    df[&#39;week_of_year&#39;] = df[&#39;date&#39;].dt.weekofyear
    for year in df[&#39;year&#39;].unique():
        tmp_df = df[df[&#39;year&#39;] == year]
        plt.plot(tmp_df[&#39;week_of_year&#39;], tmp_df[&#39;amt&#39;], &#39;.-&#39;, label=str(year))
    plt.legend()
    plt.show()


周期判断

如果每隔h个单位,ACF值有一个局部高峰,则数据存在以h为单位的周期性
from  statsmodels.graphics.tsaplots import plot_acf
plot_acf(Df[&#39;amt&#39;], lags=500).show()


自相关性

自相关

自相关函数 autocorrelation function有序的随机变量序列与其自身相比较自相关函数反映了同一序列在不同时序的取值之间的相关性
from statsmodels.graphics.tsaplots import plot_acf
_ = plot_acf(Df[&#39;amt&#39;], lags=50)




偏自相关

from statsmodels.graphics.tsaplots import plot_pacf

plot_pacf(Df[&#39;amt&#39;], lags=5)

残差


  • 外部变量
  • 残差
Prophet

官方文档:https://facebook.github.io/prophet/docs/quick_start.html#python-api
原理

模型结构

模型结构——关于时间的广义线性模型

  • g(t):trend,用分段线性函数或逻辑增长曲线(logistic)拟合
  • s(t):seasonality,用傅里叶级数拟合。可以叠加多个季节性,如weekly,yearly (s = s1+s2……)
  • h(t):regressor,用线性函数拟合。可以叠加多个外部变量,如节假日、温度、活动(h = h1+h2+……)
  • :模型残差 不用拟合
  • 以上方程也可以写成乘法形式:

    • 乘法形式和加法形式可以相互转换,乘法形式两边取对数就是加法形式



趋势

分段线性函数

线性趋势函数
分段线性趋势函数

  • 超参数,由用户给出

    • 分几段

  • 参数,根据历史数据拟合

    • k:曲线增长速率
    • m:曲线的截距

逻辑增长曲线



函数展示https://www.desmos.com/calculator/8pnqou9ojy?lang=zh-CN


  • 超参数

    • C:渐近线
    • 一共分几段

  • 参数

    • k:曲线增长速率
    • m:拐点对应时间

周期性

任何周期性函数都可以表示成傅里叶级数


  • 超参数:由用户给定
  • 参数:由历史数据拟合
  函数展示:(https://www.desmos.com/calculator/5prck2beq1?lang=zh-CN


外部因素


  • : 模型输入, 外部因素在时刻的取值
    Z可以是0-1变量 (e.g.是否是法定假日,是否是春节,是否有促销)
    也可以是连续变量 (e.g.产品价格, 温度,降雨量)
  • :线性回归系数
算法流程





1️⃣ 先设定表达式(超参数)
2️⃣ 根据训练集数据求解参数
实践

发电耗煤预测

df_train = Df[ (Df[&#39;date&#39;]<&#39;2022-01-01&#39;) & (Df[&#39;date&#39;]>=&#39;2018-01-01&#39;) ]
df_test =  Df[ (Df[&#39;date&#39;]>=&#39;2022-01-01&#39;)]
def FB(data):
    df = pd.DataFrame({
    &#39;ds&#39;: data.date,
    &#39;y&#39;: data.amt,
    })
#     df[&#39;cap&#39;] = data.amt.values.max()
#     df[&#39;floor&#39;] = data.amt.values.min()
    m = prophet.Prophet(
        changepoint_prior_scale=0.05,
        daily_seasonality=False,
        yearly_seasonality=True, #年周期性
        weekly_seasonality=True, #周周期性
#         growth=&#34;logistic&#34;,
    )
    m.add_seasonality(name=&#39;monthly&#39;, period=30.5, fourier_order=5, prior_scale=0.1)#月周期性
    m.add_country_holidays(country_name=&#39;CN&#39;)#中国所有的节假日   
    m.fit(df)
    future = m.make_future_dataframe(periods=30, freq=&#39;D&#39;)#预测时长
#     future[&#39;cap&#39;] = data.amt.values.max()
#     future[&#39;floor&#39;] = data.amt.values.min()
    forecast = m.predict(future)
    fig = m.plot_components(forecast)
    fig1 = m.plot(forecast)
    a = add_changepoints_to_plot(fig1.gca(), m, forecast)
    return forecast,m
forecast,m = FB(df_train)






def FPPredict(data,m):
    df = pd.DataFrame({
    &#39;ds&#39;: data.date,
    &#39;y&#39;: data.amt,
    })
    df_predict = m.predict(df)
    df[&#39;yhat&#39;] = df_predict[&#39;yhat&#39;].values
    df = df.set_index(&#39;ds&#39;)
    df.plot()
    return df
df = FPPredict(df_test.tail(200),m)


申购赎回金额预测

kaggle notebook
Purchase Redemption Data.zip
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import prophet
from prophet.diagnostics import cross_validation
from prophet.diagnostics import performance_metrics
from prophet.plot import plot_cross_validation_metric
import warnings
warnings.filterwarnings(&#39;ignore&#39;)
data_user = pd.read_csv(&#39;../input/purchase-redemption/Purchase Redemption Data/user_balance_table.csv&#39;)
data_user[&#39;report_date&#39;] = pd.to_datetime(data_user[&#39;report_date&#39;], format=&#39;%Y%m%d&#39;)
data_user.head()
data_user_byday = data_user.groupby([&#39;report_date&#39;])[&#39;total_purchase_amt&#39;,&#39;total_redeem_amt&#39;].sum().sort_values([&#39;report_date&#39;]).reset_index()
data_user_byday.head()
申购

#定义模型
def FB(data: pd.DataFrame):
    df = pd.DataFrame({
    &#39;ds&#39;: data.report_date,
    &#39;y&#39;: data.total_purchase_amt,
    })
#     df[&#39;cap&#39;] = data.total_purchase_amt.values.max()
#     df[&#39;floor&#39;] = data.total_purchase_amt.values.min()
    m = prophet.Prophet(
        changepoint_prior_scale=0.05,
        daily_seasonality=False,
        yearly_seasonality=True, #年周期性
        weekly_seasonality=True, #周周期性
#         growth=&#34;logistic&#34;,
    )
#     m.add_seasonality(name=&#39;monthly&#39;, period=30.5, fourier_order=5, prior_scale=0.1)#月周期性
    m.add_country_holidays(country_name=&#39;CN&#39;)#中国所有的节假日   
    m.fit(df)
    future = m.make_future_dataframe(periods=30, freq=&#39;D&#39;)#预测时长
#     future[&#39;cap&#39;] = data.total_purchase_amt.values.max()
#     future[&#39;floor&#39;] = data.total_purchase_amt.values.min()
    forecast = m.predict(future)
    fig = m.plot_components(forecast)
    fig1 = m.plot(forecast)
    return forecast,m
result_purchase,purchase_model = FB(data_user_byday.iloc[:-30])




def FPPredict(data,m):
    df = pd.DataFrame({
    &#39;ds&#39;: data.report_date,
    &#39;y&#39;: data.total_purchase_amt,
    })
#     df[&#39;cap&#39;] = data.total_purchase_amt.values.max()
#     df[&#39;floor&#39;] = data.total_purchase_amt.values.min()
    df_predict = m.predict(df)
    df[&#39;yhat&#39;] = df_predict[&#39;yhat&#39;].values
    df = df.set_index(&#39;ds&#39;)
    df.plot()
    return df
purchase_df = FPPredict(data_user_byday.iloc[-30:],purchase_model)


赎回

#定义模型
def FB(data: pd.DataFrame):
    df = pd.DataFrame({
    &#39;ds&#39;: data.report_date,
    &#39;y&#39;: data.total_redeem_amt,
    })
    df[&#39;cap&#39;] = data.total_purchase_amt.values.max()
    df[&#39;floor&#39;] = data.total_purchase_amt.values.min()
    m = prophet.Prophet(
        changepoint_prior_scale=0.05,
        daily_seasonality=False,
        yearly_seasonality=True, #年周期性
        weekly_seasonality=True, #周周期性
        growth=&#34;logistic&#34;,
    )
#     m.add_seasonality(name=&#39;monthly&#39;, period=30.5, fourier_order=5, prior_scale=0.1)#月周期性
    m.add_country_holidays(country_name=&#39;CN&#39;)#中国所有的节假日   
    m.fit(df)
    future = m.make_future_dataframe(periods=30, freq=&#39;D&#39;)#预测时长
    future[&#39;cap&#39;] = data.total_purchase_amt.values.max()
    future[&#39;floor&#39;] = data.total_purchase_amt.values.min()
    forecast = m.predict(future)
    fig = m.plot_components(forecast)
    fig1 = m.plot(forecast)
    return forecast
result_redeem = FB(data_user_byday)




Bonus 时间序列特征工程

https://www.heywhale.com/mw/project/63904f5658e3bea6a3e52800
EDA

import sweetviz as sv

def eda(df, name, target=None):
    sweet_report = sv.analyze(df, target_feat=target)
    sweet_report.show_html(f&#39;{name}.html&#39;)

def eda_compare(df1, df2, name, feature, target):
    feature_config = sv.FeatureConfig(force_text=feature, force_cat=feature)
    sweet_report = sv.compare(df1, df2, feat_cfg=feature_config, target_feat=target)
    sweet_report.show_html(f&#39;{name}_compare.html&#39;)完整版请访问:https://www.wolai.com/stupidccl/5dqha79nnrPMf5xTAs6jUu
参考资料


[1]kaggle notebook: https://www.kaggle.com/code/stupidccl/time-serious-analysis-1/edit/run/107631286

http://weixin.qq.com/r/9Du6opTEdskJrdDB927m (二维码自动识别)

干货学习,三连
本文使用 文章同步助手 同步

原文地址:https://zhuanlan.zhihu.com/p/623883379
楼主热帖
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册 微信登录 手机动态码快速登录

本版积分规则

关闭

官方推荐 上一条 /3 下一条

快速回复 返回列表 客服中心 搜索 官方QQ群 洽谈合作
快速回复返回顶部 返回列表