3. Token Embeddings

Token Embeddings

Após a tokenização dos dados textuais, o próximo passo crítico na preparação de dados para treinar grandes modelos de linguagem (LLMs) como o GPT é criar token embeddings. Token embeddings transformam tokens discretos (como palavras ou subpalavras) em vetores numéricos contínuos que o modelo pode processar e aprender. Esta explicação detalha token embeddings, sua inicialização, uso e o papel dos embeddings posicionais em melhorar a compreensão do modelo sobre sequências de tokens.

O objetivo desta terceira fase é muito simples: Atribuir a cada um dos tokens anteriores no vocabulário um vetor das dimensões desejadas para treinar o modelo. Cada palavra no vocabulário será um ponto em um espaço de X dimensões. Note que inicialmente a posição de cada palavra no espaço é apenas inicializada "aleatoriamente" e essas posições são parâmetros treináveis (serão melhorados durante o treinamento).

Além disso, durante o token embedding outra camada de embeddings é criada que representa (neste caso) a posição absoluta da palavra na frase de treinamento. Dessa forma, uma palavra em diferentes posições na frase terá uma representação (significado) diferente.

O Que São Token Embeddings?

Token Embeddings são representações numéricas de tokens em um espaço vetorial contínuo. Cada token no vocabulário está associado a um vetor único de dimensões fixas. Esses vetores capturam informações semânticas e sintáticas sobre os tokens, permitindo que o modelo entenda relacionamentos e padrões nos dados.

  • Tamanho do Vocabulário: O número total de tokens únicos (por exemplo, palavras, subpalavras) no vocabulário do modelo.

  • Dimensões do Embedding: O número de valores numéricos (dimensões) no vetor de cada token. Dimensões mais altas podem capturar informações mais sutis, mas requerem mais recursos computacionais.

Exemplo:

  • Tamanho do Vocabulário: 6 tokens [1, 2, 3, 4, 5, 6]

  • Dimensões do Embedding: 3 (x, y, z)

Inicializando Token Embeddings

No início do treinamento, os token embeddings são tipicamente inicializados com pequenos valores aleatórios. Esses valores iniciais são ajustados (afinados) durante o treinamento para representar melhor os significados dos tokens com base nos dados de treinamento.

Exemplo 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)

Saída:

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)

Explicação:

  • Cada linha corresponde a um token no vocabulário.

  • Cada coluna representa uma dimensão no vetor de embedding.

  • Por exemplo, o token no índice 3 tem um vetor de embedding [-0.4015, 0.9666, -1.1481].

Acessando o Embedding de um Token:

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

Saída:

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

Interpretação:

  • O token no índice 3 é representado pelo vetor [-0.4015, 0.9666, -1.1481].

  • Esses valores são parâmetros treináveis que o modelo ajustará durante o treinamento para representar melhor o contexto e o significado do token.

Como os Embeddings de Token Funcionam Durante o Treinamento

Durante o treinamento, cada token nos dados de entrada é convertido em seu vetor de embedding correspondente. Esses vetores são então usados em vários cálculos dentro do modelo, como mecanismos de atenção e camadas de rede neural.

Cenário de Exemplo:

  • Tamanho do Lote: 8 (número de amostras processadas simultaneamente)

  • Comprimento Máximo da Sequência: 4 (número de tokens por amostra)

  • Dimensões do Embedding: 256

Estrutura de Dados:

  • Cada lote é representado como um tensor 3D com forma (batch_size, max_length, embedding_dim).

  • Para nosso exemplo, a forma seria (8, 4, 256).

Visualização:

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   │     │
│ └─────┘     │
└─────────────┘

Explicação:

  • Cada token na sequência é representado por um vetor de 256 dimensões.

  • O modelo processa essas embeddings para aprender padrões de linguagem e gerar previsões.

Embeddings Posicionais: Adicionando Contexto às Embeddings de Token

Enquanto as embeddings de token capturam o significado de tokens individuais, elas não codificam inherentemente a posição dos tokens dentro de uma sequência. Compreender a ordem dos tokens é crucial para a compreensão da linguagem. É aqui que as embeddings posicionais entram em cena.

Por que as Embeddings Posicionais são Necessárias:

  • A Ordem dos Tokens Importa: Em frases, o significado muitas vezes depende da ordem das palavras. Por exemplo, "O gato sentou no tapete" vs. "O tapete sentou no gato."

  • Limitação da Embedding: Sem informações posicionais, o modelo trata os tokens como um "saco de palavras", ignorando sua sequência.

Tipos de Embeddings Posicionais:

  1. Embeddings Posicionais Absolutos:

  • Atribui um vetor de posição único a cada posição na sequência.

  • Exemplo: O primeiro token em qualquer sequência tem a mesma embedding posicional, o segundo token tem outra, e assim por diante.

  • Usado Por: Modelos GPT da OpenAI.

  1. Embeddings Posicionais Relativos:

  • Codifica a distância relativa entre tokens em vez de suas posições absolutas.

  • Exemplo: Indica quão distantes dois tokens estão, independentemente de suas posições absolutas na sequência.

  • Usado Por: Modelos como Transformer-XL e algumas variantes do BERT.

Como as Embeddings Posicionais são Integradas:

  • Mesmas Dimensões: As embeddings posicionais têm a mesma dimensionalidade que as embeddings de token.

  • Adição: Elas são adicionadas às embeddings de token, combinando a identidade do token com informações posicionais sem aumentar a dimensionalidade geral.

Exemplo de Adição de Embeddings Posicionais:

Suponha que um vetor de embedding de token seja [0.5, -0.2, 0.1] e seu vetor de embedding posicional seja [0.1, 0.3, -0.1]. A embedding combinada usada pelo modelo seria:

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

Benefícios dos Embeddings Posicionais:

  • Consciência Contextual: O modelo pode diferenciar entre tokens com base em suas posições.

  • Compreensão de Sequência: Permite que o modelo entenda gramática, sintaxe e significados dependentes do contexto.

Exemplo de Código

Seguindo com o exemplo de código de 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])

Referências

Last updated