Prophet 时间序列预测:缺失值处理与实战技巧
一、 为什么缺失值是“拦路虎”?
二、 Prophet 缺失值处理策略: 你需要知道的
2.1 Prophet 内置的缺失值处理方法
2.2 深入理解 Prophet 的 fit 方法
2.3 如何查看 Prophet 处理后的数据?
三、 实战演练: 如何在 Prophet 中处理缺失值?
3.1 准备数据
3.2 使用 Prophet 进行预测
3.3 评估预测结果
3.4 改进策略: 结合业务知识与参数调整
策略一: 尝试不同的插补方法
策略二: 结合业务知识,自定义缺失值处理方法
策略三: 调整模型参数
四、 案例分析: 真实场景下的缺失值处理
4.1 案例背景
4.2 解决方案
4.3 代码示例
五、 总结: 掌握 Prophet 缺失值处理的“葵花宝典”
你好,我是老K,一个在时间序列预测领域摸爬滚打了多年的老家伙。今天,咱们来聊聊 Prophet 这个好用的时间序列预测工具,以及在实际应用中经常会遇到的一个“拦路虎”—— 缺失值。 别看缺失值不起眼,处理不好,预测结果可就“惨不忍睹”了。
一、 为什么缺失值是“拦路虎”?
在真实世界的数据中,缺失值几乎是不可避免的。可能是由于数据采集的错误、传感器故障、数据传输中断,或者仅仅是数据未被记录等等。这些缺失值,就好比是拼图里的“残片”,会直接影响到我们对整个“拼图”的理解。
具体来说,缺失值会带来以下问题:
- 模型训练偏差: Prophet 模型在训练时,会试图学习数据中的模式。如果数据中存在大量缺失值,模型可能无法准确地捕捉到这些模式,导致预测结果出现偏差。
- 预测准确性降低: 缺失值会影响模型的拟合程度,使得模型在预测未来的数据时,无法准确地反映真实的趋势和季节性,从而降低预测的准确性。
- 分析结果误导: 在进行时间序列分析时,缺失值可能导致我们对数据的理解出现偏差,例如,低估或高估某个时间段内的实际情况。
二、 Prophet 缺失值处理策略: 你需要知道的
幸运的是,Prophet 已经提供了一些处理缺失值的“武器”,但要真正用好它们,还需要结合实际情况,灵活运用。咱们先来看看 Prophet 内部的处理机制,再来探讨如何结合业务知识,进行更精细的调整。
2.1 Prophet 内置的缺失值处理方法
Prophet 在处理缺失值方面,主要依赖于以下两种方式:
线性插补: 这是 Prophet 默认的缺失值处理方法。对于时间序列中的缺失值,Prophet 会使用线性插补的方式进行填充。这意味着,对于缺失值,Prophet 会根据缺失值前后两个已知值的线性关系,计算出缺失值应该取的值。这种方法简单易行,适用于数据缺失量不大的情况。
忽略缺失值: 在某些情况下,如果缺失值比较多,或者缺失值对预测结果的影响较小,Prophet 可能会选择忽略缺失值。具体来说,Prophet 会将缺失值所在的时间点,从训练数据中剔除,从而避免缺失值对模型训练的影响。但是,这种方法可能会导致模型在某些时间段内,缺乏足够的数据进行学习,从而影响预测的准确性。
2.2 深入理解 Prophet 的 fit
方法
在使用 Prophet 进行时间序列预测时,核心步骤就是调用 fit
方法。 实际上,fit
方法内部就包含了缺失值处理的逻辑。 你不需要手动进行缺失值填充, Prophet 会自动完成。 不过,了解 fit
方法的细节,有助于我们更好地理解 Prophet 的处理方式,并在必要的时候,进行更精细的控制。
在 Prophet 的 fit
方法中,主要的处理流程如下:
- 数据预处理:
fit
方法首先会对输入的数据进行预处理,包括检查数据的格式、排序等。 在这个过程中,Prophet 会自动识别缺失值。 - 线性插补: 如果数据中存在缺失值,并且
n_changepoints
(突变点数量) 参数没有被设置,或者设置的数值没有影响到缺失值,Prophet 就会使用线性插补的方式,对缺失值进行填充。 - 模型训练: 在缺失值被处理后, Prophet 会使用处理后的数据,进行模型训练。 训练过程包括,确定趋势项、季节性项,以及节假日效应等。
2.3 如何查看 Prophet 处理后的数据?
虽然 Prophet 自动处理了缺失值,但我们仍然有必要去了解 Prophet 内部到底是如何处理的。 这样做,可以帮助我们评估处理的效果,并根据需要进行调整。 你可以通过以下方式,查看 Prophet 处理后的数据:
- 使用
predict
方法: 在调用predict
方法进行预测时, Prophet 会使用处理后的数据,进行预测。 你可以通过查看预测结果,来间接了解 Prophet 的缺失值处理效果。 - 查看模型参数: 在模型训练完成后,你可以查看模型内部的参数,例如,趋势项的参数、季节性项的参数等。 这些参数可以反映出,模型对数据的拟合程度,以及对缺失值的处理效果。
三、 实战演练: 如何在 Prophet 中处理缺失值?
理论讲了这么多,咱们还是得“撸起袖子”干起来,通过实际案例,来体验一下如何在 Prophet 中处理缺失值。 为了便于理解,我将通过以下几个方面进行讲解:
- 准备数据: 模拟一个包含缺失值的时间序列数据。
- 使用 Prophet 进行预测: 直接使用 Prophet 进行预测,观察预测结果。
- 评估预测结果: 使用一些评估指标,来衡量预测的准确性。
- 改进策略: 尝试不同的缺失值处理方法,以及模型参数调整,来提高预测的准确性。
3.1 准备数据
首先,我们需要准备一个包含缺失值的时间序列数据。 这里,我们使用 Python 的 pandas
库,来模拟一个简单的时间序列,并随机引入缺失值。 数据包括日期 (ds
) 和数值 (y
) 两列。
import pandas as pd import numpy as np from prophet import Prophet from sklearn.metrics import mean_squared_error, mean_absolute_error # 生成模拟数据 np.random.seed(0) dates = pd.date_range(start='2023-01-01', end='2023-12-31') y_values = np.sin(2 * np.pi * np.arange(len(dates)) / 30) + np.random.normal(0, 0.2, len(dates)) df = pd.DataFrame({'ds': dates, 'y': y_values}) # 随机引入缺失值 missing_indices = np.random.choice(len(df), size=int(0.1 * len(df)), replace=False) df.loc[missing_indices, 'y'] = np.nan print(df.head()) print(df.isnull().sum())
运行这段代码,你将得到一个包含缺失值的数据集。 df.head()
会显示数据的前几行,df.isnull().sum()
会显示每列缺失值的数量。 从输出结果可以看出,我们的数据中确实存在缺失值。
3.2 使用 Prophet 进行预测
接下来,我们使用 Prophet 来对这个数据集进行预测。
# 创建 Prophet 模型 model = Prophet() # 拟合模型 model.fit(df) # 创建未来时间序列 future = model.make_future_dataframe(periods=30) # 进行预测 forecast = model.predict(future) # 打印预测结果 print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()) # 可视化预测结果 fig1 = model.plot(forecast) fig2 = model.plot_components(forecast)
在这段代码中,我们首先创建了一个 Prophet 模型,然后使用 fit
方法,对数据进行训练。 接着,我们使用 make_future_dataframe
方法,创建了未来的时间序列,用于预测。 最后,我们使用 predict
方法,进行预测,并打印了预测结果,以及可视化了预测结果。
3.3 评估预测结果
仅仅看到预测结果,我们还不能判断预测的准确性。 我们需要使用一些评估指标,来衡量预测的准确性。 常用的评估指标包括:
- 均方根误差 (RMSE): RMSE 衡量了预测值与真实值之间的差异。 RMSE 越小,表示预测的准确性越高。
- 平均绝对误差 (MAE): MAE 衡量了预测值与真实值之间的平均绝对差异。 MAE 越小,表示预测的准确性越高。
为了计算这些指标,我们需要将预测结果,与真实值进行比较。 由于我们的数据中,只有部分时间点有真实值,因此,我们需要将预测结果,与真实值进行对齐。
# 准备评估数据 forecast_df = forecast.set_index('ds') true_df = df.dropna().set_index('ds') # 合并预测值和真实值 merged_df = forecast_df.join(true_df, how='inner') # 计算评估指标 rmse = np.sqrt(mean_squared_error(merged_df['y'], merged_df['yhat'])) mae = mean_absolute_error(merged_df['y'], merged_df['yhat']) print(f'RMSE: {rmse}') print(f'MAE: {mae}')
在这段代码中,我们首先将预测结果和真实值,按照日期 (ds
) 进行对齐。 然后,我们使用 mean_squared_error
和 mean_absolute_error
函数,计算了 RMSE 和 MAE。 通过查看这些指标,我们可以评估预测的准确性。
3.4 改进策略: 结合业务知识与参数调整
如果预测结果不理想,我们需要采取一些改进策略,来提高预测的准确性。 以下是一些常用的策略:
- 数据清洗: 在进行预测之前,对数据进行清洗,可以提高预测的准确性。 例如,我们可以使用插补方法,对缺失值进行填充。 除了线性插补,还可以尝试其他的插补方法,例如,均值插补、中位数插补、或者使用更复杂的插补模型。
- 特征工程: 增加额外的特征,可以提高模型的预测能力。 例如,我们可以添加节假日信息、天气信息、或者其他相关的业务指标。
- 参数调整: 调整 Prophet 模型中的参数,可以优化预测结果。 例如,我们可以调整
changepoint_prior_scale
、seasonality_prior_scale
等参数,来控制模型的拟合程度。 此外,我们还可以调整季节性参数,例如,调整季节性的周期、幅度等。
策略一: 尝试不同的插补方法
前面我们提到, Prophet 默认使用线性插补。 那么,我们是否可以尝试其他插补方法呢? 当然可以! 例如,我们可以使用均值插补,或者中位数插补。 在 pandas
库中,提供了 fillna
方法,可以方便地进行缺失值填充。
# 均值插补 df_mean = df.copy() df_mean['y'].fillna(df_mean['y'].mean(), inplace=True) # 中位数插补 df_median = df.copy() df_median['y'].fillna(df_median['y'].median(), inplace=True) # 使用 Prophet 预测 (均值插补) model_mean = Prophet() model_mean.fit(df_mean) future_mean = model_mean.make_future_dataframe(periods=30) forecast_mean = model_mean.predict(future_mean) # 评估预测结果 forecast_mean_df = forecast_mean.set_index('ds') merged_mean_df = forecast_mean_df.join(true_df, how='inner') rmse_mean = np.sqrt(mean_squared_error(merged_mean_df['y'], merged_mean_df['yhat'])) mae_mean = mean_absolute_error(merged_mean_df['y'], merged_mean_df['yhat']) print(f'Mean Imputation - RMSE: {rmse_mean}, MAE: {mae_mean}') # 使用 Prophet 预测 (中位数插补) model_median = Prophet() model_median.fit(df_median) future_median = model_median.make_future_dataframe(periods=30) forecast_median = model_median.predict(future_median) # 评估预测结果 forecast_median_df = forecast_median.set_index('ds') merged_median_df = forecast_median_df.join(true_df, how='inner') rmse_median = np.sqrt(mean_squared_error(merged_median_df['y'], merged_median_df['yhat'])) mae_median = mean_absolute_error(merged_median_df['y'], merged_median_df['yhat']) print(f'Median Imputation - RMSE: {rmse_median}, MAE: {mae_median}')
通过比较不同插补方法的 RMSE 和 MAE,我们可以选择最适合的插补方法。
策略二: 结合业务知识,自定义缺失值处理方法
除了使用通用的插补方法,我们还可以结合业务知识,自定义缺失值处理方法。 例如,如果我们的数据是电商平台的销售数据,那么,缺失值可能发生在周末,因为周末的销售额通常较低。 在这种情况下,我们可以使用周末的销售额的平均值,来填充缺失值。
# 模拟业务知识,周末缺失值使用周末平均值填充 df_business = df.copy() # 找到周末的索引 df_business['dayofweek'] = df_business['ds'].dt.dayofweek weekend_indices = df_business[df_business['dayofweek'].isin([5, 6])].index # 计算周末销售额的平均值 weekend_mean = df_business.loc[~weekend_indices, 'y'].mean() # 使用周末平均值填充缺失值 df_business.loc[weekend_indices, 'y'] = df_business.loc[weekend_indices, 'y'].fillna(weekend_mean) # 使用 Prophet 预测 (业务知识插补) model_business = Prophet() model_business.fit(df_business) future_business = model_business.make_future_dataframe(periods=30) forecast_business = model_business.predict(future_business) # 评估预测结果 forecast_business_df = forecast_business.set_index('ds') merged_business_df = forecast_business_df.join(true_df, how='inner') rmse_business = np.sqrt(mean_squared_error(merged_business_df['y'], merged_business_df['yhat'])) mae_business = mean_absolute_error(merged_business_df['y'], merged_business_df['yhat']) print(f'Business Knowledge Imputation - RMSE: {rmse_business}, MAE: {mae_business}')
在这个例子中,我们根据业务知识,对缺失值进行了特殊的处理,从而提高了预测的准确性。
策略三: 调整模型参数
Prophet 模型中有很多参数,可以用来调整模型的拟合程度。 例如,changepoint_prior_scale
参数,可以控制模型对趋势变化的敏感度。 seasonality_prior_scale
参数,可以控制模型对季节性变化的敏感度。
# 调整 changepoint_prior_scale 参数 model_changepoint = Prophet(changepoint_prior_scale=0.1) model_changepoint.fit(df) future_changepoint = model_changepoint.make_future_dataframe(periods=30) forecast_changepoint = model_changepoint.predict(future_changepoint) # 评估预测结果 forecast_changepoint_df = forecast_changepoint.set_index('ds') merged_changepoint_df = forecast_changepoint_df.join(true_df, how='inner') rmse_changepoint = np.sqrt(mean_squared_error(merged_changepoint_df['y'], merged_changepoint_df['yhat'])) mae_changepoint = mean_absolute_error(merged_changepoint_df['y'], merged_changepoint_df['yhat']) print(f'Changepoint Prior Scale - RMSE: {rmse_changepoint}, MAE: {mae_changepoint}') # 调整 seasonality_prior_scale 参数 model_seasonality = Prophet(seasonality_prior_scale=10) model_seasonality.fit(df) future_seasonality = model_seasonality.make_future_dataframe(periods=30) forecast_seasonality = model_seasonality.predict(future_seasonality) # 评估预测结果 forecast_seasonality_df = forecast_seasonality.set_index('ds') merged_seasonality_df = forecast_seasonality_df.join(true_df, how='inner') rmse_seasonality = np.sqrt(mean_squared_error(merged_seasonality_df['y'], merged_seasonality_df['yhat'])) mae_seasonality = mean_absolute_error(merged_seasonality_df['y'], merged_seasonality_df['yhat']) print(f'Seasonality Prior Scale - RMSE: {rmse_seasonality}, MAE: {mae_seasonality}')
通过调整这些参数,我们可以优化模型的拟合程度,从而提高预测的准确性。
四、 案例分析: 真实场景下的缺失值处理
理论和实践都讲了,咱们再来结合一个真实的案例,看看在实际工作中,如何处理 Prophet 中的缺失值。 假设你是一家电商公司的数据分析师,需要预测未来一周的销售额。 你的数据包括每日的销售额,但是,由于系统故障,某些天的销售额数据缺失了。
4.1 案例背景
- 数据来源: 电商平台的每日销售额数据。
- 数据特点: 数据包含缺失值,缺失值可能发生在周末,也可能发生在工作日。
- 目标: 预测未来一周的销售额,并尽可能提高预测的准确性。
4.2 解决方案
- 数据预处理: 首先,我们需要对数据进行预处理,包括检查数据的格式,以及处理缺失值。 在这里,我们先使用线性插补方法,对缺失值进行填充。 当然,你也可以尝试其他插补方法,并比较不同方法的预测效果。
- 特征工程: 为了提高预测的准确性,我们可以添加一些额外的特征。 例如,我们可以添加节假日信息,天气信息,或者其他相关的业务指标。 在这个案例中,我们没有添加节假日信息,因为节假日对销售额的影响,在我们的数据中,可能并不明显。 但是,如果节假日对销售额有明显的影响,那么,添加节假日信息,可以显著提高预测的准确性。
- 模型训练: 使用 Prophet 模型,对数据进行训练。 在训练过程中,我们可以根据实际情况,调整 Prophet 模型中的参数。 例如,我们可以调整
changepoint_prior_scale
参数,来控制模型对趋势变化的敏感度。 调整seasonality_prior_scale
参数,来控制模型对季节性变化的敏感度。 - 预测: 使用训练好的模型,对未来一周的销售额进行预测。 在进行预测时,我们需要创建未来时间序列。 创建未来时间序列的方法,就是使用
make_future_dataframe
方法。 - 评估: 评估预测结果,并根据需要进行调整。 评估预测结果,可以使用 RMSE、MAE 等评估指标。 如果预测结果不理想,我们可以尝试不同的插补方法、添加额外的特征、或者调整模型参数,来提高预测的准确性。
4.3 代码示例
import pandas as pd from prophet import Prophet from sklearn.metrics import mean_squared_error, mean_absolute_error # 模拟数据 (包含缺失值) df = pd.DataFrame({ 'ds': pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05', '2024-01-06', '2024-01-07', '2024-01-08', '2024-01-09', '2024-01-10', '2024-01-11', '2024-01-12', '2024-01-13', '2024-01-14']), 'y': [100, 120, np.nan, 150, 140, np.nan, 130, 110, 130, 160, 150, 170, 160, 140] }) # 1. 数据预处理 (线性插补) df_filled = df.copy() df_filled['y'].interpolate(method='linear', inplace=True) # 2. 模型训练 model = Prophet() model.fit(df_filled) # 3. 预测 future = model.make_future_dataframe(periods=7) forecast = model.predict(future) # 4. 评估 (可选,如果原始数据有更多) # 假设我们有2024-01-01 到 2024-01-14 的真实值 # 那么就可以评估 # 5. 结果分析和调整 print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(7)) # 如果预测效果不好,尝试以下调整: # * 不同的插补方法 (均值、中位数、业务知识) # * 调整模型参数 (changepoint_prior_scale, seasonality_prior_scale) # * 增加特征 (节假日,天气等)
在这个案例中,我们通过数据预处理、模型训练、预测和评估,来处理 Prophet 中的缺失值,并提高预测的准确性。 当然,在实际工作中,我们可能需要根据实际情况,进行更多的调整和优化。
五、 总结: 掌握 Prophet 缺失值处理的“葵花宝典”
好了,老K 今天就分享到这里。 咱们一起回顾一下,在 Prophet 中处理缺失值的“葵花宝典”:
- 了解 Prophet 的内置处理机制: Prophet 默认使用线性插补处理缺失值,并自动完成。 了解
fit
方法的细节,可以帮助我们更好地理解 Prophet 的处理方式。 - 数据预处理是关键: 在进行预测之前,务必对数据进行预处理,包括检查数据的格式,以及处理缺失值。 可以尝试不同的插补方法,并比较不同方法的预测效果。
- 结合业务知识: 结合业务知识,自定义缺失值处理方法,可以提高预测的准确性。 例如,根据业务知识,对周末的缺失值进行特殊处理。
- 特征工程: 增加额外的特征,可以提高模型的预测能力。 例如,添加节假日信息、天气信息等。
- 参数调整: 调整 Prophet 模型中的参数,可以优化预测结果。 例如,调整
changepoint_prior_scale
、seasonality_prior_scale
等参数,来控制模型的拟合程度。 - 评估和迭代: 评估预测结果,并根据需要进行调整。 这是一个不断迭代的过程。 通过不断尝试不同的方法,我们可以找到最适合的解决方案。
记住,没有完美的解决方案,只有最合适的解决方案。 掌握了这些“葵花宝典”,相信你在使用 Prophet 进行时间序列预测时,就能更加游刃有余,轻松应对缺失值带来的挑战。 祝你在时间序列预测的道路上,越走越远!
如果你有任何问题,欢迎随时和我交流!