LightBGM:一个最强时间序列预测算法(附数据源码)

如需要数据及源码,关注微信公众号【爱敲代码的破晓】,后台私信【20260107】

一、LightGBM时间序列预测原理:

  1. 特征工程转换:将时间序列问题转化为监督学习问题,通过创建滞后特征(lag features)将时间依赖性转换为特征空间。

  2. 梯度提升框架:使用决策树集成方法,通过迭代训练多个弱学习器(决策树),每棵树学习前序模型的残差。

  3. 直方图算法:将连续特征离散化为直方图,大大减少内存使用和计算复杂度。

  4. Leaf-wise生长策略:与传统的level-wise生长不同,选择具有最大增益的叶子节点进行分裂,提高精度但可能过拟合。

  5. 类别特征处理:可以直接处理类别特征,无需one-hot编码,特别适合包含星期、月份等类别特征的时间序列。

  6. 自动特征选择:通过特征分数(feature importance)自动识别最重要的时间滞后特征。

二、与其他时间序列算法的优势

  1. 计算效率高

    • 相比传统GBDT,训练速度提升10倍以上

    • 内存使用减少70-90%

    • 支持并行学习和大规模数据

  2. 处理复杂模式能力强

    • 能够捕捉非线性关系

    • 自动处理特征交互

    • 对异常值鲁棒

  3. 灵活性高

    • 支持自定义损失函数

    • 可处理缺失值

    • 内置正则化防止过拟合

  4. 与传统统计方法对比

    • 相比ARIMA,无需平稳性假设

    • 相比Prophet,能更好地处理多个季节性

    • 相比RNN/LSTM,训练更快,超参数更少

  5. 特征重要性分析

    • 提供特征重要性评分

    • 可解释性比深度学习模型好

  6. 部署简便

    • 模型文件小

    • 预测速度快

    • 支持多种编程语言

三、使用示例

1.数据准备

图片

2.导入第三方库

import pandas as pd
import numpy as np
import lightgbm as lgb
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import joblib
import warnings
warnings.filterwarnings('ignore')

3.绘图设置

# 设置中文字体和样式
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
# sns.set_style("whitegrid")

4.构造LightGBM模型

class LightGBMTimeSeriesPredictor:
    """LightGBM时间序列预测器"""
    def __init__(self, test_size=0.2, n_lags=5, random_state=42):
        self.test_size = test_size
        self.n_lags = n_lags
        self.random_state = random_state
        self.model = None
        self.feature_cols = None
        # LightGBM参数
        self.params = {
            'boosting_type': 'gbdt',
            'objective': 'regression',
            'metric': 'rmse',
            'num_leaves': 31,
            'learning_rate': 0.05,
            'feature_fraction': 0.9,
            'bagging_fraction': 0.8,
            'bagging_freq': 5,
            'verbose': -1,
            'random_state': random_state
        }
    def load_data(self, file_path):
        """加载CSV数据"""
        df = pd.read_csv(file_path)
        df['Date'] = pd.to_datetime(df['Date'])
        df.set_index('Date', inplace=True)
        return df
    def create_features(self, df, target_col='Open'):
        """创建时间序列特征"""
        data = df.copy()
        # 创建滞后特征
        for lag in range(1, self.n_lags + 1):
            data[f'lag_{lag}'] = data[target_col].shift(lag)
        # 创建时间特征
        data['day_of_week'] = data.index.dayofweek
        data['day_of_month'] = data.index.day
        data['month'] = data.index.month
        data['quarter'] = data.index.quarter
        data['year'] = data.index.year
        # 创建滚动统计特征
        data['rolling_mean_7'] = data[target_col].rolling(window=7).mean()
        data['rolling_std_7'] = data[target_col].rolling(window=7).std()
        # 删除包含NaN的行
        data = data.dropna()
        return data
    def prepare_data(self, data, target_col='Open'):
        """准备训练数据"""
        self.feature_cols = [col for col in data.columns if col != target_col]
        X = data[self.feature_cols]
        y = data[target_col]
        # 按时间顺序划分训练集和测试集
        split_idx = int(len(X) * (1 - self.test_size))
        X_train, X_test = X.iloc[:split_idx], X.iloc[split_idx:]
        y_train, y_test = y.iloc[:split_idx], y.iloc[split_idx:]
        # 进一步划分训练集为训练和验证集
        X_train, X_val, y_train, y_val = train_test_split(
            X_train, y_train, test_size=0.2, random_state=self.random_state, shuffle=False
        )
        return X_train, X_val, X_test, y_train, y_val, y_test
    def train(self, X_train, y_train, X_val, y_val):
        """训练模型"""
        train_data = lgb.Dataset(X_train, label=y_train)
        val_data = lgb.Dataset(X_val, label=y_val, reference=train_data)
        self.model = lgb.train(
            self.params,
            train_data,
            valid_sets=[train_data, val_data],
            num_boost_round=1000,
            callbacks=[
                lgb.early_stopping(stopping_rounds=50),
                lgb.log_evaluation(period=100)
            ]
        )
        return self.model
    def predict(self, X):
        """进行预测"""
        if self.model is None:
            raise ValueError("模型未训练,请先调用train方法")
        return self.model.predict(X)
    def evaluate(self, y_true, y_pred):
        """评估预测结果"""
        metrics = {
            'RMSE': np.sqrt(mean_squared_error(y_true, y_pred)),
            'MAE': mean_absolute_error(y_true, y_pred),
            'R2': r2_score(y_true, y_pred),
            'MAPE': np.mean(np.abs((y_true - y_pred) / y_true)) * 100
        }
        return metrics
    def save_model(self, filepath):
        """保存模型"""
        if self.model is None:
            raise ValueError("模型未训练,无法保存")
        joblib.dump(self.model, filepath)
    def load_model(self, filepath):
        """加载模型"""
        self.model = joblib.load(filepath)
        return self.model

5.加载数据并构造特征

print("\n1. 加载数据...")
try:
    df = predictor.load_data('data.csv')
    print(f"数据加载成功,形状: {df.shape}")
    print(f"数据时间范围: {df.index.min()} 到 {df.index.max()}")
except FileNotFoundError:
    print("错误:未找到数据文件 'stock_data.csv'")
    print("请确保数据文件在当前目录下")
    return
# 2. 创建特征
print("\n2. 创建时间序列特征...")
data = predictor.create_features(df, target_col='Open')
print(f"特征创建完成,特征数量: {data.shape[1] - 1}")
# 3. 准备数据
print("\n3. 准备训练数据...")
X_train, X_val, X_test, y_train, y_val, y_test = predictor.prepare_data(data)
print(f"训练集大小: {len(X_train)}")
print(f"验证集大小: {len(X_val)}")
print(f"测试集大小: {len(X_test)}")

6.训练并保存模型

# 4. 训练模型
print("\n4. 训练LightGBM模型...")
model = predictor.train(X_train, y_train, X_val, y_val)
print("模型训练完成!")
# 5. 保存模型
predictor.save_model('lightgbm_model.pkl')
print("模型已保存为 'lightgbm_model.pkl'")

7.模型预测

# 6. 进行预测
print("\n5. 进行预测...")
y_train_pred = predictor.predict(X_train)
y_test_pred = predictor.predict(X_test)
# 7. 评估结果
print("\n6. 评估预测结果...")
train_metrics = predictor.evaluate(y_train, y_train_pred)
test_metrics = predictor.evaluate(y_test, y_test_pred)

8.模型评估并绘图

print("\n评估指标对比:")
print(f"{'指标':<10} {'训练集':<15} {'测试集':<15}")
print("-" * 40)
for metric in train_metrics:
    print(f"{metric:<10} {train_metrics[metric]:<15.4f} {test_metrics[metric]:<15.4f}")
# 8. 绘制结果
print("\n7. 绘制结果图表...")
plot_results(y_train, y_train_pred, y_test, y_test_pred, 
             X_train.index, X_test.index)
# 9. 绘制特征重要性
if hasattr(model, 'feature_importance'):
    feature_importance = pd.DataFrame({
        'feature': predictor.feature_cols,
        'importance': model.feature_importance()
    })
    feature_importance = feature_importance.sort_values('importance', ascending=False)
    plt.figure(figsize=(10, 6))
    plt.barh(feature_importance['feature'][:10], feature_importance['importance'][:10])
    plt.xlabel('特征重要性')
    plt.title('Top 10 特征重要性')
    plt.gca().invert_yaxis()
    plt.tight_layout()
    plt.savefig('feature_importance_main.png', dpi=150, bbox_inches='tight')
    plt.show()
print("\n" + "="*60)
print("LightGBM时间序列预测完成!")
print("="*60)

一下是相关图件

图片

图片

图片

图片

如需要数据及源码,关注微信公众号【爱敲代码的破晓】,后台私信【20260107】

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值