Todos los artículos

Trabajo de fin de máster: detección explicable de phishing escrito por IA

Entregado, resultado pendiente

Mi trabajo de fin de máster en la Liverpool John Moores University: detectar correos de phishing escritos por IA y medir si las explicaciones de cada detector son fieles a lo que este hace en realidad.

Mi papel
Autor: diseño experimental, código, evaluación y redacción
Año
2026
Hecho con
Python · scikit-learn · XGBoost · LightGBM · PyTorch · Transformers · SHAP · LIME · Integrated Gradients

El problema

El phishing escrito por modelos de lenguaje se lee distinto que el de las plantillas antiguas, y un detector que nadie puede explicar inspira poca confianza y es difícil de auditar. Me hice dos preguntas: qué tipo de modelo da la talla con el correo escrito por IA y si las explicaciones son fieles a lo que el modelo hace de verdad.

Cómo está construido

Tres familias de modelos comparadas sobre las mismas particiones: modelos clásicos (regresión logística, naive Bayes, SVM, árbol de decisión, random forest), ensembles de gradient boosting (XGBoost, LightGBM) y transformers (BERT, DistilBERT, RoBERTa), con pruebas cruzadas entre corpus de correo antiguo y de correo generado por IA. Las explicaciones de SHAP, LIME e Integrated Gradients se puntuaron por fidelidad, estabilidad y plausibilidad frente a una línea base de atribución aleatoria. El protocolo se registró antes de ejecutar los experimentos, el léxico de indicios quedó en un commit antes de tener ningún resultado, una batería de tests de control positivo protege los métodos de explicación y la medida de plausibilidad se contrastó con evaluadores humanos y con un LLM como juez. Todo se ejecutó en una RTX 3090 local.

Decisiones importantes

  • Registrado antes de ejecutar

    Los protocolos, el léxico y las hipótesis quedaron en commits antes de que existiera ningún resultado, así que nada se pudo elegir a posteriori.

  • Las explicaciones se midieron

    Un método que puntúa como una atribución aleatoria se presenta como tal. Cuando LIME puntuó como el azar, la causa era un bug en mi adaptador de LIME: un argumento del tokenizador invertido. Lo hice constar, lo corregí y lo volví a ejecutar. El LIME corregido resultó fiel, pero fue el método menos estable.

  • Ganó el modelo sencillo

    Con correo generado por IA, un modelo lineal TF-IDF ajustado superó a RoBERTa en ROC-AUC (0,9993 frente a 0,9976), y SHAP lo explicó con fidelidad, 64,5 veces más rápido que el LIME corregido.

Código del repositorio

src/xai/metrics.pyFidelidad, medida frente a una línea base aleatoria
def faithfulness(champ, texts, attrs, preds, seed: int = 42) -> dict:
    rng = np.random.default_rng(seed)
    preds = np.asarray(preds)
    p_orig = _p_pred(champ.proba(texts), preds)1
 
    variants: list[str] = []
    meta: list[tuple] = []   # (doc_i, kind, k, is_random)
    for i, (text, attr, pred) in enumerate(zip(texts, attrs, preds)):
        nw = len(textops.word_spans(text))
        top = textops.top_k_positions(attr, int(pred), min(20, nw))
        randperm = rng.permutation(nw).tolist()2
        for k in K_AOPC:
            variants.append(textops.remove_words(text, top[:k])); meta.append((i, "comp", k, False))3
            variants.append(textops.remove_words(text, randperm[:k])); meta.append((i, "comp", k, True))
        for k in K_REPORT:
            variants.append(textops.keep_only_words(text, top[:k])); meta.append((i, "suff", k, False))
            variants.append(textops.keep_only_words(text, randperm[:k])); meta.append((i, "suff", k, True))
 
    P = _p_pred(champ.proba(variants), preds[[m[0] for m in meta]])4
  1. Línea 4. La probabilidad de la clase predicha sobre el documento original, la referencia para todas las comparaciones.

  2. Línea 11. La línea base aleatoria: las mismas eliminaciones con las palabras en orden aleatorio, por un pipeline idéntico.

  3. Línea 13. Exhaustividad (comprehensiveness): se eliminan las palabras top-k que señala la explicación. Cuanto más cae la probabilidad, más fiel es la explicación.

  4. Línea 19. Todas las variantes de todos los documentos pasan por la GPU en un solo batch.

En qué punto está

Entregado en agosto de 2026; el resultado está pendiente. Todas las tablas y figuras se pueden reproducir con scripts versionados y semillas fijas. Ahora estoy convirtiendo el trabajo en un artículo para un congreso, junto con mi tutor.

Siguiente artículoFitEscala