精品欧美一区二区三区在线观看 _久久久久国色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最新在线视频| 五月天婷婷综合网| 久草综合在线| 亚洲精品一二三| 久久精品国产精品国产精品污| 国产成人无码精品久久久久| 精品美女在线视频| 欧美一级午夜免费电影| 国产午夜福利100集发布| 五十路在线视频| 蓝色福利精品导航| 久久久亚洲福利精品午夜| 亚洲一级中文字幕| 视频国产精品| 欧美优质美女网站| 黄页网站在线观看视频| 成人18在线| 成人激情动漫在线观看| 国产精品久久久久影院日本| 久草视频在线资源| 日韩欧美1区| 日韩麻豆第一页| 国产a级片视频| 久久久久久久性潮| 欧美日韩亚洲精品一区二区三区| 国产91av视频在线观看| 日av在线播放| 成人免费毛片片v| 成人久久一区二区三区| 乱子伦一区二区三区| 激情欧美一区二区三区| 色香阁99久久精品久久久| 加勒比精品视频| 2021年精品国产福利在线| 欧美午夜片在线看| 久久婷婷国产精品| 麻豆视频在线看| 香蕉乱码成人久久天堂爱免费| 一区二区免费在线观看| 青青九九免费视频在线| 成人aa视频在线观看| 亚洲自拍偷拍福利| 在线免费观看视频网站| 日日摸夜夜添夜夜添精品视频| 97超级碰碰碰久久久| 久久免费小视频| 综合日韩在线| 九九精品在线观看| 99久久婷婷国产综合| 亚洲欧美日韩高清在线| 久久综合免费视频| 国产一区二区三区在线视频观看| 欧美一级本道电影免费专区| 亚洲欧美国产精品| 超碰97人人干| 国产a久久精品一区二区三区 | 三级黄色片免费看| 日韩专区视频网站| 91精品国产综合久久香蕉的特点| 色综合色综合色综合色综合| a成人v在线| 欧美日韩免费不卡视频一区二区三区| 香蕉视频禁止18| 国产精品天堂蜜av在线播放| 欧美精品在线一区二区三区| 国产福利精品一区二区三区| 日本一区影院| 亚洲成人av片| 亚洲色成人网站www永久四虎 | 国产女主播喷水视频在线观看 | 国产美女福利视频| 欧美伊人影院| 国产69精品99久久久久久宅男| 国产精品第72页| 久久精品中文| 成人午夜黄色影院| 欧美自拍偷拍一区二区| 91在线一区二区三区| 欧美一区免费视频| 午夜激情视频在线观看| 亚洲欧美成aⅴ人在线观看| 中国丰满熟妇xxxx性| 国产精欧美一区二区三区蓝颜男同| 色综合视频在线观看| 高潮一区二区三区| 超碰97久久| 一道本无吗dⅴd在线播放一区 | 成人网欧美在线视频| 内射无码专区久久亚洲| 久久久精品综合| 色撸撸在线观看| 新版的欧美在线视频| 欧美三片在线视频观看| 亚洲精品成人无码毛片| 国产精品片aa在线观看| 美女视频黄免费的亚洲男人天堂| 久久久午夜影院| 久久激情综合网| 久久久福利视频| 国产三级在线播放| 色综合久久综合| 国产老头和老头xxxx×| 欧美美乳视频| 久久久视频精品| 一区二区三区黄色片| 99久精品国产| 好吊色视频988gao在线观看| 久久久成人av毛片免费观看| 欧美tickling挠脚心丨vk| 中文字幕第24页| 国产精品久久久免费| 亚洲综合在线小说| 成人av一区| 一本大道综合伊人精品热热| 国产精品中文久久久久久| 激情综合网站| 亚州国产精品久久久| 国产欧美久久久| 日本一区二区成人在线| 自慰无码一区二区三区| 综合激情久久| 欧美精品日韩三级| 一起草av在线| 欧美国产精品v| 韩国日本在线视频| 任你弄精品视频免费观看| 久久99久久亚洲国产| 91丨九色丨丰满| 国产欧美日韩精品a在线观看| 免费一级特黄特色毛片久久看| 日韩专区视频| 午夜亚洲视频| 欧美成年人网站| 一级片视频网站| 久久天天做天天爱综合色| 国产3p露脸普通话对白| 亚洲精品18| 美日韩精品免费视频| 国产又大又黄又爽| 国产日韩欧美a| 99视频精品免费| 久久97视频| 国产91精品在线播放| 天堂av电影在线观看| 天天操天天色综合| 第四色在线视频| 亚洲精选在线| 老司机精品福利在线观看| 在线看的毛片| 亚洲日韩中文字幕| 成人黄色片在线观看| 国产女同互慰高潮91漫画| 国产精品人人爽人人爽| 大片网站久久| 91久久精品在线| wwwav在线| 精品乱码亚洲一区二区不卡| 久久精品国产亚洲av高清色欲 | 国产欧美亚洲视频| 麻豆视频在线观看免费| 51精品视频一区二区三区| 国产一二三区精品| 丁香啪啪综合成人亚洲小说 | 国产一区不卡视频| 国产人妻人伦精品| 久久午夜影院| 国产成人精品免高潮费视频| 福利视频在线导航| 欧美日韩高清在线| 激情四射综合网| 99riav久久精品riav| 欧美xxxxx在线视频| 操欧美老女人| aa成人免费视频| 成人教育av| 色七七影院综合| 亚洲精选一区二区三区| 欧美午夜美女看片| 五月天免费网站| 成人激情小说乱人伦| 欧美日韩在线成人| 欧美福利电影在线观看| 精品蜜桃一区二区三区| 欧美少妇激情| 久久久久久免费精品| 久久经典视频| 日韩一区二区三区四区五区六区| 国产精品日日夜夜| 国产欧美日韩精品一区| 久久国产免费视频| 日韩一区精品字幕| 大荫蒂性生交片| 成人羞羞网站入口免费| 官网99热精品| 精品女同一区二区三区在线观看| 欧美激情乱人伦| avtt在线播放| 亚洲国产精品人人爽夜夜爽| 中文字幕资源网| 午夜视频一区在线观看| 亚洲熟女毛茸茸| 久久蜜桃一区二区| 亚洲av无码成人精品区| 蜜桃视频免费观看一区| 男人添女人下面高潮视频| 国产精品久久久久久影院8一贰佰 国产精品久久久久久麻豆一区软件 | 亚洲影院色无极综合| 欧美magnet| 欧美极品在线播放| 日本免费视频在线观看| 亚洲女同性videos| 亚洲欧美另类综合| 欧美日韩免费观看一区三区| 天天操夜夜操视频| 亚洲一区二区四区蜜桃| 国产在线免费看| 国产欧美日韩视频在线观看| 国产精品无码在线| 成人综合婷婷国产精品久久| 男生操女生视频在线观看| 日韩福利视频网| 91专区在线观看| 欧美午夜a级限制福利片| 亚洲精品一区二区三区av| 亚洲影院天堂中文av色| 国产日韩欧美精品| 9l视频自拍蝌蚪9l视频成人| 91精品啪在线观看麻豆免费| 成人在线不卡| 国产精品久久久久久五月尺| 自拍视频在线看| 18久久久久久| 国产美女精品写真福利视频| 久久久久久久久国产精品| 国产超级va在线视频| 久久激情视频免费观看| 中文字幕日本在线观看| 中文字幕一区电影| 永久免费av在线| www.久久久久| 快射视频在线观看| 久久伊人精品一区二区三区| 里番在线观看网站| 日韩午夜在线视频| 麻豆传媒在线完整视频| 久久手机免费视频| av香蕉成人| 欧美大片在线看免费观看| 国产激情视频在线观看| 色与欲影视天天看综合网| 神马午夜伦理不卡| 久久久噜噜噜久久久| 高清毛片在线观看| 91国内在线视频| 日本免费久久| 国产精品视频26uuu| 中文幕av一区二区三区佐山爱| 91精品国产综合久久香蕉| 精品国产亚洲一区二区三区大结局| 亚洲一区精品电影| 91精品尤物| 久久亚洲午夜电影| 精品一区二区三区中文字幕老牛| 亚洲精品欧洲精品| 综合久久十次| 尤物av无码色av无码| 视频在线观看91| 99sesese| 国产mv日韩mv欧美| 日韩精品卡通动漫网站| 欧美激情一区二区三区全黄| 小泽玛利亚一区二区免费| 亚洲妇熟xx妇色黄| 无码免费一区二区三区| 3d成人动漫网站| 人妻无码一区二区三区久久99| 亚洲午夜小视频| 搞黄网站在线观看| 国产69久久精品成人| 成人四虎影院| 国产福利久久精品| 精品国产一区一区二区三亚瑟| 伊人久久99| 亚洲少妇在线| 色呦色呦色精品| 91香蕉视频mp4| 中国一级片在线观看| 亚洲va韩国va欧美va精品 | 日韩欧美国产小视频| 亚洲人成色777777精品音频| 日韩在线小视频| 色戒汤唯在线观看| 亚洲伊人久久大香线蕉av| 视频国产一区| 国产毛片久久久久久国产毛片| 久久午夜精品一区二区| 午夜性福利视频| 国产精品久久久久婷婷二区次| 日本一区二区欧美| 欧美精品色综合| 男女污污视频在线观看| 欧美大片在线看免费观看| 久久免费影院| 欧美精品一区二区三区在线看午夜| 亚洲网色网站| 一道本视频在线观看| 91色porny在线视频| 91日韩中文字幕| 在线观看不卡一区| 少妇av在线播放| 欧美国产第二页| 精品国模一区二区三区欧美 | 91精品国产91久久综合| 久久久久久三级| 99在线热播精品免费| 日韩在线观看免| 在线亚洲高清视频| 日本1级在线| 97视频在线观看亚洲| 亚洲精品aⅴ| av中文字幕av| 韩国av一区二区| 免费黄色国产视频| 欧美色男人天堂| eeuss影院在线播放| 国产91亚洲精品| 亚洲区小说区图片区qvod| 狠狠97人人婷婷五月| 成人高清伦理免费影院在线观看| 日本a级片视频| 91精品国产乱| 成视频免费观看在线看| 成人国产在线视频| 999久久久免费精品国产| 亚洲激情在线观看视频| 欧美极品另类videosde| 69av视频在线观看| 亚洲欧美综合精品久久成人| 亚洲一级少妇| 欧美一二三四五区| 日韩中文字幕区一区有砖一区| 国产毛片久久久久久久| 欧美性高清videossexo| 成人资源www网在线最新版| 国产精品一区二区久久久| 日韩精品一卡| 国产精品久久久久久久av福利| 中文字幕亚洲在| 99精品国产99久久久久久97| 欧美巨大黑人极品精男| 超碰97久久| av天堂永久资源网| 国产性天天综合网| 亚洲天堂中文在线| 美女福利视频一区| 国产成人精品亚洲线观看| 免费国产a级片| 国产亚洲一二三区| 中文字幕制服诱惑| 欧美日韩爱爱视频| 人人香蕉久久| 欧美伦理片在线观看| 亚洲欧美激情小说另类| 人妻视频一区二区三区| 国产不卡av在线| 天天做天天爱天天综合网| 人妻激情偷乱视频一区二区三区| 一区二区三区免费| 欧美套图亚洲一区| 国产伦精品免费视频| 先锋资源久久| 日本人妻一区二区三区| 日本精品一区二区三区高清| 日本在线视频观看| 成人综合色站| 青青草97国产精品免费观看 | 亚洲免费中文| 国产探花视频在线| 精品成人在线观看| www.久久.com| 欧美大黑帍在线播放| 久久精品无码一区二区三区| 国产免费的av| 全亚洲最色的网站在线观看| 99精品国产一区二区三区| 中文字幕在线永久| 欧美日韩免费一区二区三区视频| 丁香高清在线观看完整电影视频 | 亚洲国产欧美视频| 欧美精品777| 在线手机中文字幕| 影音先锋男人的网站| 91天堂素人约啪| 国产女无套免费视频| 国产成人精品视频在线| 欧美三区不卡| 欧美激情视频二区| 日韩经典一区二区三区| 经典三级久久| 99视频在线视频|