基本规则法
wangzf / 2023-03-26
目录
时间序列基本面规则法介绍
要预测一个时间序列,我们首先需要发现其变化的规律。最基本的方法,就是通过人工经验, 挖掘时序数据的演化特征,找到时序变化的周期,从而预估时间序列的未来走势。 具体的观察一个时间序列,当序列存在周期性时,提取时间序列的周期性特征进行预测
时间序列基本规则法(周期因子法)思想:
- 提取时间序列的周期性特征进行预测, 当序列存在周期性时, 可以用周期因子法作为 baseline
- 对于像支付数据、客流量数据、交通数据等, 具有明显的周期性. 从预测的角度来说, 周期性是核心, 只要抓住了周期性, 任务就完成了一大半
时间序列基本规则法基本步骤:
- 计算周期因子 factor
- 计算 base
- 预测 - base
$\times$
factor
时间序列数据和任务
数据
- 前三周的客流量数据, 即 21 天每天的客流量数据:
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | 周均值 | |
---|---|---|---|---|---|---|---|---|
第 1 周 | 20 | 10 | 70 | 50 | 250 | 200 | 100 | 100 |
第 2 周 | 26 | 18 | 66 | 50 | 180 | 140 | 80 | 80 |
第 3 周 | 15 | 8 | 67 | 60 | 270 | 160 | 120 | 100 |
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({
"ts": pd.date_range("2022-10-01", periods = 21, freq = "D"),
"value": [
20, 10, 70, 50, 250, 200, 100,
26, 18, 66, 50, 180, 140, 80,
15, 8, 67, 60, 270, 160, 120,
],
})
fig, ax = plt.subplots()
plt.plot(df["ts"], df["value"])
plt.title("Value")
plt.show()
能够明显看到周一到周日的周期波动,预测的核心任务就是尽可能准确地提取这种周期性
任务
- 预测第 4 周每天的客流量
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | 周均值 | |
---|---|---|---|---|---|---|---|---|
第 1 周 | 20 | 10 | 70 | 50 | 250 | 200 | 100 | 100 |
第 2 周 | 26 | 18 | 66 | 50 | 180 | 140 | 80 | 80 |
第 3 周 | 15 | 8 | 67 | 60 | 270 | 160 | 120 | 100 |
第 4 周 | ? | ? | ? | ? | ? | ? | ? |
时间序列预测
确定周期因子
除以周均值取中位数
第一步: 每周的客流量数据除以对应的周客流量均值,每周的均值分别为 100、80、100, 得到一个比例值
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |
---|---|---|---|---|---|---|---|
第 1 周 | 0.2 | 0.1 | 0.7 | 0.5 | 2.5 | 2 | 1 |
第 2 周 | 0.325 | 0.225 | 0.825 | 0.625 | 2.25 | 1.75 | 1 |
第 3 周 | 0.15 | 0.08 | 0.67 | 0.6 | 2.7 | 1.6 | 1.2 |
第二步: 按列取中位数, 就可以得到一组鲁棒的周期因子
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |
---|---|---|---|---|---|---|---|
第 1 周 | 0.2 | 0.1 | 0.7 | 0.5 | 2.5 | 2 | 1 |
第 2 周 | 0.325 | 0.225 | 0.825 | 0.625 | 2.25 | 1.75 | 1 |
第 3 周 | 0.15 | 0.08 | 0.67 | 0.6 | 2.7 | 1.6 | 1.2 |
中位数(周期因子) | 0.2 | 0.1 | 0.7 | 0.6 | 2.5 | 1.75 | 1 |
计算季节指数
季节指数的计算方式:获得每日(工作日或周末)均值,再除以整体均值
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |
---|---|---|---|---|---|---|---|
第 1 周 | 20 | 10 | 70 | 50 | 250 | 200 | 100 |
第 2 周 | 26 | 18 | 66 | 50 | 180 | 140 | 80 |
第 3 周 | 15 | 8 | 67 | 60 | 270 | 160 | 120 |
日均值 | 20.33 | 12 | 67.67 | 53.33 | 233.33 | 166.67 | 100 |
日均值 / 整体均值(周期因子) | 0.22 | 0.13 | 0.73 | 0.57 | 2.50 | 1.79 | 1.07 |
确定 base
取最后一周的平均客流
取最后一周的平均客流量 100 作为 base, 乘以周期因子(前三周的每天的中位数), 得到第 4 周的预测客流量:
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |
---|---|---|---|---|---|---|---|
第 1 周 | 20 | 10 | 70 | 50 | 250 | 200 | 100 |
第 2 周 | 26 | 18 | 66 | 50 | 180 | 140 | 80 |
第 3 周 | 15 | 8 | 67 | 60 | 270 | 160 | 120 |
第 1 周 | 0.2 | 0.1 | 0.7 | 0.5 | 2.5 | 2 | 1 |
第 2 周 | 0.325 | 0.225 | 0.825 | 0.625 | 2.25 | 1.75 | 1 |
第 3 周 | 0.15 | 0.08 | 0.67 | 0.6 | 2.7 | 1.6 | 1.2 |
中位数(周期因子) | 0.2 | 0.1 | 0.7 | 0.6 | 2.5 | 1.75 | 1 |
第 4 周预测值(base=100) | 20 | 10 | 70 | 60 | 250 | 175 | 100 |
去周期后再取平均
去周期即用最后一周的数据除以周期因子,然后再取平均
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |
---|---|---|---|---|---|---|---|
第 1 周 | 20 | 10 | 70 | 50 | 250 | 200 | 100 |
第 2 周 | 26 | 18 | 66 | 50 | 180 | 140 | 80 |
第 3 周 | 15 | 8 | 67 | 60 | 270 | 160 | 120 |
第 1 周除以均值 | 0.2 | 0.1 | 0.7 | 0.5 | 2.5 | 2 | 1 |
第 2 周除以均值 | 0.325 | 0.225 | 0.825 | 0.625 | 2.25 | 1.75 | 1 |
第 3 周除以均值 | 0.15 | 0.08 | 0.67 | 0.6 | 2.7 | 1.6 | 1.2 |
中位数(周期因子) | 0.2 | 0.1 | 0.7 | 0.6 | 2.5 | 1.75 | 1 |
第 4 周预测值(去周期后的客流量) | 75 | 80 | 95.7 | 100 | 108 | 91.4 | 120 |
完整实现
timestamp | metric | 周均值 | 比例值 | 周期因子 | base | 预测值 |
---|---|---|---|---|---|---|
第 1 周 周一 | 20 | 100 | 0.2 | |||
第 1 周 周二 | 10 | 100 | 0.1 | |||
第 1 周 周三 | 70 | 100 | 0.7 | |||
第 1 周 周四 | 50 | 100 | 0.5 | |||
第 1 周 周五 | 250 | 100 | 2.5 | |||
第 1 周 周六 | 200 | 100 | 2.0 | |||
第 1 周 周日 | 100 | 100 | 1.0 | |||
第 2 周 周一 | 26 | 80 | 0.325 | |||
第 2 周 周二 | 18 | 80 | 0.225 | |||
第 2 周 周三 | 66 | 80 | 0.825 | |||
第 2 周 周四 | 50 | 80 | 0.625 | |||
第 2 周 周五 | 180 | 80 | 2.25 | |||
第 2 周 周六 | 140 | 80 | 1.75 | |||
第 2 周 周日 | 80 | 80 | 1 | |||
第 3 周 周一 | 15 | 100 | 0.15 | |||
第 3 周 周二 | 8 | 100 | 0.08 | |||
第 3 周 周三 | 67 | 100 | 0.67 | |||
第 3 周 周四 | 60 | 100 | 0.60 | |||
第 3 周 周五 | 270 | 100 | 2.7 | |||
第 3 周 周六 | 160 | 100 | 1.6 | |||
第 3 周 周日 | 120 | 100 | 1.2 | |||
第 4 周 周一 | 0.2 | 100 | 20 | |||
第 4 周 周二 | 0.1 | 100 | 10 | |||
第 4 周 周三 | 0.7 | 100 | 70 | |||
第 4 周 周四 | 0.6 | 100 | 60 | |||
第 4 周 周五 | 2.5 | 100 | 250 | |||
第 4 周 周六 | 1.75 | 100 | 175 | |||
第 4 周 周日 | 1 | 100 | 100 |
针对周期因子的优化
按列提取中位数是一种简单而有效的提取周期因子的方法. 中位数十分鲁棒, 不受极端值的影响. 但中位数损失了很多信息. 实践中, 可以在此基础上进一步优化. 比如可以提取一个均值和一个中位数, 然后将均值和中位数融合. 融合的比例按照测试集的表现来确定. 也可以根据与预测周的时间距离来赋予不同的权重.
针对 base 的优化
直接用最后一周的平均客流量作为 base 并不一定是最好的方法. 也许最后三天或最后五天的均值能更好的反映最新的情况. 但是, 我们不能直接对最后三天客流量取均值(最后三天是周末, 这样取的base就偏大了). 需要去掉周期性因素后, 再取平均. 具体做法, 就是用客流量除以周期因子, 然后取第 3 周最后三天的客流量的均值作为 base, 即 base = (108 + 91.4 + 120) / 3 = 106.5. 具体取多少天的, 也要通过测试集的表现来确定. 当然也可以按某些函数形式来给每天赋予不同的权重.
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |
---|---|---|---|---|---|---|---|
第 1 周 | 20 | 10 | 70 | 50 | 250 | 200 | 100 |
第 2 周 | 26 | 18 | 66 | 50 | 180 | 140 | 80 |
第 3 周 | 15 | 8 | 67 | 60 | 270 | 160 | 120 |
中位数 | 0.2 | 0.1 | 0.7 | 0.6 | 2.5 | 1.75 | 1 |
去周期以后的客流量 | 75 | 80 | 95.7 | 100 | 108 | 91.4 | 120 |
取 106.5 作为 base:
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |
---|---|---|---|---|---|---|---|
第 1 周 | 20 | 10 | 70 | 50 | 250 | 200 | 100 |
第 2 周 | 26 | 18 | 66 | 50 | 180 | 140 | 80 |
第 3 周 | 15 | 8 | 67 | 60 | 270 | 160 | 120 |
中位数 | 0.2 | 0.1 | 0.7 | 0.6 | 2.5 | 1.75 | 1 |
预测(base=106.5) | 21.3 | 10.65 | 74.55 | 63.9 | 266.25 | 186.375 | 106.5 |
最终的数据:
周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | |
---|---|---|---|---|---|---|---|
第 1 周 | 20 | 10 | 70 | 50 | 250 | 200 | 100 |
第 2 周 | 26 | 18 | 66 | 50 | 180 | 140 | 80 |
第 3 周 | 15 | 8 | 67 | 60 | 270 | 160 | 120 |
第 4 周(预测值) | 21 | 11 | 75 | 64 | 266 | 186 | 107 |