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

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

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

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

创建基于时间的特征

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

def create_date_features(df):df['month'] = df.date.dt.monthdf['day_of_month'] = df.date.dt.daydf['day_of_year'] = df.date.dt.dayofyeardf['week_of_year'] = df.date.dt.weekofyeardf['day_of_week'] = df.date.dt.dayofweek + 1df['year'] = df.date.dt.yeardf['quarter'] = df.date.dt.quarterdf['hour_of_day'] = df.date.dt.hourdf['weekday'] = df.date.dt.weekdaydf['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, textdef 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 forloopfor 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 dfff = 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.hqwc.cn/news/671070.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue2实现生成二维码和复制保存图片功能(复制的同时会给图片加文字)

<template><divstyle"display: flex;justify-content: center;align-items: center;width: 100vw;height: 100vh;"><div><!-- 生成二维码按钮和输入二维码的输入框 --><input v-model"url" placeholder"输入链接" ty…

C++ 多态(一)

一、多态定义 同一种操作作用于不同的对象时&#xff0c;可以产生不同的行为。在面向对象编程中&#xff0c;多态性是指通过继承和重写实现的&#xff0c;同一个方法在不同的子类中可以表现出不同的行为。多态性可以提高代码的灵活性和可扩展性&#xff0c;使得程序更易于维护…

全新桥隧坡安全监测解决方案,24h监测效率提升30%

4月26日&#xff0c;交通运输部党组书记、部长李小鹏在部务会上强调&#xff0c;要高度重视公路桥梁隧道结构监测工作&#xff0c;抓紧推进公路桥梁隧道结构监测系统建设&#xff0c;进一步健全完善公路桥梁隧道结构监测长效运行机制。 中海达积极参与公路桥梁隧道结构监测工作…

基于springboot+vue+Mysql的点餐平台网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

9.Admin后台系统

9. Admin后台系统 Admin后台系统也称为网站后台管理系统, 主要对网站的信息进行管理, 如文字, 图片, 影音和其他日常使用的文件的发布, 更新, 删除等操作, 也包括功能信息的统计和管理, 如用户信息, 订单信息和访客信息等. 简单来说, 它是对网站数据库和文件进行快速操作和管…

C++常用库函数——strstr、strcat

1、strstr&#xff1a;查找字符串子串函数&#xff0c;查找到的子串中第一个字符的地址&#xff0c;返回值是第一次出现子串字符串的位置。 例如&#xff1a; char a[20] "RUNOOB"; char b[10] "NOOB"; printf("%s", strstr(a, b)); 在这里…

Java苍穹外卖04-

一、缓存菜品 1.问题说明 2.实现思路 就是点击到这个分类的时候就可以展示相应的菜品数据 3.代码实现 在user的菜品的contoller中&#xff1a;增加判断redis中是否存在所需数据&#xff0c;不存在添加&#xff0c;存在直接取得 这里注意&#xff1a;你放进去用的是List<Di…

嵌入式系统应用-拓展-FLASH之操作 SFUD (Serial Flash Universal Driver)之KEIL应用

这里已经假设SFUD代码已经移植到工程下面成功了&#xff0c;如果读者对SFUD移植还不了解。可以参考笔者这篇文章&#xff1a;SFUD (Serial Flash Universal Driver)之KEIL移植 这里主要介绍测试和应用 1 硬件设计 这里采用windbond 的W25Q32这款芯片用于SFUD测试。 W25Q32是…

9.3.k8s的控制器资源(deployment部署控制器)

目录 一、deployment部署控制器概念 二、deployment资源的清单编写 三、小结 功能 使用场景 原理 四、deployment实现升级和回滚 1.编辑deployment资源清单&#xff08;v1版本&#xff09; 2.创建service资源用于访问 ​编辑 3.修改deploy清单中pod镜像版本为V2 4…

测试环境搭建:JDK+Tomcat+Mysql+Redis

基础的测试环境搭建&#xff1a; LAMPLinux(CentOS、ubuntu、redhat)ApacheMysqlPHP LTMJLinux(CentOS、ubuntu、redhat)TomcatMysql(Oracle)RedisJava 真实的测试环境搭建&#xff1a;&#xff08;企业真实的运维&#xff09; 基于SpringBoot&#xff08;SpringCloud分布式微…

node安装

1. node.js是用来干什么的&#xff1f; 简单来说&#xff0c;Node.js 是一个多功能的 JavaScript 运行环境&#xff0c;就像jdk是java的运行环境一样&#xff0c;不过node还提供了类似于tomcat一样的服务器功能&#xff0c;可以像后端一样运行起来拥有单独的地址和端口。 1.1…

智能AI摄像头项目

项目概要 硬件说明&#xff1a;易百纳rv1126 38板&#xff0c;易百纳GC2053摄像头&#xff0c;拓展版&#xff08;自绘&#xff09;&#xff0c;屏幕驱动板&#xff08;自绘&#xff09;&#xff0c;3.1inch mipi屏&#xff0c;FT5316触摸屏 开发环境 硬件分析 开发环境及sd…