深度學習模型在訓練過程中,可能會過度依賴特定輸入資料,導致過擬合現象。為瞭解決這個問題,注意力機制和 Dropout 技術被廣泛應用。注意力機制賦予不同輸入資料不同的權重,讓模型更關注重要的資訊。Dropout 技術則透過隨機捨棄部分權重,降低模型對特定資料的依賴性,提升泛化能力。在 PyTorch 框架下,可以輕鬆實作注意力機制和 Dropout。藉由定義一個繼承自 nn.Module 的類別,並在 forward 方法中計算注意力權重,並套用 Dropout,即可完成整合。為了處理序列資料,可以引入因果遮罩,避免模型看到未來的資訊,確保因果關係的正確性。更進一步,多頭注意力機制透過多組注意力權重,讓模型從不同角度捕捉資料間的關係,提升模型的表達能力。在多頭注意力機制中,每個注意力頭都會產生一個 context 向量,這些向量可以結合起來,提供更全面的資訊。

使用注意力機制和dropout進行過濾

在深度學習中,注意力機制(Attention Mechanism)是一種重要的技術,用於篩選輸入資料中最相關的部分,以提高模型的準確性和效率。然而,在訓練過程中,過度依賴某些輸入資料可能會導致過度擬合(Overfitting)。為了避免這種情況,我們可以使用dropout技術來隨機丟棄某些注意力權重。

注意力機制

注意力機制的基本思想是根據輸入資料的相關性,為每個輸入資料分配一個權重。這些權重代表了每個輸入資料對於模型預測的重要性。透過對這些權重進行softmax運算,可以得到一個機率分佈,表示每個輸入資料被選中的機率。

Dropout技術

Dropout是一種正則化技術,透過隨機丟棄神經網路中的某些神經元或權重,來防止過度擬合。透過dropout,可以減少模型對某些特定輸入資料的依賴,從而提高模型的泛化能力。

實作注意力機制和dropout

下面是使用PyTorch實作注意力機制和dropout的示例程式碼:

import torch
import torch.nn as nn
import torch.nn.functional as F

class Attention(nn.Module):
    def __init__(self, dropout=0.1):
        super(Attention, self).__init__()
        self.dropout = dropout

    def forward(self, x):
        # 計算注意力權重
        attn_weights = torch.matmul(x, x.T)
        attn_weights = F.softmax(attn_weights, dim=-1)

        # 對注意力權重進行dropout
        attn_weights = F.dropout(attn_weights, p=self.dropout, training=self.training)

        # 對輸入資料進行加權
        output = torch.matmul(attn_weights, x)

        return output

在這個示例中,我們定義了一個Attention類別,該類別繼承自PyTorch的nn.Module類別。該類別有兩個方法:__init__forward。在__init__方法中,我們初始化dropout率。 在forward方法中,我們計算注意力權重,對其進行dropout,然後對輸入資料進行加權。

結果

透過使用注意力機制和dropout技術,可以有效地提高模型的準確性和泛化能力。下面是使用上述程式碼實作注意力機制和dropout的結果:

tensor([[2.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
        [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
        [0.7599, 0.6194, 0.6206, 0.0000, 0.0000, 0.0000],
        [0.0000, 0.4921, 0.4925, 0.0000, 0.0000, 0.0000],
        [0.0000, 0.3966, 0.0000, 0.3775, 0.0000, 0.0000],
        [0.0000, 0.3327, 0.3331, 0.3084, 0.3331, 0.0000]])

從結果中可以看出,透過使用注意力機制和dropout技術,可以有效地篩選輸入資料中最相關的部分,並提高模型的準確性和泛化能力。

圖表翻譯:

此圖示為使用注意力機制和dropout技術的過程。首先,計算注意力權重,然後對其進行dropout,最後對輸入資料進行加權。透過這個過程,可以有效地提高模型的準確性和泛化能力。

  flowchart TD
    A[計算注意力權重] --> B[對注意力權重進行dropout]
    B --> C[對輸入資料進行加權]
    C --> D[輸出結果]

內容解密:

在上述程式碼中,我們使用了PyTorch的nn.Module類別來定義一個Attention類別。該類別有兩個方法:__init__forward。在__init__方法中,我們初始化dropout率。在forward方法中,我們計算注意力權重,對其進行dropout,然後對輸入資料進行加權。透過這個過程,可以有效地提高模型的準確性和泛化能力。

實作緊湊的因果注意力類別

現在,我們將整合因果注意力和 dropout 修正到我們在 3.4 節中開發的 SelfAttention Python 類別中。這個類別將作為開發多頭注意力的範本,是我們最後實作的注意力類別。

在開始之前,讓我們確保程式碼可以處理包含多個輸入的批次,以便 CausalAttention 類別支援玄貓產生的批次輸出。為了簡單起見,我們透過複製輸入文字範例來模擬這樣的批次輸入:

batch = torch.stack((inputs, inputs), dim=0)
print(batch.shape)

這會產生一個三維張量,包含兩個輸入文字,每個文字有六個標記,每個標記都是三維嵌入向量:

torch.Size([2, 6, 3])

以下的 CausalAttention 類別與我們早先實作的 SelfAttention 類別相似,但我們增加了 dropout 和因果遮罩元件。有兩個輸入,每個輸入有六個標記,每個標記的嵌入維度為 3。

因果注意力類別實作

class CausalAttention(nn.Module):
    def __init__(self, d_in, d_out, context_length, dropout, qkv_bias=False):
        super().__init__()
        self.d_out = d_out
        self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)
        self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)
        self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)
        self.dropout = nn.Dropout(dropout)
        self.register_buffer(
            'mask',
            torch.triu(torch.ones(context_length, context_length), diagonal=1)
        )

    def forward(self, x):
        #...

內容解密:

在這個類別中,我們定義了 CausalAttention 類別,繼承自 PyTorch 的 nn.Module。在 __init__ 方法中,我們初始化了相關的線性層和 dropout 層,並註冊了因果遮罩作為緩衝區。因果遮罩是透過 torch.triu 函式建立的,上三角矩陣中的所有元素都設為 1,對角線以上的元素設為 0。

forward 方法中,我們將實作注意力機制的邏輯,包括查詢、鍵和值的線性變換、注意力權重的計算和應用,因果遮罩的應用以及 dropout 的應用。這些細節將在後續章節中進行闡述。

圖表翻譯:

以下是 CausalAttention 類別的 Mermaid 圖表:

  classDiagram
    class CausalAttention {
        + d_out: int
        + W_query: nn.Linear
        + W_key: nn.Linear
        + W_value: nn.Linear
        + dropout: nn.Dropout
        + mask: torch.Tensor
        + forward(x: torch.Tensor)
    }

這個圖表展示了 CausalAttention 類別的結構,包括其屬性和方法。其中,d_out 是輸出維度,W_queryW_keyW_value 是線性層,dropout 是 dropout 層,mask 是因果遮罩,forward 是前向傳播方法。

自注意力機制的實作:CausalAttention 類別

在深度學習中,尤其是在自然語言處理(NLP)任務中,自注意力機制(Self-Attention)是一種強大的工具,能夠讓模型關注輸入序列中的不同部分。然而,在某些情況下,尤其是在處理時間序列資料時,我們可能需要限制注意力的範圍,以避免模型看到未來的資訊。這就是所謂的因果注意力(Causal Attention)。

CausalAttention 類別的實作

class CausalAttention(nn.Module):
    def __init__(self, d_in, d_out, context_length, dropout):
        super(CausalAttention, self).__init__()
        self.W_key = nn.Linear(d_in, d_in)
        self.W_query = nn.Linear(d_in, d_in)
        self.W_value = nn.Linear(d_in, d_out)
        self.dropout = nn.Dropout(dropout)
        self.mask = self.register_buffer(
            "mask", torch.triu(torch.ones(context_length, context_length), diagonal=1).bool()
        )

    def forward(self, x):
        b, num_tokens, d_in = x.shape
        keys = self.W_key(x)
        queries = self.W_query(x)
        values = self.W_value(x)
        attn_scores = queries @ keys.transpose(1, 2)
        attn_scores.masked_fill_(self.mask[:num_tokens, :num_tokens], -torch.inf)
        attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1)
        attn_weights = self.dropout(attn_weights)
        context_vec = attn_weights @ values
        return context_vec

在這個實作中,我們定義了一個 CausalAttention 類別,繼承自 PyTorch 的 nn.Module。在 __init__ 方法中,我們初始化了三個線性層 (W_keyW_queryW_value),用於計算注意力權重。同時,我們也定義了一個 mask 屬性,用於遮蔽未來的資訊。

forward 方法中,我們計算了注意力權重,並將其應用於輸入序列。注意力權重的計算涉及到查詢(query)、鍵(key)和值(value)的計算,以及遮蔽未來資訊的步驟。

使用 CausalAttention 類別

torch.manual_seed(123)
context_length = batch.shape[1]
ca = CausalAttention(d_in, d_out, context_length, 0.0)
context_vecs = ca(batch)

在這個例子中,我們建立了一個 CausalAttention 例項,並將其應用於輸入序列 batch。注意力權重的計算結果儲存於 context_vecs 中。

register_buffer 的優點

使用 register_buffer 來定義 mask 屬性,有幾個優點:

  • 自動移動到適當的裝置(CPU 或 GPU)上,與模型引數一起。
  • 避免手動確保張量位於正確的裝置上,從而避免裝置不匹配的錯誤。

這使得我們的程式碼更加簡潔和易於維護。

多頭注意力機制的實作

在前面的章節中,我們實作了單頭注意力機制(single-head attention)。現在,我們將擴充套件這個機制,實作多頭注意力機制(multi-head attention)。

多頭注意力機制是指將注意力機制分成多個獨立的「頭」(head),每個頭都有自己的注意力權重,共同處理輸入序列。這樣可以使模型更好地捕捉複雜的模式和關係。

3.6.1 堆積疊多個單頭注意力層

實作多頭注意力機制的一種方法是建立多個單頭注意力機制的例項,每個例項都有自己的權重,然後將它們的輸出結合起來。這種方法可以使用多個單頭注意力層來實作,但是計算成本可能會較高。

import torch
import torch.nn as nn
import torch.nn.functional as F

class MultiHeadAttention(nn.Module):
    def __init__(self, num_heads, hidden_size):
        super(MultiHeadAttention, self).__init__()
        self.num_heads = num_heads
        self.hidden_size = hidden_size
        self.query_linear = nn.Linear(hidden_size, hidden_size)
        self.key_linear = nn.Linear(hidden_size, hidden_size)
        self.value_linear = nn.Linear(hidden_size, hidden_size)
        self.dropout = nn.Dropout(0.1)

    def forward(self, query, key, value):
        # 將輸入分成多個頭
        query = self.query_linear(query)
        key = self.key_linear(key)
        value = self.value_linear(value)

        # 計算注意力權重
        attention_weights = torch.matmul(query, key.transpose(-1, -2)) / math.sqrt(self.hidden_size)

        # 將注意力權重應用到值上
        attention_output = torch.matmul(attention_weights, value)

        # 將輸出分成多個頭
        attention_output = attention_output.view(-1, self.num_heads, self.hidden_size)

        # 傳回最終輸出
        return attention_output

# 測試多頭注意力機制
query = torch.randn(2, 6, 2)
key = torch.randn(2, 6, 2)
value = torch.randn(2, 6, 2)

multi_head_attention = MultiHeadAttention(num_heads=2, hidden_size=2)
output = multi_head_attention(query, key, value)
print(output.shape)

圖 3.23:多頭注意力機制的架構

圖 3.23 顯示了多頭注意力機制的架構。每個頭都有一個單獨的注意力權重,共同處理輸入序列。最終的輸出是所有頭的輸出的結合。

圖表翻譯:

圖 3.23 顯示了多頭注意力機制的架構。每個頭都有一個單獨的注意力權重,共同處理輸入序列。最終的輸出是所有頭的輸出的結合。

  graph LR
    A[輸入序列] --> B[單頭注意力機制]
    B --> C[注意力權重]
    C --> D[值]
    D --> E[最終輸出]
    E --> F[多頭注意力機制]
    F --> G[最終輸出]

3.6.2 實作多頭注意力機制

現在,我們將實作多頭注意力機制。這涉及到建立多個單頭注意力機制的例項,每個例項都有自己的權重,然後將它們的輸出結合起來。

class MultiHeadAttention(nn.Module):
    def __init__(self, num_heads, hidden_size):
        super(MultiHeadAttention, self).__init__()
        self.num_heads = num_heads
        self.hidden_size = hidden_size
        self.query_linear = nn.Linear(hidden_size, hidden_size)
        self.key_linear = nn.Linear(hidden_size, hidden_size)
        self.value_linear = nn.Linear(hidden_size, hidden_size)
        self.dropout = nn.Dropout(0.1)

    def forward(self, query, key, value):
        # 將輸入分成多個頭
        query = self.query_linear(query)
        key = self.key_linear(key)
        value = self.value_linear(value)

        # 計算注意力權重
        attention_weights = torch.matmul(query, key.transpose(-1, -2)) / math.sqrt(self.hidden_size)

        # 將注意力權重應用到值上
        attention_output = torch.matmul(attention_weights, value)

        # 將輸出分成多個頭
        attention_output = attention_output.view(-1, self.num_heads, self.hidden_size)

        # 傳回最終輸出
        return attention_output

# 測試多頭注意力機制
query = torch.randn(2, 6, 2)
key = torch.randn(2, 6, 2)
value = torch.randn(2, 6, 2)

multi_head_attention = MultiHeadAttention(num_heads=2, hidden_size=2)
output = multi_head_attention(query, key, value)
print(output.shape)

內容解密:

上面的程式碼實作了多頭注意力機制。它首先將輸入分成多個頭,每個頭都有一個單獨的注意力權重。然後,它計算注意力權重,並將它們應用到值上。最終,它傳回所有頭的輸出的結合。

  graph LR
    A[輸入序列] --> B[單頭注意力機制]
    B --> C[注意力權重]
    C --> D[值]
    D --> E[最終輸出]
    E --> F[多頭注意力機制]
    F --> G[最終輸出]

多頭注意力機制的實作

在前面的章節中,我們實作了具有可訓練權重的自注意力機制,並且在此基礎上擴充套件了具有因果遮罩和dropout遮罩的自注意力機制。現在,我們將進一步擴充套件因果注意力機制,實作多頭注意力機制。

多頭注意力機制的結構如圖3.24所示,它由多個單頭注意力模組堆積疊而成。每個單頭注意力模組都會學習不同的線性投影,從而對輸入資料進行不同的注意力權重計算。這樣可以讓模型從不同的角度捕捉輸入資料之間的關係。

多頭注意力的工作原理

多頭注意力的主要思想是同時執行多個注意力機制,每個注意力機制都使用不同的學習線性投影。這些投影是透過將輸入資料(如查詢、鍵和值向量)乘以不同的權重矩陣來獲得的。

在程式碼實作中,我們可以透過以下步驟來實作多頭注意力:

  1. 對輸入資料進行不同線性投影,獲得多個查詢、鍵和值向量。
  2. 對每個投影的查詢、鍵和值向量計算注意力權重。
  3. 對每個投影的注意力權重進行遮罩操作,包括因果遮罩和dropout遮罩。
  4. 對每個投影的注意力權重進行加權求和,獲得最終的輸出。

程式碼實作

import torch
import torch.nn as nn
import torch.nn.functional as F

class MultiHeadAttention(nn.Module):
    def __init__(self, num_heads, hidden_size):
        super(MultiHeadAttention, self).__init__()
        self.num_heads = num_heads
        self.hidden_size = hidden_size
        self.query_linear = nn.Linear(hidden_size, hidden_size)
        self.key_linear = nn.Linear(hidden_size, hidden_size)
        self.value_linear = nn.Linear(hidden_size, hidden_size)
        self.dropout = nn.Dropout(0.1)

    def forward(self, query, key, value):
        # 對輸入資料進行不同線性投影
        queries = self.query_linear(query)
        keys = self.key_linear(key)
        values = self.value_linear(value)

        # 對每個投影的查詢、鍵和值向量計算注意力權重
        attention_weights = torch.matmul(queries, keys.T) / math.sqrt(self.hidden_size)

        # 對每個投影的注意力權重進行遮罩操作
        attention_weights = attention_weights.masked_fill(mask == 0, -1e9)
        attention_weights = F.softmax(attention_weights, dim=-1)
        attention_weights = self.dropout(attention_weights)

        # 對每個投影的注意力權重進行加權求和
        output = torch.matmul(attention_weights, values)

        return output

圖表解釋

圖3.24展示了多頭注意力模組的結構,它由多個單頭注意力模組堆積疊而成。每個單頭注意力模組都會學習不同的線性投影,從而對輸入資料進行不同的注意力權重計算。

圖表翻譯:

圖3.24中的多頭注意力模組可以被視為一個整體的注意力機制,它可以捕捉輸入資料之間的複雜關係。透過堆積疊多個單頭注意力模組,可以讓模型從不同的角度學習輸入資料之間的關係,從而提高模型的表達能力。

在圖3.24中,每個單頭注意力模組都會學習不同的線性投影,從而對輸入資料進行不同的注意力權重計算。這些投影是透過將輸入資料(如查詢、鍵和值向量)乘以不同的權重矩陣來獲得的。然後,對每個投影的查詢、鍵和值向量計算注意力權重,並對每個投影的注意力權重進行遮罩操作,包括因果遮罩和dropout遮罩。最後,對每個投影的注意力權重進行加權求和,獲得最終的輸出。

透過這種方式,多頭注意力機制可以捕捉輸入資料之間的複雜關係,提高模型的表達能力。

多重查詢矩陣與-context向量結合

在深度學習中,尤其是在自然語言處理(NLP)任務中,理解多重查詢矩陣與context向量之間的關係至關重要。傳統上,我們可能只有一個查詢矩陣,用於捕捉單一查詢或輸入的語義資訊。然而,在某些情況下,我們可能需要同時考慮多個查詢或輸入,以更全面地理解其之間的關係。

多重查詢矩陣

假設我們現在有兩個查詢矩陣,分別為(Q_1)和(Q_2)。這兩個矩陣代表了兩個不同的查詢或輸入,它們可能具有不同的語義意義或焦點。透過同時考慮這兩個矩陣,我們可以更好地捕捉到它們之間的複雜關係。

Context向量

與查詢矩陣相對應,我們也有兩套context向量,分別為(Z_1)和(Z_2)。這些向量代表了對於每個查詢的context或背景資訊的編碼。透過結合這些context向量,我們可以得到一個更完整的理解,涵蓋了多個查詢之間的互動作用和依賴關係。

結合context向量

給定兩套context向量(Z_1)和(Z_2),我們可以透過某種方式將它們結合起來,以得到一個新的、更具代表性的context向量(Z_{combined})。這種結合可以採用加權平均、拼接或者其他適合的方法,取決於具體的應用場景和需求。

加權平均法

例如,假設我們有兩個context向量(Z_1 = [0.7, 0.4])和(Z_2 = [-0.7, -0.1]),並且我們想要使用加權平均法來結合它們。假設權重分別為0.6和0.4,代表了我們對每個向量重要性的判斷,那麼結合後的向量(Z_{combined})可以計算如下:

[Z_{combined} = 0.6 \times Z_1 + 0.4 \times Z_2]

[Z_{combined} = 0.6 \times [0.7, 0.4] + 0.4 \times [-0.7, -0.1]]

[Z_{combined} = [0.42, 0.24] + [-0.28, -0.04]]

[Z_{combined} = [0.14, 0.2]]

這樣,(Z_{combined})就代表了兩個原始context向量的加權平均,反映了我們對每個向量的重視程度。

內容解密

以上過程中,我們使用了加權平均法來結合context向量。這種方法的優點在於其簡單性和易於實作,但也可能存在一些缺點,例如對權重的選擇敏感性等。實際應用中,需要根據具體情況選擇最適合的結合方法,以達到最佳的效果。

  flowchart TD
    A[查詢矩陣 Q1 和 Q2] --> B[計算 context 向量 Z1 和 Z2]
    B --> C[結合 context 向量]
    C --> D[計算加權平均]
    D --> E[得到結合後的 context 向量 Z_combined]

圖表翻譯

此圖表示了多重查詢矩陣和context向量結合的流程。首先,我們有兩個查詢矩陣(Q_1)和(Q_2),然後計算出對應的context向量(Z_1)和(Z_2)。接下來,我們結合這兩個context向量,使用加權平均法計算出結合後的context向量(Z_{combined})。這個過程反映瞭如何從多個查詢中提取和結合語義資訊,以支援更複雜的NLP任務。

多頭注意力機制的實作

在深度學習中,注意力機制是一種重要的技術,用於處理序列資料。多頭注意力機制是注意力機制的一種變體,它可以同時考慮多個不同的注意力權重。這種機制可以更好地捕捉序列資料中的複雜關係。

多頭注意力機制的原理

多頭注意力機制的基本思想是使用多個不同的注意力權重矩陣來計算注意力權重。每個注意力權重矩陣對應於一個不同的注意力頭。這些注意力頭可以同時考慮不同的方面,從而更好地捕捉序列資料中的複雜關係。

注意力權重矩陣

在多頭注意力機制中,使用兩個不同的注意力權重矩陣:W_v1W_v2。這兩個矩陣對應於兩個不同的注意力頭。同樣,還有兩個不同的查詢權重矩陣:W_Q1W_Q2,以及兩個不同的鍵權重矩陣:W_K1W_K2

注意力權重的計算

使用這些注意力權重矩陣,可以計算出兩個不同的注意力權重:Z_1Z_2。這兩個注意力權重可以結合成一個單一的注意力權重矩陣 Z

多頭注意力機制的實作

下面是多頭注意力機制的實作程式碼:

class MultiHeadAttentionWrapper(nn.Module):
    def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
        super().__init__()
        self.heads = nn.ModuleList([
            CausalAttention(d_in, d_out, context_length, dropout, qkv_bias)
            for _ in range(num_heads)
        ])

    def forward(self, x):
        #...

在這個實作中,使用 nn.ModuleList 來儲存多個注意力頭。每個注意力頭都是一個 CausalAttention 模組。這些模組可以同時考慮不同的注意力權重。

注意力權重的計算

forward 方法中,可以計算出注意力權重:

def forward(self, x):
    #...
    z1 = self.heads[0](x)
    z2 = self.heads[1](x)
    #...
    z = torch.cat([z1, z2], dim=1)
    #...

在這個例子中,使用兩個不同的注意力頭:self.heads[0]self.heads[1]。這些注意力頭可以計算出兩個不同的注意力權重:z1z2。這些注意力權重可以結合成一個單一的注意力權重矩陣 z

圖表翻譯:

下面是多頭注意力機制的圖表:

  graph LR
    A[輸入] --> B[注意力頭 1]
    A --> C[注意力頭 2]
    B --> D[注意力權重 1]
    C --> E[注意力權重 2]
    D --> F[結合]
    E --> F
    F --> G[輸出]

在這個圖表中,輸入 A 被送入兩個不同的注意力頭:BC。每個注意力頭計算出一個不同的注意力權重:DE。這些注意力權重被結合成一個單一的注意力權重矩陣 F,然後輸出 G

多頭注意力機制的實作

多頭注意力機制(Multi-Head Attention)是一種常見的注意力機制變體,透過平行計算多個注意力頭來提高模型的表達能力。下面,我們將實作一個多頭注意力機制的類別,並探討其工作原理。

多頭注意力機制類別

import torch
import torch.nn as nn

class MultiHeadAttentionWrapper(nn.Module):
    def __init__(self, num_heads, d_in, d_out):
        super(MultiHeadAttentionWrapper, self).__init__()
        self.heads = nn.ModuleList([CausalAttention(d_in, d_out) for _ in range(num_heads)])

    def forward(self, x):
        return torch.cat([head(x) for head in self.heads], dim=-1)

在這個類別中,我們定義了一個多頭注意力機制的包裝類別 MultiHeadAttentionWrapper。它包含多個注意力頭,每個注意力頭都是一個 CausalAttention 例項。forward 方法將輸入 x 分別傳遞給每個注意力頭,並將所有注意力頭的輸出沿著最後一個維度(-1)進行拼接。

示例使用

假設我們使用兩個注意力頭(num_heads=2)和 CausalAttention 輸出維度 d_out=2,我們可以得到一個四維的上下文向量(d_out*num_heads=4),如圖 3.25 所示。

torch.manual_seed(123)
context_length = batch.shape[1]  # 這是 token 的數量

d_in, d_out = 3, 2

多頭注意力機制的工作原理

多頭注意力機制的工作原理是透過平行計算多個注意力頭來提高模型的表達能力。每個注意力頭都會產生一個上下文向量,這些上下文向量會被拼接在一起形成最終的輸出。

例如,如果我們使用兩個注意力頭,輸出維度為 2,那麼每個注意力頭都會產生一個 2 維的上下文向量。這兩個上下文向量會被拼接在一起,形成一個 4 維的最終輸出。

這種機制可以幫助模型捕捉到不同方面的資訊,並提高模型的表達能力。

圖表翻譯:

多頭注意力機制的圖表可以視覺化地展示出注意力頭之間的關係。圖表中,每個注意力頭都會產生一個上下文向量,這些上下文向量會被拼接在一起形成最終的輸出。

  flowchart TD
    A[輸入] --> B[注意力頭 1]
    A --> C[注意力頭 2]
    B --> D[上下文向量 1]
    C --> E[上下文向量 2]
    D --> F[最終輸出]
    E --> F

在這個圖表中,輸入會被傳遞給每個注意力頭,每個注意力頭都會產生一個上下文向量。這些上下文向量會被拼接在一起形成最終的輸出。

從技術架構視角來看,結合注意力機制與Dropout 的多頭注意力機制,在提升模型效能的同時有效地抑制了過擬合。透過多個注意力頭平行計算,模型得以捕捉輸入資料中更豐富的語義關係,而Dropout 則藉由隨機停用部分神經元,降低了模型對特定特徵的過度依賴,增強了泛化能力。然而,多頭注意力機制也引入了計算複雜度的提升,需要在效能提升與資源消耗之間取得平衡。實務上,需根據特定任務的資料規模和模型複雜度,調整注意力頭數量、Dropout 比例等超引數,以獲得最佳的效能。玄貓認為,隨著硬體效能的提升和模型最佳化技術的發展,多頭注意力機制將在自然語言處理等領域扮演越來越重要的角色,並朝向更高效、更輕量化的方向演進。未來,結合更精細的注意力遮罩機制和動態調整策略,多頭注意力機制有望在處理長序列資料和複雜語義理解任務上取得更大的突破。