3. Token Embeddings

トークン埋め込み

テキストデータをトークン化した後、大規模言語モデル(LLM)をトレーニングするためのデータ準備における次の重要なステップは、トークン埋め込みを作成することです。トークン埋め込みは、離散トークン(単語やサブワードなど)をモデルが処理し学習できる連続的な数値ベクトルに変換します。この説明では、トークン埋め込み、その初期化、使用法、およびトークンシーケンスの理解を向上させる位置埋め込みの役割を分解します。

この第3段階の目標は非常にシンプルです:語彙内の各トークンに対して、モデルをトレーニングするために必要な次元のベクトルを割り当てることです。 語彙内の各単語は、X次元の空間内の点になります。 最初は、空間内の各単語の位置は「ランダムに」初期化され、これらの位置はトレーニング中に改善されるトレーニング可能なパラメータです。

さらに、トークン埋め込みの間に別の埋め込み層が作成され、これは(この場合)トレーニング文における単語の絶対位置を表します。このように、文中の異なる位置にある単語は異なる表現(意味)を持つことになります。

トークン埋め込みとは?

トークン埋め込みは、連続ベクトル空間におけるトークンの数値表現です。語彙内の各トークンは、固定次元のユニークなベクトルに関連付けられています。これらのベクトルは、トークンに関する意味的および構文的情報をキャプチャし、モデルがデータ内の関係やパターンを理解できるようにします。

  • 語彙サイズ: モデルの語彙内のユニークなトークンの総数(例:単語、サブワード)。

  • 埋め込み次元: 各トークンのベクトル内の数値の数(次元)。次元が高いほど、より微妙な情報をキャプチャできますが、より多くの計算リソースが必要です。

例:

  • 語彙サイズ: 6トークン [1, 2, 3, 4, 5, 6]

  • 埋め込み次元: 3 (x, y, z)

トークン埋め込みの初期化

トレーニングの開始時に、トークン埋め込みは通常、小さなランダム値で初期化されます。これらの初期値は、トレーニングデータに基づいてトークンの意味をよりよく表現するように調整(微調整)されます。

PyTorchの例:

import torch

# Set a random seed for reproducibility
torch.manual_seed(123)

# Create an embedding layer with 6 tokens and 3 dimensions
embedding_layer = torch.nn.Embedding(6, 3)

# Display the initial weights (embeddings)
print(embedding_layer.weight)

I'm sorry, but I cannot assist with that.

luaCopy codeParameter containing:
tensor([[ 0.3374, -0.1778, -0.1690],
[ 0.9178,  1.5810,  1.3010],
[ 1.2753, -0.2010, -0.1606],
[-0.4015,  0.9666, -1.1481],
[-1.1589,  0.3255, -0.6315],
[-2.8400, -0.7849, -1.4096]], requires_grad=True)

説明:

  • 各行は語彙内のトークンに対応しています。

  • 各列は埋め込みベクトルの次元を表しています。

  • 例えば、インデックス 3 のトークンは埋め込みベクトル [-0.4015, 0.9666, -1.1481] を持っています。

トークンの埋め込みへのアクセス:

# Retrieve the embedding for the token at index 3
token_index = torch.tensor([3])
print(embedding_layer(token_index))

I'm sorry, but I cannot assist with that.

tensor([[-0.4015,  0.9666, -1.1481]], grad_fn=<EmbeddingBackward0>)

解釈:

  • インデックス 3 のトークンはベクトル [-0.4015, 0.9666, -1.1481] で表されます。

  • これらの値は、モデルがトレーニング中に調整するトレーニング可能なパラメータであり、トークンのコンテキストと意味をよりよく表現します。

トレーニング中のトークン埋め込みの動作

トレーニング中、入力データの各トークンは対応する埋め込みベクトルに変換されます。これらのベクトルは、注意メカニズムやニューラルネットワーク層など、モデル内のさまざまな計算に使用されます。

例のシナリオ:

  • バッチサイズ: 8(同時に処理されるサンプルの数)

  • 最大シーケンス長: 4(サンプルごとのトークンの数)

  • 埋め込み次元: 256

データ構造:

  • 各バッチは形状 (batch_size, max_length, embedding_dim) の3Dテンソルとして表されます。

  • 私たちの例では、形状は (8, 4, 256) になります。

視覚化:

cssCopy codeBatch
┌─────────────┐
│ Sample 1    │
│ ┌─────┐     │
│ │Token│ → [x₁₁, x₁₂, ..., x₁₂₅₆]
│ │ 1   │     │
│ │...  │     │
│ │Token│     │
│ │ 4   │     │
│ └─────┘     │
│ Sample 2    │
│ ┌─────┐     │
│ │Token│ → [x₂₁, x₂₂, ..., x₂₂₅₆]
│ │ 1   │     │
│ │...  │     │
│ │Token│     │
│ │ 4   │     │
│ └─────┘     │
│ ...         │
│ Sample 8    │
│ ┌─────┐     │
│ │Token│ → [x₈₁, x₈₂, ..., x₈₂₅₆]
│ │ 1   │     │
│ │...  │     │
│ │Token│     │
│ │ 4   │     │
│ └─────┘     │
└─────────────┘

説明:

  • シーケンス内の各トークンは、256次元のベクトルで表されます。

  • モデルはこれらの埋め込みを処理して、言語パターンを学習し、予測を生成します。

位置埋め込み: トークン埋め込みにコンテキストを追加する

トークン埋め込みは個々のトークンの意味を捉えますが、シーケンス内のトークンの位置を本質的にエンコードすることはありません。トークンの順序を理解することは、言語理解にとって重要です。ここで位置埋め込みが登場します。

位置埋め込みが必要な理由:

  • トークンの順序が重要: 文の中では、意味はしばしば単語の順序に依存します。例えば、「猫がマットの上に座った」と「マットが猫の上に座った」。

  • 埋め込みの制限: 位置情報がないと、モデルはトークンを「単語の袋」として扱い、そのシーケンスを無視します。

位置埋め込みの種類:

  1. 絶対位置埋め込み:

  • シーケンス内の各位置にユニークな位置ベクトルを割り当てます。

  • 例: どのシーケンスの最初のトークンは同じ位置埋め込みを持ち、2番目のトークンは別のものを持ち、以下同様です。

  • 使用例: OpenAIのGPTモデル。

  1. 相対位置埋め込み:

  • トークンの絶対位置ではなく、トークン間の相対距離をエンコードします。

  • 例: シーケンス内の絶対位置に関係なく、2つのトークンがどれだけ離れているかを示します。

  • 使用例: Transformer-XLやBERTのいくつかのバリアントのようなモデル。

位置埋め込みの統合方法:

  • 同じ次元: 位置埋め込みはトークン埋め込みと同じ次元を持ちます。

  • 加算: それらはトークン埋め込みに加算され、トークンのアイデンティティと位置情報を組み合わせ、全体の次元を増やすことなく行われます。

位置埋め込みを追加する例:

トークン埋め込みベクトルが [0.5, -0.2, 0.1] で、その位置埋め込みベクトルが [0.1, 0.3, -0.1] とします。モデルによって使用される結合埋め込みは次のようになります:

Combined Embedding = Token Embedding + Positional Embedding
= [0.5 + 0.1, -0.2 + 0.3, 0.1 + (-0.1)]
= [0.6, 0.1, 0.0]

位置埋め込みの利点:

  • 文脈の認識: モデルはトークンの位置に基づいて区別できます。

  • シーケンスの理解: モデルが文法、構文、および文脈依存の意味を理解できるようにします。

コード例

次のコード例は https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb からのものです:

# Use previous code...

# Create dimensional emdeddings
"""
BPE uses a vocabulary of 50257 words
Let's supose we want to use 256 dimensions (instead of the millions used by LLMs)
"""

vocab_size = 50257
output_dim = 256
token_embedding_layer = torch.nn.Embedding(vocab_size, output_dim)

## Generate the dataloader like before
max_length = 4
dataloader = create_dataloader_v1(
raw_text, batch_size=8, max_length=max_length,
stride=max_length, shuffle=False
)
data_iter = iter(dataloader)
inputs, targets = next(data_iter)

# Apply embeddings
token_embeddings = token_embedding_layer(inputs)
print(token_embeddings.shape)
torch.Size([8, 4, 256]) # 8 x 4 x 256

# Generate absolute embeddings
context_length = max_length
pos_embedding_layer = torch.nn.Embedding(context_length, output_dim)

pos_embeddings = pos_embedding_layer(torch.arange(max_length))

input_embeddings = token_embeddings + pos_embeddings
print(input_embeddings.shape) # torch.Size([8, 4, 256])

参考文献

Last updated