时间序列预测神器:用Facebook Prophet轻松填补缺失值与优化预测效果

使用 Facebook Prophet 进行时间序列预测和缺失值填充

在数据分析和机器学习领域,时间序列预测是一个常见的任务。Facebook 开源的 Prophet 是一个专门用于时间序列预测的工具,它简单易用,能够处理复杂的季节性和趋势变化,同时对缺失值和异常值具有一定的鲁棒性。本文将介绍 Prophet 的基本功能,并通过一个代码示例展示如何使用它来填充时间序列中的缺失值。特别地,我们将深入探讨对数变换和逻辑增长模型的设置,这些步骤是根据具体业务需求进行优化的重要环节。

什么是 Facebook Prophet?

Prophet 是 Facebook 开发的一种时间序列预测工具,旨在帮助数据科学家快速生成高质量的预测结果。它基于加性回归模型,能够捕捉时间序列中的趋势、季节性和节假日效应。Prophet 的主要特点包括:

  1. 易于使用:Prophet 提供了简洁的 API,用户无需复杂的统计知识即可快速上手。
  2. 强大的季节性建模:Prophet 能够自动检测并建模年、周、日等不同粒度的季节性。
  3. 灵活的趋势建模:Prophet 使用分段线性或逻辑增长模型来捕捉趋势变化,并允许用户手动指定变化点。
  4. 鲁棒性:Prophet 对缺失值和异常值具有一定的鲁棒性,能够处理不规则采样的时间序列数据。

Prophet 的基本使用方法

Prophet 的核心思想是将时间序列分解为趋势、季节性和节假日效应。其基本模型可以表示为:

在这里插入图片描述

其中:

  • g(t) 是趋势项,捕捉时间序列的整体变化趋势。
  • s(t) 是季节性项,捕捉周期性变化(如日、周、年)。
  • h(t) 是节假日效应项,捕捉特定日期的特殊影响。
  • ϵt 是误差项,表示模型无法解释的随机波动。

在实际使用中,Prophet 会自动拟合这些组件,并生成预测结果。

对数变换:减小预测波动性

在时间序列预测中,数据的波动性可能会对模型的性能产生显著影响。为了减小预测的波动性,我们通常会对目标变量进行对数变换。对数变换可以稳定数据的方差,使数据分布更加接近正态分布,从而提高模型的预测精度。

代码示例:对数变换

# 对 y 列进行对数变换
long_df['y'] = np.log(long_df['y'] + 1)

为什么进行对数变换?

  1. 稳定方差:对数变换可以将乘法关系转化为加法关系,从而稳定数据的方差。
  2. 减小波动性:对数变换可以压缩数据的范围,减小极端值的影响,使数据更加平滑。
  3. 提高模型性能:对数变换后的数据更接近正态分布,有助于提高模型的预测性能。

对数变换的效果

假设原始数据 (y) 的分布如下:

y = [1, 2, 3, 10, 100]

经过对数变换后:

log(y + 1) = [0, 0.693, 1.098, 2.302, 4.605]

可以看到,对数变换有效地压缩了数据的范围,减小了极端值的影响。

逻辑增长模型:确保预测值非负

在某些业务场景中,预测值必须是非负的。例如,销售数据、流量数据等都不可能为负值。为了确保预测值非负,我们可以使用逻辑增长模型(Logistic Growth Model)。逻辑增长模型通过设定上限(cap)和下限(floor),限制预测值的范围。

代码示例:逻辑增长模型

model = Prophet(
    growth='logistic',  # 设置为逻辑增长模型
    yearly_seasonality=False,
    weekly_seasonality=True,
    daily_seasonality=True,
    changepoint_prior_scale=changepoint_prior_scale,  # 调整这个参数以控制变化点的强度
    seasonality_prior_scale=seasonality_prior_scale  # 调整这个参数以控制季节性强度
)

为什么使用逻辑增长模型?

  1. 业务需求:某些业务场景中,预测值必须是非负的。
  2. 模型约束:逻辑增长模型通过设定上限和下限,确保预测值在合理范围内。
  3. 提高预测精度:通过限制预测值的范围,可以避免不合理的结果,提高模型的预测精度。

逻辑增长模型的效果

逻辑增长模型通过以下公式确保预测值非负:

在这里插入图片描述

其中:

  • K 是上限(cap)。
  • r是增长率。
  • t0 是中点时间。

通过设定合理的上限和下限,可以确保预测值始终在合理范围内。

示例:使用 Prophet 填充缺失值

下面是一个使用 Prophet 填充时间序列中缺失值的完整代码示例。

完整代码示例

import pandas as pd
import numpy as np
from prophet import Prophet
from typing import Optional
from datetime import datetime, time

def fill_missing_data_prophet(group: pd.DataFrame, missing_times_list: pd.Series,
                              changepoint_prior_scale: float = 0.05, seasonality_prior_scale: float = 1,
                              error_data_save_path: Optional[str] = 'main/data/处理流程中的中间数据/异常数据.csv'):
    try:
        if not missing_times_list:
            return group
        
        # 创建一个长格式的数据框
        long_df = pd.melt(
            group,
            id_vars=['date', 'user_id'],
            value_vars=time_col_list,
            var_name='time',
            value_name='value'
        )
        
        # 生成完整的 datetime 列
        long_df['datetime'] = pd.to_datetime(
            long_df['date'].astype(str) + ' ' + long_df['time'],
            format='%Y-%m-%d %H:%M'
        )
        long_df.rename(columns={'datetime': 'ds', 'value': 'y'}, inplace=True)
        
        # 对 y 列进行对数变换
        long_df['y'] = np.log(long_df['y'] + 1)
        
        # 获取训练集的最大值和最小值
        max_value = long_df['y'].max()
        min_value = long_df['y'].min()
        if min_value > 0:
            min_value = long_df['y'].min()
        else:
            min_value = 0
        if max_value == 0 or not max_value:
            max_value = np.log(0.001 + 1)
        
        # 初始化 Prophet 模型
        model = Prophet(
            growth='logistic',  # 设置为逻辑增长模型
            yearly_seasonality=False,
            weekly_seasonality=True,
            daily_seasonality=True,
            changepoint_prior_scale=changepoint_prior_scale,  # 控制趋势变化点的强度
            seasonality_prior_scale=seasonality_prior_scale   # 控制季节性强度
        )
        
        # 设置上限和下限
        long_df['cap'] = max_value
        long_df['floor'] = min_value
        
        # 拟合模型
        model.fit(long_df)
        
        # 创建未来数据框,用于预测缺失时间段
        future = []
        for start, end in missing_times_list:
            start_datetime = pd.to_datetime(start)
            end_datetime = pd.to_datetime(end)
            future.extend(pd.date_range(start=start_datetime, end=end_datetime, freq='15T').to_pydatetime().tolist())
        
        future_df = pd.DataFrame(future, columns=['ds'])
        
        # 设置未来数据框的上限和下限
        future_df['cap'] = max_value
        future_df['floor'] = min_value
        
        # 预测缺失值
        forecast = model.predict(future_df)
        
        # 将预测值转换回原始尺度
        forecast['yhat'] = np.exp(forecast['yhat']) - 1
        forecast['yhat_lower'] = np.exp(forecast['yhat_lower']) - 1
        forecast['yhat_upper'] = np.exp(forecast['yhat_upper']) - 1
        
        # 确保预测值非负
        forecast['yhat'] = np.maximum(forecast['yhat'], 0)
        forecast['yhat_lower'] = np.maximum(forecast['yhat_lower'], 0)
        forecast['yhat_upper'] = np.maximum(forecast['yhat_upper'], 0)
        
        # 将预测值填充回原数据框
        for i, row in future_df.iterrows():
            group.loc[group['date'] == datetime.combine(row['ds'].date(), time(0, 0, 0)),
                      row['ds'].strftime('%H:%M')] = forecast.loc[i, 'yhat']
        
        return group
    
    except Exception as e:
        print("Exception: ", e)
        # 持久化存储异常数据
        user_id_err = group['user_id'].iloc[0]
        error_data_save_path = error_data_save_path.replace('.', f"_{user_id_err}.")
        group.to_csv(error_data_save_path, index=False)
        return group

代码说明

  1. 数据预处理

    • 将宽格式数据转换为长格式数据,便于 Prophet 处理。
    • 生成 datetime 列,用于时间序列建模。
    • y 列进行对数变换,以稳定数据的方差。
  2. 模型初始化

    • 使用 Prophet 类初始化模型,并设置参数:
      • growth='logistic':设置为逻辑增长模型,确保预测值非负。
      • yearly_seasonality=False:不考虑年季节性。
      • weekly_seasonality=True:考虑周季节性。
      • daily_seasonality=True:考虑日季节性。
      • changepoint_prior_scale:控制趋势变化点的强度。
      • seasonality_prior_scale:控制季节性强度。
  3. 模型拟合

    • 使用 fit 方法拟合模型。
  4. 预测缺失值

    • 创建未来数据框 future_df,包含需要预测的时间段。
    • 使用 predict 方法生成预测结果。
    • 将预测值转换回原始尺度,并确保预测值非负。
  5. 填充缺失值

    • 将预测值填充回原始数据框。

注意事项

  1. 数据格式

    • Prophet 要求输入数据框包含两列:ds(时间戳)和 y(目标值)。
  2. 异常值处理

    • Prophet 对异常值具有一定的鲁棒性,但在实际使用中,仍需对异常值进行处理以提高预测精度。
  3. 模型参数

    • changepoint_prior_scaleseasonality_prior_scale 是重要的超参数,需要根据数据特性进行调整。
  4. 季节性建模

    • Prophet 会自动检测季节性,但用户也可以手动指定季节性。

总结

Facebook Prophet 是一个强大的时间序列预测工具,适用于快速生成高质量的预测结果。通过对数变换和逻辑增长模型的设置,我们可以根据具体业务需求优化模型,确保预测结果的合理性和准确性。通过本文的介绍和代码示例,我们展示了如何使用 Prophet 填充时间序列中的缺失值。Prophet 的易用性和灵活性使其成为处理时间序列数据的首选工具之一。如果你需要处理复杂的时间序列预测任务,Prophet 绝对值得一试!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷月半明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值