Skip to content

Pipeline de Test Offline

run_test_offline_pipeline.py evalúa modelos ya entrenados sobre archivos .parquet o .csv y genera reportes offline consolidados. Puede ejecutar, en una misma corrida:

  • inferencia PFM,
  • inferencia OBSERVER,
  • detección física PPA / NPW,
  • y fusión Bayesiana LDS por caso.

La idea es reproducir un escenario de inferencia offline, con ventanas deslizantes, extracción de features compatible con training, validación por caso y generación de artefactos de análisis.

Script

python scripts/run_test_offline_pipeline.py --config configs/pipelines_config.yml

Overrides útiles por CLI:

  • --source-folder
  • --file-glob
  • --detection-model
  • --size-model
  • --location-model
  • --leakflow-model
  • --observer-detection-model
  • --observer-size-model
  • --observer-location-model
  • --features-schema
  • --feature-columns
  • --output-report
  • --window-size
  • --step-size
  • --min-leak-detection-rate
  • --leak-window
  • --plot-leak-series
  • --target-file
  • --parallel-workers

Qué hace el pipeline

En términos operativos, el script hace lo siguiente:

  1. carga la configuración desde test_offline_pipeline,
  2. resuelve modelos, schemas, mapeos y thresholds,
  3. lista archivos de entrada desde source_folder,
  4. aplica input_column_renames si los headers del CSV no coinciden con training,
  5. construye ventanas deslizantes,
  6. extrae features con el mismo vectorizador usado en training,
  7. ejecuta inferencia con modelos PFM y/u OBSERVER,
  8. opcionalmente ejecuta PPA/NPW,
  9. opcionalmente combina señales con LDS Bayes,
  10. calcula métricas por archivo y resumen global,
  11. guarda JSON, Excel, plots y metadata de idempotencia.

Salidas generadas

En output_report_folder se guardan:

  • offline_report.xlsx si generate_excel_report=true,
  • offline_results_summary.json,
  • offline_results_cases.json,
  • offline_run_metadata.json,
  • plots diagnósticos si generate_diagnostic_plots=true,
  • plots de series de fuga si plot_leak_series=true,
  • y inference_params.yml si save_inference_params=true.

Además, cuando save_inference_params=true:

  • se guarda inference_params.yml junto a los modelos de detección PFM y OBSERVER,
  • y si PPA/NPW participaron efectivamente en la corrida, se generan ppa_config.yml y npw_config.yml en model_base_path.

Contenido de esos artefactos físicos:

  • on_delay_windows
  • threshold

Configuración mínima actual en YAML

Después de la limpieza del YAML, la sección visible queda reducida a los parámetros que normalmente cambian entre corridas. Ejemplo:

test_offline_pipeline:
  source_folder: "data/csv/supe/diesel"
  output_report_folder: "reports/offline/supe/v8/1transmitter/diesel"

  feature_columns:
    - "PT 'POSITION:' 'POSITION_1378M' '(PA)' 'Pressure'"
    - "GT 'POSITION:' 'POSITION_1378M' '(KG/S)' 'Total mass flow'"
    - "PT 'POSITION:' 'POSITION_45M' '(PA)' 'Pressure'"
    - "GT 'POSITION:' 'POSITION_45M' '(KG/S)' 'Total mass flow'"
    - "PT 'POSITION:' 'POSITION_700M' '(PA)' 'Pressure'"

  input_column_renames:
    "PRESSURE_1378M": "PT 'POSITION:' 'POSITION_1378M' '(PA)' 'Pressure'"
    "MASS_FLOW_1378M": "GT 'POSITION:' 'POSITION_1378M' '(KG/S)' 'Total mass flow'"
    "PRESSURE_45M": "PT 'POSITION:' 'POSITION_45M' '(PA)' 'Pressure'"
    "MASS_FLOW_45M": "GT 'POSITION:' 'POSITION_45M' '(KG/S)' 'Total mass flow'"
    "PRESSURE_700M": "PT 'POSITION:' 'POSITION_700M' '(PA)' 'Pressure'"

  model_base_path: "models/supe/v1/1transmitter/diesel"

  pfm:
    detection_model_path: "PFM/lgbm/model_lgbm.txt"
    size_model_path: "PFM/lgbm_size/model_lgbm.txt"
    location_model_path: "PFM/lgbm_location/model_lgbm.txt"
    leakflow_model_path: "PFM/lgbm_leakflow/model_lgbm.txt"
    on_delay_windows: 5
    min_leak_detection_rate: 1.0

  observer:
    detection_model_path: "OBSERVER/lgbm/model_lgbm.txt"
    size_model_path: "OBSERVER/lgbm_size/model_lgbm.txt"
    location_model_path: "OBSERVER/lgbm_location/model_lgbm.txt"
    on_delay_windows: 5
    min_leak_detection_rate: 1.0

  ppa:
    inlet_pressure_column: "PT 'POSITION:' 'POSITION_45M' '(PA)' 'Pressure'"
    outlet_pressure_column: "PT 'POSITION:' 'POSITION_1378M' '(PA)' 'Pressure'"
    on_delay_windows: 5
    min_leak_detection_rate: 1.0
    window_size: 40

  npw:
    inlet_pressure_column: "PT 'POSITION:' 'POSITION_45M' '(PA)' 'Pressure'"
    outlet_pressure_column: "PT 'POSITION:' 'POSITION_1378M' '(PA)' 'Pressure'"
    on_delay_windows: 5
    min_leak_detection_rate: 1.0
    window_size: 40

  lds_bayesian:
    prior_leak_probability: 0.001
    detection_threshold: null

  step_size: 1
  file_glob: "*.csv"
  sample_fraction: 1.0
  plot_leak_series: false

Parámetros requeridos

El script ahora valida explícitamente los siguientes parámetros como requeridos:

1. Entrada y salida principal

Parámetro Descripción
source_folder Archivo o carpeta con casos .parquet / .csv a evaluar.
output_report_folder Carpeta donde se escriben reportes, JSON, plots y metadata.
model_base_path Ruta base para resolver modelos cuando las rutas configuradas son relativas. Requerido si no usas rutas absolutas.

2. Columnas base para extracción de features

Parámetro Descripción
feature_columns Lista de columnas base desde las que se generan las features.
input_column_renames Mapping desde nombres reales del input hacia los nombres esperados por feature_columns.

input_column_renames es requerido porque este pipeline está pensado para evaluar CSVs que pueden venir con headers cortos o históricos, mientras que los modelos fueron entrenados con nombres largos.

3. Secciones de algoritmos opcionales

El pipeline ya no obliga a definir todos los algoritmos. Cada sección es opcional:

  • pfm
  • observer
  • ppa
  • npw
  • lds_bayesian

Si una sección no existe, ese algoritmo no se ejecuta y sus resultados no se toman en cuenta.

Ejemplos válidos:

  • solo pfm.detection_model_path,
  • pfm.detection_model_path + pfm.size_model_path,
  • solo observer.detection_model_path,
  • pfm + observer + ppa,
  • ppa y npw sin observer,
  • lds_bayesian junto a cualquier subconjunto de motores de detección.

Restricciones importantes:

  • en pfm, no se puede ejecutar size, location o leakflow sin pfm.detection_model_path;
  • en observer, no se puede ejecutar size o location sin observer.detection_model_path;
  • lds_bayesian solo opera sobre los motores de detección que estén efectivamente configurados.

Diferencia entre feature_columns e input_column_renames

Aunque ambos parámetros se relacionan con las columnas del archivo de entrada, cumplen funciones distintas.

feature_columns define las columnas base canónicas que el pipeline necesita para construir las features. Es decir, representa el contrato semántico de entrada que espera el vectorizador. Estas son las señales "correctas" sobre las que luego se calculan derivadas, wavelets, correlaciones, diferencias de flujo, etc.

input_column_renames, en cambio, no define qué señales se usan, sino cómo traducir los nombres reales del archivo de entrada hacia los nombres esperados por feature_columns. Su objetivo es resolver diferencias de headers entre el archivo real y los nombres con los que se entrenaron los modelos.

Ejemplo típico:

  • feature_columns espera: "PT 'POSITION:' 'POSITION_1378M' '(PA)' 'Pressure'"
  • pero el CSV trae: PRESSURE_1378M

Entonces input_column_renames debe contener algo como:

input_column_renames:
  "PRESSURE_1378M": "PT 'POSITION:' 'POSITION_1378M' '(PA)' 'Pressure'"

Cuándo hace falta cada uno

feature_columns:

  • es necesario tanto para .parquet como para .csv;
  • no depende del formato;
  • siempre define las señales base a partir de las cuales se construyen las features.

input_column_renames:

  • normalmente se necesita sobre todo con .csv;
  • se usa cuando los nombres reales del archivo no coinciden con los nombres canónicos de feature_columns;
  • también puede ser útil con .parquet si ese .parquet viene con headers distintos a los esperados.

¿Son necesarios para archivos .parquet?

Para .parquet:

  • feature_columns: sí, sigue siendo necesario.
  • input_column_renames: solo si las columnas del .parquet no coinciden con los nombres canónicos esperados por feature_columns.

Si el .parquet ya trae exactamente los mismos nombres que feature_columns, el renombre no sería conceptualmente necesario.

¿Son necesarios para archivos .csv?

Para .csv:

  • feature_columns: sí, siempre.
  • input_column_renames: en la práctica, muchas veces sí, porque los CSV suelen venir con nombres cortos, simplificados o históricos.

Matiz importante del estado actual del pipeline

Aunque conceptualmente input_column_renames podría ser opcional cuando los nombres ya coinciden, la implementación actual del pipeline lo valida como parámetro requerido dentro de test_offline_pipeline.

Eso significa que hoy, incluso si tu .parquet o .csv ya trae exactamente los nombres de feature_columns, debes mantener input_column_renames definido en la configuración. En ese caso, puedes usar un mapping identidad o uno mínimo que refleje explícitamente los nombres usados en la entrada.

4. Sección pfm

Parámetros visibles:

Parámetro Descripción
pfm.detection_model_path Modelo PFM detection.
pfm.size_model_path Modelo PFM size.
pfm.location_model_path Modelo PFM location.
pfm.leakflow_model_path Modelo PFM leakflow.
pfm.on_delay_windows Ventanas adyacentes para declarar fuga en PFM.
pfm.min_leak_detection_rate Tasa mínima de detección dentro del on_delay de PFM.

Notas:

  • pfm.detection_model_path habilita PFM detection.
  • size, location y leakflow son opcionales y solo se ejecutan si sus modelos están definidos.
  • window_size de PFM no se toma del YAML: se carga desde lgbm_inference_config.json del modelo detection.

5. Sección observer

Parámetro Descripción
observer.detection_model_path Modelo OBSERVER detection.
observer.size_model_path Modelo OBSERVER size.
observer.location_model_path Modelo OBSERVER location.
observer.on_delay_windows Ventanas adyacentes para declarar fuga en OBSERVER.
observer.min_leak_detection_rate Tasa mínima de detección dentro del on_delay de OBSERVER.

Notas:

  • observer.detection_model_path habilita OBSERVER detection.
  • observer.size_model_path y observer.location_model_path son opcionales.
  • window_size de OBSERVER también se toma desde lgbm_inference_config.json del modelo detection.

6. Artefactos derivados automáticamente

Ya no es necesario expresar estos archivos en pipelines_config.yml:

  • features_schema.json
  • label_mapping.json para modelos PFM multiclass

El script los resuelve automáticamente en la misma carpeta donde vive cada model_lgbm.txt.

Ejemplo:

  • model_base_path = "models/supe/v1/1transmitter/diesel"
  • pfm_size_model_path = "PFM/lgbm_size/model_lgbm.txt"

Entonces el script resuelve:

  • modelo final: models/supe/v1/1transmitter/diesel/PFM/lgbm_size/model_lgbm.txt
  • schema: models/supe/v1/1transmitter/diesel/PFM/lgbm_size/features_schema.json
  • label mapping: models/supe/v1/1transmitter/diesel/PFM/lgbm_size/label_mapping.json

Lo mismo aplica para los modelos OBSERVER, salvo que en regresión no se espera label_mapping.json.

Si configuras rutas de modelo absolutas, model_base_path puede omitirse. Si configuras rutas relativas, model_base_path debe existir.

Parámetros opcionales con default interno

Todo lo que no está en la lista anterior es opcional. El script lo completa automáticamente con los valores que antes estaban en pipelines_config.yml.

Mapeos opcionales de regresión

Parámetro Default Uso
leakflow_mapping_path null Post-proceso de leakflow PFM.
observer_detection_mapping_path null Post-proceso de OBSERVER detection.
observer_size_mapping_path null Post-proceso de OBSERVER size.
observer_location_mapping_path null Post-proceso de OBSERVER location.

Estos mappings permiten escalar, desplazar, tomar valor absoluto o recortar outputs de modelos de regresión. No reemplazan el label_mapping.json de modelos PFM multiclass: ese archivo se infiere automáticamente junto al modelo.

Configuración ppa / npw

Parámetro Default
sección ppa ausente no se ejecuta PPA
sección npw ausente no se ejecuta NPW
ppa.inlet_pressure_column null
ppa.outlet_pressure_column null
ppa.on_delay_windows 5
ppa.min_leak_detection_rate 1.0
ppa.window_size 40
ppa.threshold 50.0
npw.inlet_pressure_column null
npw.outlet_pressure_column null
npw.on_delay_windows 5
npw.min_leak_detection_rate 1.0
npw.window_size 40
npw.threshold 50.0
ppa_nominal_pressure_drop_pa 0.0
ppa_sigma_nominal_h0_pa 250.0
ppa_npw_stop_after_leak_detected true

Interpretación:

  • la presencia de la sección ppa habilita PPA;
  • la presencia de la sección npw habilita NPW;
  • si defines solo outlet_pressure_column, el modo se interpreta como outlet_only;
  • si defines solo inlet_pressure_column, el modo se interpreta como inlet_only;
  • si defines ambos, el modo se interpreta como both;
  • threshold es el nombre recomendado y único a usar en el YAML agrupado;
  • threshold_percent queda solo como alias legacy interno por compatibilidad con configuraciones antiguas;
  • on_delay_windows y min_leak_detection_rate controlan la transición prealarm → leak de cada motor físico;
  • window_size puede ser distinto para ppa y npw.

Sección lds_bayesian

Para una explicación completa del algoritmo, la formulación probabilística, la calibración de p_i / q_i / alpha_i y la optimización con Optuna, ver LDS Bayesiano.

Parámetro Default
sección lds_bayesian ausente no se ejecuta LDS Bayes
lds_bayesian.prior_leak_probability 0.001
lds_bayesian.detection_threshold null
lds_bayesian_params_path null

Además, el script soporta estos parámetros avanzados de optimización/calibración LDS:

Parámetro Default
lds_bayesian_min_cases_per_state_to_optimize 5
lds_bayesian_score_tpr_weight 0.50
lds_bayesian_score_tnr_weight 0.35
lds_bayesian_score_precision_weight 0.15
lds_bayesian_false_negative_penalty 0.0
lds_bayesian_false_positive_penalty 0.0
lds_bayesian_optimization_epochs 3
lds_bayesian_optimizacion_min_improvement 1e-4
lds_bayesian_optimization_patience 0
lds_bayesian_optimization_metric "score"
lds_bayesian_optimization_threshold_min 0.50
lds_bayesian_optimization_threshold_max 0.98
lds_bayesian_optimization_threshold_step 0.02
lds_bayesian_optimization_pq_grid [0.55, 0.65, 0.75, 0.85, 0.90, 0.93, 0.95, 0.97, 0.98, 0.99]
lds_bayesian_optimization_alpha_grid [0.0, 0.05, 0.10, 0.20, 0.35, 0.50, 0.65, 0.80, 0.95, 1.0]

Ventanas y columnas reales

Parámetro Default
step_size 1
stop_fraction_leak_points 0.25
leak_column "LEAK"
leak_size_column "LEAK_SIZE_in"
leak_location_column "LEAK_LOCATION_m"
leak_flow_column "LEAK_FLOW_kg_s"

Notas:

  • step_size sigue siendo global para la generación de ventanas offline.
  • window_size de PFM y OBSERVER se toma de lgbm_inference_config.json.
  • window_size de PPA y NPW se define por sección (ppa.window_size, npw.window_size).
  • stop_fraction_leak_points limita cuánto se avanza cuando el caso contiene fuga.

Extracción de features

Parámetro Default
wavelet "db2"
wavelet_level 3
include_raw_vectorization false
temporal_sub_window_size null
temporal_sub_window_step 1

Estos valores deben mantenerse alineados con la semántica del pipeline de features.

Criterios de éxito y agregación

Parámetro Default
diagnostic_aggregation_mode "average"

Interpretación:

  • el pipeline mantiene compatibilidad con min_leak_detection_rate y leak_window globales como fallback legado;
  • en el formato agrupado nuevo, la lógica de detección usa on_delay_windows y min_leak_detection_rate dentro de cada algoritmo (pfm, observer, ppa, npw);
  • diagnostic_aggregation_mode controla cómo se resumen size/location/leakflow dentro de la ventana diagnóstica.

Descubrimiento de archivos y muestreo

Parámetro Default
file_glob "*.csv"
sample_fraction 1.0
random_state 42
target_file null
ignored_input_filenames ["reference.csv"]
csv_sep ","
csv_encoding "utf-8"

Comportamiento:

  • target_file fuerza evaluación de un solo archivo y desplaza el muestreo.
  • sample_fraction < 1.0 muestrea archivos de forma reproducible usando random_state.

Reportes, plots y performance

Parámetro Default
save_window_metrics false
progress_monitoring true
progress_update_interval 1.0
plot_leak_series false
generate_diagnostic_plots true
generate_excel_report true
save_inference_params true
show_plots false
parallel_workers 6
prediction_batch_size 256

Escalas de color para el Excel

El pipeline también tiene defaults internos para excel_report_colors:

location

  • green_threshold: 0.10
  • yellow_threshold: 0.15
  • red_threshold: 0.25
  • step: 0.05
  • is_percentage: true
  • reference_span: 1333.0

size

  • green_threshold: 0.10
  • yellow_threshold: 0.15
  • red_threshold: 0.25
  • step: 0.05
  • is_percentage: true
  • reference_span: 1.0

leakflow

  • green_threshold: 0.25
  • yellow_threshold: 2.0
  • red_threshold: 5.0
  • step: 0.5

Comportamientos automáticos importantes

Thresholds cargados desde metadata de entrenamiento

Si no defines thresholds manuales:

  • detection_threshold PFM se carga desde training_metadata.json del modelo detection.
  • observer_detection_threshold se carga desde training_metadata.json del modelo OBSERVER detection.
  • la cantidad de ventanas adyacentes para detección también puede heredarse desde metadata.

Esto evita que el offline test use thresholds distintos a los del entrenamiento.

Validaciones internas del script

El script valida varias combinaciones:

  • debe existir al menos un stack activo: PFM, OBSERVER o física,
  • si usas pfm.size_model_path, pfm.location_model_path o pfm.leakflow_model_path, debe existir pfm.detection_model_path,
  • si usas observer.size_model_path o observer.location_model_path, debe existir observer.detection_model_path,
  • si existe observer.detection_model_path, el threshold de detección resultante debe ser > 0,
  • si configuras ppa o npw, debe existir al menos una columna de presión (inlet u outlet) en su sección,
  • feature_columns debe existir y ser una lista válida,
  • input_column_renames debe existir y ser un mapping no vacío.

Idempotencia

El pipeline calcula hashes efectivos de configuración y evita repetir la evaluación si ya existe una corrida equivalente en output_report_folder.

La metadata principal es:

  • offline_run_metadata.json

Si el hash de evaluación coincide, el script finaliza sin reprocesar archivos.

Recomendaciones prácticas

  • Mantén feature_columns e input_column_renames sincronizados con los CSV reales.
  • No cambies schemas de features sin cambiar también los modelos correspondientes.
  • Usa target_file para depuración rápida de un caso puntual.
  • Si la corrida es pesada, reduce sample_fraction antes de bajar window_size.
  • Si necesitas máxima velocidad, puedes dejar plot_leak_series=false, generate_diagnostic_plots=false y generate_excel_report=false.