基于树的时间序列预测(LGBM)

news2024/12/24 2:28:42

        在大多数时间序列预测中,尽管有Prophet和NeuralProphet等方便的工具,但是了解基于树的模型仍然具有很高的价值。尤其是在监督学习模型中,仅仅使用单变量时间序列似乎信息有限,预测也比较困难。因此,为了生成足够的特征,需要采取一些方法,例如创建大量的滞后变量。此外,关于预测目标值,也要用过去的项来预测未来的项,而且需要决定是一步领先还是多步领先。

从单变量时间序列中创建特征

        在单变量时间序列中一般只能获得有限的信息。ARIMA 模型使用过去的值来预测未来的值,因此过去的值是重要的候选特征,可以创建许多滞后回归因子。时间指数是一个有价值的领域,因此可以基于此创建特征。由于日历上的事件和年度事件在生活中不断重复,它们为过去留下了印记,为未来提供了教益。因此可以从与时间相关的特征入手。

创建基于时间的特征

        创建基于时间的特征,包括日期、星期、季度等各种特征,通过 pandas series 的 "date" 类中提供的一系列函数,可以轻松实现这些需求。

def create_date_features(df):
    df['month'] = df.date.dt.month
    df['day_of_month'] = df.date.dt.day
    df['day_of_year'] = df.date.dt.dayofyear
    df['week_of_year'] = df.date.dt.weekofyear
    df['day_of_week'] = df.date.dt.dayofweek + 1
    df['year'] = df.date.dt.year
    df['quarter'] = df.date.dt.quarter
    df['hour_of_day'] = df.date.dt.hour
    df['weekday'] = df.date.dt.weekday
    df['is_year_start'] = df.date.dt.is_year_start.astype(int)
    df['is_year_end'] = df.date.dt.is_year_end.astype(int)
    df['is_month_start'] = df.date.dt.is_month_start.astype(int)
    df['is_month_end'] = df.date.dt.is_month_end.astype(int)
    df['is_quarter_start'] = df.date.dt.is_quarter_start.astype(int)
    df['is_quarter_end'] = df.date.dt.is_quarter_end.astype(int)
    df['is_quarter_end'] = df.date.dt.is_quarter_end.astype(int)
    return df

这里我使用的数据集为本地的数据集,需要可自行搜集下载,除date、open字段外,它还包含其他字段(不做说明):

from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
from pymysql import connect
from sqlalchemy import create_engine, text

def check_info(code):
    engine = create_engine('mysql+pymysql://root:152617@127.0.0.1:3306/stock_info')
    conn = engine.connect()
    result = conn.execute(text("SELECT * FROM stocks WHERE stock_code = " + code))
    conn.close()
    return result

将使用 date(日期 )和open(开盘价)字段来处理单变量时间序列。 

df = pd.DataFrame(check_info('000001'))[['date','open']]
df["date"] = pd.to_datetime(df["date"])
df = df.sort_values(by='date')
df.head()

这里数据量不多,因为有很久没有运行脚本去自动更新数据库了,大概只有:

进行可视化:

plt.figure(figsize=(10,4))
plt.plot(df['date'], df["open"])
plt.xlabel("date")
plt.ylabel("open_price")
plt.show()

显而易见的下跌趋势。

应用函数来创建日期特征:

df = create_date_features(df)
df.head()

note:这里需要进行一个步骤。在上面模型中,有几个字段不应作为数字特征,而应作为分类特征。需要把它们转化为虚拟变量

to_dummy = ['weekday', 'month', 'quarter', 'year', 'day_of_month', 'week_of_year', 'day_of_week', 'hour_of_day']
df = pd.get_dummies(df, columns= to_dummy)

一个特征列表就创建好了。

创建滞后特征和未来特征

在自动回归模型中,回归变量是滞后值。可以使用 .shift(n) 来创建滞后特征。接下来,在数据集 ff 中创建三个滞后特征。

ff = df.copy()
ff['open-1'] = ff['open'].shift(1)
ff['openy-2'] = ff['open'].shift(2)
ff['open-3'] = ff['open'].shift(3)
ff.head()

编写一个 forloop 来创建多个滞后特征。下面将在不同的数据集 ff 中创建 5 个滞后变量:

ff = df.copy()

def create_lagged(df, n_vars):
  # Use a forloop
  for i in range(n_vars):
    # The name will be y-1, y-2, etc.
    name = ('open-%d' % (i+1))
    df[name] = df['open'].shift(i+1)
  return df

ff = create_lagged(ff, 5)
ff.head()

显然,也可以将数值前移,使其成为未来的目标值,如下所示:

ff = df.copy()
ff['open+1'] = ff['open'].shift(-1)
ff['open+2'] = ff['open'].shift(-2)
ff['open+3'] = ff['open'].shift(-3)
ff.tail()

正式为建模数据 df 创建 25 个滞后变量:

df = create_lagged(df, 25)
df.columns

数据集中包含了['date', 'open', 'open-1', ..., 'open-25']的数据。在此基础上,可以进行一系列汇总统计,如过去 n 小时、n 天或 n 周的总和或平均值。

创建移动平均值

另外,可以创建1,3,5,7,10的移动平均值。

def roll_mean_features(df, windows):
    df = df.copy()
    for window in windows:
        df['mv_' + str(window)] = df['open'].transform(
            lambda x: x.shift(1).rolling(window=window, min_periods=1, win_type="triang").mean())
        # min_periods=1表示即使在窗口初期数据不足时也计算平均值
        # win_type='triang'指定了窗口的权重类型为三角形(Triangular)权重
    return df
df = roll_mean_features(df, [1, 3, 5, 7, 10])
df.tail()

监督学习框架用于提前预测。模型目标是 open,特征包括滞后项 open-1到open-25以及时间相关和移动平均变量。

该模型可以通过yt-1到yt-25产生下一期的yt,即提前一步预测。在现实应用中,多步预测也很常见,传统方法是建立n个模型来预测接下来的n期。

建立 LightGBM 预测模型

LightGBM是微软开发的梯度提升框架,它使用叶向树生长以提高准确性。相比之下,level-wise树会尝试在同一级别的分支上生长,看起来更平衡。由于其能够处理大型数据集和并行化训练,因此比其他提升算法更高效、更快速,同时内存占用更低。此外,它原生支持分类特征,无需进行单次编码。梯度提升模型是机器学习算法的一种,它将多个较弱的模型组合在一起,从而创建一个强大的预测模型。它的基本思想是迭代训练决策树,每棵树都试图纠正前一棵树所犯的错误。最终的预测结果是所有决策树预测结果的总和。梯度提升模型特别适用于处理复杂的数据集,可以处理大量特征和特征之间的交互,并且对过度拟合也很稳健,同时能够处理缺失值。常用的算法有梯度提升机(GBM)、XGB 和 LightGBM。

划分训练和测试集

将时间序列切割成 "实时" 数据作为训练数据,"非实时" 数据作为测试数据:

from datetime import timedelta
# Count the days
num_days = (df['date'].max() - df['date'].min()).days
# reserve 20% for out-of-time
oot = num_days * 0.2 
# Get the cutdate
cutdate = df['date'].max() - timedelta(days = oot)

# Create the training data
train = df.loc[(df['date'] <= cutdate), :]
print("Training data: from", train['date'].min(), "to", train['date'].max())

# Create the test data
test = df.loc[(df['date'] > cutdate), :]
print("Test data: from", test['date'].min(), "to", test['date'].max())

LightGBM 建模

LightGBM 有许多超参数可以调整。可指定关键超参数:

import lightgbm as lgb
lgb_params = {# 平均绝对误差
              'metric': {'mae'}, 
              # 树中树叶的数量
              'num_leaves': 6, # 10以上训练效果才比较好
              # 学习日期
              'learning_rate': 0.02, 
              # 随机选取 80% 的特征到训练              
              'feature_fraction': 0.8, 
              # 树的最大深度
              'max_depth':5,
              # 忽略训练进度(不显示任何内容)
              'verbose': 0,
              # 提升迭代次数
              'num_boost_round': 150,
              # 如果精度没有提高,就停止训练
              'early_stopping_rounds': 200,
              # 使用计算机上的所有内核
              'nthread': -1}

LightGBM 有一个".Dataset()"代码类,用于打包目标变量、回归变量和数据。如下所示,操作非常简单。

train = train.dropna()

Y_train = train[['open']]
X_train = train[cols]
Y_test = test[['open']]
X_test = test[cols]

from sklearn import preprocessing
lbl = preprocessing.LabelEncoder()
Y_train['open'] = lbl.fit_transform(Y_train['open'].astype(float))
Y_test['open'] = lbl.fit_transform(Y_test['open'].astype(float))
for c in cols:
    X_train[c] = lbl.fit_transform(X_train[c].astype(float)) #将提示的包含错误数据类型这一列进行转换
    X_test[c] = lbl.fit_transform(X_test[c].astype(float))


# Use the Dataset class of lightGBM
lgbtrain = lgb.Dataset(data=X_train, label=Y_train, feature_name=cols)
lgbtest = lgb.Dataset(data=X_test, label=Y_test, reference=lgbtrain, feature_name=cols)


model = lgb.train(lgb_params, lgbtrain,
                  valid_sets=[lgbtrain, lgbtest],
                  num_boost_round=1000
                  )

在这里需要注意你的数据特征或者label里面有没有NA,否则会出现报错:pandas dtype only support int float bool,检查数据是否是object

其次如果出现warm:-inf意味着可能你的数据过于稀疏(数据中特征的分布非常不均匀,或者特征值的范围很小,可能导致分割增益为负);特征质量差(某些特征可能对模型预测没有帮助,或者特征与目标变量的关联性太弱);参数设置(min_data_in_leaf(叶子节点最小样本数)或min_gain_to_split(最小增益阈值)设置得过高,导致模型在寻找分割时过于保守);需要进行参数重新设定

预测准确性评估

完成后,就可以得出训练数据和测试数据的预测值,并评估预测准确度。使用标准指标平均绝对百分比误差 (MAPE) 来评估预测准确度。MAPE 是绝对百分比误差的平均值,10% 的 MAPE 意味着预测值和实际值之间的平均偏差为 10%。

from sklearn.metrics import mean_absolute_percentage_error
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)
mean_absolute_percentage_error(Y_test, y_pred_test)

此处数据量过少,提取的特征很勉强,训练效果不好,就不放了。

实际值与预测值可视化

# 将预测值添加到训练期
train_pred = train.copy()
train_pred['open_pred_train'] = y_pred_train

# 将预测值添加到测试期
test_pred = test.copy()
test_pred['open_pred_test'] = y_pred_test
print([train_pred.shape, test_pred.shape])

# 合并训练期和测试期
actual_pred = pd.concat([train_pred, test_pred], axis=0)
actual_pred.shape

# 用蓝色绘制实际值
# 用橙色绘制训练期的预测值
# 用绿色标出测试期的预测值
plt.figure(figsize=(10,4))
plt.plot(actual_pred['date'], actual_pred[["open",'open_pred_train','open_pred_test']])
plt.xlabel("Date")
plt.ylabel("Actual vs. Predictions")
plt.show()

 不忍直视

模型可解释性

基于树的模型的优势之一是其可视性。可以通过变量重要性图直观地看到特征对预测的影响。

lgb.plot_importance(model, 
                    max_num_features=20, 
                    figsize=(10, 10),
                    importance_type="gain")
plt.show()

特征重要性图显示,影响最大的三个变量是 *、*和*。 毫无解释力。变更数据重新检验即可。

这里探讨了单变量时间序列特征的创建方法,以及如何将其纳入基于树的监督学习框架中。利用 lightGBM 模型进行了一步预测,并展示了如何利用变量显著图提高模型可解释性。

对于timeseries predict进一步还有用LSTM进行分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1646872.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker容器:Docker-Consul 的容器服务更新与发现

目录 前言 一、什么是服务注册与发现 二、 Docker-Consul 概述 1、Consul 概念 2、Consul 提供的一些关键特性 3、Consul 的优缺点 4、传统模式与自动发现注册模式的区别 4.1 传统模式 4.2 自动发现注册模式 5、Consul 核心组件 5.1 Consul-Template组件 5.2 Consu…

ICML 2024有何亮点?9473篇论文投稿,突破历史记录

会议之眼 快讯 2024年5月1日&#xff0c;第42届国际机器学习大会ICML 2024放榜啦&#xff01;录用率27.5%&#xff01;ICML 2024的录用结果受到了广泛的关注&#xff0c;本届会议的投稿量达到了9473篇&#xff0c;创下了历史新高&#xff0c;比去年的6538篇增加了近3000篇&…

C/C++开发环境配置

配置C/C开发环境 1.下载和配置MinGW-w64 编译器套件 下载地址&#xff1a;https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/ 下载后解压并放至你容易管理的路径下&#xff08;我是将其放在了D盘的一个software的文件中管理&#xff09; 2.…

Nest 快速上手 —— (三)中间件 / 异常过滤器

一、 中间件&#xff08;Middleware&#xff09; 1.特点 中间件是一个在路由处理程序之前被调用的函数。中间件函数可以访问请求和响应对象&#xff0c;以及应用程序请求-响应周期中的next()中间件函数。下一个中间件函数通常由一个名为next的变量表示。 中间件函数可以执行以…

自动驾驶融合定位系列教程四:惯性导航解算

自动驾驶融合定位系列教程四&#xff1a;惯性导航解算 一、概述 惯性导航的解算是一个实现起来非常简单&#xff0c;但是理解起来要费一番功夫的东西&#xff0c;所谓“实现”就是把公式变成代码&#xff0c;所谓“理解”&#xff0c;就是要弄明白几个公式是怎么推导出来的。…

硬盘遭遇误删分区?这些恢复技巧你必须掌握!

在日常使用电脑的过程中&#xff0c;我们有时会遇到一些棘手的问题&#xff0c;其中误删分区无疑是一个令人头疼的难题。误删分区意味着我们不小心删除了硬盘上的某个分区&#xff0c;导致该分区内的所有数据瞬间消失。对于许多用户来说&#xff0c;这可能会引发极大的恐慌和焦…

[方法] Unity 实现仿《原神》第三人称跟随相机 v1.1

参考网址&#xff1a;【Unity中文课堂】RPG战斗系统Plus 在Unity游戏引擎中&#xff0c;实现类似《原神》的第三人称跟随相机并非易事&#xff0c;但幸运的是&#xff0c;Unity为我们提供了强大的工具集&#xff0c;其中Cinemachine插件便是实现这一目标的重要工具。Cinemachi…

软件测试面试问题汇总

一般软件测试的面试分为三轮&#xff1a;笔试&#xff0c;HR面试&#xff0c;技术面试。 前两轮&#xff0c;根据不同企业&#xff0c;或有或无&#xff0c;但最后一个技术面试是企业了解你“行不行”的关键环节&#xff0c;每个企业都会有的。 在平时的学习、工作中一定要善于…

【Ping】Windows 网络延迟测试 ping 、telnet、tcping 工具

ping 命令 属于网络层的ICMP协议&#xff0c;只能检查 IP 的连通性或网络连接速度&#xff0c; 无法检测IP的端口状态。 telnet telnet命令&#xff0c;属于应用层的协议&#xff0c;用于远程登录&#xff0c;也可用于检测IP的端口状态。但是功能有限&#xff0c;只能检测一时…

【WP】第一届 “帕鲁杯“ - CTF挑战赛 Web 全解

Web Web-签到 考点&#xff1a;审计py代码 from flask import Flask, request, jsonify import requests from flag import flag # 假设从 flag.py 文件中导入了 flag 函数 app Flask(__name__)app.route(/, methods[GET, POST]) def getinfo():url request.args.get(url)i…

ue引擎游戏开发笔记(32)——为游戏添加新武器装备

1.需求分析&#xff1a; 游戏中角色不会只有一种武器&#xff0c;不同武器需要不同模型&#xff0c;甚至可能需要角色持握武器的不同位置&#xff0c;因此需要添加专门的武器类&#xff0c;方便武器后续更新&#xff0c;建立一个武器类。 2.操作实现&#xff1a; 1.在ue5中新建…

炼钢厂新篇章:可视化技术引领工业智能化变革

一、什么是炼钢厂可视化&#xff1f; 炼钢厂可视化&#xff0c;简而言之&#xff0c;就是将炼钢生产过程中的各项数据、流程通过图形化、图像化的方式直观展示出来。这不仅能让工作人员更加清晰地了解生产状态&#xff0c;还能大大提高生产效率和安全性。 山海鲸可视化搭建的炼…

C语言知识点补充——ASCLL码表

1、ASCLL码表 ASCII码表&#xff08;American Standard Code for Information Interchange&#xff09;是一种用于将字符编码为数字的标准。它定义了128个字符的编码方式&#xff0c;包括数字、字母、标点符号和控制字符等。每个字符都对应一个唯一的7位或8位二进制数 2、Ascl…

【6D位姿估计】数据集汇总 BOP

前言 BOP是6D位姿估计基准&#xff0c;汇总整理了多个数据集&#xff0c;还举行挑战赛&#xff0c;相关报告被CVPR2024接受和认可。 它提供3D物体模型和RGB-D图像&#xff0c;其中标注信息包括6D位姿、2D边界框和2D蒙版等。 包含数据集&#xff1a;LM 、LM-O 、T-LESS 、IT…

某站戴师兄——Excel实战

1、设置下拉选项&#xff1a;数据——数据验证——设置 如下设置&#xff1a; 2、If、sumif、index、match综合应用&#xff1a; sumif(条件区域&#xff0c;条件&#xff0c;目标区域&#xff09; sumifs(目标区域,条件区域1&#xff0c;条件1,条件区域2&#xff0c;条件2) …

Python深度学习基于Tensorflow(3)Tensorflow 构建模型

文章目录 数据导入和数据可视化数据集制作以及预处理模型结构低阶 API 构建模型中阶 API 构建模型高阶 API 构建模型保存和导入模型 这里以实际项目CIFAR-10为例&#xff0c;分别使用低阶&#xff0c;中阶&#xff0c;高阶 API 搭建模型。 这里以CIFAR-10为数据集&#xff0c;C…

04 深入浅出JVM

本课时的主题是 JVM 原理。JVM 是 Java 程序运行基础&#xff0c;面试时一定会遇到 JVM 相关的题。本课时会先对面试中 JVM 的考察点进行汇总介绍。然后对 JVM 内存模型、Java 的类加载机制、常用的 GC 算法这三个知识点进行详细讲解。最后汇总 JVM 考察点和加分项&#xff0c;…

Go 语言(四)【常用包使用】

1、命令行参数包 flag flag 包就是一个用来解析命令行参数的工具。 1.1、os.Args import ("fmt""os" )func main() {if len(os.Args) > 0 {for index, arg : range os.Args {fmt.Printf("args[%d]%v\n", index, arg)}} } 运行结果&#…

C#连接S7-200 smart通讯测试

honeytree 一、编程环境 VS2022软件&#xff0c;选择windows窗体应用&#xff08;.NET FrameWork&#xff09;&#xff1a;​博途TIA/WINCC社区VX群 ​博途TIA/WINCC社区VX群 添加NuGet程序包&#xff1b;S7netplus 二、引用http://S7.net 三、建立PLC链接 S7-200smart和…

41.乐理基础-拍号-小节、小节线、终止线

小节线&#xff1a;下图红框中的竖线就是小节线 小节、终止线&#xff1a;最后的终止线就是文字意思表示乐谱结束了&#xff0c;后面没有了 下图中 0.5表示0.5拍&#xff08;八分音符&#xff09;、1表示1拍&#xff08;四分音符&#xff09;、0.25表示0.25拍&#xff08;十六分…