【时间序列】时间序列预测基本方法:移动平均(SMA,EMA,WMA)
时间序列预测基本方法:移动平均(SMA,EMA,WMA)
移动平均作为时间序列中最基本的预测方法,计算简单却很实用。不仅可以用来做预测,还有一些其他的重要作用,比如平滑序列波动,揭示时间序列的趋势特征。
移动平均简而言之即使用前n个时刻的观测值来预测下一个时刻的取值。移动平均可以分为简单移动平均、加权移动平均、指数移动平均等。注意:移动平均用于预测场景时,尤其是多步预测,需要要求序列相对平稳,没有趋势、季节性的情况。
问题公式化
给定一个时间序列{Xt},观测值序列为:x1,x2,…,xt
xt+1为可预测为前n项的平均值,即xt+1=E({xt-n+1,xt-n+2,…,xt}),n表示窗口大小需要往前推多少时刻。
移动平均能够去除时间序列的短期波动,使得数据变得平滑,从而可以方便的看出序列的趋势特征。原序列波动较大,经过移动平均后,随机波动会明显减少,窗大小n越大,平滑后波动越小,滞后越明显。
简单移动平均(Simple Moving Average,SMA)
S M A t SMA_t SMAt ( n ) (n) (n) = 1 n \frac{1}{n} n1 ∑ i = t − n + 1 t \textstyle\sum_{i=t-n+1}^t ∑i=t−n+1t x n x_n xn
n n n是窗口大小, S M A t SMA_t SMAt表示 t t t时刻的移动平均值
SMA案例代码
# 导包
import numpy as np
from pandas import read_csv
import matplotlib.pyplot as plt
import pandas as pd
# 读取数据
df = pd.read_csv('household_power_consumption_days.csv', sep=',', header=0,
usecols=[0,1],parse_dates={'date':[0]},index_col=['date'])
# 真实数据列'Global_active_power'
real = df['Global_active_power']
# 取前6个时刻的数据预测下一时刻的数据
rolling = df['Global_active_power'].rolling(window=6)
rolling_mean = rolling.mean()
# 查看真实数据的维度和预测数据的维度
print("real Shape-- ",real.shape)#(1442,)
print("rolling_mean Shape-- ",rolling_mean.shape)#(1442,)
预测结果可视化
# 取最后258个时刻的数据绘图
plt.plot(real[-260:-2], color = 'red', label = 'Real')
plt.plot(rolling_mean[-260:-2], color = 'blue', label = 'Predicted')
plt.xlabel('Time')
plt.legend()
plt.show()
计算误差
real = real[-260:-2]
pred = rolling_mean[-260:-2]
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
# 计算误差
mae = mean_absolute_error(pred,real)
mse = mean_squared_error(pred,real)
print("MAE:",mae) # MAE: 218.50487338501293
print("MSE:",mse) # MSE: 90166.86320972697
加权移动平均(Weighted Moving Average,WMA)
与SMA类似,但是在计算平均数时不是等量齐观的,可以给最近的观测值相对历史观测值更大的权重。比容,最近的用电量对预测日最有影响力,历史用电量随着时间拉长影响力越小。
W M A t WMA_t WMAt ( n ) (n) (n) = w 1 x t + w 2 x t − 1 + . . . + w n − 1 x t − n + 2 + x t − n + 1 w 1 + w 2 + . . . + w n \frac{ w_1x_t+w_2x_t-1+...+w_n-1x_t-n+2+x_t-n+1 }{w_1+w_2+...+w_n} w1+w2+...+wnw1xt+w2xt−1+...+wn−1xt−n+2+xt−n+1
n n n是窗口大小, W M A t WMA_t WMAt表示 t t t时刻的移动平均值。
权重系数为 n 到 0 n到0 n到0,即最近的一个数值权重为 n n n,次近的为 n − 1 n-1 n−1,以此类推,直到 0 0 0。
W M A t WMA_t WMAt ( n ) (n) (n) = n x t + ( n − 1 ) x t − 1 + . . . + 2 x t − n + 2 + x t − n + 1 n + ( n − 1 ) + . . . + 2 + 1 \frac{nx_t+(n-1)x_t-1+...+2x_t-n+2+x_t-n+1 }{n+(n-1)+...+2+1} n+(n−1)+...+2+1nxt+(n−1)xt−1+...+2xt−n+2+xt−n+1
WMA案例代码
# 导包
import numpy as np
from pandas import read_csv
import matplotlib.pyplot as plt
import pandas as pd
# 读取数据
df = pd.read_csv('household_power_consumption_days.csv', sep=',', header=0,
usecols=[0,1],parse_dates={'date':[0]},index_col=['date'])
# 真实数据列'Global_active_power'
real = df['Global_active_power']
# 权重函数
def WMA(close, n):
weights = np.array(range(1, n+1))
sum_weights = np.sum(weights)
res = close.rolling(window=n).apply(lambda x: np.sum(weights*x) / sum_weights, raw=False)
return res
# 取前6个时刻的数据加权预测下一时刻的数据
df['WMA'] = WMA(df['Global_active_power'],6)
rolling_mean = df['WMA']
# 查看真实数据的维度和预测数据的维度
print("real Shape-- ",real.shape)#(1442,)
print("rolling_mean Shape-- ",rolling_mean.shape)#(1442,)
预测结果可视化
# 取最后258个时刻的数据绘图
plt.plot(real[-260:-2], color = 'red', label = 'Real')
plt.plot(rolling_mean[-260:-2], color = 'blue', label = 'Predicted')
plt.xlabel('Time')
plt.legend()
plt.show()
计算误差
real = real[-260:-2]
pred = rolling_mean[-260:-2]
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
# 计算误差
mae = mean_absolute_error(pred,real)
mse = mean_squared_error(pred,real)
print("MAE:",mae) # MAE: 181.05885714285714
print("MSE:",mse) # MSE: 66044.51492577454
指数移动平均(Exponential Moving Average,EMA)
可以看成一种特殊的加权移动平均,也称为指数加权移动平均(EWMA)。与WMA类似,它为以前的数值分配了一系列固定的指数递减权重,即权重系数随着时间呈指数下降。EMA提供了一个更明显的指标,能更快地反映最近的趋势。
E M A t EMA_t EMAt = x t + ( 1 − α ) x t − 1 + ( 1 − α ) 2 x t − 2... + ( 1 − α ) t x 0 1 + ( 1 − α ) + ( 1 − α ) 2 + . . . + ( 1 − α ) t \frac{x_t+(1-\alpha)x_t-1+(1-\alpha)^2x_t-2...+(1-\alpha)^tx_0}{1+(1-\alpha)+(1-\alpha)^2+...+(1-\alpha)^t} 1+(1−α)+(1−α)2+...+(1−α)txt+(1−α)xt−1+(1−α)2xt−2...+(1−α)tx0
t t t是窗口大小, 0 < α < = 1 0<\alpha<=1 0<α<=1为平滑因子,(1-\alpha)^i为呈指数增加的权重,期数离预测时刻越近权重越大。
EMA案例代码
# 导包
import numpy as np
from pandas import read_csv
import matplotlib.pyplot as plt
import pandas as pd
# 读取数据
df = pd.read_csv('household_power_consumption_days.csv', sep=',', header=0,
usecols=[0,1],parse_dates={'date':[0]},index_col=['date'])
# 真实数据列'Global_active_power'
real = df['Global_active_power']
# 指数函数,取前6个时刻的数据加权预测下一时刻的数据
df['EMA'] = df['Global_active_power'].ewm(span=6,min_periods=6).mean()
rolling_mean = df['EMA']
# 查看真实数据的维度和预测数据的维度
print("real Shape-- ",real.shape)#(1442,)
print("rolling_mean Shape-- ",rolling_mean.shape)#(1442,)
预测结果可视化
# 取最后258个时刻的数据绘图
plt.plot(real[-260:-2], color = 'red', label = 'Real')
plt.plot(rolling_mean[-260:-2], color = 'blue', label = 'Predicted')
plt.xlabel('Time')
plt.legend()
plt.show()
计算误差
real = real[-260:-2]
pred = rolling_mean[-260:-2]
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
# 计算误差
mae = mean_absolute_error(pred,real)
mse = mean_squared_error(pred,real)
print("MAE:",mae) # MAE: 178.27270483176076
print("MSE:",mse) # MSE: 62814.68751826136
SMA:权重系数一致;
WMA:权重系数随时间间隔线性递减;
EMA:权重系数随时间间隔指数递减。
参考文献:
https://zhuanlan.zhihu.com/p/430537478