Detecta texto repetido entre entrenamiento y prueba antes de evaluar una IA
En esta página
Un clasificador de solicitudes de soporte puede parecer preciso porque su conjunto de prueba repite ejemplos usados para entrenarlo. Antes de confiar en una puntuación, comprueba si ambos conjuntos comparten texto, incluso cuando cambian las mayúsculas, los espacios o la anchura de los caracteres.
Este tutorial crea un comprobador local de coincidencias, de solo lectura, con la biblioteca estándar de Python. No necesitas una cuenta de un modelo ni paquetes adicionales. Los datos son sintéticos: demuestran el comprobador, no una mejora medida de la precisión de la IA.
1. Define qué cuenta como coincidencia
Para un conjunto pequeño de solicitudes, exporta cada partición como un array JSON de cadenas de entrada, sin etiquetas ni datos de clientes. Usa el texto exacto que recibe tu clasificador. Conserva los originales aparte; el comprobador nunca los modifica.
Nuestra política de revisión considera coincidentes los textos después de aplicar normalización Unicode NFKC, plegado de mayúsculas y minúsculas y reducción de espacios en blanco. No eliminamos puntuación ni acentos. Python documenta la normalización de compatibilidad NFKC y el plegado de mayúsculas y minúsculas; estas operaciones pueden unir diferencias importantes para tu tarea, así que aprueba primero la política.
Esto comprueba una vía de fuga de información, no todas. La información del conjunto de prueba puede producir estimaciones demasiado optimistas; el preprocesamiento aprendido también debe ajustarse solo con entrenamiento. La guía de scikit-learn sobre fugas de información explica ese problema más amplio. Si no conoces las particiones, empieza por nuestra introducción a la validación cruzada.
2. Guarda el comprobador
Guarda este código como split_audit.py en un directorio de trabajo vacío. Usa Python 3.10 o posterior.
import json
import sys
import unicodedata
def key(text):
normalized = unicodedata.normalize("NFKC", text).casefold()
return " ".join(normalized.split())
def load_texts(path):
with open(path, encoding="utf-8") as stream:
rows = json.load(stream)
if not isinstance(rows, list) or not rows:
raise ValueError(f"{path}: expected a nonempty list")
if any(not isinstance(text, str) or not key(text) for text in rows):
raise ValueError(f"{path}: expected nonempty strings")
return rows
def main():
if len(sys.argv) != 3:
print("Usage: python3 split_audit.py TRAIN.json TEST.json",
file=sys.stderr)
return 2
try:
train, test = [load_texts(path) for path in sys.argv[1:]]
except (OSError, ValueError) as error:
print(f"ERROR: {error}", file=sys.stderr)
return 2
first = {}
for i, text in enumerate(train):
first.setdefault(key(text), i)
matches = []
for j, text in enumerate(test):
if key(text) in first:
matches.append((j, first[key(text)]))
for j, i in matches:
print(f"MATCH test[{j}] -> train[{i}]")
print(f"overlap={len(matches)}/{len(test)} test rows")
return int(bool(matches))
if __name__ == "__main__":
raise SystemExit(main())
Cada índice empieza en cero. El recuento indica filas de prueba coincidentes, no textos únicos ni todos los pares coincidentes. Si se repiten filas de entrenamiento, el diccionario conserva su primer índice. Solo se imprimen índices, pero el proceso lee el texto completo en memoria; ejecútalo localmente con datos autorizados.
3. Crea los datos de prueba y ejecútalos
En Bash, ejecuta lo siguiente en ese directorio nuevo. Los comandos crean seis archivos JSON pequeños; no los ejecutes sobre archivos existentes. No actives set -e: los códigos distintos de cero son intencionados.
printf '%s\n' '["Reset my password", "Track my parcel"]' > train.json
printf '%s\n' '["Change my address"]' > clean.json
printf '%s\n' '["Reset my password"]' > exact.json
printf '%s\n' '[" RESET\tmy PASSWORD "]' > formatted.json
printf '%s\n' '["Please reset my password"]' > near.json
printf '%s\n' '[" "]' > invalid.json
for case in clean exact formatted near invalid; do
python3 split_audit.py train.json "$case.json"
echo "exit=$?"
done
El caso formatted incluye letras de ancho completo y un escape de tabulación JSON. Tanto este como el caso exact deben coincidir. El caso near añade una palabra para mostrar deliberadamente una limitación.
4. Valida los resultados
Probado localmente con Python 3.11.4:
| Caso | Stdout del comprobador | Salida |
|---|---|---|
clean |
overlap=0/1 test rows |
0 |
exact |
MATCH test[0] -> train[0], después overlap=1/1 test rows |
1 |
formatted |
Las mismas dos líneas que exact |
1 |
near |
overlap=0/1 test rows |
0 |
invalid |
Vacío | 2 |
Stderr está vacío salvo en invalid, que imprime ERROR: invalid.json: expected nonempty strings. El intérprete de comandos imprime cada código de salida por separado. El comprobador dejó todos los archivos de prueba sin cambios.
La salida 0 significa no se encontraron coincidencias normalizadas, no «no hay fuga de información». La salida 1 indica que debes revisar las coincidencias antes de calcular métricas. La salida 2 exige corregir la entrada o la invocación. Conserva controles con y sin coincidencias; de lo contrario, un comprobador que siempre indicara cero parecería funcionar.
5. Resuelve problemas y corrige la partición
- Formato incorrecto: usa un array JSON no vacío de cadenas que no estén en blanco, no JSONL ni objetos. Comprueba que la codificación sea UTF-8.
- Coincidencia inesperada: revisa las filas originales indicadas. Las mayúsculas, el formato o los caracteres de compatibilidad pueden importar en tu ámbito; restringe la política y actualiza las pruebas.
- Paráfrasis no detectada: es esperable. Esto compara igualdad tras normalizar, no similitud semántica. Las solicitudes de una misma conversación también pueden filtrar contexto sin compartir texto.
- Exportación grande: este ejemplo carga ambos arrays en memoria. Empieza con archivos de tamaño limitado; no es una auditoría en streaming.
No elimines sin más las filas señaladas para presentar la puntuación resultante como comparable. Revisa el origen y las etiquetas, agrupa duplicados antes de asignar particiones y después fija y versiona el conjunto revisado. Para conversaciones o clientes repetidos, considera particiones por grupos; para predicciones futuras, respeta el orden temporal. Nuestra lista de comprobación de calidad de datos cubre otras tareas de limpieza.
Conclusión práctica
Ejecuta esta comprobación antes de entrenar y antes de evaluar una nueva versión del conjunto de datos. Registra la política, las versiones de los archivos y el número de coincidencias. Después usa un conjunto de prueba separado y revisado para tu evaluación del enrutamiento de solicitudes. Superar esta comprobación limitada es un filtro útil, no una prueba de generalización ni de ausencia de contaminación durante el preentrenamiento.
Artículos relacionados
Revisa planes de renombrado de IA sin cambiar archivos
Evalúa la clasificación de incidencias con una matriz de confusión
Prueba expresiones regulares de IA con casos pequeños en Python
Evalúa transcripciones de IA con la tasa de error por palabra
Cómo evaluar la recuperación RAG con Recall@k y MRR
Prueba el SQL generado por IA con pequeños juegos de datos de SQLite
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
Pandas en Python: La Clave para una Manipulación de Datos Sin Esfuerzo
Ú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