多頭注意力機制已成為深度學習模型處理序列資料的核心技術,尤其在自然語言處理領域,它能有效捕捉詞彙間的複雜關係。實作多頭注意力機制時,首先需初始化權重矩陣,接著計算查詢(Query)、鍵(Key)和值(Value),並將其分割成多個頭。每個頭的注意力權重透過矩陣乘法和 Softmax 函式計算,最後將各頭的輸出合併,經過線性變換和 Dropout 操作,得到最終輸出。此機制允許多個注意力頭平行運算,從不同角度理解輸入序列,提升模型的表達能力。更進一步,多頭注意力機制是建構 Transformer 和 GPT-2 等大語言模型的關鍵元件,賦予模型強大的序列理解和生成能力。

多頭注意力機制的實作

在實作多頭注意力機制時,我們需要考慮如何將單頭注意力機制擴充套件到多頭注意力機制。這涉及到如何設定嵌入維度、注意力頭數以及如何結合多個注意力頭的輸出。

多頭注意力機制的架構

多頭注意力機制的架構如圖3.25所示。假設我們設定嵌入維度為2(d_out = 2),並設定注意力頭數為2(num_heads = 2),則最終的嵌入維度將為4(d_out × num_heads = 2 × 2 = 4)。

實作多頭注意力機制

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

mha = MultiHeadAttentionWrapper(d_in, d_out, context_length, 0.0, num_heads=2)
context_vecs = mha(batch)
print(context_vecs)
print("context_vecs.shape:", context_vecs.shape)

這段程式碼建立了一個MultiHeadAttentionWrapper物件,設定嵌入維度為2,注意力頭數為2。然後,它對輸入批次進行多頭注意力運算,並輸出一個張量,代表每個token的context向量。

輸出結果

輸出結果如下:

tensor([[[-0.4519, 0.2216, 0.4772, 0.1063],
         [-0.5874, 0.0058, 0.5891, 0.3257],
         [-0.6300, -0.0632, 0.6202, 0.3860],
         [-0.5675, -0.0843, 0.5478, 0.3589],
         [-0.5526, -0.0981, 0.5321, 0.3428],
         [-0.5299, -0.1081, 0.5077, 0.3493]],
        [[-0.4519, 0.2216, 0.4772, 0.1063],
         [-0.5874, 0.0058, 0.5891, 0.3257],
         [-0.6300, -0.0632, 0.6202, 0.3860],
         [-0.5675, -0.0843, 0.5478, 0.3589],
         [-0.5526, -0.0981, 0.5321, 0.3428],
         [-0.5299, -0.1081, 0.5077, 0.3493]]], grad_fn=<CatBackward0>)
context_vecs.shape: torch.Size([2, 6, 4])

輸出結果是一個張量,形狀為(2,6,4),其中第一維度代表輸入批次,第二維度代表每個token,第三維度代表每個token的context向量維度。

內容解密:

上述程式碼實作了多頭注意力機制,設定嵌入維度為2,注意力頭數為2。然後,它對輸入批次進行多頭注意力運算,並輸出一個張量,代表每個token的context向量。輸出結果是一個張量,形狀為(2,6,4),其中第一維度代表輸入批次,第二維度代表每個token,第三維度代表每個token的context向量維度。

圖表翻譯:

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

  flowchart TD
    A[輸入批次] --> B[多頭注意力機制]
    B --> C[context向量]
    C --> D[輸出張量]
    D --> E[形狀:(2, 6, 4)]

這個圖表展示了多頭注意力機制的流程,從輸入批次到輸出張量。其中,context向量是每個token的表示,輸出張量的形狀為(2,6,4),代表每個token的context向量維度。

練習3.2:傳回二維嵌入向量

修改MultiHeadAttentionWrapper的輸入引數,使得輸出context向量為二維而不是四維。提示:你不需要修改類別實作,只需要修改其他輸入引數。

多頭注意力機制的實作與權重分割

在之前的章節中,我們已經建立了 MultiHeadAttentionWrapper 來實作多頭注意力機制。這是透過將多個注意力頭結合起來實作的,每個注意力頭代表著一個獨立的注意力機制。然而,為了提高效率和簡化程式碼,我們可以將 MultiHeadAttentionWrapperCausalAttention 合併成一個單一的 MultiHeadAttention 類別。

在新的 MultiHeadAttention 類別中,我們不僅要合併多頭注意力機制和因果注意力機制的功能,還要對程式碼進行一些修改,以實作更高效的多頭注意力機制。具體來說,我們會將輸入分割成多個頭,每個頭代表著一個獨立的注意力頭,然後計算每個頭的注意力權重,最後將所有頭的結果合併起來。

下面是 MultiHeadAttention 類別的實作程式碼:

class MultiHeadAttention(nn.Module):
    def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
        super().__init__()
        assert (d_out % num_heads == 0), "d_out 必須能被 num_heads 整除"
        self.d_out = d_out
        self.num_heads = num_heads
        self.head_dim = d_out // num_heads
        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.out_proj = nn.Linear(d_out, d_out)
        self.dropout = nn.Dropout(dropout)
        self.register_buffer("mask", torch.triu(torch.ones(context_length, context_length), diagonal=1))

    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)

內容解密:

在上面的程式碼中,我們定義了 MultiHeadAttention 類別,該類別繼承自 PyTorch 的 nn.Module。在 __init__ 方法中,我們初始化了類別的屬性,包括輸入維度 d_in、輸出維度 d_out、上下文長度 context_length、dropout 率 dropout、注意力頭數 num_heads 和是否使用偏置項 qkv_bias

我們還定義了四個全連線層:W_queryW_keyW_valueout_proj,分別用於計算查詢向量、鍵值向量、值向量和輸出向量。另外,我們定義了一個 dropout 層 dropout,用於防止過擬合。

forward 方法中,我們計算了輸入張量 x 的形狀,並根據輸入維度和注意力頭數計算了查詢向量、鍵值向量和值向量。這些向量將用於計算注意力權重和輸出向量。

圖表翻譯:

下面是 MultiHeadAttention 類別的 Mermaid 圖表:

  flowchart TD
    A[輸入] --> B[查詢向量]
    A --> C[鍵值向量]
    A --> D[值向量]
    B --> E[注意力權重]
    C --> E
    D --> E
    E --> F[輸出向量]
    F --> G[dropout]
    G --> H[最終輸出]

這個圖表展示了 MultiHeadAttention 類別的計算流程,從輸入張量到最終輸出。

多頭注意力機制的實作

在深度學習中,注意力機制(Attention Mechanism)是一種重要的技術,用於處理序列資料。單頭注意力機制(Single-Head Attention)只能捕捉到序列中的一個方面的資訊,而多頭注意力機制(Multi-Head Attention)則可以同時捕捉多個方面的資訊,從而提高模型的表達能力。

多頭注意力機制的原理

多頭注意力機制的基本思想是將輸入資料分成多個頭(Head),每個頭都有一個單獨的注意力機制。這些注意力機制可以平行執行,從而提高計算效率。多頭注意力機制的輸出是所有頭的輸出的拼接。

實作多頭注意力機制

要實作多頭注意力機制,我們需要對輸入資料進行變換,以便於計算注意力權重。具體步驟如下:

  1. 將輸入資料 keysvaluesqueries 分別變換為 (b, num_tokens, num_heads, head_dim) 的形狀,其中 b 是批次大小,num_tokens 是序列長度,num_heads 是頭數,head_dim 是每個頭的維度。
  2. keysqueriesvalues 進行轉置,以便於計算注意力權重。
  3. 計算注意力權重 attn_scores,即 querieskeys 的點積。
  4. 應用遮罩 mask_bool 以避免某些位置之間的注意力流動。

程式碼實作

import torch

class MultiHeadAttention(torch.nn.Module):
    def __init__(self, num_heads, head_dim):
        super(MultiHeadAttention, self).__init__()
        self.num_heads = num_heads
        self.head_dim = head_dim
        self.mask = None

    def forward(self, queries, keys, values):
        b, num_tokens, _ = queries.size()
        keys = keys.view(b, num_tokens, self.num_heads, self.head_dim)
        values = values.view(b, num_tokens, self.num_heads, self.head_dim)
        queries = queries.view(b, num_tokens, self.num_heads, self.head_dim)

        keys = keys.transpose(1, 2)
        queries = queries.transpose(1, 2)
        values = values.transpose(1, 2)

        attn_scores = torch.matmul(queries, keys.transpose(2, 3))
        if self.mask is not None:
            mask_bool = self.mask.bool()[:num_tokens, :num_tokens]
            attn_scores = attn_scores.masked_fill(mask_bool, -float('inf'))

        #...

內容解密:

在上述程式碼中,我們首先定義了 MultiHeadAttention 類別,該類別繼承自 torch.nn.Module。在 forward 方法中,我們首先將輸入資料 querieskeysvalues 分別變換為 (b, num_tokens, num_heads, head_dim) 的形狀。然後,我們進行轉置以便於計算注意力權重。接著,我們計算注意力權重 attn_scores,即 querieskeys 的點積。如果有遮罩 mask_bool,我們將其應用於注意力權重中。

圖表翻譯:

  graph LR
    A[輸入資料] -->|變換|> B[(b, num_tokens, num_heads, head_dim)]
    B -->|轉置|> C[(num_heads, num_tokens, head_dim)]
    C -->|計算注意力權重|> D[attn_scores]
    D -->|應用遮罩|> E[最終輸出]

在上述圖表中,我們展示了多頭注意力機制的計算流程。首先,我們將輸入資料變換為 (b, num_tokens, num_heads, head_dim) 的形狀。然後,我們進行轉置以便於計算注意力權重。接著,我們計算注意力權重 attn_scores,即 querieskeys 的點積。如果有遮罩 mask_bool,我們將其應用於注意力權重中,以得到最終輸出。

多頭注意力機制的實作

多頭注意力機制(Multi-Head Attention)是一種強大的注意力機制,它可以同時考慮多個方面的資訊。下面是多頭注意力機制的實作過程:

初始化

首先,需要初始化多頭注意力機制的引數,包括查詢(query)、鍵(key)和值(value)的維度,以及頭數(num_heads)。

查詢、鍵和值的轉換

接下來,需要將查詢、鍵和值轉換為適合多頭注意力機制的格式。這是透過線性層(linear layer)實作的。

分頭

然後,需要將查詢、鍵和值分成多個頭(head)。這是透過張量重塑(reshaping)和轉置(transposing)操作實作的。具體來說,需要將維度為(b,num_tokens,d_out)的張量重塑為維度為(b,num_tokens,num_heads,head_dim)的張量,其中head_dim = d_out / num_heads。

注意力權重的計算

接下來,需要計算注意力權重(attn_weights)。這是透過點積(dot product)和softmax函式實作的。

attn_scores = torch.matmul(query, key.transpose(-1, -2)) / math.sqrt(d_out)
attn_weights = torch.softmax(attn_scores, dim=-1)

注意力權重的dropout

然後,需要對注意力權重進行dropout操作,以防止過度擬合。

attn_weights = self.dropout(attn_weights)

結果的計算

最後,需要計算多頭注意力機制的結果。這是透過將注意力權重與值進行點積實作的。

context_vec = (attn_weights @ values).transpose(1, 2)

輸出

最終,需要將結果進行線性轉換和dropout操作,以得到最終的輸出。

context_vec = self.out_proj(context_vec)

注意力機制的實作

在實作注意力機制時,我們需要將輸入的張量進行轉置,以便正確地對齊查詢(queries)、鍵(keys)和值(values)在不同注意力頭(heads)之間。這一步驟對於高效地執行批次矩陣乘法至關重要。

假設我們有一個張量 a,其形狀為 (b, num_tokens, n_heads, head_dim),其中 b 是批次大小,num_tokens 是序列中的令牌數,n_heads 是注意力頭的數量,head_dim 是每個注意力頭的維度大小。為了將注意力頭維度移到令牌維度之前,我們需要對張量進行轉置,從而得到形狀為 (b, n_heads, num_tokens, head_dim) 的張量。

以下是這個過程的示例:

import torch

# 定義一個示例張量
a = torch.tensor([[[[0.2745, 0.6584, 0.2775, 0.8573],
                   [0.8993, 0.0390, 0.9268, 0.7388],
                   [0.7179, 0.7058, 0.9156, 0.4340]],
                  [[0.0772, 0.3565, 0.1479, 0.5331],
                   [0.4066, 0.2318, 0.4545, 0.9737],
                   [0.4606, 0.5159, 0.4220, 0.5786]]]])

# 對張量進行轉置
a_transposed = a.transpose(1, 2)

print(a_transposed.shape)  # 輸出:torch.Size([1, 2, 3, 4])

在這個示例中,原始張量 a 的形狀為 (1, 3, 2, 4),經過轉置後,新的形狀變為 (1, 2, 3, 4),其中注意力頭維度 (n_heads = 2) 現在位於令牌維度 (num_tokens = 3) 之前。

內容解密:

上述過程中的轉置操作是為了能夠正確地對齊查詢、鍵和值在不同注意力頭之間。這樣做可以高效地執行批次矩陣乘法,並且是實作注意力機制的關鍵一步。

圖表翻譯:

  graph LR
    A[原始張量] -->|轉置|> B[轉置後張量]
    B -->|批次矩陣乘法|> C[結果]
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#f9f,stroke:#333,stroke-width:2px
    style C fill:#f9f,stroke:#333,stroke-width:2px

這個圖表展示了原始張量經過轉置後,如何進行批次矩陣乘法以得到最終結果。

多頭注意力機制的矩陣運算

在多頭注意力機制中,需要進行多次矩陣乘法運算,以便從輸入資料中提取出不同的特徵。具體來說,需要對輸入資料進行兩次矩陣乘法,以獲得兩個查詢矩陣 $Q_1$ 和 $Q_2$。

查詢矩陣的計算

首先,需要計算查詢矩陣 $Q_1$ 和 $Q_2$。這可以透過對輸入資料 $X$ 進行兩次矩陣乘法實作。具體來說,需要將輸入資料 $X$ 乘以權重矩陣 $W_{q1}$ 和 $W_{q2}$,以獲得查詢矩陣 $Q_1$ 和 $Q_2$。

import numpy as np

# 輸入資料
X = np.array([[1, 2], [3, 4]])

# 權重矩陣
W_q1 = np.array([[0.1, 0.2], [0.3, 0.4]])
W_q2 = np.array([[0.5, 0.6], [0.7, 0.8]])

# 計算查詢矩陣 Q1 和 Q2
Q1 = np.dot(X, W_q1)
Q2 = np.dot(X, W_q2)

print("查詢矩陣 Q1:")
print(Q1)
print("查詢矩陣 Q2:")
print(Q2)

查詢矩陣的合併

在計算出查詢矩陣 $Q_1$ 和 $Q_2$ 後,需要將其合併成一個單一的查詢矩陣 $Q$。這可以透過將 $Q_1$ 和 $Q_2$ 的元素進行合併實作。

# 合併查詢矩陣 Q1 和 Q2
Q = np.concatenate((Q1, Q2), axis=1)

print("合併查詢矩陣 Q:")
print(Q)

多頭注意力機制的實作

在多頭注意力機制中,需要對輸入資料進行多次矩陣乘法運算,以便從輸入資料中提取出不同的特徵。具體來說,需要對輸入資料進行兩次矩陣乘法,以獲得兩個查詢矩陣 $Q_1$ 和 $Q_2$。然後,需要將查詢矩陣 $Q_1$ 和 $Q_2$ 合併成一個單一的查詢矩陣 $Q$。

內容解密:

  • 首先,需要計算查詢矩陣 $Q_1$ 和 $Q_2$。這可以透過對輸入資料 $X$ 進行兩次矩陣乘法實作。
  • 然後,需要將查詢矩陣 $Q_1$ 和 $Q_2$ 合併成一個單一的查詢矩陣 $Q$。
  • 最終,需要對查詢矩陣 $Q$ 進行處理,以便從輸入資料中提取出不同的特徵。

圖表翻譯:

  graph LR
    A[輸入資料 X] -->|矩陣乘法|> B[查詢矩陣 Q1]
    A -->|矩陣乘法|> C[查詢矩陣 Q2]
    B -->|合併|> D[合併查詢矩陣 Q]
    C -->|合併|> D

在上述圖表中,輸入資料 $X$ 進行兩次矩陣乘法,以獲得查詢矩陣 $Q_1$ 和 $Q_2$。然後,查詢矩陣 $Q_1$ 和 $Q_2$ 合併成一個單一的查詢矩陣 $Q$。

多頭注意力機制的實作

在多頭注意力(MultiheadAttention)機制中,我們首先需要了解如何將單頭注意力機制延伸到多頭注意力機制。這涉及到對輸入資料的處理和權重矩陣的初始化。

初始化權重矩陣

在初始化多頭注意力機制時,我們需要為查詢(query)、鍵(key)和值(value)分別初始化權重矩陣。這些權重矩陣將用於將輸入資料轉換為查詢、鍵和值向量。

查詢、鍵和值的計算

給定輸入資料,我們可以計算出查詢、鍵和值矩陣。這些矩陣的形狀取決於批次大小(batch size)、頭數(number of heads)、token數量(number of tokens)和頭維度(head dimension)。

多頭注意力的實作

多頭注意力機制的核心思想是將單頭注意力機制應用於多個頭上,每個頭負責捕捉不同方面的資訊。這可以透過對輸入資料進行線性變換並將結果分割為多個頭來實作。

線性變換和分割

對於查詢、鍵和值,我們分別進行線性變換,然後將結果分割為多個頭。這樣,每個頭都有一個對應的查詢、鍵和值矩陣。

矩陣乘法

多頭注意力機制中,矩陣乘法操作在查詢和鍵之間進行,以計算注意力權重。這個過程可以透過批次矩陣乘法來實作,PyTorch中的@運運算元或torch.matmul()函式可以用於此目的。

注意力權重的計算

透過矩陣乘法,我們可以計算出注意力權重,這些權重代表了不同token之間的相關性。

輸出計算

最後,透過將值矩陣與注意力權重進行點積,可以計算出多頭注意力機制的輸出。

實作細節

在實作多頭注意力機制時,需要注意輸入資料的形狀和權重矩陣的初始化。另外,矩陣乘法的實作也需要考慮批次大小和頭數,以確保正確性和效率。

內容解密:

import torch

# 初始化權重矩陣
Wq = torch.randn(1, 2, 3, 4)
Wk = torch.randn(1, 2, 3, 4)
Wv = torch.randn(1, 2, 3, 4)

# 查詢、鍵和值的計算
Q = torch.matmul(Wq, torch.randn(1, 2, 3, 4))
K = torch.matmul(Wk, torch.randn(1, 2, 3, 4))
V = torch.matmul(Wv, torch.randn(1, 2, 3, 4))

# 多頭注意力的實作
Q1, Q2 = Q.split(1, dim=1)
K1, K2 = K.split(1, dim=1)
V1, V2 = V.split(1, dim=1)

# 矩陣乘法
attention_weights = torch.matmul(Q1, K1.transpose(-1, -2))

# 注意力權重的計算
attention_weights = attention_weights / math.sqrt(K1.size(-1))

# 輸出計算
output = torch.matmul(attention_weights, V1)

圖表翻譯:

  graph LR
    A[查詢] -->|線性變換|> B[查詢矩陣]
    C[鍵] -->|線性變換|> D[鍵矩陣]
    E[值] -->|線性變換|> F[值矩陣]
    B -->|矩陣乘法|> G[注意力權重]
    G -->|點積|> H[輸出]

多頭注意力機制的實作

多頭注意力機制(MultiHeadAttention)是一種常見的注意力機制,能夠將輸入序列分成多個頭部,每個頭部都會計算注意力權重和上下文向量。這些上下文向量會被合併起來,形成最終的輸出。

多頭注意力機制的計算過程

首先,我們需要計算每個頭部的注意力權重和上下文向量。這個過程涉及到矩陣乘法和轉置操作。假設我們有兩個頭部,分別是 first_headsecond_head,我們可以計算它們的注意力權重和上下文向量如下:

first_res = first_head @ first_head.T
print("First head:\n", first_res)

second_res = second_head @ second_head.T
print("\nSecond head:\n", second_res)

這兩個頭部的注意力權重和上下文向量計算結果如下:

First head:
tensor([[1.3208, 1.1631, 1.2879],
        [1.1631, 2.2150, 1.8424],
        [1.2879, 1.8424, 2.0402]])

Second head:
tensor([[0.4391, 0.7003, 0.5903],
        [0.7003, 1.3737, 1.0620],
        [0.5903, 1.0620, 0.9912]])

多頭注意力機制的實作

多頭注意力機制的實作涉及到多個步驟,包括計算注意力權重和上下文向量、合併頭部輸出、以及新增輸出投影層。以下是多頭注意力機制的實作程式碼:

class MultiHeadAttention(nn.Module):
    def __init__(self, d_in, d_out, context_length, dropout, num_heads):
        super(MultiHeadAttention, self).__init__()
        self.W_key = nn.Linear(d_in, d_out)
        self.W_query = nn.Linear(d_in, d_out)
        self.W_value = nn.Linear(d_in, d_out)
        self.out_proj = nn.Linear(d_out, d_out)
        self.dropout = nn.Dropout(dropout)
        self.num_heads = num_heads

    def forward(self, x):
        # 計算注意力權重和上下文向量
        keys = self.W_key(x)
        queries = self.W_query(x)
        values = self.W_value(x)

        # 合併頭部輸出
        context_vectors = []
        for i in range(self.num_heads):
            attention_weights = torch.matmul(queries, keys.T) / math.sqrt(d_out)
            attention_weights = attention_weights.softmax(dim=-1)
            context_vector = torch.matmul(attention_weights, values)
            context_vectors.append(context_vector)

        # 新增輸出投影層
        output = self.out_proj(torch.cat(context_vectors, dim=-1))
        return output

這個實作中,我們使用了線性層(nn.Linear)來計算注意力權重和上下文向量,並使用了softmax函式來計算注意力權重。合併頭部輸出的過程中,我們使用了矩陣乘法和轉置操作。最後,我們增加了一個輸出投影層來形成最終的輸出。

使用多頭注意力機制

多頭注意力機制可以用於各種自然語言處理任務,例如文字分類別、語言模型等。以下是使用多頭注意力機制的示例程式碼:

torch.manual_seed(123)

batch_size, context_length, d_in = batch.shape

d_out = 2
mha = MultiHeadAttention(d_in, d_out, context_length, 0.0, num_heads=2)
output = mha(batch)

在這個示例中,我們建立了一個多頭注意力機制例項,並將輸入序列傳入其中。輸出結果是最終的輸出向量,可以用於下游任務。

多頭注意力機制的實作和應用

在自然語言處理和深度學習中,注意力機制(Attention Mechanism)是一種重要的技術,用於將輸入元素轉換為增強的上下文向量表示。這種表示結合了所有輸入元素的資訊,可以更好地捕捉輸入序列之間的關係。

注意力機制的基本概念

注意力機制可以分為兩種:自注意力機制(Self-Attention Mechanism)和簡化注意力機制(Simplified Attention Mechanism)。自注意力機制計算上下文向量表示作為輸入元素的加權和,其中權重是透過點積計算得到的。簡化注意力機制則使用點積來計算注意力權重。

多頭注意力機制的實作

多頭注意力機制(Multi-Head Attention Mechanism)是自注意力機制的一種變體,它涉及多個注意力頭,每個頭計算輸入元素的不同方面。這種機制可以更好地捕捉輸入序列之間的複雜關係。

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

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

    def forward(self, batch):
        # 將輸入batch轉換為查詢、鍵和值
        queries = self.query_linear(batch)
        keys = self.key_linear(batch)
        values = self.value_linear(batch)

        # 計算注意力權重
        attention_weights = torch.matmul(queries, keys.T) / math.sqrt(self.embedding_size)

        # 將注意力權重應用於值
        context_vectors = torch.matmul(attention_weights, values)

        # 將結果轉換為最終輸出
        output = self.dropout(context_vectors)

        return output

GPT-2 模型的實作

GPT-2 模型是一種根據變換器(Transformer)的語言模型,它涉及多個注意力層和全連線層。以下是 GPT-2 模型的基本實作:

class GPT2Model(nn.Module):
    def __init__(self, num_heads, embedding_size, num_layers):
        super(GPT2Model, self).__init__()
        self.num_heads = num_heads
        self.embedding_size = embedding_size
        self.num_layers = num_layers
        self.attention_layers = nn.ModuleList([MultiHeadAttention(num_heads, embedding_size) for _ in range(num_layers)])
        self.feed_forward_layers = nn.ModuleList([nn.Linear(embedding_size, embedding_size) for _ in range(num_layers)])

    def forward(self, batch):
        # 將輸入batch轉換為嵌入向量
        embeddings = batch

        # 遍歷注意力層和全連線層
        for i in range(self.num_layers):
            # 注意力層
            attention_output = self.attention_layers[i](embeddings)

            # 全連線層
            feed_forward_output = self.feed_forward_layers[i](attention_output)

            # 將結果轉換為最終輸出
            embeddings = feed_forward_output

        return embeddings

練習和應用

使用 MultiHeadAttention 類別初始化一個具有 12 個注意力頭和 768 維嵌入大小的多頭注意力模組。然後,使用這個模組實作一個 GPT-2 模型,並訓練它生成人類般的文字。

從技術架構視角來看,多頭注意力機制透過分割輸入資料並應用多個注意力頭,有效捕捉了不同子空間的特徵資訊,提升了模型的表達能力。分析其核心運作機制,可以發現權重矩陣的初始化、查詢/鍵/值的計算、分割操作、矩陣乘法和最終的輸出計算等步驟環環相扣,共同構成了多頭注意力的完整流程。然而,多頭注意力機制並非沒有限制,例如計算複雜度較高,需要更多的計算資源。對於資源受限的場景,需要仔細權衡效能和成本。對於追求極致效能的應用,可以探索更高效的矩陣運算方法或模型壓縮技術。玄貓認為,多頭注意力機製作為Transformer模型的核心元件,已經在自然語言處理領域展現出巨大的潛力,未來隨著硬體算力的提升和演算法的最佳化,其應用場景將會更加廣泛,並可能拓展到其他領域,例如影像處理和時間序列分析。