【Google2023】利用TiDE进行长期预测实战(时间序列密集编码器)

一、本文介绍

大家好,最近在搞论文所以在研究各种论文的思想,这篇文章给大家带来的是TiDE模型由Goggle在2023.8年发布,其主要的核心思想是:基于多层感知机(MLP)构建的编码器-解码器架构,核心创新在于它结合了线性模型的简洁性和速度优势,同时能有效处理协变量和非线性依赖。论文中号称TiDE在长期时间序列预测基准测试中不仅表现匹敌甚至超越了先前的方法,而且在速度上比最好的基于Transformer的模型快5到10倍。在官方的开源代码中是并没有预测未来数据功能的,因为这种都是学术文章发表论文的时候只看测试集表现。我在自己的框架下给其补上了这一功能同时加上了绘图的功能,非常适合大家发表论文的适合拿来做对比模型。

(开始之前给大家推荐一下我的专栏,本专栏包含时间序列领域各种模型适合各类人群,同时包含本人创新的框架和模型,无论你是想发论文还是工程项目中使用本专栏都能够满足你的需求) 

   专栏目录:时间序列预测目录:深度学习、机器学习、融合模型、创新模型实战案例

专栏: 时间序列预测专栏:基础知识+数据分析+机器学习+深度学习+Transformer+创新模型

预测未知数据功能如下->

下面的图片集成在模型的预测功能上,大家运行直接可以生成。

滚动长期预测功能如下->

下面的文件是由代码自动生成的csv文件可以用其进行各种可视化操作。

目录

一、本文介绍

二、TiDE的框架原理

2.1 TiDE的框架原理

2.1.1 密集多层感知机(MLP)编码器

2.1.2 密集MLP解码器

2.1.3 特征投影步骤

2.1.4 时序解码器

2.1.5 全局线性残差连接

2.2 TiDE的实验结果

三、实战所用数据集 

四、实战代码 

4.1 个人完善版本下载地址 

4.2 参数详解 

五、DiTE实战

5.1 训练模型

5.2 测试集表现 

5.3 预测未来一天的数据(结果可视化)

5.4 滚动长期预测(结果可视化 + CSV文件生成)

六、如何训练你自己的数据集

七、本文总结 


二、TiDE的框架原理

论文地址: 官方论文地址

代码地址: 官方代码地址


2.1 TiDE的框架原理

TiDE(时间序列密集编码器)模型是一个基于多层感知机(MLP)的编码器-解码器架构,旨在简化长期时间序列预测。该模型结合了线性模型的简单性和速度,同时能够有效处理协变量和非线性依赖。理论上,该模型的简单线性类似物能够在特定条件下为线性动态系统(LDS)实现接近最优的误差率。

TiDE(时间序列密集编码器)模型的网络结构可以概括为以下几个关键组成部分:

  1. 密集多层感知机(MLP)编码器:TiDE使用密集的MLP来编码时间序列的过去信息以及协变量。

  2. 密集MLP解码器:解码器同样基于密集的MLP,用于处理编码后的时间序列和未来的协变量。

  3. 特征投影步骤:模型在编码和解码过程中包含一个将动态协变量映射到低维空间的特征投影步骤。

  4. 时序解码器:最终的预测是通过结合每个时间步的解码向量与该时间步的投影特征来形成的。

  5. 全局线性残差连接:从回溯到预测范围,模型还增加了一个全局线性残差连接。

总结:TiDE模型的结构注重于简化和效率,避免了自注意力、递归或卷积机制,从而在处理长期时间序列预测任务时实现了线性的计算量扩展。

下面的图片是TiDE的网络结构图(附上我个人的理解)->

这个网络结构从输入到输出的工作流程是:

  1. 动态协变量:它首先对时间序列的动态协变量进行特征投影,简化特征的维度。

  2. 查回和属性输入:将过去的时间序列数据(查回部分)与相关属性(如日期、假日等)结合。

  3. 编码:这些结合后的数据被送入密集编码器,它使用多层感知机对信息进行编码,生成一个内部表示。

  4. 解码:内部表示随后被送入密集解码器,再次使用多层感知机,解码预测未来的时间序列。

  5. 时序解码:每个时间步的预测通过时序解码器进行优化,以生成最终的时间序列预测。

  6. 残差连接:为了加强模型的预测能力并减少训练中的问题,如梯度消失,一个残差连接直接将输入的查回部分连接到输出端。

这整个过程就像是将时间序列的历史数据和相关信息通过一个多层处理过程,最终转化为对未来的精准预测。

下面我来分别介绍TiDE的几个关键组成部分(同时每一个步骤在TiDE的网络结构中位置我都进行了标注)->


2.1.1 密集多层感知机(MLP)编码器

密集多层感知机(MLP)编码器是TiDE模型中的核心部分,它的作用是将时间序列的历史数据(也称为查回部分)和协变量(如日期、天气等可能影响预测的外部信息)转换成内部表示。这个编码器通过一系列层次化的网络层(即MLP层)来处理输入数据,每一层都会对数据进行转换和学习,从而捕捉时间序列的复杂模式和依赖关系。简而言之,这个编码器将原始输入转换成模型可以进一步处理的压缩信息。


2.1.2 密集MLP解码器

密集MLP解码器在TiDE模型中扮演着将编码后的信息转换回时间序列预测的角色。这个解码器接收来自编码器的内部表示,并开始构建对未来时间点的预测。它也使用多层感知机层,这些层专门训练用于识别编码信息中的模式,并将这些模式映射到未来的协变量上,从而生成对未来时间序列的预测值。简言之,解码器的任务是解读编码的数据,并将其转换为具体的未来预测。


2.1.3 特征投影步骤

特征投影步骤是TiDE模型的一部分,它负责处理动态协变量——这些是随时间变化而变化的输入变量,如天气或节假日等。在这一步骤中,模型将这些协变量从高维空间降维到一个低维空间。这个过程有助于简化模型处理的信息量,减少计算复杂性,并且可能还能帮助模型更有效地从这些协变量中提取有用的特征,以便进行准确的时间序列预测。简单来说,特征投影就像是对输入数据进行压缩,以便于编码器和解码器更有效地处理。 


2.1.4 时序解码器

时序解码器是TiDE模型中的一个重要组件,用于处理密集解码器输出的信息。它特别针对每个时间步骤进行工作,把解码器生成的预测转化为最终的时间序列输出。时序解码器通过在每个时间点上应用特定的变换,优化了预测的时间依赖性,增强了模型对时间序列数据中时间动态的捕捉能力。简而言之,时序解码器将解码过程与时间维度相结合,生成精确的逐步预测。


2.1.5 全局线性残差连接

全局线性残差连接是一种在神经网络中常见的技术,用于改善深层网络的学习效率和减少训练难度。在TiDE模型中,残差连接允许从网络的早期层(在本例中是查回部分)直接传递信息到后面的层,这有助于模型在学习过程中保留原始输入数据的信息。这样,即使在网络很深的情况下,也可以缓解梯度消失的问题,确保网络能够有效地学习和适应训练数据。简单来说,它就像是一个快捷通道,使得输入数据可以绕过多个中间层直接影响输出。


2.2 TiDE的实验结果

下面这个表格总结TiDE的效果对比,可以看出在绝大多数的数据上其都有一个最好的结果(但是真假性不易得知,我个人实验效果只能说和之前的一些模型持平吧)。

这个直方图代表了DiTE模型的训练速度(单位是秒S),我个人训练在3070上速度还可以吧毕竟不像图像领域。


三、实战所用数据集 

了解时序领域的读者都知道,最出名的数据集就是ETTh系列的数据集,我使用的就是ETTh1.csv文件。 

本文我们用到的数据集是ETTh1.csv,该数据集是一个用于时间序列预测的电力负荷数据集,它是 ETTh 数据集系列中的一个。ETTh 数据集系列通常用于测试和评估时间序列预测模型。以下是 ETTh1.csv 数据集的一些内容:

数据内容:该数据集通常包含有关电力系统的多种变量,如电力负荷、价格、天气情况等。这些变量可以用于预测未来的电力需求或价格。

时间范围和分辨率:数据通常按小时或天记录,涵盖了数月或数年的时间跨度。具体的时间范围和分辨率可能会根据数据集的版本而异。 

以下是该数据集的部分截图->


四、实战代码 

4.1 个人完善版本下载地址 

前面的代码我提供了一个官方版本,但是那个很简陋,所以我将其集成了在我的框架下,同时上传到了CSDN中地址如下->

下载地址:【Google2023】利用TiDE进行长期预测实战(时间序列密集编码器)

 


4.2 参数详解 

其中主要的配置文件是main.py文件(我们只需要配置好该文件就可以运行该代码),这里把我设置贴出来方便大家进行设置,同时其中的参数我后面也会进行讲解。

import argparse

import torch

from exp.exp_informer import Exp_Informer

parser = argparse.ArgumentParser(description='TiDE Long Sequences Forecasting')

parser.add_argument('--model', type=str, default='TiDE',
                    help='model of experiment, options: [TiDE]')
parser.add_argument('--data', type=str, default='custom', help='data')
parser.add_argument('--root_path', type=str, default='./', help='root path of the data file')
parser.add_argument('--data_path', type=str, default='ETTh1.csv', help='data file')
parser.add_argument('--is_rolling_predict', type=bool, default=False, help='rolling predict')
parser.add_argument('--rolling_data_path', type=str, default='ETTh1-Test.csv', help='data file')
parser.add_argument('--features', type=str, default='M',
                    help='forecasting task, options:[M, S, MS]; M:multivariate predict multivariate, S:univariate predict univariate, MS:multivariate predict univariate')
parser.add_argument('--target', type=str, default='OT', help='target feature in S or MS task')
parser.add_argument('--freq', type=str, default='h',
                    help='freq for time features encoding, options:[s:secondly, t:minutely, h:hourly, d:daily, b:business days, w:weekly, m:monthly], you can also use more detailed freq like 15min or 3h')
parser.add_argument('--checkpoints', type=str, default='./checkpoints/', help='location of model checkpoints')
parser.add_argument('--seq_len', type=int, default=126, help='input sequence length of Informer encoder')
parser.add_argument('--label_len', type=int, default=64, help='start token length of Informer decoder')
parser.add_argument('--pred_len', type=int, default=24, help='prediction sequence length')

# Informer decoder input: concat[start token series(label_len), zero padding series(pred_len)]
parser.add_argument('--enc_in', type=int, default=7, help='encoder input size')
parser.add_argument('--dec_in', type=int, default=7, help='decoder input size')
parser.add_argument('--c_out', type=int, default=7, help='output size')
parser.add_argument('--d_model', type=int, default=512, help='dimension of model')
parser.add_argument('--n_heads', type=int, default=8, help='num of heads')
parser.add_argument('--e_layers', type=int, default=2, help='num of encoder layers')
parser.add_argument('--d_layers', type=int, default=1, help='num of decoder layers')
parser.add_argument('--s_layers', type=str, default='3,2,1', help='num of stack encoder layers')
parser.add_argument('--d_ff', type=int, default=2048, help='dimension of fcn')
parser.add_argument('--factor', type=int, default=5, help='probsparse attn factor')
parser.add_argument('--padding', type=int, default=0, help='padding type')
parser.add_argument('--distil', action='store_false',
                    help='whether to use distilling in encoder, using this argument means not using distilling',
                    default=True)

parser.add_argument('--dropout', type=float, default=0.05, help='dropout')
parser.add_argument('--attn', type=str, default='prob', help='attention used in encoder, optio---ns:[prob, full]')
parser.add_argument('--embed', type=str, default='timeF',
                    help='time features encoding, options:[timeF, fixed, learned]')
parser.add_argument('--activation', type=str, default='gelu', help='activation')
parser.add_argument('--output_attention', action='store_true', help='whether to output attention in ecoder')
parser.add_argument('--do_predict', action='store_true', default=True, help='whether to predict unseen future data')
parser.add_argument('--mix', action='store_false', help='use mix attention in generative decoder', default=True)
parser.add_argument('--cols', type=str, nargs='+', help='certain cols from the data files as the input features')
parser.add_argument('--num_workers', type=int, default=0, help='data loader num workers')
parser.add_argument('--itr', type=int, default=1, help='experiments times')
parser.add_argument('--train_epochs', type=int, default=20, help='train epochs')
parser.add_argument('--batch_size', type=int, default=16, help='batch size of train input data')
parser.add_argument('--patience', type=int, default=5, help='early stopping patience')
parser.add_argument('--learning_rate', type=float, default=0.0001, help='optimizer learning rate')
parser.add_argument('--des', type=str, default='test', help='exp description')
parser.add_argument('--loss', type=str, default='mse', help='loss function')
parser.add_argument('--lradj', type=str, default='type1', help='adjust learning rate')
parser.add_argument('--use_amp', action='store_true', help='use automatic mixed precision training', default=False)
parser.add_argument('--inverse', action='store_true', help='inverse output data', default=False)

parser.add_argument('--use_gpu', type=bool, default=True, help='use gpu')
parser.add_argument('--gpu', type=int, default=0, help='gpu')
parser.add_argument('--use_multi_gpu', action='store_true', help='use multiple gpus', default=False)
parser.add_argument('--devices', type=str, default='0,1,2,3', help='device ids of multile gpus')

args = parser.parse_args()
args.use_gpu = True if torch.cuda.is_available() and args.use_gpu else False

args.task_name = 'long_term_forecast'
if args.use_gpu and args.use_multi_gpu:
    args.devices = args.devices.replace(' ', '')
    device_ids = args.devices.split(',')
    args.device_ids = [int(id_) for id_ in device_ids]
    args.gpu = args.device_ids[0]

data_parser = {
    'ETTh1': {'data': 'sum.csv', 'T': 'sl', 'B': [7, 7, 7], 'S': [350, 168, 4], 'MS': [7, 7, 1]},
    'ETTh2': {'data': 'ETTh2.csv', 'T': 'OT', 'M': [7, 7, 7], 'S': [1, 1, 1], 'MS': [7, 7, 1]},
    'ETTm1': {'data': 'sum.csv', 'T': 'sl', 'B': [7, 7, 7], 'S': [126, 42, 4], 'MS': [7, 7, 1]},
    'ETTm2': {'data': 'ETTm2.csv', 'T': 'OT', 'M': [7, 7, 7], 'S': [1, 1, 1], 'MS': [7, 7, 1]},
    'WTH': {'data': 'WTH.csv', 'T': 'WetBulbCelsius', 'M': [12, 12, 12], 'S': [1, 1, 1], 'MS': [12, 12, 1]},
    'ECL': {'data': 'ECL.csv', 'T': 'MT_320', 'M': [321, 321, 321], 'S': [1, 1, 1], 'MS': [321, 321, 1]},
    'Solar': {'data': 'solar_AL.csv', 'T': 'POWER_136', 'M': [137, 137, 137], 'S': [1, 1, 1], 'MS': [137, 137, 1]},
    'custom': {'data': '{}'.format(args.data_path), 'T': '{}'.format(args.target), '{}'.format(args.features):
        [args.enc_in, args.dec_in, args.c_out]},
}


if args.data in data_parser.keys():
    data_info = data_parser[args.data]
    args.data_path = data_info['data']
    args.target = data_info['T']
    args.enc_in, args.dec_in, args.c_out = data_info[args.features]

args.s_layers = [int(s_l) for s_l in args.s_layers.replace(' ', '').split(',')]
args.detail_freq = args.freq
args.freq = args.freq[-1:]

print('Args in experiment:')
print(args)

Exp = Exp_Informer

for ii in range(args.itr):
    # setting record of experiments
    setting = 'group_id{}_{}_{}_ft{}_sl{}_ll{}_pl{}_dm{}_nh{}_el{}_dl{}_df{}_at{}_fc{}_eb{}_dt{}_mx{}_{}_{}'.format(
        args.data_path, args.model, args.data, args.features,
        args.seq_len, args.label_len, args.pred_len,
        args.d_model, args.n_heads, args.e_layers, args.d_layers, args.d_ff, args.attn, args.factor,
        args.embed, args.distil, args.mix, args.des, ii)

    exp = Exp(args)  # set experiments
    print('>>>>>>>start training : {}>>>>>>>>>>>>>>>>>>>>>>>>>>'.format(setting))
    exp.train(setting)

    print('>>>>>>>testing : {}<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'.format(setting))
    exp.test(setting)

    if args.do_predict:
        print('>>>>>>>predicting : {}<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'.format(setting))
        exp.predict(args, setting, True)

    torch.cuda.empty_cache()

其中涉及到很多的参数,我来进行讲解(大家如果想运行看完参数讲解你是一定能够运行的)

其中的参数涉及到运行成功与否的我都用颜色标出来了 

参数名称参数类型参数讲解
0modelstr这是一个用于实验的参数设置,其中包含了三个选项: informer, informerstack, informerlight。根据实验需求,可以选择其中之一来进行实验,默认是使用informer模型。
1datastr数据,这个并不是你理解的你的数据集文件,而是你想要用官方定义的方法还是你自己的数据集进行定义数据加载器,如果是自己的数据集就输入custom
2root_pathstr这个才是你文件的路径,不要到具体的文件,到目录级别即可。
3data_pathstr这个填写你文件的名称。
4featuresstr这个是特征有三个选项M,MS,S。分别是多元预测多元,多元预测单元,单元预测单元。
5targetstr这个是你数据集中你想要预测那一列数据,假设我预测的特征是OT列就输入OT即可。
6freqstr时间的间隔,你数据集每一条数据之间的时间间隔。
7checkpointsstr训练出来的模型保存路径
8seq_lenint用过去的多少条数据来预测未来的数据
9label_lenint可以裂解为更高的权重占比的部分要小于seq_len
10pred_lenint预测未来多少个时间点的数据
11enc_inint你数据有多少列,要减去时间那一列,这里我是输入8列数据但是有一列是时间所以就填写7
12dec_inint同上
13c_outint这里有一些不同如果你的features填写的是M那么和上面就一样,如果填写的MS那么这里要输入1因为你的输出只有一列数据。
14d_modelint用于设置模型的维度,默认值为512。可以根据需要调整该参数的数值来改变模型的维度
15n_headsint用于设置模型中的注意力头数。默认值为8,表示模型会使用8个注意力头,我建议和的输入数据的总体保持一致,列如我输入的是8列数据不用刨去时间的那一列就输入8即可。
16e_layersint用于设置编码器的层数
17d_layersint用于设置解码器的层数
18s_layersstr用于设置堆叠编码器的层数
19d_ffint模型中全连接网络(FCN)的维度,默认值为2048
20factorint ProbSparse自注意力中的因子,默认值为5
21paddingint填充类型,默认值为0,这个应该大家都理解,如果不够数据就填写0.
22distilbool是否在编码器中使用蒸馏操作。使用--distil参数表示不使用蒸馏操作,默认为True也是我们的论文中比较重要的一个改进。
23dropoutfloat这个应该都理解不说了,丢弃的概率,防止过拟合的。
24attnstr编码器中使用的注意力类型,默认为"prob"我们论文的主要改进点,提出的注意力机制。
25embedstr时间特征的编码方式,默认为"timeF"
26activationstr激活函数
27output_attentionbool是否在编码器中输出注意力,默认为False
28do_predictbool是否进行预测,这里模型中没有给添加算是一个小bug我们需要填写一个default=True在其中。
29mixbool在生成式解码器中是否使用混合注意力,默认为True
30colsstr从数据文件中选择特定的列作为输入特征,应该用不到
31num_workersint线程windows大家最好设置成0否则会报线程错误,linux系统随便设置。
32itrint实验运行的次数,默认为2,我们这里改成数字1.
33train_epochsint训练的次数
34batch_sizeint一次往模型力输入多少条数据
35patienceint早停机制,如果损失多少个epochs没有改变就停止训练。
36learning_ratefloat学习率。
37desstr        实验描述,默认为"test"
38lossstr     损失函数,默认为"mse"
39lradjstr     学习率的调整方式,默认为"type1"
40use_ampbool混合精度训练,
41inversebool我们的数据输入之前会被进行归一化处理,这里默认为False,算是一个小bug因为输出的数据模型没有给我们转化成我们的数据,我们要改成True。
42use_gpubool是否使用GPU训练,根据自身来选择
43gpuintGPU的编号
44use_multi_gpubool是否使用多个GPU训练。
45devicesstrGPU的编号


五、DiTE实战

5.1 训练模型

当我们配置完所有的参数之后直接运行main.py文件就可以开始训练了,控制台的输出如下-> 

训练完的结果保存在该文件目录下(其中的pth文件就是我们的模型我们之后预测直接加载其就可以)-> 


5.2 测试集表现 

测试集本来想做一个画图功能了后来想着大家可能也不需要,所以就没做测试集会打印出模型误差如下->


5.3 预测未来一天的数据(结果可视化)

 下面的文件是代码自动生成预测一天的csv文件。

可视化如下->


5.4 滚动长期预测(结果可视化 + CSV文件生成)

可以看出这个效果只能说一般,但是我们研究这种最新的模型只要看的是其思想~


六、如何训练你自己的数据集

上面介绍了用我的数据集训练模型,那么大家在利用模型的时候如何训练自己的数据集呢这里给家介绍一下需要修改的几处地方。

parser.add_argument('--data', type=str, default='custom', help='data')
parser.add_argument('--root_path', type=str, default='', help='root path of the data file')
parser.add_argument('--data_path', type=str, default='ETTh1.csv', help='data file')
parser.add_argument('--features', type=str, default='MS',
                    help='forecasting task, options:[M, S, MS]; M:multivariate predict multivariate, S:univariate predict univariate, MS:multivariate predict univariate')
parser.add_argument('--target', type=str, default='OT', help='target feature in S or MS task')
parser.add_argument('--freq', type=str, default='h',

首先需要修改的就是上面这几处,

  • 其中data必须填写custom,
  • root_path填写文件夹即可,
  • data_path填写具体的文件在你文件夹下面,
  • features前面有讲解,具体是看你自己的数据集,我这里MS就是7列结果综合分析输出想要的那一列结果的预测值,
  • target就是你数据集中你想要知道那列的预测值的列名,
  • freq就是你两条数据之间的时间间隔。
parser.add_argument('--seq_len', type=int, default=96, help='input sequence length of Informer encoder')
parser.add_argument('--label_len', type=int, default=48, help='start token length of Informer decoder')
parser.add_argument('--pred_len', type=int, default=24, help='prediction sequence length')

然后这三个就是影响精度的地方,seq_len和label_len需要根据数据的特性来设置,要进行专业的数据分析,我会在下一周出教程希望到时候能够帮助到大家。

parser.add_argument('--enc_in', type=int, default=7, help='encoder input size')
parser.add_argument('--dec_in', type=int, default=7, help='decoder input size')
parser.add_argument('--c_out', type=int, default=7, help='output size')

这三个参数要修改和你的数据集对应和前面features的设定来配合设置,具体可以看我前面的参数讲解部分,参数需要修改的就这些,然后是代码部分如下。

data_parser = {
    'ETTh1': {'data': 'ETTh1.csv', 'T': 'OT', 'M': [7, 7, 7], 'S': [1, 1, 1], 'MS': [7, 7, 1]},
    'ETTh2': {'data': 'ETTh2.csv', 'T': 'OT', 'M': [7, 7, 7], 'S': [1, 1, 1], 'MS': [7, 7, 1]},
    'ETTm1': {'data': 'ETTm1.csv', 'T': 'OT', 'M': [7, 7, 7], 'S': [1, 1, 1], 'MS': [7, 7, 1]},
    'ETTm2': {'data': 'ETTm2.csv', 'T': 'OT', 'M': [7, 7, 7], 'S': [1, 1, 1], 'MS': [7, 7, 1]},
    'WTH': {'data': 'WTH.csv', 'T': 'WetBulbCelsius', 'M': [12, 12, 12], 'S': [1, 1, 1], 'MS': [12, 12, 1]},
    'ECL': {'data': 'ECL.csv', 'T': 'MT_320', 'M': [321, 321, 321], 'S': [1, 1, 1], 'MS': [321, 321, 1]},
    'Solar': {'data': 'solar_AL.csv', 'T': 'POWER_136', 'M': [137, 137, 137], 'S': [1, 1, 1], 'MS': [137, 137, 1]},
    'custom': {'data': 'ETTh1.csv', 'T': 'OT', 'M': [7, 7, 7], 'S': [1, 1, 1], 'MS': [7, 7, 1]},
}

main_informer.py文件有如上的结构,这是我修改之后的,你可以按照我的修改,其中custom就是对应你前面设置参数data的名字,然后data后面替换成你的数据集,必须是csv格式的文件这里,然后是T大家不用管,OT修改成你自己数据集中预测的哪一列列名,就是前面设置的target值,然后是M,S,MS分别对应你数据中的列的给个数即可,我这里输入是8列扣去时间一列在M中就全部填写7即可,S的话我的数据集用不到,MS就是7列输出一列。 

最后呢大家如果需要我的数据集和修改完成之后的实战代码可以在评论区留言。


七、本文总结 

到此本文的正式分享内容就结束了,在这里给大家推荐我的时间序列专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的模型进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~)如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

 专栏回顾: 时间序列预测专栏——持续复习各种顶会内容——科研必备

如果大家有不懂的也可以评论区留言一些报错什么的大家可以讨论讨论看到我也会给大家解答如何解决!最后希望大家工作顺利学业有成!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GEE:梯度卷积

作者:CSDN @ _养乐多_ 本文将介绍在 Google Earth Engine(GEE)平台上,进行梯度卷积操作的代码框架、核心函数和多种卷积核,比如 Roberts、Prewitt、Sobel、各向同性算子、Compass算子、拉普拉斯算子、不同方向线性检测算子等。 结果如下图所示, 文章目录 一、常用的梯度…

实现一个简单的网络通信下(udp)

时间过去好久了&#xff0c;先回忆一下上一篇博客的代码&#xff01;&#xff01; 目前来看&#xff0c;我们客户端发一条消息&#xff0c;我服务器收到这一条消息之后呢&#xff0c;服务器也知道了是谁给我发来的消息&#xff0c;紧接这就把这条消息放进buffer当中&#xff0c…

POJ 3734 Blocks 动态规划(矩阵的幂)

一、题目大意 我们要给排成一行的区块涂颜色&#xff0c;可以选择红、绿、蓝、黄四种&#xff0c;要求红和绿的块都必须是偶数个&#xff0c;求出最终的涂色方式&#xff0c;对10007取余。 二、解题思路 我们设三个数列A&#xff0c;B和C&#xff1a; 1、A代表红色和绿色都…

百度收录批量查询工具,免费SEO优化排名工具

拥有一个在搜索引擎中得到良好收录的网站对于个人和企业都至关重要。而百度&#xff0c;作为中国最大的搜索引擎&#xff0c;其收录情况直接影响着网站的曝光度和流量。 百度搜索引擎是中文用户获取信息的重要途径之一。而在这个竞争激烈的网络环境中&#xff0c;了解自己网站…

QT 中 QTimer 类 备查

基础 // 指定了父对象, 创建的堆内存可以自动析构 QTimer::QTimer(QObject *parent nullptr);// 根据指定的时间间隔启动或者重启定时器, 需要调用 setInterval() 设置时间间隔 void QTimer::start();// 启动或重新启动定时器&#xff0c;超时间隔为msec毫秒。 void QTimer::…

游泳馆会员服务预约管理系统预约小程序效果如何

游泳馆在各地每天都有大量用户前往&#xff0c;夏季室外、冬季室内也是学习游泳技术和休闲娱乐的好地方&#xff0c;而消费者大多是年轻人和家长带的孩子&#xff0c;这部分群体更显年轻化&#xff0c;因此在如今互联网环境下&#xff0c;传统商家需要进一步赋能客户消费路径。…

共识问题:区块链如何确认记账权?

区块链可以说是最近几年最热的技术领域之一&#xff0c;区块链起源于中本聪的比特币&#xff0c;作为比特币的底层技术&#xff0c;本质上是一个去中心化的数据库&#xff0c;其特点是去中心化、公开透明&#xff0c;作为分布式账本技术&#xff0c;每个节点都可以参与数据库的…

力扣 --- 最长公共前缀

题目描述&#xff1a; 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"…

蓝桥杯物联网竞赛_STM32L071_8_ADC扩展模块

原理图&#xff1a; 扩展模块原理图&#xff1a; RP1和RP2分别对应着AIN1和AIN2&#xff0c;扭动它们&#xff0c;其对应滑动变阻器阻值也会变化 实验板接口原理图&#xff1a; 对应实验板接口PB1和PB0 即AN1对应PB1, AN2对应PB0 CubMx配置&#xff1a; ADC通道IN8和IN9才对…

Spring MVC学习随笔-控制器(Controller)开发详解:控制器跳转与作用域(二)视图模板、静态资源访问

学习视频&#xff1a;孙哥说SpringMVC&#xff1a;结合Thymeleaf&#xff0c;重塑你的MVC世界&#xff01;&#xff5c;前所未有的Web开发探索之旅 衔接上文Spring MVC学习随笔-控制器(Controller)开发详解&#xff1a;控制器跳转与作用域&#xff08;一&#xff09; SpingMVC中…

智慧灯杆系统平台架构设计需要考虑的几个要点

智慧灯杆是一种集成了各种先进技术的道路照明设施。它不仅提供照明服务&#xff0c;还可以具有物联网技术、视频监控、环境监测、广播通讯、无线网络覆盖等多种功能。这些智能功能可以通过互联网进行控制和管理&#xff0c;从而实现智慧城市的建设。智慧灯杆能够提升城市的智能…

费解的开关

费解的开关 模拟一下开关的过程&#xff1a; 直接对第一行进行开关灯即可&#xff0c;那么第一行开关等的方案有多少个呢&#xff1f; 可以第一个想到的是5次&#xff0c;但实际上是25次&#xff0c;因为没有规定说只能开关一次吧。 那么如何获得这32种方案呢&#xff1f; 可…

【算法】前后缀分解题单⭐

文章目录 题单来源题目列表42. 接雨水238. 除自身以外数组的乘积2256. 最小平均差2483. 商店的最少代价代码1——前后缀数组代码2—— O ( 1 ) O(1) O(1)空间&#x1f402; 2420. 找到所有好下标2167. 移除所有载有违禁货物车厢所需的最少时间代码1——前后缀分解代码2——简洁…

【一个超简单的爬虫demo】探索新浪网:使用 Python 爬虫获取动态网页数据

探索新浪网&#xff1a;使用 Python 爬虫获取动态网页数据 引言准备工作选择目标新浪网的结构 编写爬虫代码爬取example.com爬取新浪首页部分内容解析代码注意&#xff1a; KeyError: href结果与展示 其他修改和适应注意事项 总结 引言 可以实战教爬虫吗&#xff0c;搭个环境尝…

利用STM32内置温度传感器实现温度监测系统

STM32微控制器是一款强大的嵌入式处理器&#xff0c;具有广泛的应用领域。其中&#xff0c;一些STM32微控制器内置了温度传感器&#xff0c;可以方便地实现温度监测功能。本文将详细介绍如何利用STM32内置温度传感器实现温度监测系统&#xff0c;并提供相应的示例代码。 一、硬…

python爬虫AES魔改案例:某音乐素材下载网

声明&#xff1a; 该文章为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;违者后果自负&#xff0c;由此产生的一切后果均与作者无关 一、找出需要加密的参数 js运行 atob(‘aHR0cHM6Ly93d3cuYWlnZWkuY29tL3NvdW5kL2NsYXNzLw’) 拿到网址&#xff0c;F12打开调…

Nginx配置反向代理与负载均衡

Nginx配置反向代理与负载均衡 一、代理服务1.正向代理2.反向代理 二、实战场景-反向代理1.修改nginx配置 -> nginx.conf文件2.修改前端路径 三、实战场景-负载均衡1.热备2.轮询3.加权轮询4.ip_hash ​ Nginx (“engine x”) 是一个高性能的HTTP和反向代理服务器&#xff0c;…

ubuntu下快速搭建docker环境训练yolov5数据集

参考文档 yolov5-github yolov5-github-训练文档 csdn训练博客 一、配置环境 1.1 安装依赖包 前往清华源官方地址 选择适合自己的版本替换自己的源 # 备份源文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list_bak # 修改源文件 # 更新 sudo apt update &&a…

机器人阻抗控制性能及其实验验证

Impedance Control 机器人阻抗控制是一种控制方法&#xff0c;其目的是构建一个系统使得执行器&#xff08;如机械臂&#xff09;能同时控制力和位置。它基于阻抗模型&#xff0c;通过调节机器人的行为&#xff0c;以维持理想的动态关系。这种动态关系可以理解为机器人末端位置…

2024年天津财经大学珠江学院专升本专业课报名缴费操作流程

天津财经大学珠江学院专升本专业课报名缴费操作流程 天津财经大学珠江学院专升本专业课报名就是缴费&#xff0c;只需要使用中国银行交专业课报名费即可。 缴费操作流程如下&#xff1a; 登录中国银行手机 APP—点击“生活”—在界面 最左上角选择定位为“天津市”—点击“生…