O avanço do Processamento de Linguagem Natural (PLN) nos últimos anos, impulsionado por modelos como GPT-4 e Claude, fundamenta-se na capacidade das máquinas de interpretar a linguagem humana. O pilar dessa itnerpretação é a transformação de palavras em representações numéricas, processo conhecido como Word Embeddings (incorporação de palavras).
Diferente de métodos simples como o Bag-of-Words ou a codificação One-Hot, os Word Embeddings permitem que algoritmos capturem relações semânticas entre termos de forma autossupervisionada. Isso significa que o sistema aprende que "rei" e "rainha" possuem uma proximidade contextual sem intervenção humana direta.
A Estrutura dos Word Embeddings
A construção de um modelo de incorporação geralmente segue dois estágios principais:
- Vetorização Esparsa: Inicialmente, as palavras são convertidas em vetores One-Hot, resultando em uma matriz vasta onde cada palavra é representada por um único bit ligado (1) em uma posição específica.
- Aprendizado de Representação Densiva: Através de redes neurais, como o algoritmo Skip-gram, o modelo aprende a prever o contexto de uma palavra-alvo. O resultado é uma matriz de pesos (o embedding) onde cada palavra é representada por um vetor denso, geralmente de 100 a 300 dimensões.
Para lidar com o alto custo computacional de calcular probabilidades em vocabulários imensos, utilizam-se técnicas como Negative Sampling (amostragem negativa) e Hierarchical Softmax. A primeira foca em distinguir a palavra correta de um pequeno conjunto de palavras incorretas, enquanto a segunda utiliza estruturas de árvore para reduzir a complexidade da busca de \(O(V)\) para \(O(\log V)\).
Redução de Dimensionalidade com PCA
Visualizar vetores de 300 dimensões é impossível para seres humanos. Para compreender como o modelo está agrupando as palavras, utilizamos o PCA (Principle Component Analysis). O PCA é um algoritmo de aprendizado não supervisionado que projeta dados de alta dimensão em um espaço menor (como 2D ou 3D), preservando a maior variância possível.
O fluxo lógico do PCA consiste em:
- Normalização dos dados (centralização na média).
- Cálculo da matriz de covariância.
- Decomposição de autovalores e autovetores (ou SVD).
- Projeção dos dados originais nos autovetores principais.
Abaixo, uma implementação funcional do PCA utilizando NumPy:
import numpy as np
def reduzir_dimensao_pca(matriz_entrada, dim_saida=2):
"""
Reduz a dimensionalidade de vetores de palavras.
"""
# Centralização dos dados
matriz_centralizada = matriz_entrada - np.mean(matriz_entrada, axis=0)
# Matriz de covariância
matriz_cov = np.cov(matriz_centralizada, rowvar=False)
# Cálculo de autovalores e autovetores
autovalores, autovetores = np.linalg.eigh(matriz_cov)
# Ordenação decrescente baseada nos autovalores
indices_ordenados = np.argsort(autovalores)[::-1]
autovetores_topo = autovetores[:, indices_ordenados[:dim_saida]]
# Projeção final
dados_reduzidos = np.dot(matriz_centralizada, autovetores_topo)
return dados_reduzidos
Implementação Prática de Word2Vec
Para aplicar Word Embeddings em cenários reais, utilizamos bibliotecas como Gensim e NLTK. O primeiro passo é o pré-processamento para limpar ruídos como tags HTML e caracteres especiais.
import re
from bs4 import BeautifulSoup
from nltk.corpus import stopwords
def filtrar_sentenca(texto_bruto):
# Remove HTML
texto_puro = BeautifulSoup(texto_bruto, "html.parser").get_text()
# Mantém apenas letras
letras = re.sub("[^a-zA-Z]", " ", texto_puro)
# Tokenização e remoção de stopwords
palavras = letras.lower().split()
stops = set(stopwords.words("english"))
return [p for p in palavras if p not in stops]
Após o tratamento dos dados, configuramos e treinamos o modelo Word2Vec. Os parâmetros principais incluem o tamanho do vetor (vector_size), a janela de contexto (window) e a contagem mínima de ocorrências (min_count).
from gensim.models import Word2Vec
# Configurações do modelo
params = {
"vector_size": 300,
"min_count": 40,
"window": 10,
"workers": 4,
"sg": 1 # 1 para Skip-gram
}
# Supondo que 'corpus_tokens' seja uma lista de listas de palavras
modelo_w2v = Word2Vec(sentences=corpus_tokens, **params)
# Otimização de memória após o treino
modelo_w2v.init_sims(replace=True)
# Testando similaridade semântica
resultado = modelo_w2v.wv.most_similar("king")
print(resultado)
Ao treinar com um volume de dados robusto, o modelo é capaz de identificar relações complexas. Por exemplo, ao buscar termos próximos a "boy" (garoto), o modelo retornará naturalmente palavras como "girl", "teenager" ou "son", demonstrando que a estrutura matemática do embedding capturou com sucesso o significado contextual das palavras.