精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入 精華

發布于 2025-3-10 00:00
瀏覽
0收藏

Transformer的關鍵組件之一是位置嵌入。你可能會問:為什么呢?因為Transformer中的自注意力機制是排列不變的;這意味著它計算輸入中每個標記從序列中其他標記接收的注意力程度,但它沒有考慮標記的順序。實際上,注意力機制將序列視為一個標記集合。因此,我們需要另一個稱為位置嵌入的組件,它可以考慮標記的順序,并對標記嵌入產生影響。

但是,位置嵌入有哪些不同類型,它們又是如何實現的呢?

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

在本文中,我們將研究三種主要的位置嵌入類型:絕對位置嵌入、相對位置嵌入和旋轉位置嵌入(RoPE),并深入探討它們的實現方式。

1. 背景

在自然語言處理(NLP)中,序列中單詞的順序對于理解語義非常重要,這對人類來說也是如此。如果順序混亂,語義就會完全改變。例如“Sam sits down on the mat”(山姆坐在墊子上)和“The mat sits down on Sam”(墊子坐在山姆身上),僅僅重新排列單詞順序,語義就完全不同了。

Transformer是許多現代NLP系統的核心,它并行處理所有單詞。這種并行處理發生在注意力機制中,在該機制中,模型計算每個標記從輸入上下文中其他標記接收的注意力分數。雖然并行處理本質上有利于提高效率,但它導致模型丟失了所有關于單詞順序的信息。因此,Transformer有一個額外的組件,即位置嵌入,它創建包含序列中標記位置或順序信息的向量。

位置嵌入有很多不同類型。三種主要的、廣為人知的類型是絕對位置嵌入、相對位置嵌入和旋轉位置嵌入(RoPE)。

2. 絕對位置嵌入

絕對位置嵌入就像是給句子中的每個標記分配一個唯一的編號。在實際操作中,我們為序列中的每個位置創建一個向量。在最簡單的情況下,每個標記的位置嵌入是一個獨熱向量,除了標記所在位置的索引處為1,其他位置均為0。然后,在將標記嵌入輸入到Transformer之前,我們將這些位置嵌入向量添加到標記嵌入中。

例如,在句子“I am a student”(我是一名學生)中,有4個標記。每個標記都有一個唯一的位置嵌入向量。假設嵌入維度為3,那么第一個標記“I”將得到獨熱編碼[1, 0, 0],第二個標記“am”將得到[0, 1, 0],依此類推。

雖然獨熱編碼是傳達位置嵌入概念的一種直接方法,但在實際中,有更好的方法來實現絕對位置嵌入。所有不同的實現方式都既簡單又有效,但它們在處理非常長的序列或比訓練時更長的序列時可能會遇到困難。

讓我們來看看這些實現方式。

2.1 實現方式

絕對位置嵌入的實現通常涉及創建一個大小為_vocabulary * embeddingdim_的查找表。這意味著詞匯表中的每個標記在查找表中都有一個條目,并且該條目的維度為_embeddingdim_。

絕對位置嵌入主要有兩種類型:

  • 學習型:在學習型方法中,嵌入向量在訓練過程中隨機初始化,然后進行訓練。原始的Transformer論文[5]以及像BERT、GPT和RoBERTa等流行模型都采用了這種方法。很快,我們將在代碼中看到這種方法的示例。這種方法的一個缺點是,它可能無法很好地泛化到比訓練時更長的序列,因為對于那些位置,查找表中不存在相應的條目。
  • 固定型:這種方法也稱為正弦位置編碼,在開創性的“Attention Is All You Need”論文[5]中被提出。該方法使用不同頻率的正弦和余弦函數為每個位置創建獨特的模式。這種編碼的公式如下:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

在上述公式中,是位置嵌入,是模型的維度,也稱為嵌入維度。基本上,位置為的位置嵌入向量,在偶數索引處由函數決定,在奇數索引處由函數決定。

這種方法的一個關鍵優點是它能夠外推到訓練期間未遇到的序列長度;這在處理不同的輸入大小方面提供了很大的靈活性。

無論采用哪種類型(學習型或固定型),一旦創建了絕對位置嵌入,就會將它們添加到標記嵌入中:

Final Embedding = Token Embedding + Positional Embedding

讓我們一起從RoBERTa模型的源代碼中查看學習型位置嵌入。代碼取自HuggingFace代碼庫。

class RobertaEmbeddings(nn.Module):
    # Copied from transformers.models.bert.modeling_bert.BertEmbeddings.__init__
    def __init__(self, config):
        super().__init__()
        self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)
        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 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
        self.dropout = nn.Dropout(config.hidden_dropout_prob)
        # position_ids (1, len position emb) is contiguous in memory and exported when serialized
        self.position_embedding_type = getattr(config, "position_embedding_type", "absolute")
        self.register_buffer(
            "position_ids", torch.arange(config.max_position_embeddings).expand((1, -1)), persistent=False
        )
        self.register_buffer(
            "token_type_ids", torch.zeros(self.position_ids.size(), dtype=torch.long), persistent=False
        )

        # End copy
        self.padding_idx = config.pad_token_id
        self.position_embeddings = nn.Embedding(
            config.max_position_embeddings, config.hidden_size, padding_idx=self.padding_idx
        )

    def forward(
        self, input_ids=None, token_type_ids=None, position_ids=None, inputs_embeds=None, past_key_values_length=0
    ):
        if position_ids isNone:
            if input_ids isnotNone:
                # Create the position ids from the input token ids. Any padded tokens remain padded.
                position_ids = create_position_ids_from_input_ids(input_ids, self.padding_idx, past_key_values_length)
            else:
                position_ids = self.create_position_ids_from_inputs_embeds(inputs_embeds)

        if input_ids isnotNone:
            input_shape = input_ids.size()
        else:
            input_shape = inputs_embeds.size()[:-1]

        seq_length = input_shape[1]

        # Setting the token_type_ids to the registered buffer in constructor where it is all zeros, which usually occurs
        # when its auto-generated, registered buffer helps users when tracing the model without passing token_type_ids, solves
        # issue #5664
        if token_type_ids isNone:
            if hasattr(self, "token_type_ids"):
                buffered_token_type_ids = self.token_type_ids[:, :seq_length]
                buffered_token_type_ids_expanded = buffered_token_type_ids.expand(input_shape[0], seq_length)
                token_type_ids = buffered_token_type_ids_expanded
            else:
                token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=self.position_ids.device)

        if inputs_embeds isNone:
            inputs_embeds = self.word_embeddings(input_ids)
        token_type_embeddings = self.token_type_embeddings(token_type_ids)

        embeddings = inputs_embeds + token_type_embeddings
        if self.position_embedding_type == "absolute":
            position_embeddings = self.position_embeddings(position_ids)
            embeddings += position_embeddings
        embeddings = self.LayerNorm(embeddings)
        embeddings = self.dropout(embeddings)
        return embeddings

注意在??__init__??方法中,以下這行代碼是如何用隨機值初始化學習型位置嵌入的:

self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)

然后在??forward??方法中,將位置嵌入添加到標記嵌入中:

if self.position_embedding_type == "absolute":
    position_embeddings = self.position_embeddings(position_ids)
    embeddings += position_embeddings

讓我們在文本輸入上一起運行這段代碼,看看結果:

from transformers import RobertaConfig

config = RobertaConfig()
print(config)

輸出:

RobertaConfig {
  "attention_probs_dropout_prob": 0.1,
"bos_token_id": 0,
"classifier_dropout": null,
"eos_token_id": 2,
"hidden_act": "gelu",
"hidden_dropout_prob": 0.1,
"hidden_size": 768,
"initializer_range": 0.02,
"intermediate_size": 3072,
"layer_norm_eps": 1e-12,
"max_position_embeddings": 512,
"model_type": "roberta",
"num_attention_heads": 12,
"num_hidden_layers": 12,
"pad_token_id": 1,
"position_embedding_type": "absolute",
"transformers_version": "4.31.0",
"type_vocab_size": 2,
"use_cache": true,
"vocab_size": 50265
}

正如你在上面打印的配置參數中看到的,我們有??"position_embedding_type": "absolute"???,并且上下文窗口長度為512:??"max_position_embeddings": 512???。讓我們獲取一個??RobertaEmbedding??對象:

emb = RobertaEmbeddings(config)
print(emb)

輸出:

RobertaEmbeddings(
  (word_embeddings): Embedding(50265, 768, padding_idx=1)
  (position_embeddings): Embedding(512, 768, padding_idx=1)
  (token_type_embeddings): Embedding(2, 768)
  (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
  (dropout): Dropout(p=0.1, inplace=False)
)

你可以看到上面的??RobertaEmbedding???層,有一個??(word_embeddings): Embedding(50265, 768, padding_idx=1)???,這是一個隨機初始化的嵌入矩陣,形狀為??50265*768??;這意味著詞匯表大小為50265,每個嵌入向量是768維的。

然后我們看到??(position_embeddings): Embedding(512, 768, padding_idx=1)???,這是位置嵌入向量,同樣是隨機初始化的,并且是768維向量。注意這個嵌入矩陣的大小是??512*768??,這表明我們只為512個位置提供位置嵌入。因此,如果在推理時出現長度超過512個標記的序列,我們將沒有為其學習到的位置嵌入!!這就是我們前面討論的學習型絕對位置嵌入的一個缺點。

讓我們取一個序列并將其輸入到嵌入層:

from transformers import RobertaTokenizer
# Initialize the tokenizer
tokenizer = RobertaTokenizer.from_pretrained("roberta-base")

sentence = "The quick brown fox jumps over the lazy dog."
# Tokenize the sentence
tokens = tokenizer.tokenize(sentence)
print(tokens)
# Get the input IDs
input_ids = tokenizer.encode(sentence, add_special_tokens=True)
print("\nInput IDs:", input_ids)

輸出:

['The', '?quick', '?brown', '?fox', '?jumps', '?over', '?the', '?lazy', '?dog', '.']
Input IDs: [0, 133, 2119, 6219, 23602, 13855, 81, 5, 22414, 2335, 4, 2]

注意這個序列有12個標記。我們將其輸入到嵌入層:

input_tensor = torch.tensor(input_ids).reshape((1,-1))
emb(input_ids=input_tensor)

輸出:

tensor([[[-0.7226, -2.3475, -0.5119,  ..., -1.3224, -0.0000, -0.9497],
         [-0.4094,  0.7778,  1.8330,  ...,  0.1183, -0.3897, -1.8805],
         [-0.7342, -1.6158,  0.2465,  ..., -0.0000, -1.4895, -0.8259],
         ...,
         [-0.2884, -3.0506,  0.6108,  ...,  0.8692,  0.9901,  0.6638],
         [ 0.6423, -2.1128,  1.2056,  ...,  0.2799,  0.5368, -1.0147],
         [-0.4305, -0.4462, -1.2317,  ...,  0.4016,  1.8494, -0.2363]]],
       grad_fn=<MulBackward0>)

輸出張量是從相應嵌入矩陣中檢索到的標記嵌入和位置嵌入的總和。

3. 相對位置嵌入

相對位置嵌入關注序列中標記之間的距離關系,而不考慮標記的具體位置。

3.1 通俗解釋

考慮句子“I am a student”(我是一名學生)。“I”的精確位置是1,“student”的精確位置是4。這些是標記的絕對位置。相對位置嵌入不考慮這些,它只考慮“I”與“student”的距離是3,與“am”的距離是1。

相對位置嵌入在處理較長序列時具有優勢,并且對訓練期間未見過的序列長度具有更好的泛化能力。我們很快就會看到原因。

一些使用相對位置嵌入的著名模型有Transformer-XL [1]、T5(文本到文本轉移Transformer)[2]、DeBERTa(具有解耦注意力的解碼增強BERT)[3]和帶有相對位置嵌入的BERT [4]。你可以隨意閱讀這些論文,了解它們是如何實現相對位置嵌入的。

3.2 技術解釋

首先,與將位置嵌入添加到標記嵌入的絕對位置嵌入不同,相對位置嵌入創建表示標記之間相對距離的矩陣。例如,如果標記i在位置2,標記j在位置5,相對位置就是??j - i = 3??。

然后,相對位置嵌入修改注意力分數,以包含關于相對位置的信息。如你所知,在自注意力機制中,注意力分數是在標記對之間計算的。因此,相對位置嵌入根據相對位置添加一個偏差項到注意力分數中,或者為每個可能的相對距離合并一個可學習的嵌入。

這種方法的一種常見實現是在注意力分數上添加一個相對位置偏差。如果A是注意力分數矩陣,添加一個相對位置偏差矩陣B:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

3.3 代碼示例:Transformer-XL的實現

下面是一個在PyTorch中實現相對位置嵌入的簡單代碼,該實現與Transformer-XL的實現方式相近。

import torch
import torch.nn as nn

class RelativePositionalEmbedding(nn.Module):
    def __init__(self, max_len, d_model):
        super(RelativePositionalEmbedding, self).__init__()
        self.max_len = max_len
        self.d_model = d_model
        self.relative_embeddings = nn.Embedding(2 * max_len - 1, d_model)

    def forward(self, seq_len):
        # 生成相對位置
        range_vec = torch.arange(seq_len)
        range_mat = range_vec[None, :] - range_vec[:, None]
        clipped_mat = torch.clamp(range_mat, -self.max_len + 1, self.max_len - 1)
        relative_positions = clipped_mat + self.max_len - 1
        return self.relative_embeddings(relative_positions)


class RelativeSelfAttention(nn.Module):
    def __init__(self, d_model, num_heads, max_len):
        super(RelativeSelfAttention, self).__init__()
        self.num_heads = num_heads
        self.d_k = d_model // num_heads
        self.query = nn.Linear(d_model, d_model)
        self.key = nn.Linear(d_model, d_model)
        self.value = nn.Linear(d_model, d_model)
        self.relative_pos_embedding = RelativePositionalEmbedding(max_len, d_model)
        self.softmax = nn.Softmax(dim=-1)

    def forward(self, x):
        batch_size, seq_len, d_model = x.size()
        Q = self.query(x).view(batch_size, seq_len, self.num_heads, self.d_k)
        K = self.key(x).view(batch_size, seq_len, self.num_heads, self.d_k)
        V = self.value(x).view(batch_size, seq_len, self.num_heads, self.d_k)

        # 計算標準注意力分數
        scores = torch.einsum('bnqd,bnkd->bnqk', Q, K) / (self.d_k ** 0.5)

        # 獲取相對位置嵌入
        rel_pos_embeddings = self.relative_pos_embedding(seq_len)
        rel_scores = torch.einsum('bnqd,rlkd->bnqk', Q, rel_pos_embeddings)

        # 添加相對位置分數
        scores += rel_scores
        attn_weights = self.softmax(scores)

        # 計算最終輸出
        output = torch.einsum('bnqk,bnvd->bnqd', attn_weights, V).contiguous()
        output = output.view(batch_size, seq_len, d_model)
        return output

我們可以使用以下參數調用它:

seq_len = 10
d_model = 512
num_heads = 8
max_len = 20
x = torch.randn(32, seq_len, d_model)  # 序列批次
attention = RelativeSelfAttention(d_model, num_heads, max_len)
output = attention(x)

注意,??seq_len???(序列長度)指的是特定批次中輸入序列的實際長度,每個批次的??seq_len??會有所不同。

然而,??max_len???(最大長度)是一個預定義的值,表示模型將考慮的最大相對位置距離。這個值決定了模型將為哪些相對位置學習嵌入。如果??max_len??設置為20,模型將為從 -19到19的相對位置學習嵌入。

請注意,這就是為什么??self.relative_embeddings = nn.Embedding(2 * max_len - 1, d_model)???設置為這個大小,以適應??max_len??定義范圍內的所有可能相對位置。

現在,讓我們解釋一下代碼:

第一個類如下,它為??2 * max_len - 1???的大小創建一個可學習的嵌入矩陣。在??forward???函數中,對于給定的序列,它從??relative_embeddings??矩陣中檢索相應的嵌入。

class RelativePositionalEmbedding(nn.Module):
    def __init__(self, max_len, d_model):
        super(RelativePositionalEmbedding, self).__init__()
        self.max_len = max_len
        self.d_model = d_model
        self.relative_embeddings = nn.Embedding(2 * max_len - 1, d_model)

    def forward(self, seq_len):
        # 生成相對位置
        range_vec = torch.arange(seq_len)
        range_mat = range_vec[None, :] - range_vec[:, None]
        clipped_mat = torch.clamp(range_mat, -self.max_len + 1, self.max_len - 1)
        relative_positions = clipped_mat + self.max_len - 1
        return self.relative_embeddings(relative_positions)

第二個類(如下)接收一個序列(即??x???),并計算查詢、鍵和值矩陣。注意,每個注意力頭都有自己的Q、K和V,這就是為什么所有這些矩陣的形狀都是??(batch_size, seq_len, self.num_heads, self.d_k)??。

class RelativeSelfAttention(nn.Module):
    def __init__(self, d_model, num_heads, max_len):
        super(RelativeSelfAttention, self).__init__()
        self.num_heads = num_heads
        self.d_k = d_model // num_heads
        self.query = nn.Linear(d_model, d_model)
        self.key = nn.Linear(d_model, d_model)
        self.value = nn.Linear(d_model, d_model)
        self.relative_pos_embedding = RelativePositionalEmbedding(max_len, self.d_k)
        self.softmax = nn.Softmax(dim=-1)

    def forward(self, x):
        batch_size, seq_len, d_model = x.size()
        Q = self.query(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)
        K = self.key(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)
        V = self.value(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2)

        # 計算標準注意力分數
        scores = torch.einsum('bhqd,bhkd->bhqk', Q, K) / (self.d_k ** 0.5)

        # 獲取相對位置嵌入
        rel_pos_embeddings = self.relative_pos_embedding(seq_len)  # (seq_len, seq_len, d_k)
        rel_pos_embeddings = rel_pos_embeddings.transpose(0, 2).transpose(1, 2)  # (d_k, seq_len, seq_len)
        rel_scores = torch.einsum('bhqd,dqk->bhqk', Q, rel_pos_embeddings)

        # 添加相對位置分數
        scores += rel_scores
        attn_weights = self.softmax(scores)

        # 計算最終輸出
        output = torch.einsum('bhqk,bhvd->bhqd', attn_weights, V).contiguous()
        output = output.transpose(1, 2).reshape(batch_size, seq_len, d_model)
        return output

這行??scores = torch.einsum('bhqd,bhkd->bhqk', Q, K) / (self.d_k ** 0.5)???是一種強大的符號表示,用于簡潔地指定復雜的張量運算。在這個上下文中,它用于計算查詢向量和鍵向量之間的點積。??'bhqd,bhkd->bhqk'??這個公式可以解釋如下:

  • ??b??:批次大小。
  • ??h??:注意力頭的數量。
  • ??q??:查詢序列長度。
  • ??k??:鍵序列長度(在自注意力中通常與查詢序列長度相同)。
  • ??d???:每個頭的深度(即??self.d_k??)。

??einsum???符號??'bhqd,bhkd->bhqk'??指定在保持其他維度不變的情況下,計算Q和K的最后一個維度之間的點積。

下一行??rel_pos_embeddings = self.relative_pos_embedding(seq_len)???檢索序列中所有現有相對距離的相對位置嵌入,這就是為什么它的形狀是??(seq_len, seq_len, d_k)???。然后我們對其進行轉置,將形狀變為??(d_k, seq_len, seq_len)???。下一行??rel_scores = torch.einsum('bhqd,dqk->bhqk', Q, rel_pos_embeddings)??計算相對位置嵌入在自注意力機制中對注意力分數的貢獻。這就是我們前面看到的公式中的相對位置偏差矩陣B。

最后,我們將矩陣B添加到原始注意力分數中:

# 添加相對位置分數
scores += rel_scores
attn_weights = self.softmax(scores)

并與值矩陣V相乘得到輸出:

# 計算最終輸出
output = torch.einsum('bhqk,bhvd->bhqd', attn_weights, V).contiguous()
output = output.transpose(1, 2).reshape(batch_size, seq_len, d_model)
return output

4. 旋轉位置嵌入

旋轉位置嵌入,通常稱為RoPE(Rotary Position Embedding),是一種巧妙的方法,結合了絕對位置嵌入和相對位置嵌入的一些優點。這種方法在Roformer論文中被提出。

4.1 通俗解釋

RoPE的核心思想是通過在高維空間中旋轉詞向量來編碼位置信息。旋轉的幅度取決于單詞或標記在序列中的位置。

這種旋轉具有一個很好的數學特性:任意兩個單詞之間的相對位置可以通過一個單詞的向量相對于另一個單詞的向量旋轉了多少來輕松計算。因此,雖然每個單詞根據其絕對位置獲得唯一的旋轉,但模型也可以很容易地確定相對位置。

RoPE有幾個優點:它比絕對位置嵌入更有效地處理更長的序列。它自然地結合了絕對位置信息和相對位置信息。而且正如我們后面將看到的,它在計算上效率高且易于實現。

4.2 技術解釋

給定一個標記嵌入和該標記的位置,絕對位置嵌入計算一個位置嵌入并將其添加到標記嵌入中:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

然而,在旋轉位置嵌入中,給定一個標記嵌入和它的位置,它會生成一個新的嵌入,其中包含位置信息:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

讓我們看看這是如何計算的:

給定一個標記,RoPE根據其在序列中的位置對其相應的鍵向量和查詢向量應用旋轉。這種旋轉是通過將向量與一個旋轉矩陣相乘來實現的。然后,旋轉后的鍵向量和查詢向量以通常的方式(點積后接softmax)用于計算注意力分數,Transformer中的其余計算照常進行。

讓我們看看什么是旋轉矩陣,以及它是如何應用到查詢向量和鍵向量上的。

旋轉矩陣:二維空間(最簡單的情況)中的旋轉矩陣如下,其中是任意角度:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

如果你將上述矩陣與二維向量相乘,它只會改變向量的角度,而保持向量的長度不變。你同意嗎?

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

我們可以看到旋轉后向量的范數與原始向量相同。讓我們來算一下:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

現在,它是如何應用到鍵向量和查詢向量上的呢?

注意,查詢向量是查詢矩陣和標記嵌入的乘積,即:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

現在如果我們對其應用旋轉矩陣,我們就是在旋轉查詢向量。

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

但是,它究竟是如何包含位置信息的呢?

問得好。在上述所有數學運算中,我們假設標記出現在位置1!如果它出現在任意位置,那么旋轉矩陣中將包含:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

4.3 相對性的數學證明

現在,讓我們證明旋轉位置嵌入(RoPE)是相對的。為此,我們需要證明兩個標記之間的注意力分數僅取決于它們的相對位置,而不是絕對位置。

  • 我們將RoPE操作定義如下:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

  • 考慮兩個位于位置和的標記:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

  • 我們將注意力分數計算為它們的點積:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

讓我們如下展開:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

  • 旋轉矩陣具有這樣一個很好的性質:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

  • 因此,注意力分數變為:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

如你所見,分數是相對位置的函數,即和之間位置的差值。

4.4 高維旋轉矩陣

通常情況下,模型的嵌入維度不是2,通常比2大得多。那么旋轉矩陣會如何變化呢?Roformer論文的作者提出了以下組合方式:

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

也就是說,對于位置和嵌入維度,旋轉矩陣由個2×2的旋轉矩陣組成。值得一提的是,由于這種構造是稀疏的,相關研究人員推薦了一種計算效率高的方法來計算它與標記嵌入向量的乘積。

深度解析理解 Transformer 中的3大位置嵌入:從絕對位置嵌入到旋轉位置嵌入-AI.x社區

4.5 代碼片段:Roformer的實現

旋轉位置嵌入(RoPE)的代碼實現相當復雜,但本次重點介紹負責計算RoPE的核心功能,它封裝在以下方法中:

def apply_rotary_position_embeddings(sinusoidal_pos, query_layer, key_layer, value_layer=None):
    # https://kexue.fm/archives/8265
    # sin [batch_size, num_heads, sequence_length, embed_size_per_head//2]
    # cos [batch_size, num_heads, sequence_length, embed_size_per_head//2]
    sin, cos = sinusoidal_pos.chunk(2, dim=-1)
    # sin [θ0,θ1,θ2......θd/2-1] -> sin_pos [θ0,θ0,θ1,θ1,θ2,θ2......θd/2-1,θd/2-1]
    sin_pos = torch.stack([sin, sin], dim=-1).reshape_as(sinusoidal_pos)
    # cos [θ0,θ1,θ2......θd/2-1] -> cos_pos [θ0,θ0,θ1,θ1,θ2,θ2......θd/2-1,θd/2-1]
    cos_pos = torch.stack([cos, cos], dim=-1).reshape_as(sinusoidal_pos)
    # rotate_half_query_layer [-q1,q0,-q3,q2......,-qd-1,qd-2]
    rotate_half_query_layer = torch.stack([-```python
    rotate_half_query_layer = torch.stack([-query_layer[..., 1::2], query_layer[..., ::2]], dim=-1).reshape_as(
        query_layer
    )
    query_layer = query_layer * cos_pos + rotate_half_query_layer * sin_pos
    # rotate_half_key_layer [-k1,k0,-k3,k2......,-kd-1,kd-2]
    rotate_half_key_layer = torch.stack([-key_layer[..., 1::2], key_layer[..., ::2]], dim=-1).reshape_as(key_layer)
    key_layer = key_layer * cos_pos + rotate_half_key_layer * sin_pos
    if value_layer isnotNone:
        # rotate_half_value_layer [-v1,v0,-v3,v2......,-vd-1,vd-2]
        rotate_half_value_layer = torch.stack([-value_layer[..., 1::2], value_layer[..., ::2]], dim=-1).reshape_as(
            value_layer
        )
        value_layer = value_layer * cos_pos + rotate_half_value_layer * sin_pos
        return query_layer, key_layer, value_layer
    return query_layer, key_layer

注意,??query_layer = query_layer * cos_pos + rotate_half_query_layer * sin_pos??這一行代碼是根據上一節提到的高效計算方法進行運算的。

結論

在本文中,本文回顧了三種主要的位置嵌入類型:絕對位置嵌入、相對位置嵌入和旋轉位置嵌入。絕對位置嵌入提供了一種直接的位置信息編碼方式,有學習型和固定型兩種方法。相對位置嵌入側重于標記之間的相對距離,這種方法被應用于像Transformer-XL和DeBERTa等模型中。最后,創新的旋轉位置嵌入(RoPE)結合了絕對位置嵌入和相對位置嵌入的優點,為位置信息編碼提供了一種更高效、可擴展的解決方案。

本文轉載自??智駐未來??,作者:小智

收藏
回復
舉報
回復
相關推薦
美女视频一区| 精品美女视频在线观看免费软件| 亚洲综合中文| 日韩精品影音先锋| 欧美日韩黄色一级片| 美女做暖暖视频免费在线观看全部网址91| 视频一区二区中文字幕| 久久久精品视频在线观看| 黑森林av导航| www.26天天久久天堂| 伊人色综合久久天天人手人婷| 久久99精品久久久久子伦| 一级黄色短视频| 99av国产精品欲麻豆| www.日韩不卡电影av| bl动漫在线观看| 亚洲日韩中文字幕一区| 午夜激情久久久| 小说区视频区图片区| 少妇性bbb搡bbb爽爽爽欧美| 精彩视频一区二区| 国产成人精品久久| 精品一级少妇久久久久久久| 久久影院一区| 亚洲视频在线视频| 国产一卡二卡三卡四卡| 91国产精品| 在线视频综合导航| 人人妻人人添人人爽欧美一区| 黄网站免费在线观看| 久久精品夜色噜噜亚洲aⅴ| 高清视频在线观看一区| 最新在线中文字幕| 亚洲女同同性videoxma| 欧美老少做受xxxx高潮| 国产精品1区2区3区4区| 最新亚洲精品| 亚洲精品久久久一区二区三区 | 中文天堂资源在线| 国产毛片精品| 欧美成人精品3d动漫h| 亚洲一级免费在线观看| 日韩三区免费| 91久久香蕉国产日韩欧美9色| 色综合久久久久无码专区| 青草影视电视剧免费播放在线观看| 国产精品久久久久9999吃药| 婷婷四房综合激情五月| 国产一区电影| 欧美高清在线精品一区| 四虎永久国产精品| 岛国大片在线观看| 中文av一区二区| 色综合久久久久久久久五月| shkd中文字幕久久在线观看| 国产欧美日本一区视频| 亚洲高清在线观看一区| 超碰在线国产| 国产欧美久久久精品影院| 日本高清视频一区二区三区| 国产一区二区三区不卡在线| 国产女主播视频一区二区| 日本一区二区三区免费观看| 北条麻妃在线| 亚洲视频综合在线| 麻豆映画在线观看| 999福利在线视频| 激情成人在线视频| 日本一本二本在线观看| 手机看片久久| 欧美日韩国产综合草草| 色18美女社区| 大奶在线精品| 国产丝袜一区视频在线观看| 黄色三级生活片| 国产精品7m凸凹视频分类| 久久九九国产精品怡红院| 精品国产欧美日韩不卡在线观看| 欧美在线91| 97精品视频在线观看| 五月婷婷视频在线| 免费日本视频一区| 亚洲一区二区三区乱码aⅴ蜜桃女| www黄色网址| 91一区二区在线观看| 色综合电影网| 蜜臀av在线播放| 日韩欧美福利视频| 污污网站在线观看视频| 国产精品国产| 一区二区三区黄色| 国产十六处破外女视频| 国产精品女主播一区二区三区| 欧洲成人午夜免费大片| 国产又粗又猛又爽又黄91| av中文字幕不卡| 亚洲一区二区三区精品在线观看 | 国产成人精品999| 国产女人高潮毛片| 91美女蜜桃在线| 一本色道久久综合亚洲二区三区| 欧美人与性动交α欧美精品图片| 精品日韩美女的视频高清| 国产高清视频网站| 久久365资源| 色噜噜亚洲精品中文字幕| 国产一级视频在线播放| 日韩不卡免费视频| 国产精品9999久久久久仙踪林| 精品电影在线| 亚洲宅男天堂在线观看无病毒| 老熟妇仑乱视频一区二区| 欧一区二区三区| 一区二区福利视频| 国产情侣自拍av| 国产成人综合视频| 视频一区二区综合| 538在线观看| 69av一区二区三区| 欧美日韩高清丝袜| 亚洲激情社区| 亚洲xxx自由成熟| 色欧美激情视频在线| 精品福利在线视频| 久久久无码人妻精品无码| 日本激情一区| 国产精品成人品| 五十路在线观看| 一区二区三区美女| www.精品在线| 精品一区av| 日本久久久久久| 亚洲欧洲综合在线| 午夜精品爽啪视频| 黄色性视频网站| 欧美久久久久| 91国产在线播放| 精品黄色免费中文电影在线播放| 在线看日韩精品电影| 亚洲最大成人网站| 99在线观看免费视频精品观看| 懂色av一区二区三区在线播放| 超鹏97在线| 91.麻豆视频| 久草福利资源在线| 老司机免费视频一区二区三区| 日韩一区二区三区资源| 欧美无毛视频| 亚洲网站在线播放| 无码人妻精品一区二区蜜桃色欲| 26uuu精品一区二区在线观看| av高清在线免费观看| 高清一区二区三区| 性欧美视频videos6一9| 三级网站免费观看| 精品久久久久久久久久久久久久| 大乳护士喂奶hd| 免费看的黄色欧美网站| 日本高清久久一区二区三区| 国产精品传媒麻豆hd| 日韩在线精品一区| 国产麻豆免费视频| 依依成人精品视频| 久久久高清视频| 亚洲影院在线| 午夜精品一区二区三区在线观看| 成人全视频免费观看在线看| 亚洲欧洲免费视频| 中文字幕自拍偷拍| 亚洲精品国产无套在线观| 免费黄视频在线观看| 亚洲精品看片| 日韩不卡av| 蜜桃精品视频| 性欧美亚洲xxxx乳在线观看| 裸体xxxx视频在线| 欧美精品第1页| 久久久无码精品亚洲国产| k8久久久一区二区三区 | 一级做a爰片久久| 日韩影片在线观看| 91高清视频免费观看| 番号集在线观看| 91精品国产91久久久久久最新毛片| 欧美日韩三级在线观看| 91蝌蚪porny九色| 亚洲国产视频直播| 99热在线这里只有精品| 国产一区二区三区日韩精品| 成人精品网站在线观看| 国产一线二线在线观看| 亚洲片在线资源| 成人高潮片免费视频| 欧美日韩国产丝袜另类| 中文字幕第69页| 丁香激情综合国产| 乌克兰美女av| 亚洲图片在线| 一区二区日本| 欧美成人一区在线观看| 91精品美女在线| 精品国产免费人成网站| 久青草国产97香蕉在线视频| 亚洲人成色777777精品音频| 777奇米成人网| 久久99国产综合精品免费| 中文字幕一区二区三区四区| 一区二区三区免费在线观看视频 | 亚洲va久久久噜噜噜无码久久| 粉嫩av一区二区三区免费野| 欧美日韩午夜视频| 国产亚洲一区字幕| 免费日本黄色网址| 国产一区二区三区香蕉| 男人天堂网视频| 黄色亚洲大片免费在线观看| 最新不卡av| 欧美手机在线| 欧美日韩亚洲在线| 97青娱国产盛宴精品视频| 国产欧美一区二区| 日韩毛片免费观看| 777国产偷窥盗摄精品视频| 91精品久久| 日韩在线播放av| 大片免费播放在线视频| 日韩精品视频在线播放| 亚洲国产精品久久久久爰性色 | 精品国产一区二区三区| 国产精品视频在线免费观看| 国产电影一区| 国产欧美日韩精品在线观看| 超碰一区二区| 91高清视频免费| 精品三级久久| 91国产美女在线观看| 国产三线在线| 久久久女人电视剧免费播放下载| 国产1区在线| 欧美成人激情视频免费观看| 欧美日本一道| 久久韩剧网电视剧| 免费超碰在线| 久久精品国产欧美亚洲人人爽| 9色在线视频| 中文字幕精品网| 98在线视频| 久久久www成人免费精品张筱雨| 99视频在线观看地址| 一区二区三区国产视频| 97超碰人人在线| 日韩最新在线视频| 久久bbxx| 久久夜色精品国产| 18网站在线观看| 久久久久久久国产精品视频| 91福利在线尤物| 91精品国产色综合| 波多视频一区| 国产精品扒开腿做爽爽爽的视频| 丁香六月综合| 国产精品老牛影院在线观看| 色综合视频一区二区三区日韩| 91精品免费视频| 亚洲青青久久| 都市激情久久久久久久久久久| 都市激情亚洲欧美| 久久综合婷婷综合| 日韩国产一区| 国产精品久久久影院| 欧美日韩综合| a√天堂在线观看| 男人的j进女人的j一区| 999在线精品视频| 成人一区二区在线观看| 国产精品无码午夜福利| 国产欧美日产一区| 欧美黑人精品一区二区不卡| 五月婷婷综合在线| 综合久久中文字幕| 欧美成人一区二区| 欧美日韩在线精品一区二区三区激情综 | 天天操天天干天天做| 国产高清不卡二三区| 黄色网址在线视频| 国产精品久久毛片av大全日韩| 欧美日韩精品在线观看视频 | 偷拍自拍在线视频| 中文字幕av一区| 欧美高清另类hdvideosexjaⅴ| 911国产网站尤物在线观看| 国产激情欧美| 国产伦理一区二区三区| 欧美三级美国一级| 国产乱人伦精品一区二区三区| 久久国产欧美| 欧美日韩一区二区区| 国产三级欧美三级日产三级99| 国产va在线播放| 色婷婷av一区二区三区大白胸| 99热这里只有精品1| 亚洲乱码av中文一区二区| 成人福利片网站| 欧美亚洲国产视频小说| 精品视频成人| 日韩影视精品| 另类av一区二区| 精品国产乱码久久久久夜深人妻| 中文字幕欧美国产| 一级免费在线观看| 日韩欧美中文一区| 91在线导航| 欧洲美女7788成人免费视频| 视频二区欧美毛片免费观看| 亚洲v日韩v欧美v综合| 国产欧美精品久久| 中文字幕永久免费| 亚洲女与黑人做爰| 一区二区视频在线免费观看| 日韩黄在线观看| av影片在线| a级国产乱理论片在线观看99| 日韩欧美视频| 丁香婷婷激情网| 91啪九色porn原创视频在线观看| 久久久久久国产精品免费播放| 欧美乱妇15p| 色影视在线观看| 国产精品欧美日韩久久| 国产一区二区三区探花 | 美女一区二区三区| 韩国三级hd中文字幕| 精品久久香蕉国产线看观看gif| www.五月婷婷| 欧美俄罗斯性视频| 日韩激情欧美| 国产专区在线视频| 国产精品一区二区视频| 91麻豆精品成人一区二区| 欧美日韩国产精品自在自线| a天堂在线资源| 国产精品欧美激情| 99热在线成人| 想看黄色一级片| 亚洲精品日韩一| 亚洲av无码乱码国产精品| 欧美俄罗斯乱妇| 成人看片黄a免费看视频| 欧美黄色免费网址| 北条麻妃一区二区三区| www.av视频在线观看| 亚洲精品一区二区三区影院| 超级碰碰不卡在线视频| 国产一区不卡在线观看| 日韩视频在线一区二区三区 | 99久久综合狠狠综合久久aⅴ| 2025韩国理伦片在线观看| 国产精品国产成人国产三级| 国产又粗又大又爽视频| 欧美成人午夜激情在线| 99re91这里只有精品| 亚洲熟妇无码一区二区三区导航| 99久久久精品免费观看国产蜜| 欧美精品一二三四区| 国产一区二区三区在线视频 | 日韩电影一区二区三区四区| 影音先锋制服丝袜| 欧美日韩国产中文| 欧美女同一区| 蜜桃视频日韩| 韩国av一区二区三区| 一级aaa毛片| 亚洲视频一区二区| www欧美在线观看| 黄色大片中文字幕| 国产免费观看久久| 国产夫妻在线观看| 2025国产精品视频| 凹凸成人精品亚洲精品密奴| 小日子的在线观看免费第8集| 一区二区三区四区视频精品免费 | 国产三级一区二区三区| 国产特级黄色片| 2019亚洲男人天堂| 97久久夜色精品国产| 美女搡bbb又爽又猛又黄www| 一本色道综合亚洲| 国产黄色在线网站| 久久狠狠久久综合桃花| 久久99蜜桃精品| 免费在线观看黄网站| 自拍偷拍亚洲欧美| 欧美顶级毛片在线播放| 日本久久久久久久久久久久| 艳妇臀荡乳欲伦亚洲一区| 免费在线看v| 99re国产在线播放| 秋霞午夜av一区二区三区| 欧美一级高潮片| xxx一区二区|