首页 > 其他分享 >【模型】Informer模型详解

【模型】Informer模型详解

时间:2025-01-19 09:00:01浏览次数:3  
标签:model train 模型 test 详解 序列 Informer self size

Informer 是一种针对长时间序列预测任务设计的深度学习模型,特别适用于解决序列数据的高效建模与预测问题。Informer 提出了许多创新的机制,尤其是在计算效率方面,能够显著提高长时间序列预测的准确性和速度。以下是对该模型的详细介绍。

1. 模型架构

在这里插入图片描述

Informer的核心思想是通过结合自注意力机制和稀疏化的操作来提高效率,并使用长短期记忆网络(LSTM)结合注意力机制进行建模。它主要由以下几部分组成:

  1. 输入编码层:对输入的时间序列数据进行预处理。通常,数据会经过标准化、嵌入等步骤,并转换为适合自注意力机制处理的形式。
  2. Encoder-Decoder结构:Informer采用类似于Transformer的Encoder-Decoder架构。
    • Encoder:由多个自注意力层(Self-Attention)和前馈神经网络(Feed-Forward Networks)堆叠组成。对于每个输入序列,使用了全局和局部自注意力机制的组合。
    • Decoder:与传统的Transformer类似,解码器通过对未来时间步的预测,结合编码器的输出生成最终结果。
  3. 稀疏化注意力(Sparse Attention)
    • ProbSparse Attention:Informer引入了一种新的注意力机制——ProbSparse Attention,其通过只关注时间序列中的重要时间点(而非所有时间点)来减少计算复杂度。通过对输入序列中的关键部分进行采样和选择,它在保证准确性的同时,大幅提高了计算效率。
  4. 细节:
    • 自注意力计算过程:传统的自注意力机制计算复杂度为 O(N2)O(N^2),其中 NN 为序列长度。Informer通过采用稀疏注意力的方法,使得复杂度降到 O(Nlog⁡N)O(N\log{N})。
    • 多层叠加:Encoder部分通常由多个自注意力层和前馈神经网络层叠加,Decoder则接收Encoder的输出,预测未来时间步的目标序列。

2. 算法使用PyTorch实现

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import DataLoader, TensorDataset
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
import numpy as np

# 定义Informer模型类
class AttentionLayer(nn.Module):
    def __init__(self, embed_size, heads, dropout=0.1):
        super(AttentionLayer, self).__init__()
        self.attn = nn.MultiheadAttention(embed_size, heads, dropout=dropout)
    
    def forward(self, query, key, value):
        # query, key, value的shape是 (batch_size, seq_len, embed_size)
        output, _ = self.attn(query, key, value)
        return output

class InformerEncoderLayer(nn.Module):
    def __init__(self, embed_size, heads, ff_hid_dim, dropout=0.1):
        super(InformerEncoderLayer, self).__init__()
        self.attn = AttentionLayer(embed_size, heads, dropout)
        self.ffn = nn.Sequential(
            nn.Linear(embed_size, ff_hid_dim),
            nn.ReLU(),
            nn.Linear(ff_hid_dim, embed_size)
        )
        self.layernorm1 = nn.LayerNorm(embed_size)
        self.layernorm2 = nn.LayerNorm(embed_size)
        self.dropout = nn.Dropout(dropout)
    
    def forward(self, x):
        attn_out = self.attn(x, x, x)
        x = self.layernorm1(x + self.dropout(attn_out))  # Add & Norm
        
        ffn_out = self.ffn(x)
        x = self.layernorm2(x + self.dropout(ffn_out))  # Add & Norm
        
        return x

class Informer(nn.Module):
    def __init__(self,input_size , embed_size, hidden_size, num_layers, num_heads, forecast_horizon, ff_hid_dim=2048, dropout=0.1):
        super(Informer, self).__init__()
        
        # 1. 输入嵌入层
        self.input_size = input_size
        self.embed_size = embed_size
        self.fc_input = nn.Linear(input_size, embed_size)

        # 2. 定义编码器层
        self.encoder_layers = nn.ModuleList([
            InformerEncoderLayer(embed_size, num_heads, ff_hid_dim, dropout) for _ in range(num_layers)
        ])
        
        # 3. 输出层
        self.fc_output = nn.Linear(embed_size, forecast_horizon)

    def forward(self, x):
        # x 的形状是 (batch_size, seq_len, input_size)
        x = self.fc_input(x)  # 将输入数据嵌入到较高维度

        # 逐层编码
        for encoder_layer in self.encoder_layers:
            x = encoder_layer(x)
        
        # 只取最后时间步的输出
        out = x[:, -1, :]  # 获取最后一个时间步的编码表示
        
        # 输出层
        out = self.fc_output(out)
        
        return out

# 设置设备,使用GPU(如果可用)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'Using device: {device}')

# 假设你已经准备好了数据,X_train, X_test, y_train, y_test等
# 将数据转换为torch tensors,并转移到设备(GPU/CPU)
X_train_tensor = torch.Tensor(X_train).to(device)
X_test_tensor = torch.Tensor(X_test).to(device)
y_train_tensor = torch.Tensor(y_train).squeeze(-1).to(device)  # 确保y_train是正确形状
y_test_tensor = torch.Tensor(y_test).squeeze(-1).to(device)

# 创建训练数据和测试数据集
train_dataset = TensorDataset(X_train_tensor, y_train_tensor)
test_dataset = TensorDataset(X_test_tensor, y_test_tensor)

# 定义 DataLoader
batch_size = 512
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 初始化Informer模型
input_size = X_train.shape[2]  # 特征数量
embed_size = 64  # 嵌入维度
hidden_size = 64  # 隐藏层神经元数量
num_layers = 2  # 编码器层数
num_heads = 4  # 自注意力的头数
forecast_horizon = 5  # 预测的目标步长

model = Informer(input_size, embed_size, hidden_size, num_layers, num_heads, forecast_horizon).to(device)

# 定义训练函数
def train_model_with_dataloader(model, train_loader, test_loader, epochs=50, lr=0.001):
    criterion = nn.MSELoss()
    optimizer = optim.Adam(model.parameters(), lr=lr)
    
    train_loss = []
    val_loss = []
    
    for epoch in range(epochs):
        model.train()
        epoch_train_loss = 0
        for X_batch, y_batch in train_loader:
            optimizer.zero_grad()
            output = model(X_batch)
            loss = criterion(output, y_batch)
            loss.backward()
            optimizer.step()
            epoch_train_loss += loss.item()
        
        train_loss.append(epoch_train_loss / len(train_loader))
        
        model.eval()
        epoch_val_loss = 0
        with torch.no_grad():
            for X_batch, y_batch in test_loader:
                output = model(X_batch)
                loss = criterion(output, y_batch)
                epoch_val_loss += loss.item()
        
        val_loss.append(epoch_val_loss / len(test_loader))
        
        if (epoch + 1) % 10 == 0:  # 每10个epoch输出一次结果
            print(f'Epoch [{epoch+1}/{epochs}], Train Loss: {train_loss[-1]:.4f}, Validation Loss: {val_loss[-1]:.4f}')
    
    plt.plot(train_loss, label='Train Loss')
    plt.plot(val_loss, label='Validation Loss')
    plt.title('Loss vs Epochs')
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.legend()
    plt.show()

# 训练模型
train_model_with_dataloader(model, train_loader, test_loader, epochs=100)

# 评估模型
def evaluate_model_with_dataloader(model, test_loader):
    model.eval()
    y_pred_list = []
    y_test_list = []
    
    with torch.no_grad():
        for X_batch, y_batch in test_loader:
            y_pred = model(X_batch)
            y_pred_list.append(y_pred.cpu().numpy())
            y_test_list.append(y_batch.cpu().numpy())
    
    y_pred_rescaled = np.concatenate(y_pred_list, axis=0)
    y_test_rescaled = np.concatenate(y_test_list, axis=0)
    
    mse = mean_squared_error(y_test_rescaled, y_pred_rescaled)
    print(f'Mean Squared Error: {mse:.4f}')
    return y_pred_rescaled, y_test_rescaled

# 评估模型性能
y_pred_rescaled, y_test_rescaled = evaluate_model_with_dataloader(model, test_loader)

# 保存模型
def save_model(model, path='./model_files/multisteps_informer_model.pth'):
    torch.save(model.state_dict(), path)
    print(f'Model saved to {path}')

save_model(model)

2.1代码解析

(1)Informer和Transformer代码实现的不同之处
特性InformerTransformer
自注意力机制采用稀疏自注意力机制(ProbSparse Attention),通过选择重要的时间步减少计算量。采用标准的全连接自注意力机制**,对每一对位置进行计算,计算复杂度为 O(N2)O(N^2)。
计算复杂度计算复杂度为 O ( N log ⁡ N ) O(N\log{N}) O(NlogN),适合处理长时间序列。计算复杂度为 O ( N 2 ) O(N^2) O(N2),在长时间序列下计算开销较大。
长序列处理能力通过稀疏化自注意力(Top-k Attention)有效减小计算复杂度,能高效处理长序列。长序列时计算和内存开销较大,通常在处理长序列时效率较低。
输入嵌入使用全连接层(fc_input)将输入数据嵌入到较高维度空间(embed_size)。使用全连接层(embedding)将输入映射到隐藏空间(hidden_size)。
位置编码位置编码假设通过稀疏自注意力内隐处理或外部手动加上。位置编码通常通过正弦函数或学习位置编码实现,用于保持序列顺序信息。
编码器设计多层InformerEncoderLayer,包含稀疏自注意力,前馈神经网络。TransformerEncoderLayer,包含标准的多头自注意力机制和前馈神经网络。
自注意力计算方式通过Top-k Attention稀疏化机制,仅关注重要的时间点。计算所有时间步之间的相似度,计算复杂度为 O(N2)O(N^2),对每对位置都进行交互。
局部与全局依赖使用稀疏注意力机制,能够灵活地处理局部和全局依赖。通过标准的自注意力机制同时建模全局依赖,无法区分局部和全局依赖。
前馈网络包含前馈神经网络(FFN),与传统Transformer相似,但侧重于适配长序列。标准的前馈神经网络(FFN),通过全连接层进行转换和激活。
模型优化方向重点优化长时间序列的计算效率,通过稀疏注意力减少计算负担。侧重于序列到序列任务的建模,未针对长时间序列进行特别优化。
序列建模效率高效建模长时间序列,特别适合预测任务,能处理大规模时序数据。在处理长序列时效率较低,计算开销大,通常不适用于超长序列预测。
计算和内存消耗降低了计算和内存消耗,特别是在处理长序列时。随着序列长度增加,计算和内存消耗急剧增加,效率较低。
应用场景适用于需要高效处理长时间依赖的长时间序列预测任务,如能源消耗预测、交通流量预测等。适用于NLP任务(如机器翻译、文本生成)和短时间序列任务,较少用于长时间序列任务。
模型改进目标专门改进了对长时间序列的建模能力,通过稀疏化注意力优化计算效率。原始设计并未专门针对长时间序列进行优化,主要用于处理较短序列。

总结:

  • Informer的设计强调通过稀疏注意力机制降低计算和内存开销,特别适合处理长时间序列的预测任务。其通过Top-k Attention和稀疏化的方式,有效捕捉序列中的长时间依赖,同时避免了标准Transformer中计算复杂度的急剧增长。
  • Transformer采用全连接的自注意力机制,能够处理全局依赖,但在长序列任务中,由于计算复杂度为 O(N2)O(N^2),在处理长序列时会面临计算和内存瓶颈。

因此,Informer相较于Transformer在长时间序列预测任务中更具优势,能够高效地捕捉长时间依赖并降低计算负担,而Transformer更适合处理传统的序列到序列任务,尤其是在序列长度相对较短的情况下。

3. 模型的优缺点

优点:

  • 高效的计算:通过使用稀疏注意力,Informer能有效减少计算复杂度,尤其适合长时间序列数据的建模。
  • 准确性:由于加入了对重要时间点的重点关注,Informer能够更准确地捕捉序列中的重要模式。
  • 扩展性:由于基于Transformer架构,Informer能够非常容易地与其他类型的模型(例如LSTM、GRU等)结合,进一步提升预测性能。

缺点:

  • 对长序列的内存要求:尽管计算复杂度减少,但仍然需要较大的内存来存储模型的权重和计算梯度,可能不适用于非常长的序列。
  • 对超参数敏感:Informer对于网络架构、学习率等超参数较为敏感,需要细致调优。
  • 训练时间较长:尽管计算上有优化,但由于模型结构复杂,训练时间仍然较长。

4. 模型算法变种

  1. Informer-XL:一种变种,它通过引入长距离依赖建模方法,能够捕获跨时间步长的长期依赖性,提升了模型在超长序列上的表现。
  2. Time Series Transformer (TST):类似于Informer,但在处理时间序列时对时间步长进行特殊处理,优化了在时间序列任务中的效果。

5. 模型特点

  • 稀疏化自注意力:Informer通过稀疏化自注意力机制降低了计算开销,尤其适用于长时间序列数据。
  • 效率提升:在长时间序列数据上的训练效率较高,能够处理传统Transformer处理起来较慢的问题。
  • 长短期依赖建模:能够捕捉长时间的依赖关系,适用于许多时间序列预测任务。

6. 应用场景

  • 金融时间序列预测:例如股票价格预测、汇率预测等,长时间序列的预测问题非常适合使用Informer。
  • 气象预测:天气预报、气候变化预测等,需要高效捕捉长时段的气候数据。
  • 交通流量预测:通过交通流量的历史数据来预测未来的交通状况。
  • 能源消耗预测:根据历史能源使用情况预测未来的电力需求或能源消耗。
  • 健康医疗数据预测:使用长时间的健康监测数据预测疾病的发生或患者的康复过程。
    在这里插入图片描述

标签:model,train,模型,test,详解,序列,Informer,self,size
From: https://blog.csdn.net/zkw54334/article/details/145236715

相关文章

  • 模型量化
    模型量化实在是太常见了,但是我完全不知道quantization是什么东西,不好!float在计算机中,float是一种用于表示单精度浮点数的标准数据类型。浮点数的存储遵循IEEE754标准,具体来说,32位浮点数由三部分组成:符号位(Signbit):占1位0表示正数1表示负数指数部分(......
  • Linux中常用命令详解
        在Linux中,有很多常用命令可以帮助你完成日常操作。以下是一些常用Linux命令的详细介绍:1.ls-列出目录内容语法:ls[选项][目录]常用选项:-l:显示详细信息(权限、文件大小、修改时间等)-a:显示所有文件,包括隐藏文件(以.开头)-h:以可读的方式显示文件......
  • 电子工程师入门-03三极管详解(上)
    以下内容均作为个人学习时遇到问题的学习历程,记在这里也是希望自己能常回顾。另外,文章出现的图片有些是个人手绘不太标准。前言:三极管是流控型器件。一,三极管初识晶体三极管中有两种带有不同极性电荷的载流子参与导电,因此称之为双极性晶体管(BJT),又称半导体三极管。根据不同......
  • 软件开发模型
    1.瀑布模型(WaterfallModel)定义瀑布模型是一种线性顺序模型,将软件开发过程分为多个阶段,每个阶段完成后才能进入下一个阶段。典型的阶段包括需求分析、设计、编码、测试和维护。优点结构化和顺序化:每个阶段都有明确的输入和输出,易于管理和控制。文档化:每个阶段都需要详细......
  • 最新AIGC创作平台功能介绍+使用教程+支持GPT对话、AI绘画、AI视频、AI PPT等大模型
    在当今快速发展的数字时代,人工智能(AI)已成为推动创新和提升工作效率的重要工具。「银河易创」作为一站式AIGC创作平台,旨在帮助用户在工作和学习中显著提高效率。无论是进行AI对话、AI绘画、AI视频制作、AI音乐创作,还是快速制作PPT,都能满足您的需求,助您轻松实现创意与灵感的碰撞......
  • 【AI论文】Diffusion模型的推理时缩放:超越降噪步骤的缩放策略
    摘要:生成模型在各个领域产生了重大影响,这主要得益于它们能够在训练过程中通过增加数据、计算资源和模型规模来进行扩展,这一现象被称为扩展定律。最近的研究已经开始探索大型语言模型(LLMs)在推理时间的扩展行为,揭示了如何通过增加推理过程中的计算来进一步提升性能。与LLMs不同,D......
  • ODIN:用于 2D 和 3D 分割的单一模型
    大家觉得有帮助记得及时关注和点赞!!!目录抽象1介绍2相关工作3D实例分割3D数据集和基准测试基于2D的3D分割3方法4实验4.13D基准测试评估4.2模拟中多视图RGB-D的评估4.3具体指令跟随4.4消融和变异4.5其他实验4.6局限性5结论6确认附录A实验答1在Scan......
  • objectMapper详解
    objectMapper详解1、主要功能ObjectMapper是Jackson库中的核心类,用于在Java对象和JSON数据之间进行序列化(将Java对象转换为JSON)和反序列化(将JSON转换为Java对象)。ObjectMapper提供了丰富的配置选项和功能,可以帮助开发者处理复杂的JSON数据结构。序列化:......
  • Profibus DP转Modbus TCP协议转换网关模块功能详解
    ProfibusDP和ModbusTCP是两种不同的工业现场总线协议,ProfibusDP常用于制造业自动化领域,而ModbusTCP则在工业自动化和楼宇自动化等领域广泛应用。实现ProfibusDP转ModbusTCP功能,通常需要特定的网关设备,以下为你详细介绍:捷米JM-DPM-TCP网关模块这......
  • ES6新特性详解:var、let、const的区别
    ECMAScript6(简称ES6)是JavaScript语言的一次重大更新,它引入了许多新特性,使得JavaScript编程更加简洁、高效。在ES6中,对变量声明的方式进行了扩展,新增了let和const关键字,与原有的var关键字一起,为开发者提供了更多选择。本文将详细介绍var、let、const三者之间的区别。一、变量......