ES EN
Parte I · Capítulo 03

Embeddings: de identificadores a vectores con significado

10 min de lectura · revisado en agosto 2026

En el capítulo anterior vimos cómo convertir texto en una secuencia de IDs numéricos mediante un tokenizador. Pero un ID como 5089 no es más que una etiqueta: no le dice nada al modelo sobre el significado de esa palabra, ni sobre su relación con otras. Un modelo de lenguaje no puede hacer matemáticas útiles con un simple número de casillero.

Necesitamos transformar ese ID en algo que el modelo pueda operar: un vector de números reales. Ese vector es lo que llamamos un embedding. Y lo fascinante es que, durante el entrenamiento, esos vectores se organizan en un espacio semántico donde las palabras similares quedan cerca, y las relaciones se codifican como direcciones geométricas.

De identificador a vector: la tabla de búsqueda

El paso es sencillo: cada ID actúa como un índice en una tabla (una matriz de embeddings). Esa tabla tiene una fila por cada token en el vocabulario, y cada fila es un vector de dimensión fija (por ejemplo, 50, 300, o 4096 números).

"gato" → ID 5089 → embedding[5089] = [0.10, -0.11, -0.12, 0.00, 0.05, ...]  (50 números)

Este vector no se calcula; se busca en la tabla. Es como un diccionario que asigna a cada palabra una lista de números. Al principio del entrenamiento, esos números son aleatorios: gato y perro tienen vectores tan distintos como gato y martes. No hay ninguna relación.

Pero durante el entrenamiento, el modelo ajusta estos vectores (junto con el resto de parámetros) para minimizar el error de predicción. El gradiente de la pérdida empuja a que los vectores de palabras que aparecen en contextos similares se acerquen, y los que aparecen en contextos distintos se alejen. Así, sin que nadie le diga explícitamente que gato y perro son animales, el modelo lo descubre por sí mismo a partir de las estadísticas del texto.

(En rigor, los LLMs embeben tokens, no siempre palabras completas — aquí usamos “palabras” para simplificar.)

Bajo el capó la matriz de embeddings Expandir Cerrar
import torch.nn as nn

embedding_layer = nn.Embedding(num_embeddings=vocab_size, embedding_dim=dim)
# Esta capa internamente tiene una matriz de forma (vocab_size, dim)

ids = tokenizer.encode("el gato durmió")   # [464, 5089, 3332]
x = embedding_layer(ids)                    # forma: (3, dim)
# x[0] es el vector de "el", x[1] el de "gato", x[2] el de "durmió"

No hay multiplicación ni activación: es una búsqueda pura. Los valores son parámetros entrenables, ajustados por descenso de gradiente como cualquier otro peso de la red.

El espacio semántico: cercanía como similitud de uso

Una vez entrenado, el espacio de embeddings tiene una propiedad notable: la distancia entre vectores refleja la similitud semántica (y sintáctica) de las palabras.

Si pides los vecinos más cercanos de gato, obtienes perro, conejo, mono, ratón… todos animales. Para rojo, obtienes otros colores. Para tres, otros números.

No hay un diccionario ni una etiqueta de categoría; el modelo ha inferido estas agrupaciones exclusivamente a partir de la compañía que mantiene cada palabra — la famosa idea del lingüista J.R. Firth: “conoces una palabra por la compañía que mantiene”.

Tabla ilustrativa (embeddings GloVe, inglés, resultados reales):

PalabraSimilitud (coseno) con “cat”
dog0.92
rabbit0.85
monkey0.80
mouse0.77
pig0.74
table0.12
red-0.05

Fíjate cómo cat y dog están muy cerca, mientras que table o red están muy lejos (o incluso en direcciones casi opuestas). El modelo nunca ha visto una imagen de un gato ni ha recibido una definición; solo ha leído miles de millones de textos en los que cat y dog aparecen en contextos parecidos.

Haciendo zoom out, todo el espacio se organiza en vecindarios temáticos — animales en una región, colores en otra, números, ciudades, familia, acciones, cada grupo en su propia zona — y todo esto emerge sin supervisión, solo con el objetivo de predecir la siguiente palabra.

Midiendo la cercanía: similitud coseno, a fondo

Hemos dicho que palabras similares quedan cerca en el espacio de embeddings. Pero, ¿cómo medimos esa cercanía de forma numérica?

La medida estándar es la similitud coseno. Para entenderla, olvidémonos por un momento de vectores de cientos de dimensiones y pensemos en un espacio de solo 2 dimensiones — un plano.

Imagina que cada palabra es una flecha que sale del origen (0,0). La similitud coseno mide el ángulo que forman dos flechas entre sí:

  • Si dos flechas apuntan exactamente en la misma dirección (ángulo 0°), su coseno es 1 — idénticas en dirección, aunque una sea más larga.
  • Si son perpendiculares (ángulo 90°), su coseno es 0 — sin relación.
  • Si apuntan en direcciones opuestas (ángulo 180°), su coseno es -1 — antónimos semánticos.

¿Por qué coseno y no distancia euclidiana (la línea recta entre dos puntos)? La distancia euclidiana es muy sensible a la longitud del vector — y en los embeddings entrenados, la longitud de un vector suele correlacionar con la frecuencia de la palabra (las palabras muy comunes tienden a tener vectores más largos). Si usáramos distancia euclidiana, dos palabras raras pero muy relacionadas podrían verse “lejanas” solo porque sus vectores son cortos. El coseno, al normalizar por longitud, se fija solo en la dirección — que es precisamente lo que codifica el significado.

Fórmula, paso a paso:

  1. Producto punto (A · B): multiplicas cada componente de A con su correspondiente en B, y sumas: Σ (Aᵢ × Bᵢ).
  2. Norma (‖A‖): raíz cuadrada de la suma de los cuadrados de sus componentes: √Σ Aᵢ² — la “longitud” de la flecha.
  3. Normalización: divides el producto punto entre el producto de las normas.
similitud_coseno(A, B) = (A · B) / (‖A‖ × ‖B‖)

Ejemplo numérico concreto, en 2D:

Sea gato = A = [2, 1] y perro = B = [3, 1.5] (apunta en la misma dirección, pero es 1.5 veces más largo):

  • Producto punto: (2×3) + (1×1.5) = 6 + 1.5 = 7.5
  • Norma de A: √(2² + 1²) = √5 ≈ 2.236
  • Norma de B: √(3² + 1.5²) = √11.25 ≈ 3.354
  • Coseno: 7.5 / (2.236 × 3.354) = 7.5 / 7.5 = 1.0 — ¡perfectamente alineados!

Ahora sea martes = C = [0, 1]:

  • Producto punto con A: (2×0) + (1×1) = 1
  • Norma de C: 1
  • Coseno: 1 / (2.236 × 1) ≈ 0.447 — un ángulo de unos 63°, apenas relacionado.

Bajo el capó — la versión que acabamos de calcular a mano, en Python puro:

from math import sqrt

def coseno(a, b):
    producto_punto = sum(x * y for x, y in zip(a, b))
    largo_a = sqrt(sum(x * x for x in a))
    largo_b = sqrt(sum(y * y for y in b))
    return producto_punto / (largo_a * largo_b)  # 1 = misma dirección

Y la versión con NumPy, que es como realmente se implementa en la práctica (misma fórmula, usando operaciones vectorizadas en vez de bucles explícitos — más rápida sobre vectores de cientos o miles de dimensiones):

import numpy as np

def coseno(a, b):
    producto_punto = np.dot(a, b)
    norma_a = np.linalg.norm(a)
    norma_b = np.linalg.norm(b)
    return producto_punto / (norma_a * norma_b)

# Ejemplo práctico: buscar palabras más similares a "gato"
def vecinos_mas_cercanos(embedding, palabra, k=5):
    vec_palabra = embedding[palabra]
    similitudes = {}
    for token, vec in embedding.items():
        if token == palabra:
            continue
        similitudes[token] = coseno(vec_palabra, vec)
    return sorted(similitudes.items(), key=lambda x: x[1], reverse=True)[:k]

Embeddings en acción: búsqueda semántica, y el contraste con BM25

Ahora que sabemos cómo se comparan vectores, podemos entender su gran utilidad práctica: la búsqueda semántica. Pero vale la pena conocer primero el enfoque clásico que vino antes.

El enfoque clásico: BM25. Antes de que los embeddings se popularizaran, los motores de búsqueda usaban algoritmos como BM25 (Best Matching 25): divide la consulta en palabras clave, busca documentos que las contengan exactamente, y puntúa según frecuencia del término, qué tan rara es esa palabra en toda la colección, y normalización por longitud del documento. Es rápido, no necesita entrenamiento, y funciona muy bien para nombres propios, códigos de producto, o términos muy específicos.

La limitación de BM25: es ciego al significado. Depende de que uses exactamente las mismas palabras que aparecen en el documento. Si buscas “coche eléctrico” y un documento habla del “automóvil a batería”, BM25 no lo encuentra — no sabe que son sinónimos. Hay un abismo léxico entre lo que escribes y lo que el documento contiene.

El enfoque moderno: convertir la consulta y los documentos en vectores, calcular similitud coseno entre ellos, y devolver los más cercanos — sin importar si las palabras exactas coinciden, solo si el significado es similar.

¿BM25 quedó obsoleto? No — en la práctica, ambos enfoques se combinan en búsqueda híbrida: BM25 captura coincidencias exactas (nombres, códigos), embeddings capturan significado general, y las puntuaciones se combinan para obtener lo mejor de ambos mundos.

Esta dualidad —búsqueda por palabras clave vs. búsqueda semántica— es exactamente el mecanismo que ya vimos a fondo en Parte II: es la base de RAG y de cómo funcionan las bases de datos vectoriales (con su propio capítulo dedicado). Ahí retomamos esta misma similitud coseno para explicar cómo un sistema recupera los fragmentos de documento más relevantes para responder una pregunta — la mecánica es idéntica a la que acabamos de calcular a mano aquí, solo que operando sobre miles o millones de vectores en vez de tres.

Las direcciones también significan algo

Una de las propiedades más sorprendentes de los embeddings es que las operaciones aritméticas con vectores capturan relaciones semánticas:

reyhombre+mujerreina\text{rey} - \text{hombre} + \text{mujer} \approx \text{reina}

El “desplazamiento” que va de hombre a rey (que codifica la idea de “realeza”) es muy similar al desplazamiento que va de mujer a reina. Esto funciona para varios tipos de relación:

RelaciónEjemploOperación
Génerohombre → mujer, rey → reinarey - hombre + mujer ≈ reina
CapitalParís → Francia, Berlín → AlemaniaBerlín - Alemania + París ≈ Francia
Tiempo verbalcorrer → corrió, comer → comiócorrió - correr + comer ≈ comió
Comparativogrande → más grande, rápido → más rápidomás rápido - rápido + grande ≈ más grande

Es importante ser honestos: esto es una regularidad geométrica aproximada, no una resta literal de “esencia”. El modelo no sabe nada ni hace juicios; la respuesta es el vector más cercano, sin garantía de corrección, y en analogías difíciles o con palabras poco frecuentes falla con frecuencia.

Bajo el capó resolver una analogía Expandir Cerrar
def analogia(palabra_a, palabra_b, palabra_c, excluidas=None):
    vec_a = embedding[palabra_a]
    vec_b = embedding[palabra_b]
    vec_c = embedding[palabra_c]
    objetivo = [b - a + c for a, b, c in zip(vec_a, vec_b, vec_c)]
    excluidas = excluidas or {palabra_a, palabra_b, palabra_c}
    mejor, mejor_sim = None, -1
    for palabra, vec in embedding.items():
        if palabra in excluidas:
            continue
        sim = coseno(vec, objetivo)
        if sim > mejor_sim:
            mejor_sim, mejor = sim, palabra
    return mejor

Calculadora de analogías (el laboratorio)

La tabla de arriba muestra la idea. Abajo, la misma operación B − A + C corre sobre vectores GloVe reales de 50 dimensiones — los mismos que alimentan la tabla cat/dog de este capítulo. Es aritmética y similitud coseno, no entrenamiento.

Calculadora de analogías vectoriales

Completá A, B y C — «A es a B como C es a ___». La calculadora hace B − A + C y busca el vecino más cercano por similitud coseno. Es aritmética sobre vectores ya entrenados, no entrenamiento.

Estos son vectores reales de GloVe, entrenados sobre texto en inglés — por eso el vocabulario está en inglés, igual que la tabla de similitud cat/dog de este mismo capítulo. No son palabras traducidas ni relaciones aproximadas.

Ejemplos
es a
como
es a ___

parisfrance + italyrome (0.84)

Respuesta más cercana: rome

Vecinos más cercanos (similitud coseno)

rome
0.84
madrid
0.75
amsterdam
0.71
lisbon
0.71
budapest
0.67

Cuidado: los sesgos también se aprenden

Esta misma geometría que codifica relaciones útiles también codifica estereotipos y sesgos presentes en los textos de entrenamiento. En algunos embeddings ampliamente estudiados se ha observado que programador o ingeniero quedan más cerca de hombre, mientras que enfermera queda más cerca de mujer.

Esto no es una decisión deliberada del modelo — es un reflejo de las distribuciones estadísticas en los datos. Si los textos históricos asocian ciertas profesiones con géneros, el embedding lo captura. Esto tiene implicaciones importantes: los modelos que usan estos embeddings pueden perpetuar o amplificar esos sesgos. Por eso, en la práctica, se aplican técnicas de debias (neutralizar direcciones específicas de sesgo) o se curan los datos de entrenamiento con más cuidado.

¿Y la posición? Embeddings posicionales

Hasta ahora hemos representado cada token de forma aislada. Pero el orden importa: “El perro muerde al hombre” y “El hombre muerde al perro” tienen exactamente los mismos tokens, y significan cosas opuestas.

Las redes recurrentes procesan el texto secuencialmente, así que el orden está implícito en la propia dinámica temporal. Pero los transformers procesan todas las posiciones en paralelo, y la atención por sí sola no distingue orden — no tiene noción de “primero” o “segundo”. Sin información de posición, el modelo vería todas las permutaciones de una oración como idénticas.

La solución clásica (GPT-1, GPT-2, BERT): sumar un embedding de posición a cada token — entrada[t] = embedding_token[ID_t] + embedding_posicion[t] — donde embedding_posicion es otra tabla aprendida, un vector por cada posición absoluta.

RoPE (Rotary Position Embeddings), la alternativa moderna: los embeddings de posición absoluta no generalizan bien a secuencias más largas que las vistas en entrenamiento — si el modelo se entrenó con hasta 512 tokens y recibe una secuencia de 1000, las posiciones más allá de 512 simplemente no tienen embedding aprendido. Modelos más recientes usan RoPE: en lugar de sumar un vector, rota los vectores de query y key en cada capa de atención, con un ángulo proporcional a la distancia entre tokens — haciendo que la comparación dependa de la posición relativa, no absoluta.

Ventajas de RoPE: generaliza mejor a longitudes de secuencia mayores a las de entrenamiento (las rotaciones son funciones continuas de la posición), no añade parámetros extra (la rotación es determinista, no hay tabla que aprender), y mejora el manejo de dependencias de largo alcance.

Bajo el capó RoPE, simplificado Expandir Cerrar
q = proyeccion_q(x)   # (largo, dim_cabeza)
k = proyeccion_k(x)   # (largo, dim_cabeza)

q_rot = rotate(q, posiciones)   # rota según la posición absoluta de cada token
k_rot = rotate(k, posiciones)

# El producto punto q_rot · k_rot dependerá de la diferencia de posiciones,
# no de la posición absoluta de cada uno

No hace falta dominar los detalles matemáticos (senos y cosenos con distintas frecuencias) — basta con entender la idea: RoPE inyecta información de posición directamente en la comparación entre tokens, como una rotación que codifica distancia relativa, no como una suma fija.

Embeddings estáticos vs. contextuales

Hasta ahora hemos hablado de embeddings estáticos: cada token tiene un único vector fijo, sin importar el contexto. Pero ese vector inicial es solo el punto de partida — a medida que la palabra pasa por las capas del transformer, su representación se va enriqueciendo con el contexto de las palabras que la rodean.

Por ejemplo, banco tiene el mismo embedding inicial en “banco de peces” y en “banco financiero” — pero después de la primera capa de atención, su representación ya es distinta según el contexto. Por eso decimos que los transformers producen embeddings contextuales. En este capítulo nos enfocamos en el embedding inicial, la base sobre la que se construye todo lo demás — los embeddings contextuales los veremos en el capítulo de anatomía de un transformer.

Resumen del capítulo

  • Los IDs de los tokens se convierten en vectores mediante una tabla de búsqueda entrenable.
  • Esos vectores se organizan en un espacio semántico donde la cercanía refleja similitud de uso.
  • La similitud se mide con el coseno del ángulo, que ignora la longitud del vector y se fija solo en la dirección.
  • Los embeddings permiten búsqueda semántica, a diferencia de BM25 (basado en palabras clave) — ambos se complementan en sistemas híbridos, y son la base de RAG (Parte II).
  • Las direcciones en ese espacio pueden representar relaciones (analogías), pero también codifican sesgos del texto de entrenamiento.
  • Para que el modelo distinga el orden, se añaden embeddings de posición — absolutos, o rotativos como RoPE.
  • Los embeddings iniciales son estáticos, pero se vuelven contextuales a lo largo de las capas del transformer.

En el próximo capítulo veremos cómo el transformer usa estos embeddings como entrada para el mecanismo de atención, que permite que cada token mire a los demás y construya representaciones contextuales ricas.

¿Encontraste un error? Sugerir una corrección