第75步 时间序列建模实战:多步滚动预测 vol-3(以决策树回归为例)

news2024/11/25 10:30:54

基于WIN10的64位系统演示

一、写在前面

上两期,我们讲了多步滚动预测的第两种策略:

对于重复的预测值,取平均处理例如,(1,2,3)预测出3.9和4.5,(2,3,4)预测出5.2和6.3,那么拼起来的结果就是3.9,(4.5 + 5.2)/2, 6.3。

删除一半的输入数据集。例如,4,5由(1,2,3)预测,6,7由(3,4,5)预测,删掉输入数据(2,3,4)。

没想到吧,还会有第三期。也是我突然记起的,叫做多模型预测。

2、多步滚动预测 vol-3

什么叫多模型预测呢,我举个例子,大家看便知:

首先,我们还是使用3个数值去预测2个数值。不同的是,这2个数值分别是由2个不同参数的模型(这里都是决策树)进行预测的。

第一个模型的构建如下:

输入

输出

1,2,3

4

2,3,4

6

3,4,5

8

...

...

4由(1,2,3)预测,6由(3,4,5)预测,8由(5,6,7)预测,以此类推。可以理解为,第一个模型专门被训练来预测偶数位的数值。

第二个模型的构建如下:

输入

输出

1,2,3

5

2,3,4

7

3,4,5

9

...

...

5由(1,2,3)预测,7由(3,4,5)预测,9由(5,6,7)预测,以此类推。可以理解为,第二个模型专门被训练来预测奇数位的数值。

最后,再把两个模型的预测结果按顺序拼接起来即可。也就是:模型一出一个4,模型二接上一个5;模型一接上一个6,模型二补上一个7,以此类推。

我们在总结和扩展:假设使用前n个数值去预测下m个数值。如果m=3时,那么就需要构建3个模型,分别预测3个数值,然后依次把这3个数值按顺序拼接在一起。如果m=4时,那么就需要构建4个模型,分别预测4个数值,然后依次把这4个数值按顺序拼接在一起。同理,如果m=d时,那么就需要构建d个模型,分别预测d个数值,然后依次把这d个数值按顺序拼接在一起。以此类推。

2.1 数据拆分

import pandas as pd
import numpy as np
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import mean_absolute_error, mean_squared_error

# 数据读取和预处理
data = pd.read_csv('data.csv')
data_y = pd.read_csv('data.csv')
data['time'] = pd.to_datetime(data['time'], format='%b-%y')
data_y['time'] = pd.to_datetime(data_y['time'], format='%b-%y')

n = 6

for i in range(n, 0, -1):
    data[f'lag_{i}'] = data['incidence'].shift(n - i + 1)

data = data.dropna().reset_index(drop=True)
train_data = data[(data['time'] >= '2004-01-01') & (data['time'] <= '2011-12-31')]
X_train = train_data[[f'lag_{i}' for i in range(1, n+1)]]
m = 3

X_train_list = []
y_train_list = []

for i in range(m):
    X_temp = X_train
    y_temp = data_y['incidence'].iloc[n + i:len(data_y) - m + 1 + i]
    
    X_train_list.append(X_temp)
    y_train_list.append(y_temp)

# 截断y_train使其与X_train的长度匹配
for i in range(m):
    X_train_list[i] = X_train_list[i].iloc[:-(m-1)]
y_train_list[i] = y_train_list[i].iloc[:len(X_train_list[i])]

核心部分在于,对于数据的划分,一个X_train,对应m个(本例子中m = 3)Y_train:

X_train_list = []
y_train_list = []
for i in range(m):
    X_temp = X_train
    y_temp = data_y['incidence'].iloc[n + i:len(data_y) - m + 1 + i]
    
    X_train_list.append(X_temp)
    y_train_list.append(y_temp)
# 截断y_train使其与X_train的长度匹配
for i in range(m):
    X_train_list[i] = X_train_list[i].iloc[:-(m-1)]
    y_train_list[i] = y_train_list[i].iloc[:len(X_train_list[i])]

这段代码主要用于为多个模型准备训练数据。GPT-4逐行解释:

(a)X_train_list = [] 和 y_train_list = []:初始化两个空列表,分别用于存储多个模型的训练数据和标签。

(b)for i in range(m)::开始一个循环,循环m次,其中m是模型的数量。

(c)X_temp = X_train:将X_train赋值给X_temp。这意味着每个模型的特征数据都相同。

(d)y_temp = data_y['incidence'].iloc[n + i:len(data_y) - m + 1 + i]:这是获取标签数据的关键步骤。它使用iloc来获取一个子集,这个子集的起始点根据循环的迭代而变化。起始点是n + i,而终止点是len(data_y) - m + 1 + i。

这意味着:

对于第一个模型(i=0),我们从第n个数据点开始选择标签。

对于第二个模型(i=1),我们从第n+1个数据点开始选择标签。

对于第三个模型(i=2),我们从第n+2个数据点开始选择标签。

...以此类推。

(e)X_train_list.append(X_temp):将X_temp添加到X_train_list。

(f)y_train_list.append(y_temp):将y_temp添加到y_train_list。

到此为止,我们已经为每个模型创建了训练数据和标签。

接下来,为了确保特征数据和标签数据的长度匹配,我们需要进行截断操作。

(g)for i in range(m)::开始另一个循环,再次循环m次。

(h)X_train_list[i] = X_train_list[i].iloc[:-(m-1)]:这行代码将X_train_list中的每个元素(即特征数据)从末尾截断m-1行。例如,如果m=3,则截断最后2行。

(i)y_train_list[i] = y_train_list[i].iloc[:len(X_train_list[i])]:这行代码确保标签数据的长度与特征数据的长度相匹配。

综上所述,我们得到的X_train_list包含三个相同的输入集(A\B\C);同样,y_train_list包含三个输出集(D\E\F),注意D\E\F的数据不一样。A和D用于训练模型一,B和E用于训练模型二,C和F用于训练模型三。

大家看上图自行体会吧!!!

2.2 建模与预测

# 模型训练
tree_model = DecisionTreeRegressor()
param_grid = {
    'max_depth': [None, 3, 5, 7, 9],
    'min_samples_split': range(2, 11),
    'min_samples_leaf': range(1, 11)
}

best_tree_models = []

for i in range(m):
    grid_search = GridSearchCV(tree_model, param_grid, cv=5, scoring='neg_mean_squared_error')
    grid_search.fit(X_train_list[i], y_train_list[i])
    best_tree_model = DecisionTreeRegressor(**grid_search.best_params_)
    best_tree_model.fit(X_train_list[i], y_train_list[i])
    best_tree_models.append(best_tree_model)

# 为了使validation_data的划分遵循上述的逻辑,我们首先需要确定其开始的时间点
# 这是在train_data最后一个时间点之后的第一个时间点
validation_start_time = train_data['time'].iloc[-1] + pd.DateOffset(months=1)
validation_data = data[data['time'] >= validation_start_time]

X_validation = validation_data[[f'lag_{i}' for i in range(1, n+1)]]
y_validation_pred_list = [model.predict(X_validation) for model in best_tree_models]
y_train_pred_list = [model.predict(X_train_list[i]) for i, model in enumerate(best_tree_models)]

def concatenate_predictions(pred_list):
    concatenated = []
    for j in range(len(pred_list[0])):
        for i in range(m):
            concatenated.append(pred_list[i][j])
    return concatenated

y_validation_pred = np.array(concatenate_predictions(y_validation_pred_list))[:len(validation_data['incidence'])]
y_train_pred = np.array(concatenate_predictions(y_train_pred_list))[:len(train_data['incidence']) - m + 1]


mae_validation = mean_absolute_error(validation_data['incidence'], y_validation_pred)
mape_validation = np.mean(np.abs((validation_data['incidence'] - y_validation_pred) / validation_data['incidence']))
mse_validation = mean_squared_error(validation_data['incidence'], y_validation_pred)
rmse_validation = np.sqrt(mse_validation)
print("验证集:", mae_validation, mape_validation, mse_validation, rmse_validation)

mae_train = mean_absolute_error(train_data['incidence'][:-(m-1)], y_train_pred)
mape_train = np.mean(np.abs((train_data['incidence'][:-(m-1)] - y_train_pred) / train_data['incidence'][:-(m-1)]))
mse_train = mean_squared_error(train_data['incidence'][:-(m-1)], y_train_pred)
rmse_train = np.sqrt(mse_train)
print("训练集:", mae_train, mape_train, mse_train, rmse_train)

核心代码一,建立m个模型:

for i in range(m):
    grid_search = GridSearchCV(tree_model, param_grid, cv=5, scoring='neg_mean_squared_error')
    grid_search.fit(X_train_list[i], y_train_list[i])
    best_tree_model = DecisionTreeRegressor(**grid_search.best_params_)
    best_tree_model.fit(X_train_list[i], y_train_list[i])
best_tree_models.append(best_tree_model)

这段代码的目的是为每一个模型(共m个)找到最优的参数,并使用这些参数训练模型,然后保存这些模型。

核心代码二,结果拼接:

def concatenate_predictions(pred_list):
    concatenated = []
    for j in range(len(pred_list[0])):
        for i in range(m):
            concatenated.append(pred_list[i][j])
    return concatenated

y_validation_pred = np.array(concatenate_predictions(y_validation_pred_list))[:len(validation_data['incidence'])]
y_train_pred = np.array(concatenate_predictions(y_train_pred_list))[:len(train_data['incidence']) - m + 1]

详细解释 concatenate_predictions 函数并通过一个简单的例子进行说明。

函数的目的是将多个模型的预测结果按照一定的顺序串联起来。

考虑如下情况:

假设我们有3个模型(即m=3),每个模型都为3个月份进行预测。那么,模型的预测列表 pred_list 可能如下所示:

pred_list = [
    [0.1, 0.2, 0.3],  # 模型1的预测结果
    [0.4, 0.5, 0.6],  # 模型2的预测结果
    [0.7, 0.8, 0.9]   # 模型3的预测结果
]

现在,我们想要的串联顺序是:模型1的第1个月预测,模型2的第1个月预测,模型3的第1个月预测,模型1的第2个月预测,模型2的第2个月预测,模型3的第2个月预测,依此类推。

所以,使用 concatenate_predictions 函数处理 pred_list 后的结果应该是:

[0.1, 0.4, 0.7, 0.2, 0.5, 0.8, 0.3, 0.6, 0.9]

这就是 concatenate_predictions 函数的作用,大家看懂了吧!

2.3 输出

三、数据

链接:https://pan.baidu.com/s/1EFaWfHoG14h15KCEhn1STg?pwd=q41n

提取码:q41n

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

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

相关文章

【深度学习】ONNX模型快速部署【入门】

【深度学习】ONNX模型快速部署【入门】 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】ONNX模型快速部署【入门】前言搭建打包环境打包可执行文件总结 前言 之前的内容已经尽可能简单、详细的介绍CPU【Pytorch2ONNX】和GPU【Pyto…

MySQL常见join关联查询分析

1、join关联查询七大类型结构图 2、建表语句 CREATE TABLE t_dept (id INT(11) NOT NULL AUTO_INCREMENT,deptName VARCHAR(30) DEFAULT NULL,address VARCHAR(40) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEINNODB AUTO_INCREMENT1 DEFAULT CHARSETutf8;CREATE TABLE t_emp (id…

均匀辐照度和局部遮光条件下光伏系统的新型样条-MPPT技术(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【Spring Boot】Spring Boot源码解读与原理剖析

这里写目录标题 前言精进Spring Boot首选读物“小册”变“大书”&#xff0c;彻底弄懂Spring Boot全方位配套资源&#xff0c;学不会来找我&#xff01;技术新赛道&#xff0c;2023领先抢跑 前言 承载着作者的厚望&#xff0c;掘金爆火小册同名读物《Spring Boot源码解读与原理…

【100天精通Python】Day66:Python可视化_Matplotlib 3D绘图,绘制3D曲面图、3D填充图,3D极坐标图,示例+代码

目录 1 绘制曲面图 2 绘制3D填充图 3 绘制极坐标图 1 绘制曲面图 当绘制3D曲面图时&#xff0c;mpl_toolkits.mplot3d 模块中的 Axes3D 对象提供了多种方法来呈现不同类型的曲面图。以下是一些常见的3D曲面图类型以及示例&#xff1a; 曲面图&#xff1a;使用 plot_surface …

Spring Boot的新篇章:探索2.0版的创新功能

文章目录 引言1. Spring Boot 2.0的响应式编程2. 自动配置的改进3. Spring Boot 2.0的嵌入式Web服务器4. Spring Boot 2.0的Actuator端点5. Spring Boot 2.0的Spring Data改进6. Spring Boot 2.0的安全性增强7. Spring Boot 2.0的监控和追踪8. Spring Boot 2.0的测试改进结论 &…

java面试题-设计模式基础

面试专题-设计模式 前言 在平时的开发中&#xff0c;涉及到设计模式的有两块内容&#xff0c;第一个是我们平时使用的框架&#xff08;比如spring、mybatis等&#xff09;&#xff0c;第二个是我们自己开发业务使用的设计模式。 面试官一般比较关心的是你在开发过程中&#…

华为OD机考算法题:分积木

目录 题目部分 解读与分析 代码实现 题目部分 题目分积木难度难题目说明Solo和koko是两兄弟&#xff0c;妈妈给了他们一大堆积木&#xff0c;每块积木上都有自己的重量。现在他们想要将这些积木分成两堆。哥哥Solo负责分配&#xff0c;弟弟koko要求两个人获得的积木总重量“…

记一次nginx负载均衡健康检查引起的事故之no live upstreams while connecting to upstream

文章目录 概要一、负载均衡1.1、常用指令解析1.2 负载算法配置1.3、反向代理 二、事故分析三、小结 概要 Nginx是工作中常用的HTTP服务中间件&#xff0c;除了提供HTTP服务&#xff0c;常用的还有反向代理、限流、负载均衡等功能。 负载均衡支持七层负载均衡&#xff08;HTTP&…

KVCache原理简述

在GPT的推理过程中&#xff0c;它根据完整的提问和回答的已生成部分&#xff0c;来生测下一个词&#xff08;的概率&#xff09;。 例如&#xff0c;我们的提问是【天王盖地虎&#xff0c;】&#xff0c;回答是【宝塔镇河妖。】。 那么第一次&#xff0c;GPT根据【天王盖地虎…

Windows安装Docker Desktop并配置镜像、修改内存占用大小

启用Hyper-V Win S 搜索控制面板 安装WSL2 第一种方法&#xff08;推荐&#xff09; 以管理员运行命令提示符&#xff0c;然后重启Docker Desktop wsl --updatewsl --set-default-version 2第2种方法去微软官网下载WSL2并安装 《微软官网下载WSL2》 配置WSL2最大内…

类和对象:运算符重载

本篇文章来介绍一下C中的运算符重载&#xff0c;以及与运算符重载有关的三个默认默认成员函数&#xff1a;赋值运算符重载&#xff0c;普通对象取地址与const对象取地址操作符重载&#xff0c;也就是下面图片中6个默认成员函数的后三个&#xff0c;前三个默认成员函数在之前文章…

Makerbase SimpleFOC MINI 基本测试

第1部分 硬件介绍 1.1 硬件清单 序号品名数量1SimpleFOC MINI V1.0 主板12ARDUINO UNO主板13MKS SF2804电机14杜邦线45DC12V电源16USB 线1 1.2 硬件连接 1.SimpleFOC MINI V1.0 主板主板与Arduino UNO主板叠接。如下图所示&#xff1a; 2.USB 线一端连接 Arduino UNO 主板…

RabbitMQ工作模式——Routing路由模式

1.Routing路由模式 Routing生产者代码 public class Producer_Routing {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory factory new ConnectionFactory();//2.设置参数factory.setHost("172.16.98.…

一文彻底搞懂PN结及其单向导电性(图解说明)

前置知识 首先我们要知道纯净的本征半导体 硅 的导电性是非常差的&#xff0c;所以我们一般都会向纯净硅中添加杂质&#xff0c;也就是P型半导体和N型半导体。P型半导体和N型半导体都是呈电中性的&#xff0c;对于N型半导体而言&#xff0c;它又多数载流子电子和带正电荷的N离子…

【LeetCode-中等题】113. 路径总和 II

文章目录 题目方法一&#xff1a;DFS回溯 题目 方法一&#xff1a;DFS回溯 解题核心 就是要知道递归在哪里结束 &#xff0c;收货结果在哪里收获&#xff0c;哪些变量需要回溯&#xff0c;哪些不需要回溯 class Solution {List<List<Integer>> res new ArrayLis…

BI技巧丨Window应用之累计求和

Window函数除了可以用来计算同环比、移动平均之外&#xff0c;还可以用来处理累计求和问题。 核心在于Window的from和to参数的设定&#xff0c;可以将其设置为绝对位置和相对位置。 先来看看本期的案例数据&#xff1a; 案例数据比较简单&#xff0c;一张销售事实表。 将其导…

C++核心编程——P45-52继承

继承 继承是面向对象三大特性之一 有些类与类之间存在特殊的关系&#xff0c;例如下图中: 我们发现&#xff0c;定义这些类的时候&#xff0c;下级别的成员除了拥有上一级的共性&#xff0c;还有自己的特性。 这时候我们就可以考虑利用继承的技术&#xff0c;减少重复代码量…

PPPoE配置

实验需求 配置IP地址使用PPPOE拨号上网设置路由让直播业务部和营销部都可以访问外网 实验拓扑 实验步骤 配置 R1地址池 电信链路&#xff1a; [Huawei]undo info-center enable Info: Information center is disabled. [Huawei]sysname r1 [r1]ip pool zhibo  //配置…

多进程编程- POSIX命名信号量(named semaphore)

POSIX命名信号量是POSIX标准下的一个进程间同步原语&#xff0c;允许多个进程共享同一个信号量&#xff0c;从而实现进程间的同步和通信。这与无名信号量不同&#xff0c;无名信号量主要用于线程之间的同步&#xff0c;而不是进程之间。 命名信号量是“命名”的&#xff0c;因…