DGCN+informer分类预测模型

本文提出了一种基于动态图卷积增强的 Informer 模型(Dynamic Graph Convolution Enhanced Informer),用于多变量时间序列分类任务。

该模型在经典 Informer 架构的基础上,引入了动态图卷积机制,以自适应地捕捉变量之间的时变依赖关系,显著提升了对复杂时间序列结构的建模能力。

目前大多数人都是用lstm,cnn-lstm,transformer类模型做分类,太老了!

代码还可以进一步继续改进,稳3-4区和北核,冲1-2区。

代码功能如下:

1.多变量输入,单标签输出(多分类,数据集如图5)

2.多个指标和结果图(如图1图2图3)

4.将训练的模型结果保存下来供后续处理

5.代码自带数据,一键运行,csv,xlsx文件读取数据,也可以替换自己数据集很简单。

1.整体结构

模型首先通过 DataEmbedding 将输入的时间序列编码为高维特征表示,随后送入由多层 ProbAttention 支持的 Encoder,以高效提取长期依赖和全局上下文信息。

在分类任务中,Encoder 的输出特征序列被送入一个动态图卷积模块(Dynamic GCN),其核心创新在于:邻接矩阵并非预设或固定,而是根据当前输入的平均特征动态计算。具体而言,在每次前向传播中,模型首先计算输入序列在时间维度上的平均特征,然后通过变量间的欧氏距离构建高斯核邻接矩阵,从而生成一个反映当前样本中变量间相关性的动态图结构。该邻接矩阵被用于图卷积操作,实现特征在变量维度上的自适应聚合。

相较于传统图卷积网络(GCN)中使用静态邻接矩阵的局限性,本模型的动态图卷积机制能够根据输入数据的变化自适应地学习变量间的依赖关系,从而更好地捕捉时间序列中非平稳、时变的关联模式。例如,在某些时刻变量间可能呈现强相关性,而在另一时刻则趋于独立,该机制能够灵活响应这种变化,增强模型的表达能力。

本文提出的动态图卷积增强的 Informer 模型(Dynamic GCN Enhanced Informer) 的核心创新点可精炼总结如下:
动态邻接矩阵: 提出基于输入序列平均特征的动态图构建机制,通过欧氏距离与高斯核自适应生成时变邻接矩阵,突破传统GCN中静态图结构的限制。
时变依赖建模: 实现变量间依赖关系的自适应学习,有效捕捉时间序列中非平稳、动态变化的变量相关性。
结构化特征增强 :将动态图卷积嵌入 Informer 编码器后,融合图结构信息与序列上下文,提升特征表示能力。
**端到端可学习:**整个图结构与卷积过程可端到端训练,增强模型对复杂时序模式的表达与分类性能。

2.代码核心细节

python 复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F
from layers.Transformer_EncDec import Decoder, DecoderLayer, Encoder, EncoderLayer, ConvLayer
from layers.SelfAttention_Family import ProbAttention, AttentionLayer
from layers.Embed import DataEmbedding

import numpy as np
import torch.optim as optim

"""
本文提出了一种基于动态图卷积增强的 Informer 模型(Dynamic Graph Convolution Enhanced Informer),用于多变量时间序列分类任务。
该模型在经典 Informer 架构的基础上,引入了动态图卷积机制,以自适应地捕捉变量之间的时变依赖关系,显著提升了对复杂时间序列结构的建模能力。
模型首先通过 DataEmbedding 将输入的时间序列编码为高维特征表示,随后送入由多层 ProbAttention 支持的 Encoder,以高效提取长期依赖和全局上下文信息。
在分类任务中,Encoder 的输出特征序列被送入一个动态图卷积模块(Dynamic GCN),其核心创新在于:邻接矩阵并非预设或固定,而是根据当前输入的平均特征动态计算。
具体而言,在每次前向传播中,模型首先计算输入序列在时间维度上的平均特征,
然后通过变量间的欧氏距离构建高斯核邻接矩阵,从而生成一个反映当前样本中变量间相关性的动态图结构。该邻接矩阵被用于图卷积操作,实现特征在变量维度上的自适应聚合。
相较于传统图卷积网络(GCN)中使用静态邻接矩阵的局限性,本模型的动态图卷积机制能够根据输入数据的变化自适应地学习变量间的依赖关系,从而更好地捕捉时间序列中非平稳、时变的关联模式。
例如,在某些时刻变量间可能呈现强相关性,而在另一时刻则趋于独立,该机制能够灵活响应这种变化,增强模型的表达能力。
此外,模型在 Informer 的编码-解码结构 基础上,通过引入动态图卷积模块,实现了特征表示的增强与结构化学习的融合。最终,经过图卷积处理的特征被展平并送入全连接分类层,完成类别预测。
"""
# --- 定义 GCN 层 ---
class SimpleGCN(nn.Module):
    def __init__(self, in_channels, out_channels, adj_matrix=None):
        super(SimpleGCN, self).__init__()
        self.W = nn.Parameter(torch.randn(in_channels, out_channels))
        if adj_matrix is None:
            # 可学习的邻接矩阵
            self.adj = nn.Parameter(torch.randn(in_channels, in_channels), requires_grad=True)
        else:
            # 固定邻接矩阵(如基于相关性)
            self.register_buffer('adj', adj_matrix)
    def forward(self, x):
        # x: [B, L, D]
        # self.adj: [D, D]
        # 应用图卷积:x @ adj.T
        x = torch.matmul(x, self.adj.T)  # [B, L, D] @ [D, D] → [B, L, D]
        x = torch.matmul(x, self.W)  # [B, L, D] @ [D, D] → [B, L, D]
        return x


# --- Model 类 ---
class Model(nn.Module):
    """
    Informer with GCN (based on correlation) for classification
    """

    def __init__(self, configs):
        super(Model, self).__init__()
        self.task_name = configs.task_name
        self.pred_len = configs.pred_len
        self.label_len = configs.label_len
        self.d_model = configs.d_model
        self.c_out = configs.c_out
        self.num_class = configs.num_class

        # Embedding
        self.enc_embedding = DataEmbedding(configs.enc_in, configs.d_model, configs.embed, configs.freq,
                                           configs.dropout)
        self.dec_embedding = DataEmbedding(configs.dec_in, configs.d_model, configs.embed, configs.freq,
                                           configs.dropout)

        # Encoder
        self.encoder = Encoder(
            [
                EncoderLayer(
                    AttentionLayer(
                        ProbAttention(False, configs.factor, attention_dropout=configs.dropout,
                                      output_attention=configs.output_attention),
                        configs.d_model, configs.n_heads),
                    configs.d_model,
                    configs.d_ff,
                    dropout=configs.dropout,
                    activation=configs.activation
                ) for l in range(configs.e_layers)
            ],
            [
                ConvLayer(
                    configs.d_model
                ) for l in range(configs.e_layers - 1)
            ] if configs.distil and ('forecast' in configs.task_name) else None,
            norm_layer=torch.nn.LayerNorm(configs.d_model)
        )

        # Decoder
        self.decoder = Decoder(
            [
                DecoderLayer(
                    AttentionLayer(
                        ProbAttention(True, configs.factor, attention_dropout=configs.dropout, output_attention=False),
                        configs.d_model, configs.n_heads),
                    AttentionLayer(
                        ProbAttention(False, configs.factor, attention_dropout=configs.dropout, output_attention=False),
                        configs.d_model, configs.n_heads),
                    configs.d_model,
                    configs.d_ff,
                    dropout=configs.dropout,
                    activation=configs.activation,
                )
                for l in range(configs.d_layers)
            ],
            norm_layer=torch.nn.LayerNorm(configs.d_model),
            projection=nn.Linear(configs.d_model, configs.c_out, bias=True)
        )

        # Classification
        if self.task_name == 'classification':
            self.act = F.gelu
            self.dropout = nn.Dropout(configs.dropout)
            # 使用 GCN 替代 CNN
            self.gcn_layer = SimpleGCN(configs.d_model, configs.d_model, None)  # 可学习 adj
            self.projection = nn.Linear(configs.d_model * configs.seq_len, configs.num_class)

        # 其他任务
        if self.task_name == 'imputation' or self.task_name == 'anomaly_detection':
            self.projection = nn.Linear(configs.d_model, configs.c_out, bias=True)

    def long_forecast(self, x_enc, x_mark_enc, x_dec, x_mark_dec):
        enc_out = self.enc_embedding(x_enc, x_mark_enc)
        dec_out = self.dec_embedding(x_dec, x_mark_dec)
        enc_out, attns = self.encoder(enc_out, attn_mask=None)
        dec_out = self.decoder(dec_out, enc_out, x_mask=None, cross_mask=None)
        return dec_out

    def short_forecast(self, x_enc, x_mark_enc, x_dec, x_mark_dec):
        mean_enc = x_enc.mean(1, keepdim=True).detach()
        x_enc = x_enc - mean_enc
        std_enc = torch.sqrt(torch.var(x_enc, dim=1, keepdim=True, unbiased=False) + 1e-5).detach()
        x_enc = x_enc / std_enc

        enc_out = self.enc_embedding(x_enc, x_mark_enc)
        dec_out = self.dec_embedding(x_dec, x_mark_dec)
        enc_out, attns = self.encoder(enc_out, attn_mask=None)
        dec_out = self.decoder(dec_out, enc_out, x_mask=None, cross_mask=None)

        dec_out = dec_out * std_enc + mean_enc
        return dec_out

    def imputation(self, x_enc, x_mark_enc, x_dec, x_mark_dec, mask):
        enc_out = self.enc_embedding(x_enc, x_mark_enc)
        enc_out, attns = self.encoder(enc_out, attn_mask=None)
        dec_out = self.projection(enc_out)
        return dec_out

    def anomaly_detection(self, x_enc):
        enc_out = self.enc_embedding(x_enc, None)
        enc_out, attns = self.encoder(enc_out, attn_mask=None)
        dec_out = self.projection(enc_out)
        return dec_out

    def classification(self, x_enc, x_mark_enc):
        # 前向传播
        enc_out = self.enc_embedding(x_enc, None)  # [B, L, D]
        enc_out, attns = self.encoder(enc_out, attn_mask=None)  # [B, L, D]

        B, L, D = enc_out.shape

        # 动态计算邻接矩阵(基于当前输入的平均特征)
        with torch.no_grad():
            mean_enc = enc_out.mean(dim=1)  # [B, D]
            # 计算变量间的距离(D 维)
            dist_var = torch.cdist(mean_enc.T, mean_enc.T, p=2)  # [D, D]
            sigma = 1.0
            adj = torch.exp(-dist_var**2 / (2 * sigma**2))  # 高斯核
            # 添加自环
            adj = adj + torch.eye(adj.size(0))
            # 归一化
            adj = adj / adj.sum(dim=1, keepdim=True)
        # 更新 gcn_layer 的 adj(必须用 .data 赋值,不破坏梯度)
        self.gcn_layer.adj.data = adj
        # GCN 层
        gcn_output = self.gcn_layer(enc_out)  # [B, L, D]
        # 分类头
        output = self.act(gcn_output)
        output = self.dropout(output)
        output = output.reshape(output.shape[0], -1)  # [B, L*D]
        output = self.projection(output)  # [B, num_class]
        return output

    def forward(self, x_enc, x_mark_enc, x_dec, x_mark_dec, mask=None):
        if self.task_name == 'long_term_forecast':
            dec_out = self.long_forecast(x_enc, x_mark_enc, x_dec, x_mark_dec)
            return dec_out[:, -self.pred_len:, :]
        if self.task_name == 'short_term_forecast':
            dec_out = self.short_forecast(x_enc, x_mark_enc, x_dec, x_mark_dec)
            return dec_out[:, -self.pred_len:, :]
        if self.task_name == 'imputation':
            return self.imputation(x_enc, x_mark_enc, x_dec, x_mark_dec, mask)
        if self.task_name == 'anomaly_detection':
            return self.anomaly_detection(x_enc)
        if self.task_name == 'classification':
            return self.classification(x_enc, x_mark_enc)
        return None

3.实验数据

多特征列+标签列即可(这里我做的是4分类)

4.实验结果

预测准确率中规中矩

5.代码地址及其详细讲解

源码地址:https://space.bilibili.com/51422950?spm_id_from=333.1007.0.0

bili私信up即可

相关推荐
Sunhen_Qiletian4 小时前
卷积神经网络搭建实战(二)——基于PyTorch框架和本地自定义图像数据集的食物分类案例(附输入图片预测功能)
pytorch·分类·cnn
minhuan4 小时前
构建AI智能体:六十六、智能的边界:通过偏差-方差理论理解大模型的能力与局限
人工智能·方差·偏差·方差-偏差分解·方差-偏差权衡·模型调优
润 下4 小时前
C语言——深入解析C语言指针:从基础到实践从入门到精通(四)
c语言·开发语言·人工智能·经验分享·笔记·程序人生·其他
koo3644 小时前
李宏毅机器学习笔记25
人工智能·笔记·机器学习
余俊晖4 小时前
如何让多模态大模型学会“自动思考”-R-4B训练框架核心设计与训练方法
人工智能·算法·机器学习
hzp6664 小时前
Magnus:面向大规模机器学习工作负载的综合数据管理方法
人工智能·深度学习·机器学习·大模型·llm·数据湖·大数据存储
hui梦呓の豚4 小时前
YOLO系列目标检测算法全面解析
人工智能·计算机视觉·目标跟踪
一水鉴天4 小时前
整体设计 逻辑系统程序 之27 拼语言整体设计 9 套程序架构优化与核心组件(CNN 改造框架 / Slave/Supervisor/ 数学工具)协同设计
人工智能·算法
Y_Chime4 小时前
从AAAI2025中挑选出对目标检测有帮助的文献——第二期
人工智能·目标检测·计算机视觉