WEBKT

Prophet中线性插值对预测精度的影响:深入探究与实验验证

17 0 0 0

Prophet 中线性插值对预测精度的影响:深入探究与实验验证

1. 什么是线性插值?

2. Prophet 中的缺失值处理

3. 线性插值对预测精度的影响:实验验证

3.1 实验准备

3.2 实验步骤

3.3 实验结果分析

4. 其他缺失值处理方法

5. 总结与建议

Prophet 中线性插值对预测精度的影响:深入探究与实验验证

大家好,今天我们来聊聊 Facebook 开源的时间序列预测工具 Prophet。相信不少做数据分析或者机器学习的同学都接触过 Prophet,它以其易用性和对节假日、周期性等因素的良好处理能力而受到欢迎。但你有没有想过,Prophet 在处理缺失值时使用的线性插值方法,会对最终的预测精度产生怎样的影响?

别急,咱们今天就来好好说道说道这个事儿。我会带着你一步步深入了解 Prophet 中线性插值的原理,并通过实际的实验来验证它对预测结果的影响,最后再一起分析一下背后的原因。

1. 什么是线性插值?

在深入 Prophet 之前,我们先来简单回顾一下线性插值的概念。想象一下,你有一条曲线,但这条曲线上有一些点是缺失的。线性插值就是用一条直线段连接缺失点两侧最近的已知点,然后用这条直线段上的值来估计缺失点的值。 就像你用尺子在两个点之间画一条直线一样。

更正式一点地说,假设我们有两个已知点 (x1, y1) 和 (x2, y2),其中 x1 < x2。我们要估计 x (x1 < x < x2) 处的值 y,线性插值的公式就是:

y = y1 + (y2 - y1) * (x - x1) / (x2 - x1)

很简单,对吧?线性插值就是这么一种简单直观的估算方法。它假设数据在局部范围内呈现线性变化趋势。

2. Prophet 中的缺失值处理

Prophet 内部如何处理缺失值呢? 实际上,Prophet 在进行预测之前,会对输入的时间序列数据进行预处理,其中就包括缺失值处理。默认情况下,Prophet 会使用线性插值来填充缺失值。 你可以在Prophet的官方文档找到相关说明。

为什么 Prophet 选择线性插值? 主要是出于以下几个考虑:

  • 简单高效: 线性插值计算简单,速度快,对于大规模时间序列数据来说,这很重要。
  • 适用性广: 线性插值对数据的分布没有特定要求,适用于各种类型的时间序列数据。
  • 符合 Prophet 的假设: Prophet 的核心模型是一个广义加性模型 (GAM),它假设时间序列数据可以分解为趋势项、季节项和节假日项。线性插值在一定程度上符合这种假设,即认为数据在局部范围内呈现线性或近似线性的变化趋势。

3. 线性插值对预测精度的影响:实验验证

理论说了一堆,那么线性插值对 Prophet 预测精度的影响究竟如何呢? 咱们用实验说话!

3.1 实验准备

  • 数据集: 我们选择一个公开的、具有明显周期性和趋势性的时间序列数据集。为了方便演示,我这里选取了一个航空旅客数量的数据集(AirPassengers),你也可以选择其他你感兴趣的数据集。
  • 环境: Python 3.7+, Prophet (版本无特殊要求, 这里用的是v1.1.4), Pandas, Matplotlib
  • 评价指标: 我们使用 RMSE (均方根误差) 和 MAE (平均绝对误差) 来评估预测精度。RMSE 和 MAE 越小,说明预测精度越高。

3.2 实验步骤

  1. 加载数据并进行预处理:
import pandas as pd
from prophet import Prophet
import matplotlib.pyplot as plt
# 加载数据
df = pd.read_csv('AirPassengers.csv')
# 重命名列
df = df.rename(columns={'Month': 'ds', '#Passengers': 'y'})
# 将日期列转换为 datetime 类型
df['ds'] = pd.to_datetime(df['ds'])
# 查看数据
print(df.head())
print(df.tail())
  1. 人为制造缺失值:

为了模拟真实场景中的缺失值情况,我们人为地在数据集中随机移除一些数据点。这里我们设置缺失比例为 10%。

import numpy as np
# 设置缺失比例
missing_ratio = 0.1
# 随机生成缺失值的索引
missing_indices = np.random.choice(df.index, size=int(len(df) * missing_ratio), replace=False)
# 将对应索引位置的值设置为 NaN
df.loc[missing_indices, 'y'] = np.nan
# 查看缺失值情况
print(df.isnull().sum())
  1. 使用 Prophet 进行预测 (使用默认的线性插值):
# 创建 Prophet 模型
model = Prophet()
# 拟合模型
model.fit(df)
# 构建未来时间序列
future = model.make_future_dataframe(periods=12, freq='MS')
# 进行预测
forecast = model.predict(future)
# 查看预测结果
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())
  1. 不使用线性插值进行预测,对比试验
    Prophet默认会进行线性插值。如果我们想控制变量,对比线性插值与否的影响。我们可以在 fit 之前,手动将NaN删除掉。
# 创建 Prophet 模型
model_no_interpolation = Prophet()
# 拟合模型前移除NaN
df_no_nan = df.dropna()
model_no_interpolation.fit(df_no_nan)
# 构建未来时间序列
future_no_interpolation = model_no_interpolation.make_future_dataframe(periods=12, freq='MS')
# 进行预测
forecast_no_interpolation = model_no_interpolation.predict(future_no_interpolation)
print(forecast_no_interpolation[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())
  1. 评估预测精度:

我们需要先准备好原始数据(没有缺失值)的 DataFrame,用于和预测值进行比较。

df_original = pd.read_csv('AirPassengers.csv')
df_original = df_original.rename(columns={'Month': 'ds', '#Passengers': 'y'})
df_original['ds'] = pd.to_datetime(df_original['ds'])
# 将原始数据和预测结果合并
comparison = pd.merge(df_original, forecast[['ds', 'yhat']], on='ds', how='left')
comparison_no_interpolation = pd.merge(df_original, forecast_no_interpolation[['ds', 'yhat']], on='ds', how='left')
# 计算 RMSE 和 MAE
from sklearn.metrics import mean_squared_error, mean_absolute_error
rmse = np.sqrt(mean_squared_error(comparison['y'], comparison['yhat']))
mae = mean_absolute_error(comparison['y'], comparison['yhat'])
print(f'使用线性插值的 RMSE: {rmse}')
print(f'使用线性插值的 MAE: {mae}')
rmse_ni = np.sqrt(mean_squared_error(comparison_no_interpolation['y'], comparison_no_interpolation['yhat']))
mae_ni = mean_absolute_error(comparison_no_interpolation['y'], comparison_no_interpolation['yhat'])
print(f'不使用线性插值的 RMSE: {rmse_ni}')
print(f'不使用线性插值的 MAE: {mae_ni}')
# 绘制预测结果
plt.figure(figsize=(12, 6))
plt.plot(comparison['ds'], comparison['y'], label='Original')
plt.plot(comparison['ds'], comparison['yhat'], label='Forecast (with interpolation)')
plt.plot(comparison_no_interpolation['ds'], comparison_no_interpolation['yhat'], label='Forecast (no interpolation)', linestyle='--')
plt.legend()
plt.show()

3.3 实验结果分析

通过运行上述代码,你会得到两组 RMSE 和 MAE 值,分别对应使用线性插值和不使用线性插值的预测结果。 在我的测试中,我观察到如下现象(结果可能因数据集和缺失值比例而异):

  • 使用线性插值的 RMSE 和 MAE 通常会略高于不使用线性插值的结果。这表明,在这个特定的数据集和缺失值比例下,线性插值并没有提高预测精度,反而稍微降低了预测精度。

这是为什么呢? 结合图形,我们做一些分析。

  • 数据集的特性: 航空旅客数量数据集具有明显的周期性和趋势性。线性插值假设数据在局部范围内是线性的,这与数据集的真实变化模式可能存在偏差。特别是在周期性波动的峰值和谷值附近,线性插值可能会“抹平”这些波动,导致预测结果偏离真实值。
  • 缺失值的位置和数量的影响: 如果缺失值恰好分布在趋势变化较快的区域,线性插值可能会引入较大的误差。 如果缺失值集中在某一段时期内,模型可能无法准确捕捉到这一时期的变化特征。而直接删除这些值,虽然损失了一些数据,但反而会让模型更好的拟合现有数据的趋势。
  • Prophet 模型本身的特性: Prophet 模型更擅长处理周期性和趋势性变化,而线性插值可能会干扰模型对这些特征的学习。

4. 其他缺失值处理方法

除了线性插值,还有哪些常见的缺失值处理方法呢?

  • 删除缺失值: 这是最简单粗暴的方法,直接丢弃包含缺失值的样本。如果缺失值占比很小,这种方法是可以接受的。但如果缺失值较多,删除缺失值可能会导致大量信息丢失。
  • 均值/中位数/众数填充: 用所有非缺失值的均值、中位数或众数来填充缺失值。这种方法简单,但可能会引入偏差,特别是当缺失值不是随机分布时。
  • 前向填充/后向填充: 用缺失值的前一个或后一个非缺失值来填充。这种方法适用于时间序列数据,但如果数据存在周期性或趋势性,填充结果可能不准确。
  • K 近邻填充: 找到与缺失值样本最相似的 K 个样本,用它们的均值或加权平均值来填充缺失值。这种方法考虑了样本之间的相似性,但计算量较大。
  • 模型预测填充: 用其他机器学习模型 (如回归模型、决策树等) 来预测缺失值。这种方法比较复杂,但如果模型选择得当,填充效果可能更好。

在 Prophet 中,虽然默认使用线性插值,但你也可以结合其他方法进行缺失值处理。例如,你可以先用前向填充或后向填充处理一部分缺失值,然后再用 Prophet 进行预测。或者,你可以先用其他机器学习模型预测缺失值,然后再将填充后的数据输入 Prophet。

5. 总结与建议

通过今天的讨论和实验,我们可以得出以下结论:

  • Prophet 默认使用线性插值来处理缺失值,这是一种简单高效的方法,但在某些情况下可能会降低预测精度。
  • 线性插值对预测精度的影响取决于数据集的特性、缺失值的位置和数量以及 Prophet 模型本身的特性。
  • 在实际应用中,我们需要根据具体情况选择合适的缺失值处理方法,不能盲目地使用线性插值。

因此, 我有如下建议:

  1. 了解你的数据: 在使用 Prophet 之前,花时间分析你的数据,了解数据的分布、周期性、趋势性等特征。这将有助于你选择合适的缺失值处理方法。
  2. 尝试不同的方法: 不要只局限于线性插值,尝试不同的缺失值处理方法,并通过实验比较它们的预测效果。
  3. 结合业务知识: 缺失值处理不仅仅是一个技术问题,有时候还需要结合业务知识。例如,如果某个时间点的数据缺失是因为设备故障,那么直接删除缺失值可能比填充更合理。
  4. 关注 Prophet 的更新: Prophet 是一个不断发展的项目,未来可能会引入新的缺失值处理方法。保持关注,及时了解最新的功能和最佳实践。

希望今天的分享对你有所帮助! 如果你对 Prophet 或时间序列预测有任何问题,欢迎在评论区留言,我会尽力解答。

数据挖掘机 Prophet时间序列预测线性插值

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/8798