目录

时间序列预测神器:用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 会自动拟合这些组件,并生成预测结果。

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

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

代码示例:对数变换

python 复制代码
# 对 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),限制预测值的范围。

代码示例:逻辑增长模型

python 复制代码
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 填充时间序列中缺失值的完整代码示例。

完整代码示例

python 复制代码
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 绝对值得一试!

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
ocr_sinosecu11 小时前
OCR定制识别:解锁文字识别的无限可能
人工智能·机器学习·ocr
何其有幸.1 小时前
实验3-3 比较大小(PTA|C语言)
c语言·数据结构·算法
奋斗者1号1 小时前
分类数据处理全解析:从独热编码到高维特征优化
人工智能·机器学习·分类
柏油1 小时前
MySQL InnoDB 行锁
数据库·后端·mysql
咖啡调调。1 小时前
使用Django框架表单
后端·python·django
白泽talk1 小时前
2个小时1w字| React & Golang 全栈微服务实战
前端·后端·微服务
摆烂工程师2 小时前
全网最详细的5分钟快速申请一个国际 “edu教育邮箱” 的保姆级教程!
前端·后端·程序员
学渣676562 小时前
【10分钟读论文】Power Transmission Line Inspections电力视觉水文
机器学习
一只叫煤球的猫2 小时前
你真的会用 return 吗?—— 11个值得借鉴的 return 写法
java·后端·代码规范
Asthenia04122 小时前
HTTP调用超时与重试问题分析
后端