Evalúa probabilidades de IA con la puntuación de Brier en Python
En esta página
Dos clasificadores de IA toman tres decisiones correctas de cada cuatro. ¿Sus pronósticos son igual de útiles? No si uno asigna una probabilidad casi segura a su error. La exactitud oculta esa diferencia; la puntuación de Brier la revela.
Este tutorial compara pronósticos de probabilidad binaria con un pequeño evaluador en Python. Validarás los cálculos, rechazarás entradas incorrectas y verás por qué una pérdida probabilística menor no demuestra automáticamente que un modelo esté listo para producción. El ejemplo funciona localmente, sin paquetes adicionales, llamadas a API ni datos de clientes.
1. Define el evento antes de recopilar probabilidades
Imagina un clasificador de solicitudes de soporte que predice si necesitan revisión especializada. El valor 1 significa que la revisión es necesaria y 0 que no lo es. Todas las probabilidades deben describir ese mismo evento positivo, independientemente de la etiqueta predicha.
Un pronóstico de 0.2 significa un 20% de probabilidad de necesitar revisión especializada, no un 20% de confianza en la clase elegida por el modelo. No sustituyas este valor por probabilidades de tokens o por la certeza declarada de un chatbot sin validar por separado su relación con este evento.
Conserva resultados revisados, identificadores estables de las solicitudes y pronósticos del modelo. Empareja los registros por identificador antes de construir las listas alineadas del ejemplo. A diferencia de nuestra evaluación del enrutamiento de solicitudes, este ejercicio evalúa probabilidades y no solo decisiones de categoría.
2. Comprende la puntuación binaria
Para cada registro, resta el resultado observado de su pronóstico y eleva la diferencia al cuadrado. Promedia esos errores: Brier = media((probabilidad − resultado)²). Usamos la convención binaria de 0 a 1; cuanto menor, mejor. Coincide con la definición binaria de la referencia de la métrica de scikit-learn.
Predecir 0.99 cuando el resultado es 0 aporta 0.9801; predecir 0.6 aporta 0.36. Ambas decisiones son incorrectas con un umbral de 0.5, pero el error más confiado cuesta más.
No conviertas las probabilidades en etiquetas antes de calcular la puntuación. Mantén la precisión y la exhaustividad, calculadas con un umbral, como medidas separadas de las decisiones resultantes.
3. Guarda un evaluador sin dependencias
Guarda lo siguiente como evaluate_brier.py y usa Python 3.10 o posterior. Los pronósticos son datos de prueba escritos a mano, no resultados medidos de un modelo. Los nombres describen estos ejemplos, no categorías generales de modelos.
import math
def brier(labels, probabilities):
if not labels or len(labels) != len(probabilities):
raise ValueError("Use nonempty, equal-length lists")
if any(type(y) is not int or y not in (0, 1) for y in labels):
raise ValueError("Labels must be integers 0 or 1")
for p in probabilities:
if type(p) not in (int, float) or not math.isfinite(p) or not 0 <= p <= 1:
raise ValueError("Probabilities must be finite numbers in [0, 1]")
return sum((p - y) ** 2 for y, p in zip(labels, probabilities)) / len(labels)
def self_checks():
assert math.isclose(brier([0, 1], [0.0, 1.0]), 0.0)
assert math.isclose(brier([0, 1], [1.0, 0.0]), 1.0)
assert math.isclose(brier([0, 1], [0.5, 0.5]), 0.25)
invalid = [
([], []),
([0, 1], [0.2]),
([2], [0.5]),
([1], [1.2]),
([0], [float("nan")]),
([1], [float("inf")]),
([True], [0.5]),
([1], [True]),
]
for labels, probabilities in invalid:
try:
brier(labels, probabilities)
except ValueError:
continue
raise AssertionError("Invalid input was accepted")
print("self-checks: passed")
if __name__ == "__main__":
self_checks()
labels = [0, 0, 1, 1]
forecasts = {
"cautious": [0.2, 0.6, 0.7, 0.8],
"bold": [0.01, 0.99, 0.95, 0.99],
"constant": [0.5, 0.5, 0.5, 0.5],
}
for name, probabilities in forecasts.items():
loss = brier(labels, probabilities)
accuracy = sum(
int(p >= 0.5) == y for y, p in zip(labels, probabilities)
) / len(labels)
print(f"{name}: accuracy={accuracy:.2f} brier={loss:.4f}")
4. Ejecuta y valida el ejemplo
Ejecuta estos comandos en una terminal sin la opción -O de Python, que desactiva las aserciones:
python3 evaluate_brier.py
echo "exit=$?"
Salida esperada:
self-checks: passed
cautious: accuracy=0.75 brier=0.1325
bold: accuracy=0.75 brier=0.2457
constant: accuracy=0.50 brier=0.2500
exit=0
Las autocomprobaciones verifican pronósticos perfectos, completamente incorrectos y constantes de 0.5. También exigen rechazar listas vacías o de distinta longitud, etiquetas inválidas, probabilidades fuera del intervalo, valores no finitos y booleanos. Una ejecución correcta escribe en la salida estándar, termina con código 0 y no escribe en la salida de error.
Tanto cautious como bold alcanzan un 75% de exactitud. La segunda solicitud es negativa, pero bold le asigna 0.99. Ese error pesa más que sus mejoras en las demás solicitudes. La referencia constante obtiene 0.25; es una comparación ilustrativa, no un umbral universal de aceptación.
5. Compara pronósticos reales sin fuga de información
Sustituye los datos de prueba por pronósticos registrados antes de que el modelo conociera sus resultados. Evalúa las versiones competidoras con los mismos registros revisados y conserva los errores cuadrados de cada registro. Comprueba el solapamiento entre entrenamiento y prueba antes de interpretar las mejoras.
Como referencia práctica, predice para cada registro de prueba la frecuencia del evento en el conjunto de entrenamiento. Nunca estimes esta referencia a partir de los resultados de prueba. Mantén una población de prueba representativa; equilibrar artificialmente eventos raros cambia lo que mide el resultado agregado.
Una puntuación de Brier menor no mide únicamente la calibración. La guía de calibración de scikit-learn explica que la capacidad de discriminación también influye. Con un conjunto reservado más grande, compara los pronósticos medios con las frecuencias observadas del evento en intervalos de probabilidad e informa del número de casos de cada intervalo. Ajusta cualquier recalibración con datos separados y evalúa después con registros intactos.
6. Investiga los resultados sospechosos
- Puntuación inesperadamente mala: verifica la definición de la clase positiva y la alineación de los registros. Invertir las probabilidades puede invalidar la comparación.
- Excelente exactitud, pronósticos probabilísticos débiles: inspecciona los errores confiados y compara con la referencia constante.
- Grandes variaciones entre ejecuciones: revisa el tamaño de la muestra, los desacuerdos en las etiquetas, las frecuencias del evento y los cambios de población antes de culpar a la fórmula.
- Solo hay etiquetas de clase: obtén probabilidades del evento si el sistema lo permite. Usar solo ceros y unos reduce esta pérdida binaria a la tasa de error de clasificación.
Cuatro casos de prueba validan una calculadora, no una decisión de despliegue. Define criterios de aceptación según los costes del flujo de trabajo, la capacidad de revisión y las pruebas con datos reservados.
Conclusión práctica
Guarda las probabilidades junto con las decisiones. Comprueba el evaluador con casos conocidos, compara sobre los mismos registros reservados e inspecciona los errores confiados antes de cambiar los umbrales de automatización.
Artículos relacionados
Evalúa la clasificación de incidencias con una matriz de confusión
Detecta texto repetido entre entrenamiento y prueba antes de evaluar una IA
Revisa planes de renombrado de IA sin cambiar archivos
Evalúa transcripciones de IA con la tasa de error por palabra
Prueba expresiones regulares de IA con casos pequeños en Python
Prueba el SQL generado por IA con pequeños juegos de datos de SQLite
Cómo evaluar la recuperación RAG con Recall@k y MRR
Por Qué el Duck Typing Hace que Python Sea Tan Poderoso
Dominando 7 Algoritmos Esenciales para Estructuras de Datos en Python
Guía para Principiantes para Elegir el Framework de Python Adecuado para tus Necesidades
Guía Completa para Principiantes sobre Booleanos en Programación Python
Optimización del Uso de Memoria con Arrays de NumPy para Computación Eficiente
Últimos artículos
Evalúa campos extraídos por IA con precisión y recall de coincidencia exacta
Comprueba las rutas propuestas por IA antes de escribir con Python
Evita actualizaciones de IA obsoletas con un control de versión en SQLite
Comprueba las dependencias de tareas de IA antes de programarlas con Python
Revisa los cambios JSON de la IA con una lista de campos permitidos
Combina resultados RAG con fusión de rangos recíprocos
Comprueba las horas de calendario de IA antes de crear eventos
Comprueba citas textuales de IA con fuentes locales y Python
Comprueba las cifras de resúmenes de IA con una tabla de referencia
Elige umbrales de revisión de IA con cobertura y tasas de error
Comprueba los marcadores de traducciones de IA con Python