相对位置编码和绝对位置编码

位置编码的区别:

相对位置编码和绝对位置编码是两种不同的位置编码方法。

绝对位置编码是一种基于位置嵌入的方法,其中每个位置都被分配了一个唯一的位置向量。这些向量是固定的,与输入序列的内容无关。这种编码方式对于处理较短的序列效果较好,但在处理长序列时可能会存在问题,因为序列的长度超过了模型能够处理的位置编码的范围。

相对位置编码是一种基于相对位置的方法,其中每个位置被编码为一个偏移量,表示该位置与其他位置之间的相对距离。相对位置编码可以通过在输入嵌入中添加额外的信息来实现。这种编码方式可以处理长序列,并且能够在不同的上下文中保持一定的一致性。

Transformers使用Position Encoding,使用sinusoidal函数

BERT和BART都换成了可学习的绝对位置嵌入 (absolute position embeddings)

T5改成了相对位置嵌入(relative position embeddings)

sinusoidal函数

在这里插入图片描述

代码也就是:

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, dropout, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2) *
                             -(math.log(10000.0) / d_model))
        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):
        x = x + Variable(self.pe[:, :x.size(1)], requires_grad=False)
        return self.dropout(x)

绝对位置编码

代码层面

class BertEmbeddings(nn.Module):
    """Construct the embeddings from word, position and token_type embeddings.
    """
    def __init__(self, config):
        super(BertEmbeddings, self).__init__()
        self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=0)
        self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)
        self.token_type_embeddings = nn.Embedding(config.type_vocab_size, config.hidden_size)

        # self.LayerNorm is not snake-cased to stick with TensorFlow model variable name and be able to load
        # any TensorFlow checkpoint file
        self.LayerNorm = BertLayerNorm(config.hidden_size, eps=1e-12)
        self.dropout = nn.Dropout(config.hidden_dropout_prob)

    def forward(self, input_ids, token_type_ids=None):
        seq_length = input_ids.size(1)
        position_ids = torch.arange(seq_length, dtype=torch.long, device=input_ids.device)
        position_ids = position_ids.unsqueeze(0).expand_as(input_ids)
        if token_type_ids is None:
            token_type_ids = torch.zeros_like(input_ids)

        words_embeddings = self.word_embeddings(input_ids)
        position_embeddings = self.position_embeddings(position_ids)
        token_type_embeddings = self.token_type_embeddings(token_type_ids)

        embeddings = words_embeddings + position_embeddings + token_type_embeddings
        embeddings = self.LayerNorm(embeddings)
        embeddings = self.dropout(embeddings)
        return embeddings

都是随机初始化的 nn.Embedding 词在神经网络中的向量表示。

介绍:

一个简单的查找表(lookup table),存储固定字典和大小的词嵌入。
此模块通常用于存储单词嵌入并使用索引检索它们(类似数组)。模块的输入是一个索引列表,输出是相应的词嵌入。
参数:
num_embeddings - 词嵌入字典大小,即一个字典里要有多少个词。
embedding_dim - 每个词嵌入向量的大小。
变量:
Embedding.weight(Tensor)–形状模块(num_embeddings,Embedding_dim)的可学习权重,初始化自(0,1)。
也就是说,pytorch的nn.Embedding()是可以自动学习每个词向量对应的w权重的。

class Embedding(Module):
    def __init__(self, num_embeddings, embedding_dim, padding_idx=None):
        super(Embedding, self).__init__()
        self.num_embeddings = num_embeddings
        self.embedding_dim = embedding_dim
        self.padding_idx = padding_idx
        
        # 构造一个num_embeddings x embedding_dim的可学习的权重矩阵
        self.weight = Parameter(torch.Tensor(num_embeddings, embedding_dim))
        self.reset_parameters()

    def reset_parameters(self):
        # 初始化权重矩阵
        nn.init.xavier_uniform_(self.weight)

    def forward(self, input):
        # 如果存在padding_idx,则将其嵌入向量设为0
        if self.padding_idx is not None:
            self.weight[self.padding_idx].zero_()
        
        # 将输入张量中的每个整数标记替换为对应的向量嵌入
        return F.embedding(input, self.weight, self.padding_idx, self.max_norm, self.norm_type, self.scale_grad_by_freq, self.sparse)

相对位置编码

参数式训练会受到句子长度的影响,bert起初训练的句子最长为512,如果只训练到128长度的句子,那在128—512之间的位置参数就无法获得,所以必须要训练更长的预料来确定这一部分的参数

在NAZHA中,距离和维度都是用正弦函数导出来的,并且在模型训练期间也是固定的。

绝对位置编码需要固定长度,一般是512,所以适用于短的

在处理较短的序列和数据集上,绝对位置编码可能会更加适用。而在处理长序列和数据集上,相对位置编码则可能会更加有效。

参考

https://zhuanlan.zhihu.com/p/369012642

### 绝对位置编码的概念 绝对位置编码是一种用于表示序列中每个标记在其上下文中相对顺序的技术。在大型语言模型(LLM)中,这种技术对于捕获输入数据中的时间依赖性结构至关重要[^1]。由于神经网络本身无法天然理解序列的位置信息,因此引入了位置编码来增强模型的学习能力。 #### 实现细节 在实际应用中,绝对位置编码可以通过多种方式实现。一种常见的方式是通过正弦余弦函数生成固定的位置向量: ```python import torch import math def absolute_position_encoding(seq_len, d_model): pe = torch.zeros(seq_len, d_model) position = torch.arange(0, seq_len).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2) * -(math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) # 偶数索引 pe[:, 1::2] = torch.cos(position * div_term) # 奇数索引 return pe.unsqueeze(0) seq_length = 512 embedding_dim = 768 position_encodings = absolute_position_encoding(seq_length, embedding_dim) print(f"Position Encoding Shape: {position_encodings.shape}") ``` 上述代码片段展示了如何基于正弦余弦波形创建绝对位置编码矩阵。这种方法最初由 Vaswani 等人在 Transformer 模型中提出,并广泛应用于各种 LLM 的实现中。 #### 编码的作用 绝对位置编码的主要作用在于帮助模型区分不同位置上的相同单词或标记的意义差异。例如,在句子 “她喜欢苹果” “苹果喜欢她” 中,“苹果”的含义因位置而异。通过加入位置编码,模型可以更好地学习到这些细微差别并提高预测准确性。 #### 替代方法 尽管绝对位置编码非常有效,但它也有一些局限性,比如难以处理超出训练期间最大长度的新序列。为此,研究人员提出了其他变体,如可学习的位置嵌入或者相对位置编码等方案作为补充或替代选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值