Métricas de recuperación: recall@k, MRR y nDCG

Qué mide cada una, cuál usar según el caso y cómo interpretarlas sin engañarse con un número bonito.

Métricas de recuperación: recall@k, MRR y nDCG
Foto de William Warby en Pexels

Segunda entrega del bloque de evaluación, y la más aritmética de la serie. Cuatro métricas, cuatro fórmulas y un único conjunto de resultados sobre el que calculamos las cuatro paso a paso, para ver por qué el mismo ranking puede parecer bueno o mediocre según lo que preguntes.

El punto de partida: qué hace falta para medir recuperación

Todas las métricas de esta entrega necesitan lo mismo: un conjunto de consultas y, para cada una, la lista de fragmentos del corpus que se consideran relevantes. Esa lista anotada a mano es el juicio de relevancia, y sin ella no hay medición posible de la capa de recuperación —la que responde a si el fragmento correcto llegó al modelo, según el esquema de tres capas de la entrega anterior—.

Vamos a trabajar sobre un caso concreto. Consulta: «¿cuál es el plazo de devolución para pedidos internacionales?». El corpus tiene cuatro fragmentos que contienen parte de la respuesta, anotados como relevantes:

R = {d3, d7, d12, d20}

El sistema devuelve estos diez fragmentos, en este orden:

posición:  1    2    3    4    5    6    7    8    9    10
fragmento: d5   d7   d11  d3   d2   d20  d9   d14  d1   d6
relevante: no   sí   no   sí   no   sí   no   no   no   no

Tres de los cuatro relevantes aparecen, en las posiciones 2, 4 y 6. El cuarto (d12) no está en el top-10. Sobre esta única fila de resultados calculamos las cuatro métricas.

Recall@k: ¿he encontrado todo lo que había?

Recall@k es la proporción de fragmentos relevantes que aparecen entre los k primeros resultados.

recall@k = |relevantes ∩ top-k| / |relevantes|

Con nuestros datos:

  • recall@3 = 1/4 = 0,25 (sólo d7 está entre los tres primeros)
  • recall@5 = 2/4 = 0,50 (d7 y d3)
  • recall@10 = 3/4 = 0,75 (d7, d3 y d20; falta d12)

Recall@k ignora por completo el orden. Da igual que d7 esté en la posición 2 o en la 10: mientras entre en el corte, cuenta lo mismo. Y es monótona: nunca baja al aumentar k. Con k igual al tamaño del corpus, recall vale 1 siempre, lo que explica por qué un recall alto con un k enorme no significa nada.

La variante que verás en muchas herramientas

Cuando cada pregunta tiene un único fragmento correcto —el caso más habitual en un golden dataset de preguntas y respuestas—, recall@k colapsa en una métrica binaria por consulta: o el fragmento está entre los k primeros (1) o no está (0). Promediada sobre el conjunto de preguntas, se llama hit rate@k o tasa de acierto. Es la misma fórmula con un solo relevante, y conviene saberlo porque muchas bibliotecas etiquetan «recall» lo que en realidad es esto.

Precision@k: ¿cuánta basura viene con lo bueno?

Precision@k es la proporción de los k resultados devueltos que son relevantes.

precision@k = |relevantes ∩ top-k| / k
  • precision@3 = 1/3 = 0,33
  • precision@5 = 2/5 = 0,40
  • precision@10 = 3/10 = 0,30

Fíjate en la asimetría: al pasar de k=5 a k=10, recall sube de 0,50 a 0,75 y precision baja de 0,40 a 0,30. Es el compromiso de siempre. Ampliar la ventana mete más aciertos y mucho más ruido.

En un RAG, precision@k tiene una lectura muy física: es la proporción del presupuesto de tokens del prompt que se está gastando en material útil. Un precision@10 de 0,30 significa que siete de cada diez fragmentos que el modelo lee no aportan nada, y compiten por su atención.

MRR: ¿aparece pronto algo bueno?

El Mean Reciprocal Rank —rango recíproco medio— mide únicamente dónde aparece el primer resultado relevante. Para una consulta, el rango recíproco es 1 dividido por la posición del primer acierto; el MRR es la media de ese valor sobre todas las consultas.

RR = 1 / posición_del_primer_relevante
MRR = (1/N) · Σ RR_i

En nuestro ejemplo, el primer relevante es d7 en la posición 2:

RR = 1/2 = 0,50

Si el sistema hubiera colocado d7 en primera posición, RR valdría 1,00. Si lo hubiera dejado en la quinta, 0,20. La caída es abrupta al principio y plana al final: la diferencia entre la posición 1 y la 2 (0,50 puntos) es mayor que entre la 3 y la 10 (0,23). MRR premia sobre todo acertar arriba del todo.

Y tiene un punto ciego enorme: una vez encontrado el primer relevante, todo lo demás le da igual. Un ranking que coloca los cuatro relevantes en las posiciones 1 a 4 y otro que coloca uno en la 1 y los otros tres en la 300 tienen el mismo MRR. Sirve cuando basta un documento para responder; no sirve cuando la respuesta hay que ensamblarla con varios.

nDCG: ¿está bien ordenado todo el ranking?

El normalized Discounted Cumulative Gain es la única de las cuatro que mira el ranking completo y admite relevancia graduada. La idea: cada resultado aporta una ganancia, descontada por lo abajo que esté; se suma todo y se normaliza dividiendo por la puntuación del ranking perfecto.

DCG@k  = Σ (rel_i / log₂(i + 1))    para i = 1..k
IDCG@k = DCG del ranking ideal (todos los relevantes arriba, ordenados por relevancia)
nDCG@k = DCG@k / IDCG@k

Cálculo con relevancia binaria

Con rel_i = 1 para los relevantes y 0 para el resto, sólo aportan las posiciones 2, 4 y 6:

posición 2:  1 / log₂(3) = 1 / 1,585 = 0,631
posición 4:  1 / log₂(5) = 1 / 2,322 = 0,431
posición 6:  1 / log₂(7) = 1 / 2,807 = 0,356
DCG@10 = 0,631 + 0,431 + 0,356 = 1,418

El ranking ideal pondría los cuatro relevantes en las posiciones 1 a 4, incluido d12, que el sistema ni recuperó:

IDCG@10 = 1/log₂(2) + 1/log₂(3) + 1/log₂(4) + 1/log₂(5)
        = 1,000 + 0,631 + 0,500 + 0,431 = 2,562

nDCG@10 = 1,418 / 2,562 = 0,554

Cálculo con relevancia graduada

Supón ahora que el anotador no dijo «relevante o no», sino que puntuó de 0 a 3: d3 responde entera la pregunta (3), d7 la responde parcialmente (2), d12 aporta contexto útil (2) y d20 la menciona de pasada (1). Se usa la variante exponencial de la ganancia, que es la habitual: gain = 2^rel − 1, es decir 7, 3, 3 y 1 respectivamente.

DCG@10 = 3/log₂(3) + 7/log₂(5) + 1/log₂(7)      (d7 en 2, d3 en 4, d20 en 6)
       = 1,893 + 3,015 + 0,356 = 5,264

IDCG@10: ganancias 7, 3, 3, 1 en las posiciones 1 a 4
       = 7,000 + 1,893 + 1,500 + 0,431 = 10,824

nDCG@10 = 5,264 / 10,824 = 0,486

El mismo ranking baja de 0,554 a 0,486 al pasar a relevancia graduada, porque el fragmento que más aporta (d3, ganancia 7) está en la cuarta posición y el ideal lo pondría el primero. Esa penalización es justamente lo que nDCG existe para capturar y las otras tres métricas no ven.

Las cuatro, juntas, sobre el mismo ranking

Métrica Valor (k=10) Qué mide Ciega a Úsala cuando
recall@k 0,75 Cobertura: cuánto de lo relevante entra en la ventana Al orden y al ruido Importa no perderse nada, y hay una etapa posterior que reordena
precision@k 0,30 Densidad de señal en lo que se entrega al modelo A lo que se quedó fuera y al orden El contexto es caro y el ruido degrada la generación
MRR 0,50 Cuánto tarda en aparecer el primer acierto A todo lo que hay después del primer acierto Un solo fragmento basta para responder
nDCG@k 0,55 binaria / 0,49 graduada Calidad del orden completo, con grados de relevancia Poca cosa; a cambio exige anotación más fina Comparas rerankers o afinas el orden del contexto

Por qué recall@k manda cuando hay reranking

Si tu pipeline recupera cincuenta candidatos y un cross-encoder los reordena para quedarse con los cinco mejores —el patrón de la entrega 16—, el reparto de responsabilidades es tajante: el recuperador decide qué es posible y el reranker decide qué es bueno. Un fragmento que no está entre los cincuenta candidatos no lo puede rescatar ningún reranker del mundo.

Por eso, en la primera etapa, la métrica que importa es recall@50 (o el k que uses como ventana de candidatos), y la precisión de esa etapa es casi irrelevante: para eso está el reranker. Optimizar la primera etapa por nDCG es un error frecuente, porque te lleva a elegir configuraciones que ordenan bonito una ventana de la que se va a descartar el orden entero.

El nDCG y el MRR entran después, para medir la etapa de reranking sobre esos mismos candidatos. Esa separación permite además localizar el fallo: si recall@50 es alto y nDCG@5 es bajo, el reranker es el culpable; si recall@50 ya es bajo, el reranker es irrelevante y el problema está en embeddings, troceado o consulta.

Cómo elegir k

El k de evaluación no es un número estadístico: es un parámetro de tu sistema. Se elige así:

  • k de la ventana de candidatos (primera etapa, con reranking posterior): entre 20 y 100 según latencia tolerable. Se mide con recall@k. Se sube hasta que el recall deje de mejorar de forma apreciable; a partir de ahí sólo pagas latencia.
  • k del contexto final (lo que llega al prompt): el número real de fragmentos que metes, típicamente entre 3 y 10. Se mide con nDCG@k y precision@k, porque aquí el orden y el ruido sí afectan a la generación.
  • Mide siempre a varios k a la vez (3, 5, 10, 20). Una curva de recall que sube rápido y se aplana pronto describe un recuperador sano; una que sube lentamente hasta k=50 indica que el orden no discrimina y que estás dependiendo del reranker para todo.

Límites y trampas

La primera trampa es la anotación incompleta. Si un fragmento relevante no está marcado como tal en tu golden dataset, el sistema lo recupera y la métrica lo cuenta como error. Cuanto mejor sea el recuperador, más castiga esto, hasta el punto de que un sistema mejor puede puntuar peor. Con corpus grandes, la anotación exhaustiva es imposible y hay que asumir que las cifras absolutas están sesgadas a la baja.

La segunda es comparar números entre proyectos. Un recall@10 de 0,75 no significa nada fuera de su corpus, su conjunto de preguntas y su criterio de anotación. Estas métricas sirven para comparar dos versiones de tu sistema sobre el mismo conjunto, y para nada más.

La tercera es el tamaño de muestra. Con veinte preguntas, una diferencia de tres o cuatro centésimas es ruido. Antes de declarar ganadora una configuración, comprueba cuántas consultas concretas cambiaron de resultado; si son dos, no has medido nada.

Y la cuarta: ninguna de estas métricas sabe si el fragmento recuperado permite redactar una buena respuesta. Eso pertenece a la capa siguiente.

Qué viene ahora

La próxima entrega sube a la capa de generación: fidelidad al contexto, relevancia de la respuesta y relevancia del contexto, calculadas con un modelo de lenguaje actuando de juez. Veremos cómo se descompone una respuesta en afirmaciones para verificarlas una a una, cuánto cuesta el procedimiento, cuánta varianza tiene entre ejecuciones y qué sesgos arrastra el juez —empezando por su debilidad conocida por las respuestas largas y por su propio estilo de redacción—.

Los tres libros gratuitos de los que nace esta serie están disponibles en PDF y EPUB: RAG para tu negocio (nivel básico), RAG por dentro (intermedio) y RAG en producción (avanzado).


Aviso de contenido generado con inteligencia artificial.
Este artículo ha sido redactado con la asistencia de sistemas de inteligencia artificial y revisado antes de su publicación. Se informa de ello de forma expresa en cumplimiento de la normativa vigente sobre transparencia en el uso de IA.