Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sesión 6: Introducción a Machine Learning (ML)

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Sesión 6: Introducción a Machine Learning (ML)

Avatar for Abraham Zamudio

Abraham Zamudio

September 22, 2026

More Decks by Abraham Zamudio

Other Decks in Education

Transcript

  1. Índice 1. Fundamentos de Inteligencia Artificial y Machine Learning 1.1.

    Contexto Evolutivo y Definiciones Formales . . . . . . . . . . . . . . . . . . . . . . 1.1.1. Paradigma Simbólico vs. Paradigma Estadístico . . . . . . . . . . . . . . . . 1.2. Fundamentos Matemáticos Clave . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.1. Álgebra Lineal Aplicada . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.2. Cálculo y Optimización . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.3. Probabilidad y Estadística . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3. Síntesis Computacional y Buenas Prácticas . . . . . . . . . . . . . . . . . . . . . . 1.4. Conclusión de la Sección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 5 6 6 8 9 10 11 2. Machine Learning: Conceptos Básicos y Aplicaciones 2.1. Componentes Esenciales de un Sistema de ML . . . . . . . . . . . . . . . . . . . . 2.1.1. Datos y Representación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.2. Función de Hipótesis y Espacio de Búsqueda . . . . . . . . . . . . . . . . . 2.1.3. Funciones de Costo (Loss Functions) . . . . . . . . . . . . . . . . . . . . . 2.2. Taxonomía del Aprendizaje Automático . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1. Aprendizaje Supervisado . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.2. Aprendizaje No Supervisado . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.3. Aprendizaje por Refuerzo (Reinforcement Learning, RL) . . . . . . . . . . . 2.2.4. Enfoques Híbridos: Semi-supervisado y Autosupervisado . . . . . . . . . . . 2.3. Aplicaciones en la Industria: Análisis Técnico . . . . . . . . . . . . . . . . . . . . . 2.3.1. Finanzas y Gestión de Riesgo . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.2. Comercio y Retail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.3. Salud y Bioinformática . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4. Síntesis y Transición a la Ingeniería de Modelos . . . . . . . . . . . . . . . . . . . . 13 13 13 13 14 16 16 16 16 17 17 17 17 18 18 3. Aprendizaje Supervisado 3.1. Marco Teórico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1. Definición Formal del Problema . . . . . . . . . . . . . . . . . . . . . . . . 3.1.2. Descomposición Sesgo-Varianza (Bias-Variance Tradeoff) . . . . . . . . . . 3.2. Familias de Algoritmos Supervisados . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.1. Modelos Lineales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2. Modelos No Lineales y Basados en Instancias . . . . . . . . . . . . . . . . . 3.2.3. Modelos Basados en Árboles y Ensembles . . . . . . . . . . . . . . . . . . 3.3. Síntesis y Criterios de Selección de Modelos . . . . . . . . . . . . . . . . . . . . . . 19 19 19 19 20 20 23 24 27 4. Aprendizaje No Supervisado 4.1. Principios y Descubrimiento de Estructuras . . . . . . . . . . . . . . . . . . . . . . 4.2. Agrupamiento (Clustering) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1. Agrupamiento Particional: K-Means . . . . . . . . . . . . . . . . . . . . . . 4.2.2. Agrupamiento Jerárquico . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.3. Agrupamiento Basado en Densidad: DBSCAN . . . . . . . . . . . . . . . . 4.3. Reducción de Dimensionalidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1. Análisis de Componentes Principales (PCA) . . . . . . . . . . . . . . . . . . 4.3.2. Métodos No Lineales: t-SNE y UMAP . . . . . . . . . . . . . . . . . . . . 4.4. Síntesis Teórica y Transición a la Ingeniería de Características . . . . . . . . . . . . 28 28 28 28 31 32 32 33 33 34
  2. Programación en Python para Ingeniería ÍNDICE 5. Problemas de Clasificación

    y de Regresión 5.1. Formalización de Clasificación vs. Regresión . . . . . . . . . . . . . . . . . . . . . 5.2. Métricas de Rendimiento en Clasificación . . . . . . . . . . . . . . . . . . . . . . . 5.2.1. La Matriz de Confusión y Métricas Derivadas . . . . . . . . . . . . . . . . . 5.2.2. Curvas ROC y el Estadístico AUC . . . . . . . . . . . . . . . . . . . . . . . 5.2.3. Manejo de Clases Desbalanceadas . . . . . . . . . . . . . . . . . . . . . . . 5.3. Métricas de Rendimiento en Regresión . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.1. Métricas de Error Basadas en Normas . . . . . . . . . . . . . . . . . . . . . 5.3.2. Coeficiente de Determinación (𝑅 2 ) y Ajustado . . . . . . . . . . . . . . . . 5.3.3. Análisis Diagnóstico de Residuales . . . . . . . . . . . . . . . . . . . . . . 5.4. Síntesis y Transición al Flujo de Trabajo de ML . . . . . . . . . . . . . . . . . . . . 37 37 38 38 38 39 41 42 42 43 45 6. Flujo Básico de Trabajo de un Proyecto de ML 46 6.1. Fases del Ciclo de Vida de ML: Una Perspectiva de Teoría de Categorías . . . . . . . 46 6.2. Preprocesamiento e Ingeniería de Características . . . . . . . . . . . . . . . . . . . 46 6.2.1. Limpieza de Datos: Imputación y Outliers . . . . . . . . . . . . . . . . . . . 47 6.2.2. Transformación Numérica y Normalización . . . . . . . . . . . . . . . . . . 47 6.2.3. Codificación Categórica: Target Encoding Bayesiano . . . . . . . . . . . . . 47 6.2.4. Feature Engineering: Interacciones y Agregaciones . . . . . . . . . . . . . . 48 6.3. Estrategias de Partición y Validación . . . . . . . . . . . . . . . . . . . . . . . . . . 49 6.3.1. El Flagelo del Data Leakage . . . . . . . . . . . . . . . . . . . . . . . . . . 50 6.3.2. Validación Cruzada: K-Fold y Variantes . . . . . . . . . . . . . . . . . . . . 50 6.3.3. Optimización de Hiperparámetros: De la Fuerza Bruta a los Procesos Gaussianos 50 6.4. Transición a Producción (MLOps Intro) . . . . . . . . . . . . . . . . . . . . . . . . 54 6.4.1. Empaquetado y Serialización: De Pipelines a ONNX . . . . . . . . . . . . . 54 6.4.2. Monitorización Continua: Detección de Drift . . . . . . . . . . . . . . . . . 54 6.5. Síntesis General de la sesión y Conclusión . . . . . . . . . . . . . . . . . . . . . . . 56 Bibliografía 58 Abraham Zamudio 4
  3. Programación en Python para Ingeniería 1 Fundamentos de Inteligencia Artificial

    y Machine Learning Las siguientes notas de clase constituyen una exposición rigurosa de los fundamentos teóricos, matemáticos y computacionales que sustentan la transición desde la Inteligencia Artificial (IA) clásica hacia el Aprendizaje Automático (Machine Learning, ML) y el Aprendizaje Profundo (Deep Learning, DL). Este documento ha sido estructurado para proporcionar una base sólida desde la perspectiva de la matemática aplicada, la estadística computacional y la ingeniería de software, siguiendo los lineamientos de las primeras 5 sesiones y estableciendo las definiciones formales, los espacios de búsqueda y los mecanismos de optimización que rigen estos paradigmas. 1.1 Contexto Evolutivo y Definiciones Formales Para evitar ambigüedades semánticas frecuentes en la literatura divulgativa, es imperativo establecer definiciones formales basadas en teoría de conjuntos y teoría de la computación. Definición Técnica Jerarquía Conceptual de Sistemas Inteligentes Sean P el conjunto de todos los problemas computables y A el conjunto de todos los algoritmos posibles. Definimos las siguientes relaciones de contención y especialización: 1. Inteligencia Artificial (IA): Es la disciplina que busca construir agentes 𝐴 ∈ A que, dado un entorno 𝐸 y un conjunto de percepciones 𝑃, ejecutan acciones 𝑎 ∈ 𝐴 para maximizar una medida de rendimiento 𝑀 a lo largo del tiempo. Formalmente, un agente es una función 𝑓 : 𝑃∗ → 𝐴. 2. Machine Learning (ML): Es un subcampo estricto de la IA. Un sistema de ML es un algoritmo 𝐴 𝑀 𝐿 que no recibe la función 𝑓 explícitamente programada, sino que infiere una 𝑛 ⊂ X × Y. El aprendizaje aproximación 𝑓ˆ a partir de un conjunto de datos D = {(x𝑖 , 𝑦𝑖 )}𝑖=1 se define como la mejora cuantificable en el rendimiento 𝑀 (generalmente la minimización de una función de pérdida esperada E[𝐿(𝑦, 𝑓ˆ(x))]) con la experiencia D. 3. Deep Learning (DL): Es una subclase de algoritmos de ML caracterizados por la composición de múltiples transformaciones no lineales parametrizadas (capas). Formalmente, 𝑓ˆ(x) = (𝑔 𝐿 ◦ 𝑔 𝐿−1 ◦ · · · ◦ 𝑔1 )(x; Θ), donde cada 𝑔 𝑘 es una función diferenciable (salvo en puntos de medida cero, como en ReLU) y Θ representa el conjunto masivo de parámetros (tensores) aprendidos mediante retropropagación del error. 1.1.1. Paradigma Simbólico vs. Paradigma Estadístico La evolución histórica de la IA puede entenderse como una transición epistemológica en la representación del conocimiento: Paradigma Simbólico (GOFAI - Good Old-Fashioned AI): Se basa en la manipulación explícita de símbolos y reglas lógicas (e.g., sistemas expertos, lógica de primer orden). El conocimiento se codifica manualmente mediante reglas if-then. Computacionalmente, esto se traduce en búsquedas en espacios de estados (e.g., algoritmos A*, resolución unificadora). La complejidad temporal de estos sistemas suele ser exponencial 𝑂 (𝑏 𝑑 ), donde 𝑏 es el factor de ramificación y 𝑑 la profundidad de la solución, lo que los hace intratables para problemas con alta dimensionalidad o reglas difusas (como el reconocimiento de imágenes o el procesamiento del lenguaje natural no estructurado). Paradigma Estadístico (Data-Driven): En lugar de codificar reglas explícitas, se define un espacio de hipótesis H (una familia de funciones parametrizadas por 𝜃 ∈ Θ ⊆ R 𝑝 ). El conocimiento no se programa, se optimiza. El sistema aprende ajustando 𝜃 para minimizar una función de pérdida Abraham Zamudio 5
  4. Programación en Python para Ingeniería 1.2 Fundamentos Matemáticos Clave empírica

    (Empirical Risk): 𝑛 1 ∑︁ ˆ 𝑅(𝜃) = 𝐿(𝑦𝑖 , 𝑓 (x𝑖 ; 𝜃)) + Ω(𝜃) 𝑛 𝑖=1 (1) donde 𝐿 mide la discrepancia entre la predicción y la realidad, y Ω(𝜃) es un término de regularización que penaliza la complejidad del modelo, vinculando directamente el ML con la teoría de la estimación estadística y la optimización numérica. Nota de Implementación Desde la perspectiva de la Programación Orientada a Objetos (POO) en Python, el paradigma simbólico se asemeja a una jerarquía rígida de clases con métodos hardcodeados, mientras que el paradigma estadístico se modela mejor mediante clases base abstractas (e.g., BaseEstimator en scikit-learn) que exponen una interfaz uniforme (fit, predict), delegando la inteligencia a un algoritmo de optimización numérica (como scipy.optimize) que opera sobre arrays de NumPy, no sobre lógica simbólica. 1.2 Fundamentos Matemáticos Clave La columna vertebral del Machine Learning moderno se sustenta en tres pilares matemáticos interconectados: Álgebra Lineal, Cálculo Multivariado y Probabilidad. A continuación, se mencionan algunos tópicos relevantes de cada uno de estos campos para lograr el rigor necesario para su implementación computacional eficiente. 1.2.1. Álgebra Lineal Aplicada El álgebra lineal proporciona el lenguaje para representar y manipular datos a escala. En ML, los datos no son entidades aisladas, sino puntos en espacios vectoriales de alta dimensión. Definición Técnica Matriz de Diseño y Espacio de Características Dado un conjunto de datos con 𝑛 instancias (muestras) y 𝑑 características (features), definimos la Matriz de Diseño X ∈ R𝑛×𝑑 como: 𝑥11 𝑥 12 · · · 𝑥1𝑑  x𝑇     1     𝑥21 𝑥 22 · · · 𝑥2𝑑  x𝑇2      X=  . =  . . .  .. .. .. ..   ...          𝑥 𝑛1 𝑥 𝑛2 · · · 𝑥 𝑛𝑑  x𝑇     𝑛 (2) donde cada fila x𝑇𝑖 ∈ R1×𝑑 representa un vector de características de una instancia, y cada columna x ( 𝑗) ∈ R𝑛 representa la observación de la 𝑗-ésima característica a través de todas las instancias. El espacio R𝑑 se denomina espacio de características. Propiedades Críticas de X en Computación Científica: 1. Rango y Columna El rango de X, denotado como rank(X), determina el número de características linealmente independientes. Si rank(X) < 𝑑, existe multicolinealidad perfecta, lo que implica que la matriz X𝑇 X es singular (no invertible), colapsando soluciones analíticas como la de Mínimos Cuadrados Ordinarios (OLS): 𝜃ˆ = (X𝑇 X) −1 X𝑇 y. Abraham Zamudio 6
  5. Programación en Python para Ingeniería 1.2 Fundamentos Matemáticos Clave 2.

    Número de Condición: Definido como 𝜅(X) = ∥X∥ · ∥X−1 ∥ (usando la norma espectral, 𝜅 = 𝜎máx /𝜎mı́n ). Un número de condición alto indica que la matriz está mal condicionada. En optimización, esto se traduce en superficies de pérdida elongadas (valles estrechos), donde el descenso de gradiente oscila violentamente y converge extremadamente lento, requiriendo técnicas de precondicionamiento o regularización. Nota de Implementación En Python, la verificación del condicionamiento es una práctica esencial de ingeniería de datos antes de entrenar modelos lineales. A continuación se ilustra un enfoque robusto utilizando numpy y scipy: 1 2 import numpy as np from numpy . linalg import matrix_rank , cond 3 4 5 6 def analizar_matriz_diseno ( X : np . ndarray , tol : float = 1e -10) -> dict : """ Analiza propiedades num é ricas cr í ticas de la matriz de dise ñ o X . 7 8 9 10 Args : X : Matriz de caracter í sticas ( n_samples , n_features ) . tol : Tolerancia para la determinaci ó n del rango num é rico . 11 12 13 14 15 16 Returns : Diccionario con m é tricas de estabilidad num é rica . """ # Centrado de datos ( opcional pero recomendado para estabilidad ) X_centered = X - np . mean (X , axis =0) 17 18 19 # C á lculo de valores singulares para estabilidad num é rica _ , s , _ = np . linalg . svd ( X_centered , full_matrices = False ) 20 21 22 rango_numerico = np . sum ( s > tol ) numero_condicion = s [0] / s [ -1] if s [ -1] > tol else np . inf 23 24 25 26 27 28 29 30 return { " dimension " : X . shape , " rango_teorico " : min ( X . shape ) , " rango_numerico " : rango_numerico , " numero_condicion " : numero_condicion , " esta_mal_condicionada " : numero_condicion > 1 e8 } 31 32 33 34 # Ejemplo de uso : Matriz mal condicionada ( casi colineal ) X_mal = np . array ([[1.0 , 1.0] , [1.0 , 1.0000001]]) print ( analizar_matriz_diseno ( X_mal ) ) Listing 1: Evaluación del Número de Condición y Rango en Python La Maldición de la Dimensionalidad: Desde una perspectiva geométrica, a medida que 𝑑 aumenta, el volumen del espacio crece exponencialmente (𝑉 ∝ 𝑟 𝑑 ), mientras que la densidad de los datos disminuye. La distancia euclidiana entre cualquier par de puntos tiende a converger al mismo valor, anulando la utilidad de métricas basadas en distancia (como en 𝑘-NN) y requiriendo técnicas de reducción de dimensionalidad o regularización fuerte. Abraham Zamudio 7
  6. Programación en Python para Ingeniería 1.2.2. 1.2 Fundamentos Matemáticos Clave

    Cálculo y Optimización El aprendizaje en ML es, en esencia, un problema de optimización numérica: encontrar 𝜃 ∗ = arg mı́n𝜃∈Θ 𝐽 (𝜃), donde 𝐽 (𝜃) es la función de costo (o pérdida). Definición Técnica Descenso de Gradiente Sea 𝐽 : R 𝑝 → R una función diferenciable y acotada inferiormente. El algoritmo de Descenso de Gradiente genera una secuencia {𝜃 (𝑘) }∞ 𝑘=0 mediante la regla de actualización iterativa: 𝜃 (𝑘+1) = 𝜃 (𝑘) − 𝛼∇𝐽 (𝜃 (𝑘) ) (3) donde 𝛼 > 0 es la tasa de aprendizaje (learning rate) y ∇𝐽 (𝜃 (𝑘) ) es el gradiente (vector de derivadas parciales) evaluado en la iteración 𝑘. Análisis de Convergencia y Tasa de Aprendizaje: La elección de 𝛼 no es arbitraria. Si asumimos que el gradiente de 𝐽 es Lipschitz continuo con constante 𝐿 (es decir, ∥∇𝐽 (𝜃 1 ) −∇𝐽 (𝜃 2 )∥ ≤ 𝐿∥𝜃 1 −𝜃 2 ∥), entonces el Teorema de Descenso garantiza que 𝐽 (𝜃 (𝑘+1) ) ≤ 𝐽 (𝜃 (𝑘) ) siempre que 𝛼 ≤ 𝐿1 . Si 𝛼 es demasiado grande, el algoritmo diverge; si es demasiado pequeño, la convergencia es sublineal y computacionalmente prohibitiva. En el contexto de ML con grandes volúmenes de datos (𝑛 muy grande), calcular ∇𝐽 (𝜃) sobre todo el conjunto de datos (Descenso de Gradiente por Lote o Batch) es costoso: 𝑂 (𝑛 · 𝑑) por iteración. Esto da lugar a variantes estocásticas: Í𝑛 1. Gradient Descent (Batch): ∇𝐽 (𝜃) = 𝑛1 𝑖=1 ∇𝐿(𝑦𝑖 , 𝑓 (x𝑖 ; 𝜃)). Convergencia suave pero lenta por paso. 2. Stochastic Gradient Descent (SGD): 𝜃 (𝑘+1) = 𝜃 (𝑘) − 𝛼∇𝐿(𝑦𝑖 , 𝑓 (x𝑖 ; 𝜃 (𝑘) )) para un 𝑖 elegido uniformemente al azar. Alta varianza en la actualización, pero costo 𝑂 (𝑑) por paso. Permite escapar de mínimos locales poco profundos debido al ruido inherente. 3. Mini-batch Gradient Descent: Compromiso óptimo. Se utiliza un subconjunto B de tamaño Abraham Zamudio 8
  7. Programación en Python para Ingeniería 1.2 Fundamentos Matemáticos Clave |B|

    = 𝑚 ≪ 𝑛 (típicamente 32, 64, 256). 𝜃 (𝑘+1) = 𝜃 (𝑘) − 𝛼 ∑︁ ∇𝐿(𝑦𝑖 , 𝑓 (x𝑖 ; 𝜃 (𝑘) )) 𝑚 𝑖∈B (4) Esta variante reduce la varianza en comparación con SGD puro y aprovecha al máximo la vectorización y las operaciones de álgebra lineal en GPU (a través de bibliotecas como PyTorch o TensorFlow), logrando un throughput computacional muy superior. 1.2.3. Probabilidad y Estadística El ML no opera en un entorno determinista; los datos son realizaciones de variables aleatorias. Por lo tanto, la teoría de la probabilidad proporciona el marco para cuantificar la incertidumbre y formalizar el proceso de aprendizaje. Distribuciones Teóricas vs. Empíricas: Sea 𝑃 la distribución de probabilidad verdadera (desconocida) que genera los datos X × Y. La distribución empírica 𝑃𝑛 asigna una probabilidad de masa 𝑛1 a cada observación en el conjunto de entrenamiento D. El objetivo del ML es encontrar un modelo cuya distribución predicha 𝑄 𝜃 esté lo más cerca posible de 𝑃. Esta cercanía se mide formalmente mediante la Divergencia de Kullback-Leibler (KL): 𝐷 𝐾 𝐿 (𝑃∥𝑄 𝜃 ). Minimizar esta divergencia con respecto a 𝜃 es matemáticamente equivalente a maximizar la verosimilitud de los datos. Definición Técnica Estimación de Máxima Verosimilitud (MLE) 𝑛 generados por una distribución paramétrica 𝑃(x; 𝜃), el estimador Dados datos i.i.d. D = {x𝑖 }𝑖=1 de máxima verosimilitud 𝜃ˆ𝑀 𝐿𝐸 es aquel que maximiza la probabilidad de observar los datos dados los parámetros: 𝜃ˆ𝑀 𝐿𝐸 = arg máx 𝑛 Ö 𝑃(x𝑖 ; 𝜃) = arg máx 𝜃 𝑛 ∑︁ log 𝑃(x𝑖 ; 𝜃) (5) 𝜃 𝑖=1 𝑖=1 La transformación logarítmica se aplica para convertir el producto en una suma, mejorando la estabilidad numérica (evitando el underflow de punto flotante) y facilitando el cálculo del gradiente. Estimación Máxima a Posteriori (MAP) y Regularización: El enfoque MLE es puramente frecuentista y puede llevar a un sobreajuste severo (overfitting), especialmente cuando 𝑑 ≈ 𝑛 o 𝑑 > 𝑛. El enfoque bayesiano introduce una distribución a priori 𝑃(𝜃), que codifica nuestras creencias sobre los parámetros antes de observar los datos. Aplicando el Teorema de Bayes: 𝑃(𝜃|D) = 𝑃(D|𝜃)𝑃(𝜃) ∝ 𝑃(D|𝜃)𝑃(𝜃) 𝑃(D) (6) El estimador MAP maximiza la probabilidad a posteriori: 𝜃ˆ𝑀 𝐴𝑃 = arg máx [log 𝑃(D|𝜃) + log 𝑃(𝜃)] (7) 𝜃 Abraham Zamudio 9
  8. Programación en Python para Ingeniería 1.3 Síntesis Computacional y Buenas

    Prácticas Nota de Implementación La conexión fundamental entre Estadística y Optimización en ML radica en que el término log 𝑃(𝜃) actúa exactamente como un término de regularización Ω(𝜃) en la función de costo. Si asumimos un prior Gaussiano 𝜃 ∼ N (0, 𝜎 2 𝐼), entonces log 𝑃(𝜃) ∝ −∥𝜃 ∥ 22 , lo que deriva directamente en la Regularización Ridge (𝐿 2 ). Si asumimos un prior Laplace 𝜃 ∼ Laplace(0, 𝑏), entonces log 𝑃(𝜃) ∝ −∥𝜃 ∥ 1 , derivando en la Regularización Lasso (𝐿 1 ), que induce dispersión (sparsity) en los pesos, realizando selección automática de características. 1.3 Síntesis Computacional y Buenas Prácticas La transición de la teoría matemática a la implementación en Python para ingeniería requiere adherencia a principios de reproducibilidad y estabilidad numérica. 1. Reproducibilidad: El uso de semillas (seeds) en generadores de números pseudoaleatorios es obligatorio para garantizar que las particiones de datos, la inicialización de pesos y los procesos estocásticos (como SGD) sean replicables. 2. Estabilidad Numérica: Operaciones como la función softmax o el cálculo de la log-loss (crossentropy) deben implementarse utilizando el "truco de la máxima resta"(max-subtraction trick) para 𝑧𝑖 −máx(𝑧) evitar desbordamientos (overflow) en la exponenciación. Por ejemplo, softmax(𝑧𝑖 ) = Í𝑒 𝑧 𝑗 −máx(𝑧) . 𝑗𝑒 3. Vectorización: Siempre que sea posible, se deben evitar los bucles for explícitos en Python. Las operaciones deben expresarse como productos matriciales (e.g., np.dot o el operador @) o funciones universales (ufuncs) de NumPy, delegando la ejecución a rutinas optimizadas en C/Fortran (BLAS/LAPACK). 1 import numpy as np 2 3 4 5 6 7 def cross_entropy_loss_stable ( y_true : np . ndarray , logits : np . ndarray , weights : np . ndarray , lambda_reg : float = 0.01) -> float : """ Calcula la p é rdida de entrop í a cruzada binaria con regularizaci ó n L2 ( equivalente a MAP con prior Gaussiano ) . 8 9 10 11 . 12 13 Args : y_true : Etiquetas verdaderas ( n_samples ,) . logits : Salidas del modelo antes de la funci ó n sigmoide ( n_samples ,) weights : Vector de pesos del modelo para la regularizaci ó n . lambda_reg : Par á metro de regularizaci ó n ( inversamente proporcional a la varianza del prior ) . 14 15 16 17 18 Returns : P é rdida total escalar ( float ) . """ n = y_true . shape [0] 19 20 21 22 23 24 # Truco de estabilidad num é rica para log (1 + exp ( - x ) ) # Para z > 0: log (1 + exp ( - z ) ) # Para z < 0: -z + log (1 + exp ( z ) ) # Usamos np . maximum y np . exp de forma vectorizada loss_data = np . maximum ( logits , 0) - logits * y_true + np . log1p ( np . exp ( - np . abs ( logits ) ) ) Abraham Zamudio 10
  9. Programación en Python para Ingeniería 1.4 Conclusión de la Sección

    25 # Promedio de la p é rdida emp í rica ( MLE ) empirical_risk = np . mean ( loss_data ) 26 27 28 # T é rmino de regularizaci ó n L2 ( MAP prior ) - no se regulariza el sesgo ( bias ) usualmente # Asumimos que weights ya excluye el bias o que se aplica uniformemente regularization_penalty = ( lambda_reg / 2.0) * np . sum ( weights ** 2) 29 30 31 32 return empirical_risk + regularization_penalty 33 34 35 36 37 38 39 # Ejemplo de uso np . random . seed (42) # Reproducibilidad y = np . random . randint (0 , 2 , size =100) logits = np . random . randn (100) * 2.5 w = np . random . randn (10) 40 41 42 loss_val = cross_entropy_loss_stable (y , logits , w , lambda_reg =0.1) print ( f " P é rdida MAP calculada : { loss_val :.4 f } " ) Listing 2: Implementación estable de Cross-Entropy Loss con Regularización L2 (MAP) 1.4 Conclusión de la Sección En conclusión y continuando con la rigurosidad del curso, la Sección 1 ha desmitificado el Machine Learning, redefiniéndolo no como un proceso heurístico opaco, sino como un problema formal de Minimización del Riesgo Empírico (ERM) estructuralmente regularizado. Hemos establecido que el aprendizaje automático es, en esencia, la proyección de una distribución de probabilidad empírica 𝑃𝑛 sobre una familia paramétrica de funciones (espacio de hipótesis) H = { 𝑓 (·; 𝜃) : 𝜃 ∈ Θ ⊆ R 𝑝 }, donde la inferencia se reduce a la búsqueda de un estimador 𝜃ˆ que optimice el compromiso fundamental entre el ajuste a los datos observados y la complejidad intrínseca del modelo. Desde una perspectiva geométrica y de análisis numérico, la matriz de diseño X ∈ R𝑛×𝑑 no opera meramente como un contenedor de datos, sino como el operador lineal que define la métrica y la topología del espacio de características. Propiedades espectrales como su número de condición 𝜅(X) y la distribución de sus valores singulares dictan directamente la curvatura y el condicionamiento de la superficie de pérdida 𝐽 (𝜃). En este paisaje topográfico, los algoritmos de optimización de primer orden (GD, SGD, Mini-batch) actúan como dinámicas discretas que, bajo la premisa de continuidad de Lipschitz en el gradiente (∇𝐽) y esquemas de tasa de aprendizaje adecuados (e.g., decrecientes o adaptativos), garantizan cotas de convergencia hacia puntos críticos estables. Crucialmente, la incorporación de términos de regularización Ω(𝜃), interpretados rigurosamente como log-prioris en el marco de la Estimación Máxima a Posteriori (MAP), trasciende la simple estabilización numérica frente a la multicolinealidad. Estos términos penalizan la norma de los parámetros, acotando efectivamente la dimensión de Vapnik-Chervonenkis (VC) o la complejidad de Rademacher del modelo. Esta restricción es la que asegura que el riesgo esperado verdadero ˆ permanezca acotado superiormente por el riesgo empírico más un término de E (x,𝑦)∼𝑃 [𝐿 (𝑦, 𝑓 (x; 𝜃))] penalización por complejidad, garantizando así la generalización fuera de la muestra (*out-of-sample*) y mitigando el sobreajuste (*overfitting*). Esta fundamentación teórica, que entrelaza de manera indisoluble el álgebra lineal numérica, el cálculo multivariado y la inferencia estadística bayesiana/frecuentista, constituye el sustrato epistemológico indispensable para las secciones subsiguientes. Sin este rigor, la aplicación de algoritmos supervisados, técnicas de agrupamiento no paramétrico o flujos de ingeniería de características carecería de criterio diagnóstico. Por tanto, el dominio de estos principios es lo que diferencia la mera invocación de APIs de librerías de alto nivel de la verdadera ingeniería de sistemas de Inteligencia Artificial: Abraham Zamudio 11
  10. Programación en Python para Ingeniería 1.4 Conclusión de la Sección

    sistemas que deben ser robustos frente a la deriva de datos, computacionalmente eficientes y, sobre todo, matemáticamente auditables. Abraham Zamudio 12
  11. Programación en Python para Ingeniería 2 Machine Learning: Conceptos Básicos

    y Aplicaciones Tras haber establecido los fundamentos epistemológicos y matemáticos en la Sección 1, esta sección se dedica a diseccionar la anatomía formal de un sistema de aprendizaje automático. Abordaremos la representación rigurosa de los datos, la formalización del espacio de hipótesis, la teoría detrás de las funciones de costo y la taxonomía que clasifica los paradigmas de aprendizaje, culminando con una análisis técnico de sus aplicaciones en dominios industriales críticos. 2.1 Componentes Esenciales de un Sistema de ML Un sistema de ML no es una entidad monolítica, sino la orquestación de tres componentes matemáticos interdependientes: la representación de los datos, el espacio de hipótesis y el criterio de optimización (función de costo). 2.1.1. Datos y Representación Desde la perspectiva de la teoría de la medida, los datos no son meros números, sino realizaciones de variables aleatorias definidas sobre un espacio de probabilidad (Ω, F , P). Definición Técnica Espacio de Datos y Representación Tensorial Sea X el espacio de entrada (dominio) y Y el espacio de salida (codominio). Un conjunto de datos D consiste en 𝑛 realizaciones independientes e idénticamente distribuidas (i.i.d.) de una variable aleatoria conjunta (𝑋, 𝑌 ) ∼ P 𝑋,𝑌 . Computacionalmente, X se representa como un tensor X ∈ R𝑛×𝑑1 ×𝑑2 ×···×𝑑 𝑘 . Para datos tabulares, 𝑘 = 1 y X ∈ R𝑛×𝑑 . Para imágenes, 𝑘 = 3 (alto, ancho, canales). El manejo de diferentes tipos de datos requiere transformaciones específicas para preservar la topología y la semántica: Variables Numéricas Continuas: Requieren estandarización o normalización para garantizar que la escala no domine la métrica de distancia. Formalmente, aplicamos una transformación 𝑇 : R → R tal que E[𝑇 (𝑋)] = 0 y Var(𝑇 (𝑋)) = 1. Variables Categóricas: No poseen una métrica euclidiana inherente. La codificación One-Hot mapea una variable categórica con 𝐶 clases a un vector en {0, 1}𝐶 , incrustándola en un espacio euclidiano donde la distancia de Hamming coincide con la discrepancia categórica. Para cardinalidad alta, se prefieren Embeddings aprendidos: una matriz E ∈ R𝐶×𝑘 (con 𝑘 ≪ 𝐶) que proyecta categorías discretas en un espacio vectorial continuo y denso, preservando similitudes semánticas. Datos Temporales: Se modelan como procesos estocásticos {𝑋𝑡 }𝑡∈T . Su representación debe preservar la dependencia temporal (autocorrelación). Estructuralmente, se organizan en tensores de secuencia (𝑛, 𝑡steps , 𝑑), donde el orden de la dimensión 𝑡steps es estrictamente invariante y crucial para modelos como RNNs o Transformers. 2.1.2. Función de Hipótesis y Espacio de Búsqueda El núcleo de cualquier algoritmo de ML es la selección de una función dentro de un conjunto predefinido. Abraham Zamudio 13
  12. Programación en Python para Ingeniería 2.1 Componentes Esenciales de un

    Sistema de ML Definición Técnica Espacio de Hipótesis y Capacidad Un espacio de hipótesis H es una familia de funciones parametrizadas: H = {ℎ 𝜃 : X → Y | 𝜃 ∈ Θ ⊆ R 𝑝 } (8) donde 𝜃 representa el vector (o tensor) de parámetros ajustables. La capacidad o expresividad de H mide su habilidad para aproximar funciones complejas. Se cuantifica formalmente mediante la Dimensión de Vapnik-Chervonenkis (VC) para clasificadores, o la Complejidad de Rademacher para funciones de valor real, las cuales acotan la brecha entre el riesgo empírico y el riesgo verdadero. Proposición / Teorema Compromiso Expresividad-Optimización A medida que la capacidad de H aumenta (e.g., mayor grado polinómico, más capas en una red neuronal), el sesgo de aproximación disminuye (Teorema de Aproximación Universal). Sin embargo, la superficie de pérdida 𝐽 (𝜃) se vuelve altamente no convexa, con múltiples mínimos locales, puntos de silla y regiones de gradiente nulo (vanishing gradients), incrementando exponencialmente la complejidad computacional de la optimización. 2.1.3. Funciones de Costo (Loss Functions) La función de costo 𝐿 : Y × Y → R≥0 cuantifica la penalización por desviación entre la predicción 𝑦ˆ = ℎ𝜃 (𝑥) y la verdad fundamental 𝑦. Para que un algoritmo de descenso de gradiente funcione de manera eficiente y estable, 𝐿 debe cumplir propiedades matemáticas específicas: no negatividad, identidad de los indiscernibles (𝐿(𝑦, 𝑦) = 0), y preferiblemente, convexidad y diferenciabilidad continua (clase 𝐶 1 o 𝐶 2 ). Análisis de Funciones de Pérdida Comunes: 1. Error Cuadrático Medio (MSE): 𝐿(𝑦, 𝑦ˆ ) = 12 (𝑦 − 𝑦ˆ ) 2 . Es estrictamente convexa y diferenciable en todas partes. Su gradiente es ∇𝑦ˆ 𝐿 = −(𝑦 − 𝑦ˆ ), lo que implica que el empuje correctivo es proporcional al error. Esto la hace sensible a valores atípicos (outliers), ya que el gradiente crece linealmente con el error, pudiendo desestabilizar la actualización de pesos. 2. Entropía Cruzada Binaria (Log-Loss): 𝐿(𝑦, 𝑝) ˆ = −[𝑦 log( 𝑝) ˆ + (1 − 𝑦) log(1 − 𝑝)], ˆ donde 𝑝ˆ = 𝜎(ℎ𝜃 (𝑥)). Es la pérdida canónica para clasificación, derivada directamente del principio de Máxima Verosimilitud (MLE) bajo una distribución de Bernoulli. Es convexa con respecto a los logits (salidas pre-activación). 3. Pérdida de Huber: Diseñada para combinar la diferenciabilidad del MSE cerca de cero con la robustez del Error Absoluto Medio (MAE) en colas pesadas. ( 1 (𝑦 − 𝑦ˆ ) 2 si |𝑦 − 𝑦ˆ | ≤ 𝛿 𝐿 𝛿 (𝑦, 𝑦ˆ ) = 2 (9) 1 2 𝛿|𝑦 − 𝑦ˆ | − 2 𝛿 si |𝑦 − 𝑦ˆ | > 𝛿 Su derivada está acotada por ±𝛿, lo que limita la influencia de los outliers en la actualización del gradiente, garantizando estabilidad numérica en entornos con ruido pesado. Abraham Zamudio 14
  13. Programación en Python para Ingeniería 2.1 Componentes Esenciales de un

    Sistema de ML Nota de Implementación Desde la Programación Orientada a Objetos (POO) en Python, las funciones de pérdida deben implementarse como una jerarquía de clases que hereden de una clase base abstracta. Esto garantiza una interfaz uniforme (‘forward‘ y ‘backward‘ o ‘gradient‘), facilitando la composición en pipelines de optimización y el cálculo automático de derivadas (autodiferenciación). 1 2 from abc import ABC , abstractmethod import numpy as np 3 4 5 class LossFunction ( ABC ) : " " " Clase base abstracta para funciones de p é rdida diferenciables . " " " 6 7 8 9 10 @abstractmethod def forward ( self , y_true : np . ndarray , y_pred : np . ndarray ) -> float : " " " Calcula el valor escalar de la p é rdida . " " " pass 11 12 13 14 15 @abstractmethod def gradient ( self , y_true : np . ndarray , y_pred : np . ndarray ) -> np . ndarray : " " " Calcula el gradiente de la p é rdida respecto a y_pred . " " " pass 16 17 18 class HuberLoss ( LossFunction ) : " " " Implementaci ó n robusta de la p é rdida de Huber . " " " 19 20 21 22 23 24 25 def __init__ ( self , delta : float = 1.0) : if delta <= 0: raise ValueError ( " El par á metro delta debe ser estrictamente positivo . " ) self . delta = delta 26 27 28 29 def forward ( self , y_true : np . ndarray , y_pred : np . ndarray ) -> float : error = y_true - y_pred is_small_error = np . abs ( error ) <= self . delta 30 31 32 33 # C á lculo vectorizado y num é ricamente estable squared_loss = 0.5 * error **2 linear_loss = self . delta * np . abs ( error ) - 0.5 * self . delta **2 34 35 return np . mean ( np . where ( is_small_error , squared_loss , linear_loss ) ) 36 37 38 39 def gradient ( self , y_true : np . ndarray , y_pred : np . ndarray ) -> np . ndarray : error = y_pred - y_true # Nota : gradiente respecto a y_pred is_small_error = np . abs ( error ) <= self . delta 40 41 42 43 44 # El gradiente est á acotado por [ - delta , delta ] , garantizando # estabilidad grad = np . where ( is_small_error , error , self . delta * np . sign ( error ) ) return np . mean ( grad , axis =0) if grad . ndim > 1 else np . mean ( grad ) 45 46 47 48 49 # Ejemplo de uso en un paso de optimizaci ó n simulado loss_fn = HuberLoss ( delta =1.5) y_t = np . array ([1.0 , -1.0 , 5.0]) # 5.0 es un outlier potencial y_p = np . array ([1.2 , -0.8 , 15.0]) # Predicci ó n con error grande en el outlier 50 51 52 print ( f " P é rdida Huber : { loss_fn . forward ( y_t , y_p ) :.4 f } " ) print ( f " Gradiente respecto a y_pred : { loss_fn . gradient ( y_t , y_p ) } " ) Abraham Zamudio 15
  14. Programación en Python para Ingeniería 2.2 Taxonomía del Aprendizaje Automático

    Listing 3: Jerarquía POO para Funciones de Pérdida con Cálculo de Gradiente Analítico 2.2 Taxonomía del Aprendizaje Automático La clasificación de los algoritmos de ML se basa fundamentalmente en la naturaleza de la señal de retroalimentación disponible durante el proceso de entrenamiento y la estructura de los datos. 2.2.1. Aprendizaje Supervisado Se define formalmente como el problema de estimar la distribución condicional 𝑃(𝑌 |𝑋) o una 𝑛 función de mapeo determinista 𝑓 : X → Y, dado un conjunto de entrenamiento D = {(x𝑖 , 𝑦𝑖 )}𝑖=1 donde cada 𝑦𝑖 es una etiqueta o valor objetivo conocido. El objetivo es minimizar el riesgo empírico regularizado. Se subdivide en: Regresión: Y ⊆ R (continuo). Se busca aproximar una función de valor real. Clasificación: Y = {𝐶1 , . . . , 𝐶 𝑘 } (discreto). Se busca estimar las probabilidades a posteriori 𝑃(𝐶 𝑘 |x) o definir fronteras de decisión en X. 2.2.2. Aprendizaje No Supervisado 𝑛 carece de etiquetas 𝑦. El objetivo es inferir la estructura Aquí, el conjunto de datos D = {x𝑖 }𝑖=1 intrínseca de la distribución marginal 𝑃(𝑋). Matemáticamente, esto se formula como: 1. Estimación de Densidad: Modelar 𝑃(x) explícitamente (e.g., Gaussian Mixture Models). 2. Agrupamiento (Clustering): Encontrar una partición C = {𝐶1 , . . . , 𝐶 𝑘 } de X que maximice la similitud intra-cluster y minimice la similitud inter-cluster, a menudo formulado como un problema de optimización combinatoria (e.g., minimizar la inercia en 𝐾-Means). 3. Reducción de Dimensionalidad: Encontrar una aplicación (mapping) 𝜙 : R𝑑 → R𝑘 con 𝑘 ≪ 𝑑, tal que se preserve la máxima información (varianza) o la estructura topológica local (variedades o manifolds). 2.2.3. Aprendizaje por Refuerzo (Reinforcement Learning, RL) A diferencia del aprendizaje estático por lotes, el RL modela la toma de decisiones secuencial bajo incertidumbre. Se formula rigurosamente como un Proceso de Decisión de Markov (MDP), definido por la tupla ⟨S, A, P, R, 𝛾⟩: S: Espacio de estados. A: Espacio de acciones. P (𝑠′ |𝑠, 𝑎): Función de probabilidad de transición (dinámica del entorno). R (𝑠, 𝑎, 𝑠′): Función de recompensa escalar. 𝛾 ∈ [0, 1): Factor de descuento temporal. ∗ El objetivo no es ajustar parámetros a datos estáticos, sino encontrar una política  óptima 𝜋 (𝑎|𝑠) Í∞ 𝑡 𝜋 que maximice el retorno esperado descontado 𝑉 (𝑠) = E𝜋 𝑡=0 𝛾 𝑅𝑡+1 | 𝑆0 = 𝑠 . Esto se resuelve mediante las Ecuaciones de Optimalidad de Bellman, que descomponen el problema global en subproblemas locales recursivos. Abraham Zamudio 16
  15. Programación en Python para Ingeniería 2.2.4. 2.3 Aplicaciones en la

    Industria: Análisis Técnico Enfoques Híbridos: Semi-supervisado y Autosupervisado La escasez de datos etiquetados ha impulsado paradigmas intermedios: Aprendizaje Semi-supervisado: Utiliza un pequeño conjunto etiquetado D 𝐿 y uno grande no etiquetado D𝑈 . Se basa en suposiciones como la suavidad (puntos cercanos deben tener la misma etiqueta) y la estructura de variedad. Matemáticamente, la función de costo se extiende: 𝐽 (𝜃) = 𝐿 𝑠𝑢 𝑝 (D 𝐿 , 𝜃) + 𝜆𝐿 𝑢𝑛𝑠𝑢 𝑝 (D𝑈 , 𝜃), donde 𝐿 𝑢𝑛𝑠𝑢 𝑝 puede ser la minimización de la entropía de las predicciones o la consistencia bajo perturbaciones de datos. Aprendizaje Autosupervisado (Self-Supervised Learning): Genera "pseudo-etiquetas.a partir de la propia estructura de los datos no etiquetados. Un ejemplo paradigmático es el modelado del lenguaje (predecir la siguiente palabra) o el enmascaramiento de entradas (Masked Autoencoders). Formalmente, se transforma un problema no supervisado en uno supervisado mediante una tarea auxiliar (pretext task) cuya representación aprendida (embeddings) se transfiere luego a la tarea principal (downstream task). 2.3 Aplicaciones en la Industria: Análisis Técnico La traducción de estos conceptos teóricos a dominios industriales requiere adaptaciones específicas en la formulación del problema, la elección de la función de pérdida y las métricas de evaluación. 2.3.1. Finanzas y Gestión de Riesgo Scoring Crediticio: Se formula como un problema de clasificación binaria desbalanceada. El objetivo es estimar 𝑃(𝑌 = default|X). Dado el desbalance, la Accuracy es una métrica engañosa; se optimiza directamente el Log-Loss ponderado o se utiliza Focal Loss para penalizar más los errores en la clase minoritaria. La interpretabilidad es crítica por regulaciones (e.g., Basilea III), por lo que se prefieren modelos aditivos generalizados (GAMs) o árboles con restricciones de monotonicidad, sobre redes neuronales profundas. Detección de Fraude en Tiempo Real: Se aborda como un problema de Detección de Anomalías (Outlier Detection). Dado que los patrones de fraude evolucionan constantemente (Concept Drift), los métodos no supervisados como Isolation Forests o One-Class SVM son fundamentales. Estos algoritmos no modelan la clase "fraude", sino que aprenden la frontera compacta de la clase "normal.en X, clasificando como fraude cualquier instancia que caiga fuera de esta región de alta densidad. 2.3.2. Comercio y Retail Pronóstico de Demanda (Forecasting): Modelado como regresión de series temporales. Los enfoques clásicos (ARIMA, ETS) asumen estacionariedad y linealidad. Los enfoques modernos de ML (LightGBM con features de retardos, o LSTMs/Transformers) capturan no linealidades y dependencias de largo alcance. La función de pérdida suele ser cuantil (Quantile Loss) para proporcionar intervalos de predicción probabilísticos, esenciales para la gestión de inventarios. Motores de Recomendación: Formalizados mediante Factorización de Matrices (Matrix Factorization). Dada una matriz de interacciones usuario-ítem 𝑅 ∈ R𝑈×𝐼 (altamente dispersa), se busca aproximar 𝑅 ≈ 𝑈𝑉 𝑇 , donde 𝑈 ∈ R𝑈×𝑘 y 𝑉 ∈ R𝐼×𝑘 son matrices de factores latentes. El problema de optimización es: ∑︁ mı́n (𝑅𝑢𝑖 − u𝑇𝑢 v𝑖 ) 2 + 𝜆(∥u𝑢 ∥ 22 + ∥v𝑖 ∥ 22 ) (10) 𝑈,𝑉 (𝑢,𝑖)∈K donde K es el conjunto de interacciones observadas. Esto se resuelve eficientemente mediante Descenso de Gradiente Estocástico (SGD) o Alternating Least Squares (ALS). Abraham Zamudio 17
  16. Programación en Python para Ingeniería 2.3.3. 2.4 Síntesis y Transición

    a la Ingeniería de Modelos Salud y Bioinformática Diagnóstico Asistido por Imagen: Utiliza Redes Neuronales Convolucionales (CNNs). Matemáticamente, una capa convolucional aplica un operador de correlación cruzada discreta entre el tensor de entrada X y un kernel (filtro) W: ∑︁ ∑︁ (X ∗ W)𝑖, 𝑗 = X𝑖+𝑚, 𝑗+𝑛 W𝑚,𝑛 (11) 𝑚 𝑛 Esta operación impone un sesgo inductivo de invariancia traslacional y localidad, reduciendo drásticamente el número de parámetros en comparación con capas densas, lo que es crucial cuando los datos médicos (e.g., resonancias magnéticas) son costosos de obtener y de alta dimensionalidad. Análisis de Supervivencia (Survival Analysis): En lugar de predecir un resultado binario, se modela la función de riesgo (hazard function) 𝜆(𝑡|x), la tasa instantánea de ocurrencia del evento (e.g., fallecimiento) en el tiempo 𝑡, dado que el sujeto ha sobrevivido hasta 𝑡. El modelo de riesgos proporcionales de Cox es el estándar, donde 𝜆(𝑡|x) = 𝜆 0 (𝑡) exp(𝜃𝑇 x). El ML moderno extiende esto con Random Survival Forests o redes neuronales de supervivencia (DeepSurv), manejando adecuadamente los datos censurados (pacientes que abandonan el estudio sin presentar el evento). 2.4 Síntesis y Transición a la Ingeniería de Modelos La Sección 2 ha establecido el andamiaje conceptual que conecta la abstracción matemática con la realidad industrial. Hemos visto que la elección de la representación de datos dicta la geometría del problema, que el espacio de hipótesis define los límites de lo que es aprendible, y que la función de costo traduce los objetivos de negocio en un paisaje de optimización navegable. La taxonomía presentada no es rígida; los sistemas de producción modernos son híbridos, combinando la estimación de densidad no supervisada para la detección de anomalías con la clasificación supervisada para la toma de decisiones, todo orquestado bajo restricciones de latencia y recursos computacionales. Este marco teórico proporciona las herramientas analíticas necesarias para descomponer cualquier problema industrial en un formato matemático resoluble. Con esta base, estamos en condiciones de profundizar en la Sección 3, donde diseccionaremos las familias de algoritmos supervisados, analizando no solo su funcionamiento, sino las condiciones matemáticas bajo las cuales cada uno converge, generaliza y falla, proporcionando un criterio de ingeniería sólido para la selección de modelos. Abraham Zamudio 18
  17. Programación en Python para Ingeniería 3 Aprendizaje Supervisado El aprendizaje

    supervisado constituye el paradigma más maduro y ampliamente desplegado del Machine Learning en entornos de producción industrial. En esta sección, trascendemos la descripción superficial de los algoritmos para realizar una disección matemática completa de sus fundamentos: desde la descomposición espectral del error de generalización hasta las condiciones de optimalidad de Karush-Kuhn-Tucker (KKT) que rigen los clasificadores de margen máximo, y la teoría del gradiente funcional que sustenta los métodos de boosting modernos. 3.1 Marco Teórico 3.1.1. Definición Formal del Problema Definición Técnica Problema de Aprendizaje Supervisado Sea (X × Y, B, P) un espacio de probabilidad donde X ⊆ R𝑑 es el espacio de entrada, Y el espacio de salida, B la 𝜎-álgebra de Borel y P la 𝑛 i.i.d. distribución conjunta desconocida. Dado un conjunto de entrenamiento D𝑛 = {(x𝑖 , 𝑦𝑖 )}𝑖=1 ∼ P, ˆ el objetivo es encontrar un estimador 𝑓𝑛 ∈ H que minimice el riesgo esperado (riesgo de Bayes generalizado): ∫ 𝑅( 𝑓 ) = E (X,𝑌 )∼P [𝐿(𝑌 , 𝑓 (X))] = 𝐿(𝑦, 𝑓 (x)) 𝑑P(x, 𝑦) (12) X×Y donde 𝐿 : Y × Y → R≥0 es una función de pérdida medible. Dado que P es desconocida, se aproxima mediante el riesgo empírico: 𝑛 1 ∑︁ 𝑅ˆ𝑛 ( 𝑓 ) = 𝐿(𝑦𝑖 , 𝑓 (x𝑖 )) 𝑛 𝑖=1 (13) El principio de Minimización del Riesgo Empírico (ERM) postula que 𝑓ˆ𝑛 = arg mı́n 𝑓 ∈H 𝑅ˆ𝑛 ( 𝑓 ) converge al minimizador del riesgo verdadero 𝑓 ∗ = arg mı́n 𝑓 𝑅( 𝑓 ) bajo condiciones de uniformidad (teorema de Glivenko-Cantelli generalizado). 3.1.2. Descomposición Sesgo-Varianza (Bias-Variance Tradeoff) La descomposición sesgo-varianza es el resultado teórico más importante para diagnosticar el comportamiento de generalización de un modelo. A continuación, presentamos la derivación completa para el caso de regresión con pérdida cuadrática. Proposición / Teorema Descomposición del Error de Predicción Esperado Sea 𝑦 = 𝑓 ∗ (x) + 𝜀 el modelo generador verdadero, donde 𝜀 ∼ (0, 𝜎 2 ) es ruido aditivo con media cero y varianza 𝜎 2 , independiente de x. Para un estimador 𝑓ˆ𝑛 (x) entrenado sobre D𝑛 , el error de predicción esperado en un punto x0 se descompone exactamente como:  2    ∗ 2 2 ED𝑛 ,𝜀 (𝑦 0 − 𝑓ˆ𝑛 (x0 )) = 𝑓 (x0 ) − ED𝑛 [ 𝑓ˆ𝑛 (x0 )] + ED𝑛 𝑓ˆ𝑛 (x0 ) − ED𝑛 [ 𝑓ˆ𝑛 (x0 )] + 𝜎2 |{z} | {z } | {z } Error Irreducible 2 Sesgo (x0 ) Varianza(x0 ) (14) Abraham Zamudio 19
  18. Programación en Python para Ingeniería 3.2 Familias de Algoritmos Supervisados

    Demostración (esquema): Definimos 𝑓¯(x0 ) = ED𝑛 [ 𝑓ˆ𝑛 (x0 )]. Expandimos el cuadrado: E[(𝑦 0 − 𝑓ˆ𝑛 ) 2 ] = E[((𝑦 0 − 𝑓 ∗ ) + ( 𝑓 ∗ − 𝑓¯) + ( 𝑓¯ − 𝑓ˆ𝑛 )) 2 ] = E[𝜀 2 ] + ( 𝑓 ∗ − 𝑓¯) 2 + E[( 𝑓¯ − 𝑓ˆ𝑛 ) 2 ] + 2 E[𝜀] ( 𝑓 ∗ − 𝑓¯) + . . . |{z} =0 Los términos cruzados se anulan por la independencia de 𝜀 respecto a D𝑛 y por la definición de 𝑓¯ (la esperanza de 𝑓ˆ𝑛 − 𝑓¯ es cero). ▪ Interpretación Computacional: Sesgo alto (Underfitting): El modelo es demasiado simple para capturar la estructura de 𝑓 ∗ . Ejemplo: ajustar una recta a datos generados por un polinomio de grado 5. El sesgo no disminuye con más datos. Varianza alta (Overfitting): El modelo es excesivamente sensible a las fluctuaciones muestrales de D𝑛 . Ejemplo: un polinomio de grado 𝑛 − 1 que interpola exactamente todos los puntos de entrenamiento. La varianza decrece como 𝑂 (1/𝑛) pero puede ser dominante cuando 𝑑 ≫ 𝑛. Error irreducible (𝜎 2 ): Es el piso teórico del error (límite de Bayes). Ningún algoritmo, por sofisticado que sea, puede superarlo. Representa la entropía inherente del proceso generador. Nota de Implementación En la práctica, la descomposición sesgo-varianza no es directamente observable porque 𝑓 ∗ es desconocida. Sin embargo, se puede diagnosticar indirectamente mediante curvas de aprendizaje (learning curves): se grafica el error de entrenamiento y de validación en función de 𝑛. Si ambos errores convergen a un valor alto, el problema es de sesgo (solución: aumentar la complejidad del modelo). Si el error de entrenamiento es bajo pero el de validación es alto, el problema es de varianza (solución: regularización, más datos, o reducción de dimensionalidad). 3.2 Familias de Algoritmos Supervisados 3.2.1. Modelos Lineales Los modelos lineales constituyen la base sobre la cual se construye toda la teoría de regularización moderna. Su simplicidad analítica permite soluciones cerradas y un análisis espectral completo. Regresión Lineal Clásica (OLS): El modelo asume 𝑦 = X𝜽 + 𝜺, con 𝜺 ∼ N (0, 𝜎 2 I𝑛 ). El estimador OLS minimiza ∥y − X𝜽 ∥ 22 . Tomando el gradiente e igualando a cero (condición de primer orden): ∇𝜽 ∥y − X𝜽 ∥ 22 = −2X𝑇 (y − X𝜽) = 0 =⇒ 𝜽ˆ OLS = (X𝑇 X) −1 X𝑇 y (15) Esta solución existe y es única si y solo si X𝑇 X es invertible, lo que requiere rank(X) = 𝑑 (es decir, 𝑛 ≥ 𝑑 y sin multicolinealidad perfecta). La complejidad computacional de la inversión directa es 𝑂 (𝑑 3 ), aunque en la práctica se utiliza la descomposición QR (X = QR) con costo 𝑂 (𝑛𝑑 2 ), que es numéricamente más estable. Regresión Ridge (𝐿 2 ): Cuando X𝑇 X está mal condicionada o 𝑑 > 𝑛, se introduce una penalización de Tikhonov:  𝜽ˆ Ridge = arg mı́n ∥y − X𝜽 ∥ 22 + 𝜆∥𝜽 ∥ 22 = (X𝑇 X + 𝜆I𝑑 ) −1 X𝑇 y (16) 𝜽 donde 𝜆 > 0 es el hiperparámetro de regularización. La adición de 𝜆I𝑑 garantiza que la matriz resultante sea siempre definida positiva (y por tanto invertible), independientemente del rango de X. Abraham Zamudio 20
  19. Programación en Python para Ingeniería 3.2 Familias de Algoritmos Supervisados

    Análisis Espectral de Ridge: Sea X = U𝚺V𝑇 la SVD de X, donde 𝜎1 ≥ 𝜎2 ≥ · · · ≥ 𝜎𝑟 > 0 son los valores singulares. La solución Ridge en la base de componentes principales se expresa como: 𝜽ˆ Ridge = 𝑟 ∑︁ 𝜎 𝑗2 𝜎2 + 𝜆 𝑗=1 𝑗 · u𝑇𝑗 y · v𝑗 (17) 𝜎𝑗 𝜎2 𝑗 El factor 𝜎2 +𝜆 ∈ (0, 1) actúa como un filtro de contracción: las componentes asociadas a valores 𝑗 singulares pequeños (direcciones de alta varianza en el espacio de parámetros, que son las más susceptibles al ruido) se atenúan fuertemente, mientras que las componentes dominantes (𝜎 𝑗2 ≫ 𝜆) se preservan casi intactas. Esto explica por qué Ridge reduce la varianza a costa de introducir un sesgo controlado. Regresión Lasso (𝐿 1 ):   1 2 𝜽ˆ Lasso = arg mı́n ∥y − X𝜽 ∥ 2 + 𝜆∥𝜽 ∥ 1 (18) 𝜽 2𝑛 A diferencia de Ridge, la norma 𝐿 1 no es diferenciable en el origen, por lo que no existe solución cerrada. Las condiciones de optimalidad se expresan mediante subgradientes (condiciones KKT): 1 ˆ + 𝜆z = 0, − X𝑇 (y − X𝜽) 𝑛   {+1}    donde 𝑧 𝑗 ∈ {−1}    [−1, 1]  si 𝜃ˆ 𝑗 > 0 si 𝜃ˆ 𝑗 < 0 si 𝜃ˆ 𝑗 = 0 (19) La geometría de la bola 𝐿 1 (un politopo con vértices en los ejes) favorece soluciones en las esquinas, lo que produce dispersión exacta (sparsity): muchos 𝜃ˆ 𝑗 = 0 exactamente. Esto convierte al Lasso en un método de selección de variables automático. Computacionalmente, se resuelve mediante el algoritmo de Coordinate Descent con complejidad 𝑂 (𝑛𝑑) por iteración, o mediante LARS (Least Angle Regression) con costo 𝑂 (𝑑 2 𝑛). Regresión Logística: Para clasificación binaria Y = {0, 1}, se modela la probabilidad a posteriori mediante la función sigmoide: 𝑃(𝑌 = 1|x; 𝜽) = 𝜎(𝜽 𝑇 x) = 1 1 + exp(−𝜽 𝑇 x) (20) La función de pérdida es la entropía cruzada (log-loss), que es estrictamente convexa en 𝜽. El gradiente y el Hessiano tienen formas cerradas elegantes: 1 ∇𝜽 𝐽 = X𝑇 ( p̂ − y), 𝑛 1 H = X𝑇 WX 𝑛 (21) donde p̂ = 𝜎(X𝜽) y W = diag( 𝑝ˆ𝑖 (1 − 𝑝ˆ𝑖 )). La convexidad estricta de 𝐽 garantiza que cualquier mínimo local es global, y la disponibilidad del Hessiano permite el uso del método de Newton-Raphson (también conocido como Iteratively Reweighted Least Squares, IRLS), que converge cuadráticamente cerca del óptimo, superando ampliamente la convergencia lineal del descenso de gradiente estándar. 1 2 import numpy as np from numpy . linalg import solve , norm 3 4 5 6 7 class LogisticRegressionIRLS : """ Regresi ó n Log í stica entrenada mediante el m é todo de Newton - Raphson ( IRLS ). Convergencia cuadr á tica local garantizada por la convexidad estricta de la log - loss . Abraham Zamudio 21
  20. Programación en Python para Ingeniería 8 3.2 Familias de Algoritmos

    Supervisados """ 9 10 11 12 13 14 15 def __init__ ( self , tol : float = 1e -8 , max_iter : int = 100 , reg_lambda : float = 0.0) : self . tol = tol self . max_iter = max_iter self . reg_lambda = reg_lambda self . theta_ : np . ndarray | None = None self . convergence_history_ : list [ float ] = [] 16 17 18 19 20 21 22 @staticmethod def _sigmoid ( z : np . ndarray ) -> np . ndarray : " " " Sigmoide num é ricamente estable ( evita overflow en exp ) . " " " return np . where ( z >= 0 , 1.0 / (1.0 + np . exp ( - z ) ) , np . exp ( z ) / (1.0 + np . exp ( z ) ) ) 23 24 25 26 27 28 def fit ( self , X : np . ndarray , y : np . ndarray ) -> " LogisticRegressionIRLS " : n , d = X . shape # A ñ adir columna de sesgo ( intercepto ) X_aug = np . column_stack ([ np . ones ( n ) , X ]) d_aug = d + 1 29 30 31 self . theta_ = np . zeros ( d_aug ) self . convergence_history_ = [] 32 33 34 for iteration in range ( self . max_iter ) : p = self . _sigmoid ( X_aug @ self . theta_ ) 35 36 37 38 39 40 41 # Gradiente : X ^ T ( p - y ) / n + lambda * theta gradient = ( X_aug . T @ ( p - y ) ) / n if self . reg_lambda > 0: reg_grad = self . reg_lambda * self . theta_ . copy () reg_grad [0] = 0.0 # No regularizar el sesgo gradient += reg_grad 42 43 44 45 46 47 48 49 # Hessiano : X ^ T W X / n + lambda * I W = np . diag ( p * (1.0 - p ) + 1e -12) # epsilon para estabilidad H = ( X_aug . T @ W @ X_aug ) / n if self . reg_lambda > 0: reg_H = self . reg_lambda * np . eye ( d_aug ) reg_H [0 , 0] = 0.0 H += reg_H 50 51 52 53 # Paso de Newton : theta <- theta - H ^{ -1} * grad delta = solve (H , gradient ) # M á s estable que inv ( H ) @ grad self . theta_ -= delta 54 55 56 step_norm = norm ( delta ) self . convergence_history_ . append ( step_norm ) 57 58 59 60 61 62 63 if step_norm < self . tol : print ( f " Convergencia en { iteration + 1} iteraciones " f " (|| delta || = { step_norm :.2 e }) " ) break else : print ( f " Advertencia : No convergi ó en { self . max_iter } iteraciones . " ) 64 65 return self 66 Abraham Zamudio 22
  21. Programación en Python para Ingeniería 67 68 69 3.2 Familias

    de Algoritmos Supervisados def predict_proba ( self , X : np . ndarray ) -> np . ndarray : X_aug = np . column_stack ([ np . ones ( X . shape [0]) , X ]) return self . _sigmoid ( X_aug @ self . theta_ ) 70 71 72 def predict ( self , X : np . ndarray , threshold : float = 0.5) -> np . ndarray : return ( self . predict_proba ( X ) >= threshold ) . astype ( int ) 73 74 75 76 77 78 79 # Demostraci ó n de convergencia cuadr á tica np . random . seed (42) X_demo = np . random . randn (500 , 5) true_theta = np . array ([0.5 , -1.0 , 0.8 , 0.0 , -0.3]) logits = X_demo @ true_theta y_demo = ( LogisticRegressionIRLS . _sigmoid ( logits ) > 0.5) . astype ( int ) 80 81 82 83 84 model = LogisticRegressionIRLS ( reg_lambda =0.01) model . fit ( X_demo , y_demo ) print ( f " Pesos estimados ( sin sesgo ) : { model . theta_ [1:]} " ) print ( f " Pesos verdaderos : { true_theta } " ) Listing 4: Regresión Logística con Newton-Raphson (IRLS) desde cero 3.2.2. Modelos No Lineales y Basados en Instancias 𝑘-Nearest Neighbors (𝑘-NN): Es un estimador no paramétrico que no asume ninguna forma funcional para 𝑓 ∗ . La predicción en un punto x0 se basa en las etiquetas de los 𝑘 puntos más cercanos en D𝑛 según una métrica 𝑑 (·, ·) (típicamente 𝐿 𝑝 ): 1 ∑︁ 𝑓ˆ𝑛 (x0 ) = 𝑦𝑖 (regresión), 𝑦ˆ 0 = moda{𝑦𝑖 : 𝑖 ∈ N𝑘 (x0 )} (clasificación) (22) 𝑘 𝑖∈N𝑘 (x0 ) Proposición / Teorema Cover-Hart (1967) En el límite asintótico (𝑛 → ∞), el error del clasificador 1-NN está acotado superiormente por el doble del error de Bayes: 𝑅 ∗ ≤ 𝑅1-NN ≤ 2𝑅 ∗ (1 − 𝑅 ∗ ) ≤ 2𝑅 ∗ (23) donde 𝑅 ∗ es el riesgo de Bayes (el clasificador óptimo teórico). Esto demuestra que, con datos suficientes, el 1-NN retiene al menos la mitad de la información disponible. Sin embargo, la maldición de la dimensionalidad degrada severamente a 𝑘-NN: en R𝑑 con 𝑑 grande, la razón entre la distancia al vecino más cercano y al más lejano converge a 1, anulando la noción de "vecindad". La complejidad de predicción ingenu es 𝑂 (𝑛𝑑) por consulta, reducible a 𝑂 (𝑑 log 𝑛) con estructuras como KD-trees o Ball-trees, aunque estas pierden eficiencia cuando 𝑑 > 20. Support Vector Machines (SVM): Las SVM representan uno de los logros teóricos más elegantes del ML. Para datos linealmente separables, la SVM busca el hiperplano de margen máximo: 1 mı́n ∥w∥ 22 w,𝑏 2 s.a. 𝑦𝑖 (w𝑇 x𝑖 + 𝑏) ≥ 1, ∀𝑖 = 1, . . . , 𝑛 (24) 2 El margen geométrico es 𝛾 = ∥w∥ , por lo que minimizar ∥w∥ 2 equivale a maximizar la separación entre clases. Para datos no separables, se introduce la formulación soft-margin (C-SVM) con variables de holgura 𝜉𝑖 ≥ 0: 𝑛 ∑︁ 1 ∥w∥ 22 + 𝐶 𝜉𝑖 w,𝑏,𝝃 2 𝑖=1 mı́n Abraham Zamudio s.a. 𝑦𝑖 (w𝑇 x𝑖 + 𝑏) ≥ 1 − 𝜉𝑖 , 𝜉𝑖 ≥ 0 (25) 23
  22. Programación en Python para Ingeniería 3.2 Familias de Algoritmos Supervisados

    Formulación Dual y Kernel Trick: Aplicando las condiciones KKT y la dualidad de Lagrange, el problema primal se transforma en el dual: máx 𝑛 ∑︁ 𝜶 𝛼𝑖 − 𝑖=1 1 ∑︁ 𝛼𝑖 𝛼 𝑗 𝑦𝑖 𝑦 𝑗 x𝑇𝑖 x 𝑗 2 𝑖, 𝑗 s.a. 0 ≤ 𝛼𝑖 ≤ 𝐶, ∑︁ 𝛼𝑖 𝑦𝑖 = 0 (26) 𝑖 La solución depende de los datos únicamente a través de productos internos x𝑇𝑖 x 𝑗 . El kernel trick reemplaza este producto interno por una función kernel 𝐾 (x𝑖 , x 𝑗 ) = ⟨𝜙(x𝑖 ), 𝜙(x 𝑗 )⟩H , donde 𝜙 : R𝑑 → H es un mapeo implícito a un espacio de Hilbert de dimensión potencialmente infinita. Proposición / Teorema Mercer (1909) Una función simétrica 𝐾 : X × X → R es un kernel válido (es decir, corresponde a un producto interno en algún espacio de Hilbert) si y solo si la matriz de Gram K𝑖 𝑗 = 𝐾 (x𝑖 , x 𝑗 ) es semidefinida positiva para cualquier conjunto finito de puntos. Kernels estándar: RBF (Gaussiano) 𝐾 (x, x′) = exp(−𝛾∥x − x′ ∥ 22 ), que induce un espacio de dimensión infinita; Polinómico 𝐾 (x, x′) = (x𝑇 x′ + 𝑐) 𝑝 ; Sigmoide 𝐾 (x, x′) = tanh(𝜅x𝑇 x′ + 𝑐). 3.2.3. Modelos Basados en Árboles y Ensembles Árboles de Decisión (CART): Un árbol de decisión particiona recursivamente el espacio X en 𝑀 . En cada nodo, se selecciona la característica 𝑗 y el regiones hiperrectangulares disjuntas {𝑅𝑚 } 𝑚=1 umbral 𝑠 que minimizan la impureza de la partición: i h𝑛 𝑛𝑅 𝐿 I (𝑅 𝐿 ( 𝑗, 𝑠)) + I (𝑅 𝑅 ( 𝑗, 𝑠)) (27) ( 𝑗 ∗ , 𝑠∗ ) = arg mı́n 𝑗,𝑠 𝑛 𝑛 donde I (·) es una medida de impureza. Para clasificación: Í Índice de Gini: I𝐺 (𝑅) = 1 − 𝐾𝑘=1 𝑝ˆ2𝑘 , donde 𝑝ˆ 𝑘 es la fracción de clase 𝑘 en la región 𝑅. Mide la probabilidad de clasificación incorrecta si se asigna una etiqueta al azar según la distribución empírica. Í Entropía de Shannon: I𝐻 (𝑅) = − 𝐾𝑘=1 𝑝ˆ 𝑘 log2 𝑝ˆ 𝑘 . Mide la incertidumbre informacional. La ganancia de información (reducción de entropía) es equivalente a la divergencia KL entre la distribución antes y después de la partición. Í Para regresión, se utiliza el MSE: IMSE (𝑅) = 𝑛1𝑅 𝑖∈𝑅 (𝑦𝑖 − 𝑦¯ 𝑅 ) 2 . Random Forest (Bagging): El bagging (Bootstrap Aggregating) reduce la varianza promediando 𝐵 2 y correlación modelos entrenados sobre muestras bootstrap. Para un árbol individual con varianza 𝜎tree 𝜌 entre pares de árboles, la varianza del bosque es: 2 Var( 𝑓ˆRF ) = 𝜌𝜎tree + 1−𝜌 2 𝜎tree 𝐵 (28) √ 2 . La aleatorización adicional (selección aleatoria de 𝑑 Cuando 𝐵 → ∞, la varianza converge a 𝜌𝜎tree características por división) reduce 𝜌, lo que explica la superioridad empírica de Random Forest sobre el bagging simple. El sesgo del bosque es aproximadamente igual al de un árbol individual (ligeramente mayor), pero la reducción masiva de varianza compensa con creces. Gradient Boosting Machines (GBM): A diferencia del bagging (que entrena modelos en paralelo), el boosting construye modelos secuencialmente, donde cada nuevo árbol corrige los errores residuales del ensemble actual. La formulación moderna de Friedman (2001) interpreta el boosting como descenso de gradiente en el espacio de funciones: 𝑓𝑚 (x) = 𝑓𝑚−1 (x) + 𝜈 · ℎ𝑚 (x) Abraham Zamudio (29) 24
  23. Programación en Python para Ingeniería 3.2 Familias de Algoritmos Supervisados

    donde 𝜈 ∈ (0, 1] es la tasa de aprendizaje (shrinkage) y ℎ𝑚 es un árbol de regresión ajustado a los pseudo-residuales:   𝜕𝐿(𝑦𝑖 , 𝑓 (x𝑖 )) 𝑟𝑖𝑚 = − (30) 𝜕 𝑓 (x𝑖 ) 𝑓 = 𝑓𝑚−1 Para MSE, 𝑟𝑖𝑚 = 𝑦𝑖 − 𝑓𝑚−1 (x𝑖 ) (el residuo clásico). Para log-loss en clasificación binaria, 𝑟𝑖𝑚 = 𝑦𝑖 − 𝜎( 𝑓𝑚−1 (x𝑖 )). Esta generalización permite aplicar boosting a cualquier función de pérdida diferenciable. Las implementaciones modernas (XGBoost, LightGBM, CatBoost) introducen optimizaciones computacionales críticas: Regularización de segundo orden: XGBoost utiliza una aproximación de Taylor de segundo orden de la función de pérdida, incorporando tanto el gradiente 𝑔𝑖 como el Hessiano ℎ𝑖 en el criterio de división: " # 𝐺 2𝐿 𝐺 2𝑅 (𝐺 𝐿 + 𝐺 𝑅 ) 2 1 Gain = + − −𝛾 (31) 2 𝐻𝐿 + 𝜆 𝐻𝑅 + 𝜆 𝐻𝐿 + 𝐻𝑅 + 𝜆 donde 𝐺 𝐿 , 𝐺 𝑅 y 𝐻 𝐿 , 𝐻 𝑅 son las sumas de gradientes y hessianos en las ramas izquierda y derecha, 𝜆 es la regularización 𝐿 2 en las hojas, y 𝛾 es el costo de complejidad por nodo adicional. Histogram-based splitting (LightGBM): En lugar de evaluar todos los umbrales posibles para cada característica (costo 𝑂 (𝑛 log 𝑛) por división), se discretizan los valores continuos en 𝐵 bins (𝐵 ≪ 𝑛), reduciendo la complejidad a 𝑂 (𝐵) y acelerando el entrenamiento en órdenes de magnitud para datasets masivos. Gradient-based One-Side Sampling (GOSS): LightGBM preserva las instancias con gradientes grandes (alto error) y submuestrea aleatoriamente las de gradiente pequeño, manteniendo la precisión del cálculo de la ganancia de información con una fracción de los datos. 1 2 import numpy as np from dataclasses import dataclass , field 3 4 5 6 7 8 9 10 @dataclass class GBMConfig : " " " Configuraci ó n de hiperpar á metros para Gradient Boosting . " " " n_estimators : int = 100 learning_rate : float = 0.1 max_depth : int = 3 reg_lambda : float = 1.0 # Regularizaci ó n L2 en hojas ( estilo XGBoost ) 11 12 13 class SimpleDecisionStump : " " " Á rbol de decisi ó n de profundidad fija ( simplificado para demostraci ó n ) . " " " 14 15 16 17 def __init__ ( self , max_depth : int = 3) : self . max_depth = max_depth self . tree_ = None 18 19 20 21 22 def _best_split ( self , X : np . ndarray , residuals : np . ndarray ) -> tuple : n , d = X . shape best_gain , best_feat , best_thresh = - np . inf , None , None total_var = np . var ( residuals ) * n 23 24 25 26 27 28 for j in range ( d ) : thresholds = np . unique ( X [: , j ]) for t in thresholds : left_mask = X [: , j ] <= t right_mask = ~ left_mask Abraham Zamudio 25
  24. Programación en Python para Ingeniería 3.2 Familias de Algoritmos Supervisados

    n_l , n_r = left_mask . sum () , right_mask . sum () if n_l < 2 or n_r < 2: continue var_l = np . var ( residuals [ left_mask ]) * n_l var_r = np . var ( residuals [ right_mask ]) * n_r gain = total_var - var_l - var_r if gain > best_gain : best_gain , best_feat , best_thresh = gain , j , t 29 30 31 32 33 34 35 36 37 38 return best_feat , best_thresh , best_gain 39 40 41 42 43 44 45 def fit_predict ( self , X : np . ndarray , residuals : np . ndarray ) -> np . ndarray : " " " Ajusta un á rbol a los pseudo - residuales y retorna predicciones . " " " # Implementaci ó n simplificada : á rbol de un solo nivel ( stump ) feat , thresh , _ = self . _best_split (X , residuals ) if feat is None : return np . full ( X . shape [0] , np . mean ( residuals ) ) 46 47 48 49 50 51 left_mask = X [: , feat ] <= thresh pred = np . empty ( X . shape [0]) pred [ left_mask ] = np . mean ( residuals [ left_mask ]) pred [~ left_mask ] = np . mean ( residuals [~ left_mask ]) return pred 52 53 54 55 56 57 class GradientBoostingRegressor : """ Gradient Boosting para regresi ó n con p é rdida MSE . Implementa descenso de gradiente en el espacio de funciones ( Friedman , 2001) . """ 58 59 60 61 62 def __init__ ( self , config : GBMConfig = None ) : self . config = config or GBMConfig () self . trees_ : list = [] self . initial_prediction_ : float = 0.0 63 64 65 66 67 68 69 def fit ( self , X : np . ndarray , y : np . ndarray ) -> " GradientBoostingRegressor " : n = X . shape [0] # Inicializaci ó n : f_0 ( x ) = argmin_gamma sum L (y , gamma ) = mean ( y ) para MSE self . initial_prediction_ = np . mean ( y ) f = np . full (n , self . initial_prediction_ ) self . trees_ = [] 70 71 72 73 74 for m in range ( self . config . n_estimators ) : # Paso 1: Calcular pseudo - residuales ( gradiente negativo de MSE ) # Para MSE : -d / d_f [0.5*( y - f ) ^2] = y - f residuals = y - f 75 76 77 78 79 # Paso 2: Ajustar á rbol a los pseudo - residuales tree = SimpleDecisionStump ( max_depth = self . config . max_depth ) h_m = tree . fit_predict (X , residuals ) self . trees_ . append ( tree ) 80 81 82 # Paso 3: Actualizar el modelo con shrinkage ( tasa de aprendizaje ) f += self . config . learning_rate * h_m 83 84 return self 85 86 def predict ( self , X : np . ndarray ) -> np . ndarray : Abraham Zamudio 26
  25. Programación en Python para Ingeniería 3.3 Síntesis y Criterios de

    Selección de Modelos f = np . full ( X . shape [0] , self . initial_prediction_ ) for tree in self . trees_ : f += self . config . learning_rate * tree . fit_predict ( X , np . zeros ( X . shape [0]) # Placeholder para predicci ó n ) return f 87 88 89 90 91 92 93 94 95 96 97 # Demostraci ó n np . random . seed (42) X_reg = np . sort ( np . random . uniform (0 , 10 , 200) ) . reshape ( -1 , 1) y_reg = np . sin ( X_reg . ravel () ) + np . random . normal (0 , 0.2 , 200) 98 99 100 101 102 103 config = GBMConfig ( n_estimators =50 , learning_rate =0.1 , max_depth =3) gbm = GradientBoostingRegressor ( config ) gbm . fit ( X_reg , y_reg ) print ( f " N ú mero de á rboles entrenados : { len ( gbm . trees_ ) } " ) print ( f " Predicci ó n inicial ( media ) : { gbm . initial_prediction_ :.4 f } " ) Listing 5: Gradient Boosting desde cero: descenso de gradiente en espacio funcional 3.3 Síntesis y Criterios de Selección de Modelos La Sección 3 ha proporcionado un análisis exhaustivo de las tres grandes familias de algoritmos supervisados, revelando que la elección del modelo no es una cuestión empírica arbitraria, sino una decisión de ingeniería fundamentada en las propiedades matemáticas del problema: 1. Modelos Lineales (Ridge/Lasso/Logística): Óptimos cuando la relación subyacente es aproximadamente lineal o cuando la interpretabilidad y la inferencia estadística (intervalos de confianza, tests de hipótesis) son prioritarias. Ridge es preferible cuando todas las características son informativas (efecto de contracción uniforme); Lasso cuando se sospecha que solo un subconjunto es relevante (selección de variables). Su costo computacional 𝑂 (𝑛𝑑 2 ) los hace escalables a millones de instancias. 2. SVM con Kernels: Teóricamente óptimas para márgenes de clasificación en espacios de dimensión moderada-alta. El kernel RBF proporciona flexibilidad no lineal universal, pero la complejidad 𝑂 (𝑛2 𝑑) a 𝑂 (𝑛3 ) del entrenamiento las hace prohibitivas para 𝑛 > 105 . Su fortaleza radica en la solidez teórica (cotas de generalización basadas en la dimensión VC del espacio de características inducido) y en la garantía de optimalidad global del problema dual convexo. 3. Ensembles (Random Forest / Gradient Boosting): Dominan las competencias de ML tabular (Kaggle) y la mayoría de los casos de uso industrial. Random Forest es robusto .out-of-thebox"(pocos hiperparámetros críticos, resistente al overfitting por la ley de grandes números del bagging). Gradient Boosting (especialmente XGBoost/LightGBM) ofrece el mejor rendimiento predictivo a costa de una sintonización más delicada (learning rate, profundidad, regularización). Su capacidad de manejar heterogeneidad de características (numéricas, categóricas, missing values) y su eficiencia computacional mediante histogramas los convierten en la opción por defecto para datos estructurados. La comprensión profunda de la descomposición sesgo-varianza, las condiciones KKT y la teoría del gradiente funcional presentadas en esta sección constituye el andamiaje analítico indispensable para diagnosticar fallos de generalización, seleccionar arquitecturas adecuadas y justificar decisiones de modelado ante stakeholders técnicos y no técnicos. En la Sección 4, extenderemos este marco al dominio no supervisado, donde la ausencia de etiquetas transforma radicalmente la formulación del problema y las métricas de éxito. Abraham Zamudio 27
  26. Programación en Python para Ingeniería 4 Aprendizaje No Supervisado Si

    el aprendizaje supervisado es el arte de aproximar funciones condicionales 𝑃(𝑌 |𝑋), el aprendizaje no supervisado es la disciplina matemática de inferir la estructura intrínseca de la distribución marginal 𝑃(𝑋). Al carecer de la señal de retroalimentación explícita proporcionada por las etiquetas 𝑦, el algoritmo debe extraer patrones latentes, regularidades estadísticas y topologías subyacentes únicamente a partir de la geometría del espacio de características X. Esta sección aborda con rigor formal los dos pilares de este paradigma: el agrupamiento (clustering) como problema de partición y estimación de densidad, y la reducción de dimensionalidad como proyección óptima y preservación de variedades (manifolds). 4.1 Principios y Descubrimiento de Estructuras El aprendizaje no supervisado no busca "predecir.en el sentido clásico, sino çomprimir", "segmentar.o representar". Matemáticamente, esto se enmarca en la teoría de la información y la geometría diferencial. Definición Técnica i.i.d. 𝑛 Objetivos del Aprendizaje No Supervisado Dado un conjunto de datos D = {x𝑖 }𝑖=1 ∼ 𝑃𝑋 , 𝑑 donde x𝑖 ∈ R , las tareas fundamentales se clasifican en: 1. Estimación de Densidad: Construir un estimador 𝑝(x) ˆ que aproxime la función de densidad de probabilidad 𝑝(x) subyacente. 2. Agrupamiento (Clustering): Encontrar una partición C = {𝐶1 , 𝐶2 , . . . , 𝐶𝐾 } del dominio X tal que se maximice una medida de similitud intra-cluster y se minimice la similitud inter-cluster. 3. Reducción de Dimensionalidad: Hallar una aplicación (mapping) 𝜙 : R𝑑 → R 𝑘 con 𝑘 ≪ 𝑑, tal que la representación z𝑖 = 𝜙(x𝑖 ) preserve propiedades geométricas o topológicas críticas de los datos originales. La viabilidad de estas tareas descansa sobre la Hipótesis de la Variedad (Manifold Hypothesis), la cual postula que los datos de alta dimensión observados en la práctica rara vez llenan uniformemente R𝑑 ; en cambio, residen en o cerca de una variedad (manifold) de dimensión intrínseca 𝑘 ≪ 𝑑. El aprendizaje no supervisado es, en esencia, el proceso de descubrir y parametrizar esta variedad latente. 4.2 Agrupamiento (Clustering) El clustering es un problema de optimización combinatoria intrínsecamente difícil (NP-hard en su formulación general). Dado que no existe una definición única de çluster", la elección del algoritmo dicta la definición geométrica de lo que se considera un grupo. 4.2.1. Agrupamiento Particional: K-Means El algoritmo 𝐾-Means es el método de clustering más ubicuo en la industria debido a su escalabilidad lineal y su simplicidad conceptual. Su objetivo es minimizar la inercia (o varianza intra-cluster). Abraham Zamudio 28
  27. Programación en Python para Ingeniería 4.2 Agrupamiento (Clustering) Definición Técnica

    Problema de Optimización de K-Means Dado un conjunto de datos D y un número de clusters 𝐾, el objetivo es encontrar una matriz de asignación binaria R ∈ {0, 1}𝑛×𝐾 y una matriz de centroides M ∈ R𝐾×𝑑 que minimicen la función de costo: 𝐽 (R, M) = 𝑛 ∑︁ 𝐾 ∑︁ 𝑟𝑖𝑘 ∥x𝑖 − 𝝁 𝑘 ∥ 22 (32) 𝑖=1 𝑘=1 sujeto a la restricción de que cada punto pertenezca a exactamente un cluster: Í𝐾 𝑘=1 𝑟 𝑖𝑘 = 1, ∀𝑖. El Algoritmo de Lloyd (Expectation-Maximization para Gaussianas Esféricas): Dado que la optimización conjunta de R y M es NP-hard, se utiliza un enfoque de coordenadas descendentes (Coordinate Descent) que alterna entre dos pasos: 1. Paso E (Asignación): Fijar M y actualizar R. Para minimizar 𝐽, cada punto se asigna al centroide más cercano: ( 1 si 𝑘 = arg mı́n 𝑗 ∥x𝑖 − 𝝁 𝑗 ∥ 22 𝑟𝑖𝑘 = (33) 0 en otro caso 2. Paso M (Actualización): Fijar R y actualizar M. Tomando la derivada parcial de 𝐽 respecto a 𝝁 𝑘 e igualando a cero, obtenemos la media condicional: Í𝑛 𝑟𝑖𝑘 x𝑖 𝝁 𝑘 = Í𝑖=1 (34) 𝑛 𝑖=1 𝑟 𝑖𝑘 Proposición / Teorema Convergencia de Lloyd En cada iteración, el valor de la función objetivo 𝐽 (R, M) disminuye monótonamente o permanece constante. Dado que 𝐽 está acotada inferiormente por cero, la secuencia de valores de 𝐽 converge. Limitaciones y Extensiones Computacionales: 𝐾-Means asume implícitamente que los clusters son convexos, isotrópicos (esféricos) y de tamaños similares. Además, es altamente sensible a la inicialización. Para mitigar esto, se utiliza el algoritmo K-Means++, que inicializa los centroides con una probabilidad proporcional a su distancia cuadrática al centroide más cercano ya elegido, garantizando una cota de aproximación de 𝑂 (log 𝐾) respecto al óptimo global. Selección del número de clusters (𝐾): Dado que 𝐾 es un hiperparámetro, su selección requiere métricas de validación interna: Método del Codo (Elbow Method): Se grafica 𝐽 (𝐾) en función de 𝐾. El çodoïndica el punto donde la disminución marginal de la inercia se estabiliza, sugiriendo un sobreajuste geométrico para 𝐾 mayores. Coeficiente de Silueta (Silhouette Coefficient): Mide qué tan similar es un objeto a su propio cluster en comparación con otros clusters. Para una instancia 𝑖, sea 𝑎(𝑖) la distancia media a todos los puntos de su mismo cluster, y 𝑏(𝑖) la distancia media al cluster vecino más cercano (el de menor distancia media). El coeficiente de silueta para 𝑖 es: 𝑠(𝑖) = 𝑏(𝑖) − 𝑎(𝑖) ∈ [−1, 1] máx{𝑎(𝑖), 𝑏(𝑖)} (35) Un valor cercano a 1 indica una asignación densa y bien separada; valores cercanos a 0 indican superposición; valores negativos indican una posible asignación errónea. Abraham Zamudio 29
  28. Programación en Python para Ingeniería 1 4.2 Agrupamiento (Clustering) import

    numpy as np 2 3 4 class KMeansPP : " " "K - Means con inicializaci ó n robusta K - Means ++. " " " 5 6 7 8 9 10 11 12 13 def __init__ ( self , k : int , max_iter : int = 300 , tol : float = 1e -4 , random_state : int = None ) : self . k = k self . max_iter = max_iter self . tol = tol self . rng = np . random . default_rng ( random_state ) self . centroids_ : np . ndarray | None = None self . labels_ : np . ndarray | None = None self . inertia_ : float = np . inf 14 15 16 17 def _init_centroids_pp ( self , X : np . ndarray ) -> np . ndarray : n = X . shape [0] centroids = [ X [ self . rng . integers ( n ) ]] 18 19 20 =0) 21 22 23 24 25 26 for _ in range (1 , self . k ) : dists = np . min ([ np . sum (( X - c ) **2 , axis =1) for c in centroids ] , axis probs = dists / dists . sum () cumprobs = np . cumsum ( probs ) r = self . rng . random () idx = np . searchsorted ( cumprobs , r ) centroids . append ( X [ idx ]) return np . array ( centroids ) 27 28 29 def fit ( self , X : np . ndarray ) -> " KMeansPP " : self . centroids_ = self . _init_centroids_pp ( X ) 30 for _ in range ( self . max_iter ) : # Paso E : Asignaci ó n dists = np . linalg . norm ( X [: , np . newaxis ] - self . centroids_ , axis =2) self . labels_ = np . argmin ( dists , axis =1) 31 32 33 34 35 # Paso M : Actualizaci ó n ( protegido contra clusters vac í os ) new_centroids = np . zeros_like ( self . centroids_ ) for k in range ( self . k ) : mask = self . labels_ == k if np . any ( mask ) : new_centroids [ k ] = X [ mask ]. mean ( axis =0) else : new_centroids [ k ] = X [ self . rng . integers ( X . shape [0]) ] 36 37 38 39 40 41 42 43 44 # Criterio de convergencia shift = np . linalg . norm ( new_centroids - self . centroids_ ) self . centroids_ = new_centroids if shift < self . tol : break 45 46 47 48 49 50 51 52 **2) self . inertia_ = float ( np . sum ([ np . sum (( X [ self . labels_ == k ] - self . centroids_ [ k ]) 53 ]) ) 54 55 for k in range ( self . k ) return self 56 57 Abraham Zamudio 30
  29. Programación en Python para Ingeniería 58 59 60 61 62

    63 4.2 Agrupamiento (Clustering) def silhouette_score ( X : np . ndarray , labels : np . ndarray ) -> float : " " " Calcula el coeficiente de silueta medio ( implementaci ó n vectorizada ) . " " " n = X . shape [0] unique_labels = np . unique ( labels ) if len ( unique_labels ) < 2: return -1.0 64 65 66 67 dist_matrix = np . linalg . norm ( X [: , np . newaxis ] - X , axis =2) a = np . zeros ( n ) b = np . full (n , np . inf ) 68 69 70 71 72 for i in range ( n ) : cluster_i = labels [ i ] mask_same = labels == cluster_i mask_same [ i ] = False 73 if mask_same . sum () > 0: a [ i ] = dist_matrix [i , mask_same ]. mean () else : a [ i ] = 0.0 74 75 76 77 78 for k in unique_labels : if k == cluster_i : continue mask_k = labels == k if mask_k . sum () > 0: dist_k = dist_matrix [i , mask_k ]. mean () if dist_k < b [ i ]: b [ i ] = dist_k 79 80 81 82 83 84 85 86 87 88 89 s = ( b - a ) / np . maximum (a , b ) return float ( np . mean ( s ) ) 90 91 92 93 94 95 96 # Ejemplo de uso np . random . seed (42) X_demo = np . vstack ([ np . random . randn (100 , 2) + [2 , 2] , np . random . randn (100 , 2) + [ -2 , -2]]) kmeans = KMeansPP ( k =2 , random_state =42) . fit ( X_demo ) print ( f " Inercia final : { kmeans . inertia_ :.2 f } " ) print ( f " Silueta media : { silhouette_score ( X_demo , kmeans . labels_ ) :.4 f } " ) Listing 6: Implementación de K-Means con Inicialización K-Means++ y Cálculo de Silueta 4.2.2. Agrupamiento Jerárquico A diferencia de 𝐾-Means, el clustering jerárquico no requiere especificar 𝐾 a priori y construye una jerarquía anidada de clusters, representada visualmente mediante un dendrograma. Enfoque Aglomerativo (Bottom-Up): Inicialmente, cada punto es su propio cluster (𝑛 clusters). En cada paso, se fusionan los dos clusters más cercanos hasta que todos los puntos pertenecen a un solo cluster. La complejidad computacional ingenua es 𝑂 (𝑛3 ) debido a la actualización de la matriz de distancias, reducible a 𝑂 (𝑛2 log 𝑛) con estructuras de datos eficientes. La definición de "distancia entre clusters"(criterio de enlace o linkage) determina la topología de la jerarquía: Single Linkage (Enlace Simple): 𝑑 (𝐶𝑖 , 𝐶 𝑗 ) = mı́nx∈𝐶𝑖 ,y∈𝐶 𝑗 𝑑 (x, y). Tiende a producir clusters alargados y sufre del .efecto encadenamiento"(chaining effect). Complete Linkage (Enlace Completo): 𝑑 (𝐶𝑖 , 𝐶 𝑗 ) = máxx∈𝐶𝑖 ,y∈𝐶 𝑗 𝑑 (x, y). Favorece clusters compactos y esféricos, similar a 𝐾-Means. Abraham Zamudio 31
  30. Programación en Python para Ingeniería 1 Average Linkage (Enlace Promedio):

    𝑑 (𝐶𝑖 , 𝐶 𝑗 ) = |𝐶𝑖 ||𝐶 𝑗| robusto entre los dos anteriores. 4.3 Reducción de Dimensionalidad Í Í x∈𝐶𝑖 y∈𝐶 𝑗 𝑑 (x, y). Un compromiso Ward’s Method (Método de Ward): No se basa en una métrica de distancia directa, sino en la minimización de la varianza. Fusiona los clusters que resultan en el menor incremento de la suma total de errores cuadráticos (inercia). Es matemáticamente equivalente a la ANOVA y es el criterio por defecto para datos continuos debido a su optimalidad estadística. 4.2.3. Agrupamiento Basado en Densidad: DBSCAN Los métodos particionales y jerárquicos fallan catastróficamente cuando los clusters tienen formas arbitrarias, no convexas, o cuando el dataset contiene ruido significativo. DBSCAN (Density-Based Spatial Clustering of Applications with Noise) aborda esto definiendo clusters como regiones continuas de alta densidad separadas por regiones de baja densidad. Definición Técnica Formalización de DBSCAN Dados los parámetros 𝜖 > 0 (radio de vecindad) y MinPts ≥ 1 (densidad mínima), se define la 𝜖-vecindad de un punto x como: N𝜖 (x) = {y ∈ D | 𝑑 (x, y) ≤ 𝜖 } (36) Un punto x se clasifica como: 1. Punto Núcleo (Core): Si |N𝜖 (x)| ≥ MinPts. 2. Punto Borde (Border): Si |N𝜖 (x)| < MinPts, pero pertenece a la 𝜖-vecindad de algún punto núcleo. 3. Punto de Ruido (Noise): Si no es ni núcleo ni borde. Conectividad Densa: DBSCAN construye clusters basándose en la conectividad densa directa. Un punto y es densamente conectado directamente a x si x es núcleo y y ∈ N𝜖 (x). Un cluster es el conjunto maximal de puntos densamente conectados. Complejidad Computacional: La búsqueda ingenua de vecindades tiene complejidad 𝑂 (𝑛2 ). Sin embargo, utilizando estructuras de indexación espacial como KD-Trees o Ball-Trees, la complejidad se reduce a 𝑂 (𝑛 log 𝑛) en espacios de baja dimensionalidad (𝑑 < 20). Para dimensionalidades altas, la maldición de la dimensionalidad degrada estas estructuras, requiriendo aproximaciones basadas en hashing local (LSH) o gráficos de vecinos (HNSW). Nota de Implementación La principal ventaja de DBSCAN es su capacidad para identificar outliers de forma nativa (los puntos de ruido) y detectar clusters de topologías complejas (e.g., anillos concéntricos, espirales). Su principal desventaja es la dificultad para calibrar los hiperparámetros 𝜖 y MinPts en datasets con densidades heterogéneas (clusters con distintas varianzas). Para estos casos, algoritmos evolucionados como OPTICS o HDBSCAN (Hierarchical DBSCAN) construyen un árbol de reachability que adapta la noción de densidad localmente. 4.3 Reducción de Dimensionalidad La reducción de dimensionalidad es crucial para mitigar la maldición de la dimensionalidad, comprimir información, eliminar colinealidad y visualizar datos en 2D o 3D. Se divide en métodos lineales (proyecciones ortogonales) y no lineales (preservación de variedades). Abraham Zamudio 32
  31. Programación en Python para Ingeniería 4.3.1. 4.3 Reducción de Dimensionalidad

    Análisis de Componentes Principales (PCA) PCA es la técnica lineal por excelencia. Busca un subespacio lineal de dimensión 𝑘 que capture la máxima varianza de los datos, o equivalentemente, que minimice el error de reconstrucción ortogonal. Proposición / Teorema Derivación de PCA vía Multiplicadores de Lagrange Sea X𝑐 ∈ R𝑛×𝑑 la matriz de datos centrada 1 X𝑇𝑐 X𝑐 . Buscamos un (media cero por columnas). La matriz de covarianza empírica es S = 𝑛−1 𝑑 𝑇 vector unitario v ∈ R que maximice la varianza proyectada v Sv. Formulamos el Lagrangiano con la restricción de norma unitaria v𝑇 v = 1: L (v, 𝜆) = v𝑇 Sv − 𝜆(v𝑇 v − 1) (37) Derivando respecto a v e igualando a cero: ∇v L = 2Sv − 2𝜆v = 0 =⇒ Sv = 𝜆v (38) Esta es la ecuación de autovalores. Sustituyendo en la función objetivo, la varianza es v𝑇 (𝜆v) = 𝜆v𝑇 v = 𝜆. Por lo tanto, para maximizar la varianza, v debe ser el autovector asociado al autovalor más grande de S. Conexión con la Descomposición en Valores Singulares (SVD): En la práctica, nunca se calcula S explícitamente para luego resolver el problema de autovalores, ya que elevar al cuadrado los valores singulares amplifica los errores de precisión de punto flotante. En su lugar, se aplica la SVD directamente a la matriz de datos centrada: X𝑐 = U𝚺V𝑇 (39) donde U ∈ R𝑛×𝑑 y V ∈ R𝑑×𝑑 son matrices ortogonales, y 𝚺 es diagonal con los valores singulares 𝜎1 ≥ 𝜎2 ≥ · · · ≥ 𝜎𝑑 ≥ 0. Las columnas de V (los componentes principales) son exactamente los 𝜎2 autovectores de S, y los autovalores de S son 𝜆 𝑗 = 𝑛−1𝑗 . La proyección de los datos en los primeros 𝑘 componentes principales se obtiene simplemente como Z 𝑘 = X𝑐 V 𝑘 , donde V 𝑘 contiene las primeras 𝑘 columnas de V. Criterio de Retención de Componentes: La fracción de varianza explicada por el 𝑗-ésimo Í 𝜆 componente es 𝑓 𝑗 = Í𝑑 𝑗 𝜆 . Se selecciona 𝑘 tal que la varianza acumulada 𝑘𝑗=1 𝑓 𝑗 supere un umbral 𝑚=1 𝑚 (típicamente 0.90 - 0.95), o mediante el Scree Plot (gráfico de sedimentación) buscando el codo en la curva de autovalores. 4.3.2. Métodos No Lineales: t-SNE y UMAP PCA falla cuando la variedad subyacente es no lineal (e.g., un rollo de papel enrollado en 3D). Los métodos de Manifold Learning buscan "desenrollar.esta variedad preservando la topología local. t-Distributed Stochastic Neighbor Embedding (t-SNE): Introducido por van der Maaten y Hinton (2008), t-SNE es el estándar de facto para la visualización exploratoria de alta calidad. Fundamentación Matemática: t-SNE convierte las distancias euclidianas de alta dimensión en probabilidades condicionales que representan similitudes. En el espacio de alta dimensión, la similitud de x 𝑗 dado x𝑖 se modela con una distribución Gaussiana centrada en x𝑖 con varianza 𝜎𝑖2 (ajustada mediante búsqueda binaria para lograr una perplejidad objetivo):  exp −∥x𝑖 − x 𝑗 ∥ 2 /2𝜎𝑖2 𝑝 𝑗 |𝑖 = Í (40)  2 2 𝑘≠𝑖 exp −∥x𝑖 − x 𝑘 ∥ /2𝜎𝑖 Se define la similitud conjunta 𝑝𝑖 𝑗 = Abraham Zamudio 𝑝 𝑗 |𝑖 +𝑝 𝑖 | 𝑗 . 2𝑛 33
  32. Programación en Python para4.4 Ingeniería Síntesis Teórica y Transición a

    la Ingeniería de Características En el espacio de baja dimensión (2D o 3D), las similitudes 𝑞𝑖 𝑗 se modelan utilizando una distribución t de Student con un grado de libertad (equivalente a una distribución de Cauchy): 𝑞𝑖 𝑗 = Í 1 + ∥y𝑖 − y 𝑗 ∥ 2 𝑘≠𝑙  −1 1 + ∥y 𝑘 − y𝑙 ∥ 2  −1 (41) El uso de colas pesadas (Cauchy) en lugar de Gaussianas es la genialidad de t-SNE: resuelve el problema de aglomeración (crowding problem), permitiendo que puntos moderadamente distantes en alta dimensión se separen adecuadamente en 2D sin colapsar en un solo cúmulo central. El objetivo es minimizar la Divergencia de Kullback-Leibler entre la distribución conjunta 𝑃 y 𝑄: ∑︁ 𝑝𝑖 𝑗 𝐶 = 𝐾 𝐿(𝑃||𝑄) = 𝑝𝑖 𝑗 log (42) 𝑞𝑖 𝑗 𝑖≠ 𝑗 El gradiente tiene una forma elegante y computable:   −1 ∑︁ 𝜕𝐶 =4 ( 𝑝𝑖 𝑗 − 𝑞𝑖 𝑗 ) 1 + ∥y𝑖 − y 𝑗 ∥ 2 (y𝑖 − y 𝑗 ) 𝜕y𝑖 𝑗≠𝑖 (43) Este gradiente se optimiza utilizando Descenso de Gradiente con momentum y una fase inicial de early exaggeration (multiplicar 𝑝𝑖 𝑗 por 4) para facilitar la formación de clusters bien separados. Uniform Manifold Approximation and Projection (UMAP): UMAP (McInnes et al., 2018) ha ganado popularidad por ser más rápido que t-SNE y preservar mejor la estructura global (distancias entre clusters). Fundamentación en Topología Algebraica: UMAP asume que los datos están distribuidos uniformemente en una variedad Riemanniana localmente conectada. Construye un grafo fuzzy ponderado en alta dimensión donde los pesos representan la probabilidad de que exista una arista entre dos puntos, basada en la distancia y una noción de densidad local (k-vecinos más cercanos). En baja dimensión, UMAP construye un grafo fuzzy análogo y optimiza la cross-entropy binaria entre las estructuras de los dos grafos: " ! !# ∑︁ 1 − 𝑤 𝑖𝐻𝑗 𝑤 𝑖𝐻𝑗 𝐶= 𝑤 𝑖𝐻𝑗 log + (1 − 𝑤 𝑖𝐻𝑗 ) log (44) 𝐿 𝐿 𝑤 1 − 𝑤 𝑖𝑗 𝑖𝑗 𝑖≠ 𝑗 donde 𝑤 𝐻 y 𝑤 𝐿 son los pesos de las aristas en alta y baja dimensión respectivamente. Esta formulación permite el uso de técnicas de optimización estocástica por lotes (mini-batch SGD), haciendo que UMAP escale a millones de puntos, mientras que t-SNE tiene una complejidad cuadrática 𝑂 (𝑛2 ) que lo limita a decenas de miles de puntos (salvo usando Barnes-Hut t-SNE con 𝑂 (𝑛 log 𝑛)). 4.4 Síntesis Teórica y Transición a la Ingeniería de Características La Sección 4 ha desentrañado la anatomía matemática del aprendizaje no supervisado, revelando que no constituye un conjunto de heurísticas aisladas, sino un marco riguroso de inferencia geométrica y topológica. Hemos establecido que el agrupamiento (clustering) no es una tarea monolítica, sino un espectro de problemas de optimización combinatoria y estimación de densidad. Desde la minimización de la inercia euclidiana en 𝐾-Means y la construcción de dendrogramas ultramétricos en el clustering jerárquico, hasta la identificación de componentes conexas en grafos de densidad mediante DBSCAN, cada algoritmo impone un sesgo inductivo distinto sobre la topología de los clusters, dictando qué estructuras latentes en la distribución marginal 𝑃(𝑋) son recuperables. De manera análoga, la reducción de dimensionalidad se ha formalizado más allá de la simple compresión de datos. Desde la proyección ortogonal de máxima varianza y minimización del error de Abraham Zamudio 34
  33. Programación en Python para4.4 Ingeniería Síntesis Teórica y Transición a

    la Ingeniería de Características reconstrucción (PCA/SVD), hasta la preservación de variedades Riemannianas de dimensión intrínseca baja mediante la optimización de divergencias de información (t-SNE) y la cross-entropy de grafos fuzzy (UMAP). Estas técnicas son operadores matemáticos 𝜙 : R𝑑 → R 𝑘 que mapean datos crudos, ruidosos y colineales hacia espacios latentes Z donde las relaciones no lineales se vuelven linealmente separables o donde la redundancia informacional ha sido purgada. El Paradigma de los Transformadores en Programación Orientada a Objetos Desde la perspectiva de la ingeniería de software y la arquitectura de sistemas de ML, estos algoritmos trascienden su rol analítico para integrarse como componentes fundamentales en los flujos de Feature Engineering. En el paradigma de la POO implementado en librerías como scikit-learn, los modelos no supervisados se estructuran bajo el patrón de diseño Transformer. A diferencia de los predictores supervisados que exponen un método predict, los Transformers exponen una interfaz dual: 1. fit(X): Estima los parámetros de la transformación (e.g., los autovectores de la matriz de covarianza en PCA, los centroides en 𝐾-Means, o la estructura del grafo de vecinos en UMAP). Matemáticamente, calcula 𝜙ˆD ≈ 𝜙. 2. transform(X): Aplica la proyección determinista Z = 𝜙ˆD (X) a nuevos datos, utilizando estrictamente los parámetros estimados en la fase de ajuste. Esta abstracción permite la composición funcional mediante Pipelines, garantizando que las transformaciones no supervisadas se encadenen matemáticamente con los estimadores supervisados posteriores, manteniendo la inmutabilidad de los datos originales y la trazabilidad de las operaciones. El Aprendizaje No Supervisado como Motor de Características El aprendizaje no supervisado actúa así como un generador de características de alto nivel, enriqueciendo el espacio de entrada X para los modelos supervisados: Decorrelación y Regularización Implícita: El PCA no solo reduce la dimensionalidad, sino que rota el espacio de características hacia un sistema de coordenadas ortogonales. Alimentar un modelo de Regresión Lineal o Logística con componentes principales elimina la multicolinealidad perfecta, estabilizando la inversión de matrices (o la convergencia del descenso de gradiente) y actuando como un regularizador de Tikhonov implícito (PCA Truncado). Features Basados en Distancia y Densidad: Las salidas de algoritmos de clustering enriquecen el espacio de entrada. Las distancias euclidianas a los 𝐾 centroides (en 𝐾-Means) o las distancias al 𝑘-ésimo vecino más cercano (en LOF - Local Outlier Factor) se inyectan como nuevas variables continuas que capturan la rareza.o la "pertenencia estructural"de una instancia. De manera similar, la etiqueta de ruido generada por DBSCAN puede utilizarse para filtrar instancias anómalas antes del entrenamiento supervisado, o como una característica binaria indicativa de anomalía. Embeddings Topológicos: Las representaciones de baja dimensión generadas por UMAP o t-SNE, al preservar la topología local y global de la variedad subyacente, sirven como embeddings densos. Estos vectores latentes pueden ser concatenados con las características tabulares originales para alimentar modelos basados en árboles (como XGBoost o LightGBM), proporcionando a los algoritmos de división de nodos una señal geométrica global que de otra manera requeriría árboles de mayor profundidad para descubrir. Rigor Estadístico: Prevención de Fuga de Datos (Data Leakage) La integración de transformadores no supervisados conlleva un riesgo estadístico crítico que debe ser mitigado mediante disciplina computacional estricta: la fuga de datos (Data Leakage). Dado que Abraham Zamudio 35
  34. Programación en Python para4.4 Ingeniería Síntesis Teórica y Transición a

    la Ingeniería de Características los transformadores 𝜙 estiman parámetros globales a partir de los datos, es imperativo que el método fit se ejecute exclusivamente sobre el conjunto de entrenamiento Dtrain . Nota de Implementación Si se aplica fit_transform sobre el conjunto completo antes de la partición, o si se calculan los centroides de 𝐾-Means utilizando datos de validación, se contamina el espacio latente Z con información del futuro (o de la evaluación). Formalmente, esto viola la suposición de que los datos de prueba son realizaciones independientes no vistas durante el entrenamiento. El resultado es una estimación del error de generalización E[𝐿(𝑌 , 𝑓ˆ(Z))] sesgada y excesivamente optimista, lo que en producción se traduce en un despliegue de modelos que fallan catastróficamente al enfrentarse a datos verdaderamente inéditos. Transición Formal a la Sección 5 El dominio exhaustivo de estos algoritmos, sus condiciones de convergencia, sus complejidades asintóticas y sus implementaciones vectorizadas en Python, constituye el puente indispensable hacia la Sección 5. En la próxima sección, abandonaremos el dominio de la inferencia de la distribución marginal 𝑃(𝑋) para adentrarnos en la estimación de la distribución condicional 𝑃(𝑌 |Z). Tomaremos las representaciones latentes y las características ingenierizadas Z = 𝜙(X) como el nuevo espacio de entrada formal, diseccionando rigurosamente los problemas de clasificación y regresión, y estableciendo las métricas de evaluación estadística que permiten cuantificar, auditar y garantizar el éxito predictivo de los modelos en entornos industriales reales y restrictivos. Abraham Zamudio 36
  35. Programación en Python para Ingeniería 5 Problemas de Clasificación y

    de Regresión Habiendo establecido los fundamentos teóricos de los algoritmos supervisados (Sección 3) y las técnicas de representación latente (Sección 4), es imperativo formalizar rigurosamente los criterios de evaluación. En la ingeniería de Machine Learning, un modelo no es "bueno.o "malo.en términos absolutos; su utilidad es una función estricta de la métrica de rendimiento elegida, la cual debe estar intrínsecamente alineada con la función de costo de negocio. Esta sección disecciona las diferencias topológicas y probabilísticas entre clasificación y regresión, y proporciona un marco matemático completo para la cuantificación del error, la calibración de modelos y el diagnóstico estadístico de residuos. 5.1 Formalización de Clasificación vs. Regresión Aunque ambos problemas pertenecen al paradigma supervisado, la naturaleza del espacio de salida Y dicta diferencias fundamentales en la topología del espacio de hipótesis H , la elección de la función de pérdida 𝐿 y la interpretación geométrica del error. Definición Técnica Espacios de Salida y Naturaleza del Problema Sea X ⊆ R𝑑 el espacio de características. Definimos los dos problemas fundamentales: 1. Clasificación: El espacio de salida es un conjunto finito y discreto Y = {𝐶1 , 𝐶2 , . . . , 𝐶𝐾 }. Para 𝐾 = 2, tenemos clasificación binaria (Y = {0, 1}). El objetivo probabilístico es estimar la distribución condicional categórica 𝑃(𝑌 = 𝐶 𝑘 |X = x). Geométricamente, el modelo aprende una frontera de decisión 𝜕D ⊂ X que particiona el espacio en regiones de Voronoi generalizadas. 2. Regresión: El espacio de salida es un subconjunto continuo Y ⊆ R. El objetivo probabilístico es estimar la esperanza condicional (o un cuantil) 𝐸 [𝑌 |X = x]. Geométricamente, el modelo aproxima una función de valor continuo 𝑓 : X → R, y el error se mide como la desviación métrica (distancia) en R. Análisis Comparativo de la Interpretación del Residuo La divergencia más crítica entre ambos paradigmas radica en cómo se conceptualiza y penaliza el residuo 𝜖𝑖 = 𝑦𝑖 − 𝑦ˆ 𝑖 : En Clasificación: El residuo no es una magnitud escalar continua, sino un estado discreto de asignación. Un error no es ün poco malo.o "muy malo.en términos de distancia euclidiana; es una violación de la frontera de decisión. Por ello, las funciones de pérdida no operan sobre 𝑦 − 𝑦ˆ directamente, sino sobre las probabilidades estimadas 𝑝. ˆ La Log-Loss (Entropía Cruzada) penaliza la confianza incorrecta de manera logarítmica: 𝐿(𝑦, 𝑝) ˆ = −[𝑦 log( 𝑝) ˆ + (1 − 𝑦) log(1 − 𝑝)]. ˆ Un error con alta confianza (ej. predecir 𝑝ˆ = 0,01 cuando 𝑦 = 1) recibe una penalización asintóticamente infinita, forzando al modelo a ser conservador en sus fronteras. En Regresión: El residuo es una magnitud continua en R. La interpretación es puramente métrica. Si utilizamos 𝑀𝑆𝐸, el espacio de pérdida es un paraboloide hiperbólico (convexo y diferenciable). Si utilizamos 𝑀 𝐴𝐸, el espacio es un cono (convexo pero no diferenciable en el origen). La magnitud del error es proporcional a la distancia en el espacio de salida, lo que implica que un error de 10 unidades es exactamente el doble de "malo"que un error de 5 unidades (bajo 𝐿 1 ) o cuatro veces peor (bajo 𝐿 2 ). Abraham Zamudio 37
  36. Programación en Python para Ingeniería 5.2 5.2 Métricas de Rendimiento

    en Clasificación Métricas de Rendimiento en Clasificación La evaluación de clasificadores requiere herramientas de la teoría de la decisión estadística. Dado que las probabilidades 𝑝ˆ son continuas pero las etiquetas 𝑦 son discretas, toda métrica de clasificación depende implícitamente de un umbral de decisión 𝑡 ∈ [0, 1], donde 𝑦ˆ = I( 𝑝ˆ ≥ 𝑡). 5.2.1. La Matriz de Confusión y Métricas Derivadas Definición Técnica Matriz de Confusión Binaria Para un umbral 𝑡, definimos los cuatro resultados fundamentales mediante funciones indicadoras sobre el conjunto de prueba D𝑡𝑒𝑠𝑡 de tamaño 𝑁: 𝑇𝑃 = 𝑇𝑁 = 𝑁 ∑︁ I(𝑦𝑖 = 1 ∧ 𝑦ˆ 𝑖 = 1), 𝐹𝑃 = 𝑁 ∑︁ 𝑖=1 𝑖=1 𝑁 ∑︁ 𝑁 ∑︁ I(𝑦𝑖 = 0 ∧ 𝑦ˆ 𝑖 = 0), 𝐹𝑁 = 𝑖=1 I(𝑦𝑖 = 0 ∧ 𝑦ˆ 𝑖 = 1) I(𝑦𝑖 = 1 ∧ 𝑦ˆ 𝑖 = 0) 𝑖=1 A partir de esta matriz, derivamos las métricas operativas, las cuales deben interpretarse desde una perspectiva bayesiana: 𝑃+𝑇 𝑁 ˆ 1. Exactitud (Accuracy): 𝑇 𝑃+𝑇𝑇𝑁+𝐹𝑃+𝐹 𝑁 . Representa la probabilidad a priori de acierto 𝑃(𝑌 = 𝑌 ). Flaw estadístico: Es una métrica paradójica en datasets desbalanceados. Si el 99 % de las instancias son negativas, un clasificador que siempre predice 0 tiene un 99 % de Accuracy, pero es computacionalmente inútil. 𝑇𝑃 2. Precisión (Precision): 𝑇 𝑃+𝐹𝑃 = 𝑃(𝑌 = 1|𝑌ˆ = 1). Es el Valor Predictivo Positivo. Mide la pureza de las alertas. En aplicaciones donde los Falsos Positivos son costosos (ej. spam filter, alertas de fraude que bloquean al usuario), la Precisión es la métrica rey. 𝑇𝑃 ˆ 3. Sensibilidad (Recall / TPR): 𝑇 𝑃+𝐹 𝑁 = 𝑃(𝑌 = 1|𝑌 = 1). Es la Potencia Estadística del test. Mide la capacidad del modelo para no dejar pasar positivos. En aplicaciones donde los Falsos Negativos son catastróficos (ej. diagnóstico de cáncer, mantenimiento predictivo de turbinas), el Recall es la métrica crítica. 𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛·𝑅𝑒𝑐𝑎𝑙𝑙 4. 𝐹1 -Score: 2 · 𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛+𝑅𝑒𝑐𝑎𝑙𝑙 . Es la media armónica de Precisión y Recall. La media armónica penaliza severamente los valores extremos; un 𝐹1 alto requiere que ambas métricas sean altas simultáneamente, evitando el sesgo de la media aritmética. 5.2.2. Curvas ROC y el Estadístico AUC Dado que las métricas anteriores dependen del umbral 𝑡, necesitamos una evaluación invariante al umbral. La curva ROC (Receiver Operating Characteristic) traza la Tasa de Falsos Positivos (FPR) en el eje X contra la Tasa de Verdaderos Positivos (TPR / Recall) en el eje Y, mientras 𝑡 varría de 1 a 0. 𝐹𝑃𝑅(𝑡) = Abraham Zamudio 𝐹𝑃 = 𝑃(𝑌ˆ = 1|𝑌 = 0), 𝐹𝑃 + 𝑇 𝑁 𝑇 𝑃𝑅(𝑡) = 𝑇𝑃 = 𝑃(𝑌ˆ = 1|𝑌 = 1) 𝑇𝑃 + 𝐹𝑁 (45) 38
  37. Programación en Python para Ingeniería 5.2 Métricas de Rendimiento en

    Clasificación Proposición / Teorema Interpretación Probabilística del AUC El Área Bajo la Curva ROC (AUC) no es solo una métrica geométrica; tiene una interpretación estadística profunda. El AUC es exactamente equivalente al estadístico U de Mann-Whitney-Wilcoxon. Formalmente:  𝐴𝑈𝐶 = 𝑃 𝑓 (x+ ) > 𝑓 (x− ) (46) donde x+ es una instancia positiva extraída al azar, x− es una instancia negativa extraída al azar, y 𝑓 (x) es la puntuación (probabilidad) asignada por el modelo. Significado Práctico: Un AUC de 0.85 significa que si extraemos un par positivo-negativo al azar, hay un 85 % de probabilidad de que el modelo asigne una puntuación más alta al positivo. Un AUC de 0.5 indica un clasificador aleatorio (diagonal de la ROC), y un AUC < 0,5 indica que el modelo está aprendiendo la relación inversa (basta con invertir las predicciones). 5.2.3. Manejo de Clases Desbalanceadas Cuando 𝑃(𝑌 = 1) ≪ 𝑃(𝑌 = 0), el gradiente del modelo se ve dominado por la clase mayoritaria. Las soluciones se clasifican en tres enfoques matemáticos: 1. Cost-Sensitive Learning (A nivel de Algoritmo): En lugar de balancear los datos, modificamos la función de pérdida. Asignamos costos asimétricos 𝐶𝐹𝑃 y 𝐶𝐹 𝑁 . La nueva pérdida empírica es: 𝑛 1 ∑︁ ˆ [𝐶𝐹 𝑁 · 𝑦𝑖 · 𝐿(𝑦𝑖 , 𝑦ˆ 𝑖 ) + 𝐶𝐹𝑃 · (1 − 𝑦𝑖 ) · 𝐿(𝑦𝑖 , 𝑦ˆ 𝑖 )] 𝑅𝑐𝑜𝑠𝑡 (𝜃) = 𝑛 𝑖=1 (47) En la práctica, esto se implementa en scikit-learn mediante el parámetro class_weight=’balanced’, 𝑛 que escala la pérdida inversamente proporcional a la frecuencia de la clase: 𝑤 𝑘 = 𝐾·𝑛 . 𝑘 2. SMOTE (A nivel de Datos): Synthetic Minority Over-sampling Technique. En lugar de hacer un simple oversampling (que causa sobreajuste por duplicación exacta), SMOTE genera instancias sintéticas interpolando en el espacio de características. Para una instancia minoritaria x𝑖 y su vecino x 𝑗 (ambos de la clase 1), se genera: x𝑛𝑒𝑤 = x𝑖 + 𝜆(x 𝑗 − x𝑖 ), donde 𝜆 ∼ U (0, 1) (48) Esto expande la región de decisión de la clase minoritaria de forma suave y continua. 3. Threshold-Tuning (A nivel de Decisión): Entrenamos el modelo con la pérdida estándar (o cost-sensitive), pero no usamos 𝑡 = 0,5 para clasificar. Buscamos el umbral óptimo 𝑡 ∗ que maximice una métrica de negocio. Una técnica robusta es maximizar el Índice J de Youden: 𝑡 ∗ = arg máx (𝑇 𝑃𝑅(𝑡) − 𝐹𝑃𝑅(𝑡)) (49) 𝑡 Esto encuentra el punto en la curva ROC que está a la máxima distancia vertical de la línea de no-discriminación (diagonal). 1 2 import numpy as np from typing import Tuple 3 4 5 class ClassificationEvaluator : " " " Motor de evaluaci ó n de clasificadores con c á lculo de m é tricas y tuning de umbral . " " " 6 Abraham Zamudio 39
  38. Programación en Python para Ingeniería 7 8 9 10 11

    12 13 14 15 5.2 Métricas de Rendimiento en Clasificación def __init__ ( self , y_true : np . ndarray , y_scores : np . ndarray ) : """ Args : y_true : Etiquetas binarias verdaderas ( n_samples ,) . y_scores : Probabilidades continuas predichas para la clase positiva ( n_samples ,) . """ self . y_true = np . asarray ( y_true , dtype = int ) self . y_scores = np . asarray ( y_scores , dtype = float ) self . _validate_inputs () 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def _validate_inputs ( self ) : if self . y_true . shape != self . y_scores . shape : raise ValueError ( " Las dimensiones de y_true y y_scores deben coincidir . " ) if not np . all ( np . isin ( self . y_true , [0 , 1]) ) : raise ValueError ( " y_true debe contener ú nicamente etiquetas binarias (0 , 1) . " ) if not np . all (( self . y_scores >= 0) & ( self . y_scores <= 1) ) : raise ValueError ( " y_scores debe contener probabilidades en el intervalo [0 , 1]. " ) 30 31 32 33 def compute_metrics_at_threshold ( self , t : float = 0.5) -> dict : " " " Calcula la matriz de confusi ó n y m é tricas derivadas para un umbral t . """ y_pred = ( self . y_scores >= t ) . astype ( int ) 34 tp fp tn fn 35 36 37 38 = = = = np . sum (( self . y_true np . sum (( self . y_true np . sum (( self . y_true np . sum (( self . y_true == == == == 1) 0) 0) 1) & & & & ( y_pred ( y_pred ( y_pred ( y_pred == == == == 1) ) 1) ) 0) ) 0) ) 39 40 41 42 43 precision = tp / ( tp + fp ) if ( tp + fp ) > 0 else 0.0 recall = tp / ( tp + fn ) if ( tp + fn ) > 0 else 0.0 f1 = 2 * ( precision * recall ) / ( precision + recall ) if ( precision + recall ) > 0 else 0.0 accuracy = ( tp + tn ) / ( tp + fp + tn + fn ) 44 45 46 47 : f1 48 return { " threshold " : t , " tp " : tp , " fp " : fp , " tn " : tn , " fn " : fn , " accuracy " : accuracy , " precision " : precision , " recall " : recall , " f1 " } 49 50 51 52 53 54 55 def compute_auc ( self ) -> float : " " " Calcula el AUC utilizando la regla del trapecio sobre la curva ROC emp í rica . " " " # Ordenar por puntuaciones descendentes desc_score_indices = np . argsort ( self . y_scores ) [:: -1] y_score_sorted = self . y_scores [ desc_score_indices ] y_true_sorted = self . y_true [ desc_score_indices ] 56 57 58 # Identificar umbrales ú nicos distinct_value_indices = np . where ( np . diff ( y_score_sorted ) ) [0] Abraham Zamudio 40
  39. Programación en Python para Ingeniería 5.3 Métricas de Rendimiento en

    Regresión threshold_indices = np . concatenate ([ distinct_value_indices , np . array ([ len ( y_true_sorted ) - 1]) ]) 59 60 # Calcular TPR y FPR acumulados tps = np . cumsum ( y_true_sorted ) [ threshold_indices ] fps = threshold_indices + 1 - tps 61 62 63 64 tps = np . concatenate ([ np . array ([0]) , tps ]) fps = np . concatenate ([ np . array ([0]) , fps ]) 65 66 67 tpr = tps / tps [ -1] fpr = fps / fps [ -1] 68 69 70 # Integraci ó n num é rica ( Regla del trapecio ) auc = np . trapz ( tpr , fpr ) return float ( auc ) 71 72 73 74 def find_optimal_threshold_youden ( self ) -> Tuple [ float , dict ]: " " " Encuentra el umbral que maximiza el Í ndice J de Youden ( TPR - FPR ) . " " " thresholds = np . linspace (0.01 , 0.99 , 200) best_j , best_t , best_metrics = - np . inf , 0.5 , {} 75 76 77 78 79 for t in thresholds : metrics = self . compute_metrics_at_threshold ( t ) j_index = metrics [ " recall " ] - ( metrics [ " fp " ] / ( metrics [ " fp " ] + metrics [ " tn " ]) ) if j_index > best_j : best_j = j_index best_t = t best_metrics = metrics 80 81 82 83 84 85 86 87 return best_t , best_metrics 88 89 90 91 92 93 94 # Ejemplo de uso np . random . seed (42) y_t = np . concatenate ([ np . zeros (900) , np . ones (100) ]) # Dataset desbalanceado 9:1 # Simulamos scores donde el modelo tiene un AUC ~ 0.85 y_s = np . clip ( np . concatenate ([ np . random . beta (2 , 5 , 900) , np . random . beta (5 , 2 , 100) ]) , 0.01 , 0.99) 95 96 97 evaluator = ClassificationEvaluator ( y_t , y_s ) print ( f " AUC del modelo : { evaluator . compute_auc () :.4 f } " ) 98 99 100 101 102 opt_t , opt_metrics = evaluator . find_optimal_threshold_youden () print ( f " Umbral ó ptimo ( Youden J ) : { opt_t :.3 f } " ) print ( f " M é tricas en umbral ó ptimo -> Precision : { opt_metrics [ ' precision ']:.3 f } , " f" Recall : { opt_metrics [ ' recall ']:.3 f } , F1 : { opt_metrics [ ' f1 ']:.3 f } " ) Listing 7: Evaluación Rigurosa y Threshold-Tuning mediante el Índice J de Youden 5.3 Métricas de Rendimiento en Regresión En regresión, al no existir un umbral de decisión, la evaluación se centra en la magnitud, la distribución y la varianza de los residuos 𝜖𝑖 = 𝑦𝑖 − 𝑦ˆ 𝑖 . Abraham Zamudio 41
  40. Programación en Python para Ingeniería 5.3.1. 5.3 Métricas de Rendimiento

    en Regresión Métricas de Error Basadas en Normas 1. Error Cuadrático Medio (MSE) y Raíz (RMSE): √ 𝑛 1 ∑︁ 𝑀𝑆𝐸 = (𝑦𝑖 − 𝑦ˆ 𝑖 ) 2 , 𝑛 𝑖=1 𝑅𝑀𝑆𝐸 = 𝑀𝑆𝐸 (50) Análisis: El MSE es la norma 𝐿 2 al cuadrado. Al elevar al cuadrado, penaliza desproporcionadamente los errores grandes (outliers). Estadísticamente, si el modelo es insesgado, 𝑀𝑆𝐸 = Var(𝜖). El RMSE es preferible para la interpretación de negocio porque recupera las unidades originales de la variable 𝑌 . 2. Error Absoluto Medio (MAE): 𝑛 1 ∑︁ 𝑀 𝐴𝐸 = |𝑦𝑖 − 𝑦ˆ 𝑖 | 𝑛 𝑖=1 (51) Análisis: Es la norma 𝐿 1 . Es una métrica robusta frente a outliers, ya que el gradiente de la pérdida es constante (±1) independientemente de la magnitud del error. Si la distribución de los errores tiene colas pesadas, el MAE es una métrica mucho más representativa del error "típico"que el RMSE. 3. Error Porcentual Absoluto Medio (MAPE): 𝑀 𝐴𝑃𝐸 = 𝑛 100 % ∑︁ 𝑦𝑖 − 𝑦ˆ 𝑖 𝑛 𝑖=1 𝑦𝑖 (52) Análisis y Crítica Matemática: Aunque es intuitivo para stakeholders (.el modelo se equivoca un 5 % en promedio"), el MAPE tiene defectos matemáticos severos: Asimetría de Penalización: Penaliza mucho más los sobreajustes (predicciones mayores al valor real) que los subajustes. Si 𝑦 = 100 y 𝑦ˆ = 150, el error es 50 %. Si 𝑦ˆ = 50, el error es 50 %. Pero si 𝑦ˆ → ∞, el error → ∞; mientras que si 𝑦ˆ → 0, el error está acotado en 100 %. Esto sesga al modelo a predecir hacia abajo (underforecasting). Indefinición: Si 𝑦𝑖 = 0, el MAPE explota (división por cero). Alternativa: Se prefiere el SMAPE (Symmetric MAPE) o el MAE escalado por la media. 5.3.2. Coeficiente de Determinación (𝑅 2 ) y Ajustado El 𝑅 2 mide la proporción de la varianza en la variable dependiente 𝑌 que es predecible a partir de las variables independientes X. Definición Técnica Í𝑛 Formalización del 𝑅 2 Sea 𝑆𝑆𝑡𝑜𝑡 = 𝑖=1 (𝑦𝑖 − 𝑦¯ ) 2 la suma total de cuadrados (varianza total no Í𝑛 explicada) y 𝑆𝑆𝑟𝑒𝑠 = 𝑖=1 (𝑦𝑖 − 𝑦ˆ 𝑖 ) 2 la suma de cuadrados de los residuos (varianza no explicada por el modelo). 𝑆𝑆𝑟𝑒𝑠 𝑅2 = 1 − (53) 𝑆𝑆𝑡𝑜𝑡 Interpretación Geométrica: En el espacio de Hilbert 𝐿 2 , 𝑅 2 es el cuadrado del coseno del ángulo entre el vector de valores reales centrados (y − ȳ) y el vector de predicciones centradas ( ŷ − ȳ). Un 𝑅 2 = 1 significa que ambos vectores son colineales (ajuste perfecto). Abraham Zamudio 42
  41. Programación en Python para Ingeniería 5.3 Métricas de Rendimiento en

    Regresión El Problema de la Complejidad y el 𝑅 2 Ajustado: El 𝑅 2 tiene una propiedad matemática peligrosa: siempre aumenta o se mantiene igual al añadir nuevas variables al modelo, incluso si estas son puro ruido (variables espurias). Para penalizar la complejidad (número de predictores 𝑝), utilizamos el Adjusted 𝑅 2 :   𝑛−1 𝑆𝑆𝑟𝑒𝑠 /(𝑛 − 𝑝 − 1) 2 𝑅𝑎𝑑 𝑗 = 1 − = 1 − (1 − 𝑅 2 ) (54) 𝑆𝑆𝑡𝑜𝑡 /(𝑛 − 1) 𝑛− 𝑝−1 𝑛−1 El término 𝑛−𝑝−1 actúa como un factor de penalización basado en los grados de libertad. Si añadimos una variable irrelevante, la disminución en 𝑆𝑆𝑟𝑒𝑠 no compensará la pérdida de grados de libertad, y el 2 disminuirá. Esto lo convierte en la métrica canónica para la selección de modelos en regresión 𝑅𝑎𝑑 𝑗 lineal múltiple. 5.3.3. Análisis Diagnóstico de Residuales Las métricas de error globales (MSE, 𝑅 2 ) son necesarias pero no suficientes. Para que un modelo de regresión sea estadísticamente válido (especialmente si se utilizan para inferencia o intervalos de confianza), los residuos 𝜖𝑖 deben cumplir los supuestos de Gauss-Markov. 1. Homocedasticidad (Varianza Constante): Supuesto: 𝑉 𝑎𝑟 (𝜖𝑖 |X) = 𝜎 2 , ∀𝑖. Diagnóstico: Gráfico de Residuos vs. Valores Ajustados. Si los residuos forman un patrón de .embudo.o çono", existe heterocedasticidad. Esto invalida los errores estándar de los coeficientes. Test Formal: Test de Breusch-Pagan. Regresiona los residuos al cuadrado 𝜖𝑖2 contra X. Si las variables de X son estadísticamente significativas en esta regresión auxiliar, se rechaza la homocedasticidad. Solución Computacional: Utilizar errores estándar robustos (White / HC3) o transformar la variable objetivo (Box-Cox, log). 2. Normalidad de los Residuos: Supuesto: 𝜖𝑖 ∼ N (0, 𝜎 2 ). Diagnóstico: Gráfico Q-Q (QuantileQuantile). Se grafizan los cuantiles empíricos de los residuos contra los cuantiles teóricos de una N (0, 1). Si los puntos se desvían de la línea diagonal 𝑦 = 𝑥, la normalidad se viola. Test Formal: Test de Jarque-Bera, basado en la asimetría (skewness) y la curtosis (kurtosis) de los residuos:   𝑛 2 (𝐾 − 3) 2 𝐽𝐵 = 𝑆 + ∼ 𝜒22 (55) 6 4 donde 𝑆 es la asimetría y 𝐾 la curtosis muestral. Impacto: La falta de normalidad no sesga las predicciones puntuales 𝑦ˆ , pero invalida los intervalos de predicción y los tests de hipótesis sobre los coeficientes. 1 2 import numpy as np from scipy import stats 3 4 5 class RegressionDiagnostics : " " " An á lisis estad í stico de residuos para validaci ó n de supuestos de regresi ó n.""" 6 7 8 9 10 11 def __init__ ( self , y_true : np . ndarray , y_pred : np . ndarray ) : self . y_true = np . asarray ( y_true , dtype = float ) self . y_pred = np . asarray ( y_pred , dtype = float ) self . residuals = self . y_true - self . y_pred self . n = len ( self . y_true ) 12 13 14 15 16 def compute_metrics ( self ) -> dict : " " " Calcula MSE , RMSE , MAE , MAPE y R2 . " " " ss_res = np . sum ( self . residuals **2) ss_tot = np . sum (( self . y_true - np . mean ( self . y_true ) ) **2) 17 Abraham Zamudio 43
  42. Programación en Python para Ingeniería 18 19 20 21 5.3

    Métricas de Rendimiento en Regresión mae = np . mean ( np . abs ( self . residuals ) ) # MAPE con protecci ó n contra divisi ó n por cero mask = self . y_true != 0 mape = np . mean ( np . abs ( self . residuals [ mask ] / self . y_true [ mask ]) ) * 100 if np . any ( mask ) else np . nan 22 23 24 25 26 27 28 29 return { " MSE " : np . mean ( self . residuals **2) , " RMSE " : np . sqrt ( np . mean ( self . residuals **2) ) , " MAE " : mae , " MAPE " : mape , " R2 " : 1 - ( ss_res / ss_tot ) if ss_tot > 0 else 0.0 } 30 31 32 33 34 35 36 37 38 39 def test_homoscedasticity_breusch_pagan ( self ) -> dict : """ Test de Breusch - Pagan simplificado . Eval ú a si la varianza de los residuos depende de los valores ajustados . """ # Regresi ó n auxiliar : residuos ^2 ~ y_pred # Usamos OLS manual para evitar dependencias circulares X_aux = np . column_stack ([ np . ones ( self . n ) , self . y_pred ]) y_aux = self . residuals **2 40 41 42 43 # Beta = ( X 'X ) ^ -1 X 'y beta = np . linalg . lstsq ( X_aux , y_aux , rcond = None ) [0] y_aux_pred = X_aux @ beta 44 45 46 47 48 # Estad í stico de prueba ( LM - Lagrange Multiplier ) lm_stat = np . sum (( y_aux_pred - np . mean ( y_aux ) ) **2) / np . sum ( y_aux **2 / self . n ) # El estad í stico sigue una chi - cuadrada con 1 grado de libertad ( solo y_pred ) p_value = 1 - stats . chi2 . cdf ( lm_stat , df =1) 49 50 51 52 53 54 55 56 return { " LM_statistic " : lm_stat , " p_value " : p_value , " is_homoscedastic " : p_value > 0.05 , " interpretation " : " No se rechaza homocedasticidad ( p > 0.05) " if p_value > 0.05 else " Evidencia de heterocedasticidad ( p <= 0.05) " } 57 58 59 60 61 62 63 64 65 66 67 def test_normality_jarque_bera ( self ) -> dict : " " " Test de Jarque - Bera para normalidad de residuos . " " " jb_stat , p_value = stats . jarque_bera ( self . residuals ) return { " JB_statistic " : jb_stat , " p_value " : p_value , " is_normal " : p_value > 0.05 , " skewness " : stats . skew ( self . residuals ) , " kurtosis " : stats . kurtosis ( self . residuals , fisher = True ) # Exceso de curtosis } 68 69 70 71 # Ejemplo de uso np . random . seed (42) n_samples = 500 Abraham Zamudio 44
  43. Programación en Python para Ingeniería 72 73 74 75 76

    5.4 Síntesis y Transición al Flujo de Trabajo de ML X_test = np . random . uniform (0 , 10 , n_samples ) # Generamos datos con heterocedasticidad ( varianza aumenta con X ) noise = np . random . normal (0 , X_test * 0.5) y_test = 2.5 * X_test + 10 + noise y_pred_test = 2.5 * X_test + 10 # Predicci ó n perfecta del componente determinista 77 78 79 80 81 diag = RegressionDiagnostics ( y_test , y_pred_test ) print ( " M é tricas Globales : " , diag . compute_metrics () ) print ( " Test Homocedasticidad : " , diag . test_homoscedasticity_breusch_pagan () ) print ( " Test Normalidad : " , diag . test_normality_jarque_bera () ) Listing 8: Motor de Diagnóstico de Residuales para Regresión 5.4 Síntesis y Transición al Flujo de Trabajo de ML La Sección 5 ha establecido que la evaluación de modelos no es un paso final de verificación, sino un proceso de diagnóstico estadístico continuo. Hemos formalizado cómo la topología del espacio de salida Y dicta la naturaleza del error (discreto vs. continuo), y cómo las métricas deben elegirse no por convención, sino por la función de costo asimétrica del negocio (ej. maximizar Recall en salud, minimizar MAPE en inventarios). Asimismo, hemos demostrado que las métricas globales (Accuracy, RMSE, 𝑅 2 ) son insuficientes si no se acompañan de un análisis riguroso de los residuos (homocedasticidad, normalidad) y de la calibración de los umbrales de decisión (Curvas ROC, Índice J de Youden). Este marco de evaluación exhaustivo es el cimiento sobre el cual se construye la Sección 6. En la próxima sección, integraremos estas métricas y diagnósticos dentro del Ciclo de Vida de un Proyecto de ML. Abordaremos cómo prevenir la fuga de datos (Data Leakage) mediante validación cruzada anidada, cómo optimizar hiperparámetros sin sobreajustar el conjunto de validación, y cómo empaquetar estos modelos y sus transformadores previos en Pipelines robustos y reproducibles para su despliegue en entornos de producción (MLOps). Abraham Zamudio 45
  44. Programación en Python para Ingeniería 6 Flujo Básico de Trabajo

    de un Proyecto de ML Habiendo consolidado el arsenal teórico y algorítmico en las secciones precedentes, nos enfrentamos al desafío de ingeniería más crítico: la orquestación de estos componentes en un sistema cohesivo, reproducible y escalable. El Machine Learning en producción no es un ejercicio de modelado aislado en un entorno de laboratorio; es una disciplina de ingeniería de sistemas donde la matemática se intersecta con la arquitectura de software, la gestión de datos y la monitorización continua. Esta sección formaliza el ciclo de vida completo de un proyecto de ML, elevando las prácticas empíricas a un marco riguroso basado en la teoría de la computación, la estadística bayesiana y los principios de MLOps. 6.1 Fases del Ciclo de Vida de ML: Una Perspectiva de Teoría de Categorías Desde una perspectiva de la informática teórica, un pipeline de Machine Learning puede modelarse formalmente utilizando la Teoría de Categorías. Definimos una categoría C𝑀 𝐿 donde: Los objetos son los estados de los datos (tensores en diferentes etapas de transformación). Los morfismos son las transformaciones deterministas o estocásticas (funciones de preprocesamiento, modelos entrenados) que mapean un estado de datos a otro. La composición de morfismos (𝜙 𝑘 ◦ 𝜙 𝑘−1 ◦ · · · ◦ 𝜙1 ) representa el pipeline end-to-end, donde la asociatividad garantiza que el orden de ejecución es matemáticamente consistente. El ciclo de vida se estructura como un grafo acíclico dirigido (DAG) de seis fases críticas: 1. Definición del Problema (Formalización): Traducción de una métrica de negocio (e.g., maximizar el ROI, minimizar el tiempo de inactividad) a una función de pérdida matemática 𝐿(𝑦, 𝑦ˆ ) y un espacio de hipótesis H . Se establecen las restricciones de latencia, memoria y interpretabilidad. 2. Ingesta y EDA (Análisis Exploratorio): No es solo visualización; es el cálculo de perfiles estadísticos de alto orden. Se evalúan los momentos de las distribuciones marginales 𝑃(𝑋 𝑗 ), las dependencias no lineales (correlación de Spearman, información mutua 𝐼 (𝑋; 𝑌 )) y la estructura de valores faltantes (patrones MCAR, MAR, MNAR). 3. Preprocesamiento e Ingeniería de Características: Aplicación de los morfismos 𝜙 𝑘 para mapear los datos crudos a un espacio Z donde las suposiciones de los algoritmos de H se satisfacen (e.g., estacionariedad, linealidad, independencia condicional). 4. Estrategia de Partición y Validación: Diseño del protocolo de evaluación para estimar el riesgo de generalización E[𝐿] sin incurrir en fuga de datos (Data Leakage), respetando la estructura temporal o espacial de los datos. 5. Entrenamiento y Optimización de Hiperparámetros: Búsqueda en el espacio de configuración Θ para encontrar 𝜃 ∗ = arg mı́n𝜃∈Θ ED [ 𝑅ˆ𝑛 (𝜃)], utilizando algoritmos de optimización global. 6. Evaluación Final y Despliegue: Serialización del pipeline completo, empaquetado en contenedores, y establecimiento de bucles de retroalimentación para la monitorización de la deriva (drift). 6.2 Preprocesamiento e Ingeniería de Características La ingeniería de características es el proceso de aplicar conocimiento de dominio y transformaciones matemáticas para aumentar la capacidad expresiva del espacio de entrada X. Un modelo complejo con características pobres siempre será superado por un modelo simple con características excelentes (el principio de la "navaja de Occam.en ML). Abraham Zamudio 46
  45. Programación en Python para Ingeniería 6.2.1. 6.2 Preprocesamiento e Ingeniería

    de Características Limpieza de Datos: Imputación y Outliers Imputación Multivariada (MICE): La imputación univariada (media, mediana) destruye las covarianzas entre variables. El enfoque riguroso es Multiple Imputation by Chained Equations (MICE). MICE asume que los datos faltantes son Missing at Random (MAR) y modela la distribución condicional completa 𝑃(𝑋 𝑗 |𝑋− 𝑗 , Φ 𝑗 ) para cada variable 𝑋 𝑗 con missing values, utilizando un modelo predictivo (e.g., regresión lineal, random forest). El algoritmo opera mediante un muestreador de Gibbs: 1. Inicializar 𝑋 (0) con imputación simple. 2. Para la iteración 𝑡 = 1 . . . 𝑇: a) Para cada variable 𝑗 = 1 . . . 𝑑: (𝑡−1) b) Ajustar el modelo condicional Φ (𝑡) como target y 𝑋−(𝑡−1) como predictores. 𝑗 usando 𝑋 𝑗 𝑗 (𝑡) (𝑡) c) Muestrear los valores faltantes de la distribución predictiva posterior: 𝑋 𝑗,𝑚𝑖𝑠𝑠 ∼ 𝑃(𝑋 𝑗 |𝑋−(𝑡−1) 𝑗 , Φ 𝑗 ). Esto preserva la estructura de correlación multivariada original, generando 𝑚 datasets imputados que luego se combinan mediante las reglas de Rubin para obtener estimaciones robustas y errores estándar correctos. Detección de Outliers Multivariados: La regla de las 3 sigmas (𝜇 ± 3𝜎) falla en dimensiones 𝑑 > 3 debido a la maldición de la dimensionalidad. La herramienta matemática correcta es la Distancia de Mahalanobis: √︁ 𝐷 𝑀 (x) = (x − 𝝁)𝑇 S−1 (x − 𝝁) (56) donde 𝝁 es el vector de medias y S es la matriz de covarianza muestral. Bajo la suposición de normalidad multivariada X ∼ N𝑑 ( 𝝁, S), el cuadrado de la distancia 𝐷 2𝑀 (x) sigue una distribución 𝜒𝑑2 . Un punto se 2 considera outlier si 𝐷 2𝑀 (x) > 𝜒𝑑,1−𝛼 (e.g., 𝛼 = 0,001). Nota computacional: Si S es singular o mal condicionada, se utiliza la Distancia de Mahalanobis Robusta (Minimum Covariance Determinant, MCD), que estima 𝝁 y S utilizando solo el subconjunto de ℎ observaciones con el menor determinante de covarianza, rompiendo el efecto de enmascaramiento (masking effect) de los outliers. 6.2.2. Transformación Numérica y Normalización Transformaciones de Potencia (Box-Cox y Yeo-Johnson): Muchos modelos (e.g., regresión lineal, LDA) asumen normalidad o homocedasticidad. La transformación de Box-Cox busca un parámetro 𝜆 que maximice la log-verosimilitud de los datos transformados bajo una distribución Gaussiana: ( 𝜆 𝑦 𝑖 −1 si 𝜆 ≠ 0 (𝜆) 𝜆 sujeto a 𝑦𝑖 > 0 (57) 𝑦𝑖 = ln(𝑦𝑖 ) si 𝜆 = 0 Dado que Box-Cox requiere 𝑦 > 0, la transformación de Yeo-Johnson extiende este concepto a todo R, aplicando Box-Cox a 𝑦 si 𝑦 ≥ 0 y una transformación análoga a −𝑦 si 𝑦 < 0. El parámetro 𝜆 se optimiza mediante búsqueda en cuadrícula o métodos de Newton sobre la perfil de log-verosimilitud. 6.2.3. Codificación Categórica: Target Encoding Bayesiano El One-Hot Encoding dispersa la matriz de diseño y es ineficiente para variables de alta cardinalidad. El Target Encoding reemplaza la categoría por la media de la variable objetivo en esa categoría. Sin embargo, para categorías con pocas muestras, esto introduce un sobreajuste severo (ruido). La solución rigurosa es el Target Encoding con Suavizado Bayesiano (Bayesian Smoothing). Tratamos la media global 𝜇 como un prior y la media de la categoría 𝜇𝑐 como la verosimilitud. La estimación suavizada 𝜇ˆ 𝑐 es una media ponderada: 𝜇ˆ 𝑐 = 𝜆(𝑛𝑐 ) · 𝜇𝑐 + (1 − 𝜆(𝑛𝑐 )) · 𝜇 Abraham Zamudio (58) 47
  46. Programación en Python para Ingeniería 6.2 Preprocesamiento e Ingeniería de

    Características donde el factor de suavizado 𝜆(𝑛𝑐 ) depende del número de muestras 𝑛𝑐 en la categoría y de la varianza global 𝜎 2 : 𝑛𝑐 1  o formalmente: 𝜆(𝑛𝑐 ) =  𝜆(𝑛𝑐 ) = (59) 𝑛𝑐 + 𝑚 1 + exp − 𝑛𝑐 −𝑘 𝑓 donde 𝑚 es un parámetro de regularización (frecuencia efectiva del prior). Si 𝑛𝑐 ≫ 𝑚, 𝜆 → 1 y confiamos en la media de la categoría. Si 𝑛𝑐 → 0, 𝜆 → 0 y regresamos a la media global, previniendo el sobreajuste. 6.2.4. Feature Engineering: Interacciones y Agregaciones La ingeniería de características explícita permite a modelos lineales capturar no linealidades. Interacciones Polinómicas y de Tensor: Dado x ∈ R𝑑 , generamos x ⊗ x (producto exterior) o 𝑑+𝑝  combinaciones de grado 𝑝. La dimensionalidad resultante es 𝑝 , lo que requiere una posterior reducción de dimensionalidad (PCA truncado o regularización 𝐿 1 ). Agregaciones Temporales (Rolling Windows): Para series de tiempo, extraemos características estadísticas sobre ventanas deslizantes 𝑊𝑡 = [𝑥𝑡−𝑤 , . . . , 𝑥𝑡 ]. Características como mean(𝑊𝑡 ), std(𝑊𝑡 ), skew(𝑊𝑡 ), y la tasa de cruce por cero (zero-crossing rate) capturan la dinámica local y la volatilidad, transformando un problema de serie temporal en uno de regresión tabular supervisada. 1 2 import numpy as np 3 4 5 from scipy . stats import boxcox_normmax , from scipy . stats import yeojohnson yeojohnson_normmax 6 7 8 9 10 11 12 13 14 15 class BayesianTargetEncoder : """ Target Encoding con suavizado bayesiano para prevenir overfitting en categor í as de baja frecuencia . """ def __init__ ( self , smoothing_factor : float = 10.0) : self . m = smoothing_factor # Regularizaci ó n ( frecuencia del prior ) self . global_mean_ : float = 0.0 self . mapping_ : dict = {} 16 17 18 19 def fit ( self , categories : np . ndarray , target : np . ndarray ) -> " BayesianTargetEncoder " : self . global_mean_ = np . mean ( target ) self . mapping_ = {} 20 21 22 23 24 25 unique_cats = np . unique ( categories ) for cat in unique_cats : mask = categories == cat n_c = np . sum ( mask ) mu_c = np . mean ( target [ mask ]) 26 27 28 29 30 # Factor de suavizado bayesiano lambda_c = n_c / ( n_c + self . m ) smoothed_target = lambda_c * mu_c + (1 - lambda_c ) * self . global_mean_ self . mapping_ [ cat ] = smoothed_target 31 32 return self 33 34 def transform ( self , categories : np . ndarray ) -> np . ndarray : Abraham Zamudio 48
  47. Programación en Python para Ingeniería 6.3 Estrategias de Partición y

    Validación # Manejo de categor í as no vistas en entrenamiento ( fallback a media global ) return np . array ([ self . mapping_ . get ( cat , self . global_mean_ ) for cat in categories ]) 35 36 37 38 39 class PowerTransformerRobust : " " " Transformaci ó n de Yeo - Johnson para normalizar datos con ceros y negativos .""" 40 def __init__ ( self ) : self . lambda_ : float = 1.0 41 42 43 def fit ( self , X : np . ndarray ) -> " PowerTransformerRobust " : # Optimizaci ó n de la log - verosimilitud de perfil para encontrar lambda ó ptimo self . lambda_ = yeojohnson_normmax ( X ) return self 44 45 46 47 48 def transform ( self , X : np . ndarray ) -> np . ndarray : # Aplicaci ó n de la transformaci ó n de Yeo - Johnson return yeojohnson (X , lmbda = self . lambda_ ) 49 50 51 52 53 54 55 # Ejemplo de uso np . random . seed (42) cats = np . random . choice ([ 'A ' , 'B ' , 'C ' , ' Rare '] , size =1000 , p =[0.4 , 0.3 , 0.2 , 0.1]) 56 57 58 59 # Asignar literales float para inicializar target como float64 target = np . where ( cats == 'A ' , 10.0 , np . where ( cats == 'B ' , 5.0 , np . where ( cats == 'C ' , 2.0 , 0.0) ) ) target += np . random . normal (0 , 1 , 1000) # Ahora suma float64 + float64 sin problemas 60 61 62 63 encoder = BayesianTargetEncoder ( smoothing_factor =5.0) . fit ( cats , target ) encoded = encoder . transform ( cats ) print ( f " Medias suavizadas -> A : { encoder . mapping_ [ ' A ']:.2 f } , Rare : { encoder . mapping_ [ ' Rare ']:.2 f } " ) 64 65 66 67 68 69 70 71 # Transformaci ó n de datos sesgados ( ej . ingresos con colas pesadas ) income = np . random . exponential ( scale =30000 , size =500) pt = PowerTransformerRobust () . fit ( income ) income_norm = pt . transform ( income ) print ( f " Lambda ó ptimo de Yeo - Johnson : { pt . lambda_ :.4 f } " ) print ( f " Asimetr í a original : { np . mean ((( income - income . mean () ) / income . std () ) **3) :.2 f } -> " f" Transformada : { np . mean ((( income_norm - income_norm . mean () ) / income_norm . std () ) **3) :.2 f } " ) Listing 9: Implementación de Target Encoding Bayesiano y Transformación de Yeo-Johnson 6.3 Estrategias de Partición y Validación La evaluación del modelo es un problema de estimación estadística. El objetivo es estimar el riesgo esperado ED [𝐿( 𝑓ˆD )] con la menor varianza y sesgo posible, garantizando que la estimación sea insesgada respecto a datos futuros no vistos. Abraham Zamudio 49
  48. Programación en Python para Ingeniería 6.3.1. 6.3 Estrategias de Partición

    y Validación El Flagelo del Data Leakage La fuga de datos ocurre cuando información del conjunto de prueba (o del futuro) contamina el proceso de entrenamiento. Matemáticamente, esto viola la suposición fundamental de que los conjuntos D𝑡𝑟𝑎𝑖𝑛 y D𝑡𝑒𝑠𝑡 son realizaciones independientes de P. Fuentes comunes de Leakage: Preprocesamiento Global: Estandarizar (𝑍-score) o imputar usando la media de todo el dataset antes de dividir. La media de D𝑡𝑒𝑠𝑡 se filtra en D𝑡𝑟𝑎𝑖𝑛 . Target Leakage: Incluir características que se calculan después del evento a predecir (e.g., usar la .edad al cierre de la cuenta"para predecir si la cuenta se abrirá). Solución Arquitectónica: Utilizar Pipelines estrictos donde los transformadores se ajustan (fit) exclusivamente en los folds de entrenamiento y se aplican (transform) en los folds de validación. 6.3.2. Validación Cruzada: K-Fold y Variantes La validación cruzada de 𝐾 particiones (K-Fold) reduce la varianza de la estimación del error en comparación con una sola división Hold-Out. Proposición / Teorema Sesgo y Varianza de K-Fold Sea 𝑛 el tamaño de la muestra y 𝑘 el número de folds. El tamaño del conjunto de entrenamiento en cada fold es 𝑛(1 − 1/𝑘). Leave-One-Out (LOOC, 𝑘 = 𝑛): Estimador casi insesgado del error verdadero, pero con alta varianza porque los conjuntos de entrenamiento están altamente correlacionados entre sí. Costo computacional: 𝑂 (𝑛 · 𝐶𝑡𝑟𝑎𝑖𝑛 ). K-Fold estándar (𝑘 = 5 o 10): Compromiso óptimo. El sesgo es ligeramente mayor que LOOC (entrenamos con 0,9𝑛 datos en lugar de 0,99𝑛), pero la varianza es significativamente menor. Stratified K-Fold: Para clasificación desbalanceada, garantiza que la proporción de clases 𝑃(𝑌 ) se mantenga constante en cada fold, evitando que algún fold no tenga representación de la clase minoritaria. TimeSeriesSplit (Validación Cruzada Temporal): En series de tiempo, la suposición i.i.d. se viola debido a la autocorrelación temporal. Dividir aleatoriamente (K-Fold) causa fuga de datos futura al pasado. TimeSeriesSplit utiliza una ventana deslizante o expansiva que respeta la causalidad: (𝑘) D𝑡𝑟𝑎𝑖𝑛 = {(x𝑖 , 𝑦𝑖 ) | 𝑖 ≤ 𝑡 𝑘 }, (𝑘) D𝑣𝑎𝑙 = {(x𝑖 , 𝑦𝑖 ) | 𝑡 𝑘 < 𝑖 ≤ 𝑡 𝑘+1 } (60) Esto simula rigurosamente el escenario de producción donde el modelo entrena con datos históricos y predice el futuro. 6.3.3. Optimización de Hiperparámetros: De la Fuerza Bruta a los Procesos Gaussianos El espacio de hiperparámetros Θ = Θ1 × · · · × Θ 𝑝 define la configuración del algoritmo. Grid Search vs. Random Search: Grid Search evalúa una rejilla cartesiana. Su complejidad es Î𝑝 𝑂 ( 𝑖=1 |Θ𝑖 |), sufriendo la maldición de la dimensionalidad. Bergstra y Bengio (2012) demostraron que Random Search es exponencialmente más eficiente que Grid Search cuando solo un subconjunto de los hiperparámetros es influyente, ya que explora el espacio marginal de cada parámetro de forma independiente. Optimización Bayesiana (Bayesian Optimization, BO): Cuando la evaluación de la función objetivo 𝑓 (𝜃) (el score de validación cruzada) es computacionalmente costosa (e.g., entrenar un Abraham Zamudio 50
  49. Programación en Python para Ingeniería 6.3 Estrategias de Partición y

    Validación XGBoost o una Red Neuronal), BO modela 𝑓 (𝜃) como un Proceso Gaussiano (GP): 𝑓 (𝜃) ∼ GP (𝑚(𝜃), 𝑘 (𝜃, 𝜃 ′)) (61) donde 𝑚(𝜃) es la función de media (usualmente 0) y 𝑘 (𝜃, 𝜃 ′) es el kernel (e.g., Matérn 5/2), que codifica la suposición de suavidad de la función. A medida que evaluamos puntos 𝜃 1:𝑡 , actualizamos la distribución posterior del GP. Para decidir el siguiente punto a evaluar, utilizamos una Función de Adquisición (Acquisition Function), como la Expected Improvement (EI):   EI(𝜃) = E máx 𝑓 (𝜃 + ) − 𝑓 (𝜃), 0 (62) donde 𝜃 + es el mejor hiperparámetro encontrado hasta el momento. EI equilibra la explotación (zonas donde el GP predice un score alto) y la exploración (zonas donde la varianza del GP es alta). Maximizar EI es analíticamente tratable usando la PDF y CDF de la distribución normal. 1 2 3 4 5 6 from typing import Any , Callable import numpy as np from scipy . optimize import minimize from scipy . stats import norm 7 8 9 10 11 class BayesianOptimizerCore : """ Implementaci ó n del n ú cleo matem á tico de Optimizaci ó n Bayesiana 12 13 utilizando la funci ó n de adquisici ó n Expected Improvement ( EI ) . 14 15 16 17 18 Soporta tanto estimadores con interfaz tipo scikit - learn (. predict (X , return_std = True ) ) como funciones directas ( callables ) que retornen la tupla ( mean , std ) . """ 19 20 21 def __init__ ( self , bounds : np . ndarray ) : " " " Args : 22 bounds : Array de forma (d , 2) con los l í mites [ inferior , superior ] de cada hiperpar á metro . """ self . bounds = np . asarray ( bounds , dtype = float ) self . dim = self . bounds . shape [0] 23 24 25 26 27 28 29 30 31 ]. " 32 33 34 35 36 37 if self . bounds . ndim != 2 or self . bounds . shape [1] != 2: raise ValueError ( " bounds debe ser un array de dimensi ó n (d , 2) con pares [ min , max ) if np . any ( self . bounds [: , 0] >= self . bounds [: , 1]) : raise ValueError ( " Cada l í mite inferior debe ser estrictamente menor que el " " superior . " ) 38 39 40 41 42 43 44 def expected_improvement ( self , X_candidate : np . ndarray , gp_mean : np . ndarray , gp_std : np . ndarray , best_score : float , Abraham Zamudio 51
  50. Programación en Python para Ingeniería 45 46 47 6.3 Estrategias

    de Partición y Validación xi : float = 0.01 , ) -> np . ndarray : " " " Calcula anal í ticamente la Expected Improvement ( EI ) para un conjunto de candidatos . 48 49 50 Se asume un problema de MINIMIZACI Ó N ( ej . funci ó n de p é rdida o error de validaci ó n ) . 51 52 53 54 55 56 57 58 59 Args : X_candidate : Puntos candidatos de evaluaci ó n ( n_points , d ) . gp_mean : Medias predichas por el GP ( n_points ,) . gp_std : Desviaciones est á ndar predichas por el GP ( n_points ,) . best_score : El valor m í nimo de la funci ó n objetivo observado hasta el momento . xi : Par á metro de exploraci ó n que balancea explotaci ó n / exploraci ó n . 60 61 62 63 64 65 Returns : Valores de EI correspondientes a cada candidato ( n_points ,) . """ gp_mean = np . asarray ( gp_mean , dtype = float ) gp_std = np . asarray ( gp_std , dtype = float ) 66 67 68 # Evitar divisi ó n por cero en regiones con certeza absoluta gp_std = np . maximum ( gp_std , 1e -9) 69 70 71 72 # Magnitud de la mejora esperada respecto al mejor valor hist ó rico improvement = best_score - gp_mean - xi Z = improvement / gp_std 73 74 75 # Expresi ó n en forma cerrada de EI bajo supuestos Gaussianos ei = improvement * norm . cdf ( Z ) + gp_std * norm . pdf ( Z ) 76 77 78 79 # La mejora esperada es id é nticamente cero si no hay varianza ni mejora potencial ei = np . where ( gp_std <= 1e -9 , 0.0 , ei ) return np . maximum ( ei , 0.0) 80 81 82 83 84 85 86 87 88 89 def suggest_next_point ( self , gp_model : Any | Callable , best_score : float , xi : float = 0.01 , n_restarts : int = 25 , random_state : int | None = None , ) -> np . ndarray : " " " Sugiere el siguiente punto hiperparam é trico a evaluar maximizando la EI 90 91 mediante optimizaci ó n multirreinicios con L - BFGS - B . 92 93 94 95 96 97 98 99 100 Args : gp_model : Modelo GP ( con m é todo . predict (X , return_std = True ) ) o callable f ( X ) . best_score : El valor m í nimo hist ó rico registrado . xi : Par á metro de exploraci ó n para la adquisici ó n . n_restarts : N ú mero de inicializaciones aleatorias para sortear m í nimos locales . random_state : Semilla para reproducibilidad de los reinicios . 101 Abraham Zamudio 52
  51. Programación en Python para Ingeniería 102 103 104 105 106

    6.3 Estrategias de Partición y Validación Returns : Vector 1 D con las coordenadas del pr ó ximo punto propuesto en el espacio de b ú squeda . """ rng = np . random . default_rng ( random_state ) 107 108 109 def neg_ei ( x : np . ndarray ) -> float : x_2d = x . reshape (1 , -1) 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 # Polimorfismo : soporta interfaz scikit - learn o callables nativos if hasattr ( gp_model , " predict " ) : mean , std = gp_model . predict ( x_2d , return_std = True ) elif callable ( gp_model ) : out = gp_model ( x_2d ) if isinstance ( out , tuple ) and len ( out ) == 2: mean , std = out else : raise TypeError ( " El callable gp_model debe devolver una tupla ( mean , std ) . " ) else : raise AttributeError ( " gp_model debe exponer el m é todo ' predict ' o ser una funci ó n invocable . " ) 126 127 128 129 ei_val = self . expected_improvement ( x_2d , mean , std , best_score , xi = xi ) 130 131 return float ( - ei_val [0]) 132 133 134 best_x = None best_val = np . inf 135 136 137 138 139 140 141 142 143 144 # Optimizaci ó n con reinicios aleatorios en el dominio acotado for _ in range ( n_restarts ) : x0 = rng . uniform ( self . bounds [: , 0] , self . bounds [: , 1]) res = minimize ( neg_ei , x0 = x0 , bounds = self . bounds , method = "L - BFGS - B " , ) 145 146 147 148 149 if res . success or res . fun < best_val : if res . fun < best_val : best_val = res . fun best_x = res . x 150 151 152 153 # Fallback defensivo ante fallos num é ricos de convergencia if best_x is None : best_x = rng . uniform ( self . bounds [: , 0] , self . bounds [: , 1]) 154 155 return best_x 156 157 158 159 160 # Ejemplo conceptual de uso # Definici ó n de l í mites : [ learning_rate (0.001 a 0.5) , max_depth (1 a 10) ] bounds = np . array ([[1 e -3 , 0.5] , [1.0 , 10.0]]) Abraham Zamudio 53
  52. Programación en Python para Ingeniería 161 6.4 Transición a Producción

    (MLOps Intro) optimizer = BayesianOptimizerCore ( bounds ) 162 163 164 165 166 167 168 # Mock con interfaz compatible ( funci ó n o clase tipo scikit - learn ) def dummy_gp ( X : np . ndarray ) : # Simula predicci ó n de media y desviaci ó n est á ndar mean = np . mean (X , axis =1) std = np . std (X , axis =1) * 0.1 + 0.05 return mean , std 169 170 171 172 173 174 175 # Sugerencia del siguiente hiperpar á metro next_point = optimizer . suggest_next_point ( dummy_gp , best_score =0.15 , random_state =42 ) print ( f " LR sugerido : { next_point [0]:.4 f } " ) print ( f " Depth sugerido : { next_point [1]:.2 f } " ) Listing 10: Núcleo de Optimización Bayesiana: Cálculo de Expected Improvement (EI) 6.4 Transición a Producción (MLOps Intro) El abismo entre un modelo validado en Jupyter y un sistema de ML en producción es donde fracasan el 80 % de los proyectos. MLOps (Machine Learning Operations) aplica los principios de DevOps (versionado, CI/CD, monitorización) al ciclo de vida del ML. 6.4.1. Empaquetado y Serialización: De Pipelines a ONNX Pipelines de ‘scikit-learn‘: La unidad atómica de despliegue no es el modelo, sino el Pipeline. Un pipeline encapsula la secuencia completa de transformaciones 𝜙1 , . . . , 𝜙 𝑘 y el estimador final 𝑓ˆ. Esto garantiza que los datos en producción sufran exactamente las mismas transformaciones deterministas que en entrenamiento. Π(x𝑛𝑒𝑤 ) = 𝑓ˆ (𝜙 𝑘 (. . . 𝜙2 (𝜙1 (x𝑛𝑒𝑤 )) . . . )) (63) En Python, esto se serializa típicamente con joblib o pickle. Sin embargo, pickle es inseguro (vulnerabilidades de ejecución de código arbitrario) y dependiente de la versión de Python/librerías. El Estándar ONNX (Open Neural Network Exchange): Para sistemas de producción de alto rendimiento y multiplataforma, el estándar industrial es ONNX. ONNX representa el pipeline como un grafo computacional dirigido, donde los nodos son operaciones matemáticas (MatMul, Relu, Scaler) y las aristas son tensores. Ventajas Computacionales de ONNX: Interoperabilidad: Entrenas en Python (PyTorch, scikit-learn vía sklearn-onnx), despliegas en C++ (ONNX Runtime), C# o Java. Optimización de Grafo: ONNX Runtime aplica fusiones de nodos (e.g., fusionar MatMul + Add en una sola operación de GPU), cuantización de precisión (FP32 a INT8) y paralelización automática, reduciendo la latencia de inferencia en órdenes de magnitud. 6.4.2. Monitorización Continua: Detección de Drift Una vez desplegado, el modelo opera en un entorno no estacionario. La distribución conjunta de producción 𝑃 𝑝𝑟𝑜𝑑 (𝑋, 𝑌 ) diverge de la distribución de entrenamiento 𝑃𝑡𝑟𝑎𝑖𝑛 (𝑋, 𝑌 ). Esta divergencia se clasifica en dos fenómenos matemáticos distintos: 1. Data Drift (Covariate Shift): Ocurre cuando 𝑃 𝑝𝑟𝑜𝑑 (𝑋) ≠ 𝑃𝑡𝑟𝑎𝑖𝑛 (𝑋), pero la relación condicional se mantiene 𝑃 𝑝𝑟𝑜𝑑 (𝑌 |𝑋) = 𝑃𝑡𝑟𝑎𝑖𝑛 (𝑌 |𝑋). Las características cambian de distribución (e.g., inflación económica cambia los montos de transacciones). Detección Rigurosa: Las pruebas univariadas (Kolmogorov-Smirnov, Chi-cuadrada) fallan en capturar dependencias multivariadas. La métrica Abraham Zamudio 54
  53. Programación en Python para Ingeniería 6.4 Transición a Producción (MLOps

    Intro) robusta es la Discrepancia de Media Máxima (Maximum Mean Discrepancy, MMD) o la Distancia de Wasserstein. La MMD mide la distancia entre las incrustaciones de las distribuciones en un Espacio de Hilbert de Características Reproducidas (RKHS) H asociado a un kernel 𝑘: 2 MMD2 (𝑃, 𝑄) = Ex∼𝑃 [𝜙(x)] − Ey∼𝑄 [𝜙(y)] H (64) Usando el "kernel trick", esto se estima empíricamente sin calcular 𝜙 explícitamente: ∑︁ 2 2 ∑︁ 1 ∑︁ \ = 1 𝑘 (x , x ) − 𝑘 (y𝑖 , y 𝑗 ) 𝑘 (x , y ) + MMD 𝑖 𝑗 𝑖 𝑗 𝑚𝑛 𝑖, 𝑗 𝑚 2 𝑖, 𝑗 𝑛2 𝑖, 𝑗 (65) 2 \ supera un umbral estadístico (calculado mediante bootstrap o permutaciones), se alerta de Si MMD Data Drift. 2. Concept Drift: Ocurre cuando 𝑃 𝑝𝑟𝑜𝑑 (𝑌 |𝑋) ≠ 𝑃𝑡𝑟𝑎𝑖𝑛 (𝑌 |𝑋). La relación fundamental entre las características y el objetivo cambia (e.g., durante una crisis, el comportamiento de gasto de los clientes cambia drásticamente, invalidando las fronteras de decisión aprendidas). Detección: Se monitoriza la distribución de las predicciones 𝑌ˆ o el error en tiempo real (si hay ground truth retrasado). Algoritmos como ADWIN (Adaptive Windowing) mantienen una ventana de tamaño variable que crece hasta que se detecta un cambio significativo en la media del error (usando el test de Hoeffding), momento en el cual la ventana se trunca y se dispara una reentrenamiento. 1 2 import numpy as np from sklearn . metrics . pairwise import rbf_kernel 3 4 5 6 7 8 9 10 11 class MultivariateDriftDetector : """ Detector de Data Drift multivariado utilizando Maximum Mean Discrepancy ( MMD ) con un kernel RBF ( Gaussiano ) . """ def __init__ ( self , gamma : float = None ) : self . gamma = gamma self . threshold_ : float = 0.0 12 13 14 15 16 17 def _compute_mmd_squared ( self , X_train : np . ndarray , X_prod : np . ndarray ) -> float : " " " Calcula la MMD ^2 emp í rica usando el kernel trick . " " " K_XX = rbf_kernel ( X_train , X_train , gamma = self . gamma ) K_YY = rbf_kernel ( X_prod , X_prod , gamma = self . gamma ) K_XY = rbf_kernel ( X_train , X_prod , gamma = self . gamma ) 18 19 m , n = X_train . shape [0] , X_prod . shape [0] 20 21 22 23 24 # Estimador insesgado de MMD ^2 ( excluyendo la diagonal en K_XX y K_YY ) mmd2 = ( K_XX . sum () - np . trace ( K_XX ) ) / ( m * ( m - 1) ) mmd2 += ( K_YY . sum () - np . trace ( K_YY ) ) / ( n * ( n - 1) ) mmd2 -= 2 * K_XY . mean () 25 26 return float ( mmd2 ) 27 28 29 30 31 32 33 def calibrate_threshold ( self , X_train : np . ndarray , n_permutations : int = 100 , alpha : float = 0.05) -> float : """ Calcula el umbral de alerta usando un test de permutaciones ( bootstrap ) . """ mmd_null_dist = [] Abraham Zamudio 55
  54. Programación en Python para Ingeniería 6.5 Síntesis General de la

    sesión y Conclusión X_combined = np . vstack ([ X_train , X_train ]) # Hip ó tesis nula : mismas distribuciones n = X_train . shape [0] 34 35 36 for _ in range ( n_permutations ) : np . random . shuffle ( X_combined ) X_perm_1 = X_combined [: n ] X_perm_2 = X_combined [ n :] mmd_null_dist . append ( self . _compute_mmd_squared ( X_perm_1 , X_perm_2 ) ) 37 38 39 40 41 42 # El umbral es el percentil (1 - alpha ) de la distribuci ó n nula self . threshold_ = np . percentile ( mmd_null_dist , 100 * (1 - alpha ) ) return self . threshold_ 43 44 45 46 def detect_drift ( self , X_prod : np . ndarray , X_train_ref : np . ndarray ) -> dict : mmd2 = self . _compute_mmd_squared ( X_train_ref , X_prod ) return { " MMD_squared " : mmd2 , " threshold " : self . threshold_ , " is_drift_detected " : mmd2 > self . threshold_ , " severity " : " Alta " if mmd2 > self . threshold_ * 2 else " Moderada " if mmd2 > self . threshold_ else " Nula " } 47 48 49 50 51 52 53 54 55 56 57 58 59 60 # Ejemplo de uso np . random . seed (42) X_train = np . random . multivariate_normal ([0 , 0] , [[1 , 0.5] , [0.5 , 1]] , size =500) # Datos en producci ó n con covariate shift ( media desplazada ) X_prod = np . random . multivariate_normal ([1.5 , 1.5] , [[1 , 0.5] , [0.5 , 1]] , size =200) 61 62 63 detector = MultivariateDriftDetector ( gamma =0.5) detector . calibrate_threshold ( X_train , n_permutations =200) 64 65 66 drift_report = detector . detect_drift ( X_prod , X_train ) print ( f " Reporte de Drift : { drift_report } " ) 67 68 69 70 71 72 73 74 75 # # # # # # # # Nota sobre ONNX : En producci ón , el pipeline de scikit - learn se convertir í a as í : from skl2onnx import convert_sklearn from skl2onnx . common . data_types import FloatTensorType initial_type = [( ' float_input ', FloatTensorType ([ None , X_train . shape [1]]) ) ] onnx_model = convert_sklearn ( sklearn_pipeline , initial_types = initial_type ) with open (" model_pipeline . onnx " , " wb ") as f : f . write ( onnx_model . SerializeToString () ) Listing 11: Detección de Data Drift Multivariado mediante MMD y Pipeline ONNX 6.5 Síntesis General de la sesión y Conclusión La Sección 6 ha completado el ciclo de vida del Machine Learning, transformando algoritmos matemáticos aislados en un sistema de ingeniería robusto. Hemos formalizado el preprocesamiento no como un conjunto de trucos empíricos, sino como la aplicación de transformaciones probabilísticas (MICE, Target Encoding Bayesiano) que preservan la integridad estadística de los datos. Hemos elevado la validación cruzada y la optimización de hiperparámetros desde búsquedas ciegas hasta marcos de inferencia bayesiana (Procesos Gaussianos, Expected Improvement) que optimizan el costo computacional. Finalmente, hemos abordado el despliegue mediante la abstracción de grafos computacionales (ONNX) y la monitorización rigurosa de la no estacionariedad mediante tests de Abraham Zamudio 56
  55. Programación en Python para Ingeniería 6.5 Síntesis General de la

    sesión y Conclusión discrepancia de kernels (MMD). Reflexión Final del Paradigma POO en Computación Científica: A lo largo de estas seis secciones, hemos demostrado que la Programación Orientada a Objetos no es meramente un paradigma de organización de código, sino la materialización computacional de la abstracción matemática. Las clases base abstractas (ABC) definen los contratos de los espacios de hipótesis; los patrones de diseño Strategy y Transformer permiten la composición de morfismos en los pipelines; y la encapsulación protege los invariantes estadísticos (como la prevención de Data Leakage) de la mutación accidental. El Ingeniero de Machine Learning moderno debe ser un híbrido: poseer la profundidad analítica para derivar el gradiente de una función de pérdida o entender la descomposición espectral de una matriz de covarianza, y simultáneamente poseer la disciplina de ingeniería de software para empaquetar ese conocimiento en sistemas distribuidos, escalables, monitorizables y matemáticamente auditables. Este curso ha proporcionado el andamiaje teórico y práctico para operar con excelencia en esa intersección crítica, preparando al profesional para diseñar los sistemas de Inteligencia Artificial que definirán la infraestructura tecnológica de la próxima década. Abraham Zamudio 57
  56. Programación en Python para Ingeniería REFERENCIAS Bibliografía Textos Fundamentales y

    Teoría del Aprendizaje Estadístico Referencias [1] Bishop, C. M. (2006). Pattern Recognition and Machine Learning. Springer. Texto canónico que establece la formulación probabilística del aprendizaje automático, con énfasis en modelos generativos, máquinas de vectores de soporte y métodos gráficos. [2] Hastie, T., Tibshirani, R., & Friedman, J. (2009). The Elements of Statistical Learning: Data Mining, Inference, and Prediction (2nd ed.). Springer. Referencia definitiva para la teoría estadística del aprendizaje supervisado, incluyendo descomposición sesgo-varianza, regularización, kernels y métodos de ensemble. [3] Murphy, K. P. (2012). Machine Learning: A Probabilistic Perspective. MIT Press. Tratamiento exhaustivo del ML desde la perspectiva bayesiana, con cobertura de modelos lineales generalizados, procesos gaussianos y métodos de inferencia aproximada. [4] Vapnik, V. N. (1998). Statistical Learning Theory. Wiley-Interscience. Obra fundacional de la teoría VC (Vapnik-Chervonenkis), que proporciona las cotas de generalización rigurosas para el principio de minimización del riesgo empírico. [5] Mohri, M., Rostamizadeh, A., & Talwalkar, A. (2018). Foundations of Machine Learning (2nd ed.). MIT Press. Texto moderno que formaliza la teoría del aprendizaje mediante la complejidad de Rademacher, cotas de generalización y algoritmos de optimización convexa. [6] Shalev-Shwartz, S., & Ben-David, S. (2014). Understanding Machine Learning: From Theory to Algorithms. Cambridge University Press. Puente riguroso entre la teoría del aprendizaje computacional (PAC learning) y los algoritmos prácticos, con énfasis en garantías de convergencia. Aprendizaje Profundo y Representaciones [7] Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep Learning. MIT Press. Biblia del deep learning que cubre desde álgebra lineal y probabilidad hasta redes convolucionales, recurrentes y métodos de regularización avanzados. [8] Murphy, K. P. (2022). Probabilistic Machine Learning: An Introduction & Advanced Topics. MIT Press. Actualización moderna del texto de 2012, con cobertura exhaustiva de deep learning generativo (VAEs, GANs, diffusion models) y métodos de inferencia variacional. Optimización y Álgebra Lineal Numérica [9] Boyd, S., & Vandenberghe, L. (2004). Convex Optimization. Cambridge University Press. Referencia estándar para optimización convexa, incluyendo condiciones KKT, dualidad de Lagrange y algoritmos de punto interior. Abraham Zamudio 58
  57. Programación en Python para Ingeniería REFERENCIAS [10] Nocedal, J., &

    Wright, S. J. (2006). Numerical Optimization (2nd ed.). Springer. Texto fundamental sobre métodos numéricos de optimización, incluyendo descenso de gradiente, Newton, quasi-Newton (BFGS) y métodos de regiones de confianza. [11] Golub, G. H., & Van Loan, C. F. (2013). Matrix Computations (4th ed.). Johns Hopkins University Press. Tratamiento exhaustivo de álgebra lineal numérica, descomposiciones matriciales (SVD, QR, Cholesky) y análisis de estabilidad y condicionamiento. Artículos Seminales: Algoritmos de Aprendizaje Supervisado [12] Friedman, J. H. (2001). Greedy function approximation: A gradient boosting machine. Annals of Statistics, 29(4), 1189–1232. Paper fundacional que introduce el Gradient Boosting como descenso de gradiente en el espacio funcional, generalizando el boosting a cualquier función de pérdida diferenciable. [13] Chen, T., & Guestrin, C. (2016). XGBoost: A scalable tree boosting system. In Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining (pp. 785–794). Artículo que presenta XGBoost, detallando la regularización de segundo orden, el manejo de valores faltantes y las optimizaciones de hardware para entrenamiento distribuido. [14] Ke, G., Meng, Q., Finley, T., Wang, T., Chen, W., Ma, W., Ye, Q., & Liu, T.-Y. (2017). LightGBM: A highly efficient gradient boosting decision tree. In Advances in Neural Information Processing Systems (pp. 3146–3154). Introduce técnicas de muestreo basadas en gradientes (GOSS) y discretización por histogramas que reducen la complejidad computacional del gradient boosting en órdenes de magnitud. [15] Breiman, L. (2001). Random forests. Machine Learning, 45(1), 5–32. Paper seminal que formaliza los Random Forests y demuestra teóricamente la convergencia del error de generalización mediante la ley de los números fuertes. [16] Cortes, C., & Vapnik, V. (1995). Support-vector networks. Machine Learning, 20(3), 273–297. Artículo original que introduce las Support Vector Machines con margen suave y el kernel trick, estableciendo las bases de la teoría de márgenes máximos. [17] Cover, T. M., & Hart, P. E. (1967). Nearest neighbor pattern classification. IEEE Transactions on Information Theory, 13(1), 21–27. Demostración clásica de que el error del clasificador 1-NN está acotado por el doble del error de Bayes en el límite asintótico. Aprendizaje No Supervisado: Clustering y Reducción de Dimensionalidad [18] Ester, M., Kriegel, H.-P., Sander, J., & Xu, X. (1996). A density-based algorithm for discovering clusters in large spatial databases with noise. In Proceedings of the 2nd International Conference on Knowledge Discovery and Data Mining (pp. 226–231). Paper fundacional de DBSCAN, que introduce el concepto de clustering basado en densidad y conectividad densa para manejar clusters de formas arbitrarias y ruido. Abraham Zamudio 59
  58. Programación en Python para Ingeniería REFERENCIAS [19] van der Maaten,

    L., & Hinton, G. (2008). Visualizing data using t-SNE. Journal of Machine Learning Research, 9, 2579–2605. Artículo seminal que introduce t-SNE, utilizando distribuciones t de Student para resolver el problema de aglomeración en la visualización de datos de alta dimensión. [20] McInnes, L., Healy, J., & Melville, J. (2018). UMAP: Uniform manifold approximation and projection for dimension reduction. arXiv preprint arXiv:1802.03426. Introduce UMAP basado en topología algebraica y teoría de variedades Riemannianas, ofreciendo preservación de estructura global y escalabilidad superior a t-SNE. [21] Jolliffe, I. T., & Cadima, J. (2016). Principal component analysis: a review and recent developments. Philosophical Transactions of the Royal Society A, 374(2065). Revisión comprehensiva del PCA, incluyendo variantes robustas, kernel PCA y aplicaciones en análisis exploratorio de datos de alta dimensión. Ingeniería de Características y Preprocesamiento [22] Zheng, A., & Casari, A. (2018). Feature Engineering for Machine Learning: Principles and Techniques for Data Scientists. O’Reilly Media. Guía práctica que cubre transformaciones numéricas, codificación categórica, extracción de características de texto e imágenes, y técnicas de selección de variables. [23] van Buuren, S. (2018). Flexible Imputation of Missing Data (2nd ed.). CRC Press. Referencia definitiva sobre imputación múltiple (MICE), con fundamentos teóricos de los mecanismos de datos faltantes (MCAR, MAR, MNAR) y métodos de combinación de Rubin. [24] Micci-Barreca, D. (2001). A preprocessing scheme for high-cardinality categorical attributes in classification and prediction problems. ACM SIGKDD Explorations Newsletter, 3(1), 27–32. Introduce el Target Encoding con suavizado bayesiano para manejar variables categóricas de alta cardinalidad sin sobreajuste. Validación, Optimización de Hiperparámetros y Métricas [25] Bergstra, J., & Bengio, Y. (2012). Random search for hyper-parameter optimization. Journal of Machine Learning Research, 13, 281–305. Demostración teórica y empírica de que Random Search es exponencialmente más eficiente que Grid Search cuando solo un subconjunto de hiperparámetros es influyente. [26] Snoek, J., Larochelle, H., & Adams, R. P. (2012). Practical Bayesian optimization of machine learning algorithms. In Advances in Neural Information Processing Systems (pp. 2951–2959). Aplica la optimización bayesiana con procesos gaussianos y funciones de adquisición (Expected Improvement) al ajuste de hiperparámetros de algoritmos de ML. [27] Arlot, S., & Celisse, A. (2010). A survey of cross-validation procedures for model selection. Statistics Surveys, 4, 40–79. Revisión exhaustiva de métodos de validación cruzada (K-Fold, LOOC, bootstrap), analizando sus propiedades de sesgo-varianza y aplicabilidad a diferentes escenarios. [28] Hand, D. J., & Christen, P. (2011). A note on using the F-measure for evaluating classifiers with imbalanced datasets. Machine Learning, 85(3), 395–410. Análisis crítico de las métricas de evaluación en datasets desbalanceados, incluyendo limitaciones de la Accuracy y propiedades del F1-Score. Abraham Zamudio 60
  59. Programación en Python para Ingeniería REFERENCIAS MLOps, Despliegue y Monitorización

    [29] Sculley, D., Holt, G., Golovin, D., Davydov, E., Phillips, T., Ebner, D., ... & Young, M. (2015). Hidden technical debt in machine learning systems. In Advances in Neural Information Processing Systems (pp. 2503–2511). Artículo influyente que identifica las fuentes de deuda técnica en sistemas de ML en producción, enfatizando la complejidad de los pipelines de datos y la monitorización. [30] Karras, T., Aila, T., Laine, S., & Lehtinen, J. (2018). Progressive growing of GANs for improved quality, stability, and variation. In International Conference on Learning Representations. Aunque enfocado en GANs, introduce prácticas de ingeniería de entrenamiento progresivo y monitorización de métricas que son transferibles a MLOps. [31] Breck, E., Cai, S., Chen, E., Chen, M., Chi, M., Chiu, C., ... & Zilka, M. (2016). The ML test score: A rubric for ML production systems. In IEEE International Conference on Big Data (pp. 1105–1112). Propone un marco de evaluación (rubric) para sistemas de ML en producción, cubriendo pruebas de datos, modelos, infraestructura y monitorización. [32] Gretton, A., Borgwardt, K. M., Rasch, M. J., Schölkopf, B., & Smola, A. (2012). A kernel two-sample test. Journal of Machine Learning Research, 13, 723–773. Desarrolla el test estadístico basado en Maximum Mean Discrepancy (MMD) para detectar diferencias entre distribuciones, fundamental para la detección de data drift. [33] Lu, J., Liu, A., Greer, D., & Dong, G. (2004). Capturing concept drift to retrain classifiers. ACM SIGKDD Explorations Newsletter, 6(1), 52–59. Introduce métodos adaptativos para detectar concept drift en flujos de datos continuos y disparar reentrenamientos automáticos. Implementaciones de Software y Librerías [34] Pedregosa, F., Varoquaux, G., Gramfort, A., Michel, V., Thirion, B., Grisel, O., ... & Duchesnay, É. (2011). Scikit-learn: Machine learning in Python. Journal of Machine Learning Research, 12, 2825–2830. Paper original de scikit-learn que describe la arquitectura orientada a objetos, la API consistente (fit/predict/transform) y los principios de diseño que han establecido el estándar de facto en ML. [35] Abadi, M., Agarwal, A., Barham, P., Brevdo, E., Chen, Z., Citro, C., ... & Zheng, X. (2016). TensorFlow: A system for large-scale machine learning. In 12th USENIX Symposium on Operating Systems Design and Implementation (pp. 265–283). Describe la arquitectura de computación gráfica de TensorFlow, incluyendo diferenciación automática, ejecución distribuida y optimizaciones de hardware. [36] Paszke, A., Gross, S., Massa, F., Lerer, A., Bradbury, J., Chanan, G., ... & Chintala, S. (2019). PyTorch: An imperative style, high-performance deep learning library. In Advances in Neural Information Processing Systems (pp. 8024–8035). Introduce el modelo de programación imperativa (eager execution) de PyTorch, que facilita la depuración y la investigación en deep learning. [37] Harris, C. R., Millman, J. K., van der Walt, S. J., Gommers, R., Virtanen, P., Cournapeau, D., ... & Oliphant, T. E. (2020). Array programming with NumPy. Nature, 585(7825), 357–362. Abraham Zamudio 61
  60. Programación en Python para Ingeniería REFERENCIAS Artículo de referencia sobre

    NumPy que describe la arquitectura de arrays n-dimensionales, el broadcasting, y la integración con bibliotecas de álgebra lineal de alto rendimiento. Abraham Zamudio 62