当前位置: 首页 > article >正文

N-Beats:一种用于时间序列预测的纯前馈神经网络模型

介绍

N-Beats(Neural Basis Expansion Analysis for Interpretable Time Series Forecasting)是一种基于纯前馈神经网络的时间序列预测模型,由Boris Oreshkin等人在2019年提出。与传统的递归神经网络(如LSTM和GRU)不同,N-Beats通过堆叠多个简单的前馈块来生成预测,具有高度的可解释性和灵活性。

工作原理

模型架构

N-Beats的核心思想是使用一系列简单的前馈块(称为“基础块”)来逐步生成预测值。每个基础块包含一个全连接层(或多个全连接层),用于学习时间序列的模式,并输出两个部分:

  1. 后向分量(Backcast):用于拟合输入的历史数据。
  2. 前向分量(Forecast):用于生成未来的预测值。

基础块可以分为两种类型:

  • 通用块(Generic Block):直接学习时间序列的复杂模式。
  • 趋势块(Trend Block)和季节性块(Seasonality Block):分别用于捕捉时间序列的趋势成分和季节性成分。

训练过程

  1. 数据准备

    • 输入数据包括历史观测值。
    • 每个时间序列被分成训练集和测试集。
  2. 模型训练

    • 对于每个基础块,输入为历史观测值的一部分(即“窗口”)。
    • 基础块生成后向分量和前向分量。
    • 后向分量用于拟合输入的历史数据,前向分量用于生成未来预测值。
    • 损失函数通常采用均方误差(MSE),以最小化预测值与真实值之间的差异。
  3. 堆叠基础块

    • 多个基础块按顺序堆叠,每个块的后向分量用于校正前一个块的残差。
    • 最终的预测值是所有基础块前向分量的累加结果。

优势

  • 可解释性:通过堆叠不同类型的基础块(如趋势块和季节性块),N-Beats能够明确地分解时间序列的不同成分,提高模型的可解释性。
  • 灵活性:N-Beats可以处理不同长度和频率的时间序列数据,并且支持多种类型的预测任务。
  • 高效性:由于不依赖递归结构,N-Beats在训练和推理过程中具有较高的计算效率。
  • 鲁棒性:N-Beats在处理噪声和异常值方面表现出色,能够在一定程度上抵抗这些因素的影响。

实现步骤

数据准备

  1. 收集数据:获取时间序列数据及其相关的协变量。
  2. 预处理
    • 处理缺失值。
    • 标准化或归一化数据。
    • 提取时间特征(如月份、星期几等)。

模型构建

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

class GenericBlock(nn.Module):
    def __init__(self, input_size, theta_size, hidden_size, num_layers):
        super(GenericBlock, self).__init__()
        layers = [nn.Linear(input_size, hidden_size), nn.ReLU()]
        for _ in range(num_layers - 1):
            layers.append(nn.Linear(hidden_size, hidden_size))
            layers.append(nn.ReLU())
        layers.append(nn.Linear(hidden_size, theta_size))
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        return self.layers(x)

class NBeatsBlock(nn.Module):
    def __init__(self, input_size, theta_size, hidden_size, num_layers, basis_function):
        super(NBeatsBlock, self).__init__()
        self.input_size = input_size
        self.theta_size = theta_size
        self.basis_function = basis_function
        self.fc = GenericBlock(input_size, theta_size, hidden_size, num_layers)

    def forward(self, x):
        backcast, forecast = self.basis_function(self.fc(x))
        return backcast, forecast

class NBeatsNet(nn.Module):
    def __init__(self, input_size, output_size, stack_types, nb_blocks_per_stack, thetas_dim, hidden_layer_units, share_weights_in_stack=False):
        super(NBeatsNet, self).__init__()
        self.blocks = []
        for stack_id in range(len(stack_types)):
            for block_id in range(nb_blocks_per_stack[stack_id]):
                if share_weights_in_stack and block_id != 0:
                    self.blocks[-1].requires_grad_(True)
                else:
                    self.blocks.append(NBeatsBlock(input_size, thetas_dim[stack_id], hidden_layer_units[stack_id], 4, stack_types[stack_id]))
        self.blocks = nn.ModuleList(self.blocks)

    def forward(self, x):
        residuals = x
        forecast = 0
        for i, block in enumerate(self.blocks):
            backcast, block_forecast = block(residuals)
            residuals = (residuals - backcast)
            forecast = forecast + block_forecast
        return forecast

# 参数设置
input_size = 10  # 输入窗口大小
output_size = 1  # 输出窗口大小
stack_types = ['generic', 'trend', 'seasonality']
nb_blocks_per_stack = [2, 2, 2]
thetas_dim = [5, 3, 7]
hidden_layer_units = [64, 64, 64]
batch_size = 32
epochs = 100

# 初始化模型
model = NBeatsNet(input_size, output_size, stack_types, nb_blocks_per_stack, thetas_dim, hidden_layer_units)
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 数据加载
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

# 训练模型
for epoch in range(epochs):
    for i, (inputs, targets) in enumerate(train_loader):
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, targets)
        loss.backward()
        optimizer.step()
    print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')

模型评估

  1. 生成预测

    • 使用训练好的模型对测试集进行预测。
    • 生成未来时间点的预测值。
  2. 评估指标

    • 计算均方误差(MSE)、平均绝对误差(MAE)等点估计指标。
    • 评估预测的准确性。

结果分析

  • 可视化:绘制预测值与真实值的对比图。
  • 成分分解:展示各个基础块的后向分量和前向分量,分析其对最终预测结果的贡献。

总结

N-Beats是一种强大的时间序列预测模型,通过堆叠简单的前馈块来生成预测值,具有高度的可解释性和灵活性。


http://www.kler.cn/a/540739.html

相关文章:

  • 在npm上传属于自己的包
  • 2025.2.9 每日学习记录2:技术报告写了一半+一点点读后感
  • 信创领域的PostgreSQL管理员认证
  • 心脏滴血漏洞复现(CVE-2014-0160)
  • 黑马React保姆级(PPT+笔记)
  • 基于SpringBoot的线上历史馆藏管理系统
  • 仿 RabbitMQ 实现的简易消息队列
  • 【Docker】从技术架构到容器实战{空间隔离/资源控制/LXC容器/mount}
  • Git冲突解决技巧
  • 日常吐槽。
  • PostgreSQL的学习心得和知识总结(一百六十七)|深入理解PostgreSQL数据库之静态语法检查工具PgSanity的使用和实现
  • 示波器使用指南
  • [7] 游戏机项目说明
  • SQL自学,mysql从入门到精通 --- 第 15天,数据导入、导出
  • 《深度学习》——pytorch框架及项目
  • 处理STM32 DMA方式下的HAL_UART_ERROR_ORE错误
  • 中央处理器
  • 分布式微服务接口基于多线程进行性能优化
  • 蓝桥杯试题:冒泡排序 选择排序
  • 六.logback记录日志文件并按大小日期分割文件
  • 操作系统调度算法解析(SJF)
  • EtherNet/IP转Modbus TCP实现三菱变频器与西门子PLC通讯的配置案例
  • 从零复现DeepSeek R1:从V3中对MoE、MLA、MTP的实现,到Open R1对R1中SFT、GRPO的实现
  • ESP8266配置为TCP客户端,连接电脑和手机(使用Arduino配置)
  • javaEE-10.CSS入门
  • 【Elasticsearch】管道聚合