深入探讨时间序列分析中的模型残差

2025年02月18日 由 alex 发表 750 0

模型残差揭示了预测模型所遗漏的信息。对残差进行扎实的分析有助于验证模型的准确性,并指出改进的方向。本章将详细讲解如何有效地分析预测残差。


理解时间序列中的残差

残差是模型预测值与实际发生值之间的差距。在一个运作良好的时间序列模型中,这些残差应该表现出白噪声的特性——即随机、不相关且呈正态分布。如果它们不具备这些特性,就说明模型还有改进的空间。


以下是分析残差的Python实现:


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from statsmodels.tsa.stattools import acf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from statsmodels.tsa.stattools import acf  # Correct import
from statsmodels.graphics.gofplots import ProbPlot
class ResidualAnalyzer:
    """
    A toolkit for analyzing residuals.
    """
    def __init__(self, actual_values, predicted_values):
        self.actual = np.array(actual_values)
        self.predicted = np.array(predicted_values)
        self.residuals = self.actual - self.predicted
    def basic_statistics(self):
        """
        Get key stats on residuals.
        """
        stats_dict = {
            'Mean': np.mean(self.residuals),
            'Std Dev': np.std(self.residuals),
            'Skewness': stats.skew(self.residuals),
            'Kurtosis': stats.kurtosis(self.residuals),
            'Min': np.min(self.residuals),
            'Max': np.max(self.residuals)
        }
        return pd.Series(stats_dict)
    def plot_residual_distribution(self):
        """
        Show how residuals are distributed.
        """
        plt.figure(figsize=(12, 6))
        
        plt.subplot(1, 2, 1)
        sns.histplot(self.residuals, kde=True)
        plt.title('Residual Distribution')
        plt.xlabel('Residual Value')
        plt.ylabel('Frequency')
        plt.savefig("residual_distribution.png")
        
        plt.subplot(1, 2, 2)
        stats.probplot(self.residuals, dist="norm", plot=plt)
        plt.title('Q-Q Plot of Residuals')
        plt.savefig("qq_plot.png")
        
        plt.tight_layout()
        plt.show()
    def normality_tests(self):
        """
        Run normality tests on residuals.
        """
        shapiro_stat, shapiro_p = stats.shapiro(self.residuals)
        anderson_result = stats.anderson(self.residuals)
        jb_stat, jb_p = stats.jarque_bera(self.residuals)
        results = {
            'Shapiro-Wilk': {'statistic': shapiro_stat, 'p-value': shapiro_p},
            'Anderson-Darling': {'statistic': anderson_result.statistic, 
                                 'critical_values': anderson_result.critical_values},
            'Jarque-Bera': {'statistic': jb_stat, 'p-value': jb_p}
        }
        return results
    def autocorrelation_analysis(self, nlags=40):
        """
        Check if residuals are autocorrelated.
        """
        acf_values = acf(self.residuals, nlags=nlags, fft=False)
        confidence_interval = 1.96 / np.sqrt(len(self.residuals))
        
        plt.figure(figsize=(12, 4))
        plt.bar(range(len(acf_values)), acf_values)
        plt.axhline(y=confidence_interval, color='r', linestyle='--')
        plt.axhline(y=-confidence_interval, color='r', linestyle='--')
        plt.title('Autocorrelation Function of Residuals')
        plt.xlabel('Lag')
        plt.ylabel('ACF')
        plt.savefig("autocorrelation_function.png")
        
        plt.show()
        return acf_values
    def interpret_residual_analysis(self):
        """
        Explain what the residuals tell us.
        """
        interpretations = []
        stats = self.basic_statistics()
        if abs(stats['Mean']) < 0.1:
            interpretations.append("Residuals have a near-zero mean, which is good.")
        else:
            interpretations.append("Residuals show bias, suggesting model adjustments are needed.")
        
        normality_tests = self.normality_tests()
        shapiro_p = normality_tests['Shapiro-Wilk']['p-value']
        if shapiro_p > 0.05:
            interpretations.append("Residuals look normally distributed.")
        else:
            interpretations.append("Residuals deviate from normality, which may impact reliability.")
        
        return "\n".join(interpretations)
def main():
    """
    Main function to demonstrate the ResidualAnalyzer
    """
    # Example dataset (simulated)
    np.random.seed(42)
    actual_values = np.random.normal(loc=50, scale=10, size=100)
    predicted_values = actual_values + np.random.normal(loc=0, scale=5, size=100)
    # Initialize ResidualAnalyzer
    analyzer = ResidualAnalyzer(actual_values, predicted_values)
    
    # Print basic statistics
    print("### Basic Statistics ###")
    print(analyzer.basic_statistics())
    # Plot residual distribution
    print("\n### Residual Distribution ###")
    analyzer.plot_residual_distribution()
    # Perform normality tests
    print("\n### Normality Tests ###")
    normality_results = analyzer.normality_tests()
    for test, result in normality_results.items():
        print(f"{test}: {result}")
    # Perform autocorrelation analysis
    print("\n### Autocorrelation Analysis ###")
    analyzer.autocorrelation_analysis(nlags=20)
    # Interpret residual analysis
    print("\n### Residual Analysis Interpretation ###")
    print(analyzer.interpret_residual_analysis())
if __name__ == "__main__":
    main()


1


### Normality Tests ###
Shapiro-Wilk: {'statistic': 0.977533993395285, 'p-value': 0.0852560281344462}
Anderson-Darling: {'statistic': 0.6214102099727086, 'critical_values': array([0.555, 0.632, 0.759, 0.885, 1.053])}
Jarque-Bera: {'statistic': 2.42505305943258, 'p-value': 0.29744482609021683}


2


这些图表展示的内容

直方图和密度图展示了残差的分布情况。对称的钟形曲线表明残差呈正态分布。偏离此形状则暗示存在偏斜或厚尾现象。


Q-Q图将残差分布与正态分布进行比较。如果残差落在对角线上,则表明它们遵循正态分布。偏离对角线则表明残差非正态,这可能会影响统计假设。


自相关函数(ACF)图用于检查残差是否与过去的值相关。位于置信区间内的条形表示随机性。超出置信区间的条形则表明存在自相关,意味着模型尚未捕捉到所有时间依赖模式。


理解残差

在依赖统计测试之前,务必检查残差图。如果残差随时间形成模式,则模型可能遗漏了重要特征。自相关是另一个关键问题——如果残差在时间上存在相关性,则模型尚未充分考虑时间序列的结构。如果存在明显的模式,考虑修改模型或应用变换。


残差中的警示信号

当残差方差随时间变化时,会出现异方差性。这表明预测存在不稳定性。残差中的系统性模式表明遗漏了季节性因素或外部影响。自相关意味着过去的残差会影响当前的残差。这表明模型尚未完全捕捉到时间动态。非正态残差表明模型假设可能不正确。离群值则指示罕见事件或数据问题。


残差为何重要

模型的目标不仅仅是做出接近实际的预测,更重要的是理解其出错的地方。残差分析有助于识别盲点,确保模型捕捉到所有必要的模式。通过结合统计测试、可视化和领域知识,可以完善模型,从而做出更好、更可靠的预测。

文章来源:https://medium.com/@kylejones_47003/model-residuals-in-time-series-analysis-66ad7aed30f9
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
写评论取消
回复取消