时间序列(Time-Series)Crossformer_EncDec.py代码解析

import torch
import torch.nn as nn
from einops import rearrange, repeat
from layers.SelfAttention_Family import TwoStageAttentionLayer

#用于合并时间序列的不同片段
class SegMerging(nn.Module):
    #初始化方法,参数包含模型维度d_model、窗口大小win_size、以及正则化层默认为LayerNorm
    def __init__(self, d_model, win_size, norm_layer=nn.LayerNorm):
        super().__init__() #调用父类的构造方法进行初始化
        self.d_model = d_model
        self.win_size = win_size
        #定义线性变换层,将合并后的窗口重新投影到原始维度空间
        self.linear_trans = nn.Linear(win_size * d_model, d_model)
        #定义正则化层,标准化输入数据
        self.norm = norm_layer(win_size * d_model)
    #
    def forward(self, x):
        #从输入数据的形状中提取批次大小、时间步长、段数和模型维度
        batch_size, ts_d, seg_num, d_model = x.shape
        #计算需要填充的段数以保证窗口大小
        pad_num = seg_num % self.win_size
        #如果需要填充,则在时间序列的末尾复制最后几个段以进行填充
        if pad_num != 0:
            pad_num = self.win_size - pad_num
            x = torch.cat((x, x[:, :, -pad_num:, :]), dim=-2)
        #以窗口为步长,从每个窗口开始选取片段,并将其添加在seg_to_merge
        seg_to_merge = []
        for i in range(self.win_size):
            seg_to_merge.append(x[:, :, i::self.win_size, :])
        #将列表中的所有片段按最后一个维度(特征维度)拼接
        x = torch.cat(seg_to_merge, -1)
        #对合并后的数据进行正则化
        x = self.norm(x)
        #通过线性变换将数据投影回原来的特征维度
        x = self.linear_trans(x)

        return x

#处理不同尺度时间序列的模块
class scale_block(nn.Module):
    #初始化方法,参数包括模型的配置configs,窗口大小win_size,模型维度d_model,注意力头数n_heads,前馈网络的维度d_ff,模块的深度depth,dropout率,段数seg_num以及一个因子factor。
    def __init__(self, configs, win_size, d_model, n_heads, d_ff, depth, dropout, \
                 seg_num=10, factor=10):
        #调用父类的构造方法进行初始化
        super(scale_block, self).__init__()
        #如果窗口大小大于1,则创建一个合并层,否则设置为None。
        if win_size > 1:
            self.merge_layer = SegMerging(d_model, win_size, nn.LayerNorm)
        else:
            self.merge_layer = None
        #创建模块列表以存储编码层。
        self.encode_layers = nn.ModuleList()
        #向模块列表中添加depth数量的TwoStageAttentionLayer,这是一个包含两阶段注意力机制的层。
        for i in range(depth):
            self.encode_layers.append(TwoStageAttentionLayer(configs, seg_num, factor, d_model, n_heads, \
                                                             d_ff, dropout))
    #定义前向传播方法,接收输入x和额外的参数。
    def forward(self, x, attn_mask=None, tau=None, delta=None):
        #从输入数据的形状中提取时间步长维度。
        _, ts_dim, _, _ = x.shape
        #如果存在合并层,则将输入数据通过合并层。
        if self.merge_layer is not None:
            x = self.merge_layer(x)
        #将数据通过所有编码层。
        for layer in self.encode_layers:
            x = layer(x)

        return x, None

#编码器类
class Encoder(nn.Module):
    #初始化方法,参数为注意力层列表
    def __init__(self, attn_layers):
        #调用父类的构造方法进行初始化
        super(Encoder, self).__init__()
        #将传入的注意力层参数转换为模块列表
        self.encode_blocks = nn.ModuleList(attn_layers)
    #定义前向传播方法
    def forward(self, x):
        #创建列表并添加原始输入x
        encode_x = []
        encode_x.append(x)
        #通过所有编码块迭代,并将每个块的输出添加到列表中。
        for block in self.encode_blocks:
            x, attns = block(x)
            encode_x.append(x)

        return encode_x, None

#解码器层类
class DecoderLayer(nn.Module):
    #初始化方法接收自注意力和交叉注意力层,段长度seg_len,模型维度d_model,可选的前馈网络维度d_ff,以及dropout率。
    def __init__(self, self_attention, cross_attention, seg_len, d_model, d_ff=None, dropout=0.1):
        #调用父类的构造方法进行初始化。
        super(DecoderLayer, self).__init__()
        #存储自注意力和交叉注意力机制。
        self.self_attention = self_attention
        self.cross_attention = cross_attention
        #定义两个正则化层,用于标准化数据
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        #定义dropout层
        self.dropout = nn.Dropout(dropout)
        #创建一个简单的多层感知器(MLP)结构,其中包含GELU激活函数
        self.MLP1 = nn.Sequential(nn.Linear(d_model, d_model),
                                  nn.GELU(),
                                  nn.Linear(d_model, d_model))
        #线性预测层,用于将解码器输出映射到段长度。
        self.linear_pred = nn.Linear(d_model, seg_len)
    #定义前向传播方法
    def forward(self, x, cross):
        #获取批次大小
        batch = x.shape[0]
        #将数据通过自注意力层
        x = self.self_attention(x)
        #使用rearrange函数重组数据以匹配交叉注意力层的期望输入格式
        x = rearrange(x, 'b ts_d out_seg_num d_model -> (b ts_d) out_seg_num d_model')

        #将交叉编码数据也重组以匹配期望的格式
        cross = rearrange(cross, 'b ts_d in_seg_num d_model -> (b ts_d) in_seg_num d_model')
        #通过交叉注意力层,输入是重组后的数据和交叉编码数据
        tmp, attn = self.cross_attention(x, cross, cross, None, None, None,)
        #将注意力层的输出加到输入上,并应用dropout
        x = x + self.dropout(tmp)
        #应用第一个正则化层,并将结果保存在y中。
        y = x = self.norm1(x)
        #将y通过多层感知器。
        y = self.MLP1(y)
        #将MLP的输出与x相加,并应用第二个正则化层。
        dec_output = self.norm2(x + y)
        
        #重新解码输出以恢复原始批次维度。
        dec_output = rearrange(dec_output, '(b ts_d) seg_dec_num d_model -> b ts_d seg_dec_num d_model', b=batch)
        #通过线性预测层生成解码层的预测
        layer_predict = self.linear_pred(dec_output)
        #重新预测输出以匹配期望的输出格式
        layer_predict = rearrange(layer_predict, 'b out_d seg_num seg_len -> b (out_d seg_num) seg_len')

        return dec_output, layer_predict

#解码器类
class Decoder(nn.Module):
    #初始化方法,参数为解码器层列表
    def __init__(self, layers):
        #调用父类的构造方法进行初始化
        super(Decoder, self).__init__()
        #将解码器层转换为模块列表
        self.decode_layers = nn.ModuleList(layers)

    #定义前向传播方法,接收输入x和编码器的输出cross
    def forward(self, x, cross):
        #初始化最终预测为None
        final_predict = None
        i = 0
        #从输入数据的形状中提取时间步长维度
        ts_d = x.shape[1]
        #迭代所有解码器层
        for layer in self.decode_layers:
            #获取当前对应的编码器输出
            cross_enc = cross[i]
            #将数据通过解码器层
            x, layer_predict = layer(x, cross_enc)
            #如果是第一次迭代,将最终预测设置为该层预测,否则将该层预测累加到最终预测上
            if final_predict is None:
                final_predict = layer_predict
            else:
                final_predict = final_predict + layer_predict
            i += 1
        #重新安排最终预测的形状以匹配期望的输出格式
        final_predict = rearrange(final_predict, 'b (out_d seg_num) seg_len -> b (seg_num seg_len) out_d', out_d=ts_d)

        return final_predict
 

你可能感兴趣的:(算法,python,python,人工智能,深度学习,机器学习)