【问题标题】:Positional Encoding for time series based data for Transformer DNN modelsTransformer DNN 模型的基于时间序列的数据的位置编码
【发布时间】:2021-09-29 06:57:48
【问题描述】:

在几篇学术论文中,研究人员使用以下位置编码来表示序列中元素的位置,无论是基于时间序列的序列还是用于 NLP 目的的句子中的单词。

我的问题是在数据被馈送到深度神经网络(在我的例子中是变压器网络)之前,定位是如何实际应用于数据的:

  • 位置值是否直接添加到序列中元素的实际值(或单词表示值)?还是它们被连接了?位置嵌入是数据预处理阶段的一部分吗?
  • Tensorflow/Keras MultiHeadAttention 层实际上是否已经包含一个负责位置编码的Embeeding 层?还是不行?
  • 数据的规范化怎么样?是否仅对实际元素值进行归一化,然后将位置编码添加到该归一化值?还是将位置编码值添加到元素的原始值中,并将结果值归一化?

我对实际实现细节感兴趣,而不是位置编码的概念部分,因为我已经阅读了大多数关于位置编码的学术论文。不幸的是,大多数学术论文都没有详细描述位置编码在什么阶段以及如何精确地应用于数据结构。

谢谢!!!

【问题讨论】:

  • 关于您的第一个和第三个问题。位置嵌入是与您的输入嵌入具有相同维度的向量,即added 到您的每个“单词嵌入”上,以对句子中单词的位置信息进行编码(因为它不再是连续的)。您可以将其视为将位置信息合并到词向量表示中的预处理步骤。在添加位置编码之前,将归一化步骤应用于词嵌入本身(归一化为单位长度的向量)。
  • @OmarAlSuwaidi,感谢您的评论。当您说“与输入嵌入相同维度的向量”时,我理解 NLP 中单词嵌入的概念。但是基于时间序列的数据呢?嵌入向量会是序列中同一位置的所有特征吗?我的基于时间序列的输入数据具有以下形状:(批次、序列、特征)。因此,对于给定序列中的每个位置,我有 n 个特征。位置编码是否会应用于序列中任何给定位置的每个特征的每个值?
  • 在基于时间序列的数据的情况下,您的输入嵌入将是一个d_model 维向量,该向量通过将输入时间序列数据映射到维度为d_model 的向量通过全连接生成网络。然后像往常一样对待这些输入嵌入;您可以使用正弦和余弦函数为每个位置生成位置编码(与d_model 具有相同的维度),具体取决于它在序列中出现的位置。然后将输入向量与位置编码向量进行元素相加。
  • 但这不会带走变压器网络并行化能力的许多好处吗?天真地,我觉得在数据预处理阶段附加位置编码比在网络内部执行元素添加更有益。注意头仍将并行运行,但是,大量开销将转移到数据预处理阶段,并且可以通过数据管道非常有效地存储和加载具有所有编码的数据集......
  • @OmarAlSuwaidi,Omar,我按照“Attention is all you need”论文中的规定实现了位置编码。但是,添加位置编码会使模型的性能更差。对于“玩具 [容易预测的数据集]”,模型需要大约 2-3 个 epoch 才能达到 99% 的准确度水平,而添加位置编码需要 100 多个 epoch 才能达到相同的准确度水平。这怎么可能?

标签: python tensorflow deep-learning pytorch transformer


【解决方案1】:

位置编码只是让模型区分两个相同但出现在序列中不同位置的元素(单词)的方法。

在 LM 语言模型中应用嵌入之后,我们添加 PE 以添加有关每个单词位置的信息。

位置值是否直接添加到序列中元素的实际值(或单词表示值)?还是它们被连接了?位置嵌入是数据预处理阶段的一部分吗?

是的,PE 值只是直接添加到实际值(嵌入在 LM 中)。这将导致出现在序列开头的单词a的嵌入向量将与出现在序列中间的相同单词的嵌入向量不同。不,PE 不是数据预处理阶段的一部分。

这是一个代码示例:

class PositionalEncodingLayer(nn.Module):
    
    def __init__(self, d_model, max_len=100):
        super(PositionalEncodingLayer, self).__init__()
        self.d_model = d_model
        self.max_len = max_len
    
    def get_angles(self, positions, indexes):
        d_model_tensor = torch.FloatTensor([[self.d_model]]).to(positions.device)
        angle_rates = torch.pow(10000, (2 * (indexes // 2)) / d_model_tensor)
        return positions / angle_rates

    def forward(self, input_sequences):
        """
        :param Tensor[batch_size, seq_len] input_sequences
        :return Tensor[batch_size, seq_len, d_model] position_encoding
        """
        positions = torch.arange(input_sequences.size(1)).unsqueeze(1).to(input_sequences.device) # [seq_len, 1]
        indexes = torch.arange(self.d_model).unsqueeze(0).to(input_sequences.device) # [1, d_model]
        angles = self.get_angles(positions, indexes) # [seq_len, d_model]
        angles[:, 0::2] = torch.sin(angles[:, 0::2]) # apply sin to even indices in the tensor; 2i
        angles[:, 1::2] = torch.cos(angles[:, 1::2]) # apply cos to odd indices in the tensor; 2i
        position_encoding = angles.unsqueeze(0).repeat(input_sequences.size(0), 1, 1) # [batch_size, seq_len, d_model]
        return position_encoding

class InputEmbeddingAndPositionalEncodingLayer(nn.Module):

    def __init__(self, vocab_size, max_len, d_model, dropout):
        super(InputEmbeddingAndPositionalEncodingLayer, self).__init__()
        self.vocab_size = vocab_size
        self.max_len = max_len
        self.d_model = d_model
        self.dropout = nn.Dropout(p=dropout)
        self.token_embedding = nn.Embedding(vocab_size, d_model)
        self.position_encoding = PositionalEncodingLayer(d_model=d_model, max_len=max_len)

    def forward(self, sequences):
        """
        :param Tensor[batch_size, seq_len] sequences
        :return Tensor[batch_size, seq_len, d_model]
        """
        token_embedded = self.token_embedding(sequences) # [batch_size, seq_len, d_model]
        position_encoded = self.position_encoding(sequences) # [batch_size, seq_len, d_model]
        return self.dropout(token_embedded) + position_encoded # [batch_size, seq_len, d_model]

Tensorflow/Keras MultiHeadAttention 层实际上是否已经包含一个负责位置编码的嵌入层?还是不行?

不,您必须自己构建 PE。

数据的规范化呢?是否仅对实际元素值进行归一化,然后将位置编码添加到该归一化值?还是将位置编码值添加到元素的原始值中,并将结果值归一化?

标准化部分由您自行决定。你做你想做的。但是你应该应用标准化。此外,PE 被添加到标准化值而不是实际值。

【讨论】:

  • 感谢您的 cmets。我要补充一点,PE 不仅是为了区分句子中不同位置的两个原本相等的单词,而且是为了嵌入对不同单词的一般定位的意识,因为单词的顺序有时在语义上很重要。但是在这里我处理基于时间序列的数据,并且序列中元素的顺序绝对重要。否则,我发现您的 cmets 非常有帮助且增值。谢谢
  • 我仍然困惑的是为什么我们不能在数据预处理阶段添加位置编码。为什么重要?
猜你喜欢
  • 2020-08-16
  • 2017-08-19
  • 2020-08-09
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 2020-11-28
相关资源
最近更新 更多