12,584 leituras
12,584 leituras

Embeddings 101: Desbloqueio de relações semânticas em texto

por Ritesh Modi14m2025/03/27
Read on Terminal Reader
Read this story w/o Javascript

Muito longo; Para ler

Os embeddings abordam as limitações de como as máquinas entendem a linguagem. Eles não são apenas uma nova técnica fantástica – eles abordam as limitações fundamentais na compreensão da linguagem.
featured image - Embeddings 101: Desbloqueio de relações semânticas em texto
Ritesh Modi HackerNoon profile picture
0-item
1-item


Quando comecei a trabalhar com dados de texto anos atrás, todo o conceito de incorporações parecia desnecessariamente complexo. Fiquei confortável com minhas abordagens de saco de palavras e vetores TF-IDF simples.


Eu estava trabalhando com comentários de produtos, e meus modelos tradicionais continuaram classificando comentários com sarcasmo ou linguagem nuancada.O problema ficou claro: meus modelos não entenderam que "este produto está doente" poderia realmente ser positivo ou que "funcionou exatamente como esperado" poderia ser neutro ou negativo dependendo do contexto.


Eles não são apenas uma nova técnica fantástica – eles abordam limitações fundamentais em como as máquinas entendem a linguagem.


The Old Days: Life Before Embeddings

Os velhos dias: a vida antes dos embriões

Vamos entender a história de usar representações de texto antes de inserções sem entrar nos detalhes desses métodos e abordagens.

One-Hot Encoding

Representava cada palavra como um vetor escasso com todos os zeros, exceto um único "1" na posição correspondente a essa palavra em um vocabulário. Representava palavras como vetores maciços e escassos, onde cada palavra tinha sua própria dimensão. Se o seu vocabulário tinha 100.000 palavras (o que é modesto), cada vetor de palavra tinha 99,999 zeros e um único 1. Essas representações nos disseram absolutamente nada de significado. As palavras "excelente" e "fantastic" eram matematicamente tão diferentes quanto "excelente" e "terrível" - completamente ausentes das relações semânticas óbvias.


"gato" → [1, 0, 0, 0, ..., 0] (posição 5432 no vocabulário) "cão" → [0, 1, 0, 0, ..., 0] (posição 8921 no vocabulário)


Limitações

    Não
  • Explosão de dimensionalidade: os vetores tinham tantas dimensões quanto o tamanho do vocabulário (frequentemente mais de 100.000)
  • Não
  • Sem relações semânticas: "gato" e "gato" eram tão diferentes quanto "gato" e "avião" (todos equidistantes)
  • Não
  • Ineficiência computacional: Multiplicar essas matrizes escassas foi extremamente intensivo em recursos
  • Não
  • Sem generalização: o sistema não conseguiu entender palavras fora de seu vocabulário original
  • Não

Bag-of-Words Approach

Ele contava as ocorrências de palavras em documentos, às vezes ponderadas pela sua importância. Tratava as palavras em documentos como coleções de palavras não classificadas, eliminando completamente a ordem de palavras. "O cão morde o homem" e "O homem morde o cão" teriam representações idênticas.


Documento: "O gato sentado no tapete" BoW: {"o": 2, "gato": 1, "sat": 1, "on": 1, "mat": 1}

As limitações:

    Não
  • Perda de ordem de palavras: "Cão morde homem" e "Homem morde cão" tinham representações idênticas
  • Não
  • Vectores de alta dimensão: ainda são necessários vetores de tamanho de vocabulário
  • Não
  • Semântica: Sinônimos foram representados como características completamente diferentes
  • Não
  • Sem significado contextual: cada palavra tinha uma representação fixa, independentemente do contexto
  • Não

N-grams

To capture some word order, we started using n-grams (sequences of n consecutive words). It looked at sequences of N consecutive words to capture some contextual information.


Com unigrams (palavras únicas), você pode ter um vocabulário de 100.000. Com bigrams (pares de palavras), de repente você está olhando para milhões de recursos potenciais. Com trigrams? bilhões, teoricamente. Mesmo com corte agressivo, a dimensionalidade tornou-se incontrolável.

Limitations:

As limitações:
    Não
  • Explosão combinatória: o número de n-gramas possíveis cresce exponencialmente
  • Não
  • Escassez de dados: a maioria dos n-gramas possíveis nunca aparecem nos dados de treinamento
  • Não
  • Janela de contexto limitada: apenas relações capturadas dentro de janelas pequenas (tipicamente 2-5 palavras)
  • Não

TF-IDF (Term Frequency-Inverse Document Frequency)

O TF-IDF melhorou as coisas ponderando palavras com base em quão importantes elas eram para um documento específico em relação ao corpus.

Limitations:

As limitações:

Sem significado semântico: é o número e a frequência das palavras que determinam a importância de seu uso.

The Embedding Revolution: What Changed?

A Revolução Civil: o que mudou?

A transição para os embeddings não foi apenas uma melhoria incremental; foi uma mudança de paradigma na forma como representamos a linguagem.

Meaning Through Context

A visão fundamental por trás das incorporações é enganosamente simples: palavras que aparecem em contextos semelhantes provavelmente têm significados semelhantes.Se você ver "cão" e "gato" aparecendo em torno dos mesmos tipos de palavras ("animal de estimação", "alimento", "forro"), eles provavelmente estão semanticamente relacionados.


Os primeiros modelos de incorporação como o Word2Vec capturaram isso treinando redes neurais para prever:


    Não
  • Uma palavra baseada em seu contexto circundante (Saco contínuo de palavras)
  • Não
  • O contexto circundante baseado em uma palavra (Skip-gram)
  • Não


Os pesos de camada ocultos desses modelos tornaram-se nossos vetores de palavras, codificando relações semânticas nas propriedades geométricas do espaço vetorial.


Quando eu comecei a traçar os vetores de palavras e vi que "rei" - "homem" + "mulher" ≈ "rei", eu sabia que estávamos em algo revolucionário.


Os primeiros modelos como Word2Vec e GloVe deram a cada palavra um único vetor, independentemente do contexto.


"I need to bank the money" vs. "I'll meet you by the river bank"


Modelos como BERT e GPT resolveram isso gerando diferentes inserções para a mesma palavra dependendo do seu contexto circundante.


Então, primeiro vamos entender o que são os embeddings e como eles transformaram a NLP e abordaram as limitações das abordagens anteriores.

What Are Embeddings?

O que são Embeddings?

Os embeddings são representações numéricas de dados (texto, imagens, áudio, etc.) em um espaço vetorial contínuo.Para o texto, os embeddings capturam relações semânticas entre palavras ou documentos, permitindo que as máquinas entendam o significado de uma forma que é matematicamente processável.

Key Concepts:

    Não
  • Vectores: listas ordenadas de números que representam um ponto no espaço multidimensional
  • Não
  • Dimensões: O número de valores em cada vetor (por exemplo, 768-dim, 1024-dim)
  • Não
  • Espaço vetorial: o espaço matemático onde existem embeddings
  • Não
  • Semântica: medida pela distância ou ângulo entre os vectores (mais próximo = mais semelhante)
  • Não

What Do Dimensions Represent?

Cada dimensão em um vetor de incorporação representa um recurso ou aspecto aprendido dos dados. Ao contrário da engenharia de características clássica, onde os seres humanos definem o que cada dimensão significa, em modelos modernos de incorporação:


    Não
  • Dimensões emergem durante o treinamento para representar "conceitos" abstratos
  • Não
  • As dimensões individuais muitas vezes carecem de significado humano-interpretável específico
  • Não
  • O vetor completo, no entanto, captura informação semântica holisticamente
  • Não
  • Algumas dimensões podem corresponder ao sentimento, formalidade, tópico ou sintaxe, mas a maioria representa combinações complexas de características.
  • Não

Why We Need Embeddings

Os computadores basicamente trabalham com números, não palavras.Quando processamos linguagem, precisamos converter texto em representações numéricas que:


    Não
  1. Capturar relações semânticas – conceitos semelhantes devem ter representações semelhantes
  2. Não
  3. Manter o significado contextual – A mesma palavra pode significar coisas diferentes em contextos diferentes
  4. Não
  5. Ativar operações matemáticas – como encontrar semelhanças ou executar analogias
  6. Não
  7. Trabalhar de forma eficiente em escala – Processar grandes volumes de texto sem explosão computacional
  8. Não


Os embeddings resolvem esses problemas representando palavras, frases ou documentos como vetores densos em um espaço contínuo onde as relações semânticas são preservadas como relações geométricas.

Fundamentos de Embeddings

Representação do vetor dense

Em vez de vetores escassos com milhares ou milhões de dimensões, os embeddings usam algumas centenas de dimensões densas, onde cada dimensão contribui para o significado.


"cat" → [0.2, -0.4, 0.1, -0.8, ..., 0.3] (300 dimensions)

"kitten" → [0.19, -0.38, 0.15, -0.75, ..., 0.29] (similar to "cat")


Isso torna as ordens de computação de magnitude mais eficientes, permitindo uma representação semântica mais rica.

Semântica Distributiva

Os embeddings são construídos sobre o princípio de que "você saberá uma palavra pela empresa que mantém" (J.R. Firth). Ao analisar quais palavras aparecem em contextos similares, os embeddings capturam relações semânticas automaticamente.


Por exemplo, "rei" e "rei" terão contextos semelhantes, então eles terão inserções semelhantes, embora raramente apareçam na mesma posição exata.

Propriedades matemáticas

Os espaços incorporados têm propriedades matemáticas notáveis:


vector("king") - vector("man") + vector("woman") ≈ vector("queen")


Isso permite raciocínio analógico e operações semânticas diretamente no espaço vetorial.

Transferência de aprendizagem

Os embeddings pré-treinados capturam conhecimentos gerais de linguagem que podem ser ajustados para tarefas específicas, reduzindo drasticamente os dados necessários para novas aplicações.

Entendimento Contextual

As incorporações contextuais modernas (como as da BERT, GPT, etc.) representam a mesma palavra de forma diferente com base no contexto:


"I'll deposit money in the bank" → "bank" relates to finance

"I'll sit by the river bank" → "bank" relates to geography


With all the knowledge about the history and understanding of embeddings, it’s time to get down to using them.

Use os Modelos LLM/SLM para gerar embeddings

Várias equipes de pesquisa desenvolveram modelos de incorporação treinados em vários conjuntos de dados que abrangem vários idiomas e domínios. Esta diversidade resulta em modelos com vocabulários muito diferentes e capacidades de compreensão semântica. Por exemplo, modelos treinados predominantemente em literatura científica inglesa codificarão conceitos técnicos de forma diferente daqueles treinados em conteúdo de mídia social multilíngue. Esta especialização permite que os profissionais selecionem modelos de incorporação que melhor se alinham com seus casos de uso específicos.


A implementação prática de embeddings foi muito simplificada por bibliotecas como o pacote SentenceTransformer da Hugging Face, que fornece um SDK abrangente para trabalhar com vários modelos de embedding. Da mesma forma, o SDK da OpenAI oferece acesso direto aos seus modelos de embedding, que mostraram desempenho impressionante em muitos benchmarks. Essas ferramentas, e há muitos mais, têm acesso democratizado a tecnologias de embedding de última geração, permitindo que os desenvolvedores integram a compreensão semântica em aplicações sem ter que treinar modelos a partir do zero.


Os modelos, por causa deste artigo, devem ser tratados como uma caixa preta que toma sentenças como uma entrada e retorna sua representação vetorial correspondente.

Usando a SentenceTransformers Library para Embeddings

A maneira mais simples de gerar embeddings usando SentenceTransformer:

from sentence_transformers import SentenceTransformer

# Load a pre-trained model
model = SentenceTransformer('all-MiniLM-L6-v2')  # 384 dimensions

# Generate embeddings
texts = ["This is an example sentence", "Each sentence becomes a vector"]

embeddings = model.encode(texts)

print(f"Shape: {embeddings.shape}")  # (2, 384)

max_seq_length = model.tokenizer.model_max_length

print(max_seq_length) # 256


​​O modelo “all-MiniLM-L6-v2” disponível da HuggingFace tem 384 dimensões. Isso significa que ele pode capturar 384 características ou nuances para uma determinada palavra ou frase. O comprimento de sequência deste modelo é de 256 tokens. As sentenças são divididas em palavras e palavras em tokens pelo tokenizador durante o processo de incorporação. O número de tokens gerados para uma frase é geralmente 25% a 40% mais do que o número de palavras na frase.


O comprimento da sequência denota o número de tokens que podem ser processados pelo modelo como entrada dada. Qualquer coisa menos é padded para torná-lo 256 em comprimento, e qualquer coisa mais é descartado.


O método de codificação da classe SentenceTransformer é um envelope no modo de inferência PyTorch para usar o modelo.


from sentence_transformers import SentenceTransformer
import torch

# Load the model directly with SentenceTransformer
model = SentenceTransformer("sentence-transformers/msmarco-distilbert-base-tas-b")

# Input text
texts = ["This is an example sentence", "Each sentence becomes a vector"]

# Get embedding directly
with torch.no_grad():
    embedding = model.encode(texts, convert_to_tensor=True)
print(embedding)


Aqui, a função torch.no_grad garante que não sejam calculados gradientes durante a propagação traseira.


Outra maneira mais genérica de gerar embeddings usando o PyTorch:


# Load the model
model = AutoModel.from_pretrained("sentence-transformers/msmarco-distilbert-base-tas-b")

# Get the tokenizer
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/msmarco-distilbert-base-tas-b")

# Tokenize input
text = ["This is an example sentence"]
encoded_input = tokenizer(text, padding=True, truncation=True, return_tensors='pt')

# Get embedding of the [CLS] token
with torch.no_grad():
    outputs = model(**encoded_input, return_dict=True)
    cls_embedding = outputs.last_hidden_state[:, 0]
print(cls_embedding)


A diferença entre este e fragmentos de código anteriores é que a função de codificação foi substituída por usar tokenizer e modelo explicitamente.


Outra diferença é que estamos usando outputs.last_hidden_state[:, 0] para recuperar o vetor relacionado ao token CLS. Este token especial CLS é adicionado a cada sentença no início de cada sentença, e contém informações acumuladas sobre a sentença inteira.


Deve-se notar que esta abordagem de adição de um token CLS é aplicável apenas a certas arquiteturas baseadas em transformadores, e isso inclui BERT e suas variantes e transformadores baseados apenas em codificadores.


Best for:Tarefas de Classificação e Previsão de Nível de Sequência


Why they work:O token [CLS] nos modelos de estilo BERT é especificamente treinado para agregar informações de toda a sequência durante o pré-treinamento.


When to choose:

    Não
  • Quando se utilizam modelos BERT, RoBERTa ou similares para a classificação
  • Não
  • Quando você precisa de um único vetor que represente uma seqüência inteira
  • Não
  • Quando sua tarefa subsequente envolve prever uma propriedade de todo o texto
  • Não


O método CLS usado é apenas um dos métodos para capturar as incorporações para uma sentença.

Mean Pooling

Tomar a média de todas as incorporações de token é surpreendentemente eficaz para muitas tarefas.É o meu método go-to quando estou usando incorporações para tarefas de semelhança ou recuperação.


Best for:Semântica de semelhança, recuperação e representações de propósito geral.


Why it works:Ao medir em todas as representações de token, o pooling médio capta o conteúdo semântico coletivo enquanto reduz o ruído.


When to choose:

    Não
  • Para aplicações de semelhança de documentos ou de pesquisa semântica
  • Não
  • Quando você precisa de representações robustas que não são dominadas por nenhum token único
  • Quando o teste empírico mostra que ele supera outros métodos (muitas vezes faz para tarefas de semelhança)
  • Não


import torch
from transformers import AutoTokenizer, AutoModel

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Tokenize input
texts = ["This is an example sentence", "Each sentence becomes a vector"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Mean pooling
with torch.no_grad():
    outputs = model(**inputs)
    
    # Get attention mask to ignore padding tokens
    attention_mask = inputs['attention_mask']
    
    # Sum token embeddings and divide by the number of tokens
    sum_embeddings = torch.sum(outputs.last_hidden_state * attention_mask.unsqueeze(-1), dim=1)
    count_tokens = torch.sum(attention_mask, dim=1, keepdim=True)
    mean_embeddings = sum_embeddings / count_tokens

print(f"Shape: {mean_embeddings.shape}")  # (2, 768)


Max Pooling

Max pooling leva o valor máximo para cada dimensão em todos os tokens.É surpreendentemente bom em capturar recursos importantes, independentemente de onde eles aparecem no texto.


Best for:Detecção de recursos e tarefas de extração de informações


Why it works:O Max pooling seleciona a ativação mais forte para cada dimensão em todos os tokens, capturando efetivamente os recursos mais proeminentes, independentemente de onde eles aparecem no texto.


When to choose:

    Não
  • Quando características específicas importam mais do que sua frequência ou posição
  • Não
  • Ao procurar a presença de conceitos ou entidades particulares
  • Não
  • Ao lidar com textos longos onde sinais importantes podem ser diluídos na média
  • Não


import torch
from transformers import AutoTokenizer, AutoModel

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Tokenize input
texts = ["This is an example sentence", "Each sentence becomes a vector"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Max pooling
with torch.no_grad():
    outputs = model(**inputs)
    
    # Create a mask to ignore padding tokens for max pooling
    attention_mask = inputs['attention_mask'].unsqueeze(-1)
    
    # Replace padding token representations with -inf so they're never selected as max
    token_embeddings = outputs.last_hidden_state.masked_fill(attention_mask == 0, -1e9)
    
    # Take max over token dimension
    max_embeddings = torch.max(token_embeddings, dim=1)[0]

print(f"Shape: {max_embeddings.shape}")  # (2, 768)

Weighted Mean Pooling

O método de agrupamento ponderado tenta dar mais peso a tokens mais importantes com base na posição (por exemplo, dando mais peso a tokens posteriores).


Best for:Tarefas onde diferentes partes da entrada têm importância diferente


Why it works:O agrupamento ponderado permite que você enfatize certos tokens com base em sua posição, pontuação de atenção ou outras métricas de relevância.


When to choose:

  • Quando a ordem de sequência importa (por exemplo, dando mais peso a tokens posteriores)
  • Não
  • Quando certos tokens são inerentemente mais informativos (por exemplo, núcleos e verbos versus artigos)
  • Não
  • Quando você tem uma importância heurística específica que faz sentido para sua tarefa
  • Não


import torch
import torch.nn.functional as F
from transformers import AutoTokenizer, AutoModel

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Tokenize input
texts = ["This is an example sentence", "Each sentence becomes a vector"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Weighted mean pooling - more weight to later tokens
with torch.no_grad():
    outputs = model(**inputs)
    
    # Get token embeddings and attention mask
    token_embeddings = outputs.last_hidden_state
    attention_mask = inputs['attention_mask']
    
    # Create position-based weights (later positions get higher weights)
    input_lengths = torch.sum(attention_mask, dim=1).unsqueeze(-1)
    position_indices = torch.arange(token_embeddings.size(1)).unsqueeze(0).expand_as(attention_mask)
    position_weights = position_indices.float() / input_lengths.float()
    position_weights = position_weights * attention_mask
    
    # Normalize weights to sum to 1
    position_weights = position_weights / torch.sum(position_weights, dim=1, keepdim=True)
    
    # Apply weights and sum
    weighted_embeddings = torch.sum(token_embeddings * position_weights.unsqueeze(-1), dim=1)

print(f"Shape: {weighted_embeddings.shape}")  # (2, 768)


Última polêmica

O último token pooling é uma técnica para criar um único vetor de incorporação a partir de uma sequência de incorporações de token selecionando apenas a representação do token final.


Best for:Modelos Autoregressivos e Processamento Sequencial


Why it works:Em modelos de esquerda para direita, como o GPT, o token final contém o contexto acumulado de toda a sequência, tornando-o rico em informações para certas tarefas.


When to choose:

    Não
  • Ao usar o GPT ou outros modelos exclusivos para decodificadores
  • Não
  • Quando se trabalha com tarefas que dependem fortemente do contexto anterior
  • Não
  • Para geração de texto ou tarefas de conclusão
  • Não


import torch
from transformers import AutoTokenizer, AutoModel

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Tokenize input
texts = ["This is an example sentence", "Each sentence becomes a vector"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Last token pooling
with torch.no_grad():
    outputs = model(**inputs)
    
    # Get the last non-padding token for each sequence
    attention_mask = inputs['attention_mask']
    last_token_indices = torch.sum(attention_mask, dim=1) - 1
    batch_indices = torch.arange(attention_mask.size(0))
    
    # Extract the last token embedding for each sequence
    last_token_embeddings = outputs.last_hidden_state[batch_indices, last_token_indices]

print(f"Shape: {last_token_embeddings.shape}")  # (2, 768)



Existem muitas outras maneiras, e esses métodos podem ser combinados juntos, bem como para criar métodos personalizados.Este foi apenas o começo para entender embeddings como um conceito e implementação básica para obter embeddings usando técnicas diferentes.

Looking Forward: Where Embeddings Are Headed

Olhando para a frente: para onde os embriões estão indo

O espaço de incorporação (pun intended) continua a evoluir:


    Não
  • Os embeddings multimodais estão quebrando barreiras entre texto, imagens, áudio e vídeo. Modelos como o CLIP e o DALL-E usam embeddings para criar um espaço semântico compartilhado entre diferentes modalidades.
  • Não
  • Arquiteturas mais eficientes, como MobileBERT e DistilBERT, estão permitindo a utilização de incorporações poderosas em dispositivos de borda com recursos limitados.
  • Não
  • Embeddings específicos de domínio pré-treinados em corpora especializada estão impulsionando o estado da arte em campos como medicina, direito e finanças.
  • Não

Estou particularmente animado com as incorporações conscientes da composição que capturam melhor como o significado é construído a partir de unidades menores, o que poderia finalmente resolver desafios de longa data com negação e frases de composição.

Final Thoughts

Pensamentos finais

Os embeddings não são apenas outra técnica de NLP – eles são uma mudança fundamental na forma como as máquinas entendem e processam a linguagem. Eles nos mudaram de tratar o texto como símbolos arbitrários para capturar a rica e complexa rede de significados e relações que os humanos entendem intuitivamente.


Seja qual for a tarefa de NLP em que você esteja trabalhando, as chances são de que as incorporações aplicadas cuidadosamente possam torná-lo melhor.A chave é entender não apenas como gerá-las, mas quando e por que usar diferentes abordagens.


E se você ainda estiver usando saco de palavras ou codificação one-hot para análise de texto...


Há um mundo inteiro de possibilidades esperando por você.

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks