基于时间序列预测算法的嵌入表示

#创作灵感#

时间序列预测模型中的嵌入表示

Autoformer中的嵌入表示代码:共包含值嵌入、位置嵌入和时间维度嵌入

class DataEmbedding_wo_pos(nn.Module):
    def __init__(self, c_in, d_model, embed_type='fixed', freq='h', dropout=0.1):
        super(DataEmbedding_wo_pos, self).__init__()

        self.value_embedding = TokenEmbedding(c_in=c_in, d_model=d_model)
        self.position_embedding = PositionalEmbedding(d_model=d_model)
        self.temporal_embedding = TemporalEmbedding(d_model=d_model, embed_type=embed_type,
                                                    freq=freq) if embed_type != 'timeF' else TimeFeatureEmbedding(
            d_model=d_model, embed_type=embed_type, freq=freq)
        self.dropout = nn.Dropout(p=dropout)

    def forward(self, x, x_mark):
        if x_mark is None:
            x = self.value_embedding(x)
        else:
            x = self.value_embedding(x) + self.temporal_embedding(x_mark)
        return self.dropout(x)

值嵌入详解:

class TokenEmbedding(nn.Module):
    def __init__(self, c_in, d_model):
        super(TokenEmbedding, self).__init__()
        padding = 1 if torch.__version__ >= '1.5.0' else 2
        self.tokenConv = nn.Conv1d(in_channels=c_in, out_channels=d_model,
                                   kernel_size=3, padding=padding, padding_mode='circular', bias=False)
        for m in self.modules():
            if isinstance(m, nn.Conv1d):
                nn.init.kaiming_normal_(
                    m.weight, mode='fan_in', nonlinearity='leaky_relu')

    def forward(self, x):
        x = self.tokenConv(x.permute(0, 2, 1)).transpose(1, 2)
        return x

值嵌入的本质是定义了一个一维卷积层 self.tokenConv,其输入通道数为 c_in,输出通道数为 d_model(嵌入维度),卷积核大小为 3。填充方式根据前面设置的 padding 值,并使用循环填充(padding_mode='circular')。此卷积层不使用偏置项(bias=False)。

随后遍历模块中的所有子模块,如果子模块是 nn.Conv1d 类型,则使用 Kaiming 正态初始化方法(He 初始化)初始化其权重。mode='fan_in'nonlinearity='leaky_relu' 指定了初始化的模式和非线性函数。

位置嵌入:

class PositionalEmbedding(nn.Module):
    def __init__(self, d_model, max_len=5000):
        super(PositionalEmbedding, self).__init__()
        # Compute the positional encodings once in log space.
        pe = torch.zeros(max_len, d_model).float()
        pe.require_grad = False

        position = torch.arange(0, max_len).float().unsqueeze(1)
        div_term = (torch.arange(0, d_model, 2).float()
                    * -(math.log(10000.0) / d_model)).exp()

        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)

        pe = pe.unsqueeze(0)
        self.register_buffer('pe', pe)

    def forward(self, x):
        return self.pe[:, :x.size(1)]

位置编码在 Transformer 模型中非常重要,因为 Transformer 本身不具备顺序感知能力。位置编码能向输入序列中添加位置信息。

代码中首先创建一个大小为 (max_len, d_model) 的零矩阵 pe,并将其设置为不需要梯度计算,因为位置编码是固定的,不需要在训练过程中更新。

然后生成一个从 0max_len-1 的序列 position,并通过 unsqueeze(1) 转换成列向量。

然后计算除数项 div_term,它是用于位置编码的周期性变化因子,通过指数运算得到。

positiondiv_term 相乘的结果分别传给 torch.sintorch.cos 函数,生成位置编码的奇数和偶数列。

pe 扩展一个维度,使其形状变为 (1, max_len, d_model)register_buffer 方法将 pe 注册为模块的缓冲区,这意味着它不会作为模型参数被更新,但会作为模型的一部分保存和加载。

在前向传播中,输入 x 的形状为 (batch_size, seq_len, d_model)。这个方法返回位置编码 pe 中对应于输入序列长度 seq_len 的部分。

时间嵌入:

class TemporalEmbedding(nn.Module):
    def __init__(self, d_model, embed_type='fixed', freq='h'):
        super(TemporalEmbedding, self).__init__()

        minute_size = 4
        hour_size = 24
        weekday_size = 7
        day_size = 32
        month_size = 13

        Embed = FixedEmbedding if embed_type == 'fixed' else nn.Embedding
        if freq == 't':
            self.minute_embed = Embed(minute_size, d_model)
        self.hour_embed = Embed(hour_size, d_model)
        self.weekday_embed = Embed(weekday_size, d_model)
        self.day_embed = Embed(day_size, d_model)
        self.month_embed = Embed(month_size, d_model)

    def forward(self, x):
        x = x.long()
        minute_x = self.minute_embed(x[:, :, 4]) if hasattr(
            self, 'minute_embed') else 0.
        hour_x = self.hour_embed(x[:, :, 3])
        weekday_x = self.weekday_embed(x[:, :, 2])
        day_x = self.day_embed(x[:, :, 1])
        month_x = self.month_embed(x[:, :, 0])

        return hour_x + weekday_x + day_x + month_x + minute_x

首先构造函数里定义了与时间特征相关的大小:

  • minute_size:一分钟有 4 个时间段(假设)。
  • hour_size:一天有 24 小时。
  • weekday_size:一周有 7 天。
  • day_size:一个月最多有 31 天(所以用 32 作为大小)。
  • month_size:一年有 12 个月(所以用 13 作为大小)。根据 embed_type 选择嵌入方式。

如果 embed_typefixed,使用 FixedEmbedding,否则使用 nn.Embedding(PyTorch 的嵌入层)。

根据 freq 的值,如果是分钟级别('t'),则创建 minute_embed。无论如何,都会创建 hour_embedweekday_embedday_embedmonth_embed

在前向传播中,输入 x 的形状假定为 (batch_size, seq_len, feature_size),其中 feature_size 至少为 5(分别表示月份、日期、星期几、小时和分钟)。

  • 将输入转换为长整型。
  • 根据是否存在 minute_embed,提取分钟嵌入。
  • 提取小时、星期几、日期和月份的嵌入。
  • 返回所有这些嵌入的和。

 

固定嵌入的代码为:

class FixedEmbedding(nn.Module):
    def __init__(self, c_in, d_model):
        super(FixedEmbedding, self).__init__()

        w = torch.zeros(c_in, d_model).float()
        w.require_grad = False

        position = torch.arange(0, c_in).float().unsqueeze(1)
        div_term = (torch.arange(0, d_model, 2).float()
                    * -(math.log(10000.0) / d_model)).exp()

        w[:, 0::2] = torch.sin(position * div_term)
        w[:, 1::2] = torch.cos(position * div_term)

        self.emb = nn.Embedding(c_in, d_model)
        self.emb.weight = nn.Parameter(w, requires_grad=False)

    def forward(self, x):
        return self.emb(x).detach()

其类似位置嵌入,但是编码固定,不更新

创建一个大小为 (c_in, d_model) 的零矩阵 w,并将其设置为不需要梯度计算,因为固定嵌入在训练过程中不会更新。

创建一个嵌入层 self.emb,大小为 (c_in, d_model),然后将其权重设置为之前计算的固定嵌入矩阵 w,并且设置 requires_grad=False,以确保这些权重不会在训练过程中更新。

在前向传播中,输入 x 是一个索引序列。通过 self.emb(x) 获取对应的嵌入,并通过 .detach() 确保返回的嵌入在计算图中是独立的,不会反向传播梯度。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Transformer模型最初是为了自然语言处理任务而设计的,但是由于其并行化和可扩展性的优势,也被应用于时间序列预测任务中。以下是一个基于Transformer的时间序列预测的示例: 假设我们有一组时间序列数据,其中每个时间步都有3个特征。我们的目标是预测下一个时间步的第一个特征。我们可以使用Transformer模型来训练预测模型。 首先,我们需要将数据转换为符合Transformer输入格式的张量。具体地,我们需要将每个时间步的3个特征组成一个向量,并将所有时间步的向量组成一个矩阵。这个矩阵的大小为(时间步数, 特征数)。 接着,我们需要将这个矩阵输入到Transformer模型中进行训练。在Transformer模型中,我们需要为每个时间步的向量添加位置嵌入,以便模型能够学习到时间序列之间的依赖关系。 在训练过程中,我们可以使用自回归模式来预测下一个时间步的第一个特征。具体地,我们可以将已知的时间步的特征输入到模型中,然后用模型预测下一个时间步的第一个特征。接着,我们将预测结果添加到已知时间步的特征中,得到新的输入矩阵,并重复以上过程直到预测出所有未知时间步的特征。 最后,我们可以将预测结果与真实值进行比较,计算模型的预测误差,并使用梯度下降算法来更新模型参数,以最小化预测误差。 这就是一个基于Transformer的时间序列预测的示例。在实际应用中,我们还需要考虑很多其他因素,比如如何选择模型超参数、如何进行模型优化等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值