时间序列篇:Prophet负责优雅,LightGBM负责杀疯

在时间序列预测中,我们经常会面临具有季节性波动、节假日效应和突发变化的数据。例如,电力需求的预测不仅受到季节变化的影响,还会受到节假日、周末等因素的波动。传统的时间序列方法,如ARIMA和SARIMA,虽然能够捕捉一定的趋势和季节性,但它们对于复杂的非线性关系和残差修正的能力有限。为了解决这些问题,我们可以结合 ProphetLightGBM,让两者各自发挥优势,提高预测精度。

本文将分享如何结合Prophet和LightGBM来进行时间序列预测,解决相关技术难点,并展示具体的实现方法。

Prophet + LightGBM组合:如何让它们协同工作?

在时间序列预测中,Prophet模型通常能够有效地捕捉趋势和季节性波动,但它对于一些复杂的波动,特别是"突发性波动"或非线性波动的预测效果较差。而LightGBM,作为一种强大的机器学习模型,能够通过学习历史数据的残差来修正这些复杂的波动。因此,将两者结合起来,就能实现对时间序列数据的更精准预测。

如何结合Prophet和LightGBM?

首先,我们用Prophet模型对时间序列进行初步的预测,获得趋势和季节性成分。然后,计算出Prophet预测值与真实值之间的残差。接着,用LightGBM模型来预测这些残差,最后将LightGBM修正后的残差加到Prophet的预测值上,得到最终的预测结果。

ini 复制代码
from prophet import Prophet
import lightgbm as lgb
import pandas as pd
import numpy as np

# 读取数据
data = pd.read_excel("data/用户日用电数据2023-01-01_2025-08-11.xlsx", parse_dates=["Date"])
data["ds"] = data["Date"].dt.floor("D")
data.rename(columns={"This Day Power": "y"}, inplace=True)

# 训练Prophet模型
model = Prophet(yearly_seasonality=True, weekly_seasonality=False, daily_seasonality=True)
model.fit(data)

# 预测
future = model.make_future_dataframe(data, periods=365)
forecast = model.predict(future)

# 获取Prophet预测值
data['yhat'] = forecast['yhat']
data['residual'] = data['y'] - data['yhat']

上面的代码首先使用Prophet模型对数据进行预测,并计算出残差。接下来,LightGBM将用于修正这些残差。

滞后特征:让模型"记住"过去的预测误差

在时间序列建模中,滞后特征(即过去某些时刻的值)非常重要。特别是在残差修正中,过去的预测误差会对当前的预测产生影响。因此,在构建LightGBM模型时,我们需要将这些滞后特征作为输入特征,让模型能根据过去的误差做出更精准的修正。

我们为数据添加了滞后特征,比如过去1天、2天和7天的残差。这些特征有助于LightGBM捕捉数据的周期性和规律性。

bash 复制代码
def add_lag_features(df, col, lags):
    for lag in lags:
        df[f'{col}_lag{lag}'] = df[col].shift(lag)
    return df

# 添加滞后特征
lags = [1, 2, 7]  # 滞后1天、2天、7天
data = add_lag_features(data, 'residual', lags)

通过add_lag_features函数,我们将过去几天的残差作为特征输入到LightGBM中,以帮助模型更好地进行残差修正。

LightGBM模型训练与参数优化

LightGBM模型的超参数选择对于模型的性能至关重要。对于参数的优化,网格搜索(GridSearch)和时间序列交叉验证(TimeSeries CV)是一种有效的方案。网格搜索通过遍历可能的超参数组合,选择最优的参数配置,而时间序列交叉验证确保模型在训练时不打乱数据的时间顺序。

ini 复制代码
from sklearn.model_selection import ParameterGrid
import lightgbm as lgb

# 设置参数网格
param_grid = {
    'num_leaves': [15, 31, 63],
    'learning_rate': [0.01, 0.05, 0.1],
    'max_depth': [3, 5, 7]
}

best_score = float('inf')
best_params = None

# 使用网格搜索优化LightGBM参数
grid = list(ParameterGrid(param_grid))
lgb_train_set = lgb.Dataset(data[['residual_lag1', 'residual_lag2', 'residual_lag7']], data['residual'])

for params in grid:
    cv_params = {
        'objective': 'regression',
        'metric': 'rmse',
        'num_leaves': params['num_leaves'],
        'learning_rate': params['learning_rate'],
        'max_depth': params['max_depth'],
    }
    cv_result = lgb.cv(cv_params, lgb_train_set, num_boost_round=2000, nfold=5, seed=42)
    mean_rmse = min(cv_result['rmse-mean'])
    if mean_rmse < best_score:
        best_score = mean_rmse
        best_params = params

print("最佳参数:", best_params)

通过网格搜索,我们能够找到最优的超参数,并用这些参数重新训练LightGBM模型,从而提高预测精度。

增强波动性:模拟真实数据中的不确定性

在许多实际应用中,我们不仅关心预测的准确性,还需要考虑到预测波动的真实性。比如在电力需求预测中,实际的电力需求往往具有一定的波动性,而我们希望在预测中也能体现出这种波动。

因此,我们设计了一个"波动增强"的策略,在保持总电量不变的前提下,放大预测值的日常波动。

ini 复制代码
def amplify_fluctuation(df, factor, col_date='ds', col_power='yhat'):
    df = df.copy()
    mean = df[col_power].mean()
    delta = df[col_power] - mean
    df[col_power] = mean + delta * factor
    df[col_power] += (df[col_power].sum() - df[col_power].sum()) / len(df)
    return df

# 增加预测波动性
data['yhat_amplified'] = amplify_fluctuation(data, factor=1.05, col_date='ds', col_power='yhat')

通过这种方法,我们能够放大预测结果中的波动性,同时确保总电量的和不变。这样的处理能够更好地模拟现实世界中的波动趋势。

模型评估:验证预测效果

最后,为了评估Prophet和LightGBM结合模型的效果,我们使用了常见的评估指标,如MAE(平均绝对误差)、RMSE(均方根误差)和MAPE(平均绝对百分比误差)。这些指标帮助我们量化模型在训练集、验证集和测试集上的表现,并对比不同模型的效果。

scss 复制代码
from sklearn.metrics import mean_absolute_error, mean_squared_error

def print_metrics(name, df):
    print(f"{name}集:")
    print("Prophet MAE:", mean_absolute_error(df['y'], df['yhat']))
    print("Prophet RMSE:", np.sqrt(mean_squared_error(df['y'], df['yhat'])))
    print("Prophet MAPE:", np.mean(np.abs((df['y'] - df['yhat']) / (df['y'] + 1e-8))) * 100)
    print("Prophet+LGB MAE:", mean_absolute_error(df['y'], df['yhat_lgb']))
    print("Prophet+LGB RMSE:", np.sqrt(mean_squared_error(df['y'], df['yhat_lgb'])))

print_metrics("训练", data)

通过这些评估指标,我们可以清晰地看到Prophet与LightGBM模型结合后的预测效果,并与单独使用Prophet模型的结果进行对比。

总结

结合Prophet和LightGBM进行时间序列预测,不仅能够利用Prophet捕捉季节性和趋势,还能通过LightGBM修正残差,进一步提升预测的准确性。通过合理的特征工程、超参数调优以及波动增强策略,最终我们能够得到更精确且灵活的预测结果。

这种方法在电力需求预测、气象预测等场景中非常有效。希望本文能够帮助大家理解如何结合统计模型和机器学习模型来提高时间序列预测的性能,并为实际应用提供一些启发。

相关推荐
做科研的周师兄1 分钟前
【机器学习入门】1.2 初识机器学习:从数据到智能的认知之旅
大数据·数据库·人工智能·python·机器学习·数据分析·机器人
耳总是一颗苹果15 分钟前
排序---插入排序
数据结构·算法·排序算法
YLCHUP31 分钟前
【联通分量】题解:P13823 「Diligent-OI R2 C」所谓伊人_连通分量_最短路_01bfs_图论_C++算法竞赛
c语言·数据结构·c++·算法·图论·广度优先·图搜索算法
王小王-12338 分钟前
基于Python的游戏推荐与可视化系统的设计与实现
python·游戏·游戏推荐系统·游戏可视化
KevinWang_1 小时前
让 AI 写一个给图片加水印的 Python 脚本
python
花火|1 小时前
算法训练营day62 图论⑪ Floyd 算法精讲、A star算法、最短路算法总结篇
算法·图论
GuGu20241 小时前
新手刷题对内存结构与形象理解的冲突困惑
算法
汤永红1 小时前
week4-[二维数组]平面上的点
c++·算法·平面·信睡奥赛
go&Python2 小时前
检索模型与RAG
开发语言·python·llama
晴空闲雲2 小时前
数据结构与算法-字符串、数组和广义表(String Array List)
数据结构·算法