数据STUDIO

如何检测时间序列中的异方差性


检测和处理时间序列中的非恒定方差

如果时间序列的方差随时间变化,则该时间序列是异方差的。否则,数据集是同方差的。

异方差性影响时间序列的建模。因此,检测和处理这种情况很重要。

介绍

下面的图显示了热门航空公司乘客的时间序列。你可以看到整个系列的变化是不同的。该系列的后半部分方差较高。这也是数据水平也更高的地方。

图 1:一家航空公司的每月乘客。

该 数据集 [1] 在 pmdarima Python 库中公开可用。

方差的变化对预测来说是有问题的。它会影响适当模型的拟合,从而影响预测性能。

但是,仅目视检查是不切实际的。你如何以更系统的方式检测和处理异方差性?

检测异方差

你可以使用统计检验检查时间序列是否异方差。其中包括:

  • White 测试 [2] ;
  • Breusch-Pagan 测试 [3] ;
  • Goldfeld–Quandt 检验 [4]
这些测试的主要输入是回归模型的残差(例如普通最小二乘法)。原假设是残差以等方差分布。如果 p 值小于显着性水平,我们将拒绝该假设。这意味着时间序列是异方差的。显着性水平通常设置为最大 0.05 的值。

statsmodels Python 库实现了上述三个测试。这是将这些包装在一个类中的片段:

import pandas as pd
import statsmodels.stats.api as sms
from statsmodels.formula.api import ols

TEST_NAMES = [ 'White' , ' Breusch -Pagan' , ' Goldfeld -Quandt' ] 
FORMULA = 'value ~ time' 

class Heteroskedasticity:
  @staticmethod 
  def het_tests ( series: pd.Series, test: str ) -> float : 
     """        
    异方差测试        
    :param series: 单变量时间序列作为 pd.Series
        :param test: 表示测试的字符串。'white','goldfeldquandt', 或者 'breuschpagan'之一
        :return: p 值作为浮点数。
        如果 p 值很高,我们接受零假设,即数据是同方差的
        """
 
        assert test in TEST_NAMES, 'Unknown test'
  
        series = series.reset_index(drop= True ).reset_index() 
        series.columns = [ ' time' , 'value' ] 
        series[ 'time' ] += 1

         olsr = ols(FORMULA, series).fit()
        if test == 'White':
            _, p_value, _, _ = sms.het_white(olsr.resid, olsr.model.exog) 
        elif test == 'Goldfeld-Quandt' : 
            _, p_value, _ = sms.het_goldfeldquandt(olsr.resid, olsr.model. exog, alternative= 'two-sided' ) 
        else : 
            _, p_value, _, _ = sms.het_breuschpagan(olsr.resid, olsr.model.exog) 
        return p_value
      
    @classmethod 
    def  run_all_tests ( cls, series: pd.Series ): 
        test_results = {k: cls.het_tests(series, k) for k in TEST_NAMES} 
        return test_results
      
    @staticmethod
    def get_residuals(series: pd.Series):
        series = series.reset_index(drop=True).reset_index()
        series.columns = ['time', 'value']
        series['time'] += 1
        olsr = ols(FORMULA, series).fit()
        return olsr.resid

Heteroskedasticity类包含两个函数。函数 het_tests 应用特定测试(White、Breusch-Pagan 或 Goldfeld-Quandt)。函数 run_all_tests 一次应用所有三个测试。这些函数的输出是相应检验的 p 值。

下面介绍如何将此代码应用于图 1 中的时间序列。

from pmdarima.datasets import load_airpassengers 
from src.heteroskedasticity import Heteroskedasticity 
series = load_airpassengers( True ) 
test_results = Heteroskedasticity.run_all_tests(series) 
# {'Breusch-Pagan': 4.55e-07,
# 'Goldfeld-Quandt': 8.81e-13,
# 'White': 4.34e-07}

所有测试的 p 值都接近于零。因此,你可以拒绝原假设。这些检验很好地证明了异方差性的存在。

这是时间序列前半部分和后半部分的残差分布:

图 2:时间序列前半部分和后半部分的残差分布。

这两个部分的残差分布不同。Goldfeld-Quandt 检验使用这种类型的拆分来检验异方差性。它检查两个数据子样本中残差的方差是否不同。

转换数据

时间序列中异方差性的常见补救措施是转换数据。对时间序列取对数有助于稳定其变异性。

这是与之前相同的时间序列,但采用对数标度:

图 3:与图 1 相似,但采用对数标度。在这里时间序列随时间显示出稳定的方差。

这一次,该系列的可变性看起来很稳定。我们使用对数标度时间序列重新运行测试:

import numpy as np 
test_results = Heteroskedasticity.run_all_tests(np.log(series)) 

# {'Breusch-Pagan': 0.033, 
# 'Goldfeld-Quandt': 0.18, 
# 'White': 0.10}
这次的 p 值更大。只有一个测试(Breusch-Pagan)拒绝了恒定方差的假设。这是假设显着性水平为 0.05 。

还原log转换

假设你正在使用对数log转换数据进行预测。此时,你需要将预测恢复到原始比例。这是通过逆向转换完成的——在对数的情况下,你应该使用指数。

因此,预测过程的步骤如下:

  1. 变换数据以稳定方差;
  2. 拟合预测模型;
  3. 获取预测,并将它们恢复到原始比例。

下面是一个例子。

import numpy as np 
from pmdarima.datasets import load_airpassengers 
from pmdarima.arima import auto_arima 
from sklearn.model_selection import train_test_split 
series = load_airpassengers( True ) 

# 保留最后 12 个点用于测试
train, test = train_test_split(series, test_size= 12 , shuffle= False ) 
# 稳定训练中的方差
log_train = np.log(train) 

# 构建 arima 模型,m 是季节周期(每月)
 mod = auto_arima(log_train, seasonal= True, m= 12 ) 

# 获取日志预测
log_forecasts = mod.predict( 12 ) 

# 恢复预测
forecasts = np.exp(log_forecasts)
图 4:在对转换后的序列建模后将预测恢复到原始比例。

总结

  • 如果方差不是常数,则时间序列是异方差的;
  • 你可以使用统计检验来检验时间序列是否异方差。其中包括 White Breusch-Pagan 或 Goldfeld–Quandt 检验;
  • 使用对数变换来稳定方差;
  • 不要忘记将预测恢复到原始比例。

参考资料

[1] 数据集: https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.datasets.load_airpassengers.html [2] White 测试: https://www.statsmodels.org/stable/generated/statsmodels.stats.diagnostic.het_white.html#statsmodels.stats.diagnostic.het_white [3] Breusch-Pagan 测试: https://www.statsmodels.org/stable/generated/statsmodels.stats.diagnostic.het_breuschpagan.html#statsmodels.stats.diagnostic.het_breuschpagan [4] Goldfeld–Quandt 检验: https://www.statsmodels.org/stable/generated/statsmodels.stats.diagnostic.het_goldfeldquandt.html#statsmodels.stats.diagnostic.het_goldfeldquandt
作者|Vitor Cerqueira

🏴‍☠️宝藏级🏴‍☠️ 原创公众号『 数据STUDIO 』内容超级硬核。公众号以Python为核心语言,垂直于数据科学领域,包括 可戳 👉 Python | MySQL | 数据分析 | 数据可视化 | 机器学习与数据挖掘 | 爬虫 等,从入门到进阶!

长按👇关注- 数据STUDIO -设为星标,干货速递